/*
  main.css - Alves Freres
  Feuille de style unique, ecrite a la main, basee sur les tokens de
  /_projet/design-system.md et sur la direction "architectural-precision"
  portee dans /_build/themes.py.

  La zone ci-dessous est GENEREE par /_build/theme_apply.py. Elle ne doit
  jamais etre editee a la main : toute modification serait ecrasee au
  prochain changement de direction artistique. Le reste du fichier est du
  CSS de production ecrit a la main.
*/

/* @@@ DEBUT ZONE GENEREE - ne pas editer a la main.
   Reecrite par : python3 _build/theme_apply.py --appliquer <direction>
   Catalogue des directions : _build/themes.py @@@ */

@font-face{
  font-family:'Hanken Grotesk';font-style:normal;font-weight:400 700;font-display:swap;
  src:url('/assets/fonts/hankengrotesk-latin.woff2') format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2192,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:'Geist';font-style:normal;font-weight:400 600;font-display:swap;
  src:url('/assets/fonts/geist-latin.woff2') format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2192,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}

/* ---------- Direction : Architectural Precision, vert foret et tuile ----------
   Registre moderne suisse et catalogue architectural : aplats, angles droits, filets de 1 px, aucune ombre. Le rouge de la maquette (#C92A2A) est remplace : il tombait a 2,47:1 sur le vert foret.
   Direction en aplats : aucun degrade, aucune ombre, rayon zero.
   Le vert le plus clair admissible sous du texte blanc est --i-550 (#4A6452).
   Les verts plus clairs sont decoratifs : jamais sous du texte blanc. */
:root{
  /* Rampe de vert */
  --i-1000:#050E08;
  --i-950:#091E11;
  --i-900:#16261C;
  --i-800:#1E3325;
  --i-700:#2A4230;
  --i-600:#0E5B32;
  --i-550:#4A6452;
  --i-500:#5D7A66;
  --i-400:#8AA492;
  --i-300:#B4CDB9;
  --i-200:#CCEAD2;
  --i-100:#E4F1E7;
  --i-50:#F1F7F2;
  --i-25:#F8FBF9;

  /* Accent tuile. Le 500 ne vit que sur fond vert, le 600 et le ink
     que sur fond clair. Les deux mondes ne se croisent jamais. */
  --a-500:#E2705B;
  --a-600:#B0362A;
  --a-ink:#8E2A20;
  --a-50:#FBEDE9;

  /* Gris neutres */
  --g-900:#1C1B1B;
  --g-800:#2E2D2C;
  --g-700:#434843;
  --g-600:#575C57;
  --g-500:#686866;
  --g-400:#8B8B88;
  --g-300:#B6B6B2;
  --g-200:#E5E4DE;
  --g-100:#F0EFEA;
  --g-50:#F7F6F2;
  --n-0:#FFFFFF;

  /* Surfaces */
  --surface-limestone:#FBFBFA;
  --surface-cream:#F5F4F0;
  --surface-noir:#0F0F0F;
  --surface-white:#FFFFFF;
  --border-subtle:#E5E4DE;
  --border-field:#8B8B88;
  --border-inverse:rgba(255,255,255,0.12);
  --rule-w:1px;

  /* Aplats. Les noms --grad-* sont conserves pour compatibilite mais
     ne portent aucun degrade : cette direction est en couleurs pleines. */
  --grad-panel:var(--i-800);
  --grad-cta:var(--i-950);
  --grad-ink:var(--i-900);
  --grad-btn:var(--i-800);
  --grad-soft:var(--surface-cream);
  --grad-card:var(--surface-white);
  --grad-footer:var(--surface-noir);
  --grad-amber:var(--a-600);

  /* Etats semantiques */
  --err:#BA1A1A;
  --err-bg:#FFDAD6;
  --err-ink:#93000A;
  --ok:#072012;
  --ok-bg:#CCEAD2;
  --ok-ink:#072012;

  /* Typographie : deux familles */
  --font-display:'Hanken Grotesk',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
  --font-body:'Geist',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;
  --titre-graisse:600;
  --titre-tracking:-.028em;
  --titre-align:left;

  /* Echelle. Bornes basses = valeurs mobiles du design system,
     bornes hautes = valeurs desktop. Tout en rem, jamais en px figes. */
  --fs-display:clamp(2.5rem,1.55rem + 4.2vw,4.5rem);
  --fs-h1:clamp(2.125rem,1.5rem + 2.6vw,3.5rem);
  --fs-h2:clamp(1.75rem,1.32rem + 1.8vw,3rem);
  --fs-h3:clamp(1.25rem,1.14rem + 0.45vw,1.5rem);
  --fs-lead:clamp(1.0625rem,1.02rem + 0.2vw,1.1875rem);
  --fs-body:1rem;
  --fs-small:0.875rem;
  --fs-label:0.75rem;
  --lh-display:1.2;
  --lh-titre:1.2;
  --lh-body:1.625;
  --ls-display:-0.03em;
  --ls-titre:-0.03em;
  --ls-body:-0.01em;
  --ls-label:0.08em;

  --measure:66ch;
  --measure-lead:56ch;
  --measure-head:24ch;

  /* Espacements */
  --sp-1:0.25rem;--sp-2:0.5rem;--sp-3:0.75rem;--sp-4:1rem;--sp-6:1.5rem;--sp-8:2rem;
  --sp-10:2.5rem;--sp-16:4rem;--sp-24:6rem;
  --gutter:1.5rem;
  --marge-page:clamp(1.25rem,4vw,4rem);
  --section-y:clamp(4rem,7vw,6rem);
  --maxw:1280px;
  --maxw-narrow:760px;

  /* Formes. Rayon zero partout, --r-pill reserve aux puces circulaires
     et aux pastilles d'etat. Aucune ombre : filets de 1 px. */
  --r-sm:0;--r-md:0;--r-lg:0;--r-xl:0;--r-panel:0;--r-pill:999px;
  --shadow-1:none;
  --shadow-2:none;
  --shadow-v:none;
  --ease:cubic-bezier(.22,.61,.36,1);
  --ease-out:cubic-bezier(.16,.84,.34,1);
  --ease-soft:cubic-bezier(.4,0,.2,1);

  /* Contexte par defaut : fond clair */
  --bg:var(--surface-limestone);
  --bg-alt:var(--surface-cream);
  --fg:var(--g-900);
  --fg-soft:var(--g-700);
  --fg-faint:var(--g-500);
  --fg-titre:var(--i-950);
  --eyebrow:var(--i-550);
  --accent:var(--a-ink);
  --accent-rule:var(--a-600);
  --accent-bg:var(--a-50);
  --rule:var(--border-subtle);
  --rule-strong:var(--g-300);
  --card:var(--surface-white);
  --card-alt:var(--surface-cream);
  --field-bg:var(--surface-white);
  --field-border:var(--border-field);
  --btn-fill:var(--i-800);
  --btn-fill-text:var(--n-0);
  --btn-fill-border:var(--i-800);
  --btn-fill-hover:var(--i-950);
  --btn-line:var(--i-950);
  --btn-line-text:var(--i-950);
  --focus:var(--i-950);
}

/* Inversion monolithique : pleine largeur en vert foret, texte blanc.
   Memes tokens, valeurs de l'autre contexte. L'accent y passe au 500,
   seul palier de tuile qui tienne 3:1 sur ces fonds. */
.bloc-inverse{
  --bg:var(--i-800);
  --bg-alt:var(--i-900);
  --fg:var(--n-0);
  --fg-soft:var(--i-300);
  --fg-faint:var(--i-300);
  --fg-titre:var(--n-0);
  --eyebrow:var(--i-200);
  --accent:var(--a-500);
  --accent-rule:var(--a-500);
  --accent-bg:var(--i-900);
  --rule:var(--border-inverse);
  --rule-strong:var(--i-700);
  --card:var(--i-900);
  --card-alt:var(--i-950);
  --field-bg:var(--n-0);
  --field-border:var(--i-700);
  --btn-fill:var(--n-0);
  --btn-fill-text:var(--i-950);
  --btn-fill-border:var(--n-0);
  --btn-fill-hover:var(--i-200);
  --btn-line:var(--n-0);
  --btn-line-text:var(--n-0);
  --focus:var(--n-0);
}

/* @@@ FIN ZONE GENEREE @@@ */

/* ===========================================================================
   CSS DE PRODUCTION - ecrit a la main.
   Tout ce qui suit s'appuie exclusivement sur les tokens de la zone generee
   ci-dessus (variables --i-*, --a-*, --g-*, --sp-*, --fs-*, etc). Aucune
   valeur de couleur ou de taille de police n'est ecrite en dur ici.
   Repères de rupture : 480, 768, 1024, 1280 (design-system.md section 4).
   =========================================================================== */

/* ---------- 1. Reset ---------- */

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

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

body {
  margin: 0;
  background: var(--surface-limestone);
  color: var(--g-900);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  letter-spacing: var(--ls-body);
  -webkit-font-smoothing: antialiased;
}

img, picture, svg { max-width: 100%; display: block; }
/* Garde-fou de taille des icones.
   "max-width: 100%" ne borne que la largeur : un svg sans attribut width ni
   classe dimensionnante prend toute la largeur de son conteneur. Dans le
   contenu des quatre pages legales, les icones telephone, enveloppe et epingle
   s'affichaient ainsi a 215 px de haut a cote d'un texte de 14 px, et jusqu'a
   290 px sur mobile. On leur donne une taille par defaut proportionnelle au
   texte ; toute regle nommee (.logo svg, .burger svg, .coord-list svg) reste
   plus specifique et continue de primer. */
svg:not([width]) { width: 1.25em; height: 1.25em; flex-shrink: 0; }
img { height: auto; }

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: var(--titre-graisse);
  letter-spacing: var(--ls-titre);
  line-height: var(--lh-titre);
  color: var(--fg-titre, var(--i-950));
  margin: 0 0 var(--sp-4);
  text-wrap: balance;
}
h1 { font-size: var(--fs-h1); }
h2 { font-size: var(--fs-h2); }
h3 { font-size: var(--fs-h3); }
h4 { font-size: var(--fs-lead); }

/* Le modele de reference ne met la graisse 600 que sur deux titres par page,
   celui du premier ecran et celui du bloc d'appel a l'action final ; tous ses
   autres titres sont en 500. Mesures relevees au navigateur : h1 72/600,
   en-tete de section 48/500, titre de carte 32/500. On s'aligne. */
h2, h3, h4 { font-weight: 500; }

/* Mesure des grands titres. Le jeton --measure-head existait depuis le debut du
   projet et n'etait utilise nulle part : les titres de section poses en enfant
   direct du conteneur traversaient donc la page sur une seule ligne de 48 px,
   large de 1150 px. Le modele de reference casse tous ses titres autour de
   22 signes, sur deux ou trois lignes. On ne cible que l'enfant direct du
   conteneur : les titres deja places dans une colonne de grille, dans une carte
   ou dans le pied de page ont leur propre mesure, plus etroite. */
#contenu .container > h2 { max-width: var(--measure-head); }
/* Les h1 sont a 72 px : a mesure egale en "ch", ils portent une ligne bien plus
   longue que les h2 a 48 px, et le titre de la page aides tenait sur une seule
   ligne de 968 px. On les serre d'un cran. */
#contenu .container > h1 { max-width: 18ch; }

p { margin: 0 0 var(--sp-4); max-width: var(--measure); color: var(--g-700); }
p.lead { font-size: var(--fs-lead); color: var(--g-900); max-width: var(--measure-lead); }

ul, ol { padding-left: 1.25em; margin: 0 0 var(--sp-4); color: var(--g-700); }
li { margin-bottom: var(--sp-2); }

a { color: var(--i-900); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { color: var(--i-800); }

small { font-size: var(--fs-small); color: var(--g-500); }

hr { border: none; border-top: 1px solid var(--border-subtle); margin: var(--sp-16) 0; }

/* Un tableau a cinq colonnes ne tient pas dans 390 px. Sans ce defilement
   propre, celui de la page "gestion des cookies" debordait le viewport et
   emportait la mise en page de toute la page sur telephone. "display: block"
   fait du tableau une boite defilable ; les rangees restent des rangees, le
   navigateur reconstruisant la table anonyme a l'interieur.
   Les balises <table> portent tabindex="0", role="region" et un nom pris dans
   leur legende (voir la reprise du 9 septembre 2026) : WCAG 2.1.1 exige qu'une
   zone a defilement soit operable au clavier, et Chrome comme Safari ne
   donnent pas le focus a une boite "overflow: auto" sans tabindex. */
table {
  display: block;
  overflow-x: auto;
  max-width: 100%;
  border-collapse: collapse;
  margin: 0 0 var(--sp-6);
  font-size: var(--fs-small);
}
@media (min-width: 900px) { table { display: table; width: 100%; } }
caption { text-align: left; font-weight: 600; margin-bottom: var(--sp-2); color: var(--g-900); }
th, td { text-align: left; padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--border-subtle); vertical-align: top; }
th { color: var(--g-900); font-weight: 600; }

dt { font-weight: 600; color: var(--g-900); margin-top: var(--sp-3); }
dd { margin: 0 0 var(--sp-2); color: var(--g-700); }

/* Focus visible partout : jamais outline:none sans remplacement. */
:focus { outline: none; }
:focus-visible {
  outline: 2px solid var(--focus, var(--i-950));
  outline-offset: 2px;
}
a:focus-visible, button:focus-visible, input:focus-visible,
textarea:focus-visible, select:focus-visible, summary:focus-visible,
[tabindex]:focus-visible { outline: 2px solid var(--i-950); outline-offset: 2px; }

/* ---------- 2. Accessibilite utilitaire ---------- */

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

[hidden] { display: none !important; }

.skip-link {
  position: absolute;
  left: var(--sp-4);
  top: -3rem;
  z-index: 1000;
  background: var(--i-950);
  color: #fff;
  padding: var(--sp-3) var(--sp-4);
  font-weight: 600;
  transition: top .15s var(--ease-out);
}
.skip-link:focus { top: var(--sp-4); }

/* Marqueur visible de contenu manquant : jamais de faux contenu. */
.a-fournir {
  display: inline-block;
  background: var(--err-bg);
  color: var(--err-ink);
  border: 1px solid var(--err);
  padding: 0 var(--sp-2);
  font-size: var(--fs-small);
  font-weight: 600;
}
p .a-fournir, li .a-fournir { display: inline-block; margin: var(--sp-1) 0; }

/* ---------- 3. Grille et conteneur ---------- */

.container {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--marge-page);
}

.container--narrow { max-width: var(--maxw-narrow); }

.grid {
  display: grid;
  gap: var(--gutter);
  grid-template-columns: repeat(1, 1fr);
}
@media (min-width: 768px) { .grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .grid { grid-template-columns: repeat(12, 1fr); } }

.grid--3 { grid-template-columns: repeat(1, 1fr); }
@media (min-width: 768px) { .grid--3 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .grid--3 { grid-template-columns: repeat(3, 1fr); } }

.grid--2 { grid-template-columns: repeat(1, 1fr); }
@media (min-width: 768px) { .grid--2 { grid-template-columns: repeat(2, 1fr); } }

/* M2 (audit visuel) : un h3 qui suit directement un ".grid" (typiquement une
   illustration en demi-colonne) n'heritait d'aucune marge haute propre : sa
   marge de titre standard est nulle (voir "h1,h2,h3,h4" plus haut) et la
   marge basse de l'image qui le precede ne compense pas la sortie de grille.
   Resultat mesure : 6 px entre l'image et le titre suivant, contre 40 a 45 px
   ailleurs entre un paragraphe et le titre suivant. On aligne sur ce rythme. */
.grid + h3 { margin-top: var(--sp-10); }

.stack { display: flex; flex-direction: column; gap: var(--sp-4); }
.cluster { display: flex; flex-wrap: wrap; gap: var(--sp-3); align-items: center; }

/* Rythme vertical entre sections majeures. */
.section { padding-block: var(--section-y); border-top: 1px solid var(--rule); }
.section:first-of-type, .hero + .section { border-top: none; }
.section--alt { background: var(--surface-cream); }
.section--inverse { background: var(--i-800); }

