/* ============================================================
   VOLTZEN — identite visuelle NATIVE du clone, sans un mot de metier.

   Ce que ce template a de propre, et que la coquille doit rendre :
     - une barre de navigation en PILULE FLOTTANTE posee sur le hero,
       les liens groupes dans une capsule ; elle passe en clair au defilement
     - un hero PLEINE HAUTEUR, image sombre + degrade vertical, contenu
       aligne en BAS, avec une carte de verre a droite
     - des cartes de service HAUTES (image 4/5 plein cadre, pastille
       numerotee posee dessus, texte dessous)
     - des sections SOMBRES en alternance, cartes translucides dessus
     - des boutons en pilule totale, avec une pastille-fleche ronde inversee
     - un eyebrow en pilule pleine, precede d'une puce

   Couleur : 8 variables, aucune autre. --sur-marque est CALCULE par
   render.mjs, jamais choisi. Aucun hex en dur ici : les translucides
   passent par color-mix(), qui derive des memes variables.
   ============================================================ */

:root {
  --r-card: 16px;
  --r-card-lg: 24px;
  --r-img: 12px;
  --r-pill: 999px;

  --f-titre: "Onest", system-ui, sans-serif;
  --f-texte: "Inter", system-ui, sans-serif;

  --pad-section: 120px;
  --max: 1280px;

  /* Les voiles et surfaces translucides derivent des 8 variables. */
  --sur-fonce: color-mix(in srgb, var(--fond) 100%, transparent);
  --verre: color-mix(in srgb, var(--fond) 5%, transparent);
  --verre-fort: color-mix(in srgb, var(--fond) 8%, transparent);
  --trait-fonce: color-mix(in srgb, var(--fond) 12%, transparent);
  --encre-fonce-doux: color-mix(in srgb, var(--fond) 72%, transparent);
  --encre-fonce-faible: color-mix(in srgb, var(--fond) 50%, transparent);
}

* { box-sizing: border-box; }

html, body {
  margin: 0; padding: 0;
  background: var(--fond); color: var(--texte);
  font-family: var(--f-texte);
  font-size: 16px; line-height: 1.55; letter-spacing: -.01em;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

h1, h2, h3, h4 {
  font-family: var(--f-titre); font-weight: 500;
  letter-spacing: -.04em; line-height: 1.08; margin: 0;
  text-wrap: balance;
}
h1 { font-size: clamp(38px, 6vw, 72px); line-height: 1.05; letter-spacing: -.045em; }
h2 { font-size: clamp(30px, 4.5vw, 56px); letter-spacing: -.04em; }

/* La balise dit le plan du document, la taille dit la mise en page. Quand une
   page n ouvre sur aucun titre de premier rang, le moteur promeut le premier
   titre de sa section de tete : il change de balise, il ne doit pas changer de
   corps. Sans cette regle, un titre de section double de taille et vient
   recouvrir l etiquette posee au-dessus de lui. */
h1[data-rang="2"] { font-size: clamp(30px, 4.5vw, 56px); }
h3 { font-size: clamp(21px, 2.2vw, 32px); line-height: 1.16; letter-spacing: -.025em; }
h4 { font-size: clamp(17px, 1.6vw, 22px); line-height: 1.3; letter-spacing: -.015em; }
p { margin: 0; text-wrap: pretty; }
a { color: inherit; text-decoration: none; }
img { max-width: 100%; display: block; }

.vz-wrap { width: 100%; max-width: var(--max); margin-inline: auto; padding-inline: 24px; }
@media (min-width: 768px) { .vz-wrap { padding-inline: 40px; } }

.sec { padding-block: clamp(64px, 9vw, var(--pad-section)); }
.sec--alt { background: var(--fond-2); }
.sec--fonce { background: var(--accent); color: var(--sur-fonce); }
/* Trois scenes sombres existent dans cette coquille, pas une : la section
   `--fonce`, le hero, et le bloc de conversion `.cta` — qui pose lui aussi un
   aplat d accent sous un voile a 86 pour cent. Les deux premieres etaient
   nommees partout ; la troisieme ne l etait nulle part, et se faisait rattraper
   enfant par enfant (`.cta__txt h2`). Resultat : le propos du bloc de contact
   gardait `--texte-doux`, une encre pensee pour le papier clair, rgb(61,61,60),
   posee sur du presque-noir — mesure 1,76 contre 1. Une scene sombre se nomme
   avec les autres, elle ne se rapiece pas. */
.sec--fonce h1, .sec--fonce h2, .sec--fonce h3, .sec--fonce h4,
.cta h1, .cta h2, .cta h3, .cta h4 { color: var(--sur-fonce); }
.sec--fonce .body, .cta .body { color: var(--encre-fonce-doux); }

.body { color: var(--texte-doux); font-size: 16px; }
.body--grand { font-size: 18px; }

/* ---------- eyebrow : pilule pleine a puce ---------- */
.eyebrow {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 14px 6px 10px; margin: 0 0 22px;
  background: var(--marque); color: var(--sur-marque);
  border-radius: var(--r-pill);
  font-family: var(--f-texte); font-size: 12px; font-weight: 500;
  letter-spacing: .02em; text-transform: uppercase;
}
.eyebrow::before { content: ""; width: 8px; height: 8px; border-radius: var(--r-pill); background: var(--sur-marque); flex: none; }
.sec--fonce .eyebrow, .cta .eyebrow { background: var(--verre-fort); color: var(--sur-fonce); }
.sec--fonce .eyebrow::before, .cta .eyebrow::before { background: var(--marque); }

/* ---------- boutons : pilule + pastille-fleche ronde ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  padding: 14px 22px; border-radius: var(--r-pill);
  font-size: 14px; font-weight: 500; letter-spacing: -.005em;
  background: var(--marque); color: var(--sur-marque);
  transition: transform .22s ease, background .22s ease;
  max-width: 100%;
}
.btn:hover { transform: translateY(-1px); }
.btn__fleche {
  width: 26px; height: 26px; border-radius: var(--r-pill); flex: none;
  background: var(--sur-marque); color: var(--marque);
  display: inline-flex; align-items: center; justify-content: center; font-size: 13px;
}
.btn--fonce { background: var(--accent); color: var(--sur-fonce); }
.btn--fonce .btn__fleche { background: var(--marque); color: var(--sur-marque); }
.btn--fantome { background: transparent; color: var(--texte); border: 1px solid var(--bordure); }
.btn--fantome .btn__fleche { background: var(--texte); color: var(--fond); }
.sec--fonce .btn--fantome, .hero .btn--fantome, .cta .btn--fantome { color: var(--sur-fonce); border-color: var(--trait-fonce); }
.sec--fonce .btn--fantome .btn__fleche, .hero .btn--fantome .btn__fleche, .cta .btn--fantome .btn__fleche { background: var(--sur-fonce); color: var(--accent); }

/* ---------- cartes ---------- */
.carte { background: var(--fond); border: 1px solid var(--bordure); border-radius: var(--r-card); overflow: hidden; }
.carte--verre { background: var(--verre); border-color: var(--trait-fonce); color: var(--sur-fonce); }
.num {
  display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; border-radius: var(--r-pill); flex: none;
  background: var(--marque); color: var(--sur-marque);
  font-family: var(--f-titre); font-size: 14px; font-weight: 500;
}
.sur-titre { font-size: 12px; text-transform: uppercase; letter-spacing: .18em; color: var(--texte-doux); }
/* Le hero EST une scene sombre, il ne porte simplement pas la classe
   `.sec--fonce` : son fond vient du cadre, pas d un aplat de section. Sans
   lui dans le selecteur, `.sur-titre` et `.puces li` retombent sur
   `--texte-doux` — une encre pensee pour le papier clair, rgb(61,61,60),
   posee sur du #171b20 (R4b). Les scenes sombres se nomment ensemble. */
.sec--fonce .sur-titre, .hero .sur-titre, .cta .sur-titre { color: var(--encre-fonce-faible); }

.chip {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 8px 16px; border-radius: var(--r-pill);
  border: 1px solid var(--bordure); background: var(--fond);
  font-size: 14px; color: var(--texte); max-width: 100%; overflow-wrap: anywhere;
}
.chips { display: flex; flex-wrap: wrap; gap: 10px; }
.sec--fonce .chip, .hero .chip, .cta .chip { background: var(--verre); border-color: var(--trait-fonce); color: var(--sur-fonce); }

.puces { list-style: none; margin: 18px 0 0; padding: 0; display: grid; gap: 11px; }
.puces li { position: relative; padding-left: 26px; color: var(--texte-doux); }
.puces li::before {
  content: ""; position: absolute; left: 0; top: .5em;
  width: 9px; height: 9px; border-radius: var(--r-pill); background: var(--marque);
}
.sec--fonce .puces li, .hero .puces li, .cta .puces li { color: var(--encre-fonce-doux); }

/* ---------- grilles ----------
   NORME COQUILLE, R3 — UNE SEULE LARGEUR PAR GRILLE, et le nombre de colonnes
   est COMPTE, jamais deduit du remplissage. La base en pourcentage assortie
   d un flex-grow etirait la derniere carte d une rangee incomplete sur toute
   la largeur : la grille annoncait une mise en avant qu aucune donnee n avait
   demandee, et le meme emplacement visuel se recadrait de deux facons. Des
   pistes comptees laissent la piste vide vide. */
.g2, .g3, .g4 { display: grid; gap: 16px; align-items: stretch; }
.g2 > *, .g3 > *, .g4 > * { min-width: 0; }
.g2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.g3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.g4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 1100px) { .g4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 980px) { .g3 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 720px) {
  .g2, .g3, .g4 { grid-template-columns: minmax(0, 1fr); }
}

