﻿/* =============================================================================
   LMB Couverture Lorraine — Design System
   Concept : « l'aplomb ». Angles justes, lignes nettes, matières franches —
   la grammaire visuelle d'une toiture bien posée.
   Palette échantillonnée pixel par pixel sur le logo officiel.
   ========================================================================== */

:root{
  /* ---- Marque ---- */
  --blue:#014AD1;
  --blue-d:#0033A0;
  --blue-l:#3D6FE0;
  --blue-e:#4D8BFF;          /* électrique — accents sur fond sombre */
  --blue-wash:#EEF3FF;
  --steel:#767676;
  --grey:#B3B3B3;

  /* ---- Encres & surfaces ---- */
  --ink:#080D18;             /* fond sombre principal */
  --ink-2:#0F1626;
  --ink-3:#1A2438;
  --title:#0B1220;
  --text:#414B5E;
  --muted:#6B7484;
  --faint:#9AA5B8;
  --surface:#FFFFFF;
  --surface-alt:#F4F6FA;
  --border:#E3E8F0;
  --border-dark:rgba(255,255,255,.12);

  /* ---- Fonctionnels ---- */
  --urgent:#F0761E;
  --urgent-d:#CE5D0C;
  --success:#12915B;
  --star:#FBBC05;

  /* ---- Typo ---- */
  --display:'Barlow Condensed',ui-sans-serif,system-ui,sans-serif;
  --body:'Inter',ui-sans-serif,system-ui,-apple-system,'Segoe UI',sans-serif;

  /* ---- Rayons ---- */
  --r-xs:8px; --r-sm:12px; --r-md:20px; --r-lg:32px; --r-xl:44px; --r-pill:999px;

  /* ---- Structure ---- */
  --container:1320px;
  --gutter:clamp(1.25rem,4vw,2.75rem);
  --section-y:clamp(3.4rem,5.6vw,5.4rem);
  --header-h:84px;

  /* ---- Ombres ---- */
  --sh-xs:0 1px 2px rgba(8,13,24,.05);
  --sh-sm:0 2px 8px rgba(8,13,24,.06),0 1px 2px rgba(8,13,24,.04);
  --sh-md:0 10px 30px rgba(8,13,24,.09);
  --sh-lg:0 28px 64px rgba(8,13,24,.16);
  --sh-xl:0 44px 96px rgba(8,13,24,.24);
  --sh-blue:0 18px 44px rgba(1,74,209,.28);

  --ease:cubic-bezier(.22,.61,.36,1);
  --ease-out:cubic-bezier(.16,1,.3,1);
}

/* --------------------------------------------------------------- Reset --- */
*,*::before,*::after{box-sizing:border-box}
*{margin:0}
/* Un composant à qui la feuille donne display:grid ou display:flex l'emporte
   sur le display:none que le navigateur applique à [hidden] : il reste alors
   à l'écran, invisible, et capte les clics. La règle vaut pour tout le site. */
[hidden]{display:none!important}
html{
  -webkit-text-size-adjust:100%;
  scroll-behavior:smooth;
  scroll-padding-top:calc(var(--header-h) + 20px);
}
body{
  /* « clip » et non « hidden » : hidden ferait du corps une boîte de
     défilement et neutraliserait toutes les positions collantes du site. */
  overflow-x:clip;
  font-family:var(--body);
  font-size:1.0625rem;
  line-height:1.68;
  color:var(--text);
  background:var(--surface);
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
  overflow-x:hidden;
}
img,svg,video{display:block;max-width:100%;height:auto}
button,input,select,textarea{font:inherit;color:inherit}
button{cursor:pointer;border:0;background:none}
a{color:inherit;text-decoration:none}
ul{list-style:none;padding:0}
:focus-visible{outline:3px solid var(--blue-e);outline-offset:3px;border-radius:4px}
::selection{background:var(--blue);color:#fff}

/* Grain — donne de la matière, évite le rendu « plat » des aplats */
body::after{
  content:"";position:fixed;inset:0;z-index:200;pointer-events:none;opacity:.032;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ---------------------------------------------------------- Typographie -- */
h1,h2,h3,h4,.display{
  font-family:var(--display);
  color:var(--title);
  line-height:.98;
  letter-spacing:-.012em;
  text-wrap:balance;
}
h1{font-size:clamp(3rem,7.2vw,6.5rem);font-weight:700;text-transform:uppercase}
h2{font-size:clamp(2.05rem,4vw,3.4rem);font-weight:700;text-transform:uppercase}
h3{font-size:clamp(1.35rem,2vw,1.7rem);font-weight:600;line-height:1.1}
h4{font-size:1.1rem;font-weight:600;font-family:var(--body);letter-spacing:0}
p{text-wrap:pretty}
strong{color:var(--title);font-weight:600}

/* Surtitre indexé — « 01 · NOS SAVOIR-FAIRE » */
.eyebrow{
  display:inline-flex;align-items:center;gap:.75rem;
  font-family:var(--body);font-size:.75rem;font-weight:600;
  letter-spacing:.22em;text-transform:uppercase;color:var(--blue);
  margin-bottom:1.15rem;
}
.eyebrow::before{
  content:attr(data-i);
  font-family:var(--display);font-size:1.05rem;font-weight:700;letter-spacing:0;
  color:var(--blue);opacity:.4;
}
.eyebrow::after{content:"";width:36px;height:1px;background:currentColor;opacity:.45}
.eyebrow--light{color:var(--blue-e)}

.lead{font-size:clamp(1.05rem,1.5vw,1.22rem);line-height:1.65;color:var(--muted);max-width:60ch}
/* Les noms propres composés — Ville-en-Vermois, Meurthe-et-Moselle — se
   coupent sur leurs traits d'union si on les laisse faire. */
.insecable{white-space:nowrap}
.accent{color:var(--blue)}
.accent-o{color:var(--urgent)}

/* Filet dégradé — séparateur discret */
.hairline{height:1px;background:linear-gradient(90deg,transparent,var(--border) 18%,var(--border) 82%,transparent)}

/* -------------------------------------------------------------- Layout --- */
.container{width:min(100% - var(--gutter)*2,var(--container));margin-inline:auto}
.section{padding-block:var(--section-y);position:relative}
.section--alt{background:var(--surface-alt)}
.section--ink{background:var(--ink);color:#B7C1D4}
.section--ink h1,.section--ink h2,.section--ink h3,.section--ink h4{color:#fff}
.section--tight{padding-block:clamp(2.6rem,4.2vw,3.9rem)}

.section-head{max-width:62ch;margin-bottom:clamp(2.75rem,5vw,4.5rem)}
.section-head--center{margin-inline:auto;text-align:center}
.section-head--center .eyebrow{justify-content:center}
/* Le filet de gauche, pour que le sur-titre soit centré sur son texte et
   non sur son encombrement. Peint en fond du numéro : mêmes 36 px, même
   opacité, aucun élément supplémentaire dans le HTML. */
.section-head--center .eyebrow::before{
  padding-left:calc(36px + .75rem);
  background:linear-gradient(currentColor,currentColor) no-repeat left 50% / 36px 1px;
}
.section-head--split{
  display:flex;justify-content:space-between;align-items:flex-start;
  gap:clamp(1.5rem,4vw,4rem);max-width:none;flex-wrap:wrap;
}
.section-head--split>*:first-child{flex:1 1 24rem;max-width:44rem}
.section-head--split>*:last-child{flex:0 1 27rem}
.section-head--split .lead{max-width:none;margin-top:0}
/* La première ligne du chapô s'aligne sur la première ligne du titre, pas sur
   le haut du bloc : sans ce calage, le paragraphe flotte trop haut. */
.section-head--split>*:last-child{padding-top:2.05rem}
/* Le calage ne vaut que côte à côte. Les deux colonnes réclament 24 rem et
   27 rem : elles s'empilent donc dès que le conteneur passe sous ~850 px, et
   le rembourrage devenait alors 33 px de blanc ajoutés aux 30 px d'écart de
   grille — 63 px entre un titre et son chapô. Mesuré : empilées à 834,
   côte à côte à 900. La borne était à 720, elle passe à 880. */
@media (max-width:880px){.section-head--split>*:last-child{padding-top:0}}
.section-head p{margin-top:1.15rem}

/* ------------------------------------------------------------- Boutons --- */
.btn{
  position:relative;display:inline-flex;align-items:center;justify-content:center;gap:.65rem;
  padding:1rem 2rem;border-radius:var(--r-pill);
  font-weight:600;font-size:.98rem;letter-spacing:.005em;
  transition:transform .3s var(--ease),box-shadow .3s var(--ease),
             background-color .25s,color .25s,border-color .25s;
  white-space:nowrap;overflow:hidden;isolation:isolate;
}
.btn svg{width:18px;height:18px;flex:none}
.btn:hover{transform:translateY(-2px)}
.btn:active{transform:translateY(0)}

.btn--primary{background:var(--blue);color:#fff;box-shadow:var(--sh-blue)}
.btn--primary::before{
  content:"";position:absolute;inset:0;z-index:-1;
  background:linear-gradient(115deg,var(--blue-l),var(--blue-e));
  opacity:0;transition:opacity .35s var(--ease);
}
.btn--primary:hover::before{opacity:1}
.btn--primary:hover{box-shadow:0 24px 56px rgba(1,74,209,.38)}

.btn--urgent{background:var(--urgent);color:#fff;box-shadow:0 16px 36px rgba(240,118,30,.3)}
.btn--urgent:hover{background:var(--urgent-d)}

.btn--ghost{border:1.5px solid var(--border);color:var(--title);background:#fff}
.btn--ghost:hover{border-color:var(--blue);color:var(--blue);box-shadow:var(--sh-md)}

.btn--ondark{border:1.5px solid rgba(255,255,255,.28);color:#fff;backdrop-filter:blur(8px)}
.btn--ondark:hover{background:#fff;color:var(--title);border-color:#fff}

.btn--lg{padding:1.15rem 2.4rem;font-size:1.05rem}

.link-arrow{
  display:inline-flex;align-items:center;gap:.5rem;
  font-weight:600;color:var(--blue);font-size:.94rem;
}
.link-arrow svg{width:16px;height:16px;transition:transform .35s var(--ease)}
.link-arrow:hover svg{transform:translateX(6px)}

/* Barre de progression de lecture */
.progress{
  position:fixed;top:0;left:0;height:2px;z-index:120;
  background:linear-gradient(90deg,var(--blue),var(--blue-e));
  width:var(--p,0%);transition:width .1s linear;
}

/* -------------------------------------------------------------- Topbar --- */
.topbar{
  background:var(--ink);color:#93A0B8;font-size:.8rem;
  padding-block:.6rem;border-bottom:1px solid var(--border-dark);
}
.topbar__in{display:flex;align-items:center;justify-content:space-between;gap:1.5rem;flex-wrap:wrap}
.topbar__items{display:flex;align-items:center;gap:1.75rem;flex-wrap:wrap}
.topbar__item{display:inline-flex;align-items:center;gap:.45rem;transition:color .2s}
a.topbar__item:hover{color:#fff}
.topbar__item svg{width:14px;height:14px;color:var(--blue-e);flex:none}

.gstars{display:inline-flex;align-items:center;gap:.4rem}
.gstars b{font-weight:700;color:#fff}
.stars{display:inline-flex;gap:1px;color:var(--star)}
.stars svg{width:13px;height:13px}

/* -------------------------------------------------------------- Header --- */
.header{
  position:sticky;top:0;z-index:80;
  background:rgba(255,255,255,.86);
  backdrop-filter:saturate(180%) blur(16px);
  border-bottom:1px solid transparent;
  transition:box-shadow .35s var(--ease),border-color .35s,background-color .35s;
}
.header.is-stuck{box-shadow:0 4px 28px rgba(8,13,24,.08);border-color:var(--border)}
.header__in{display:flex;align-items:center;gap:1.5rem;min-height:var(--header-h);position:relative}
.logo{flex:none;transition:transform .3s var(--ease)}
.logo:hover{transform:scale(1.03)}
.logo img{height:50px;width:auto}

.nav{margin-left:auto;align-self:stretch}
.nav__list{display:flex;align-items:stretch;gap:.15rem;height:100%}
.nav__link{
  position:relative;display:flex;align-items:center;gap:.35rem;
  padding:.6rem .9rem;border-radius:var(--r-xs);
  font-weight:500;font-size:.94rem;color:var(--text);
  transition:color .22s;
}
.nav__link::after{
  content:"";position:absolute;left:.9rem;right:.9rem;bottom:.3rem;height:1.5px;
  background:var(--blue);transform:scaleX(0);transform-origin:left;
  transition:transform .35s var(--ease);
}
.nav__link:hover::after,.nav__item:focus-within .nav__link::after{transform:scaleX(1)}
.nav__link:hover,.nav__item:focus-within>.nav__link{color:var(--blue)}
.nav__link svg{width:11px;height:11px;opacity:.5;transition:transform .3s var(--ease)}
.nav__item:hover .nav__link svg{transform:rotate(180deg)}

/* Méga-menu */
/* Le méga-menu se cale sur le conteneur de l'en-tête, pas sur le lien.
   Centré sur le lien « Nos services », un panneau de 900 px sortait de
   l'écran par la gauche dès 1 300 px de large (-84 px à 1 280). */
.nav__item{position:static;display:flex;align-items:center}
.mega{
  position:absolute;top:calc(100% + 12px);left:50%;
  transform:translateX(-50%) translateY(-10px) scale(.985);
  /* Dix métiers depuis le 13/09/2026, et non plus neuf. Sur trois colonnes,
     le dixième se retrouvait seul sur sa rangée, un trou de deux cases au
     milieu du panneau. Deux colonnes rangent les dix en cinq rangées pleines,
     et laissent enfin aux libellés la place de tenir sur une ligne — la
     largeur est réduite en conséquence, sinon le panneau lit comme un
     tableau à trous. */
  width:min(94vw,760px);background:#fff;border:1px solid var(--border);
  border-radius:var(--r-lg);box-shadow:var(--sh-xl);padding:1.4rem;
  display:grid;grid-template-columns:repeat(2,1fr);gap:.2rem .5rem;
  opacity:0;visibility:hidden;
  transition:opacity .28s var(--ease),transform .28s var(--ease),visibility .28s;
}
.nav__item:hover .mega,.nav__item:focus-within .mega{
  opacity:1;visibility:visible;transform:translateX(-50%) translateY(0) scale(1);
}
.mega__link{display:flex;gap:.85rem;padding:.8rem;border-radius:var(--r-md);transition:background-color .22s}
.mega__link:hover{background:var(--blue-wash)}
.mega__ico{
  width:38px;height:38px;flex:none;border-radius:11px;
  background:var(--blue-wash);color:var(--blue);
  display:grid;place-items:center;transition:background-color .22s,color .22s;
}
.mega__link:hover .mega__ico{background:var(--blue);color:#fff}
.mega__ico svg{width:19px;height:19px}
.mega__t{display:block;font-weight:600;color:var(--title);font-size:.92rem;line-height:1.3}
.mega__d{display:block;font-size:.775rem;color:var(--muted);line-height:1.4;margin-top:.15rem}

.header__cta{display:flex;align-items:center;gap:.9rem;flex:none}
.header__tel{
  display:inline-flex;align-items:center;gap:.55rem;
  font-family:var(--display);font-size:1.4rem;font-weight:700;
  color:var(--title);letter-spacing:.005em;transition:color .22s;
}
.header__tel svg{width:17px;height:17px;color:var(--blue)}
.header__tel:hover{color:var(--blue)}

.burger{display:none;width:44px;height:44px;border-radius:var(--r-xs);place-items:center}
.burger span{display:block;width:22px;height:2px;background:var(--title);position:relative;transition:.32s var(--ease)}
.burger span::before,.burger span::after{
  content:"";position:absolute;left:0;width:22px;height:2px;background:var(--title);transition:.32s var(--ease)
}
.burger span::before{top:-7px} .burger span::after{top:7px}
.burger[aria-expanded="true"] span{background:transparent}
.burger[aria-expanded="true"] span::before{top:0;transform:rotate(45deg)}
.burger[aria-expanded="true"] span::after{top:0;transform:rotate(-45deg)}

/* Menu mobile */
.mnav{
  position:fixed;inset:0;z-index:90;background:#fff;
  padding:1.25rem var(--gutter) 2.5rem;overflow-y:auto;
  transform:translateX(100%);
  /* Fermé, le tiroir ne doit pas compter dans la largeur du document :
     hors champ, un élément fixe reste mesuré. */
  visibility:hidden;
  transition:transform .45s var(--ease-out),visibility 0s .45s;
}
.mnav.is-open{transform:translateX(0);visibility:visible;transition:transform .45s var(--ease-out)}
/* Le bouton de fermeture : même dessin que le bouton d'ouverture, posé dans
   l'en-tête du tiroir. */
.mnav__close{position:relative;flex:none}
.mnav__head{display:flex;align-items:center;justify-content:space-between;margin-bottom:1.5rem;min-height:var(--header-h)}
.mnav__list{display:flex;flex-direction:column;margin-bottom:2rem}
.mnav__list li{display:flex;flex-wrap:wrap;align-items:stretch}
.mnav__link{
  display:block;flex:1;padding:1rem .25rem;border-bottom:1px solid var(--border);
  font-family:var(--display);font-size:1.65rem;font-weight:600;
  text-transform:uppercase;color:var(--title);letter-spacing:-.01em;
}
/* Le chevron des neuf métiers. Il partage le filet du libellé pour que la
   ligne reste une ligne, et sa zone de touche fait la hauteur de l'entrée —
   viser une flèche de 20 px au doigt ne marche pas. */
.mnav__plus{
  flex:none;display:grid;place-items:center;width:56px;
  border-bottom:1px solid var(--border);color:var(--muted);
  transition:color .2s var(--ease);
}
.mnav__plus svg{width:22px;height:22px;transition:transform .28s var(--ease-out)}
.mnav__plus[aria-expanded="true"]{color:var(--blue)}
.mnav__plus[aria-expanded="true"] svg{transform:rotate(180deg)}
.mnav__plus:focus-visible{outline:2px solid var(--blue);outline-offset:-2px}
.mnav__sub{
  /* Fermé d'office : le tiroir s'ouvrait sur quatorze entrées, dont neuf en
     petit gris, et les cinq pages principales passaient sous la ligne de
     flottaison. */
  flex:0 0 100%;
  padding:.5rem 0 .75rem 1rem;border-bottom:1px solid var(--border);
}
.mnav__sub[hidden]{display:none}
.mnav__sub a{display:block;padding:.55rem 0;font-size:.95rem;color:var(--muted)}
.mnav__cta{display:grid;gap:.75rem}
/* ================================================================ HERO ===
   Le logo LMB est fait de bandes obliques parallèles qui dessinent des
   versants de toit. Le hero reprend cette géométrie à l'échelle de la page.

   Tout tient dans UNE grille, sans positionnement absolu : quatre colonnes
   (gouttière · texte · visuel · bord d'écran) et deux rangées (composition ·
   socle). Le visuel démarre au milieu du conteneur et file jusqu'au bord
   droit de l'écran ; son arête gauche est coupée à la pente du toit.
   ------------------------------------------------------------------------ */
.hero{
  position:relative;isolation:isolate;overflow:hidden;
  background:var(--ink);color:#C3CCDD;

  /* Déport de l'arête entre le haut et le bas du panneau photo. Une seule
     valeur pilote la découpe de l'image ET les trois bandes. */
  --cut:21%;
  --split:.5;
  --hero-h:clamp(560px,calc(100svh - 9rem),820px);

  display:grid;
  min-height:var(--hero-h);
  grid-template-columns:
    [full-start] minmax(var(--gutter),1fr)
    [main-start] minmax(0,calc(var(--container) * var(--split)))
    [mid]        minmax(0,calc(var(--container) * (1 - var(--split))))
    [main-end]   minmax(var(--gutter),1fr)
    [full-end];
  grid-template-rows:[top] 1fr [socle] auto [bottom];
}

/* --- Le champ d'encre : fond de toute la composition ------------------- */
.hero__field{
  grid-area:top/full-start/bottom/full-end;z-index:0;
  background:
    radial-gradient(66% 58% at 16% -14%,rgba(31,96,236,.44) 0%,transparent 68%),
    radial-gradient(58% 52% at -8% 90%,rgba(44,86,196,.34) 0%,transparent 74%),
    linear-gradient(158deg,#0D1836 0%,#0A1228 40%,#070C1B 72%,#050915 100%);
}
/* Trame de hachures parallèles à la pente — même angle que les bandes du
   logo. Elle donne de la matière à l'encre sans jamais se voir vraiment. */
.hero__field::before{
  content:"";position:absolute;inset:0;
  background-image:repeating-linear-gradient(117deg,
    rgba(140,180,255,.06) 0 1px,transparent 1px 26px);
  -webkit-mask-image:linear-gradient(108deg,#000 0%,rgba(0,0,0,.5) 48%,transparent 80%);
          mask-image:linear-gradient(108deg,#000 0%,rgba(0,0,0,.5) 48%,transparent 80%);
}

/* --- Colonne de texte -------------------------------------------------- */
.hero__copy{
  grid-area:top/main-start/socle/mid;z-index:2;
  align-self:center;
  padding-block:clamp(2.5rem,5vw,4rem);
  padding-right:clamp(1rem,2.5vw,2.5rem);
  max-width:41rem;position:relative;
}
/* Le fil d'aplomb : un couvreur pose une toiture à l'aplomb, et c'est le nom
   du concept graphique du site. Trait vertical + contrepoids, tracé à
   l'entrée. Purement décoratif, invisible sous 900 px. */
.hero__copy::before{
  content:"";position:absolute;left:calc(-1 * clamp(1.1rem,2.2vw,2rem));
  top:.4rem;bottom:.4rem;width:1px;
  background:linear-gradient(180deg,transparent,rgba(120,160,240,.42) 14%,rgba(120,160,240,.42) 86%,transparent);
  transform-origin:top;
}
.hero__copy::after{
  content:"";position:absolute;left:calc(-1 * clamp(1.1rem,2.2vw,2rem) - 2.5px);
  bottom:.4rem;width:6px;height:6px;background:var(--blue-e);
  transform:rotate(45deg);opacity:.85;
}

/* Surtitre : un filet et un libellé. Pas une pastille de plus. */
.hero__kicker{
  display:flex;align-items:center;gap:.85rem;
  font-size:.735rem;font-weight:600;letter-spacing:.2em;text-transform:uppercase;
  color:#9FB2D2;margin-bottom:clamp(1.1rem,2vw,1.6rem);
}
.hero__kicker i{
  display:block;width:clamp(28px,4vw,54px);height:2px;flex:none;
  background:linear-gradient(90deg,var(--blue-e),rgba(77,139,255,.15));
  transform-origin:left;
}

/* Titre — deux lignes, chacune révélée derrière son propre cache.
   Le palier haut est calé pour que « ENTRE DE BONNES MAINS » (la ligne la
   plus longue) tienne toujours dans la colonne : au-delà, elle débordait
   sur la photo. */
.hero h1{
  color:#fff;
  font-size:clamp(2.45rem,.2rem + 4.2vw,4.1rem);
  line-height:.9;letter-spacing:-.022em;
  margin-bottom:clamp(1.1rem,2vw,1.6rem);
}
.hero h1 .ln{display:block;overflow:hidden;padding-bottom:.11em;margin-bottom:-.08em}
.hero h1 .ln i{display:block;font-style:normal}
/* Le mot-clé n'est pas souligné : il est éclairé. Une nappe de lumière bleue
   passe derrière les lettres, en écho aux nappes du champ d'encre. */
.hero h1 em{
  font-style:normal;position:relative;display:inline-block;isolation:isolate;
  background:linear-gradient(102deg,#A9C8FF 0%,#6C9EFF 42%,#2F6DF2 100%);
  -webkit-background-clip:text;background-clip:text;color:transparent;
}
.hero h1 em::before{
  content:"";position:absolute;z-index:-1;
  left:-6%;right:-6%;top:6%;bottom:10%;
  background:radial-gradient(58% 130% at 50% 55%,rgba(64,124,255,.5) 0%,transparent 72%);
  filter:blur(24px);opacity:0;
}
.js .hero h1 em::before{animation:kindle 1.4s var(--ease-out) .95s forwards}
@keyframes kindle{to{opacity:1}}

.hero__lead{
  font-size:clamp(1rem,.9rem + .3vw,1.14rem);line-height:1.62;
  color:#B7C2D6;max-width:44ch;
  margin-bottom:clamp(1.5rem,2.6vw,2.1rem);
}
.hero__lead strong{color:#fff;font-weight:600}
.hero__actions{display:flex;gap:.8rem;flex-wrap:wrap}

/* --- Preuve sociale : une ligne, séparée par un filet ------------------- */
.hero__proof{
  display:inline-flex;align-items:center;gap:.7rem;flex-wrap:wrap;
  margin-top:clamp(1.6rem,2.8vw,2.2rem);padding-top:clamp(1.2rem,2vw,1.6rem);
  border-top:1px solid rgba(255,255,255,.13);
  width:100%;max-width:30rem;
}
.hero__g{width:20px;height:20px;flex:none}
.hero__proof b{font-family:var(--display);font-size:1.75rem;line-height:1;color:#fff;font-weight:700}
.hero__proof .stars{color:var(--star)}
.hero__proof .stars svg{width:14px;height:14px}
.hero__proof-n{font-size:.82rem;color:#93A2BC;letter-spacing:.01em}
.hero__proof-go{
  margin-left:auto;width:30px;height:30px;flex:none;border-radius:50%;
  display:grid;place-items:center;color:#B7C2D6;
  border:1px solid rgba(255,255,255,.16);
  transition:transform .32s var(--ease),background-color .28s,border-color .28s,color .28s;
}
.hero__proof-go svg{width:14px;height:14px}
.hero__proof:hover .hero__proof-go,
.hero__proof:focus-visible .hero__proof-go{
  background:var(--blue);border-color:var(--blue);color:#fff;transform:translateX(4px);
}
.hero__proof:hover .hero__proof-n{color:#D5DEEE}

/* --- Le panneau photo -------------------------------------------------- */
.hero__art{
  grid-area:top/mid/bottom/full-end;z-index:1;
  position:relative;margin:0;pointer-events:none;
}
/* La découpe porte sur l'enveloppe, pas sur la figure : l'annotation doit
   pouvoir déborder à gauche, sur l'encre. */
.hero__art-img{
  position:absolute;inset:0;display:block;overflow:hidden;
  clip-path:polygon(0 0,100% 0,100% 100%,var(--cut) 100%);
}
.hero__art-img img{
  width:100%;height:100%;object-fit:cover;object-position:64% 42%;
  transform:scale(1.04);will-change:transform;
}
/* Voile : très léger en haut à droite (le ciel reste ouvert), plus dense le
   long de l'arête pour que la couture avec l'encre ne se voie pas. */
.hero__art-img::after{
  content:"";position:absolute;inset:0;
  background:
    linear-gradient(101deg,rgba(8,13,24,.92) 0%,rgba(8,13,24,.55) 9%,rgba(8,13,24,.08) 24%,transparent 44%),
    linear-gradient(180deg,rgba(8,13,24,.34) 0%,transparent 26%,transparent 58%,rgba(8,13,24,.72) 100%);
}

/* Les trois obliques du logo, posées sur l'arête. Une seule variable pilote
   leur pente : elles suivent exactement la découpe de l'image. */
.hero__bands{position:absolute;inset:0;pointer-events:none}
.hero__bands i{position:absolute;inset:0;display:block;transform-origin:top center}
.hero__bands i:nth-child(1){
  background:linear-gradient(180deg,#6FA0FF,var(--blue-e) 40%,var(--blue) 76%,var(--blue-d));
  clip-path:polygon(0 0,1.35% 0,calc(var(--cut) + 1.35%) 100%,var(--cut) 100%);
  filter:drop-shadow(0 0 22px rgba(77,139,255,.8));
}
.hero__bands i:nth-child(2){
  background:linear-gradient(180deg,rgba(255,255,255,.6),rgba(255,255,255,.12));
  clip-path:polygon(3.2% 0,3.75% 0,calc(var(--cut) + 3.75%) 100%,calc(var(--cut) + 3.2%) 100%);
}
.hero__bands i:nth-child(3){
  background:var(--blue-e);opacity:.5;
  clip-path:polygon(5.6% 0,5.9% 0,calc(var(--cut) + 5.9%) 100%,calc(var(--cut) + 5.6%) 100%);
}

/* Annotation de chantier : le repère chiffré d'un plan technique. Elle
   traverse l'arête et pose un pied sur l'encre — c'est le seul chevauchement
   de la composition, et il est voulu. */
.hero__note{
  position:absolute;left:clamp(-2.5rem,-2vw,-1rem);
  bottom:clamp(5.5rem,9vw,7.5rem);
  padding-left:clamp(.85rem,1.4vw,1.15rem);
  border-left:2px solid var(--blue-e);
  max-width:min(20rem,62%);
  text-shadow:0 1px 12px rgba(8,13,24,.9);
}
.hero__note-k{
  display:block;font-size:.66rem;letter-spacing:.2em;text-transform:uppercase;
  color:var(--blue-e);margin-bottom:.3rem;
}
.hero__note-v{
  display:block;font-family:var(--display);font-size:clamp(1.05rem,1.5vw,1.32rem);
  font-weight:600;color:#fff;line-height:1.14;
}
.hero__note-m{display:block;font-size:.76rem;color:#A8B6CE;margin-top:.28rem;line-height:1.4}

/* --- Socle : la réassurance, en filets ---------------------------------- */
.hero__socle{
  grid-area:socle/full-start/bottom/full-end;z-index:3;
  display:grid;grid-template-columns:repeat(4,1fr);
  background:rgba(6,10,20,.55);backdrop-filter:blur(18px) saturate(140%);
  border-top:1px solid rgba(255,255,255,.13);
  padding-inline:max(var(--gutter),calc((100% - var(--container)) / 2));
}
.hero__socle-i{
  padding:clamp(1rem,1.9vw,1.45rem) clamp(.9rem,1.6vw,1.5rem);
  display:flex;align-items:flex-start;gap:.8rem;position:relative;
}
.hero__socle-i+.hero__socle-i::before{
  content:"";position:absolute;left:0;top:22%;bottom:22%;width:1px;
  background:rgba(255,255,255,.12);
}
.hero__socle-i:first-child{padding-left:0}
.hero__socle-i:last-child{padding-right:0}
.hero__socle-i svg{width:20px;height:20px;color:var(--blue-e);flex:none;margin-top:.15rem;
  transition:transform .35s var(--ease)}
.hero__socle-i:hover svg{transform:translateY(-2px)}
.hero__socle-i b{display:block;font-family:var(--display);font-size:clamp(1.05rem,1.5vw,1.24rem);
  font-weight:600;color:#fff;line-height:1.15;letter-spacing:.005em}
.hero__socle-i span{display:block;font-size:.765rem;color:#8B99B2;margin-top:.12rem;line-height:1.4}

/* Indice de défilement — côté encre, sous le bloc de texte */
.scroll-cue{
  grid-area:top/main-start/socle/mid;z-index:2;
  align-self:end;justify-self:start;
  margin-bottom:clamp(1rem,2vw,1.6rem);
  display:flex;align-items:center;gap:.7rem;
  font-size:.64rem;letter-spacing:.22em;text-transform:uppercase;color:#7C8AA3;
  pointer-events:none;
}
.scroll-cue i{display:block;width:44px;height:1px;
  background:linear-gradient(90deg,var(--blue-e),transparent);
  animation:cue 2.4s ease-in-out infinite}
@keyframes cue{0%,100%{opacity:.3;transform:scaleX(.55);transform-origin:left}50%{opacity:1;transform:scaleX(1)}}

/* --- Entrée séquencée -----------------------------------------------------
   Une idée par famille d'élément, pas un fondu générique appliqué à tout :
   · l'image se dévoile par un volet qui descend la pente ;
   · les bandes se tracent du haut vers le bas ;
   · les lignes de titre montent derrière leur cache ;
   · les filets se tirent ; les blocs de texte montent de très peu.
   -------------------------------------------------------------------------- */
.js .hero__art-img{animation:artwipe 1.25s var(--ease-out) .1s backwards}
@keyframes artwipe{
  from{clip-path:polygon(100% 0,100% 0,100% 100%,100% 100%)}
  to  {clip-path:polygon(0 0,100% 0,100% 100%,var(--cut) 100%)}
}
.js .hero__art-img img{animation:artsettle 1.9s var(--ease-out) .1s backwards}
@keyframes artsettle{from{transform:scale(1.14)}to{transform:scale(1.04)}}

.js .hero__bands i{transform:scaleY(0);animation:trace 1.1s var(--ease-out) .38s forwards}
.js .hero__bands i:nth-child(2){animation-delay:.47s}
.js .hero__bands i:nth-child(3){animation-delay:.54s}
@keyframes trace{to{transform:scaleY(1)}}

.js .hero__kicker i{animation:draw-x .7s var(--ease-out) .18s backwards}
.js .hero__copy::before{animation:draw-y 1s var(--ease-out) .1s backwards}
@keyframes draw-x{from{transform:scaleX(0)}to{transform:scaleX(1)}}
@keyframes draw-y{from{transform:scaleY(0)}to{transform:scaleY(1)}}

.js .hero h1 .ln i{transform:translateY(108%);animation:lineup 1s var(--ease-out) forwards}
.js .hero h1 .ln:nth-child(1) i{animation-delay:.26s}
.js .hero h1 .ln:nth-child(2) i{animation-delay:.37s}
@keyframes lineup{to{transform:none}}

.js .hero__kicker,
.js .hero__lead,
.js .hero__actions,
.js .hero__proof,
.js .hero__note,
.js .hero__socle-i,
.js .scroll-cue{opacity:0;transform:translateY(14px);animation:rise .8s var(--ease-out) forwards}
.js .hero__kicker{animation-delay:.14s}
.js .hero__lead{animation-delay:.6s}
.js .hero__actions{animation-delay:.7s}
.js .hero__proof{animation-delay:.8s}
.js .hero__note{animation-delay:.95s}
.js .hero__socle-i{animation-delay:.9s}
.js .hero__socle-i:nth-child(2){animation-delay:.97s}
.js .hero__socle-i:nth-child(3){animation-delay:1.04s}
.js .hero__socle-i:nth-child(4){animation-delay:1.11s}
.js .scroll-cue{animation-delay:1.35s}
@keyframes rise{to{opacity:1;transform:none}}

/* ============================================================= MARQUEE === */
.marquee{
  background:var(--ink-2);border-block:1px solid var(--border-dark);
  padding-block:.9rem;overflow:hidden;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent);
          mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent);
}
.marquee__track{display:flex;width:max-content;animation:slide 46s linear infinite}
.marquee:hover .marquee__track{animation-play-state:paused}
@keyframes slide{to{transform:translateX(-50%)}}
.marquee__set{display:flex;align-items:center;gap:2.5rem;padding-right:2.5rem}
.marquee__i{
  display:inline-flex;align-items:center;gap:.7rem;
  font-family:var(--display);font-size:1.15rem;font-weight:600;
  text-transform:uppercase;letter-spacing:.04em;color:#7C8AA3;white-space:nowrap;
  transition:color .25s;
}
.marquee__i:hover{color:#fff}
.marquee__i::before{content:"";width:5px;height:5px;border-radius:50%;background:var(--blue);flex:none}

/* ============================================================== PREUVE === */
.proof{background:var(--ink);position:relative}
.proof__in{display:grid;grid-template-columns:repeat(4,1fr)}
.proof__i{
  padding:1.9rem 1.5rem;display:flex;align-items:flex-start;gap:1rem;
  border-right:1px solid var(--border-dark);transition:background-color .3s;
}
.proof__i:last-child{border-right:0}
.proof__i:hover{background:rgba(255,255,255,.028)}
.proof__i svg{width:24px;height:24px;color:var(--blue-e);flex:none;margin-top:.15rem}
.proof__i b{display:block;font-family:var(--display);font-size:1.32rem;font-weight:600;color:#fff;line-height:1.15}
.proof__i span{display:block;font-size:.79rem;color:#7C8AA3;margin-top:.15rem}

/* ============================================================ COMPTEURS == */
.stats{
  display:grid;grid-template-columns:repeat(4,1fr);
  border:1px solid var(--border);border-radius:var(--r-lg);overflow:hidden;background:#fff;
  box-shadow:var(--sh-sm);
}
.stat{padding:clamp(1.75rem,3.5vw,2.75rem) 1.5rem;border-right:1px solid var(--border);position:relative;overflow:hidden}
.stat:last-child{border-right:0}
.stat::before{
  content:"";position:absolute;left:0;right:0;bottom:0;height:3px;
  background:linear-gradient(90deg,var(--blue),var(--blue-e));
  transform:scaleX(0);transform-origin:left;transition:transform .6s var(--ease);
}
.stat.is-in::before{transform:scaleX(1)}
.stat__n{
  font-family:var(--display);font-size:clamp(3rem,6vw,4.75rem);font-weight:800;
  color:var(--title);line-height:.92;letter-spacing:-.02em;
  display:flex;align-items:baseline;gap:.05em;
}
.stat__n i{font-style:normal;color:var(--blue);font-size:.55em;font-weight:700}
.stat__l{font-size:.9rem;color:var(--title);margin-top:.65rem;font-weight:600}
.stat__p{display:block;font-size:.75rem;color:var(--faint);margin-top:.2rem}

/* ============================================================= SERVICES == */
/* Bento 4 colonnes : 2+1+1 / 1+1+2 — aucune cellule vide, hiérarchie claire */
.bento{display:grid;grid-template-columns:repeat(4,1fr);gap:clamp(.85rem,1.4vw,1.15rem)}
.card{
  position:relative;overflow:hidden;background:var(--ink);
  border-radius:var(--r-lg);display:flex;flex-direction:column;justify-content:flex-end;
  min-height:340px;isolation:isolate;
  transition:transform .5s var(--ease-out),box-shadow .5s var(--ease-out);
}
.card--wide{grid-column:span 2;min-height:380px}
.card:hover{transform:translateY(-5px);box-shadow:var(--sh-xl)}
.card__media{position:absolute;inset:0;z-index:-2}
.card__media img{width:100%;height:100%;object-fit:cover;transition:transform 1.1s var(--ease-out)}
.card:hover .card__media img{transform:scale(1.07)}
.card::before{
  content:"";position:absolute;inset:0;z-index:-1;
  background:linear-gradient(180deg,rgba(8,13,24,.12) 0%,rgba(8,13,24,.62) 52%,rgba(8,13,24,.94) 100%);
  transition:opacity .45s;
}
.card::after{
  content:"";position:absolute;inset:0;z-index:-1;
  background:linear-gradient(180deg,transparent 30%,rgba(1,74,209,.5) 100%);
  opacity:0;transition:opacity .45s;
}
.card:hover::after{opacity:1}
.card__i{
  position:absolute;top:1.35rem;left:1.5rem;
  font-family:var(--display);font-size:.95rem;font-weight:700;letter-spacing:.14em;
  color:rgba(255,255,255,.62);
  /* Le haut de la photo n'est pas voilé : sur un ciel clair, un blanc à
     demi-opaque s'efface complètement. */
  text-shadow:0 1px 10px rgba(4,8,18,.9),0 0 2px rgba(4,8,18,.6);
}
.card__body{padding:1.6rem 1.6rem 1.7rem;color:#fff}
.card__body h3{color:#fff;margin-bottom:.5rem}
.card__body p{
  font-size:.92rem;color:rgba(255,255,255,.74);line-height:1.55;
  max-width:44ch;
  /* Le texte se déplie au survol : la carte reste graphique au repos */
  max-height:0;opacity:0;overflow:hidden;
  transition:max-height .55s var(--ease-out),opacity .4s,margin .55s var(--ease-out);
}
.card:hover .card__body p,.card:focus-within .card__body p{max-height:9rem;opacity:1;margin-bottom:.9rem}
.card__go{
  display:inline-flex;align-items:center;gap:.5rem;
  font-size:.86rem;font-weight:600;color:#fff;
}
.card__go svg{width:15px;height:15px;transition:transform .35s var(--ease)}
.card:hover .card__go svg{transform:translateX(6px)}
.card__link{position:absolute;inset:0;z-index:5}

/* ========================================================= AVANT/APRÈS === */
.split{display:grid;grid-template-columns:.9fr 1.1fr;gap:clamp(2rem,5vw,5rem);align-items:center}
.split--rev .split__copy{order:2}

.ba{
  position:relative;border-radius:var(--r-lg);overflow:hidden;
  box-shadow:var(--sh-xl);aspect-ratio:3/2;
  cursor:ew-resize;user-select:none;touch-action:pan-y;background:var(--surface-alt);
}
.ba img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.ba__after{clip-path:inset(0 0 0 var(--pos,50%))}
.ba__handle{
  position:absolute;top:0;bottom:0;left:var(--pos,50%);width:2px;z-index:3;
  background:#fff;box-shadow:0 0 12px rgba(8,13,24,.35);
}
.ba__grip{
  position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
  width:56px;height:56px;border-radius:50%;background:#fff;
  box-shadow:var(--sh-lg);display:grid;place-items:center;color:var(--blue);
  transition:transform .3s var(--ease);
}
.ba:hover .ba__grip{transform:translate(-50%,-50%) scale(1.08)}
.ba__grip svg{width:22px;height:22px}
.ba__lbl{
  position:absolute;bottom:1.15rem;z-index:2;
  background:rgba(8,13,24,.72);color:#fff;backdrop-filter:blur(8px);
  font-size:.7rem;font-weight:700;letter-spacing:.14em;text-transform:uppercase;
  padding:.42rem .9rem;border-radius:var(--r-pill);
}
.ba__lbl--l{left:1.15rem} .ba__lbl--r{right:1.15rem}
.ba__hint{
  position:absolute;top:1.15rem;left:50%;transform:translateX(-50%);z-index:4;
  background:rgba(8,13,24,.72);color:#fff;backdrop-filter:blur(8px);
  font-size:.72rem;padding:.42rem .95rem;border-radius:var(--r-pill);
  display:flex;align-items:center;gap:.45rem;
  transition:opacity .4s;pointer-events:none;
}
.ba.is-touched .ba__hint{opacity:0}
.ba__hint svg{width:14px;height:14px}

/* Liste à puces cochées */
.checks{display:grid;gap:.7rem;margin-top:1.6rem}
.checks li{display:flex;gap:.7rem;align-items:flex-start;font-size:.95rem}
.checks svg{width:19px;height:19px;color:var(--blue);flex:none;margin-top:.16rem}

/* ============================================================= MÉTHODE === */
/* align-items:stretch — le visuel prend toute la hauteur de la colonne de
   texte, sinon un vide se creuse au-dessus et en dessous de l'image. */
.method{display:grid;grid-template-columns:.82fr 1.18fr;gap:clamp(2rem,5vw,4.5rem);align-items:stretch}
.method__visual{
  position:relative;border-radius:var(--r-lg);overflow:hidden;
  min-height:100%;box-shadow:var(--sh-lg);
  clip-path:polygon(0 0,100% 0,100% 90%,88% 100%,0 100%);
}
.method__visual img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.method__copy{display:flex;flex-direction:column;justify-content:center}
/* Les étapes ont leur propre bloc plus bas : la chronologie commune à
   l accueil et aux pages services (.steps / .step / .step__n). */

/* ======================================================== RÉALISATIONS ===
   Section immersive : fond encre, photos plein cadre. Le bloc est composé de
   trois bandes dont la hauteur est toujours déterminée par un rapport
   d'image, jamais par la hauteur d'un texte. C'est ce qui garantit qu'aucun
   vide ne peut s'ouvrir au milieu.
   ------------------------------------------------------------------------ */
.showsec{
  --pj-gap:clamp(.6rem,1.1vw,1rem);
  background:var(--ink);color:#B7C1D4;position:relative;isolation:isolate;
  padding-block:clamp(3.25rem,6vw,5.5rem) clamp(3rem,5vw,4.5rem);
}
/* Trame de hachures à la pente du toit — la même que dans le hero, en très
   discret : elle relie visuellement les deux blocs encre de la page. */
.showsec::before{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background-image:repeating-linear-gradient(117deg,rgba(140,180,255,.05) 0 1px,transparent 1px 30px);
  -webkit-mask-image:linear-gradient(180deg,#000,transparent 55%);
          mask-image:linear-gradient(180deg,#000,transparent 55%);
}
.showsec h2{color:#fff}
.showsec .lead{color:#93A1B9}
.showsec .section-head{margin-bottom:clamp(1.8rem,3vw,2.6rem)}
.showsec__aside{display:flex;flex-direction:column;align-items:flex-start;gap:.9rem;flex:0 1 27rem}
.showsec__all{color:#fff}
.showsec__all:hover{color:var(--blue-e)}

/* La grille d'ensemble : une colonne, trois bandes.
   Les lignes nommées permettent aux images de sortir du conteneur. */
.showcase{
  display:grid;gap:var(--pj-gap);
  grid-template-columns:
    [full-start] minmax(var(--gutter),1fr)
    [main-start] minmax(0,var(--container))
    [main-end] minmax(var(--gutter),1fr)
    [full-end];
}
.showcase>*{grid-column:main-start/main-end}

/* --- Une vignette --- */
.pj{
  position:relative;overflow:hidden;background:var(--ink-2);
  border-radius:var(--r-md);display:block;
}
.pj img{width:100%;height:100%;object-fit:cover;transition:transform .55s var(--ease-out)}
.pj:hover img,.pj:focus-visible img{transform:scale(1.045)}
.pj__ov{
  position:absolute;inset:0;display:flex;flex-direction:column;justify-content:flex-end;
  gap:.28rem;padding:clamp(1rem,1.9vw,1.7rem);color:#fff;
  background:linear-gradient(180deg,transparent 26%,rgba(6,10,20,.4) 58%,rgba(6,10,20,.92) 100%);
}
/* Une façade rose et un mur enduit clair passent sous le voile : le texte
   porte sa propre ombre plutôt que d'assombrir toutes les photos. */
.pj__ov>*{text-shadow:0 1px 12px rgba(4,8,18,.85)}
.pj__city{font-size:.68rem;font-weight:600;letter-spacing:.17em;text-transform:uppercase;color:#7BA8FF}
.pj__t{
  font-family:var(--display);font-size:clamp(1.1rem,1.55vw,1.4rem);
  font-weight:600;line-height:1.08;position:relative;
}
/* Filet qui se tire sous le titre au survol : le même geste que la ligne qui
   se trace sur la carte des zones. Une seule idée pour toute la page. */
.pj__t::after{
  content:"";position:absolute;left:0;right:0;bottom:-.34em;height:1.5px;
  background:var(--blue-e);transform:scaleX(0);transform-origin:left;
  transition:transform .45s var(--ease-out);
}
.pj:hover .pj__t::after,.pj:focus-visible .pj__t::after{transform:scaleX(1)}
.pj__m{
  font-size:.8rem;color:rgba(255,255,255,.76);line-height:1.45;max-width:44ch;
  max-height:0;opacity:0;overflow:hidden;
  transition:max-height .45s var(--ease-out),opacity .3s,margin-top .45s var(--ease-out);
}
.pj:hover .pj__m,.pj:focus-visible .pj__m{max-height:5rem;opacity:1;margin-top:.45rem}

/* --- Bande 1 : le chantier dominant, sorti par la gauche --- */
.pj--lead{
  grid-column:full-start/main-end;
  border-radius:0 var(--r-md) var(--r-md) 0;
  aspect-ratio:2.5/1;
}
.pj--lead .pj__t{font-size:clamp(1.5rem,2.9vw,2.6rem)}
.pj--lead .pj__city{font-size:.74rem}
.pj--lead .pj__ov{padding:clamp(1.2rem,2.4vw,2.2rem)}

/* --- La fiche technique, en bande sous la photo ---
   Sa hauteur est celle de son contenu : elle ne s'étire jamais. */
.pj__spec{
  display:grid;grid-template-columns:minmax(0,.85fr) minmax(0,2.15fr);
  gap:clamp(1.4rem,3vw,3rem);align-items:start;
  padding-top:clamp(1.1rem,2vw,1.7rem);margin-top:.3rem;
  border-top:1px solid rgba(255,255,255,.14);
}
.pj__spec-i{
  display:block;font-family:var(--display);font-size:.82rem;font-weight:700;
  letter-spacing:.2em;text-transform:uppercase;color:var(--blue-e);
}
.pj__spec h3{color:#fff;font-size:clamp(1.2rem,1.8vw,1.6rem);line-height:1.08;margin:.45rem 0 .85rem}
.pj__spec .link-arrow{color:#fff}
.pj__spec .link-arrow:hover{color:var(--blue-e)}
.pj__spec dl{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:clamp(1rem,2vw,2rem)}
.pj__spec dt{
  font-size:.68rem;letter-spacing:.14em;text-transform:uppercase;color:#7E8CA6;
  padding-bottom:.45rem;margin-bottom:.45rem;border-bottom:1px solid rgba(255,255,255,.1);
}
.pj__spec dd{font-size:.88rem;color:#D3DBE9;line-height:1.4}

/* --- Bande 2 : quatre chantiers, quatre formats --- */
.show-row{
  display:grid;grid-template-columns:repeat(12,minmax(0,1fr));
  gap:var(--pj-gap);margin-top:clamp(1.2rem,2.4vw,2.2rem);
  grid-auto-rows:clamp(130px,13vw,190px);
}
.pj--a{grid-column:span 3;grid-row:span 2}
.pj--b{grid-column:span 4}
.pj--c{grid-column:span 4}
.pj--d{grid-column:span 5;grid-row:span 2}
/* Les deux carrés s'empilent dans la même colonne, à droite du portrait. */
.pj--b{grid-column:4/8;grid-row:1}
.pj--c{grid-column:4/8;grid-row:2}
.pj--a{grid-column:1/4;grid-row:1/3}
.pj--d{grid-column:8/13;grid-row:1/3}

/* --- Bande 3 : la bande cinéma --- */
.pj--e{aspect-ratio:3.1/1;margin-top:var(--pj-gap)}

@media (max-width:1080px){
  .pj--lead{aspect-ratio:2.2/1}
  .pj__spec{grid-template-columns:minmax(0,1fr);gap:1.4rem}
  .pj__spec dl{grid-template-columns:repeat(4,minmax(0,1fr))}
  .show-row{grid-auto-rows:clamp(120px,15vw,165px)}
}
@media (max-width:820px){
  /* La photo dominante sort toujours par la gauche : ses deux coins de gauche
     restent donc carrés, ils sont hors de l'écran. Ses deux coins de droite,
     eux, s'arrêtent sur la gouttière comme toutes les autres vignettes du
     mur — les mettre à angle droit la faisait lire comme un bandeau posé sur
     la section, et non comme la première des cinq photos. */
  .pj--lead{aspect-ratio:16/10}
  .pj__spec dl{grid-template-columns:repeat(2,minmax(0,1fr));gap:1.2rem}
  .show-row{grid-auto-rows:clamp(120px,22vw,175px)}
  .pj--a{grid-column:1/7;grid-row:1/3}
  .pj--b{grid-column:7/13;grid-row:1}
  .pj--c{grid-column:7/13;grid-row:2}
  .pj--d{grid-column:1/13;grid-row:3}
  .pj--e{aspect-ratio:2.2/1}
}
@media (max-width:560px){
  .pj--lead{aspect-ratio:4/3}
  .pj__spec dl{grid-template-columns:minmax(0,1fr);gap:.9rem}
  .pj__spec dt{padding-bottom:.3rem;margin-bottom:.3rem}
  .show-row{grid-auto-rows:clamp(120px,34vw,190px)}
  .pj--a{grid-column:1/13;grid-row:1/3}
  .pj--b{grid-column:1/13;grid-row:3}
  .pj--c{grid-column:1/13;grid-row:4}
  .pj--d{grid-column:1/13;grid-row:5}
  .pj--e{aspect-ratio:3/2}
  /* Pas de survol au doigt : le détail est affiché d'emblée. */
  .pj__m{max-height:5rem;opacity:1;margin-top:.4rem}
  .pj__t::after{display:none}
}

/* ============================================================= LE SIÈGE ===
   Trois photos du local de Ville-en-Vermois, posées sur l'accueil le
   13/09/2026 avec le reportage fourni par le client.

   La grande file à gauche sur les deux rangs, les deux autres tiennent la
   colonne de droite. Le portrait des enseignes est en bas parce que c'est la
   seule image verticale du lot et qu'elle se coupe mal en paysage : mise en
   haut, on perdait l'une des deux enseignes.

   Les rangées portent une hauteur explicite. Avec `repeat(2,1fr)` et des
   images en `height:100%`, la hauteur de la grille dépendrait de celle des
   images, qui dépend de celle de la grille : les rangs s'écrasaient à zéro.
   ------------------------------------------------------------------------ */
.siege{
  display:grid;
  grid-template-columns:minmax(0,1.55fr) minmax(0,1fr);
  grid-template-rows:repeat(2,clamp(148px,16.5vw,232px));
  gap:var(--pj-gap);
}
.siege figure{
  position:relative;margin:0;overflow:hidden;
  border-radius:var(--r-md);background:var(--ink-2);
}
.siege img{
  width:100%;height:100%;object-fit:cover;display:block;
  transition:transform .55s var(--ease-out);
}
.siege figure:hover img,.siege figure:focus-within img{transform:scale(1.04)}
.siege__lead{grid-row:1/3}

.siege__ov{
  position:absolute;inset:auto 0 0 0;
  padding:clamp(.75rem,1.6vw,1.3rem);color:#fff;
  background:linear-gradient(to top,rgba(8,13,24,.84),rgba(8,13,24,.28) 62%,rgba(8,13,24,0));
}
.siege__ov b{
  display:block;font-family:var(--display);font-weight:600;
  font-size:clamp(.95rem,1.5vw,1.18rem);letter-spacing:-.01em;
}
.siege__ov span{display:block;font-size:.815rem;color:#D3DBE9;margin-top:.12rem;line-height:1.35}

.siege__adr{
  display:flex;align-items:center;gap:.85rem;flex-wrap:wrap;
  margin-top:clamp(1.1rem,2vw,1.7rem);
  font-family:var(--display);font-weight:600;font-size:1.02rem;color:var(--title);
}
.siege__adr svg{width:20px;height:20px;color:var(--blue);flex:none}
.siege__adr .btn{margin-left:auto;padding:.7rem 1.4rem}

/* Deux vues côte à côte, sans photo dominante : la variante employée dans la
   colonne de texte de la page contact, où la place est plus étroite et où il
   s'agit seulement de montrer l'endroit avant d'y venir. */
.siege--duo{
  grid-template-columns:repeat(2,minmax(0,1fr));
  grid-template-rows:clamp(160px,19vw,235px);
}

@media (max-width:720px){
  /* Une colonne, et chaque vignette porte son propre rapport plutôt qu'une
     hauteur de rangée commune : l'enseigne est un portrait 790 × 1180, et
     dans un bandeau paysage elle perdait l'une des deux plaques. */
  .siege{
    grid-template-columns:minmax(0,1fr);
    grid-template-rows:none;grid-auto-rows:auto;
  }
  .siege__lead{grid-row:auto;aspect-ratio:3/2}
  .siege__a{aspect-ratio:3/2}
  .siege__b{aspect-ratio:4/5}
  .siege__adr .btn{margin-left:0;width:100%;justify-content:center}
  .siege--duo{grid-template-rows:none;grid-auto-rows:auto}
  .siege--duo figure{aspect-ratio:3/2}
}

/* ================================================== ZONE D'INTERVENTION ===
   Liste et carte partagent un seul état actif, porté par la classe .is-on.
   Trois signaux d'activation seulement, toujours les mêmes : la ligne se
   tire depuis l'atelier, le marqueur grossit, le libellé apparaît. Côté
   liste, une seule transition de fond. Rien d'autre ne bouge.
   ------------------------------------------------------------------------ */
.zsec{background:var(--surface-alt)}
.zsec .section-head{margin-bottom:clamp(2rem,3.5vw,3rem)}

.zone{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.04fr);
  gap:clamp(2rem,4.5vw,4.5rem);align-items:start;
}


.zone__tier{
  display:flex;align-items:baseline;justify-content:space-between;gap:1rem;
  flex-wrap:wrap;
  margin:clamp(1.5rem,2.6vw,2.1rem) 0 .85rem;
  padding-bottom:.6rem;border-bottom:1px solid var(--border);
}
.zone__tier>span{
  font-family:var(--display);font-size:.98rem;font-weight:600;
  letter-spacing:.05em;text-transform:uppercase;color:var(--title);
}
.zone__tier>i{font-style:normal;font-size:.8rem;color:var(--faint)}
.zone__tier:first-of-type{margin-top:0}

/* Quarante-quatre lignes d'index, c'était 1 280 px de tableau : la carte se
   retrouvait à trois écrans de son propre titre. Le nuage de pastilles dit la
   même chose — nom et distance — en 450 px, et il se lit comme une couverture
   de territoire plutôt que comme un annuaire. */
.zcloud{display:flex;flex-wrap:wrap;gap:.42rem}

.zpill{
  display:inline-block;
  padding:.38rem .78rem .42rem;
  font-size:.855rem;line-height:1.25;color:var(--text);
  border:1px solid var(--border);border-radius:999px;background:#fff;
  transition:border-color .22s var(--ease),background-color .22s var(--ease),
             color .22s,transform .22s var(--ease-out);
}
.zpill.is-on,.zpill:hover,.zpill:focus-visible{
  border-color:var(--blue);background:var(--blue-wash);color:var(--blue);
  transform:translateY(-1px);
}

/* Les cinq communes qui gardent leur étiquette sur la carte la portent aussi
   dans le nuage : le repère est le même des deux côtés. */
.zpill--key{border-color:rgba(1,74,209,.28);font-weight:600;color:var(--title)}

.zone__all{
  display:block;margin-top:clamp(1.5rem,2.6vw,2.1rem);
  padding-top:1.2rem;border-top:1px solid var(--border);
  font-size:.9rem;color:var(--muted);
}
.zone__all span{
  display:inline-flex;align-items:center;gap:.45rem;margin-top:.25rem;
  font-weight:600;color:var(--blue);
}
.zone__all svg{width:15px;height:15px;transition:transform .3s var(--ease)}
.zone__all:hover svg{transform:translateX(5px)}

/* --- La carte --- */
.zone__fig{position:sticky;top:calc(var(--header-h) + 2rem)}
.map{position:relative;width:100%;aspect-ratio:1;max-width:600px;margin-inline:auto}
.map svg{width:100%;height:100%;overflow:visible}
.map .ring{fill:none;stroke:var(--border);stroke-width:1}
.map .ring--d{stroke-dasharray:3 6}
.map .rlabel{font-family:var(--body);font-size:11px;font-weight:600;fill:var(--faint);letter-spacing:.1em}

.map .town{cursor:pointer}
.map .spoke{stroke:var(--border);stroke-width:1;stroke-dasharray:2 5}
/* Ligne d'activation : tracée depuis l'atelier vers la commune. */
.map .spoke-on{
  stroke:var(--blue);stroke-width:1.6;fill:none;
  stroke-dasharray:1;stroke-dashoffset:1;
  transition:stroke-dashoffset .5s var(--ease-out);
}
.map .town.is-on .spoke-on{stroke-dashoffset:0}

.map .dot{fill:var(--blue);transition:r .3s var(--ease),fill .3s}
.map .town.is-on .dot{r:7;fill:var(--blue-d)}
/* Repli pour les cartes sans état partagé (page /zones-intervention/). */
.map .town:hover .dot{r:6;fill:var(--blue-d)}
.map .town:hover .tlabel{fill:var(--blue)}
.map .town.is-on .dot--big{r:8.5}

.map .tlabel{
  font-family:var(--body);font-size:12.5px;font-weight:500;fill:var(--text);
  transition:fill .25s,opacity .28s var(--ease);
  pointer-events:none;
}
.map .tlabel--big{font-size:15px;font-weight:700;fill:var(--title)}
/* Libellés de la grappe proche : un seul est visible à la fois, avec un
   liseré blanc pour rester lisible par-dessus les autres marqueurs. */
.map .tlabel--hid{
  opacity:0;font-weight:600;
  paint-order:stroke fill;stroke:var(--surface-alt);stroke-width:4px;stroke-linejoin:round;
}
.map .town.is-on .tlabel{fill:var(--blue)}
.map .town.is-on .tlabel--hid{opacity:1}

.map .hq{fill:var(--blue);filter:drop-shadow(0 6px 16px rgba(1,74,209,.45))}
.map .hqlabel{font-family:var(--display);font-size:17px;font-weight:700;fill:var(--title);text-transform:uppercase;letter-spacing:.02em}
.map .pulse{fill:var(--blue);opacity:.16;transform-origin:center;animation:pulse 3.2s ease-out infinite}

@media (max-width:1080px){
  .zone{grid-template-columns:minmax(0,1fr)}
  /* La carte passe au-dessus : elle donne le contexte avant la liste. */
  .zone__fig{position:static;order:-1;max-width:520px;margin-inline:auto;width:100%}
}
@media (max-width:560px){
  .zcloud{gap:.36rem}
  .zpill{padding:.34rem .62rem .38rem;font-size:.81rem}
  .zone__fig{max-width:none;margin-inline:calc(-1 * var(--gutter) / 2)}
  .map .tlabel{font-size:15px}
  .map .tlabel--big{font-size:17px}
  .map .rlabel{font-size:12.5px}
  .map .hqlabel{font-size:19px}
}

/* ================================================================ AVIS === */
.rev-marquee{overflow:hidden;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 6%,#000 94%,transparent);
          mask-image:linear-gradient(90deg,transparent,#000 6%,#000 94%,transparent);
}
.rev-track{display:flex;width:max-content;gap:1.15rem;animation:slide 64s linear infinite}
.rev-marquee:hover .rev-track{animation-play-state:paused}
.rev-set{display:flex;gap:1.15rem;padding-right:1.15rem}
.review{
  width:min(84vw,380px);flex:none;
  background:#fff;border:1px solid var(--border);border-radius:var(--r-lg);
  padding:1.75rem;display:flex;flex-direction:column;gap:1rem;
  box-shadow:var(--sh-xs);transition:box-shadow .35s,transform .35s var(--ease);
}
.review:hover{box-shadow:var(--sh-md);transform:translateY(-3px)}
.review .stars svg{width:16px;height:16px}
.review p{font-size:.94rem;color:var(--text);flex:1;line-height:1.62}
.review__who{display:flex;align-items:center;gap:.8rem;padding-top:1rem;border-top:1px solid var(--border)}
.review__av{
  width:40px;height:40px;border-radius:50%;flex:none;display:grid;place-items:center;
  background:linear-gradient(140deg,var(--blue-wash),#DCE7FF);color:var(--blue);
  font-weight:700;font-size:.92rem;
}
.review__n{font-weight:600;font-size:.9rem;color:var(--title);display:block;line-height:1.3}
.review__d{font-size:.78rem;color:var(--muted)}

.gscore{
  display:inline-flex;align-items:center;gap:1.15rem;background:#fff;
  border:1px solid var(--border);border-radius:var(--r-pill);
  padding:.8rem 1.6rem;box-shadow:var(--sh-sm);
}
.gscore b{font-family:var(--display);font-size:2.1rem;line-height:1;color:var(--title)}
.gscore .stars svg{width:17px;height:17px}

/* ============================================================== ÉQUIPE === */
.team__img{
  position:relative;overflow:hidden;border-radius:var(--r-xl);aspect-ratio:16/10;
  clip-path:polygon(0 0,100% 0,100% 84%,86% 100%,0 100%);box-shadow:var(--sh-xl);
}
.team__img img{width:100%;height:100%;object-fit:cover}
.quote{
  border-left:3px solid var(--blue);padding:.35rem 0 .35rem 1.35rem;margin-top:1.6rem;
  font-family:var(--display);font-size:clamp(1.35rem,2.4vw,1.85rem);font-weight:600;
  color:var(--title);line-height:1.2;
}
.badge-rge{
  display:inline-flex;align-items:center;gap:.6rem;
  background:var(--blue-wash);border:1px solid #D5E2FF;border-radius:var(--r-sm);
  padding:.6rem .95rem;font-size:.83rem;font-weight:500;color:var(--blue-d);margin-top:1.75rem;
}
.badge-rge svg{width:17px;height:17px;color:var(--blue)}

/* ================================================================= FAQ === */
.faq{max-width:54rem;margin-inline:auto}
.faq__i{border-bottom:1px solid var(--border);transition:padding-left .4s var(--ease)}
.faq__i.is-open{padding-left:.5rem}
.faq__q{
  width:100%;display:flex;align-items:center;justify-content:space-between;gap:1.5rem;
  padding:1.45rem 0;text-align:left;
  font-family:var(--display);font-size:clamp(1.2rem,1.8vw,1.4rem);font-weight:600;
  color:var(--title);transition:color .22s;
}
.faq__q:hover{color:var(--blue)}
.faq__ico{
  width:34px;height:34px;border-radius:50%;background:var(--blue-wash);color:var(--blue);
  display:grid;place-items:center;flex:none;
  transition:transform .4s var(--ease),background-color .28s,color .28s;
}
.faq__ico svg{width:15px;height:15px}
.faq__q[aria-expanded="true"] .faq__ico{transform:rotate(135deg);background:var(--blue);color:#fff}
.faq__a{display:grid;grid-template-rows:0fr;transition:grid-template-rows .42s var(--ease-out)}
.faq__i.is-open .faq__a{grid-template-rows:1fr}
.faq__a>div{overflow:hidden}
.faq__a p{padding-bottom:1.45rem;color:var(--muted);font-size:.97rem;max-width:62ch}

/* =========================================================== CTA FINAL === */
.cta{position:relative;overflow:hidden;background:var(--ink);color:#fff;isolation:isolate}
.cta__bg{position:absolute;inset:0;z-index:-2}
.cta__bg img{width:100%;height:100%;object-fit:cover;opacity:.28}
.cta::before{
  content:"";position:absolute;inset:0;z-index:-1;
  background:
    radial-gradient(120% 90% at 12% 50%,rgba(8,13,24,.97) 30%,rgba(8,13,24,.72) 100%),
    linear-gradient(115deg,rgba(1,74,209,.5) 0%,transparent 60%);
}
.cta__in{display:grid;grid-template-columns:1.05fr .95fr;gap:clamp(2rem,5vw,4.5rem);align-items:center}
.cta h2{color:#fff}
.cta p{color:rgba(255,255,255,.8);margin-top:1.15rem;max-width:44ch}
.cta__tel{
  display:inline-flex;align-items:center;gap:.95rem;margin-top:2rem;
  font-family:var(--display);font-size:clamp(2.1rem,4.2vw,3.1rem);font-weight:700;color:#fff;
  transition:color .25s;
}
.cta__tel:hover{color:var(--blue-e)}
.cta__tel svg{width:30px;height:30px;color:var(--blue-e)}
.cta__note{font-size:.85rem;color:rgba(255,255,255,.62);margin-top:.5rem}

.form{background:#fff;border-radius:var(--r-lg);padding:clamp(1.6rem,3vw,2.4rem);box-shadow:var(--sh-xl)}
.form h3{margin-bottom:.35rem}
.form__sub{font-size:.87rem;color:var(--muted);margin-bottom:1.5rem}
.field{margin-bottom:.9rem}
.field label{display:block;font-size:.8rem;font-weight:600;color:var(--title);margin-bottom:.35rem}
.field input,.field select,.field textarea{
  width:100%;padding:.85rem 1rem;border:1.5px solid var(--border);border-radius:var(--r-sm);
  background:#fff;font-size:.95rem;transition:border-color .22s,box-shadow .22s;
}
.field input:focus,.field select:focus,.field textarea:focus{
  outline:none;border-color:var(--blue);box-shadow:0 0 0 4px rgba(1,74,209,.1)
}
.field textarea{resize:vertical;min-height:88px}
.field--row{display:grid;grid-template-columns:1fr 1fr;gap:.9rem}
.form .btn{width:100%;margin-top:.65rem}
.form__legal{font-size:.75rem;color:var(--muted);margin-top:1rem;text-align:center;line-height:1.5}

/* ============================================================== FOOTER === */
.footer{background:var(--ink);color:#8794AC;padding-top:clamp(3.5rem,6vw,5rem);font-size:.9rem}
.footer__grid{display:grid;grid-template-columns:1.5fr 1fr 1fr 1.25fr;gap:clamp(1.75rem,4vw,3.5rem);padding-bottom:3.5rem}
.footer h4{color:#fff;font-family:var(--display);font-size:1.05rem;text-transform:uppercase;letter-spacing:.07em;margin-bottom:1.15rem}
.footer a{transition:color .22s}
.footer a:hover{color:#fff}
.footer li{margin-bottom:.55rem}
.footer__logo{background:#fff;border-radius:var(--r-sm);padding:.6rem .85rem;display:inline-block;margin-bottom:1.15rem}
.footer__logo img{height:42px}
.footer__nap{display:flex;gap:.7rem;margin-bottom:.8rem;align-items:flex-start}
.footer__nap svg{width:16px;height:16px;color:var(--blue-e);flex:none;margin-top:.28rem}
.footer__bot{
  border-top:1px solid var(--border-dark);padding-block:1.5rem;
  display:flex;justify-content:space-between;gap:1rem;flex-wrap:wrap;font-size:.81rem;
}

/* ======================================================= BARRE MOBILE ====
   La barre ne s'accroche plus aux bords de l'écran : elle flotte. Un bandeau
   collé en bas se lit comme une partie du navigateur ; une carte posée
   au-dessus du contenu se lit comme une partie du site. C'est la même
   grammaire que le lanceur de l'assistant, juste au-dessus d'elle.

   Le verre est plus transparent qu'avant (.78 contre .95) parce qu'il est
   maintenant saturé : le contenu qui passe dessous reste deviné, jamais lu.
   ====================================================================== */
.callbar{
  position:fixed;z-index:70;display:none;gap:.5rem;
  left:.6rem;right:.6rem;bottom:calc(.55rem + env(safe-area-inset-bottom));
  padding:.42rem;border-radius:1.15rem;
  background:linear-gradient(178deg,rgba(255,255,255,.9) 0%,rgba(246,248,252,.82) 100%);
  border:1px solid rgba(255,255,255,.86);
  -webkit-backdrop-filter:blur(18px) saturate(180%);
  backdrop-filter:blur(18px) saturate(180%);
  /* Trois plans d'ombre : le liseré clair qui donne l'épaisseur du verre,
     l'ombre courte qui pose la carte, la longue qui la décolle du fond. */
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.9),
    0 2px 8px rgba(8,13,24,.10),
    0 14px 34px rgba(8,13,24,.20);
}
/* Le rayon intérieur suit le rayon extérieur moins la marge : sans cela les
   deux courbes ne sont pas concentriques et l'œil le voit. */
.callbar .btn{
  flex:1;padding:.85rem .7rem;font-size:.92rem;border-radius:calc(1.15rem - .42rem);
  box-shadow:none;
}
.callbar .btn--urgent{box-shadow:0 6px 16px rgba(240,118,30,.3)}
.callbar .btn:active{transform:translateY(1px) scale(.985)}
/* Elle monte une fois, au chargement, après le lanceur de l'assistant. */
.js .callbar{animation:callbarEntre .5s var(--ease-out) .35s backwards}
@keyframes callbarEntre{from{opacity:0;transform:translateY(120%)}}
@media (prefers-reduced-motion:reduce){
  .js .callbar{animation:none}
  .callbar .btn:active{transform:none}
}

/* ========================================================== ANIMATIONS === */
/* L'état masqué est conditionné à la classe `js` posée par un script inline
   dans le <head>. Si le JavaScript échoue ou est bloqué, rien n'est jamais
   caché : le contenu reste intégralement visible. */
.js .reveal{opacity:0;transform:translateY(30px);transition:opacity .8s var(--ease-out),transform .8s var(--ease-out)}
.js .reveal.is-in{opacity:1;transform:none}
.reveal-d1{transition-delay:.09s} .reveal-d2{transition-delay:.18s}
.reveal-d3{transition-delay:.27s} .reveal-d4{transition-delay:.36s} .reveal-d5{transition-delay:.45s}

/* Révélation d'image par volet — plus élégant qu'un simple fondu */



/* ========================================================== RESPONSIVE === */
@media (max-width:1200px){
  .bento{grid-template-columns:repeat(2,1fr)}
  .card--wide{grid-column:span 2}
  .gal{grid-template-columns:repeat(2,1fr);grid-auto-rows:210px}
  .rea--big,.rea--wide{grid-column:span 2}
}
@media (max-width:1080px){
  .split,.zones,.cta__in,.method{grid-template-columns:1fr}
  .split--rev .split__copy{order:0}
  .stats{grid-template-columns:repeat(2,1fr)}
  .stat:nth-child(2){border-right:0}
  .stat:nth-child(-n+2){border-bottom:1px solid var(--border)}
  .footer__grid{grid-template-columns:1fr 1fr}
  .method__visual{max-width:420px}
}
@media (max-width:720px){
  .nav,.header__tel,.header__cta>.btn{display:none}
  .burger{display:grid}
  .header__cta{margin-left:auto}
  .callbar{display:flex}
  /* La barre flotte : la réserve est sa hauteur mesurée plus son retrait bas,
     plus l’encoche éventuelle. */
  body{padding-bottom:calc(82px + env(safe-area-inset-bottom))}
}
@media (max-width:680px){
  .bento,.gal{grid-template-columns:1fr}
  .card--wide,.rea--big,.rea--wide{grid-column:span 1}
  .rea--tall,.rea--big{grid-row:span 1}
  .gal{grid-auto-rows:250px}
  .footer__grid{grid-template-columns:1fr}
  .proof__in,.stats{grid-template-columns:1fr}
  .proof__i,.stat{border-right:0;border-bottom:1px solid var(--border-dark)}
  .stat{border-bottom-color:var(--border)}
  .field--row{grid-template-columns:1fr}
  .section-head--split{align-items:flex-start}
  /* La topbar ne doit pas dévorer la hauteur au-dessus de la ligne de
     flottaison : on ne garde que la note Google, la plus persuasive. */
  .topbar__items .topbar__item:not(:first-child),
  .topbar a.topbar__item{display:none}
  .topbar__in{justify-content:center}
  .eyebrow::after{display:none}
  .section-head--center .eyebrow::before{padding-left:0;background:none}
  /* Le rapport 4/3 est désormais posé dès 1080 px, là où la grille se
     replie : cette ligne ne faisait que le répéter. Voir le bloc
     « MÉTHODE — SUR UNE COLONNE » plus bas. */
}

/* =================================== HERO — RECOMPOSITION RESPONSIVE ====
   Pas un simple empilement du desktop : à chaque palier, la grille est
   recomposée. Deux variables suffisent — la part de la colonne de texte
   (--split) et la pente de l'arête (--cut). Sous 900 px, la composition
   bascule : la photo prend une bande en haut, l'arête passe à l'horizontale.
   ------------------------------------------------------------------------ */
@media (max-width:1280px){
  .hero{--cut:17%;--split:.52}
  .hero__note{max-width:min(17.5rem,68%)}
}
@media (max-width:1080px){
  .hero{--cut:13%;--split:.56;--hero-h:clamp(540px,calc(100svh - 7rem),780px)}
  .hero__note{bottom:clamp(4.5rem,8vw,6rem)}
  .hero__socle-i{gap:.65rem}
  .hero__socle-i svg{width:18px;height:18px}
  .scroll-cue{display:none}
}
@media (max-width:720px){
  .hero{
    --hero-h:auto;
    grid-template-columns:
      [full-start] var(--gutter)
      [main-start] minmax(0,1fr)
      [mid main-end] var(--gutter)
      [full-end];
    grid-template-rows:[top copy] auto [socle] auto [bottom];
  }
  /* La photo passe derrière le texte au lieu de le précéder : le titre
     revient sous l'en-tête, et l'ordre de lecture du grand écran est
     conservé. */
  .hero__art{grid-area:top/full-start/socle/full-end;z-index:0}
  .hero__art-img{clip-path:none;inset:0}
  .hero__art-img img{object-position:58% 34%}
  /* Le voile : ouvert en haut à droite, où il n'y a que du ciel ; opaque
     sous le texte, et fondu à l'encre au contact du socle. */
  .hero__art-img::after{
    background:
      linear-gradient(182deg,rgba(8,13,24,.26) 0%,rgba(8,13,24,.5) 28%,rgba(8,13,24,.78) 68%,#080D18 100%),
      linear-gradient(96deg,rgba(8,13,24,.5) 0%,rgba(8,13,24,.14) 48%,transparent 76%);
  }
  /* L'image porte le LCP : aucune animation ne doit retarder son affichage. */
  .js .hero__art-img{animation:none}
  .js .hero__art-img img{animation:none}
  /* La nappe d'encre est entièrement couverte par la photo. */
  .hero__field{display:none}

  .hero__copy{
    grid-area:copy/main-start/socle/main-end;
    position:relative;z-index:2;
    max-width:none;padding-right:0;
    padding-block:clamp(1.9rem,6vw,2.8rem) clamp(1.7rem,5vw,2.4rem);
  }
  .hero__copy::before,.hero__copy::after{display:none}

  /* Les trois obliques du logo traversent le haut de la composition, comme
     elles traversent l'arête sur grand écran. */
  .hero__bands{z-index:1}
  .hero__bands i:nth-child(1){clip-path:polygon(86% 0,90.5% 0,64% 100%,59.5% 100%)}
  .hero__bands i:nth-child(2){clip-path:polygon(93% 0,95.2% 0,71% 100%,68.8% 100%)}
  .hero__bands i:nth-child(3){clip-path:polygon(97.5% 0,98.8% 0,75.5% 100%,74.2% 100%)}
  .hero__bands i{opacity:.28}
  .hero__note{display:none}

  .hero__socle{
    grid-area:socle/full-start/bottom/full-end;
    position:relative;z-index:2;
    grid-template-columns:repeat(2,1fr);
    padding-inline:var(--gutter);
  }
  .hero__socle-i:nth-child(odd)::before{content:none}
  .hero__socle-i:nth-child(-n+2){border-bottom:1px solid rgba(255,255,255,.1)}
  .hero__socle-i:first-child,.hero__socle-i:nth-child(3){padding-left:0}
  .hero__socle-i:nth-child(2),.hero__socle-i:last-child{padding-right:0}
}
@media (max-width:680px){
  .hero h1{font-size:min(9.4vw,2.5rem)}
  .hero__lead{font-size:.97rem;line-height:1.58}
  /* Les deux CTA tiennent sur une ligne : empilés, le second passait sous
     la barre d'appel fixe. Le libellé long est masqué à cette largeur. */
  .only-lg{display:none}
  .hero__actions{gap:.6rem;flex-wrap:nowrap}
  .hero__actions .btn{flex:1 1 0;min-width:0;padding:.95rem .6rem;font-size:.9rem}
  .hero__proof{max-width:none;gap:.55rem}
  .hero__proof b{font-size:1.5rem}
  .hero__proof-n{font-size:.78rem}
  .hero__socle-i{padding:.9rem .75rem;gap:.55rem}
  .hero__socle-i svg{width:17px;height:17px}
  .hero__socle-i b{font-size:1rem}
  .hero__socle-i span{font-size:.71rem}
}
@media (max-width:400px){
  .hero__socle{grid-template-columns:repeat(2,1fr);column-gap:.9rem}
  .hero__socle-i{padding-inline:0;align-items:flex-start}
  .hero__socle-i::before{content:none!important}
  .hero__socle-i:nth-child(-n+2){border-bottom:1px solid rgba(255,255,255,.1)}
  .hero__socle-i b{font-size:.92rem;line-height:1.2}
  .hero__socle-i span span{font-size:.7rem;line-height:1.35}
}

@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  .reveal,.reveal-img{opacity:1;transform:none;clip-path:none;transition:none}
  .marquee__track,.rev-track,.pulse,.scroll-cue i{animation:none}
  .hero h1 em::after{animation:none;transform:scaleX(1)}
  *,*::before,*::after{animation-duration:.01ms!important;transition-duration:.01ms!important}
}

@media print{.header,.topbar,.callbar,.cta,.mnav,.progress,.marquee{display:none}}

/* ==========================================================================
   PAGES INTERNES
   Composants partagés par toutes les pages hors accueil. L'ADN reste le
   même — arête oblique, encre bleu nuit, Barlow condensé — mais chaque page
   a son propre registre (voir la classe posée sur .phero).
   ========================================================================== */

/* ------------------------------------------------------- Hero de page ---- */
/* ═════════════════ LE HERO DES PAGES INTERNES — « LA COUPE » ════════════
   Reproche fondé : le hero des pages internes était la copie de celui de
   l'accueil — même panneau encre en aplomb, mêmes deux bandes obliques. Une
   page de service n'a aucune raison de se présenter comme la page d'accueil.

   Nouvelle construction, propre aux pages internes, et qui reste de la même
   famille sans être la même chose :

     1. Un motif d'écailles en fond. C'est la tuile plate lorraine, celle du
        chantier de Bosserville, réduite à sa trame. Elle n'existe nulle part
        ailleurs sur le site : c'est la signature.
     2. La photo n'est plus un fond plein cadre voilé de noir. C'est un
        panneau à droite, coupé par une pente — la même pente qu'un rampant.
     3. Une seule ligne lumineuse, qui longe cette pente au lieu de tomber à
        l'aplomb. L'accueil descend, les pages internes penchent.
     4. Le bas du bloc est lui-même une pente : la section suivante monte
        dessous au lieu de s'arrêter net sur une ligne droite.
   ======================================================================== */

.phero{
  --cut-haut:56%;         /* la coupe, en haut du bloc */
  --cut-bas:50%;          /* la même coupe, en bas */
  --pente:12%;            /* la coupe, exprimée dans le repère de la photo */
  --coupe:clamp(2rem,4.5vw,3.6rem);  /* hauteur de la pente basse */
  position:relative;isolation:isolate;overflow:hidden;
  background:var(--ink);color:#B7C1D4;
  padding-block:clamp(3.2rem,5.4vw,4.6rem) calc(clamp(2.4rem,4vw,3.4rem) + var(--coupe));
  clip-path:polygon(0 0,100% 0,100% calc(100% - var(--coupe)),0 100%);
  margin-bottom:calc(-1 * var(--coupe) / 2);
}

/* --- 1. La trame d'écailles ------------------------------------------- */
/* Deux arcs décalés d'un demi-pas : c'est le recouvrement d'une tuile plate.
   Le masque radial la fait disparaître avant d'atteindre la photo — une
   trame qui court sous une image la salit. */
.phero__panel{
  position:absolute;inset:0;z-index:-3;
  background:
    radial-gradient(72% 78% at 18% -10%,rgba(31,96,236,.30) 0%,transparent 62%),
    radial-gradient(56% 60% at -8% 104%,rgba(44,86,196,.24) 0%,transparent 70%),
    linear-gradient(152deg,#0D1836 0%,#0A1228 44%,#060B18 100%);
  /* Le panneau s'arrête sur la coupe : au-delà, c'est la photo. */
  clip-path:polygon(0 0,calc(var(--cut-haut) + .3%) 0,calc(var(--cut-bas) + .3%) 100%,0 100%);
}
.phero__panel::before{
  content:"";position:absolute;inset:0;
  --e:34px;
  background-image:
    radial-gradient(circle at 50% 100%,transparent 47.5%,rgba(150,186,255,.10) 48.5%,transparent 50%),
    radial-gradient(circle at 50% 100%,transparent 47.5%,rgba(150,186,255,.10) 48.5%,transparent 50%);
  background-size:var(--e) calc(var(--e) * .58);
  background-position:0 0,calc(var(--e) / 2) calc(var(--e) * .29);
  -webkit-mask-image:linear-gradient(104deg,#000 0%,rgba(0,0,0,.55) 34%,transparent 62%);
          mask-image:linear-gradient(104deg,#000 0%,rgba(0,0,0,.55) 34%,transparent 62%);
}

/* --- 2. La photo, en panneau incliné ---------------------------------- */
.phero__media{
  position:absolute;inset:0 0 0 var(--cut-bas);z-index:-4;overflow:hidden;
  clip-path:polygon(var(--pente) 0,100% 0,100% 100%,0 100%);
}
.phero__media img{width:100%;height:100%;object-fit:cover;object-position:50% 45%}
/* Le voile ne sert plus à faire tenir du texte blanc par-dessus — le texte
   n'est plus dessus. Il ne sert qu'à raccorder la photo à l'encre. */
.phero__media::after{
  content:"";position:absolute;inset:0;
  background:
    linear-gradient(100deg,rgba(8,13,24,.92) 0%,rgba(8,13,24,.34) 22%,transparent 46%),
    linear-gradient(180deg,rgba(8,13,24,.28) 0%,transparent 30%,rgba(8,13,24,.42) 100%);
}

/* --- 3. La ligne qui longe la pente ----------------------------------- */
.phero__bands{position:absolute;inset:0;z-index:-2;pointer-events:none}
.phero__bands i{position:absolute;inset:0;display:block;transform-origin:top center}
.phero__bands i:nth-child(1){
  background:linear-gradient(160deg,#6FA0FF,var(--blue-e) 46%,var(--blue-d));
  clip-path:polygon(var(--cut-haut) 0,calc(var(--cut-haut) + .85%) 0,calc(var(--cut-bas) + .85%) 100%,var(--cut-bas) 100%);
  filter:drop-shadow(0 0 20px rgba(77,139,255,.75));
}
.phero__bands i:nth-child(2){
  background:linear-gradient(180deg,rgba(255,255,255,.42),rgba(255,255,255,.08));
  clip-path:polygon(calc(var(--cut-haut) + 2.3%) 0,calc(var(--cut-haut) + 2.7%) 0,calc(var(--cut-bas) + 2.7%) 100%,calc(var(--cut-bas) + 2.3%) 100%);
}
.js .phero__bands i{transform:scaleY(0);animation:trace 1.1s var(--ease-out) forwards}
.js .phero__bands i:nth-child(2){animation-delay:.1s}

/* --- 4. Le contenu ---------------------------------------------------- */
/* Bornée six points en deçà du point le plus étroit de la coupe : ni le
   filet des repères ni un bouton ne peuvent la franchir. */
.phero__in{position:relative;z-index:2;max-width:min(38rem,44%)}
.phero h1{
  color:#fff;font-size:clamp(2.3rem,4.4vw,3.9rem);line-height:.98;
  letter-spacing:-.02em;margin-bottom:1.1rem;
}
.phero h1 em{font-style:normal;color:var(--blue-l);display:block}
.phero__lead{font-size:clamp(1rem,1.3vw,1.13rem);color:#AFBBD0;max-width:33rem;line-height:1.62}
.phero__lead strong{color:#fff;font-weight:600}
.phero__actions{display:flex;gap:.75rem;flex-wrap:wrap;margin-top:1.9rem}

/* Les repères : trois colonnes séparées par un filet, pas trois blocs
   flottants. Le filet part du haut et s'éteint — il tient sans peser. */
/* Trois colonnes fixes, pas un rang qui se réorganise : en flex, le
   quatrième repère tombait à la ligne et le troisième gardait un filet
   séparateur en bout de rang. La grille rend le découpage prévisible, et le
   filet se pose sur les colonnes 2 et 3 — jamais sur un début de rang. */
.phero__facts{
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  gap:1.2rem 0;
  margin-top:clamp(1.7rem,2.8vw,2.3rem);
  border-top:1px solid rgba(255,255,255,.14);padding-top:1.15rem;
}
.phero__facts div{
  position:relative;min-width:0;
  padding-inline:clamp(.9rem,1.8vw,1.5rem) clamp(.6rem,1.2vw,1rem);
}
.phero__facts div:nth-child(3n+1){padding-left:0}
.phero__facts div:not(:nth-child(3n+1))::before{
  content:"";position:absolute;top:.1rem;bottom:.1rem;left:0;width:1px;
  background:linear-gradient(180deg,rgba(255,255,255,.22),transparent);
}
.phero__facts b{
  display:block;font-family:var(--display);font-size:clamp(1.05rem,1.5vw,1.32rem);
  line-height:1.1;color:#fff;letter-spacing:-.005em;
}
.phero__facts span{display:block;font-size:.74rem;color:#8391AB;margin-top:.28rem;line-height:1.35}

/* --- Responsive ------------------------------------------------------- */
@media (max-width:1080px){
  /* La coupe se redresse et recule : le texte a besoin de plus de largeur
     qu'une photo à cette taille d'écran. Mais il lui faut toujours une
     borne — une largeur libre franchit forcément un bord oblique. */
  .phero{--cut-haut:66%;--cut-bas:60%;--pente:15%}
  .phero__in{max-width:min(34rem,54%)}
}

/* En dessous de 900 px, deux colonnes ne tiennent plus : la photo passe
   derrière le texte au lieu d'être à côté. La composition du grand écran
   pivote, elle ne se brise pas. */
@media (max-width:720px){
  .phero{--coupe:1.5rem;padding-block:clamp(1.9rem,6vw,2.6rem) clamp(2.6rem,8vw,3.6rem)}
  .phero__in{max-width:none}
  .phero__media{inset:0;clip-path:none;z-index:-4}
  .phero__media img{object-position:56% 42%}
  .phero__media::after{
    background:
      linear-gradient(182deg,rgba(8,13,24,.3) 0%,rgba(8,13,24,.54) 26%,rgba(8,13,24,.82) 66%,#080D18 100%),
      linear-gradient(96deg,rgba(8,13,24,.52) 0%,rgba(8,13,24,.16) 46%,transparent 74%);
  }
  /* Le panneau d'encre et son motif d'écailles n'ont plus de surface à eux :
     la photo occupe tout le bloc. */
  .phero__panel{display:none}
  /* Les obliques du logo restent, dans le couloir libre à droite. */
  .phero__bands i:nth-child(1){clip-path:polygon(87% 0,91% 0,66% 100%,62% 100%)}
  .phero__bands i:nth-child(2){clip-path:polygon(94% 0,96% 0,73% 100%,71% 100%)}
  .phero__bands i{opacity:.3}
}

@media (max-width:680px){
  .phero h1{font-size:clamp(1.72rem,7.7vw,2.3rem);line-height:1.02}
  .phero__facts{grid-template-columns:repeat(3,minmax(0,1fr));gap:1rem 0}
  .phero__facts div{padding-inline:.9rem .6rem}
  .phero__facts div:nth-child(3n+1){padding-left:0}
}

.crumbs{display:flex;flex-wrap:wrap;align-items:center;gap:.45rem;font-size:.8rem;color:#8B99B2;margin-bottom:1.2rem}
.crumbs a{transition:color .2s}
.crumbs a:hover{color:#fff}
.crumbs svg{width:12px;height:12px;opacity:.5}
.crumbs [aria-current]{color:#D6DEEC}

/* Chiffres posés sous le hero de page */
.prose{max-width:70ch}
.prose>*+*{margin-top:1.15rem}
.prose h2{font-size:clamp(1.8rem,3.2vw,2.6rem);margin-top:2.8rem}
.prose h2:first-child{margin-top:0}
.prose h3{font-size:clamp(1.25rem,1.8vw,1.5rem);margin-top:2rem;color:var(--title)}
.prose p{color:var(--text)}
.prose strong{color:var(--title);font-weight:600}
.prose a:not(.btn):not(.chip){color:var(--blue);text-decoration:underline;text-underline-offset:3px;text-decoration-thickness:1px}
.prose a:not(.btn):not(.chip):hover{color:var(--blue-d)}
.prose ul,.prose ol{display:grid;gap:.6rem;padding-left:0}
.prose ul{list-style:none}
.prose ul li{position:relative;padding-left:1.45rem;color:var(--text);line-height:1.72}
.prose ul li::before{
  content:"";position:absolute;left:0;top:.68em;
  width:7px;height:7px;border-radius:2px;
  background:var(--blue);transform:rotate(45deg);
}
.prose ul li strong{color:var(--title);font-weight:600}
.prose ol{counter-reset:o;list-style:none}
.prose ol li{position:relative;padding-left:2.4rem;color:var(--text);line-height:1.72;min-height:1.7rem}
.prose ol li::before{
  counter-increment:o;content:counter(o);position:absolute;left:0;top:.1rem;
  width:24px;height:24px;border-radius:50%;background:var(--blue-wash);color:var(--blue);
  font-size:.78rem;font-weight:700;display:grid;place-items:center;
}
.prose blockquote{
  border-left:3px solid var(--blue);padding:.2rem 0 .2rem 1.3rem;
  font-family:var(--display);font-size:clamp(1.3rem,2.2vw,1.7rem);font-weight:600;
  color:var(--title);line-height:1.25;
}
.prose blockquote cite{
  display:block;font-family:var(--body);font-size:.85rem;font-weight:500;
  font-style:normal;color:var(--muted);margin-top:.5rem;
}

/* Mise en page à deux colonnes : texte + colonne latérale collante */
.layout{display:grid;grid-template-columns:minmax(0,1fr) 340px;gap:clamp(2rem,5vw,4.5rem);align-items:start}
.aside{position:sticky;top:calc(var(--header-h) + 24px);display:grid;gap:1.15rem}

/* Encadré */
.note{
  background:var(--blue-wash);border:1px solid #D5E2FF;border-radius:var(--r-md);
  padding:1.35rem 1.5rem;
}
.note--warn{background:#FFF6EC;border-color:#FFE0BE}
.note__t{
  display:flex;align-items:center;gap:.55rem;font-weight:600;color:var(--title);
  margin-bottom:.5rem;font-size:.98rem;
}
.note__t svg{width:18px;height:18px;color:var(--blue)}
.note--warn .note__t svg{color:var(--urgent)}
.note p{font-size:.93rem;color:var(--text);margin:0}

/* Carte latérale de contact */
.sidecard{
  background:var(--ink);color:#B7C1D4;border-radius:var(--r-lg);
  padding:1.6rem;position:relative;overflow:hidden;isolation:isolate;
}
.sidecard::before{
  content:"";position:absolute;inset:0;z-index:-1;
  background:
    radial-gradient(70% 60% at 80% -10%,rgba(31,96,236,.45) 0%,transparent 70%),
    linear-gradient(158deg,#0D1836,#070C1B);
}
.sidecard h3{color:#fff;font-size:1.35rem;margin-bottom:.5rem}
.sidecard p{font-size:.9rem;color:#9CAAC2;margin-bottom:1.1rem}
.sidecard .btn{width:100%}
.sidecard__tel{
  display:flex;align-items:center;gap:.6rem;margin-bottom:.8rem;
  font-family:var(--display);font-size:1.75rem;font-weight:700;color:#fff;
}
.sidecard__tel svg{width:20px;height:20px;color:var(--blue-e)}

/* Sommaire d'ancres */
.toc{border:1px solid var(--border);border-radius:var(--r-md);padding:1.25rem 1.4rem;background:#fff}
/* Le titre de l encart est un H2 pour la hierarchie du document, mais il ne
   doit surtout pas peser comme un titre de section : c est une etiquette. */
.toc h4,.toc .aside-t,.aside .aside-t{
  font-family:var(--body);font-size:.76rem;font-weight:600;letter-spacing:.16em;
  text-transform:uppercase;color:var(--muted);margin-bottom:.8rem;line-height:1.3;
}
.toc ol{list-style:none;counter-reset:t;display:grid;gap:.1rem}
.toc a{
  display:flex;gap:.6rem;padding:.4rem 0;font-size:.9rem;color:var(--text);
  border-bottom:1px solid transparent;transition:color .2s;
}
.toc a::before{counter-increment:t;content:"0" counter(t);color:var(--blue);font-weight:700;font-size:.78rem;padding-top:.1rem}
.toc a:hover{color:var(--blue)}

/* --------------------------------------------------------- Composants --- */
/* Grille de fiches */
/* Six entrées : trois et trois. En auto-fit la grille en posait quatre puis
   deux, et le rang du bas restait en suspens. */
.tiles{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:clamp(1rem,2vw,1.4rem)}
/* Six cartes passent par deux colonnes ; trois cartes ne le peuvent pas —
   elles feraient 2 + 1. Elles vont directement de trois à une. */
@media (max-width:900px){
  .tiles:has(> :nth-child(4)){grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media (max-width:620px){.tiles{grid-template-columns:minmax(0,1fr)}}
.tile{
  background:#fff;border:1px solid var(--border);border-radius:var(--r-lg);
  padding:1.5rem;transition:transform .35s var(--ease),box-shadow .35s var(--ease),border-color .3s;
}
.tile:hover{transform:translateY(-4px);box-shadow:var(--sh-lg)}
.tile__ico{
  width:44px;height:44px;border-radius:12px;background:var(--blue-wash);color:var(--blue);
  display:grid;place-items:center;margin-bottom:1rem;
}
.tile__ico svg{width:22px;height:22px}
.tile h3{font-size:1.2rem;margin-bottom:.45rem}
.tile p{font-size:.92rem;color:var(--muted)}

/* Tableau */
/* Le conteneur est un enfant de grille : sans min-width:0 il se dilate à la
   largeur du tableau et pousse toute la page en débordement horizontal. */
.tablewrap{overflow-x:auto;min-width:0;max-width:100%;border:1px solid var(--border);border-radius:var(--r-md);background:#fff}
.tablewrap>table{min-width:30rem}
table{width:100%;border-collapse:collapse;font-size:.94rem;min-width:34rem}
thead th{
  background:var(--surface-alt);text-align:left;padding:.9rem 1.1rem;
  font-size:.76rem;letter-spacing:.1em;text-transform:uppercase;color:var(--muted);font-weight:700;
  border-bottom:1px solid var(--border);
}
tbody td{padding:.9rem 1.1rem;border-bottom:1px solid var(--border);color:var(--text);vertical-align:top}
tbody tr:last-child td{border-bottom:0}
tbody tr:hover{background:var(--surface-alt)}
td strong{color:var(--title)}
.num{font-family:var(--display);font-size:1.05rem;font-weight:600;color:var(--title);white-space:nowrap}

/* Bandeau d'appel à l'action en milieu de page */
.ctaband{
  position:relative;overflow:hidden;isolation:isolate;border-radius:var(--r-lg);
  background:var(--ink);color:#fff;padding:clamp(2rem,4vw,3rem);
  display:flex;align-items:center;justify-content:space-between;gap:2rem;flex-wrap:wrap;
}
.ctaband::before{
  content:"";position:absolute;inset:0;z-index:-1;
  background:
    radial-gradient(60% 90% at 88% 10%,rgba(31,96,236,.55) 0%,transparent 68%),
    repeating-linear-gradient(117deg,rgba(140,180,255,.05) 0 1px,transparent 1px 26px),
    linear-gradient(150deg,#0D1836,#070C1B);
}
.ctaband h2{color:#fff;font-size:clamp(1.7rem,3vw,2.4rem);margin-bottom:.5rem}
.ctaband p{color:rgba(255,255,255,.78);font-size:.96rem;max-width:46ch}
.ctaband__act{display:flex;gap:.8rem;flex-wrap:wrap;flex:none}

/* Liste de communes */
.towns{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:.5rem}
.towns a{
  display:flex;align-items:center;justify-content:space-between;gap:.7rem;
  padding:.75rem 1rem;border:1px solid var(--border);border-radius:var(--r-sm);
  background:#fff;font-size:.92rem;color:var(--title);font-weight:500;
  transition:.25s var(--ease);
}
.towns a span{font-size:.78rem;color:var(--muted);font-variant-numeric:tabular-nums}
.towns a:hover{border-color:var(--blue);background:var(--blue-wash);transform:translateY(-2px)}
.towns a:hover span{color:var(--blue)}

/* Étapes numérotées horizontales */
/* Trois etapes : trois colonnes ou une, jamais deux. */
.flow{counter-reset:f;display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:clamp(1.2rem,2.5vw,2rem)}
@media (max-width:640px){.flow{grid-template-columns:minmax(0,1fr)}}
/* Le filet traversait le numéro en son milieu : deux traits superposés,
   aucun des deux lisible. Le filet ouvre le bloc, le numéro se pose dessous
   — et il devient net au lieu d'être un fantôme à 18 %. */
.flow__i{position:relative;padding-top:2.9rem}
.flow__i::before{
  content:"";position:absolute;top:0;left:0;right:0;height:2px;
  background:linear-gradient(90deg,var(--blue) 0 34px,var(--border) 34px);
}
.flow__i::after{
  counter-increment:f;content:"0" counter(f);position:absolute;top:.95rem;left:0;
  font-family:var(--display);font-size:1.32rem;font-weight:800;color:var(--blue);
  line-height:1;letter-spacing:.01em;font-variant-numeric:tabular-nums;
}
.flow__i h3{font-size:1.08rem;margin-bottom:.35rem}
.flow__i p{font-size:.89rem;color:var(--muted)}

/* Galerie de réalisations en page dédiée */
.works{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:clamp(1rem,2vw,1.4rem)}
.work{
  background:#fff;border:1px solid var(--border);border-radius:var(--r-lg);overflow:hidden;
  display:flex;flex-direction:column;transition:transform .35s var(--ease),box-shadow .35s var(--ease);
}
.work:hover{transform:translateY(-5px);box-shadow:var(--sh-lg)}
.work__img{aspect-ratio:4/3;overflow:hidden;background:var(--surface-alt)}
.work__img img{width:100%;height:100%;object-fit:cover;transition:transform .9s var(--ease)}
.work:hover .work__img img{transform:scale(1.06)}
.work__b{padding:1.3rem 1.4rem 1.5rem;display:flex;flex-direction:column;gap:.5rem;flex:1}
.work__city{
  display:flex;align-items:center;gap:.4rem;font-size:.72rem;font-weight:700;
  letter-spacing:.12em;text-transform:uppercase;color:var(--blue);
}
.work__city svg{width:12px;height:12px}
.work__b h3{font-size:1.15rem}
.work__b p{font-size:.89rem;color:var(--muted);flex:1}
.work__meta{display:flex;flex-wrap:wrap;gap:.4rem;margin-top:.3rem}
.work__meta span{
  font-size:.74rem;padding:.25rem .6rem;border-radius:var(--r-pill);
  background:var(--surface-alt);color:var(--muted);
}

/* Bloc légal */
.legal{max-width:74ch}
.legal h2{font-size:clamp(1.4rem,2.2vw,1.8rem);margin-top:2.4rem}
.legal h2:first-child{margin-top:0}
.legal p,.legal li{font-size:.95rem;color:var(--text)}
.legal>*+*{margin-top:.9rem}
.legal dl{display:grid;grid-template-columns:auto 1fr;gap:.5rem 1.5rem;font-size:.95rem}
.legal dt{font-weight:600;color:var(--title)}
.legal dd{margin:0;color:var(--text)}

@media (max-width:980px){
  .layout{grid-template-columns:minmax(0,1fr)}
  .aside{position:static}
  /* Reliquat de l'ancien héros. La coupe est gérée par les paliers 1080 et
     900 ; ce bloc n'a plus rien à faire ici. Il ne doit surtout pas libérer
     la colonne de texte : entre 901 et 980 px, la photo occupe encore le
     panneau de droite. */
}
@media (max-width:560px){
  .phero__facts{gap:1.4rem}
  .phero__facts b{font-size:1.55rem}
  .ctaband{flex-direction:column;align-items:flex-start}
  .legal dl{grid-template-columns:1fr;gap:.15rem 0}
  .legal dd{margin-bottom:.6rem}
}

/* ==========================================================================
   LECTEUR VIDÉO
   Rien n'est téléchargé tant que le visiteur n'a pas cliqué : l'affiche seule
   est chargée, la vidéo n'arrive qu'à la demande. Une vidéo de 10 Mo ne doit
   jamais peser sur le temps de chargement de la page.
   ========================================================================== */
.vplayer{
  position:relative;overflow:hidden;border-radius:var(--r-lg);
  aspect-ratio:1280/674;background:var(--ink-2);
  box-shadow:var(--sh-xl);
  clip-path:polygon(0 0,100% 0,100% 88%,90% 100%,0 100%);
}
.vplayer__poster{width:100%;height:100%;object-fit:cover}
.vplayer::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(190deg,rgba(8,13,24,.15) 0%,transparent 40%,rgba(8,13,24,.65) 100%);
  transition:opacity .4s;
}
.vplayer.is-playing::after{opacity:0}
.vplayer__play{
  position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);z-index:3;
  width:clamp(74px,8vw,102px);aspect-ratio:1;border-radius:50%;
  background:rgba(255,255,255,.14);border:1.5px solid rgba(255,255,255,.4);
  backdrop-filter:blur(14px) saturate(160%);
  display:grid;place-items:center;color:#fff;
  transition:transform .35s var(--ease),background-color .3s,border-color .3s;
}
.vplayer__play svg{width:34%;height:34%;margin-left:8%}
.vplayer__play::before{
  content:"";position:absolute;inset:-2px;border-radius:50%;
  border:1.5px solid rgba(255,255,255,.5);
  animation:halo 2.8s ease-out infinite;
}
@keyframes halo{0%{transform:scale(1);opacity:.7}100%{transform:scale(1.5);opacity:0}}
.vplayer:hover .vplayer__play{transform:translate(-50%,-50%) scale(1.07);background:var(--blue);border-color:var(--blue)}
.vplayer__meta{
  position:absolute;left:1.4rem;bottom:1.4rem;z-index:3;
  display:inline-flex;align-items:center;gap:.6rem;
  background:rgba(8,13,24,.6);backdrop-filter:blur(10px);
  border:1px solid rgba(255,255,255,.14);border-radius:var(--r-pill);
  padding:.45rem 1rem;font-size:.8rem;color:#D6DEEC;
}
.vplayer__meta b{color:#fff;font-weight:600}
.vplayer__video{width:100%;height:100%;object-fit:cover;display:block;background:#000}
.vplayer.is-playing{clip-path:none}

/* Colonne de points clés à côté du lecteur */
.vpoints{display:grid;gap:1.15rem;align-content:center}
.vpoints li{display:flex;gap:.9rem;align-items:flex-start}
.vpoints svg{width:22px;height:22px;color:var(--blue-e);flex:none;margin-top:.15rem}
.vpoints b{display:block;color:#fff;font-family:var(--display);font-size:1.25rem;font-weight:600;line-height:1.15}
.vpoints span{display:block;font-size:.88rem;color:#93A0B8;margin-top:.15rem}

.videosec{display:grid;grid-template-columns:1.45fr .95fr;gap:clamp(2rem,4vw,3.5rem);align-items:center}
@media (max-width:980px){
  .videosec{grid-template-columns:1fr}
  .vplayer{clip-path:polygon(0 0,100% 0,100% 92%,93% 100%,0 100%)}
}
@media (max-width:560px){
  .vplayer__meta{left:.9rem;bottom:.9rem;font-size:.74rem;padding:.38rem .8rem}
}









/* ═══════════════════════════════════════════════ PAGE RÉALISATIONS ═════
   ADN propre à la page : un mur de chantiers filtrable, puis la
   matériauthèque en strates — la page se lit comme une coupe de toiture. */

/* --- Barre de filtres ------------------------------------------------ */
.filters{
  display:flex;flex-wrap:wrap;gap:.55rem;align-items:center;
  margin:0 0 clamp(1.6rem,3vw,2.4rem)
}
.filter{
  appearance:none;cursor:pointer;font:inherit;
  display:inline-flex;align-items:center;gap:.5rem;
  padding:.6rem 1.05rem;border-radius:100px;
  border:1px solid var(--border);background:#fff;color:var(--text);
  font-size:.86rem;font-weight:600;letter-spacing:.01em;
  transition:background .25s var(--ease),color .25s var(--ease),
             border-color .25s var(--ease),transform .25s var(--ease),box-shadow .25s var(--ease)
}
.filter b{
  font-size:.72rem;font-weight:700;color:var(--muted);
  background:var(--surface-alt);border-radius:100px;padding:.1rem .42rem;
  transition:background .25s var(--ease),color .25s var(--ease)
}
.filter:hover{border-color:var(--blue);color:var(--blue);transform:translateY(-2px)}
.filter[aria-pressed="true"]{
  background:var(--ink);border-color:var(--ink);color:#fff;box-shadow:var(--sh-lg)
}
.filter[aria-pressed="true"] b{background:rgba(255,255,255,.16);color:#fff}

/* Le mur : chaque vignette se replie sans faire sauter la grille. */
.gal .rea{transition:opacity .45s var(--ease),transform .45s var(--ease),box-shadow .35s var(--ease)}
.gal.is-filtering .rea{animation:pop .5s var(--ease-out) backwards}
@keyframes pop{from{opacity:0;transform:scale(.955)}to{opacity:1;transform:none}}

/* Sur la page réalisations les vignettes ne sont pas des liens : le
   curseur ne doit pas mentir. */
figure.rea{cursor:default}
figure.rea:hover img{transform:scale(1.05)}

.gal__empty{
  grid-column:1/-1;text-align:center;color:var(--muted);
  padding:3rem 1rem;font-size:.95rem
}

/* --- Matériauthèque : des strates, comme les couches d'un toit ------- */
.mat{display:grid;gap:clamp(1rem,2vw,1.5rem)}
.mat__i{
  display:grid;grid-template-columns:minmax(0,.85fr) minmax(0,1.15fr);
  align-items:stretch;gap:0;overflow:hidden;
  border:1px solid var(--border);border-radius:var(--r-lg);background:#fff
}
.mat__i:nth-child(even) .mat__ph{order:2}
.mat__ph{position:relative;overflow:hidden;min-height:clamp(220px,26vw,340px);background:var(--surface-alt)}
.mat__ph img{width:100%;height:100%;object-fit:cover;transition:transform 1.2s var(--ease-out)}
.mat__i:hover .mat__ph img{transform:scale(1.05)}
.mat__n{
  position:absolute;left:1rem;top:1rem;z-index:2;
  font-family:var(--display);font-size:.78rem;font-weight:700;letter-spacing:.16em;
  color:#fff;background:rgba(6,14,30,.62);backdrop-filter:blur(6px);
  border-radius:100px;padding:.4rem .85rem
}
.mat__b{padding:clamp(1.5rem,3vw,2.4rem)}
.mat__b h3{font-size:clamp(1.25rem,2.2vw,1.6rem);margin-bottom:.6rem}
.mat__b p{font-size:.95rem;color:var(--muted)}
.mat__tags{display:flex;flex-wrap:wrap;gap:.4rem;margin-top:1.1rem}
.mat__tags span{
  font-size:.75rem;font-weight:600;color:var(--blue);
  background:var(--blue-wash);border-radius:100px;padding:.3rem .7rem
}

/* --- « Ce qui ne se voit pas » : liste numérotée sur fond encre ------ */
/* Quatre postes : meme regle que .svmats. */
.unseen{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:clamp(1.4rem,3vw,2.4rem)}
/* Le pictogramme du poste, sur fond encre : meme langage que les autres
   pages, en version claire. */
.unseen__ico{
  display:grid;place-items:center;width:44px;height:44px;border-radius:12px;
  background:rgba(77,139,255,.14);color:var(--blue-e);
  margin-bottom:1rem;border:1px solid rgba(120,166,255,.22);
}
.unseen__ico svg{width:22px;height:22px}
@media (max-width:1080px){.unseen{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:560px){.unseen{grid-template-columns:minmax(0,1fr)}}
.unseen__i{position:relative;padding-left:3.4rem}
.unseen__i::before{
  content:attr(data-n);position:absolute;left:0;top:-.15rem;
  font-family:var(--display);font-size:1.5rem;font-weight:700;
  color:var(--blue-e);opacity:.9;line-height:1
}
.unseen__i::after{
  content:"";position:absolute;left:.15rem;top:2rem;bottom:.2rem;width:1px;
  background:linear-gradient(180deg,rgba(255,255,255,.22),transparent)
}
.unseen__i h3{font-size:1.06rem;margin-bottom:.4rem;color:#fff}
.unseen__i p{font-size:.9rem;color:rgba(255,255,255,.72)}

@media (max-width:820px){
  .mat__i{grid-template-columns:1fr}
  .mat__i:nth-child(even) .mat__ph{order:0}
  .mat__ph{min-height:210px}
}

/* ══════════════════════════════════════════════════ PAGE DEVIS ═════════
   ADN propre : ici le formulaire EST le héros. Pas de grande photo, pas
   de scroll avant d'agir. Le visiteur arrive d'une annonce Ads, il doit
   pouvoir remplir ou appeler sans rien chercher. */

.dhero{
  position:relative;background:var(--ink);color:#fff;overflow:hidden;
  padding:clamp(1.5rem,3vw,2.4rem) 0 clamp(3rem,6vw,5rem)
}
.dhero::before{                       /* nappe bleue diffuse, en profondeur */
  content:"";position:absolute;inset:-30% -10% auto -20%;height:120%;
  background:radial-gradient(60% 60% at 22% 30%,rgba(1,74,209,.42),transparent 70%);
  pointer-events:none
}
.dhero__bands{position:absolute;inset:0;pointer-events:none;opacity:.5}
.dhero__bands i{position:absolute;inset:0;display:block;background:var(--blue-e);transform-origin:top center}
.dhero .crumbs{margin-bottom:clamp(1rem,2vw,1.5rem)}
.dhero__bands i:nth-child(1){clip-path:polygon(6% 0,7.1% 0,31.1% 100%,30% 100%)}
.dhero__bands i:nth-child(2){clip-path:polygon(9.6% 0,10.2% 0,34.2% 100%,33.6% 100%);opacity:.6}
.dhero__bands i:nth-child(3){clip-path:polygon(12.2% 0,12.5% 0,36.5% 100%,36.2% 100%);opacity:.35}
.js .dhero__bands i{transform:scaleY(0);animation:trace 1.1s var(--ease-out) forwards}
.js .dhero__bands i:nth-child(2){animation-delay:.09s}
.js .dhero__bands i:nth-child(3){animation-delay:.16s}

.dhero__grid{
  position:relative;z-index:2;display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,.95fr);
  gap:clamp(2rem,5vw,4.5rem);align-items:start
}
.dhero h1{color:#fff;font-size:clamp(2.3rem,5vw,4.1rem);line-height:.98;letter-spacing:-.015em}
.dhero h1 em{font-style:normal;color:var(--blue-e)}
.dhero__lead{font-size:clamp(1rem,1.5vw,1.15rem);color:#B9C4D6;margin-top:1.2rem;max-width:32rem}
.dhero__lead strong{color:#fff}

/* L'appel reste au même niveau que le formulaire : beaucoup de gens ne
   remplissent jamais un champ, ils composent un numéro. */
.dhero__tel{
  display:inline-flex;align-items:center;gap:.9rem;margin-top:1.8rem;
  padding:1rem 1.5rem 1rem 1.15rem;border-radius:var(--r-pill);
  background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.16);
  color:#fff;transition:background .3s var(--ease),transform .3s var(--ease),border-color .3s var(--ease)
}
.dhero__tel:hover{background:rgba(255,255,255,.13);border-color:rgba(255,255,255,.3);transform:translateY(-2px)}
.dhero__tel svg{width:26px;height:26px;color:var(--urgent);flex:none}
.dhero__tel b{display:block;font-family:var(--display);font-size:1.6rem;line-height:1}
.dhero__tel span{display:block;font-size:.76rem;color:#8B99B2;margin-top:.15rem}

.dhero__points{display:grid;gap:.85rem;margin-top:2.2rem;max-width:30rem}
.dhero__points li{display:flex;gap:.75rem;align-items:flex-start;font-size:.93rem;color:#C6D0E0}
.dhero__points svg{width:19px;height:19px;color:var(--blue-e);flex:none;margin-top:.16rem}

/* La carte formulaire, biseautée comme les autres surfaces de la marque. */
.dform{
  background:#fff;color:var(--text);border-radius:var(--r-lg);
  padding:clamp(1.5rem,3vw,2.4rem);box-shadow:var(--sh-xl);
  clip-path:polygon(0 0,100% 0,100% calc(100% - 34px),calc(100% - 34px) 100%,0 100%)
}
/* ⚠️ DEUX CARTES EMPILÉES — signalé le 15/09/2026 (« un morceau gris de
   chaque côté du formulaire »).

   `.form` est une carte autonome : fond blanc, rayon, padding ET `--sh-xl`.
   Elle est juste là où elle est seule (colonne de l'accueil, aside du bas de
   /contact/). Mais dans `.dform`, la carte est DÉJÀ dessinée par le parent :
   on se retrouvait avec deux fonds blancs et surtout DEUX ombres, celle de
   l'enfant venant peindre un halo gris sur le blanc du parent — d'où la bande
   grise sur les côtés, et un double rembourrage qui rétrécissait les champs.

   À l'intérieur de `.dform`, `.form` n'est donc plus qu'un conteneur de
   champs : aucune décoration propre. */
.dform>.form{
  gap:0;background:none;border-radius:0;padding:0;box-shadow:none;
}
.dform h2{font-size:clamp(1.3rem,2.2vw,1.7rem);color:var(--title);margin-bottom:.35rem}
.dform__sub{font-size:.9rem;color:var(--muted);margin-bottom:1.5rem}
.dform__foot{
  margin-top:1.1rem;padding-top:1.1rem;border-top:1px solid var(--border);
  font-size:.8rem;color:var(--muted);line-height:1.6
}
.dform__foot a{text-decoration:underline}
/* Posée par le script quand le visiteur arrive depuis le diagnostic : elle
   explique pourquoi deux champs sont déjà remplis, sinon on croit à un bug. */
.dform__reprise{
  display:flex;gap:.55rem;margin-bottom:1.15rem;padding:.7rem .85rem;
  border-radius:var(--r-xs);background:var(--blue-wash);
  border:1px solid rgba(1,74,209,.16);
  font-size:.82rem;line-height:1.5;color:var(--blue-d);
}
.dform__reprise::before{content:"✓";font-weight:700;color:var(--blue)}

/* --- Ligne de réassurance sous le héros ----------------------------- */
/* Quatre chiffres : quatre colonnes, puis deux. */
.reassure{
  display:grid;grid-template-columns:repeat(4,minmax(0,1fr));
  gap:0;border:1px solid var(--border);border-radius:var(--r-md);
  background:#fff;overflow:hidden;margin-top:clamp(-2rem,-3vw,-1rem)
}
.reassure__i{padding:1.4rem 1.6rem;border-right:1px solid var(--border)}
.reassure__i:last-child{border-right:0}
.reassure__i b{display:block;font-family:var(--display);font-size:1.5rem;color:var(--title);line-height:1.05}
.reassure__i span{display:block;font-size:.83rem;color:var(--muted);margin-top:.3rem}

@media (max-width:960px){
  /* minmax(0,…) : sans lui, la largeur min-content de la carte téléphone
     élargit la colonne au-delà du viewport et fait déborder la page. */
  .dhero__grid{grid-template-columns:minmax(0,1fr)}
  .dhero__points{max-width:none}
  .dhero__lead{max-width:none}
  .dhero__tel{width:100%;max-width:100%}
  .dhero__tel span span{white-space:normal}
}
@media (max-width:640px){
  .reassure__i{border-right:0;border-bottom:1px solid var(--border)}
  .reassure__i:last-child{border-bottom:0}
  .dform{clip-path:none}
}

/* ══════════════════════════════════════════════ PAGE AVIS CLIENTS ══════
   ADN propre : la preuve, en typographie. Pas de photo d'accroche — le
   score EST l'image. Puis un mur d'avis en colonnes, pas en grille : les
   témoignages n'ont pas tous la même longueur, une maçonnerie CSS les
   laisse respirer au lieu de les tronquer. */

.ahero{
  position:relative;background:var(--ink);color:#fff;overflow:hidden;
  padding:clamp(2rem,4vw,3.2rem) 0 clamp(3.5rem,7vw,6rem);text-align:center
}
.ahero::before{
  content:"";position:absolute;inset:-40% -20% auto -20%;height:150%;
  background:radial-gradient(50% 55% at 50% 25%,rgba(1,74,209,.45),transparent 70%);
  pointer-events:none
}
.ahero__bands{position:absolute;inset:0;pointer-events:none;opacity:.42}
.ahero__bands i{position:absolute;inset:0;display:block;background:var(--blue-e);transform-origin:top center}
.ahero__bands i:nth-child(1){clip-path:polygon(63% 0,64.2% 0,88.2% 100%,87% 100%)}
.ahero__bands i:nth-child(2){clip-path:polygon(66.8% 0,67.4% 0,91.4% 100%,90.8% 100%);opacity:.6}
.ahero__bands i:nth-child(3){clip-path:polygon(69.5% 0,69.8% 0,93.8% 100%,93.5% 100%);opacity:.35}
.js .ahero__bands i{transform:scaleY(0);animation:trace 1.1s var(--ease-out) forwards}
.js .ahero__bands i:nth-child(2){animation-delay:.09s}
.js .ahero__bands i:nth-child(3){animation-delay:.16s}
.ahero>.container{position:relative;z-index:2}
.ahero .crumbs{justify-content:center;margin-bottom:clamp(1.2rem,2.5vw,2rem)}

/* Le score, traité comme un logotype. */
.ascore{display:flex;flex-direction:column;align-items:center;gap:.5rem}
.ascore b{
  font-family:var(--display);font-weight:700;line-height:.8;
  font-size:clamp(6rem,17vw,13rem);letter-spacing:-.03em;
  background:linear-gradient(168deg,#FFFFFF 0%,#CBDAF5 52%,#7FA8FF 100%);
  -webkit-background-clip:text;background-clip:text;color:transparent
}
.ascore .stars svg{width:clamp(22px,3vw,30px);height:clamp(22px,3vw,30px)}
.ascore__n{font-size:.95rem;color:#B9C4D6;letter-spacing:.02em}
.ascore__n strong{color:#fff}

.ahero h1{color:#fff;font-size:clamp(2rem,4.4vw,3.5rem);line-height:1;margin-top:clamp(1.6rem,3vw,2.4rem)}
.ahero h1 em{font-style:normal;color:var(--blue-e)}
.ahero__lead{
  font-size:clamp(1rem,1.4vw,1.12rem);color:#B9C4D6;
  margin:1.1rem auto 0;max-width:44rem
}
.ahero__actions{display:flex;flex-wrap:wrap;gap:.9rem;justify-content:center;margin-top:2rem}

/* --- Mur d'avis : grille, surtout pas colonnes ----------------------
   En `columns`, des avis de 15 et de 90 mots produisent des colonnes de
   hauteurs très différentes : le bas du mur se déchire et laisse des vides.
   En grille, chaque rangée est d'un seul tenant et les cartes s'étirent à
   la même hauteur ; le texte pousse la signature en pied de carte. */
.wall{
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  gap:clamp(.9rem,1.6vw,1.4rem);align-items:stretch
}
.wall .review{width:auto;height:100%;margin:0}
.wall .review>p{flex:1}

/* L'avis d'ouverture : deux colonnes, fond encre, citation en grand.
   Il donne au mur un point d'entrée au lieu d'une bouillie homogène. */
.review--lead{
  grid-column:span 2;background:var(--ink);border-color:transparent;
  justify-content:space-between
}
.review--lead>p{
  font-family:var(--display);font-size:clamp(1.15rem,1.9vw,1.6rem);
  font-weight:500;line-height:1.42;color:#fff
}
.review--lead .wall__src{color:#8FB6FF}
.review--lead .review__who{border-top-color:rgba(255,255,255,.14)}
.review--lead .review__n{color:#fff}
.review--lead .review__d{color:rgba(255,255,255,.58)}
.review--lead .review__av{background:var(--blue);color:#fff}
.review--lead:hover{box-shadow:var(--sh-xl)}

/* La tuile qui ferme le mur : elle occupe la rangée restante au lieu de
   laisser un trou, et renvoie sur la fiche. */
.wall__more{
  grid-column:1/-1;display:flex;flex-wrap:wrap;align-items:center;
  justify-content:space-between;gap:1.4rem;
  padding:clamp(1.4rem,2.6vw,2rem) clamp(1.5rem,3vw,2.4rem);
  border-radius:var(--r-lg);border:1px solid var(--border);
  background:linear-gradient(120deg,var(--blue-wash) 0%,#fff 65%)
}
.wall__more b{
  display:block;font-family:var(--display);font-size:clamp(1.5rem,2.6vw,2.1rem);
  font-weight:700;color:var(--title);line-height:1.1
}
.wall__more span{font-size:.93rem;color:var(--muted);display:block;margin-top:.3rem}
.wall__src{
  display:inline-flex;align-items:center;gap:.4rem;
  font-size:.72rem;font-weight:600;letter-spacing:.04em;text-transform:uppercase;
  color:var(--success);margin-bottom:-.25rem
}
.wall__src svg{width:14px;height:14px}

/* --- Ce qui revient le plus souvent --------------------------------- */
/* Quatre cartes : deux colonnes, ou une. Trois laisserait la quatrième
   seule sur sa rangée, avec le vide de deux cartes à sa droite. */
.themes{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:clamp(1rem,2vw,1.5rem)}
@media (max-width:640px){.themes{grid-template-columns:minmax(0,1fr)}}
.theme{
  border:1px solid var(--border);border-radius:var(--r-lg);background:#fff;
  padding:clamp(1.4rem,2.5vw,2rem);position:relative;overflow:hidden
}
.theme::before{
  content:"";position:absolute;left:0;top:0;bottom:0;width:4px;background:var(--blue);
  transform:scaleY(0);transform-origin:top;transition:transform .7s var(--ease-out)
}
.theme.is-in::before,.reveal.is-in .theme::before{transform:scaleY(1)}
/* Le mot compte plus que la phrase qui l'entoure : il est l'objet du bloc.
   Le compte se pose à côté, en pastille — c'est la donnée, pas le titre. */
.theme h3{
  display:flex;align-items:baseline;flex-wrap:wrap;gap:.5rem .7rem;
  margin-bottom:.7rem;font-size:1rem;
}
.theme__mot{
  font-family:var(--display);font-weight:800;
  font-size:clamp(1.35rem,2.1vw,1.72rem);line-height:1;
  letter-spacing:-.01em;color:var(--title);text-transform:uppercase;
}
.theme__n{
  padding:.2rem .55rem;border-radius:999px;
  background:var(--blue-wash);color:var(--blue);
  font-family:var(--sans);font-size:.72rem;font-weight:700;
  letter-spacing:.03em;white-space:nowrap;
}
.theme>p{font-size:.92rem;color:var(--muted)}
.theme blockquote{
  margin-top:1.1rem;padding-top:1.1rem;border-top:1px dashed var(--border);
  font-size:.88rem;font-style:italic;color:var(--text);line-height:1.6
}
.theme cite{display:block;margin-top:.5rem;font-style:normal;font-size:.78rem;color:var(--muted)}

@media (max-width:1000px){
  .wall{grid-template-columns:repeat(2,minmax(0,1fr))}
  /* Sur deux colonnes, l'avis d'ouverture reprend une largeur normale : étalé
     sur toute la rangée, il laissait une cellule vide dans la rangée suivante.
     Les huit avis remplissent alors exactement quatre rangées. */
  .review--lead{grid-column:span 1}
  .review--lead>p{font-size:1.15rem}
}
@media (max-width:640px){
  .wall{grid-template-columns:minmax(0,1fr)}
  .review--lead{grid-column:span 1}
  .wall__more{flex-direction:column;align-items:flex-start}
}

/* ══════════════════════════════════════════════ PAGES LÉGALES ══════════
   ADN : la sobriété. Ces pages ne vendent rien, elles doivent être lisibles
   et trouvables. Un bandeau court, une colonne de texte, un sommaire collant. */
.lhero{
  background:var(--ink);color:#fff;position:relative;overflow:hidden;
  padding:clamp(1.5rem,3vw,2.4rem) 0 clamp(2.4rem,5vw,3.6rem)
}
.lhero::before{
  content:"";position:absolute;inset:auto -10% -60% 40%;height:150%;
  background:radial-gradient(50% 50% at 50% 50%,rgba(1,74,209,.4),transparent 70%);
  pointer-events:none
}
.lhero>.container{position:relative;z-index:2}
.lhero .crumbs{margin-bottom:clamp(.9rem,2vw,1.4rem)}
.lhero h1{color:#fff;font-size:clamp(1.9rem,4vw,3rem);line-height:1.02}
.lhero p{color:#B9C4D6;font-size:.98rem;margin-top:.9rem;max-width:52rem}
.lhero__maj{
  display:inline-block;margin-top:1.4rem;padding:.4rem .9rem;border-radius:var(--r-pill);
  background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.16);
  font-size:.78rem;color:#C6D0E0
}

/* Plan du site */
/* Six colonnes de liens : trois et trois. */
.sitemap{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:clamp(1.2rem,2.5vw,2rem)}
@media (max-width:820px){.sitemap{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:520px){.sitemap{grid-template-columns:minmax(0,1fr)}}
.sitemap section{border:1px solid var(--border);border-radius:var(--r-md);background:#fff;padding:1.4rem 1.5rem}
.sitemap h2{font-size:1.05rem;margin-bottom:.9rem;padding-bottom:.7rem;border-bottom:1px solid var(--border)}
.sitemap ul{display:grid;gap:.45rem}
.sitemap li{list-style:none}
.sitemap a{font-size:.92rem;color:var(--text);display:inline-flex;gap:.5rem;align-items:baseline}
.sitemap a::before{content:"›";color:var(--blue);font-weight:700}
.sitemap a:hover{color:var(--blue)}

/* Champs qu'il reste à faire remplir par le client. Volontairement criards :
   ces pages ne doivent pas partir en production dans cet état. */
mark[data-todo]{
  background:#FFE9E3;color:#B22B00;border:1px dashed #FF8A5B;border-radius:6px;
  padding:.1rem .45rem;font-size:.86em;font-weight:600
}

/* ═══════════════════════════════ CTA DE FIN — PAGES INTÉRIEURES ═════════
   Le bloc encre ferme la page d'un bord à l'autre, comme sur l'accueil.
   Enfermé dans un .container, il laissait un liseré blanc tout autour du
   bleu : le bloc flottait au lieu de conclure. Et .cta__in étant une
   grille à deux colonnes, une colonne restait vide quand il n'y a qu'un
   seul bloc de texte — d'où la variante centrée ci-dessous. */
.cta__in--solo{grid-template-columns:minmax(0,1fr);justify-items:center;text-align:center}
.cta__in--solo p{margin-inline:auto;max-width:52ch}
.cta__in--solo .phero__actions{justify-content:center}
.cta__in--solo .eyebrow{justify-content:center}

/* ══════════════════════════════════ D'OÙ VIENNENT LES AVIS ══════════════
   Panneau de droite du bloc éditorial : sans lui, le texte restait collé
   à gauche d'un conteneur de 1200 px, avec un vide à droite. */
.origin{
  background:var(--surface-alt);border:1px solid var(--border);
  border-radius:var(--r-lg);padding:clamp(1.5rem,3vw,2.2rem)
}
.origin__t{
  display:flex;align-items:center;gap:.6rem;font-family:var(--display);
  font-size:1.15rem;font-weight:700;color:var(--title);letter-spacing:.01em
}
.origin__t svg{width:19px;height:19px;color:var(--blue);flex:none}
.origin__tags{display:flex;flex-wrap:wrap;gap:.45rem;margin-top:1rem}
.origin__tags span{
  padding:.4rem .8rem;border-radius:var(--r-pill);background:#fff;
  border:1px solid var(--border);font-size:.84rem;color:var(--text)
}
.origin__split{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));
  gap:1.2rem;margin-top:1.8rem;padding-top:1.5rem;border-top:1px solid var(--border)
}
.origin__split b{
  display:block;font-family:var(--display);font-size:1.5rem;
  font-weight:700;color:var(--blue);line-height:1
}
.origin__split p{font-size:.87rem;color:var(--muted);margin-top:.35rem}

/* Entre le point de bascule du burger (950 px) et 1 200 px, l'en-tête était
   trop serré : « Nos services » et « Zones d'intervention » passaient à la
   ligne et déformaient la barre. On resserre les libellés plutôt que de les
   laisser se couper. */
@media (max-width:1200px){
  .header__in{gap:1rem}
  .nav__link{padding:.6rem .55rem;font-size:.89rem;white-space:nowrap}
  .nav__link::after{left:.55rem;right:.55rem}
  .header__tel{font-size:1rem}
}

/* ══════════════════════════════════ PASSE 2 — RYTHME, TYPO, MOTION ══════
   Ce bloc vient après le reste : il ajuste plutôt qu'il ne redéfinit.
   ------------------------------------------------------------------------ */

/* --- 1. Rythme vertical -------------------------------------------------
   Toutes les sections n'ont pas à respirer pareil. Trois régimes :
   compact (bandeaux d'information), courant, ample (les deux respirations
   de la page, avant et après le bloc immersif des réalisations). */
.section--compact{padding-block:clamp(2.4rem,4vw,3.6rem)}
.section--ample{padding-block:clamp(4.4rem,8vw,7.6rem)}

/* Le socle du hero et le bandeau des communes se suivent : sans ce filet,
   les deux encres se collaient en une seule masse. */
.marquee{border-top:0}

/* --- 2. En-têtes de section --------------------------------------------
   Le bloc de droite ne doit pas passer à la ligne sous le titre : il tient
   sa colonne, comme dans une mise en page de magazine. */
[data-page="/"] .section-head--split>*:first-child{flex:1 1 24rem;max-width:44rem}
[data-page="/"] .section-head--split>*:last-child{flex:0 1 27rem}
[data-page="/"] .section-head--split .lead{max-width:none}
.showsec .section-head--split>*:first-child{flex:1 1 24rem;max-width:44rem}
.showsec__aside{flex:0 1 27rem}

/* --- 3. Réalisations : placement explicite -----------------------------
   Sans lignes fixées, le placement automatique décalait l'image de droite
   d'une demi-rangée. */

/* --- 4. Compteurs : contraste d'échelle --------------------------------
   Les chiffres portent la section ; le reste se met à leur service. */
.stats{border-block:1px solid var(--border)}
.stat{padding-block:clamp(1.6rem,3vw,2.4rem)}
.stat__n{font-size:clamp(2.9rem,5.4vw,4.6rem);letter-spacing:-.03em}
.stat__l{font-size:.86rem;letter-spacing:.01em}
.stat__p{font-size:.74rem}

/* --- 5. Services : une carte domine ------------------------------------
   Six cartes de même poids, c'est un catalogue. La première prend deux
   rangées et sa légende reste ouverte : elle devient l'entrée de lecture. */
.card--hero{grid-column:span 2;grid-row:span 2;min-height:0}
.card--hero .card__body{padding:clamp(1.6rem,2.6vw,2.2rem)}
.card--hero .card__body h3{font-size:clamp(1.5rem,2.3vw,2rem);max-width:16ch}
.card--hero .card__body p{max-height:9rem;opacity:1;margin-bottom:.9rem}
.card--hero .card__i{font-size:1.1rem}
.bento{grid-auto-rows:minmax(0,1fr)}
@media (max-width:1200px){.card--hero{grid-column:span 2;grid-row:span 1}}
@media (max-width:680px){.card--hero{grid-column:span 1}}

/* --- 6. Micro-interactions ---------------------------------------------
   Rapides et tactiles : 180 à 320 ms, jamais plus. */
[data-page="/"] .link-arrow{position:relative}
[data-page="/"] .link-arrow::after{
  content:"";position:absolute;left:0;right:0;bottom:-.25em;height:1px;
  background:currentColor;transform:scaleX(0);transform-origin:right;
  transition:transform .32s var(--ease-out);
}
[data-page="/"] .link-arrow:hover::after,
[data-page="/"] .link-arrow:focus-visible::after{transform:scaleX(1);transform-origin:left}
.faq__q{transition:color .2s,padding-left .3s var(--ease)}
.step{transition:padding-left .3s var(--ease),background-color .3s}
.chip{transition:background-color .2s,border-color .2s,color .2s,transform .2s var(--ease)}

/* --- 7. Motion : un comportement par famille ---------------------------
   Le fondu + translateY générique est réservé aux blocs de texte. Les
   titres se dévoilent par un volet, les images par un balayage, les listes
   entrent élément par élément. Chaque famille a sa propre grammaire. */



.js .reveal-seq>*{
  opacity:0;transform:translateY(15px);
  transition:opacity .65s var(--ease-out),transform .65s var(--ease-out);
}
.js .reveal-seq>.is-in{opacity:1;transform:none}
.js .reveal-seq>.is-in:nth-child(2){transition-delay:.07s}
.js .reveal-seq>.is-in:nth-child(3){transition-delay:.14s}
.js .reveal-seq>.is-in:nth-child(4){transition-delay:.21s}
.js .reveal-seq>.is-in:nth-child(5){transition-delay:.28s}
.js .reveal-seq>.is-in:nth-child(6){transition-delay:.35s}
.js .reveal-seq>.is-in:nth-child(7){transition-delay:.42s}
.js .reveal-seq>.is-in:nth-child(8){transition-delay:.49s}

/* Les images des réalisations se dévoilent dans le sens de la pente : le
   volet descend la diagonale au lieu de monter à plat. */


.js .showcase .pj--b{transition-delay:.08s}
.js .showcase .pj--c{transition-delay:.14s}
.js .showcase .pj--d{transition-delay:.1s}

/* --- 8. Filets de section ----------------------------------------------
   La géométrie du métier : un raccord franc entre deux plans, pas un
   dégradé. Une oblique fine à la pente du logo ferme le bloc immersif. */
.showsec::after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:clamp(28px,4vw,54px);
  background:linear-gradient(117deg,transparent 0 49.4%,rgba(77,139,255,.5) 49.4% 49.8%,transparent 49.8%);
  pointer-events:none;
}

@media (prefers-reduced-motion:reduce){
  .js .reveal-mask,.js .reveal-mask.is-in,
  .js .showcase .reveal-img,.js .showcase .reveal-img.is-in{clip-path:none;transition:none}
  .js .reveal-seq>*{opacity:1;transform:none;transition:none}
}

/* Un élément ne doit porter qu'une seule grammaire d'animation : quand un
   titre est révélé par un volet ou une liste élément par élément, le fondu
   générique de .reveal doit se taire. Sinon les deux se superposent. */
.js .reveal.reveal-mask,
.js .reveal.reveal-seq{opacity:1;transform:none}

/* La sixième prestation ferme la grille en bandeau : sur deux colonnes, elle
   laissait deux cellules vides à droite — un trou involontaire au bas de la
   section. Pleine largeur, elle devient une respiration voulue. */
.card--band{
  grid-column:1/-1;grid-row:span 1;
  min-height:clamp(210px,24vw,300px);
}
.card--band .card__body{max-width:46rem}
.card--band .card__body h3{font-size:clamp(1.35rem,2vw,1.75rem)}
.card--band .card__body p{max-height:9rem;opacity:1;margin-bottom:.9rem;max-width:52ch}
@media (max-width:680px){.card--band{min-height:clamp(240px,60vw,320px)}}

/* ═══════════════════════════════ PASSE TYPO — PAGE D'ACCUEIL SEULEMENT ══
   Portée par [data-page="/"] : la refonte typographique ne doit rien
   changer aux autres pages.
   ------------------------------------------------------------------------ */
[data-page="/"]{
  /* Échelle fluide resserrée. Les H2 montaient à 68 px : à cette taille,
     « 152 avis, et pas un en dessous de 5 étoiles » occupait deux lignes
     pleines sans que la hiérarchie y gagne quoi que ce soit. */
  --h2:clamp(2.05rem,1.15rem + 2.5vw,3.35rem);
  --h3:clamp(1.18rem,1.05rem + .45vw,1.5rem);
}
[data-page="/"] h2{font-size:var(--h2);line-height:.96;letter-spacing:-.018em}
[data-page="/"] h3{font-size:var(--h3)}

/* Longueurs de ligne : un paragraphe de corps ne dépasse jamais 62 signes,
   une accroche 46. Au-delà, l'œil perd le début de la ligne suivante. */
[data-page="/"] .lead{max-width:46ch;line-height:1.6}
[data-page="/"] .section-head--split .lead{max-width:42ch}
[data-page="/"] .step p,
[data-page="/"] .checks li{max-width:56ch}
[data-page="/"] .card__body p{max-width:46ch}

/* Le surtitre indexé porte la respiration du titre : on la lui donne une
   fois pour toutes plutôt que par des marges au cas par cas. */
[data-page="/"] .eyebrow{margin-bottom:.95rem;font-size:.72rem;letter-spacing:.2em}
[data-page="/"] .section-head{margin-bottom:clamp(2.2rem,3.6vw,3.4rem)}

/* La grande échelle est réservée à ce qui la mérite : le titre du hero et
   les chiffres. Partout ailleurs, le texte compose au lieu de crier. */
[data-page="/"] .stat__n{font-family:var(--display);line-height:.9}
[data-page="/"] .gscore b{font-size:1.9rem}

/* ══════════════════════════════════════════════ FOCUS & MICRO-DÉTAILS ══ */
/* Les vignettes rognent leur contenu : un liseré posé à l'extérieur serait
   coupé. On le rentre. */
.pj:focus-visible,.card:focus-within,.rea:focus-visible{outline-offset:-4px}
.zpill:focus-visible{outline-offset:2px}
.map .town:focus-visible{outline:none}

/* Le surtitre du hero peut passer à la ligne sur mobile : le filet doit
   alors s'aligner sur la première ligne, pas se centrer sur les deux. */
.hero__kicker{align-items:flex-start}
.hero__kicker i{margin-top:.48em}
.hero__proof{max-width:26.5rem}

/* Le surtitre du hero tient sur une ligne jusqu'en bas de l'échelle : à
   360 px, « & en Meurthe-et-Moselle » cassait après « & EN », ce qui est le
   pire endroit possible. Texte raccourci et interlettrage resserré. */
@media (max-width:520px){
  .hero__kicker{font-size:.66rem;letter-spacing:.1em;gap:.6rem}
  .hero__kicker i{width:22px}
}

/* Annotation sur la photo de la méthode : le repère d'un plan, posé sur
   l'image, pas une légende sous l'image. */
.method__visual{position:relative}
.method__note{
  position:absolute;left:0;right:0;bottom:0;z-index:2;
  display:block;padding:clamp(1.4rem,3vw,2rem) clamp(1rem,2vw,1.4rem) clamp(.9rem,1.8vw,1.2rem);
  font-size:.78rem;color:rgba(255,255,255,.82);line-height:1.4;
  background:linear-gradient(180deg,transparent,rgba(6,10,20,.86));
}
.method__note b{
  display:block;font-family:var(--display);font-size:.8rem;font-weight:700;
  letter-spacing:.18em;text-transform:uppercase;color:var(--blue-e);margin-bottom:.2rem;
}

/* Les deux encres qui se suivent — socle du hero puis bandeau des communes —
   se lisaient comme un seul bloc. Un cran de valeur les sépare. */
.marquee{background:#060B15;border-top:1px solid rgba(255,255,255,.07)}

/* Les rangées de la grille des réalisations ont une hauteur plancher, pas
   une hauteur figée : sur mobile, la fiche technique du chantier dominant
   était tronquée par la vignette suivante. Les photos gardent leur module,
   le bloc de texte prend la hauteur qu'il lui faut. */


/* La parallaxe glisse l'image dans son cadre, pas le cadre lui-même : appliqué
   à l'enveloppe rognée, le décalage découvrait l'encre le long de l'arête.
   L'échelle donne la réserve nécessaire au glissement. */
.hero__art-img img{transform:scale(1.12) translate3d(0,var(--par,0px),0)}
@keyframes artsettle{from{transform:scale(1.2)}to{transform:scale(1.12)}}
@media (prefers-reduced-motion:reduce){
  .hero__art-img img{transform:none}
}

/* ══════════════════════════════════════════ RÉGLAGE FIN DES DURÉES ══════
   Une révélation au scroll peut durer une seconde : on la subit, elle
   raconte quelque chose. Un survol, non — il doit répondre sous 350 ms,
   sinon l'interface paraît molle sous la souris. */
.pj img{transition:transform .55s var(--ease-out)}
[data-page="/"] .card__media img{transition:transform .6s var(--ease-out)}
[data-page="/"] .btn{transition-duration:.22s}

/* Le survol ne doit rien apprendre que le clavier n'apprenne aussi. */
.pj:focus-visible .pj__m,


/* <picture> n'est qu'un conteneur de sélection : c'est lui qui doit remplir
   le panneau, sinon l'image calcule ses 100 % sur une boîte en ligne. */
.hero__art-img .hero__pic{position:absolute;inset:0;display:block}
/* Deux cadrages, deux images, deux alternatives textuelles : le panneau
   vertical du grand écran montre l'ouvrage, le bandeau du téléphone montre
   l'équipe. Une seule des deux est affichée, et une seule est téléchargée. */
.hero__art-img .hero__pic--mob{display:none}

/* ═══════════════════════════ PASSE 3 — SUPPRESSION DES VIDES ════════════
   Les trous venaient d'un mécanisme simple : la marge basse d'une section
   s'ajoute à la marge haute de la suivante. Avec --section-y à 144 px, deux
   sections voisines de même fond créaient 288 px de blanc mort — lu comme un
   trou, pas comme une respiration.
   ------------------------------------------------------------------------ */
[data-page="/"]{--section-y:clamp(2.75rem,4.2vw,4.25rem)}
[data-page="/"] .section--ample{padding-block:clamp(3rem,5vw,5rem)}
[data-page="/"] .section--compact{padding-block:clamp(2rem,3.2vw,2.75rem)}

/* Aux jonctions de même valeur, on ne paie la respiration qu'une fois. */
[data-page="/"] .section--ample+.section--alt:not(.proof):not(.section--ink):not(.showsec){padding-top:clamp(2.5rem,4vw,3.75rem)}
[data-page="/"] .section--alt+.section:not(.proof):not(.section--ink):not(.showsec){padding-top:clamp(2.5rem,4vw,3.75rem)}
[data-page="/"] .section--ink+.section--alt{padding-top:calc(clamp(2.5rem,4vw,3.75rem) + var(--p,0px))}
[data-page="/"] .section--compact+.section--ink{padding-top:calc(clamp(2.75rem,4.4vw,4rem) + var(--p))}

/* --- Compteurs : un bandeau, pas une carte qui flotte -------------------
   La carte blanche posée sur du blanc, avec quatre traits bleus dessous,
   avait l'air d'un composant oublié en cours de route. */
[data-page="/"] .stats{
  background:none;box-shadow:none;border-radius:0;
  border-top:1px solid var(--border);border-bottom:1px solid var(--border);
}
[data-page="/"] .stat::before{display:none}
[data-page="/"] .stat{padding-block:clamp(1.5rem,2.6vw,2.1rem)}

/* --- Le tiret oblique de fin de section immersive ----------------------
   Isolé sur trente pixels d'encre, il se lisait comme un défaut d'affichage.
   La section se ferme par son bord, c'est suffisant. */
.showsec::after{display:none}
.showsec{padding-bottom:clamp(3rem,5vw,4.5rem)}

/* --- FAQ : la liste ne doit pas flotter au milieu du blanc -------------- */
[data-page="/"] .faq{max-width:52rem}
[data-page="/"] .faq__q{padding-block:1.15rem}

/* --- CTA final : la colonne de gauche se cale sur le formulaire --------- */
[data-page="/"] .cta__in{align-items:center}
[data-page="/"] .cta__in>div:first-child{padding-block:clamp(0rem,2vw,1.5rem)}

/* ═════════════════════════════ ZONES — CARTE AGRANDIE, 22 COMMUNES ══════
   La carte est le sujet de la section : elle prend la plus grande colonne et
   n'est plus bridée à 600 px. La grappe autour de l'atelier compte désormais
   quatorze points — c'est précisément ce qu'elle doit montrer : une densité,
   pas une liste. Les libellés ne s'y ouvrent qu'à l'activation. */
.zone{grid-template-columns:minmax(0,.88fr) minmax(0,1.32fr)}
.map{max-width:none}
.map .dot{stroke:var(--surface-alt);stroke-width:1.4px}
.map .town.is-on .dot{r:6.5;stroke-width:2px}
.map .town.is-on .dot--big{r:8}
.map .tlabel--hid{stroke-width:4.5px}
.zone__legende{
  display:flex;flex-wrap:wrap;align-items:center;justify-content:center;
  gap:.5rem 1.35rem;margin-top:1.1rem;
  font-size:.78rem;color:var(--faint);
}
.zone__leg-i{display:inline-flex;align-items:center;gap:.45rem}
.zone__leg-hq{
  width:9px;height:9px;border-radius:50%;background:var(--blue);flex:none;
  box-shadow:0 0 0 4px rgba(1,74,209,.14);
}
.zone__leg-ring{
  width:11px;height:11px;border-radius:50%;flex:none;
  border:1px dashed rgba(1,74,209,.5);
}
.zone__leg-i--hint{color:var(--blue);font-weight:500}
@media (hover:none){.zone__leg-i--hint{display:none}}
/* Les deux colonnes de la liste doivent finir ensemble : dépareillées, elles
   ouvraient un décroché au bas du bloc. */
.zcloud{align-content:start}
/* Le sur-titre annonce déjà ces communes comme le second cercle — « de 15 à
   50 km ». Les pastilles suivaient au même niveau que les communes proches :
   la hiérarchie était écrite, pas montrée. */
.zcloud--far .zpill{background:var(--surface-alt);color:var(--muted)}
.zcloud--far .zpill:hover{background:#fff;color:var(--text)}
.zone__all{margin-top:clamp(1.2rem,2vw,1.6rem)}

@media (max-width:1080px){
  .zone{grid-template-columns:minmax(0,1fr)}
  .zone__fig{max-width:600px}
}

/* Les noms longs se replient au lieu d'être coupés par des points de
   suspension : « Laneuveville-devant-N… » n'est pas une information. Les deux
   colonnes restent alignées, la grille partage la hauteur de rangée. */


/* Colonne de gauche du CTA final : elle faisait la moitié de la hauteur du
   formulaire, d'où un décroché en bas. Trois arguments courts la calent —
   de l'information, pas du remplissage. */
.cta__pts{display:grid;gap:.6rem;margin-top:clamp(1.6rem,2.6vw,2.2rem)}
.cta__pts li{
  display:flex;align-items:flex-start;gap:.65rem;
  font-size:.9rem;color:rgba(255,255,255,.8);
}
.cta__pts li::before{
  content:"";width:16px;height:16px;flex:none;margin-top:.24rem;border-radius:50%;
  background:rgba(77,139,255,.16);
  box-shadow:inset 0 0 0 1px rgba(77,139,255,.5);
}

/* Le bandeau de chiffres n'est pas une carte : c'est une règle graduée. On
   retire complètement le cadre et l'ombre — restent deux filets et les
   séparateurs verticaux, comme sur un relevé. */
[data-page="/"] .stats{
  border:0;border-top:1px solid var(--border);border-bottom:1px solid var(--border);
  border-radius:0;box-shadow:none;background:none;overflow:visible;
}
[data-page="/"] .stat{padding-inline:clamp(.9rem,2vw,1.6rem)}
[data-page="/"] .stat:first-child{padding-left:0}
[data-page="/"] .stat:last-child{padding-right:0}

/* Sur mobile, quatre chiffres empilés occupaient 655 px pour quatre lignes
   d'information : beaucoup de vide pour peu de contenu. Deux colonnes. */
@media (max-width:680px){
  [data-page="/"] .stats{grid-template-columns:repeat(2,minmax(0,1fr))}
  [data-page="/"] .stat{
    padding:1.1rem clamp(.6rem,3vw,1.1rem);
    border-right:1px solid var(--border);border-bottom:0;
  }
  [data-page="/"] .stat:nth-child(2n){border-right:0}
  [data-page="/"] .stat:nth-child(-n+2){border-bottom:1px solid var(--border)}
  [data-page="/"] .stat__n{font-size:clamp(2.3rem,11vw,3rem)}
  [data-page="/"] .stat__l{font-size:.82rem;margin-top:.4rem}
  [data-page="/"] .stat__p{font-size:.71rem}
  .zone__legende{font-size:.7rem}
}


/* ═══════════════════ RÉVÉLATIONS — CORRECTION DE FOND ═══════════════════
   Un élément réduit à une aire nulle par clip-path n'est jamais signalé par
   IntersectionObserver : il ne reçoit donc jamais sa classe d'apparition et
   reste invisible pour toujours. C'était l'origine des titres manquants et
   des images qui ne s'affichaient pas.

   Règle : on n'anime jamais la géométrie de l'élément OBSERVÉ. On anime ce
   qu'il y a dedans.
   ------------------------------------------------------------------------ */

/* --- Titres : chaque ligne monte derrière son propre cache --- */
.ttl .ln{display:block;overflow:hidden;padding-bottom:.09em;margin-bottom:-.07em}
.ttl .ln i{display:block;font-style:normal}
.js .ttl .ln i{transform:translateY(106%);transition:transform .95s var(--ease-out)}
.js .ttl.is-in .ln i{transform:none}
.js .ttl.is-in .ln:nth-child(2) i{transition-delay:.08s}
.js .ttl.is-in .ln:nth-child(3) i{transition-delay:.16s}
/* Le fondu générique de .reveal se tait : le cache suffit. */
.js .reveal.ttl{opacity:1;transform:none}

/* --- Images : le volet descend à l'intérieur du cadre --- */
.js .reveal-img>img,
.js .reveal-img>picture>img{
  clip-path:inset(0 0 100% 0);
  transition:clip-path 1.05s var(--ease-out);
}
.js .reveal-img.is-in>img,
.js .reveal-img.is-in>picture>img{clip-path:inset(0 0 0 0)}
/* Dans le showcase, le volet suit la pente du toit. */
.js .showcase .reveal-img>img{clip-path:polygon(0 0,0 0,0 100%,0 100%)}
.js .showcase .reveal-img.is-in>img{clip-path:polygon(0 0,112% 0,112% 100%,0 100%)}
/* La légende n'apparaît qu'une fois la photo installée. */
.js .showcase .reveal-img .pj__ov{opacity:0;transition:opacity .5s .35s}
.js .showcase .reveal-img.is-in .pj__ov{opacity:1}

@media (prefers-reduced-motion:reduce){
  .js .ttl .ln i{transform:none;transition:none}
  .js .reveal-img>img,.js .reveal-img>picture>img,
  .js .showcase .reveal-img>img{clip-path:none;transition:none}
  .js .showcase .reveal-img .pj__ov{opacity:1}
}

/* ═══════════════════════ BOUTONS & TÉLÉPHONE — REPRISE 2026 ═════════════
   Les deux pastilles du hero faisaient 76 px de haut avec un rayon complet :
   deux gros galets qui se disputent l'attention. On rétablit une hiérarchie —
   une action pleine, une action tenue par un liseré — et on resserre tout.
   Ces réglages valaient d'abord pour l'accueil ; ils valent pour tout le site,
   sinon les pages internes gardent des boutons d'une autre époque que la
   page qui y mène.
   ------------------------------------------------------------------------ */
.btn{
  padding:.82rem 1.35rem;border-radius:12px;
  font-size:.94rem;font-weight:600;letter-spacing:.002em;gap:.55rem;
}
.btn--lg{padding:.95rem 1.6rem;font-size:.97rem}
.btn svg{width:16px;height:16px}
.btn--primary{
  box-shadow:0 1px 0 rgba(255,255,255,.22) inset,0 10px 26px rgba(1,74,209,.34);
}
.btn--primary:hover{box-shadow:0 1px 0 rgba(255,255,255,.28) inset,0 16px 36px rgba(1,74,209,.42)}
.btn:hover{transform:translateY(-1px)}
/* La flèche avance au survol : un signal, pas une décoration. */
.btn--primary svg{transition:transform .3s var(--ease)}
.btn--primary:hover svg{transform:translateX(4px)}

/* L'urgence n'a plus besoin d'un aplat orange de 360 px : un liseré, un
   point qui bat, et le mot. Elle reste lisible sans écraser le devis. */
.hero__actions .btn--urgent{
  background:transparent;color:#fff;
  border:1px solid rgba(255,255,255,.24);
  box-shadow:none;
}
.hero__actions .btn--urgent:hover{
  background:rgba(240,118,30,.14);border-color:rgba(240,118,30,.6);color:#fff;
}
.hero__actions .btn--urgent svg{color:var(--urgent);width:15px;height:15px}
.hero__actions .btn--urgent::after{
  content:"";width:6px;height:6px;border-radius:50%;background:var(--urgent);
  margin-left:.15rem;flex:none;
  box-shadow:0 0 0 0 rgba(240,118,30,.65);animation:ping 2.6s ease-out infinite;
}
@keyframes ping{0%{box-shadow:0 0 0 0 rgba(240,118,30,.6)}70%,100%{box-shadow:0 0 0 8px rgba(240,118,30,0)}}

/* --- Le numéro dans l'en-tête : une pastille avec un halo ---------------
   Le numéro nu ne se lisait pas comme un bouton. Une pastille bleue, un
   halo qui respire, le numéro à côté : on voit que ça s'appelle. */
.header__tel{
  gap:.7rem;font-size:1.24rem;padding:.3rem .2rem;
  transition:color .22s;
}
.header__tel svg{
  width:34px;height:34px;padding:9px;box-sizing:content-box;
  border-radius:50%;background:var(--blue);color:#fff;
  width:16px;height:16px;
  box-shadow:0 0 0 0 rgba(1,74,209,.45),0 6px 16px rgba(1,74,209,.3);
  animation:halo 3s ease-out infinite;
  transition:transform .3s var(--ease),background-color .25s;
}
@keyframes halo{
  0%{box-shadow:0 0 0 0 rgba(1,74,209,.4),0 6px 16px rgba(1,74,209,.28)}
  70%,100%{box-shadow:0 0 0 12px rgba(1,74,209,0),0 6px 16px rgba(1,74,209,.28)}
}
.header__tel:hover svg{transform:scale(1.06);background:var(--blue-d)}

/* ═════════════════════════════════════════════ BANDEAU DE PREUVES ═══════
   Le bloc qui ferme le hero. Chiffres en grand sur encre, puis le défilé des
   communes en filet. Posé sur du blanc avec un cadre, il ne se voyait pas ;
   sur encre, il fait le premier point d'arrêt de la page. */
.proofband{
  position:relative;isolation:isolate;overflow:hidden;
  background:linear-gradient(178deg,#0A1120 0%,#070C18 60%,#060A15 100%);
  padding-top:clamp(2.2rem,4vw,3.4rem);
}
.proofband__grain{
  position:absolute;inset:0;z-index:-1;pointer-events:none;
  background-image:repeating-linear-gradient(117deg,rgba(140,180,255,.07) 0 1px,transparent 1px 30px);
  -webkit-mask-image:radial-gradient(120% 100% at 78% 0%,#000,transparent 72%);
          mask-image:radial-gradient(120% 100% at 78% 0%,#000,transparent 72%);
}
.proofband .stats{
  display:grid;grid-template-columns:repeat(4,minmax(0,1fr));
  border:0;border-radius:0;background:none;box-shadow:none;overflow:visible;
  padding-bottom:clamp(2rem,3.6vw,3rem);
}
.proofband .stat{
  position:relative;padding:0 clamp(1rem,2.2vw,2rem);border:0;overflow:visible;
}
.proofband .stat+.stat::before{
  content:"";position:absolute;left:0;top:.35rem;bottom:.35rem;width:1px;
  background:linear-gradient(180deg,transparent,rgba(255,255,255,.16) 22%,rgba(255,255,255,.16) 78%,transparent);
}
.proofband .stat:first-child{padding-left:0}
.proofband .stat:last-child{padding-right:0}
.proofband .stat__n{
  font-family:var(--display);font-weight:700;line-height:.86;
  font-size:clamp(3rem,5.6vw,5rem);letter-spacing:-.035em;color:#fff;
}
.proofband .stat__n i{
  font-style:normal;font-size:.42em;font-weight:700;
  color:var(--blue-e);margin-left:.06em;letter-spacing:0;
}
.proofband .stat__l{
  font-size:.92rem;font-weight:600;color:#EAF0FB;margin-top:.85rem;letter-spacing:.005em;
}
.proofband .stat__p{display:block;font-size:.76rem;color:#7C8BA5;margin-top:.25rem}
.proofband .marquee{background:rgba(255,255,255,.035);border-top:1px solid rgba(255,255,255,.09);border-bottom:0}

@media (max-width:900px){
  .proofband .stats{grid-template-columns:repeat(2,minmax(0,1fr));gap:clamp(1.4rem,4vw,2.2rem) 0}
  .proofband .stat{padding-inline:clamp(.7rem,3vw,1.4rem)}
  .proofband .stat:nth-child(odd){padding-left:0}
  .proofband .stat:nth-child(even){padding-right:0}
  .proofband .stat:nth-child(odd)::before{content:none}
  .proofband .stat__n{font-size:clamp(2.6rem,12vw,3.6rem)}
  .proofband .stat__l{font-size:.86rem;margin-top:.6rem}
}

/* ═══════════════════════ EN-TÊTES DE SECTION — ALIGNEMENT ═══════════════
   Les deux blocs étaient calés par le bas : le paragraphe de droite partait
   donc plus haut que le titre, à hauteur du surtitre. On aligne la première
   ligne du paragraphe sur la première ligne du titre. */
[data-page="/"] .section-head--split{align-items:flex-start}
[data-page="/"] .section-head--split>*:last-child{padding-top:2.05rem}
/* Même borne que la règle générale, et pour la même raison : le calage ne vaut
   que côte à côte, et les deux colonnes s'empilent jusqu'à ~880. Cette
   variante-ci est plus spécifique que la règle générale (l'attribut de page
   la fait gagner), elle ne pouvait donc pas hériter de sa correction : à 768,
   l'accueil gardait ses 33 px de rembourrage quand toutes les autres pages
   les avaient perdus. */
@media (max-width:880px){
  [data-page="/"] .section-head--split>*:last-child{padding-top:0}
}

/* ═══════════════ SAVOIR-FAIRE — LA PENTE EN ARRIÈRE-PLAN ════════════════
   Le haut de la section était nu à gauche du surtitre. Une trame de pentes
   parallèles, à l'angle des bandes du logo, vient habiller le vide sans
   ajouter de bruit : on la remarque à peine, mais l'espace n'est plus mort. */
[data-page="/"] .section--ample{position:relative;isolation:isolate;overflow:hidden}
[data-page="/"] .section--ample::before{
  content:"";position:absolute;z-index:-1;pointer-events:none;
  left:0;right:0;top:0;height:min(46rem,60%);
  background-image:repeating-linear-gradient(117deg,
    rgba(1,74,209,.075) 0 1px,transparent 1px 34px);
  -webkit-mask-image:radial-gradient(85% 90% at 22% 0%,#000 0%,rgba(0,0,0,.5) 42%,transparent 78%);
          mask-image:radial-gradient(85% 90% at 22% 0%,#000 0%,rgba(0,0,0,.5) 42%,transparent 78%);
}
/* Trois obliques plus marquées, calées sur le surtitre : la signature du
   logo, à l'échelle de la section. */
[data-page="/"] .section--ample::after{
  content:"";position:absolute;z-index:-1;pointer-events:none;
  left:clamp(-6rem,-3vw,-2rem);top:-4rem;width:min(30rem,34vw);height:26rem;
  background:
    linear-gradient(117deg,transparent calc(50% - .8px),rgba(1,74,209,.28) calc(50% - .8px) calc(50% + .8px),transparent calc(50% + .8px)),
    linear-gradient(117deg,transparent calc(56% - .5px),rgba(1,74,209,.16) calc(56% - .5px) calc(56% + .5px),transparent calc(56% + .5px)),
    linear-gradient(117deg,transparent calc(61% - .4px),rgba(1,74,209,.1) calc(61% - .4px) calc(61% + .4px),transparent calc(61% + .4px));
  -webkit-mask-image:linear-gradient(200deg,#000 8%,transparent 82%);
          mask-image:linear-gradient(200deg,#000 8%,transparent 82%);
}

/* ══════════════════════════════ AVIS — LE SCORE SOUS LE TITRE ═══════════
   La pastille flottait à deux centimètres du titre, sans alignement. Elle
   devient une ligne composée, calée juste dessous. */
.ascore-line{
  display:inline-flex;align-items:center;gap:.7rem;flex-wrap:wrap;justify-content:center;
  margin-top:1.15rem;padding:.55rem 1.15rem;
  background:#fff;border:1px solid var(--border);border-radius:var(--r-pill);
  box-shadow:var(--sh-xs);
}
.ascore-line__g{display:block;width:20px;height:20px;flex:none}
.ascore-line b{font-family:var(--display);font-size:1.65rem;line-height:1;color:var(--title);font-weight:700}
.ascore-line .stars{color:var(--star)}
.ascore-line .stars svg{width:15px;height:15px}
.ascore-line__n{font-size:.86rem;color:var(--muted)}
.ascore-line__n strong{color:var(--title)}
.section--compact .section-head--center{margin-bottom:clamp(1.8rem,3vw,2.6rem)}

/* ══════════════════════════════════ FAQ — DEUX COLONNES ═════════════════
   La liste centrée flottait au milieu du blanc. Elle est maintenant tenue
   par une colonne de gauche qui pose la question et donne la sortie : le
   téléphone, parce que c'est ce que la page cherche à provoquer. */
.faqsec__grid{
  display:grid;grid-template-columns:minmax(0,.82fr) minmax(0,1.18fr);
  gap:clamp(2rem,5vw,5rem);align-items:start;
}
.faqsec__aside{position:sticky;top:calc(var(--header-h) + 2.5rem)}
.faqsec__aside .lead{margin-top:1.1rem;max-width:34ch}
.faqsec__tel{
  display:inline-flex;align-items:center;gap:.85rem;margin-top:1.8rem;
  padding:.7rem 1.1rem .7rem .7rem;border-radius:var(--r-pill);
  background:#fff;border:1px solid var(--border);
  transition:border-color .25s,box-shadow .3s var(--ease),transform .3s var(--ease);
}
.faqsec__tel:hover{border-color:var(--blue);box-shadow:var(--sh-md);transform:translateY(-2px)}
.faqsec__tel-i{
  width:40px;height:40px;flex:none;border-radius:50%;display:grid;place-items:center;
  background:var(--blue);color:#fff;
  box-shadow:0 0 0 0 rgba(1,74,209,.4);animation:halo 3s ease-out infinite;
}
.faqsec__tel-i svg{width:17px;height:17px}
.faqsec__tel b{display:block;font-family:var(--display);font-size:1.3rem;color:var(--title);line-height:1.1}
.faqsec__tel span span{display:block;font-size:.78rem;color:var(--muted);margin-top:.1rem}
.faqsec .faq{max-width:none;margin:0}
.faqsec .faq__i:first-child{border-top:1px solid var(--border)}

@media (max-width:900px){
  .faqsec__grid{grid-template-columns:minmax(0,1fr)}
  .faqsec__aside{position:static}
}

/* Cible de survol de chaque commune : les pastilles font 7 px de diamètre à
   l'écran — impossible à viser, d'où l'impression que la carte ne réagit
   pas. Un disque transparent de 30 px prend le survol à leur place. */
.map .hit{fill:transparent;stroke:none}
.map .tlabel{pointer-events:auto;cursor:pointer}
.map .tlabel--hid{pointer-events:none}

/* La section vidéo laissait respirer 90 px entre son titre et le lecteur :
   sur fond encre, ça se lit comme un trou. On resserre. */
[data-page="/"] .section--ink .section-head{margin-bottom:clamp(1.6rem,2.6vw,2.2rem)}

/* Le bandeau de preuves ferme le hero : pas de marge entre les deux. */
.hero+.proofband{margin-top:0}

/* Hero un peu resserré : sur un portable de 630 px de haut, chaque dizaine
   de pixels gagnée rapproche le socle de réassurance de la ligne de
   flottaison. Rien n'est sacrifié, seuls les blancs se resserrent. */
.hero{--hero-h:clamp(460px,calc(100svh - 8.5rem),780px)}
.hero__copy{padding-block:clamp(1.8rem,3.4vw,3rem)}
.hero__lead{margin-bottom:clamp(1.2rem,2.2vw,1.7rem)}
.hero__proof{margin-top:clamp(1.2rem,2.2vw,1.7rem);padding-top:clamp(1rem,1.7vw,1.35rem)}
.hero__kicker{margin-bottom:clamp(.9rem,1.6vw,1.25rem)}
.hero h1{margin-bottom:clamp(.9rem,1.7vw,1.35rem)}

/* ═══════════════════════ EN-TÊTE — LE COUPLE APPEL / DEVIS ══════════════
   Le numéro écrit en toutes lettres doublait celui de la barre du haut et de
   la barre d'appel mobile. Reste le geste : un bouton rond jumelé au devis,
   même hauteur, même rayon d'attention. */
.header__cta{gap:.6rem}
.header__tel{
  display:grid;place-items:center;flex:none;
  width:48px;height:48px;padding:0;border-radius:14px;
  /* Aucun aplat : un contour. Un carré plein sous le curseur se lisait
     comme un bloc posé sur l'en-tête. */
  background:transparent;color:var(--blue);
  border:1px solid rgba(1,74,209,.22);
  transition:color .25s var(--ease),border-color .25s var(--ease),transform .3s var(--ease);
}
.header__tel svg{
  width:19px;height:19px;padding:0;border-radius:0;
  background:none;color:currentColor;box-shadow:none;animation:none;
}
/* Le halo respire sur le bouton lui-même, pas sur l'icône. */
.header__tel::after{
  content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;
  box-shadow:0 0 0 0 rgba(1,74,209,.35);animation:halo 3.2s ease-out infinite;
}
.header__tel{position:relative}
.header__tel:hover{background:var(--blue);color:#fff;border-color:var(--blue);transform:translateY(-1px)}
.header__tel:hover svg{transform:none}
.header__cta>.btn{border-radius:14px;padding:.85rem 1.45rem;font-size:.95rem}
@keyframes halo{
  0%{box-shadow:0 0 0 0 rgba(1,74,209,.34)}
  70%,100%{box-shadow:0 0 0 12px rgba(1,74,209,0)}
}

/* Panneau du hero resserré : moins large, donc mieux servi par la définition
   native de la photo — et le titre gagne de la place. */
.hero{--split:.56}
@media (max-width:1280px){.hero{--split:.58}}
@media (max-width:1080px){.hero{--split:.6}}

/* Le volet des images durait plus d'une seconde : en défilant, on voyait la
   photo se construire au lieu d'être là. Ramené à 600 ms, et la légende suit
   de près au lieu d'attendre. */
.js .reveal-img>img,
.js .reveal-img>picture>img{transition-duration:.6s}
.js .showcase .reveal-img .pj__ov{transition:opacity .35s .2s}

/* Avec 44 communes, les libellés fixes croisent forcément des pastilles : un
   liseré de la couleur du fond les détache proprement, comme sur une carte
   IGN. */
.map .rlabel,.map .hqlabel{
  paint-order:stroke fill;stroke:var(--surface-alt);stroke-width:5px;stroke-linejoin:round;
}
.map .tlabel:not(.tlabel--hid){
  paint-order:stroke fill;stroke:var(--surface-alt);stroke-width:3.5px;stroke-linejoin:round;
}
/* La liste est plus longue que la carte : la carte reste à l'écran pendant
   qu'on parcourt les communes. */
.zone__fig{align-self:start}

/* =============================================================== SERVICES ===
   Le gabarit des pages métier. Il reprend l'ADN de l'accueil — l'aplomb, la
   palette, les titres sur deux lignes qui montent derrière leur cache — mais
   il compose autrement : ici on explique un métier, pas on présente une
   entreprise. Chaque bloc a donc une fonction éditoriale précise, et aucun
   n'est un remplissage.

   Ordre de lecture : ce qu'on fait → avec quoi → une preuve → comment →
   quand appeler → où → questions → métiers voisins → devis.
   ========================================================================= */

/* --- 1. Le chapô : la promesse à gauche, ce que comprend la prestation à
       droite. Deux colonnes de poids inégal — le texte porte, la liste
       accompagne. --- */
.svcx{
  display:grid;grid-template-columns:minmax(0,1.06fr) minmax(0,.94fr);
  gap:clamp(2rem,4.5vw,4.5rem);align-items:start;
}
.svcx>div>h2{margin-bottom:clamp(1.1rem,1.8vw,1.5rem)}
.svcx__lead{font-size:clamp(1.12rem,1.5vw,1.32rem);line-height:1.55;color:var(--title);font-weight:500}
.svcx__lead+p{margin-top:1.1rem}
.svcx p{color:var(--muted);line-height:1.72}
.svcx p+p{margin-top:1.05rem}
.svcx strong{color:var(--title);font-weight:600}

/* La prise de position de l'entreprise sur le métier. Ce n'est pas un
   paragraphe de plus : un filet la tient à gauche, il se tire à l'arrivée du
   bloc, et le corps monte d'un demi-point. */
.svcx__mot{
  position:relative;
  margin-top:clamp(1.3rem,2.2vw,1.8rem)!important;
  padding:clamp(.9rem,1.5vw,1.2rem) 0 clamp(.9rem,1.5vw,1.2rem) clamp(1.1rem,1.8vw,1.5rem);
  font-size:clamp(1.02rem,1.25vw,1.12rem);line-height:1.62!important;
  color:var(--title)!important;
}
.svcx__mot::before{
  content:"";position:absolute;left:0;top:0;bottom:0;width:3px;border-radius:2px;
  background:linear-gradient(180deg,var(--blue),rgba(1,74,209,.18));
  transform-origin:top;
}
.js .reveal .svcx__mot::before{transform:scaleY(0);transition:transform .8s .3s var(--ease-out)}
.js .reveal.is-in .svcx__mot::before{transform:scaleY(1)}

/* Le texte de gauche est plus long que la carte de droite : sans rien, il
   reste 250 px de blanc sous la carte. Elle suit donc la lecture au lieu de
   rester plantée en haut — le vide devient un mouvement. */
.svcx__card{
  position:sticky;top:calc(var(--header-h) + 2rem);
  border:1px solid var(--border);border-radius:var(--r-lg);background:#fff;
  padding:clamp(1.5rem,2.6vw,2.1rem);box-shadow:var(--sh-sm);
}
@media (max-width:1080px){.svcx__card{position:static}}
.svcx__card h3{
  font-family:var(--display);font-size:.86rem;font-weight:600;
  letter-spacing:.09em;text-transform:uppercase;color:var(--blue);
  padding-bottom:.9rem;margin-bottom:.3rem;border-bottom:1px solid var(--border);
}
.svcl{display:grid;gap:0}
.svcl li{
  display:grid;grid-template-columns:auto minmax(0,1fr);gap:.75rem;
  align-items:start;padding:.82rem 0;border-bottom:1px solid var(--border);
}
.svcl li:last-child{border-bottom:0;padding-bottom:0}
.svcl svg{width:17px;height:17px;color:var(--blue);flex:none;margin-top:.16rem}
.svcl b{display:block;font-size:.96rem;font-weight:600;color:var(--title)}
.svcl span{display:block;font-size:.88rem;color:var(--muted);margin-top:.12rem;line-height:1.5}

/* --- 2. Les matériaux : une grille de cartes photo. C'est le bloc qui
       justifie le vocabulaire du métier — tuile mécanique, ardoise, joint
       debout, lamellé-collé — avec l'image en face du mot. --- */
/* Quatre cartes : quatre colonnes, puis deux, puis une. En auto-fit,
   l etape intermediaire tombait a trois et laissait la quatrieme seule. */
.svmats{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:clamp(1rem,1.8vw,1.5rem)}
@media (max-width:1080px){.svmats{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:540px){.svmats{grid-template-columns:minmax(0,1fr)}}
.svmat{
  position:relative;overflow:hidden;border-radius:var(--r-lg);
  background:var(--ink);isolation:isolate;
  transition:transform .34s var(--ease-out),box-shadow .34s var(--ease);
}
.svmat:hover{transform:translateY(-4px);box-shadow:var(--sh-lg)}
.svmat__ph{position:relative;aspect-ratio:4/3;overflow:hidden}
.svmat__ph img{width:100%;height:100%;object-fit:cover;transition:transform .7s var(--ease-out)}
.svmat:hover .svmat__ph img{transform:scale(1.06)}
.svmat__ph::after{
  content:"";position:absolute;inset:0;
  background:linear-gradient(180deg,transparent 18%,rgba(8,13,24,.42) 52%,rgba(8,13,24,.9) 100%);
}
.svmat__b{position:absolute;inset:auto 0 0 0;padding:1.05rem 1.15rem 1.15rem;z-index:2}
.svmat__b b{
  display:block;font-family:var(--display);font-size:1.06rem;font-weight:600;
  color:#fff;line-height:1.2;
}
.svmat__b span{display:block;font-size:.84rem;color:#AEBBD2;margin-top:.3rem;line-height:1.45}

/* --- 3. La preuve : une image forte en pleine largeur, sur fond encre, avec
       sa fiche technique en dessous. C'est le même geste que la section
       « Nos chantiers » de l'accueil, resserré sur un seul chantier. --- */
.proof{background:var(--ink);color:#B7C1D4;position:relative;overflow:hidden}
.proof::before{
  content:"";position:absolute;inset:0;pointer-events:none;
  background-image:repeating-linear-gradient(117deg,rgba(140,180,255,.045) 0 1px,transparent 1px 30px);
}
.proof .container{position:relative;z-index:2}
.proof h2{color:#fff}
.proof .lead{color:#93A2BC}
.proof__fig{position:relative;overflow:hidden;border-radius:var(--r-lg);margin-top:clamp(1.8rem,3vw,2.6rem)}
.proof__fig img{display:block;width:100%;height:auto;aspect-ratio:16/9;object-fit:cover}
.proof__tag{
  position:absolute;left:clamp(1rem,2vw,1.6rem);bottom:clamp(1rem,2vw,1.6rem);
  display:inline-flex;align-items:center;gap:.55rem;
  padding:.55rem .95rem;border-radius:999px;
  background:rgba(8,13,24,.72);backdrop-filter:blur(8px);
  font-size:.8rem;color:#fff;
}
.proof__tag i{width:7px;height:7px;border-radius:50%;background:var(--blue-l);flex:none}
/* Quatre postes de fiche : quatre colonnes, puis deux, puis une. */
.proof__specs{
  display:grid;grid-template-columns:repeat(4,minmax(0,1fr));
  gap:clamp(1.2rem,2.4vw,2.2rem);
  margin-top:clamp(1.6rem,2.6vw,2.2rem);padding-top:clamp(1.4rem,2.4vw,2rem);
  border-top:1px solid rgba(255,255,255,.13);
}
.proof__specs dt{
  font-size:.72rem;letter-spacing:.1em;text-transform:uppercase;color:#6E7E9B;
  margin-bottom:.45rem;
}
.proof__specs dd{color:#DDE4F0;font-size:.94rem;line-height:1.5}

/* --- 4. Le comparateur avant/après. La poignée se déplace au pointeur, au
       clavier et au toucher : c'est un input range invisible posé sur les
       deux images, donc accessible sans une ligne de code en plus. --- */
.cmp{position:relative;border-radius:var(--r-lg);overflow:hidden;background:var(--surface-2);isolation:isolate}
.cmp{aspect-ratio:3/2}
.cmp img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;user-select:none}
.cmp__apres{position:absolute;inset:0;clip-path:inset(0 0 0 var(--x,50%))}
.cmp__r{
  position:absolute;appearance:none;-webkit-appearance:none;
  inset:0;width:100%;height:100%;margin:0;background:transparent;cursor:ew-resize;z-index:4;
}
.cmp__r::-webkit-slider-thumb{-webkit-appearance:none;width:46px;height:100%;background:transparent;cursor:ew-resize}
.cmp__r::-moz-range-thumb{width:46px;height:100%;border:0;background:transparent;cursor:ew-resize}
.cmp__r:focus-visible{outline:3px solid var(--blue);outline-offset:-3px}
.cmp__bar{position:absolute;top:0;bottom:0;left:var(--x,50%);width:2px;background:#fff;z-index:3;box-shadow:0 0 14px rgba(0,0,0,.4)}
.cmp__grip{
  position:absolute;top:50%;left:var(--x,50%);z-index:3;
  transform:translate(-50%,-50%);
  width:46px;height:46px;border-radius:50%;
  display:grid;place-items:center;background:#fff;color:var(--blue);
  box-shadow:0 6px 22px rgba(8,13,24,.34);pointer-events:none;
}
.cmp__grip svg{width:19px;height:19px}
.cmp__t{
  position:absolute;bottom:.85rem;z-index:3;padding:.4rem .8rem;border-radius:999px;
  background:rgba(8,13,24,.74);backdrop-filter:blur(6px);
  font-family:var(--display);font-size:.7rem;font-weight:600;
  letter-spacing:.11em;text-transform:uppercase;color:#fff;pointer-events:none;
}
.cmp__t--a{left:.85rem}
.cmp__t--b{right:.85rem}

/* --- 5. Le déroulé. L'image tient à gauche pendant que les étapes défilent :
       on garde le chantier sous les yeux tout le long de l'explication. --- */
.svflow{display:grid;grid-template-columns:minmax(0,.82fr) minmax(0,1.18fr);gap:clamp(2rem,5vw,5rem);align-items:start}
.svflow__fig{position:sticky;top:calc(var(--header-h) + 2rem);border-radius:var(--r-lg);overflow:hidden}
.svflow__fig img{display:block;width:100%;height:auto;aspect-ratio:3/4;object-fit:cover}
/* Les étapes des pages services utilisent désormais la chronologie
   commune (.steps / .step), définie plus bas. */

/* --- 6. Les signes qui alertent. Trame d'obliques en fond, comme les pentes
       du logo — le bloc doit se lire comme un avertissement tenu, pas comme
       une alarme. --- */
.warn{position:relative;overflow:hidden}
.warn::before{
  content:"";position:absolute;inset:0;pointer-events:none;
  background-image:repeating-linear-gradient(117deg,rgba(1,74,209,.05) 0 1px,transparent 1px 22px);
  -webkit-mask-image:radial-gradient(70% 100% at 50% 0,#000,transparent 76%);
          mask-image:radial-gradient(70% 100% at 50% 0,#000,transparent 76%);
}
.warn .container{position:relative;z-index:2}
/* Le nombre de signes change selon la page : quatre sur une page metier,
   six sur le sommaire. Deux colonnes pour quatre, trois pour six — la
   grille s adapte au contenu au lieu de le laisser en plan. */
.signs{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:clamp(.9rem,1.6vw,1.3rem)}
.signs:has(> :nth-child(5)){grid-template-columns:repeat(3,minmax(0,1fr))}
@media (max-width:900px){.signs{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:560px){.signs{grid-template-columns:minmax(0,1fr)}}
.sign{
  position:relative;padding:clamp(1.25rem,2.2vw,1.6rem);
  border:1px solid var(--border);border-radius:var(--r-md);background:#fff;
  transition:border-color .28s var(--ease),transform .28s var(--ease-out);
}
.sign:hover{border-color:rgba(1,74,209,.32);transform:translateY(-3px)}
.sign__i{
  width:38px;height:38px;border-radius:11px;display:grid;place-items:center;
  background:var(--blue-wash);color:var(--blue);margin-bottom:.9rem;
}
.sign__i svg{width:19px;height:19px}
.sign b{display:block;font-family:var(--display);font-size:1.02rem;font-weight:600;color:var(--title);margin-bottom:.4rem}
.sign p{font-size:.91rem;color:var(--muted);line-height:1.6}

/* --- 7. Le bandeau localité. Le service est le même partout, mais le
       visiteur cherche « couvreur à Nancy », pas « couvreur ». --- */
.geo{
  display:grid;grid-template-columns:minmax(0,1fr) auto;gap:clamp(1.5rem,3vw,3rem);
  align-items:center;
  padding:clamp(1.6rem,3vw,2.4rem) clamp(1.6rem,3vw,2.6rem);
  border:1px solid var(--border);border-radius:var(--r-lg);
  background:linear-gradient(120deg,var(--blue-wash) 0%,#fff 62%);
}
.geo h3{font-family:var(--display);font-size:clamp(1.15rem,1.8vw,1.42rem);font-weight:600;color:var(--title);line-height:1.25;margin-bottom:.55rem}
.geo p{font-size:.95rem;color:var(--muted);line-height:1.65;max-width:62ch}
.geo__pills{display:flex;flex-wrap:wrap;gap:.38rem;margin-top:1rem}
.geo__pills span,.geo__pills a{
  display:inline-block;padding:.3rem .68rem;border-radius:999px;
  border:1px solid var(--border);background:#fff;font-size:.81rem;color:var(--text);
}
.geo__pills a{transition:border-color .2s,color .2s}
.geo__pills a:hover{border-color:var(--blue);color:var(--blue)}
.geo__go{flex:none}

/* --- 8. Les métiers voisins. Un couvreur qui reprend une toiture touche
       forcément à la charpente et à la zinguerie : le maillage interne suit
       la réalité du chantier. --- */
/* Trois prestations voisines : trois colonnes ou une, jamais deux. */
.near{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:clamp(1rem,1.8vw,1.4rem)}
@media (max-width:680px){.near{grid-template-columns:minmax(0,1fr)}}
.nearc{
  position:relative;display:grid;grid-template-rows:auto 1fr auto;
  padding:clamp(1.3rem,2.2vw,1.7rem);
  border:1px solid var(--border);border-radius:var(--r-md);background:#fff;
  transition:border-color .28s,transform .28s var(--ease-out),box-shadow .28s;
}
.nearc:hover{border-color:rgba(1,74,209,.3);transform:translateY(-4px);box-shadow:var(--sh-md)}
.nearc__i{width:36px;height:36px;border-radius:10px;display:grid;place-items:center;background:var(--blue-wash);color:var(--blue);margin-bottom:.85rem}
.nearc__i svg{width:19px;height:19px}
.nearc b{display:block;font-family:var(--display);font-size:1.05rem;font-weight:600;color:var(--title);margin-bottom:.35rem}
.nearc p{font-size:.9rem;color:var(--muted);line-height:1.6;margin-bottom:.9rem}
/* Ces règles visaient « .nearc span » : elles habillaient donc aussi le
   picto, qui est un span lui aussi. Il en héritait display:flex et une
   taille de 14 px, ce qui le décalait en haut à gauche de sa pastille. */
.nearc__go{display:inline-flex;align-items:center;gap:.4rem;font-size:.87rem;font-weight:600;color:var(--blue)}
.nearc__go svg{width:14px;height:14px;transition:transform .3s var(--ease)}
.nearc:hover .nearc__go svg{transform:translateX(5px)}
.nearc::after{content:"";position:absolute;inset:0;border-radius:inherit}

/* --- 9. La vidéo de chantier, sur les pages qui en ont une. Affiche d'abord,
       lecture au clic : rien ne se télécharge tant qu'on ne demande pas. --- */
.clips{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:clamp(1rem,2vw,1.6rem)}
.clip{position:relative}
.clip video{display:block;width:100%;height:100%;object-fit:cover}
.clip__cap{
  position:absolute;left:0;right:0;bottom:0;z-index:2;padding:2.4rem 1.15rem 1.05rem;
  background:linear-gradient(180deg,transparent,rgba(8,13,24,.85));
  font-size:.86rem;color:#DDE4F0;pointer-events:none;
}
.clip__cap b{display:block;font-family:var(--display);font-weight:600;color:#fff;font-size:.98rem;margin-bottom:.18rem}

/* --- 10. La page mère : les neuf métiers en grille. Les cartes ne portent
       pas de photo — neuf visuels côte à côte se neutralisent. Le numéro et
       le pictogramme suffisent à distinguer, et le regard reste sur les
       mots, qui sont ici l'information. --- */
/* Neuf prestations : trois rangées de trois, pas quatre + quatre + une. */
.svgrid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:clamp(1rem,1.8vw,1.4rem)}
/* Neuf ne se divisait ni par deux ni par quatre : trois colonnes, puis une.
   Depuis le 13/09/2026 il y en a dix, et dix se divise encore moins bien —
   sur trois colonnes, la dixième carte restait seule avec les deux tiers de
   sa rangée vides. Passer à deux colonnes réglait le compte mais étirait des
   cartes courtes sur 600 px.

   La réponse est éditoriale autant que géométrique : la première carte prend
   la rangée entière. Il reste neuf cartes en trois rangées pleines, et la
   couverture — le métier d'origine, celui qu'on vient chercher — cesse d'être
   une vignette parmi dix. */
@media (min-width:761px){
  .svgrid>.svcard:first-child{
    grid-column:1/-1;
    grid-template-columns:auto minmax(0,1fr) auto;
    grid-template-rows:auto auto;
    align-items:center;
    column-gap:clamp(1.2rem,2.6vw,2.4rem);
  }
  .svgrid>.svcard:first-child .svcard__i{grid-column:1;grid-row:1/3;margin:0}
  .svgrid>.svcard:first-child b{grid-column:2;grid-row:1;align-self:end;margin:0}
  .svgrid>.svcard:first-child p{
    grid-column:2;grid-row:2;align-self:start;
    margin:.25rem 0 0;max-width:58ch;
  }
  .svgrid>.svcard:first-child .svcard__go{
    grid-column:3;grid-row:1/3;margin:0;white-space:nowrap;justify-self:end;
  }
  /* Le grand numéro se cale en haut à droite : dans une carte couchée, il
     tomberait derrière le lien « Voir la prestation ». On le sort. */
  .svgrid>.svcard:first-child .svcard__n{display:none}
}
/* Sous 761 px la grille passe à une colonne : la première carte redevient
   une carte comme les autres, et les règles ci-dessus ne s'appliquent plus. */
@media (max-width:760px){.svgrid{grid-template-columns:minmax(0,1fr)}}
.svcard{
  position:relative;display:grid;grid-template-rows:auto auto auto 1fr auto;
  padding:clamp(1.4rem,2.4vw,1.9rem);
  border:1px solid var(--border);border-radius:var(--r-lg);background:#fff;
  overflow:hidden;isolation:isolate;
  transition:border-color .3s var(--ease),transform .3s var(--ease-out),box-shadow .3s var(--ease);
}
/* Le voile bleu monte depuis le bas au survol : le même geste que les cartes
   de l'accueil, en plus sobre. */
.svcard::before{
  content:"";position:absolute;inset:0;z-index:-1;
  background:linear-gradient(180deg,transparent 40%,var(--blue-wash) 100%);
  opacity:0;transition:opacity .34s var(--ease);
}
/* La pile : deux feuilles derrière la carte, décalées vers le haut à
   droite — le sens des obliques du logo. Le contour de chaque feuille est
   tracé par une seconde ombre au même décalage, un pixel plus large. */
.svcard{
  --feuille:5px;
  box-shadow:
    calc(var(--feuille) * 1) calc(var(--feuille) * -1) 0 0 #fff,
    calc(var(--feuille) * 1) calc(var(--feuille) * -1) 0 1px var(--border),
    calc(var(--feuille) * 2) calc(var(--feuille) * -2) 0 0 #fff,
    calc(var(--feuille) * 2) calc(var(--feuille) * -2) 0 1px var(--border);
  transition:border-color .3s var(--ease),transform .34s var(--ease-out),
             box-shadow .34s var(--ease-out),--feuille .34s var(--ease-out);
}
.svcard:hover,
.svcard:focus-visible{
  --feuille:10px;
  border-color:rgba(1,74,209,.34);
  transform:translateY(-6px);
  box-shadow:
    10px -10px 0 0 #fff,
    10px -10px 0 1px rgba(1,74,209,.22),
    20px -20px 0 0 #fff,
    20px -20px 0 1px rgba(1,74,209,.14),
    0 26px 50px rgba(8,13,24,.14);
}
.svcard:hover::before{opacity:1}
/* La variable ne s'anime que là où @property est reconnu ; ailleurs, le
   passage d'une pile à l'autre reste net et lisible. */
@property --feuille{syntax:'<length>';inherits:false;initial-value:5px}

@media (prefers-reduced-motion:reduce){
  .svcard,.svcard:hover{transition:none;transform:none}
}
.svcard__n{
  position:absolute;top:clamp(1.1rem,2vw,1.5rem);right:clamp(1.2rem,2.2vw,1.7rem);
  font-family:var(--display);font-size:2.4rem;font-weight:700;line-height:1;
  color:var(--blue);opacity:.13;font-variant-numeric:tabular-nums;
  transition:opacity .34s var(--ease);
}
.svcard:hover .svcard__n{opacity:.28}
.svcard__i{
  width:42px;height:42px;border-radius:12px;display:grid;place-items:center;
  background:var(--blue-wash);color:var(--blue);margin-bottom:1rem;
  transition:background-color .3s var(--ease),color .3s var(--ease);
}
.svcard:hover .svcard__i{background:var(--blue);color:#fff}
.svcard__i svg{width:21px;height:21px}
.svcard b{
  display:block;font-family:var(--display);font-size:1.12rem;font-weight:600;
  color:var(--title);line-height:1.25;margin-bottom:.45rem;padding-right:2.4rem;
}
.svcard p{font-size:.92rem;color:var(--muted);line-height:1.6;margin-bottom:1.1rem}
.svcard__go{
  display:inline-flex;align-items:center;gap:.45rem;
  font-size:.88rem;font-weight:600;color:var(--blue);
}
.svcard__go svg{width:14px;height:14px;transition:transform .3s var(--ease)}
.svcard:hover .svcard__go svg{transform:translateX(5px)}

/* --------------------------------------------------------- RESPONSIVE --- */
@media (max-width:1080px){
  .svcx,.svflow{grid-template-columns:minmax(0,1fr)}
  .svflow__fig{position:static;max-width:520px;margin-inline:auto}
  .svflow__fig img{aspect-ratio:4/3}
  .geo{grid-template-columns:minmax(0,1fr)}
  .geo__go{justify-self:start}
}
@media (max-width:680px){
  .svmats{grid-template-columns:minmax(0,1fr)}
  .proof__fig img{aspect-ratio:4/3}
  .svstep{grid-template-columns:minmax(0,1fr);gap:.5rem}
  .svstep__n{opacity:1}
  .cmp{aspect-ratio:4/3}
}


/* ═══════════════════════ RYTHME ET SORTIE DES PAGES SERVICES ═══════════
   Même correction que sur l'accueil : à 144 px de marge, deux sections
   voisines créent 288 px de blanc mort. On resserre, et on ne paie la
   respiration qu'une fois aux jonctions de même fond.
   ---------------------------------------------------------------------- */
[data-page^="/services/"]{--section-y:clamp(3rem,4.6vw,4.75rem)}
[data-page^="/services/"] .section--alt+.section:not(.proof):not(.section--ink):not(.showsec){padding-top:clamp(2.6rem,4vw,3.9rem)}
/* La pente du bloc de preuve déborde sur le bloc suivant : sans la
   compensation, le sur-titre du déroulé se posait à −5 px de la diagonale.
   Même correction que sur l'accueil — voir « CE QUI VIENT APRÈS LA PENTE ».
   Cette règle-ci est plus spécifique, elle doit donc porter la valeur. */
[data-page^="/services/"] .proof+.section:not(.proof):not(.section--ink):not(.showsec){
  padding-top:calc(clamp(2.6rem,4vw,3.9rem) + clamp(2.2rem,4.4vw,3.9rem));
}

/* Le bloc de devis final ferme la page : il se colle à la section qui le
   précède, et il passe sur encre pour ne pas répéter le bandeau localité. */
.svcend{padding-block:0 clamp(3rem,5vw,5rem)}
.geo--ink{
  background:linear-gradient(150deg,#0D1836 0%,#0A1228 46%,#060B18 100%);
  border-color:rgba(255,255,255,.1);position:relative;overflow:hidden;isolation:isolate;
}
.geo--ink::before{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background-image:repeating-linear-gradient(117deg,rgba(140,180,255,.06) 0 1px,transparent 1px 26px);
}
/* La bande d'aplomb, en plus petit : la signature du logo jusque dans le
   dernier bloc de la page. */
.geo--ink::after{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:linear-gradient(180deg,#6FA0FF,var(--blue-e) 45%,var(--blue-d));
  /* Assez à droite pour ne croiser aucun bouton, quelle que soit la largeur
     du bloc : elle sort par le coin, elle ne traverse pas le contenu. */
  clip-path:polygon(94.2% 0,95.3% 0,106% 100%,104.9% 100%);
  filter:drop-shadow(0 0 18px rgba(77,139,255,.7));
}
.geo--ink h3{color:#fff}
.geo--ink p{color:#93A2BC}
@media (max-width:1080px){.geo--ink::after{clip-path:polygon(95% 0,96.4% 0,108% 100%,106.6% 100%)}}


/* Les séquences de chantier sont filmées à la verticale : le lecteur reprend
   ce format au lieu d'imposer le 16/9 de l'affiche de l'accueil. */
.clips .vplayer{aspect-ratio:3/4;clip-path:polygon(0 0,100% 0,100% 92%,88% 100%,0 100%)}
.clips .vplayer__play{width:clamp(62px,6vw,80px)}
.clips .vplayer__meta{left:1rem;bottom:1rem;font-size:.82rem}
.clips .vplayer__video{width:100%;height:100%;object-fit:cover}
@media (max-width:680px){.clips .vplayer{aspect-ratio:4/5}}
/* ══════════════════════════ PAGE ZONE D'INTERVENTION ════════════════════
   La carte prend ici la place principale — c'est le sujet de la page, pas un
   composant de rappel. Elle passe donc à gauche, en grand, et le répertoire
   des 108 communes défile à sa droite.
   ---------------------------------------------------------------------- */
.zone--large{grid-template-columns:minmax(0,1.02fr) minmax(0,.98fr)}
.zone--large .zone__fig{position:sticky;top:calc(var(--header-h) + 1.5rem)}
.zone--large .map{max-width:none}
.zone--large .zone__list{padding-top:.25rem}
@media (max-width:1080px){
  .zone--large{grid-template-columns:minmax(0,1fr)}
  .zone--large .zone__fig{position:static;order:-1;max-width:560px;margin-inline:auto}
}
/* L'atelier se distingue dans le nuage : c'est le point de départ de toutes
   les distances affichées. */
.zpill--hq{border-color:var(--blue);background:var(--blue);color:#fff;font-weight:600}
.zpill--hq b{color:rgba(255,255,255,.72)}
.zpill--hq:hover{background:var(--blue-d);border-color:var(--blue-d);color:#fff}
.zpill b{font-family:var(--display);font-size:.76rem;font-weight:600;color:var(--faint);margin-left:.3rem}
.zpill.is-on b,.zpill:hover b{color:var(--blue)}
.zpill--hq.is-on b,.zpill--hq:hover b{color:rgba(255,255,255,.8)}

/* Les six secteurs : un bloc éditorial par zone géographique. */
/* Six secteurs : trois et trois. */
.secteurs{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:clamp(1rem,1.8vw,1.5rem)}
@media (max-width:980px){.secteurs{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:620px){.secteurs{grid-template-columns:minmax(0,1fr)}}
.secteur{
  display:flex;flex-direction:column;
  padding:clamp(1.4rem,2.4vw,1.9rem);
  border:1px solid var(--border);border-radius:var(--r-lg);background:#fff;
  transition:border-color .28s var(--ease),transform .28s var(--ease-out),box-shadow .28s;
}
.secteur:hover{border-color:rgba(1,74,209,.3);transform:translateY(-4px);box-shadow:var(--sh-md)}
.secteur header{padding-bottom:.85rem;margin-bottom:.95rem;border-bottom:1px solid var(--border)}
.secteur b{
  display:block;font-family:var(--display);font-size:1.06rem;font-weight:600;
  color:var(--title);line-height:1.25;
}
.secteur header span{display:block;font-size:.79rem;color:var(--blue);margin-top:.3rem;font-weight:500}
.secteur p{font-size:.93rem;color:var(--muted);line-height:1.65}
.secteur__villes{
  margin-top:auto;padding-top:1rem;
  font-size:.83rem;color:var(--faint);font-style:normal;
}



/* Les liens glissés dans le corps d'une carte doivent se voir comme des
   liens : sans marque, personne ne clique. */
.sign p a,.secteur p a{
  color:var(--blue);font-weight:600;
  text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:2px;
  text-decoration-color:rgba(1,74,209,.34);transition:text-decoration-color .22s;
}
.sign p a:hover,.secteur p a:hover{text-decoration-color:var(--blue)}

/* ═══════════════════════ COMPOSANTS QUI N'AVAIENT PAS DE STYLE ══════════
   Relevés par tools/audit-classes.js. Une classe orpheline ne lève aucune
   erreur : l'élément s'affiche nu, avec le style par défaut du navigateur.
   C'est ce qui arrivait au mur de réalisations — dix-huit photos empilées
   pleine largeur, légendes en texte brut — et à `.sr-only`, dont le rôle est
   précisément de **ne pas** s'afficher.
   ======================================================================== */

/* --- Réservé aux lecteurs d'écran ---------------------------------------
   Sans cette règle, la légende du tableau des horaires de /contact/ était
   simplement affichée. C'est la seule classe du site dont l'absence de style
   produit l'exact contraire de son intention. */
.sr-only{
  position:absolute!important;width:1px;height:1px;
  padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0;
}

/* ═══════════════════════════════ LE MUR DE CHANTIERS ════════════════════
   Une grille dense de quatre colonnes. Chaque vue occupe une, deux ou quatre
   cases selon ce que la photo demande : un rampant vertical prend deux rangs,
   un panorama prend deux colonnes. `grid-auto-flow:dense` referme les trous
   laissés par le filtrage — sans lui, masquer une catégorie ouvrirait des
   brèches au milieu du mur.
   ---------------------------------------------------------------------- */
.gal{
  display:grid;
  grid-template-columns:repeat(4,minmax(0,1fr));
  grid-auto-rows:clamp(160px,14.6vw,224px);
  /* Les vues larges et hautes laissent des trous : en flux dense, les vues
     simples viennent les combler. Vaut aussi au filtrage, quand une partie
     du mur disparait. */
  grid-auto-flow:dense;
  grid-auto-flow:dense;
  gap:clamp(.6rem,1vw,.9rem);
}
.rea--big{grid-column:span 2;grid-row:span 2}
.rea--tall{grid-row:span 2}
.rea--wide{grid-column:span 2}

.rea{
  position:relative;overflow:hidden;isolation:isolate;
  border-radius:var(--r-md);background:var(--ink-2);
  transition:transform .45s var(--ease-out),box-shadow .45s var(--ease);
}
.rea img{
  width:100%;height:100%;object-fit:cover;display:block;
  transition:transform .9s var(--ease-out),filter .5s var(--ease);
}
.rea:hover{transform:translateY(-4px);box-shadow:var(--sh-xl);z-index:2}
.rea:hover img{transform:scale(1.06)}

/* Le voile ne s'assombrit qu'au survol : au repos, la photo prime, et seul
   le métier reste lisible en bas. C'est un mur de chantiers, pas un mur de
   texte. */
.rea__ov{
  position:absolute;inset:0;z-index:2;
  display:flex;flex-direction:column;justify-content:flex-end;
  padding:clamp(.85rem,1.4vw,1.15rem);
  background:linear-gradient(180deg,transparent 42%,rgba(8,13,24,.5) 72%,rgba(8,13,24,.88) 100%);
  transition:background .45s var(--ease);
}
.rea:hover .rea__ov{
  background:linear-gradient(180deg,rgba(8,13,24,.1) 0%,rgba(8,13,24,.58) 55%,rgba(8,13,24,.93) 100%);
}

.rea__city{
  align-self:flex-start;
  padding:.24rem .6rem;margin-bottom:auto;border-radius:999px;
  background:rgba(255,255,255,.14);backdrop-filter:blur(8px);
  border:1px solid rgba(255,255,255,.22);
  font-family:var(--display);font-size:.66rem;font-weight:600;
  letter-spacing:.1em;text-transform:uppercase;color:#fff;
}
.rea__t{
  font-family:var(--display);font-weight:600;color:#fff;line-height:1.22;
  font-size:clamp(.95rem,1.15vw,1.08rem);
  text-shadow:0 1px 12px rgba(8,13,24,.5);
}
/* Le détail technique n'apparaît qu'au survol : c'est la récompense de
   l'attention, pas une information imposée. */
.rea__m{
  font-size:.82rem;color:#C3CDDE;line-height:1.45;
  max-height:0;opacity:0;overflow:hidden;
  transition:max-height .45s var(--ease-out),opacity .35s var(--ease),margin-top .45s var(--ease-out);
}
.rea:hover .rea__m,.rea:focus-within .rea__m{max-height:5rem;opacity:1;margin-top:.4rem}

/* La grande vue porte le biseau du logo : une seule, sinon le motif devient
   une manie. */
.rea--big{clip-path:polygon(0 0,100% 0,100% 100%,7% 100%,0 92%)}

/* Le filtrage : les vues masquées disparaissent, les autres se replacent. */
.gal.is-filtering .rea{animation:pop .5s var(--ease-out) backwards}

@media (max-width:1080px){
  .gal{grid-template-columns:repeat(3,minmax(0,1fr));grid-auto-rows:clamp(150px,19vw,200px)}
}
/* ═══════════ LE MUR SUR TÉLÉPHONE — UNE PHOTO, PAS UN PARAGRAPHE ════════
   Signalé par le client le 15/09/2026 : « c'est un peu indigeste, il y a
   beaucoup de textes et de paragraphes ».

   Il avait raison, et c'est une décision antérieure qui l'avait causé : sur
   grand écran le détail technique n'apparaît qu'au survol, et comme le survol
   n'existe pas sur un écran tactile, on l'avait rendu PERMANENT ici. Trois
   lignes de texte par vignette, sur des vignettes de 132 px : le voile devait
   couvrir la photo pour que ça reste lisible, et on ne voyait plus le
   chantier. Un mur de chantiers devenu un mur de texte.

   La bonne réponse n'était pas d'afficher le détail à la place du survol,
   c'était de lui donner le geste équivalent : le TOUCHER. Il part donc dans
   la boîte à lumière — qui le lisait déjà, et qui montre la photo en grand
   par-dessus le marché. Le texte n'est pas perdu, il est au bon endroit.

   Reste à le faire savoir. Une loupe qui n'apparaît qu'au survol ne sert à
   rien sur un téléphone : elle devient permanente. Et une seule vignette
   porte le mot « Touchez pour agrandir » — l'écrire quarante-deux fois, ce
   serait remettre le texte qu'on vient d'enlever.
   ---------------------------------------------------------------------- */
@media (max-width:720px){
  /* Les rangées gagnent ce que le texte a rendu : la photo est le sujet. */
  .gal{grid-template-columns:repeat(2,minmax(0,1fr));grid-auto-rows:clamp(148px,34vw,200px)}
  .rea--big{grid-column:span 2;grid-row:span 2;clip-path:none}
  .rea--wide{grid-column:span 2;grid-row:span 1}

  .rea__m{display:none}

  /* Le voile peut redevenir discret : il n'a plus qu'un titre à porter. */
  .rea__ov{
    padding:.7rem .75rem;
    background:linear-gradient(180deg,transparent 44%,rgba(8,13,24,.5) 72%,rgba(8,13,24,.92) 100%);
  }
  .rea__t{
    font-size:.9rem;line-height:1.24;
    /* Deux lignes au maximum : un titre long ne doit pas reprendre la place
       qu'on vient de rendre à la photo. */
    display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
  }
  .rea__city{font-size:.6rem;padding:.2rem .5rem;letter-spacing:.1em}

  /* La loupe, en permanence.
     ⚠️ `.rea` en tête n'est pas décoratif : la règle qui masque la loupe au
     repos (`.rea__open svg{opacity:0}`) est déclarée PLUS BAS dans le fichier,
     à spécificité égale — elle l'emporterait donc. */
  .rea .rea__open{padding:.55rem;align-items:flex-start}
  .rea .rea__open svg{width:30px;height:30px;padding:6px;border-radius:10px;opacity:1;transform:none}

  /* L'invitation, une seule fois, sur la grande vue d'ouverture. */
  .gal>.rea:first-child .rea__open::before{
    content:"Touchez pour agrandir";
    align-self:flex-start;margin-right:.4rem;padding:.42rem .62rem;
    border-radius:999px;background:rgba(8,13,24,.62);
    -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);
    border:1px solid rgba(255,255,255,.22);
    font-family:var(--display);font-size:.68rem;font-weight:600;
    letter-spacing:.02em;color:#fff;white-space:nowrap;
  }
}
/* Sous 380 px, le mot et la loupe n'ont plus la largeur : la loupe suffit. */
@media (max-width:380px){
  .gal>.rea:first-child .rea__open::before{display:none}
}

/* ─── Quelques classes restées sans règle ─────────────────────────────── */
/* Les huit repères permanents de la carte : un point un peu plus marqué. */
.map .dot--key{fill:var(--blue);opacity:.9}
/* Le sur-titre de l'atelier, au-dessus de son nom. */
.map .hqsup{font-size:9.5px;letter-spacing:.16em}

/* ═══════════════════════ LE FLUX ÉDITORIAL ══════════════════════════════
   Le site n'avait aucune règle d'espacement entre les éléments d'un bloc de
   texte : chaque composant redéfinissait ses marges, et là où personne n'y
   avait pensé — les colonnes de texte des pages internes — les paragraphes
   se touchaient. Résultat : deux paragraphes lus comme un seul, et un titre
   collé à sa première ligne.

   Une seule règle de flux, posée sur les conteneurs éditoriaux, remplace
   toutes les marges au coup par coup. Le principe : c'est le conteneur qui
   décide de l'espacement, pas chaque élément.
   ======================================================================== */
.split__copy > * + *,
.svcx > div > * + *,
.faqsec__aside > * + *,
.legal > * + *{margin-top:clamp(.95rem,1.5vw,1.25rem)}

/* Un titre a besoin de plus d'air que deux paragraphes entre eux. Le cache
   typographique des titres porte une marge négative (-.07em) qui mange
   l'écart : on la compense ici, une fois pour tout le site. */
.ttl + *{margin-top:clamp(1.15rem,1.9vw,1.5rem)!important}
.eyebrow + .ttl{margin-top:.35rem}

/* Une liste à puces ou un bouton après du texte : une respiration de plus. */
.split__copy > .checks,
.split__copy > .btn{margin-top:clamp(1.5rem,2.4vw,2rem)}

/* Deux blocs de prose qui se suivent gardent leur propre rythme interne. */
.prose > * + *{margin-top:1.15rem}
.prose h3{margin-top:clamp(1.8rem,2.8vw,2.4rem)}
.prose h3:first-child{margin-top:0}

/* ══════════════════════ LES PENTES DE SECTION ═══════════════════════════
   Les sections se succédaient sur des lignes droites : un bandeau clair, un
   bandeau sombre, un bandeau clair. Correct, et parfaitement plat.

   Sur un site de couvreur, la transition évidente est une pente de toit. Les
   blocs sur encre — et eux seuls, sinon le motif devient une manie — entrent
   et sortent en biais. Toutes les pentes montent vers la droite, comme le
   bas du hero : c'est une seule ligne de toit qui traverse la page, pas une
   collection de biseaux décoratifs.

   Le rembourrage compense la hauteur de la pente, sans quoi le premier mot
   du bloc se retrouverait sous la coupe.
   ---------------------------------------------------------------------- */
.section--ink,
.showsec,
.proof{
  --p:clamp(2.2rem,4.4vw,3.9rem);
  clip-path:polygon(0 var(--p),100% 0,100% calc(100% - var(--p)),0 100%);
  /* La coupe est déjà du blanc : elle est comptée dans le rembourrage, pas
     ajoutée par-dessus. D'où le plafond — sinon un bloc encre s'ouvre sur
     190 px de vide quand ses voisins en ont 130. */
  --py:min(var(--section-y),clamp(3rem,4.6vw,4.5rem));
  /* La demi-pente ajoutée au rembourrage : sans elle, le sur-titre se pose
     à quelques pixels de la diagonale. */
  padding-block:calc(var(--py) + var(--p) * 1.5) calc(var(--py) + var(--p));
  /* Chevauchement d'une pente ENTIÈRE. Avec une demi-pente, la diagonale
     descendait plus bas que le bord du bloc précédent et laissait un coin
     de fond non peint — le triangle blanc visible en bas à gauche. */
  margin-block:calc(-1 * var(--p));
  position:relative;z-index:1;
}

/* ⚠️ CE QUI VIENT APRÈS LA PENTE — signalé le 15/09/2026 sur « 08 L'ADRESSE ».

   Un bloc à pente basse déborde sur son voisin d'une pente entière
   (`margin-block:-var(--p)`), pour qu'aucun coin de fond ne reste non peint.
   Ce recouvrement est volontaire. Ce qui ne l'était pas, c'est que le bloc
   SUIVANT garde son rembourrage normal : mesuré, son sur-titre arrivait à
   −2 px du bord bas du bloc précédent, c'est-à-dire posé SUR la diagonale.

   Le bloc à pente, lui, se protège déjà (`+ var(--p) * 1.5` en haut). Son
   voisin n'avait rien, parce que `--p` est déclaré SUR le bloc à pente : une
   variable personnalisée descend aux enfants, pas au frère suivant. Le
   `var(--p,0px)` écrit ailleurs pour ce même usage retombait donc toujours
   sur 0. D'où la valeur réécrite en clair ici.

   Trois jonctions concernées sur l'accueil — bandeau de chiffres → métiers,
   réalisations → zones, siège encre → adresse — et les pages services. */
.section--ink+.section,
.showsec+.section,
.proof+.section,
.proofband+.section{
  padding-top:calc(clamp(2.75rem,4.2vw,4.25rem) + clamp(2.2rem,4.4vw,3.9rem));
}

/* Le bandeau de chiffres suit le hero : il n'a pas de pente en haut, il
   prolonge celle du hero. */
.proofband{
  --p:clamp(2.2rem,4.4vw,3.9rem);
  clip-path:polygon(0 0,100% 0,100% calc(100% - var(--p)),0 100%);
  padding-bottom:calc(var(--p) + .5rem);
  margin-bottom:calc(-1 * var(--p));
  position:relative;z-index:1;
}

/* Le bloc de devis final ferme la page : une pente en entrée, rien en
   sortie — on ne coupe pas le pied de page en biais. */
.cta{
  --p:clamp(2.2rem,4.4vw,3.9rem);
  clip-path:polygon(0 var(--p),100% 0,100% 100%,0 100%);
  padding-top:calc(clamp(2.4rem,3.6vw,3.4rem) + var(--p));
  margin-top:calc(-1 * var(--p) / 2);
  position:relative;z-index:1;
}
/* Deux blocs sur encre à la suite ne doivent pas avoir de couture du tout :
   le second remonte sous la pente du premier et la remplit de sa propre encre.
   Sans ça, le triangle laissé par la coupe laisse passer le blanc de la page. */
.section--ink + .cta,
.proof + .cta,
.showsec + .cta{
  clip-path:none;z-index:0;
  margin-top:calc(-1 * var(--p));
  padding-top:calc(clamp(2.4rem,3.6vw,3.4rem) + var(--p));
}
/* Idem pour deux sections encre consécutives. */
.section--ink + .section--ink,
.proof + .section--ink{clip-path:polygon(0 0,100% 0,100% calc(100% - var(--p)),0 100%)}

/* Sur téléphone, une pente de 4 rem sur 375 px de large devient un angle
   très marqué : on la réduit de moitié. */
@media (max-width:680px){
  .section--ink,.showsec,.proof,.proofband,.cta{--p:1.5rem}
}

/* Les navigateurs qui ignorent clip-path retombent sur des blocs droits :
   c'est une dégradation propre, rien à prévoir de plus. */
@supports not (clip-path:polygon(0 0,100% 0)){
  .section--ink,.showsec,.proof,.proofband,.cta{margin-block:0;padding-block:var(--section-y)}
}

/* ══════════════════════════ MOTION — LES DÉTAILS ════════════════════════
   Trois retouches, aucune décoration. Chacune sert la lecture : elle donne
   au regard un ordre d'arrivée au lieu de tout poser d'un coup.
   ---------------------------------------------------------------------- */

/* --- 1. Les lignes de titre montent l'une après l'autre ------------------
   Les deux lignes d'un titre partaient ensemble : le cache typographique
   fonctionnait, mais l'effet ressemblait à un bloc qui glisse. Décalées de
   90 ms, elles se lisent dans l'ordre où on les lit. */
.js .ttl .ln:nth-child(2) i{transition-delay:.09s}
.js .ttl .ln:nth-child(3) i{transition-delay:.18s}

/* --- 2. Le filet du sur-titre se tire -----------------------------------
   Le trait qui suit « 01 NOS SAVOIR-FAIRE » apparaissait déjà tracé. Il se
   tire maintenant depuis le mot, en 0,5 s, une fois le bloc entré. */
.js .reveal .eyebrow::after,
.js .reveal.eyebrow::after{
  width:0;transition:width .55s .25s var(--ease-out);
}
.js .reveal.is-in .eyebrow::after,
.js .reveal.is-in.eyebrow::after{width:36px}

/* --- 3. Le numéro du sur-titre remonte ----------------------------------
   Il porte le rythme de la page : il arrive avant le texte, pas avec. */
.js .reveal .eyebrow::before{
  opacity:0;transform:translateY(.35em);
  transition:opacity .5s var(--ease-out),transform .5s var(--ease-out);
}
.js .reveal.is-in .eyebrow::before{opacity:.4;transform:none}

/* --- 4. Les cartes du mur de chantiers entrent en cascade ---------------
   Dix-huit vues qui apparaissent d'un bloc, c'est un rideau qui se lève.
   Décalées par colonne, elles se posent comme on les découvre. */
.js .gal .rea{transition-delay:calc(var(--i,0) * 45ms)}

@media (prefers-reduced-motion:reduce){
  .js .ttl .ln:nth-child(2) i,
  .js .ttl .ln:nth-child(3) i{transition-delay:0s}
  .js .reveal .eyebrow::after,
  .js .reveal.eyebrow::after{width:36px;transition:none}
  .js .reveal .eyebrow::before{opacity:.4;transform:none;transition:none}
  .js .gal .rea{transition-delay:0s}
}

/* La colonne de gauche de la FAQ est plus étroite qu'un en-tête de section :
   le titre y prenait trois lignes au lieu des deux prévues. Il descend d'un
   cran — c'est la seule colonne du site où le H2 n'a pas la place standard. */
.faqsec__aside .ttl{font-size:clamp(1.85rem,2.9vw,2.7rem)}

/* ─── Le bouton d'appel de l'en-tête, au survol ──────────────────────────
   Il se remplissait de bleu foncé : un carré plein qui apparaît sous le
   curseur, sans rapport avec le reste de l'en-tête. Au survol, c'est le halo
   qui s'intensifie et se resserre — le bouton reste le même objet, il signale
   simplement qu'il est vivant. */
.header__tel{
  --halo:rgba(1,74,209,.34);
  animation:none;
}
.header__tel::after{animation:halo-tel 3.2s ease-out infinite}
.header__tel:hover,
.header__tel:focus-visible{
  color:var(--urgent);
  border-color:rgba(240,118,30,.55);
  transform:translateY(-1px);
}
.header__tel:hover,
.header__tel:focus-visible{--halo:rgba(240,118,30,.5)}
.header__tel:hover::after{animation-duration:1.5s}
.header__tel:active{transform:translateY(0) scale(.96)}

@keyframes halo-tel{
  0%   {box-shadow:0 0 0 0 var(--halo)}
  70%  {box-shadow:0 0 0 13px transparent}
  100% {box-shadow:0 0 0 0 transparent}
}
@media (prefers-reduced-motion:reduce){
  .header__tel::after{animation:none;box-shadow:0 0 0 3px rgba(1,74,209,.14)}
}

/* Le défilé des communes a quitté le haut de page pour la section Zone
   d'intervention. Il y sert d'introduction à la carte : on lit les noms qui
   passent, puis on les retrouve situés. Sur fond clair, il change de registre
   — filet discret plutôt que bandeau sur encre. */
.marquee--zone{
  margin:0 0 clamp(1.8rem,3vw,2.6rem);
  border-block:1px solid var(--border);
  background:linear-gradient(90deg,var(--surface-alt),#fff 50%,var(--surface-alt));
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 12%,#000 88%,transparent);
          mask-image:linear-gradient(90deg,transparent,#000 12%,#000 88%,transparent);
}
.marquee--zone .marquee__i{color:var(--muted)}
.marquee--zone .marquee__i::before{background:var(--blue);opacity:.5}

/* ═══════════════════ LA CHRONOLOGIE DE L'ACCUEIL ════════════════════════
   Les cinq étapes étaient un numéro gris et deux lignes de texte, empilés.
   Elles deviennent des jalons reliés : un filet court derrière les numéros,
   chaque jalon s'allume à son tour, et un pictogramme annonce l'étape avant
   qu'on ait lu son titre.
   ---------------------------------------------------------------------- */
.steps{
  --jalon:44px;
  position:relative;list-style:none;
  display:grid;gap:0;margin-top:clamp(1.6rem,2.6vw,2.2rem);
}
/* Deux traits au même endroit : la voie, toujours visible, et l'avance,
   tirée par le défilement. ::before est la voie, ::after l'avance. */
.steps::before,
.steps::after{
  content:"";position:absolute;z-index:0;
  left:calc(var(--jalon) / 2 - 1px);width:2px;
  top:calc(var(--jalon) / 2);bottom:calc(var(--jalon) / 2);
}
.steps::before{background:var(--border)}
.steps::after{
  background:linear-gradient(180deg,var(--blue) 0%,var(--blue-l) 100%);
  box-shadow:0 0 14px rgba(1,74,209,.4);
  transform-origin:top;transform:scaleY(var(--avance,1));
  will-change:transform;
}
/* Sans JavaScript le trait est plein : la chronologie reste lisible. */
.js .steps::after{transform:scaleY(var(--avance,0))}
/* Sur fond encre la voie doit rester perceptible sans éclairer le bloc. */
.section--ink .steps::before{background:rgba(255,255,255,.14)}

.step{
  position:relative;z-index:1;
  display:grid;grid-template-columns:var(--jalon) minmax(0,1fr);
  gap:clamp(.9rem,1.6vw,1.3rem);
  padding-block:clamp(.85rem,1.4vw,1.15rem);
}
.step:first-child{padding-top:0}
.step:last-child{padding-bottom:0}

.step__n{
  display:grid;place-items:center;
  width:var(--jalon);height:var(--jalon);border-radius:13px;
  background:#fff;border:1.5px solid var(--border);
  font-family:var(--display);font-size:.92rem;font-weight:700;
  color:var(--blue);font-variant-numeric:tabular-nums;
  transition:background-color .45s var(--ease),border-color .45s var(--ease),
             color .45s var(--ease),box-shadow .45s var(--ease);
}
/* Le jalon s'allume à l'instant où le trait l'atteint — pas avant, pas
   selon un minuteur : c'est la lecture qui commande. */
.step.est-passe .step__n{
  background:var(--blue);border-color:var(--blue);color:#fff;
  box-shadow:0 6px 18px rgba(1,74,209,.28);
}
/* Sans JavaScript, tous les jalons sont allumés — l'état par défaut est
   l'état complet, jamais l'état vide. */
html:not(.js) .step__n{
  background:var(--blue);border-color:var(--blue);color:#fff;
}

.step__c{padding-top:.35rem}
.step h3{
  display:flex;align-items:center;gap:.55rem;
  font-family:var(--display);font-size:1.1rem;font-weight:600;
  color:var(--title);margin-bottom:.35rem;
}
.step h3 svg{width:17px;height:17px;color:var(--blue);flex:none}
.step p{font-size:.95rem;color:var(--muted);line-height:1.65;max-width:46ch}

@media (max-width:560px){
  .steps{--jalon:38px}
  .step h3{font-size:1.02rem}
}
/* Mouvement réduit : la chronologie est posée d'emblée, entièrement. */
@media (prefers-reduced-motion:reduce){
  .js .steps::after{transform:none}
  .js .step__n{transition:none}
}

/* ─── La carte isole la commune visée ────────────────────────────────────
   Cent points dont la moitié se touchent : mettre le bon en évidence ne
   suffit pas, il faut effacer les autres. Les traits, les pastilles et les
   étiquettes permanentes s'estompent ; seule la commune visée reste pleine. */
.map .town{transition:opacity .28s var(--ease)}
.map.is-focus .town{opacity:.16}
.map.is-focus .town.is-on{opacity:1}
.map.is-focus .ring,
.map.is-focus .hq,
.map.is-focus .pulse{opacity:.4;transition:opacity .28s var(--ease)}
.map.is-focus .rlabel,
.map.is-focus .hqlabel{opacity:.35;transition:opacity .28s var(--ease)}

/* Le cercle de couverture pesait trop dans la page : l'anneau extérieur
   s'affine et la carte perd de la largeur. */
.map .ring{stroke-width:1}
[data-page="/"] .zone__fig .map{max-width:540px}

/* Les deux actions qui ferment la section avis : lire, et publier. */
.avis-cta{
  display:flex;flex-wrap:wrap;align-items:center;justify-content:center;
  gap:.7rem;margin-top:clamp(2rem,3.2vw,2.75rem);
}
.avis-cta .btn--primary svg{width:15px;height:15px;color:#FFC93C}
.avis-cta__note{
  flex-basis:100%;text-align:center;margin-top:.85rem;
  font-size:.84rem;color:var(--faint);
}

/* ═════════════════ LE BLOC DE DEVIS FINAL — DYNAMIQUE ═══════════════════
   Trois gestes, tous liés à l'arrivée du bloc dans le cadre. Aucun n'est
   décoratif : chacun désigne l'action qu'on attend du visiteur.
   ---------------------------------------------------------------------- */

/* 1. Le titre se souligne d'un trait qui se tire de gauche à droite. */
.cta__in h2.ttl{position:relative;padding-bottom:.22em}
.cta__in h2.ttl::after{
  content:"";position:absolute;left:0;bottom:0;height:3px;width:0;
  border-radius:2px;
  background:linear-gradient(90deg,var(--blue-l),var(--blue) 60%,transparent);
  box-shadow:0 0 16px rgba(77,139,255,.55);
}
.js .cta__in h2.ttl::after{transition:width 1.1s .45s var(--ease-out)}
.js .cta__in h2.ttl.is-in::after,
.js .reveal.is-in .cta__in h2.ttl::after{width:min(100%,15ch)}
.no-js .cta__in h2.ttl::after{width:min(100%,15ch)}

/* Sur un appel à l'action centré, la boîte du titre fait toute la largeur
   du conteneur alors que le texte est centré dedans : un trait ancré à
   gauche commençait très loin du premier mot. Le titre se réduit donc à sa
   propre largeur, et le trait se centre dessous. */
.cta__in--solo h2.ttl{width:fit-content;margin-inline:auto}
.cta__in--solo h2.ttl::after{left:50%;transform:translateX(-50%)}
.js .cta__in--solo h2.ttl.is-in::after,
.js .reveal.is-in .cta__in--solo h2.ttl::after{width:min(100%,17ch)}
.no-js .cta__in--solo h2.ttl::after{width:min(100%,17ch)}

/* 2. Le numéro respire. Le halo tourne autour du chiffre, pas autour d'un
      bouton : c'est le numéro qu'on veut voir, pas son cadre. */
.cta__tel{position:relative;isolation:isolate}
.cta__tel::before{
  content:"";position:absolute;z-index:-1;
  inset:-.55rem -1.1rem;border-radius:999px;
  background:radial-gradient(60% 120% at 20% 50%,rgba(77,139,255,.28),transparent 70%);
  opacity:0;transform:scale(.92);
  transition:opacity .6s var(--ease),transform .6s var(--ease-out);
}
.js .reveal.is-in .cta__tel::before{opacity:1;transform:none}
.cta__tel svg{transition:transform .4s var(--ease)}
.cta__tel:hover svg{transform:rotate(-12deg) scale(1.08)}

/* 3. Les trois garanties s'allument l'une après l'autre, puce comprise. */
.cta__pts li{position:relative;transition:color .4s var(--ease)}
.js .cta__pts li{opacity:0;transform:translateX(-8px);
  transition:opacity .5s var(--ease-out),transform .5s var(--ease-out)}
.js .reveal.is-in .cta__pts li{opacity:1;transform:none}
.js .reveal.is-in .cta__pts li:nth-child(2){transition-delay:.1s}
.js .reveal.is-in .cta__pts li:nth-child(3){transition-delay:.2s}

@media (prefers-reduced-motion:reduce){
  .js .cta__in h2.ttl::after{width:min(100%,15ch);transition:none}
  .js .cta__tel::before{opacity:1;transform:none;transition:none}
  .js .cta__pts li{opacity:1;transform:none;transition:none}
}


/* Le comparateur et la fiche du chantier, côte à côte. Le comparateur tombe
   à ~740 px : sous la définition des deux photos, donc net. */
.proof__duo{
  display:grid;grid-template-columns:minmax(0,1.55fr) minmax(0,1fr);
  gap:clamp(1.6rem,3.2vw,3rem);align-items:stretch;
  margin-top:clamp(1.8rem,3vw,2.6rem);
}
.proof__specs--col{
  display:grid;grid-template-columns:minmax(0,1fr);gap:0;
  margin-top:0;padding-top:0;border-top:0;
  /* Les quatre lignes se répartissent sur la hauteur du comparateur : sans
     ça, la colonne s'arrête à mi-photo et ouvre un vide sous elle. */
  align-content:space-between;
}
.proof__specs--col>div{
  padding-block:clamp(.85rem,1.5vw,1.15rem);
  border-bottom:1px solid rgba(255,255,255,.13);
}
.proof__specs--col>div:first-child{padding-top:0}
.proof__specs--col>div:last-child{border-bottom:0}
@media (max-width:900px){
  .proof__duo{grid-template-columns:minmax(0,1fr);align-items:start}
  .proof__specs--col{align-content:start}
  .proof__specs--col{
    grid-template-columns:repeat(auto-fit,minmax(180px,1fr));
    gap:0 clamp(1.2rem,2.4vw,2.2rem);
  }
}


/* La chronologie, dans la colonne du déroulé : le texte n'a pas la largeur
   d'une pleine page, les paragraphes s'y ajustent. */
.svflow .steps{margin-top:0}
.svflow .step p{max-width:none}


/* ═══════════════════════════════ LE MUR : OUVRIR UNE VUE ════════════════
   Le bouton couvre toute la vignette — on clique la photo, pas une icône —
   et la loupe n'apparaît qu'au survol : au repos, rien ne doit se mettre
   entre le regard et le chantier.
   ---------------------------------------------------------------------- */
.rea__open{
  position:absolute;inset:0;z-index:3;
  display:flex;align-items:flex-start;justify-content:flex-end;
  padding:clamp(.7rem,1.2vw,.95rem);
  background:none;border:0;cursor:zoom-in;color:#fff;
}
.rea__open svg{
  width:34px;height:34px;padding:7px;border-radius:11px;
  background:rgba(8,13,24,.5);backdrop-filter:blur(10px);
  border:1px solid rgba(255,255,255,.22);
  opacity:0;transform:scale(.82) translateY(-4px);
  transition:opacity .3s var(--ease),transform .3s var(--ease-out);
}
.rea:hover .rea__open svg,
.rea__open:focus-visible svg{opacity:1;transform:none}
.rea__open:focus-visible{outline:2px solid var(--blue-l);outline-offset:-3px;border-radius:var(--r-md)}
/* La légende passe devant le bouton : elle reste lisible, il reste cliquable. */
.rea__ov{pointer-events:none}

/* Le filtre dit ce qu'il a gardé. */
.filters__n{
  margin-left:auto;align-self:center;
  font-size:.82rem;color:var(--muted);font-variant-numeric:tabular-nums;
}

/* ═════════════════════════ LES FILTRES SUR TÉLÉPHONE ════════════════════
   Cinq pastilles de largeurs très différentes — de « Zinguerie » à
   « Charpente & ossature » — dans 350 px. Deux essais avant celui-ci :

   1. Le retour à la ligne libre : deux, puis deux, puis une, avec un
      compteur orphelin au bout. Trois rangées inégales pour cinq boutons.
   2. Une bande qui défile : une seule ligne, mais la troisième pastille
      coupée par le bord droit. C'était voulu — c'est l'usage, pour dire
      qu'il y en a d'autres — et ça se lit quand même comme inachevé. Une
      commande à moitié visible n'est pas une invitation, c'est un doute.

   Ici, tout est visible d'un coup, sans geste à faire. « Tout voir » prend
   la première ligne à lui seul : c'est l'état par défaut, il vaut les quatre
   autres réunis. Les quatre métiers suivent en deux colonnes égales, le
   libellé calé à gauche et le compte à droite — les quatre chiffres
   s'alignent, et la grille se lit comme un tableau de bord plutôt que comme
   un tas de bulles. Rien ne dépasse, rien n'est coupé, rien ne défile.
   ---------------------------------------------------------------------- */
@media (max-width:680px){
  .filters{
    display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
    gap:.5rem;align-items:stretch;
  }
  /* L'état par défaut sur toute la largeur : il n'est pas un métier. */
  .filters .filter:first-child{grid-column:1/-1}
  .filter{
    justify-content:space-between;gap:.4rem;
    padding:.62rem .72rem;font-size:.79rem;line-height:1.25;text-align:left;
    /* « Charpente & ossature » ne tient pas sur une ligne dans 156 px à 360.
       Elle se replie donc plutôt que de pousser son compte hors du bouton —
       les cellules d'une même rangée s'étirent à la même hauteur, la grille
       reste droite. */
  }
  .filter b{flex:none;font-size:.68rem;padding:.1rem .36rem}
  /* Le bouton actif se soulevait au survol ; au doigt, ce déplacement n'a
     pas de déclencheur et casserait l'alignement de la grille. */
  .filter:hover{transform:none}
  /* Le compte des vues fait double emploi avec le chiffre porté par la
     pastille active, et la grille n'a pas de sixième case. Il reste lu par
     les lecteurs d'écran : c'est une zone `aria-live`, la masquer avec
     `display:none` la ferait taire. */
  .filters__n{
    position:absolute!important;width:1px;height:1px;
    padding:0;margin:-1px;overflow:hidden;
    clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0;
  }
}

/* ══════════════════════════════════ LA VISIONNEUSE ══════════════════════ */
html.lbx-ouverte{overflow:hidden}
.lbx{
  position:fixed;inset:0;z-index:120;
  display:grid;place-items:center;padding:clamp(1rem,4vw,3rem);
  opacity:0;transition:opacity .26s var(--ease);
  /* ── La colonne doit être bornée, sinon rien en dessous ne l'est ──────
     Sans cette ligne, la grille n'avait qu'une colonne implicite, donc
     dimensionnée sur son contenu. Or `.lbx__box` est en `width:max-content`
     et contient une légende : la colonne prenait la largeur du texte NON
     REPLIÉ. Sur un écran de 390 px, la boîte sortait à 716 px.

     Et le `max-width:min(1000px,100%)` de la boîte ne pouvait pas rattraper :
     son `100%` se résout contre cette même colonne, déjà débordée. Un
     pourcentage calculé sur un parent qui a grandi avec l'enfant ne
     contraint rien.

     `minmax(0,1fr)` fixe la colonne à la largeur utile de `.lbx`. À partir
     de là, le `100%` de la boîte, puis celui de l'image, ont un repère réel.
     Le défaut ne se voyait pas sur grand écran : la hauteur maximale de
     l'image suffisait à la maintenir sous la largeur disponible. */
  grid-template-columns:minmax(0,1fr);
}
.lbx.is-on{opacity:1}
.lbx__fond{
  position:absolute;inset:0;border:0;cursor:zoom-out;
  background:rgba(6,10,20,.88);backdrop-filter:blur(6px);
}
.lbx__box{
  position:relative;margin:0;width:max-content;
  max-width:min(1000px,100%);min-width:min(22rem,100%);
  transform:scale(.965) translateY(10px);
  transition:transform .32s var(--ease-out);
}
.lbx.is-on .lbx__box{transform:none}
.lbx__img{
  display:block;width:auto;max-width:100%;height:auto;
  max-height:calc(100dvh - 13rem);
  border-radius:var(--r-md);
  background:var(--ink-2);box-shadow:0 40px 90px rgba(0,0,0,.55);
}
.lbx__leg{
  display:grid;gap:.28rem;margin-top:1rem;padding-right:4.5rem;
  color:#C3CDDE;
}
.lbx__metier{
  justify-self:start;padding:.2rem .6rem;border-radius:999px;
  background:rgba(255,255,255,.12);border:1px solid rgba(255,255,255,.16);
  font-size:.7rem;letter-spacing:.08em;text-transform:uppercase;color:#E6ECF6;
}
.lbx__t{font-family:var(--display);font-size:clamp(1.05rem,1.6vw,1.3rem);color:#fff;font-weight:600}
.lbx__m{font-size:.88rem;line-height:1.5}
.lbx__x,.lbx__nav{
  position:absolute;display:grid;place-items:center;
  width:44px;height:44px;border-radius:13px;cursor:pointer;color:#fff;
  background:rgba(8,13,24,.62);border:1px solid rgba(255,255,255,.2);
  backdrop-filter:blur(10px);transition:background .2s,transform .2s var(--ease-out),border-color .2s;
}
.lbx__x svg,.lbx__nav svg{width:20px;height:20px}
.lbx__x:hover,.lbx__nav:hover{background:var(--blue);border-color:var(--blue);transform:scale(1.06)}
.lbx__x{top:.8rem;right:.8rem}
.lbx__nav{top:50%;margin-top:-22px}
.lbx__nav--prev{left:.8rem}
.lbx__nav--next{right:.8rem}
.lbx.is-seul .lbx__nav,.lbx.is-seul .lbx__rang{display:none}
.lbx__rang{
  position:absolute;right:0;bottom:0;
  font-size:.8rem;color:#8391AB;font-variant-numeric:tabular-nums;
}
@media (max-width:680px){
  .lbx__leg{padding-right:0}
  .lbx__rang{position:static;display:block;margin-top:.4rem}
  .lbx__nav{top:auto;bottom:-3.6rem;margin-top:0}
  .lbx__nav--prev{left:0}
  .lbx__nav--next{left:3.4rem;right:auto}
  .lbx__img{max-height:58vh}
}
@media (prefers-reduced-motion:reduce){
  .lbx,.lbx__box{transition:none}
  .lbx__box{transform:none}
}

/* Sur /contact/, le héros n'a pas de repères sous le chapô : la colonne de
   texte est courte, la coupe peut donc reculer et donner six points de plus
   à la photo de l'équipe. La colonne se resserre d'autant — une largeur
   fixe ne cohabite pas avec un bord oblique. */
[data-page="/contact/"] .phero{--cut-haut:50%;--cut-bas:44%}
[data-page="/contact/"] .phero__in{max-width:min(34rem,38%)}
[data-page="/contact/"] .phero__media img{object-position:52% 42%}
@media (max-width:1080px){
  /* La coupe de /contact/ rejoint celle des autres pages internes ; la
     borne de la colonne aussi. */
  [data-page="/contact/"] .phero{--cut-haut:66%;--cut-bas:60%}
  [data-page="/contact/"] .phero__in{max-width:min(34rem,54%)}
}
@media (max-width:720px){
  /* Et sous 901 px, la photo passe derrière le texte : la borne doit sauter
     ici comme partout ailleurs. Sans cette ligne, le sélecteur [data-page]
     l'emporte sur la règle générale et laisse le chapô sur 189 px. */
  [data-page="/contact/"] .phero__in{max-width:none}
}


/* ═══ LE LISERÉ BLEU DES CARTES ══════════════════════════════════════════
   Une arête de couleur en tête de carte : bleu franc sur le premier tiers,
   bleu pâli ensuite, puis rien — les trois obliques du logo, réduites à un
   trait. C'est posé en fond et non en pseudo-élément : plusieurs de ces
   cartes utilisent déjà ::before et ::after pour autre chose.

   Le fond blanc reste déclaré par chaque composant ; on n'ajoute ici que
   l'image de fond, donc l'ordre des règles suffit.
   ---------------------------------------------------------------------- */
.tile,
.svcard,
.secteur,
.nearc,
.work{
  background-image:linear-gradient(90deg,
    var(--blue) 0 32%,
    rgba(1,74,209,.28) 32% 58%,
    rgba(1,74,209,0) 58%);
  background-repeat:no-repeat;
  background-size:100% 3px;
  background-position:0 0;
  transition:transform .35s var(--ease),box-shadow .35s var(--ease),
             border-color .3s var(--ease),background-size .4s var(--ease-out);
}
/* Au survol le liseré s'épaissit d'un cheveu et le bord prend la couleur :
   la carte se désigne, elle ne change pas de nature. */
.tile:hover,
.work:hover{border-color:rgba(1,74,209,.34)}
.tile:hover,
.svcard:hover,
.secteur:hover,
.nearc:hover,
.work:hover{background-size:100% 4px}

/* Le liseré se tire de gauche à droite quand la carte arrive dans le champ.
   La transition porte sur background-size, déjà déclarée plus haut. */
.js .tile,
.js .svcard,
.js .secteur,
.js .nearc,
.js .work,
.js .implant{background-size:0 3px}
.js .tile.is-in,      .js .reveal.is-in .tile,
.js .svcard.is-in,    .js .reveal.is-in .svcard,
.js .secteur.is-in,   .js .reveal.is-in .secteur,
.js .nearc.is-in,     .js .reveal.is-in .nearc,
.js .work.is-in,      .js .reveal.is-in .work,
.js .implant.is-in,   .js .reveal.is-in .implant{background-size:100% 3px}
.js .implant{transition:background-size .75s .1s var(--ease-out)}
@media (prefers-reduced-motion:reduce){
  .js .tile,.js .svcard,.js .secteur,.js .nearc,.js .work,.js .implant{background-size:100% 3px}
}

/* Le dégradé de survol de .svcard est peint derrière le fond de la carte :
   il ne doit pas effacer le liseré, qui est ce même fond. */
.svcard::before{border-radius:inherit}


/* ═══════════ LES REPÈRES DE L'IMPLANTATION (/zones-intervention/) ═══════
   .zones n'avait qu'une exception responsive et aucune grille de base : le
   texte tombait en pleine largeur avec sa largeur de lecture, et laissait
   le reste vide. Deux colonnes, la seconde tenue par un panneau.
   ---------------------------------------------------------------------- */
.zones{
  display:grid;grid-template-columns:minmax(0,1.3fr) minmax(0,1fr);
  gap:clamp(1.8rem,4vw,3.6rem);align-items:start;
}

.implant{
  position:sticky;top:calc(var(--header-h,72px) + 1.4rem);
  border:1px solid var(--border);border-radius:var(--r-lg);background:#fff;
  padding:clamp(1.3rem,2.2vw,1.75rem);
  box-shadow:var(--sh-md);
  background-image:linear-gradient(90deg,
    var(--blue) 0 32%,rgba(1,74,209,.28) 32% 58%,rgba(1,74,209,0) 58%);
  background-repeat:no-repeat;background-size:100% 3px;background-position:0 0;
}
.implant__hd{display:flex;gap:.85rem;align-items:flex-start;padding-bottom:1.1rem}
.implant__hd svg{
  flex:none;width:38px;height:38px;padding:9px;border-radius:11px;
  background:var(--blue-wash);color:var(--blue);
}
.implant__hd b{display:block;font-family:var(--display);font-size:1.05rem;color:var(--title)}
.implant__hd span{display:block;font-size:.82rem;color:var(--muted);margin-top:.15rem}

/* Les trois anneaux de la carte, en chiffres : combien de communes chaque
   cercle ajoute. Calculé sur les coordonnées, pas estimé. */
.implant__rings{
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:0;
  list-style:none;margin:0;padding:1.1rem 0;
  border-block:1px solid var(--border);
}
.implant__rings li{position:relative;padding-inline:0 .6rem}
.implant__rings li+li{padding-left:.85rem}
.implant__rings li+li::before{
  content:"";position:absolute;left:0;top:.1rem;bottom:.1rem;width:1px;background:var(--border);
}
.implant__rings b{
  display:block;font-family:var(--display);font-size:clamp(1.1rem,1.5vw,1.3rem);
  line-height:1.05;color:var(--blue);
}
.implant__rings span{display:block;font-size:.76rem;color:var(--muted);margin-top:.25rem;line-height:1.3}

.implant__pts{list-style:none;margin:0;padding:1.05rem 0 0;display:grid;gap:0}
.implant__pts li{
  display:flex;align-items:baseline;justify-content:space-between;gap:1rem;
  padding-block:.52rem;font-size:.9rem;color:var(--text);
}
.implant__pts li+li{border-top:1px dashed var(--border)}
.implant__pts b{
  font-family:var(--display);font-weight:600;color:var(--title);
  font-variant-numeric:tabular-nums;white-space:nowrap;
}
.implant__note{margin-top:1rem;font-size:.76rem;line-height:1.5;color:var(--muted)}

@media (max-width:980px){
  .zones{grid-template-columns:minmax(0,1fr)}
  .implant{position:static}
}

/* Deux h1 qui doivent tenir sur deux lignes pleines, pas trois : leur
   seconde ligne est une expression qu'on ne coupe pas (un nom de
   département, une phrase courte). Réduction ciblée, page par page. */
@media (min-width:1081px){
  [data-page="/zones-intervention/"] .phero h1{font-size:clamp(2.3rem,4vw,3.55rem)}
  [data-page="/contact/"] .phero h1{font-size:clamp(2.3rem,4.2vw,3.7rem)}
}


/* ═════════════════ LES MÉTIERS, DANS LE HÉROS DE L'ACCUEIL ══════════════
   Quatre pastilles sobres entre le chapô et les boutons. Elles doivent se
   lire comme une précision du chapô, jamais concurrencer l'appel à
   l'action : pas de fond plein, pas de couleur vive, une simple arête.
   ---------------------------------------------------------------------- */
/* Les pastilles précisent le chapô ; l'appel à l'action est autre chose.
   Il lui faut sa propre respiration, sinon les deux rangs se lisent comme
   une seule barre de boutons. */
.hero__metiers + .hero__actions{margin-top:clamp(1.1rem,1.7vw,1.4rem)}
.hero__metiers{
  display:flex;flex-wrap:wrap;gap:.5rem;
  margin-top:clamp(1.1rem,1.8vw,1.45rem);
}
.hero__metiers a{
  display:inline-flex;align-items:center;gap:.4rem;
  padding:.42rem .82rem;border-radius:999px;
  border:1px solid rgba(255,255,255,.17);
  background:rgba(255,255,255,.045);
  font-size:.83rem;font-weight:500;color:#C7D2E4;
  transition:background-color .24s var(--ease),border-color .24s var(--ease),
             color .24s var(--ease),transform .24s var(--ease-out);
}
.hero__metiers a:hover,
.hero__metiers a:focus-visible{
  background:rgba(1,74,209,.28);border-color:rgba(120,166,255,.55);
  color:#fff;transform:translateY(-1px);
}
/* La cinquième mène au sommaire des neuf : elle se distingue par le bleu du
   texte, pas par un fond de plus. */
.hero__metiers-plus{color:var(--blue-e);border-color:rgba(77,139,255,.32)}
.hero__metiers-plus svg{width:14px;height:14px;transition:transform .24s var(--ease-out)}
.hero__metiers-plus:hover svg{transform:translateX(3px)}

@media (max-width:720px){
  .hero__metiers{gap:.42rem}
  .hero__metiers a{padding:.38rem .7rem;font-size:.79rem}
}


/* ══════════════════════════ LE VOCABULAIRE DU MÉTIER ════════════════════
   « Est-ce qu'on ne peut pas mettre ce texte davantage en valeur ? »

   Ce qui a de la valeur dans ces paragraphes, ce n'est pas leur mise en
   forme : c'est qu'ils emploient les mots du métier. Lattage, noue, solin,
   entrait, abergement. Un lecteur qui bute sur l'un d'eux décroche en
   silence — et c'est justement ce vocabulaire qui prouve qu'un couvreur a
   écrit la page.

   Le mot est donc souligné d'un pointillé et porte sa définition. Trois par
   page au maximum : au-delà, le paragraphe se couvre de pointillés et le
   procédé se voit plus que le texte.

   Sur écran tactile il n'y a pas de survol : le mot est focalisable, et la
   définition se déplie sous le paragraphe plutôt que de flotter au-dessus —
   une infobulle de 350 px n'a nulle part où aller sur 375 px de large.
   ---------------------------------------------------------------------- */
.terme{position:relative;display:inline}
.terme__m{
  color:var(--title);font-weight:500;
  border-bottom:1px dashed rgba(1,74,209,.55);border-radius:2px;
  cursor:help;
  transition:color .2s var(--ease),border-color .2s var(--ease),background-color .2s var(--ease);
}
.terme__m:hover,
.terme__m:focus-visible{color:var(--blue-d);border-bottom-color:var(--blue);background:var(--blue-wash)}
.terme__m:focus-visible{outline:2px solid var(--blue);outline-offset:2px}
/* Sur fond encre, le mot doit rester clair. */
.section--ink .terme__m{color:#fff;border-bottom-color:rgba(120,166,255,.6)}
.section--ink .terme__m:hover,
.section--ink .terme__m:focus-visible{color:#fff;background:rgba(1,74,209,.32);border-bottom-color:var(--blue-e)}

.terme__def{
  position:absolute;left:var(--decalage,0px);bottom:calc(100% + .75rem);z-index:40;
  width:max-content;max-width:min(22rem,calc(100vw - 3rem));
  padding:.75rem .9rem;border-radius:12px;
  background:var(--ink-2);color:#D5DEEC;border:1px solid rgba(255,255,255,.1);
  font-family:var(--body);font-size:.83rem;line-height:1.52;font-weight:400;font-style:normal;
  letter-spacing:0;text-transform:none;
  box-shadow:0 18px 44px rgba(8,13,24,.34);
  opacity:0;transform:translateY(5px);pointer-events:none;
  transition:opacity .22s var(--ease),transform .22s var(--ease-out);
}
.terme__def::after{
  content:"";position:absolute;top:100%;left:var(--pointe,1.5rem);
  border:6px solid transparent;border-top-color:var(--ink-2);
}
.terme:hover .terme__def,
.terme:focus-within .terme__def{opacity:1;transform:none}

@media (max-width:680px){
  .terme__def{
    position:static;display:none;max-width:none;width:auto;
    opacity:1;transform:none;box-shadow:none;
    margin-top:.6rem;
  }
  .terme:focus-within .terme__def{display:block}
  .terme__def::after{display:none}
}
@media (prefers-reduced-motion:reduce){
  .terme__def{transition:none;transform:none}
}


/* ═══════════ LE FORMULAIRE, DANS LA PAGE CONTACT FUSIONNÉE ══════════════
   Le formulaire venait d'un héros sur fond encre ; il vit désormais dans une
   section claire. La carte téléphone et la liste de réassurance qui
   l'accompagnent doivent donc changer de registre : blanc sur gris clair, et
   non blanc translucide sur encre.
   ---------------------------------------------------------------------- */
.dform__grid{
  display:grid;grid-template-columns:minmax(0,.9fr) minmax(0,1fr);
  gap:clamp(1.8rem,4vw,3.4rem);align-items:start;
  margin-top:clamp(1.6rem,2.8vw,2.4rem);
}
/* La colonne d'appui fait 250 px, le formulaire 600 : elle laisserait un
   vide de 350 px sous elle. Elle accompagne donc la saisie au lieu de
   défiler hors de l'écran — le numéro reste sous les yeux pendant qu'on
   remplit, ce qui est précisément le moment où l'on hésite à appeler. */
.dform__aside{position:sticky;top:calc(var(--header-h,72px) + 1.6rem)}
@media (max-width:900px){.dform__aside{position:static}}

.dform__aside .dhero__tel{
  margin-top:0;background:#fff;color:var(--title);
  border-color:var(--border);box-shadow:var(--sh-sm);
}
.dform__aside .dhero__tel:hover{
  background:#fff;border-color:rgba(1,74,209,.42);box-shadow:var(--sh-md);
}
.dform__aside .dhero__tel span{color:var(--muted)}
.dform__aside .dhero__points{margin-top:clamp(1.3rem,2.2vw,1.8rem);max-width:none}
.dform__aside .dhero__points li{color:var(--text)}
.dform__aside .dhero__points svg{color:var(--blue)}

@media (max-width:900px){
  .dform__grid{grid-template-columns:minmax(0,1fr)}
  /* Sur une colonne, le formulaire passe devant : c'est l'objet de la
     section, la réassurance vient l'appuyer ensuite. */
  .dform__aside{order:2}
}


/* ═══════════════════════ LA COUPE DE TOITURE (/sous-les-tuiles/) ════════
   Le dessin est produit par tools/build-coupe.js : huit solides en
   projection isométrique, inclinés de 15°, plus une colonne d'étiquettes
   restée horizontale et reliée par des traits de rappel.

   Deux mouvements, un seul pilote — la variable --eclate, de 0 à 1 :
     · chaque couche s'élève proportionnellement à son rang ;
     · le point d'accroche de son étiquette la suit (JavaScript redessine le
       trait de rappel, dont un seul bout bouge).

   Survoler une couche ou sa fiche isole cette couche et éteint les autres.
   ---------------------------------------------------------------------- */
.cpe{--eclate:0;margin-top:clamp(1.4rem,2.4vw,2rem)}
.cpe__scene{position:relative}
.cpe__svg{display:block;width:100%;height:auto;overflow:visible}
/* Vue recadrée sur l'empilement : les étiquettes sortent du cadre, ce sont
   les fiches qui prennent le relais — et les pastilles numérotées qui font
   le lien, numéro pour numéro. */
.cpe.is-etroite .cpe__nom,
.cpe.is-etroite .cpe__rol,
.cpe.is-etroite .cpe__fil,
.cpe.is-etroite .cpe__renvoi{display:none}

/* Le recentrage : l'empilement redescend de la moitié de ce que sa couche
   la plus haute monte. Sans lui, le toit fermé — celui qu'on voit en
   arrivant sur la section — se tasse dans le coin bas-gauche d'un cadre
   taillé pour le toit ouvert. */
.cpe__cadrage{transition:transform .12s linear}

/* Le renvoi vers les fiches, en pied de colonne : il dit à quoi servent les
   pastilles, et il occupe le bas de la colonne, qui resterait vide. */
.cpe__renvoi path{fill:none;stroke:var(--blue-e);stroke-width:2.4}
.cpe__renvoi text{fill:#7C8AA3;font-family:var(--body);font-size:12.5px}

/* --- Les solides ------------------------------------------------------ */
.cpe__couche{transition:opacity .32s var(--ease)}
.cpe__ecl{transition:transform .12s linear}
/* On tire la couche désignée hors de l'empilement : le geste de la main
   qui soulève une tuile pour regarder dessous. */
.cpe__tir{transition:transform .38s var(--ease-out)}
.cpe__couche.is-on .cpe__tir{transform:translate(22px,-11px)}

.cpe__f{stroke-linejoin:round}
/* Le dessus prend un filet clair, les tranches un filet sombre : c'est ce
   contraste, et lui seul, qui fait lire le volume sur fond encre. */
.cpe__f--dessus{stroke:rgba(255,255,255,.24);stroke-width:.9}
.cpe__f--sud{stroke:rgba(4,9,20,.34);stroke-width:.7}
.cpe__f--ouest{stroke:rgba(4,9,20,.42);stroke-width:.7}
.cpe__f--motif{stroke:none;pointer-events:none}
/* L'arête haute du fond : la ligne de lumière qui donne l'épaisseur.
   Sans elle, vingt-deux dalles plates posées les unes sur les autres. */
.cpe__arete{
  fill:none;stroke:rgba(255,255,255,.4);stroke-width:1.1;
  stroke-linecap:round;stroke-linejoin:round;pointer-events:none;
}
/* Le sol : une nappe de lumière et le contour du pan projeté. */
.cpe__ombre{fill:url(#cpe-sol);opacity:.9}
.cpe__trace{
  fill:none;stroke:rgba(120,166,255,.3);stroke-width:1.2;
  stroke-dasharray:6 9;pointer-events:none;
}
.cpe__pile{transform-box:view-box}
/* Le corps d'une fiche, à droite de son numéro : sans largeur minimale
   nulle, un mot long élargit la colonne de grille au lieu de se replier. */
.cpef__c{min-width:0}
.cpe__lbls{pointer-events:none}
.cpe__lbl{pointer-events:auto}

/* --- Les pastilles et les étiquettes ---------------------------------- */
/* Tant que le toit est fermé, les huit pastilles se superposent : elles
   n'apparaissent qu'à mesure qu'il s'ouvre. La valeur déborde de l'échelle,
   le navigateur la ramène dans [0,1] — l'apparition est donc plus franche
   que l'ouverture. */
.cpe__lbl{opacity:calc((var(--eclate,0) - .28) * 2.6);transition:opacity .3s var(--ease)}
.cpe__past{
  transform:translate(calc(var(--eclate,0) * var(--mx,0) * 1px),
                      calc(var(--eclate,0) * var(--my,0) * 1px));
  transition:transform .12s linear;
}
.cpe__fil{fill:none;stroke:rgba(255,255,255,.24);stroke-width:1}
.cpe__pt{fill:#0B1220;stroke:var(--blue-e);stroke-width:1.6;transition:fill .25s var(--ease)}
.cpe__num{
  fill:var(--blue-e);font-family:var(--display);font-size:12px;font-weight:700;
  text-anchor:middle;font-variant-numeric:tabular-nums;pointer-events:none;
  transition:fill .25s var(--ease);
}
.cpe__nom{
  fill:#fff;font-family:var(--display);font-size:18px;font-weight:600;
  letter-spacing:-.005em;
}
.cpe__rol{fill:#93A1B8;font-family:var(--body);font-size:12.5px}

/* L'isolement : une couche désignée, les autres en retrait. */
.cpe.is-cible .cpe__couche{opacity:.2}
.cpe.is-cible .cpe__couche.is-on{opacity:1}
.cpe.is-cible .cpe__lbl{opacity:calc((var(--eclate,0) - .28) * .5)}
.cpe.is-cible .cpe__lbl.is-on{opacity:calc((var(--eclate,0) - .28) * 2.6)}
.cpe .cpe__lbl.is-on .cpe__nom{fill:var(--blue-e)}
.cpe .cpe__lbl.is-on .cpe__fil{stroke:var(--blue-e)}
.cpe .cpe__lbl.is-on .cpe__pt{fill:var(--blue-e);stroke:#fff}
.cpe .cpe__lbl.is-on .cpe__num{fill:#fff}

/* Sur téléphone le dessin est réduit de moitié : les pastilles doivent
   grossir d'autant pour rester lisibles et cliquables. */
.cpe.is-etroite .cpe__pt{r:19;stroke-width:2.2}
.cpe.is-etroite .cpe__num{font-size:17px}

/* --- Les fiches, sous le dessin --------------------------------------- */
/* Deux colonnes, pas quatre : sur quatre, la mesure tombait à trente
   signes par ligne — un texte technique ne se lit pas en colonne de
   journal. */
.cpe__fiches{
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  gap:clamp(1rem,2vw,1.5rem);
  margin-top:clamp(2rem,3.4vw,3rem);
}
.cpef{
  position:relative;display:grid;grid-template-columns:auto minmax(0,1fr);
  gap:.9rem;align-items:start;
  padding:clamp(1rem,1.8vw,1.35rem);
  border:1px solid rgba(255,255,255,.12);border-radius:var(--r-md);
  background:rgba(255,255,255,.035);
  background-image:linear-gradient(90deg,
    var(--blue-e) 0 32%,rgba(77,139,255,.3) 32% 58%,rgba(77,139,255,0) 58%);
  background-repeat:no-repeat;background-size:100% 3px;background-position:0 0;
  transition:background-color .3s var(--ease),border-color .3s var(--ease),
             transform .3s var(--ease-out),background-size .5s var(--ease-out);
  cursor:default;
}
.js .cpef{background-size:0 3px}
.js .cpef.is-in,.js .reveal-seq.is-in .cpef{background-size:100% 3px}
.cpef:hover,.cpef:focus-within{
  background-color:rgba(1,74,209,.16);border-color:rgba(120,166,255,.42);
  transform:translateY(-3px);
}
.cpef__n{
  font-family:var(--display);font-size:.95rem;font-weight:700;
  color:var(--blue-e);font-variant-numeric:tabular-nums;
  padding-top:.16rem;
}
.cpef h3{font-family:var(--display);font-size:1.06rem;font-weight:600;color:#fff;margin-bottom:.3rem}
.cpef__role{font-size:.83rem;color:var(--blue-e);line-height:1.45;margin-bottom:.55rem}
.cpef p{font-size:.87rem;line-height:1.6;color:#AAB6CA}
.cpef__go{
  display:inline-flex;align-items:center;gap:.4rem;margin-top:.8rem;
  font-size:.8rem;font-weight:600;color:#fff;
  border-bottom:1px solid rgba(255,255,255,.22);padding-bottom:.12rem;
  transition:color .22s var(--ease),border-color .22s var(--ease);
}
.cpef__go svg{width:14px;height:14px;transition:transform .24s var(--ease-out)}
.cpef__go:hover{color:var(--blue-e);border-color:var(--blue-e)}
.cpef__go:hover svg{transform:translateX(3px)}

@media (max-width:820px){.cpe__fiches{grid-template-columns:minmax(0,1fr)}}
@media (max-width:700px){
  .cpe__fiches{grid-template-columns:minmax(0,1fr)}
  /* Le dessin va d'un bord à l'autre : le cadre étroit tient dans l'écran,
     et chaque pixel de large compte pour la lisibilité des pastilles. */
  .cpe__scene{margin-inline:calc(-1 * var(--gutter))}
}
@media (prefers-reduced-motion:reduce){
  .cpe{--eclate:1}
  .cpe__couche > g,.cpe__pt{transition:none}
}


/* ═══════════════ LES CARTES QUI S'EMPILENT (/zones-intervention/) ═══════
   Quatre types de bâti présentés en quatre cartes qui viennent se poser
   les unes sur les autres au défilement. Chacune se colle un cran plus bas
   que la précédente : on voit l'arête de celles du dessous, et la pile se
   lit comme un jeu de fiches.

   Aucun JavaScript : position:sticky et un décalage indexé sur --i
   suffisent. Le comportement dégrade proprement là où sticky n'existe pas —
   les cartes redeviennent une simple liste.
   ---------------------------------------------------------------------- */
.empil{
  display:grid;gap:clamp(1.1rem,2vw,1.6rem);
  margin-top:clamp(1.6rem,2.8vw,2.4rem);
}
.empil__c{
  position:sticky;
  /* Un élément de grille étiré ne peut pas coller : sa hauteur est imposée
     par la rangée. On le laisse à sa hauteur de contenu. */
  align-self:start;
  top:calc(var(--header-h,72px) + 1.4rem + var(--i,0) * 16px);
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,.82fr);
  align-items:stretch;
  background:#fff;border:1px solid var(--border);border-radius:var(--r-lg);
  overflow:hidden;box-shadow:var(--sh-lg);
  /* Le liseré de la marque, en tête de carte comme partout ailleurs. */
  background-image:linear-gradient(90deg,
    var(--blue) 0 32%,rgba(1,74,209,.28) 32% 58%,rgba(1,74,209,0) 58%);
  background-repeat:no-repeat;background-size:100% 3px;background-position:0 0;
}
.empil__t{padding:clamp(1.5rem,2.8vw,2.3rem);display:flex;flex-direction:column;gap:.85rem}
.empil__n{
  font-family:var(--display);font-size:.9rem;font-weight:700;
  color:var(--blue);letter-spacing:.08em;
}
.empil__t h3{
  font-family:var(--display);font-size:clamp(1.2rem,1.9vw,1.55rem);
  font-weight:600;color:var(--title);line-height:1.15;
}
.empil__t p{font-size:.93rem;line-height:1.68;color:var(--muted);margin:0}
.empil__t strong{color:var(--title);font-weight:600}
.empil__go{
  margin-top:auto;padding-top:.4rem;
  display:inline-flex;align-items:center;gap:.45rem;align-self:flex-start;
  font-size:.86rem;font-weight:600;color:var(--blue);
  border-bottom:1px solid rgba(1,74,209,.3);padding-bottom:.15rem;
  transition:color .22s var(--ease),border-color .22s var(--ease);
}
.empil__go svg{width:15px;height:15px;transition:transform .24s var(--ease-out)}
.empil__go:hover{color:var(--blue-d);border-color:var(--blue)}
.empil__go:hover svg{transform:translateX(4px)}

.empil__f{margin:0;position:relative;background:var(--surface-alt);min-height:100%}
.empil__f img{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block;
}
/* L'arête oblique de la marque, entre le texte et la photo. */
.empil__f::before{
  content:"";position:absolute;inset:0 auto 0 -1px;width:34px;z-index:2;
  background:#fff;
  clip-path:polygon(0 0,100% 0,0 100%);
}

@media (max-width:940px){
  /* En dessous de cette largeur la pile n'a plus de sens : deux cartes
     collées se recouvriraient entièrement. On revient à une suite. */
  .empil__c{position:static;grid-template-columns:minmax(0,1fr)}
  .empil__f{min-height:0;aspect-ratio:16/10;order:-1}
  .empil__f img{position:static;height:100%}
  .empil__f::before{display:none}
}
@media (prefers-reduced-motion:reduce){
  .empil__c{position:static}
}


/* ══════════════════════════════ LES PAGES VILLES ════════════════════════
   Trois composants seulement : la figure qui accompagne la prose, la
   variante inversée du bloc en deux colonnes, et la note sous les
   pastilles de communes. Tout le reste réutilise l'existant.
   ---------------------------------------------------------------------- */
.ville__fig{
  margin:0;position:sticky;top:calc(var(--header-h,72px) + 1.6rem);
  border-radius:var(--r-lg);overflow:hidden;box-shadow:var(--sh-lg);
  background:var(--surface-alt);
}
.ville__fig img{display:block;width:100%;height:auto}

/* Le bloc « un chantier ici » place la photo à gauche : deux blocs à deux
   colonnes qui se suivent dans le même sens se lisent comme un tableau. */
.split--inv{direction:rtl}
.split--inv > *{direction:ltr}

.ville__note{
  margin-top:clamp(1.4rem,2.4vw,2rem);
  padding-top:clamp(1.2rem,2vw,1.6rem);
  border-top:1px solid var(--border);
  font-size:.94rem;color:var(--muted);max-width:62ch;
}
.ville__note a{color:var(--blue);text-decoration:underline;text-underline-offset:3px}
.ville__note a:hover{color:var(--blue-d)}

/* La grille des trois cartes de métier : même composant que les
   « prestations voisines » des pages services, sur trois colonnes. */
.nearby{
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  gap:clamp(1rem,2vw,1.5rem);
  margin-top:clamp(1.6rem,2.8vw,2.4rem);
}
/* Trois cartes : trois colonnes ou une. */
@media (max-width:680px){.nearby{grid-template-columns:minmax(0,1fr)}}

/* La prose sur fond encre : le corps de texte reprend la couleur du bloc. */
.prose--light p{color:#AEBACE}
.prose--light strong{color:#fff}

@media (max-width:900px){
  .ville__fig{position:static}
  .split--inv{direction:ltr}
}

/* Le renvoi vers la page de la commune principale du secteur. */
.secteur__go{
  display:inline-flex;align-items:center;gap:.4rem;margin-top:auto;padding-top:.9rem;
  font-size:.85rem;font-weight:600;color:var(--blue);
}
.secteur__go svg{width:15px;height:15px;transition:transform .24s var(--ease-out)}
.secteur:hover .secteur__go svg{transform:translateX(4px)}

/* Les paliers des grilles à quatre cartes, groupés : trois colonnes leur
   feraient 3 + 1. */
@media (max-width:1080px){
  .proof__specs{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media (max-width:960px){
  .reassure{grid-template-columns:repeat(2,minmax(0,1fr))}
  .reassure__i:nth-child(2n){border-right:0}
  .reassure__i:nth-child(-n+2){border-bottom:1px solid var(--border)}
}
@media (max-width:520px){
  .proof__specs{grid-template-columns:minmax(0,1fr)}
}


/* ═════════ /sous-les-tuiles/ — LE TEXTE ACCOMPAGNÉ D'UNE PHOTO ══════════
   Deux sections de la page étaient des colonnes de texte bornées à leur
   largeur de lecture dans un conteneur de 1 200 px : le reste était du
   vide. Elles passent en deux colonnes, avec une photo qui montre ce dont
   le texte parle.
   ---------------------------------------------------------------------- */
.coupe__duo{
  display:grid;grid-template-columns:minmax(0,1.15fr) minmax(0,1fr);
  gap:clamp(1.8rem,4vw,3.4rem);align-items:start;
  margin-top:clamp(1.6rem,2.8vw,2.4rem);
}
/* La chronologie garde la lecture à gauche : la photo passe donc à droite
   dans l'ordre du document, et à gauche à l'écran. */
.coupe__duo--inv{grid-template-columns:minmax(0,1fr) minmax(0,1.25fr)}

.coupe__fig{
  margin:0;border-radius:var(--r-lg);overflow:hidden;
  box-shadow:var(--sh-lg);background:var(--surface-alt);
  background-image:linear-gradient(90deg,
    var(--blue) 0 32%,rgba(1,74,209,.28) 32% 58%,rgba(1,74,209,0) 58%);
  background-repeat:no-repeat;background-size:100% 3px;background-position:0 0;
}
.coupe__fig img{display:block;width:100%;height:auto}
.coupe__fig figcaption{
  padding:.85rem 1.1rem 1rem;font-size:.84rem;line-height:1.5;
  color:var(--muted);background:#fff;
}
/* Sur fond encre, la légende suit le bloc. */
.section--ink .coupe__fig figcaption{background:var(--ink-2);color:#94A2BA}
.coupe__fig--collante{position:sticky;top:calc(var(--header-h,72px) + 1.6rem)}

.coupe__duo .prose{max-width:none}
.coupe__duo .steps{margin-top:0}
/* Dans une composition à deux colonnes, la colonne de texte fait près de
   sept cents pixels : une mesure de 46 signes y laisse deux cents pixels
   de vide à droite de chaque étape. */
.coupe__duo .step p{max-width:56ch}

@media (max-width:900px){
  .coupe__duo,.coupe__duo--inv{grid-template-columns:minmax(0,1fr)}
  .coupe__fig--collante{position:static}
  /* Sur une colonne, la photo passe devant le texte : trois paragraphes
     d'emblée, sans respiration, se lisent mal sur un téléphone. */
  .coupe__duo .coupe__fig{order:-1}
  .coupe__fig img{max-height:52vh;object-fit:cover}
}


/* ═══════════════════════════════════════════════════ ASSISTANT TOITURE ═══
   Le panneau qui traduit un symptôme en métier. Sobre : il ne doit pas
   entrer en concurrence avec le bouton d'appel, qui reste la conversion
   principale du site. D'où l'encre pour le lanceur, l'orange réservé au
   téléphone, et le bleu pour tout ce qui mène au devis.
   ====================================================================== */
.asst{
  position:fixed;right:clamp(1rem,2.4vw,1.9rem);bottom:clamp(1rem,2.4vw,1.9rem);
  z-index:110;display:flex;flex-direction:column-reverse;align-items:flex-end;
  gap:.8rem;
  /* Le conteneur couvre en permanence le coin de la page : il ne doit
     intercepter aucun clic là où il est vide. */
  pointer-events:none;
}
.asst>*{pointer-events:auto}

/* Le menu mobile et la visionneuse prennent tout l'écran : rien ne doit
   flotter par-dessus. Le sélecteur d'adjacence marche parce que .mnav et
   .asst sont deux enfants du corps, dans cet ordre. */
.mnav.is-open ~ .asst,html.lbx-ouverte .asst{display:none}
/* Sur la page contact, le visiteur est arrivé où le diagnostic voulait
   l'emmener : le lanceur n'aurait plus qu'à recouvrir le formulaire. */
main[data-page="/contact/"] ~ .asst{display:none}

/* ---------------------------------------------------------- Le lanceur -- */
.asst__ouvre{
  display:inline-flex;align-items:center;gap:.62rem;
  padding:.52rem 1.05rem .52rem .52rem;border-radius:var(--r-pill);
  background:var(--ink);color:#fff;border:1px solid rgba(255,255,255,.11);
  box-shadow:0 16px 40px rgba(8,13,24,.3),0 3px 10px rgba(8,13,24,.18);
  transition:transform .22s var(--ease-out),box-shadow .22s var(--ease);
}
.asst__ouvre:hover{transform:translateY(-2px);box-shadow:0 22px 52px rgba(8,13,24,.36)}
.asst__ouvre:focus-visible{outline:3px solid var(--blue-e);outline-offset:3px}
.asst__ouvre-i{
  display:grid;place-items:center;width:36px;height:36px;flex:none;
  border-radius:50%;color:#fff;
  background:linear-gradient(145deg,var(--blue-l) 0%,var(--blue-d) 100%);
}
.asst__ouvre-i svg{width:20px;height:20px}
.asst__ouvre-t{
  display:grid;gap:.05rem;text-align:left;font-family:var(--display);
  line-height:1.12;letter-spacing:.012em;
}
.asst__ouvre-t b{font-size:1.06rem;font-weight:700}
.asst__ouvre-t span{
  font-family:var(--body);font-size:.72rem;font-weight:500;
  letter-spacing:0;color:#9DB0CC;
}
/* Entrée retardée : le lanceur ne dispute pas l'attention au héros. En
   « backwards » et non « forwards » — l'état final est l'état naturel, donc
   rien ne dépend de la bonne exécution de l'animation. */
@keyframes asstEntre{from{opacity:0;transform:translateY(16px) scale(.94)}}
.js .asst__ouvre{animation:asstEntre .55s var(--ease-out) 1.5s backwards}

/* ---------------------------------------------------------- Le panneau -- */
.asst__panneau{
  display:flex;flex-direction:column;overflow:hidden;
  width:min(27.5rem,calc(100vw - 2rem));
  max-height:min(41rem,calc(100vh - 7.5rem));
  background:var(--surface);border:1px solid var(--border);
  border-radius:var(--r-md);box-shadow:var(--sh-xl);
}
@keyframes asstPan{from{opacity:0;transform:translateY(12px) scale(.985)}}
.asst__panneau{animation:asstPan .28s var(--ease-out)}

.asst__tete{
  display:flex;align-items:center;gap:.55rem;flex:none;
  padding:.8rem .8rem .8rem 1.05rem;background:var(--ink);color:#fff;
}
.asst__ident{display:grid;gap:.1rem;min-width:0;flex:1}
.asst__ident b{
  font-family:var(--display);font-size:1.08rem;font-weight:700;
  letter-spacing:.012em;line-height:1.15;
}
.asst__etat{
  display:flex;align-items:center;gap:.42rem;
  font-size:.765rem;line-height:1.3;color:#9DB0CC;
}
.asst__etat::before{
  content:"";width:7px;height:7px;flex:none;border-radius:50%;
  background:var(--faint);
}
.asst__etat.est-ouvert{color:#8FE3BC}
.asst__etat.est-ouvert::before{background:#3ED08C;box-shadow:0 0 0 3px rgba(62,208,140,.2)}
.asst__retour,.asst__ferme{
  display:grid;place-items:center;width:32px;height:32px;flex:none;
  border-radius:var(--r-xs);color:#C2D0E4;
  transition:background .18s var(--ease),color .18s var(--ease);
}
.asst__retour:hover,.asst__ferme:hover{background:rgba(255,255,255,.11);color:#fff}
.asst__retour:focus-visible,.asst__ferme:focus-visible{outline:2px solid var(--blue-e);outline-offset:1px}
.asst__retour svg,.asst__ferme svg{width:18px;height:18px}

.asst__corps{
  flex:1;min-height:0;overflow-y:auto;overscroll-behavior:contain;
  padding:1.05rem 1.05rem 1.3rem;
}
.asst__corps:focus{outline:none}
.asst__attente{padding:2.4rem 0;text-align:center;font-size:.88rem;color:var(--muted)}

.asst__pied{flex:none;padding:.55rem .7rem;border-top:1px solid var(--border);background:var(--surface-alt)}
.asst__tel{
  display:flex;align-items:center;gap:.7rem;padding:.5rem .6rem;
  border-radius:var(--r-xs);transition:background .18s var(--ease);
}
.asst__tel:hover{background:rgba(1,74,209,.07)}
.asst__tel:focus-visible{outline:2px solid var(--blue);outline-offset:1px}
.asst__tel>svg{width:19px;height:19px;flex:none;color:var(--urgent)}
.asst__tel>span{display:grid;gap:.02rem;min-width:0}
.asst__tel b{
  font-family:var(--display);font-size:1.12rem;font-weight:700;
  letter-spacing:.015em;line-height:1.15;color:var(--title);
}
.asst__tel>span>span{font-size:.745rem;line-height:1.3;color:var(--muted)}

/* ------------------------------------------------------- Les contenus --- */
.asst__intro{margin-bottom:.9rem;font-size:.885rem;line-height:1.55;color:var(--muted)}
.asst__q{
  margin-bottom:.55rem;font-family:var(--display);font-size:1.34rem;
  font-weight:700;line-height:1.18;letter-spacing:.005em;color:var(--title);
}
.asst__aide{
  margin-bottom:.9rem;padding-left:.72rem;border-left:2px solid var(--border);
  font-size:.815rem;line-height:1.52;color:var(--muted);
}
/* Le fil des réponses déjà données : le visiteur voit ce qu'il a dit, et
   c'est aussi ce qui partira dans le formulaire. */
.asst__fil{display:flex;flex-wrap:wrap;gap:.28rem;margin-bottom:.85rem}
.asst__fil span{
  padding:.2rem .55rem;border-radius:var(--r-pill);
  background:var(--surface-alt);border:1px solid var(--border);
  font-size:.715rem;line-height:1.4;color:var(--muted);
}

.asst__portes{display:grid;gap:.5rem}
.asst__porte{
  display:grid;grid-template-columns:38px 1fr;gap:.06rem .78rem;
  align-items:center;padding:.78rem .9rem;text-align:left;
  border:1px solid var(--border);border-radius:var(--r-sm);background:var(--surface);
  transition:border-color .18s var(--ease),box-shadow .18s var(--ease),transform .18s var(--ease);
}
.asst__porte:hover{border-color:var(--blue);box-shadow:var(--sh-sm);transform:translateY(-1px)}
.asst__porte:focus-visible{outline:2px solid var(--blue);outline-offset:2px}
.asst__porte-i{
  grid-row:span 2;display:grid;place-items:center;width:38px;height:38px;
  border-radius:11px;background:var(--blue-wash);color:var(--blue);
}
.asst__porte-i svg{width:20px;height:20px}
.asst__porte-t{
  font-family:var(--display);font-size:1.04rem;font-weight:700;
  line-height:1.2;letter-spacing:.008em;color:var(--title);
}
.asst__porte-d{font-size:.785rem;line-height:1.35;color:var(--muted)}

.asst__choix{display:grid;gap:.42rem}
.asst__ch{
  display:grid;gap:.12rem;padding:.7rem .88rem;text-align:left;
  border:1px solid var(--border);border-radius:var(--r-sm);background:var(--surface);
  transition:border-color .18s var(--ease),background .18s var(--ease);
}
.asst__ch:hover{border-color:var(--blue);background:var(--blue-wash)}
.asst__ch:focus-visible{outline:2px solid var(--blue);outline-offset:2px}
.asst__ch b{font-size:.935rem;font-weight:600;line-height:1.32;color:var(--title)}
.asst__ch span{font-size:.775rem;line-height:1.35;color:var(--muted)}

/* ------------------------------------------------------ La conclusion --- */
/* Plus spécifique que .asst__fin p, sinon la règle des paragraphes
   l'emporte et le titre sort à la taille du corps de texte. */
.asst__fin .asst__fin-t{
  margin-bottom:.6rem;font-family:var(--display);font-size:1.45rem;
  font-weight:700;line-height:1.16;letter-spacing:.005em;color:var(--title);
}
.asst__fin p{margin-bottom:.68rem;font-size:.895rem;line-height:1.62;color:var(--text)}
.asst__fin--urgent .asst__fin-t{color:var(--urgent-d)}
.asst__fin .asst__note{
  margin:.15rem 0 .7rem;padding:.7rem .85rem;border-radius:var(--r-xs);
  background:#FFF6ED;border:1px solid #F6DCC2;
  font-size:.835rem;line-height:1.5;color:#8A4A12;
}
/* La réserve : ces pistes orientent, elles ne diagnostiquent pas. Elle est
   sur toutes les conclusions — c'est ce qui empêche l'outil de sonner faux. */
.asst__fin .asst__reserve{
  margin:.2rem 0 0;padding-top:.68rem;border-top:1px solid var(--border);
  font-size:.775rem;line-height:1.52;color:var(--muted);
}
.asst__actions{display:grid;gap:.45rem;margin-top:.95rem}
.asst__cta{
  display:flex;align-items:center;justify-content:center;gap:.5rem;
  padding:.75rem 1rem;border-radius:var(--r-xs);color:#fff;
  font-family:var(--display);font-size:1rem;font-weight:700;letter-spacing:.015em;
  transition:background .18s var(--ease),transform .18s var(--ease);
}
.asst__cta svg{width:18px;height:18px;flex:none}
.asst__cta:hover{transform:translateY(-1px)}
.asst__cta:focus-visible{outline:3px solid var(--blue-e);outline-offset:2px}
.asst__cta--tel{background:var(--urgent);box-shadow:0 10px 24px rgba(240,118,30,.26)}
.asst__cta--tel:hover{background:var(--urgent-d)}
.asst__cta--devis{background:var(--blue);box-shadow:0 10px 24px rgba(1,74,209,.22)}
.asst__cta--devis:hover{background:var(--blue-d)}
.asst__lien{
  display:inline-flex;align-items:center;gap:.4rem;padding:.35rem 0;
  font-size:.855rem;font-weight:600;color:var(--blue);
}
.asst__lien svg{width:15px;height:15px;transition:transform .2s var(--ease)}
.asst__lien:hover svg{transform:translateX(3px)}

/* ------------------------------------------------------- La recherche --- */
.asst__rech{position:relative;margin-bottom:.85rem}
.asst__rech>svg{
  position:absolute;left:.82rem;top:50%;transform:translateY(-50%);
  width:17px;height:17px;color:var(--faint);pointer-events:none;
}
.asst__champ{
  width:100%;padding:.72rem .9rem .72rem 2.45rem;font-size:.92rem;
  border:1px solid var(--border);border-radius:var(--r-sm);
  background:var(--surface-alt);
  transition:border-color .18s var(--ease),background .18s var(--ease);
}
.asst__champ:focus{
  outline:none;border-color:var(--blue);background:var(--surface);
  box-shadow:0 0 0 3px rgba(1,74,209,.12);
}
.asst__res{display:grid;gap:.38rem}
.asst__r{
  display:grid;gap:.18rem;padding:.62rem .8rem;text-align:left;
  border:1px solid var(--border);border-radius:var(--r-xs);background:var(--surface);
  transition:border-color .18s var(--ease),background .18s var(--ease);
}
.asst__r:hover{border-color:var(--blue);background:var(--blue-wash)}
.asst__r:focus-visible{outline:2px solid var(--blue);outline-offset:2px}
.asst__r b{font-size:.875rem;font-weight:600;line-height:1.35;color:var(--title)}
.asst__r>span{
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  overflow:hidden;font-size:.775rem;line-height:1.42;color:var(--muted);
}
.asst__r em{font-style:normal;font-size:.7rem;font-weight:600;color:var(--blue)}
.asst__vide{
  padding:1.4rem .4rem;text-align:center;font-size:.855rem;
  line-height:1.55;color:var(--muted);
}
.asst__sugg{display:flex;flex-wrap:wrap;gap:.32rem;margin-top:.2rem}
.asst__sugg button{
  padding:.34rem .7rem;border-radius:var(--r-pill);
  border:1px solid var(--border);background:var(--surface-alt);
  font-size:.775rem;font-weight:500;color:var(--text);
  transition:border-color .18s var(--ease),color .18s var(--ease);
}
.asst__sugg button:hover{border-color:var(--blue);color:var(--blue)}

/* -------------------------------------------------- Le lecteur de devis - */
.asst__liste{display:grid;gap:.28rem;margin:0 0 .9rem;padding:0;list-style:none}
.asst__poste{margin:0}
.asst__poste label{
  display:grid;grid-template-columns:auto 1fr;gap:.06rem .68rem;
  align-items:start;padding:.58rem .72rem;cursor:pointer;
  border:1px solid var(--border);border-radius:var(--r-xs);
  transition:border-color .18s var(--ease),background .18s var(--ease);
}
.asst__poste label:hover{border-color:var(--blue-l)}
.asst__poste input{
  grid-row:span 2;width:18px;height:18px;margin:.14rem 0 0;
  accent-color:var(--blue);cursor:pointer;
}
.asst__poste b{font-size:.875rem;font-weight:600;line-height:1.32;color:var(--title)}
.asst__poste span{font-size:.755rem;line-height:1.35;color:var(--muted)}
.asst__poste.est-coche label{border-color:var(--blue);background:var(--blue-wash)}
.asst__sous{
  margin:1.05rem 0 .5rem;font-family:var(--display);font-size:1.02rem;
  font-weight:700;letter-spacing:.012em;color:var(--title);
}
.asst__verdict{margin-bottom:.9rem;padding:.9rem 1rem;border-radius:var(--r-sm)}
.asst__verdict b{
  display:block;margin-bottom:.22rem;font-family:var(--display);
  font-size:1.16rem;font-weight:700;letter-spacing:.008em;line-height:1.18;
}
.asst__verdict p{font-size:.85rem;line-height:1.55}
.asst__verdict--ok{background:#EAF7F0;border:1px solid #BCE2CF;color:#0B6B43}
.asst__verdict--manque{background:#FFF6ED;border:1px solid #F6DCC2;color:#8A4A12}
.asst__manque{margin-bottom:.85rem;padding-left:.8rem;border-left:2px solid var(--urgent)}
.asst__manque b{display:block;margin-bottom:.2rem;font-size:.895rem;color:var(--title)}
.asst__manque p{font-size:.835rem;line-height:1.55;color:var(--text)}
.asst__champs{display:grid;grid-template-columns:1fr 1fr;gap:.55rem;margin-bottom:.75rem}
.asst__num label{
  display:block;margin-bottom:.24rem;font-size:.755rem;
  font-weight:600;color:var(--muted);
}
.asst__num input{
  width:100%;padding:.6rem .7rem;font-size:.95rem;
  border:1px solid var(--border);border-radius:var(--r-xs);background:var(--surface);
}
.asst__num input:focus{
  outline:none;border-color:var(--blue);box-shadow:0 0 0 3px rgba(1,74,209,.12);
}
.asst__seg{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:.32rem;margin-bottom:.9rem}
.asst__seg button{
  padding:.52rem .35rem;border:1px solid var(--border);border-radius:var(--r-xs);
  background:var(--surface);font-size:.795rem;font-weight:600;
  line-height:1.25;color:var(--text);
  transition:border-color .18s var(--ease),background .18s var(--ease),color .18s var(--ease);
}
.asst__seg button:hover{border-color:var(--blue)}
.asst__seg button.est-on{border-color:var(--blue);background:var(--blue);color:#fff}
.asst__seg small{display:block;font-size:.685rem;font-weight:400;opacity:.78}

/* ------------------------------------------------------------ Écrans ---- */
@media (max-width:720px){
  /* La barre d'appel occupe déjà le bas de l'écran : le lanceur se pose
     au-dessus d'elle, jamais dessus. */
  .asst{bottom:calc(76px + .75rem + env(safe-area-inset-bottom));right:.85rem}
}
@keyframes asstPlein{from{opacity:0;transform:translateY(22px)}}
@media (max-width:700px){
  .asst__ouvre{padding:.46rem .95rem .46rem .46rem}
  .asst__ouvre-t span{display:none}
  .asst__ouvre-t b{font-size:1rem}
  .asst__panneau{
    position:fixed;inset:0;width:auto;max-height:none;
    border:0;border-radius:0;animation-name:asstPlein;
  }
  .asst__corps{padding:1rem .95rem 1.4rem}
  /* Sous 16 px, iOS agrandit la page à la mise au point d'un champ. */
  .asst__champ,.asst__num input{font-size:16px}
}
/* Panneau plein écran : plus rien d'autre ne doit défiler ni s'afficher. */
html.asst-plein{overflow:hidden}
html.asst-plein .callbar,html.asst-plein .asst__ouvre{display:none}

@media (prefers-reduced-motion:reduce){
  .asst__ouvre,.asst__panneau{animation:none}
  .asst__ouvre:hover,.asst__porte:hover,.asst__cta:hover{transform:none}
}
@media print{.asst{display:none}}


/* ═══════════════════════════════════════════ EN-TÊTE — REPRISE VISUELLE ═══
   Le bandeau était un blanc plat coincé entre la barre encre et le héros
   sombre : il se lisait comme un intervalle, pas comme un élément dessiné.
   Il ne portait aucune couleur au repos, et rien n'y disait où l'on se
   trouvait sur le site.
   ====================================================================== */

/* Un sol, plutôt qu'un vide. Le dégradé est presque invisible — c'est le
   but : il donne une épaisseur au bandeau sans le colorer. */
.header{
  /* Deux couches. Dessous, un blanc légèrement refroidi vers le bas : le
     bandeau devient une matière au lieu d'un vide. Dessus, un lavis bleu qui
     s'éteint en quarante pixels — le blanc naît de la barre encre au lieu de
     commencer net. */
  background:
    linear-gradient(180deg,rgba(230,238,253,.92) 0%,rgba(245,248,253,.9) 58%,rgba(253,254,255,.9) 100%);
  /* Une ombre dès le repos : l'en-tête est un plan posé sur la page, pas une
     bande découpée dedans. */
  box-shadow:0 12px 32px -22px rgba(8,13,24,.5);
}
.header.is-stuck{
  background:
    linear-gradient(180deg,rgba(233,240,254,.96) 0%,rgba(246,249,254,.95) 58%,rgba(255,255,255,.95) 100%);
  box-shadow:0 6px 30px rgba(8,13,24,.11);
}
/* La couture avec la barre encre. Un filet bleu qui s'éteint vers les bords :
   au centre il accroche l'œil, aux extrémités il n'existe plus. */
.header::before{
  content:"";position:absolute;top:0;left:0;right:0;height:1px;pointer-events:none;
  background:linear-gradient(90deg,
    transparent 0%,rgba(1,74,209,.32) 18%,rgba(77,139,255,.72) 50%,
    rgba(1,74,209,.32) 82%,transparent 100%);
}
.header__in{z-index:1}

/* Où l'on se trouve. Le trait de la rubrique courante est déjà tiré, mais en
   bleu clair : le survol d'un autre lien reste plus fort que la marque de la
   page en cours. */
.nav__link.est-ici{color:var(--blue);font-weight:600}
.nav__link.est-ici::after{transform:scaleX(1);background:var(--blue-l);opacity:.5}
.nav__link.est-ici:hover::after{background:var(--blue);opacity:1}
.mnav__link.est-ici{color:var(--blue)}

/* Une réglure fine avant le bloc d'appel : la navigation et les deux boutons
   ne sont pas la même chose, l'en-tête le montre maintenant. */
.header__cta::before{
  content:"";width:1px;height:30px;flex:none;
  background:linear-gradient(180deg,transparent,var(--border) 22%,var(--border) 78%,transparent);
}
@media (max-width:720px){
  /* La navigation disparaît : la réglure n'aurait plus rien à séparer. */
  .header__cta::before{display:none}
}

/* ═════════════════════════════════ FORMULAIRE : ÉTAT DE L'ENVOI ══════════
   Le formulaire annonçait « Demande envoyée » sans que rien ne parte. Il
   envoie maintenant pour de bon, et il dit ce qui s'est réellement passé —
   y compris quand ça échoue, auquel cas il donne le numéro. */
.dform__etat{
  margin-bottom:.9rem;padding:.75rem .95rem;border-radius:var(--r-xs);
  font-size:.88rem;line-height:1.55;
}
.dform__etat.est-bon{
  background:#EAF7F0;border:1px solid #BCE2CF;color:#0B6B43;
}
.dform__etat.est-rate{
  background:#FDF0E9;border:1px solid #F3CDB4;color:#9A4A12;
}
/* Le piège à robots. Hors de l'écran plutôt qu'en display:none : un automate
   qui sait lire la feuille de style ignore ce qui est masqué, il ignore moins
   souvent ce qui est simplement ailleurs. */
.piege{
  position:absolute;left:-9999px;top:auto;width:1px;height:1px;overflow:hidden;
}
/* ══════════════════════════ BOUTON TÉLÉPHONE DE L'EN-TÊTE ════════════════
   Deux blocs de règles se disputaient cet élément, et une auréole pulsait en
   boucle par-dessus. Sur un bouton de 48 px, une ombre portée de 12 px de
   diffusion ne se lit pas comme un halo : elle se lit comme un carré bleu
   derrière l'icône. Au repos comme à l'appui.

   L'état est maintenant franc : un aplat uni, le combiné en orange dessus,
   et rien autour. */
.header__tel::after{content:none}
.header__tel{
  background:transparent;color:var(--blue);
  border-color:rgba(1,74,209,.24);
  transition:background-color .2s var(--ease),color .2s var(--ease),
             border-color .2s var(--ease),transform .2s var(--ease);
}
.header__tel:hover,
.header__tel:focus-visible,
.header__tel:active{
  background:var(--blue);
  border-color:var(--blue);
  color:var(--urgent);
  box-shadow:none;
  transform:translateY(-1px);
}
.header__tel:active{transform:translateY(0) scale(.97)}
.header__tel:focus-visible{outline:3px solid var(--blue-e);outline-offset:2px}


/* ═════════════════════════ VIGNETTES MÉTIERS — MOBILE ════════════════════
   Le texte d'une vignette se déplie au survol : la carte reste graphique au
   repos. Deux d'entre elles étaient exemptées — la première et celle en
   bandeau — parce qu'elles sont plus grandes sur grand écran.

   Sur téléphone elles ont toutes la même taille, et le survol n'existe pas :
   ces deux-là se retrouvaient seules à porter un paragraphe. La série n'avait
   plus d'unité. */
@media (max-width:900px){
  .card--hero .card__body p,
  .card--band .card__body p{max-height:0;opacity:0;margin-bottom:0}
}

/* ══════════════════════ LE LANCEUR ATTEND LA FIN DU HÉROS ════════════════
   Il apparaissait par-dessus « Urgence toiture », c'est-à-dire par-dessus la
   conversion que le héros existe pour produire. Il attend maintenant que le
   visiteur ait quitté le premier écran — ou six secondes, pour les pages
   trop courtes pour être défilées. */
.asst{opacity:0;visibility:hidden;transform:translateY(14px);
      transition:opacity .45s var(--ease-out),transform .45s var(--ease-out),visibility 0s .45s}
.asst.est-la{opacity:1;visibility:visible;transform:none;transition-delay:0s}
.js .asst__ouvre{animation:none}
@media (prefers-reduced-motion:reduce){
  .asst{transition:none}
}

/* ════════════════════════════ MÉTHODE — SUR UNE COLONNE ══════════════════
   Deux défauts sur téléphone, une fois la grille repliée sur une colonne.

   La photo passait AVANT les cinq étapes, et sa légende annonçait une
   « étape 04 » que le lecteur n'avait pas encore rencontrée. Elle passe
   après : on lit le déroulé, puis on en voit un moment.

   Et la découpe en biseau du coin bas-droit, dessinée pour un panneau
   vertical de grand écran, laissait sur un format large un angle clair
   sous la légende — le détail gris sur blanc. Elle ne sert plus ici. */
/* ⚠️ LE POINT QUI CASSAIT — signalé le 15/09/2026 sur une tablette.

   Entre 681 et 1080 px, la photo se réduisait à un filet d'une trentaine de
   pixels : on ne voyait plus que le dégradé de la légende, coupé par l'arête
   de la section suivante.

   La cause n'est pas la découpe ni la marge. Dans ce panneau, l'image ET sa
   légende sont toutes deux en position:absolute — RIEN n'est dans le flux,
   donc la boîte n'a aucune hauteur propre. Sur grand écran, elle empruntait
   celle de la colonne de texte par `min-height:100%` dans une grille en
   `align-items:stretch`. Repliée sur une colonne, il n'y a plus rien contre
   quoi s'étirer : `100 %` se résout sur une rangée auto, donc sur zéro.

   Le palier 680 px avait déjà son `aspect-ratio`, ce qui explique que le
   défaut ne se voyait NI sur téléphone NI sur grand écran — seulement dans
   la bande du milieu. Le rapport est donc posé dès que la grille se replie. */
@media (max-width:1080px){
  .method__visual{
    order:2;margin-top:clamp(1.6rem,4vw,2.4rem);
    aspect-ratio:4/3;min-height:0;
  }
  .method__copy{order:1}
}
@media (max-width:900px){
  .method__visual{clip-path:none}
  .method__note{
    padding-top:clamp(2.2rem,7vw,3rem);
    background:linear-gradient(180deg,transparent,rgba(6,10,20,.5) 42%,rgba(6,10,20,.9) 100%);
    font-size:.79rem;color:rgba(255,255,255,.88);
  }
}

/* ═══════════════════════ LISIBILITÉ DES BLEUS ═══════════════════════════
   Le numéro du surtitre était posé à 40 % d'opacité : sur blanc, un #014AD1
   à 40 % descend sous le seuil de lecture. Il indexe la page, il doit se
   lire. */
.eyebrow::before{opacity:.62}

/* ══════════════════════ CHANTIERS — TEXTE SUR PHOTO ═════════════════════
   Le voile s'ouvrait à 26 % de la hauteur : sur un ciel clair, le libellé de
   commune en bleu clair et le titre en blanc se posaient sur du blanc. Une
   ombre portée ne rattrape pas un fond aussi lumineux — c'est le voile qui
   doit tenir, et le texte qui doit être plus compact. */
@media (max-width:900px){
  .pj__ov{
    background:linear-gradient(180deg,
      transparent 14%,rgba(6,10,20,.34) 44%,rgba(6,10,20,.78) 74%,rgba(6,10,20,.96) 100%);
    padding:1rem .95rem 1.05rem;gap:.22rem;
  }
  .pj__city{font-size:.66rem;letter-spacing:.15em;color:#A8C6FF}
  .pj__t{font-size:1.16rem;line-height:1.14}
  .pj--lead .pj__t{font-size:1.28rem}
  .pj--lead .pj__city{font-size:.68rem}
  .pj--lead .pj__ov{padding:1.1rem 1rem 1.15rem}
}

/* Sur fond encre, la variante claire du surtitre ne touchait que le libellé :
   le numéro restait en #014AD1, c'est-à-dire du bleu sombre sur du sombre. */
.eyebrow--light::before{color:var(--blue-e);opacity:.72}

/* L'étiquette de la carte au doigt : le nom et la distance, posés sur le
   point touché. Elle remplace le renvoi vers la liste, qui faisait
   disparaître la carte au moment où on l'interrogeait. */
.map__nom{
  position:absolute;z-index:4;pointer-events:none;
  transform:translate(-50%,calc(-100% - 12px));
  padding:.4rem .7rem;border-radius:var(--r-xs);
  background:var(--ink);color:#fff;
  font-size:.775rem;font-weight:600;line-height:1.3;white-space:nowrap;
  box-shadow:0 8px 22px rgba(8,13,24,.4);
  opacity:0;transition:opacity .18s var(--ease);
}
.map__nom.est-la{opacity:1}
.map__nom.est-a-gauche{transform:translate(-88%,calc(-100% - 12px))}
.map__nom::after{
  content:"";position:absolute;top:100%;left:50%;transform:translateX(-50%);
  border:5px solid transparent;border-top-color:var(--ink);
}
.map__nom.est-a-gauche::after{left:88%}

/* ═══════════════════════════ BOUTON DE LECTURE VIDÉO ════════════════════
   Le cercle est bien centré — c'est le triangle qui ne l'était pas. Son
   décalage optique était exprimé en pourcentage du bouton (8 % de 74 px, soit
   6 px) et non du glyphe : sur un triangle de 25 px, c'est un quart de sa
   largeur. Rapporté au glyphe, le décalage fait 2 px et remplit son office
   sans se voir. */
.vplayer__play svg{margin-left:0;transform:translateX(9%)}
@media (max-width:680px){
  /* Sur une vidéo de 350 px de large, un cercle de 74 px prend 40 % de la
     hauteur de l'affiche. */
  .vplayer__play{width:60px}
  .vplayer__play svg{width:32%;height:32%}
}

/* La dernière ligne de la section avis passait SOUS le biseau de la section
   suivante — 18 px de recouvrement mesurés sur grand écran, pas seulement un
   manque d'air. Le texte finissait dans le noir. La respiration vaut à toutes
   les largeurs, pas seulement sur téléphone. */
.avis-cta__note{margin-bottom:clamp(1.9rem,3.4vw,3.1rem)}

/* ══════════════════════ HÉROS DES PAGES INTERNES — MOBILE ════════════════
   Le même défaut que sur l'accueil, et sur toutes les pages à la fois :
   les obliques du logo descendaient en travers du titre et du chapô, et la
   photo transparaissait derrière les mots.

   Ici, pas de place pour une bande photo : entre l'en-tête et le titre il
   n'y a que soixante-dix pixels. La photo devient donc une matière — elle
   éclaire le coin haut-droit, là où passent les obliques, et s'éteint sous
   le texte. C'est un héros de page intérieure : ce qu'on doit y lire, c'est
   le titre.
   ====================================================================== */
@media (max-width:720px){
  .phero__media::after{
    background:
      linear-gradient(104deg,
        rgba(8,13,24,.94) 0%,rgba(8,13,24,.78) 34%,
        rgba(8,13,24,.42) 68%,rgba(8,13,24,.24) 100%),
      linear-gradient(180deg,
        rgba(8,13,24,.42) 0%,rgba(8,13,24,.66) 46%,rgba(8,13,24,.9) 100%);
  }
  /* Les obliques se retirent dans le coin haut-droit, où la photo est claire
     et où il n'y a pas un mot.

     Treize points plus à droite qu'à la première écriture. Le couloir laissé
     libre supposait des titres de deux lignes courtes ; il y en a de longues
     — « Recherche et réparation », « Zinguerie et couverture », « Une équipe
     de couvreurs » atteignent 302 px sur 390, et l'oblique descendait alors
     derrière la dernière syllabe. Mesuré page par page, le pied de l'oblique
     passe désormais à 289 px au plus bas, contre 238 auparavant.

     Et elles descendent maintenant **vers la droite**, comme sur le héros des
     avis : elles entrent par le haut et sortent par le côté, au lieu de
     plonger vers le titre. C'est le sens qui les éloigne du texte à mesure
     qu'elles descendent, au lieu de l'en rapprocher — d'où le fondu devenu
     inutile, retiré. La hauteur n'est plus choisie mais déduite : il leur
     faut 22,4 points pour atteindre le bord droit à cette pente, soit 156 px.

     Le départ à 78 % n'est pas rond non plus. À 74 %, l'oblique frôlait le
     fil d'Ariane le plus long (« Accueil → Nos services → Couverture &
     toiture », 318 px) ; à 78 %, elle passe à 331 px de son niveau. Et au
     niveau du titre — 68 px plus bas — elle est déjà à 342 px, contre 314 px
     pour la ligne la plus longue du site (/zones-intervention/). */
  .phero__bands{bottom:auto;height:156px;overflow:hidden}
  .phero__bands i{opacity:1}
  .phero__bands i:nth-child(1){
    clip-path:polygon(78% 0,83.2% 0,105.6% 100%,100.4% 100%);opacity:.92;
  }
  .phero__bands i:nth-child(2){
    clip-path:polygon(88% 0,90.6% 0,113% 100%,110.4% 100%);opacity:.52;
  }

  /* #3D6FE0 sur une photo sombre ne se voit pas : c'est le bleu du logo, pas
     un bleu de texte sur fond sombre. */
  .phero h1 em{color:#8AB6FF}
}

@media (max-width:680px){
  /* Les trois mentions : « 4 matériaux » repassait à la ligne quand
     « 10 ans » et « 48 h » tenaient sur une seule — les trois blocs
     n'avaient plus la même assise. */
  .phero__facts{align-items:start;gap:1rem 0}
  .phero__facts b{font-size:1.16rem;line-height:1.15}
  .phero__facts span{font-size:.7rem;margin-top:.22rem}
  .phero__facts div{padding-inline:.7rem .45rem}
  .phero__facts div:nth-child(3n+1){padding-left:0}
}

/* Les cartes des points singuliers restaient sur deux colonnes jusqu'en bas :
   la règle « six cartes ou plus » porte un :has(), donc une spécificité plus
   forte que le passage à une colonne, qu'elle écrasait. À 390 px la mesure du
   texte tombait à quatre mots par ligne. */
@media (max-width:620px){
  .tiles,.tiles:has(> :nth-child(4)){grid-template-columns:minmax(0,1fr)}
}

/* ═══════════════════════════ LA BULLE D'UNE COUCHE ═══════════════════════
   Ouverte au toucher d'une pastille de la coupe. Fond encre, filet bleu, le
   reste de la page assombri : la réponse arrive sur le dessin, sans avoir à
   descendre chercher la fiche. */
html.cpop-ouverte{overflow:hidden}
/* Le lanceur de l'assistant s'efface le temps de la bulle. Deux panneaux
   flottants à la fois, dont l'un propose de poser une question pendant que
   l'autre y répond : c'en est un de trop. La barre d'appel, elle, reste —
   c'est le bouton pour lequel la page existe, et le placement de la bulle
   tient compte de sa hauteur réelle.

   Le sélecteur vise aussi les ENFANTS : `.asst>*{pointer-events:auto}` rend
   la main au lanceur, et l'éteindre sur le seul conteneur ne suffisait pas. */
html.cpop-ouverte .asst,
html.cpop-ouverte .asst>*{opacity:0;pointer-events:none}
.cpop{
  position:fixed;inset:0;z-index:130;
  display:grid;place-items:center;padding:clamp(1rem,5vw,2rem);
  background:rgba(4,7,14,.72);
  -webkit-backdrop-filter:blur(6px) saturate(120%);
          backdrop-filter:blur(6px) saturate(120%);
  opacity:0;transition:opacity .22s var(--ease);
}
.cpop.est-la{opacity:1}
.cpop__box{
  position:relative;width:min(29rem,100%);max-height:86vh;overflow-y:auto;
  padding:clamp(1.4rem,4.5vw,1.9rem);
  background:linear-gradient(158deg,#0E1830 0%,#0A1024 58%,#070C1A 100%);
  border:1px solid rgba(77,139,255,.55);border-radius:var(--r-md);
  box-shadow:0 30px 80px rgba(2,5,12,.7),0 0 0 1px rgba(77,139,255,.14),
             0 0 46px -12px rgba(77,139,255,.45);
  transform:translateY(14px) scale(.97);
  transition:transform .28s var(--ease-out);
}
.cpop.est-la .cpop__box{transform:none}
.cpop__x{
  position:absolute;top:.7rem;right:.7rem;
  /* Explicite, et pas par accident d'ordre. La zone de texte porte un
     `mask-image` dès qu'elle déborde, ce qui lui ouvre un contexte
     d'empilement : elle passait alors PAR-DESSUS la fermeture, qui n'est
     positionnée qu'en `absolute` sans rang. Mesuré : le doigt tombait sur le
     texte, la bulle ne se fermait pas. */
  z-index:2;
  display:grid;place-items:center;width:34px;height:34px;
  border-radius:var(--r-xs);color:#9FB2D2;
  transition:background-color .18s var(--ease),color .18s var(--ease);
}
.cpop__x:hover{background:rgba(255,255,255,.1);color:#fff}
.cpop__x:focus-visible{outline:2px solid var(--blue-e);outline-offset:2px}
.cpop__x svg{width:19px;height:19px}
.cpop__n{
  display:inline-block;margin-bottom:.6rem;padding:.16rem .55rem;
  border:1px solid rgba(77,139,255,.5);border-radius:var(--r-pill);
  font-family:var(--display);font-size:.8rem;font-weight:700;
  letter-spacing:.14em;color:var(--blue-e);
}
.cpop__t{
  font-family:var(--display);font-size:clamp(1.55rem,6vw,1.95rem);
  font-weight:700;line-height:1.08;color:#fff;margin-bottom:.45rem;
}
.cpop__role{
  font-size:.92rem;line-height:1.5;color:var(--blue-e);
  margin-bottom:.75rem;
}
.cpop__d{font-size:.92rem;line-height:1.62;color:#B9C6DC}
.cpop__go{
  display:inline-flex;align-items:center;gap:.5rem;margin-top:1.1rem;
  padding:.62rem 1.05rem;border-radius:var(--r-xs);
  background:var(--blue);color:#fff;
  font-family:var(--display);font-size:.98rem;font-weight:700;letter-spacing:.012em;
  transition:background-color .2s var(--ease),transform .2s var(--ease);
}
.cpop__go:hover{background:var(--blue-d);transform:translateY(-1px)}
.cpop__go:focus-visible{outline:3px solid var(--blue-e);outline-offset:2px}
.cpop__go svg{width:16px;height:16px}

/* ---- Le pied : parcourir l'empilement sans refermer ----------------------
   Une bulle qui se ferme à chaque couche oblige à viser huit fois une pastille
   de 27 px. Les deux chevrons font la même chose d'un doigt qui ne bouge pas.
   Ils ne bouclent pas : un toit a un dessus et un dessous, revenir de la tuile
   au plafond par la gauche ne voudrait rien dire. Aux extrémités, le chevron
   s'éteint au lieu de disparaître — une commande qui s'en va déplace tout ce
   qui l'entoure.

   UNE seule rangée, et c'est le point important. Elle en faisait deux — le
   lien d'abord, les chevrons et le rang ensuite —, soit 113 px de commandes.
   Sur une bulle qui peut n'en faire que 215, il ne restait alors que 47 px de
   texte : moins que la hauteur du titre. Mesuré à 390 × 640, six titres sur
   huit étaient coupés en leur milieu, et pas une ligne d'explication n'était
   visible. Le rang, lui, n'est pas perdu : la pastille de la bulle porte déjà
   le numéro de la couche. */
.cpop__pied{
  display:flex;align-items:center;gap:.5rem;
  margin-top:.9rem;padding-top:.75rem;
  border-top:1px solid rgba(255,255,255,.1);
}
.cpop__pied .cpop__go{flex:1;margin-top:0;justify-content:center}
.cpop__pas{
  display:grid;place-items:center;width:38px;height:38px;flex:none;
  border:1px solid rgba(77,139,255,.4);border-radius:var(--r-xs);
  color:#CFE0FF;background:rgba(77,139,255,.08);
  transition:background-color .18s var(--ease),border-color .18s var(--ease),
             color .18s var(--ease),opacity .18s var(--ease);
}
.cpop__pas svg{width:17px;height:17px}
.cpop__pas:hover:not(:disabled){background:rgba(77,139,255,.22);border-color:var(--blue-e);color:#fff}
.cpop__pas:focus-visible{outline:2px solid var(--blue-e);outline-offset:2px}
.cpop__pas:disabled{opacity:.3;cursor:default}

/* ---- La jauge de défilement ---------------------------------------------
   Un fondu au bas du texte dit qu'il continue, mais pas COMBIEN. Ce filet
   bleu le dit : sa longueur est la part qu'on voit, sa position est l'endroit
   où l'on en est. Il n'apparaît que si le texte déborde vraiment, et il est
   posé par le script — lui seul connaît la hauteur réelle de la zone.
   Il ne défile pas avec le texte : il est frère de la zone, pas son enfant. */
.cpop__jauge{
  position:absolute;right:.45rem;width:3px;border-radius:2px;
  background:rgba(77,139,255,.15);pointer-events:none;overflow:hidden;
}
.cpop__jauge[hidden]{display:none}
.cpop__jauge i{
  display:block;width:100%;border-radius:2px;background:var(--blue-e);
  box-shadow:0 0 8px rgba(77,139,255,.5);
  transition:transform .12s linear,height .18s var(--ease);
}

/* ---- Sur téléphone, la bulle se pose contre sa pastille ------------------
   Centrée et voilée, elle prenait tout l'écran : on touchait « 03 » et le
   dessin disparaissait au moment précis où on venait de l'interroger. On
   lisait la réponse sans plus voir la question.

   Ancrée, elle se pose sous la pastille quand il reste de la place dessous,
   au-dessus sinon — c'est ce qui arrive aux quatre couches basses. La couche
   désignée reste donc visible, et à pleine opacité pendant que les sept
   autres sont retombées à 20 % (voir `.cpe.is-cible`).

   Le voile perd son flou et presque toute sa densité : il ne sert plus à
   isoler la bulle, seulement à recevoir le toucher qui la referme.
   Les coordonnées sont posées en ligne par le script — elles dépendent de
   l'endroit où la pastille se trouve, ce qu'aucune règle ne peut savoir. */
@media (max-width:720px){
  .cpop--ancree{
    display:block;padding:0;
    background:rgba(4,7,14,.30);
    -webkit-backdrop-filter:none;backdrop-filter:none;
  }
  .cpop--ancree .cpop__box{
    position:fixed;
    width:min(19.5rem,calc(100vw - 1.5rem));
    max-height:min(44vh,330px);
    padding:1.05rem 1.15rem 1.2rem;
    border-radius:var(--r-sm);
    transform:translateY(6px) scale(.98);
    /* Elle arrive du côté de sa pastille, pas d'en bas : la bulle qui s'ouvre
       vers le haut montait de six pixels, c'est-à-dire qu'elle descendait
       vers ce qu'elle quittait. */
    transform-origin:50% 0;
  }
  .cpop--ancree[data-sens="haut"] .cpop__box{
    transform:translateY(-6px) scale(.98);transform-origin:50% 100%;
  }
  .cpop--ancree.est-la .cpop__box{transform:none}

  /* Le glissement d'une pastille à l'autre. Il n'est armé qu'une fois la
     bulle posée — sinon elle traverserait l'écran depuis sa position de
     repos à la première ouverture. C'est ce mouvement qui dit que les huit
     couches sont un seul objet, et non huit fiches sans rapport. */
  .cpop--ancree.cpop--glisse .cpop__box{
    transition:transform .28s var(--ease-out),
               left .3s var(--ease-out),top .3s var(--ease-out),
               max-height .3s var(--ease-out);
  }
  .cpop--ancree.cpop--glisse::after{
    transition:left .3s var(--ease-out),top .3s var(--ease-out);
  }
  /* Quand le recalage a éloigné la boîte de la pastille, la pointe ne relie
     plus rien : elle s'efface plutôt que de flotter au milieu du dessin. */
  .cpop--sans-pointe::after{display:none}

  .cpop--ancree .cpop__pied{margin-top:.75rem;padding-top:.65rem}
  /* Le pied ne défile pas. La bulle rétrécit pour tenir du côté qui laisse le
     pan visible — jusqu'à 190 px — et son texte défile alors en interne. Avec
     un bloc d'un seul tenant, le bouton et les deux chevrons partaient sous le
     bord : les commandes disparaissaient au moment précis où la bulle devenait
     petite, c'est-à-dire au moment où l'on en avait le plus besoin.
     Seul le texte défile ; le lien et la navigation restent posés au fond. */
  .cpop--ancree .cpop__box{display:flex;flex-direction:column;overflow:hidden}
  .cpop--ancree .cpop__c{
    overflow-y:auto;min-height:0;-webkit-overflow-scrolling:touch;
    /* La place de la jauge, pour que le texte ne passe pas dessous. */
    padding-right:.75rem;
    /* La barre native ferait double emploi avec la jauge, et sur Android elle
       mange huit pixels de mesure au texte. */
    scrollbar-width:none;-ms-overflow-style:none;
  }
  .cpop--ancree .cpop__c::-webkit-scrollbar{display:none}
  /* La classe est posée par le script, qui seul sait si le texte dépasse. */
  .cpop--ancree .cpop__c.deborde{
    -webkit-mask-image:linear-gradient(180deg,#000 0 80%,transparent 100%);
            mask-image:linear-gradient(180deg,#000 0 80%,transparent 100%);
  }
  .cpop--ancree .cpop__go{flex:none;align-self:flex-start}
  .cpop--ancree .cpop__nav{flex:none}

  .cpop--ancree .cpop__t{font-size:1.3rem}
  .cpop--ancree .cpop__role{font-size:.86rem;margin-bottom:.5rem}
  .cpop--ancree .cpop__d{font-size:.86rem;line-height:1.55}
  .cpop--ancree .cpop__go{padding:.5rem .85rem;font-size:.9rem}

  /* ---- Le mode serré --------------------------------------------------
     Sous 265 px de haut, chaque pixel de rembourrage se paie en ligne de
     texte perdue. Le décor recule : marges resserrées, titre d'un cran plus
     petit, badge collé au titre. Vingt-six pixels rendus, soit deux lignes
     de plus — la différence entre « on voit le titre » et « on voit ce que
     fait la couche ». La classe est posée par le script, qui seul connaît la
     hauteur retenue. */
  .cpop--court .cpop__box{padding:.75rem .85rem .8rem}
  .cpop--court .cpop__n{margin-bottom:.35rem;padding:.1rem .45rem;font-size:.74rem}
  .cpop--court .cpop__t{font-size:1.12rem;margin-bottom:.3rem}
  .cpop--court .cpop__role{font-size:.83rem;line-height:1.42;margin-bottom:.35rem}
  .cpop--court .cpop__d{font-size:.83rem;line-height:1.48}
  .cpop--court .cpop__pied{margin-top:.55rem;padding-top:.5rem}
  .cpop--court .cpop__pas{width:34px;height:34px}
  .cpop--court .cpop__go{padding:.42rem .7rem;font-size:.85rem}
  .cpop--court .cpop__x{top:.25rem;right:.25rem;width:28px;height:28px}
  /* Le texte défile dessous : sans assise, la croix se lit sur des mots. */
  .cpop--ancree .cpop__x{
    top:.35rem;right:.35rem;width:32px;height:32px;
    background:rgba(12,20,42,.82);
    -webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);
  }

  /* La pointe. Elle vise la pastille, pas le milieu de la bulle : quand
     celle-ci a dû se recaler contre un bord de l'écran, les deux ne sont
     plus au même endroit. D'où un élément à part, posé aux coordonnées de
     la pastille, et non un `::before` de la boîte — qui serait de toute
     façon rogné par son `overflow`. */
  .cpop--ancree::after{
    content:"";position:fixed;z-index:1;
    left:var(--fleche-x,50%);top:var(--fleche-y,50%);
    width:13px;height:13px;margin:-7px 0 0 -7px;transform:rotate(45deg);
    border:1px solid rgba(77,139,255,.55);
  }
  .cpop--ancree[data-sens="bas"]::after{
    background:#0E1830;border-right:0;border-bottom:0;
  }
  .cpop--ancree[data-sens="haut"]::after{
    background:#070C1A;border-left:0;border-top:0;
  }
}

/* ---- Le mode d'emploi des pastilles -------------------------------------
   Sur grand écran, chaque couche porte son nom au bout d'un trait de rappel :
   il n'y a rien à expliquer. Sur téléphone, la colonne d'étiquettes est
   recadrée hors du champ et il ne reste que huit pastilles numérotées, dont
   rien ne dit qu'elles s'ouvrent. Cette ligne le dit, une fois, juste
   au-dessus du dessin. Elle ne s'affiche que là où elle sert. */
.cpe__mode{display:none}
@media (max-width:720px){
  /* Bloc, pas flex : une phrase qui contient des `<b>` et un signe se
     découperait en autant de colonnes, un mot par ligne. Le signe est donc
     sorti du flux, et le texte garde sa mesure. */
  .cpe__mode{
    display:block;position:relative;
    margin:0 0 clamp(1rem,3vw,1.4rem);
    padding:.85rem 1rem .85rem 2.5rem;
    border:1px solid rgba(77,139,255,.28);border-left-width:3px;
    border-radius:var(--r-xs);
    background:rgba(77,139,255,.07);
    font-size:.86rem;line-height:1.55;color:#B9C6DC;
  }
  .cpe__mode span{
    position:absolute;left:1rem;top:.8rem;
    color:var(--blue-e);font-size:1rem;line-height:1.35;
  }
  .cpe__mode b{
    color:var(--blue-e);font-family:var(--display);font-weight:700;
    letter-spacing:.06em;font-variant-numeric:tabular-nums;
  }
}

/* La pastille doit se donner comme touchable. */
.cpe__couche{outline:none}
.cpe__couche:focus-visible .cpe__pt{stroke:#fff;stroke-width:3}

@media (prefers-reduced-motion:reduce){
  .cpop,.cpop__box{transition:none}
}

/* ═══════════════════════ TABLEAU DE COORDONNÉES — MOBILE ═════════════════
   Deux colonnes dont une de 12 rem, et une adresse électronique de trente
   signes : 480 px de large pour 350 disponibles. Le lecteur devait défiler
   vers la droite pour lire le numéro de téléphone de l'entreprise.

   Sur téléphone, chaque ligne devient un bloc : le libellé au-dessus, la
   valeur en dessous. Tout est visible d'un coup. */
.tablewrap td:first-child{width:12rem}
@media (max-width:680px){
  .tablewrap,.tablewrap>table,.tablewrap table,.tablewrap tbody,
  .tablewrap tr,.tablewrap td{display:block;width:auto;min-width:0}
  .tablewrap{overflow-x:visible;padding:.2rem 1rem .6rem}
  .tablewrap td:first-child{
    width:auto;padding:.9rem 0 .1rem;border:0;
    font-size:.72rem;letter-spacing:.14em;text-transform:uppercase;color:var(--muted);
  }
  .tablewrap td:first-child strong{font-weight:600}
  .tablewrap td:last-child{
    padding:0 0 .9rem;border-bottom:1px solid var(--border);
    overflow-wrap:anywhere;
  }
  .tablewrap tr:last-child td:last-child{border-bottom:0}
}

/* ══════════════════ MUR DE RÉALISATIONS — LISIBILITÉ SUR PHOTO ══════════
   Le libellé de métier était une pastille de verre translucide : sur un ciel
   clair elle disparaissait, faute de contraste avec ce qu'elle recouvrait.
   Un aplat d'encre et un filet bleu lui donnent une assise, quelle que soit
   la photo dessous. */
.rea__city{
  background:rgba(6,10,20,.78);border-color:rgba(77,139,255,.42);
  color:#CFE0FF;letter-spacing:.12em;
}
@media (max-width:900px){
  .rea__ov{
    background:linear-gradient(180deg,
      transparent 20%,rgba(8,13,24,.42) 52%,rgba(8,13,24,.86) 82%,rgba(8,13,24,.96) 100%);
  }
  .rea__t{font-size:1.02rem;line-height:1.2;text-shadow:0 1px 10px rgba(8,13,24,.7)}
}

/* Le héros des avis a ses propres obliques — troisième variante, oubliée par
   la reprise des deux autres. Centré, il n'a pas de côté libre : elles
   descendaient donc en travers de la note, du titre et du chapô. Sur
   téléphone, elles se retirent dans le coin haut-droit, au-dessus du fil
   d'Ariane, qui est centré et court. */
@media (max-width:720px){
  /* La hauteur n'est plus choisie, elle est déduite. Les obliques entrent par
     le haut et descendent vers la droite : arrêtées trop tôt, elles étaient
     sectionnées sur une horizontale, en plein milieu du bandeau.

     Le calcul portait sur le mauvais bord. À 134 px, c'est le côté DROIT de
     l'oblique qui avait quitté l'écran ; son côté gauche, lui, était encore
     à 96,5 % — et c'est ce bord-là qu'on voyait coupé net. Pour que toute
     l'oblique soit sortie, c'est le bord GAUCHE qui doit atteindre 100 %.

     À la pente conservée (0,153 point par pixel), il lui faut 24,8 points,
     soit 162 px. La seconde, huit points plus à droite, a quitté le champ
     cinquante-sept pixels plus haut. Aucune des deux ne montre plus son pied :
     elles entrent par le haut et disparaissent par le côté. Le titre commence
     à 236 px, soit soixante-quatorze plus bas — rien n'est touché. */
  .ahero__bands{bottom:auto;height:162px;overflow:hidden;opacity:.62}
  .ahero__bands i:nth-child(1){clip-path:polygon(76% 0,80% 0,104.8% 100%,100.8% 100%)}
  .ahero__bands i:nth-child(2){clip-path:polygon(84% 0,86.2% 0,111% 100%,108.8% 100%)}
  .ahero__bands i:nth-child(3){display:none}
}

/* L'icône portait encore son propre décor, hérité d'une version où elle était
   elle-même la pastille bleue : un rond plein, une ombre et une auréole posés
   sur le <svg>. La remise à zéro qui suivait ne visait que l'état de repos —
   `.header__tel:hover svg` est plus spécifique et rétablissait l'aplat
   #0033A0 à l'appui. D'où le carré bleu foncé derrière le combiné.

   Le bouton porte la couleur, l'icône ne porte plus rien. */
.header__tel:hover svg,
.header__tel:focus svg,
.header__tel:focus-visible svg,
.header__tel:active svg{
  background:none;box-shadow:none;animation:none;transform:none;
  padding:0;border-radius:0;color:currentColor;
}


/* ══════════════════════════════ HÉROS MOBILE ═════════════════════════════
   Contrainte posée : tout doit tenir sur le premier écran — photo, titre,
   chapô, les deux boutons et la note Google — sans avoir à défiler.

   Sur un écran de 844 px, l'en-tête en prend 127 et la barre d'appel 76 : il
   reste 641 px. Le texte en occupe environ 350, la photo prend le reste.
   Chaque marge de ce bloc est donc comptée, pas choisie au jugé.

   Les obliques du logo sont retirées : elles reposent, sur grand écran, sur
   l'arête entre le panneau d'encre et la photo. Ici il n'y a pas d'arête, et
   en inventer une pour justifier l'ornement était un raisonnement à l'envers.
   ====================================================================== */
@media (max-width:720px){
  .hero{--bande:278px;background:var(--ink)}

  /* La nappe d'encre reprend du service sous le texte. Sans elle le bas du
     héros est un aplat noir ; avec elle, une lueur bleue passe derrière le
     titre — c'est la profondeur du grand écran, à l'échelle du téléphone. */
  .hero__field{
    display:block;grid-area:top/full-start/bottom/full-end;z-index:0;
    background:
      radial-gradient(80% 42% at 22% 42%,rgba(38,104,240,.30) 0%,transparent 70%),
      radial-gradient(70% 38% at 96% 88%,rgba(44,86,196,.22) 0%,transparent 72%),
      linear-gradient(178deg,#0B142A 0%,#080F20 52%,#060A16 100%);
  }
  .hero__field::before{content:none}

  /* La photo, pleine largeur, sans découpe. Sur le téléphone, ce n'est plus
     l'ouvrage mais l'équipe : quatre visages en haut de la page d'accueil
     disent, avant toute phrase, que l'entreprise a des salariés et un
     chantier. C'est l'argument que le format vertical ne pouvait pas porter. */
  .hero__art{z-index:1}
  .hero__bands{display:none}
  .hero__art-img{inset:0 0 auto 0;height:var(--bande);clip-path:none}
  .hero__art-img .hero__pic--desk{display:none}
  .hero__art-img .hero__pic--mob{display:block}
  .hero__art-img img{
    height:100%;object-fit:cover;object-position:50% 42%;transform:none;
  }
  /* Les quatre compagnons devant les trois véhicules de l'entreprise, au
     dépôt. C'est la photo demandée par le client, et c'est la bonne : on y
     voit à la fois des visages et une flotte, ce qu'aucune des deux autres ne
     faisait seule.

     Le recadrage part de 200 px sous le haut de la source, et ce n'est pas
     un choix de composition. Le panneau d'enseigne du dépôt, en haut à
     gauche, porte un NOM ET UNE ADRESSE DE SITE différents de ceux de cette
     page. Le laisser dans le cadre reviendrait à afficher, lisible, une autre
     adresse que celle où se trouve le visiteur. Il est donc hors champ — et
     le cadre y gagne : les visages sont plus grands, il n'y a plus de ciel
     mort. Ne remonte pas ce recadrage sans avoir réglé la question de
     l'enseigne.

     Aucun rapprochement, et c'est voulu : la fenêtre est prise dans les
     pixels natifs au rapport exact de la bande — 1 040 × 741 pour 390 × 278,
     soit 1,4035 contre 1,4029. Le recouvrement ne rogne donc rien. Si la
     bande change de hauteur, c'est le recadrage qu'il faut refaire, pas un
     zoom qu'il faut ajouter (voir tools/recadrer.js). */
  .hero__pic--mob img{object-position:50% 50%;transform:none}
  /* Le voile s'arrête à .88 : la séparation n'est plus faite par le noir,
     elle est faite par le trait. */
  .hero__art-img::after{
    background:linear-gradient(180deg,
      rgba(8,13,24,.18) 0%,
      rgba(8,13,24,.02) 24%,
      rgba(8,13,24,.10) 66%,
      rgba(8,13,24,.55) 92%,
      rgba(8,13,24,.88) 100%);
  }

  /* ---- Le trait ------------------------------------------------------
     La photo et l'encre se touchaient dans un fondu. Un fondu n'est pas une
     décision : il masque la couture au lieu de la dessiner. Le trait la
     dessine, et une lueur le parcourt lentement — le seul mouvement de tout
     le premier écran, donc le seul endroit où l'œil est appelé. */
  .hero__art::after{
    content:"";position:absolute;left:0;right:0;top:calc(var(--bande) - 1px);
    height:2px;z-index:3;pointer-events:none;
    background:linear-gradient(90deg,
      rgba(77,139,255,0) 0%,rgba(77,139,255,.5) 13%,
      var(--blue-e) 40%,#A6C7FF 56%,rgba(77,139,255,.5) 87%,
      rgba(77,139,255,0) 100%);
    box-shadow:0 0 16px rgba(77,139,255,.42);
  }
  .hero__art::before{
    content:"";position:absolute;top:calc(var(--bande) - 2.5px);
    left:0;width:34%;height:5px;z-index:4;pointer-events:none;border-radius:3px;
    background:linear-gradient(90deg,
      transparent 0%,rgba(216,232,255,.9) 50%,transparent 100%);
    animation:heroTrait 6.4s cubic-bezier(.4,0,.25,1) 1.4s infinite;
  }
  @keyframes heroTrait{
    0%{transform:translateX(-105%);opacity:0}
    10%{opacity:.95}
    46%{opacity:.95}
    62%{transform:translateX(300%);opacity:0}
    100%{transform:translateX(300%);opacity:0}
  }
  @media (prefers-reduced-motion:reduce){
    .hero__art::before{animation:none;opacity:0}
  }

  /* Les pastilles de métiers quittent le héros : deux lignes de navigation
     secondaire entre le chapô et les boutons, alors que les neuf métiers sont
     dans le menu et dans la section juste en dessous. */
  .hero__metiers{display:none}

  .hero__copy{
    grid-area:copy/main-start/socle/main-end;
    position:relative;z-index:2;
    padding-top:calc(var(--bande) + 1.15rem);
    padding-bottom:1rem;
  }

  /* ---- La fin du héros ------------------------------------------------
     Le bandeau de chiffres — 9 métiers, 50 km, 15 min, 6 h – 20 h — quitte
     le téléphone. Sur deux colonnes il faisait un second palier de quatre
     mentions juste après le socle de réassurance, qui en porte déjà quatre :
     huit blocs de rassurance à la file avant le premier titre de la page, et
     « Nos savoir-faire » repoussé d'un écran entier. Sur grand écran les
     quatre chiffres tiennent sur une ligne et ne coûtent rien : ils y restent.

     Ils emportaient avec eux la pente qui fermait le hero. C'est donc le
     hero qui la reprend, avec exactement les mêmes valeurs : la ligne de
     toit qui traverse la page n'a pas à changer d'angle parce qu'on a retiré
     un bloc. Le rembourrage compense la coupe, la marge négative la fait
     mordre sur la section suivante, et z-index la pose par-dessus. */
  .proofband{display:none}
  .hero{
    --p:clamp(2.2rem,4.4vw,3.9rem);
    clip-path:polygon(0 0,100% 0,100% calc(100% - var(--p)),0 100%);
    padding-bottom:var(--p);
    margin-bottom:calc(-1 * var(--p));
    z-index:1;
  }
}

/* Le compte, sur 641 px utiles. Chaque valeur ci-dessous a été mesurée, pas
   estimée : la note Google doit finir au-dessus de la barre d'appel. */
@media (max-width:680px){
  .hero h1{font-size:min(10.2vw,2.72rem);line-height:.96;margin-bottom:.72rem}
  /* Le surtitre passait sur deux lignes : trente-sept signes espacés de
     .19em ne tiennent pas dans 350 px.

     Et le filet part. Sur grand écran il ouvre la ligne dans une colonne
     large, où le décalage ne se voit pas. Ici il pousse le texte trente-deux
     pixels à droite pendant que le titre, le chapô, les boutons et la note
     Google partent tous du même bord — la ligne ne semblait alors ni calée à
     gauche ni centrée, seulement mal posée. Sans lui, le premier écran a un
     seul bord gauche, et le surtitre récupère la place qui lui manquait. */
  .hero__kicker{margin-bottom:.45rem;font-size:.68rem;letter-spacing:.14em;gap:0}
  .hero__kicker i{display:none}
  /* Le chapô rend six pixels. Mesuré après le changement de photo et le
     retrait du filet du surtitre : le bas de la note Google tombait à 768,
     c'est-à-dire exactement sur le haut de la barre d'appel. Elles ne se
     recouvraient pas, mais elles se touchaient — le projet tient 6 px de
     marge, et c'est l'écart entre « ça tient » et « ça tient tout juste ».
     C'est le plus grand blanc du bloc, donc celui qui se resserre sans que
     rien ne se voie. */
  .hero__lead{font-size:.95rem;line-height:1.54;margin-bottom:.5rem}
  .hero__actions{gap:.55rem}
  .hero__actions .btn{padding:.86rem .6rem;font-size:.9rem}
  .hero__proof{margin-top:.78rem;padding-top:.68rem}
  .hero__socle-i{align-items:flex-start}
  .hero__socle-i b{font-size:.95rem;line-height:1.18;letter-spacing:.004em}
  .hero__socle-i span span{font-size:.695rem;line-height:1.34;color:#94A3BC}
  /* La même réduction de moitié que les autres blocs sur encre : une pente de
     4 rem sur 375 px de large devient un angle très marqué. La règle générale
     (§ LES PENTES) ne cite pas .hero, qui n'a de pente qu'en dessous de 900. */
  .hero{--p:1.5rem}
}

/* Sous 381 px — les Android compacts — le compte ne tombe plus juste : le
   chapô gagne une ligne et le surtitre repasse sur deux. La bande photo rend
   trente pixels, et le surtitre se resserre encore. */
@media (max-width:380px){
  .hero{--bande:258px}
  /* Le filet retiré rend trente-deux pixels : le surtitre tient sur une ligne
     sans descendre sous .64 rem, là où il fallait .605 avec lui. */
  .hero__kicker{font-size:.64rem;letter-spacing:.1em}
  .hero h1{font-size:min(10.4vw,2.5rem)}
  .hero__lead{font-size:.92rem;margin-bottom:.95rem}
}


/* ══════════════════════════════════ TABLETTE ════════════════════════════
   De 721 à 900 px : la composition du PC, à l'échelle de l'écran.

   Jusqu'ici, la borne « mobile » était à 900 px et toutes les tablettes en
   portrait — 744 pour l'iPad mini, 768, 810, 820, 834 — recevaient donc la
   version téléphone : menu burger, barre d'appel, héros recomposé sur une
   colonne. Ce n'est pas ce qu'on montre à un client sur son iPad. La borne
   est descendue à 720 (sous les 744 du plus petit iPad), et cette bande-ci
   rattrape ce qui ne tient pas à cette largeur.

   Le problème central est l'en-tête : logo, cinq liens, bouton d'appel et
   bouton de devis réclament 896 px là où il y en a 744. Mesuré, pas estimé.
   On ne retire rien — c'est justement ce qui distingue la version PC de la
   version téléphone — on resserre : gouttière, écart de l'en-tête, corps et
   rembourrage des liens, corps des boutons. Chaque valeur ci-dessous est le
   résultat d'une mesure, pas d'un choix.
   ---------------------------------------------------------------------- */
@media (min-width:721px) and (max-width:900px){

  /* ---- La gouttière et l'en-tête ------------------------------------- */
  :root{--gutter:1.15rem;--header-h:72px}
  .header__in{gap:.7rem}
  .logo img{height:40px}

  .nav__list{gap:0}
  .nav__link{padding:.55rem .42rem;font-size:.83rem;gap:.25rem}
  .nav__link::after{left:.42rem;right:.42rem}
  .nav__link svg{width:10px;height:10px}

  .header__cta{gap:.4rem}
  .header__tel{width:40px;height:40px}
  .header__tel svg{width:15px;height:15px}
  .header__cta .btn--primary{padding:.6rem .85rem;font-size:.85rem}

  /* La réglure qui sépare la navigation des boutons n'a plus la place. */
  .header__cta::before{display:none}

  /* ---- La barre du haut ----------------------------------------------
     Quatre mentions et une adresse électronique passaient sur deux lignes
     sous 800 px : la barre doublait de hauteur et repoussait tout. L'adresse
     s'en va — elle est dans le pied de page et sur /contact/ —, les autres
     se resserrent. */
  .topbar__in{flex-wrap:nowrap;gap:.9rem}
  .topbar__items{gap:.95rem;flex-wrap:nowrap}
  .topbar__mail{display:none}
  .topbar{font-size:.76rem}

  /* ---- Le héros d'accueil ---------------------------------------------
     La colonne de texte gagne six points sur la photo : à 744 px, le chapô
     tombait à quatre mots par ligne et les deux boutons s'empilaient. */
  .hero{--split:.66;--cut:11%}
  .hero h1{font-size:clamp(2.1rem,5.2vw,2.9rem)}
  .hero__kicker{font-size:.66rem;letter-spacing:.13em}
  .hero__lead{font-size:.93rem;line-height:1.6}
  .hero__actions{flex-wrap:nowrap}
  .hero__actions .btn{padding-inline:1rem;font-size:.9rem;white-space:nowrap}
  .hero__metiers{gap:.35rem}
  .hero__metiers a{padding:.4rem .7rem;font-size:.82rem}

  /* Le socle de réassurance : quatre mentions sur une ligne à 744 px, c'est
     186 px chacune. Le libellé passe avant le détail. */
  .hero__socle-i{padding-inline:.7rem;gap:.5rem}
  .hero__socle-i svg{width:17px;height:17px}
  .hero__socle-i b{font-size:.92rem;line-height:1.2}
  .hero__socle-i span span{font-size:.68rem;line-height:1.35}

  /* ---- Les héros de page intérieure ----------------------------------- */
  .phero h1{font-size:clamp(1.9rem,4.6vw,2.6rem)}
  .phero__in{max-width:min(30rem,58%)}
  .phero__lead{font-size:.95rem}
  .phero__actions .btn{padding-inline:1rem;font-size:.9rem}

  /* ---- Les filtres de /realisations/ ----------------------------------
     Cinq pastilles et le compte réclament 798 px pour 731 disponibles : la
     dernière passait à la ligne, seule, et le compte restait en haut à
     droite. On resserre plutôt que de replier — une rangée unique, c'est la
     composition du PC, et c'est ce qu'on est venu chercher ici. */
  .filter{padding:.5rem .8rem;font-size:.78rem}
  .filter b{font-size:.68rem;padding:.1rem .38rem}
  .filters{gap:.45rem}
  .filters__n{font-size:.76rem}

  /* ---- Le corps des pages ---------------------------------------------
     Les titres de section et les chapôs sont calibrés pour 1 320 px de
     conteneur ; ici il y en a 700. */
  .section-head h2,.ttl{font-size:clamp(1.7rem,4.4vw,2.4rem)}
  .lead{font-size:.97rem}
}

/* ---- Les tablettes étroites : 721 à 810 px -----------------------------
   À 834 px l'en-tête tient avec 56 px de reste ; à 744 il lui en manque 34.
   Ce n'est donc pas la bande entière qu'il faut resserrer, c'est son bas.
   Mesuré : logo 83 + navigation 479 + boutons 157 + écarts 22 = 741 pour un
   conteneur de 707. Les valeurs ci-dessous rendent 63 px. */
@media (min-width:721px) and (max-width:810px){
  .logo img{height:36px}
  .header__in{gap:.5rem}
  .nav__link{padding:.5rem .3rem;font-size:.78rem}
  .nav__link::after{left:.3rem;right:.3rem}
  .header__cta .btn--primary{padding:.55rem .7rem;font-size:.8rem}
  .topbar{font-size:.73rem}
  .topbar__items{gap:.75rem}

  /* Le libellé long du bouton de devis s'en va, comme sur téléphone : « Devis
     gratuit sous 48 h » réclame 210 px dans une colonne qui en offre 350 pour
     DEUX boutons. Le « sous 48 h » est redit trois lignes plus bas, dans le
     socle. */
  .only-lg{display:none}
  .hero__actions .btn{flex:1 1 0;min-width:0;justify-content:center}

  /* Le surtitre passait sur deux lignes : trente-sept signes espacés de .13em
     ne tiennent pas dans 310 px une fois le filet déduit. */
  .hero__kicker{font-size:.6rem;letter-spacing:.09em}

  /* Quatre mentions dans 704 px font 176 px chacune ; « Nancy &
     Meurthe-et-Moselle » en réclame 190 à .92 rem. */
  .hero__socle-i{padding-inline:.5rem;gap:.4rem}
  .hero__socle-i b{font-size:.84rem}
  .hero__socle-i span span{font-size:.64rem;line-height:1.3}

  /* Les filtres : même à .78 rem il manque une soixantaine de pixels pour
     tenir sur une rangée. Le compte des vues s'en va — il redit le chiffre
     que porte déjà la pastille active — mais reste lu par les lecteurs
     d'écran, car c'est une zone « aria-live ». */
  .filter{padding:.48rem .7rem;font-size:.75rem}
  .filters__n{
    position:absolute!important;width:1px;height:1px;
    padding:0;margin:-1px;overflow:hidden;
    clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0;
  }
}


/* ════════════════════════════════════════════════════ BANDEAU COOKIES ═══
   Une carte d'encre, discrète, en bas à gauche : elle ne recouvre ni le
   titre du héros ni le lanceur de l'assistant à droite. Sur téléphone elle
   se pose au-dessus de la barre d'appel, jamais dessous.

   Les deux boutons sont STRICTEMENT identiques. Un « Accepter » plus
   visible ferait monter le taux d'accord — et c'est exactement ce que la
   CNIL sanctionne. */
.cc{
  position:fixed;z-index:140;left:1.25rem;bottom:1.25rem;
  width:min(25rem,calc(100vw - 2.5rem));
  padding:1.1rem 1.2rem 1.15rem;border-radius:var(--r-md);
  background:var(--ink);color:#B9C4D6;border:1px solid var(--border-dark);
  box-shadow:0 24px 60px rgba(8,13,24,.4),0 4px 14px rgba(8,13,24,.25);
  font-family:var(--body);font-size:.86rem;line-height:1.52;
  animation:ccEntre .5s var(--ease-out) .4s backwards;
}
.cc__t{
  margin:0 0 .3rem;font-family:var(--display);font-weight:700;font-size:1.12rem;
  letter-spacing:.03em;text-transform:uppercase;color:#fff;
}
.cc__d{margin:0 0 .95rem}
.cc__d a{color:var(--blue-e);text-decoration:underline;text-underline-offset:2px;white-space:nowrap}
.cc__d a:hover{color:#fff}
.cc__b{display:grid;grid-template-columns:1fr 1fr;gap:.55rem}
.cc__btn{
  appearance:none;cursor:pointer;
  padding:.72rem .8rem;border-radius:var(--r-pill);
  border:1px solid rgba(255,255,255,.24);background:rgba(255,255,255,.07);
  font:600 .9rem/1 var(--body);color:#fff;
  transition:background-color .2s var(--ease-out),border-color .2s var(--ease-out);
}
.cc__btn:hover{background:var(--blue);border-color:var(--blue)}
.cc__btn:focus-visible{outline:3px solid var(--blue-e);outline-offset:2px}
@keyframes ccEntre{from{opacity:0;transform:translateY(14px)}}

/* Le bandeau et le lanceur de l'assistant se disputeraient le bas de
   l'écran : tant que le choix n'est pas fait, l'assistant attend. */
html.cc-ouvert .asst{display:none}

/* Sur téléphone : pleine largeur, au-dessus de la barre d'appel flottante
   (67 px de haut, posée à 9 px du bord). */
@media (max-width:900px){
  .cc{left:.6rem;right:.6rem;width:auto;bottom:calc(76px + .6rem + env(safe-area-inset-bottom))}
}

/* Le lien « Cookies » du pied de page est un bouton — il rouvre le bandeau,
   il ne mène nulle part — habillé comme ses voisins. */
.footer__cc{
  appearance:none;background:none;border:0;padding:0;cursor:pointer;
  font:inherit;color:inherit;transition:color .22s;
}
.footer__cc:hover{color:#fff}

@media (prefers-reduced-motion:reduce){.cc{animation:none}}
@media print{.cc{display:none}}