/* ---------- 4. Libelles de section (barre verticale) ---------- */

.eyebrow {
  display: flex;
  width: fit-content;
  align-items: center;
  gap: var(--sp-2);
  font-family: var(--font-body);
  font-size: 1rem;
  font-weight: 500;
  line-height: 1.5;
  letter-spacing: -0.02em;
  text-transform: none;
  /* --i-900 (#16261C) et non --eyebrow (--i-550, #4A6452) : le modele pose son
     sur-titre en #17271C, presque noir. --eyebrow reste la couleur des puces,
     des icones et des etiquettes, ou le vert moyen est a sa place. */
  color: var(--i-900);
  margin: 0 0 var(--sp-4);
}
.eyebrow::before {
  content: "";
  display: inline-block;
  width: 3px;
  height: 1em;
  background: currentColor;
}
.bloc-inverse .eyebrow, .section--inverse .eyebrow { color: rgba(255,255,255,.56); }

/* ---------- 5. Boutons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  min-height: 44px;
  padding: 0.875rem 1.5rem;
  font-family: var(--font-body);
  font-size: var(--fs-small);
  font-weight: 500;
  line-height: 1;
  text-decoration: none;
  border-radius: var(--r-md);
  border: 1px solid transparent;
  cursor: pointer;
  transition: background-color .15s var(--ease-out), color .15s var(--ease-out), transform .15s var(--ease-out), border-color .15s var(--ease-out);
}
.btn__arrow { transition: transform .15s var(--ease-out); }
.btn:hover .btn__arrow { transform: translateX(4px); }

.btn--primary,
.btn--primary:link, .btn--primary:visited {
  background: var(--i-800);
  color: #fff;
  border-color: var(--i-800);
}
.btn--primary:hover { background: var(--i-950); border-color: var(--i-950); color: #fff; }

.btn--primary-inverse,
.btn--primary-inverse:link, .btn--primary-inverse:visited {
  background: #fff;
  color: var(--i-950);
  border-color: #fff;
}
.btn--primary-inverse:hover { background: var(--i-200); border-color: var(--i-200); color: var(--i-950); }

.btn--secondary,
.btn--secondary:link, .btn--secondary:visited {
  background: transparent;
  color: var(--i-950);
  border-color: var(--i-950);
}
.btn--secondary:hover { background: var(--i-950); color: #fff; }

/* Bouton secondaire sur fond sombre.
   .hero est inclus deliberement, en plus de .bloc-inverse et .section--inverse :
   un hero porte TOUJOURS le fond vert foret (voir .hero plus bas), la variante
   claire du bouton y est donc structurellement obligatoire, jamais optionnelle.
   Sans cette ligne, le bouton s'affichait en vert d'encre sur vert foret, soit
   un contraste de 1,29:1 pour un minimum exige de 4,5:1 : le libelle etait
   quasiment invisible. Le defaut n'existait que sur l'accueil, seule page a
   combiner un bouton secondaire dans un hero sans la classe .bloc-inverse ;
   dependre de cette classe rendait la lisibilite tributaire d'un oubli
   d'integration, alors qu'elle decoule du fond. */