/* ---------- primitive image ---------- */
.frame {
  position: relative; overflow: hidden; border-radius: var(--r-img);
  background: var(--fond-2);
  background-image: repeating-linear-gradient(135deg,
    var(--bordure) 0 1px, transparent 1px 11px);
  display: grid; place-items: center; padding: 18px;
  min-height: 190px;
  font-size: 13px; color: var(--texte-doux); text-align: center;
}
.frame img { width: 100%; height: 100%; object-fit: cover; position: absolute; inset: 0; }
/* Dans un conteneur qui impose deja sa hauteur (fond de hero, fond de bande
   CTA, volets de l'avant/apres), le min-height de secours de la primitive
   laisserait l'image a 190px au lieu de couvrir. */
.hero__bg > .frame, .cta__bg > .frame { position: absolute; inset: 0; min-height: 0; border-radius: 0; }

/* ---------- entete : pilule flottante ----------
   Deux etats, comme le clone :
   - CLAIR par defaut. C'est l'etat d'une page sans hero (mentions, blog,
     contact) : la pilule est posee sur un fond clair, l'encre doit etre
     sombre sinon les liens sont invisibles.
   - SUR-HERO : quand l'entete precede directement un hero sombre, elle
     passe en verre et son encre s'inverse. Au-dela de 24px de defilement
     app.js pose .is-scrolle, qui la ramene a l'etat clair. */
.hd { position: fixed; inset-inline: 0; top: 0; z-index: 50; padding-block: 16px; transition: background .25s ease, box-shadow .25s ease; }
.hd__inner { display: flex; align-items: center; justify-content: space-between; gap: 16px; }
.hd__logo { display: inline-flex; align-items: center; gap: 10px; font-family: var(--f-titre); font-size: 18px; color: var(--texte); }
.hd__mark {
  width: 36px; height: 36px; border-radius: var(--r-pill); flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--marque); color: var(--sur-marque);
  font-family: var(--f-titre); font-size: 15px;
}
.hd__nav { display: flex; align-items: center; gap: 2px; padding: 6px; border-radius: var(--r-pill); background: var(--fond-2); border: 1px solid var(--bordure); }
.hd__lien { padding: 9px 16px; border-radius: var(--r-pill); font-size: 14px; color: var(--texte); white-space: nowrap; cursor: pointer; }
.hd__lien:hover { background: var(--fond); }
.hd__cta { flex: none; }
/* Commande de menu : absente au bureau, elle remplace la pilule de nav
   sous 900px. Sa couleur suit le texte, donc le contraste du hero clair. */
.hd__bascule { display: none; width: 42px; height: 42px; padding: 0; flex: none;
  border: 1px solid var(--bordure); border-radius: var(--r-pill); background: var(--fond-2);
  cursor: pointer; flex-direction: column; align-items: center; justify-content: center; gap: 5px; }
.hd__bascule i { display: block; width: 17px; height: 2px; border-radius: 2px; background: currentColor; transition: transform .18s ease, opacity .18s ease; }
.hd--ouvert .hd__bascule i:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.hd--ouvert .hd__bascule i:nth-child(2) { opacity: 0; }
.hd--ouvert .hd__bascule i:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

.hd:has(+ .hero):not(.is-scrolle) { background: transparent; }
.hd:has(+ .hero):not(.is-scrolle) .hd__bascule { color: var(--sur-fonce); background: var(--verre-fort); border-color: var(--trait-fonce); }
.hd:has(+ .hero):not(.is-scrolle) .hd__logo { color: var(--sur-fonce); }
.hd:has(+ .hero):not(.is-scrolle) .hd__nav { background: var(--verre-fort); border-color: var(--trait-fonce); }
.hd:has(+ .hero):not(.is-scrolle) .hd__lien { color: var(--sur-fonce); }
.hd:has(+ .hero):not(.is-scrolle) .hd__lien:hover { background: var(--verre-fort); }
/* REGLE 7 — l entete porte la PAIRE appel + devis. L etat sur-hero inversait
   le logo, la nav et la commande de menu, mais oubliait la seconde porte :
   « Devis gratuit » restait en encre sombre sur une photo sombre, donc
   illisible. Une porte qu on ne voit pas n est pas une porte. */
.hd:has(+ .hero):not(.is-scrolle) .btn--fantome { color: var(--sur-fonce); border-color: var(--trait-fonce); }
.hd:has(+ .hero):not(.is-scrolle) .btn--fantome .btn__fleche { background: var(--sur-fonce); color: var(--accent); }

.hd.is-scrolle {
  background: color-mix(in srgb, var(--fond) 88%, transparent);
  backdrop-filter: blur(14px);
  box-shadow: 0 1px 0 var(--bordure);
}

/* menu deroulant : le panneau reprend la pilule */
.drop { position: relative; }
/* Un lien qui ouvre un volet le DIT : chevron bas dessine par la bordure,
   pivote quand le panneau est la. Jamais un caractere, jamais un emoji. */
.drop .hd__lien { display: inline-flex; align-items: center; gap: 7px; }
.drop__chev {
  width: 7px; height: 7px; border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
  transform: translateY(-2px) rotate(45deg); transition: transform .18s ease;
}
.drop:hover .drop__chev, .drop:focus-within .drop__chev { transform: translateY(1px) rotate(225deg); }
/* Le volet est CENTRE sous sa tete : cale a gauche, un panneau large deborde
   la fenetre des que l entree est du cote droit de la barre. Le decalage sous
   le lien est le `padding-top` du panneau, jamais une marge — sinon la souris
   traverse un vide et le survol retombe. */
.drop__panneau {
  position: absolute; left: 50%; top: 100%; padding-top: 12px;
  opacity: 0; visibility: hidden; transform: translate(-50%, -6px);
  transition: opacity .18s ease, transform .18s ease, visibility .18s;
}
.drop:hover .drop__panneau, .drop:focus-within .drop__panneau { opacity: 1; visibility: visible; transform: translate(-50%, 0); }
.drop__grille {
  background: var(--fond); border: 1px solid var(--bordure); border-radius: var(--r-card-lg);
  padding: 14px; display: flex; align-items: flex-start; gap: 18px;
  min-width: 560px; max-width: min(94vw, 820px);
  box-shadow: 0 30px 70px color-mix(in srgb, var(--accent) 18%, transparent);
}
.drop__liste { display: grid; gap: 2px; align-content: start; flex: 1 1 auto; min-width: 0; }
/* Le titre d une colonne du volet : il vient des donnees, jamais du gabarit. */
.drop__col {
  font-family: var(--f-titre); font-size: 12px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--texte-doux); padding: 6px 14px 8px;
}
/* La vitrine : la carte voltzen en reduction. Son visuel a une hauteur FIXE,
   sinon le `min-height` du cadre etire tout le volet. `flex: 0 0` et non
   `0 1` : une base compressible la reduirait a un mot par ligne. */
