/* =========================================================================
   Rénovation Optimale — feuille de style partagée par toutes les pages du site
   Source unique de la charte graphique (voir
   ../contexte-statique/ressources/design/charte-graphique.md).
   Toute page du site la charge via <link rel="stylesheet" href="styles.css">.
   ========================================================================= */

:root{
  --cream:#f8f9eb;
  --greige:#eeeee4;
  --forest:#022c22;
  --pine:#137030;
  --neon:#00ffab;
  --ink:#022c22;
  /* Accents chauds à l'essai (2026-08-10), hors palette officielle tant que le
     rendu n'est pas validé. Rôles : ambre = le chiffre qui gagne, terracotta =
     ce qui fait peur. Deux valeurs par teinte, et elles ne sont pas
     interchangeables :
       --*        version vive, APLAT uniquement (elle est illisible en texte
                  sur crème, exactement comme le néon)
       --*-ink    version encre, TEXTE sur fond clair uniquement
     Le terracotta vif est passé de #c2593a à #b04e33 le 2026-08-10 : la
     première valeur ne portait le texte blanc qu'à 4,36:1, sous le seuil, ce
     qui la rendait inutilisable en fond de carte. #b04e33 donne 5,2:1.
     Voir le bloc « ESSAI » en fin de fichier pour les usages réels. */
  --amber:#e8a317;
  --amber-ink:#9c6404;
  --terra:#b04e33;
  --terra-ink:#8f3b22;
  /* Pas de ton sombre de fond ni de ton clair d'accent pour le terracotta,
     contrairement au vert : ils n'auraient servi qu'à des surfaces de la
     taille d'une section, écartées le 2026-08-10. Le terracotta reste
     volontairement une couleur à deux valeurs, donc à petits usages. */
  --muted:rgba(2,44,34,.62);
  --line:rgba(2,44,34,.10);
  --radius-section:24px; /* arrondi de TOUS les raccords de section (jamais un encadré : eux sont à 8px) */
  --header-h:70px;  /* hauteur du header fixe */
  --banner-h:36px;  /* hauteur du bandeau promo, quand il est là */
  --chrome-h:var(--header-h); /* hauteur totale du bloc fixe en haut de page */
  --pad:8rem;      /* 128px standard */
  --pad-lg:10rem;  /* 160px moments forts */
}
*{box-sizing:border-box;}
html{scroll-behavior:smooth;}
body{
  margin:0;overflow-x:hidden;background:var(--cream);color:var(--ink);
  font-family:'Geist','Inter',-apple-system,'Segoe UI',Roboto,sans-serif;
  font-size:18px;line-height:1.4;letter-spacing:-.6px;-webkit-font-smoothing:antialiased;
}
img{max-width:100%;display:block;}
a{color:inherit;text-decoration:none;}

/* Texte réservé aux lecteurs d'écran : invisible à l'œil, lu à voix haute.
   Sert à annoncer ce que le visuel dit tout seul (ouverture dans un nouvel
   onglet, par exemple). En position:absolute, l'élément n'est pas un item de
   flex : il n'ajoute pas de gap dans un .btn. */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0;}

.display{font-family:'Fraunces',Georgia,serif;font-variation-settings:'opsz' 144,'SOFT' 50,'WONK' 0;line-height:1.06;}
.mono{font-family:'JetBrains Mono',ui-monospace,monospace;font-weight:500;}

/* Largeur de page élargie le 2026-07-28 (1200 → 1320px, gouttières 24 → 32px),
   pour se rapprocher des marges des sites de référence (Treso2, Defacto,
   Delville) et donner de l'air aux mises en page à deux colonnes. */
/* --wrap-pad est exposé en variable pour que les blocs qui doivent déborder du
   .wrap (barres d'onglets qui défilent, rubans) reprennent exactement la même
   valeur : en la codant en dur, un bloc calé sur 32px dépassait la page de 10px
   sur les écrans où la marge tombe à 22px. */
:root{--wrap-pad:32px;}
@media(max-width:560px){:root{--wrap-pad:22px;}}
.wrap{max-width:1320px;margin:0 auto;padding:0 var(--wrap-pad);}
.narrow{max-width:660px;margin:0 auto;text-align:center;}
.section{padding:var(--pad) 0;}
.section-lg{padding:var(--pad-lg) 0;}

/* Bandeau de section (2026-08-08) : la pilule blanche a petite pastille ronde
   est remplacee par un label nu, precede d'un carre cerne d'un second carre qui
   pulse tres discretement. Le texte n'est plus en capitales tassees a 9px mais
   lisible a 13px. Sur fond clair il passe en vert foret : le neon n'a pas assez
   de contraste sur le creme une fois la pilule blanche retiree. */
.eyebrow{
  display:inline-flex;align-items:center;gap:12px;
  font-size:.82rem;font-weight:600;letter-spacing:.01em;
  margin-bottom:22px;
}
.eyebrow-center{display:flex;width:fit-content;margin-left:auto;margin-right:auto;}
.eyebrow.on-light{color:var(--pine);}
.eyebrow.on-dark{color:var(--neon);}
/* Le point devient un carre. La classe reste .dot : le HTML de toutes les pages
   la porte deja, inutile de le reecrire partout. */
.eyebrow .dot{position:relative;flex:none;width:8px;height:8px;border-radius:2px;
  background:currentColor;
  /* -1px : le carre parfaitement centre sur la line-box paraissait bas. */
  top:-1px;}
.eyebrow .dot::after{content:"";position:absolute;inset:-6px;border-radius:4px;
  border:1.5px solid currentColor;opacity:0;
  animation:ebPulse 2.6s cubic-bezier(.25,.8,.25,1) infinite;}
@keyframes ebPulse{
  0%   {transform:scale(.62);opacity:.55;}
  70%  {transform:scale(1.25);opacity:0;}
  100% {transform:scale(1.25);opacity:0;}
}
/* Sur l'aplat neon, le vert foret du .on-light serait illisible : on force
   l'encre. */
.bg-neon .eyebrow.on-light{color:var(--forest);}
@media(prefers-reduced-motion:reduce){
  .eyebrow .dot::after{animation:none;opacity:.4;transform:scale(1);}
}

/* text-wrap:balance (2026-08-10) : le navigateur egalise la longueur des lignes
   d'un titre au lieu de remplir la premiere au maximum. Il supprime les lignes
   veuves, ces fins de titre reduites a un seul mot (« ... laissent / filer. »).
   Mesure faite sur les 6 pages principales, en 1440 et en 390px : 24 titres
   finissaient sur un mot isole, il n'en reste aucun, et aucun titre n'a ete
   degrade au passage. Prefere a une espace insecable posee a la main, qui ne
   corrige qu'une largeur d'ecran et se retourne contre nous a toutes les
   autres. Les navigateurs qui ne connaissent pas la propriete l'ignorent et
   retombent sur le comportement actuel. */
.h1{font-size:clamp(2.5rem,6vw,3.75rem);font-weight:500;margin:0 0 24px;letter-spacing:-.01em;
  text-wrap:balance;}
.h2{font-size:clamp(2rem,4.5vw,2.875rem);font-weight:400;margin:0 0 20px;letter-spacing:-.005em;
  text-wrap:balance;}
/* Modificateur pour un H1 plus long que la moyenne : un cran en dessous, 56px
   au lieu de 60, ce qui reste dans la plage 56-64px que la charte donne pour
   un H1. Seul le maximum du clamp bouge, les petits ecrans sont inchanges.
   Raison : text-wrap:balance egalise les lignes mais ne choisit pas leur
   nombre. Sur un titre qui deborde de quelques pixels sur une troisieme ligne,
   il produit une silhouette qui s'elargit vers le bas (mesure sur le H1 de
   dpe-impact a 60px : 370 / 370 / 572px). Lui rendre deux lignes a remplir
   suffit : a 56px le meme titre donne 618 / 615px.
   A n'appliquer qu'au cas par cas, sur le titre concerne, jamais globalement. */
.h1-long{font-size:clamp(2.5rem,6vw,3.5rem);}
.lead{font-size:18px;color:var(--muted);margin:0 0 18px;font-weight:300;}
.accent-pine{color:var(--pine);}
.on-dark .lead{color:rgba(248,249,235,.72);}

/* buttons
   RÈGLE (2026-08-03) : un nouveau bouton s'écrit `class="btn btn-dark"`, point.
   `.btn-dark` est LA classe du bouton standard : c'est la seule qui porte
   l'ombre, et elle s'adapte déjà au fond (néon sur clair, pine sur .on-dark,
   forest sur .bg-neon). `.btn-neon` (néon forcé quel que soit le fond) est une
   variante de niche, sans ombre, réservée aux formulaires sur fond forêt et
   aux CTA latéraux d'articles : ne pas s'en servir pour un bouton ordinaire,
   il sortirait plat à côté des autres. */
.btn{display:inline-flex;align-items:center;gap:10px;font-weight:600;font-size:1rem;
  padding:15px 26px;border-radius:4px;border:1px solid transparent;cursor:pointer;
  transition:transform .3s cubic-bezier(.25,.8,.25,1),box-shadow .3s,background .3s;}
.btn:hover{transform:translateY(-2px);}
.btn svg{width:18px;height:18px;}
/* Bouton principal : néon sur fond clair (généralisé à tout le site le
   2026-07-28, après le test cantonné à la page Bible). Écart assumé avec la
   charte, qui prescrivait #137030 + texte blanc et interdit #00ffab sur fond
   crème faute de contraste suffisant.
   L'ombre est volontairement dense et verte foncée, et non un halo néon : le
   néon sur crème ne se détache que d'environ 1,3:1, c'est l'ombre qui donne au
   bouton son arête et le fait exister sur la page. La deuxième couche, courte
   et serrée, tient lieu de contour ; la première assoit le bloc. */
.btn-dark{background:var(--neon);color:var(--forest);
  box-shadow:0 10px 26px -10px rgba(2,44,34,.45),0 2px 6px -1px rgba(2,44,34,.22);}
.btn-dark:hover{box-shadow:0 18px 38px -12px rgba(2,44,34,.5),0 3px 8px -1px rgba(2,44,34,.26);}
/* Fonds sombres : un bouton néon y perdrait sa fonction de contraste, il reste
   vert foncé + texte blanc comme avant. */
.on-dark .btn-dark,.cookie-banner .btn-dark{background:var(--pine);color:#fff;
  box-shadow:0 10px 30px -12px rgba(2,44,34,.4);}
.on-dark .btn-dark:hover,.cookie-banner .btn-dark:hover{filter:brightness(1.08);
  box-shadow:0 18px 40px -12px rgba(2,44,34,.5);}
/* Fond néon : un bouton néon serait invisible. */
.bg-neon .btn-dark{background:var(--forest);color:#fff;
  box-shadow:0 10px 30px -12px rgba(2,44,34,.4);}
.bg-neon .btn-dark:hover{filter:brightness(1.08);box-shadow:0 18px 40px -12px rgba(2,44,34,.5);}
.btn-neon{background:var(--neon);color:var(--forest);}
.btn-neon:hover{box-shadow:0 16px 36px -12px rgba(0,255,171,.5);}
.btn-ghost{background:transparent;border:1px solid var(--line);color:var(--ink);}
.on-dark .btn-ghost{border-color:rgba(248,249,235,.2);color:var(--cream);}

.link-arrow{display:inline-flex;align-items:center;gap:7px;font-weight:600;color:var(--pine);
  border-bottom:1px solid transparent;transition:gap .3s,border-color .3s;padding-bottom:2px;}
.link-arrow:hover{gap:12px;border-color:var(--pine);}
.link-arrow svg{width:16px;height:16px;}
.on-dark .link-arrow{color:var(--neon);}
.on-dark .link-arrow:hover{border-color:var(--neon);}

/* Bandeau d'appel au guide, fixé tout en haut, au-dessus du header (injecté
   par layout.js). Il pousse le header vers le bas et allonge d'autant le
   décalage haut des pages : c'est --chrome-h, la hauteur totale du bloc fixe,
   que tous les héros utilisent au lieu des 70px du header seul.
   Le bandeau n'est pas présent sur toutes les pages, d'où le :has(). */