.hero .btn--secondary,
.hero .btn--secondary:link, .hero .btn--secondary:visited,
.bloc-inverse .btn--secondary,
.bloc-inverse .btn--secondary:link, .bloc-inverse .btn--secondary:visited,
.section--inverse .btn--secondary,
.section--inverse .btn--secondary:link, .section--inverse .btn--secondary:visited,
.footer-cta .btn--secondary,
.footer-cta .btn--secondary:link, .footer-cta .btn--secondary:visited {
  color: #fff;
  border-color: #fff;
}
.hero .btn--secondary:hover,
.bloc-inverse .btn--secondary:hover, .section--inverse .btn--secondary:hover,
.footer-cta .btn--secondary:hover { background: #fff; color: var(--i-950); }

.btn--link,
.btn--link:link, .btn--link:visited {
  background: transparent;
  color: var(--i-950);
  border: none;
  padding: var(--sp-2) 0;
  min-height: auto;
  font-weight: 600;
}
.btn--link:hover { color: var(--i-800); }
.bloc-inverse .btn--link, .bloc-inverse .btn--link:link, .bloc-inverse .btn--link:visited { color: #fff; }

.btn--call {
  background: var(--a-600);
  color: #fff;
  border-color: var(--a-600);
}
.btn--call:link, .btn--call:visited { color: #fff; }
.btn--call:hover { background: var(--a-ink); border-color: var(--a-ink); color: #fff; }
/* Le libelle "Appeler le 05 63 66 17 89" se cassait en trois lignes dans le
   panneau etroit du hero de la page depannage, le numero se retrouvant coupe
   en deux. C'est le bouton le plus important de cette page : il doit tenir sur
   une ligne, quitte a reduire legerement son texte sur les petites largeurs. */
.btn--call { white-space: nowrap; }
@media (max-width: 420px) { .btn--call { font-size: var(--fs-small); padding-inline: var(--sp-4); } }

.btn--full { width: 100%; }

/* ---------- 6. En-tete ---------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 500;
  background: var(--surface-limestone);
  border-bottom: 1px solid var(--border-subtle);
}

.header-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  padding-block: var(--sp-3);
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--marge-page);
}

.logo {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.25rem;
  color: var(--i-950);
  text-decoration: none;
  letter-spacing: var(--ls-titre);
}
.logo:hover { color: var(--i-800); }
.logo svg { width: 32px; height: 32px; }

.main-nav { display: none; }
@media (min-width: 1024px) {
  .main-nav {
    display: flex;
    align-items: center;
    gap: var(--sp-6);
    font-size: var(--fs-small);
    font-weight: 600;
  }
  .main-nav a { color: var(--g-900); text-decoration: none; }
  .main-nav a:hover { color: var(--i-800); }
}

.nav-metiers { position: relative; }
.nav-metiers > summary {
  list-style: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  color: var(--g-900);
}
.nav-metiers > summary::-webkit-details-marker { display: none; }
.nav-metiers > summary::after {
  content: "";
  width: 8px; height: 8px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg);
  margin-top: -4px;
}
.nav-metiers[open] > summary::after { transform: rotate(225deg); margin-top: 4px; }
.nav-metiers-panel {
  position: absolute;
  top: calc(100% + var(--sp-3));
  left: 0;
  min-width: 260px;
  background: var(--surface-white);
  border: 1px solid var(--border-subtle);
  padding: var(--sp-2);
  display: flex;
  flex-direction: column;
}
.nav-metiers-panel a {
  padding: var(--sp-2) var(--sp-3);
  color: var(--g-900);
  font-weight: 500;
}
.nav-metiers-panel a:hover { background: var(--surface-cream); }
.nav-metiers-panel a.nav-urgence {
  margin-top: var(--sp-2);
  border-top: 1px solid var(--border-subtle);
  padding-top: var(--sp-3);
  color: var(--a-ink);
}

.header-actions { display: flex; align-items: center; gap: var(--sp-4); }

.header-phone {
  display: none;
  flex-direction: column;
  text-align: right;
  font-size: var(--fs-small);
  color: var(--g-700);
  text-decoration: none;
}
/* Le numero et le libelle ne doivent jamais se couper : "05 63 66 17" sur une
   ligne et "89" sur la suivante se lit comme deux nombres, et c'est l'element
   que l'on veut le plus lisible de tout l'en-tete. Constate a 1440 px. */
.header-phone strong { color: var(--i-950); font-size: var(--fs-body); white-space: nowrap; }
.header-phone span { white-space: nowrap; }
.header-cta { white-space: nowrap; }
@media (min-width: 1024px) { .header-phone { display: flex; } }

.header-urgence {
  display: none;
  font-size: var(--fs-small);
  font-weight: 600;
  color: var(--a-ink);
  text-decoration: none;
  border: 1px solid var(--a-600);
  padding: var(--sp-2) var(--sp-3);
}
.header-urgence:hover { background: var(--a-50); color: var(--a-ink); }
@media (min-width: 1024px) { .header-urgence { display: inline-flex; align-items: center; } }

.header-phone-mobile {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px; height: 44px;
  color: var(--i-950);
  border: 1px solid var(--border-subtle);
}
@media (min-width: 1024px) { .header-phone-mobile { display: none; } }

.header-cta { display: none; }
@media (min-width: 1024px) { .header-cta { display: inline-flex; } }

/* Burger, uniquement mobile/tablette */
.burger {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px; height: 44px;
  border: 1px solid var(--border-subtle);
  background: transparent;
  cursor: pointer;
}
@media (min-width: 1024px) { .burger { display: none; } }
.burger svg { width: 22px; height: 22px; }

/* Tiroir mobile, plein ecran. Fonctionne sans JS via checkbox.
   Le controle reellement focusable et activable au clavier (Tab puis Espace)
   EST cette case a cocher : le <label class="burger"> qui la double visuellement
   est purement decoratif (aria-hidden, voir plus bas), il ne recoit jamais le
   focus. Correction QA M3/M4 : avant cette correction, le label portait
   role="button" tabindex="0" sans gestionnaire clavier, ce qui creait un second
   arret de tabulation visible mais inerte. */
.drawer-toggle { position: absolute; opacity: 0; pointer-events: none; }

/* Anneau de focus visible sur le bouton burger DECORATIF quand c'est la case
   .drawer-toggle (invisible mais reellement focusable) qui recoit le focus
   clavier. Trois formes de selecteur necessaires, une par structure de gabarit
   reellement livree (verifie sur les 19 pages) :
   1. case et label freres directs dans .header-actions (la majorite des pages) ;
   2. case placee en tete de <header>, sœur de .header-bar, label niche dedans
      (contact, depannage-toiture-montauban, realisations) ;
   3. case placee au niveau du <body>, sœur de <header> lui-meme, label niche
      dans .header-bar (accueil, gabarit de reference). */
.drawer-toggle:focus-visible ~ .burger,
.drawer-toggle:focus-visible ~ .header-bar .burger,
.drawer-toggle:focus-visible ~ header .burger {
  outline: 2px solid var(--focus, var(--i-950));
  outline-offset: 2px;
}

.drawer {
  position: fixed;
  inset: 0;
  z-index: 2000;
  background: var(--i-950);
  color: #fff;
  display: flex;
  flex-direction: column;
  transform: translateX(100%);
  transition: transform .2s var(--ease-out);
  overflow-y: auto;
}
.drawer-toggle:checked ~ .drawer { transform: translateX(0); }

.drawer-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--sp-4) var(--marge-page);
  border-bottom: 1px solid var(--border-inverse);
}
.drawer-close {
  width: 44px; height: 44px;
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent; border: 1px solid var(--border-inverse); color: #fff;
  cursor: pointer;
}
.drawer-nav { padding: var(--sp-6) var(--marge-page); display: flex; flex-direction: column; gap: var(--sp-1); }
.drawer-nav a {
  color: #fff;
  text-decoration: none;
  font-family: var(--font-display);
  font-size: var(--fs-lead);
  padding: var(--sp-3) 0;
  border-bottom: 1px solid var(--border-inverse);
}
.drawer-nav a.nav-urgence { color: var(--a-500); font-weight: 700; }
.drawer-foot { margin-top: auto; padding: var(--sp-6) var(--marge-page); }
@media (min-width: 1024px) { .drawer, .drawer-toggle { display: none; } }

/* Barre CTA sticky mobile, amelioration progressive JS. Repli : invisible tant
   que JS ne l'active pas, l'appel reste possible via l'en-tete a tout moment. */
.mobile-cta-bar {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 400;
  display: none;
  gap: 1px;
  background: var(--border-subtle);
  border-top: 1px solid var(--border-subtle);
  transform: translateY(100%);
  transition: transform .2s var(--ease-out);
}
.mobile-cta-bar.is-visible { transform: translateY(0); }
.js .mobile-cta-bar { display: flex; }
@media (min-width: 1024px) { .mobile-cta-bar { display: none !important; } }
.mobile-cta-bar a {
  flex: 1;
  display: flex; align-items: center; justify-content: center;
  min-height: 52px;
  text-decoration: none;
  font-weight: 700;
  font-size: var(--fs-small);
}
.mobile-cta-bar .mcb-appeler { background: var(--a-600); color: #fff; }
.mobile-cta-bar .mcb-devis { background: var(--i-800); color: #fff; }
.mobile-cta-bar--seule .mcb-appeler { flex: 1 1 100%; }

/* ---------- 7. Fil d'Ariane ----------
   Cible l'attribut aria-label plutot qu'une classe : les fragments de contenu
   ecrits par copywriting-contenu portent deja <nav aria-label="Fil d'Ariane">
   sans aucune classe CSS (convention documentee dans les fragments). */

nav[aria-label="Fil d'Ariane"] {
  padding-block: var(--sp-4);
  font-size: var(--fs-small);
  color: var(--g-500);
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--marge-page);
}
nav[aria-label="Fil d'Ariane"] ol { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--sp-2); }
nav[aria-label="Fil d'Ariane"] li:not(:last-child)::after { content: "/"; margin-left: var(--sp-2); color: var(--g-300); }
nav[aria-label="Fil d'Ariane"] a { color: var(--g-500); text-decoration: none; }
nav[aria-label="Fil d'Ariane"] a:hover { color: var(--i-800); }
nav[aria-label="Fil d'Ariane"] [aria-current="page"] { color: var(--g-900); font-weight: 600; }

/* ---------- 8. Heros ---------- */

.hero {
  background: var(--i-800);
  color: #fff;
  padding-block: var(--sp-24);
  min-height: 100svh;
  display: flex;
  align-items: center;
}
@media (min-width: 1024px) { .hero { min-height: auto; padding-block: var(--sp-24); } }

.hero--court { min-height: auto; padding-block: var(--sp-16); }

.hero-grid {
  display: grid;
  gap: var(--sp-10);
  width: 100%;
}
@media (min-width: 1024px) { .hero-grid { grid-template-columns: 1.6fr 1fr; align-items: start; } }

.hero h1 { color: #fff; font-size: var(--fs-display); }
.hero p.lead { color: var(--i-200); max-width: 46ch; }
.hero .cluster { margin-top: var(--sp-6); }

.hero-reassurance {
  border: 1px solid var(--border-inverse);
  padding: var(--sp-6);
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
}
.hero-reassurance dt { color: var(--i-200); font-weight: 600; font-size: var(--fs-small); margin-top: 0; }
.hero-reassurance dd { color: #fff; margin: 0; font-weight: 600; }

/* Bandeau urgence */
.bandeau-urgence {
  background: var(--a-600);
  color: #fff;
}
.bandeau-urgence .container {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  padding-block: var(--sp-4);
}
.bandeau-urgence p { color: #fff; margin: 0; font-weight: 600; }
.bandeau-urgence a.tel { color: #fff; font-size: var(--fs-lead); font-weight: 700; text-decoration: none; }
.bandeau-urgence a.tel:hover { text-decoration: underline; }

/* ---------- 9. Cartes metier numerotees ---------- */

.card-metier {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--border-subtle);
  background: var(--surface-cream);
}
.card-metier__index {
  font-family: var(--font-display);
  font-size: var(--fs-lead);
  font-weight: 400;
  color: var(--eyebrow);
}
.card-metier__body { padding: var(--sp-6); display: flex; flex-direction: column; gap: var(--sp-3); flex: 1; }
.card-metier__cat { text-transform: uppercase; letter-spacing: var(--ls-label); font-size: var(--fs-label); color: var(--g-500); font-weight: 600; }
.card-metier__specs { list-style: none; padding: 0; margin: 0 0 var(--sp-2); font-size: var(--fs-small); }
.card-metier__specs li { position: relative; padding-left: var(--sp-4); margin-bottom: var(--sp-1); color: var(--g-700); }
.card-metier__specs li::before { content: "\2013"; position: absolute; left: 0; color: var(--eyebrow); }
.card-metier__media { height: 256px; background: var(--i-700); overflow: hidden; }
.card-metier__media img { width: 100%; height: 100%; object-fit: cover; }
.card-metier--inverse { background: var(--i-800); border-color: var(--border-inverse); }
.card-metier--inverse .card-metier__index { color: var(--i-200); }
.card-metier--inverse h3 { color: #fff; }
.card-metier--inverse p { color: var(--i-300); }
.card-metier--inverse .card-metier__cat { color: var(--i-300); }

/* ---------- 10. Realisations et filtres ---------- */

.filtres {
  display: flex;
  flex-wrap: nowrap;
  overflow-x: auto;
  gap: var(--sp-2);
  padding-bottom: var(--sp-2);
  margin-bottom: var(--sp-10);
  -webkit-overflow-scrolling: touch;
}
@media (min-width: 768px) { .filtres { flex-wrap: wrap; overflow: visible; } }
.filtre {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 var(--sp-4);
  border: 1px solid var(--border-subtle);
  background: var(--surface-white);
  color: var(--g-700);
  text-decoration: none;
  font-size: var(--fs-small);
  font-weight: 600;
  white-space: nowrap;
}
.filtre:hover { border-color: var(--i-800); color: var(--i-900); }
/* Les filtres sont de vrais liens <a>, pas des boutons : aria-pressed n'y est pas
   valide (WAI-ARIA), on utilise aria-current="true" sur le lien actif. Le
   selecteur aria-pressed reste couvert par prudence si un futur filtre est
   rendu en <button> plutot qu'en lien. */
.filtre[aria-current="true"], .filtre[aria-pressed="true"] { background: var(--i-800); border-color: var(--i-800); color: #fff; }

.card-realisation {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--border-subtle);
  background: var(--surface-white);
  text-decoration: none;
  color: inherit;
}
.card-realisation:hover { border-color: var(--i-800); }
.card-realisation__media { height: 220px; background: var(--surface-cream); overflow: hidden; }
.card-realisation__media img { width: 100%; height: 100%; object-fit: cover; }
.card-realisation__body { padding: var(--sp-4); display: flex; flex-direction: column; gap: var(--sp-1); }
.card-realisation__tag { font-size: var(--fs-label); text-transform: uppercase; letter-spacing: var(--ls-label); color: var(--eyebrow); font-weight: 600; }
.card-realisation__body h3 { font-size: var(--fs-lead); margin-bottom: 0; }
.card-realisation__body p { font-size: var(--fs-small); margin: 0; }

.etat-vide {
  border: 1px dashed var(--border-field);
  padding: var(--sp-10);
  text-align: center;
  color: var(--g-500);
}

.pagination { display: flex; gap: var(--sp-2); list-style: none; padding: 0; margin-top: var(--sp-10); }
.pagination a, .pagination span {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 44px; min-height: 44px;
  border: 1px solid var(--border-subtle);
  text-decoration: none; color: var(--g-700);
}
.pagination a:hover { border-color: var(--i-800); color: var(--i-900); }
.pagination [aria-current="page"] { background: var(--i-800); color: #fff; border-color: var(--i-800); }

/* ---------- 11. Blocs de chiffres ---------- */

.stats { display: grid; gap: var(--sp-6); grid-template-columns: repeat(1, 1fr); }
@media (min-width: 768px) { .stats { grid-template-columns: repeat(3, 1fr); } }
.stat__nombre {
  font-family: var(--font-display);
  font-size: var(--fs-display);
  font-weight: var(--titre-graisse);
  color: var(--fg-titre, var(--i-950));
  line-height: 1;
}
.stat__label {
  font-size: var(--fs-label);
  text-transform: uppercase;
  letter-spacing: var(--ls-label);
  color: var(--g-500);
  margin-top: var(--sp-2);
}

/* ---------- 12. Formulaires ---------- */

.field { display: flex; flex-direction: column; gap: var(--sp-2); margin-bottom: var(--sp-6); }
.field > label, .fieldset-legend {
  font-weight: 600;
  color: var(--g-900);
  font-size: var(--fs-small);
}
.field .aide { font-size: var(--fs-small); color: var(--g-500); margin: 0; }
.field input[type="text"],
.field input[type="tel"],
.field input[type="email"],
.field input[type="file"],
.field textarea,
.field select {
  min-height: 44px;
  padding: var(--sp-3);
  background: var(--field-bg);
  border: 1px solid var(--field-border);
  border-radius: var(--r-sm);
  font: inherit;
  color: var(--g-900);
}
.field textarea { min-height: 120px; resize: vertical; }
.field input:focus-visible, .field textarea:focus-visible, .field select:focus-visible {
  outline: 2px solid var(--i-950);
  outline-offset: 1px;
  border-color: var(--i-950);
}
.field.has-error input, .field.has-error textarea { border-color: var(--err); }
.field .erreur-champ { color: var(--err-ink); font-size: var(--fs-small); font-weight: 600; }

.check-group, .radio-group { display: flex; flex-direction: column; gap: var(--sp-3); }
.check-item, .radio-item { display: flex; align-items: flex-start; gap: var(--sp-3); }
.check-item input, .radio-item input { margin-top: 4px; width: 20px; height: 20px; flex-shrink: 0; }
.check-item label, .radio-item label { font-weight: 400; color: var(--g-700); }

/* .consentement (retiree) : la case a cocher RGPD bloquante qu'elle habillait a ete
   supprimee de contact.html et depannage-toiture-montauban.html (correction QA BLOQUANT 3,
   4 septembre 2026 : base legale article 6.1.b, pas de consentement a recueillir). Regle
   devenue du code mort, retiree ici pour la meme raison que .bandeau-cookies plus haut. */

/* Honeypot : masque hors ecran, jamais display:none seul, hors tabulation. */
.piege-anti-spam {
  position: absolute;
  left: -9999px;
  top: auto;
  width: 1px; height: 1px;
  overflow: hidden;
}

.fieldset-etape { border: none; padding: 0; margin: 0 0 var(--sp-10); }
/* M9 (audit visuel) : la <legend> de chaque etape et le paragraphe ".aide" qui
   la suit s'affichaient dans la meme graisse, le meme corps et le meme gris
   (aucune des deux n'etait stylee : le CSS ecrit pour elles ciblait
   "#formulaire-devis legend"/"#formulaire-devis fieldset > p:first-of-type",
   un identifiant qui ne correspond a aucun formulaire reellement livre, les
   deux formulaires du site portant "#form-devis" et "#form-urgence". On
   restyle ici la legend et l'aide par leur position reelle dans le HTML
   (".fieldset-etape"), qui est commune aux deux formulaires. La <legend> gagne
   la typographie de titre (comme un h3) pour se distinguer nettement du texte
   d'aide qui suit ; "padding:0" retire les 2 px de padding-inline que
   certains navigateurs appliquent par defaut a <legend>, qui la decalaient
   par rapport aux paragraphes voisins. */
.fieldset-etape legend {
  font-family: var(--font-display);
  font-weight: var(--titre-graisse);
  letter-spacing: var(--ls-titre);
  line-height: var(--lh-titre);
  font-size: var(--fs-h3);
  color: var(--i-950);
  padding: 0;
  margin: 0 0 var(--sp-3);
  width: 100%;
}
/* "> .aide" et non ".aide" : a l'etape 3, chaque champ repete ce composant en
   <span> a l'interieur d'un ".field" (deja stylee par ".field .aide", marge
   nulle pour rester colle a son champ). Un selecteur non scope aurait impose
   la meme marge basse de 24 px a ces spans, les detachant de leur champ. */
.fieldset-etape > .aide { font-size: var(--fs-small); color: var(--g-500); margin: 0 0 var(--sp-6); }

.form-recap {
  border: 1px solid var(--border-subtle);
  background: var(--surface-cream);
  padding: var(--sp-4) var(--sp-6);
  margin-bottom: var(--sp-6);
  font-size: var(--fs-small);
}
.form-recap dt { font-size: var(--fs-label); text-transform: uppercase; color: var(--g-500); }
.form-recap dd { color: var(--g-900); font-weight: 600; }

.progression { display: flex; gap: var(--sp-1); margin-bottom: var(--sp-10); }
.progression span { flex: 1; height: 4px; background: var(--border-subtle); }
.progression span.is-active, .progression span.is-done { background: var(--i-800); }

.alerte {
  padding: var(--sp-4);
  border: 1px solid;
  margin-bottom: var(--sp-6);
  font-size: var(--fs-small);
}
.alerte--info { background: var(--surface-white); border-color: var(--border-subtle); color: var(--g-700); }
.alerte--erreur { background: var(--err-bg); border-color: var(--err); color: var(--err-ink); }
.alerte--succes { background: var(--ok-bg); border-color: var(--i-800); color: var(--ok-ink); }

.form-etat-envoi { display: none; align-items: center; gap: var(--sp-3); margin-top: var(--sp-4); font-size: var(--fs-small); color: var(--g-700); }

/* ---------- 13. Contact, coordonnees ---------- */

.coord-list { list-style: none; padding: 0; margin: 0 0 var(--sp-6); }
.coord-list li { display: flex; gap: var(--sp-3); align-items: flex-start; margin-bottom: var(--sp-4); }
.coord-list svg { width: 22px; height: 22px; flex-shrink: 0; color: var(--eyebrow); margin-top: 2px; }
.coord-list a { color: var(--g-900); font-weight: 600; text-decoration: none; }
.coord-list a:hover { color: var(--i-800); }

/* ---------- 14. Pied de page ---------- */

/* --- Bande de reperes, en tete du pied de page --- */
.footer-bande { background: var(--i-800); }
.footer-bande .container {
  display: grid;
  gap: var(--sp-6) var(--sp-6);
  grid-template-columns: 1fr;
  padding-block: 3.5rem;
}
@media (min-width: 640px) { .footer-bande .container { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .footer-bande .container { grid-template-columns: repeat(4, 1fr); } }
.footer-bande .container > * { min-width: 0; }
.repere__titre {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  color: #fff;
  font-size: 1.125rem;
  font-weight: 500;
  line-height: 1.55;
  letter-spacing: -0.02em;
  margin: 0 0 var(--sp-3);
}
/* Dimensions explicites en secours : un SVG sans largeur prend celle de son
   conteneur. Le defaut a deja produit des icones de 290 px sur ce site. */
.repere__titre svg { width: 24px; height: 24px; flex-shrink: 0; }
.repere__texte {
  color: rgba(255,255,255,.56);
  font-size: var(--fs-small);
  line-height: 1.7;
  max-width: 34ch;
  margin: 0;
}

/* --- Photographie du bloc d'appel a l'action --- */
.footer-cta__grille { display: grid; gap: var(--sp-10); align-items: center; }
@media (min-width: 900px) {
  .footer-cta__grille { grid-template-columns: 1fr 1fr; gap: var(--sp-16); }
}
.footer-cta__grille > * { min-width: 0; }
.footer-cta__photo { margin: 0; }
.footer-cta__photo img { display: block; width: 100%; height: auto; }

/* Grammaire reprise du template de reference, mesuree au navigateur et non
   decrite : intitules de colonne en 18 px / 500 en blanc plein (et non en
   petites capitales de 12 px), liens en 14 px / 400 a 72 % de blanc, rythme
   vertical de 36 px entre deux liens, bloc de marque a gauche et colonnes de
   liens a droite. L'ancien pied de page tenait dans 630 px de haut, colonnes
   serrees ; celui-ci respire, ce qui etait tout l'ecart avec le modele. */

/* Fond du bas de page : --grad-footer, soit --surface-noir (#0F0F0F). C'est la
   seule surface sombre que le gabarit de reference ne fait pas en vert, et le
   releve de sa palette le confirme (1,6 M px2 de quasi-noir, toutes les autres
   sections sombres en #1E3325). Le bloc d'appel a l'action final herite du meme
   fond : dans le modele, les deux ne font qu'un aplat continu. */
.site-footer { background: var(--grad-footer); color: rgba(255,255,255,.72); }

/* --- Appel a l'action final --- */
.footer-cta { border-bottom: 1px solid var(--border-inverse); }
.footer-cta .container { padding-block: clamp(3.5rem, 6vw, 6rem); }
.footer-cta .eyebrow { color: rgba(255,255,255,.72); margin-bottom: var(--sp-6); }
.footer-cta h2 {
  color: #fff;
  /* Le palier haut doit etre ATTEINT a 1440 px, pas seulement declare :
     l'ancienne pente donnait 53,28 px la ou le modele est a 56. */
  font-size: clamp(2rem, 1.4rem + 3vw, 3.5rem);
  /* Graisse 600, comme le titre de premier ecran : ce sont les deux seuls
     titres que le modele met en 600. La regle generique "h2 { 500 }" ne doit
     pas s'appliquer ici. */
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.03em;
  max-width: 18ch;
  margin: 0 0 var(--sp-6);
}
.footer-cta__lead {
  color: rgba(255,255,255,.6);
  font-size: var(--fs-lead);
  max-width: 52ch;
  margin: 0 0 var(--sp-10);
}
.footer-cta .cluster { margin: 0; }

/* --- Marque et colonnes de liens --- */
.footer-top { padding-block: clamp(3.5rem, 6vw, 5.5rem) clamp(2.5rem, 4vw, 4rem); }
.footer-cols {
  display: grid;
  gap: var(--sp-10);
  grid-template-columns: 1fr;
}
@media (min-width: 640px) { .footer-cols { grid-template-columns: repeat(2, 1fr); } }
/* Le bloc de marque prend une colonne et demie : c'est le rapport du modele
   entre le bloc de marque et chacune des deux colonnes de liens. */
@media (min-width: 1024px) {
  .footer-cols { grid-template-columns: 1.5fr 1fr 1fr; gap: var(--sp-16); }
}
.footer-cols > * { min-width: 0; }

.footer-logo {
  color: #fff;
  font-family: var(--font-display);
  /* Le modele pose le nom de marque a 24 px, mais precede d'un symbole ; sans
     symbole, 24 px ne se distinguait plus des intitules de colonne a 18 px. */
  font-size: 1.75rem;
  font-weight: var(--titre-graisse);
  letter-spacing: var(--ls-titre);
  line-height: 1.2;
  display: inline-block;
  margin-bottom: var(--sp-6);
  text-decoration: none;
}
.footer-col--marque p {
  color: rgba(255,255,255,.6);
  font-size: var(--fs-small);
  line-height: var(--lh-body);
  max-width: 42ch;
  margin: 0 0 var(--sp-6);
}
.footer-adresse {
  font-style: normal;
  font-size: var(--fs-small);
  line-height: 2;
  color: rgba(255,255,255,.72);
}
.footer-adresse a { color: rgba(255,255,255,.72); text-decoration: none; }
.footer-adresse a:hover { color: #fff; }

.footer-col h2 {
  color: #fff;
  font-family: var(--font-body);
  font-size: 1.125rem;
  font-weight: 500;
  line-height: 1.55;
  letter-spacing: -0.02em;
  text-transform: none;
  margin: 0 0 var(--sp-6);
}
.footer-col ul { list-style: none; padding: 0; margin: 0; }
.footer-col li { margin: 0 0 var(--sp-3); }
.footer-col li:last-child { margin-bottom: 0; }
/* Le nom de marque est un lien, et il vit dans une .footer-col : sans
   l'exclusion, ".footer-col a" (0-2-0) ecrasait ".footer-logo" (0-1-0) et le
   nom s'affichait a 14 px, plus petit que les intitules de colonne a 18 px.
   Meme piege de specificite que celui qui avait rendu le credit d'agence
   illisible : ici encore, la regle la plus generale gagnait. */
.footer-col a:not(.footer-logo) {
  color: rgba(255,255,255,.72);
  text-decoration: none;
  font-size: var(--fs-small);
  line-height: 1.7;
}
.footer-col a:not(.footer-logo):hover { color: #fff; }
.footer-col a[aria-current="page"] { color: #fff; }

.footer-badge {
  display: inline-block;
  border: 1px solid var(--border-inverse);
  color: rgba(255,255,255,.72);
  font-size: var(--fs-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  padding: var(--sp-2) var(--sp-3);
  margin-top: var(--sp-6);
}

/* --- Filet et ligne de bas de page --- */
.footer-bottom {
  border-top: 1px solid var(--border-inverse);
  padding-block: var(--sp-6);
}
.footer-bottom .container {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3) var(--sp-6);
  align-items: center;
  justify-content: space-between;
  font-size: var(--fs-small);
}
.footer-copyright { color: rgba(255,255,255,.5); margin: 0; }
.footer-legal {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3) var(--sp-6);
  list-style: none;
  padding: 0;
  margin: 0;
}
.footer-legal a { color: rgba(255,255,255,.72); text-decoration: none; }
.footer-legal a:hover { color: #fff; }
.footer-credit { color: rgba(255,255,255,.72); margin: 0; }
.footer-credit a { color: #fff; font-weight: 500; }
.footer-credit a:hover { color: #fff; }

/* Boutons de navigation du formulaire multi-etapes.
   "Etape suivante" venait coller la derniere case a cocher du groupe qui le
   precede : rien ne separait le choix de l'action, et les deux se lisaient
   comme un seul bloc. On degage le bouton et on le detache par un filet. */
/* Cible les boutons par leur attribut de donnees plutot que par l'identifiant
   du formulaire : il y en a deux sur le site, #form-devis et #form-urgence,
   et un selecteur nomme aurait laisse le second sans correction. */
form fieldset > p:has(> [data-suivant]),
form fieldset > p:has(> [data-precedent]),
form fieldset > p.cluster:has([data-suivant]) {
  margin-top: var(--sp-8);
  padding-top: var(--sp-6);
  border-top: 1px solid var(--border-subtle);
}

/* ---------- 15. FAQ ---------- */

.faq-item { border-bottom: 1px solid var(--border-subtle); padding-block: var(--sp-4); }
.faq-item summary {
  cursor: pointer;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--fs-lead);
  color: var(--i-950);
  list-style: none;
  display: flex;
  justify-content: space-between;
  gap: var(--sp-4);
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after { content: "+"; font-size: 1.5em; line-height: 1; color: var(--eyebrow); }
.faq-item[open] summary::after { content: "\2212"; }
.faq-item p { margin-top: var(--sp-3); }

/* ---------- 16. Etapes de methode ---------- */

.etapes { counter-reset: etape; list-style: none; padding: 0; margin: 0; display: grid; gap: var(--sp-6); }
@media (min-width: 768px) { .etapes { grid-template-columns: repeat(2, 1fr); } }
/* Trois colonnes et non quatre : toutes les pages qui emploient ce composant
   comptent cinq ou six etapes. Sur quatre colonnes, cela donnait une rangee de
   quatre puis une rangee orpheline de deux ou d'une seule, qui se lisait comme
   une erreur de mise en page. Sur trois, six etapes forment deux rangees
   pleines, et cinq etapes donnent trois puis deux, ce qui reste equilibre. */
@media (min-width: 1024px) { .etapes { grid-template-columns: repeat(3, 1fr); } }
.etapes li { border-top: 3px solid var(--i-800); padding-top: var(--sp-3); }
.etapes li::before {
  counter-increment: etape;
  content: counter(etape, decimal-leading-zero);
  display: block;
  font-family: var(--font-display);
  font-size: var(--fs-lead);
  color: var(--eyebrow);
  margin-bottom: var(--sp-2);
}

/* ---------- 17. Page 404 et pages courtes ---------- */

.page-erreur { padding-block: var(--sp-24); text-align: center; }
.page-erreur h1 { font-size: var(--fs-display); }

/* ---------- 18. (retire) ----------
   Le bandeau de consentement cookies a ete retire (decision QA du 4 septembre
   2026, voir main.js section 6) : le site ne depose aucun cookie de suivi et
   ne charge aucun script tiers. Ses styles .bandeau-cookies ont ete supprimes
   ici comme code mort (aucun HTML ne les referme plus). S'il redevient
   necessaire le jour ou un script tiers est active, le reconstruire a neuf
   plutot que de restaurer cette ancienne regle. */

/* ---------- 19. Sections generiques de contenu ---------- */

.section-head { max-width: 62ch; margin-bottom: var(--sp-10); }
.section--inverse .section-head p,
.hero p { color: var(--i-200); }

.maillage {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-4);
  padding: var(--sp-6);
  border: 1px solid var(--border-subtle);
  background: var(--surface-cream);
  align-items: center;
  justify-content: space-between;
}

.bandeau-cta-final {
  background: var(--i-800);
  color: #fff;
  padding-block: var(--sp-16);
  text-align: center;
}
.bandeau-cta-final h2 { color: #fff; }
.bandeau-cta-final .cluster { justify-content: center; }

/* ---------- 20. Utilitaires responsives ---------- */

.mobile-only { display: block; }
.desktop-only { display: none; }
@media (min-width: 1024px) {
  .mobile-only { display: none; }
  .desktop-only { display: block; }
}

/* ===========================================================================
   CSS STRUCTUREL POUR LE CONTENU SANS CLASSE.
   Les fragments de /_projet/contenus/pages/ sont livres volontairement sans
   classe CSS ("le design system est applique par le frontend"). Plutot que
   d'editer le texte des redacteurs, on style leur HTML semantique par sa
   position dans l'arbre (enfants directs de #contenu, de <article>, de
   <section id="...">) et par un identifiant de gabarit pose sur <body> a la
   generation (voir generate_site.py). Aucune valeur codee en dur : tokens
   uniquement.
   =========================================================================== */

body { overflow-x: hidden; }

#contenu { display: block; }

/* --- Conteneur générique pour tout bloc de premier niveau non hero --- */
#contenu > section,
#contenu > article > header,
#contenu > article > section,
#contenu > h1,
#contenu > p,
#contenu > dl,
#contenu > ol,
#contenu > nav[aria-label="Filtrer les réalisations par corps de métier"],
#contenu > nav[aria-label="Pagination des réalisations"] {
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--marge-page);
  box-sizing: border-box;
}
/* Exclusion ajoutee le 6 septembre 2026. Ce selecteur porte un identifiant
   (specificite 1-0-1) : il ecrasait donc silencieusement le padding-block de
   .hero (.sp-24), de .hero--court (.sp-16) et de .bandeau-cta-final (.sp-16),
   qui ne sont que des classes (0-1-0). Les sections qui portent une classe de
   mise en page gerent elles-memes leur marge verticale et leur filet. Voir la
   section 21.1 pour le meme defaut sur la largeur maximale. */
#contenu > section:not(.section):not(.hero):not(.bandeau-cta-final):not(.bande-photos),
#contenu > article > section:not(.section):not(.hero):not(.bandeau-cta-final) {
  padding-block: var(--section-y);
  border-top: 1px solid var(--rule);
}
#contenu > section:first-of-type,
#contenu > article > header {
  border-top: none;
}
#contenu > h1:first-child { padding-top: var(--sp-16); }
#contenu > h1:first-child + p { padding-inline: var(--marge-page); max-width: var(--maxw); margin-inline: auto; }

/* --- Heros en inversion monolithique : pleine largeur, vert foret ---
   Portees uniquement aux gabarits qui en ont un (accueil, metiers, depannage,
   aides, isolation). Les autres pages (entreprise, contact, realisations,
   zone d'intervention, legal) restent en h1 simple sur fond clair. */

.tpl-accueil #contenu > section:first-of-type,
.tpl-metier #contenu > article > header,
.tpl-depannage #contenu > section:first-of-type,
.tpl-aides #contenu > section:first-of-type,
.tpl-isolation #contenu > section:first-of-type {
  max-width: none;
  margin-inline: 0;
  padding-inline: 0;
  padding-block: var(--sp-24);
  background: var(--i-800);
  color: #fff;
  border-top: none;
}
.tpl-accueil #contenu > section:first-of-type > *,
.tpl-metier #contenu > article > header > *,
.tpl-depannage #contenu > section:first-of-type > *,
.tpl-aides #contenu > section:first-of-type > *,
.tpl-isolation #contenu > section:first-of-type > * {
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--marge-page);
  box-sizing: border-box;
}
.tpl-accueil #contenu > section:first-of-type h1,
.tpl-metier #contenu > article > header h1,
.tpl-depannage #contenu > section:first-of-type h1,
.tpl-aides #contenu > section:first-of-type h1,
.tpl-isolation #contenu > section:first-of-type h1 {
  color: #fff;
  font-size: var(--fs-display);
  max-width: 22ch;
}
.tpl-accueil #contenu > section:first-of-type p,
.tpl-metier #contenu > article > header p,
.tpl-depannage #contenu > section:first-of-type p,
.tpl-aides #contenu > section:first-of-type p,
.tpl-isolation #contenu > section:first-of-type p {
  color: var(--i-200);
  font-size: var(--fs-lead);
  max-width: 62ch;
}
.tpl-accueil #contenu > section:first-of-type ul,
.tpl-depannage #contenu > section:first-of-type ul {
  list-style: none;
  padding: 0;
  margin: var(--sp-6) 0 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
}
.tpl-accueil #contenu > section:first-of-type ul li,
.tpl-depannage #contenu > section:first-of-type ul li {
  border: 1px solid var(--border-inverse);
  padding: var(--sp-2) var(--sp-4);
  font-size: var(--fs-small);
  color: #fff;
  font-weight: 600;
  margin-bottom: 0;
}

/* Hero pleine hauteur mobile pour l'accueil et le depannage (pages ou le
   premier ecran doit se comprendre sans defiler, voir ux-architecture.md). */
.tpl-accueil #contenu > section:first-of-type,
.tpl-depannage #contenu > section:first-of-type {
  min-height: 100svh;
  display: flex;
  align-items: center;
}
.tpl-accueil #contenu > section:first-of-type > .hero-inner,
.tpl-depannage #contenu > section:first-of-type > .hero-inner { width: 100%; }
@media (min-width: 1024px) {
  .tpl-accueil #contenu > section:first-of-type,
  .tpl-depannage #contenu > section:first-of-type {
    min-height: auto;
    display: block;
  }
}