.drop__vit { flex: 0 0 250px; display: grid; gap: 8px; align-content: start; padding: 8px 8px 12px; }
.drop__vitPh { min-height: 0; height: 130px; width: 100%; border-radius: var(--r-card); }
.drop__vitN { font-size: 16px; line-height: 1.3; }
.drop__vitX { font-size: 13px; color: var(--texte-doux); line-height: 1.5; }
/* Le libelle reste a l encre du texte : `--marque` est un vert clair, illisible
   sur le fond blanc du volet. La pastille-fleche porte la couleur. */
.drop__vitZ { display: inline-flex; align-items: center; gap: 8px; font-size: 14px; color: var(--texte); justify-self: start; }
.drop__vit .eyebrow { justify-self: start; }
.drop__vitZ .btn__fleche { width: 24px; height: 24px; font-size: 12px; }
.drop__liste a { padding: 10px 14px; border-radius: var(--r-card); font-size: 14px; color: var(--texte); }
.drop__liste a:hover { background: var(--fond-2); }

/* ---------- hero : pleine hauteur, contenu en bas, carte de verre ---------- */
/* F1 — la section porte DEUX etages : la fenetre pleine hauteur, puis le
   socle des atouts, qui commence sous elle. La hauteur pleine est donc
   demandee a la fenetre, plus a la section. */
.hero { position: relative; isolation: isolate; overflow: hidden; background: var(--accent); color: var(--sur-fonce); display: flex; flex-direction: column; }
.hero__bg { position: absolute; inset: 0; z-index: -2; }
.hero__bg img { width: 100%; height: 100%; object-fit: cover; }
.hero__voile {
  position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(to bottom,
    color-mix(in srgb, var(--accent) 45%, transparent) 0%,
    color-mix(in srgb, var(--accent) 35%, transparent) 40%,
    color-mix(in srgb, var(--accent) 88%, transparent) 100%);
}
.hero__inner { display: flex; flex-direction: column; justify-content: space-between; gap: 40px; width: 100%; min-height: 100svh; padding-block: 130px 56px; }
.hero__haut { max-width: 900px; }
.hero__socle-zone { width: 100%; padding-bottom: 64px; }
.hero__grille { display: flex; flex-wrap: wrap; gap: 40px; align-items: flex-end; }
.hero__txt { flex: 1 1 58%; min-width: min(100%, 320px); }
.hero__txt h1 { color: var(--sur-fonce); }
/* Le mot accent du titre. Il est ne dans le hero — scene sombre — ou le lime
   de marque tient sans effort, puis il a ete reemploye dans CINQ titres de
   sections claires ou il tombait a 1,2 contre 1 : le mot le plus important du
   titre etait le moins lisible. Une teinte de sol ne devient pas une encre.
   Sur papier, l accent garde son identite de marque mais s assombrit — un
   melange de la marque et de l encre de page, donc toujours calcule a partir
   des variables que la fabrique change, jamais une couleur ecrite en dur.
   Sur les scenes sombres, le lime reprend sa place, inchange au pixel. */
.hero__accent { color: color-mix(in srgb, var(--marque) 42%, var(--texte)); }
.hero .hero__accent, .sec--fonce .hero__accent, .cta .hero__accent { color: var(--marque); }
.hero__sous { margin-top: 24px; max-width: 560px; font-size: 17px; color: var(--encre-fonce-doux); }
.hero__actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 32px; }
/* REGLE 7 — la boite qui tient la paire appel + devis, partout ou une section
   n'a pas deja sa propre rangee d'actions. */