:root:has(.top-banner){--chrome-h:calc(var(--header-h) + var(--banner-h));}
.top-banner{position:fixed;top:0;left:0;right:0;z-index:49;height:var(--banner-h);
/* Texte en blanc et non en neon (2026-08-05) : le neon sur le vert sombre
   tirait l'oeil avant le contenu de la page alors que ce bandeau est une
   proposition secondaire. Blanc pur, comme le texte des boutons sombres de la
   charte. */
  background:var(--forest);color:#fff;}
/* Le lien occupe toute la barre pour rester une grande cible de clic ; la croix
   passe par-dessus, à droite. Le padding est symétrique pour que la phrase
   reste optiquement centrée dans l'écran malgré la croix. */
.top-banner-link{display:flex;align-items:center;justify-content:center;gap:11px;
  height:100%;padding:0 52px;color:inherit;text-align:center;
  font-size:.78rem;font-weight:400;transition:gap .3s,background .25s;}
.top-banner-link:hover{gap:16px;background:#03392c;}
.top-banner-link svg{width:15px;height:15px;flex:none;}
.top-banner-close{position:absolute;top:50%;right:12px;transform:translateY(-50%);
  display:grid;place-items:center;width:26px;height:26px;padding:0;border:0;border-radius:6px;
  background:transparent;color:rgba(255,255,255,.55);cursor:pointer;transition:color .25s,background .25s;}
.top-banner-close:hover{color:#fff;background:rgba(255,255,255,.12);}
.top-banner-close svg{width:14px;height:14px;}
/* Sous 560px la phrase complète passerait sur deux lignes et doublerait la
   hauteur du bloc fixe : on la tronque plutôt que de casser la mise en page. */
@media(max-width:560px){
  .top-banner-link{font-size:.72rem;gap:8px;padding:0 44px 0 14px;}
  .top-banner-link span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
}

/* header */
.header{position:fixed;top:calc(var(--chrome-h) - var(--header-h));left:0;right:0;z-index:50;
  background:rgba(248,249,235,.72);backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);
  border-bottom:1px solid var(--line);}
.header .wrap{display:flex;align-items:center;justify-content:space-between;height:var(--header-h);}
.header .logo img{height:38px;width:auto;}
.nav{display:flex;align-items:center;gap:30px;}
.nav a{font-size:.95rem;font-weight:500;color:var(--muted);transition:color .25s;}
.nav a:hover{color:var(--ink);}
.header .cta-wrap{display:flex;align-items:center;gap:18px;}
.header .btn{padding:11px 20px;font-size:.9rem;}
@media(max-width:900px){.nav{display:none;}}

/* ---- Menu mobile (2026-08-14) ----
   Sous 900px la nav était simplement masquée et rien ne la remplaçait : le
   header ne proposait plus que le logo et le bouton Contact, et aucune page du
   site n'était atteignable depuis le haut de l'écran.
   Le burger est posé à DROITE du bouton Contact, qui reste visible : c'est le
   seul chemin direct vers la vente, il ne doit pas être replié dans le menu.
   Le panneau est construit par initMenuMobile (layout.js) à partir de la nav du
   header, il n'y a donc pas de seconde liste de liens à tenir à jour. */
.burger{display:none;flex-direction:column;justify-content:center;gap:5px;
  width:40px;height:40px;padding:0 8px;border:0;background:none;cursor:pointer;}
.burger span{display:block;height:2px;border-radius:2px;background:var(--ink);
  transition:transform .25s,opacity .2s;}
/* Croix à l'ouverture : les deux barres extrêmes se rejoignent au centre (les
   5px de gap plus les 2px d'épaisseur, soit 7px à parcourir), celle du milieu
   s'efface. */
.burger.is-open span:nth-child(1){transform:translateY(7px) rotate(45deg);}
.burger.is-open span:nth-child(2){opacity:0;}
.burger.is-open span:nth-child(3){transform:translateY(-7px) rotate(-45deg);}
.burger:focus-visible{outline:2px solid var(--pine);outline-offset:2px;}
@media(max-width:900px){
  .burger{display:flex;}
  /* Le panneau part sous le bloc fixe du haut (bandeau promo compris, d'où
     --chrome-h) et occupe le reste de l'écran. En overflow auto pour rester
     utilisable sur un petit écran en paysage, où neuf liens ne tiennent pas. */
  .menu-mobile{position:fixed;top:var(--chrome-h);left:0;right:0;bottom:0;z-index:48;
    display:flex;flex-direction:column;gap:4px;
    padding:26px var(--wrap-pad) 40px;overflow-y:auto;
    background:var(--cream);border-top:1px solid var(--line);}
  .menu-mobile[hidden]{display:none;}
  .mm-groupe{display:flex;flex-direction:column;gap:4px;padding-bottom:14px;
    margin-bottom:14px;border-bottom:1px solid var(--line);}
  /* Le libellé de premier niveau devient un intertitre et non un lien : dans le
     mega-menu il pointe sur « # », il n'a jamais mené nulle part. */
  .mm-titre{margin:0 0 4px;font-size:.78rem;font-weight:700;letter-spacing:.12em;
    text-transform:uppercase;color:var(--pine);}
  .mm-link{padding:10px 0;font-size:1.15rem;font-weight:500;color:var(--ink);}
  /* Pas de filet sous le dernier groupe : il ne sépare plus rien et se lirait
     comme un trait décoratif suspendu au milieu du panneau. */
  .mm-groupe:last-child{border-bottom:0;}
}
/* Le fond de page ne défile plus derrière le panneau ouvert. Posé sur <html> et
   non sur <body> : c'est l'élément que Safari iOS fait effectivement défiler. */
html.menu-ouvert{overflow:hidden;}

/* sections colors */
.bg-cream{background:var(--cream);}
.bg-greige{background:var(--greige);}
.bg-forest{background:var(--forest);color:var(--cream);}
.bg-neon{background:var(--neon);color:var(--forest);}
.bg-forest .h1,.bg-forest .h2{color:#fff;}

/* hero (page d'accueil) */
.hero{padding-top:calc(var(--chrome-h) + 6rem);padding-bottom:var(--pad-lg);position:relative;overflow:hidden;}
.grid-bg{position:absolute;inset:0;z-index:0;pointer-events:none;
  background-size:32px 32px;
  background-image:linear-gradient(to right,rgba(2,44,34,.04) 1px,transparent 1px),linear-gradient(to bottom,rgba(2,44,34,.04) 1px,transparent 1px);
  -webkit-mask-image:radial-gradient(circle at 30% 40%,#000 5%,transparent 65%);
  mask-image:radial-gradient(circle at 30% 40%,#000 5%,transparent 65%);}
.hero-grid{display:grid;grid-template-columns:1.1fr .9fr;gap:60px;align-items:center;position:relative;z-index:1;}
@media(max-width:920px){.hero-grid{grid-template-columns:1fr;gap:48px;}}
.hero .micro{font-size:.82rem;color:var(--muted);margin-top:14px;}
.hero-ctas{display:flex;gap:16px;flex-wrap:wrap;align-items:center;margin-top:32px;}
.trust{display:flex;align-items:center;gap:12px;margin-top:34px;font-size:.9rem;color:var(--muted);}
.stars{display:inline-flex;gap:2px;color:var(--pine);}
.stars svg{width:16px;height:16px;}

/* hero reviews */
.reviews-title{font-size:22px;line-height:1.2;text-align:center;color:var(--ink);margin:0;font-weight:500;letter-spacing:-.01em;}
/* Le titre est a marge nulle pour le ruban .reviews-band de l'accueil, qui gere
   son propre espacement. Quand il vit DANS le hero (page investisseurs, avis en
   deux cartes fixes), il lui faut son air au-dessus : sans ca il se colle au
   bloc de reassurance du hero. */
.hero .reviews-title{margin-top:6rem;}
@media(max-width:820px){.hero .reviews-title{margin-top:3.5rem;}}
.hero-reviews{display:grid;grid-template-columns:1fr 1fr;gap:22px;margin-top:32px;}
@media(max-width:820px){.hero-reviews{grid-template-columns:1fr;}}
.review{background:#fff;border:1px solid var(--line);border-radius:8px;padding:26px;box-shadow:0 14px 34px -22px rgba(2,44,34,.24);}
.review-head{display:flex;align-items:center;gap:12px;margin-bottom:14px;}
.review-av{width:44px;height:44px;border-radius:50%;object-fit:cover;flex:none;}
.review-meta .n{font-weight:600;font-size:.95rem;}
.review-meta .m{font-size:.78rem;color:var(--muted);}
.review-stars{display:inline-flex;gap:2px;color:var(--pine);margin-bottom:12px;}
.review-stars svg{width:17px;height:17px;}
.review h4{font-size:1rem;margin:0 0 8px;font-weight:600;}
.review p{font-size:.9rem;color:var(--muted);margin:0;line-height:1.4;}
/* Fragment mis en avant dans un avis : le gras ne suffit pas sur du texte déjà
   grisé, c'est le retour à l'encre pleine qui crée l'accroche. */
.review p strong{font-weight:600;color:var(--ink);}
.reviews-more{text-align:center;margin-top:30px;font-size:.9rem;color:var(--muted);font-weight:600;}
.reviews-more a{color:var(--ink);border-bottom:1px solid var(--line);transition:border-color .3s;}
.reviews-more a:hover{border-color:var(--pine);}

/* ---- Bande d'avis à cheval sur la section suivante (home) ----
   Le raccord crème → vert forêt passe au milieu des cartes : la rangée d'avis
   fait la couture entre les deux sections au lieu d'être posée dans l'une des
   deux. La bande n'a donc pas de fond à elle (le crème vient du body) et se
   contente de passer au-dessus, pendant que la section suivante remonte de
   --reviews-overlap par-dessous.
   Pas de fondu latéral sur le ruban : un fondu qui croise le raccord délave les
   cartes des bords en blanc sale sur le vert. La coupe nette au bord de l'écran
   se lit comme voulue dès lors que le raccord traverse la rangée. */
:root{--reviews-overlap:140px;}
/* Le hero garde son padding-bas normal quand il finit une section, mais quand
   la bande d'avis le suit, ce padding + celui de la bande feraient un trou de
   240px : c'est le hero qui cède, la bande ne rajoute rien au-dessus du titre.
   Padding resserre le 2026-08-05, en haut aussi. Depuis que le visuel de
   l'accueil est une fiche en portrait, c'est lui qui fixe la hauteur du hero :
   815px de hero plus 107px de header et de bandeau, soit 922px, quand une
   fenetre de portable en fait environ 860. Les 96px du bas passaient donc
   toujours sous le pli et le hero paraissait cale trop haut, alors que ses
   deux marges sont symetriques. A 4rem/5rem l'ensemble tient dans l'ecran.
   Le selecteur ne vise que le hero suivi du ruban d'avis, donc la seule page
   d'accueil : les autres heros du site gardent le 6rem commun. */
.hero:has(+ .reviews-band){padding-top:calc(var(--chrome-h) + 4rem);padding-bottom:5rem;}
.reviews-band{position:relative;z-index:2;padding:0;}
.reviews-band + .bg-forest{
  position:relative;z-index:0;
  margin-top:calc(var(--reviews-overlap) * -1);
  padding-top:calc(var(--pad) + var(--reviews-overlap));
}
/* Exception quand cette section porte aussi le visuel débordant des onglets
   (accueil) : le z-index:0 ci-dessus en fait un contexte d'empilement, qui
   enferme le z-index:3 de .risk-visual et laisse la section claire suivante
   (.round-top, z-index:2) recouvrir le bas de l'image. En z-index:auto la
   section ne crée plus de contexte et le visuel remonte au niveau racine.
   La bande d'avis reste au-dessus sans rien changer : un élément positionné en
   z-index:2 se peint après ceux en z-index auto, quel que soit l'ordre du DOM. */
.reviews-band + .bg-forest.risk-section{z-index:auto;}
/* Les cartes sont plus hautes sur petit écran (texte sur plus de lignes) :
   il faut monter le raccord d'autant pour qu'il tombe au même endroit. */
@media(max-width:640px){:root{--reviews-overlap:150px;}}

/* ---- Ruban d'avis défilant (home) ----
   Le ruban occupe toute la largeur utile : l'objectif est de faire percevoir un
   flux d'avis, pas d'en faire lire deux. Le défilement est autonome et lent, il
   se met en pause au survol et au focus clavier pour rendre la lecture possible.
   Il est posé dans le HTML en dehors du .wrap, ce qui lui donne cette pleine
   largeur par un simple 100% hérité de la section. Ne pas revenir à un
   width:100vw pour le remettre dans le .wrap : 100vw compte la barre de
   défilement, le ruban dépassait alors la page d'une quinzaine de pixels sur
   tout navigateur qui en affiche une, et une bande de crème apparaissait à
   droite des sections. Le bug est invisible en test headless, où la barre de
   défilement fait zéro pixel. */
.reviews-marquee{
  margin-top:32px;
  overflow:hidden;padding:14px 0 30px;   /* laisse respirer l'ombre des cartes */
}
.marquee-track{display:flex;gap:22px;width:max-content;animation:marquee 70s linear infinite;}
.marquee-group{display:flex;gap:22px;flex:none;}
/* Le second groupe est une copie du premier : on translate d'exactement une
   largeur de groupe + un gap, soit calc(-50% - 11px) puisque la piste vaut
   2 groupes + 1 gap. */
@keyframes marquee{from{transform:translate3d(0,0,0);}to{transform:translate3d(calc(-50% - 11px),0,0);}}
.reviews-marquee:hover .marquee-track,
.reviews-marquee:focus-within .marquee-track{animation-play-state:paused;}
/* Assez large pour que le plus long avis (293 caractères) tienne en 6 lignes :
   un avis coupé par un « … » affaiblit la preuve qu'il est censé apporter, donc
   aucune troncature. Les cartes s'alignent sur la hauteur de la plus haute. */
.marquee-group .review{width:min(420px,80vw);flex:none;display:flex;flex-direction:column;}
@media(max-width:640px){
  .marquee-group .review{width:min(340px,84vw);padding:22px;}
}
/* Sur mobile le défilement automatique est abandonné pour un carrousel qu'on
   fait glisser au doigt, avec accrochage sur une carte (2026-08-14). Le ruban
   qui défile marche en desktop, où trois cartes et demie sont visibles : on
   perçoit un flux d'avis même si on n'en lit aucun en entier. Sur 390px il
   n'entre qu'une carte et demie, donc en arrivant sur la section on tombe
   toujours sur deux avis coupés, en mouvement, dont aucun n'est lisible : la
   preuve sociale ne prouve plus rien.
   scroll-snap-type:x mandatory recale toujours la vue sur une carte entière, il
   n'y a plus d'arrêt intermédiaire possible. La carte fait 84vw et non 100 :
   les 16vw restants laissent voir le bord de la suivante, ce qui dit qu'il y en
   a d'autres et invite à glisser. Le padding-inline compense l'accrochage
   centré, sans lui les cartes des deux bouts ne peuvent pas être atteintes.
   Le second groupe est masqué : c'est la copie qui assure la boucle sans
   raccord du défilement automatique. Sans animation elle n'a plus d'objet, et
   elle obligerait à traverser deux fois les mêmes avis. */
@media(max-width:760px){
  .reviews-marquee{overflow-x:auto;scrollbar-width:none;-webkit-overflow-scrolling:touch;
    scroll-snap-type:x mandatory;}
  .reviews-marquee::-webkit-scrollbar{display:none;}
  .marquee-track{animation:none;padding-inline:8vw;}
  .marquee-group[aria-hidden="true"]{display:none;}
  .marquee-group .review{width:84vw;scroll-snap-align:center;}
}
/* Flèche du carrousel d'avis (mobile). Le bord de la carte suivante qui dépasse
   ne suffisait pas à faire comprendre qu'on peut glisser : la flèche le dit, et
   comme c'est un vrai bouton elle le fait aussi d'un tap, pour qui ne pense pas
   à glisser. Le conteneur .reviews-carousel n'existe que pour l'ancrer.
   Fond crème plein et non translucide : la flèche est posée à cheval sur le
   raccord crème → vert, un fond translucide changerait de teinte selon la
   hauteur où elle tombe. Elle est calée à 42% et non à 50% pour rester dans le
   haut de la carte, la moitié basse étant déjà dans le vert. */
.reviews-carousel{position:relative;}
.reviews-next{display:none;}
@media(max-width:760px){
  .reviews-next{display:flex;align-items:center;justify-content:center;
    position:absolute;top:42%;right:8px;transform:translateY(-50%);
    width:40px;height:40px;padding:0;border:1px solid var(--line);border-radius:50%;
    background:var(--cream);color:var(--pine);cursor:pointer;
    box-shadow:0 6px 18px -8px rgba(0,0,0,.45);}
  .reviews-next svg{width:20px;height:20px;}
  .reviews-next:focus-visible{outline:2px solid var(--pine);outline-offset:3px;}
  /* La flèche ne s'efface jamais en fin de liste : sur le dernier avis elle
     ramène au premier (voir initReviewsCarrousel dans layout.js), le parcours
     boucle comme le ruban qui tourne en desktop. Un bouton qui disparaît ou se
     désactive laisserait croire que la rangée s'arrête là. */
}
@media(prefers-reduced-motion:reduce){
  .marquee-track{animation:none;}
  .reviews-marquee{overflow-x:auto;scrollbar-width:none;}
  .reviews-marquee::-webkit-scrollbar{display:none;}
}

.hero-visual-wrap{position:relative;}

/* ---- Gabarit du visuel d'un hero sur une colonne (2026-08-09) --------------
   A poser sur le conteneur du visuel de tout hero centre (une seule colonne),
   par opposition a .hero-visual-wrap qui est la colonne de droite d'un hero a
   deux colonnes. C'est LA regle de dimension de ces visuels : on ne la
   redefinit pas page par page.

   Reference mesuree sur slite.com/solutions/it-operations : le visuel y fait
   1200x700 (ratio .58), largeur figee, identique en 1440, 1680 et 1920 de
   large. On retient de cette reference le principe (largeur bornee en pixels,
   pas en pourcentage d'ecran, et un bloc franchement haut plutot qu'un
   bandeau) mais pas ses valeurs :

   - largeur 1080 et non 1200 : 1200 est calibre pour une capture d'app dense.
     Nos visuels sont des cartes de synthese, plus maigres, qui a cette largeur
     s'etirent et paraissent vides.
   - hauteur cible ~.52 de la largeur, un cran sous le .58 de la reference,
     pour la meme raison.

   min-height et non aspect-ratio : le contenu peut depasser la hauteur cible
   (une capture plus haute, une carte plus fournie), jamais descendre dessous.
   39vw tient le ratio sur les tailles d'ecran courantes, le plancher de 340px
   prend la main sur un ecran etroit. */
.hero-visual-solo{position:relative;width:100%;max-width:1080px;
  margin:clamp(44px,6vw,88px) auto 0;
  min-height:clamp(340px,39vw,580px);
  display:flex;}
/* Le visuel s'etire sur toute la hauteur du gabarit : c'est a lui de repartir
   son contenu, pas au gabarit de le centrer dans du vide. */
.hero-visual-solo > :not(.grille-accent){flex:1;display:flex;flex-direction:column;}

/* ---- Aplat de couleur + capture d'app qui deborde (2026-08-09) -------------
   Le second motif de visuel de hero sur une colonne, a poser DANS
   .hero-visual-solo : un aplat plein de la charte, dans lequel la capture est
   ancree en haut a gauche et se fait rogner par les bords droit et bas. Le
   debordement est ce qui donne la profondeur ; overflow:hidden garantit que
   rien ne sort du cadre, donc pas de defilement horizontal.

   Meme motif que .sim-frame-app (page simulateur, etapes 2 et 3), mais
   generique : pas d'aspect-ratio fige, c'est le gabarit de .hero-visual-solo
   qui donne la hauteur.

   Insets mesures sur la reference slite.com/solutions/it-operations : aplat
   1200x700, capture decalee de 65px du bord gauche et du bord haut, soit 5,5 %
   de la largeur et 9 % de la hauteur. En pourcentage et non en pixels pour que
   le decalage suive la taille du cadre. */
/* 8px, la valeur de charte pour tout encadre, carte ou bloc (fixee le
   2026-07-08). PAS --radius-section (24px), qui est reserve aux raccords entre
   sections : un aplat pose dans une colonne n'en est pas un.

   Filet et ombre portes par le CADRE et non par la capture : la capture est
   rognee par overflow:hidden, donc son ombre a elle disparait sur les bords ou
   elle deborde. Or c'est justement la que le probleme se pose : l'interface de
   l'app a le meme fond creme que le site (#f8f9eb), le bord droit du visuel se
   dissolvait donc dans la page. Le filet dit ou le visuel s'arrete, l'ombre le
   decolle du fond. */
.hero-app-frame{position:relative;overflow:hidden;
  /* Vert #19b277 (2026-08-11, demande de Lois) : un cran plus clair et plus
     franc que le vert pin, il detache toujours la capture d'interface claire
     sans partir dans le neon, qui reste reserve aux cadres de la section
     « Comment ca marche », plus bas, ou il rythme la page. */
  border-radius:8px;background:#19b277;
  border:1px solid var(--line);
  /* Deux ombres : une longue vers le bas, qui pose le bloc sur la page, et une
     courte et serree, qui existe aussi sur les cotes. Sans la seconde, le bord
     droit n'a aucun contraste puisque l'ombre longue ne porte pratiquement pas
     lateralement. */
  box-shadow:0 40px 90px -40px rgba(2,44,34,.35),
             0 2px 20px -6px rgba(2,44,34,.22);}
/* width:115% : la capture est prise dans un viewport de 1400px CSS, et le
   cadre en fait 1080. A 100 % elle serait affichee a 77 % de sa taille reelle,
   texte tasse et illisible ; a 125 % elle est a l'echelle 1:1 mais on perd la
   moitie droite de l'ecran (schema des deperditions, cartes de travaux). 115 %
   (1242px, echelle 0,89) est le point ou l'interface se lit encore et ou le
   contenu qui porte l'argument reste dans le cadre. */
/* max-width:none obligatoire : la regle globale `img{max-width:100%}` (l.31)
   ramenerait sinon la capture a la largeur du cadre, et tout le debordement
   disparaitrait sans rien signaler. */
.hero-app-shot{position:absolute;top:9%;left:5.5%;width:115%;max-width:none;
  height:auto;display:block;
  border-top-left-radius:8px;   /* meme valeur de charte que le cadre */
  box-shadow:0 34px 80px -30px rgba(2,44,34,.5);}
/* Sur telephone, une capture d'application de bureau rentree en entier dans
   350px de large ne se lit plus : c'est une vignette grise. On change donc de
   parti, on ne montre plus l'ecran entier mais on zoome (260 %) et on decale
   vers la gauche (left negatif) pour cadrer sur le contenu, en laissant la
   barre laterale sortir du cadre. Il reste une bande d'aplat en haut : le
   motif « capture posee dans la couleur » tient toujours. */
@media(max-width:700px){
  .hero-app-shot{top:8%;left:-46%;width:260%;}
}
/* max-width (2026-08-05) : le visuel est passe d'un format paysage a une fiche
   en portrait. A 100% de la colonne il faisait 709px de haut et repoussait le
   CTA sous la ligne de flottaison sur un portable. Borne, il rend au hero sa
   hauteur d'avant et equilibre les deux colonnes. */
.hero-visual{width:100%;height:auto;display:block;
  filter:drop-shadow(0 26px 46px rgba(2,44,34,.16));}
/* Uniquement le visuel de l'accueil (2026-08-05). .hero-visual est partage
   avec la page investisseurs, dont l'image est en paysage : un max-width pose
   sur la classe commune l'avait rapetissee au passage. Celui-ci ne concerne
   que la fiche en portrait, qui a pleine largeur de colonne repoussait le CTA
   de l'accueil sous la ligne de flottaison.
   Pas de bordure CSS : le cadre est dessine dans le fichier lui-meme. */
/* Ombre plus courte que celle de .hero-visual (2026-08-05) : le hero est en
   overflow:hidden, et l'ombre commune (26px de decalage + 46px de flou, soit
   environ 95px de portee) depassait les 80px de padding bas de l'accueil. Elle
   etait donc coupee net et laissait un trait horizontal en travers de la page.
   16 + 30 tient dans les 80px. L'ombre de la page investisseurs, dont le hero
   a 160px de padding bas, n'est pas touchee. */
.hero-visual-fiche{max-width:430px;margin:0 auto;
  filter:drop-shadow(0 16px 30px rgba(2,44,34,.16));}

/* ---- Carte d'écart de budget (hero propriétaires, 2026-08-07) --------------
   Deux montants, deux barres à la même échelle : la barre du plan est plus
   courte dans la proportion exacte des sommes, de sorte que l'écart se lit
   avant même que les chiffres soient lus. Tout est en encre et en blanc ; la
   seule couleur du bloc est le néon du montant économisé, en bas, sur le
   bandeau forest. C'est le point d'arrivée du regard et le seul accent de la
   carte, conformément à la charte (le néon ne se disperse pas).
   Les libellés sont en JetBrains Mono : c'est le registre du chiffrage
   technique, celui d'un relevé, pas d'une plaquette commerciale. */
.budget{margin:0;background:#fff;border:1px solid var(--line);border-radius:8px;
  overflow:hidden;box-shadow:0 30px 70px -30px rgba(2,44,34,.28);}
/* Paddings verticaux calibres (2026-08-07) pour que la carte depasse legerement
   la colonne de texte en face : a 22/26/20 elle etait 30 a 55px plus courte
   selon la largeur d'ecran, et le hero paraissait desequilibre vers la gauche.
   L'air gagne profite au bloc, c'est pour ca que la hauteur vient des paddings
   et non d'un min-height, qui aurait juste ajoute du vide en bas. */
.budget-head{display:flex;align-items:center;justify-content:space-between;gap:20px;
  padding:29px 30px;border-bottom:1px solid var(--line);background:#fcfdfa;}
.budget-case{font-size:.66rem;text-transform:uppercase;letter-spacing:.1em;color:var(--muted);}
/* Le saut d'étiquettes est l'ancrage DPE de la carte : il dit en un coup d'œil
   de quoi on parle, sans avoir à l'écrire. Format réduit, c'est une mention,
   pas le sujet. */
.budget-jump{display:inline-flex;align-items:center;gap:9px;}
.budget-jump .dpe-letter{width:34px;height:34px;font-size:1.05rem;border-radius:6px;box-shadow:none;}
.budget-jump svg{width:15px;height:15px;color:var(--muted);}

/* Classes explicites plutôt que :first-of-type/:last-of-type : le dernier div
   de la carte est le bandeau du bas, pas la seconde ligne de budget, et la
   barre du plan se retrouvait collée sous lui. */
.budget-row{padding:42px 30px 0;}
.budget-row-plan{padding-bottom:42px;}
.budget-line{display:flex;align-items:baseline;justify-content:space-between;gap:16px;
  margin-bottom:13px;}
.budget-lbl{font-size:.68rem;text-transform:uppercase;letter-spacing:.09em;color:var(--muted);}
.budget-amount{font-size:clamp(1.5rem,2.4vw,1.9rem);font-weight:600;
  font-variant-numeric:tabular-nums;letter-spacing:-.02em;}
/* La ligne des devis reste en encre sourde, celle du plan en forest plein :
   c'est la même donnée, mais une seule des deux est une décision. */
.budget-row-devis .budget-amount{color:var(--muted);}

.budget-bar{display:block;height:12px;border-radius:999px;overflow:hidden;
  background:rgba(2,44,34,.07);}
/* Piste rayée sous la barre du plan : la portion vide n'est pas un manque,
   c'est le budget qui n'est pas dépensé. Les hachures le disent sans légende. */
.budget-bar-cut{background-color:rgba(2,44,34,.045);
  background-image:repeating-linear-gradient(-45deg,
    rgba(2,44,34,.13) 0 1px,transparent 1px 7px);}
.budget-fill{display:block;height:100%;border-radius:999px;
  transform:scaleX(0);transform-origin:left center;
  transition:transform 1.15s cubic-bezier(.2,.75,.2,1) .15s;}
.reveal.in .budget-fill{transform:scaleX(1);}
.budget-fill-devis{width:100%;background:rgba(2,44,34,.2);}
/* 17 000 / 36 081 = 47,1 %. Le chiffre n'est pas arrondi au hasard : si un
   montant change, c'est ce ratio qu'il faut recalculer. */
.budget-fill-plan{width:47.1%;background:var(--forest);}

.budget-foot{display:flex;align-items:center;justify-content:space-between;gap:20px;
  flex-wrap:wrap;padding:26px 30px;background:var(--forest);color:rgba(248,249,235,.72);
  font-size:.82rem;}
.budget-saved strong{display:block;font-family:'Fraunces',Georgia,serif;
  font-variation-settings:'opsz' 144,'SOFT' 50,'WONK' 0;
  font-size:1.65rem;font-weight:600;line-height:1.1;color:var(--neon);
  font-variant-numeric:tabular-nums;}
.budget-link{display:inline-flex;align-items:center;gap:7px;flex:none;
  font-size:.76rem;font-weight:600;color:var(--cream);
  border-bottom:1px solid rgba(248,249,235,.3);padding-bottom:2px;
  transition:border-color .2s ease,color .2s ease;}
.budget-link svg{width:14px;height:14px;transition:transform .25s ease;}
.budget-link:hover{color:var(--neon);border-color:var(--neon);}
.budget-link:hover svg{transform:translateX(3px);}
.budget-link:focus-visible{outline:2px solid var(--neon);outline-offset:3px;}
@media(prefers-reduced-motion:reduce){
  .budget-fill{transform:none;transition:none;}
  .budget-link svg{transition:none;}
}
@media(max-width:560px){
  .budget-head{padding:18px 20px;}
  /* Le padding bas est repris ici : sans lui, la regle courte de .budget-row,
     declaree plus tard, l'emporte sur .budget-row-plan a specificite egale et
     la barre du plan vient toucher le bandeau. */
  .budget-row{padding:22px 20px 0;}
  .budget-row-plan{padding-bottom:24px;}
  .budget-foot{padding:18px 20px;}
  /* Le libellé et le montant ne tiennent plus sur une ligne à cette largeur
     sans que le montant se réduise sous sa taille de lecture. */
  .budget-line{flex-direction:column;align-items:flex-start;gap:4px;}
}
/* DPE ladder signature */
.dpe-card{background:#fff;border-radius:8px;padding:30px;border:1px solid var(--line);
  box-shadow:0 30px 70px -30px rgba(2,44,34,.28);position:relative;}
.dpe-head{display:flex;justify-content:space-between;align-items:baseline;margin-bottom:20px;}
.dpe-head .t{font-weight:600;font-size:.95rem;}
.dpe-head .s{font-size:.72rem;text-transform:uppercase;letter-spacing:.1em;color:var(--muted);}
.ladder{display:flex;flex-direction:column;gap:9px;}
.rung{display:flex;align-items:center;gap:12px;}
.rung .lt{width:24px;font-weight:700;text-align:center;font-size:.95rem;color:var(--ink);flex:none;}
.rung .bar{height:26px;border-radius:6px;display:flex;align-items:center;padding:0 10px;color:#fff;font-size:.7rem;font-weight:600;
  transform-origin:left;animation:grow .9s cubic-bezier(.25,.8,.25,1) both;}
@keyframes grow{from{transform:scaleX(.2);opacity:0;}to{transform:scaleX(1);opacity:1;}}
.rung .tag{margin-left:auto;font-size:.68rem;font-weight:700;padding:3px 10px;border-radius:999px;white-space:nowrap;}
.tag-now{background:rgba(226,72,58,.12);color:#c23a2e;border:1px solid rgba(226,72,58,.3);}
.tag-goal{background:var(--forest);color:var(--neon);}
.dpe-foot{margin-top:22px;display:flex;align-items:center;gap:10px;font-size:.8rem;color:var(--muted);}
.dpe-foot .mono{color:var(--ink);}

/* cards */
.cards-3{display:grid;grid-template-columns:repeat(3,1fr);gap:22px;margin-top:94px;}
@media(max-width:820px){.cards-3{grid-template-columns:1fr;}}
.card{border-radius:8px;padding:28px;transition:transform .35s cubic-bezier(.25,.8,.25,1),box-shadow .35s,border-color .35s;}
.card-ico{width:46px;height:46px;border-radius:8px;display:flex;align-items:center;justify-content:center;margin-bottom:18px;}
.card-ico svg{width:22px;height:22px;}
.card h3{font-size:1.12rem;margin:0 0 8px;font-weight:600;}
.card p{margin:0;font-size:.95rem;}
/* multi-ton cards on dark */
.on-dark .card-cream{background:var(--cream);color:var(--ink);}
.on-dark .card-cream p{color:var(--muted);}
.on-dark .card-cream .card-ico{background:#fff;color:var(--forest);}
.on-dark .card-neon{background:var(--neon);color:var(--forest);}
.on-dark .card-neon p{color:rgba(2,44,34,.72);}
.on-dark .card-neon .card-ico{background:#fff;color:var(--forest);}
.on-dark .card-outline{background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.12);color:var(--cream);}
.on-dark .card-outline p{color:rgba(248,249,235,.7);}
.on-dark .card-outline .card-ico{background:rgba(0,255,171,.12);color:var(--neon);}
.on-dark .card:hover{transform:translateY(-6px);}
/* multi-ton cards on light */
.card-greige{background:var(--greige);}
.card-greige p{color:var(--muted);}
.card-greige .card-ico{background:#fff;color:var(--forest);}
.card-white{background:#fff;border:1px solid var(--line);box-shadow:0 4px 20px rgba(2,44,34,.04);}
.card-white p{color:var(--muted);}
.card-white .card-ico{background:var(--cream);color:var(--forest);}
.card:hover{box-shadow:0 24px 50px -22px rgba(2,44,34,.18);}
/* pattern « grille papier millimétré » (charte) : TOUJOURS derrière la carte et débordant du coin,
   jamais clippé dans la carte. La carte opaque masque la partie qu'elle recouvre,
   seul le débord hors de la carte reste visible.

   COMMENT C'EST GARANTI (2026-08-14) : le motif est en z-index:-1 et sa
   section est un contexte d'empilement (règle .section:has(...) plus bas).
   Il est donc peint juste au-dessus du fond de section et EN DESSOUS de tout
   le contenu, positionné ou non, à l'intérieur comme à l'extérieur de son
   conteneur. C'est le seul montage qui tienne sans exception de mise en page :
   à z-index:0 il passait devant tout élément non positionné, ce qui se voyait
   surtout en mobile, où le débord de 200px vers le haut retombe sur la carte
   précédente d'une grille passée en une colonne.
   À RETENIR pour un futur ajout : poser .grille-accent dans un conteneur en
   position:relative (.card-wrap, .grille-wrap, ou un bloc déjà positionné) et
   ne rien ajouter d'autre. Ne jamais remonter son z-index, et ne pas créer de
   contexte d'empilement entre lui et sa section (transform, filter, opacity < 1
   ou isolation sur un bloc intermédiaire), sinon il repasserait devant. */
.card-wrap{position:relative;display:flex;}
.card-wrap > .card,
.card-wrap > .review{flex:1;} /* la carte s'étire à la hauteur de la rangée comme les autres */
.grille-accent{position:absolute;z-index:-1;pointer-events:none;
  top:-200px;right:-200px;width:440px;height:440px;   /* centré ~ sur le coin haut-droit de la carte */
  background-size:44px 44px;
  background-image:
    linear-gradient(to right,rgba(2,44,34,.12) 1px,transparent 1px),
    linear-gradient(to bottom,rgba(2,44,34,.12) 1px,transparent 1px);
  -webkit-mask-image:radial-gradient(circle at center,#000 24%,transparent 74%);
  mask-image:radial-gradient(circle at center,#000 24%,transparent 74%);}
/* Variante coin haut-gauche. La règle existait depuis le 2026-07-28 mais était
   câblée sur `.id-card-wrap > .grille-tl` (page à propos), donc inutilisable
   ailleurs : elle est ici générique, et .id-card-wrap ne garde que son propre
   décalage vertical. */
.grille-tl{top:-200px;left:-200px;right:auto;}
/* À poser sur le bloc derrière lequel le motif doit apparaître, quand ce bloc
   n'est pas déjà .card-wrap. Le motif est en position:absolute : sans ancêtre
   positionné il se calerait sur le viewport et partirait n'importe où. */
.grille-wrap{position:relative;}
/* Le contexte d'empilement qui rend le z-index:-1 du motif opérant : sans lui,
   le motif remonterait jusqu'à la racine et passerait DERRIÈRE le fond de la
   section, donc invisible. Posé sur la section (et sur le hero), il le garde
   entre le fond et le contenu. z-index:0 et non une valeur plus haute : la
   section ne doit pas changer de rang vis-à-vis de ses voisines, seulement
   ouvrir un contexte. */
.section:has(.grille-accent),.section:has(.bento-grid-pattern),
.hero:has(.grille-accent){position:relative;z-index:0;}

/* offer card */
.offer{background:var(--forest);color:var(--cream);border-radius:8px;padding:52px;margin-top:94px;position:relative;overflow:hidden;}
.offer .badge{display:inline-block;font-size:.72rem;font-weight:700;text-transform:uppercase;letter-spacing:.12em;
  color:var(--neon);background:rgba(0,255,171,.1);border:1px solid rgba(0,255,171,.3);padding:5px 13px;border-radius:999px;margin-bottom:20px;}
.offer h3{font-size:clamp(1.6rem,3vw,2.1rem);margin:0 0 16px;font-weight:500;}
.offer p{color:rgba(248,249,235,.75);max-width:560px;margin:0 0 14px;}
.offer .btn{margin-top:20px;}
.offer .glow{position:absolute;right:-80px;top:-80px;width:280px;height:280px;border-radius:50%;background:radial-gradient(circle,rgba(0,255,171,.16),transparent 70%);}

/* offre section reworked (2026-07-08) */
.round-top{border-top-left-radius:var(--radius-section);border-top-right-radius:var(--radius-section);
  margin-top:-40px;position:relative;z-index:2;}
.offre-grid{display:grid;grid-template-columns:1fr 1fr;gap:48px;align-items:center;margin-top:94px;}
@media(max-width:900px){.offre-grid{grid-template-columns:1fr;gap:40px;}}
.offre-text{text-align:left;}
/* position:relative et z-index indispensables, pas cosmétiques : le motif
   millimétré du bento (.bento-grid-pattern) est positionné en z-index:0, ce qui
   suffit à le peindre AU-DESSUS de tout contenu non positionné, même situé
   avant lui dans le DOM. Sans cette règle il passait devant le bouton « Voir un
   exemple de chiffrage » dès que la grille tombait sur une colonne et que son
   débord haut remontait sur la colonne de texte. Même piège que .grille-wrap,
   documenté plus haut. */
.offre-text{position:relative;z-index:1;}
.offre-text p{color:var(--muted);margin:0 0 16px;}
.offre-text .btn{margin-top:14px;}
/* grid-auto-rows monté de 158 à 188px le 2026-08-03 : à 158, les deux tuiles
   de gauche étaient plus larges que hautes et le bento paraissait écrasé face
   à la colonne de texte. La photo occupe deux rangées, elle grandit d'autant. */
.offre-bento{display:grid;grid-template-columns:1fr 1fr;grid-auto-rows:188px;gap:16px;position:relative;}
/* z-index:-1 pour la même raison que .grille-accent, voir le commentaire long
   qui accompagne ce dernier : le motif doit rester sous tout le contenu. */
.bento-grid-pattern{position:absolute;top:-125px;right:-150px;width:490px;height:490px;pointer-events:none;z-index:-1;background-size:44px 44px;background-image:linear-gradient(to right,rgba(2,44,34,.12) 1px,transparent 1px),linear-gradient(to bottom,rgba(2,44,34,.12) 1px,transparent 1px);-webkit-mask-image:radial-gradient(circle at center,#000 24%,transparent 74%);mask-image:radial-gradient(circle at center,#000 24%,transparent 74%);}
/* Les deux motifs de grille (.bento-grid-pattern, .grille-accent) débordent
   volontairement de leur bloc par la droite, mais à partir d'un
   certain écran elle dépasse aussi le viewport : la page devient plus large que
   l'écran et, dès qu'on la décale d'un cran, on voit une bande de crème (le fond
   du body) à droite des sections. On coupe donc à la section : le débord voulu
   sur le coin du bento reste visible, seul ce qui sort de la page est rogné.
   overflow-x:clip et non hidden, qui aurait rendu la section scrollable et
   surtout forcé overflow-y:auto, coupant le visuel qui la recouvre par le haut. */
.section:has(.bento-grid-pattern),.section:has(.grille-accent),
.hero:has(.grille-accent){overflow-x:clip;}
/* Cas particulier : quand le motif est ancré sur une bande de couleur pleine
   et non sur une carte, son débord VERTICAL sort de la bande et se voit sur la
   section voisine, qui n'a pas la même couleur de fond. `overflow-x:clip` ne
   coupe que l'horizontale, d'où la coupe sur les deux axes ici. Le motif se
   lit alors comme émergeant du coin de la bande, ce qui est l'intention.
   Ne pas généraliser aux sections dont le motif est posé derrière une carte :
   là, le débord hors de la carte est justement ce qu'on veut voir. */
.section.bg-neon:has(.grille-accent){overflow:clip;}
@media(max-width:520px){.offre-bento{grid-auto-rows:160px;}}
.bento-box{border-radius:8px;padding:22px;display:flex;flex-direction:column;justify-content:space-between;overflow:hidden;position:relative;z-index:1;}
.bento-dark{background:var(--forest);color:var(--cream);grid-column:1;grid-row:1;}
.bento-greige{background:var(--greige);color:var(--ink);grid-column:1;grid-row:2;}
.bento-img{grid-column:2;grid-row:1 / span 2;padding:0;}
.bento-img img{width:100%;height:100%;object-fit:cover;border-radius:8px;display:block;}
/* tuile « document » : aplat vert, image détourée posée dessus (pas de crop) */
.bento-doc{background:#24e19f;display:flex;align-items:center;justify-content:center;padding:26px;}
.bento-doc img{width:100%;height:100%;object-fit:contain;border-radius:0;filter:drop-shadow(0 18px 32px rgba(2,44,34,.28));}
.bento-ico{width:42px;height:42px;border-radius:8px;display:flex;align-items:center;justify-content:center;}
.bento-ico svg{width:20px;height:20px;}
.bento-dark .bento-ico{background:rgba(0,255,171,.12);color:var(--neon);}
.bento-greige .bento-ico{background:#fff;color:var(--forest);}
.bento-box .bt{font-weight:600;font-size:.98rem;line-height:1.4;}
.bento-dark .bt{color:#fff;}

/* ---- Bento « dossier de financement » en mobile (2026-08-14) ----
   La grille restait en deux colonnes quelle que soit la largeur : sur un
   téléphone, le DPE projeté se retrouvait dans une demi-colonne de 165px, en
   object-fit:contain, donc réduit à une vignette illisible. Or c'est LA preuve
   que la banque réclame, les deux autres tuiles ne sont que des mentions.
   Le document passe donc seul, en pleine largeur et en premier, et les deux
   mentions deviennent des pastilles posées dessus, en haut et en bas. Elles
   gardent leurs couleurs respectives (forest et greige).
   Les hauteurs des pastilles sont en pourcentage et non en pixels : elles
   doivent laisser lisible la bande « Performance énergétique et climatique »,
   qui porte l'étiquette D et le filigrane « Projeté », et qui occupe le tiers
   central du document quelle que soit la taille du rendu. */
@media(max-width:760px){
  .offre-bento{display:block;}
  /* Le document reprend sa proportion naturelle (900x1186) au lieu d'être
     étiré sur deux rangées de hauteur fixe.
     Plus d'aplat vert ni de padding : l'aplat servait à donner un corps à une
     tuile de bento parmi trois. Ici le document EST le bloc, il occupe toute la
     largeur, et le vert ne faisait plus que le rétrécir.
     Fond blanc et non transparent : l'image porte une marge blanche opaque tout
     autour de l'éventail, qui se détacherait en rectangle sur le crème. Le blanc
     de la tuile la prolonge, et l'ensemble se lit comme une feuille posée.
     Ne pas essayer de rendre ce blanc transparent dans le fichier : il communique
     avec le fond blanc des pages placées derrière la première, qui perdent alors
     le leur et laissent voir l'aplat vert au travers en desktop (essayé le
     2026-08-14, annulé). */
  .bento-img{padding:0;background:#fff;}
  .bento-doc img{height:auto;}
  .offre-bento .bento-dark,
  .offre-bento .bento-greige{position:absolute;z-index:2;
    flex-direction:row;align-items:center;justify-content:flex-start;gap:9px;
    width:auto;padding:9px 15px 9px 11px;border-radius:999px;
    box-shadow:0 10px 24px -12px rgba(2,44,34,.5);}
  /* Sous l'en-tête du document et au-dessus de l'étiquette énergie pour la
     première, sous le tableau des coûts pour la seconde. */
  .offre-bento .bento-dark{top:15%;left:6px;}
  .offre-bento .bento-greige{bottom:11%;right:6px;}
  .offre-bento .bento-ico{width:26px;height:26px;border-radius:50%;flex:none;}
  .offre-bento .bento-ico svg{width:15px;height:15px;}
  .offre-bento .bento-box .bt{font-size:.8rem;line-height:1.25;}
}

/* faq */
.faq-list{display:flex;flex-direction:column;gap:12px;margin-top:90px;max-width:820px;margin-left:auto;margin-right:auto;}
/* le bandeau final est une cible d'ancre (#commander) : on dégage la hauteur du header */
.peps{scroll-margin-top:var(--chrome-h);}
details{background:#fff;border:1px solid var(--line);border-radius:8px;overflow:hidden;transition:border-color .3s;}
details[open]{border-color:rgba(0,255,171,.4);}
summary{list-style:none;cursor:pointer;padding:22px 26px;display:flex;justify-content:space-between;align-items:center;gap:16px;font-weight:500;font-size:1.04rem;}
summary::-webkit-details-marker{display:none;}
summary .chev{transition:transform .3s;color:var(--pine);flex:none;}
summary .chev svg{width:20px;height:20px;}
details[open] summary .chev{transform:rotate(180deg);}
.faq-body{padding:0 26px 24px;color:var(--muted);font-size:.98rem;line-height:1.4;}

/* author (accueil) + about (page à propos) : layout portrait + texte partagé */
.author-grid{display:grid;grid-template-columns:.8fr 1.2fr;gap:56px;align-items:center;}
@media(max-width:860px){.author-grid{grid-template-columns:1fr;gap:36px;}}
.about-hero{padding-top:calc(var(--chrome-h) + 6rem);padding-bottom:var(--pad-lg);}
.about-grid{display:grid;grid-template-columns:.8fr 1.2fr;gap:56px;align-items:center;}
@media(max-width:860px){.about-grid{grid-template-columns:1fr;gap:36px;}}
.portrait{position:relative;border-radius:8px;overflow:hidden;aspect-ratio:4/5;
  box-shadow:0 30px 60px -28px rgba(2,44,34,.4);
  }
.portrait-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;filter:grayscale(1);transition:filter .6s ease,transform .6s ease;}
.portrait:hover .portrait-img{filter:grayscale(0);transform:scale(1.03);}
.portrait .scrim{position:absolute;inset:0;background:linear-gradient(to top,rgba(2,44,34,.92),rgba(2,44,34,.1) 55%,transparent);z-index:1;}
.portrait .ph-label{position:absolute;inset:0;display:flex;align-items:flex-end;padding:26px;color:rgba(248,249,235,.9);z-index:2;}
.portrait .ph-label .n{font-family:'Fraunces';font-variation-settings:'opsz' 144,'SOFT' 50,'WONK' 0;font-size:1.7rem;line-height:1.1;}
.portrait .ph-label .r{font-size:.72rem;text-transform:uppercase;letter-spacing:.13em;color:var(--neon);margin-top:6px;}
.portrait .ph-note{position:absolute;top:16px;left:16px;font-size:.68rem;color:rgba(248,249,235,.5);background:rgba(0,0,0,.25);padding:4px 9px;border-radius:6px;}

/* hero « à propos » : en-tête centré + bande d'images (façon Treso2) */
.hero-head{max-width:820px;margin:0 auto;text-align:center;}
.hero-head .lead{max-width:640px;margin:0 auto 0;}
.hero-head .tagline{font-weight:600;margin:16px 0 0;}
.hero-strip{display:grid;grid-template-columns:repeat(5,1fr);gap:18px;margin-top:64px;align-items:start;}
.shot{position:relative;border-radius:8px;overflow:hidden;aspect-ratio:4/5;box-shadow:0 24px 50px -30px rgba(2,44,34,.35);}
.shot img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;transition:transform .5s ease;}
.shot:not(.shot-hero):hover img{transform:scale(1.05);} /* pas de hover sur le portrait (.shot-hero) */
/* ombre dégradée + mini-description en bas de chaque image (Geist, blanc) */
.shot .cap{position:absolute;left:0;right:0;bottom:0;z-index:1;padding:16px 14px 12px;
  background:linear-gradient(to top,rgba(2,44,34,.82),rgba(2,44,34,.32) 55%,transparent);
  color:#fff;font-size:.85rem;font-weight:400;line-height:1.25;}
.shot-hero{aspect-ratio:3/4;}                      /* portrait de Loïs : image centrale, plus haute */
.shot-hero .cap .n{font-size:1.15rem;font-weight:600;line-height:1.15;display:block;}
.shot-hero .cap .r{font-size:.66rem;font-weight:600;text-transform:uppercase;letter-spacing:.12em;color:var(--neon);margin-top:4px;display:block;} /* seul le titre reste en vert clair */
/* Les cinq photos sont réparties en deux .row dans le HTML, pour l'éventail
   mobile plus bas. En desktop et en tablette ces rangées doivent disparaître :
   display:contents rend les .shot enfants directs de la grille, comme avant. */
.hero-strip .row{display:contents;}
@media(min-width:901px){                            /* décalage vertical symétrique, Loïs (centre) au sommet */
  .hero-strip .row-1 .shot:nth-child(1){margin-top:48px;}
  .hero-strip .row-1 .shot:nth-child(2){margin-top:24px;}
  .hero-strip .row-2 .shot:nth-child(1){margin-top:24px;}
  .hero-strip .row-2 .shot:nth-child(2){margin-top:48px;}
}
@media(max-width:900px){                            /* tablette : 3 colonnes, sans décalage */
  .hero-strip{grid-template-columns:repeat(3,1fr);gap:14px;margin-top:48px;}
  .shot-hero{aspect-ratio:4/5;}
}

/* -----------------------------------------------------------------------------
   MOBILE : DOUBLE ÉVENTAIL 3 + 2 (2026-08-14)
   En grille à deux colonnes, cinq photos laissent la cinquième seule sur sa
   ligne, ce qui se voyait comme un oubli. Elles sont donc empilées en deux
   rangées qui se chevauchent, façon photos posées sur une table : trois en
   haut (chantier 1, chantier 2, portrait), deux en bas.
   Les cinq légendes restent lisibles SANS toucher l'écran, condition posée
   avant d'accepter ce parti pris : la bande raconte une chronologie 1 -> 4,
   une légende cachée derrière un tap aurait été perdue pour presque tout le
   monde. Seul le bord droit d'une carte passe sous sa voisine, les rangées
   elles ne se recouvrent jamais (la haute a le z-index le plus fort), donc
   rendre --ov au texte en padding droit suffit.
   Le tap ne sert plus qu'à redresser et agrandir une carte, c'est du confort,
   pas un passage obligé pour lire. */
@media(max-width:560px){
  /* Recouvrement en px et NON en % : une marge négative en % se calcule sur la
     largeur de la rangée, pas sur celle de la carte, et le padding de la
     légende ne compenserait plus la bonne largeur. */
  .hero-strip{--ov:24px;display:block;padding-inline:14px;}
  .hero-strip .row{display:flex;justify-content:center;align-items:flex-start;}
  /* Liseré crème : sans lui deux photos qui se chevauchent se lisent comme un
     seul collage, les angles arrondis disparaissant sous la voisine. */
  .hero-strip .shot{position:relative;background:var(--cream);
    border:5px solid var(--cream);transform-origin:50% 100%;
    transition:transform .35s ease,box-shadow .35s ease;
    -webkit-tap-highlight-color:transparent;}
  /* z-index porté par les cartes et pas par les rangées : une rangée qui en
     porte un devient un contexte d'empilement, et la carte mise au premier
     plan resterait prisonnière de sa rangée. */
  .hero-strip .row-1 .shot{width:38%;z-index:2;}
  .hero-strip .row-2 .shot{width:42%;z-index:1;}
  .hero-strip .row .shot + .shot{margin-left:calc(-1 * var(--ov));}
  .hero-strip .row-2{margin-top:-9%;}
  .hero-strip .row-1 .shot:nth-child(1){transform:rotate(-5deg) translateY(6px);}
  .hero-strip .row-1 .shot:nth-child(3){transform:rotate(5deg) translateY(6px);}
  .hero-strip .row-2 .shot:nth-child(1){transform:rotate(-4deg) translateY(5px);}
  .hero-strip .row-2 .shot:nth-child(2){transform:rotate(4deg) translateY(5px);}
  .hero-strip .shot-hero{aspect-ratio:4/5;}
  /* Cartes deux fois moins larges qu'en desktop : à la taille d'origine la
     légende partait en cinq lignes. */
  .hero-strip .shot .cap{padding:12px 10px 9px;font-size:.72rem;line-height:1.2;
    padding-right:calc(var(--ov) + 10px);}
  .hero-strip .row .shot:last-child .cap{padding-right:10px;}
  /* Les deux lignes de titres sous le nom sautent : sur une carte de 130px de
     large elles prennent cinq lignes et recouvrent le visage, qui est la seule
     raison d'être de cette photo. Le nom suffit, les titres sont répétés en
     toutes lettres dans la section « Une expertise construite » juste dessous. */
  .hero-strip .shot-hero .cap .n{font-size:.95rem;}
  .hero-strip .shot-hero .cap .r{display:none;}
  /* Carte mise au premier plan au tap (classe posée par le script de la page). */
  .hero-strip .shot.is-front{z-index:9;box-shadow:0 30px 60px -24px rgba(2,44,34,.5);}
  .hero-strip .row .shot.is-front{transform:rotate(0) scale(1.08);}
  .hero-strip .shot.is-front .cap{padding-right:10px;}
}

.checklist{list-style:none;padding:0;margin:22px 0;display:grid;grid-template-columns:1fr 1fr;gap:12px;}
@media(max-width:520px){.checklist{grid-template-columns:1fr;}}
.checklist li{display:flex;align-items:center;gap:10px;font-weight:500;font-size:.98rem;}
.checklist .ck{width:24px;height:24px;border-radius:7px;background:var(--cream);border:1px solid var(--line);display:flex;align-items:center;justify-content:center;color:var(--pine);flex:none;}
.checklist .ck svg{width:14px;height:14px;}

/* citation suricate (page à propos) */
.quote-section{position:relative;overflow:hidden;}
.quote{position:relative;z-index:1;max-width:760px;margin:0 auto;text-align:center;}
.quote-mark{color:var(--neon);font-family:'Fraunces';font-style:italic;font-variation-settings:'opsz' 144,'SOFT' 50,'WONK' 0;
  font-size:6rem;line-height:.5;margin-bottom:26px;display:block;height:.55em;}
.quote p{font-family:'Fraunces';font-variation-settings:'opsz' 144,'SOFT' 50,'WONK' 0;font-size:clamp(1.5rem,3vw,2.1rem);font-weight:400;color:#fff;line-height:1.2;margin:0;}
/* citation sur fond neon : texte et guillemet en vert forêt */
.bg-neon .quote p{color:var(--forest);}
.bg-neon .quote-mark{color:var(--forest);}

/* timeline formations (page à propos) */
.timeline{display:flex;flex-direction:column;gap:0;max-width:720px;margin:90px auto 0;}
.tl-item{display:flex;gap:24px;position:relative;padding-bottom:40px;}
.tl-item:last-child{padding-bottom:0;}
.tl-marker{flex:none;display:flex;flex-direction:column;align-items:center;}
.tl-dot{width:14px;height:14px;border-radius:50%;background:var(--pine);border:3px solid var(--cream);box-shadow:0 0 0 1px var(--line);transition:background .25s ease, box-shadow .25s ease, transform .25s ease;}
.tl-item:hover .tl-dot{background:var(--neon);box-shadow:0 0 0 1px rgba(0,255,171,.5), 0 0 0 5px rgba(0,255,171,.18);transform:scale(1.15);}
.tl-line{flex:1;width:1px;background:var(--line);margin-top:4px;}
.tl-item:last-child .tl-line{display:none;}
.tl-body{padding-top:-2px;}
.tl-body h3{font-size:1.05rem;margin:0 0 6px;font-weight:600;}
.tl-body p{margin:0;font-size:.95rem;color:var(--muted);}

/* infos perso (page à propos) */
.facts{display:flex;flex-wrap:wrap;gap:14px;margin-top:26px;}
.fact{display:inline-flex;align-items:center;gap:9px;background:#fff;border:1px solid var(--line);border-radius:999px;padding:9px 16px 9px 12px;font-size:.9rem;font-weight:500;}
.fact svg{width:17px;height:17px;color:var(--pine);flex:none;}

/* carte d'identité */
.id-accent{font-style:italic;}
.id-card-wrap{position:relative;max-width:890px;margin:94px auto 0;}
.id-card-wrap > .grille-tl{top:-190px;}
.id-card{background:#fff;border:1px solid var(--line);border-radius:8px;overflow:hidden;
  box-shadow:0 40px 90px -40px rgba(2,44,34,.35);position:relative;z-index:1;}
.id-card::before{content:"";position:absolute;inset:0;pointer-events:none;z-index:0;opacity:.5;
  background-image:radial-gradient(rgba(2,44,34,.05) 1px,transparent 1.4px);background-size:22px 22px;}
.id-card-head{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:16px 26px;
  background:var(--forest);color:var(--cream);position:relative;z-index:1;}
.id-card-country{font-family:'Fraunces',Georgia,serif;font-variation-settings:'opsz' 144,'SOFT' 50,'WONK' 0;font-size:1.05rem;font-weight:600;}
.id-card-type{font-family:'JetBrains Mono',monospace;font-size:.66rem;letter-spacing:.18em;text-transform:uppercase;
  color:var(--neon);border:1px solid rgba(0,255,171,.35);border-radius:999px;padding:5px 12px;white-space:nowrap;}
.id-card-body{display:grid;grid-template-columns:200px 1fr;gap:40px;padding:34px 40px 30px;position:relative;z-index:1;align-items:start;}
.id-photo{position:relative;border-radius:8px;overflow:hidden;aspect-ratio:3/4;background:var(--greige);
  border:1px solid var(--line);box-shadow:0 20px 40px -22px rgba(2,44,34,.4);}
.id-photo img{width:100%;height:100%;object-fit:cover;display:block;filter:grayscale(.12);}
.id-photo-tag{position:absolute;left:8px;bottom:8px;right:8px;font-family:'JetBrains Mono',monospace;font-size:.6rem;
  letter-spacing:.14em;text-align:center;color:#fff;background:rgba(2,44,34,.72);border-radius:5px;padding:4px 6px;backdrop-filter:blur(2px);}
.id-fields{display:flex;flex-direction:column;gap:15px;margin:0;}
.id-field{display:flex;align-items:flex-start;gap:14px;padding-bottom:15px;border-bottom:1px dashed var(--line);}
.id-field:last-child{border-bottom:none;padding-bottom:0;}
.id-ico{flex:none;width:36px;height:36px;border-radius:8px;background:var(--cream);border:1px solid var(--line);
  display:flex;align-items:center;justify-content:center;color:var(--pine);margin-top:1px;}
.id-ico svg{width:19px;height:19px;}
.id-field dt{font-size:.68rem;text-transform:uppercase;letter-spacing:.1em;color:var(--pine);font-weight:600;margin-bottom:3px;}
.id-field dd{margin:0;font-size:.92rem;color:var(--ink);line-height:1.45;}
.id-note{color:var(--muted);font-style:italic;}
.id-mrz{font-family:'JetBrains Mono',monospace;font-size:clamp(.6rem,1.5vw,.82rem);letter-spacing:.12em;
  color:rgba(2,44,34,.42);background:var(--cream);border-top:1px solid var(--line);padding:14px 26px;
  overflow:hidden;white-space:nowrap;text-overflow:ellipsis;position:relative;z-index:1;}
@media(max-width:620px){
  .id-card-body{grid-template-columns:1fr;gap:26px;padding:28px 24px 24px;}
  .id-photo{max-width:170px;aspect-ratio:3/4;}
}

/* articles */
.art-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:24px;margin-top:94px;}
@media(max-width:860px){.art-grid{grid-template-columns:1fr;}}
.art{background:#fff;border:1px solid var(--line);border-radius:8px;overflow:hidden;transition:transform .35s cubic-bezier(.25,.8,.25,1),box-shadow .35s;display:flex;flex-direction:column;}
/* Au survol c'est la carte entière qui monte et grossit très légèrement.
   Ne jamais zoomer l'image seule à l'intérieur d'un cadre fixe : l'image
   bouge pendant que la carte reste immobile, ce qui donne un effet bancal. */
.art:hover{transform:translateY(-6px) scale(1.02);box-shadow:0 26px 50px -24px rgba(2,44,34,.2);}
.art .thumb{aspect-ratio:16/10;background:linear-gradient(135deg,#e3e6d2,#d5dcc4);position:relative;display:flex;align-items:center;justify-content:center;color:rgba(2,44,34,.3);}
.art .thumb svg{width:34px;height:34px;}
.art .body{padding:24px;display:flex;flex-direction:column;flex:1;}
.art .date{font-size:.72rem;text-transform:uppercase;letter-spacing:.1em;color:var(--pine);font-weight:600;margin-bottom:10px;}
.art h3{font-size:1.1rem;line-height:1.3;margin:0 0 10px;font-weight:500;}
.art p{font-size:.9rem;color:var(--muted);margin:0 0 18px;flex:1;}

.center{text-align:center;}
/* 44 → 72px le 2026-08-07. La charte a deja tranche que 44px etait trop serre
   entre un en-tete de section et le bloc qui suit (elle y impose ~90px) ; la
   meme valeur produisait ici un CTA colle au bloc du dessus, a 68px de lui pour
   104px jusqu'au bas de section. A 72px, l'ecart visuel monte a ~96px et le
   bouton se pose au milieu de son air au lieu de pendre sous les cartes.
   L'exception .stack + .mt-cta (100px) reste prioritaire, elle est plus
   specifique. */
.mt-cta{margin-top:72px;}

/* showcase */
.showcase{position:relative;min-height:680px;display:flex;align-items:flex-start;justify-content:center;text-align:center;padding:96px 24px 80px;background-size:cover;background-position:center;overflow:hidden;}
.showcase::before{content:"";position:absolute;inset:0;background:linear-gradient(to bottom,rgba(2,44,34,.9) 0%,rgba(2,44,34,.5) 38%,rgba(2,44,34,.35) 68%,rgba(2,44,34,.55) 100%);}
.showcase-content{position:relative;z-index:1;max-width:820px;}
.showcase h2{color:#fff;font-size:clamp(2rem,4.5vw,3rem);font-weight:400;line-height:1.12;margin:0;}

/* peps */
.peps{text-align:center;}
.peps .h2{color:var(--forest);max-width:720px;margin-inline:auto;}
.peps p{color:rgba(2,44,34,.7);max-width:520px;margin:0 auto 30px;}
.peps-ctas{display:flex;gap:16px;justify-content:center;flex-wrap:wrap;}

/* contact + footer */
.contact-grid{display:grid;grid-template-columns:1fr 1fr;gap:56px;align-items:start;}
@media(max-width:820px){.contact-grid{grid-template-columns:1fr;gap:40px;}}
.form{display:flex;flex-direction:column;gap:16px;}
.form input,.form textarea{background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.14);border-radius:8px;
  padding:15px 17px;color:var(--cream);font-family:inherit;font-size:1rem;transition:border-color .3s,background .3s;}
.form input::placeholder,.form textarea::placeholder{color:rgba(248,249,235,.45);}
.form input:focus,.form textarea:focus{outline:none;border-color:var(--neon);background:rgba(0,255,171,.05);}
.form textarea{min-height:130px;resize:vertical;}
/* ---- footer complet (corps + sub-footer), injecté par layout.js ---- */
.footer-full{background:var(--forest);color:var(--cream);padding:96px 0 34px;}
/* Quand le footer suit une section déjà en vert foncé (contact), on réduit le
   padding haut : les deux blocs se fondent et l'écart resterait sinon énorme.
   On garde un peu d'air pour que le cadre ne colle pas à la section du dessus. */
.bg-forest + .footer-full{padding-top:40px;}

/* Raccord arrondi entre une section claire et le footer : le footer remonte de
   40px et la section qui le précède porte un arrondi bas, si bien que le vert
   foncé du footer apparaît dans les deux coins. Le padding haut compense la
   remontée pour que le contenu du footer garde son air.
   Ne s'applique pas quand la section précédente est déjà en vert foncé
   (section contact de l'accueil) : les deux blocs s'y fondent déjà. */
section:not(.bg-forest) + .footer-full{margin-top:-40px;padding-top:136px;}
section:not(.bg-forest):has(+ .footer-full){
  position:relative;z-index:1;
  border-bottom-left-radius:var(--radius-section);border-bottom-right-radius:var(--radius-section);}

/* Cadre qui encadre l'ensemble du footer. Le padding latéral est porté par les
   blocs internes et non par le cadre, pour que le filet du sub-footer coure
   d'un bord à l'autre. */
/* 1px est le minimum fiable sur un écran non-HiDPI : pour affiner le trait on
   joue sur l'opacité du néon, pas sur l'épaisseur. */
.footer-frame{border:1px solid rgba(0,255,171,.45);position:relative;}

/* Trait vertical unique, centré, qui relie le haut du cadre à la section
   précédente, pour que le footer y soit visiblement accroché au lieu de
   flotter dans le vert foncé. Mêmes trait et opacité que le cadre.

   Uniquement quand le footer suit une section claire : c'est le seul cas où il
   remonte de 40px avec un padding haut de 136px, soit 136 - 40 = 96px de vert
   foncé entre le bas de la section et le haut du cadre. Toucher à l'un de ces
   trois nombres impose de recaler la hauteur ci-dessous. Quand la section
   précédente est déjà en forest (contact.html, à propos), les deux blocs se
   fondent, l'écart n'est que de 40px et le trait n'aurait rien à relier.

   Posé en bottom:100% et non en hauteur négative : la section précédente est
   en z-index 1 et recouvrirait tout dépassement. Le demi-pixel de retrait
   centre un trait de largeur impaire, qui sinon tombe à côté de l'axe. */
section:not(.bg-forest) + .footer-full .footer-frame::before{
  content:"";position:absolute;bottom:100%;left:50%;transform:translateX(-.5px);
  width:1px;height:96px;background:rgba(0,255,171,.45);pointer-events:none;}

.footer-top{display:flex;align-items:center;justify-content:space-between;gap:24px;flex-wrap:wrap;
  padding:44px 40px 0;}
/* Logo complet en version claire (blanc + néon), fourni pour fond sombre.
   Hauteur fixe, largeur libre : le ratio du fichier (2,83) fait le reste. */
.footer-brand{display:block;}
.footer-brand img{height:72px;width:auto;}
@media(max-width:560px){.footer-brand img{height:52px;}}
.footer-social{display:flex;gap:10px;}
.footer-social-btn{display:grid;place-items:center;width:38px;height:38px;border-radius:8px;
  border:1px solid rgba(248,249,235,.18);color:rgba(248,249,235,.75);
  transition:color .25s,border-color .25s,background .25s;}
.footer-social-btn svg{width:17px;height:17px;}
.footer-social-btn:hover{color:var(--forest);background:var(--neon);border-color:var(--neon);}

.footer-cols{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:40px;
  margin-top:64px;padding:0 40px 56px;}
@media(max-width:760px){.footer-cols{grid-template-columns:1fr 1fr;gap:32px;margin-top:44px;}}
@media(max-width:460px){.footer-cols{grid-template-columns:1fr;}}
.footer-col{display:flex;flex-direction:column;align-items:flex-start;gap:14px;}
.footer-col-title{margin:0 0 2px;font-size:12px;font-weight:700;text-transform:uppercase;
  letter-spacing:.12em;color:var(--cream);}
.footer-col a{font-size:.95rem;color:rgba(248,249,235,.62);transition:color .25s;}
.footer-col a:hover{color:var(--neon);}

.footer-sub{border-top:1px solid rgba(0,255,171,.45);padding:34px 40px;
  display:flex;align-items:center;justify-content:space-between;gap:18px;flex-wrap:wrap;}
/* En dessous de 560px le padding de 40px mange trop de largeur utile. */
@media(max-width:560px){
  .footer-top{padding:32px 22px 0;}
  .footer-cols{padding:0 22px 40px;}
  .footer-sub{padding:28px 22px;}
}
.footer-sub p{margin:0;font-size:.85rem;color:rgba(248,249,235,.5);}
.footer-sub-links{display:flex;gap:26px;flex-wrap:wrap;}
.footer-sub-links a,.footer-sub-links button{font-size:.85rem;color:rgba(248,249,235,.5);
  background:none;border:0;padding:0;font-family:inherit;cursor:pointer;transition:color .25s;}
.footer-sub-links a:hover,.footer-sub-links button:hover{color:var(--neon);}

/* bannière cookies */
.cookie-banner{position:fixed;left:0;right:0;bottom:0;z-index:80;
  background:var(--forest);color:var(--cream);border-top:1px solid rgba(0,255,171,.25);
  transform:translateY(110%);transition:transform .4s cubic-bezier(.25,.8,.25,1);}
.cookie-banner.open{transform:none;}
.cookie-banner-inner{max-width:1200px;margin:0 auto;padding:20px 24px;
  display:flex;align-items:center;justify-content:space-between;gap:24px;flex-wrap:wrap;}
.cookie-banner p{margin:0;font-size:.9rem;color:rgba(248,249,235,.8);max-width:640px;}
.cookie-banner a{color:var(--neon);border-bottom:1px solid rgba(0,255,171,.4);}
.cookie-banner-actions{display:flex;gap:12px;flex-shrink:0;}
.cookie-banner .btn{padding:11px 20px;font-size:.9rem;}
.cookie-banner .btn-ghost{border-color:rgba(248,249,235,.28);color:var(--cream);}

/* pages légales (texte long + sommaire sticky) */
.legal-page{padding:calc(var(--chrome-h) + 70px) 0 var(--pad);}
.legal-layout{display:grid;grid-template-columns:290px minmax(0,1fr);gap:72px;align-items:start;}
@media(max-width:960px){.legal-layout{grid-template-columns:1fr;gap:36px;}}

/* Sommaire : rempli par layout.js à partir des <h2> de .legal-body */
.legal-toc{position:sticky;top:calc(var(--chrome-h) + 30px);background:#fff;border:1px solid var(--line);
  border-radius:8px;padding:24px 26px;box-shadow:0 18px 40px -30px rgba(2,44,34,.35);}
@media(max-width:960px){.legal-toc{position:static;}}
.legal-toc-title{margin:0 0 16px;font-size:10px;font-weight:600;text-transform:uppercase;
  letter-spacing:.13em;color:var(--muted);}
.legal-toc ul{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:12px;}
/* overflow-wrap:anywhere : les entrées reprennent les titres de l'article, dont
   certains contiennent des mots ou des formules trop longs pour la colonne. */
.legal-toc a{display:block;font-size:.92rem;line-height:1.35;color:rgba(2,44,34,.45);transition:color .25s;
  overflow-wrap:anywhere;}
.legal-toc a:hover{color:var(--pine);}
.legal-toc a.on{color:var(--ink);font-weight:600;}

.legal-body{max-width:720px;counter-reset:legal-section;}
.legal-body h2{font-family:'Fraunces',Georgia,serif;
  font-variation-settings:'opsz' 144,'SOFT' 50,'WONK' 0;
  font-size:2rem;font-weight:400;line-height:1.15;margin:56px 0 18px;scroll-margin-top:calc(var(--chrome-h) + 30px);}
.legal-body h2:first-of-type{margin-top:40px;}
.legal-body h2::before{counter-increment:legal-section;content:counter(legal-section) ". ";}
.legal-body h3{font-size:1.05rem;font-weight:600;margin:28px 0 8px;}
.legal-body p,.legal-body li{font-size:1rem;color:rgba(2,44,34,.75);line-height:1.6;}
.legal-body ul{padding-left:20px;}
.legal-body li{margin-bottom:6px;}
.legal-body a{color:var(--pine);border-bottom:1px solid rgba(19,112,48,.3);}
.legal-meta{font-size:.85rem;color:var(--muted);}

/* =========================================================================
   BLOG — page d'index (blog.html)
   Réutilise la carte .art de l'accueil, en lui ajoutant une vraie vignette
   photo et une ligne de méta (tag + date). Les cartes sans image gardent le
   fond dégradé + pictogramme de .art .thumb comme repli.
   ========================================================================= */
.blog-hero{padding:calc(var(--chrome-h) + 6rem) 0 0;}
.blog-hero .narrow{max-width:760px;}
.blog-hero .lead{max-width:600px;margin-inline:auto;}
.blog-list{padding:56px 0 var(--pad);}
.blog-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:24px;}
@media(max-width:980px){.blog-grid{grid-template-columns:1fr 1fr;}}
@media(max-width:640px){.blog-grid{grid-template-columns:1fr;}}

/* Vignette photo : même ratio que le repli SVG, donc pas de saut de gabarit
   entre une carte illustrée et une carte qui ne l'est pas encore. */
.art .thumb img{width:100%;height:100%;object-fit:cover;}
.art .thumb{overflow:hidden;}

.art-meta{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:12px;}
.art-tag{font-size:.68rem;font-weight:700;text-transform:uppercase;letter-spacing:.1em;
  padding:6px 11px;border-radius:4px;background:var(--pine);color:#fff;white-space:nowrap;}
.art-date{font-size:.78rem;color:var(--muted);font-weight:500;}
.art .body h3{font-size:1.08rem;line-height:1.3;margin:0 0 10px;font-weight:600;}
/* Les cartes n'affichent plus de lien « Lire l'article » : l'extrait est le
   dernier élément du corps, il ne doit donc plus réserver d'espace en bas. */
.art .body p:last-child{margin-bottom:0;}
/* La carte entière est cliquable : le titre porte le lien, un ::after invisible
   couvre la carte. Le lien « Lire l'article » reste présent pour la lisibilité. */
.art{position:relative;}
.art h3 a::after{content:"";position:absolute;inset:0;}

/* =========================================================================
   BLOG — page article
   Même ossature que les pages légales (sommaire sticky à gauche, corps de
   texte à droite), mais sans la numérotation automatique des <h2> : sur un
   article les titres sont rédactionnels, pas des articles de contrat.
   ========================================================================= */
.article-page{padding:calc(var(--chrome-h) + 50px) 0 var(--pad);}

/* Fil d'Ariane, pleine largeur au-dessus des deux colonnes. Il ne reprend que
   des étapes réellement cliquables : « Ressources » y figurait au départ, mais
   c'est un item déroulant du header et non une page, donc un maillon mort. */
.breadcrumb{display:flex;align-items:center;flex-wrap:wrap;gap:8px;margin:0 0 40px;
  font-size:.85rem;color:var(--muted);}
.breadcrumb a{color:var(--muted);transition:color .25s;}
.breadcrumb a:hover{color:var(--pine);}
.breadcrumb .sep{color:rgba(2,44,34,.32);flex:none;}
.breadcrumb .sep svg{width:14px;height:14px;display:block;}
.breadcrumb .current{color:var(--ink);font-weight:500;}
/* Sur mobile le titre complet mange 3 lignes : on le tronque. */
@media(max-width:640px){
  .breadcrumb{flex-wrap:nowrap;}
  .breadcrumb .current{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
}
.article-layout{display:grid;grid-template-columns:330px minmax(0,1fr);gap:80px;align-items:start;}
@media(max-width:1080px){.article-layout{grid-template-columns:290px minmax(0,1fr);gap:56px;}}
@media(max-width:960px){.article-layout{grid-template-columns:1fr;gap:36px;}}
/* La colonne s'étire sur toute la hauteur de l'article : c'est la condition
   pour que son enfant collé (.article-sticky) puisse suivre jusqu'en bas.
   Sans ça, il se décrocherait dès la fin de la colonne. */
/* min-width:0 : sans ça, la colonne refuse de descendre sous la largeur du plus
   long mot du sommaire (un titre à rallonge suffit) et déborde de l'écran sur
   mobile, où elle est pourtant censée passer en pleine largeur. */
.article-side{align-self:stretch;display:flex;flex-direction:column;gap:20px;min-width:0;}

/* Seuls le sommaire et l'encadré CTA sont collés. La signature reste dans le
   flux et disparaît au défilement : elle a fait son travail dès la première
   lecture, la garder collée mangeait 68px de hauteur utile sur une colonne
   déjà trop haute pour les petites fenêtres.
   Le sommaire hérite de .legal-toc, lui-même sticky pour les pages légales :
   il faut le remettre en flux ici, sinon il colle à l'intérieur du bloc et
   finit par recouvrir l'encadré CTA en fin d'article.
   Pas de max-height ni d'overflow : une barre de défilement interne avait été
   essayée pour les écrans peu hauts, elle transformait le tout en un bloc
   défilant peu lisible (rejeté le 2026-07-28). */
.article-sticky{position:sticky;top:calc(var(--chrome-h) + 30px);display:flex;flex-direction:column;gap:20px;}
.article-sticky .legal-toc{position:static;}
@media(max-width:960px){.article-sticky{position:static;}}

/* Signature de l'autrice, en tête de colonne de gauche. Sa hauteur est calée
   sur celle de la ligne de méta de l'article (.article-body .art-meta), pour
   que le haut du sommaire tombe exactement au niveau du titre. */
.article-author{display:flex;align-items:center;gap:14px;height:48px;}
.article-author img{width:48px;height:48px;border-radius:50%;object-fit:cover;flex:none;}
.article-author .n{font-weight:600;font-size:.95rem;line-height:1.25;}
.article-author .r{font-size:.82rem;color:var(--muted);line-height:1.25;margin-top:2px;}

/* Encadré d'appel à l'action sous le sommaire : bloc indépendant, fond forêt
   pour trancher avec la carte blanche du sommaire sans crier. */
.side-cta{background:var(--forest);color:var(--cream);border-radius:8px;padding:24px 26px;
  box-shadow:0 22px 46px -30px rgba(2,44,34,.55);}
.side-cta p{margin:0 0 16px;font-size:.95rem;line-height:1.4;color:rgba(248,249,235,.78);}
.side-cta .side-cta-title{font-family:'Fraunces',Georgia,serif;
  font-variation-settings:'opsz' 144,'SOFT' 50,'WONK' 0;
  font-size:1.3rem;line-height:1.15;color:#fff;margin:0 0 10px;font-weight:400;}
.side-cta .btn{width:100%;justify-content:center;padding:13px 20px;font-size:.95rem;}

/* min-width:0 : la colonne d'article est une cellule de grille, et une cellule
   refuse par défaut de descendre sous la largeur minimale de son contenu. Un
   tableau large suffisait alors à élargir toute la grille au-delà de l'écran sur
   mobile. Avec min-width:0 la colonne suit l'écran et c'est .article-table, déjà
   en overflow-x:auto, qui fait défiler le tableau tout seul. */
.article-body{max-width:820px;min-width:0;}
/* Hauteur calée sur la signature de la colonne de gauche : les deux blocs font
   48px + 20px de marge, donc le titre et le haut du sommaire démarrent au
   même endroit. Toucher à l'un des deux impose de recaler l'autre. */
.article-body .art-meta{min-height:48px;margin-bottom:20px;}
.article-body h1{margin-bottom:28px;}
.article-body h2{font-family:'Fraunces',Georgia,serif;
  font-variation-settings:'opsz' 144,'SOFT' 50,'WONK' 0;
  font-size:clamp(1.6rem,3vw,2rem);font-weight:400;line-height:1.15;
  margin:56px 0 18px;scroll-margin-top:calc(var(--chrome-h) + 30px);}
.article-body h3{font-size:1.08rem;font-weight:600;margin:32px 0 8px;}
.article-body p,.article-body li{font-size:1.02rem;color:rgba(2,44,34,.78);line-height:1.65;}
.article-body ul{padding-left:20px;}
.article-body li{margin-bottom:8px;}
.article-body a{color:var(--pine);border-bottom:1px solid rgba(19,112,48,.3);}
.article-body strong{font-weight:600;color:var(--ink);}
/* Pas d'image principale en tête d'article (retirée le 2026-07-28) : le visuel
   sert de vignette sur les cartes du blog, le répéter juste sous le titre
   repoussait le texte sans rien apprendre au lecteur. Les illustrations
   utiles restent dans le corps de l'article, en .article-figure. */
/* Blocs présents dans les articles WordPress importés : listes numérotées,
   citations et tableaux. Le tableau défile horizontalement dans son propre
   conteneur, pour que la page elle-même ne défile jamais latéralement. */
.article-body ol{padding-left:22px;}
.article-body blockquote{margin:32px 0;padding:4px 0 4px 24px;border-left:3px solid var(--neon);}
.article-body blockquote p{font-size:1.1rem;color:var(--ink);font-style:italic;}
.article-body blockquote p:last-child{margin-bottom:0;}
/* Widget tiers embarqué (simulateur France Rénov', etc.). Le conteneur est vide
   dans le HTML : layout.js y pose une façade, et l'iframe n'est créée qu'au
   clic (voir initEmbeds). WordPress ne transmet aucune hauteur utilisable et le
   widget ne sait pas se redimensionner : elle est fixée ici, assez grande pour
   que le formulaire tienne sans barre de défilement interne. */
.article-embed{margin:34px 0;border:1px solid var(--line);border-radius:8px;
  overflow:hidden;background:#fff;}
.article-embed iframe{display:block;width:100%;height:1080px;border:0;}
@media(max-width:640px){.article-embed iframe{height:1320px;}}

.embed-facade{padding:40px 32px;text-align:center;}
.embed-facade .embed-titre{font-weight:600;font-size:1.05rem;margin:0 0 6px;color:var(--ink);}
.embed-facade .embed-note{font-size:.88rem;color:var(--muted);margin:0 0 22px;}
.embed-facade .embed-note strong{font-weight:500;color:var(--ink);}

.article-table{margin:34px 0;overflow-x:auto;border:1px solid var(--line);border-radius:8px;background:#fff;}
.article-table table{border-collapse:collapse;width:100%;min-width:520px;}
.article-table th,.article-table td{padding:12px 16px;text-align:left;font-size:.95rem;
  border-bottom:1px solid var(--line);line-height:1.45;}
.article-table th{background:var(--cream);font-weight:600;color:var(--ink);}
.article-table td{color:rgba(2,44,34,.78);}
.article-table tr:last-child td{border-bottom:none;}
.article-table figcaption{padding:12px 16px;font-size:.82rem;color:var(--muted);}

/* La figure se cale sur la largeur réelle de son image (width:fit-content), et
   non sur celle de la colonne : sinon la légende d'une petite image court sur
   toute la largeur du texte et déborde visuellement de l'illustration.
   min-width évite l'effet inverse, une légende essorée sur une image étroite.
   Les figures restent alignées à gauche, jamais centrées. */
.article-figure{margin:34px 0;width:fit-content;max-width:100%;min-width:min(100%,340px);}
/* Variante demi-largeur, pour les visuels qui n'ont pas besoin de toute la
   colonne : captures d'écran de texte (avis client), petits schémas, extraits
   de document. En pleine largeur ils écrasent le texte autour. */
.article-figure.figure-sm{max-width:50%;}
@media(max-width:720px){.article-figure.figure-sm{max-width:100%;}}
.article-figure img{border-radius:8px;border:1px solid var(--line);}
/* width:0 + min-width:100% : la légende remplit la figure sans peser dans le
   calcul de sa largeur. Sans ça, une légende longue élargit la figure au-delà
   de l'image et déborde d'elle. */
.article-figure figcaption{width:0;min-width:100%;
  font-size:.82rem;color:var(--muted);margin-top:10px;line-height:1.4;}

/* « L'essentiel à retenir » : encadré de synthèse en tête d'article, repris du
   format des blogs SEO longs (résumé lisible en 20 secondes). */
.takeaways{background:#fff;border:1px solid var(--line);border-radius:8px;padding:28px 30px;margin:0 0 40px;
  box-shadow:0 18px 40px -32px rgba(2,44,34,.35);}
.takeaways .tk-title{font-size:.7rem;font-weight:700;text-transform:uppercase;letter-spacing:.13em;
  color:var(--pine);margin:0 0 14px;}
.takeaways ul{margin:0;padding-left:20px;}
.takeaways li{font-size:.98rem;line-height:1.55;}

/* Séparateur avant la synthèse finale (équivalent du `---` du Markdown) */
.article-body hr{border:0;border-top:1px solid var(--line);margin:48px 0 32px;}
/* CTA de fin d'article (format 👉 des articles WordPress) */
.article-cta{font-weight:500;}

/* Section « Explorez d'autres articles » : fond greige, pas néon. Les vignettes
   des articles sont elles-mêmes vertes, un fond néon derrière effaçait la
   limite entre la carte et la section. */
.more-articles .h2{color:var(--forest);}
.bg-neon .art{border-color:rgba(2,44,34,.12);}

/* reveal */
.reveal{opacity:0;transform:translateY(24px);transition:opacity .7s ease,transform .7s cubic-bezier(.25,.8,.25,1);}
.reveal.in{opacity:1;transform:none;}

@media(prefers-reduced-motion:reduce){
  *{animation:none !important;transition:none !important;}
  .reveal{opacity:1;transform:none;}
}

/* ---- Mega-menu navigation (façon Table 22) ---- */
.header .nav{align-self:stretch;}
.nav-list{list-style:none;margin:0;padding:0;display:flex;align-items:stretch;height:100%;gap:6px;}
.nav-item{display:flex;align-items:stretch;}
.nav-link{display:flex;align-items:center;gap:5px;padding:0 14px;font-size:.95rem;font-weight:500;color:var(--muted);transition:color .25s,background .25s;}
.nav-link:hover{color:var(--ink);}
.nav-chev{width:14px;height:14px;stroke:currentColor;stroke-width:2;fill:none;transition:transform .25s;}
.nav-item:hover .nav-chev{transform:rotate(180deg);}
.mega{position:absolute;top:100%;left:0;right:0;background:var(--cream);border-bottom:1px solid var(--line);box-shadow:0 24px 48px rgba(2,44,34,.10);opacity:0;visibility:hidden;transform:translateY(-6px);transition:opacity .2s,transform .2s,visibility .2s;}
.nav-item:hover .mega{opacity:1;visibility:visible;transform:translateY(0);}
.mega-inner{max-width:1200px;margin:0 auto;padding:44px 24px;display:grid;grid-template-columns:1fr 1fr 320px;gap:48px;align-items:start;}
.mega-col-title{font-size:.72rem;text-transform:uppercase;letter-spacing:.08em;color:rgba(2,44,34,.4);margin:0 0 16px;font-weight:600;}
.mega-item{display:flex;flex-direction:column;gap:3px;padding:10px 12px;margin:0 -12px;border-radius:8px;color:var(--ink);font-size:1rem;font-weight:500;transition:background .2s;}
.mega-item:hover{background:var(--greige);}
.mega-item .sub{font-size:.82rem;font-weight:400;color:var(--muted);}
.mega-visual{border-radius:8px;overflow:hidden;position:relative;background:var(--forest);display:block;}
.mega-visual img{width:100%;height:190px;object-fit:cover;display:block;transition:transform .4s;}
.mega-visual:hover img{transform:scale(1.05);}
.mega-visual .caption{position:absolute;left:0;right:0;bottom:0;padding:14px 16px;background:linear-gradient(to top,rgba(2,44,34,.85),transparent);color:#fff;font-size:.85rem;font-weight:500;}
.header .cta-wrap .btn{font-size:.95rem;font-weight:500;}
.header{transition:background .15s ease;}
.header:has(.nav-item:hover .mega),
.header.nav-open{background:var(--cream);backdrop-filter:none;-webkit-backdrop-filter:none;border-bottom-color:transparent;}
@media(max-width:900px){.mega{display:none;}}

/* =========================================================================
   Page contact dédiée (contact.html) — créée le 2026-07-28
   Toute la page est en forest : le header fixe (clair) flotte au-dessus, d'où
   le padding-top qui compense ses 70px, et le footer se fond dans la section
   grâce à la règle .bg-forest + .footer-full plus haut.
   ========================================================================= */
.contact-page{padding-top:calc(var(--chrome-h) + 5.5rem);padding-bottom:6rem;}
@media(max-width:820px){.contact-page{padding-top:calc(var(--chrome-h) + 3.5rem);padding-bottom:4rem;}}
.contact-page-grid{grid-template-columns:1.05fr 1fr;gap:72px;align-items:start;}
@media(max-width:960px){.contact-page-grid{grid-template-columns:1fr;gap:44px;}}

.contact-intro .h1{max-width:15ch;}
.contact-intro .lead{max-width:46ch;}
/* Coordonnées en clair : le formulaire n'est pas le seul canal. */
.contact-direct{list-style:none;margin:34px 0 0;padding:0;display:flex;flex-direction:column;gap:12px;}
.contact-direct a{display:inline-flex;align-items:center;gap:12px;font-weight:500;
  color:var(--cream);transition:color .25s;}
.contact-direct a:hover{color:var(--neon);}
.contact-direct svg{width:18px;height:18px;color:var(--neon);flex:none;}

.contact-points{list-style:none;margin:34px 0 0;padding:26px 0 0;display:flex;flex-direction:column;gap:11px;
  border-top:1px solid rgba(248,249,235,.12);}
.contact-points li{display:flex;align-items:center;gap:11px;font-size:.95rem;color:rgba(248,249,235,.72);}
.contact-points .dot{width:6px;height:6px;border-radius:999px;background:var(--neon);flex:none;}

/* ---- Panneau du formulaire ----
   Fond opaque (et non translucide) parce que la grille d'accent passe derrière
   et ne doit rester visible que sur son débord hors du panneau. */
.form-panel-wrap{position:relative;}
.form-panel{position:relative;z-index:1;background:#04382b;border:1px solid rgba(255,255,255,.11);
  border-radius:8px;padding:38px;}
@media(max-width:560px){.form-panel{padding:26px 22px;}}
/* Variante sombre de .grille-accent : mêmes règles, lignes néon au lieu d'encre. */
.grille-dark{background-image:
    linear-gradient(to right,rgba(0,255,171,.16) 1px,transparent 1px),
    linear-gradient(to bottom,rgba(0,255,171,.16) 1px,transparent 1px);}

/* ---- Colonne de prise de rendez-vous (Calendly) ----
   Le calendrier est servi par Calendly sur fond blanc : le panneau devient donc
   une carte blanche, et c'est le contraste avec le forest qui joue le rôle du
   cadre clair de la maquette de référence. Pas de titre au-dessus du widget
   (retiré le 2026-07-28) : Calendly affiche déjà le sien, la colonne de gauche
   annonce le créneau de 30 min, et un troisième rappel faisait redondance. */
.booking-col{position:relative;}
.booking-panel{position:relative;z-index:1;background:#fff;border-radius:8px;overflow:hidden;}
.booking-panel .calendly-inline-widget{width:100%;min-width:280px;height:700px;}
@media(max-width:960px){.booking-panel .calendly-inline-widget{height:960px;}}
.booking-note{position:relative;z-index:1;font-size:12px;line-height:1.45;color:rgba(248,249,235,.45);margin:18px 0 0;}
.booking-note a{color:rgba(248,249,235,.7);text-decoration:underline;text-underline-offset:2px;}
.booking-note a:hover{color:var(--neon);}

/* ---- Champs étiquetés (label au-dessus, façon Delville) ---- */
.form .field{display:flex;flex-direction:column;gap:8px;}
.form .field label{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.13em;
  color:rgba(248,249,235,.6);}
.form .field input,.form .field textarea{width:100%;}

/* Case de consentement RGPD : neutralise les styles de .form input (padding,
   fond, bordure) qui ne valent que pour les champs texte. */
.form-consent{display:flex;align-items:flex-start;gap:12px;font-size:13px;line-height:1.45;
  color:rgba(248,249,235,.62);cursor:pointer;margin-top:2px;}
.form .form-consent input[type=checkbox]{width:16px;height:16px;flex:none;margin:2px 0 0;padding:0;
  background:transparent;border:1px solid rgba(255,255,255,.3);border-radius:3px;accent-color:var(--neon);}
.form-consent a{color:var(--neon);text-decoration:underline;text-underline-offset:2px;}

/* Piège à robots : hors écran, jamais display:none (certains bots l'ignorent). */
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden;}

/* Retour d'envoi, injecté par layout.js */
.form-status{margin:4px 0 0;font-size:.9rem;line-height:1.4;display:none;}
.form-status.on{display:block;}
.form-status.ok{color:var(--neon);}
.form-status.ko{color:#ffb4a2;}
.form button[disabled]{opacity:.6;cursor:progress;transform:none;}

/* ---- Bandeau CTA vers la page contact (pages sans formulaire) ---- */
.cta-band{text-align:center;}
.cta-band .h2{max-width:20ch;margin-inline:auto;}
.cta-band .lead{max-width:52ch;margin-inline:auto;}
.cta-band-actions{display:flex;flex-wrap:wrap;gap:14px;justify-content:center;margin-top:32px;}

/* =========================================================================
   Page guide enduit chaux/sable (guide-enduit-chaux-sable.html) — 2026-07-28
   Lead magnet : hero forest + formulaire, sections de contenu claires, puis
   rappel du formulaire en bas. Reprend au maximum les composants existants
   (.contact-grid, .form-panel, .grille-accent, .card-white, .checklist) ;
   ce bloc ne contient que ce qui leur manquait.
   ========================================================================= */

/* Même compensation du header fixe que .contact-page, le header flottant
   au-dessus de ses 70px. Le hero est en crème et non en forest : la page
   alterne crème / greige / crème / greige / forest, jamais deux fonds
   identiques à la suite. */
.guide-hero{padding-top:calc(var(--chrome-h) + 5.5rem);padding-bottom:7rem;}
@media(max-width:820px){.guide-hero{padding-top:calc(var(--chrome-h) + 3.5rem);padding-bottom:4.5rem;}}
.guide-hero-grid{grid-template-columns:1.05fr .95fr;gap:72px;align-items:start;}
@media(max-width:960px){.guide-hero-grid{grid-template-columns:1fr;gap:44px;}}
/* Titre du hero (2026-07-29) : deux lignes, les plus grosses possibles.
   À 3,75rem sur 16ch il tombait sur trois lignes ; en descendant à 3rem sur
   22ch il repassait à deux, mais coupé après « chaux, » donc avec une seconde
   ligne deux fois plus courte que la première, et un titre inutilement petit.
   La mesure à 20ch force la coupure au milieu de la phrase et text-wrap:balance
   égalise les deux lignes, ce qui laisse la place de remonter le corps à
   3,5rem. Les navigateurs sans text-wrap:balance coupent au même endroit, la
   mesure suffit à l'imposer. */
.guide-intro .h1{font-size:clamp(2.5rem,5.6vw,3.5rem);max-width:20ch;text-wrap:balance;}
.guide-intro .lead{max-width:48ch;}

/* ---- Rangée d'arguments sous le hero (2026-07-29) ----
   Remplace la liste à puces qui était dans la colonne de gauche : elle
   déséquilibrait le hero (colonne de texte deux fois plus haute que le
   formulaire). Ici les trois arguments sont des labels sur une seule ligne,
   centrés sous la grille.
   Volontairement DIFFÉRENTS de .eyebrow (pilule blanche, bord clair, rayon
   plein, majuscules) : sans ça on lisait trois étiquettes de section de plus,
   sœurs du « GUIDE GRATUIT » du hero. D'où le rectangle arrondi (rayon 10px et
   non 999px), le fond teinté encre sans bordure, et la coche pine reprise de
   .checklist, qui est le vrai composant de la même famille (des arguments, pas
   des catégories). Pas de filet de séparation : la rangée appartient au hero,
   elle ne le referme pas. */
.guide-specs{list-style:none;margin:60px 0 0;padding:0;
  display:flex;flex-wrap:wrap;justify-content:center;gap:12px;}
.guide-specs li{display:inline-flex;align-items:center;gap:9px;
  background:rgba(2,44,34,.05);border-radius:10px;
  padding:11px 18px;font-size:.9rem;font-weight:500;line-height:1.3;color:var(--ink);}
.guide-specs svg{width:15px;height:15px;color:var(--pine);flex:none;}
/* En dessous de 640px les trois labels côte à côte se cassent en lignes
   déséquilibrées : un par ligne. Calés à gauche (2026-08-14) : centrés, leurs
   largeurs différentes formaient un escalier et le texte du label qui passe sur
   deux lignes n'avait plus de bord de lecture commun avec les autres. */
@media(max-width:640px){
  .guide-specs{flex-direction:column;align-items:flex-start;gap:10px;margin-top:44px;}
  /* align-items:flex-start suffit à coller les pastilles à gauche, mais la coche
     doit rester en haut du label à deux lignes, pas centrée sur sa hauteur. */
  .guide-specs li{align-items:flex-start;}
  .guide-specs svg{margin-top:.22em;}
}

/* ---- Panneau de formulaire blanc ----
   Variante claire de .form-panel, dont le fond sombre et les styles de .form
   (champs translucides, texte crème, accents néon) sont écrits pour un fond
   forest. Sur blanc il faut l'inverse, sinon rien n'est lisible.
   Les champs sont en crème et non en blanc : sur un panneau blanc, un champ
   blanc ne tient que par sa bordure et le formulaire paraît vide. */
.form-panel-light{background:#fff;border-color:var(--line);
  box-shadow:0 30px 60px -34px rgba(2,44,34,.28);}
.form-panel-light .form-panel-title{color:var(--ink);}
.form-panel-light .form-panel-sub{color:var(--muted);}
.form-panel-light .form input,.form-panel-light .form textarea{
  background:var(--cream);border-color:rgba(2,44,34,.14);color:var(--ink);}
.form-panel-light .form input::placeholder,.form-panel-light .form textarea::placeholder{color:var(--muted);}
.form-panel-light .form input:focus,.form-panel-light .form textarea:focus{
  border-color:var(--pine);background:#fff;}
.form-panel-light .form-consent{color:rgba(2,44,34,.66);}
.form-panel-light .form .form-consent input[type=checkbox]{
  background:#fff;border-color:rgba(2,44,34,.3);accent-color:var(--pine);}
.form-panel-light .form-consent a{color:var(--pine);}
.form-panel-light .form-status.ok{color:var(--pine);}
.form-panel-light .form-status.ko{color:#8f1d00;}

/* En-tête du panneau de formulaire. Sur contact.html le panneau n'en avait pas
   (le calendrier porte son propre titre) : ici il faut nommer l'action, le
   formulaire arrivant sans contexte pour qui atterrit directement dessus. */
.form-panel-title{font-family:'Fraunces',Georgia,serif;font-variation-settings:'opsz' 144,'SOFT' 50,'WONK' 0;
  font-size:1.6rem;line-height:1.1;margin:0 0 8px;color:#fff;}
.form-panel-sub{margin:0 0 26px;font-size:.92rem;line-height:1.45;color:rgba(248,249,235,.62);}

/* Accès immédiat au guide, révélé par layout.js après un envoi réussi.
   `hidden` en HTML suffit à le masquer ; on ne le repose pas ici, sinon il
   resterait invisible une fois l'attribut retiré. */
.form-reveal{margin-top:4px;}
.form-reveal .btn{width:100%;justify-content:center;}
/* Posée par layout.js après livraison : le formulaire s'efface au profit du
   seul bouton d'accès, sinon deux boutons néon identiques se superposent. */
.form-done .form-inline-row,
.form-done .form-consent,
.form-done > input:not([type=hidden]),
.form-done button[type=submit]{display:none;}

/* ---- Section « Le vrai risque » : onglets + visuel débordant ----
   Trois libellés cliquables, un seul visuel affiché à la fois, légende en
   surimpression au bas de l'image. Le visuel déborde sur la section suivante.
   Mécanique du débordement : la section ne porte plus de padding bas, et c'est
   le visuel qui descend de 72px sous elle via une marge négative. Il doit donc
   être positionné avec un z-index, sinon le fond de la section suivante le
   recouvre. Aucun overflow:hidden sur la section, il couperait le débord. */
.risk-section{padding-bottom:0;}
/* flow-root est indispensable : sans lui, la marge négative du visuel
   s'échappe de la section (effondrement de marges) au lieu d'en réduire la
   hauteur. La section descendait alors jusqu'au bas de l'image et le débord
   valait zéro, le fond vert suivant simplement l'image. */
.risk-section > .wrap{display:flow-root;}
/* Bloc volontairement plus étroit que le .wrap : en pleine largeur (1320px)
   le visuel 16/9 dépassait 740px de haut et écrasait tout le reste de la page.
   La barre d'onglets porte la même contrainte, elle doit rester calée sur la
   largeur de l'image comme dans la maquette de référence. */
/* position/z-index ici et pas seulement sur .risk-visual : ce bloc porte
   .reveal, dont le transform d'entrée (translateY, puis transition de 0,7 s)
   en fait un contexte d'empilement tant que l'animation n'est pas finie. Le
   z-index:3 du visuel y était enfermé, et pendant une seconde la section claire
   suivante (.round-top, z-index:2) recouvrait le bas de la carte, qui semblait
   « se déplier » après coup. Avec un z-index:3 porté par le bloc lui-même, le
   dépassement est bon dès la première image, transform ou pas. */
.risk-tabs{max-width:960px;margin:64px auto 0;position:relative;z-index:3;}

/* ---- Phrase révélée mot à mot au scroll (accueil, section « cibles ») ----
   Calée sur la même largeur que .risk-tabs et alignée à gauche, pas centrée :
   une phrase longue centrée donne des lignes de longueurs inégales, et l'œil
   perd le début de chaque ligne, alors que l'effet demande justement de suivre
   la lecture mot après mot.
   Le découpage en <span> est fait par le JS, jamais écrit dans le HTML : la
   phrase doit rester une phrase pour les moteurs de recherche, les lecteurs
   d'écran et le copier-coller. */
/* text-wrap:balance (2026-08-03) : le navigateur répartit lui-même les mots
   pour que toutes les lignes fassent à peu près la même longueur. Il règle le
   mot orphelin de la dernière ligne (« travaux. » tout seul) sans qu'on ait à
   forcer une coupure à un endroit précis, qui ne tiendrait qu'à une largeur
   d'écran et sauterait au premier mot changé dans la phrase.
   Deux limites connues, sans conséquence ici : les navigateurs anciens
   l'ignorent et retombent sur la coupure normale, et Chrome cesse d'équilibrer
   au-delà de 6 lignes. La phrase en fait 4 en desktop et 6 sur un iPhone : si
   elle est rallongée un jour, revérifier le rendu mobile. */
.scroll-phrase{max-width:960px;margin:0 auto;text-align:left;line-height:1.24;
  text-wrap:balance;}
/* Opacité de départ des mots pas encore atteints. Assez basse pour que la
   progression se voie, assez haute pour que la phrase reste lisible d'un coup
   si le visiteur arrive vite : elle ne doit jamais ressembler à un bug de
   chargement. Le JS écrase cette valeur mot par mot. */
.scroll-phrase .sp-w{opacity:.22;}
/* Filet de sécurité : sans JavaScript, ou si le visiteur a demandé moins
   d'animations, tout est affiché en pleine opacité. */
.scroll-phrase.sp-done .sp-w{opacity:1;}
@media(prefers-reduced-motion:reduce){.scroll-phrase .sp-w{opacity:1;}}

.risk-nav{display:flex;justify-content:space-between;gap:24px;margin-bottom:34px;}
.risk-tab{background:none;border:0;padding:0 0 10px;font:inherit;font-size:.95rem;font-weight:500;
  color:rgba(248,249,235,.5);cursor:pointer;text-align:left;
  border-bottom:1px solid transparent;transition:color .25s,border-color .25s;}
.risk-tab:hover{color:rgba(248,249,235,.8);}
/* L'onglet actif est signalé par la couleur ET par le filet : la couleur seule
   ne suffit pas pour qui la distingue mal. */
.risk-tab.is-active{color:var(--cream);border-bottom-color:var(--neon);}
.risk-tab:focus-visible{outline:2px solid var(--neon);outline-offset:4px;}
/* Sur mobile les trois libellés ne tiennent plus sur une ligne. Ils étaient
   d'abord posés côte à côte dans une barre à défilement horizontal, mais rien
   ne signalait qu'on pouvait la faire glisser : le troisième onglet (« Agent
   immobilier ») était simplement invisible, donc mort. Depuis le 2026-08-14 ils
   passent l'un sous l'autre, comme dans la maquette de référence : les trois
   cibles sont lues d'un coup, chacune sur sa ligne avec son filet. */
@media(max-width:760px){
  .risk-nav{flex-direction:column;align-items:stretch;gap:0;margin-bottom:26px;}
  /* Filet sur chaque ligne, pas seulement sur l'active : il fait la séparation
     entre les trois et donne la liste, l'active se distinguant par la couleur
     du filet et du texte. */
  .risk-tab{padding:13px 0;border-bottom-color:rgba(248,249,235,.16);}
}

/* z-index 3 et non 2 : la section suivante porte .round-top, qui est elle-même
   en z-index 2 et venant après dans le DOM, elle recouvrirait le visuel.
   Le chevauchement apparent sur le fond clair vaut 32 + 40 = 72px : 32px de
   marge négative ici, plus les 40px dont .round-top fait remonter la section
   claire. Changer l'un des deux impose de reprendre l'autre. */
.risk-visual{position:relative;z-index:3;margin-bottom:-32px;}
/* La section suivante récupère ce que le visuel lui a mangé, sinon son contenu
   démarre trop haut et se retrouve serré sous l'image. */
.risk-section + section{padding-top:calc(var(--pad) + 72px);}
@media(max-width:760px){
  .risk-visual{margin-bottom:-24px;}
  .risk-section + section{padding-top:calc(var(--pad) + 48px);}
}
.risk-panel{position:relative;margin:0;border-radius:8px;overflow:hidden;
  box-shadow:0 40px 80px -40px rgba(0,0,0,.6);}
.risk-panel[hidden]{display:none;}
/* Porte-image. Tant qu'aucun <img> n'y est posé, le dégradé et la mention
   « Visuel à venir » tiennent lieu de placeholder ; dès qu'une image arrive,
   :has(img) éteint les deux. Rien d'autre à changer dans le HTML. */
.risk-ph{position:relative;aspect-ratio:16/9;background:
    radial-gradient(circle at 30% 25%,rgba(0,255,171,.10),transparent 55%),
    linear-gradient(150deg,#0b4535,#06281f);}
.risk-ph::after{content:"Visuel à venir";position:absolute;inset:0;display:flex;
  align-items:center;justify-content:center;font-size:.75rem;font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;color:rgba(248,249,235,.22);}
.risk-ph:has(img){background:none;}
.risk-ph:has(img)::after{content:none;}
/* Léger assombrissement : les photos de chantier sont prises en plein soleil
   et détonnaient sur le fond forest de la section. Porté par filter et non par
   un voile en surimpression, qui aurait aussi terni la légende posée dessus. */
.risk-ph img{width:100%;height:100%;object-fit:cover;filter:brightness(.88);}
/* Les images sont recadrées en 16/9 à la source, mais sur un écran de 390px un
   16/9 ne fait plus que ~200px de haut : la photo se réduit à une bande et la
   carte semble deux fois plus petite que dans la maquette de référence. En
   dessous de 760px on passe donc en 3/2 (2026-08-14), qui rend de la hauteur
   sans rogner autant que le 4/3 (16% de la largeur perdue contre 25%) : le
   panneau « À vendre » du pavillon, proche du bord droit, reste dans le cadre.
   Les placeholders, eux sans contenu à préserver, vont jusqu'au 4/3. */
@media(max-width:760px){.risk-ph{aspect-ratio:3/2;}}
@media(max-width:560px){.risk-ph:not(:has(img)){aspect-ratio:4/3;}}
/* Voile sombre en bas de l'image, pour que la légende reste lisible quelle que
   soit la photo qui finira dessous. */
.risk-panel figcaption{position:absolute;left:0;right:0;bottom:0;
  padding:96px 40px 32px;font-size:.92rem;line-height:1.5;font-weight:500;color:#fff;
  background:linear-gradient(to top,rgba(2,26,20,.92) 18%,rgba(2,26,20,.7) 48%,transparent);}
/* La légende reste en surimpression sur mobile, comme dans la maquette de
   référence. C'est tenable à une seule condition, posée le 2026-08-14 : les
   légendes doivent faire 3 à 4 lignes sur un écran de 390px, soit ~180
   caractères, lien non compris. La hauteur disponible est celle de l'image et
   le panneau est en overflow:hidden : tout ce qui dépasse est coupé, sans
   ascenseur ni avertissement. Une variante « légende en flux sous l'image » a
   été essayée puis abandonnée : elle acceptait n'importe quelle longueur, mais
   la carte perdait ce qui fait le composant, du texte posé sur la photo.
   Donc en cas de texte tronqué : raccourcir la légende, pas toucher au CSS. */
@media(max-width:760px){.risk-panel figcaption{padding:72px 22px 22px;font-size:.85rem;}}
/* Lien de fin de légende (accueil : une sortie par cible). Posé en bloc pour
   qu'il ne se noie pas dans le paragraphe, et souligné en permanence : sur une
   photo, la couleur seule ne suffirait pas à le signaler comme cliquable.
   display:block et non inline-block (corrigé le 2026-08-03) : en inline-block
   le lien restait dans le fil du texte, à la suite de la dernière phrase, et
   son margin-top de 10px gonflait la hauteur de cette ligne-là. Résultat, un
   écart inexpliqué entre l'avant-dernière et la dernière ligne de la légende,
   alors que le lien n'était même pas détaché comme voulu. En block il passe
   vraiment à la ligne et les 10px se lisent comme une respiration.
   width:fit-content : sans elle, le bloc occupe toute la largeur de la légende
   et rend cliquable une longue bande vide à droite du libellé. */
.risk-panel figcaption .risk-link{display:block;width:fit-content;margin-top:10px;color:var(--neon);
  font-weight:600;text-decoration:underline;text-underline-offset:4px;
  text-decoration-thickness:1px;transition:opacity .2s;}
.risk-panel figcaption .risk-link:hover{opacity:.75;}
.risk-panel figcaption .risk-link:focus-visible{outline:2px solid var(--neon);outline-offset:3px;}

/* Sommaire du guide : 6 cartes. Grille propre plutôt que .cards-3, qui est
   figée à 3 colonnes et porte un margin-top calé sur la page d'accueil. */
.guide-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:22px;margin-top:72px;}
@media(max-width:980px){.guide-grid{grid-template-columns:repeat(2,1fr);}}
@media(max-width:640px){.guide-grid{grid-template-columns:1fr;}}

/* Bloc auteurs : texte à gauche, photo des auteurs à droite. */
.guide-authors{display:grid;grid-template-columns:1.15fr .85fr;gap:64px;align-items:center;}
@media(max-width:900px){.guide-authors{grid-template-columns:1fr;gap:36px;}}
.guide-authors .h2{max-width:16ch;}
.guide-authors .lead{max-width:54ch;}

/* Porte-photo de la section auteurs (2026-07-29), en remplacement des points
   de réassurance qui occupaient cette colonne.
   Même mécanique de placeholder que .risk-ph : tant qu'aucun <img> n'est posé
   dedans, le fond et la mention « Photo à venir » s'affichent ; :has(img) les
   éteint dès que la photo arrive, sans rien changer au HTML.
   Ratio 3/4, celui de la photo servie : elle passe donc entière, sans recadrage
   à l'affichage. Le fond du placeholder est clair (et non forest comme
   .risk-ph) : la section est en greige, un rectangle sombre y ferait un trou. */
.authors-photo{position:relative;margin:0;border-radius:8px;overflow:hidden;
  aspect-ratio:3/4;background:
    radial-gradient(circle at 30% 25%,rgba(0,255,171,.16),transparent 55%),
    linear-gradient(150deg,#e4e5d6,#d7d9c8);
  border:1px solid var(--line);}
.authors-photo::after{content:"Photo à venir";position:absolute;inset:0;display:flex;
  align-items:center;justify-content:center;font-size:.75rem;font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;color:rgba(2,44,34,.28);}
.authors-photo:has(img){background:none;border-color:transparent;}
.authors-photo:has(img)::after{content:none;}
.authors-photo img{width:100%;height:100%;object-fit:cover;display:block;}
/* En une seule colonne, un portrait pleine largeur ferait un mur d'image de
   plus de 1000px de haut : on le borne et on le centre. */
@media(max-width:900px){.authors-photo{max-width:420px;margin-inline:auto;}}

/* FAQ du guide : elle a sa propre section depuis le 2026-07-29, donc elle suit
   un .hero-head et n'a plus besoin des 90px de .faq-list, calibrés pour une
   FAQ posée en fin de section sans titre à elle. */
.guide-faq .faq-list{margin-top:56px;}

/* ---- Formulaire sur fond néon ----
   Les styles de .form sont écrits pour un fond sombre (champs translucides
   blancs, texte crème, accents néon). Sur le néon, tout cela devient illisible :
   il faut l'exact opposé, des champs blancs pleins et des accents encre.
   Les boutons, eux, sont passés en btn-dark directement dans le HTML. */
.bg-neon .form input,.bg-neon .form textarea{background:#fff;border-color:rgba(2,44,34,.16);color:var(--ink);}
.bg-neon .form input::placeholder,.bg-neon .form textarea::placeholder{color:var(--muted);}
.bg-neon .form input:focus,.bg-neon .form textarea:focus{border-color:var(--forest);background:#fff;}
.bg-neon .form-consent{color:rgba(2,44,34,.7);}
.bg-neon .form .form-consent input[type=checkbox]{background:#fff;border-color:rgba(2,44,34,.3);accent-color:var(--pine);}
.bg-neon .form-consent a{color:var(--forest);}
.bg-neon .form-status.ok{color:var(--forest);}
.bg-neon .form-status.ko{color:#8f1d00;}

/* Rappel du formulaire en bas de page : les champs passent sur une ligne, le
   bloc reste centré comme le reste du .cta-band. */
.form-inline{max-width:760px;margin:36px auto 0;align-items:center;}
.form-inline-row{display:flex;gap:12px;width:100%;}
.form-inline-row input{flex:1;min-width:0;}
.form-inline-row .btn{flex:none;white-space:nowrap;}
@media(max-width:700px){.form-inline-row{flex-direction:column;}.form-inline-row .btn{width:100%;justify-content:center;}}
.form-inline .form-consent{justify-content:center;text-align:left;max-width:60ch;}
.form-inline .form-status{text-align:center;}

/* =========================================================================
   Page de vente Bible de la Ventilation (bible-de-la-ventilation.html)
   Créée le 2026-07-28. Reprend la structure de l'ancienne maquette Tailwind
   (contexte-statique/ressources/design/templates/labibledelaventilation.html)
   en la repassant dans la charte : palette, Fraunces/Geist, arrondis 8px,
   paddings 128/160px, icônes en traits fins. Le bandeau compte à rebours et
   le code promo de la maquette ne sont pas repris, le prix est ferme.
   ========================================================================= */

/* ---- Hero ----
   Le mockup produit est un PNG détouré : pas de cadre ni d'arrondi, juste une
   ombre portée qui suit sa silhouette, et la respiration de .animate-breathe. */
.bible-mockup{max-width:520px;margin:0 auto;
  filter:drop-shadow(0 30px 50px rgba(2,44,34,.22));
  animation:breathe 5s ease-in-out infinite;}
@keyframes breathe{0%,100%{transform:scale(1);}50%{transform:scale(1.035);}}
@media(prefers-reduced-motion:reduce){.bible-mockup{animation:none;}}

/* Ligne de réassurance : note Trustpilot + garantie, séparées par un point. */
.trust{flex-wrap:wrap;gap:14px;}
.trust-link,.trust-item{display:inline-flex;align-items:center;gap:8px;color:var(--muted);}
.trust-link{transition:color .25s;}
.trust-link:hover{color:var(--ink);}
.trust-item svg{width:17px;height:17px;color:var(--pine);flex:none;}
.trust-sep{width:4px;height:4px;border-radius:999px;background:rgba(2,44,34,.25);flex:none;}

/* ---- Colonnes texte + visuel (sections problème et solution) ----
   .split-reverse ne change que l'ordre visuel : le texte reste avant le visuel
   dans le HTML, donc dans l'ordre de lecture d'un lecteur d'écran. */
.split{display:grid;grid-template-columns:1fr 1fr;gap:72px;align-items:center;}
@media(max-width:960px){.split{grid-template-columns:1fr;gap:48px;}}
.split-visual{display:flex;justify-content:center;}
@media(max-width:960px){.split-reverse .split-visual{order:-1;}}
/* La mascotte 3D est un asset de marque (charte), servie détourée sur le fond
   de section : jamais de cadre, jamais de passage en noir et blanc. */
.mascotte{width:100%;max-width:360px;height:auto;
  filter:drop-shadow(0 26px 46px rgba(2,44,34,.28));}
.bg-cream .mascotte{filter:drop-shadow(0 26px 46px rgba(2,44,34,.16));}

/* ---- Liste des douleurs (section problème, fond forest) ---- */
.pains{list-style:none;margin:34px 0 0;padding:0;display:flex;flex-direction:column;gap:14px;}
.pain{display:flex;align-items:flex-start;gap:16px;padding:18px 20px;border-radius:8px;
  background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.11);
  transition:background .3s,border-color .3s;}
.pain:hover{background:rgba(255,255,255,.08);border-color:rgba(0,255,171,.35);}
.pain-ico{flex:none;width:40px;height:40px;border-radius:8px;display:grid;place-items:center;
  background:rgba(0,255,171,.12);color:var(--neon);}
.pain-ico svg{width:20px;height:20px;}
.pain strong{display:block;font-weight:600;font-size:1.02rem;color:#fff;margin-bottom:4px;}
.pain-note{display:block;font-size:.92rem;line-height:1.45;color:rgba(248,249,235,.7);}

/* ---- Grille 2x2 des bénéfices (section solution) ---- */
.cards-2{display:grid;grid-template-columns:1fr 1fr;gap:18px;margin-top:34px;}
@media(max-width:520px){.cards-2{grid-template-columns:1fr;}}
.cards-2 .card{padding:24px;}
.cards-2 .card h3{font-size:1.02rem;}
.cards-2 .card p{font-size:.92rem;}

/* ---- Grille des avis clients ----
   Réutilise le composant .review du hero de l'accueil : la citation d'abord,
   l'identité en pied de carte. Les cartes s'alignent en hauteur pour que les
   pieds de carte tombent au même niveau sur une rangée. */
.reviews-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:22px;margin-top:90px;align-items:stretch;}
@media(max-width:980px){.reviews-grid{grid-template-columns:1fr 1fr;}}
@media(max-width:640px){.reviews-grid{grid-template-columns:1fr;}}
.reviews-grid .review{display:flex;flex-direction:column;}
.reviews-grid .review p{flex:1;}
.reviews-grid .review-head{margin:20px 0 0;padding-top:18px;border-top:1px solid var(--line);}

/* ---- Bento du programme ----
   6 colonnes, cartes multi-tons : le rôle fond/carte n'est pas figé (charte).
   Chaque carte s'étire à la hauteur de sa rangée. */
.prog-grid{display:grid;grid-template-columns:repeat(6,1fr);gap:18px;margin-top:90px;align-items:stretch;}
.prog-2{grid-column:span 2;}
.prog-3{grid-column:span 3;}
.prog-4{grid-column:span 4;}
@media(max-width:900px){
  .prog-grid{grid-template-columns:repeat(2,1fr);}
  .prog-2,.prog-3,.prog-4{grid-column:span 1;}
  .prog-4{grid-column:span 2;}
}
@media(max-width:600px){
  .prog-grid{grid-template-columns:1fr;}
  .prog-2,.prog-3,.prog-4{grid-column:span 1;}
}
/* Carte sombre du bento sur fond clair : variante manquante du système de
   cartes, les autres (.card-white, .card-greige) existent déjà plus haut. */
.card-forest{background:var(--forest);color:var(--cream);}
.card-forest h3{color:#fff;}
.card-forest p{color:rgba(248,249,235,.72);}
.card-forest .card-ico{background:rgba(0,255,171,.12);color:var(--neon);}
.checklist-dark{grid-template-columns:1fr;gap:10px;margin:20px 0 0;}
.checklist-dark li{color:rgba(248,249,235,.85);font-size:.92rem;}
.checklist-dark .ck{background:rgba(0,255,171,.12);border-color:rgba(0,255,171,.3);color:var(--neon);}

/* ---- Carte d'offre ----
   Cette section partage le fond de la section « programme » qui la précède :
   la coupure n'est donc pas une bascule de couleur mais le mockup produit posé
   à cheval sur la carte. D'où le padding-top nul de la section (l'air vient du
   .price-wrap, qui réserve la place du mockup) et le fond blanc de la carte,
   seul contraste qui la détache du cream. */
.offer-section{padding-top:0;}
.price-wrap{position:relative;max-width:620px;margin:0 auto;padding-top:150px;}
/* Centrage par les marges et non par translateX(-50%) : l'animation breathe
   pose son propre transform, qui écraserait le décalage de centrage. */
.price-mockup{position:absolute;top:0;left:0;right:0;margin-inline:auto;width:320px;height:auto;
  z-index:2;filter:drop-shadow(0 26px 40px rgba(2,44,34,.28));
  animation:breathe 5s ease-in-out infinite;}
@media(prefers-reduced-motion:reduce){.price-mockup{animation:none;}}
@media(max-width:560px){
  .price-wrap{padding-top:120px;}
  .price-mockup{width:250px;}
}

/* Le padding haut de la carte dégage la hauteur dont le mockup déborde
   dessus : agrandir le mockup impose de l'augmenter d'autant, sinon l'image
   recouvre le titre. L'air au-dessus du mockup et sous la carte, lui, ne
   bouge pas (il vient du padding des sections). */
.price-card{position:relative;background:#fff;color:var(--ink);
  border:1px solid var(--line);border-radius:8px;
  padding:190px 48px 44px;text-align:center;
  box-shadow:0 30px 70px -40px rgba(2,44,34,.35);}
@media(max-width:560px){.price-card{padding:150px 24px 32px;}}
.price-card .h2{margin-bottom:8px;}
.price-sub{margin:0 0 30px;font-size:.98rem;color:var(--muted);}

.price-head{padding-bottom:26px;border-bottom:1px dashed var(--line);}
.price-amount{display:flex;align-items:baseline;justify-content:center;gap:14px;}
.price-now{font-size:clamp(2.75rem,7vw,3.5rem);font-weight:500;color:var(--forest);line-height:1;}
.price-note{margin:12px 0 0;font-size:.9rem;color:var(--muted);}

.price-list{list-style:none;margin:26px 0 0;padding:0;display:flex;flex-direction:column;gap:13px;
  width:fit-content;margin-inline:auto;text-align:left;}
.price-list li{display:flex;align-items:center;gap:12px;font-weight:500;font-size:.98rem;}
.price-list .ck{flex:none;width:24px;height:24px;border-radius:7px;background:var(--cream);
  border:1px solid var(--line);display:grid;place-items:center;color:var(--pine);}
.price-list .ck svg{width:14px;height:14px;}

.price-cta{margin-top:34px;width:100%;justify-content:center;padding:16px 28px;font-size:1.05rem;}
.price-reassure{display:flex;align-items:center;justify-content:center;gap:9px;flex-wrap:wrap;
  margin:18px 0 0;font-size:.85rem;color:var(--muted);}
.price-reassure svg{width:16px;height:16px;color:var(--pine);flex:none;}

/* Le test « CTA néon sur fond clair » cantonné à .page-bible a été généralisé
   le 2026-07-28 dans .btn-dark (voir la section « buttons » en haut du fichier). */

/* =========================================================================
   Page DPE projeté investisseurs (dpe-projete-investisseurs.html) — 2026-07-31
   Reprise du contenu de l'ancienne page WordPress /plan-de-renovation/ dans la
   charte. Elle réutilise au maximum l'existant (.hero-reviews, .cards-3,
   .split, .price-card, .faq-list, .peps) ; ce bloc ne contient que ce qui
   manquait vraiment.
   ========================================================================= */

/* ---- Porte-image générique en attente du visuel définitif ----
   Même mécanique que .risk-ph et .authors-photo : tant qu'aucun <img> n'est
   posé dedans, le fond et la mention « Visuel à venir » s'affichent, et
   :has(img) les éteint dès que l'image arrive. Déposer le .webp dans la figure
   suffit, il n'y a rien d'autre à modifier dans le HTML.
   Généralisé ici (et non copié une troisième fois) parce que le cas se répète :
   toute nouvelle page arrive avant ses visuels. */
.visual-ph{position:relative;margin:0;border-radius:8px;overflow:hidden;aspect-ratio:4/3;
  background:
    radial-gradient(circle at 30% 25%,rgba(0,255,171,.16),transparent 55%),
    linear-gradient(150deg,#e4e5d6,#d7d9c8);
  border:1px solid var(--line);}
.visual-ph::after{content:"Visuel à venir";position:absolute;inset:0;display:flex;
  align-items:center;justify-content:center;font-size:.75rem;font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;color:rgba(2,44,34,.28);}
.visual-ph:has(img){background:none;border-color:transparent;}
.visual-ph:has(img)::after{content:none;}
.visual-ph img{width:100%;height:100%;object-fit:cover;display:block;}
/* Variante pour une section en forest : un rectangle clair y ferait un trou. */
.visual-ph-dark{border-color:rgba(255,255,255,.12);
  background:
    radial-gradient(circle at 30% 25%,rgba(0,255,171,.10),transparent 55%),
    linear-gradient(150deg,#0b4535,#06281f);}
.visual-ph-dark::after{color:rgba(248,249,235,.22);}

/* ---- Cartes empilées au scroll (section « Le contexte », 2026-08-01) ----
   Effet dit « sticky stacking cards » : chaque carte est en position:sticky au
   même offset haut, si bien que la suivante remonte et vient recouvrir la
   précédente au lieu de se poser dessous. Aucun JavaScript n'est nécessaire,
   c'est du sticky en flux normal.
   L'offset augmente de 22px par carte (nth-child) pour laisser dépasser une
   arête de celle du dessous : sans ce décalage, la pile ne se lit plus comme
   une pile mais comme une seule carte qui change de contenu.
   Structure d'une carte : texte à gauche, visuel à droite, séparés par une
   diagonale légère (clip-path) qui casse la verticale et donne du mouvement. */
.stack{margin-top:90px;text-align:left;}
.stack-card{position:sticky;top:calc(var(--chrome-h) + 40px);
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,.82fr);
  min-height:clamp(520px,77vh,780px);border-radius:16px;}
/* Cet écart n'est pas une gouttière décorative, c'est le temps de pause de la
   carte : une fois collée, elle reste seule à l'écran tant que la suivante n'a
   pas remonté depuis le bas. Il faut donc au moins la hauteur de fenêtre restée
   libre sous la carte (~100px), plus la durée de pause voulue. En dessous de
   ~150px, la carte suivante entre dans le cadre avant même que la précédente
   soit posée, et l'empilement se lit comme un simple défilement. */
.stack-card + .stack-card{margin-top:300px;}
.stack-card:nth-child(2){top:calc(var(--chrome-h) + 62px);}
.stack-card:nth-child(3){top:calc(var(--chrome-h) + 84px);}
/* Quatrième carte ajoutée le 2026-08-04 (financement). Sans cette ligne, elle
   se collerait au même offset que la première et écraserait la pile à plat. */
.stack-card:nth-child(4){top:calc(var(--chrome-h) + 106px);}
/* La dernière carte reste collée en haut jusqu'au bout de la pile : sans une
   marge franche, le bouton semble accroché à son bord bas. */
.stack + .mt-cta{margin-top:100px;}
.stack-cream{background:var(--cream);color:var(--ink);}
.stack-forest{background:var(--forest);color:var(--cream);}

/* La carte étant haute, le texte n'est pas centré mais réparti : le cartouche
   reste accroché en haut, le bloc titre + paragraphe descend en bas (d'où le
   margin-top:auto sur le h3). C'est la respiration de la référence. */
.stack-body{position:relative;display:flex;flex-direction:column;padding:60px 68px;}
/* Le cartouche reprend le surligneur jaune de la référence, transposé au néon
   de la charte : sur le forest il vire au néon plein, sinon il disparaît. */
.stack-tag{align-self:flex-start;padding:3px 9px;border-radius:4px;
  font-size:.82rem;font-weight:500;line-height:1.4;
  background:rgba(0,255,171,.3);color:var(--forest);}
.stack-forest .stack-tag{background:var(--neon);color:var(--forest);}
/* Le grand numéro est un filigrane : posé en haut à droite de la colonne de
   texte, il ne doit jamais entrer en concurrence avec le titre. */
.stack-num{position:absolute;top:78px;right:68px;
  font-size:clamp(3.4rem,6vw,5rem);font-weight:600;line-height:1;
  letter-spacing:-.03em;color:rgba(2,44,34,.07);pointer-events:none;}
/* Plus contrasté que sur les cartes cream : un filigrane clair sur le forest
   se lit nettement moins bien qu'un filigrane sombre sur le cream, à opacité
   égale il disparaissait sur les cartes 02 et 04. */
.stack-forest .stack-num{color:rgba(248,249,235,.14);}
.stack-body h3{font-size:clamp(1.5rem,2.4vw,2rem);font-weight:500;line-height:1.15;
  letter-spacing:-.02em;margin:auto 0 16px;max-width:20ch;}
.stack-body p{margin:0;font-size:1rem;color:var(--muted);max-width:46ch;}
.stack-forest .stack-body p{color:rgba(248,249,235,.72);}

/* Le visuel mord de 56px sur la colonne de texte et sa bordure gauche est
   coupée en biais : la marge négative et le premier point du polygone doivent
   donc rester égaux, sinon un liseré du fond de carte reste visible. */
.stack-visual{position:relative;margin:0 0 0 -56px;overflow:hidden;
  border-radius:0 16px 16px 0;
  clip-path:polygon(56px 0,100% 0,100% 100%,0 100%);
  background:
    radial-gradient(circle at 30% 25%,rgba(0,255,171,.16),transparent 55%),
    linear-gradient(150deg,#e4e5d6,#d7d9c8);}
/* Même mécanique que .visual-ph : la mention s'éteint dès qu'une <img> est
   déposée dans la figure, il n'y a rien d'autre à changer dans le HTML. */
.stack-visual::after{content:"Visuel à venir";position:absolute;inset:0;display:flex;
  align-items:center;justify-content:center;font-size:.75rem;font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;color:rgba(2,44,34,.28);}
.stack-visual:has(img){background:none;}
.stack-visual:has(img)::after{content:none;}
/* En absolu, et non en flux : une image en flux impose sa hauteur intrinsèque
   à la figure (height:100% ne résout pas, la figure n'ayant pas de hauteur
   propre), ce qui étirait la carte à la hauteur de la photo. Hors flux, c'est
   la carte qui commande et l'image qui s'y adapte. */
.stack-visual img{position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;display:block;}
/* Recadrage sur le bas de la photo, à poser sur l'image quand son sujet n'est
   pas au centre. Cas de la carte 03 : les panneaux de fibre de bois occupent la
   moitié basse du cliché, et le cadrage 16/9 du mobile, centré, ne montrait que
   l'enduit gris du haut. Sans effet en grand écran, où le cadre est plus haut
   que large et où c'est la largeur qui est rognée. */
.stack-visual img.focus-bas{object-position:center bottom;}

/* Témoignage en surimpression du visuel (2026-08-04). Le voile n'est pas un
   effet de style : sur une photo de chantier, du texte clair sans dégradé
   derrière devient illisible dès que la zone basse est claire.
   Valeurs calibrées sur le pire cas du lot, la façade en brique blonde en
   plein soleil de la carte 01 : un voile qui suffit sur une photo sombre y
   laisse le texte illisible. Il faut donc rester quasi opaque sur toute la
   hauteur du texte et ne s'éteindre qu'au-dessus.
   L'avatar est en display:block dans un span en flex : sans ça, la règle
   .stack-visual img ci-dessus le mettrait en absolute plein cadre. */
.stack-quote{position:absolute;left:0;right:0;bottom:0;z-index:1;
  padding:92px 34px 30px 34px;color:var(--cream);
  background:linear-gradient(to top,
    rgba(2,44,34,.95) 0%,rgba(2,44,34,.92) 38%,
    rgba(2,44,34,.66) 66%,transparent 100%);}
.stack-quote p{margin:0 0 12px;font-size:1.02rem;font-weight:500;line-height:1.35;
  letter-spacing:-.01em;max-width:26ch;color:var(--cream);}
/* Le texte est déjà en crème plein sur le voile : c'est la graisse seule qui
   marque le fragment, pas un retour à l'opacité comme dans les cartes d'avis. */
.stack-quote p strong{font-weight:700;}
.stack-quote-who{display:flex;align-items:center;gap:9px;
  font-size:.82rem;font-weight:500;color:rgba(248,249,235,.78);}
.stack-quote-who img{position:static;width:26px;height:26px;border-radius:50%;
  object-fit:cover;display:block;flex:none;}

/* En une colonne, l'empilement n'a plus de sens (les cartes deviennent hautes
   et le sticky masquerait le texte) : retour à des cartes qui se suivent.
   Texte d'abord, visuel et témoignage en bas (2026-08-14) : le titre de la
   carte doit être le premier point d'entrée, comme en grand écran où il est
   à gauche. La diagonale suit le visuel et passe donc sur son bord haut. */
@media(max-width:900px){
  .stack{margin-top:64px;}
  .stack-card{position:static;grid-template-columns:1fr;min-height:0;
    overflow:hidden;}
  .stack-card + .stack-card{margin-top:20px;}
  .stack-body{padding:36px 28px 40px;order:1;}
  /* Le clamp du grand écran plancherait à 3.4rem : sur une carte en une
     colonne, le filigrane arrive alors à hauteur du titre et lui dispute la
     place au lieu de rester en fond. */
  .stack-num{top:24px;right:28px;font-size:2.4rem;}
  .stack-body h3{margin-top:34px;}
  /* 4/3 et non 16/9 : le témoignage posé en bas mange près de la moitié d'un
     cadre panoramique, il ne restait qu'un bandeau de photo au-dessus. */
  .stack-visual{order:2;margin:0;aspect-ratio:4/3;border-radius:0;
    clip-path:polygon(0 28px,100% 0,100% 100%,0 100%);}
  .stack-quote{padding:44px 24px 30px;}
  .stack-quote p{font-size:.92rem;margin-bottom:9px;max-width:34ch;}
}

/* ---- Protocole en 3 étapes (timeline horizontale) ----
   La timeline verticale de la page à propos raconte un parcours dans le temps
   long ; ici il s'agit d'un protocole en trois temps courts, d'où la version
   horizontale prévue par la charte : pastilles numérotées reliées par un filet.
   Le filet part de chaque pastille et court jusque sous la suivante (d'où le
   right négatif égal à la gouttière) ; la pastille, opaque, masque le segment
   qui passerait derrière elle. */
.steps{display:grid;grid-template-columns:repeat(3,1fr);gap:72px;margin-top:90px;}
.step{position:relative;padding-top:72px;}
/* Le filet part de la pastille et court jusque sous la suivante : sa marge
   droite négative vaut la gouttière de la grille, et doit être reprise si
   celle-ci change. */
.step::before{content:"";position:absolute;top:17px;left:0;right:-72px;height:1px;
  background:var(--line);}
.step:last-child::before{right:0;}
.step-num{position:absolute;top:0;left:0;z-index:1;
  display:grid;place-items:center;width:36px;height:36px;border-radius:999px;
  background:var(--cream);border:1px solid var(--line);
  font-size:.72rem;font-weight:500;color:var(--pine);
  transition:background .25s ease,border-color .25s ease,color .25s ease,
    box-shadow .25s ease,transform .25s ease;}
/* Même langage de survol que les points de la timeline de la page à propos :
   bascule vers le néon et halo diffus. Le survol porte sur l'étape entière,
   pas sur la seule pastille, qui serait une cible minuscule. */
.step:hover .step-num{background:var(--neon);border-color:var(--neon);color:var(--forest);
  box-shadow:0 0 0 5px rgba(0,255,171,.18);transform:scale(1.1);}
.step h3{font-size:1.12rem;margin:0 0 14px;font-weight:600;}
.step p{margin:0;font-size:.95rem;color:var(--muted);}
/* En une colonne le filet horizontal n'a plus rien à relier : il disparaît,
   les pastilles suffisent à porter l'ordre de lecture. */
@media(max-width:820px){
  .steps{grid-template-columns:1fr;gap:44px;margin-top:64px;}
  .step::before{display:none;}
}

/* ---- Timeline en trois étapes (page investisseurs, 2026-08-01) ----
   Remplace la grille .steps en trois colonnes. Rail sticky à gauche dont les
   pastilles se remplissent au scroll (classe .is-active posée par layout.js),
   puis une rangée par étape : texte à gauche, maquette du livrable à droite.
   Les maquettes sont en HTML/CSS et reprennent le vocabulaire des fiches de
   l'étude de cas (feuille blanche + quadrillage millimétré de 20px). */
/* La hauteur des trois cartes est pilotée depuis ici (2026-08-04). C'est la
   carte de l'étape 3 qui commande : sa hauteur vaut celle du document plus le
   « chrome » fixe (padding 36px en haut et en bas, cartouche ADEME de 72px,
   puis l'air avant l'image). Les étapes 1 et 2 reprennent le même total en
   min-height, sinon elles restaient 70px plus courtes que l'étape 3. */
.flow{--fc-doc-h:clamp(320px,52vh,520px);
  --fc-doc-gap:48px;
  --fc-card-h:calc(var(--fc-doc-h) + 148px + var(--fc-doc-gap));
  display:grid;grid-template-columns:140px minmax(0,1fr);gap:56px;margin-top:90px;
  text-align:left;}
.flow-rail{align-self:start;position:sticky;top:calc(var(--chrome-h) + 56px);}
.flow-rail ol{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:20px;}
.flow-rail li{display:flex;align-items:center;gap:12px;
  font-size:.95rem;color:var(--muted);transition:color .3s ease;}
.flow-rail li.is-active{color:var(--ink);font-weight:600;}
/* Pastille creuse tant que l'étape n'est pas atteinte, pleine ensuite. Le vert
   est le pine et non le néon : à 11px sur fond cream, le néon ne se voit pas. */
.flow-rail .fd{flex:none;width:15px;height:15px;border-radius:999px;
  border:2px solid rgba(2,44,34,.28);background:transparent;
  transition:background .3s ease,border-color .3s ease;}
.flow-rail li.is-active .fd{background:var(--pine);border-color:var(--pine);}

/* align-items:start et non center : « Étape 1 » doit partir sur la bordure
   haute de la maquette d'en face, pas flotter au milieu. Le décalage négatif
   rattrape l'espace au-dessus des capitales du cartouche, sinon le texte
   commence visiblement plus bas que l'arête de la carte. */
.flow-step{display:grid;grid-template-columns:minmax(0,.62fr) minmax(0,1fr);
  gap:0 100px;align-items:start;}
/* Le visuel occupe les deux rangées de sa colonne : le bouton de l'étape 3,
   qui le suit dans le HTML pour passer sous lui en mobile, se replace ainsi
   tout seul en rangée 2 de la colonne de texte, là où il était quand il vivait
   dans .flow-text. Sans ce span, il partirait à droite sous la maquette. */
.flow-visual{grid-column:2;grid-row:1/span 2;}
.flow-step + .flow-step{margin-top:80px;}
.flow-text{margin-top:-2px;}
/* Interlignage serré : le cartouche et le titre se lisent comme un seul bloc
   de deux lignes, pas comme deux éléments empilés. */
/* Tailles en clamp (2026-08-14) : à taille fixe, le titre d'étape (1.6rem en
   gras) arrivait au niveau du .h2 de la section une fois celui-ci descendu à
   son plancher de 2rem en mobile, et la hiérarchie titre de section / titre
   d'étape disparaissait. Les maximums sont ceux d'avant, le rendu sur grand
   écran ne bouge pas. Le cartouche suit la même pente, sinon il finirait plus
   gros que le titre qu'il annonce. */
.flow-kicker{display:block;font-size:clamp(1.1rem,2.8vw,1.4rem);font-weight:400;
  color:var(--muted);line-height:1.2;letter-spacing:-.01em;margin-bottom:0;}
.flow-text h3{font-size:clamp(1.25rem,3.2vw,1.6rem);font-weight:600;
  line-height:1.2;margin:0 0 18px;letter-spacing:-.01em;}
.flow-text p{margin:0;font-size:1rem;color:var(--muted);}
/* Bouton secondaire de l'étape 3 (récupérer un exemple), enfant direct de
   .flow-step et non de .flow-text : la marge tient lieu de row-gap, que la
   grille laisse à 0 pour ne pas écarter les étapes sans bouton. */
.flow-cta{margin:22px 0 0;}

/* Feuille blanche, comme les fiches du comparatif : même quadrillage à 20px,
   mais coins arrondis à 8px, parce que c'est ici un encadré d'interface et
   non une feuille de papier posée de travers. */
/* Hauteur de la maquette (2026-08-04) : avant, la carte se contentait de la
   hauteur de son contenu (~250px) et faisait figure de vignette à côté du texte.
   Sur les sites de référence, ce visuel occupe presque toute la hauteur d'écran.
   D'où la min-height en vh, bornée par clamp : en dessous de 440px la maquette
   redevient une vignette, au-dessus de 700px elle ne tient plus dans un écran de
   portable une fois le header déduit. Le contenu est alors réparti sur la
   hauteur (flex + règles par étape plus bas), sinon on gagnerait juste du vide
   en bas de carte. */
.flow-card{position:relative;overflow:hidden;padding:36px;border-radius:8px;
  display:flex;flex-direction:column;min-height:var(--fc-card-h);
  background:#fff;border:1px solid var(--line);
  box-shadow:0 22px 50px -18px rgba(2,44,34,.16);}
.flow-card::before{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background-size:20px 20px;
  background-image:
    linear-gradient(to right,rgba(2,44,34,.05) 1px,transparent 1px),
    linear-gradient(to bottom,rgba(2,44,34,.05) 1px,transparent 1px);}
.flow-card > *{position:relative;z-index:1;}
.flow-card-center{align-items:center;justify-content:center;text-align:center;}

/* Étape 1 : la ligne « fichier transmis », puis la note actuelle. */
/* Fonds opaques et non teintés en alpha : le quadrillage de la carte
   traverserait sinon les encadrés, qui doivent se lire comme des blocs posés
   par-dessus la feuille. */
.fc-row{display:flex;align-items:center;gap:16px;padding:18px;border-radius:8px;
  background:#f6f8f7;border:1px solid var(--line);}
.fc-ico{flex:none;display:grid;place-items:center;width:44px;height:44px;border-radius:8px;}
.fc-ico svg{width:22px;height:22px;}
.fc-ico-pdf{background:rgba(194,58,46,.09);border:1px solid rgba(194,58,46,.18);color:#c23a2e;}
.fc-row-txt{flex:1;min-width:0;}
.fc-row-txt strong{display:block;font-size:.92rem;}
.fc-sub{display:block;margin-top:3px;font-size:.78rem;color:var(--muted);}
.fc-check{flex:none;display:grid;place-items:center;width:30px;height:30px;border-radius:999px;
  background:rgba(0,255,171,.16);color:var(--pine);}
.fc-check svg{width:15px;height:15px;}
.fc-note{display:flex;align-items:center;justify-content:center;gap:22px;
  margin-top:26px;padding:22px;border-radius:8px;border:1px solid var(--line);
  background:#fff;}
/* Étape 1 seulement : le bloc « note actuelle » absorbe la hauteur restante de
   la carte et garde son étiquette centrée. Sans le :not(), il ferait la même
   chose sur la carte de l'étape 3, dont tout le contenu est au contraire centré
   en bloc. */
.flow-card:not(.flow-card-center) .fc-note{flex:1;}
.fc-note-col{flex-direction:column;gap:16px;width:100%;background:#f6f8f7;}
.fc-note-lbl{font-size:.68rem;font-weight:600;text-transform:uppercase;letter-spacing:.13em;
  color:var(--muted);text-align:right;}
.fc-note-col .fc-note-lbl{text-align:center;}

/* Étiquette DPE : carré de couleur officielle, comme sur un vrai diagnostic. */
.dpe-letter{position:relative;display:grid;place-items:center;
  width:70px;height:70px;border-radius:8px;color:#fff;
  font-size:2rem;font-weight:700;line-height:1;}
/* Dans les maquettes de la timeline, l'étiquette est l'élément qu'on doit voir
   de loin : à 70px elle se perdait dans une carte de 600px de haut. Le sélecteur
   est limité à .flow-card, ailleurs (comparatif avant/après de la page
   propriétaires) le format d'origine reste le bon. */
.flow-card .dpe-letter{width:104px;height:104px;font-size:3rem;border-radius:10px;}
/* Étape 1 : l'encadré « note actuelle » occupe la moitié basse de la carte.
   L'étiquette reste l'élément fort mais sans écraser le bloc ; le reste de la
   hauteur est occupé par un mini-récapitulatif des données lues sur le DPE. */
.flow-card:not(.flow-card-center) .dpe-letter{width:104px;height:104px;font-size:3rem;border-radius:12px;}
.flow-card:not(.flow-card-center) .fc-note{gap:18px;}
.flow-card:not(.flow-card-center) .fc-note-lbl{font-size:.78rem;}

/* Récapitulatif « ce qu'on a lu sur votre DPE » : trois lignes posées sous
   l'étiquette pour remplir l'encadré et montrer que le document est exploité. */
.fc-facts{list-style:none;margin:4px 0 0;padding:0;width:100%;max-width:280px;
  display:flex;flex-direction:column;gap:9px;}
.fc-facts li{display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:9px 14px;border-radius:8px;background:#fff;border:1px solid var(--line);}
.fc-facts li span{font-size:.64rem;font-weight:600;text-transform:uppercase;
  letter-spacing:.09em;color:var(--muted);}
.fc-facts li strong{font-size:.84rem;font-weight:700;color:var(--ink);}
.dpe-g{background:#d7221f;box-shadow:0 12px 26px -12px rgba(215,34,31,.7);}
/* Lettre toujours blanche, y compris sur les fonds clairs D et C (regle posee
   le 2026-08-07) : une etiquette DPE se lit comme un bloc, et une lettre qui
   change d'encre selon la classe casse la serie. L'ombre portee du texte
   redonne au blanc le detachement qu'il perd sur un jaune clair. */
.dpe-d{background:#f2df4a;box-shadow:0 12px 26px -12px rgba(242,223,74,.7);}
.dpe-c,.dpe-d{text-shadow:0 1px 2px rgba(2,44,34,.38);}
/* La pastille se pose à cheval sur le coin haut droit de l'étiquette, d'où le
   left calé sur la largeur du carré moins un chevauchement de 18px. */
.dpe-tag{position:absolute;top:-13px;left:calc(100% - 18px);display:inline-flex;align-items:center;gap:5px;
  padding:5px 9px;border-radius:999px;background:#fff;border:1px solid var(--line);
  box-shadow:0 8px 18px -8px rgba(2,44,34,.35);
  font-size:.62rem;font-weight:700;letter-spacing:.02em;color:var(--ink);white-space:nowrap;}
.dpe-tag svg{width:12px;height:12px;color:var(--pine);}

/* Étape 2 : l'en-tête « analyse en cours », puis un bloc par scénario. */
.fc-head{display:flex;align-items:center;justify-content:flex-start;gap:10px;margin-bottom:26px;
  width:100%;
  font-size:.82rem;font-weight:600;text-transform:uppercase;letter-spacing:.08em;}
.fc-head-ico{display:grid;place-items:center;width:28px;height:28px;border-radius:999px;
  background:rgba(0,255,171,.16);color:var(--pine);}
.fc-head-ico svg{width:15px;height:15px;animation:fc-spin 1.6s linear infinite;}
@keyframes fc-spin{to{transform:rotate(360deg);}}
@media(prefers-reduced-motion:reduce){.fc-head-ico svg{animation:none;}}
/* flex:1 : les deux scénarios se partagent la hauteur libre de la carte à parts
   égales, leur contenu restant centré verticalement. C'est ce qui évite une
   grande carte avec deux encadrés serrés en haut et du vide en dessous. */
/* Padding resserré depuis le passage à trois scénarios (2026-08-07) : à 22px et
   16px d'écart, la carte dépassait la hauteur commune aux trois étapes. */
.fc-scn{flex:1;display:flex;flex-direction:column;justify-content:center;
  padding:18px 20px;border-radius:8px;border:1px solid var(--line);background:#fff;}
.fc-scn + .fc-scn{margin-top:12px;}
.fc-scn-head{display:flex;align-items:flex-end;justify-content:space-between;gap:14px;
  margin-bottom:13px;}
.fc-scn-lbl{display:block;margin-bottom:3px;font-size:.68rem;font-weight:600;
  text-transform:uppercase;letter-spacing:.13em;color:var(--muted);}
.fc-scn-head strong{font-size:.9rem;}
.dpe-chip{flex:none;padding:3px 10px;border-radius:999px;font-size:.75rem;font-weight:600;}
.dpe-chip-d{background:rgba(244,231,79,.22);border:1px solid rgba(180,166,20,.35);color:#7a6f0d;}
.dpe-chip-c{background:rgba(164,203,112,.2);border:1px solid rgba(120,160,70,.35);color:#4f6f2a;}
.dpe-chip-b{background:rgba(82,177,83,.18);border:1px solid rgba(52,130,66,.4);color:#2f6b3c;}
.fc-bar{display:block;height:8px;border-radius:999px;background:rgba(2,44,34,.07);overflow:hidden;}
.fc-bar-fill{display:block;height:100%;border-radius:999px;}
.fc-bar-d{width:60%;background:#e2d43f;}
.fc-bar-c{width:85%;background:#a4cb70;}
.fc-bar-b{width:96%;background:#52b153;}
/* Scénario recommandé : un liseré pine et une pastille suffisent à créer le
   chemin par défaut. Pas de fond coloré, les trois encadrés doivent rester
   lisibles comme un même jeu d'options. */
.fc-scn.is-reco{border-color:var(--pine);box-shadow:0 0 0 1px var(--pine) inset;}
.fc-scn-reco{margin-left:6px;padding:2px 7px;border-radius:999px;
  background:rgba(0,255,171,.18);color:var(--pine);
  font-size:.6rem;font-weight:700;letter-spacing:.08em;}
/* Condition d'atteinte de la classe B, dite sous la barre plutôt que dans la
   pastille : elle ne doit pas concurrencer la lettre. */
.fc-scn-note{display:block;margin-top:9px;font-size:.68rem;color:var(--muted);}

/* Étape 3 : le livrable lui-même (2026-08-04). Avant, la carte affichait une
   promesse abstraite (logo ADEME, titre, étiquette visée). Elle montre
   maintenant la photo des premières pages du DPE projeté en éventail : le
   visiteur voit ce qu'il reçoit, ce qui lève le « concrètement j'ai quoi ? ».
   Le titre et le logo sont ramenés sur une seule ligne en haut pour rendre
   toute la hauteur restante au document, sinon l'image tombait sous 200px. */
/* flex-end et non flex-start : le cartouche ADEME est plus haut que les deux
   lignes de titre. Aligné par le haut, sa bordure basse tombait dans le vide
   sous « Sous 72h ». C'est le bas des deux blocs qui doit coïncider. */
.fc-deliv-head{display:flex;align-items:flex-end;justify-content:space-between;
  gap:24px;width:100%;text-align:left;}
.fc-deliv-titles{display:block;}
.fc-ademe{flex:none;display:inline-flex;padding:10px 20px;border-radius:8px;
  border:1px solid var(--line);background:#fff;}
.fc-ademe img{width:auto;height:52px;display:block;}
.fc-title{display:block;font-size:1.35rem;font-weight:400;margin:0 0 6px;}
.fc-kicker{display:block;margin:0;font-size:.7rem;font-weight:700;text-transform:uppercase;
  letter-spacing:.13em;color:var(--pine);}

/* Hauteur définie et non flex:1 : avec flex:1, la hauteur du bloc reste
   indéfinie, le max-height:100% de l'image ne résout pas et le document
   débordait de la carte (rogné par son overflow:hidden). En fixant la hauteur
   en vh, l'image se cale dessus. width:fit-content : la figure se réduit à la
   largeur réelle du document, sinon la pastille flottait dans le vide à droite
   au lieu de se poser sur le bord de la feuille. */
.fc-doc{position:relative;height:var(--fc-doc-h);
  width:fit-content;max-width:100%;margin:var(--fc-doc-gap) auto 0;}
.fc-doc img{display:block;height:100%;width:auto;max-width:100%;object-fit:contain;}
/* Pastille flottante : l'étiquette visée reste l'élément fort de la carte, le
   document sert de preuve derrière elle. Posée en bas à droite plutôt qu'au
   centre, elle laisse lisible l'en-tête du DPE et l'échelle A-G. */
/* min-width : sans elle, la pastille de l'étape 1 (« Note actuelle ») faisait
   141px contre 223px à l'étape 3 (« Nouvelle étiquette visée »), et l'effet de
   miroir entre les deux cartes tombait. Les deux sont calées sur la plus large,
   avec un peu de marge pour rester égales si la police de secours s'applique. */
.fc-doc-badge{position:absolute;right:0;bottom:14px;z-index:2;min-width:206px;
  display:flex;flex-direction:column;align-items:center;gap:9px;
  padding:14px 15px;border-radius:10px;background:#fff;border:1px solid var(--line);
  box-shadow:0 20px 40px -14px rgba(2,44,34,.45);
  animation:fc-breathe 4.5s ease-in-out infinite;}
/* Respiration : la pastille monte et redescend de 7px, l'ombre s'étale au
   sommet du mouvement comme si elle décollait vraiment du document. Lent et de
   faible amplitude : c'est un signal de vie, pas une animation d'attention. */
@keyframes fc-breathe{
  0%,100%{transform:translateY(0) scale(1);
    box-shadow:0 20px 40px -14px rgba(2,44,34,.45);}
  50%{transform:translateY(-7px) scale(1.018);
    box-shadow:0 32px 54px -14px rgba(2,44,34,.34);}}
@media(prefers-reduced-motion:reduce){.fc-doc-badge{animation:none;}}
/* Intitulé resserré : c'est lui qui fixait la largeur des deux pastilles, et
   « Nouvelle étiquette visée » à .68rem espacé de .13em les rendait trop
   larges par rapport au document. */
.fc-doc-badge .fc-note-lbl{text-align:center;font-size:.61rem;letter-spacing:.1em;}
.fc-doc-badge .dpe-letter{width:76px;height:76px;font-size:2.2rem;border-radius:9px;}
/* Étape 3 : les trois classes des scénarios plutôt qu'une cible unique. À 76px
   chacune, la pastille aurait été plus large que la feuille qu'elle survole,
   d'où le format réduit ; l'ombre portée de chaque étiquette est coupée, trois
   halos côte à côte dans un cartouche de 15px de padding bavaient dessus. */
.fc-scale{display:inline-flex;align-items:center;gap:7px;}
.fc-scale .dpe-letter,
.fc-doc-badge .fc-scale .dpe-letter{width:46px;height:46px;font-size:1.5rem;
  border-radius:7px;box-shadow:none;}
.fc-doc-tag{display:inline-flex;align-items:center;gap:5px;
  font-size:.64rem;font-weight:700;letter-spacing:.02em;color:var(--ink);white-space:nowrap;}
.fc-doc-tag svg{width:12px;height:12px;color:var(--pine);}
/* Étape 1 : pas de promesse ici, juste la consommation lue sur le document. */
.fc-doc-tag-now{font-size:.62rem;font-weight:600;color:var(--muted);letter-spacing:.03em;}

/* Ligne de transfert de l'étape 1, en surcouche sur le haut de la feuille.
   Décalée vers le haut et la gauche pour mordre sur l'air au-dessus du
   document plutôt que sur son en-tête, qui est ce qu'on doit reconnaître. */
.fc-doc-row{position:absolute;top:-32px;left:-14px;z-index:2;width:auto;
  gap:13px;padding:13px 15px;border-radius:10px;background:#fff;
  box-shadow:0 18px 34px -14px rgba(2,44,34,.42);}
.fc-doc-row .fc-ico{width:38px;height:38px;}
.fc-doc-row .fc-ico svg{width:19px;height:19px;}
.fc-doc-row .fc-row-txt{flex:none;}
.fc-doc-row .fc-check{width:26px;height:26px;}
.fc-doc-row .fc-check svg{width:13px;height:13px;}

@media(max-width:1000px){
  /* Colonnes empilées : la maquette n'a plus de texte à côté d'elle à équilibrer,
     une carte pleine hauteur d'écran ne ferait qu'allonger le scroll. Le
     document reste le pilote de la hauteur, mais borné plus bas. */
  .flow{grid-template-columns:1fr;gap:0;
    --fc-doc-h:min(56vh,440px);}
  .fc-scn{flex:none;}
  /* Le rail perd son intérêt une fois les colonnes empilées : il doublerait
     les titres d'étapes juste en dessous. */
  .flow-rail{display:none;}
  .flow-step{grid-template-columns:1fr;gap:32px;}
  /* Une seule colonne : le visuel reprend sa place dans le flux, donc après le
     texte et avant le bouton, dans l'ordre du HTML. */
  .flow-visual{grid-column:auto;grid-row:auto;}
  .flow-cta{margin-top:0;}
  .flow-text{margin-top:0;}
  .flow-step + .flow-step{margin-top:52px;}
  /* Colonnes empilées : la carte n'a plus à tenir la hauteur d'écran, mais le
     document doit rester lisible, d'où une hauteur plancher un peu plus haute
     que le min-height de la carte. */
  .fc-doc{height:min(56vh,440px);}
}
@media(max-width:520px){
  .flow-card{padding:22px;min-height:0;}
  /* Même spécificité que la règle « étape 1 » plus haut, sinon celle-ci, plus
     spécifique, garderait ses 150px et ferait déborder la carte en mobile. */
  .flow-card .dpe-letter,
  .flow-card:not(.flow-card-center) .dpe-letter{width:80px;height:80px;font-size:2.2rem;}
  .flow-card:not(.flow-card-center) .fc-note{gap:18px;}
  /* Sur mobile la pastille sortirait de la carte : elle repasse au-dessus de
     l'étiquette, centrée. */
  .dpe-tag{top:-15px;left:50%;transform:translateX(-50%);}
  /* Étape 3 : le logo ADEME passe sous le titre, il n'y a plus la largeur pour
     les tenir côte à côte sans écraser l'un des deux. */
  .fc-deliv-head{flex-direction:column;align-items:flex-start;gap:16px;}
  .fc-doc{height:44vh;margin-top:32px;}
  /* min-width neutralisée : 232px sur un document de 256px de large mangerait
     toute la feuille. */
  .fc-doc-badge{padding:12px 13px;gap:7px;bottom:0;min-width:0;}
  .fc-doc-badge .dpe-letter,
  .flow-card .fc-doc-badge .dpe-letter{width:62px;height:62px;font-size:1.8rem;}
  /* Les trois classes de l'étape 3 : sur un document de 256px de large, trois
     carrés de 62px sortiraient de la feuille. Sélecteur aligné sur celui de la
     règle précédente, sinon c'est elle qui gagne. */
  .fc-doc-badge .fc-scale .dpe-letter,
  .flow-card .fc-doc-badge .fc-scale .dpe-letter{width:40px;height:40px;font-size:1.25rem;}
  .fc-scale{gap:5px;}
  .fc-doc-badge .fc-note-lbl{font-size:.6rem;letter-spacing:.1em;}
  /* « Classe D garantie au minimum » ne tient pas sur une ligne à cette
     largeur : le white-space:nowrap du tag élargirait la pastille au-delà du
     document. */
  .fc-doc-badge .fc-doc-tag{white-space:normal;text-align:center;line-height:1.35;}
  /* La ligne de transfert ne tient plus si elle déborde à gauche : elle rentre
     dans le cadre et se resserre. */
  .fc-doc-row{top:-24px;left:0;gap:10px;padding:10px 11px;}
  .fc-doc-row .fc-ico{width:32px;height:32px;}
  .fc-doc-row .fc-row-txt strong{font-size:.82rem;}
  .fc-doc-row .fc-sub{font-size:.7rem;}
}

/* ---- Tuiles de résultat (étude de cas, fond forest) ----
   Deux chiffres, le gain de classe et l'économie. En mono, comme tous les
   chiffres du site (effet « donnée mesurée » plutôt que promesse marketing). */
.results{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-top:34px;}
@media(max-width:520px){.results{grid-template-columns:1fr;}}
.result{padding:20px 22px;border-radius:8px;
  background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.11);}
.result .rl{display:block;font-size:.68rem;font-weight:600;text-transform:uppercase;
  letter-spacing:.13em;color:rgba(248,249,235,.6);}
.result .rv{display:block;margin-top:9px;font-size:1.5rem;line-height:1.1;color:var(--neon);}

/* La carte d'offre unique (.offer-card et ses enfants .offer-ico,
   .offer-card-title, .offer-items, .offer-sep, .offer-bonus-intro,
   .offer-price) a été retirée le 2026-08-01 : la section offre est désormais
   éclatée en trois blocs, voir « Section offre éclatée » plus bas. */

/* ---- Encadré bonus ----
   Pattern « bordure gauche colorée » de la charte. Le filet est en pine et non
   en néon : sur une carte blanche le néon ne se détache pas. */
.bonus-card{margin-top:22px;padding:30px 32px;background:#fff;border:1px solid var(--line);
  border-left:4px solid var(--pine);border-radius:8px;
  box-shadow:0 18px 40px -32px rgba(2,44,34,.35);}
@media(max-width:560px){.bonus-card{padding:24px 22px;}}
.bonus-card h3{font-size:1.08rem;margin:0 0 6px;font-weight:600;}
.bonus-card > p{margin:0 0 20px;font-size:.95rem;color:var(--muted);}
.bonus-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:18px;}
.bonus-list li{display:flex;align-items:flex-start;gap:14px;}
.bonus-list .bi{flex:none;width:36px;height:36px;border-radius:8px;display:grid;place-items:center;
  background:var(--cream);border:1px solid var(--line);color:var(--pine);}
.bonus-list .bi svg{width:18px;height:18px;}
.bonus-list strong{display:block;font-weight:600;font-size:.98rem;margin-bottom:3px;}
.bonus-list span.bn{display:block;font-size:.92rem;line-height:1.45;color:var(--muted);}

/* ---- Section offre éclatée (page investisseurs, 2026-08-01) ----
   Remplace la carte blanche unique .offer-card, qui empilait livrables,
   avantages et prix en une seule colonne. Trois blocs successifs : la grille
   .cards-3 (réutilisée telle quelle), le bandeau des avantages inclus, puis le
   prix seul. Les trois sont séparés par de l'air, pas par des filets. */
.incl{max-width:940px;margin:56px auto 0;}
/* Intitulé en capitales espacées, comme les .eyebrow : il annonce le bloc sans
   se faire passer pour un titre de section. */
.incl-lbl{margin:0 0 18px;text-align:center;font-size:.76rem;font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;color:var(--muted);}
.incl-grid{display:grid;grid-template-columns:1fr 1fr;gap:22px;}
@media(max-width:820px){.incl-grid{grid-template-columns:1fr;}}
/* .bonus-card portait une marge haute pensée pour un empilement : ici les
   cartes sont côte à côte dans une grille qui gère déjà l'écart. */
.incl-grid .bonus-card{margin-top:0;}
.incl-ico{display:grid;place-items:center;width:38px;height:38px;margin-bottom:14px;
  border-radius:8px;background:var(--cream);border:1px solid var(--line);color:var(--pine);}
.incl-ico svg{width:19px;height:19px;}
.incl-grid .bonus-card p{margin:0;font-size:.95rem;color:var(--muted);}

/* ---- Livrables de l'offre, en 2×2 (page investisseurs, 2026-08-14) ----
   940px et non les 1200px du wrap : à pleine largeur, deux cartes côte à côte
   donnent des lignes de 90 caractères, illisibles. C'est aussi la largeur qu'
   avait le bloc « Inclus » que cette grille remplace.
   Chaque carte porte une des quatre couleurs de la charte, le texte en haut et
   son visuel en bas. Le visuel est poussé en pied par margin-top:auto : les
   quatre textes n'ont pas la même longueur, sans ça les images se décalaient
   d'une carte à l'autre sur une même rangée. */
.deliv-grid{max-width:940px;margin:64px auto 0;
  display:grid;grid-template-columns:1fr 1fr;gap:22px;align-items:stretch;}
.card-wrap > .deliv-card{flex:1;}
/* overflow:hidden : les visuels débordent des côtés pour toucher les bords de
   la carte (marges négatives ci-dessous), c'est lui qui les recoupe à l'arrondi. */
.deliv-card{display:flex;flex-direction:column;overflow:hidden;
  border-radius:12px;padding:32px 32px 0;text-align:left;}
.deliv-card h3{margin:0 0 12px;font-size:1.16rem;font-weight:600;line-height:1.25;
  letter-spacing:-.01em;}
.deliv-card p{margin:0;font-size:.95rem;line-height:1.5;color:var(--muted);}
.deliv-forest{background:var(--forest);color:var(--cream);}
.deliv-forest h3{color:#fff;}
.deliv-forest p{color:rgba(248,249,235,.72);}
.deliv-cream{background:var(--cream);}
/* Variante de la carte cream pour les sections en fond cream (page
   propriétaires occupants), où celle-ci se fondrait dans le fond. */
.deliv-greige{background:var(--greige);}
/* Blanche et non greige (2026-08-14) : le greige de la carte était celui du
   fond de section, elle n'avait pas de bord franc et se lisait comme un trou
   dans la grille. Le greige n'est pas perdu pour autant, il passe sur la
   feuille de chiffrage à l'intérieur. */
.deliv-white{background:#fff;box-shadow:0 0 0 1px var(--line) inset;}
.deliv-neon{background:var(--neon);}
.deliv-neon p{color:rgba(2,44,34,.75);}

/* Le visuel touche les trois bords bas de la carte : c'est ce qui distingue
   ces cartes des encadrés à icône du reste du site, et ce qui donne à la
   rangée son assise. */
/* margin-top:auto et non une marge fixe : les quatre textes n'ont pas la même
   longueur, et les cartes d'une même rangée sont étirées à la même hauteur. La
   marge fixe collait l'image sous le texte et laissait le vide en bas de la
   carte la plus courte. Le padding assure l'écart minimum sous le texte. */
.deliv-visual{margin:auto -32px 0;padding:38px 0 0;}
.deliv-visual img{display:block;width:100%;height:100%;object-fit:cover;
  aspect-ratio:3/2;}
/* Le DPE en éventail est un document et non une photo : il entre par le bas de
   la carte, cadré sur sa tête (object-position:top) pour montrer l'étiquette.
   Sans recadrage il gardait sa hauteur naturelle, très supérieure à celle des
   autres visuels, et étirait toute la rangée. */
.deliv-visual-doc{margin-inline:22px;}
.deliv-visual-doc img{aspect-ratio:16/11;object-position:center top;
  border-radius:6px 6px 0 0;}
/* Portrait carré ramené à la même bande que les autres visuels, cadré haut
   pour ne pas couper le visage. */
.deliv-visual-portrait img{object-position:center 22%;}

/* Maquette du chiffrage : une feuille blanche qui entre par le bas de la
   carte, sur le modèle des fiches du comparatif plus haut dans la page. */
.deliv-visual-chiffrage{margin-inline:0;}
/* La feuille prend toujours l'autre neutre que celui du fond de section, sinon
   elle s'y fond dès qu'elle dépasse de la carte : cream sur une section greige
   (page investisseurs), greige sur une section cream (page propriétaires). */
.bg-cream .chif{background:var(--greige);}
.chif{background:var(--cream);color:var(--ink);border-radius:8px 8px 0 0;
  padding:22px 20px 24px;}
.chif-head{display:flex;align-items:baseline;justify-content:space-between;gap:10px;
  padding-bottom:12px;margin-bottom:12px;border-bottom:1px dashed var(--line);}
.chif-lbl{font-size:.74rem;font-weight:600;letter-spacing:.1em;text-transform:uppercase;
  color:var(--pine);}
.chif-ref{font-size:.74rem;color:var(--muted);}
.chif-rows{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:12px;}
.chif-rows li{display:flex;align-items:baseline;justify-content:space-between;gap:14px;
  font-size:.88rem;color:var(--muted);}
.chif-rows strong{font-weight:500;color:var(--ink);white-space:nowrap;}
.chif-total{display:flex;align-items:baseline;justify-content:space-between;gap:14px;
  margin:14px 0 0;padding-top:12px;border-top:1px solid var(--line);
  font-size:.9rem;font-weight:600;color:var(--ink);}
.chif-total strong{font-size:1.05rem;color:var(--pine);}
.chif-foot{margin:10px 0 0;font-size:.78rem;color:var(--muted);}

/* Une colonne : même seuil que l'ancien bloc « Inclus », les cartes deviennent
   illisibles à deux bien avant 900px à cause de leur padding. */
@media(max-width:820px){
  .deliv-grid{grid-template-columns:1fr;max-width:520px;margin-top:48px;}
  .deliv-card{padding:28px 24px 0;}
  /* En une colonne la feuille ne fait plus que ~300px : le libellé et la
     référence ne tiennent plus sur la même ligne, ils s'empilent. */
  .chif-head{flex-direction:column;align-items:flex-start;gap:5px;}
  .deliv-visual{margin-inline:-24px;padding-top:24px;}
  .deliv-visual-doc{margin-inline:16px;}
  .deliv-visual-chiffrage{margin-inline:0;}
}

/* Le prix est le point d'arrivée de la page et la cible de tous les CTA : il a
   son propre bloc blanc, plus étroit que les grilles au-dessus pour concentrer
   le regard au moment de décider. */
.offer-buy{max-width:560px;margin:64px auto 0;padding:44px 48px;text-align:center;
  background:#fff;border:1px solid var(--line);border-radius:8px;
  box-shadow:0 30px 70px -40px rgba(2,44,34,.35);}
@media(max-width:560px){.offer-buy{padding:34px 24px;margin-top:48px;}}
.offer-buy .price-cta{margin-top:30px;}
/* Sous 560px la carte ne fait plus que ~300px utiles : à 1,05rem le libellé
   passe sur deux lignes et rejette la flèche à l'autre bout. */
@media(max-width:560px){.offer-buy .price-cta{font-size:.92rem;padding:15px 20px;}}
/* Variante sans encadré (page investisseurs, 2026-08-14) : plus de bloc blanc
   ni de montant en gros, le prix est dans le libellé du bouton et il ne reste
   que lui, sa ligne de modalité et sa garantie. Le bouton reprend sa largeur
   naturelle : étiré sur les 560px du bloc, seul au milieu du greige, il faisait
   barre pleine largeur au lieu de bouton. */
/* Sans son encadré, le bouton n'a plus de padding de carte pour le décoller de
   la grille des livrables : la marge haute reprend ce que le bloc blanc
   apportait, sinon il paraît accroché au bas des cartes. */
/* Nommée -solo et non -bare : la page formation a créé de son côté un
   .offer-buy-bare, plus bas dans ce fichier, avec sa propre marge de 34px.
   Deux blocs différents portaient le même nom, et c'est le dernier qui
   gagnait, d'où un bouton recollé aux cartes ici. */
/* 72px : la valeur de .mt-cta, l'écart des boutons de fin de section partout
   ailleurs sur le site. Le bloc n'ayant plus d'encadré, c'est bien la même
   situation qu'un CTA posé sous une grille de cartes. */
.offer-buy-solo{padding:0;background:none;border:0;box-shadow:none;margin-top:72px;}
.offer-buy-solo .price-cta{width:auto;margin-top:0;}
/* Le libellé porte le prix, il est donc plus long que celui de la carte de
   prix d'origine : sous 560px il passait sur deux lignes en laissant « TTC »
   seul en dessous, la flèche restant collée au milieu du bloc. */
@media(max-width:560px){
  .offer-buy-solo .price-cta{font-size:.84rem;padding:15px 16px;gap:8px;}
}
.offer-buy-solo .price-note{margin-top:18px;}
.offer-buy-solo .price-reassure{margin-top:6px;}

/* ---- Comparatif « plan des artisans » vs « Rénovation Optimale » ----
   Reproduction en HTML/CSS d'un visuel qui existait en PNG : deux fiches de
   papier légèrement inclinées, un montant en pastille sur chacune, et
   l'économie en pied. Codé plutôt qu'exporté en image pour rester net à toutes
   les tailles d'écran, rester lisible par les moteurs de recherche, et pouvoir
   corriger un chiffre sans repasser par un logiciel de dessin.
   Le rouge #c23a2e n'est pas dans la palette de marque : c'est le même que
   celui de l'étiquette « classe actuelle » de l'échelle DPE (.tag-now), déjà
   admis comme le rouge du site pour signaler l'état qu'on veut quitter. */
/* Composition en diagonale : la fiche des artisans en haut à gauche, celle de
   Rénovation Optimale en bas à droite et posée par-dessus. Les deux se
   chevauchent d'environ un tiers de leur largeur, la seconde passant devant :
   c'est elle qui doit rester lisible en entier. */
/* Le padding latéral réserve la place dont les pastilles débordent des
   fiches : sans lui elles sortiraient du bloc et mordraient sur la colonne de
   texte à gauche. */
.compare{position:relative;width:100%;max-width:596px;margin-inline:auto;
  padding:26px 30px 26px;}
/* Angles droits (et non les 8px des cartes du site) : ce sont des feuilles de
   papier, pas des encadrés d'interface.
   Double ombre : une large en néon très dilué, qui décolle la fiche du fond
   vert et lui donne sa profondeur, plus une noire courte qui lui donne son
   arête. Le néon seul resterait mou, le noir seul plaquerait la fiche. */
.cmp-card{position:relative;margin:0;width:66%;padding:26px 22px 24px;
  background:#fff;color:var(--ink);border-radius:0;
  box-shadow:0 34px 64px -18px rgba(0,255,171,.34),
             0 10px 24px -14px rgba(0,0,0,.5);}
/* Quadrillage « papier millimétré » à l'intérieur de la fiche, très dilué : il
   appuie la lecture « document technique » sans concurrencer le texte. Carreaux
   de 20px, la moitié du pattern d'accent de la charte, qui lui déborde d'un
   coin alors que celui-ci reste dans la feuille.
   Posé en z-index 0 et non en -1, qui le ferait passer derrière le fond blanc
   de la fiche : c'est le contenu qui remonte en z-index 1. */
.cmp-card::before{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background-size:20px 20px;
  background-image:
    linear-gradient(to right,rgba(2,44,34,.06) 1px,transparent 1px),
    linear-gradient(to bottom,rgba(2,44,34,.06) 1px,transparent 1px);}
.cmp-card figcaption,.cmp-card ul{position:relative;z-index:1;}
/* Sans contenu à afficher, la fiche des artisans serait deux fois plus courte
   que celle d'en face : une hauteur plancher lui garde sa présence de feuille. */
.cmp-before{min-height:240px;}
/* Inclinaison volontairement faible : au-delà, l'ensemble tourne au collage. */
.cmp-before{margin-right:auto;transform:rotate(-1.2deg);z-index:1;}
/* La marge négative fait remonter la seconde fiche sur la première : c'est
   elle qui dose le chevauchement vertical. */
.cmp-after{margin-left:auto;margin-top:-58px;transform:rotate(1.2deg);z-index:2;}
.cmp-card figcaption{margin-bottom:16px;font-size:.9rem;font-weight:600;
  text-transform:uppercase;letter-spacing:.04em;line-height:1.25;}
/* Pastilles de montant : elles ne sont plus collées au bord de la fiche mais
   flottent au-dessus, en respirant lentement. Le décalage d'animation évite
   qu'elles ne montent et descendent à l'unisson, ce qui trahirait le procédé.
   Arrondi léger (10px) : les fiches restent à angle droit, les pastilles non. */
.cmp-badge{position:absolute;z-index:3;padding:9px 17px;border-radius:10px;
  font-size:.92rem;font-weight:600;white-space:nowrap;
  box-shadow:0 14px 28px -12px rgba(0,0,0,.55);
  animation:cmpFloat 4.5s ease-in-out infinite;}
@keyframes cmpFloat{0%,100%{transform:translateY(0);}50%{transform:translateY(-7px);}}
@media(prefers-reduced-motion:reduce){.cmp-badge{animation:none;}}
.cmp-badge-bad{top:-17px;right:-16px;background:#c23a2e;color:#fff;}
/* Vert forêt exclu ici : c'est la couleur du fond de section, la pastille y
   disparaîtrait. Pine plein + texte blanc, comme la règle de contraste des
   boutons sur fond clair. */
.cmp-badge-good{top:-19px;right:-16px;background:var(--pine);color:#fff;
  animation-delay:-2.2s;}

/* Postes du plan des artisans, volontairement occultés (le visuel d'origine
   les floute) : la fiche sert de repoussoir, son détail n'apporte rien.
   Des barres et non du faux texte flouté, pour ne rien afficher qui puisse se
   lire comme un vrai devis. */
.cmp-redacted{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:12px;}
.cmp-redacted li{height:13px;border-radius:3px;background:rgba(2,44,34,.8);filter:blur(2.5px);}
.cmp-redacted li:nth-child(2){width:88%;}
.cmp-redacted li:nth-child(3){width:70%;}

/* Croix et coches en traits fins plutôt que puces rondes + texte barré : le
   statut de chaque poste se lit d'un coup d'œil, et le texte reste lisible au
   lieu d'être rayé. */
.cmp-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:11px;
  font-size:.88rem;line-height:1.35;}
.cmp-list li{display:flex;align-items:flex-start;gap:10px;}
.cmp-list .ci{flex:none;display:block;width:16px;height:16px;margin-top:1px;color:var(--pine);}
.cmp-list .ci svg{width:16px;height:16px;display:block;}
/* Postes écartés par l'optimisation. */
.cmp-list li.out{color:var(--muted);}
.cmp-list li.out .ci{color:#c23a2e;opacity:.75;}

/* Flèche logée dans l'espace libre en haut à droite, entre les deux fiches.
   Elle finit en piqué sur la pastille « 17 000 € » : pointe et barbes suivent
   la tangente de la courbe à son extrémité, sinon la tête vise à côté. */
.cmp-arrow{position:absolute;z-index:3;top:13%;right:4%;
  width:104px;height:auto;color:rgba(248,249,235,.5);}
/* ---- Étude de cas sur fond clair (page investisseurs, 2026-08-01) ----
   Le bloc a été écrit pour un fond forest : halo néon, filets blancs, chiffres
   en néon. Sur cream ou greige tout ça devient illisible, d'où ces reprises,
   limitées aux sections qui ne sont pas en .on-dark. Le reste (fiches papier,
   quadrillage, pastilles) marche déjà sur les deux fonds. */
.section:not(.on-dark) .result{background:rgba(2,44,34,.04);border-color:var(--line);}
.section:not(.on-dark) .result .rl{color:var(--muted);}
.section:not(.on-dark) .result .rv{color:var(--pine);}
.section:not(.on-dark) .cmp-card{box-shadow:0 34px 64px -18px rgba(2,44,34,.22),
             0 10px 24px -14px rgba(2,44,34,.28);}
.section:not(.on-dark) .cmp-arrow{color:rgba(2,44,34,.38);}
/* En une colonne, les fiches s'empilent en pleine largeur : il n'y a plus
   d'espace libre en diagonale où loger la flèche. Elle passe donc en flux,
   entre les deux fiches, ce qui la remet dans le sens de lecture (la fiche du
   dessus mène à celle du dessous). Le positionnement absolu ne convenait pas
   ici : la hauteur de la première fiche dépend du texte, on ne peut pas viser
   l'interstice avec un pourcentage. */
@media(max-width:600px){
  .compare{padding:26px 26px 20px;display:flex;flex-direction:column;}
  .cmp-card{width:100%;}
  .cmp-before{order:1;}
  .cmp-arrow{order:2;position:static;width:64px;align-self:center;
    margin:16px 0 10px;}
  .cmp-after{order:3;margin-top:0;}
  .cmp-before,.cmp-after{transform:none;}
}

/* ---- Variante « identité en tête de carte » de la grille d'avis ----
   .reviews-grid est écrite pour la page Bible, où la citation vient d'abord et
   l'identité en pied, d'où le filet de séparation au-dessus de .review-head.
   Ici l'identité est en tête (comme dans le hero et sur Trustpilot) : ce filet
   n'a plus rien à séparer et laisserait un trait orphelin en haut de carte. */
.reviews-top .review-head{margin:0 0 14px;padding-top:0;border-top:0;}

/* ---- Carte « avis certifiés », en fin de grille d'avis ----
   Occupe la dernière cellule de .reviews-grid : la mention de certification
   compte autant qu'un témoignage, elle est donc traitée comme une carte et non
   comme une note de bas de page. */
.review-certified{display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:14px;padding:34px 28px;text-align:center;border-radius:8px;
  background:rgba(0,255,171,.12);border:1px solid rgba(0,255,171,.45);}
.review-certified .rc-ico{display:grid;place-items:center;width:52px;height:52px;
  border-radius:999px;border:1.5px solid var(--pine);color:var(--pine);}
.review-certified .rc-ico svg{width:24px;height:24px;}
.review-certified .rc-title{margin:0;font-size:1.1rem;font-weight:600;}
.review-certified p{margin:0;font-size:.92rem;line-height:1.45;color:rgba(2,44,34,.7);}

/* Ces trois règles ciblaient .offer-card, supprimée le 2026-08-01. Leur rôle
   (largeur du CTA et de la ligne de garantie) est repris par .offer-buy, qui
   fait déjà 560px de large : plus rien à contraindre ici. */

/* =========================================================================
   Composants de la page « DPE projeté — propriétaires »
   (dpe-projete-proprietaires.html, 2026-08-03)
   ========================================================================= */

/* ---- Témoignage en attente ----
   Les avis de cette page ne sont pas encore collectés. Plutôt que d'afficher
   des citations inventées ou des photos de banque d'images (ce que faisait
   l'ancienne page), la carte reste vide mais garde exactement l'encombrement
   d'un .review : le jour où le texte arrive, la mise en page ne bouge pas.
   Bordure en pointillés et libellé explicite : impossible de la confondre avec
   un vrai avis, y compris pour un visiteur. */
.review-ph{display:flex;flex-direction:column;gap:14px;padding:26px;min-height:220px;
  border:1.5px dashed rgba(2,44,34,.22);border-radius:8px;background:rgba(255,255,255,.45);}
.review-ph .rph-lbl{font-size:.7rem;font-weight:700;letter-spacing:.14em;text-transform:uppercase;
  color:rgba(2,44,34,.38);}
/* Identité à venir : pastille ronde + deux traits, calqués sur .review-head. */
.review-ph .rph-who{display:flex;align-items:center;gap:12px;}
.review-ph .rph-av{width:44px;height:44px;border-radius:999px;background:rgba(2,44,34,.08);flex:none;}
.review-ph .rph-who i{display:block;height:9px;border-radius:999px;background:rgba(2,44,34,.09);}
.review-ph .rph-who i:first-child{width:110px;margin-bottom:7px;}
.review-ph .rph-who i:last-child{width:70px;}
/* Fausses lignes de texte : elles donnent le volume du futur avis. Largeurs
   décroissantes, comme un vrai paragraphe qui se termine en milieu de ligne. */
.review-ph .rph-lines{display:flex;flex-direction:column;gap:10px;margin-top:auto;}
.review-ph .rph-lines span{display:block;height:9px;border-radius:999px;background:rgba(2,44,34,.09);}
.review-ph .rph-lines span:nth-child(2){width:92%;}
.review-ph .rph-lines span:nth-child(3){width:78%;}
.review-ph .rph-lines span:nth-child(4){width:55%;}

/* ---- Comparatif en deux colonnes (« Le vrai problème ») ----
   Deux listes face à face avec une pastille VS au milieu. La colonne repoussoir
   n'est pas colorée en rouge : elle décrit un métier légitime, simplement mal
   outillé pour ce besoin. C'est le contraste greige / forest qui porte
   l'opposition, pas un code faute/réussite. */
.versus{position:relative;display:grid;grid-template-columns:1fr 1fr;gap:22px;margin-top:90px;}
.vs-col{padding:34px 32px;border-radius:8px;}
.vs-col-bad{background:var(--greige);border:1px solid var(--line);}
.vs-col-good{background:var(--forest);color:var(--cream);}
.vs-col h3{margin:0 0 24px;font-size:1.12rem;font-weight:600;}
.vs-col-good h3{color:#fff;}
.vs-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:14px;}
.vs-list li{display:flex;align-items:flex-start;gap:12px;font-size:.98rem;line-height:1.35;}
.vs-list .vi{display:grid;place-items:center;width:22px;height:22px;border-radius:6px;flex:none;
  margin-top:1px;}
.vs-list .vi svg{width:13px;height:13px;}
.vs-list-bad li{color:rgba(2,44,34,.72);}
.vs-list-bad .vi{background:rgba(2,44,34,.07);color:rgba(2,44,34,.5);}
.vs-list-good li{color:rgba(248,249,235,.88);}
.vs-list-good .vi{background:rgba(0,255,171,.14);color:var(--neon);}
/* La pastille est posée à cheval sur la gouttière, à mi-hauteur. En
   position:absolute elle ne prend pas de place dans la grille : les deux
   colonnes restent parfaitement égales. */
.vs-badge{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);z-index:2;
  display:grid;place-items:center;width:56px;height:56px;border-radius:999px;
  background:var(--neon);color:var(--forest);font-size:.85rem;font-weight:700;letter-spacing:.04em;
  box-shadow:0 10px 26px -10px rgba(2,44,34,.5);}
/* En une colonne, la pastille ne peut plus rester en absolute à 50 % : ce point
   n'est la jonction des deux cartes que si elles font exactement la même
   hauteur, ce qui n'arrive pas avec des listes de longueurs différentes. Elle
   repasse donc dans le flux, entre les deux cartes (son ordre dans le HTML),
   et ses marges négatives la font mordre sur chacune d'une vingtaine de pixels
   sans rien décaler : -28px de part et d'autre annulent ses 56px de hauteur. */
@media(max-width:860px){
  .versus{display:flex;flex-direction:column;gap:0;}
  .vs-badge{position:static;transform:none;margin:-28px auto;}
  .vs-col-bad{margin-bottom:9px;}
  .vs-col-good{margin-top:9px;}
}

/* ---- Études de cas (fond forest) ----
   Une rangée par projet : le récit à gauche, les chiffres à droite. Le second
   projet inverse l'ordre pour éviter deux rangées identiques à la suite. */
.cases{display:flex;flex-direction:column;gap:72px;margin-top:90px;}
.case{display:grid;grid-template-columns:1fr 1fr;gap:64px;align-items:center;}
.case:nth-child(even) .case-text{order:2;}
.case-tag{display:inline-block;margin-bottom:16px;padding:5px 12px;border-radius:999px;
  background:rgba(0,255,171,.12);border:1px solid rgba(0,255,171,.32);
  font-size:.68rem;font-weight:700;letter-spacing:.13em;text-transform:uppercase;color:var(--neon);}
.case-text h3{margin:0 0 22px;font-family:'Fraunces';font-variation-settings:'opsz' 96,'SOFT' 50,'WONK' 0;
  font-size:clamp(1.4rem,2.6vw,1.85rem);font-weight:400;line-height:1.15;color:#fff;}
.case-quote{margin:0;padding-left:20px;border-left:2px solid rgba(0,255,171,.45);}
.case-quote p{margin:0;font-size:1rem;line-height:1.5;color:rgba(248,249,235,.8);font-style:italic;}
.case-who{display:flex;align-items:center;gap:14px;margin-top:26px;}
/* Initiales plutôt qu'une photo : l'ancienne page utilisait des portraits de
   banque d'images qui ne représentaient personne. */
.case-av{display:grid;place-items:center;width:46px;height:46px;border-radius:999px;flex:none;
  background:rgba(0,255,171,.14);border:1px solid rgba(0,255,171,.3);
  font-size:.82rem;font-weight:700;color:var(--neon);letter-spacing:.02em;}
.case-who strong{display:block;font-size:.98rem;font-weight:600;color:#fff;}
.case-who .cw-sub{display:block;font-size:.86rem;color:rgba(248,249,235,.6);}

/* Le panneau de chiffres : en-tête, saut de classe, puis deux tuiles .results. */
.case-panel{padding:32px;border-radius:8px;
  background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.11);}
.case-panel-lbl{margin:0;font-size:.68rem;font-weight:700;letter-spacing:.13em;
  text-transform:uppercase;color:var(--neon);}
.case-panel-sub{margin:6px 0 0;font-size:1.05rem;font-weight:600;color:#fff;}
.case-jump{display:flex;align-items:flex-end;justify-content:center;gap:18px;margin-top:28px;}
.cj-side{display:flex;flex-direction:column;align-items:center;gap:10px;}
.cj-lbl{font-size:.66rem;font-weight:600;letter-spacing:.12em;text-transform:uppercase;
  color:rgba(248,249,235,.6);text-align:center;}
/* La flèche et le gain de classe forment un seul bloc, aligné sur le bas des
   étiquettes et non sur leur milieu : sinon le « +3 » flotte trop haut. */
.cj-gain{display:flex;flex-direction:column;align-items:center;gap:6px;padding-bottom:14px;}
.cj-gain svg{width:26px;height:26px;color:rgba(248,249,235,.45);}
.cj-gain span{font-size:.82rem;font-weight:700;color:var(--neon);}
.case-panel .results{margin-top:28px;}
@media(max-width:960px){
  .case{grid-template-columns:1fr;gap:36px;}
  /* Empilé, le récit repasse toujours avant les chiffres. */
  .case:nth-child(even) .case-text{order:0;}
}
@media(max-width:420px){
  /* Les deux étiquettes DPE et le gain ne tiennent plus côte à côte. */
  .case-jump{gap:10px;}
  .dpe-letter{width:58px;height:58px;font-size:1.6rem;}
}

/* Étiquettes DPE manquantes (couleurs officielles du diagnostic).
   Le C est un jaune-vert clair, mais sa lettre reste blanche comme toutes les
   autres : voir la règle et son ombre portée avec .dpe-d. */
.dpe-f{background:#ee7d18;box-shadow:0 12px 26px -12px rgba(238,125,24,.7);}
/* E manquait a la serie : ajoute le 2026-08-08 pour le mur de scenarios du
   hero du simulateur, ou E est la classe de depart du logement. Teinte relevee
   sur la barre E des etiquettes rendues par l'app, entre le F et le D. */
.dpe-e{background:#f2a93b;box-shadow:0 12px 26px -12px rgba(242,169,59,.7);}
.dpe-c{background:#c9d24c;box-shadow:0 12px 26px -12px rgba(201,210,76,.75);}
.dpe-b{background:#52b153;box-shadow:0 12px 26px -12px rgba(82,177,83,.7);}

/* ---- Grille d'avis à quatre colonnes ----
   .reviews-grid est en trois colonnes : avec quatre cartes, la quatrième reste
   seule sur une deuxième rangée. Les placeholders n'ayant pas de texte à
   accueillir, quatre colonnes plus étroites tiennent sans problème. */
.reviews-4{grid-template-columns:repeat(4,1fr);}
@media(max-width:1100px){.reviews-4{grid-template-columns:1fr 1fr;}}
@media(max-width:640px){.reviews-4{grid-template-columns:1fr;}}

/* ---- Bascule « valeur verte » (fond forest) ----
   Le raisonnement qui suit le simulateur : le chiffre affiché par la calculette
   rend l'achat évident. Détaché en gros texte, c'est le pivot de la page. */
.turn{max-width:760px;margin:56px auto 0;text-align:center;}
.turn p{margin:0;font-size:1.05rem;line-height:1.5;color:rgba(248,249,235,.72);}
.turn .turn-punch{margin-top:18px;font-family:'Fraunces';
  font-variation-settings:'opsz' 144,'SOFT' 50,'WONK' 0;
  font-size:clamp(1.5rem,3vw,2.05rem);line-height:1.2;color:#fff;}
.turn .turn-punch em{font-style:normal;color:var(--neon);}

/* Le simulateur intégré reprend la façade des articles (.article-embed) : même
   composant, même comportement au clic, rien de nouveau à maintenir. Seuls la
   largeur et la hauteur sont recalées, la page n'est pas une colonne d'article. */
.embed-sim{max-width:820px;margin-left:auto;margin-right:auto;}
.embed-sim iframe{height:900px;}
@media(max-width:640px){.embed-sim iframe{height:1240px;}}

/* « Paiement unique » sert d'étiquette au prix juste en dessous : les 30px de
   .price-sub (écrits pour la carte de prix, où le texte est un sous-titre)
   coupent le lien entre les deux. */
.offer-buy .price-sub{margin-bottom:10px;}

/* =========================================================================
   PAGE DPE IMPACT (formation agents immobiliers, 2026-08-10)
   La page reprend le gabarit des autres pages de vente : hero cream, .flow
   pour le déroulé, .prog-grid pour le programme, .price-card pour l'offre.
   Seuls les blocs qui n'existaient nulle part ailleurs sont écrits ici.
   ========================================================================= */

/* ---- Carte « argumentaire » du hero ----
   Même grammaire que .budget (hero propriétaires) : carte blanche, en-tête
   greige, bandeau forest en pied où tombe le seul accent néon de la carte.
   Elle montre le livrable mental de la formation (l'objection de l'acquéreur
   et la réponse chiffrée) plutôt qu'un coffret produit qui n'existe pas. */
.argu{margin:0;background:#fff;border:1px solid var(--line);border-radius:8px;
  overflow:hidden;box-shadow:0 30px 70px -30px rgba(2,44,34,.28);}
.argu-head{display:flex;align-items:center;justify-content:space-between;gap:20px;
  padding:22px 26px;border-bottom:1px solid var(--line);background:#fcfdfa;}
.argu-case{font-size:.66rem;text-transform:uppercase;letter-spacing:.1em;color:var(--muted);}
.argu-jump{display:inline-flex;align-items:center;gap:9px;}
.argu-jump .dpe-letter{width:34px;height:34px;font-size:1.05rem;border-radius:6px;box-shadow:none;}
.argu-jump svg{width:15px;height:15px;color:var(--muted);}

/* L'objection est citée telle qu'un acquéreur la formule, en Fraunces : c'est
   une parole, pas une donnée. Le filet à gauche la marque comme citation sans
   ajouter de guillemets décoratifs. */
.argu-obj{padding:22px 24px;border-left:3px solid rgba(2,44,34,.14);
  margin:26px 26px 0;background:rgba(2,44,34,.03);border-radius:0 6px 6px 0;}
.argu-obj p{margin:0 0 8px;font-family:'Fraunces',Georgia,serif;
  font-variation-settings:'opsz' 144,'SOFT' 50,'WONK' 0;
  font-size:1.12rem;line-height:1.25;}
.argu-who{font-size:.7rem;text-transform:uppercase;letter-spacing:.09em;color:var(--muted);}

.argu-ans{padding:24px 26px 26px;}
.argu-ans-lbl{display:block;font-size:.68rem;text-transform:uppercase;
  letter-spacing:.09em;color:var(--pine);margin-bottom:14px;}
.argu-lines{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:12px;}
.argu-lines li{display:flex;align-items:baseline;justify-content:space-between;gap:16px;
  font-size:.92rem;padding-bottom:12px;border-bottom:1px solid var(--line);}
.argu-lines li:last-child{border-bottom:0;padding-bottom:0;}
.argu-lines span{color:var(--muted);}
.argu-lines strong{flex:none;font-family:'JetBrains Mono',ui-monospace,monospace;
  font-weight:500;font-variant-numeric:tabular-nums;letter-spacing:-.02em;}
/* Le montant réellement à payer est la chute du raisonnement : seule ligne en
   encre pleine, les deux au-dessus ne sont que du contexte. */
.argu-lines .argu-key strong{color:var(--forest);font-size:1.1rem;}

.argu-foot{display:flex;align-items:center;gap:12px;padding:20px 26px;
  background:var(--forest);color:rgba(248,249,235,.72);font-size:.82rem;}
.argu-foot svg{width:20px;height:20px;flex:none;color:var(--neon);}
.argu-foot strong{color:var(--neon);font-weight:600;}

/* ---- Carte d'offre sans mockup produit ----
   .offer-section réserve la place d'un mockup posé à cheval sur la carte
   (padding-top nul sur la section, 150px sur le .price-wrap, 190px sur la
   carte). Une formation n'a pas d'objet à montrer : sans cette variante, la
   carte s'ouvrait sur 340px de blanc. L'air revient dans le padding de section,
   là où il est chez toutes les autres. */
.offer-nomockup{padding-top:var(--pad-lg);}
.offer-nomockup .price-wrap{padding-top:0;}
.offer-nomockup .price-card{padding-top:48px;}
@media(max-width:560px){.offer-nomockup .price-card{padding-top:34px;}}

/* ---- Timeline .flow, variante courte ----
   Les maquettes de cette page tiennent en quelques lignes : elles ne portent
   pas de document en éventail comme celles de la page investisseurs, pour
   lesquelles --fc-card-h a été calibré. Reprise telle quelle, cette hauteur
   laissait 300px de vide sous chaque bloc. Les scénarios de l'étape 2 perdent
   aussi leur flex:1, qui n'a de sens que s'il reste de la hauteur à répartir. */
.flow-court{--fc-card-h:clamp(280px,36vh,370px);}
.flow-court .fc-scn{flex:none;}
.flow-court .fc-scn + .fc-scn{margin-top:14px;}

/* ---- Bandeau des réseaux ----
   Logos en niveaux de gris et opacité réduite : ils situent le public de la
   formation, ils ne servent pas de caution. La mention en dessous n'est pas une
   précaution de style, elle dit qu'il n'y a aucun partenariat commercial. */
/* ---- Deux « résultats clients » sous le hero (2026-08-10) ----
   Remplacent le bandeau de logos de réseaux. Même grammaire que la carte
   .argu du hero juste au-dessus : fond blanc, filet, rayon 8px, ombre portée
   basse.
   Pas de filet de séparation au-dessus (retiré le 2026-08-10) : l'ancien
   bandeau de logos en avait un parce qu'il n'était qu'une ligne d'images
   flottantes, sans forme propre. Deux cartes posées sur le crème se détachent
   déjà toutes seules, le trait ne faisait que barrer le bas du hero.
   L'espacement est celui de .hero-reviews (page investisseurs) : c'est
   `.hero .reviews-title` qui porte les 6rem de respiration sous le hero, le
   bloc de cartes ne garde que les 32px qui le séparent de son titre. */
.hero-proof{display:grid;grid-template-columns:1fr 1fr;gap:22px;
  margin-top:32px;}
@media(max-width:820px){.hero-proof{grid-template-columns:1fr;gap:18px;}}

.proof{margin:0;background:#fff;border:1px solid var(--line);border-radius:8px;
  padding:26px 28px;box-shadow:0 14px 34px -22px rgba(2,44,34,.24);}
/* Le titre est la promesse tenue, pas une citation : il est en Geist et non en
   Fraunces, pour ne pas concurrencer le H1 à deux cents pixels au-dessus. */
.proof-claim{margin:0 0 20px;font-size:1.16rem;font-weight:600;line-height:1.25;}
.proof-who{display:flex;align-items:center;gap:12px;
  padding-top:18px;border-top:1px solid var(--line);}
/* EXCEPTION ASSUMÉE à la règle « portraits en noir et blanc, couleur au
   survol » de la charte : ici les visages restent en couleur, sans survol
   (demandé le 2026-08-10). Ces deux cartes sont vues dès le premier écran, où
   rien n'invite encore à survoler : un portrait gris y passait pour une photo
   éteinte plutôt que pour un parti pris. Ne pas « remettre en conformité »
   sans revenir sur cette décision. */
.proof-who img{width:44px;height:44px;border-radius:50%;object-fit:cover;flex:none;}
.proof-who .n{display:block;font-weight:600;font-size:.95rem;}
.proof-who .r{display:block;font-size:.78rem;color:var(--muted);}
.proof blockquote{margin:18px 0 0;font-style:italic;font-size:.95rem;
  line-height:1.5;color:var(--muted);}
.proof blockquote strong{font-style:italic;font-weight:600;color:var(--ink);}

/* Deux colonnes pour la grille d'avis du bas de page, depuis que deux des
   quatre témoignages sont remontés dans le hero. */
.reviews-2{grid-template-columns:repeat(2,1fr);max-width:900px;margin-inline:auto;}
@media(max-width:760px){.reviews-2{grid-template-columns:1fr;}}

/* Le bandeau de logos de reseaux du hero de dpe-impact (.logos-band,
   .logos-row, .logos-note) a ete retire le 2026-08-10 au profit de deux
   cartes « resultat client » (.hero-proof ci-dessus). Ses regles sont
   supprimees et non commentees : plus aucune page du site ne les utilisait,
   verifie sur tout le HTML, le JS et le PHP. */

/* ---- Carte du dossier (étude de cas Christophe) ----
   Pendant clair de .argu : la carte du hero projette, celle-ci constate. */
.dossier{margin:0;background:#fff;border:1px solid var(--line);border-radius:8px;
  overflow:hidden;box-shadow:0 30px 70px -30px rgba(2,44,34,.28);}
.dossier-head{display:flex;align-items:center;justify-content:space-between;gap:20px;
  padding:22px 26px;border-bottom:1px solid var(--line);background:#fcfdfa;}
.dossier-lbl{font-size:.66rem;text-transform:uppercase;letter-spacing:.1em;color:var(--muted);}
.dossier-jump{display:inline-flex;align-items:center;gap:9px;}
.dossier-jump .dpe-letter{width:34px;height:34px;font-size:1.05rem;border-radius:6px;box-shadow:none;}
.dossier-jump svg{width:15px;height:15px;color:var(--muted);}
.dossier-rows{list-style:none;margin:0;padding:24px 26px;display:flex;flex-direction:column;gap:14px;}
.dossier-rows li{display:flex;align-items:baseline;justify-content:space-between;gap:16px;
  font-size:.92rem;padding-bottom:14px;border-bottom:1px solid var(--line);}
.dossier-rows li:last-child{border-bottom:0;padding-bottom:0;}
.dossier-rows span{color:var(--muted);}
.dossier-rows strong{flex:none;font-family:'JetBrains Mono',ui-monospace,monospace;
  font-weight:500;font-variant-numeric:tabular-nums;}
.dossier-rows .dossier-key strong{color:var(--forest);font-size:1.3rem;}
/* Le témoignage est dans la carte, pas à côté : c'est la personne du dossier
   qui parle, les séparer en ferait deux preuves sans lien. */
.dossier-quote{padding:22px 26px;background:var(--forest);color:rgba(248,249,235,.8);}
.dossier-quote p{margin:0 0 14px;font-size:.9rem;line-height:1.45;}
/* Même principe que .review p strong, transposé sur fond forêt : le texte est
   volontairement à 80 % d'opacité, le fragment mis en avant repasse en crème
   plein. Pas de néon ici, la carte en compte déjà assez avec le chiffre clé. */
.dossier-quote p strong{font-weight:600;color:var(--cream);}
.dossier-who{display:flex;align-items:center;gap:12px;}
.dossier-who img{width:40px;height:40px;border-radius:50%;object-fit:cover;flex:none;}
.dossier-who .n{font-size:.85rem;font-weight:600;color:var(--cream);}
.dossier-who .r{font-size:.74rem;color:rgba(248,249,235,.6);}

/* ---- Lecteur vidéo de l'extrait ----
   Même boîte que .article-embed, mais en 16/9 fluide : l'extrait est une vidéo,
   pas un widget à hauteur fixe. */
.video-frame{max-width:900px;margin:60px auto 0;aspect-ratio:16/9;
  border:1px solid rgba(248,249,235,.14);border-radius:8px;overflow:hidden;
  background:#000;box-shadow:0 30px 70px -30px rgba(0,0,0,.6);}
.video-frame iframe{display:block;width:100%;height:100%;border:0;}

/* ---- Bandeau « qui vous forme » ----
   Version courte de la section auteur de l'accueil. Sur une page de vente le
   parcours n'est pas le sujet : il répond à une seule question (pourquoi lui
   plutôt qu'un organisme certifié) et renvoie à /a-propos pour le reste. */
.trainer{display:flex;align-items:center;gap:28px;max-width:820px;
  margin:0 auto;padding:30px 34px;background:#fff;border:1px solid var(--line);
  border-radius:8px;}
.trainer img{width:96px;height:96px;border-radius:50%;object-fit:cover;flex:none;}
.trainer h3{margin:0 0 8px;font-size:1.15rem;font-weight:600;}
.trainer p{margin:0 0 10px;font-size:.92rem;color:var(--muted);line-height:1.45;}
@media(max-width:640px){
  /* La photo reste centrée, mais le texte s'aligne à gauche : centré sur une
     colonne étroite, le paragraphe finit en drapeau des deux côtés et se lit
     mal (dernières lignes orphelines au milieu). */
  .trainer{flex-direction:column;align-items:stretch;text-align:left;
    gap:20px;padding:28px 24px;}
  .trainer img{align-self:center;}
}

/* ---- Contre-indication (« ce n'est pas pour vous si ») ----
   Encadré sobre, sans rouge ni pictogramme d'alerte : écarter les mauvais
   profils est un service rendu, pas un avertissement. */
.notfor{max-width:820px;margin:56px auto 0;padding:30px 34px;
  border:1px dashed rgba(2,44,34,.22);border-radius:8px;}
.notfor h3{margin:0 0 16px;font-size:1.05rem;font-weight:600;}
.notfor ul{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:10px;}
.notfor li{display:flex;gap:12px;font-size:.94rem;color:var(--muted);}
.notfor li svg{width:18px;height:18px;flex:none;margin-top:3px;color:var(--muted);}

/* ---- Calcul de retour sur investissement, sous la carte de prix ----
   Le seul ancrage de prix de la page : pas de tarif barré, c'est une commission
   réelle qui sert de référence. */
.roi{max-width:560px;margin:26px auto 0;text-align:center;font-size:.92rem;
  color:var(--muted);line-height:1.5;}
.roi strong{color:var(--forest);font-weight:600;}

/* ---- Section « Le problème » : accordéon à gauche, visuel à droite ----
   Structure apportée par Loïs le 2026-08-10 (référence Orasio). Elle remplace
   les trois cartes côte à côte : le lecteur ne lit plus trois paragraphes de
   front, il ouvre celui qui le concerne. La colonne de droite tient le visuel.
   Accordéon en <details> natif, comme la FAQ : la charte interdit le JS custom
   pour ce composant. L'attribut name commun aux trois rend l'ouverture
   exclusive sans une ligne de script. */
.pb-split{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  gap:64px;align-items:start;text-align:left;}
.pb-col .lead{margin-bottom:40px;}

.pb-acc{display:flex;flex-direction:column;gap:14px;}
/* Cartes claires sur la section sombre : c'est la seule façon de garder le
   contraste du texte une fois l'item ouvert. Le fond de section reste forest,
   ce sont les cartes qui portent le clair. Crème et non blanc pur (2026-08-10)
   pour rester sur la dominante de la charte. */
.pb-item{background:var(--cream);color:var(--ink);border-radius:8px;
  box-shadow:0 4px 20px rgba(2,44,34,.06);}
.pb-item summary{display:flex;align-items:center;justify-content:space-between;
  gap:24px;padding:22px 24px;cursor:pointer;list-style:none;}
/* Le marqueur natif (triangle) doit être neutralisé sur les deux moteurs. */
.pb-item summary::-webkit-details-marker{display:none;}
.pb-item summary::marker{content:"";}
.pb-t{font-size:1.12rem;font-weight:500;line-height:1.25;
  transition:color .25s ease;}
.pb-item[open] .pb-t{color:var(--terra-ink);}

/* Le bouton rond. Deux barres en CSS plutôt que deux icônes : la barre
   verticale disparaît à l'ouverture, le + devient un −, sans second fichier
   ni bascule d'affichage. */
/* 28px (2026-08-10, réduit d'un tiers depuis 42px).

   La croix est un SVG à bouts ronds et non deux barres en CSS. Les barres ont
   été essayées puis abandonnées : le bouton hérite d'un y fractionnaire (521,234
   par exemple), conséquence de l'interligne 1,4 du corps de texte plus haut dans
   la colonne, et il n'y a aucun moyen en CSS de recaler un élément sur la grille
   de pixels. Résultat, la barre horizontale se peignait sur quatre lignes
   (valeurs mesurées 112, 255, 255, 113) pendant que la verticale, elle, tombait
   sur un x entier et restait nette. C'est cette asymétrie, une barre floue
   contre une barre franche, qui donnait au « + » son air de travers.
   Un tracé SVG à `stroke-linecap:round` est fait pour vivre à n'importe quel
   sous-pixel : l'adoucissement des extrémités se lit comme voulu, pas comme un
   défaut. C'est déjà l'idiome de toutes les autres icônes du site. */
.pb-tog{flex:none;display:grid;place-items:center;
  width:28px;height:28px;border-radius:999px;
  background:var(--forest);color:#fff;transition:background .25s ease;}
.pb-tog svg{width:15px;height:15px;}
/* Seule la barre verticale disparaît : le + devient un −, sans second fichier
   ni bascule d'affichage. */
.pb-tog-v{transition:opacity .25s ease;}
.pb-item[open] .pb-tog-v{opacity:0;}
/* Terracotta sur l'item ouvert : la couleur ne décore pas, elle dit « c'est
   ce problème-là que vous êtes en train de lire ». Elle réapparaît à chaque
   ouverture, donc elle vit dans la section au lieu d'y être posée une fois. */
.pb-item[open] .pb-tog{background:var(--terra);}
.pb-item summary:hover .pb-tog{background:var(--terra);}

.pb-body{padding:0 24px 24px;}
.pb-body p{margin:0;color:var(--muted);font-size:.98rem;}

/* Colonne de droite. min-height plutôt qu'une hauteur calée sur l'accordéon :
   la colonne de gauche change de hauteur à chaque ouverture, un alignement
   strict ferait sauter le visuel à chaque clic. */
.pb-visual{align-self:stretch;min-height:520px;display:flex;}
.pb-ph{flex:1;display:flex;flex-direction:column;align-items:center;
  justify-content:center;gap:14px;border-radius:8px;
  background:rgba(255,255,255,.04);border:1px dashed rgba(255,255,255,.22);
  color:rgba(248,249,235,.5);font-size:.85rem;letter-spacing:.04em;}
.pb-ph svg{width:38px;height:38px;}

/* ---- Extrait du DPE + pastilles sur les montants ----
   Le document est posé sur la section sombre comme une pièce de dossier, pas
   comme une illustration : fond blanc conservé, coins à peine adoucis, ombre
   portée franche. Il occupe toute la colonne, ce que le cadrage sur les deux
   tableaux permet : la page entière devait être bridée à 470px pour ne pas
   dépasser la colonne de texte, et les montants y tombaient à cinq pixels. */
.pb-doc{flex:1;margin:0;align-self:start;}
.pb-doc-frame{position:relative;}
.pb-doc-page{display:block;width:100%;height:auto;border-radius:4px;
  box-shadow:0 18px 44px rgba(2,44,34,.42);}

/* La pastille entoure le montant là où il est imprimé. Coordonnées en
   pourcentages (--x/--y/--w/--h, imprimées par build_dpe_reco.py depuis les
   coordonnées du texte dans le PDF) : elles suivent le document à toutes les
   largeurs, là où des pixels se décaleraient dès le premier point de rupture.
   Elle est plus grande que le texte de 14px sur chaque axe, et décalée d'une
   demi-marge : sans quoi elle serre le chiffre. Le décalage horizontal est
   volontairement plus court que la moitié, pour ne pas mordre sur le
   deux-points de « Montant estimé : » qui précède le nombre.
   Néon plutôt que terracotta : c'est la couleur de surlignage du site sur fond
   sombre, et elle ne peut pas être confondue avec l'orange du document. */
.pb-mark{position:absolute;left:var(--x);top:var(--y);
  width:calc(var(--w) + 14px);height:calc(var(--h) + 14px);
  margin:-7px 0 0 -5px;border-radius:999px;
  border:2px solid var(--neon);background:rgba(0,255,171,.14);
  box-shadow:0 0 0 4px rgba(0,255,171,.12);}


/* Variante sur fond clair (page Simulateur, section greige). Le crème des
   cartes est trop proche du greige pour se détacher : elles passent en blanc,
   comme les .card-white du reste de cette page. Rien d'autre ne change. */
.pb-light .pb-item{background:#fff;}

/* Visuel réel : photo pleine, masque sombre, témoignage par-dessus.
   Le masque n'est pas un effet, il porte le texte : dégradé et non aplat, pour
   que le haut de la photo reste lisible en tant que photo. L'image est en
   position absolue et c'est la citation qui donne sa hauteur au bloc, sinon
   un témoignage plus long que la photo déborderait. */
.pb-photo{position:relative;flex:1;margin:0;min-height:520px;
  border-radius:8px;overflow:hidden;background:var(--forest);}
/* Sélecteur d'enfant direct et non « .pb-photo img » : l'avatar de la citation
   est lui aussi une image dans ce bloc, il ne doit pas hériter du plein cadre. */
.pb-photo > img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  object-position:center 40%;}
/* Le voile ne sert qu'à porter la citation : il est dense en pied, où le texte
   commence, et tombe à zéro en haut du cadre, où la photo doit rester une
   photo. Un voile uniforme, même léger, verdissait toute l'image. */
.pb-photo::after{content:"";position:absolute;inset:0;
  background:linear-gradient(to top,rgba(2,44,34,.8) 0%,rgba(2,44,34,.68) 38%,rgba(2,44,34,.26) 62%,rgba(2,44,34,.05) 84%,rgba(2,44,34,0) 100%);}
.pb-quote{position:relative;z-index:1;height:100%;
  display:flex;flex-direction:column;justify-content:flex-end;
  padding:38px 36px;color:#fff;text-align:left;}
.pb-quote blockquote{margin:0;}
.pb-quote p{margin:0;font-size:1.06rem;line-height:1.5;color:rgba(248,249,235,.88);}
/* Néon réservé à la phrase qui EST le problème que le produit résout : c'est
   l'usage texte-sur-fond-sombre déjà en place ailleurs, jamais sur clair. */
.pb-quote strong{font-weight:600;color:var(--neon);}
.pb-quote-who{display:flex;align-items:center;gap:14px;margin-top:26px;
  padding-top:22px;border-top:1px solid rgba(255,255,255,.18);}
.pb-quote-av{width:46px;height:46px;flex:none;border-radius:999px;object-fit:cover;
  border:2px solid rgba(255,255,255,.3);}
.pb-quote-id{font-size:.85rem;line-height:1.35;}
.pb-quote-id b{display:block;font-weight:600;}
.pb-quote-id span{color:rgba(248,249,235,.64);}

@media(max-width:960px){
  .pb-split{grid-template-columns:1fr;gap:44px;}
  .pb-photo{min-height:400px;}
  /* Le visuel passe en premier une fois empilé : sur mobile, ouvrir un item
     repousserait sinon l'image toujours plus bas, et personne ne la verrait. */
  .pb-visual{order:-1;min-height:300px;}
  /* Exception de la variante claire : ici le visuel porte un témoignage, pas
     une illustration. Remonté avant le titre, la section s'ouvrirait sur une
     citation sans avoir dit de quoi elle parle. Il reste donc en pied. */
  .pb-light .pb-visual{order:0;}
}
@media(max-width:600px){
  /* Pastilles resserrées : sur un document de 350px de large, la marge de
     20 x 14px les faisait mordre sur la colonne voisine. */
  .pb-mark{width:calc(var(--w) + 10px);height:calc(var(--h) + 8px);
    margin:-4px 0 0 -5px;border-width:1.5px;}
  .pb-item summary{padding:18px 18px;gap:16px;}
  .pb-t{font-size:1.02rem;}
  .pb-tog{width:24px;height:24px;}
  .pb-tog svg{width:13px;height:13px;}
  .pb-body{padding:0 18px 20px;}
  .pb-photo{min-height:340px;}
  .pb-quote{padding:28px 22px;}
  .pb-quote p{font-size:.98rem;}
}

/* ---- Section « Le programme » : intro collée, modules qui défilent ----
   Maquette apportée par Loïs le 2026-08-10. Le bento .prog-grid montrait les
   quatre modules d'un coup, ce qui obligeait à écrire des textes de longueurs
   très inégales pour tenir dans des spans de 2, 3 et 4 colonnes. Ici chaque
   module a la même place et le même gabarit.
   Le sticky reprend le réglage éprouvé de .flow-rail : align-self:start (sans
   quoi la colonne s'étire sur toute la hauteur de la grille et le collage n'a
   plus rien à faire) et un décalage haut calé sur le header fixe. */
/* Hauteur dont le mockup mord sur la section suivante. Une seule valeur pilote
   les trois règles concernées (marge du mockup, padding de la section
   suivante) : la régler ici suffit. Critère de réglage : la ligne de séparation
   des deux fonds doit passer sous le socle du moniteur et couper le portable et
   la tablette à peu près à mi-hauteur, pour que le mockup appartienne aux deux
   sections. Plus haut, elle tranche l'écran du moniteur comme une ligne
   d'horizon ; plus bas, le mockup se retrouve entièrement dans la première
   section et le chevauchement ne se voit plus.
   La valeur tient compte du vide que l'image porte sous les appareils : elle
   est mesurée depuis le bas du fichier, pas depuis le bas du portable. */
:root{--prog-overlap:220px;}

.prog-split{display:grid;grid-template-columns:minmax(0,.86fr) minmax(0,1fr);
  gap:80px;align-items:start;margin-top:90px;text-align:left;}
.prog-intro{align-self:start;position:sticky;top:calc(var(--chrome-h) + 64px);}
.prog-intro .lead{margin-bottom:26px;}
/* La checklist par défaut est sur deux colonnes : dans une colonne déjà
   étroite, chaque item tombait sur trois lignes. */
.checklist-stack{grid-template-columns:1fr;gap:14px;margin:0 0 30px;}

.prog-cards{display:flex;flex-direction:column;gap:20px;}
.prog-card{padding:32px 34px;border-radius:8px;}
.prog-card-head{display:flex;align-items:center;justify-content:space-between;
  gap:20px;margin-bottom:16px;}
.prog-card-head svg{width:20px;height:20px;flex:none;opacity:.45;}
.prog-num{font-size:.7rem;text-transform:uppercase;letter-spacing:.13em;
  color:var(--pine);}
.prog-card h3{margin:0 0 10px;font-size:1.3rem;font-weight:600;}
.prog-card p{margin:0;color:var(--muted);}
/* Les quatre modules sont blancs. Le quatrième était en card-forest, ce qui le
   faisait passer pour un module à part alors que les quatre ont le même
   statut ; la variante sombre et ses surcharges de couleur ont été retirées
   le 2026-08-10 avec lui. */

/* Mockup de la plateforme, récupéré de l'ancienne page dpeimpact.html. Il est
   détouré sur transparent : pas de cadre ni d'ombre de boîte, seule une ombre
   portée qui suit la silhouette des appareils, et la respiration de breathe,
   comme .price-mockup.

   Il est posé À CHEVAL sur la frontière avec la section suivante (2026-08-10),
   donc sur les deux fonds : motif « mockup produit flottant » de la charte, et
   même mécanique que .risk-visual sur l'accueil. Ce chevauchement coud « Le
   programme » aux « outils qui vont avec », qui répondent à la même question
   du lecteur et viennent d'être remis côte à côte pour cette raison.

   90px de marge haute : écart standard de la charte entre un bloc de contenu
   et ce qui le suit. */
/* height:auto obligatoire. La règle globale `img{max-width:100%}` n'en pose
   pas, donc quand la largeur est contrainte (ici par le max-width du figure),
   c'est l'attribut height="516" du HTML qui reste la hauteur utilisée : le
   mockup sortait en 843x518 au lieu de 843x428, étiré de 21% en desktop, et en
   348x518 sur mobile. Le piège vaut pour toute image du site dont la largeur
   est bridée par son conteneur sans hauteur explicite. */
.prog-mockup img{height:auto;}
.prog-mockup{margin:90px auto calc(-1 * var(--prog-overlap));max-width:1100px;
  filter:drop-shadow(0 40px 60px rgba(2,44,34,.28));
  animation:breathe 5s ease-in-out infinite;
  /* position:relative indispensable : .section n'a aucune position, sans elle
     le z-index ne s'applique pas et le fond de la section suivante, postérieure
     dans le DOM, recouvre le mockup. z-index 3 et non 2 pour rester au-dessus
     d'une eventuelle section suivante en .round-top (elle-même en z-index 2),
     au cas où l'ordre des sections rebougerait.
     Le z-index est porté par l'élément qui porte .reveal, et c'est voulu : le
     transform d'entrée de .reveal crée un contexte d'empilement, un z-index
     posé sur un enfant y resterait enfermé pendant toute l'animation (piège
     déjà documenté sur .risk-tabs). */
  position:relative;z-index:3;}

/* Le padding bas de la section disparaît, sinon le mockup déborderait depuis
   128px plus haut et la frontière tomberait bien en dessous de lui. */
#programme{padding-bottom:0;}
/* La section suivante récupère ce que le mockup lui a mangé, sinon son eyebrow
   démarre sous l'image. Sélecteur `+ section` et non #inclus : il survit à un
   renommage d'id et lie la compensation à la section qui déborde. */
#programme + section{padding-top:calc(var(--pad) + var(--prog-overlap));}

@media(max-width:1000px){
  /* Sous cette largeur les deux colonnes deviennent trop étroites pour que le
     collage ait un intérêt : l'intro repasse au-dessus des modules, en flux
     normal, et le sticky est désactivé (sinon il resterait collé sur toute la
     longueur de la liste et mangerait un écran entier en mobile). */
  .prog-split{grid-template-columns:1fr;gap:56px;}
  .prog-intro{position:static;}
  .checklist-stack{margin-bottom:24px;}
}
@media(max-width:600px){
  .prog-card{padding:26px 24px;}
  /* À 390px le mockup ne fait plus que ~176px de haut : 140px de débordement
     en avaleraient 80%. Une seule variable à reprendre, les trois règles
     suivent. */
  :root{--prog-overlap:70px;}
  .prog-mockup{max-width:100%;}
}
@media(prefers-reduced-motion:reduce){.prog-mockup{animation:none;}}

/* =========================================================================
   ESSAI — accents chauds sur /dpe-impact (2026-08-10, revu le même jour)
   =========================================================================
   Test des deux couleurs complémentaires proposées en audit de palette. Bloc
   volontairement isolé en fin de feuille, avec une spécificité au moins égale
   aux règles d'origine : le supprimer suffit à revenir à l'état antérieur,
   aucune règle plus haut n'a été modifiée.

   Principe testé : la page raconte un affrontement entre deux chiffres, celui
   qui fait peur (le montant du DPE, le mandat perdu) et celui qui gagne (le
   reste à charge, la commission préservée). La palette verte ne sait pas
   distinguer les deux, elle les affiche tous en encre forest. Terracotta pour
   le premier, ambre pour le second.

   PREMIÈRE VERSION ABANDONNÉE : 7 touches en texte seul, aucun aplat, sur une
   règle « les accents chauds ne servent jamais de fond » qui était fausse.
   Elle confondait rareté et petitesse. Elle interdisait de fait les versions
   vives des deux teintes, qui n'ont d'usage possible qu'en aplat, et ne
   laissait que les versions encre : le résultat fade était garanti d'avance.
   La charte autorise déjà l'inverse (« système de cartes multi-tons » :
   n'importe quelle couleur peut jouer fond OU carte), et le néon en fait déjà
   la démonstration à chaque fin de page.

   RÈGLES QUI EN SORTENT, à reprendre si les couleurs passent dans la charte :
   - une surface chaude par couleur et par page, maximum. C'est le placement
     qui assure la parcimonie, pas la taille de la tache
   - les versions vives ne servent qu'en aplat, les versions encre qu'en texte
     sur fond clair. Jamais l'inverse
   - l'ambre marque un montant, jamais une lettre de DPE : la tuile « E → D »
     passée en ambre au premier essai se lisait comme un code d'étiquette, à
     30px du badge E orange. La couleur chaude reproduirait alors exactement la
     confusion que le vert entretient déjà avec l'étiquette
   - jamais sur un bouton : les CTA restent forest / pine / néon

   DEUXIÈME VERSION ABANDONNÉE : un seul aplat par couleur. Une couleur qui
   n'apparaît qu'une fois ne se lit pas comme une décision, elle se lit comme
   une erreur de code hexa. Il faut trois occurrences à échelle réelle pour
   qu'une teinte devienne un système reconnaissable.

   TROISIÈME VERSION ABANDONNÉE côté terracotta : les deux couleurs avaient été
   élargies en même temps à trois surfaces chacune, dont la section « Le
   problème » entièrement en fond oxblood. Trop : cette section arrive en
   position 2, elle faisait basculer la page de « marque verte à accents
   chauds » à « page marron ». Retirés le 2026-08-10 : le fond de section
   oxblood, le bloc « passez votre chemin » en aplat, et l'objection du hero en
   aplat plein (revenue à son filet).

   Dosage retenu, asymétrique et assumé :

     TERRACOTTA = ce qu'il en coûte de ne rien faire. Parcimonieux, une seule
     surface, deux rappels :
       1. le bouton rond de l'item ouvert dans l'accordéon « Le problème »
          (voir la section dédiée plus haut). Il a remplacé le 2026-08-10 la
          carte « le mandat part chez le concurrent », emportée par le passage
          des trois cartes à l'accordéon. Le rôle est le même en mieux : la
          couleur ne se pose plus une fois pour toutes sur un des trois
          problèmes, elle suit celui que le lecteur ouvre
       2. le filet de l'objection de l'acquéreur dans la carte du hero
       3. le montant brut du DPE, en encre

     AMBRE = le chiffre qui compte. Trois fois la même bande :
       1. la ligne de chute de la carte du hero (reste à charge)
       2. la ligne de chute de la carte dossier (commission préservée)
       3. la bande de ROI sous le prix
       C'est l'identité de composant qui fait système, pas la seule présence de
       la couleur. L'ambre supporte cette répétition parce qu'il ne dit qu'une
       chose et toujours au même endroit, la dernière ligne d'un bloc chiffré.

   L'asymétrie est volontaire : l'ambre accompagne un raisonnement qui revient
   à chaque section chiffrée, le terracotta ne nomme qu'un moment, celui du
   risque. Lui donner la même fréquence reviendrait à installer la peur sur
   toute la page. */

/* --- Terracotta : ce qu'il en coûte de ne rien faire --------------------- */

/* La surface terracotta de la section « Le problème » est écrite plus haut,
   avec le reste de l'accordéon (.pb-item[open] .pb-tog) : elle est
   indissociable de son composant. La variante .card-terra qui existait ici
   pour la troisième carte du trio a été supprimée avec le trio lui-même. */

/* L'objection de l'acquéreur, dans la carte du hero. Un filet et une teinte de
   fond très diluée, pas un aplat : testé en terracotta plein, ce bloc devenait
   la chose la plus voyante de la page dès le premier écran, et il annonçait un
   registre chaud que la suite ne tient volontairement plus. Ici il ne fait que
   marquer la citation comme le moment où la vente se perd. */
.argu-obj{border-left-color:var(--terra);background:rgba(176,78,51,.06);}

/* Le montant brut du diagnostic, celui que la formation apprend à corriger.
   Version encre : sur carte blanche, le terracotta vif tombe à 3,4:1. */
.argu-lines .argu-cost strong{color:var(--terra-ink);}

/* --- Ambre : le chiffre qui compte --------------------------------------- */

/* La bande, déclinée trois fois. Forest sur ambre = 6,9:1, soit mieux que le
   bandeau néon de fin de page : cette couleur est faite pour être un fond, et
   n'a aucun usage possible en texte sur crème. */

/* 1 et 2. Dernière ligne des deux cartes de données (hero et dossier). Elle
   déborde jusqu'aux bords de la carte par des marges négatives calées sur le
   padding du conteneur : 26px sur les côtés dans les deux cas, 26px en bas
   pour .argu-ans et 24px pour .dossier-rows. */
/* Sélecteurs écrits `li.classe` et non `.conteneur .classe` : les deux listes
   ont une règle `li:last-child{padding-bottom:0}` de spécificité (0,2,1), et
   la bande est justement le dernier enfant. En (0,2,0) le padding bas de la
   bande était écrasé et elle sortait dissymétrique. */
.argu-lines li.argu-key,
.dossier-rows li.dossier-key{background:var(--amber);color:var(--forest);
  border-bottom:0;padding:16px 26px;margin-left:-26px;margin-right:-26px;}
/* Pas de rayon bas : la bande n'est jamais au bord bas de la carte, un bandeau
   forest (.argu-foot) ou la citation client vient juste en dessous. Des coins
   arrondis y ouvriraient deux encoches blanches. */
.argu-lines li.argu-key{margin-bottom:-26px;}
.dossier-rows li.dossier-key{margin-bottom:-24px;}
.argu-lines li.argu-key span,
.dossier-rows li.dossier-key span{color:rgba(2,44,34,.8);}
.argu-lines li.argu-key strong,
.dossier-rows li.dossier-key strong{color:var(--forest);}

/* 3. Sous la carte de prix. C'était une phrase grise que personne ne lisait,
   alors qu'elle porte le seul ancrage de prix de la page (pas de tarif barré,
   une commission réelle). 620px et pas davantage : c'est la largeur de
   .price-wrap. Testée à 760px, la bande dépassait des deux côtés la carte
   qu'elle commente et se lisait comme un bloc indépendant. */
.roi{max-width:620px;margin-top:34px;padding:28px 34px;border-radius:8px;
  background:var(--amber);color:var(--forest);font-size:1rem;}
.roi strong{color:var(--forest);}


/* =========================================================================
   /dpe-impact — carte « Le simulateur Rénovation Optimale » (section Inclus)
   La seule carte de la grille qui porte un visuel. C'est voulu : les trois
   autres promettent du contenu (un GPT, une masterclass, des mises à jour),
   celle-ci promet un LOGICIEL, et un logiciel qu'on ne voit pas ne rassure
   personne. Le visuel n'est pas une décoration, c'est la preuve.
   ========================================================================= */
/* Les deux cartes de la rangée gardent la hauteur de la grille (comportement
   par défaut) : c'est la fenêtre de conversation qui absorbe la différence,
   voir .outil-chat plus bas. Une tentative précédente les laissait s'arrêter
   chacune à son contenu (align-items:start) : deux cartes voisines de hauteurs
   différentes se lisaient comme un défaut d'alignement. */
.card-outil{display:flex;flex-direction:column;}

/* Cadre navigateur autour de la capture. Barre sombre + trois pastilles : le
   code visuel « application » le plus court qui soit, il évite d'avoir à
   écrire « c'est une vraie interface ». Les pastilles sont décoratives et
   n'imitent aucun OS en particulier (couleurs de la charte, pas celles de
   macOS) : on suggère une fenêtre, on ne contrefait pas un système. */
.outil-shot{margin:18px 0 0;border-radius:8px;overflow:hidden;
  border:1px solid var(--line);background:var(--cream);}
.outil-bar{display:flex;align-items:center;gap:5px;
  padding:7px 9px;background:var(--forest);}
.outil-bar i{width:7px;height:7px;border-radius:999px;background:rgba(248,249,235,.28);}
.outil-bar i:first-child{background:var(--neon);}

/* Le cadrage est fait ICI et pas dans un fichier image découpé : l'original
   (assets/photos/app/app-hero-logement.webp) est régénéré par capture_app.py
   à chaque évolution de l'interface, et ce visuel doit suivre sans qu'on
   pense à recouper quoi que ce soit.
   Ratio 2:1 + object-position en haut : on garde la barre latérale de marque,
   le fil d'Ariane et le bloc étiquette F→C, et la coupe tombe au milieu de la
   première rangée de tuiles de travaux. Coupe assumée : une fenêtre qui montre
   le haut d'une page et laisse deviner la suite se lit comme une vraie
   fenêtre. Le cadrage exact au ras du bloc étiquette (~3,2:1) donnait une
   fente de 100 px de haut, plus une capture d'application. */
.outil-shot img{display:block;width:100%;height:auto;aspect-ratio:2/1;
  object-fit:cover;object-position:top center;}

/* Titre facultatif dans la barre de fenêtre (carte du GPT). Il remplace le
   fil d'Ariane que porte la capture du simulateur : sans lui, une fenêtre de
   conversation nue ne dit pas de quel outil elle vient. */
.outil-bar b{margin-left:6px;font-size:.68rem;font-weight:600;
  letter-spacing:.08em;text-transform:uppercase;color:rgba(248,249,235,.66);}

/* Conversation maquettée (carte du GPT). Fond blanc et non crème : le crème
   du cadre sert de gouttière autour des bulles, sinon la bulle de l'assistant,
   claire elle aussi, se dissoudrait dans le fond.
   La fenêtre prend toute la hauteur restante de la carte (flex:1) : c'est elle
   qui rattrape la différence de hauteur avec la carte du simulateur, qui porte
   en plus une capture et une ligne d'offre. Le vide se retrouve donc SOUS le
   dernier message, à l'endroit exact où une vraie conversation en a. */
.outil-chat{background:#fff;flex:1;display:flex;flex-direction:column;}
.chat{flex:1;display:flex;flex-direction:column;gap:10px;padding:16px 14px;}
/* Les deux bulles sont bornées à 88 % et alignées de part et d'autre : c'est
   ce décalage, plus que les couleurs, qui fait lire le bloc comme un dialogue.
   Rayon cassé du côté de l'interlocuteur, comme partout ailleurs. */
.chat p{margin:0;max-width:88%;padding:10px 13px;border-radius:12px;
  font-size:.84rem;line-height:1.45;}
/* Sélecteurs `.chat .chat-*` et non `.chat-*` seuls : `.card-white p` est en
   (0,1,1) et écrasait la couleur des bulles, ce qui peignait le texte de la
   réponse en gris foncé sur le fond forest, donc invisible.
   La question vient de l'utilisateur : à droite, en greige, sans emphase.
   Elle est courte exprès, c'est la réponse qu'on vend. */
.chat .chat-q{align-self:flex-end;border-bottom-right-radius:4px;
  background:var(--greige);color:var(--ink);}
/* La réponse est le produit : fond forest, la seule surface sombre de la
   section, elle capte l'œil avant le reste de la carte. */
.chat .chat-a{align-self:flex-start;border-bottom-left-radius:4px;
  background:var(--forest);color:rgba(248,249,235,.9);}
/* Néon sur la conclusion chiffrée uniquement, et c'est bien un texte clair sur
   fond sombre : le seul emploi autorisé de cette couleur en texte. */
.chat-a strong{color:var(--neon);font-weight:600;}
/* Barre de saisie factice : elle referme la fenêtre en bas, comme la barre
   sombre la referme en haut. Contour et gris léger, jamais l'aspect d'un champ
   actif : on suggère qu'on peut continuer à demander, on n'invite pas au clic
   sur une page de vente où le seul clic utile est le bouton d'achat. */
.chat-ask{display:flex;align-items:center;gap:10px;margin:0 14px 14px;
  padding:9px 12px;border:1px solid var(--line);border-radius:999px;
  font-size:.8rem;color:rgba(2,44,34,.42);}
.chat-ask span{flex:1;}
.chat-ask svg{width:15px;height:15px;flex:none;color:var(--pine);}

/* Poussée en pied de carte par le margin-top auto : quel que soit le nombre
   de lignes du paragraphe au-dessus, l'offre reste la dernière chose lue.
   Ambre encre et non néon : c'est un texte sur fond blanc (cf. :root). */
.card-outil .outil-offre{margin-top:auto;padding-top:16px;
  font-size:.9rem;color:var(--muted);}
.card-outil .outil-offre strong{color:var(--amber-ink);font-weight:700;}

/* =============================================================================
   ÉCART TITRE → CONTENU EN MOBILE (2026-08-14)
   Les composants qui suivent un titre de section portent des marges hautes
   dessinées pour le desktop : 66 à 94px selon le bloc. Sur un écran de 390px
   ces valeurs isolent le H2 de ce qu'il annonce, on lisait un titre puis un
   trou, et le bloc suivant démarrait presque hors de l'écran.
   La référence est l'écart de la section « Qui suis-je » de la page à propos,
   soit les 20px de margin-bottom du .h2 lui-même, sans rien qui s'y ajoute.
   Cette règle est délibérément générique et vit en FIN de feuille : elle doit
   passer après les composants (.faq-list, .reviews-grid, .timeline…), qui ont
   la même spécificité qu'elle. La déplacer plus haut la rend sans effet.
   Les trois sélecteurs couvrent les trois façons d'écrire un en-tête de section
   sur le site : titre isolé dans un .narrow ou un .hero-head suivi du bloc de
   contenu, ou titre frère direct de ce bloc.
   Ne touche que le haut du bloc : les composants centrés par margin:x auto 0
   gardent leur centrage horizontal. */
@media(max-width:760px){
  :root{--gap-titre:20px;--gap-titre-bloc:36px;}
  .narrow + *,
  .hero-head + *,
  .h2 + *{margin-top:var(--gap-titre);}
  /* Deux valeurs et non une, parce que 20px identiques ne se VOIENT pas
     identiques (constaté le 2026-08-14 sur la FAQ, qui paraissait plus serrée
     que le texte de « Qui suis-je » alors que les deux mesuraient 20px).
     Un paragraphe commence par 3 à 4px de blanc, le demi-interligne au-dessus de
     ses capitales : le vide lu vaut donc 24px. Une carte, elle, commence par son
     bord, à 20px pile. Les blocs à bord, à fond ou à image reçoivent donc plus.
     Valeur relevée de 26 à 36px le 2026-08-14 : à 26px la bande d'images de la
     page à propos et la timeline « Une expertise construite » collaient encore
     au texte qui les précède. Un bord franc ou une photo pèsent visuellement
     plus qu'une carte crème, le blanc doit être franc pour se voir.
     Sélecteur en :is() pour que la liste vaille après les trois formes
     d'en-tête du site sans les recopier, et pour passer devant une marge posée
     dans le <style> d'une page (spécificité 0,2,0 contre 0,1,0).
     Un bloc ajouté ici plus tard n'a besoin de cette ligne que s'il a un bord,
     un fond ou une image qui démarre au ras du conteneur. */
  :is(.narrow, .hero-head, .h2) + :is(
    .faq-list, .reviews-grid, .cards-2, .cards-3, .id-card-wrap, .versus,
    .flow, .stack, .offre-grid, .art-grid, .risk-tabs, .offer-acc,
    .hero-strip, .hero-visual-solo, .timeline, .prog-grid, .guide-grid,
    .deliv-grid, .video-frame, .article-embed, .sim-proof, .sim-acc,
    .sim-verbatim){margin-top:var(--gap-titre-bloc);}
  /* La timeline demande plus que les autres : elle démarre par une pastille de
     puce, pas par un bord ni un fond, donc rien ne vient marquer le début du
     bloc et les 36px communs se lisaient comme la moitié. */
  :is(.narrow, .hero-head, .h2) + .timeline{margin-top:56px;}
}

/* -----------------------------------------------------------------------------
   ALIGNEMENT DES EN-TÊTES DE SECTION EN MOBILE (2026-08-14)
   Les en-têtes de section sont centrés, ce qui tient en desktop où un titre
   centré coiffe une grille large et symétrique. Sur 390px le contenu, lui, est
   toujours au fer à gauche : le titre et sa pastille flottaient alors au-dessus
   d'un texte qui commençait ailleurs, et chaque section imposait deux points de
   départ au regard.
   La règle ne vise que les .narrow d'une .section : les en-têtes de hero
   (.about-hero, .blog-hero) et la page 404 ne sont pas des sections et gardent
   leur composition. Pour garder un en-tête centré dans une section, lui ajouter
   .narrow-center. Aucune section n'en a besoin aujourd'hui : partout où le
   contenu qui suit est du texte, il est déjà au fer à gauche.
   margin-inline:0 sur le titre en plus de l'alignement du texte : plusieurs
   titres portent un max-width en ch avec des marges auto, qui laisseraient la
   BOÎTE du titre centrée même avec son texte à gauche. Le .eyebrow n'a pas
   besoin d'être traité, il est en inline-flex et suit donc l'alignement du
   texte, sauf s'il porte .eyebrow-center, qui se centre par marges auto. */
@media(max-width:760px){
  /* L'en-tête d'une FAQ est exclu et reste centré (demandé le 2026-08-14) : le
     bloc qu'il annonce est une pile de cartes pleine largeur, pas du texte
     courant dont il faudrait suivre le fer à gauche.
     Repéré par :has plutôt que par une classe posée dans chaque page, toutes les
     FAQ du site suivant le même gabarit : un .narrow puis un .faq-list.
     L'exclusion vaut pour les trois déclarations et pas seulement pour
     l'alignement du texte : .eyebrow-center se centre par marges auto, le
     laisser à margin-left:0 le renverrait à gauche sous un titre centré.
     Idem pour la grille d'articles en fin de page de blog. */
  /* Même exclusion pour « Explorez d'autres articles » (.art-grid) : une grille
     de cartes pleine largeur, pas du texte courant. */
  .section .narrow:not(.narrow-center):not(:has(+ .faq-list)):not(:has(+ .art-grid)){text-align:left;}
  .section .narrow:not(.narrow-center):not(:has(+ .faq-list)):not(:has(+ .art-grid)) .h1,
  .section .narrow:not(.narrow-center):not(:has(+ .faq-list)):not(:has(+ .art-grid)) .h2{margin-inline:0;}
  .section .narrow:not(.narrow-center):not(:has(+ .faq-list)):not(:has(+ .art-grid)) .eyebrow-center{margin-left:0;margin-right:0;}

  /* Même traitement pour un .hero-head qui le demande explicitement, via
     .hero-head-left. Pas de règle globale sur .hero-head : la classe sert aussi
     à des en-têtes annonçant une bande d'images ou une pile de cartes, qui
     restent centrés. Comme pour .narrow, il faut neutraliser les marges auto du
     titre et du .lead, sinon leur BOÎTE reste centrée sous un texte à gauche. */
  .hero-head-left{text-align:left;}
  .hero-head-left .h1,
  .hero-head-left .h2,
  .hero-head-left .lead{margin-inline:0;}
  .hero-head-left .eyebrow-center{margin-left:0;margin-right:0;}
}


/* =========================================================================
   /dpe-impact — section de l'offre (2026-08-14)
   La carte de prix seule ne vendait rien : elle listait ce qu'on reçoit. Cette
   section lui rend une tête (promesse + coût de l'inaction), lui met dedans ce
   que le lecteur saura faire, et sort l'arsenal en dessous.
   ========================================================================= */

/* Le .narrow d'en-tête a besoin d'air avant les cartes. */
.offer-section .narrow + .offer-acc{margin-top:72px;}

/* ---- Les trois cartes d'arguments ----
   Même dispositif que .sim-acc sur /simulation-dpe (un ton de la charte par
   carte, une maquette sous chaque texte), réécrit ici plutôt que partagé :
   .sim-acc vit dans le <style> de sa page. Si une troisième page en a besoin,
   c'est le moment de promouvoir un composant commun plutôt que d'en écrire un
   troisième. */
.offer-acc{display:grid;grid-template-columns:repeat(3,1fr);gap:22px;}
.offer-acc-card{display:flex;flex-direction:column;min-height:520px;
  padding:34px 30px;border-radius:8px;
  transition:transform .35s cubic-bezier(.25,.8,.25,1),box-shadow .35s;}
.offer-acc-card:hover{transform:translateY(-6px);box-shadow:0 24px 50px -22px rgba(2,44,34,.24);}
.offer-acc-head h3{font-size:1.12rem;margin:0 0 10px;font-weight:600;}
.offer-acc-head p{margin:0;font-size:.95rem;}
/* margin-block auto : la maquette se centre dans la hauteur libre plutôt que
   de se coller au bas de la carte, quel que soit le nombre de lignes du
   paragraphe au-dessus. */
.offer-acc-viz{margin-block:auto;padding-top:34px;}

/* Crème pour la première : la section est greige, un greige sur greige ne se
   détacherait pas (c'est ce que fait /simulation-dpe, dont la section est
   crème). Le blanc pur, essayé d'abord, tirait trop froid à côté du forest et
   du néon, et surtout il est déjà la couleur des maquettes posées dans les
   deux autres cartes. */
.offer-acc-cream{background:var(--cream);color:var(--ink);border:1px solid var(--line);}
.offer-acc-cream p{color:var(--muted);}
.offer-acc-forest{background:var(--forest);color:var(--cream);}
.offer-acc-forest p{color:rgba(248,249,235,.72);}
.offer-acc-neon{background:var(--neon);color:var(--forest);}
.offer-acc-neon p{color:rgba(2,44,34,.72);}

/* ---- Carte 1 : les deux répliques en estimation ----
   Le vendeur entend les deux dans la même semaine. Les poser l'une sous
   l'autre est ce qui rend la différence lisible sans l'expliquer. */
.face{display:flex;flex-direction:column;gap:10px;}
.face-row{padding:13px 15px;border-radius:8px;
  background:rgba(2,44,34,.05);border:1px solid transparent;}
.face-who{display:block;font-size:.62rem;font-weight:700;letter-spacing:.12em;
  text-transform:uppercase;color:var(--muted);margin-bottom:5px;}
.face-row p{margin:0;font-size:.84rem;line-height:1.4;color:var(--muted);}
/* La réplique qui fait signer : blanc bordé de vert et texte à pleine encre.
   Pas d'aplat néon, ce serait la seule surface néon d'une carte claire.
   Le fond de la carte étant crème, c'est le blanc qui ressort ici, l'inverse
   de la version précédente sur carte blanche. */
.face-row.is-you{background:#fff;border-color:rgba(19,112,48,.3);}
.face-row.is-you .face-who{color:var(--pine);}
.face-row.is-you p{color:var(--ink);font-weight:500;}
.face-foot{margin:4px 0 0;font-size:.72rem;font-weight:600;color:var(--pine);}

/* ---- Carte 2 : les objections couvertes ----
   Sur fond forest : contours et fonds translucides, jamais une couleur pleine
   qui trouerait la carte. */
.objs{background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.14);
  border-radius:8px;padding:18px;}
.objs-row{display:flex;align-items:flex-start;gap:10px;font-size:.84rem;
  line-height:1.4;color:rgba(248,249,235,.86);}
.objs-row + .objs-row{margin-top:13px;}
.objs-row svg{width:14px;height:14px;flex:none;margin-top:3px;color:var(--neon);}
.objs-foot{margin:15px 0 0;padding-top:13px;border-top:1px dashed rgba(255,255,255,.18);
  font-size:.72rem;font-weight:600;color:var(--neon);}

/* ---- Carte 3 : l'écart de négociation ----
   Fond blanc sur le néon : le néon est un aplat de carte, il ne peut pas
   servir aussi de fond de maquette. */
.nego{background:#fff;border-radius:8px;padding:18px 18px 0;
  box-shadow:0 18px 40px -22px rgba(2,44,34,.35);overflow:hidden;}
.nego-case{display:block;font-size:.6rem;font-weight:700;letter-spacing:.1em;
  text-transform:uppercase;color:var(--muted);}
.nego-rows{list-style:none;margin:14px 0 0;padding:0;}
.nego-rows li{display:flex;align-items:baseline;justify-content:space-between;gap:14px;
  padding:11px 0;border-bottom:1px solid var(--line);font-size:.8rem;}
.nego-rows li span{color:var(--muted);}
.nego-rows li strong{font-weight:600;color:var(--ink);white-space:nowrap;}
/* La ligne clé déborde du padding de la maquette pour former une bande, comme
   .argu-key dans le hero : c'est le même geste, ce doit être la même forme. */
.nego-rows li.nego-key{margin:0 -18px;padding:14px 18px;border-bottom:0;
  background:var(--forest);}
.nego-rows li.nego-key span{color:rgba(248,249,235,.72);}
.nego-rows li.nego-key strong{color:var(--neon);}

/* ---- Bloc d'achat sans encadré ----
   Le prix est dans le libellé du bouton : sous trois cartes, un encadré de
   prix ferait une quatrième carte. Largeur du bouton alignée sur .sim-buy-cta
   pour que l'emprise soit la même d'une page de vente à l'autre. */
/* 34px et non 60 : l'arsenal vient juste au-dessus et lui appartient, le
   bouton ne doit pas s'en détacher comme d'un bloc étranger. */
.offer-buy-bare{margin:34px auto 0;text-align:center;}
.offer-bare-cta{display:flex;max-width:560px;margin-inline:auto;
  justify-content:center;padding:16px 28px;font-size:1.05rem;}
@media(max-width:560px){.offer-bare-cta{font-size:.92rem;padding:15px 20px;}}
.offer-buy-bare .price-note{margin-top:8px;}

/* Une colonne dès 980px : sous cette largeur les trois maquettes se serrent au
   point que les libellés de la carte 3 passent sur deux lignes. La hauteur
   imposée saute alors, chaque carte reprenant celle de son contenu. */
@media(max-width:980px){
  .offer-acc{grid-template-columns:1fr;gap:18px;}
  .offer-section .narrow + .offer-acc{margin-top:56px;}
  .offer-acc-card{min-height:0;}
  .offer-acc-viz{padding-top:30px;}
}

/* ---- L'arsenal, entre les cartes et le bouton ----
   En pastilles et non en lignes de carte : ces quatre-là ne sont pas des
   caractéristiques de plus, ce sont des objets qu'on reçoit.
   Marge haute alignée sur celle du bloc d'achat qui suivait auparavant, pour
   que l'écart cartes → arsenal → bouton reste régulier. */
.arsenal{max-width:620px;margin:56px auto 0;text-align:center;}
.arsenal-lbl{margin:0 0 14px;font-size:.72rem;font-weight:700;
  letter-spacing:.12em;text-transform:uppercase;color:var(--amber-ink);}
.arsenal ul{list-style:none;margin:0;padding:0;
  display:flex;flex-wrap:wrap;justify-content:center;gap:9px;}
/* Fond blanc sur le greige de la section : les pastilles se détachent sans
   ajouter de couleur, la carte de prix reste le seul blanc plein. */
.arsenal li{display:inline-flex;align-items:center;gap:8px;
  padding:8px 15px;border:1px solid var(--line);border-radius:999px;
  background:#fff;font-size:.86rem;font-weight:500;color:var(--ink);}
.arsenal li svg{width:15px;height:15px;flex:none;color:var(--pine);}

/* La bande de rentabilité ferme la section : elle est centrée comme la carte
   et l'arsenal, et garde la largeur du .price-wrap. */
.offer-section .roi{margin-inline:auto;text-align:center;}