/* --- Bandeau urgence de l'accueil : 2e section du fragment, avant #metiers --- */
.tpl-accueil #contenu > section:nth-of-type(2) {
  max-width: none;
  margin-inline: 0;
  padding-inline: 0;
  background: var(--a-600);
  color: #fff;
  border-top: none;
}
.tpl-accueil #contenu > section:nth-of-type(2) > * {
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--marge-page);
}
.tpl-accueil #contenu > section:nth-of-type(2) h2,
.tpl-accueil #contenu > section:nth-of-type(2) p { color: #fff; }
.tpl-accueil #contenu > section:nth-of-type(2) { padding-block: var(--sp-10); }

/* --- Sections identifiees, communes aux pages metier --- */
#faq h3 {
  margin-top: var(--sp-10);
  padding-top: var(--sp-6);
  border-top: 1px solid var(--rule);
}
#faq h3:first-of-type { margin-top: 0; padding-top: 0; border-top: none; }
#faq p { max-width: var(--measure); }

/* M3 (audit visuel) : dans les sections "glossaire" des quatre pages metier
   (#prestations, #materiaux, #bati-ancien, #techniques), des h3 et des p
   s'enchainent en pleine largeur du conteneur (1177 px), parfois entrecoupes
   d'un ".grid grid--2" en demi-colonne. La regle generique "p { max-width:
   var(--measure) }" (66ch, environ 700 px) plafonnait les paragraphes mais pas
   les h3 : le titre occupait toute la largeur, le texte qui suivait sautait a
   700 px, et la bande droite du bloc restait vide sur toute la hauteur de la
   section.

   Cette coherence-la se payait cher : a 1440 px, ces paragraphes couraient sur
   1165 px, soit environ 160 signes par ligne. Le modele de reference ne
   depasse jamais une soixantaine de signes, et l'oeil perd la ligne suivante
   bien avant 160. On rend donc la mesure de lecture, et on aligne le titre h3
   dessus : le bloc reste coherent, sans bande vide a droite d'un titre qui
   traverserait la page, et le texte redevient lisible. */
#prestations > .container > p,
#materiaux > .container > p,
#bati-ancien > .container > p,
#techniques > .container > p,
#prestations > .container > h3,
#materiaux > .container > h3,
#bati-ancien > .container > h3,
#techniques > .container > h3,
#prestations > .container > ul,
#materiaux > .container > ul,
#bati-ancien > .container > ul,
#techniques > .container > ul {
  max-width: var(--measure);
}

/* M1 (audit visuel) : #methode ol portait sa propre grille (2 colonnes) et son
   propre compteur CSS sur "#methode li h3::before", en plus de ceux deja
   fournis par ".etapes" (section 16 : liste, grille responsive a 3 colonnes,
   filet superieur, compteur "01/02/..."). Les deux compteurs s'incrementaient
   chacun de leur cote sur le meme <ol class="etapes">, d'ou le doublon visuel
   ("01" seul puis "02 Prise de contact"), et les deux grilles se contredisaient
   (3 colonnes contre 2). La page isolation, qui n'utilise que ".etapes" sans
   cet identifiant, numerotait juste : on retire donc la grille et le compteur
   redondants d'ici, ".etapes" reste la seule source de verite pour les quatre
   pages metier qui partagent ce gabarit. */

#garanties dl, #devis dl { margin-top: var(--sp-6); }
#garanties dt, #devis dt { font-family: var(--font-display); font-size: var(--fs-lead); color: var(--i-950); }

/* M4 (audit visuel) : cette regle plafonnait ".liste-grille" (2 ou 3 colonnes,
   voir section 21.11) a 700 px dans un conteneur de 1177 px, ce qui ecrasait
   ses colonnes a 190 px (cesures, rangee orpheline). La preuve que c'etait un
   defaut et non une intention : sur maconnerie, la liste "Fissures" (section
   #fissures, non couverte par ce selecteur) s'affiche en pleine largeur et
   rend tres bien, quand "Ce qui fait varier un devis" (#devis, couverte)
   etait ecrasee a cote. ".liste-grille" gere deja ses propres colonnes
   (section 21.11) : elle n'a besoin d'aucun plafond ici, retire. */
#signes-alerte li strong, #devis li strong { color: var(--g-900); }

/* --- Coordonnees (page contact) : dl transforme en liste iconee --- */
section[aria-label="Coordonnées d'Alves Frères"] dl {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  margin: 0 0 var(--sp-6);
  max-width: none;
}
section[aria-label="Coordonnées d'Alves Frères"] dt { font-size: var(--fs-label); text-transform: uppercase; letter-spacing: var(--ls-label); color: var(--g-500); margin-top: 0; }
section[aria-label="Coordonnées d'Alves Frères"] dd { font-size: var(--fs-lead); font-weight: 600; color: var(--g-900); margin: 0; }