.actes { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
.actes > * { min-width: 0; }
.hero__carte {
  flex: 1 1 30%; min-width: min(100%, 280px);
  border-radius: var(--r-card-lg); border: 1px solid var(--trait-fonce);
  background: var(--verre); backdrop-filter: blur(12px); padding: 24px;
}
.hero__phrase { margin-top: 12px; font-family: var(--f-titre); font-size: 22px; font-weight: 500; line-height: 1.2; color: var(--sur-fonce); }
/* R3 — une seule largeur par grille. `flex: 1 1 <base>` etire la carte
   orpheline du dernier rang. Des pistes COMPTEES donnent la meme largeur a
   toutes les cartes, quel que soit leur nombre. */
/* T5 — le socle des atouts occupe la LARGEUR DU CONTENEUR, pas la colonne de
   la carte : 1200 px pour trois pistes valent 390 px chacune, ou un corps 28
   dispose de 14 em. Le nombre de pistes est celui des atouts, pose en
   `--n` par le gabarit : compte, jamais devine. */
.hero__socle { display: grid; grid-template-columns: repeat(var(--n, 3), minmax(0, 1fr)); gap: 14px; margin-top: 40px; }
.hero__stat { min-width: 0; border-radius: var(--r-card); background: var(--verre); padding: 16px; }
.hero__stat b { display: block; font-family: var(--f-titre); font-size: 28px; font-weight: 500; color: var(--marque); }
.hero__stat span { display: block; margin-top: 4px; font-size: 12px; color: var(--encre-fonce-doux); }

/* ---------- tete de section : titre a gauche, texte + CTA a droite ---------- */
/* Intro : colonne gauche COLLANTE face a la coulee de texte (Maintenance.tsx,
   lg:sticky lg:top-28). Le collant se desactive seul quand la colonne
   repasse en pleine largeur au point d'arret 900. */
.intro { display: flex; flex-wrap: wrap; gap: 48px; align-items: flex-start; }
.intro > * { min-width: 0; }
.intro__g { flex: 1 1 38%; min-width: min(100%, 280px); position: sticky; top: 112px; }
.intro__d { flex: 1 1 52%; min-width: min(100%, 300px); }
.intro__lead { font-family: var(--f-titre); font-size: clamp(19px, 2.1vw, 24px); font-weight: 400; line-height: 1.45; color: var(--texte); }
.intro__d p + p { margin-top: 16px; }

.tete { display: flex; flex-wrap: wrap; gap: 28px; align-items: flex-end; justify-content: space-between; }
.tete__g { flex: 1 1 48%; min-width: min(100%, 300px); }
.tete__d { flex: 1 1 38%; min-width: min(100%, 280px); }

/* ---------- services : carte haute, image 4/5, pastille posee dessus ---------- */
.svc { display: flex; flex-direction: column; transition: transform .3s ease; }
.svc:hover { transform: translateY(-4px); }
/* Le ratio 4/5 est celui du clone. Le plafond de hauteur ne le contredit pas :
   il ne mord QUE quand une carte occupe une ligne entiere (compte d'items non
   multiple du nombre de colonnes — cas legitime, le compte vient des donnees).
   Sans lui, une carte orpheline etiree produirait une image de 1600px de haut.
   A largeur de colonne nominale (~300px) la hauteur vaut ~375px : jamais atteint. */
.svc__img { position: relative; aspect-ratio: 4 / 5; max-height: 400px; min-height: 0; border-radius: 0; }
/* La primitive image porte un min-height de secours ; dans un conteneur qui
   impose deja un ratio, ce secours laisserait un vide sous le cadre. */
.svc__img > .frame { position: absolute; inset: 0; min-height: 0; }
.svc__num { position: absolute; left: 16px; top: 16px; z-index: 2; }
.svc__corps { display: flex; flex-direction: column; gap: 12px; padding: 20px; flex: 1; }
.svc__lien { margin-top: auto; padding-top: 12px; display: inline-flex; align-items: center; gap: 8px; font-size: 14px; font-weight: 500; }

/* ---------- materiel : intitule collant a gauche, cartes a droite ----------
   Patron natif de la reference (colonne d'intitule + grille de cartes). Le
   compte de cartes vient des donnees : flex-wrap et une base en pourcentage,
   jamais un nombre de colonnes fixe. La colonne ne devient collante qu'a
   partir du moment ou les deux colonnes tiennent cote a cote. */
.mat-duo { display: flex; flex-wrap: wrap; gap: 40px; align-items: flex-start; }
.mat-duo__intitule { flex: 1 1 34%; min-width: min(100%, 300px); }
.mats { flex: 1 1 52%; min-width: min(100%, 300px); display: flex; flex-wrap: wrap; gap: 16px; }
.mat { flex: 1 1 44%; min-width: min(100%, 240px); padding: 24px; }
.mat__vig { width: 64px; height: 64px; min-height: 0; border-radius: var(--r-img); overflow: hidden; }
.mat__titre { margin: 20px 0 10px; }
@media (min-width: 1000px) { .mat-duo__intitule { position: sticky; top: 104px; } }

/* ---------- blocs SEO texte+image alternes ---------- */
.bloc { display: flex; flex-wrap: wrap; gap: 44px; align-items: center; margin-top: 56px; }
.bloc > * { min-width: 0; }
.bloc__txt { flex: 1 1 46%; min-width: min(100%, 300px); }
.bloc .frame { flex: 1 1 44%; min-width: min(100%, 280px); min-height: 380px; border-radius: var(--r-card-lg); }
.bloc--inv .frame { order: -1; }
.bloc p + p { margin-top: 16px; }
.bloc__lien { display: inline-flex; align-items: center; gap: 8px; margin-top: 24px; font-weight: 500; }

/* ---------- atouts ---------- */
.feats { display: flex; flex-wrap: wrap; gap: 20px; margin-top: 48px; }
.feat { flex: 1 1 45%; min-width: min(100%, 240px); display: flex; gap: 14px; align-items: flex-start; }
.feat .num { width: 30px; height: 30px; font-size: 13px; }

/* ---------- bandeau defilant ---------- */
.marquee { overflow: hidden; }
.marquee__track { display: flex; width: max-content; gap: 16px; animation: defile 38s linear infinite; }
.marquee__item {
  border: 1px solid var(--bordure); border-radius: var(--r-card-lg);
  padding: 14px 22px; font-family: var(--f-titre); font-size: 15px;
  color: var(--texte-doux); white-space: nowrap; flex: none;
}
.sec--fonce .marquee__item { border-color: var(--trait-fonce); background: var(--verre); color: var(--encre-fonce-doux); }
@keyframes defile { to { transform: translateX(-50%); } }

/* ---------- secteurs B2B ---------- */
/* R3 — une seule largeur par grille. `flex: 1 1 <base>` etire la carte
   orpheline du dernier rang. Des pistes COMPTEES donnent la meme largeur a
   toutes les cartes, quel que soit leur nombre. */
.b2b { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; margin-top: 48px; }
.b2b > * { min-width: 0; }
.b2b__carte { min-width: 0; position: relative; overflow: hidden; padding: 28px; border-radius: var(--r-card); border: 1px solid var(--bordure); background: var(--fond); }
.b2b__num { font-size: 12px; text-transform: uppercase; letter-spacing: .18em; color: var(--texte-doux); }
/* Une image portee par un secteur : elle coiffe la carte, bord a bord,
   en annulant le padding de la carte. */
.b2b__img { margin: -28px -28px 22px; }
.b2b__img > .frame { height: 190px; min-height: 190px; border-radius: var(--r-card) var(--r-card) 0 0; }
.b2b__halo { position: absolute; right: -40px; bottom: -40px; width: 160px; height: 160px; border-radius: var(--r-pill); background: color-mix(in srgb, var(--marque) 22%, transparent); filter: blur(34px); }

/* ---------- zones ---------- */
/* Rangees bordees numerotees, pas des pastilles : c'est la ligne de chiffres
   de HowItWorks.tsx (flex items-baseline justify-between rounded-2xl border). */
.zones { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 36px; }
.zones > * { min-width: 0; }
.zone-ligne {
  flex: 1 1 46%; min-width: min(100%, 280px);
  display: flex; align-items: baseline; gap: 14px;
  padding: 16px 20px; border-radius: var(--r-card);
  border: 1px solid var(--bordure); background: var(--fond); font-size: 15px;
}
.zone-ligne__num { font-size: 12px; letter-spacing: .18em; color: var(--texte-doux); flex: none; }
.zone-ligne__nom { font-family: var(--f-titre); font-weight: 500; min-width: 0; overflow-wrap: anywhere; }
.zone-ligne__fl { margin-left: auto; flex: none; color: var(--texte-doux); }
.zone-ligne:hover { border-color: var(--marque); background: var(--fond-2); }
.zone-ligne:hover .zone-ligne__fl { color: var(--marque); }
.zone-bande { display: flex; flex-wrap: wrap; gap: 16px; margin-top: 36px; }
.zone-bande .frame { flex: 1 1 30%; min-width: min(100%, 250px); height: 200px; min-height: 200px; border-radius: var(--r-card-lg); }

/* ---------- etapes ---------- */
.etapes { display: flex; flex-wrap: wrap; gap: 16px; margin-top: 48px; list-style: none; }
.etape { flex: 1 1 30%; min-width: min(100%, 270px); position: relative; overflow: hidden; padding: 28px; border-radius: var(--r-card); }
.etape__haut { display: flex; align-items: center; gap: 14px; }
.etape h3 { margin-top: 26px; }
.etape p { margin-top: 12px; }
.etape__halo { position: absolute; right: -40px; bottom: -40px; width: 160px; height: 160px; border-radius: var(--r-pill); background: color-mix(in srgb, var(--marque) 18%, transparent); filter: blur(34px); }

/* ---------- chiffres : rangee de cases ---------- */
/* Tuiles empilees, mise en page native : la mesure au-dessus, la mention en
   dessous, l ensemble aligne a gauche. Jamais valeur et mention sur la meme
   ligne — c est la disposition d une coquille voisine, pas de la reference. */
.chiffres-panneau { display: grid; gap: 24px; }
.chiffres__vue { border-radius: var(--r-card-lg); min-height: 280px; }
.chiffres { display: flex; flex-wrap: wrap; gap: 16px; list-style: none; }
.chiffre {
  flex: 1 1 22%; min-width: min(100%, 200px);
  padding: 20px 24px; border-radius: var(--r-card-lg);
  border: 1px solid var(--bordure); background: var(--fond);
}
.chiffre__val { font-family: var(--f-titre); font-size: 30px; font-weight: 500; color: var(--texte); }
.chiffre__lib { margin-top: 6px; font-size: 13px; color: var(--texte-doux); }
.sec--fonce .chiffre { background: var(--verre); border-color: var(--trait-fonce); }
.sec--fonce .chiffre__val { color: var(--marque); }
.sec--fonce .chiffre__lib { color: var(--encre-fonce-doux); }

/* ---------- carte locale ---------- */
/* Carte flottante qui chevauche le bas de l'image, comme la barre de chiffres
   de WhoWeAre.tsx (absolute -bottom-6 left-6 right-6). Jamais deux colonnes
   cote a cote. Decalage en inset-inline, jamais en left/right negatifs. */
.loc { margin-top: 44px; }
.loc__vue { position: relative; padding-bottom: 40px; }
.loc__vue > .frame { min-height: 420px; border-radius: var(--r-card-lg); }
.loc__carte {
  position: absolute; bottom: 0; inset-inline: 28px;
  padding: 26px 30px; border-radius: var(--r-card-lg);
  border: 1px solid var(--bordure); background: var(--fond);
  box-shadow: 0 18px 44px rgba(0, 0, 0, .10);
}
.loc__carte p { margin-bottom: 6px; }
.loc__carte p:last-child { margin-bottom: 0; }
.loc__phare { font-family: var(--f-titre); font-size: clamp(19px, 2vw, 24px); font-weight: 500; line-height: 1.2; overflow-wrap: anywhere; }
.loc__chips { margin-top: 28px; }

/* ---------- avis : bandeau defilant de cartes ---------- */
.avis-piste { overflow: hidden; margin-top: 48px; }
.avis-piste__track { display: flex; width: max-content; gap: 16px; animation: defile 46s linear infinite; }
.avis { flex: none; width: 320px; max-width: 86vw; padding: 24px; border-radius: var(--r-card); }
.avis__etoiles { color: var(--marque); letter-spacing: 3px; font-size: 14px; }
.avis__cite { margin-top: 20px; overflow-wrap: anywhere; }
.avis__pied { display: flex; align-items: center; gap: 12px; margin-top: 24px; padding-top: 20px; border-top: 1px solid var(--trait-fonce); }
.avis__portrait { width: 40px; height: 40px; border-radius: var(--r-pill); flex: none; overflow: hidden; }
.avis__portrait img { width: 100%; height: 100%; object-fit: cover; }
.avis__qui { display: grid; min-width: 0; }
.avis__av { width: 40px; height: 40px; border-radius: var(--r-pill); flex: none; display: grid; place-items: center; background: var(--marque); color: var(--sur-marque); font-family: var(--f-titre); font-size: 15px; }
.avis__nom { font-size: 14px; font-weight: 500; }
.avis__role { font-size: 12px; color: var(--encre-fonce-faible); }

/* ---------- realisations : une grande + une colonne ---------- */
.reas { display: flex; flex-wrap: wrap; gap: 16px; margin-top: 48px; }
.reas > * { min-width: 0; }
.rea-une { flex: 1 1 56%; min-width: min(100%, 300px); position: relative; }
.rea-une .frame { aspect-ratio: 4 / 3; min-height: 260px; border-radius: var(--r-card-lg); }
.rea-une__pave {
  position: absolute; inset-inline: 20px; bottom: 20px;
  display: flex; align-items: flex-end; justify-content: space-between; gap: 16px;
  padding: 18px; border-radius: var(--r-card); background: var(--fond);
}
.rea-une__rond { width: 46px; height: 46px; flex: none; border-radius: var(--r-pill); background: var(--marque); color: var(--sur-marque); display: grid; place-items: center; }
.rea-liste { flex: 1 1 34%; min-width: min(100%, 280px); display: flex; flex-direction: column; gap: 16px; }
.rea { display: flex; gap: 14px; padding: 12px; border-radius: var(--r-card); border: 1px solid var(--bordure); background: var(--fond); }
.rea .frame { width: 110px; height: 90px; min-height: 90px; flex: none; border-radius: var(--r-img); padding: 6px; font-size: 11px; }
.rea__corps { min-width: 0; display: flex; flex-direction: column; justify-content: center; gap: 6px; }

/* ---------- FAQ ---------- */
/* Accordeon pleine largeur numerote sous une tete de section, jamais loge
   dans la colonne droite d'un duo tete__g / tete__d. */
.faq { display: grid; gap: 12px; margin-top: 44px; }
.faq-item { border: 1px solid var(--bordure); border-radius: var(--r-card); background: var(--fond); padding: 20px 24px; }
.faq-item summary {
  list-style: none; cursor: pointer; display: flex; align-items: center; justify-content: space-between; gap: 18px;
  font-family: var(--f-titre); font-size: 17px; font-weight: 500; color: var(--texte);
}
.faq-item__num { font-family: var(--f-titre); font-size: 12px; letter-spacing: .18em; color: var(--texte-doux); flex: none; margin-right: 16px; }
.faq-item__q { flex: 1; min-width: 0; overflow-wrap: anywhere; }
/* `--marque` est un vert lime pense comme SOL : partout ailleurs il porte
   `--sur-marque` par-dessus (pastille, bouton, croix de la FAQ). Employe ici
   comme ENCRE sur la carte blanche, il tombait a 1,3 contre 1 — le numero de
   la question ouverte disparaissait. L etat ouvert se marque par la force de
   l encre de page, pas en empruntant une couleur de fond. Une teinte de sol
   ne devient pas une encre. */
.faq-item[open] .faq-item__num { color: var(--texte); }
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after {
  content: "+"; flex: none; width: 30px; height: 30px; border-radius: var(--r-pill);
  background: var(--fond-2); color: var(--texte);
  display: grid; place-items: center; font-size: 18px; transition: transform .22s ease;
}
.faq-item[open] summary::after { transform: rotate(45deg); background: var(--marque); color: var(--sur-marque); }
.faq-item p { margin-top: 14px; color: var(--texte-doux); }
/* L'encart de fin de FAQ : une carte a part, jamais un item deguise. */
.faq-encart { margin-top: 28px; padding: 28px; }
.faq-encart h4 { font-family: var(--f-titre); font-size: 20px; line-height: 1.25; }

/* ---------- maillage ---------- */
.liens { display: flex; flex-wrap: wrap; gap: 16px; margin-top: 40px; }
.liens > * { min-width: 0; }
.lien-card { flex: 1 1 30%; min-width: min(100%, 260px); display: flex; flex-direction: column; gap: 10px; padding: 22px; border-radius: var(--r-card); border: 1px solid var(--bordure); background: var(--fond); transition: transform .25s ease; }
.lien-card:hover { transform: translateY(-3px); }
.lien-card__img { margin: -22px -22px 6px; }
.lien-card__img > .frame { height: 150px; min-height: 150px; border-radius: var(--r-card) var(--r-card) 0 0; }
.lien-card__meta { margin-top: auto; padding-top: 12px; font-size: 13px; color: var(--texte-doux); display: inline-flex; align-items: center; gap: 8px; }

/* ---------- bande CTA ---------- */
.cta { position: relative; isolation: isolate; overflow: hidden; border-radius: var(--r-card-lg); padding: clamp(40px, 6vw, 72px); background: var(--accent); color: var(--sur-fonce); }
.cta__bg { position: absolute; inset: 0; z-index: -2; }
.cta__bg img { width: 100%; height: 100%; object-fit: cover; }
.cta__voile { position: absolute; inset: 0; z-index: -1; background: color-mix(in srgb, var(--accent) 86%, transparent); }
.cta__grille { display: flex; flex-wrap: wrap; gap: 32px; align-items: center; justify-content: space-between; }
.cta__txt { flex: 1 1 52%; min-width: min(100%, 300px); }
.cta__form { flex: 1 1 36%; min-width: min(100%, 280px); }

/* ---------- urgence ---------- */
/* Panneau sombre a halo avec une carte de verre : le couple hero/CtaBanner du
   clone (rounded-[32px] sombre + halo lime floute), pas une boite claire. */
.urgence {
  position: relative; overflow: hidden;
  display: flex; flex-wrap: wrap; gap: 32px; align-items: center;
  padding: clamp(28px, 4vw, 52px); border-radius: var(--r-card-lg);
  background: var(--accent); color: var(--sur-fonce);
}
.urgence > * { min-width: 0; }
.urgence__halo { position: absolute; right: -60px; top: -60px; width: 320px; height: 320px; border-radius: var(--r-pill); background: color-mix(in srgb, var(--marque) 30%, transparent); filter: blur(34px); }
.urgence__txt { position: relative; flex: 1 1 52%; min-width: min(100%, 300px); }
.urgence__txt h2, .urgence__txt .h2 { color: var(--sur-fonce); }
.urgence__txt .body { color: var(--encre-fonce-doux); }
.urgence__txt .sur-titre { color: var(--encre-fonce-faible); }
.urgence__txt .puces li { color: var(--encre-fonce-doux); }
.urgence__pave {
  position: relative; flex: 1 1 30%; min-width: min(100%, 260px);
  padding: 30px; border-radius: var(--r-card);
  background: var(--verre); border: 1px solid var(--trait-fonce);
}
.urgence__tel { display: inline-block; font-family: var(--f-titre); font-size: clamp(26px, 3vw, 40px); font-weight: 500; line-height: 1.05; color: var(--sur-fonce); overflow-wrap: anywhere; }

/* ---------- contact ---------- */
.contact { display: flex; flex-wrap: wrap; gap: 24px; align-items: flex-start; margin-top: 44px; }
.contact > * { min-width: 0; }
.contact__form { flex: 1 1 55%; min-width: min(100%, 320px); }
.contact__col { flex: 1 1 32%; min-width: min(100%, 280px); display: grid; gap: 16px; }
/* R3 — une seule largeur par grille. `flex: 1 1 <base>` etire la carte
   orpheline du dernier rang. Des pistes COMPTEES donnent la meme largeur a
   toutes les cartes, quel que soit leur nombre. */
.champs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; margin-top: 8px; }
.champ { min-width: 0; display: grid; gap: 7px; font-size: 13px; color: var(--texte-doux); }
/* Le pied du formulaire porte desormais DEUX portes — l appel et l envoi,
   cote a cote (regle 7). Elles se replient a plat sur les fenetres etroites
   au lieu de deborder : c est la boite qui tient l alignement, pas la donnee. */