/* --- Filtres de realisations, sur le vrai HTML livre (ul de liens) --- */
nav[aria-label="Filtrer les réalisations par corps de métier"] ul {
  list-style: none;
  padding: 0;
  margin: var(--sp-4) 0 var(--sp-10);
  display: flex;
  flex-wrap: nowrap;
  overflow-x: auto;
  gap: var(--sp-2);
}
@media (min-width: 768px) { nav[aria-label="Filtrer les réalisations par corps de métier"] ul { flex-wrap: wrap; overflow: visible; } }
nav[aria-label="Filtrer les réalisations par corps de métier"] li { margin: 0; }
nav[aria-label="Filtrer les réalisations par corps de métier"] a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 var(--sp-4);
  border: 1px solid var(--border-subtle);
  color: var(--g-700);
  text-decoration: none;
  font-size: var(--fs-small);
  font-weight: 600;
  white-space: nowrap;
}
nav[aria-label="Filtrer les réalisations par corps de métier"] a:hover { border-color: var(--i-800); color: var(--i-900); }
nav[aria-label="Filtrer les réalisations par corps de métier"] a[aria-current="true"] { background: var(--i-800); border-color: var(--i-800); color: #fff; }
nav[aria-label="Filtrer les réalisations par corps de métier"] h2 { font-size: var(--fs-label); text-transform: uppercase; letter-spacing: var(--ls-label); color: var(--g-500); font-family: var(--font-body); font-weight: 600; }

nav[aria-label="Pagination des réalisations"] ul { list-style: none; display: flex; gap: var(--sp-2); padding: 0; margin: var(--sp-10) 0; }
nav[aria-label="Pagination des réalisations"] a { display: inline-flex; align-items: center; justify-content: center; min-width: 44px; min-height: 44px; border: 1px solid var(--border-subtle); text-decoration: none; color: var(--g-700); }
nav[aria-label="Pagination des réalisations"] [aria-current="page"] { background: var(--i-800); color: #fff; border-color: var(--i-800); }

article[aria-label], section[aria-label="Liste des chantiers"] article {
  border: 1px solid var(--border-subtle);
  padding: var(--sp-6);
  margin-bottom: var(--sp-6);
}

/* --- Formulaire de devis, sur les gabarits reellement livres (etapes en <p>) --- */
#formulaire-devis fieldset { border: none; padding: 0; margin: 0 0 var(--sp-10); }
#formulaire-devis legend {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--fs-h3);
  color: var(--i-950);
  padding: 0;
  margin-bottom: var(--sp-2);
  width: 100%;
}
#formulaire-devis fieldset > p:first-of-type { color: var(--g-500); font-size: var(--fs-small); margin-bottom: var(--sp-6); }
#formulaire-devis ul { list-style: none; padding: 0; margin: 0 0 var(--sp-6); display: flex; flex-direction: column; gap: var(--sp-3); }
#formulaire-devis ul li { display: flex; align-items: flex-start; gap: var(--sp-3); margin: 0; }
#formulaire-devis input[type="checkbox"], #formulaire-devis input[type="radio"] { margin-top: 4px; width: 20px; height: 20px; flex-shrink: 0; }
#formulaire-devis fieldset > p { margin-bottom: var(--sp-6); }
#formulaire-devis fieldset > p > label { display: block; font-weight: 600; color: var(--g-900); font-size: var(--fs-small); margin-bottom: var(--sp-2); }
#formulaire-devis fieldset > p > span { display: block; font-size: var(--fs-small); color: var(--g-500); margin-bottom: var(--sp-2); }
#formulaire-devis fieldset > p > span[role="alert"] { color: var(--err-ink); font-weight: 600; }
#formulaire-devis input[type="text"],
#formulaire-devis input[type="tel"],
#formulaire-devis input[type="email"],
#formulaire-devis input[type="file"],
#formulaire-devis textarea {
  width: 100%;
  min-height: 44px;
  padding: var(--sp-3);
  background: var(--field-bg);
  border: 1px solid var(--field-border);
  font: inherit;
  color: var(--g-900);
  box-sizing: border-box;
}
#formulaire-devis textarea { min-height: 120px; resize: vertical; }
#formulaire-devis input:focus-visible, #formulaire-devis textarea:focus-visible {
  outline: 2px solid var(--i-950);
  outline-offset: 1px;
}
#formulaire-devis button[type="submit"] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 0.875rem 1.5rem;
  background: var(--i-800);
  color: #fff;
  border: none;
  font-weight: 600;
  font-size: var(--fs-body);
  cursor: pointer;
}
#formulaire-devis button[type="submit"]:hover { background: var(--i-950); }
#formulaire-devis button[type="submit"]:disabled { opacity: .6; cursor: wait; }

[role="alert"][hidden] { display: none !important; }
div[role="alert"]:not([hidden]) {
  padding: var(--sp-4) var(--sp-6);
  border: 1px solid var(--err);
  background: var(--err-bg);
  color: var(--err-ink);
  margin-bottom: var(--sp-6);
  max-width: var(--maxw);
  margin-inline: auto;
}
div[role="alert"]:not([hidden]) h3 { color: var(--err-ink); margin-bottom: var(--sp-2); }
div[role="alert"]:not([hidden]) a { color: var(--err-ink); text-decoration: underline; }

/* --- Liens d'action : le lien fleche (fond clair, couleur d'encre) ---
   M11 (audit visuel) : cette mise en forme reposait sur "p > a:only-child",
   qui ne regarde que les ELEMENTS freres (la specification CSS l'exige) et
   ignore les noeuds de texte. Un lien cite au milieu d'une phrase ("Le
   simulateur officiel mesaides.france-renov.gouv.fr redirige...") est donc
   lui aussi l'unique enfant ELEMENT de son <p>, et recevait la meme fleche
   qu'un vrai lien d'action ("En savoir plus"), au milieu du texte. C'etait le
   defaut le plus diffus de l'audit (au moins neuf occurrences citees, sur
   sept gabarits differents). Aucune regle purement structurelle ne peut
   distinguer les deux cas : on marque donc explicitement, dans le HTML, les
   seuls liens qui sont reellement des liens d'action isoles avec la classe
   ".lien-fleche" (utilisee ici uniquement par le credit d'agence en pied de
   page). Tout lien cite en pleine phrase redevient un lien de texte ordinaire
   ("a { color: var(--i-900) }", deja lisible sur fond clair comme sur aplat
   vert via la regle contextuelle ".hero a:not(.btn)" etc. plus bas). --- */
p > a.lien-fleche {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-weight: 600;
  color: var(--i-950);
  text-decoration: none;
}
p > a.lien-fleche:hover { color: var(--i-800); }
p > a.lien-fleche:not([href^="tel:"]):not([href^="mailto:"])::after {
  content: "\2192";
  transition: transform .15s var(--ease-out);
}
p > a.lien-fleche:hover::after { transform: translateX(4px); }

/* Le meme lien fleche, mais pose sur un aplat vert (aucun usage actuel, la
   regle est conservee pour le jour ou ".lien-fleche" apparaitrait dans un
   bloc inverse : sans elle, le lien heriterait de "a { color: var(--i-900) }",
   soit 1,17:1 sur le vert foret). */
.hero p > a.lien-fleche,
.bloc-inverse p > a.lien-fleche,
.section--inverse p > a.lien-fleche,
.bandeau-cta-final p > a.lien-fleche { color: var(--n-0); }
.hero p > a.lien-fleche:hover,
.bloc-inverse p > a.lien-fleche:hover,
.section--inverse p > a.lien-fleche:hover,
.bandeau-cta-final p > a.lien-fleche:hover { color: var(--i-200); }

/* Credit d'agence en pied de page : seul usage reel de ".lien-fleche" a ce
   jour. Le combiner au contexte ".footer-credit"/".site-footer" est ce qui
   maintient le credit et son eventuel voisinage lisibles sur le vert le plus
   sombre (--i-950), memes valeurs qu'avant la correction M11. */
.site-footer p > a.lien-fleche,
.footer-credit p > a.lien-fleche,
.footer-credit > a.lien-fleche,
.footer-col p > a.lien-fleche { color: var(--i-200); }
.site-footer p > a.lien-fleche:hover,
.footer-credit > a.lien-fleche:hover,
.footer-col p > a.lien-fleche:hover { color: #fff; }

/* Intitules de garantie sur aplat vert. "#garanties dt" est un identifiant
   (1-0-1) et ecrasait ".section--inverse dt" (0-1-1) : "Un an", "Deux ans" et
   "Dix ans" s'affichaient a 1,29 contre 1 sur le vert foret. On reprend la
   main avec un selecteur qui combine l'identifiant et le contexte. */
.section--inverse #garanties dt, .bloc-inverse #garanties dt,
#garanties.section--inverse dt, #garanties.bloc-inverse dt,
.section--inverse #devis dt, .bloc-inverse #devis dt,
#devis.section--inverse dt, #devis.bloc-inverse dt { color: var(--i-200); }

/* Listes du pied de page. "ul, ol { color: var(--g-700) }" est une valeur
   brute qui survivait au fond vert : l'adresse s'affichait a 1,86 contre 1,
   alors que le numero juste en dessous etait a 10,27. */
.site-footer li, .site-footer ul, .site-footer ol { color: var(--i-300); }
.site-footer .coord-list svg { color: var(--i-300); }
.tpl-accueil #contenu > section:first-of-type p > a.lien-fleche,
.tpl-metier #contenu > article > header p > a.lien-fleche,
.tpl-depannage #contenu > section:first-of-type p > a.lien-fleche,
.tpl-aides #contenu > section:first-of-type p > a.lien-fleche,
.tpl-isolation #contenu > section:first-of-type p > a.lien-fleche,
.tpl-accueil #contenu > section:nth-of-type(2) p > a.lien-fleche {
  color: #fff;
}

/* CTA primaire "Demander un devis..." : converti en bouton plein a la
   generation (classes .btn .btn--primary posees par generate_site.py). */
.btn.btn--primary .btn__arrow, .btn.btn--primary-inverse .btn__arrow { margin-left: var(--sp-1); }

/* Liens telephone : accent tuile, icone en prefixe, jamais un simple lien
   texte perdu dans un paragraphe. */
a.tel-link {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-weight: 700;
  color: var(--a-ink);
  text-decoration: none;
}
a.tel-link:hover { color: var(--a-600); text-decoration: underline; }
a.tel-link svg { width: 18px; height: 18px; flex-shrink: 0; }
.tpl-accueil #contenu > section:first-of-type a.tel-link,
.tpl-metier #contenu > article > header a.tel-link,
.tpl-depannage #contenu > section:first-of-type a.tel-link,
.tpl-aides #contenu > section:first-of-type a.tel-link,
.tpl-isolation #contenu > section:first-of-type a.tel-link,
.tpl-accueil #contenu > section:nth-of-type(2) a.tel-link {
  color: #fff;
  font-size: var(--fs-lead);
}
.tpl-depannage #contenu > section:first-of-type a.tel-link {
  font-size: var(--fs-display);
  border-bottom: 2px solid var(--a-500);
}

/* --- Encart d'urgence inline (etape 2 du formulaire) --- */
#formulaire-devis fieldset div:not(.piege-anti-spam):not([hidden]) {
  border: 1px solid var(--a-600);
  background: var(--a-50);
  padding: var(--sp-4);
  margin-top: var(--sp-4);
}

/* --- Recapitulatif etapes 1-2 dans l'etape 3 --- */
#formulaire-devis fieldset div h3 { font-size: var(--fs-lead); margin-bottom: var(--sp-2); }
#formulaire-devis fieldset div ul { background: var(--surface-cream); padding: var(--sp-4) var(--sp-6); border: 1px solid var(--border-subtle); }

/* --- Bloc d'etat d'envoi (ajoute par le gabarit, pas par le contenu) --- */
.form-etat-envoi {
  display: none;
  align-items: center;
  gap: var(--sp-3);
  margin-top: var(--sp-4);
  font-size: var(--fs-small);
  color: var(--g-700);
}

/* --- Page 404 --- */
.tpl-404 #contenu { text-align: center; padding-block: var(--sp-24); }
.tpl-404 #contenu h1 { font-size: var(--fs-display); }

/* --- Pages legales : lecture longue, colonne plus etroite --- */
/* Pages legales : le contenu est ecrit a plat sous #contenu, sans conteneur
   intermediaire. La regle generique plus haut n'enumere que h1, p, dl, ol et
   section : les h2, h3, ul, table et figure n'etaient donc ni centres ni
   marges, et venaient toucher le bord de la fenetre pendant que les
   paragraphes voisins restaient centres. Sur mobile, le "1." des titres
   touchait litteralement le bord de l'ecran. On applique ici la meme mise en
   page a TOUS les enfants directs, quel que soit leur nom de balise. */
.tpl-legal #contenu > * {
  max-width: var(--maxw-narrow);
  margin-inline: auto;
  padding-inline: var(--marge-page);
}
.tpl-legal #contenu > .breadcrumb { padding-inline: 0; }
.tpl-legal #contenu > h1:first-child { padding-top: var(--sp-16); }

/* Echelle propre aux pages utilitaires. Le reste du site suit l'echelle du
   modele de reference, ou un h2 vaut 48 px ; ici les h2 sont les douze
   rubriques numerotees d'un texte juridique, lues a la suite, et 48 px contre
   un corps de 16 px donnait un sommaire geant plutot qu'un document. Ces pages
   sont en noindex et n'ont pas de role de vitrine. */
.tpl-legal #contenu h2 { font-size: clamp(1.375rem, 1.15rem + 0.7vw, 1.75rem); }
.tpl-legal #contenu h3 { font-size: clamp(1.125rem, 1.05rem + 0.25vw, 1.25rem); }

/* --- Section "Nos metiers" de l'accueil : cinq metiers numerotes en liste
   sobre, filets de separation plutot qu'une grille de cartes a wrapper
   manquant (aucune classe n'est posee dans le contenu redactionnel). --- */
.tpl-accueil #metiers h3 {
  border-top: 3px solid var(--i-800);
  padding-top: var(--sp-4);
  margin-top: var(--sp-10);
  font-size: var(--fs-h3);
}
.tpl-accueil #metiers h3:first-of-type { margin-top: var(--sp-6); }
.tpl-accueil #metiers > p:first-of-type { margin-bottom: var(--sp-10); }

/* --- Mini-formulaire de repli de la page depannage : volontairement
   secondaire, sous la ligne de flottaison (ux-architecture.md 3.3). --- */
.tpl-depannage #contenu form {
  border: 1px solid var(--border-subtle);
  background: var(--surface-cream);
  padding: var(--sp-6);
  max-width: 480px;
}
.tpl-depannage #contenu form p { margin-bottom: var(--sp-4); }
.tpl-depannage #contenu form label { display: block; font-weight: 600; font-size: var(--fs-small); margin-bottom: var(--sp-2); }
.tpl-depannage #contenu form input[type="text"],
.tpl-depannage #contenu form input[type="tel"],
.tpl-depannage #contenu form textarea {
  width: 100%;
  min-height: 44px;
  padding: var(--sp-3);
  border: 1px solid var(--field-border);
  background: var(--surface-white);
  font: inherit;
  box-sizing: border-box;
}
.tpl-depannage #contenu form input[type="checkbox"] { width: 20px; height: 20px; margin-right: var(--sp-2); }

/* ===========================================================================
   21. RYTHME VISUEL
   Ajoute le 6 septembre 2026, apres le constat client : "c'est bien, mais
   c'est que du texte, on dirait un blog". Le diagnostic n'est pas un exces de
   texte, c'est une absence de rythme : les aplats pleine largeur, qui sont
   l'atout principal de la direction "Architectural Precision", ne s'etendaient
   pas sur toute la largeur (voir 21.1), et plusieurs blocs verts portaient du texte gris fonce
   illisible (voir 21.2), ce qui ecrasait visuellement les chapitres.

   Regles de la direction respectees a la lettre : aplats pleins, angles
   droits, filets de 1 px, aucune ombre, aucun degrade, aucune animation
   decorative. Toutes les couleurs viennent des tokens de la zone generee.
   Toutes les combinaisons texte/fond employees ici figurent deja dans la
   cle "paires" de _build/themes.py, direction architectural-precision, a une
   exception documentee en 21.6 (texte blanc sur --a-600, pair ajoutee).
   =========================================================================== */

/* ---------- 21.1 Portee des aplats pleine largeur ----------
   Defaut corrige. La regle generique "#contenu > section" (bloc CSS
   STRUCTUREL plus haut) imposait a TOUTE section de premier niveau une
   largeur maximale de 1280 px et une marge interne. Or les gabarits livres
   posent deja une classe de mise en page sur la section (.hero, .section,
   .bandeau-cta-final) et un .container a l'interieur. Consequences mesurees
   avant correction :

   1. Aucun aplat ne prenait la pleine largeur. Le hero vert, les sections creme
      (.section--alt), le bloc inverse et le bandeau final s'arretaient a
      1280 px, centres dans du limestone. L'alternance de fonds, qui est le
      moyen principal de decouper la page en chapitres dans cette direction,
      etait donc invisible au-dela de 1280 px de large.
   2. La marge interne etait comptee deux fois (section + .container) : la
      colonne utile tombait de 1152 a 1024 px en desktop, et de 350 a 310 px
      en 390 px de large.

   La correction ne touche que les sections qui portent une classe de mise en
   page, donc qui gerent deja leur propre conteneur. Les sections sans classe
   (fragments rediges sans classe CSS, cf. bloc precedent) gardent le
   comportement generique. Elle vaut pour les 19 gabarits, pas seulement pour
   l'accueil. */
#contenu > section.hero,
#contenu > section.section,
#contenu > section.bande-photos,
#contenu > section.bandeau-cta-final,
#contenu > article > section.section {
  max-width: none;
  margin-inline: 0;
  padding-inline: 0;
}
#contenu > section.hero,
#contenu > section.bande-photos { border-top: none; }
#contenu > section.bande-photos { padding-block: 0; }

/* Meme defaut de double marge sur le fil d'Ariane : la regle d'attribut pose
   deja la largeur et la marge, et les gabarits ajoutent un .container. */
nav[aria-label="Fil d'Ariane"] > .container { padding-inline: 0; max-width: none; }

/* ---------- 21.2 Lisibilite sur aplat vert ----------
   Defaut corrige, et c'est le plus grave trouve sur la page. La regle de base
   "p { color: var(--g-700) }" ecrit une valeur BRUTE, pas un token
   contextuel. Elle survit donc a .bloc-inverse, qui ne remappe que des
   variables (--fg, --fg-soft...). Resultat : tout paragraphe pose sur un
   aplat vert et situe hors d'un .section-head s'affichait en #434843 sur
   #1E3325, soit 1,44:1 pour un minimum exige de 4,5:1. Concerne, avant
   correction : les deux paragraphes du bloc "L'entreprise" de l'accueil et
   les trois paragraphes du bandeau d'appel final, sur l'accueil comme sur
   les cinq pages metier.

   Le meme raisonnement que celui deja applique a .btn--secondary (section 5)
   est repris ici : la variante claire ne depend pas d'une classe que l'on
   peut oublier a l'integration, elle decoule du FOND. Les quatre selecteurs
   couvrent les quatre facons dont un aplat vert existe dans les gabarits.
   Ratios obtenus : --i-300 sur --i-800 = 7,96:1 ; --i-200 sur --i-800 =
   10,46:1 ; blanc sur --i-800 = 13,50:1. Toutes ces paires sont au
   catalogue. */
/* Premier etage de la correction : ces trois selecteurs sont, par
   construction, des aplats verts. On y remappe les tokens CONTEXTUELS que
   consomment les composants, exactement comme .bloc-inverse le fait dans la
   zone generee. Seuls les noms reellement utilises par le CSS ecrit a la main
   sont repris : dupliquer tout .bloc-inverse ici ferait deriver les deux
   listes au prochain changement de direction. */
.hero, .section--inverse, .bandeau-cta-final {
  --fg-titre: var(--n-0);
  --fg-soft: var(--i-300);
  --eyebrow: var(--i-200);
  --rule: var(--border-inverse);
  --card-alt: var(--i-950);
  --accent-rule: var(--a-500);
}

/* Second etage : les regles de base qui ecrivent une couleur BRUTE et que le
   remappage de tokens ne peut donc pas atteindre. */
.hero p, .hero li, .hero dd, .hero td, .hero th,
.bloc-inverse p, .bloc-inverse li, .bloc-inverse dd, .bloc-inverse td, .bloc-inverse th,
.section--inverse p, .section--inverse li, .section--inverse dd,
.bandeau-cta-final p, .bandeau-cta-final li, .bandeau-cta-final dd {
  color: var(--i-300);
}
.hero p.lead, .hero dt,
.bloc-inverse p.lead, .bloc-inverse dt,
.section--inverse p.lead, .section--inverse dt,
.bandeau-cta-final p.lead, .bandeau-cta-final dt {
  color: var(--i-200);
}
.hero h1, .hero h2, .hero h3, .hero h4,
.section--inverse h2, .section--inverse h3, .section--inverse h4,
.bandeau-cta-final h2, .bandeau-cta-final h3, .bandeau-cta-final h4 {
  color: var(--n-0);
}
/* Le libelle de section herite sinon de --eyebrow, qui vaut --i-550 hors
   .bloc-inverse : 2,08:1 sur le vert foret. */
.hero .eyebrow, .bandeau-cta-final .eyebrow { color: rgba(255,255,255,.56); }
/* Un lien nu sur aplat vert heriterait de "a { color: var(--i-900) }". */
.hero a:not(.btn), .bloc-inverse a:not(.btn),
.section--inverse a:not(.btn), .bandeau-cta-final a:not(.btn) {
  color: var(--n-0);
}
/* Le panneau de reassurance du hero de la page depannage ecrivait deja ses
   propres couleurs ; on preserve son blanc, que la regle ".hero dd"
   ci-dessus ferait autrement basculer en --i-300. Les deux passent (13,50:1
   et 7,96:1), mais changer un gabarit hors perimetre n'est pas le sujet. */
.hero-reassurance dd { color: var(--n-0); }
/* Suite directe du commentaire de la section 5 : le bandeau d'appel final est
   TOUJOURS un aplat vert, la variante claire du bouton secondaire y est donc
   structurellement obligatoire. Sur l'accueil, ce bandeau ne portait pas
   .bloc-inverse et le bouton "05 63 66 17 89" s'affichait a 1,29:1. */
.bandeau-cta-final .btn--secondary,
.bandeau-cta-final .btn--secondary:link,
.bandeau-cta-final .btn--secondary:visited {
  color: var(--n-0);
  border-color: var(--n-0);
}
.bandeau-cta-final .btn--secondary:hover { background: var(--n-0); color: var(--i-950); }

/* ---------- 21.3 Hero de l'accueil ----------
   Trois differences avec .hero standard : pas de hauteur d'ecran imposee (le
   100svh reportait tout le contenu sous la ligne de flottaison sans rien
   montrer), composition editoriale en deux colonnes (titre a gauche, promesse
   et actions a droite, alignes sur la meme ligne de base), et fermeture par
   une bande photographique collee au bas de l'aplat vert (21.4). */
.hero--accueil {
  min-height: auto;
  display: block;
  padding-block: clamp(2.5rem, 5vw, 4.5rem) 0;
}
.hero--accueil .hero-grid { gap: var(--sp-6); }
@media (min-width: 1024px) {
  .hero--accueil .hero-grid {
    grid-template-columns: 1.15fr 1fr;
    align-items: end;
    gap: var(--sp-16);
  }
}
.hero--accueil h1 { margin-bottom: 0; }
.hero--accueil .cluster { margin-top: var(--sp-6); }

/* ---------- 21.4 Bande photographique pleine largeur ----------
   Reponse a la contrainte materielle : les meilleures sources plafonnent a
   1024 px de large et la plupart sont carrees en 570 px. Une image unique en
   pleine largeur serait donc floue. Une bande de trois vignettes en pleine
   largeur ne l'est pas : a 1440 px de viewport chaque tuile fait 480 px, soit
   la resolution native des sources ; a 1920 px elle fait 640 px, soit un
   agrandissement de 1,13x, invisible sur une photographie.

   Les filets entre tuiles sont des gouttieres de 1 px qui laissent voir le
   fond du bloc porteur : sur le hero, ce fond est le vert foret. C'est le
   meme vocabulaire que la grille explicite du reste de la direction. */
/* Cinq colonnes et non trois. Raison mesuree, pas esthetique : les photos de
   chantier recuperees du site actuel font 570 px de large. Sur trois colonnes
   elles s'affichent a 426 px, soit 0,67 pixel natif par pixel ecran sur un
   ecran a double densite : visiblement floues. Sur cinq colonnes elles
   tombent a 255 px, soit une densite de 1,12, et redeviennent nettes. Le
   site actuel les affichait a 20 pour cent de largeur, c'est-a-dire petites,
   et c'est precisement pour cela qu'elles y paraissaient meilleures.
   Regle a retenir : une source de 570 px ne doit jamais depasser 285 px
   d'affichage. */
.bande-photos {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 1px;
  width: 100%;
}
@media (max-width: 700px) { .bande-photos { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 420px) { .bande-photos { grid-template-columns: repeat(2, 1fr); } }
.bande-photos figure {
  margin: 0;
  height: clamp(150px, 19vw, 300px);
  background: var(--i-700);
  overflow: hidden;
}
.bande-photos img { width: 100%; height: 100%; object-fit: cover; }
.hero .bande-photos { margin-top: clamp(2rem, 4vw, 3.5rem); }

/* Photographie de la ville, en pied de bandeau d'accueil.
   Elle remplace une bande de trois vignettes de 570 px qui, etalees sur
   426 px chacune, n'avaient que 0,67 pixel natif par pixel ecran et etaient
   visiblement floues. Une seule image de 2048 px tient toute la largeur en
   restant nette. */
.hero-photo {
  margin: clamp(2rem, 4vw, 3.5rem) 0 0;
  width: 100%;
  height: clamp(200px, 26vw, 420px);
  overflow: hidden;
  background: var(--i-700);
}
.hero-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ---------- 21.5 Registre de faits ----------
   "Depuis 1984", "cinq corps d'etat", "Montauban" etaient noyes dans des
   phrases. Sortis en tres grande typographie et separes par des filets
   horizontaux, ils deviennent des respirations et des preuves. La forme est
   celle d'une legende de plan : valeur en gros, descripteur dessous, filets
   qui s'alignent d'une colonne a l'autre.

   Le composant est contextuel : sur fond clair il prend --fg-titre et
   --g-700, sur aplat vert il bascule par heritage des regles 21.2. Seul le
   filet doit etre remappe a la main, --rule valant le filet clair hors
   .bloc-inverse. */
.faits {
  --faits-rule: var(--rule);
  display: grid;
  grid-template-columns: 1fr;
  column-gap: var(--gutter);
  margin: 0;
  border-top: 1px solid var(--faits-rule);
}
.hero .faits,
.bloc-inverse .faits,
.section--inverse .faits,
.bandeau-cta-final .faits { --faits-rule: var(--border-inverse); }
.faits .fait {
  padding-block: var(--sp-6);
  padding-right: var(--sp-6);
  border-bottom: 1px solid var(--faits-rule);
}
.faits dt {
  font-family: var(--font-display);
  font-weight: var(--titre-graisse);
  letter-spacing: var(--ls-titre);
  line-height: 1.06;
  font-size: clamp(1.625rem, 1rem + 2.1vw, 2.625rem);
  color: var(--fg-titre);
  margin-top: 0;
  overflow-wrap: break-word;
  hyphens: auto;
}
.faits dd {
  margin: var(--sp-3) 0 0;
  font-size: var(--fs-small);
  color: var(--fg-soft);
  max-width: 32ch;
}
/* Le registre de quatre faits reste sur DEUX colonnes des le plus petit
   ecran : empile en une colonne, il ajoutait environ 520 px au premier ecran
   mobile et repoussait la bande photographique tres loin sous la ligne de
   flottaison, ce qui annulait l'effet recherche. A 390 px, chaque colonne
   fait 163 px et la plus longue valeur ("Decennale", 26 px) en occupe 117. */
.faits--4 { grid-template-columns: repeat(2, 1fr); }
@media (min-width: 640px) { .faits--2 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .faits--4 { grid-template-columns: repeat(4, 1fr); } }
@media (max-width: 639px) { .faits .fait { padding-block: var(--sp-4); padding-right: var(--sp-4); } }
.hero .faits { margin-top: var(--sp-10); }

/* M6 (audit visuel) : les trois garanties legales ("Un an", "Deux ans",
   "Dix ans") forment un ".faits--2" a 3 elements : le dernier se retrouve seul
   dans sa ligne, en colonne 1 uniquement. Son filet de separation (border-
   bottom, herite de ".faits .fait") ne courait donc que sur la moitie de la
   largeur du bloc, quand le paragraphe qui suit la liste occupe toute cette
   largeur : le filet semblait tronque et mal separe du texte suivant. On fait
   porter cet element orphelin (dernier enfant en position impaire dans une
   grille a 2 colonnes) sur les deux colonnes : son filet redevient continu et
   s'aligne avec le paragraphe suivant. Les ".faits--2" a nombre pair d'elements
   (page d'accueil) ne sont jamais cibles par ce selecteur. */
.faits--2 .fait:nth-child(odd):last-child { grid-column: 1 / -1; }

/* ---------- 21.6 Encart d'alerte ----------
   Sort le bloc "urgence" du flux de prose : filet d'accent epais a gauche,
   fond creme, actions groupees en colonne a droite. Le filet est en --a-ink
   et non en --a-600 : la paire (--a-ink sur creme, 7,63:1) est deja au
   catalogue, la seconde ne l'etait pas.

   Le bouton d'appel .btn--call pose du blanc sur --a-600 (6,16:1). Cette
   combinaison existait deja dans le CSS livre (.btn--call, .mcb-appeler) mais
   ne figurait dans aucune paire du catalogue : elle y a ete ajoutee le
   6 septembre 2026, pour la meme raison que la paire du bouton secondaire
   avant elle. */
.encart-alerte {
  background: var(--surface-cream);
  border-left: 4px solid var(--a-ink);
  padding: clamp(1.5rem, 3vw, 2.5rem);
  display: grid;
  gap: var(--sp-6);
  align-items: center;
}
@media (min-width: 1024px) { .encart-alerte { grid-template-columns: 1.6fr 1fr; gap: var(--sp-10); } }
.encart-alerte h2 { margin-bottom: var(--sp-3); }
.encart-alerte p:last-of-type { margin-bottom: 0; }
.encart-alerte__actions { display: flex; flex-direction: column; gap: var(--sp-3); }
.encart-alerte__actions .btn { width: 100%; }
.eyebrow--accent { color: var(--a-ink); }
.bloc-inverse .eyebrow--accent, .section--inverse .eyebrow--accent { color: var(--a-500); }

/* ---------- 21.7 Fait cle ----------
   Un seul chiffre ou une seule date, sortis du paragraphe et poses en grand
   contre un filet d'accent. Sert a ancrer une information qui change la
   decision du lecteur (ici, la date de reforme MaPrimeRenov'). */
.fait-cle {
  border-left: 4px solid var(--a-ink);
  padding: var(--sp-2) 0 var(--sp-2) var(--sp-6);
}
.bloc-inverse .fait-cle, .section--inverse .fait-cle, .hero .fait-cle { border-left-color: var(--a-500); }
.fait-cle__valeur {
  font-family: var(--font-display);
  font-weight: var(--titre-graisse);
  letter-spacing: var(--ls-titre);
  line-height: 1.1;
  font-size: clamp(1.5rem, 1rem + 1.9vw, 2.25rem);
  color: var(--fg-titre);
  margin: 0 0 var(--sp-3);
  max-width: 18ch;
}
.fait-cle__texte { margin: 0; }

/* ---------- 21.8 Grilles de cartes ----------
   .grid--metiers : cinq cartes de meme largeur a chaque palier (1 colonne en
   mobile, 2 en tablette, 3 en desktop), sans exception de taille pour les
   dernieres cartes.
   .grid--4 : trois realisations plus une tuile de lien (21.9). */
/* M7 (audit visuel) : la version precedente donnait trois cartes de deux
   colonnes sur six puis deux cartes de trois colonnes sur six. Les six
   colonnes etant partagees par toute la grille, les aretes verticales de la
   rangee du bas (limites a 3/6) ne tombaient jamais en face de celles de la
   rangee du haut (limites a 2/6 et 4/6) : 376 px de large en haut, 576 px en
   bas, aucun alignement possible par construction. A 768 px, la carte 05
   heritait en plus d'un agrandissement disproportionne. On revient a une
   grille uniforme : memes colonnes a tous les paliers, donc memes aretes. */
.grid--metiers { display: grid; gap: var(--gutter); grid-template-columns: 1fr; }
@media (min-width: 768px) { .grid--metiers { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .grid--metiers { grid-template-columns: repeat(3, 1fr); } }
.grid--metiers .card-metier__media { height: clamp(190px, 19vw, 260px); }
/* Le corps de carte est un conteneur flex en colonne : sans align-self, le
   lien flechu s'etirait sur toute la largeur et son libelle se centrait. Le
   margin-top auto le plaque en bas, ce qui aligne les liens d'une carte a
   l'autre quelle que soit la longueur du texte. */
.grid--metiers .card-metier__specs { margin-bottom: 0; }
.grid--metiers .card-metier__body .btn--link { align-self: flex-start; margin-top: auto; }

/* Alignement vertical d'un duo texte + image en demi-colonne. */
.grid--aligne-centre { align-items: center; }

.grid--4 { display: grid; gap: var(--gutter); grid-template-columns: repeat(2, 1fr); }
@media (min-width: 1024px) { .grid--4 { grid-template-columns: repeat(4, 1fr); } }
.grid--4 .card-realisation__media { height: auto; aspect-ratio: 1 / 1; }
@media (min-width: 1024px) { .grid--4 .card-realisation__media { aspect-ratio: 4 / 5; } }

/* ---------- 21.9 Tuile de lien ----------
   Aplat vert plein glisse dans une grille de cartes claires. Remplit la
   quatrieme case sans exiger une photographie de plus, et fait respirer la
   grille par le contraste de surface, jamais par une ombre. */
.tuile-lien {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--sp-6);
  background: var(--i-800);
  border: 1px solid var(--i-800);
  color: var(--n-0);
  text-decoration: none;
  padding: clamp(1rem, 2.4vw, 1.5rem);
}
.tuile-lien .eyebrow { color: var(--i-200); margin-bottom: var(--sp-3); }
.tuile-lien h3 { color: var(--n-0); margin-bottom: 0; }
.tuile-lien__action { display: inline-flex; align-items: center; gap: var(--sp-2); font-weight: 600; color: var(--n-0); }
.tuile-lien:hover { background: var(--i-950); border-color: var(--i-950); color: var(--n-0); }
.tuile-lien:hover .btn__arrow { transform: translateX(4px); }

/* ---------- 21.10 Cadre d'image ----------
   Une image en demi-colonne plutot qu'en vignette : a 560 px de large, les
   sources de 570 a 1080 px restent nettes, ce qui n'est pas le cas d'un
   bandeau unique en pleine largeur. Le cadre est un filet de 1 px, jamais une
   ombre, et le fond de reserve evite le saut de mise en page au chargement. */
.media-cadre { border: 1px solid var(--rule); background: var(--card-alt); overflow: hidden; }
.media-cadre img { width: 100%; height: auto; object-fit: cover; }
.media-cadre--carre img { aspect-ratio: 1 / 1; }
.media-cadre--paysage img { aspect-ratio: 3 / 2; }
.media-cadre--portrait img { aspect-ratio: 4 / 5; }

/* ---------- 21.11 Liste sortie du flux ----------
   Composant prevu pour la propagation aux pages metier, ou les listes sont
   nombreuses et noyees dans la prose. Une liste devient une grille de deux ou
   trois colonnes, chaque entree separee par un filet et prefixee d'un tiret
   d'accent. La puce utilise --eyebrow, seul token dont la valeur est
   verifiee au catalogue dans les TROIS contextes (limestone, creme, vert). */
.liste-grille {
  list-style: none;
  padding: 0;
  margin: 0 0 var(--sp-6);
  display: grid;
  grid-template-columns: 1fr;
  column-gap: var(--gutter);
  border-top: 1px solid var(--rule);
}
@media (min-width: 640px) { .liste-grille { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .liste-grille--3 { grid-template-columns: repeat(3, 1fr); } }
.liste-grille li {
  position: relative;
  margin: 0;
  padding: var(--sp-3) 0 var(--sp-3) var(--sp-6);
  border-bottom: 1px solid var(--rule);
}
.liste-grille li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 1.5em;
  width: 12px;
  height: 1px;
  background: var(--eyebrow);
}

/* ---------- 21.12 Bandeau d'appel final, variante en deux colonnes ---------- */
.bandeau-cta-final--duo { text-align: left; }
.bandeau-cta-final--duo .container { display: grid; gap: var(--sp-10); }
@media (min-width: 1024px) {
  .bandeau-cta-final--duo .container { grid-template-columns: 1.3fr 1fr; align-items: start; gap: var(--sp-16); }
}
.bandeau-cta-final--duo .cluster { justify-content: flex-start; }
.bandeau-cta-final address { font-style: normal; }

/* ---------- 21.14 Degagement de la barre d'appel mobile ----------
   La barre fixe de bas d'ecran recouvrait le bas du pied de page, donc le
   credit d'agence et les liens legaux, sur les seules largeurs ou elle est
   affichee. Elle n'existe que si JavaScript a pose la classe .js. */
@media (max-width: 1023px) {
  .js .footer-bottom { padding-bottom: calc(var(--sp-4) + 64px); }
}

/* ===========================================================================
   22. GRAMMAIRE DE COMPOSITION DE L'ACCUEIL

   Le design system de ce projet (_projet/design-system.md) cite deja un
   gabarit de reference pour ses en-tetes de section et son registre de plan.
   Cette section en reprend la GRAMMAIRE de mise en page, pas les valeurs :
   toutes les couleurs viennent des tokens de la zone generee, la direction
   reste "architectural-precision" (aplats, angles droits, filets de 1 px,
   aucune ombre, aucun degrade, rayon zero).

   Ecrite d'abord pour l'accueil (22.1 a 22.8), cette grammaire a ete etendue en 22.9 a
   dix pages de service et de contenu. Deux niveaux d'extension, selon la matiere
   disponible sur chaque page :

   1. Bandeau debordant, carte divisee et grande photographie : charpente, couverture,
      maconnerie, carrelage, isolation (bandeau existant reutilise), entreprise et
      zone d'intervention (photo repositionnee en pleine largeur), contact (bloc
      photographique en surimpression, 22.4). Realisations reprend la grille de
      vignettes et l'en-tete asymetrique sans bandeau, faute de photo dediee.
   2. En-tete asymetrique seul, par simple libelle .eyebrow pose devant le h2, sur
      aides a la renovation energetique et depannage toiture : aucune des deux ne
      disposait d'une photo a deplacer sans la sortir de son contexte, et la seconde
      garde volontairement sa mise en page etroite (container--narrow), pensee pour
      une lecture rapide en urgence.

   Les quatre pages legales restent hors perimetre. Aucune de ces extensions ne
   redefinit un composant : toutes s'appuient sur les classes generiques ecrites en
   22.1 a 22.8, completees en 22.9 la ou une regle etait implicitement scopee a
   l'accueil (.hero--metier, .section-head--split h1, .card-metier--split hors
   .grid--metiers).
   =========================================================================== */

/* Deux mesures partagees par le bandeau d'accueil ET par la section qui le
   suit. Elles sont posees sur #contenu, pas sur .hero--accueil : une variable
   personnalisee descend dans l'arbre, elle ne traverse pas entre freres, et la
   section suivante doit connaitre la hauteur du debord pour se degager. */
#contenu {
  --hero-pb: clamp(2.5rem, 4vw, 4rem);
  --hero-debord: 0px;
}
@media (min-width: 1024px) {
  #contenu { --hero-debord: clamp(3rem, 5vw, 5.5rem); }
}