.champ--long, .champs > .champs__pied { grid-column: 1 / -1; }
.champs__pied { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
.champ input, .champ textarea {
  font: inherit; font-size: 15px; color: var(--texte);
  padding: 13px 16px; border-radius: var(--r-card); border: 1px solid var(--bordure); background: var(--fond);
}
.champ textarea { min-height: 130px; resize: vertical; }
.cta .champ { color: var(--encre-fonce-doux); }
.cta .champ input, .cta .champ textarea { background: var(--verre); border-color: var(--trait-fonce); color: var(--sur-fonce); }

/* ---------- blog ---------- */
.art__hero { padding-top: 150px; padding-bottom: 40px; background: var(--fond-2); }
.art { display: flex; flex-wrap: wrap; gap: 44px; align-items: flex-start; margin-top: 44px; }
.art > * { min-width: 0; }
.art__som { flex: 1 1 26%; min-width: min(100%, 250px); position: sticky; top: 100px; padding: 22px; border-radius: var(--r-card-lg); border: 1px solid var(--bordure); background: var(--fond-2); }
.art__som ol { margin: 12px 0 0; padding-left: 18px; display: grid; gap: 9px; font-size: 14px; color: var(--texte-doux); }
.art__corps { flex: 1 1 62%; min-width: min(100%, 300px); }
.art__corps h2 { margin-top: 44px; }
.art__corps h3 { margin-top: 32px; }
.art__corps p { margin-top: 16px; color: var(--texte-doux); }
.art__corps ul { margin-top: 16px; padding-left: 20px; color: var(--texte-doux); display: grid; gap: 9px; }
.art__encadre { margin-top: 28px; padding: 24px; border-radius: var(--r-card); background: var(--fond-2); border-left: 4px solid var(--marque); }
.art__corps .frame { margin-top: 28px; min-height: 300px; border-radius: var(--r-card-lg); }

/* ---------- legal ---------- */
/* Colonne centree etroite, blocs numerotes sans filet : LegalShell.tsx. */
.legal-sec { padding-top: 150px; }
.legal { max-width: 760px; margin-inline: auto; display: grid; gap: 40px; }
.legal__tete { padding-bottom: 8px; }
.legal__maj { margin-top: 14px; }
.legal__bloc { display: flex; gap: 20px; align-items: flex-start; }
.legal__bloc > * { min-width: 0; }
.legal__corps { flex: 1; min-width: 0; }
.legal__bloc h2 { font-size: clamp(20px, 2vw, 26px); }
.legal__bloc p { margin-top: 14px; color: var(--texte-doux); }

/* ---------- fil d'ariane ---------- */
/* Chaine en capitales espacees, separateur en barre oblique attenuee :
   le fil de PageHeader.tsx, transpose sur fond clair. */
.fil { padding-top: 130px; }
.fil__chaine { display: flex; flex-wrap: wrap; align-items: baseline; font-size: 12px; text-transform: uppercase; letter-spacing: .18em; color: var(--texte-doux); }
.fil__pas { display: inline-flex; align-items: baseline; min-width: 0; overflow-wrap: anywhere; }
.fil__sep { margin-inline: 10px; opacity: .45; }
.fil__ici { color: var(--texte); }
.fil a:hover { color: var(--marque); }

/* ---------- pied ---------- */
.footer { background: var(--accent); color: var(--sur-fonce); padding-block: 80px 32px; }
.footer h4 { color: var(--sur-fonce); }
.footer a { color: var(--encre-fonce-doux); }
.footer a:hover { color: var(--marque); }
/* Colonne de marque large qui porte AUSSI le NAP, en paires
   libelle-capitales / valeur : Footer.tsx (lg:grid-cols-[1.4fr_1fr_1fr]). */
.footer__grille { display: flex; flex-wrap: wrap; gap: 40px; }
.footer__grille > * { min-width: 0; }
.footer__marque-col { flex: 1 1 40%; min-width: min(100%, 300px); }
.footer__col { flex: 1 1 22%; min-width: min(100%, 180px); }
.footer__marque { display: inline-flex; align-items: center; gap: 10px; font-family: var(--f-titre); font-size: 20px; color: var(--sur-fonce); margin-bottom: 16px; }
.footer__phrase { font-family: var(--f-titre); font-size: clamp(20px, 2.4vw, 28px); font-weight: 400; line-height: 1.25; color: var(--sur-fonce); max-width: 30ch; }
.footer .body { color: var(--encre-fonce-doux); }
.footer .sur-titre { color: var(--encre-fonce-faible); }
.footer__liste { list-style: none; margin: 16px 0 0; padding: 0; display: grid; gap: 10px; font-size: 14px; }
.footer__nap { margin-top: 32px; }
.footer__nap-grille { display: flex; flex-wrap: wrap; gap: 12px 32px; margin-top: 14px; }
.footer__nap-case { flex: 1 1 40%; min-width: min(100%, 200px); font-size: 14px; color: var(--encre-fonce-doux); overflow-wrap: anywhere; }
.footer__bas { margin-top: 56px; padding-top: 24px; border-top: 1px solid var(--trait-fonce); display: flex; flex-wrap: wrap; gap: 16px; justify-content: space-between; font-size: 13px; color: var(--encre-fonce-faible); }
.footer__bas-liens { display: flex; flex-wrap: wrap; gap: 20px; }

/* ============================================================
   AVANT / APRES — deux photos superposees, decoupe par --pos,
   pilotee par un input range en overlay (souris, tactile, clavier).
   ============================================================ */
/* Cas d'avant/apres : l'intitule ouvre le cas, la vue vient ensuite. Le compte
   par ligne vient des donnees — base en pourcentage et repli a plat. */
.abs { display: flex; flex-wrap: wrap; gap: 32px; margin-top: 40px; }
.ab-cas { flex: 1 1 44%; min-width: min(100%, 300px); margin: 0; }
.ab-cas__repere { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
.ab__titre { min-width: 0; }
.ab-cas__texte { margin-top: 10px; }
.ab { position: relative; --pos: 50%; aspect-ratio: 4 / 3; overflow: hidden; border-radius: var(--r-card-lg); touch-action: pan-y; margin-top: 20px; }
.ab__vue { position: absolute; inset: 0; }
.ab__vue .frame { width: 100%; height: 100%; border-radius: 0; min-height: 0; }
.ab__vue--avant { clip-path: inset(0 calc(100% - var(--pos)) 0 0); z-index: 2; }
/* Les deux libelles et la poignee voyagent avec le filet : ils en sont les
   enfants, poses de part et d'autre a hauteur de poignee. Le debordement
   eventuel aux extremites de la course est clippe par .ab (overflow hidden). */
.ab__barre { position: absolute; top: 0; bottom: 0; left: var(--pos); width: 2px; margin-left: -1px; background: var(--fond); z-index: 3; }
.ab__lab { position: absolute; top: 50%; z-index: 4; margin-top: -13px; padding: 7px 15px; border-radius: var(--r-pill); font-size: 12px; font-weight: 500; white-space: nowrap; text-transform: uppercase; letter-spacing: .06em; background: var(--fond); color: var(--texte); }
.ab__lab--avant { right: 34px; }
.ab__lab--apres { left: 34px; background: var(--marque); color: var(--sur-marque); }
.ab__poignee {
  position: absolute; top: 50%; left: 1px; z-index: 4;
  width: 44px; height: 44px; margin: -22px 0 0 -22px;
  border-radius: var(--r-pill); background: var(--fond); color: var(--texte);
  display: grid; place-items: center; font-size: 15px;
  box-shadow: 0 8px 24px color-mix(in srgb, var(--accent) 30%, transparent);
}
.ab__range { position: absolute; inset: 0; z-index: 5; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: ew-resize; -webkit-appearance: none; appearance: none; background: transparent; }
.ab__range::-webkit-slider-thumb { -webkit-appearance: none; width: 46px; height: 100%; cursor: ew-resize; }
.ab__range::-moz-range-thumb { width: 46px; height: 100%; border: 0; background: transparent; cursor: ew-resize; }
.ab__range:focus-visible { opacity: 1; outline: 3px solid var(--marque); outline-offset: 3px; }

/* ============================================================
   FACETTES / PRODUITS / SPECS
   Aucun compte de colonnes fige : flex-wrap + flex-basis, et
   min-width:0 sur les enfants pour qu'un libelle long ne pousse
   jamais la grille hors de la fenetre.
   ============================================================ */
.fac { display: flex; flex-wrap: wrap; gap: 12px; }
.fac__i {
  display: inline-flex; align-items: center; gap: 12px; min-width: 0;
  padding: 12px 22px 12px 12px; border-radius: var(--r-pill);
  border: 1px solid var(--bordure); background: var(--fond);
  color: var(--texte); font-size: 15px; font-weight: 500;
}
.fac__i .num { flex: none; }
a.fac__i:hover { border-color: var(--marque); }
.fac__i--ici { background: var(--marque); border-color: var(--marque); color: var(--sur-marque); font-weight: 700; }
.fac__i--ici .num { background: var(--sur-marque); color: var(--marque); }

.prod__prix { margin-top: 4px; }
.prod__chiffre { font-family: var(--f-titre); font-size: 30px; line-height: 1.1; margin-top: 4px; }
.prod__chiffre--grand { font-size: 42px; }
.prod .svc__lien { padding-top: 16px; }

.specs { margin: 0; }
.spec { display: flex; flex-direction: column; align-items: flex-start; gap: 10px; padding: 26px; }
.spec__v { margin: 0; font-family: var(--f-titre); font-size: 26px; line-height: 1.15; min-width: 0; }
.spec__l { color: var(--texte-doux); font-size: 14px; text-transform: uppercase; letter-spacing: .12em; min-width: 0; }

/* ============================================================
   POINTS D'ARRET — ceux du clone : 1080 / 900 / 640
   ============================================================ */
@media (max-width: 1080px) {
  .hero__inner { padding-block: 120px 44px; }
  .bloc { gap: 28px; }
}

@media (max-width: 900px) {
  /* R3 — le nombre de pistes se DECLARE a chaque palier. */
  .b2b { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* La pilule de nav se replie derriere la commande : elle redescend sous
     l'entete, en colonne, avec les deroulants deplies en flux — au doigt,
     le survol n'existe pas. Fond opaque impose : l'entete est transparente
     au-dessus du hero. */
  .hd__bascule { display: flex; }
  .hd__nav { display: none; position: absolute; top: 100%; left: 16px; right: 16px;
    flex-direction: column; align-items: stretch; gap: 2px; padding: 12px;
    border-radius: var(--r-card-lg); background: var(--fond); border: 1px solid var(--bordure);
    box-shadow: var(--ombre); max-height: calc(100vh - 110px); overflow-y: auto; }
  .hd--ouvert .hd__nav { display: flex; }
  .hd:has(+ .hero):not(.is-scrolle) .hd__nav { background: var(--fond); border-color: var(--bordure); }
  .hd:has(+ .hero):not(.is-scrolle) .hd__nav .hd__lien { color: var(--texte); }
  .drop { position: static; }
  .drop__chev { display: none; }
  .drop__panneau { position: static; opacity: 1; visibility: visible; transform: none;
    min-width: 0; padding: 0 0 4px 12px; }
  .drop__grille { display: block; background: none; border: 0; box-shadow: none; padding: 0;
    min-width: 0; max-width: none; }
  .drop__liste { background: none; border: 0; box-shadow: none; padding: 0; }
  /* La vitrine est un confort d ecran large : au doigt, elle pousserait les
     liens hors de vue. Le volet redescend a la liste seule. */
  .drop__vit { display: none; }
  .art__som { position: static; }
  .avis { width: 300px; }
  /* Une colonne collante n'a plus de sens des qu'elle occupe toute la largeur. */
  .intro__g { position: static; top: auto; }
}

@media (max-width: 640px) {
  .b2b, .champs { grid-template-columns: minmax(0, 1fr); }
  /* Le panneau du deroulant reste AFFICHE : replie dans le menu, il porte
     le seul acces aux pages enfants. */
  .sec { padding-block: 56px; }
  .hero__inner { padding-block: 104px 40px; }
  .hero__grille, .bloc, .tete, .intro, .contact, .cta__grille, .urgence, .art, .footer__grille { gap: 24px; }
  .hero__txt, .hero__carte, .bloc__txt, .bloc .frame, .tete__g, .tete__d,
  .intro__g, .intro__d, .urgence__txt, .urgence__pave, .zone-ligne,
  .footer__marque-col, .footer__col, .footer__nap-case, .contact__form, .contact__col,
  .cta__txt, .cta__form, .art__som, .art__corps, .rea-une, .rea-liste { flex-basis: 100%; }
  .cta { padding: 32px 24px; }
  .rea-une__pave { position: static; inset: auto; margin-top: 12px; }
  /* La carte d'adresse cesse de chevaucher l'image : plus de place en dessous. */
  .loc__vue { padding-bottom: 0; }
  .loc__carte { position: static; inset: auto; margin-top: 12px; }
  .footer__bas { flex-direction: column; }
}

/* Tres etroit : la carte de realisation garde une vignette de 110px a cote du
   texte, qui tombe alors sous 170px et casse les titres en un mot par ligne.
   Elle passe donc en colonne, vignette pleine largeur au-dessus du corps. */
/* Entre les deux : trois pistes dans 660 px tomberaient a 220 px, soit moins
   de huit em pour un corps 28. On passe a deux, comptees. */
@media (max-width: 860px) {
  .hero__socle { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 430px) {
  .hero__socle { grid-template-columns: minmax(0, 1fr); }
  .rea { flex-direction: column; }
  .rea .frame { width: 100%; height: 140px; min-height: 140px; }
}

/* ================= SIGNATURES DE FORME =================
   Traits releves EN LIGNE sur voltzen.framer.website. CSS pur.
   Documentation lisible : voltzen/signatures.md */

/* SIGNATURE — le RAYON UNIQUE DE 12px (x78) : quatre pieces arrondies sur
   cinq portent exactement cette valeur. Le modele ne module pas sa
   courbure, il la repete. */
.carte, .svc, .etape, .b2b__carte, .loc__carte, .mat__vig, .rea__corps,
.lien-card, .faq-item, .spec, .chiffres-panneau { border-radius: 12px; }
.chip, .fac__i, .avis__etoiles { border-radius: 11px; }

/* SIGNATURE — la PILULE LONGUE tient le second rang (100px x20, 99px x3),
   et le DISQUE la suit de pres (100% x18) : les deux extremes coexistent,
   sans rien entre eux et les 12px. */
.chips li, .loc__chips li, .eyebrow, .btn--fantome { border-radius: 100px; }
.svc__num, .etape__haut .num, .b2b__num, .avis__av, .faq-item__num { border-radius: 100%; }

/* SIGNATURE — l ARRONDI DU SEUL COTE GAUCHE (`2px 0 0 2px`, x4). Trait rare
   et tres reconnaissable : la piece est adoucie a l entree et coupee net a
   la sortie, dans le sens de lecture. */
.zone-ligne, .fil__pas, .spec__l, .avis__cite { border-radius: 2px 0 0 2px; }

/* SIGNATURE — LE MODELE EST PLAT : le releve ne trouve AUCUN degrade. La
   nuit se pose en aplat, jamais en voile degrade. */
.hero__voile, .cta__voile { background: color-mix(in srgb, var(--texte) 44%, transparent); }

/* SIGNATURE — l ombre est MINUSCULE (`0 1px 2px` a 25 pour cent, x1) : la
   profondeur passe par le contour, pas par la chute. */
.carte, .svc { box-shadow: 0 1px 2px 0 color-mix(in srgb, var(--texte) 25%, transparent); }

/* SIGNATURE — le CONTOUR INTERNE net d un pixel (x2), en regles distinctes. */
.carte { position: relative; }
.carte::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  border-radius: inherit;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--texte) 10%, transparent);
}
.svc { position: relative; }
.svc::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  border-radius: inherit;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--texte) 8%, transparent);
}
.etape { position: relative; }
.etape::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  border-radius: inherit;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--texte) 7%, transparent);
}
.mat__vig { position: relative; }
.mat__vig::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  border-radius: inherit;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--texte) 7%, transparent);
}