/* ---------- 22.1 Bandeau d'accueil ----------
   Aplat vert forêt sur la pleine largeur, colonne de texte sur les deux tiers
   gauche, photographie sur le tiers droit. Le geste caracteristique du modele
   est le DEBORD : la photo descend sous l'aplat vert, sur le fond clair de la
   section suivante.

   Le debord est produit par un decalage negatif du bord bas de l'image, pas
   par une marge negative sur la figure : la figure reste une cellule de grille
   normale, donc son bord droit reste aligne sur le bord droit du conteneur de
   page, exactement comme le titre est aligne sur son bord gauche. Rien a
   recalculer si --maxw ou --marge-page changent.

   L'image est un descendant POSITIONNE du bandeau. Dans l'ordre de peinture
   CSS, les descendants positionnes passent apres les fonds des blocs en flux
   des freres suivants : le debord recouvre donc bien la section d'apres, sans
   z-index de surenchere. Le z-index:1 n'est la que pour rester au-dessus de
   l'aplat vert de son propre bandeau. */
.hero--accueil {
  background: var(--surface-limestone);
  min-height: auto;
  display: block;
  padding: 0;
}
.hero-plaque {
  position: relative;
  background: var(--i-800);
  padding-block: clamp(2rem, 4vw, 3.5rem) var(--hero-pb);
}
.hero-plaque__grille {
  display: grid;
  gap: clamp(2rem, 4vw, 3rem);
}
.hero-plaque__grille > * { min-width: 0; }

/* Le titre est nettement plus gros que l'echelle --fs-display : c'est le seul
   endroit de la page ou la typographie doit tenir le premier ecran a elle
   seule. La mesure de 22ch est calee sur le titre reel, long de 58 signes :
   elle le repartit sur trois lignes en desktop, ce que le modele fait aussi.
   Reduire cette mesure ferait tomber le titre a cinq lignes, l'augmenter le
   ferait deborder de la colonne de texte. */
.hero--accueil .hero-plaque h1 {
  /* Plafonne par la hauteur d'ecran autant que par la largeur : 7,6vh vaut
     72 px a partir de 950 px de haut, et descend en dessous. Le titre ne peut
     jamais depasser --fs-display, il ne fait que se reduire sur un ecran bas. */
  font-size: min(var(--fs-display), 7.6vh);
  line-height: var(--lh-display);
  /* Approche normale, comme le modele : a 72 px, le resserrement de -0,03em
     fermait les contreformes du "g" et du "p". */
  letter-spacing: normal;
  max-width: 22ch;
  margin-bottom: var(--sp-6);
}
.hero-plaque p.lead { max-width: 52ch; }
@media (min-height: 0px) and (max-height: 900px) and (min-width: 1024px) {
  .hero--accueil .hero-plaque { padding-top: 6.5rem; padding-bottom: 2.5rem; }
  .hero--accueil .hero-plaque h1 { margin-bottom: var(--sp-4); }
  .hero-plaque .cluster { margin-top: var(--sp-4); }
  .hero-plaque .faits--vitrine { margin-top: var(--sp-6); }
}
.hero-plaque .cluster { margin-top: var(--sp-6); }

/* Registre de faits du bandeau : deux entrees seulement, valeur en tres grande
   typographie, legende en petites capitales espacees. Les filets du composant
   .faits sont retires ici : dans le modele, le registre du bandeau ne porte
   aucune reglure, il ne tient que par sa taille. Deux colonnes des le plus
   petit ecran, sinon le bandeau gagne plus de 200 px de hauteur inutile. */
.hero-plaque .faits {
  margin-top: clamp(2rem, 4vw, 3.25rem);
  border-top: none;
}
.hero-plaque .faits--vitrine { grid-template-columns: repeat(2, 1fr); }
.hero-plaque .faits .fait {
  border-bottom: none;
  padding-block: 0;
}
.hero-plaque .faits dt {
  font-size: clamp(2rem, 1.2rem + 2.6vw, 3rem);
  line-height: 1.02;
}
.hero-plaque .faits dd {
  margin-top: var(--sp-3);
  font-size: var(--fs-label);
  font-weight: 600;
  line-height: 1.5;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  max-width: 26ch;
}

/* Photographie du bandeau. Sous 1024 px elle passe sous le texte et sort du
   conteneur pour tenir la pleine largeur de l'ecran : c'est la seule facon de
   lui donner de la presence sur une colonne unique. */
.hero-plaque__photo {
  margin: clamp(2rem, 5vw, 3rem) calc(-1 * var(--marge-page)) calc(-1 * var(--hero-pb));
  background: var(--i-700);
  height: clamp(15rem, 62vw, 26rem);
  overflow: hidden;
}
.hero-plaque__photo img { width: 100%; height: 100%; object-fit: cover; }

@media (min-width: 1024px) {
  .hero-plaque__grille {
    grid-template-columns: minmax(0, 1.62fr) minmax(0, 1fr);
    gap: clamp(3rem, 5vw, 5rem);
    align-items: stretch;
  }
  .hero-plaque__photo {
    position: relative;
    margin: 0;
    height: auto;
    min-height: 26rem;
    overflow: visible;
  }
  .hero-plaque__photo img {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    /* Le bord bas descend sous la CELLULE de la marge basse du bandeau plus la
       hauteur de debord ; comme la cellule s'arrete au bord interieur de cette
       marge, l'image depasse l'aplat vert d'exactement --hero-debord. C'est ce
       seul calcul qui produit le geste, et c'est la meme valeur dont la section
       suivante se degage : les deux ne peuvent pas deriver l'une de l'autre. */
    bottom: calc(-1 * (var(--hero-pb) + var(--hero-debord)));
    /* Hauteur EXPLICITE, et non "auto".
       Sur un element remplace comme une image, "height: auto" vaut la hauteur
       intrinseque du fichier, meme lorsque "top" et "bottom" sont tous deux
       definis : la specification ne resout l'equation de position que pour les
       elements NON remplaces. L'image gardait donc son ratio d'origine et
       n'occupait que le haut de sa cellule, laissant un grand rectangle vert
       vide en dessous. On lui donne la hauteur de la cellule augmentee du
       debord, et object-fit recadre. */
    height: calc(100% + var(--hero-pb) + var(--hero-debord));
    object-fit: cover;
    z-index: 1;
  }
  /* La section qui suit se degage de la hauteur exacte du debord : la photo
     surplombe du vide, jamais du texte. .hero--metier (22.9) rejoue le meme
     geste sur les pages de service : les deux classes degagent donc la meme
     section suivante, avec la meme variable. */
  .hero--accueil + .section,
  .hero--metier + .section { padding-top: calc(var(--section-y) + var(--hero-debord)); }
}

/* ---------- 22.1 bis En-tete en surimpression du bandeau vert ----------
   Le modele de reference fait passer sa barre de navigation PAR-DESSUS
   l'aplat vert : la page commence par la couleur, pas par une barre blanche.
   La classe .entete-sur-hero est posee par main.js tant que la page n'a pas
   defile, et retiree des le premier defilement (demande du client, 14 septembre
   2026 : auparavant elle restait posee pendant toute la traversee du bandeau).
   Deux garde-fous :
   - sans JavaScript, la classe n'existe jamais et l'en-tete reste opaque,
     donc lisible : l'effet est un agrement, jamais une condition ;
   - la classe ne change que fond, bordure et couleurs. La position fixe tient
     a .a-hero-sombre, posee une fois pour toutes : basculer au premier pixel
     de defilement ne deplace rien dans la page.
   Le bandeau se decale sous la barre par un padding, pas par une marge
   negative : la barre le survole, elle ne le recouvre pas. */
/* L'en-tete doit SORTIR DU FLUX pour que le bandeau vert passe dessous.
   En "sticky" il occupe sa propre place avant le bandeau : le fond
   transparent laissait alors voir le blanc de la page, et la barre devenait
   blanche sur blanc. En "fixed" elle survole reellement le bandeau, qui
   reprend le haut de la page. Le bandeau se degage par un padding, jamais par
   une marge negative, pour que rien ne soit recouvert. */
body.a-hero-sombre .site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
}
/* Le degagement se pose sur l'element QUI PORTE L'APLAT VERT, pas sur la
   section qui l'englobe. Sur .hero, le padding creait une bande blanche
   au-dessus du vert, la section n'ayant pas de fond propre. */
body.a-hero-sombre .hero--accueil .hero-plaque,
body.a-hero-sombre .hero--metier .hero-plaque { padding-top: calc(5.5rem + var(--sp-10)); }
body.a-hero-sombre .hero.bloc-inverse:not(:has(.hero-plaque)) { padding-top: calc(5.5rem + var(--sp-10)); }
/* Le bandeau d'urgence de la page depannage precede le bandeau vert : c'est
   lui qui doit se degager, sinon la barre le recouvre. */
body.a-hero-sombre .bandeau-urgence { padding-top: calc(5.5rem + var(--sp-3)); }

body.entete-sur-hero .site-header {
  background: transparent;
  border-bottom-color: transparent;
}
body.entete-sur-hero .site-header .main-nav a,
body.entete-sur-hero .site-header .logo,
body.entete-sur-hero .site-header .header-phone,
body.entete-sur-hero .site-header .header-phone strong,
body.entete-sur-hero .site-header .header-phone span,
body.entete-sur-hero .site-header .nav-metiers > summary { color: var(--n-0); }
body.entete-sur-hero .site-header .header-urgence {
  color: var(--a-500);
  border-color: var(--a-500);
}
/* Le logo est un PNG noir : sur le vert il disparaitrait. On l'eclaircit par
   filtre plutot que de charger un second fichier, ce qui evite une requete de
   plus et garde une seule source pour la marque. */
body.entete-sur-hero .site-header .logo img { filter: brightness(0) invert(1); }
body.entete-sur-hero .site-header .burger svg { color: var(--n-0); }
/* Le bouton d'appel a l'action reste plein, mais inverse : blanc sur vert. */
body.entete-sur-hero .site-header .header-cta {
  background: var(--n-0);
  border-color: var(--n-0);
  color: var(--i-950);
}
.site-header, body.entete-sur-hero .site-header { transition: background .2s var(--ease-out), border-color .2s var(--ease-out); }

/* ---------- 22.1 ter Citation client ----------
   Le modele de reference isole un avis client au milieu d'une pleine page de
   blanc, en tres grande typographie, sans encadre ni guillemets decoratifs.
   C'est la respiration la plus forte de sa mise en page.
   Chez nous, la citation porte un avis REEL, verifiable sur la fiche Google
   de l'entreprise, et la note publique est affichee a cote : afficher un avis
   favorable en masquant la note globale exposerait a une pratique commerciale
   trompeuse (article L111-7-2 du code de la consommation). */
.citation-client {
  /* Meme colonne que le reste de la page : une citation alignee a gauche dans
     une colonne etroite centree flotterait sans rapport avec la grille. */
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--marge-page);
  text-align: left;
}
.citation-client blockquote {
  margin: 0;
  max-width: 32ch;
  font-family: var(--font-display);
  /* Graisse 500, comme tous les titres du modele hors premier ecran et bloc
     final. --titre-graisse vaut 600 et s'appliquait ici par heritage. */
  font-weight: 500;
  letter-spacing: var(--ls-titre);
  font-size: clamp(1.375rem, 1.05rem + 1.4vw, 2rem);
  line-height: 1.25;
  color: var(--fg-titre);
}
.citation-client figcaption {
  margin-top: var(--sp-6);
  font-size: 1.25rem;
  font-weight: 500;
  line-height: 1.4;
  color: var(--g-600);
}
.citation-client figcaption strong { color: var(--fg-titre); font-weight: 600; }
.citation-client .citation-source {
  display: block;
  margin-top: var(--sp-3);
  font-size: var(--fs-small);
  font-weight: 400;
  letter-spacing: -0.01em;
  text-transform: none;
  color: var(--g-500);
}

/* ---------- 22.2 En-tete de section asymetrique ----------
   A gauche le libelle et son filet vertical puis le titre en tres grande
   typographie ; a droite le texte d'accompagnement et, s'il y en a un, le
   bouton. Colonnes alignees en haut, titre sur environ la moitie de la
   largeur. Le point de bascule est a 900 px : en dessous, deux colonnes
   rendraient le titre illisible en escalier. */
.section-head--split {
  max-width: none;
  display: grid;
  gap: var(--sp-6);
  margin-bottom: clamp(2.5rem, 5vw, 4rem);
}
.section-head--split > * { min-width: 0; }
@media (min-width: 900px) {
  .section-head--split {
    grid-template-columns: minmax(0, 1fr) minmax(0, 0.82fr);
    gap: clamp(2.5rem, 5vw, 5rem);
    align-items: start;
  }
}
.section-head--split h2 {
  font-size: clamp(1.875rem, 1.3rem + 1.9vw, 3rem);
  font-weight: 500;
  line-height: var(--lh-display);
  letter-spacing: var(--ls-display);
  max-width: 22ch;
  margin-bottom: 0;
}
.section-head--split .eyebrow { margin-bottom: var(--sp-4); }
.section-head--split p { max-width: 48ch; }
.section-head--split p:last-of-type { margin-bottom: 0; }
.section-head--split .cluster { margin-top: var(--sp-6); }

/* ---------- 22.3 Cartes de metier divisees verticalement ----------
   Chaque carte est coupee en deux dans le sens de la hauteur : a gauche un
   aplat vert portant le numero d'ordre en haut puis, cales en bas, le titre,
   la description, les prestations et le lien flechu ; a droite une photo qui
   occupe toute la hauteur de la carte. Deux cartes par rangee.

   Le panneau porte aussi .bloc-inverse (zone generee) : c'est lui qui remappe
   --fg-soft, --eyebrow, --rule et les boutons pour un fond sombre. On ne
   redecrit pas ces valeurs ici, sinon les deux listes deriveraient au prochain
   changement de direction. */
.card-metier--split {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  border: none;
  background: transparent;
}
@media (min-width: 560px) {
  .card-metier--split { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
}
/* Des que la carte ne fait plus que la moitie de la page, le panneau reprend
   la main sur la photo. Nos cartes portent, en plus du titre et de la
   description, une liste de quatre prestations : a parts egales, la colonne de
   texte tombait a 219 px utiles et la plus longue prestation s'y cassait en
   quatre lignes. Le rapport 1,25 pour 1 lui rend 30 px. */
@media (min-width: 1024px) {
  .card-metier--split { grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); }
}
.card-metier__panneau {
  background: var(--i-800);
  padding: clamp(1.25rem, 2.2vw, 2rem);
  display: flex;
  flex-direction: column;
  gap: var(--sp-10);
  min-width: 0;
}
/* Le corps de carte est plaque en bas du panneau : c'est ce calage, et non un
   alignement au pixel, qui fait tenir la rangee quand deux cartes n'ont pas la
   meme quantite de texte. */
.card-metier__corps { margin-top: auto; }
.card-metier--split .card-metier__index {
  font-size: clamp(1.25rem, 1.15rem + 0.35vw, 1.5rem);
  font-weight: 400;
  line-height: 1.33;
  /* --i-400 sur --i-800 : 5,02:1. Paire ajoutee au catalogue le 8 septembre
     2026 (_build/themes.py, "Index de carte sur vert foret"). Le --i-200 des
     libelles serait trop present : le numero d'ordre se lit, il ne se
     proclame pas. */
  color: var(--i-400);
}
.card-metier--split h3 {
  font-size: clamp(1.25rem, 1.1rem + 0.45vw, 1.5rem);
  font-weight: 500;
  line-height: 1.33;
  letter-spacing: -0.02em;
  margin-bottom: var(--sp-3);
}
.card-metier--split .card-metier__corps p {
  line-height: 1.5;
  margin-bottom: var(--sp-4);
}
.card-metier--split .card-metier__specs { margin-bottom: var(--sp-2); }
.card-metier--split .card-metier__corps .btn--link { display: inline-flex; }
/* La photo est une cellule de grille etiree : sa hauteur est celle de la
   rangee, donc celle du panneau. La hauteur fixe des cartes empilees ne doit
   pas s'appliquer ici. L'image est posee en absolu plutot qu'en hauteur de
   100 pour cent : sur une cellule etiree, une hauteur en pourcentage depend de
   la resolution de la hauteur du parent, et cette dependance a deja produit
   des images ecrasees ailleurs. En absolu, il n'y a rien a resoudre. */
.grid--metiers .card-metier--split .card-metier__media {
  position: relative;
  height: auto;
  min-height: 12rem;
}
.grid--metiers .card-metier--split .card-metier__media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Cinq metiers ne se rangent pas en colonnes paires. La cinquieme carte prend
   la pleine largeur et inverse sa composition : photo a gauche, panneau a
   droite. Les aretes verticales de la grille restent identiques d'une rangee a
   l'autre, ce qui n'etait pas le cas de la version a six colonnes partagees
   corrigee precedemment. L'ordre du DOM reste titre avant image : seul
   l'affichage est inverse. */
@media (min-width: 768px) {
  .grid--metiers { grid-template-columns: repeat(2, 1fr); }
  .grid--metiers > .card-metier--large { grid-column: 1 / -1; }
  .card-metier--large .card-metier__panneau { order: 2; }
  .card-metier--large .card-metier__media { order: 1; }
}
@media (min-width: 1024px) {
  /* Deux colonnes et non trois : une carte divisee en deux a besoin de la
     moitie de la page pour que le panneau et la photo respirent. */
  .grid--metiers { grid-template-columns: repeat(2, 1fr); }
  .card-metier--large { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); }
  .grid--metiers .card-metier--large .card-metier__media { min-height: 20rem; }
}

/* ---------- 22.4 Bloc photographique en surimpression ----------
   Le bloc "mis en avant" du modele : une photographie sur toute la largeur du
   conteneur, un libelle, un titre et les actions poses sur sa partie gauche.

   Le voile est un APLAT, jamais un degrade : la direction est en couleurs
   pleines et un degrade obligerait a chercher son pire point. Ici le pire
   point est connu et unique. Sur un pixel blanc pur, un aplat de --i-1000 a
   66 pour cent compose #5A605C, ou le texte blanc tient 6,44:1 ; sur tout
   pixel plus sombre de la photo, le ratio ne peut que monter. C'est donc une
   garantie, pas une moyenne. La paire figure au catalogue.

   Consequence a ne pas oublier : le --i-300 du texte doux tomberait a 3,80:1
   sur ce meme compose. Tout le texte de ce bloc est donc en blanc, y compris
   le libelle de section, qui heriterait sinon de --i-550. */
.bloc-photo {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  min-height: clamp(19rem, 29vw, 26rem);
  display: flex;
  align-items: flex-start;
}
.bloc-photo__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
}
.bloc-photo__voile {
  position: absolute;
  inset: 0;
  background: var(--i-1000);
  opacity: .66;
  z-index: 1;
}
.bloc-photo__contenu {
  position: relative;
  z-index: 2;
  padding: clamp(1.5rem, 3.5vw, 3rem);
  max-width: 44rem;
}
.bloc-photo__contenu .eyebrow { color: var(--n-0); margin-bottom: var(--sp-4); }
.bloc-photo__contenu h2 {
  color: var(--n-0);
  font-size: clamp(1.5rem, 1.1rem + 1.6vw, 2.375rem);
  line-height: var(--lh-display);
  letter-spacing: var(--ls-display);
  max-width: 22ch;
}
.bloc-photo__contenu p { color: var(--n-0); max-width: 50ch; }
.bloc-photo__contenu .cluster { margin-top: var(--sp-6); }
/* Lien nu dans le paragraphe du voile. Defaut trouve en propageant le
   composant : la regle de base "a { color: var(--i-900) }" (section 2) rendait
   un lien pratiquement invisible sur l'aplat sombre du voile, --i-900 sur le
   compose #5A605C tombant sous 2:1. Meme correction que celle deja posee pour
   .hero, .bloc-inverse et .section--inverse (section 21.2). */
.bloc-photo__contenu a:not(.btn) { color: var(--n-0); }
.bloc-photo__contenu a:not(.btn):hover { color: var(--i-200); }

/* Bouton secondaire sur le voile. Meme raisonnement que pour .hero et
   .bandeau-cta-final (sections 5 et 21.2) : la variante claire decoule du
   FOND, pas d'une classe que l'on peut oublier a l'integration. Ordre LVHA
   respecte, et les pseudo-classes sont reprises pour egaler la specificite des
   regles de la section 5, que celles-ci portent deja. */
.bloc-photo__contenu .btn--secondary,
.bloc-photo__contenu .btn--secondary:link,
.bloc-photo__contenu .btn--secondary:visited {
  background: transparent;
  color: var(--n-0);
  border-color: var(--n-0);
}
.bloc-photo__contenu .btn--secondary:hover { background: var(--n-0); color: var(--i-950); }
.bloc-photo__contenu .btn--secondary:active { background: var(--i-200); color: var(--i-950); }

/* ---------- 22.5 Grande photographie de section ----------
   Le modele ferme sa section verte par une photographie sur toute la largeur
   du conteneur. Pas de cadre, pas de filet : l'image EST le bloc. */
.photo-large {
  margin: clamp(2.5rem, 5vw, 4rem) 0 0;
  background: var(--i-700);
  overflow: hidden;
}
.photo-large img {
  width: 100%;
  height: clamp(13rem, 32vw, 30rem);
  object-fit: cover;
}

/* ---------- 22.6 Fiches de realisation ----------
   Photographie nue, titre, puis corps de metier en petites capitales a
   l'emplacement ou le modele pose ses metadonnees. Trois colonnes en desktop :
   ce n'est pas un choix de composition mais une contrainte de nettete, les
   sources font 580 px de large et ne doivent pas etre etalees davantage. */
.grid--realisations {
  display: grid;
  gap: var(--gutter) clamp(1.5rem, 3vw, 2.5rem);
  grid-template-columns: minmax(0, 1fr);
}
@media (min-width: 560px) { .grid--realisations { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .grid--realisations { grid-template-columns: repeat(3, 1fr); } }

.card-realisation--nu {
  border: none;
  background: transparent;
}
.card-realisation--nu:hover { border-color: transparent; }
.card-realisation--nu .card-realisation__media {
  height: auto;
  aspect-ratio: 4 / 3;
  background: var(--surface-cream);
}
.card-realisation--nu .card-realisation__body {
  padding: var(--sp-4) 0 0;
  gap: var(--sp-2);
}
.card-realisation--nu h3 {
  font-size: clamp(1.125rem, 1rem + 0.6vw, 1.5rem);
  margin-bottom: 0;
}

/* ---------- 22.7 Fait cle en pleine largeur ----------
   Sorti de sa demi-colonne : dans l'en-tete asymetrique, le texte qui
   l'entourait est deja passe a droite du titre. Le fait devient une barre. */
.fait-cle--large { max-width: 60ch; }
.fait-cle--large .fait-cle__valeur { max-width: none; }

/* ---------- 22.8 Titres des blocs de fin de page ----------
   Le bandeau d'appel final adopte l'echelle des en-tetes asymetriques, sinon
   il retombe a 24 px juste apres une page entiere de titres a 50 px. */
.bandeau-cta-final--duo h2 {
  font-size: clamp(1.875rem, 1.3rem + 1.9vw, 3rem);
  font-weight: 500;
  line-height: var(--lh-display);
  letter-spacing: var(--ls-display);
  max-width: 18ch;
}

/* ---------- 22.9 Extension de la grammaire aux pages metier et de contenu ----------
   La grammaire ci-dessus n'etait posee que sur l'accueil. Ce lot la generalise aux
   pages de service et de contenu (charpente, couverture, maconnerie, carrelage,
   isolation, realisations, entreprise, zone d'intervention, contact) : bandeau
   debordant sur les pages metier, en-tete asymetrique partout, carte divisee et
   grande photographie ou elles rendent mieux que la liste ou la vignette existante.

   .hero--metier rejoue exactement le role de .hero--accueil : aplat neutre, padding
   nul, la couleur et le geste du debord viennent entierement de .hero-plaque. Les deux
   classes sont deux portes d'entree vers le meme composant, jamais redefini. */
.hero--metier {
  background: var(--surface-limestone);
  min-height: auto;
  display: block;
  padding: 0;
}

/* section-head--split accueille aussi un h1 : sur les pages sans fiche de service
   (realisations, entreprise, zone d'intervention), le titre de page occupe cette
   meme colonne asymetrique plutot qu'un h2 de sous-section. Meme echelle que le h2
   du composant : c'est la meme position dans la grille, ce doit etre la meme voix
   typographique. */
.section-head--split h1 {
  font-size: clamp(1.875rem, 1.3rem + 1.9vw, 3rem);
  font-weight: 500;
  line-height: var(--lh-display);
  letter-spacing: var(--ls-display);
  max-width: 22ch;
  margin-bottom: 0;
}

/* Carte divisee en dehors de la grille de l'accueil : les pages metier n'en posent
   qu'une a la fois, en tete de section "prestations", a la place d'un ancien
   grid--2 + media-cadre. Sans .grid--metiers comme parent, la carte a besoin de son
   propre etirement de la colonne photo : meme mecanique qu'en 22.3, simplement pas
   conditionnee a la grille de l'accueil. Specificite plus faible que la regle scopee
   .grid--metiers .card-metier--split .card-metier__media : les deux ecrivent la
   meme valeur, elles ne peuvent donc pas se contredire. */
.card-metier--split .card-metier__media {
  position: relative;
  height: auto;
  min-height: 12rem;
}
.card-metier--split .card-metier__media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