/* SIGNATURE — le seul fondu du modele monte par le bas et n agit que sur le
   dernier tiers (`transparent 65% -> plein 100%`). */
.hero__bg {
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 65%, #000 100%);
  mask-image: linear-gradient(180deg, transparent 0, #000 65%, #000 100%);
}
.chiffres__vue {
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 60%, #000 100%);
  mask-image: linear-gradient(180deg, transparent 0, #000 60%, #000 100%);
}

/* >>> NORME COQUILLE — cadre vide (pose par _lib/poser-cadre-vide.mjs) */
/* ============================================================
   NORME COQUILLE — LE CADRE VIDE PORTE SON ENCRE (R4b)
   ------------------------------------------------------------
   R4 dit depuis toujours que le cadre VIDE et le cadre REMPLI sont deux
   etats TENABLES. Seule la moitie basse etait mesuree : « le cadre vide ne
   s effondre pas sous 24 px ». Personne ne mesurait la moitie haute : « le
   cadre vide reste tenable quand il est GRAND ».

   C est la faute qu Angelo a vue le 22 aout 2026. Il n a pas vu une
   composition fausse — les bandes de reference le prouvent : le hero de
   roofer est bien une photo plein cadre avec le texte ecrit dessus, et le
   cadre de plumbfixx mesure 5,5 colonnes sur 12 la ou le modele en prend 7.
   Il a vu l ETAT VIDE : un mur blanc de 800 x 750 px portant une lettre
   perdue. La coquille n embarque aucune photo — c est la regle — donc l
   etat vide n est pas un accident de fixture, c est l etat NORMAL d une
   coquille au repos. Il devait etre dessine, il ne l avait jamais ete.

   Ce fichier le dessine, UNE fois, pour toutes les coquilles. Il ne touche
   ni `display`, ni `position`, ni `overflow`, ni aucune boite : la
   geometrie de chaque modele est deja jugee par F1/F2 et par R2/R3, on n y
   revient pas. Il ne pose que de la peinture et de l encre.

   Le crochet est volontairement AGRAMMATICAL : `[data-slot]` sans image
   dedans. Les sept coquilles nomment leur cadre `kr-vue--nue`, `pf-ph--nu`,
   `ig--nu`, ou ne le nomment pas du tout — s appuyer sur ces noms, c est
   ecrire sept correctifs a la main, puis trente-sept. `data-slot` est pose
   par R1 sur TOUS les cadres de TOUTES les coquilles : c est le seul point
   d appui qui passe a l echelle.

   Les quatre couleurs sont des variables : la fabrique les change comme elle
   change une palette.

   LA TEINTE SE DECIDE PAR CADRE, PAS PAR COQUILLE. C est la faute qu Angelo
   a vue le 22 aout 2026 sur plumfixx : la coquille avait ete teintee SOMBRE
   en bloc, parce que son hero ecrit en blanc — sauf que ce blanc repose sur
   l aplat bleu de la SECTION, pas sur le cadre. Le placeholder lateral, qui
   ne porte aucune encre, devenait une dalle noire de 800 x 750 px au milieu
   d une page claire. Un placeholder qui ne porte rien n a aucune raison
   d etre sombre.

   Le defaut est donc CLAIR : un emplacement en attente se lit comme une
   carte grise, c est la convention de tout le metier, et c est la version
   qu Angelo avait validee. Seuls les cadres PORTEURS — ceux sur lesquels de
   l encre repose vraiment, hero pleine fenetre sous son voile — prennent la
   teinte que leur encre exige. Ces cadres-la sont trouves par la MESURE, pas
   a la main : `_lib/teinter-cadres.mjs` ouvre les pages rendues, regarde
   quelle encre tombe dans quel cadre, et ecrit la liste en queue du
   `style.css` de la coquille. R4b verifie ensuite le resultat sur les pixels.
   ============================================================ */

:root {
  --cadre-vide-fond: #e6e9ec;
  --cadre-vide-trame: rgba(0, 0, 0, .045);
  --cadre-vide-encre: rgba(17, 22, 28, .68);
  --cadre-vide-filet: rgba(0, 0, 0, .10);
}

[data-slot]:not(:has(img)):not(:has(video)) {
  background-color: var(--cadre-vide-fond);
  /* Une trame diagonale : sans elle un aplat sombre se lit comme une panne
     d affichage. Avec elle, il se lit comme un emplacement en attente. */
  background-image: repeating-linear-gradient(135deg,
    transparent 0 13px, var(--cadre-vide-trame) 13px 14px);
  box-shadow: inset 0 0 0 1px var(--cadre-vide-filet);
  color: var(--cadre-vide-encre);
  /* SEULE propriete de boite de cette feuille, et elle ne vit que sur l etat
     VIDE : elle disparait des que la fabrique injecte une photo. Elle sert a
     une chose — permettre a la legende de savoir si son cadre est assez large
     pour la porter (voir le @container plus bas). Sans elle, la meme legende
     s ecrit dans une pastille de zone de 28 px et dans un hero de 800 px. */
  container-type: inline-size;
}

/* L intitule. Les gabarits y mettent tantot l alt complet, tantot la seule
   initiale du sujet — et cette initiale, dans un cadre de hero, sort a
   78 px : une lettre geante a la derive, c est ce qui faisait « casse ».
   On la ramene a la taille d une legende, quelle que soit la taille du
   cadre : une legende ne grandit pas avec son cadre.

   Et par defaut elle se TAIT. Un cadre ne porte une legende que s il est
   assez large pour l ecrire sur une ligne lisible : une pastille de zone de
   28 px, un cadre de maillage de 84 px, ne portent pas de phrase — ils
   tiennent leur aplat. Ecrite quand meme, la legende s y empile en colonne
   d une lettre : c est exactement ce que T5 appelle un serrage, et la pose
   du cadre vide en avait fabrique 306 sur heatfix2, 256 sur roofivo, 220 sur
   electria. Le libelle n est pas perdu pour autant : les gabarits le portent
   deja en `aria-label`, il reste lu par les lecteurs d ecran et par le gate.

   Le seuil est en unites de conteneur, pas de fenetre : c est la largeur du
   CADRE qui decide, pas celle de l ecran. Un hero garde sa legende a 390 px
   de fenetre ; une pastille ne l a jamais, meme a 1440. */
[data-slot]:not(:has(img)):not(:has(video)) > * {
  font-size: 0 !important;
  font-weight: 500;
  line-height: 1.45;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--cadre-vide-encre);
  -webkit-text-fill-color: var(--cadre-vide-encre);
  opacity: 1;
  max-width: 34ch;
  text-align: center;
  text-shadow: none;
}

/* 260 px : en dessous, une legende de 34ch a 11 px ne tient pas deux mots par
   ligne — le seuil est celui de T5, pas un gout. Au-dessus, elle s ecrit. */
@container (min-width: 260px) {
  [data-slot]:not(:has(img)):not(:has(video)) > * {
    font-size: clamp(11px, .95vw, 14px) !important;
  }
}
/* <<< NORME COQUILLE — cadre vide */

/* >>> NORME COQUILLE — teinte des cadres porteurs (pose par _lib/teinter-cadres.mjs) */
/* Cadres PORTEURS : de l encre claire repose reellement dessus (mesure du
   2026-08-22 sur 4 page(s), 1440 et 390 px). Leur etat vide prend
   le sol de leur section, assombri d un cran, pour que cette encre reste
   lisible sans plaquer une dalle etrangere a la palette ; tous les autres
   cadres gardent le clair par defaut. Ne pas editer a la main : remesurer.

   Un cadre porteur SE TAIT. Sa legende est centree ; de l encre repose
   deja dessus, par definition — l ecrire, c est la poser en travers du
   titre. C est la collision qu on voyait sur le hero pleine fenetre de
   template-14 : « EMPLACEMENT VISUEL — ... » ecrit sur le paragraphe.
   Le libelle reste porte en aria-label, il n est pas perdu. */
[data-slot="drop__vitPh"]:not(:has(img)):not(:has(video)) {
  --cadre-vide-fond: #0d0d0d;
  --cadre-vide-trame: rgba(255, 255, 255, .05);
  --cadre-vide-encre: rgba(255, 255, 255, .82);
  --cadre-vide-filet: rgba(255, 255, 255, .10);
}
[data-slot="drop__vitPh"]:not(:has(img)):not(:has(video)) > * {
  font-size: 0 !important;
}
[data-slot="frame--hro"]:not(:has(img)):not(:has(video)) {
  --cadre-vide-fond: #0d0d0d;
  --cadre-vide-trame: rgba(255, 255, 255, .05);
  --cadre-vide-encre: rgba(255, 255, 255, .82);
  --cadre-vide-filet: rgba(255, 255, 255, .10);
}
[data-slot="frame--hro"]:not(:has(img)):not(:has(video)) > * {
  font-size: 0 !important;
}
/* <<< NORME COQUILLE — teinte des cadres porteurs */


/* === CONTRAT GRILLE (factory, chantier 20/08, #1/#2) — services taille égale + avant/après 3-col === */
.g3 > * { flex-grow: 0 !important; }
.g2 > * { flex: 0 1 calc(33.333% - 20px) !important; min-width: min(240px, 100%) !important; }
