/* == ADEXWEB - La seule source de style. `critique.css` et `differe.css`
      sont FABRIQUES depuis ce fichier par `tools/css-critique.mjs`.  D-820 == */

/* ===================================================================
   1 · LA PAGE
   =================================================================== */

.enveloppe {
  width: 100%;
  max-width: var(--page-max);
  margin-inline: auto;
  padding-inline: var(--gouttiere);
}

/* Une colonne de texte ne depasse jamais 68 signes : au-dela, l'oeil rate
   le retour a la ligne, et c'est le premier reflexe qui se degrade a 45 ans. */
.mesure { max-width: var(--colonne-texte); }
.mesure-courte { max-width: 34rem; }

/* Une bande = une section = UNE idee. Si elle a besoin de deux titres,
   c'est deux bandes.  D-821 */
.bande { padding-block: var(--bande); }
.bande--coupure { padding-block: var(--bande-coupure); }
.bande--silk { background: var(--silk); }
/* MARBRE N'EST PLUS UN FOND DE BANDE.  D-870
   #EEE5D9 et #E8E4E0 ne se distinguent pas cote a cote — deux beiges pour
   dire la meme chose, c'est un rythme qu'on croit poser et que personne ne
   percoit. Le marbre reste ce qu'il doit etre : des filets, des bordures,
   le fond d'une carte. Le rythme des bandes se fait sur DEUX etats,
   perle et silk, plus le navy pour ce qui compte. */
.bande--marble { background: var(--silk); }
.bande--navy { background: var(--navy-dark); color: var(--pearl); }
.bande--navy h1, .bande--navy h2, .bande--navy h3 { color: var(--pearl); }

/* Le filet est la seule separation entre deux bandes de meme fond. */
.bande + .bande:not([class*="--"]) { border-top: var(--filet) solid var(--line); }

/* ===================================================================
   2 · L'EN-TETE DE BANDE — sur-titre, titre, chapo. Toujours a gauche.
   =================================================================== */

.tete { margin-bottom: var(--e-5); }

/* Le sur-titre est le seul endroit ou le champagne touche du texte : il ne
   le PORTE pas, il le suit — le filet est champagne, les lettres restent
   lisibles.  D-822 */
.sur-titre {
  display: flex; align-items: center; gap: var(--e-2);
  font-size: var(--t-00);
  font-weight: 600;
  letter-spacing: var(--ls-etiquette);
  text-transform: uppercase;
  color: var(--text-soft);
  margin-bottom: var(--e-2);
}
.sur-titre::after {
  content: ""; flex: 0 0 3rem; height: 1px; background: var(--champagne-dark);
}
.bande--navy .sur-titre { color: var(--champagne-light); }
.bande--navy .sur-titre::after { background: var(--champagne); }

.titre-bande {
  font-size: var(--t-3);
  line-height: var(--lh-3);
  letter-spacing: var(--ls-3);
  max-width: 20ch;
}
.chapo {
  font-size: var(--t-1);
  line-height: var(--lh-1);
  letter-spacing: var(--ls-1);
  color: var(--text-soft);
  margin-top: var(--e-2);
  max-width: 46ch;
}
.bande--navy .chapo { color: var(--champagne-light); }

/* ===================================================================
   3 · LA BARRE DE NAVIGATION — la meme sur toutes les pages
   =================================================================== */

/* LA BARRE NE COLLE PLUS AU BORD, ELLE FLOTTE.  D-918
   Une barre pleine largeur posee sur le bord superieur est le gabarit par
   defaut de tout site : elle ne dit rien. Une pilule en verre qui flotte
   dit qu'on a decide quelque chose, et surtout elle permet au premier
   ecran de passer DESSOUS — sans quoi un hero sombre commence par un
   bandeau blanc de 72 px et le « boom » n'a pas lieu.
   Le fond n'est plus opaque mais il reste MESURABLE : voir D-916, le
   plancher d'alpha se calcule sur le pire fond, pas sur le fond moyen.
   L'objection de D-864 — « ca a l'air sale, comme une feuille imprimee
   deux fois » — visait 0,94 SANS flou. Le flou est ce qui change tout :
   ce qui passe dessous n'est plus lisible, donc plus confondable avec le
   texte de la barre. */
.barre {
  position: fixed; inset-inline: 0; top: 0; z-index: var(--z-nav);
  padding-block: var(--barre-marge);
  pointer-events: none;      /* la bande transparente ne bloque rien */
}
.barre-dedans {
  max-width: var(--page-max); margin-inline: auto;
  padding-inline: var(--gouttiere);
}
.barre-verre {
  pointer-events: auto;
  display: flex; align-items: center; gap: var(--e-2);
  min-height: var(--nav-h);
  padding: var(--e-1) var(--e-1) var(--e-1) var(--e-3);
  border-radius: var(--rayon-pilule);
  background: var(--verre-clair);
  -webkit-backdrop-filter: var(--verre-flou);
  backdrop-filter: var(--verre-flou);
  border: var(--filet) solid var(--verre-filet);
  box-shadow: var(--ombre-pose);
  transition: min-height var(--t-panneau) var(--m-courbe),
              background-color var(--t-etat), box-shadow var(--t-etat);
}
/* Une fois qu'on a quitte le haut, la pilule se resserre et s'appuie. Le
   geste est de 8 px de hauteur : c'est ce qui se voit sans qu'on se
   demande ce qui vient de bouger.  D-823
   ELLE PERD AUSSI SON FLOU, ET C'EST MESURE.  D-933
   Un `backdrop-filter` sur un element FIXE oblige le navigateur a
   recomposer le flou a chaque image du defilement. Releve a la molette,
   plancher de bruit a 60 i/s : 20 i/s medians sur le premier ecran avec
   `blur(20px) saturate(1.6)`, 60 sans. Or le flou ne sert qu'a UN
   moment — la pilule posee sur le premier ecran sombre, page immobile,
   quand on la regarde. Des qu'on defile, personne ne regarde le verre :
   on regarde ce qui monte. A 0,88 d'alpha, ce qui passe a travers vaut
   douze pour cent de l'image ; le rendre opaque a ce moment-la ne se
   remarque pas, et c'est verifie a l'image, pas deduit. */
.barre[data-detachee="oui"] .barre-verre {
  min-height: calc(var(--nav-h) - 0.5rem);
  background: var(--pearl);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  box-shadow: var(--ombre-flottante);
}

/* LA BARRE FLOTTE, DONC ELLE NE POUSSE PLUS RIEN : le contenu doit se
   pousser lui-meme. Une seule regle, sur `main`, pour les neuf pages —
   et l'accueil la reprend a son compte pour passer SOUS la barre. */
main { padding-top: var(--barre-espace); }

/* Le logotype se mesure en HAUTEUR, et sa largeur suit : a 40 px de haut il
   fait 187 px de large, et sur un ecran de 320 il ne restait plus rien pour
   le bouton et le menu — la barre debordait de 54 px et le site devenait
   innavigable. Il descend a 22 px sous 480.  D-846 */
/* Le lien du logotype ne faisait que 28 px de haut, sous le plancher de
   44 px : il etait la premiere cible de chaque page, et la plus difficile
   a viser au pouce.  D-850 */
.logo { display: flex; align-items: center; flex: 0 0 auto; text-decoration: none;
        min-width: 0; min-height: var(--cible-min); }
.logo img, .logo svg { height: 1.375rem; width: auto; }
@media (min-width: 30em) { .logo img, .logo svg { height: 1.625rem; } }
@media (min-width: 48em) { .logo img, .logo svg { height: 1.75rem; } }
.logo-mot {
  font-family: var(--font-texte);
  font-size: 1.0625rem; font-weight: 700;
  letter-spacing: 0.11em; text-transform: uppercase;
  color: var(--navy-dark);
}
.logo-mot i { font-style: normal; color: var(--champagne-dark); }

.nav-liens { display: none; align-items: center; gap: 0.125rem; margin-inline: auto; }
/* DEUX GROUPES SEPARES PAR UN FILET.  D-979
   Cinq liens a pas egal ne disent pas qu'ils repondent a deux questions
   differentes. Le filet fait 1 px sur 18 de haut : il separe sans peser, et
   il est en `--line-strong`, pas en champagne — un separateur ne porte
   aucune information, il n'a donc pas a etre lisible, mais il ne doit pas
   non plus attirer l'oeil plus qu'un lien. */
.nav-groupe { display: flex; align-items: center; gap: 0.125rem; }
.nav-filet {
  flex: 0 0 auto;
  width: 1px; height: 1.125rem;
  margin-inline: 0.5rem;
  background: var(--line-strong);
}
.nav-lien {
  display: inline-flex; align-items: center;
  min-height: var(--cible-min);
  padding: 0 var(--e-2);
  font-size: var(--t-00); font-weight: 600;
  color: var(--text-soft);
  text-decoration: none;
  border-radius: var(--rayon);
  /* UN LIBELLE DE NAVIGATION NE SE COUPE PAS EN DEUX. Sans ca, la barre
     « rentrait » — la sonde de debordement rendait 0 — parce que « Comment
     ca marche » se pliait sur deux lignes. La mesure disait oui, l'image
     disait non.  D-860 */
  white-space: nowrap;
  position: relative;
  transition: color var(--t-etat), background-color var(--t-etat);
}
.nav-lien:hover { color: var(--navy-dark); background: rgb(34 45 82 / 0.07); }
/* LE FILET QUI POUSSE SOUS LE MOT AU SURVOL.  D-979
   Un fond qui s'allume est un etat ; un trait qui POUSSE est un geste, et
   il dit dans quel sens on lit. Il part du centre pour ne pas donner une
   direction que le lien n'a pas. Il n'ajoute aucune information : la page
   courante garde son filet permanent ci-dessous, qui lui en porte une. */
@media (prefers-reduced-motion: no-preference) {
  .nav-lien::after {
    content: "";
    position: absolute; left: var(--e-2); right: var(--e-2); bottom: 0.5rem;
    height: 2px; border-radius: 2px;
    background: var(--champagne-dark);
    transform: scaleX(0);
    transition: transform var(--t-etat) var(--m-courbe);
  }
  .nav-lien:hover::after, .nav-lien:focus-visible::after { transform: scaleX(1); }
  .nav-lien[aria-current="page"]::after { content: none; }
}
/* La page courante est marquee par un filet champagne SOUS le mot, et par
   `aria-current` : la couleur seule ne dirait rien a qui ne la voit pas. */
.nav-lien[aria-current="page"] {
  color: var(--navy-dark);
  box-shadow: inset 0 -2px 0 var(--champagne-dark);
}

.barre-actes { display: flex; align-items: center; gap: var(--e-1); margin-left: auto; }

/* Sous 67em, aucun bouton ecrit ne tient dans la barre : les trois actions
   sont dans la barre de pouce, en bas, et dans le menu. Ce qui reste en
   haut : le logo et le menu.  D-847 · D-919 · D-992
   `.barre-appel` — l'icone de telephone, puis le numero ecrit — vivait ici.
   Elle est partie avec le numero : on ne donne plus un numero, on donne une
   heure. Ses trois regles auraient survecu a leur balise sans lever
   d'erreur, comme toute regle dont le selecteur disparait. */

/* LES TROIS SEUILS DE LA BARRE, ET CE QU'ILS COUTENT EN PIXELS.  D-918
   Mesure a 1 440 (colonne utile 1 248, remplissage de pilule 32) :
     logo 131 · cinq liens 542 + 16 de pas · trois boutons 474 + 16
     total 1 211, reserve 37.
   Le NUMERO ECRIT n'y entre pas — il coute 120 de plus. Il revient a
   103em, ou la reserve passe a 245. Il reste joignable partout ailleurs :
   l'icone dans la barre sous 62em, la barre de pouce, le menu, le pied et
   la page de contact. Un pixel de trop ne deborde pas, il PLIE (D-892) :
   ces trois seuils sont releves a l'image, pas calcules. */
.barre-actes .barre-estim,
.barre-actes .barre-appel-rdv,
.barre-actes .barre-projet { display: none; }

/* LE BUDGET DE PIXELS DE LA PILULE, RELEVE ET NON SUPPOSE.  D-918
   A 1 440 l'interieur de la pilule fait 1 222 px. Ce qu'il faut y mettre,
   mesure a l'element :
     logo 131 · cinq liens 560 · trois boutons 556 · deux pas 32 = 1 279.
   Cinquante-sept de trop, et un debordement d'en-tete NE SE VOIT PAS :
   il pousse le dernier bouton hors de l'ecran (D-849). Les 57 se
   reprennent la ou ils ne coutent aucune cible ni aucun mot :
     logo a 24 px de haut au lieu de 28 ...... 19
     pas des liens a 4 px au lieu de 6 ....... 20
     remplissage des boutons a 12 au lieu de 16  24
     pas entre les trois blocs a 12 .......... 8
     pas entre les boutons a 6 ............... 4
   Total 75, reserve 18. Toutes les cibles restent a 44 px de haut : elles
   viennent du `min-height`, jamais du remplissage. */
/* ENTRE 62 ET 90em, LA PILULE PREND UNE GOUTTIERE PLUS ETROITE QUE LE
   TEXTE.  D-918
   A 1 024 la gouttiere du site vaut 80 px de chaque cote : la pilule n'a
   plus que 830 px d'interieur pour 853 de contenu, et le seul bouton
   visible sort de l'ecran. A 32 px elle en a 926, soit 73 de reserve.
   Ce n'est PAS la faute que D-872 a corrigee : la barre y etait plus
   ETROITE que le contenu et son bord droit s'arretait avant le sien —
   un alignement rate se lit comme un defaut. Une pilule qui FLOTTE plus
   large que la colonne de lecture est une composition, pas un ratage :
   elle est detachee des quatre bords, elle ne s'aligne sur rien. Au-dela
   de 90em la colonne s'elargit a 1 408 et les deux se rejoignent. */
@media (min-width: 67em) and (max-width: 89.99em) {
  .barre-dedans { padding-inline: var(--e-4); }
}

/* LES QUATRE SEUILS DE LA BARRE, RELEVES A L'IMAGE.  D-979
   `tools/_entete-vue.mjs` compare chaque action au bord INTERIEUR de la
   pilule, sur 23 largeurs. Il fallait ca : un debordement d'en-tete ne
   parait dans AUCUN `scrollWidth` (D-849) — la pilule rogne, le dernier
   bouton sort du cadre, et rien ne le signale. L'outil precedent rendait
   « 0 pliage » pendant que « Demarrer un projet » etait coupe en deux a
   1 100 px. Deux de ces six rognages sont ANTERIEURS a ce tour : entre
   992 et 1 056 px, la barre pliait deja.
     67em  les cinq liens + « Demarrer un projet »  (112+555+279+64 = 1 010)
     74em  « Referer » entre                        (+108)
     84em  le numero s'ecrit au lieu de l'icone     (+125)
   Sous 67em : logo, appel, menu — et la barre de pouce en bas, qui suit
   le meme seuil pour qu'il n'existe jamais de bande sans action. */
@media (min-width: 67em) {
  .nav-liens { display: flex; }
  .barre-actes { margin-left: 0; gap: 0.375rem; }
  .nav-lien { padding: 0 0.25rem; }
  .nav-lien::after { left: 0.25rem; right: 0.25rem; }
  .nav-filet { margin-inline: 0.375rem; }
  .barre-actes .barre-projet { display: inline-flex; }
  .barre-estim, .barre-appel-rdv, .barre-projet { padding-inline: 0.75rem; }
  .barre-verre { gap: 0.75rem; padding-left: var(--e-2); }
  .barre-verre .logo img { height: 1.5rem; }
  /* La fleche du bouton principal : elle avance de 3 px au survol comme
     partout ailleurs, mais elle reste petite — la barre n'a pas la place
     d'un geste plus grand. */
  .barre-projet svg { width: 1rem; height: 1rem; margin-left: 0.125rem; }
}

/* LES DEUX SEUILS QUI RESTENT, ET CE QU'ILS COUTENT.  D-979
   Mesure a l'element, pas au calcul (D-918 : « un pixel de trop ne deborde
   pas, il PLIE »).
     a 1 247 : logo 112 · nav 540 · appel 44 · projet 201 = 897 + pas
     a 1 248 : l'appel passe a 169 (le numero ecrit), total 1 022
   « Referer » coute 96 de plus. Il entre des 68em, ou la colonne utile
   passe a 1 088 ; le numero ecrit, lui, attend 82em pour que les deux
   tiennent ensemble sans reprendre un pixel ailleurs. Sous 68em le
   parcours de reference reste dans le menu, dans la bande de l'accueil,
   dans les six portes et dans le pied — il n'est jamais perdu. */
/* 80em ET NON 74em, ET LE CHIFFRE VIENT DE L'IMAGE.  D-992
   `tools/_entete-vue.mjs` à 1 216 : le bord droit de « Démarrer un
   projet » tombe à 1 234 pour une pilule qui s'arrête à 1 184 — cinquante
   pixels dehors, et RIEN ne le signale (D-849 : un débordement d'en-tête
   n'apparaît dans aucun `scrollWidth`, la pilule rogne). À 1 280 il tient.
   L'ancien seuil de 74em était juste pour « Référer », qui coûte 96 px ;
   « Réserver un appel » en coûte 201. */
@media (min-width: 80em) {
  .barre-actes .barre-appel-rdv { display: inline-flex; }
}
/* ===================================================================
   LA BARRE NE REPETE PAS CE QUE LE HERO OFFRE DEJA.  D-961

   Le rôle « client » du banc a compté, sur un écran de 1440 : TREIZE
   actions sans défiler, dont « Estimation », « Réserver un appel » et
   « Démarrer un projet » DEUX FOIS — une fois dans la barre, une fois
   dans le hero, les deux visibles en même temps.

   Le hero les porte en grand, au centre, là où le regard va. La barre
   les redisait en petit, en haut. Deux fois la même chose n'est pas
   deux occasions de cliquer : c'est une hésitation de plus.

   La barre ne garde donc que « Démarrer un projet » — l'action
   principale, celle qui doit rester à portée quand on défile — et
   elle gagne LE NUMÉRO DE TÉLÉPHONE, qui n'était visible que sur
   téléphone. Le même banc l'avait relevé : dix liens `tel:` sur la
   page, aucun visible en arrivant. Pour un patron de garage qui veut
   juste appeler, c'était un geste de trop.
   CE RAISONNEMENT TIENT ENCORE, ET SA CONCLUSION A CHANGÉ.  D-992
   Le numéro est sorti du site : on ne donne plus un numéro, on donne une
   HEURE. Ce que la barre gagne à sa place est « Réserver un appel » — la
   même intention, sans la sonnerie à laquelle personne ne répond.

   TROIS ACTIONS, TROIS SEUILS, ET AUCUNE NE DISPARAÎT JAMAIS.
   « Démarrer un projet » ouvre `modal-start`, qui pose les trois côte à
   côte avec la phrase qui les distingue : sous 74em la barre n'en montre
   qu'une, mais elle en ouvre trois. Sous 67em c'est la barre de pouce qui
   les porte toutes les trois, en bas, sous le pouce.

   ET « ESTIMATION » NE PARAÎT PAS DANS LA BARRE. Ce n'est pas un oubli,
   c'est une MESURE. À l'image, sur 23 largeurs :
     logo 112 · nav 616 · trois boutons 582 · deux pas 24 = 1 334
   pour une pilule dont l'intérieur vaut 1 260 — et il les vaut à 1 440
   comme à 1 920, parce que la colonne est PLAFONNÉE à 1 408 px. Les
   soixante-quatorze pixels de trop ne s'en vont donc jamais : élargir
   l'écran ne les reprend pas. `_entete-vue.mjs` a relevé le rognage à
   1 920, 1 700, 1 600 ET 1 440, toujours du même montant.

   Reprendre ces pixels ailleurs, on l'a déjà fait deux fois (D-918,
   D-979) : le logo est à 24 px, le pas des liens à 4, le remplissage
   des boutons à 12. Il n'y a plus rien à reprendre qui ne coûte une
   cible ou un mot.

   « Estimation » vit donc à UN clic, et à quatre endroits : dans
   `modal-start` que le bouton principal ouvre — côte à côte avec les
   deux autres et avec la phrase qui les distingue, ce qui se lit mieux
   que trois boutons serrés —, dans le menu, dans la barre de pouce sur
   téléphone, et dans les six portes au bas de chaque page.

   LES SEUILS SONT RELEVÉS À L'IMAGE, PAS CALCULÉS — `tools/_entete-vue.mjs`
   compare le bord droit de chaque action au bord INTÉRIEUR de la pilule
   sur 23 largeurs, parce qu'un débordement d'en-tête ne paraît dans AUCUN
   `scrollWidth` (D-849) : la pilule rogne, et rien ne le signale.
   =================================================================== */

/* ===================================================================
   3.1 · LA BARRE DE POUCE — les trois actions sur telephone  D-919
   Elle n'existe que sous 62em, ou la barre du haut ne peut rien porter.
   Elle est POSEE, jamais flottante au-dessus du texte : un fond plein,
   un filet en haut, et la page reserve sa hauteur en bas — sans quoi
   elle mange la derniere ligne du pied.
   =================================================================== */

.pouce {
  position: fixed; inset-inline: 0; bottom: 0; z-index: var(--z-nav);
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: var(--e-1);
  padding: var(--e-1) var(--e-2) calc(var(--e-1) + env(safe-area-inset-bottom, 0px));
  background: var(--verre-clair-appui);
  -webkit-backdrop-filter: var(--verre-flou);
  backdrop-filter: var(--verre-flou);
  border-top: var(--filet) solid var(--line);
  box-shadow: 0 -8px 24px -12px rgb(24 33 61 / 0.24);
}
.pouce[hidden] { display: none; }
@media (min-width: 67em) { .pouce { display: none; } }

.pouce-acte {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 0.125rem;
  min-height: var(--cible); padding: var(--e-1) 0.25rem;
  border-radius: var(--rayon-large);
  font-size: 0.8125rem; font-weight: 600; line-height: 1.2;
  color: var(--navy-dark); text-decoration: none; text-align: center;
  background: transparent;
  transition: background-color var(--t-vif), transform var(--t-vif);
}
.pouce-acte svg { width: 1.25rem; height: 1.25rem; color: var(--navy); }
.pouce-acte:active { transform: scale(0.96); }
.pouce-acte--fort { background: var(--navy); color: var(--pearl); }
.pouce-acte--fort svg { color: var(--champagne); }
.pouce-acte--fort:active { background: var(--navy-dark); }

/* LE MOUVEMENT D'ARRIVEE de la barre de pouce : elle monte, elle ne se
   fond pas — trois actions a opacite 0 seraient trois actions absentes
   si le verdict se perdait (D-905). */
@media (prefers-reduced-motion: no-preference) {
  html.js .pouce { transform: translateY(100%); transition: transform var(--t-panneau) var(--m-courbe); }
  html.js .pouce[data-pouce-vu] { transform: none; }
}

/* Les actions du menu plein ecran : une colonne de cibles de 56 px, sous
   les liens de navigation et au-dessus du bouton d'appel. */
.menu-actes { margin-top: var(--e-5); display: grid; gap: 0; }
.menu-actes-t {
  font-size: var(--t-00); font-weight: 700;
  letter-spacing: var(--ls-etiquette); text-transform: uppercase;
  color: var(--text-soft);
  margin-bottom: var(--e-1);
}
/* CHAQUE ROUTE DIT CE QU'ELLE EST, SOUS SON NOM.  D-979
   « Demarrer un projet », « Estimation », « Reserver un appel » : trois
   libelles qui se ressemblent pour qui ne connait pas encore la maison.
   La ligne du dessous les separe en un coup d'oeil. Elle est en grille a
   deux colonnes pour que le second texte s'aligne sous le premier et non
   sous l'icone. */
.menu-acte {
  display: grid; align-items: center;
  grid-template-columns: 1.25rem 1fr;
  gap: 0.125rem var(--e-2);
  min-height: var(--cible); padding-block: var(--e-2);
  font-size: var(--t-0); font-weight: 600;
  color: var(--navy-dark); text-decoration: none; text-align: left;
  border-bottom: var(--filet) solid var(--line);
}
.menu-acte svg { width: 1.25rem; height: 1.25rem; flex: 0 0 auto; color: var(--navy); }
.menu-acte small {
  grid-column: 2;
  font-size: var(--t-00); font-weight: 400; line-height: 1.4;
  color: var(--text-soft);
}
/* La route qu'on veut qu'il prenne, marquee par un filet champagne a
   gauche — pas par une couleur de texte : la couleur seule ne dit rien a
   qui ne la voit pas, et le mot suffit deja. */
.menu-acte--fort {
  padding-left: var(--e-2);
  margin-left: calc(var(--e-2) * -1);
  border-left: 3px solid var(--champagne-dark);
}

/* Le bouton du menu ne parait que sous 62em, ou les liens sont caches. */
.menu-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--e-1);
  width: var(--cible-min); height: var(--cible-min);
  border-radius: var(--rayon);
  color: var(--navy-dark);
}
.menu-btn:hover { background: var(--marble); }
/* Le burger suit le MEME seuil que les liens : entre 62 et 67em il
   disparaissait alors que la nav n'etait pas encore la — la barre n'avait
   plus AUCUNE porte, ni menu ni bouton.  D-979 */
@media (min-width: 67em) { .menu-btn { display: none; } }

/* Le menu plein ecran : une colonne, des cibles de 56 px, rien d'autre. */
.menu {
  position: fixed; inset: 0; z-index: var(--z-menu);
  background: var(--pearl);
  display: flex; flex-direction: column;
  padding: var(--e-3) var(--gouttiere) var(--e-7);
  overflow-y: auto;
}
.menu[hidden] { display: none; }
.menu-tete { display: flex; align-items: center; justify-content: space-between; height: var(--nav-h); }
.menu-liste { margin-top: var(--e-4); display: flex; flex-direction: column; }
.menu-liste a {
  display: flex; align-items: center;
  min-height: var(--cible); padding-block: var(--e-1);
  font-family: var(--font-titre);
  font-size: var(--t-2); line-height: var(--lh-2); letter-spacing: var(--ls-2);
  color: var(--navy-dark); text-decoration: none;
  border-bottom: var(--filet) solid var(--line);
}
/* `.menu-pied` portait le numero en gros au bas du menu.  D-992 */

/* ===================================================================
   4 · LES BOUTONS — trois voix, jamais quatre
   =================================================================== */

.btn {
  position: relative; overflow: hidden;   /* le reflet ne sort pas du bouton */
  display: inline-flex; align-items: center; justify-content: center; gap: var(--e-1);
  min-height: var(--cible);
  padding: 0 var(--e-4);
  border-radius: var(--rayon-pilule);
  font-size: var(--t-00); font-weight: 600; letter-spacing: 0.01em;
  text-decoration: none; text-align: center;
  /* Un libelle de bouton ne se casse pas en deux : « Reserver un / appel »
     dans la barre lui donnait deux hauteurs de ligne et le desalignait de
     tout le reste. MAIS PAS SUR TELEPHONE : a 320 px, un libelle long en
     non-retour poussait la page de 87 px hors de l'ecran. Le non-retour
     est un confort de bureau, pas une regle.  D-875 */
  white-space: normal;
  transition: background-color var(--t-etat), color var(--t-etat),
              border-color var(--t-etat), transform var(--t-vif),
              box-shadow var(--t-etat);
}
.btn svg { position: relative; width: 1.125rem; height: 1.125rem; flex: 0 0 auto;
           transition: transform var(--t-etat) var(--m-courbe); }
.btn:hover svg { transform: translateX(3px); }

/* LE REFLET — le « verre liquide », et ce qu'il coute.  D-920
   Une bande claire inclinee traverse le bouton en 620 ms au survol. Elle
   ne porte AUCUNE information : c'est du plaisir, et la seule question
   qui vaut est ce qu'elle coute. Elle coute une couche composee, sur un
   pseudo-element deja peint, animee par `transform` seul — donc rien au
   fil principal. Elle ne se declenche ni au chargement ni au defilement.
   Le tact l'obtient aussi : `:active` la joue en 300 ms. Notre public
   est sur telephone, et un effet reserve au survol n'existe pas pour lui. */
.btn::after {
  content: ""; position: absolute; inset: 0;
  border-radius: inherit;
  background: linear-gradient(105deg,
              transparent 38%,
              rgb(253 255 255 / 0.30) 48%,
              rgb(253 255 255 / 0.42) 52%,
              transparent 62%);
  transform: translateX(-130%);
  pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
  .btn:hover::after  { animation: reflet 620ms var(--m-courbe); }
  .btn:active::after { animation: reflet 300ms var(--m-courbe); }
}
@keyframes reflet {
  from { transform: translateX(-130%); }
  to   { transform: translateX(130%); }
}
/* Le reflet clair ne se voit pas sur un bouton clair : sur les deux voix
   claires, il s'assombrit au lieu de s'eclaircir. */
.btn--second::after, .btn--verre::after {
  background: linear-gradient(105deg,
              transparent 38%,
              rgb(34 45 82 / 0.07) 48%,
              rgb(34 45 82 / 0.10) 52%,
              transparent 62%);
}
.btn--nu { overflow: visible; }
.btn--nu::after { content: none; }

/* Un seul bouton primaire par ecran. C'est la regle, pas une preference. */
.btn--primaire {
  background: var(--navy); color: var(--pearl);
  box-shadow: var(--ombre-pose);
}
.btn--primaire:hover { background: var(--navy-dark); box-shadow: var(--ombre-levee); }
.btn--primaire:active { transform: translateY(1px); box-shadow: var(--ombre-pose); }

/* LA SECONDE VOIX EST UNE PILULE BLANCHE : SON CONTOUR EST TOUT CE
   QU'ELLE A.  D-981
   `--line-strong` #C9C2BA sur perle rend 1,76:1, et 1,41:1 sur silk. Le
   fond, lui, est le MEME que la page : un bouton second n'avait donc,
   litteralement, aucun bord mesurable. `--navy-light` rend 9,48:1 sur
   perle et 7,26:1 sur silk — c'est la meme famille de couleur, ce n'est
   pas une voix de plus, et c'est ce qui fait qu'on voit qu'on peut
   cliquer. Le survol descend d'un cran vers `--navy-dark` plutot que de
   monter : la difference entre repos et survol reste lisible. */
.btn--second {
  background: var(--pearl); color: var(--navy-dark);
  border: var(--filet) solid var(--navy-light);
}
.btn--second:hover { border-color: var(--navy-dark); background: var(--marble); }

/* LE CHAMPAGNE COMME FOND, ET LA MESURE QUI L'AUTORISE.  D-979
   La regle du projet dit : le champagne ne porte NI TEXTE NI INFORMATION.
   Elle vise le champagne EN AVANT-PLAN, ou le plus fonce plafonne a 2,63:1
   sur perle. Ici il est DERRIERE : `--navy-dark` #18213D sur `--champagne`
   #D2B68A rend 8,47:1, et 6,23:1 au survol sur `--champagne-dark`. C'est le
   meme couple que `.bande--navy .btn--primaire` (ligne 515), qui existe
   depuis le debut — ce n'est pas une voix de plus, c'est la voix primaire
   quand le fond ne peut pas porter du navy.
   Elle sert dans la pilule de l'en-tete : un bouton navy y disparaissait
   sur le hero navy, et « demarrer un projet » est la seule action qu'on
   veut voir de loin. `node tools/palette-check.mjs` tient les chiffres. */
/* LE CONTOUR N'EST PAS UNE DECORATION, C'EST CE QUI FAIT LA PILULE.  D-981
   Champagne #D2B68A sur perle #FDFFFF rend 1,94:1 : sur les pages
   claires, la pilule de l'en-tete n'avait pas de bord et se lisait comme
   une tache. Son TEXTE tient 8,16:1 — c'est pour ca qu'aucun outil de
   contraste ne s'en plaignait. `--navy-light` en contour rend 9,48:1 sur
   perle, et le fond champagne tient deja 4,32:1 quand la barre passe sur
   le hero navy : le composant a un bord sur les deux fonds.
   `node tools/bord-check.mjs`. */
.btn--accent {
  background: var(--champagne); color: var(--navy-dark);
  border: var(--filet) solid var(--navy-light);
  box-shadow: var(--ombre-pose);
}
.btn--accent:hover { background: var(--champagne-dark); border-color: var(--navy-dark); box-shadow: var(--ombre-levee); }
.btn--accent:active { transform: translateY(1px); box-shadow: var(--ombre-pose); }
.btn--accent svg { color: var(--navy-dark); }
/* Le reflet de `.btn` est clair : sur du champagne il ne se voit pas. */
.btn--accent::after {
  background: linear-gradient(100deg,
              transparent 38%,
              rgb(24 33 61 / 0.08) 48%,
              rgb(24 33 61 / 0.12) 52%,
              transparent 62%);
}

/* LA QUATRIEME VOIX N'EN EST PAS UNE : c'est la SECONDE, posee sur du
   verre.  D-916
   « Trois voix, jamais quatre » tient toujours — `--verre` ne change ni le
   rang, ni le poids, ni la taille du bouton second. Il change son fond,
   parce qu'un fond perle plein dans une pilule en verre y dessine un
   rectangle blanc. Elle ne s'emploie QUE dans la barre et sur un panneau
   de verre ; ailleurs c'est `.btn--second`. */
.btn--verre {
  background: rgb(34 45 82 / 0.06); color: var(--navy-dark);
  border: var(--filet) solid rgb(34 45 82 / 0.14);
}
.btn--verre:hover { background: rgb(34 45 82 / 0.11); border-color: rgb(34 45 82 / 0.26); }
.btn--verre:active { transform: translateY(1px); }

/* La meme voix, sur du navy plein. Le fond compose rend #2C3760 et le
   perle y tient 12,9:1 — mesure, pas suppose. */
.btn--verre-fonce {
  background: rgb(253 255 255 / 0.09); color: var(--pearl);
  border: var(--filet) solid rgb(253 255 255 / 0.26);
}
.btn--verre-fonce:hover { background: rgb(253 255 255 / 0.16); border-color: rgb(253 255 255 / 0.50); }
.btn--verre-fonce:active { transform: translateY(1px); }
.btn--verre-fonce svg { color: var(--champagne); }

/* LE GRAND PRIMAIRE — un seul par page, celui du premier ecran. 56 px de
   haut c'est la taille d'un bouton de formulaire ; le premier bouton d'un
   site a 100 000 $ ne fait pas la meme taille qu'un champ. */
.btn--grand {
  min-height: 4rem; padding-inline: var(--e-5);
  font-size: var(--t-0);
}
.btn--grand svg { width: 1.25rem; height: 1.25rem; }

/* Le troisieme n'est pas un bouton, c'est un lien qui se comporte en bouton :
   il ne doit jamais entrer en concurrence avec le primaire. */
.btn--nu {
  padding-inline: var(--e-1); min-height: var(--cible-min);
  color: var(--navy-dark);
  text-decoration: underline; text-decoration-color: var(--champagne-dark);
  text-decoration-thickness: 2px; text-underline-offset: 0.3em;
}
.btn--nu:hover { text-decoration-color: var(--navy); }

.btn--large { width: 100%; white-space: normal; }
@media (min-width: 48em) {
  .btn:not(.btn--large) { white-space: nowrap; }
}
.actes { display: flex; flex-wrap: wrap; gap: var(--e-2); align-items: center; }

/* LE HERO EST UN FOND NAVY QUI NE PORTE PAS LA CLASSE `.bande--navy`.
   D-981
   La regle ci-dessous existe depuis le debut et elle n'a JAMAIS atteint le
   premier bouton du site : le hero porte `.hero`, pas `.bande--navy`.
   « Demarrer un projet » y etait donc `--navy` #222D52 pose sur
   `--navy-dark` #18213D — 1,18:1 de BORD. WCAG 1.4.11 demande 3:1 pour le
   contour d'un composant : a 1,18 il n'y a pas de contour, et seul le
   texte blanc separait le bouton de la page.
   POURQUOI AUCUN OUTIL NE L'AVAIT VU : `contraste-min.mjs` et
   `contraste-arret.mjs` mesurent la couleur du TEXTE sur son fond. Le
   texte, lui, tenait 13,37:1. Un bouton peut donc etre parfaitement
   lisible et parfaitement invisible. C'est une mesure de BORD, et elle
   n'existait nulle part — `node tools/bord-check.mjs` la tient
   maintenant, sur les neuf pages.
   `--navy-dark` sur `--champagne` rend 8,47:1 de texte et 4,32:1 de bord
   sur le fond du hero. */
.bande--navy .btn--primaire,
.hero .btn--primaire,
.pied .btn--primaire { background: var(--champagne); color: var(--navy-dark); }
.bande--navy .btn--primaire:hover,
.hero .btn--primaire:hover,
.pied .btn--primaire:hover { background: var(--champagne-light); }
/* LE PIED PORTAIT LE MEME DEFAUT, SUR LES NEUF PAGES.  D-981
   Il est en `--navy-dark` et il n'a pas non plus la classe
   `.bande--navy` : « Reserver un appel » y etait navy sur navy fonce,
   1,18:1, du premier au dernier ecran du site. C'est le dernier bouton
   que voit un visiteur qui a tout lu. */
/* Le reflet de `.btn` est CLAIR : sur du champagne il ne se voit pas. Le
   meme arbitrage que `.btn--accent`, au meme endroit que sa cause. */
/* LE CADRE DE LA VISITE 360 EST CLAIR, MEME DANS UNE BANDE NAVY.  D-981
   `.visite360` porte `.bande--navy`, donc son bouton primaire passe au
   champagne — sauf que CELUI-LA vit a l'interieur de `.tour-cadre`, dont
   le fond est `--silk`. Champagne sur silk : 1,56:1. La regle du fond
   fonce ne suit pas le bouton dans une boite claire ; on la reprend. */
.bande--navy .tour-cadre .btn--primaire { background: var(--navy); color: var(--pearl); }
.bande--navy .tour-cadre .btn--primaire:hover { background: var(--navy-dark); }
.bande--navy .tour-cadre .btn--primaire::after {
  background: linear-gradient(105deg,
              transparent 38%,
              rgb(253 255 255 / 0.30) 48%,
              rgb(253 255 255 / 0.42) 52%,
              transparent 62%);
}

.bande--navy .btn--primaire::after,
.hero .btn--primaire::after,
.pied .btn--primaire::after {
  background: linear-gradient(100deg,
              transparent 38%,
              rgb(24 33 61 / 0.08) 48%,
              rgb(24 33 61 / 0.12) 52%,
              transparent 62%);
}
.bande--navy .btn--second { background: transparent; color: var(--pearl); border-color: rgb(253 255 255 / 0.34); }
.bande--navy .btn--second:hover { background: rgb(253 255 255 / 0.08); border-color: var(--pearl); }

/* ===================================================================
   5 · L'ACCUEIL — LE PREMIER ECRAN
   Un fond navy plein, un mur de douze premiers ecrans qui derive, un
   titre qui NOMME le produit, trois actions.  D-921
   =================================================================== */

/* LE HERO PASSE SOUS LA BARRE. `main` se pousse de la hauteur de la barre
   flottante (D-918) ; le hero reprend ces pixels et les remet dans son
   propre remplissage. Resultat : le fond sombre commence au bord haut de
   l'ecran et la pilule en verre flotte dessus. Aucun decalage de mise en
   page : les deux valeurs sont statiques, le CLS reste a 0. */
.hero {
  position: relative; isolation: isolate;
  margin-top: calc(-1 * var(--barre-espace));
  padding-top: calc(var(--barre-espace) + var(--e-6));
  padding-bottom: var(--e-6);
  background: var(--navy-dark);
  color: var(--pearl);
  overflow: hidden;
}
/* LE PREMIER ECRAN TIENT DANS LE PREMIER ECRAN.  D-921
   Premiere mesure a 1 440 x 900 : le hero pesait 1 186 px. Les trois
   promesses tombaient a 966 et le lien de descente a 1 078 — sous la
   ligne de flottaison tous les deux. Un premier ecran qui deborde du
   premier ecran n'est pas un premier ecran.
   Trois causes, dans l'ordre de ce qu'elles coutaient : les trois boutons
   sur TROIS rangs (144 px, la colonne de texte etait a 50 % et n'en
   tenait qu'un), le titre a 92 px sur trois lignes, et deux coussins de
   64. Mesure apres : 878. */
@media (min-width: 62em) {
  .hero {
    min-height: 100svh;
    display: flex; flex-direction: column; justify-content: center;
    padding-top: calc(var(--barre-espace) + var(--e-6));
    padding-bottom: var(--e-6);
  }
}

/* LE MUR — douze premiers ecrans de metier, qui derivent.  D-921
   Il ne porte AUCUN texte : c'est ce qui permet de le poser sur une image
   sans avoir a mesurer un contraste qui ne se mesure pas. Le texte, lui,
   vit sur le navy PLEIN, a gauche, sans rien derriere.
   Sur telephone c'est une seule bande horizontale sous le texte ; a partir
   de 62em, deux colonnes verticales dans la moitie droite. */
.hero-mur { position: relative; margin-top: var(--e-6); }
.hero-mur-colonne { overflow: hidden; }
.hero-mur-piste { display: flex; gap: var(--e-2); width: max-content; }
.hero-mur-piste img {
  width: 15rem; height: auto; flex: 0 0 auto;
  border-radius: var(--rayon-large);
  border: var(--filet) solid rgb(253 255 255 / 0.10);
  /* Les captures sont claires : posees telles quelles sur du navy elles
     deviennent douze rectangles blancs qui hurlent plus fort que le
     titre. Elles reculent d'un cran — assez pour qu'on VOIE que ce sont
     des sites, pas assez pour concurrencer ce qu'on lit. */
  opacity: 0.62;
}
.hero-mur-colonne[data-mur="2"] { display: none; }

/* LA BANDE SE DISSOUT DANS LE FOND A SES DEUX BOUTS — PAR-DESSUS, PAS
   PAR UN MASQUE.  D-933
   Un masque etait le geste evident, et il coutait : un element ANIME sous
   un masque doit etre recompose avec lui a chaque image. Releve a la
   molette sur le premier ecran, plancher de bruit a 60 i/s : 8 images sur
   38 au-dessus de 20 ms avec les deux masques, 0 sans.
   Le fond du hero est un navy PLEIN et uni. Un degrade de ce meme navy
   peint AU-DESSUS des captures rend donc exactement la meme image qu'un
   masque — et c'est une peinture, faite une fois, pas une composition
   refaite soixante fois par seconde. La couleur est ecrite en `rgb(… / 0)`
   et non `transparent` : `transparent` vaut noir transparent, et
   l'interpolation vers lui salit le milieu du degrade d'un voile gris. */
.hero-mur::before, .hero-mur::after {
  content: ""; position: absolute; inset: 0;
  z-index: 1; pointer-events: none;
}
.hero-mur::before {
  background: linear-gradient(to right,
              var(--navy-dark) 0%, rgb(24 33 61 / 0) 8%,
              rgb(24 33 61 / 0) 92%, var(--navy-dark) 100%);
}
.hero-mur::after { display: none; }

@media (prefers-reduced-motion: no-preference) {
  /* 64 s pour un tour : c'est LENT, et c'est voulu. A 30 s le mur tire
     l'oeil hors du titre — verifie a l'image. Une derive qu'on remarque
     sans la regarder est exactement ce qu'on cherche.
     `translate3d` et rien d'autre : aucune propriete de mise en page
     n'est animee, la composition reste sur le fil du compositeur. */
  .hero-mur-piste { animation: derive-x 64s linear infinite; }
  .hero-mur-colonne[data-mur="2"] .hero-mur-piste { animation-direction: reverse; }
  .hero:hover .hero-mur-piste { animation-play-state: paused; }

  /* LE MUR NE DERIVE PAS PENDANT QU'ON DEFILE.  D-933
     Mesure a la molette, plancher de bruit a 60 i/s : le premier ecran
     rendait 30 i/s medians et 21 images sur 25 au-dessus de 20 ms. Deux
     causes, mesurees separement : le `backdrop-filter` de la barre
     flottante (30 -> 60 en le retirant) et la derive du mur (21 -> 15,
     puis 3 en retirant les deux). Le flou de la barre est ce qui permet
     au premier ecran sombre de passer dessous : il reste.
     La derive, elle, n'a rien a faire pendant un defilement — l'ecran
     porte deja UN mouvement, celui du doigt, et « si un ecran contient
     deux choses importantes, il en contient une de trop ». La pause est
     donc un choix de composition autant qu'une mesure. */
  html[data-defile] .hero-mur-piste { animation-play-state: paused; }
}
/* La piste porte ses six ecrans DEUX fois : a -50 % elle est exactement
   superposee a elle-meme, donc la boucle ne saute pas. */
@keyframes derive-x {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-50%, 0, 0); }
}
@keyframes derive-y {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(0, -50%, 0); }
}

@media (min-width: 62em) {
  .hero-mur {
    position: absolute; inset: 0 0 0 auto;
    /* 42 % et non 46 : a 46 le mur commence a 778 px et la troisieme
       promesse se termine a 800. Quarante-deux pixels de texte poses sur
       une image — le fondu du masque les rend presque noirs, mais
       « presque » n'est pas une mesure de contraste. A 42 % le mur
       commence a 835, soit 15 px apres la fin du texte. */
    /* PLAFONNE A 640 px, ET C'EST ENCORE LE LCP QUI LE DEMANDE.  D-926
       A 1 920, 42 % rendent 806 px : chaque capture est peinte a 391 x 246,
       soit 96 000 px², et redevient le plus grand element de la page
       devant le titre (63 000). Le navigateur horodatait alors le LCP a
       l'arrivee d'une image decorative. A 640 px de mur, la capture pese
       300 x 188 et le titre reprend le premier rang a toutes les largeurs. */
    width: min(42%, 640px); margin-top: 0;
    display: grid; grid-template-columns: 1fr 1fr; gap: var(--e-3);
    padding-block: 0;
  }
  /* Les deux fondus du bureau, en peinture eux aussi : le gauche, qui
     rencontre la colonne de texte, et le haut/bas qui passe sous la
     barre et sous le bord de l'ecran. */
  .hero-mur::before {
    background: linear-gradient(to left,
                rgb(24 33 61 / 0) 62%, var(--navy-dark) 100%);
  }
  .hero-mur::after {
    display: block;
    background: linear-gradient(to bottom,
                var(--navy-dark) 0%, rgb(24 33 61 / 0) 15%,
                rgb(24 33 61 / 0) 85%, var(--navy-dark) 100%);
  }
  .hero-mur-colonne[data-mur="2"] { display: block; }
  .hero-mur-colonne { display: flex; align-items: flex-start; }
  .hero-mur-piste {
    flex-direction: column; width: 100%; height: max-content;
    gap: var(--e-3);
  }
  .hero-mur-piste img { width: 100%; }
  /* La seconde colonne demarre a mi-hauteur : deux colonnes alignees se
     lisent comme un tableau, decalees elles se lisent comme un mur. */
  .hero-mur-colonne[data-mur="2"] .hero-mur-piste { margin-top: -6rem; }
  @media (prefers-reduced-motion: no-preference) {
    .hero-mur-piste { animation: derive-y 78s linear infinite; }
  }
}

.hero-dedans { position: relative; z-index: 1; }
/* 58 % et non 50 : a 50 les trois boutons tombaient sur TROIS rangs et
   poussaient les promesses et le lien de descente sous la ligne de
   flottaison. Mesure a 1 440 : les trois pesent 710 px, la colonne en
   rend 724.  D-921 */
@media (min-width: 62em) { .hero-dit { max-width: 58%; } }

/* LE TITRE. 60 px etait la taille d'un titre pose sur du blanc au milieu
   d'une page ; sur un premier ecran de 900 px de haut c'est un sous-titre.
   Il monte a 76 au-dela de 62em et a 92 au-dela de 90em — releve a
   l'image contre cuberto.com, qui tient 96 px a 1 440.  D-921 */
.hero-titre {
  font-size: var(--t-5);
  line-height: 1.02;
  letter-spacing: -0.024em;
  font-weight: 440;
  color: var(--pearl);
  max-width: 18ch;
}
.hero-titre em { color: var(--champagne-light); }
/* 86 PX ET NON 80, ET C'EST UNE MESURE DE LCP AVANT D'ETRE UN GOUT.  D-926
   Le plus grand element peint du premier ecran etait une capture du mur,
   290 x 183 = 53 000 px². Le navigateur horodatait donc le LCP a
   l'arrivee d'une image DECORATIVE, a 356 ms, pour un seuil de 400.
   A 86 px la plus longue ligne du titre pese 688 x 88 = 60 500 px² : le
   titre redevient le plus grand element, et il est peint des la premiere
   passe. Le LCP retombe a l'ordre du FCP.
   688 tient dans les 724 de la colonne — la marge est de 36 px, elle a
   ete relevee a l'element, pas estimee. */
@media (min-width: 62em) { .hero-titre { font-size: 4.25rem; } }
@media (min-width: 90em) { .hero-titre { font-size: 5.375rem; } }

/* LA LEVEE — la seule facon de lever un texte sans passer par l'opacite.
   D-917 · D-905
   La boite rogne, l'enfant monte de 110 % de SA hauteur. Le repos est la
   forme FINALE : sans script, les trois lignes sont en place et lisibles.
   Le script pose `data-lever-pret` juste avant d'observer, exactement
   comme `.entre` — un observateur qui ne rend jamais son verdict laisse
   donc un titre visible, pas un titre absent. Le filet de 2 s de
   `site.js` le libere de toute facon. */
.lever { display: block; overflow: hidden; padding-bottom: 0.06em; }
.lever > span { display: block; }

/* LE TITRE DU PREMIER ECRAN NE SE ROGNE PAS.  D-921
   Une ligne rognee est une ligne NON PEINTE : le navigateur horodate alors
   le LCP a la fin de la levee, et le seuil du projet est 400 ms. Ailleurs
   dans la page le LCP est deja acquis et le rognage ne coute rien. Ici, la
   levee se fait sans boite qui rogne, de 28 px, a opacite 1 tout du long —
   le titre est peint des la premiere passe. */
.hero-titre .lever { overflow: visible; }
@media (prefers-reduced-motion: no-preference) {
  html.js .hero-titre[data-lever-pret] .lever > span { transform: translateY(28px); }
}
@media (prefers-reduced-motion: no-preference) {
  html.js [data-lever-pret] .lever > span { transform: translateY(110%); }
  html.js [data-lever-pret][data-vu] .lever > span {
    transform: none;
    transition: transform var(--m-lever) var(--m-courbe);
  }
  html.js [data-lever-pret][data-vu] .lever:nth-child(2) > span { transition-delay: var(--m-lever-pas); }
  html.js [data-lever-pret][data-vu] .lever:nth-child(3) > span { transition-delay: calc(var(--m-lever-pas) * 2); }
  html.js [data-lever-pret][data-vu-net] .lever > span { transform: none; transition: none; }
}

.hero .sur-titre { color: var(--champagne-light); }
.hero .sur-titre::after { background: var(--champagne); }

.hero-phrase {
  font-size: var(--t-1); line-height: var(--lh-1); letter-spacing: var(--ls-1);
  color: rgb(253 255 255 / 0.82);
  margin-top: var(--e-3);
  max-width: 44ch;
}
.hero-actes { margin-top: var(--e-5); gap: var(--e-2); }

/* Les trois promesses : elles repondent aux trois objections qui viennent
   avant l'appel, et elles ne se disputent rien. */
.hero-socle {
  margin-top: var(--e-6);
  padding-top: var(--e-3);
  border-top: var(--filet) solid rgb(253 255 255 / 0.18);
  display: grid; gap: var(--e-2);
}
.hero-socle li { display: flex; align-items: flex-start; gap: var(--e-1); font-size: var(--t-00); color: rgb(253 255 255 / 0.78); }
.hero-socle svg { width: 1.0625rem; height: 1.0625rem; color: var(--champagne); flex: 0 0 auto; margin-top: 0.15rem; }
.hero-socle b { color: var(--pearl); font-weight: 600; }
@media (min-width: 48em) { .hero-socle { grid-template-columns: repeat(3, 1fr); gap: var(--e-3); } }

/* L'ENCHAINEMENT — ce qui donne envie de descendre.  D-901
   Ce n'est pas un ornement : c'est un LIEN, il nomme la section suivante,
   il repond au clavier, et il a une cible de 56 px. */
/* LE LIEN DE DESCENTE RESTE DANS LA COLONNE DE TEXTE.  D-921
   Centre sur toute la largeur, il se posait au milieu du mur d'ecrans : un
   bouton pose sur une photographie, exactement ce que le projet interdit.
   A gauche, sous les promesses, il est sur du navy plein. */
.hero-suite {
  position: relative; z-index: 1;
  display: flex; justify-content: flex-start;
  width: 100%; max-width: var(--page-max);
  margin-inline: auto; margin-top: var(--e-5);
  padding-inline: var(--gouttiere);
}
.hero-suite a {
  display: inline-flex; align-items: center; gap: var(--e-2);
  min-height: var(--cible-min);
  padding-inline: var(--e-3);
  border-radius: var(--rayon-pilule);
  font-size: var(--t-00); font-weight: 600;
  color: rgb(253 255 255 / 0.86); text-decoration: none;
  border: var(--filet) solid rgb(253 255 255 / 0.22);
  transition: background-color var(--t-etat), color var(--t-etat), border-color var(--t-etat);
}
.hero-suite a:hover { background: rgb(253 255 255 / 0.10); color: var(--pearl); border-color: rgb(253 255 255 / 0.44); }
.hero-suite svg { width: 1.125rem; height: 1.125rem; color: var(--champagne); }
@media (prefers-reduced-motion: no-preference) {
  .hero-suite a svg { animation: respire 2.4s var(--m-courbe) infinite; }
  .hero-suite a:hover svg { animation: none; transform: translateY(3px); }
}
@keyframes respire {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(4px); }
}

/* ===================================================================
   6 · LES CINQ SERVICES — LE RAIL HORIZONTAL EPINGLE  D-923
   Jamais un accordeon : aucune agence du corpus n'en met, et un accordeon
   cache l'offre (D-825). Jamais cinq lignes de tableau non plus : elles
   ne se REGARDENT pas.
   =================================================================== */

/* LA HAUTEUR DU RAIL EST ECRITE EN CSS, PAS CALCULEE PAR LE SCRIPT.
   Une hauteur posee par JS apres le chargement est un decalage de mise en
   page — le seuil du projet est CLS 0. Toutes les mesures du rail sont
   des `vw`, donc la longueur de la piste est connue d'avance :
     2 marges 7 + 2 panneaux 30 + 5 cartes 40 + 6 pas 4 = 298 vw
   et la course vaut 298 - 100 = 198 vw. Le script ne fait que LIRE ces
   valeurs et deplacer la piste ; il ne pose aucune geometrie.
   LA CARTE EST PASSEE DE 34 A 40 vw.  D-980
   Une fois la capture montree en entier au lieu d'etre rognee, le panneau
   descendu dessous et la hauteur rendue au contenu, la carte ne faisait
   plus que 470 px de haut dans une fenetre de 900 : il restait 430 px de
   silk vide sous le rail. Six vw de plus rendent la capture a 576 px de
   large — la ou un premier ecran se LIT — sans changer une seule regle. */
.vitrine {
  --vit-carte: 40vw;
  --vit-panneau: 30vw;
  --vit-pas: 4vw;
  --vit-marge: 7vw;
  --vit-course: 198vw;
  background: var(--silk);
}
.vitrine-colle { padding-block: var(--bande); }
.vitrine-piste { display: grid; gap: var(--e-5); }
.vitrine-piste > * { min-width: 0; }

/* Sous 62em : aucun epinglage, aucune course. Les memes cartes, empilees,
   dans le meme ordre. Un rail horizontal au doigt entre en conflit avec le
   defilement de la page, et notre public est sur telephone. */
.vitrine-colle { max-width: var(--page-max); margin-inline: auto; padding-inline: var(--gouttiere); }
.vitrine-reperes { display: none; }
.vitrine-consigne { display: none; }

.vitrine-panneau--fin { margin-top: var(--e-3); }
.vitrine-fin-dit {
  font-family: var(--font-titre);
  font-size: var(--t-2); line-height: var(--lh-2); letter-spacing: var(--ls-2);
  color: var(--navy-dark);
  margin-bottom: var(--e-3);
  max-width: 20ch;
}

/* ---- LA CARTE ---- */
.svc-carte {
  /* La hauteur de la barre de navigateur est ECRITE : la hauteur du media
     en depend, et une valeur devinee par le script serait un decalage de
     mise en page. Elle vit sur la CARTE et non sur le rail : la carte sert
     aussi hors du rail, dans la grille de `contact.html`.  D-984 */
  --svc-barre: 2.125rem;
  display: flex; flex-direction: column;
  text-decoration: none; color: inherit;
  /* La carte entiere est la cible : un titre cliquable de 300 px dans une
     carte de 500 est une cible qu'il faut viser. */
}
.svc-carte .svc-vue { flex: 1 1 auto; }
.svc-carte-haut {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--e-2);
  margin-bottom: var(--e-1);
  font-size: var(--t-00); font-weight: 600;
  letter-spacing: var(--ls-etiquette); text-transform: uppercase;
  color: var(--text-soft);
}
/* LE NUMERO EST DE L'INFORMATION, DONC IL N'EST PAS EN CHAMPAGNE.  D-931
   Il l'a ete, copie de la demo de design interieur ou le laiton numerote
   les maisons. Le champagne le plus fonce plafonne a 2,63:1 sur perle, et
   `tools/banc.mjs` a rendu 2,12:1 sur silk — cinq echecs, aux cinq
   largeurs. « Le champagne ne porte ni texte ni information » n'a pas
   d'exception, et « 01 » a 2,12:1 en est la demonstration : c'est le RANG
   du service, la seule chose qui dit qu'il y en a cinq et dans quel ordre.
   La signature reste l'italique de Newsreader, pas la couleur. */
.svc-num { font-family: var(--font-titre); font-style: italic; font-size: var(--t-0);
           letter-spacing: 0; text-transform: none; color: var(--navy-light); }

/* LA BOITE D'IMAGE PORTAIT LE RAPPORT D'UN PORTRAIT ET RECEVAIT CINQ
   PAYSAGES.  D-980
   `aspect-ratio: 4/5` sur 34vw rendait 490 x 540 px, et les cinq captures
   sont des 1440 x 900 : `object-fit: cover` en jetait 43 a 49 %. On ne
   voyait pas un site, on voyait sa bande du haut. Le proprietaire l'a dit
   sans instrument : « la il est coupe ».
   La vue est maintenant une COLONNE — le media au rapport de sa prise de
   vue, le panneau dessous — et plus une boite ou le texte recouvre
   l'image. Le panneau prend ce qui reste : les cinq cartes ont donc la
   meme hauteur meme quand leurs medias n'ont pas le meme rapport. */
.svc-vue {
  position: relative;
  display: flex; flex-direction: column;
  overflow: hidden;
  border-radius: var(--rayon-carte);
  background: var(--pearl);
  border: var(--filet) solid var(--line-strong);
  box-shadow: var(--ombre-pose);
  transition: box-shadow var(--t-etat), transform var(--t-etat);
}

/* LE CADRE DE NAVIGATEUR. Une capture sans cadre se lit comme une
   illustration ; avec trois pastilles et une barre muette, elle se lit
   comme un SITE — c'est exactement ce qu'on vend (§ 20.4). La barre a une
   hauteur ECRITE parce que la hauteur du media en depend. */
.svc-media { position: relative; display: block; flex: 0 0 auto; background: var(--marble); }
.svc-barre {
  display: flex; align-items: center; gap: 0.375rem;
  height: var(--svc-barre);
  padding-inline: 0.75rem;
  background: var(--marble);
  border-bottom: var(--filet) solid var(--line);
}
.svc-barre i { width: 0.5rem; height: 0.5rem; border-radius: 50%; background: var(--line-strong); flex: 0 0 auto; }
.svc-barre b { margin-left: 0.5rem; flex: 1 1 auto; height: 1rem; border-radius: var(--rayon-pilule); background: var(--pearl); }
.svc-media img {
  display: block; width: 100%; height: auto;
  aspect-ratio: 16 / 10;
  object-fit: cover; object-position: top center;
}
/* UNE VISITE 360 N'EST PAS UN SITE : pas de cadre de navigateur, et le
   rapport de SA prise de vue, 1040 x 585. Un 16/9 force dans un 16/10
   reperdrait un dixieme de l'image — le defaut qu'on vient de corriger. */
.svc-media--nu img { aspect-ratio: 16 / 9; }

/* LE MEDIA SORTI DE SA CARTE.  D-986
   Dans une carte, c'est `.svc-vue` qui porte le cadre — le rayon, le
   filet, l'ombre — et qui rogne son contenu. Pose seul dans une colonne
   (bloc 02 de `services.html`), le media n'avait plus rien autour : le
   schema flottait sur le silk, sans bord. Il reprend ici le cadre de la
   carte, et rien d'autre. */
.svc-media--seul {
  margin: 0 0 var(--e-3);
  border-radius: var(--rayon-large);
  overflow: hidden;
  border: var(--filet) solid var(--line-strong);
  box-shadow: var(--ombre-pose);
}
/* LE RAPPORT 16/10 EST UNE BONNE REGLE DANS UNE CARTE DE 576 px ET UNE
   MAUVAISE DANS UNE COLONNE DE 1 200.  D-986
   Hors de la carte, la colonne de `services.html` fait presque toute la
   largeur : le schema y rendait 780 px de haut et ses quatre lignes 170
   px chacune — un formulaire geant, pas un schema. La hauteur est donc
   plafonnee ICI et nulle part ailleurs : dans la carte, le rapport doit
   rester exact, c'est lui qui aligne les cinq. */
/* `width: 100%` N'EST PAS DECORATIF ICI. Avec `aspect-ratio` et une
   largeur AUTO, un plafond de hauteur fait retomber la LARGEUR pour
   garder le rapport : le schema rendait 512 px dans une colonne de 1 200
   et laissait 700 px de marbre nu a sa droite. La largeur imposee gagne,
   et c'est la hauteur qui plie. */
.svc-media--seul .flux { width: 100%; max-height: 20rem; }

/* L'etiquette d'un media qui n'est pas une capture de site. */
.svc-etiq {
  position: absolute; left: var(--e-2); top: var(--e-2);
  display: inline-flex; align-items: center;
  padding: 0.25rem 0.5rem;
  border-radius: var(--rayon);
  background: var(--navy-dark); color: var(--pearl);
  font-size: 0.75rem; font-weight: 700;
  letter-spacing: var(--ls-etiquette); text-transform: uppercase;
}

/* LE SURVOL NE MET PLUS L'IMAGE A L'ECHELLE.  D-980
   `transform: scale(1.06)` sur 900 ms, dans un cadre en `overflow:
   hidden` a coin arrondi, se declenchait tout seul pendant le
   defilement : le pointeur reste immobile et ce sont les cartes qui
   passent dessous. Cinq images de 490 px remises a l'echelle pendant que
   la piste se deplace, c'est huit images au-dessus de 20 ms sur le rail.
   La carte se souleve maintenant d'un bloc, en 220 ms. */
@media (hover: hover) {
  .svc-carte:hover .svc-vue { box-shadow: var(--ombre-flottante); transform: translateY(-4px); }
}
/* AU DOIGT AUSSI, PAS SEULEMENT AU SURVOL. Tout le budget d'animation du
   site partait en `:hover`, invisible sur telephone — c'est-a-dire la ou
   vit notre public. */
.svc-carte:active .svc-vue { transform: translateY(-2px); }

/* LE PANNEAU EST PLEIN, JAMAIS TRANSLUCIDE.  D-923
   C'est du texte pose sur une photographie : un contraste sur une image ne
   se mesure pas. Le fond est `--navy-dark` a 0,96 — le pire fond possible
   derriere lui est le navy lui-meme, et le perle y tient 15,2:1.
   Sur ordinateur il est REPLIE au repos et se deploie au survol : la
   demo de design interieur le fait, et c'est ce qui donne envie de
   pointer la carte. Le nom du service, lui, ne se replie JAMAIS — sinon
   la carte ne dit plus ce qu'elle vend tant qu'on ne la survole pas. */
/* LE PANNEAU NE RECOUVRE PLUS RIEN, IL SUIT.  D-980
   Pose sur l'image, il en mangeait le tiers du bas — sur une capture de
   site, c'est le tiers ou vivent les boutons. Il descend donc SOUS le
   media : le fond est le navy PLEIN, plus un navy a 0,96 pose sur une
   photographie, et le contraste se mesure enfin pour de vrai (15,2:1)
   plutot que de se defendre par le pire fond possible.
   AUCUN `backdrop-filter` ICI, ET IL Y EN A EU UN.  D-933
   A 0,96 d'alpha, ce qui traversait valait quatre pour cent de l'image :
   le flou etait invisible. Il coutait, lui, cinq recompositions par image
   pendant que le rail se deplace — 49 images sur 276 au-dessus de 20 ms.
   Un effet qu'on ne voit pas et qui se paie n'est pas un arbitrage. */
.svc-panneau {
  position: relative;
  flex: 1 1 auto;
  display: grid; gap: 0.25rem; align-content: start;
  /* La fleche est POSEE en haut a droite du panneau : sans reserve a
     droite, « Immobilier et visibilite locale » passait dessous. Une
     pastille de 32 px, plus les 24 de sa marge, plus 8 de repos. */
  padding: var(--e-3);
  padding-right: calc(var(--e-3) + 4rem);
  background: var(--navy-dark);
  color: var(--pearl);
}
.svc-nom {
  font-family: var(--font-titre);
  font-size: var(--t-1); line-height: 1.15; letter-spacing: var(--ls-2);
  color: var(--pearl);
}
.svc-dit { font-size: var(--t-00); line-height: 1.5; color: rgb(253 255 255 / 0.80); }
.svc-fleche {
  position: absolute; top: var(--e-3); right: var(--e-3);
  display: inline-flex; align-items: center; justify-content: center;
  width: 2rem; height: 2rem;
  border-radius: var(--rayon-pilule);
  background: var(--champagne); color: var(--navy-dark);
  transition: transform var(--t-etat) var(--m-courbe);
}
.svc-fleche svg { width: 1rem; height: 1rem; }
@media (hover: hover) { .svc-carte:hover .svc-fleche { transform: translateX(4px); } }

/* ---- LE SCHEMA DE LA CARTE 02 — QUATRE LIGNES QUI SE FONT SEULES ----
   D-980
   « Dans l'automatisation, mettre peut-etre une animation a la place
   d'une image [...] on voit une photo avec des piles, on ne comprend pas
   trop. » La pile de dossiers disait la paperasse, pas ce qu'on en fait.
   Quatre lignes de travail se remplissent l'une apres l'autre, une passe
   les descend, et une coche tombe au bout de chacune. Personne ne touche
   a rien : c'est tout le propos du service, et il se lit sans un mot.

   TROIS CHOSES QUI EN FONT UN ARBITRAGE ET NON UN ORNEMENT :
   · le repos EST l'etat FINAL — quatre lignes faites, quatre coches.
     Sans script, sans `IntersectionObserver`, ou avant que la carte soit
     vue, le schema dit deja ce qu'il a a dire. C'est le meme contrat que
     `.entre` (§ 10) ;
   · il ne se joue qu'une fois la carte VUE, et il s'arrete pendant que la
     page defile (`data-defile`, D-933) : le rail est deja ce qui coute le
     plus cher a l'image, on n'y ajoute pas une animation perpetuelle ;
   · rien n'y est anime a part `transform` et `opacity`.

   Ce n'est pas la capture d'un produit — c'est un schema, et il porte son
   etiquette. Une demonstration se dit. */
.flux {
  position: relative;
  display: flex; flex-direction: column; gap: 0.5rem;
  aspect-ratio: 16 / 10;
  padding: var(--e-2);
  background: var(--pearl);
  color: var(--champagne-dark);      /* la seule couleur du trace de fond */
  overflow: hidden;
}
.flux-fond { position: absolute; inset: 0; width: 100%; height: 100%; }
.flux-etiq {
  position: relative;
  align-self: flex-start;
  font-size: 0.75rem; font-weight: 700;
  letter-spacing: var(--ls-etiquette); text-transform: uppercase;
  color: var(--text-soft);
}
.flux-ligne {
  position: relative;
  flex: 1 1 0; min-height: 0;
  display: flex; align-items: center;
  padding-inline: 0.75rem;
  padding-right: 2.5rem;
  border: var(--filet) solid var(--line-strong);
  border-radius: var(--rayon);
  background: var(--marble);
  overflow: hidden;
}
/* LE REMPLISSAGE EST DERRIERE LE MOT, JAMAIS DESSUS : un texte qui se
   fait recouvrir est un texte qu'on relit. `--text` sur champagne clair
   tient 11,9:1, sur marbre 15,2:1 — les deux etats sont lisibles. */
.flux-fill {
  position: absolute; inset: 0;
  background: var(--champagne-light);
  transform: scaleX(1); transform-origin: left;
}
.flux-mot {
  position: relative;
  font-size: var(--t-00); font-weight: 600; color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.flux-coche {
  position: absolute; right: 0.625rem; top: 50%;
  margin-top: -0.6875rem;
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.375rem; height: 1.375rem;
  border-radius: 50%;
  background: var(--navy); color: var(--pearl);
}
.flux-coche svg { width: 0.8125rem; height: 0.8125rem; }
/* LA PASSE — le seul objet qui dit qu'il se passe quelque chose SANS
   qu'on y touche. Elle n'existe qu'en mouvement : au repos, invisible. */
.flux-passe {
  position: absolute; left: var(--e-2); right: var(--e-2); top: 0;
  height: 2px; border-radius: var(--rayon-pilule);
  background: var(--champagne-dark);
  opacity: 0;
}

@media (prefers-reduced-motion: no-preference) {
  /* LE DECLENCHEUR EST `[data-vu]`, PAS `.svc-carte[data-vu]`.  D-986
     Le schema sert aussi hors du rail — bloc 02 de `services.html` — et
     la porte etait fermee a clef sur la carte de service. Tout bloc qui
     porte le geste d'entree du site le fait donc jouer, une fois vu. */
  [data-vu] .flux-fill  { animation: flux-fill 7.2s var(--m-courbe) infinite; animation-delay: calc(var(--flux-rang) * 1.2s); }
  [data-vu] .flux-coche { animation: flux-coche 7.2s var(--m-courbe) infinite; animation-delay: calc(var(--flux-rang) * 1.2s); }
  [data-vu] .flux-passe { animation: flux-passe 7.2s linear infinite; }
  /* PENDANT QUE LA PAGE DEFILE, TOUT S'ARRETE.  D-933
     Le compositeur a deja le rail sur les bras ; il reprend exactement ou
     il en etait 200 ms apres le dernier evenement. */
  html[data-defile] .flux-fill,
  html[data-defile] .flux-coche,
  html[data-defile] .flux-passe { animation-play-state: paused; }
}
@keyframes flux-fill {
  0%            { transform: scaleX(0); }
  12.5%, 86%    { transform: scaleX(1); }
  94%, 100%     { transform: scaleX(0); }
}
@keyframes flux-coche {
  0%, 11%       { opacity: 0; transform: scale(0.5); }
  16%           { opacity: 1; transform: scale(1.14); }
  20%, 86%      { opacity: 1; transform: scale(1); }
  92%, 100%     { opacity: 0; transform: scale(0.5); }
}
@keyframes flux-passe {
  0%            { transform: translateY(0); opacity: 0; }
  6%            { opacity: 1; }
  58%           { transform: translateY(var(--flux-course, 260px)); opacity: 1; }
  64%, 100%     { transform: translateY(var(--flux-course, 260px)); opacity: 0; }
}

/* ---- LA VITRINE, A PARTIR DE 62em ---- */
@media (min-width: 62em) {
  .vitrine { position: relative; height: calc(100svh + var(--vit-course)); }
  .vitrine-colle {
    position: sticky; top: 0;
    height: 100svh; max-width: none; margin-inline: 0; padding: 0;
    display: flex; flex-direction: column; justify-content: center;
    overflow: hidden;
  }
  /* `stretch` ET NON `center`, ET C'EST LA HAUTEUR DU PANNEAU QUI LE
     DEMANDE.  D-980
     Avec une hauteur de carte ECRITE (62svh), le panneau navy recevait
     tout ce que le media ne prenait pas : 218 px de navy vide sous trois
     lignes de texte, sur chacune des cinq cartes. En `stretch`, les
     cartes prennent la hauteur de la PLUS HAUTE et rien de plus : le
     panneau ne porte que son texte, et les cinq restent alignees meme si
     leurs medias n'ont pas le meme rapport. */
  .vitrine-piste {
    display: flex; align-items: stretch;
    grid-template-columns: none;
    width: max-content;
    gap: var(--vit-pas);
    padding-inline: var(--vit-marge);
    /* Deplacee par `transform` seul : aucune propriete de mise en page
       n'est animee, le compositeur fait tout le travail.
       `will-change` N'EST PLUS ECRIT ICI.  D-982
       Ecrit dans la feuille, il n'est jamais relache : la piste fait
       `max-content` de large — 298 vw, 4 290 px a 1 440 — sur 100 svh, et
       cette texture restait promue du haut de l'accueil jusqu'au pied
       pour une section qui occupe un cinquieme de la page. `js/site.js`
       la promeut a l'entree dans le rail et la relache a la sortie. */
  }
  /* Les deux panneaux de texte restent CENTRES : `stretch` les etirerait
     sur toute la hauteur du rail et les collerait en haut. */
  .vitrine-panneau { width: var(--vit-panneau); flex: 0 0 auto; align-self: center; }
  .vitrine-panneau--fin { margin-top: 0; }
  .svc-carte { width: var(--vit-carte); flex: 0 0 auto; }
  /* AUCUNE HAUTEUR ECRITE : le media prend ce que SON rapport demande, le
     panneau ne porte que son texte, et `align-items: stretch` aligne les
     cinq sur la plus haute. Une hauteur en `svh` rendait 218 px de navy
     vide par carte sur un ecran de 900. */

  .vitrine-consigne {
    display: inline-flex; align-items: center; gap: var(--e-1);
    margin-top: var(--e-5);
    font-size: var(--t-00); font-weight: 600;
    letter-spacing: var(--ls-etiquette); text-transform: uppercase;
    color: var(--text-soft);
  }
  .vitrine-consigne svg { width: 1rem; height: 1rem; color: var(--champagne-dark); transform: rotate(90deg); }

  /* LES REPERES — ou on est, et combien il en reste. */
  .vitrine-reperes {
    display: flex; align-items: center; gap: var(--e-3);
    position: absolute; left: var(--vit-marge); right: var(--vit-marge); bottom: var(--e-6);
    z-index: 2;
  }
  .vitrine-compte { font-size: var(--t-00); font-weight: 600; color: var(--text-soft); white-space: nowrap; }
  .vitrine-compte b { font-family: var(--font-titre); font-size: var(--t-1); color: var(--navy-dark); }
  .vitrine-jauge { flex: 1; height: 3px; border-radius: var(--rayon-pilule); background: var(--marble); overflow: hidden; }
  .vitrine-jauge span {
    display: block; height: 100%; width: 100%;
    border-radius: inherit; background: var(--navy);
    transform: scaleX(0.02); transform-origin: left;
  }
}

/* EN MOUVEMENT REDUIT, LE RAIL N'EXISTE PAS.  D-913
   Pas « il ne bouge pas » : il n'existe pas. Une piste epinglee immobile
   laisserait quatre cartes hors de l'ecran, sans aucun moyen d'y aller —
   ce serait une PERTE d'information, et la regle est que le mouvement
   reduit rend la MEME page. Les cartes reprennent donc leur pile
   verticale, exactement comme sous 62em. */
@media (prefers-reduced-motion: reduce) {
  .vitrine { height: auto; }
  .vitrine-colle {
    position: static; height: auto; overflow: visible;
    max-width: var(--page-max); margin-inline: auto;
    padding-block: var(--bande); padding-inline: var(--gouttiere);
  }
  .vitrine-piste {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
    width: auto; gap: var(--e-5); padding-inline: 0;
    will-change: auto; transform: none !important;
  }
  .vitrine-panneau, .svc-carte { width: auto; }
  .svc-vue { height: auto; }
  .vitrine-reperes, .vitrine-consigne { display: none; }
  .vitrine-panneau { grid-column: 1 / -1; }
}

/* ===================================================================
   7 · LES CARTES
   =================================================================== */

.cartes { display: grid; gap: var(--e-3); }
@media (min-width: 48em) { .cartes--2 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 62em) { .cartes--3 { grid-template-columns: repeat(3, 1fr); } }

.carte {
  background: var(--pearl);
  border: var(--filet) solid var(--line);
  border-radius: var(--rayon-large);
  padding: var(--e-4);
  display: grid; gap: var(--e-2); align-content: start;
  transition: border-color var(--t-etat), box-shadow var(--t-etat), transform var(--t-etat);
}
.bande--silk .carte, .bande--marble .carte { border-color: transparent; box-shadow: var(--ombre-pose); }
.carte-titre { font-size: var(--t-1); line-height: var(--lh-1); letter-spacing: var(--ls-1); }
.carte p { color: var(--text-soft); font-size: var(--t-00); line-height: 1.6; }
/* `.carte p` battait `.chiffre` a la specificite : le chiffre de preuve
   sortait a 15 px au lieu de 38.  D-842 */
.carte p.chiffre { font-size: var(--t-3); line-height: 1; color: var(--navy-dark); }

/* Une carte cliquable se souleve d'un cheveu. Une carte qui ne l'est pas ne
   bouge jamais : le mouvement au survol est une PROMESSE de clic.  D-826 */
a.carte:hover, button.carte:hover {
  border-color: var(--navy-light);
  box-shadow: var(--ombre-levee);
  transform: translateY(-2px);
}
button.carte { text-align: left; width: 100%; font: inherit; }

.carte-etiquette {
  justify-self: start;
  font-size: var(--t-00); font-weight: 700;
  letter-spacing: var(--ls-etiquette); text-transform: uppercase;
  color: var(--navy-dark);
  background: var(--champagne-light);
  padding: 0.3rem 0.6rem; border-radius: var(--rayon);
}

/* ===================================================================
   8 · LES CHAMPS
   =================================================================== */

/* L'ECHELLE DES FORMULAIRES BAISSE D'UN CRAN.  D-985
   Verdict du proprietaire : « trop gros, envahissants, comme si on
   regardait a la loupe ». Mesure a l'appui, sur un ecran de 900 px de
   haut, le premier ecran de « demarrer un projet » ne montrait QUE
   TROIS CHAMPS. Trois valeurs faisaient tout :
     .champs   gap 48 px  — la plus grosse valeur de la page
     --cible   56 px      — sur tout champ, bouton, choix et case
     .modal .etiquette 19 px — +27 % par rapport au reste du site
   Elles passent a 24 px, 48 px et 15 px. `--cible-champ` est un jeton
   neuf : les CIBLES TACTILES restent au-dessus des 44 px exiges
   (`--cible-min`), et `--cible` garde ses 56 px partout ailleurs — la
   barre de pouce, les boutons de page. On reduit le formulaire, pas la
   prise du doigt. */
.champ { display: grid; gap: 0.375rem; }
.champs { display: grid; gap: var(--e-3); }
@media (min-width: 48em) { .champs--2 { grid-template-columns: repeat(2, 1fr); gap: var(--e-3); } }

/* L'etiquette est TOUJOURS au-dessus du champ, jamais dans le champ : un
   `placeholder` qui sert d'etiquette disparait des qu'on ecrit, et le
   visiteur ne sait plus ce qu'il remplit. C'est le defaut de formulaire le
   plus documente, et Cuberto le commet.  D-827 */
.etiquette { font-size: var(--t-00); font-weight: 600; color: var(--text); }
.etiquette .facultatif { font-weight: 400; color: var(--text-soft); }
.aide { font-size: var(--t-00); color: var(--text-soft); }

.saisie,
select.saisie,
textarea.saisie {
  width: 100%;
  min-height: var(--cible-champ);
  padding: 0.625rem 0.75rem;
  background: var(--pearl);
  border: var(--filet) solid var(--line-strong);
  border-bottom-width: 2px;
  border-radius: var(--rayon);
  /* 16 px et pas 15 : sous 16, iOS ZOOME la page a la mise au point du
     champ, et le visiteur se retrouve dans un formulaire agrandi qu'il
     doit faire glisser. Le reste de l'interface descend a 15.  D-985 */
  font-size: 1rem;
  color: var(--text);
  transition: border-color var(--t-etat), box-shadow var(--t-etat);
}
textarea.saisie { min-height: 6.5rem; resize: vertical; line-height: 1.5; padding-block: 0.625rem; }
.saisie::placeholder { color: var(--text-muted); }
.saisie:hover { border-color: var(--navy-light); }
.saisie:focus-visible { outline-offset: 0; border-color: var(--navy); }

select.saisie {
  appearance: none;
  padding-right: var(--e-6);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='%2318213D' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--e-2) center;
}

/* Un champ refuse dit POURQUOI, sous lui, et le dit aussi autrement qu'en
   rouge : le filet passe a 3 px et un pictogramme parait.  D-828 */
.champ[data-refus] .saisie { border-color: var(--danger); border-bottom-width: 3px; background: var(--danger-wash); }
.refus {
  display: flex; align-items: flex-start; gap: var(--e-1);
  font-size: var(--t-00); font-weight: 600; color: var(--danger);
}
.refus svg { width: 1.0625rem; height: 1.0625rem; flex: 0 0 auto; margin-top: 0.15rem; }

/* Le piege a robots. Sorti du cadre, jamais `display:none` : un robot
   ignore ce qui est masque. */
.piege {
  position: absolute; left: -9999px;
  width: 1px; height: 1px; overflow: hidden;
}

/* `--text-muted` fait 3,88:1 sur silk et 3,83 sur marble. Une mention se
   pose sur n'importe quel fond : elle prend donc le gris qui tient partout,
   a 6,12:1 au pire.  D-851 */
.mention {
  font-size: var(--t-00); color: var(--text-soft);
  max-width: 52ch;
}

/* ===================================================================
   8bis · LES PAGES INTERIEURES
   Le `--t-5` est reserve a l'accueil : une page interieure ne crie pas
   aussi fort que la porte d'entree.  D-843
   =================================================================== */

.titre-page {
  font-size: var(--t-4);
  line-height: var(--lh-4);
  letter-spacing: var(--ls-4);
  font-weight: 450;
  max-width: 18ch;
}

/* La page 404 : six portes, pas un jeu de piste. */
.liste-404 {
  margin-top: var(--e-6);
  display: grid; gap: var(--e-1);
  max-width: 34rem;
}
.liste-404 a {
  display: flex; align-items: center; justify-content: space-between; gap: var(--e-3);
  min-height: var(--cible);
  padding-inline: var(--e-3);
  border: var(--filet) solid var(--line);
  border-radius: var(--rayon);
  font-weight: 600;
  text-decoration: none;
  transition: border-color var(--t-etat), background-color var(--t-etat);
}
.liste-404 a:hover { border-color: var(--navy-light); background: var(--marble); }
.liste-404 svg { width: 1.125rem; height: 1.125rem; color: var(--navy); }

.lien-tel {
  display: inline-flex; align-items: center;
  min-height: var(--cible-min);
  font-family: var(--font-titre);
  font-size: var(--t-1);
  color: var(--navy-dark);
  text-decoration-color: var(--champagne-dark);
  text-underline-offset: 0.24em;
  white-space: nowrap;
}

/* La page de confidentialite. Une colonne, un seul filet entre les
   articles, aucune carte : c'est un texte de loi, il se lit en descendant. */
.legal .chapo, .legal p, .legal li { max-width: var(--colonne-texte); }
.legal .mention { margin-top: var(--e-2); }
.legal-sec { margin-top: var(--e-7); padding-top: var(--e-5); border-top: var(--filet) solid var(--line); }
.legal-sec h2 {
  font-size: var(--t-2); line-height: var(--lh-2); letter-spacing: var(--ls-2);
  margin-bottom: var(--e-2);
  max-width: 24ch;
}
.legal-sec h3 {
  font-family: var(--font-texte);
  font-size: var(--t-0); font-weight: 700;
  color: var(--text);
  margin-top: var(--e-4); margin-bottom: var(--e-1);
}
.legal-sec ul { margin-top: var(--e-2); display: grid; gap: var(--e-1); }
.legal-sec ul li { padding-left: var(--e-3); position: relative; color: var(--text-soft); }
.legal-sec ul li::before {
  content: ""; position: absolute; left: 0; top: 0.72em;
  width: 8px; height: 1px; background: var(--champagne-dark);
}
.legal-sec strong, .legal-sec b { font-weight: 700; color: var(--text); }

/* Un tableau ne se comprime pas : a 320 px il debordait de 31, et c'est la
   PAGE qui partait de travers. Il roule dans son propre cadre.  D-853 */
.table-roule { overflow-x: auto; margin-top: var(--e-3); max-width: 100%; }
.legal-table { border-collapse: collapse; min-width: 30rem; font-size: var(--t-00); }
.legal-table th, .legal-table td {
  text-align: left; padding: var(--e-2) var(--e-3) var(--e-2) 0;
  border-bottom: var(--filet) solid var(--line);
  vertical-align: top;
}
.legal-table th { font-weight: 700; color: var(--text); }
.legal-table td { color: var(--text-soft); }

/* `.appel-num` vient de l'ancienne page : un numero de telephone est une
   cible, pas un mot dans une phrase. */
.appel-num {
  display: inline-flex; align-items: center;
  min-height: var(--cible-min);
  font-weight: 600; color: var(--navy-dark);
  text-decoration-color: var(--champagne-dark); text-underline-offset: 0.24em;
  white-space: nowrap;
}

/* ===================================================================
   9 · LE PIED DE PAGE — complet, sur toutes les pages
   =================================================================== */

.pied {
  background: var(--navy-dark);
  color: var(--pearl);
  padding-block: var(--e-9) var(--e-6);
}
/* Une bande navy suivie du pied navy, c'est UNE seule masse pour l'oeil —
   et leurs deux respirations s'additionnaient en 224 px de vide au milieu.
   Un filet champagne dit la couture, et la respiration se partage.  D-871 */
.bande--navy + .pied {
  padding-top: var(--e-7);
  border-top: var(--filet) solid rgb(210 182 138 / 0.28);
}
.pied a { color: var(--champagne-light); }
/* `.btn--nu` porte `color: var(--navy-dark)` — sur le pied, c'est du
   navy sur navy : 1,00:1, trois boutons purement invisibles. Le fond
   change, la couleur du texte doit changer avec lui.  D-848 */
/* TROIS BOUTONS CASSAIENT LA COLONNE. Dans une colonne de liens a 15 px,
   cadres a gauche, non soulignes, ils rendaient 19 px, CENTRES et
   SOULIGNES : le defaut le plus voyant du site, sur les neuf pages. Un
   bouton qui vit dans une liste de liens s'habille en lien.  D-869 */
.pied .btn--nu {
  justify-content: flex-start;
  padding: 0;
  min-height: var(--cible-min);
  font-size: var(--t-00); font-weight: 400;
  color: var(--champagne-light);
  text-decoration: none;
  text-align: left;
}
.pied .btn--nu:hover { text-decoration: underline; text-underline-offset: 0.24em; }
.bande--navy .btn--nu { color: var(--champagne-light); text-decoration-color: var(--champagne-dark); }
.pied-haut { display: grid; gap: var(--e-7); }
.pied-appel h2 {
  color: var(--pearl);
  font-size: var(--t-3); line-height: var(--lh-3); letter-spacing: var(--ls-3);
  max-width: 16ch;
}
.pied-appel p { color: var(--champagne-light); margin-top: var(--e-2); max-width: 40ch; }
.pied-colonnes { display: grid; gap: var(--e-5); }
.pied-colonne h3 {
  color: var(--champagne);
  font-family: var(--font-texte);
  /* 13 px etait sous le plancher de lisibilite qu'on s'impose. */
  font-size: var(--t-00); font-weight: 700;
  letter-spacing: var(--ls-etiquette); text-transform: uppercase;
  margin-bottom: var(--e-2);
}
.pied-colonne li + li { margin-top: var(--e-1); }
.pied-colonne a {
  display: inline-flex; align-items: center;
  min-height: var(--cible-min);
  font-size: var(--t-00);
  text-decoration: none;
}
.pied-colonne a:hover { text-decoration: underline; text-underline-offset: 0.24em; }
/* `.pied-tel` — le numero au bas du pied — est parti avec lui.  D-992 */
.pied-bas {
  margin-top: var(--e-7); padding-top: var(--e-3);
  border-top: var(--filet) solid rgb(253 255 255 / 0.16);
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--e-1) var(--e-4);
  font-size: var(--t-00); color: var(--champagne-light);
}
.pied-bas a { display: inline-flex; align-items: center; min-height: var(--cible-min); }

@media (min-width: 48em) {
  .pied-colonnes { grid-template-columns: repeat(3, 1fr); }
}
@media (min-width: 62em) {
  .pied-haut { grid-template-columns: 1fr 1.2fr; gap: var(--e-9); align-items: start; }
}

/* ===================================================================
   10 · LE MOUVEMENT — UN SEUL GESTE D'ENTREE DANS TOUT LE SITE
   16 px, 500 ms, courbe (.16,1,.3,1), decalage 60 ms par BLOC, trois au
   plus. Aucun etat de depart ne vit ici : le repos EST la forme finale,
   et le script pose le depart.  D-829
   =================================================================== */

/* LE TEXTE MONTE, IL NE SE FOND PAS.  D-905
   Releve du 2026-08-08 sur cuberto.com : l'opacite de chaque mot de titre
   reste a 1,000 sur les DIX-HUIT echantillons pris pendant son entree.
   Le seul mouvement est une montee. Trois raisons de faire pareil :
   1 · un texte a opacite 0 est un texte ABSENT. Si l'observateur rate son
       verdict — un doigt qui lance la page d'un coup le devance — le bloc
       ne revient pas. C'est exactement ce qui a fait disparaitre neuf
       captures de sites il y a une heure, et huit blocs de l'accueil
       avant ca. Un mouvement qui ne peut pas cacher son element ne peut
       pas casser.
   2 · le LCP. Un element a opacite 0 n'est PAS peint : le navigateur
       horodate la derniere peinture, et notre propre fondu avait porte le
       LCP de l'accueil a 768 ms pour un FCP a 204 (D-854). Une montee ne
       retarde aucune peinture.
   3 · un lecteur de 55 ans lit pendant que ca bouge. Un texte qui monte
       reste lisible tout du long ; un texte qui se fond ne l'est pas.
   Les IMAGES gardent leur fondu : une image n'a pas a etre lue, et son
   apparition franche est plus dure a l'oeil qu'un fondu. Voir 20.10. */
.entre { }
@media (prefers-reduced-motion: no-preference) {
  html.js .entre {
    transform: translateY(var(--m-distance));
  }
  html.js .entre[data-vu] {
    transform: none;
    transition: transform var(--m-duree) var(--m-courbe);
    transition-delay: var(--m-retard, 0ms);
  }
  /* CE QUI EST DEJA A L'ECRAN NE S'ANIME PAS.
     Mesure : le LCP de l'accueil etait a 768 ms pour un FCP a 204. L'ecart
     n'etait pas le poids du document — c'etait mon propre fondu. Le plus
     gros element peint N'EST PAS FINI tant qu'il monte de 0 a 1, et le
     navigateur horodate la DERNIERE peinture. Une animation qui retarde de
     500 ms le moment ou le titre est lisible ne sert aucune comprehension :
     elle la retarde.  D-854 */
  html.js .entre[data-vu-net] {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* ===================================================================
   11 · LA TRANSITION DE PAGE
   180 ms, pas 1 680. Le voile ne cache jamais le contenu : il fond.  D-830
   =================================================================== */

@view-transition { navigation: auto; }

@media (prefers-reduced-motion: no-preference) {
  ::view-transition-old(root) { animation: sortir 120ms var(--e-sortie) both; }
  ::view-transition-new(root) { animation: entrer 180ms var(--m-courbe) both; }
}
@keyframes sortir { to { opacity: 0; } }
@keyframes entrer { from { opacity: 0; transform: translateY(8px); } }

/* La barre et le pied ne clignotent pas d'une page a l'autre : ils portent
   le meme nom de transition des deux cotes, donc le navigateur les garde. */
.barre { view-transition-name: barre; }
.pied { view-transition-name: pied; }

/* ===================================================================
   FUSIONNE DEPUIS modales.css
   =================================================================== */

/* == ADEXWEB - LES MODALES, LES ASSISTANTS, L'AGENDA, LA FOURCHETTE ==  D-843
      A FUSIONNER dans `css/app.css`, puis `node tools/css-critique.mjs` et
      `node tools/cascade-check.mjs`. Ce fichier se pose APRES les sections
      existantes : il complete `.champ`, `.saisie`, `.refus` et `.btn`, il ne
      les remplace pas.

      DEUX NOMS POUR UNE MEME BOITE, ET C'EST VOULU. Le balisage porte
      `class="champ field"` et `class="refus field-error"` : `champ` et
      `refus` sont le systeme ADEXWEB, `field` et `field-error` sont les
      crochets que `js/main.js` interroge (`closest(".field")`,
      `$(".field-error", field)`, `.field.is-invalid`). Renommer l'un des
      deux casse la validation sans une erreur.
      `refonte-adexweb/INVENTAIRE-PLOMBERIE.md § 11`. */

/* ===================================================================
   1 · `hidden` DOIT GAGNER SUR TOUT `display` POSE PAR UNE CLASSE
   Sans ces lignes, un bouton « Retour » marque `hidden` reste visible :
   `.btn { display: inline-flex }` bat l'attribut.  D-844
   =================================================================== */

.modal[hidden], .step[hidden], .step-second[hidden], .champ[hidden],
.btn[hidden], .devis[hidden], .devis-suite[hidden], .devis-petit[hidden],
.devis-question[hidden], .retenue[hidden], .retenue-champ[hidden],
.cadeau-avant[hidden], .cadeau-suite[hidden], .cadeau-deja[hidden],
.cond-texte[hidden], .step-manque[hidden], .empty[hidden],
.step-nav[hidden], .form-portes[hidden], .booking[hidden] { display: none; }

/* ===================================================================
   2 · LE VOILE ET LE PANNEAU
   Un seul panneau a l'ecran, cadre a 92 % de la hauteur : c'est le corps
   qui defile, jamais la page derriere.  D-845
   =================================================================== */

.modal {
  position: fixed; inset: 0; z-index: var(--z-modal);
  display: flex; align-items: flex-end; justify-content: center;
  padding: 0;
}
@media (min-width: 48em) {
  .modal { align-items: center; padding: var(--e-5) var(--e-3); }
}

.modal-scrim {
  position: absolute; inset: 0;
  background: var(--scrim);
  border: 0;
}

.modal-panel {
  position: relative;
  display: flex; flex-direction: column;
  width: 100%; max-width: 38rem;
  max-height: 94vh;
  background: var(--pearl);
  border-radius: var(--rayon-large) var(--rayon-large) 0 0;
  box-shadow: var(--ombre-levee);
  overflow: hidden;
}
.modal-panel--large { max-width: 60rem; }
@media (min-width: 48em) {
  .modal-panel { max-height: 88vh; border-radius: var(--rayon-large); }
}

/* L'en-tete ne defile pas : la croix reste sous le pouce, et le titre
   reste lisible au vingtieme ecran d'un assistant. */
.modal-head {
  flex: 0 0 auto;
  display: flex; align-items: flex-start; justify-content: space-between; gap: var(--e-3);
  padding: var(--e-3) var(--e-3) var(--e-2);
  border-bottom: var(--filet) solid var(--line);
  background: var(--pearl);
}
.modal-titre {
  font-size: var(--t-2); line-height: var(--lh-2); letter-spacing: var(--ls-2);
}
.modal-sub {
  color: var(--text-soft);
  margin-top: var(--e-1);
  max-width: 54ch;
}
.modal-corps {
  flex: 1 1 auto;
  overflow-y: auto; overscroll-behavior: contain;
  padding: var(--e-3);
}
@media (min-width: 48em) {
  .modal-head { padding: var(--e-4) var(--e-4) var(--e-2); }
  .modal-corps { padding: var(--e-4); }
}

/* Le bouton-icone : 44 px de cible, aucun fond au repos. Le script en
   fabrique aussi (retirer un fichier) — la classe doit tenir seule. */
.btn-icon {
  display: inline-flex; align-items: center; justify-content: center;
  flex: 0 0 auto;
  width: var(--cible-min); height: var(--cible-min);
  border-radius: var(--rayon);
  color: var(--navy-dark);
  transition: background-color var(--t-etat), color var(--t-etat);
}
.btn-icon:hover { background: var(--marble); }
.btn-icon:disabled { color: var(--text-muted); cursor: not-allowed; }
.btn-icon:disabled:hover { background: none; }
.btn-icon svg { width: 1.375rem; height: 1.375rem; }

/* ===================================================================
   3 · LES DEUX NOMS DE BOUTON QUE LE SCRIPT FABRIQUE
   `js/main.js` cree des boutons `btn--primary` et `btn--ghost` (repli
   d'envoi, actions du popup). Sans ces alias, ils sortent NUS.  D-846
   =================================================================== */

.btn--primary {
  background: var(--navy); color: var(--pearl);
  box-shadow: var(--ombre-pose);
}
.btn--primary:hover { background: var(--navy-dark); box-shadow: var(--ombre-levee); }
.btn--ghost {
  background: var(--pearl); color: var(--navy-dark);
  border: var(--filet) solid var(--line-strong);
}
.btn--ghost:hover { border-color: var(--navy-light); background: var(--marble); }

.btn--bloc { width: 100%; }
/* Un envoi en cours ne se reclique pas, et ca se VOIT. */
.btn.is-loading { opacity: 0.62; cursor: progress; pointer-events: none; }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }

/* Les `<svg>` fabriques par le script portent `class="icon"` et aucune
   dimension : sans ceci ils sortent a 300 x 150. */
.icon { width: 1.125rem; height: 1.125rem; flex: 0 0 auto; }

.form-actes { display: flex; flex-wrap: wrap; gap: var(--e-2); margin-top: var(--e-4); }

/* ===================================================================
   4 · LES ECRANS D'ASSISTANT
   =================================================================== */

.step { display: block; }
.step + .step-nav { margin-top: var(--e-4); }

/* « Étape 3 sur 7 » se lit, la barre ne se lit pas. Les deux, jamais la
   barre seule.  D-847 */
.step-compte,
.progress-compte {
  font-size: var(--t-00); font-weight: 600;
  letter-spacing: var(--ls-etiquette); text-transform: uppercase;
  color: var(--text-soft);
  margin-bottom: var(--e-2);
}
.progress-compte { margin-bottom: 0; white-space: nowrap; }
.progress-compte b { color: var(--navy-dark); }

.step-q {
  font-family: var(--font-titre);
  font-size: var(--t-1); line-height: var(--lh-1); letter-spacing: var(--ls-1);
  color: var(--navy-dark);
  margin-bottom: var(--e-2);
  max-width: 34ch;
}
.step-q--second { font-size: var(--t-1); margin-top: var(--e-4); }
/* Un ecran qui refuse d'avancer dit LEQUEL des deux choix manque. */
.step-q--manque { color: var(--danger); }
.step-aide { color: var(--text-soft); margin: calc(var(--e-3) * -1) 0 var(--e-3); max-width: 58ch; }
.step-manque {
  display: flex; align-items: center; gap: var(--e-1);
  font-size: var(--t-00); font-weight: 600; color: var(--danger);
  margin-bottom: var(--e-2);
}

.step-second { margin-top: var(--e-4); padding-top: var(--e-3); border-top: var(--filet) solid var(--line); }

.step-nav {
  display: flex; align-items: center; gap: var(--e-2);
  margin-top: var(--e-4); padding-top: var(--e-3);
  border-top: var(--filet) solid var(--line);
}
/* Le bouton d'avancement est toujours a droite, meme quand « Retour »
   n'est pas la : la cible ne bouge pas d'un ecran a l'autre. */
.step-nav > :last-child { margin-left: auto; }

/* L'ecran de fin. Une seule chose y est vraie : c'est parti. */
.step-reussi .modal-titre { margin-top: var(--e-1); }
.step-reussi > .modal-sub { margin-bottom: var(--e-2); }

.progress-ligne {
  display: flex; align-items: center; gap: var(--e-3);
  margin-bottom: var(--e-5);
}
.progress {
  flex: 1 1 auto;
  height: 6px;
  background: var(--marble);
  border-radius: var(--rayon);
  overflow: hidden;
}
.progress i {
  display: block; height: 100%; width: 14%;
  background: var(--navy);
  border-radius: var(--rayon);
  transition: width var(--t-panneau) var(--m-courbe);
}
#projectWizard > .progress,
.modal-corps > .progress { margin-bottom: var(--e-3); }

/* ===================================================================
   5 · LES LISTES DE CHOIX
   Un groupe de choix est un `<fieldset>` : sans lui, un lecteur d'ecran
   entend six boutons sans savoir a quelle question ils repondent.
   =================================================================== */

.bloc-choix {
  display: block;
  border: 0; padding: 0; margin: 0; min-width: 0;
}
.bloc-choix > legend { display: block; width: 100%; padding: 0; }
.bloc-choix > legend.etiquette { margin-bottom: var(--e-1); }

/* 5.1 · LES GRANDES CARTES DE L'ESTIMATEUR */
.options { display: grid; gap: var(--e-2); }
.options--serre { gap: var(--e-1); }
/* UN CHOIX DE REPONSE EST CE QU'ON TOUCHE LE PLUS, ET C'ETAIT UN
   RECTANGLE BLANC.  D-985
   Verdict : « laids et trop simples ». Ce qui change, et rien de plus :
   le numero vit dans une pastille champagne au lieu de flotter en gris,
   la carte se souleve d'un cheveu au survol comme toute carte cliquable
   du site (D-826), et le filet de gauche s'epaissit — la meme grammaire
   que `.options button[aria-pressed="true"]`, pour que l'etat choisi
   soit la CONTINUATION du survol et non un autre langage.
   Le rayon passe a `--rayon-carte` : c'est une carte, pas un champ, et
   les quatre rayons ont chacun leur etage (D-915). */
.options button {
  display: grid;
  grid-template-columns: 1.75rem 1fr 1.25rem;
  align-items: center; gap: var(--e-2);
  width: 100%;
  min-height: var(--cible-champ);
  padding: 0.625rem 0.875rem;
  text-align: left;
  background: var(--pearl);
  border: var(--filet) solid var(--line-strong);
  border-radius: var(--rayon-carte);
  color: var(--text);
  box-shadow: inset 0 0 0 var(--navy);
  transition: border-color var(--t-etat), background-color var(--t-etat),
              box-shadow var(--t-etat), transform var(--t-vif);
}
.options button:hover {
  border-color: var(--navy-light);
  box-shadow: inset 3px 0 0 var(--champagne-dark), var(--ombre-pose);
}
@media (prefers-reduced-motion: no-preference) {
  .options button:hover { transform: translateY(-2px); }
}
.options button:active { transform: none; }
.options button strong { display: block; font-weight: 600; line-height: var(--lh-1); }
.options button small {
  display: block;
  font-size: var(--t-00); line-height: 1.5;
  color: var(--text-soft);
  margin-top: 0.15rem;
}
.options button > svg { width: 1.25rem; height: 1.25rem; color: var(--navy-light); }
@media (prefers-reduced-motion: no-preference) {
  .options button > svg { transition: transform var(--t-etat) var(--m-courbe); }
  .options button:hover > svg { transform: translateX(4px); }
}

/* ===================================================================
   LE CHOIX DE DEPART — les trois routes, cote a cote  D-980
   Il existait deja (`#modal-start`) et n'etait ouvert par RIEN : zero
   `data-modal-open="modal-start"` dans les neuf pages. « Demarrer un
   projet » l'ouvre maintenant, dans la barre et dans les six portes.
   Les trois cartes sont plus hautes qu'une option ordinaire parce que
   leur seconde ligne est ce qui les distingue : la rogner ferait
   exactement le defaut qu'on repare.
   =================================================================== */
.depart-choix button { align-items: start; padding-block: var(--e-3); }
.depart-choix button > svg { margin-top: 0.2rem; }
.depart-choix .o-num { align-self: start; margin-top: 0.15rem; }
.depart-choix button small { max-width: 46ch; }
/* La premiere route est celle du bouton qui a ouvert ce panneau : elle
   porte le filet, pour qu'on retrouve d'ou l'on vient. */
.depart-choix button:first-child { border-color: var(--champagne-dark); box-shadow: inset 3px 0 0 var(--champagne-dark); }
.depart-choix button:first-child:hover { border-color: var(--navy-light); box-shadow: inset 3px 0 0 var(--navy), var(--ombre-pose); }
.depart-note {
  margin-top: var(--e-3); padding-top: var(--e-3);
  border-top: var(--filet) solid var(--line);
}

/* CE QU'ON PROPOSE APRES L'ENVOI — UNE COMMODITE, PAS UNE ETAPE.  D-983
   L'ecran de fin portait la fourchette et une question ; il porte
   maintenant ce qui se passe ensuite. Le bouton est SECOND, jamais
   primaire : la demande est deja partie, et un bouton primaire de plus
   ferait croire qu'il reste quelque chose a faire. */
.fin-suite {
  margin-top: var(--e-4);
  padding: var(--e-3);
  background: var(--silk);
  border-radius: var(--rayon-carte);
}
.fin-suite-t {
  font-size: var(--t-00); font-weight: 700;
  letter-spacing: var(--ls-etiquette); text-transform: uppercase;
  color: var(--text-soft);
}
.fin-suite-d { margin: var(--e-1) 0 var(--e-2); color: var(--text-soft); }
/* Le numero est du TEXTE : il tient 4,5:1, donc jamais en champagne. */
/* Le numero est du TEXTE : il tient 4,5:1, donc jamais en champagne.
   Il est POSE sur du champagne clair, ou le navy rend 9,41:1 — le meme
   couple que l'etat choisi, deux crans plus bas.  D-985 */
.o-num {
  display: grid; place-content: center;
  width: 1.75rem; height: 1.75rem;
  font-size: 0.8125rem; font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--navy-dark);
  background: var(--champagne-light);
  border-radius: var(--rayon);
}
/* CHOISI : le fond champagne clair porte du navy a 9,41:1, et la barre
   navy a gauche dit la meme chose sans la couleur.  D-848 */
/* LE SCRIPT POSE `aria-pressed`, PAS UNE CLASSE.  D-885
   La feuille stylait `.is-on` ; `js/main.js` marque le choix de
   l'estimateur avec `aria-pressed="true"` — le contrat est lisible ligne
   3857 : `$$("[data-key] button[aria-pressed]")`. Resultat : on cliquait,
   la reponse etait bien enregistree, et RIEN ne changeait a l'ecran. Un
   patron a clique trois fois de suite pour verifier. Les deux marques sont
   maintenant reconnues. */
.options button.is-on,
.options button[aria-pressed="true"] {
  background: var(--champagne-light);
  border-color: var(--champagne-dark);
  box-shadow: inset 3px 0 0 var(--navy);
}
.options button.is-on small,
.options button[aria-pressed="true"] small { color: var(--text-soft); }
.options button.is-on .o-num,
.options button[aria-pressed="true"] .o-num { color: var(--navy-dark); }

/* 5.2 · LES CHOIX A DEUX OU TROIS BOUTONS */
.choices { display: flex; flex-wrap: wrap; gap: var(--e-2); }
.choices--empile { flex-direction: column; align-items: stretch; }
.choices button {
  flex: 1 1 10rem;
  min-height: var(--cible-champ);
  padding: 0 var(--e-2);
  background: var(--pearl);
  border: var(--filet) solid var(--line-strong);
  border-radius: var(--rayon);
  font-size: var(--t-00); font-weight: 600;
  color: var(--navy-dark);
  transition: border-color var(--t-etat), background-color var(--t-etat), color var(--t-etat);
}
.choices button:hover { border-color: var(--navy-light); background: var(--marble); }
.choices button.is-on,
.choices button[aria-pressed="true"] { background: var(--navy); border-color: var(--navy); color: var(--pearl); }

/* 5.3 · LES CASES A COCHER */
/* Meme motif que `.deux-portes` : c'est la largeur du PANNEAU qui decide,
   pas celle de la fenetre.  D-852 */
.check-grid { display: grid; gap: var(--e-2); grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr)); }

.check {
  display: flex; align-items: flex-start; gap: var(--e-2);
  min-height: var(--cible-champ);
  padding: 0.625rem 0.875rem;
  background: var(--pearl);
  border: var(--filet) solid var(--line-strong);
  border-radius: var(--rayon);
  cursor: pointer;
  transition: border-color var(--t-etat), background-color var(--t-etat);
}
.check:hover { border-color: var(--navy-light); box-shadow: var(--ombre-pose); }
.check--bloc { align-items: flex-start; }
/* La case est dessinee ici : `base.css` remet `background` et `border` a
   zero sur tout `input`, ce qui efface la case native.  D-849 */
.check input[type="checkbox"] {
  appearance: none; -webkit-appearance: none;
  flex: 0 0 auto;
  width: 1.375rem; height: 1.375rem;
  margin-top: 0.28rem;
  background: var(--pearl);
  border: 2px solid var(--line-strong);
  border-radius: var(--rayon);
  display: grid; place-content: center;
  transition: background-color var(--t-vif), border-color var(--t-vif);
}
.check input[type="checkbox"]:checked { background: var(--navy); border-color: var(--navy); }
.check input[type="checkbox"]:checked::after {
  content: "";
  width: 0.7rem; height: 0.35rem;
  border-left: 2px solid var(--pearl);
  border-bottom: 2px solid var(--pearl);
  transform: rotate(-45deg) translate(1px, -2px);
}
.check:has(input:checked) { border-color: var(--navy); background: var(--champagne-light); }
.check span strong { display: block; font-weight: 600; line-height: var(--lh-1); }
.check span small {
  display: block;
  font-size: var(--t-00); line-height: 1.5;
  color: var(--text-soft);
  margin-top: 0.15rem;
}

/* ===================================================================
   6 · LES CHAMPS — CE QUE LE SYSTEME N'A PAS ENCORE
   =================================================================== */

/* Dans une modale, l'etiquette d'un champ est du texte a LIRE avant de
   repondre : elle passe au corps, pas a la mention.  D-850 */
/* D-850 les montait a 19 px « pour qu'on les lise avant de repondre ».
   Elles etaient 27 % plus grosses que partout ailleurs sur le site, et
   c'est une des trois valeurs qui donnaient l'effet de loupe. Elles
   reviennent a la taille du reste — ce qui les fait lire, c'est leur
   graisse 600 et le blanc autour, pas leur corps.  D-985 */
.modal .etiquette,
.cadeau .etiquette { font-size: var(--t-00); line-height: 1.4; }

/* Le message de refus ne parait que quand le champ est refuse. Le script
   pose `.is-invalid` sur le `.field` et lie le texte par
   `aria-describedby` : la classe et l'attribut disent la meme chose. */
.field .refus,
.champ .refus { display: none; }
.field.is-invalid .refus,
.champ[data-refus] .refus { display: flex; }
.field.is-invalid .saisie {
  border-color: var(--danger);
  border-bottom-width: 3px;
  background: var(--danger-wash);
}
/* Un champ qui vient d'etre corrige le dit une fois, puis se tait. */
.field.is-valid .saisie { border-color: var(--ok); }

.field-note, .field-aide { max-width: 58ch; }
.field-aide--avant { margin-top: var(--e-4); }
/* `.opt` est l'ancien nom de `.facultatif` ; le script reecrit un libelle
   entier avec, il faut donc que les deux rendent pareil. */
.opt { font-weight: 400; color: var(--text-muted); }
/* Sur un fond silk ou champagne, `--text-muted` tombe sous 4,5:1. */
.devis .opt, .devis .facultatif,
.cond .opt, .cond .facultatif,
.porte .opt, .porte .facultatif { color: var(--text-soft); }

.form-note {
  margin-top: var(--e-3);
  font-size: var(--t-00); color: var(--text-soft);
  max-width: 58ch;
}

/* L'etat d'un envoi. Vide, il ne prend aucune place — un cadre vide sous
   chaque bouton est du bruit permanent. */
.form-status {
  margin-top: var(--e-2);
  font-size: var(--t-00); font-weight: 600;
  color: var(--text-soft);
}
.form-status:empty { display: none; }
.form-status.is-err {
  color: var(--danger);
  background: var(--danger-wash);
  padding: var(--e-2); border-radius: var(--rayon);
}
.form-status.is-ok {
  color: var(--ok);
  background: var(--ok-wash);
  padding: var(--e-2); border-radius: var(--rayon);
}

.form-legal { margin-top: var(--e-3); }

/* La porte de secours : le numero, la ou l'envie de decrocher est la plus
   forte. Elle vit HORS des ecrans, donc elle parait a tous.  D-783 */
.form-appel {
  margin-top: var(--e-4);
  font-size: var(--t-00); color: var(--text-soft);
}
.form-appel--pied {
  margin-top: var(--e-5); padding-top: var(--e-3);
  border-top: var(--filet) solid var(--line);
}
.appel-num {
  font-family: var(--font-titre);
  font-size: var(--t-1); letter-spacing: var(--ls-1);
  color: var(--navy-dark);
  text-decoration: none;
  white-space: nowrap;
}
.appel-num:hover { text-decoration: underline; text-decoration-color: var(--champagne-dark); text-underline-offset: 0.24em; }

/* Les deux chemins plus courts, sous la barre de navigation.  D-764 */
.form-portes {
  margin-top: var(--e-5); padding: var(--e-4);
  background: var(--marble);
  border-radius: var(--rayon-large);
}
.form-portes-quoi {
  font-size: var(--t-00); font-weight: 600;
  letter-spacing: var(--ls-etiquette); text-transform: uppercase;
  color: var(--text-soft);
  margin-bottom: var(--e-2);
}
.form-portes-choix { display: flex; flex-wrap: wrap; gap: var(--e-2); }
.form-portes-note { margin-top: var(--e-2); font-size: var(--t-00); color: var(--text-soft); }

/* Le repli d'envoi, fabrique par le script quand la porte ne repond pas. */
.form-repli {
  margin-top: var(--e-3); padding: var(--e-3);
  background: var(--silk);
  border-radius: var(--rayon);
  display: grid; gap: var(--e-2);
}

/* ===================================================================
   7 · LE CALENDRIER ET LES PLAGES
   =================================================================== */

.booking { display: grid; gap: var(--e-5); }
@media (min-width: 48em) {
  .booking { grid-template-columns: 1fr 15rem; gap: var(--e-6); }
}

.cal-head { display: flex; align-items: center; justify-content: space-between; gap: var(--e-2); }
.cal-mois {
  font-family: var(--font-titre);
  font-size: var(--t-1); letter-spacing: var(--ls-1);
  color: var(--navy-dark);
  text-transform: capitalize;
}
.cal-week {
  display: grid; grid-template-columns: repeat(7, 1fr);
  margin-top: var(--e-3);
  font-size: var(--t-00); font-weight: 600;
  color: var(--text-soft);
  text-align: center;
}
.cal-days { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; margin-top: var(--e-1); }
.cal-day {
  display: flex; align-items: center; justify-content: center;
  min-height: var(--cible-min);
  border-radius: var(--rayon);
  font-size: var(--t-00); font-weight: 600;
  color: var(--navy-dark);
  border: var(--filet) solid transparent;
  transition: background-color var(--t-vif), color var(--t-vif), border-color var(--t-vif);
}
.cal-day:hover:not(:disabled) { background: var(--marble); }
.cal-day:disabled { color: var(--text-muted); cursor: not-allowed; }
.cal-day.is-blank { pointer-events: none; }
/* Aujourd'hui se marque par un filet, pas par une couleur : un jour
   marque en couleur se lit comme un jour CHOISI. */
.cal-day.is-today { border-color: var(--champagne-dark); }
.cal-day.is-on { background: var(--navy); color: var(--pearl); border-color: var(--navy); }
.cal-long { display: none; }

/* SOUS 30em LA GRILLE LACHE. Sept colonnes dans un panneau de 288 px
   donnent des cases de 40 px, sous le seuil de 44 : se tromper de case
   ne rate pas un clic, ca reserve le mauvais jour.  D-740 */
@media (max-width: 29.99em) {
  .cal-week { display: none; }
  .cal-days { display: flex; flex-direction: column; gap: var(--e-1); }
  .cal-day:disabled, .cal-day.is-blank { display: none; }
  .cal-day {
    justify-content: flex-start;
    min-height: var(--cible);
    padding-inline: var(--e-3);
    border-color: var(--line);
  }
  .cal-num { display: none; }
  .cal-long { display: block; text-transform: capitalize; }
}

.slots { display: flex; flex-direction: column; }
.slots-title {
  font-size: var(--t-00); font-weight: 700;
  letter-spacing: var(--ls-etiquette); text-transform: uppercase;
  color: var(--text-soft);
  margin-bottom: var(--e-2);
}
.slots-list { display: grid; gap: var(--e-1); }
/* LE CRAN DE L'ATTENTE. Les plages restent lisibles, elles ne se
   cliquent plus. */
.slots-list.is-attente { opacity: 0.55; pointer-events: none; }
.slot {
  min-height: var(--cible);
  padding: 0 var(--e-3);
  background: var(--pearl);
  border: var(--filet) solid var(--line-strong);
  border-radius: var(--rayon);
  font-size: var(--t-00); font-weight: 600;
  color: var(--navy-dark);
  transition: border-color var(--t-etat), background-color var(--t-etat), color var(--t-etat);
}
.slot:hover { background: var(--navy); border-color: var(--navy); color: var(--pearl); }
.slot.is-on { background: var(--navy); border-color: var(--navy); color: var(--pearl); }

/* La note dit D'OU viennent les heures. Trois etats, jamais de silence :
   un visiteur qui ne sait pas si les plages sont a jour n'ose pas
   reserver.  D-726 */
.slots-note { margin-top: var(--e-2); font-size: var(--t-00); color: var(--text-soft); }
.slots-note.is-filet {
  padding: var(--e-2);
  background: var(--silk);
  border-left: 3px solid var(--champagne-dark);
  border-radius: 0 var(--rayon) var(--rayon) 0;
}
.slots-note.is-attente { color: var(--text-soft); font-style: italic; }

.empty { margin-top: var(--e-2); font-size: var(--t-00); color: var(--text-soft); }

.recap {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--e-2);
  margin-bottom: var(--e-5); padding: var(--e-2) var(--e-3);
  background: var(--silk);
  border-radius: var(--rayon);
  font-weight: 600; color: var(--text);
}

/* ===================================================================
   8 · LE DEPOT DE FICHIERS
   =================================================================== */

.dropzone {
  display: grid; justify-items: center; gap: var(--e-1);
  padding: var(--e-5) var(--e-3);
  text-align: center;
  background: var(--pearl);
  border: 2px dashed var(--line-strong);
  border-radius: var(--rayon-large);
  cursor: pointer;
  transition: border-color var(--t-etat), background-color var(--t-etat);
}
.dropzone:hover { border-color: var(--navy-light); }
.dropzone.is-over { border-color: var(--navy); background: var(--champagne-light); }
.dropzone > svg { width: 2rem; height: 2rem; color: var(--navy-light); }
.dropzone strong { font-weight: 600; }
.dropzone > span { font-size: var(--t-00); color: var(--text-soft); }

.file-list { display: grid; gap: var(--e-1); margin-top: var(--e-2); }
.file-list li {
  display: flex; align-items: center; justify-content: space-between; gap: var(--e-2);
  min-height: var(--cible-min);
  padding: var(--e-1) var(--e-1) var(--e-1) var(--e-2);
  background: var(--silk);
  border-radius: var(--rayon);
  font-size: var(--t-00);
}
.file-list li.is-warn {
  background: var(--danger-wash);
  color: var(--danger);
  font-weight: 600;
  padding: var(--e-2);
}

/* ===================================================================
   9 · LA FOURCHETTE
   Elle ne parait qu'apres un formulaire complete, et le texte dit ce
   qu'elle vaut : « ordre de grandeur, pas un devis ».  D-748
   =================================================================== */

.devis {
  margin-top: var(--e-4);
  padding: var(--e-4);
  background: var(--silk);
  border-radius: var(--rayon-large);
}
.devis-quoi { color: var(--text-soft); max-width: 44ch; }
.devis-montant {
  font-family: var(--font-titre);
  font-size: var(--t-4); line-height: 1.05; letter-spacing: var(--ls-4);
  color: var(--navy-dark);
  margin-top: var(--e-2);
}
.devis-montant--petit { font-size: var(--t-3); letter-spacing: var(--ls-3); }
.devis-sur { margin-top: var(--e-1); font-size: var(--t-00); color: var(--text-soft); }

/* LA NOTE VIENT AVEC LE CHIFFRE, PAS PLUS BAS. Elle porte son propre
   titre et elle est sur son propre fond : elle doit etre LUE. Une
   reserve enterree en petits caracteres ne protege personne.  D-784 */
.devis-note {
  margin-top: var(--e-4); padding: var(--e-3);
  background: var(--pearl);
  border-left: 3px solid var(--champagne-dark);
  border-radius: 0 var(--rayon) var(--rayon) 0;
}
.devis-note-t {
  font-size: var(--t-00); font-weight: 700;
  letter-spacing: var(--ls-etiquette); text-transform: uppercase;
  color: var(--navy-dark);
  margin-bottom: var(--e-2);
}
.devis-note p { color: var(--text); }

.devis-question, .devis-suite, .devis-petit {
  margin-top: var(--e-4); padding-top: var(--e-4);
  border-top: var(--filet) solid var(--line-strong);
}
.devis-demande { font-weight: 600; margin-bottom: var(--e-2); }
.devis-mise { color: var(--text-soft); margin-bottom: var(--e-3); max-width: 56ch; }
.devis-retire { display: grid; gap: var(--e-1); margin: var(--e-2) 0 var(--e-3); }
.devis-retire li {
  position: relative; padding-left: var(--e-2);
  font-size: var(--t-00); color: var(--text);
}
.devis-retire li::before {
  content: "·"; position: absolute; left: 0;
  color: var(--champagne-dark); font-weight: 700;
}
.devis--sansprix .devis-quoi {
  font-family: var(--font-titre);
  font-size: var(--t-2); line-height: var(--lh-2); letter-spacing: var(--ls-2);
  color: var(--navy-dark);
}

.estim-resume {
  font-family: var(--font-titre);
  font-size: var(--t-1); line-height: var(--lh-1); letter-spacing: var(--ls-1);
  color: var(--navy-dark);
  margin-bottom: var(--e-3);
}
.estim-note { margin-top: var(--e-4); font-size: var(--t-00); color: var(--text-soft); }

/* ===================================================================
   10 · LES CONDITIONS DU PROGRAMME DE REFERENCE
   LE TEXTE EST ICI, PAS AU BOUT D'UN LIEN : un lien qui ouvre une autre
   page fait perdre cinq ecrans de saisie a celui qui le suit.  D-773
   =================================================================== */

.cond-puces { display: grid; gap: var(--e-2); margin-bottom: var(--e-4); }
/* LA PUCE EST POSEE, PAS EMPILEE. En `display: flex`, le `<b>` de tete
   devient un ELEMENT FLEX et la fin de la phrase un autre : « Votre prime
   depend du type de projet signe » se retrouvait a gauche et « , pas de
   son prix » a droite, avec un trou entre les deux. Vu a l'image.  D-851 */
.cond-puces li {
  position: relative;
  padding-left: var(--e-3);
  color: var(--text-soft);
}
.cond-puces li::before {
  content: ""; position: absolute; left: 0; top: 0.62rem;
  width: 0.5rem; height: 0.5rem;
  background: var(--champagne-dark);
  border-radius: var(--rayon);
}
.cond-puces b { color: var(--text); }

.cond-tiroir { margin-bottom: var(--e-5); }
.btn--tiroir { justify-content: space-between; text-align: left; }
.btn--tiroir .icon--moins { display: none; }
.btn--tiroir[aria-expanded="true"] .icon--plus { display: none; }
.btn--tiroir[aria-expanded="true"] .icon--moins { display: block; }

.cond {
  margin-top: var(--e-2);
  padding: var(--e-4);
  max-height: 26rem; overflow-y: auto; overscroll-behavior: contain;
  background: var(--silk);
  border-radius: var(--rayon-large);
  font-size: var(--t-00); line-height: 1.6;
  color: var(--text);
}
.cond-t {
  font-family: var(--font-titre);
  font-size: var(--t-1); line-height: var(--lh-1); letter-spacing: var(--ls-1);
  color: var(--navy-dark);
  margin: var(--e-4) 0 var(--e-2);
}
.cond-t:first-child { margin-top: 0; }
.cond p + p { margin-top: var(--e-2); }
.cond-grille {
  width: 100%; margin: var(--e-3) 0;
  border-collapse: collapse;
  background: var(--pearl);
  border-radius: var(--rayon);
  overflow: hidden;
}
.cond-grille th, .cond-grille td {
  padding: var(--e-2);
  text-align: left;
  border-bottom: var(--filet) solid var(--line);
}
.cond-grille th {
  font-size: var(--t-00); font-weight: 700;
  letter-spacing: var(--ls-etiquette); text-transform: uppercase;
  color: var(--navy-dark);
}
.cond-grille tr:last-child td { border-bottom: 0; }
.cond-prime { text-align: right; white-space: nowrap; color: var(--navy-dark); }
.cond-version { margin-top: var(--e-4); color: var(--text-soft); }

/* ===================================================================
   11 · LES DEUX PORTES DE L'URGENCE
   Une vraie urgence n'ecrit pas : elle appelle. Le numero passe donc
   DEVANT, en gros, et c'est un vrai lien `tel:`.  D-751
   =================================================================== */

/* `auto-fit`, PAS UNE REQUETE DE MEDIA. Une requete de media mesure la
   FENETRE ; ici ce qui compte est la largeur du PANNEAU, qui plafonne a
   38 rem quelle que soit la fenetre. A 1440 px les deux portes tombaient
   donc en deux colonnes de 240 px, et le numero de 38 px n'y tenait
   plus.  D-852 */
.deux-portes {
  display: grid; gap: var(--e-2); margin-bottom: var(--e-6);
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
}

.porte {
  padding: var(--e-4);
  background: var(--marble);
  border-radius: var(--rayon-large);
}
/* Le champagne clair porte du navy a 9,41:1 : il peut etre un FOND. */
.porte--forte { background: var(--champagne-light); }
.porte-quand {
  font-size: var(--t-00); font-weight: 700;
  letter-spacing: var(--ls-etiquette); text-transform: uppercase;
  color: var(--navy-dark);
  margin-bottom: var(--e-2);
}
/* LA PORTE FORTE DE L'URGENCE PORTAIT LE NUMERO EN GROS.  D-992
   Elle porte maintenant le DELAI, dans la meme graisse et a la meme
   place : c'est la seule chose qu'on controle et qu'on peut donc
   promettre. `white-space: nowrap` est parti avec le numero — un delai
   sur deux lignes se lit tres bien, un numero coupe en deux, non. */
.porte-delai {
  margin-top: var(--e-1);
  font-family: var(--font-titre);
  font-size: var(--t-2); line-height: 1.15; letter-spacing: var(--ls-2);
  color: var(--navy-dark);
}
.porte-delai b { font-weight: 560; }
.porte-note, .porte-texte { margin-top: var(--e-2); font-size: var(--t-00); color: var(--text-soft); }

/* ===================================================================
   12 · LA RETENUE
   Elle ne bloque rien : Echap la ferme, le fond aussi, et « Je continue »
   rend la main au formulaire exactement ou il en etait.  D-753
   =================================================================== */

.retenue {
  position: fixed; inset: auto 0 0 0; z-index: calc(var(--z-modal) + 1);
  display: flex; justify-content: flex-end;
  padding: var(--e-2);
  pointer-events: none;
}
@media (min-width: 48em) { .retenue { padding: var(--e-4); } }

.retenue-in {
  pointer-events: auto;
  width: 100%; max-width: 26rem;
  padding: var(--e-4);
  background: var(--pearl);
  border: var(--filet) solid var(--line);
  border-radius: var(--rayon-large);
  box-shadow: var(--ombre-levee);
}
/* `.sur-titre` accroche un filet en `::after` : sur deux lignes il reste
   colle a la PREMIERE et flotte dans le vide. Ces deux libelles-la sont
   ecrits par le script, longueur inconnue — le filet saute.  D-853 */
.retenue-quoi::after, .cadeau-eyebrow::after { display: none; }

.retenue-titre {
  font-size: var(--t-2); line-height: var(--lh-2); letter-spacing: var(--ls-2);
  margin-bottom: var(--e-2);
}
.retenue-texte { font-size: var(--t-00); color: var(--text-soft); }
.retenue-champ { display: grid; gap: var(--e-2); margin-top: var(--e-4); }
.retenue-champ .btn { width: 100%; }
.retenue-suite { margin-top: var(--e-3); }

/* ===================================================================
   13 · LE CADEAU — `<dialog>` natif, `showModal()`
   Ce n'est pas un cadeau, c'est un echange, et le balisage le dit.  D-083
   =================================================================== */

.cadeau {
  width: min(100% - 2rem, 58rem);
  max-height: 92vh;
  margin: auto;
  padding: 0;
  background: var(--pearl);
  border: 0;
  border-radius: var(--rayon-large);
  box-shadow: var(--ombre-levee);
  color: var(--text);
  overflow: hidden;
}
.cadeau::backdrop { background: var(--scrim); }
.cadeau-in { position: relative; display: grid; max-height: 92vh; overflow-y: auto; }
/* LA MENTION LEGALE ETAIT ROGNEE, SANS ASCENSEUR, SUR ORDINATEUR.  D-977
   `max-height` sur un conteneur de grille NE COMPRIME PAS une piste `auto` :
   la rangee prenait la hauteur de son contenu (1 137 px pour 828 de boite) et
   `overflow: hidden` coupait le reste — la phrase s'arretait sur « Politique
   de confi ». `minmax(0, 1fr)` force la rangee dans la boite ; le `min-height:
   0` de `.cadeau-dire` laisse enfin son propre `overflow-y: auto` mordre.
   Sous 52em rien ne changeait : la grille etait a une colonne et defilait. */
@media (min-width: 52em) {
  .cadeau-in { grid-template-columns: 0.85fr 1fr; grid-template-rows: minmax(0, 1fr); overflow: hidden; }
}
.cadeau-x { position: absolute; top: var(--e-1); right: var(--e-1); z-index: 2; background: var(--pearl); }

.cadeau-vue {
  display: none;
  position: relative;
  background: var(--silk);
  padding: var(--e-7) var(--e-5);
}
@media (min-width: 52em) { .cadeau-vue { display: block; } }
.cadeau-couv {
  position: absolute;
  width: 58%; height: auto;
  border-radius: var(--rayon);
  box-shadow: var(--ombre-levee);
}
.cadeau-couv--1 { top: 12%; left: 10%; transform: rotate(-4deg); }
.cadeau-couv--2 { top: 24%; left: 32%; transform: rotate(3deg); }

.cadeau-dire { padding: var(--e-5) var(--e-4) var(--e-4); overflow-y: auto; min-height: 0; }
@media (min-width: 52em) { .cadeau-dire { padding: var(--e-6) var(--e-5); } }
.cadeau-titre {
  font-size: var(--t-3); line-height: var(--lh-3); letter-spacing: var(--ls-3);
  margin-bottom: var(--e-3);
}
/* Les trois chiffres. Le premier porte la valeur, « 91 pages » vient en
   dernier : un patron de 55 ans lit « 91 pages » comme « je ne lirai
   jamais ca ».  D-782 */
.cadeau-fiche {
  display: flex; flex-wrap: wrap; gap: var(--e-3);
  padding: var(--e-2) 0;
  border-block: var(--filet) solid var(--line);
  margin-bottom: var(--e-3);
}
.cadeau-fiche span {
  display: flex; align-items: baseline; gap: 0.35rem;
  font-size: var(--t-00); color: var(--text-soft);
}
.cadeau-fiche b {
  font-family: var(--font-titre);
  font-size: var(--t-2); letter-spacing: var(--ls-2);
  color: var(--navy-dark);
}
.cadeau-lead { color: var(--text-soft); margin-bottom: var(--e-4); }
.cadeau-lead b { color: var(--text); }
.cadeau-go { margin-top: var(--e-4); }
.cadeau-fin { margin-top: var(--e-3); font-size: var(--t-00); color: var(--text-muted); }
.cadeau-actes { display: grid; gap: var(--e-2); margin-top: var(--e-4); }
.cadeau-liens { margin-top: var(--e-3); font-size: var(--t-00); color: var(--text-soft); }
.cadeau-non { margin-top: var(--e-3); }

/* ===================================================================
   14 · LES SUGGESTIONS DE VILLE ET DE DOMAINE
   Le champ garde son `<datalist>` : c'est le repli sans JavaScript. Le
   panneau fabrique par le script se pose par-dessus.  D-759
   =================================================================== */

.champ { position: relative; }
.sug {
  position: absolute; z-index: 3; left: 0; right: 0;
  max-height: 18rem; overflow-y: auto;
  background: var(--pearl);
  border: var(--filet) solid var(--line-strong);
  border-radius: var(--rayon);
  box-shadow: var(--ombre-levee);
}
.sug-o {
  display: flex; align-items: center;
  width: 100%;
  min-height: var(--cible-min);
  padding: 0 var(--e-2);
  text-align: left;
  font-size: var(--t-00);
  color: var(--text);
  border-left: 3px solid transparent;
}
.sug-o:hover, .sug-o.is-on { background: var(--champagne-light); border-left-color: var(--navy); }
.sug-o b { font-weight: 700; color: var(--navy-dark); }

/* ===================================================================
   FUSIONNE DEPUIS pages.css
   =================================================================== */

/* == ADEXWEB — LE STYLE DES QUATRE PAGES INTERIEURES ==
      services.html · processus.html · contact.html · reference.html

      CE FICHIER N'EST PAS SERVI. Il est le brouillon d'une fusion dans
      `css/app.css`, qui reste la seule source. Les pages livrees ne le
      chargent pas : le lien de travail a ete retire avant la remise.

      Il ne redefinit aucune classe d'`app.css` sauf trois corrections de
      contraste, nommees et justifiees en section 9.
      Ordre de fusion : a la SUITE d'`app.css`, jamais avant — deux regles
      de meme specificite s'y departagent par l'ordre.
   ================================================================== */


/* ===================================================================
   1 · L'EN-TETE DE PAGE
   Un seul h1 par page, et il ne monte JAMAIS a --t-5 : ce cran-la est
   celui de l'accueil. Deux pages qui crient aussi fort ne disent plus
   laquelle est la porte d'entree.
   =================================================================== */

.titre-page {
  font-size: var(--t-4);
  line-height: var(--lh-4);
  letter-spacing: var(--ls-4);
  font-weight: 460;
  max-width: 18ch;
}

/* La premiere bande remplace le hero : elle respire plus haut que les
   suivantes, sans en prendre la hauteur. */
.bande--entete { padding-block: var(--e-5) var(--e-6); }
@media (min-width: 62em) { .bande--entete { padding-block: var(--e-7) var(--e-8); } }

/* Le filet d'`app.css` ne separe que deux bandes de MEME fond. Apres une
   bande coloree, le changement de fond separe deja : un filet de plus
   n'est qu'un trait qui traine. */
.bande--silk + .bande:not([class*="--"]),
.bande--marble + .bande:not([class*="--"]),
.bande--navy + .bande:not([class*="--"]) { border-top: 0; }


/* ===================================================================
   2 · LES ANCRES DE PAGE
   Cinq raccourcis vers les cinq services. Ce n'est pas une seconde idee
   dans la bande : c'est la table de ce qu'elle annonce.
   =================================================================== */

.ancres {
  display: flex; flex-wrap: wrap; gap: var(--e-1);
  margin-top: var(--e-5);
  padding-top: var(--e-3);
  border-top: var(--filet) solid var(--line);
}
.ancre {
  display: inline-flex; align-items: center; gap: var(--e-1);
  min-height: var(--cible-min);
  padding-inline: var(--e-2);
  font-size: var(--t-00); font-weight: 600;
  color: var(--navy-dark); text-decoration: none;
  border: var(--filet) solid var(--line-strong);
  border-radius: var(--rayon);
  transition: border-color var(--t-etat), background-color var(--t-etat);
}
.ancre:hover { border-color: var(--navy-light); background: var(--marble); }
.ancre b { color: var(--text-soft); font-weight: 700; letter-spacing: var(--ls-etiquette); }


/* ===================================================================
   3 · CE QUI EST INCLUS — la colonne de droite d'un service
   Le crochet est une icone PORTEUSE DE SENS : elle dit « compris ».
   Elle est donc en navy, jamais en champagne (2,63:1 au mieux).
   =================================================================== */

.inclus { display: grid; gap: var(--e-3); align-content: start; }
.liste-oui { display: grid; gap: var(--e-2); }
.liste-oui li {
  display: flex; align-items: flex-start; gap: var(--e-2);
  font-size: var(--t-0); line-height: var(--lh-0);
  color: var(--text);
}
.liste-oui svg {
  width: 1.25rem; height: 1.25rem; flex: 0 0 auto;
  margin-top: 0.34rem; color: var(--navy);
}

/* Le delai est une donnee, pas une mention : il porte son chiffre en
   pleine couleur de texte. */
.delai {
  display: flex; align-items: flex-start; gap: var(--e-1);
  margin-top: var(--e-4);
  font-size: var(--t-00); color: var(--text-soft);
}
.delai svg {
  width: 1.0625rem; height: 1.0625rem; flex: 0 0 auto;
  margin-top: 0.18rem; color: var(--navy);
}
.delai b { color: var(--text); font-weight: 600; }

/* Une precision qui ne tient pas dans la liste : elle reste du CORPS,
   19 px, jamais une mention de 15. Dans une carte, `.carte p` d'`app.css`
   la ferait tomber a 15 : on la retient a deux classes. */
.precision {
  margin-top: var(--e-3);
  color: var(--text-soft);
  max-width: 58ch;
}
.carte .precision { font-size: var(--t-0); line-height: var(--lh-0); }


/* ===================================================================
   4 · LES ETAPES — un rail, pas un accordeon
   Deux colonnes : le numero, puis tout le reste. Le livrable descend
   SOUS le texte et n'ouvre pas une troisieme colonne — notre lecteur
   descend une colonne, il ne balaye pas une grille.
   64 px entre deux etapes sous 992, 96 px au-dela (rythme § 6.3).
   =================================================================== */

.etapes { display: grid; }
.etape {
  display: grid; gap: var(--e-2);
  padding-block: var(--e-4);
  border-top: var(--filet) solid var(--line);
  align-items: start;
}
.etape:last-child { border-bottom: var(--filet) solid var(--line); }

.etape-num {
  font-family: var(--font-texte);
  font-size: var(--t-00); font-weight: 700;
  letter-spacing: var(--ls-etiquette);
  color: var(--text-soft);
}
.etape-nom {
  font-size: var(--t-2); line-height: var(--lh-2); letter-spacing: var(--ls-2);
}
.etape-dit {
  margin-top: var(--e-1);
  color: var(--text-soft);
  max-width: 58ch;
}
.etape-corps { display: grid; gap: var(--e-3); }

/* Le livrable est ce qui reste dans les mains du client : il porte le
   seul filet champagne de la page, a gauche, la ou l'oeil revient. */
.livrable {
  display: grid; gap: 0.15rem;
  padding-left: var(--e-3);
  border-left: 3px solid var(--champagne);
}
.livrable span {
  font-size: var(--t-00); font-weight: 700;
  letter-spacing: var(--ls-etiquette); text-transform: uppercase;
  color: var(--text-soft);
}
.livrable b { font-weight: 600; color: var(--text); }

@media (min-width: 48em) {
  .etape { grid-template-columns: 3.5rem 1fr; gap: var(--e-3) var(--e-4); }
  .etape-num { padding-top: 0.5rem; }
}
@media (min-width: 62em) { .etape { padding-block: var(--e-6); } }


/* ===================================================================
   5 · LES QUESTIONS — `<details>` natif
   Le marqueur ne tourne pas : il CHANGE. Un plus devient un moins. Le
   site n'a droit qu'a un seul geste, et il est deja pris par l'entree.
   =================================================================== */

/* 736 px, pas les 1120 de la colonne utile : au-dela, le marqueur `+` se
   retrouve a un demi-metre de la question qu'il ouvre, et le lien entre les
   deux se perd. */
.questions {
  display: grid;
  max-width: 46rem;
  border-top: var(--filet) solid var(--line);
}
.question { border-bottom: var(--filet) solid var(--line); }

.question > summary {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: var(--e-3);
  min-height: var(--cible);
  padding-block: var(--e-3);
  font-family: var(--font-titre);
  font-size: var(--t-1); line-height: var(--lh-1); letter-spacing: var(--ls-1);
  color: var(--navy-dark);
  cursor: pointer;
  list-style: none;
}
.question > summary::-webkit-details-marker { display: none; }
.question > summary:hover { color: var(--navy-light); }

.question-icone {
  width: 1.5rem; height: 1.5rem; flex: 0 0 auto;
  margin-top: 0.4rem; color: var(--navy);
}
.question:not([open]) .question-icone--moins { display: none; }
.question[open] .question-icone--plus { display: none; }

.question-dit {
  padding-bottom: var(--e-4);
  max-width: var(--colonne-texte);
}
.question-dit p { color: var(--text-soft); }
.question-dit b { color: var(--text); font-weight: 600; }
.question-dit .actes { margin-top: var(--e-3); }


/* ===================================================================
   6 · NOUS JOINDRE
   =================================================================== */

/* Le numero est la porte que cherche un patron de 55 ans. Il est en
   grand, en serif, et c'est un lien — pas une image de numero. */
/* `.tel-geant` — le numero en tres gros du hero de contact et de l'encart
   de la FAQ — est parti avec le numero.  D-992 */

/* Les cinq portes. Deux colonnes au plus ; la porte recommandee prend la
   largeur, parce qu'une recommandation qui a la meme taille que le reste
   n'en est plus une. */
.tuiles { display: grid; gap: var(--e-3); }
@media (min-width: 48em) {
  .tuiles { grid-template-columns: repeat(2, 1fr); }
  .tuile--large { grid-column: 1 / -1; }
}
/* Une tuile est un BOUTON : son contenu est du texte en ligne, jamais un
   `<h3>` ni un `<p>` — le modele de contenu d'un bouton ne les admet pas,
   et un titre dans un bouton brouille l'annonce du lecteur d'ecran. Le
   nom de la tuile reprend donc a la main ce que la base donnait au `<h3>`. */
.tuile .carte-titre {
  display: block;
  font-family: var(--font-titre); font-weight: 440;
  color: var(--navy-dark);
  text-wrap: balance;
}
/* `.carte p` d'`app.css` descend a 15 px. Ici c'est du CORPS : 19. */
.tuile-dit {
  display: block;
  font-size: var(--t-0); line-height: var(--lh-0);
  color: var(--text-soft);
}
.tuile-ou {
  display: flex; align-items: center; gap: var(--e-1);
  margin-top: var(--e-1);
  font-size: var(--t-00); font-weight: 600;
  color: var(--navy-dark);
}
.tuile-ou svg { width: 1rem; height: 1rem; transition: transform var(--t-etat); }
.tuile:hover .tuile-ou svg { transform: translateX(3px); }

/* Les quatre garanties : un mot, une phrase. */
.garanties { display: grid; gap: var(--e-5); }
@media (min-width: 48em) { .garanties { grid-template-columns: repeat(2, 1fr); } }
.garantie {
  display: grid; gap: var(--e-1);
  padding-left: var(--e-3);
  border-left: 3px solid var(--champagne);
}
.garantie p { color: var(--text-soft); }

/* Le septieme formulaire : le message ordinaire. */
.form-contact { display: grid; gap: var(--e-5); max-width: 44rem; }
.form-status { font-size: var(--t-00); font-weight: 600; color: var(--text-soft); }
.form-status:empty { display: none; }
.form-appel { color: var(--text-soft); }
.form-appel a {
  font-weight: 600; color: var(--navy-dark);
  text-decoration-color: var(--champagne-dark);
  text-decoration-thickness: 2px;
  text-underline-offset: 0.24em;
}


/* ===================================================================
   7 · LE PROGRAMME DE REFERENCE
   Le champagne porte le montant EN FOND, avec du navy dessus : 11,2:1.
   Il ne porte jamais le trait ni la lettre.
   =================================================================== */

.prime-max {
  display: grid; gap: var(--e-2);
  padding: var(--e-5);
  background: var(--champagne-light);
  border-radius: var(--rayon-large);
}
.prime-max .etiquette-prime {
  font-size: var(--t-00); font-weight: 700;
  letter-spacing: var(--ls-etiquette); text-transform: uppercase;
  color: var(--navy-dark);
}
.prime-max .chiffre {
  font-size: var(--t-4); line-height: var(--lh-4); letter-spacing: var(--ls-4);
  color: var(--navy-dark);
}
.prime-max p { color: var(--navy-dark); }


/* ===================================================================
   8 · LES CONDITIONS — bloc GENERE par `tools/conditions.mjs`
   Le HTML entre les bornes ne s'ecrit jamais a la main : ces regles
   habillent des balises qu'un outil produit. Ne renommer aucune classe
   `cond-*` sans toucher au convertisseur.
   =================================================================== */

.conditions { max-width: var(--colonne-texte); }
.conditions p { margin-top: var(--e-2); color: var(--text-soft); }
.conditions strong { color: var(--text); font-weight: 600; }

.cond-t {
  font-family: var(--font-titre);
  font-size: var(--t-1); line-height: var(--lh-1); letter-spacing: var(--ls-1);
  color: var(--navy-dark);
  margin-top: var(--e-6);
}
.cond-t:first-child { margin-top: 0; }

/* `table-layout: fixed` : sans lui, la ligne la plus longue de la grille
   pousse la page au-dela de 320 px de large. */
.cond-grille {
  width: 100%; table-layout: fixed; border-collapse: collapse;
  margin-top: var(--e-3);
  background: var(--pearl);
  border: var(--filet) solid var(--line);
}
.cond-grille th,
.cond-grille td {
  text-align: left; vertical-align: top;
  padding: var(--e-2);
  border-bottom: var(--filet) solid var(--line);
  font-size: var(--t-0); line-height: var(--lh-0);
}
.cond-grille th {
  font-family: var(--font-texte);
  font-size: var(--t-00); font-weight: 700;
  letter-spacing: var(--ls-etiquette); text-transform: uppercase;
  color: var(--text-soft);
}
.cond-grille tbody tr:last-child td { border-bottom: 0; }
/* `.cond-grille td` pose `text-align: left` a deux crans : la classe seule
   ne le bat pas, et les montants restaient colles au libelle. */
.cond-grille td.cond-prime { text-align: right; white-space: nowrap; }
.cond-prime b { color: var(--navy-dark); font-weight: 600; }
/* Sous 768 les deux colonnes se partagent la largeur : une colonne de
   montants figee a 9 rem y laisserait des libelles de trois mots par ligne. */
@media (min-width: 48em) {
  /* 11 rem : « VOTRE PRIME » en capitales espacees tient sur UNE ligne. */
  .cond-grille th:last-child,
  .cond-grille td:last-child { width: 11rem; }
  .cond-grille th:last-child { text-align: right; }
}

.cond-version {
  margin-top: var(--e-6);
  padding-top: var(--e-3);
  border-top: var(--filet) solid var(--line);
  font-size: var(--t-00);
}


/* ===================================================================
   9 · TROIS CORRECTIONS DE CONTRASTE — les seules redefinitions
   `--text-muted` rend 3,88:1 sur silk et 3,83:1 sur marble : il y est
   INTERDIT (D-803). Trois classes d'`app.css` le posent en dur et se
   retrouvent sur ces fonds dans ces quatre pages.
   =================================================================== */

.bande--silk .facultatif,   .bande--marble .facultatif,
.bande--silk .mention,      .bande--marble .mention,
.bande--silk .service-num,  .bande--marble .service-num,
.bande--silk .service-delai, .bande--marble .service-delai { color: var(--text-soft); }

/* ===================================================================
   FUSIONNE DEPUIS visuel.css
   =================================================================== */

/* == ADEXWEB — LE STYLE DES DEUX PAGES VISUELLES ==
      realisations.html · automatisation.html

      CE FICHIER N'EST PAS SERVI. Il est le brouillon d'une fusion dans
      `css/app.css`, qui reste la seule source. Les deux pages livrees ne
      le chargent pas : le lien de travail a ete retire avant la remise.
      Ordre de fusion : a la SUITE d'`app.css`, jamais avant.

      DEUX DEPENDANCES EXTERIEURES, chargees telles quelles par les pages
      et JAMAIS modifiees : `css/secteurs.css` (les treize maquettes) et
      `css/tour360.css` (la visite 360). Les deux sont ecrites contre les
      jetons de l'ANCIENNE identite, qui n'existent plus. La section 0
      leur en rend la valeur nouvelle, sur les seuls elements concernes.

      DOUBLON ASSUME avec `refonte-adexweb/css-a-fusionner/pages.css` :
      la section 1 y est identique (`.titre-page`, `.bande--entete`, la
      remise a zero du filet). A LA FUSION, N'EN GARDER QU'UNE.

      SOMMAIRE
        0 · Le pont de jetons vers les deux feuilles heritees
        1 · L'en-tete de page              (doublon de pages.css § 1)
        2 · L'aveu de demonstration
        3 · Avant / apres — le cadre, la vitre, la poignee
        4 · Les treize apercus de secteur
        5 · Les neuf sites de demonstration
        6 · La visite 360 — les complements
        7 · Le calculateur
        8 · Le comparatif a la main / automatise
        9 · Les deux guides
       10 · LES RECONSTITUTIONS « AVANT » — HORS SYSTEME D'IDENTITE
   ================================================================== */


/* ===================================================================
   0 · LE PONT DE JETONS
   `css/secteurs.css` et `css/tour360.css` ne sont pas a nous a
   reecrire : ils nomment des jetons de l'ancienne identite. Plutot que
   de les toucher, on leur redonne une valeur — la NOUVELLE — sur les
   trois racines qui les portent. Les proprietes personnalisees
   heritent : tout descendant est couvert.

   TROIS NOMS NE SONT PAS PONTES, ET C'EST VOULU : `--t-1` a `--t-4`
   sont des DUREES dans l'ancien systeme et des TAILLES DE TEXTE dans
   le nouveau. Les ponter casserait la typographie de tout ce qui vit
   dans ces trois racines. Non pontes, les `transition` qui les citent
   deviennent invalides et tombent — on perd un fondu, jamais une
   information.
   =================================================================== */

.ba-scene,
.sector-preview,
.tour {
  --surface-0: var(--pearl);
  --surface-1: var(--marble);
  --surface-2: var(--silk);
  --surface-inverse: var(--navy-dark);

  --ink: var(--text);
  --ink-muted: var(--text-soft);
  --ink-inverse: var(--pearl);

  /* Le champagne reste DECOR. Partout ou l'ancien `--accent-text`
     portait des lettres, il vaut donc `--navy` : 13,37:1. */
  --accent: var(--champagne);
  --accent-text: var(--navy);
  --accent-ink: var(--navy-dark);
  --accent-wash: var(--champagne-light);
  --accent-on-inverse: var(--champagne-light);

  --rule: var(--line);
  --rule-strong: var(--line-strong);
  --rule-w: var(--filet);

  --font-text: var(--font-texte);
  --font-data: var(--font-texte);
  --font-display: var(--font-titre);

  --fs-4: var(--t-1);
  --fs-5: var(--t-0);
  --fs-6: var(--t-00);
  --fs-7: var(--t-00);
  --fs-8: var(--t-00);
  --measure: var(--colonne-texte);
  --tracking-label: var(--ls-etiquette);

  --s-1: 0.25rem;
  --s-2: var(--e-1);
  --s-3: 0.75rem;
  --s-4: var(--e-2);
  --s-5: var(--e-3);
  --s-6: var(--e-4);
  --s-7: var(--e-6);

  --e-snap: var(--m-courbe);
  --e-brake: var(--e-sortie);
  --e-drive: var(--m-courbe);
}


/* ===================================================================
   1 · L'EN-TETE DE PAGE — DOUBLON de `pages.css` § 1
   Un seul h1 par page, et il ne monte JAMAIS a --t-5 : ce cran-la est
   celui de l'accueil.
   =================================================================== */

.titre-page {
  font-size: var(--t-4);
  line-height: var(--lh-4);
  letter-spacing: var(--ls-4);
  font-weight: 460;
  max-width: 18ch;
}
.bande--entete { padding-block: var(--e-5) var(--e-6); }
@media (min-width: 62em) { .bande--entete { padding-block: var(--e-7) var(--e-8); } }

.bande--silk + .bande:not([class*="--"]),
.bande--marble + .bande:not([class*="--"]),
.bande--navy + .bande:not([class*="--"]) { border-top: 0; }


/* ===================================================================
   2 · L'AVEU DE DEMONSTRATION
   Il est dit UNE fois, en haut de la page, AU-DESSUS de tout ce qu'il
   couvre — les quatre comparateurs, les treize apercus, la visite. En
   CORPS (19 px), jamais en mention de 15 sous une image : une reserve
   ecrite plus petit que ce qu'elle corrige est un petit caractere.
   Les blocs suivants portent une etiquette neutre, pas une seconde
   confession : une reserve dite trois fois se lit « on n'a jamais rien
   livre ».
   =================================================================== */

.aveu {
  margin-top: var(--e-5);
  padding: var(--e-3) var(--e-4);
  border-left: 3px solid var(--champagne);
  background: var(--silk);
  border-radius: 0 var(--rayon) var(--rayon) 0;
  max-width: 62ch;
}
.aveu b { font-weight: 600; color: var(--text); }
.bande--silk .aveu, .bande--marble .aveu { background: var(--pearl); }

/* L'etiquette neutre, en tete de chaque bloc concerne. */
.etiquette-demo {
  display: inline-flex; align-items: center;
  padding: 0.3rem 0.6rem;
  margin-bottom: var(--e-4);
  font-size: var(--t-00); font-weight: 700;
  letter-spacing: var(--ls-etiquette); text-transform: uppercase;
  color: var(--navy-dark);
  background: var(--champagne-light);
  border-radius: var(--rayon);
}


/* ===================================================================
   3 · AVANT / APRES — quatre demonstrations
   L'unite interne du cadre est le `cqw` : la maquette « avant » est
   dessinee a l'echelle de la fenetre, pas de la page. Sans
   `container-type`, aucun `cqw` ne veut rien dire.
   La poignee est un `input[type=range]` NATIF : la valeur, le clavier,
   l'annonce vocale et l'anneau de mise au point viennent du navigateur.
   Le script ne fait que reporter sa valeur dans `--ba-p`.
   =================================================================== */

.ba-grille { display: grid; gap: var(--e-8); }
@media (min-width: 62em) {
  .ba-grille { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--e-9) var(--e-7); }
}

.ba { display: grid; gap: var(--e-3); align-content: start; }

/* Le cadre porte la requete de conteneur : la barre du haut se met a
   l'echelle de l'ecran, comme la page dedans. */
.ba-cadre {
  position: relative;
  container-type: inline-size;
  border: var(--filet) solid var(--line-strong);
  border-radius: var(--rayon-large);
  overflow: hidden;
  background: var(--pearl);
  box-shadow: var(--ombre-pose);
}

.ba-chrome {
  display: flex; align-items: center; gap: 0.5em;
  min-width: 0;
  padding: 0.7em 0.9em;
  background: var(--pearl);
  border-bottom: var(--filet) solid var(--line);
  font-size: clamp(9px, 2.1cqw, 13px);
  color: var(--text-soft);
}
/* Les deux etiquettes sont permanentes : sans elles, on ne sait pas de
   quel cote est quoi avant d'avoir bouge la poignee. */
.ba-etq {
  flex: 0 0 auto;
  padding: 0.25em 0.7em;
  font-size: 1em; font-weight: 700;
  letter-spacing: var(--ls-etiquette); text-transform: uppercase;
  border-radius: var(--rayon);
  pointer-events: none;
}
.ba-etq--a { background: var(--marble); color: var(--text); }
.ba-etq--b { margin-left: auto; background: var(--navy); color: var(--pearl); }

.ba-scene {
  position: relative;
  container-type: inline-size;
  aspect-ratio: 16 / 11;
  overflow: hidden;
  background: var(--marble);
  isolation: isolate;
  /* La position de repos est 50 : les deux moities se voient d'emblee. */
  --ba-p: 50;
  touch-action: pan-y;
  cursor: ew-resize;
  user-select: none; -webkit-user-select: none;
}

/* La vitre et la piste sont le crochet du defilement interne, pose par
   le script du site. Au repos la piste fait la hauteur de la vitre :
   rien ne defile, le cadre montre le haut des deux pages. */
.ba-vitre { position: absolute; inset: 0; overflow: hidden; }
.ba-piste { width: 100%; height: var(--ba-piste, 100%); }

.ba-pile { position: absolute; inset: 0; display: grid; overflow: hidden; pointer-events: none; }
.ba-vue { grid-area: 1 / 1; min-width: 0; overflow: hidden; background: #ffffff; }
/* Le fond des deux vues est blanc EN DUR : c'est une image de site, pas
   une surface d'ADEXWEB. Voir la section 10. */
.ba-page { position: relative; background: #ffffff; color: #000000; transform: translateY(calc(var(--ba-y, 0) * -1cqw)); }
.ba-page--shot { background: none; }
.ba-shot { display: block; width: 100%; height: auto; -webkit-user-drag: none; }

/* L'apres est la couche du dessous, entiere ; l'avant est rogne par la
   poignee. Un `clip-path` ne redessine rien : il coupe. */
.ba-vue--avant { z-index: 2; clip-path: inset(0 calc((100 - var(--ba-p)) * 1%) 0 0); }

/* Les scenes epinglees de deux des quatre « apres ». */
.ba-bande {
  position: absolute; left: 0; right: 0;
  top: calc(var(--ba-b-y) * 1cqw);
  height: calc(var(--ba-b-h) * 1cqw);
  overflow: hidden;
}
.ba-bande img { display: block; width: 100%; height: auto; }
.ba-bande--continue .ba-bande-fond { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.ba-bande--continue .ba-bande-piste {
  position: absolute;
  left: calc(var(--ba-p-x) * 1cqw);
  top: calc(var(--ba-p-y) * 1cqw);
  width: calc(var(--ba-p-l) * 1cqw);
  height: auto; max-width: none;
  transform: translateX(calc(var(--ba-piste, 0) * -1cqw));
}

/* L'arete. Un filet de 2 px en navy, et sa prise carree au milieu. */
.ba-trait {
  position: absolute; top: 0; bottom: 0;
  left: calc(var(--ba-p) * 1%);
  z-index: 3;
  width: 2px;
  background: var(--navy);
  pointer-events: none;
}
.ba-trait::before {
  content: "‹ ›";
  position: absolute; top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  display: grid; place-items: center;
  width: 2.75rem; height: 2.75rem;
  background: var(--navy); color: var(--pearl);
  border-radius: var(--rayon);
  box-shadow: var(--ombre-levee);
  font-size: var(--t-00); font-weight: 700; letter-spacing: 0.06em;
  white-space: nowrap;
}

/* Le champ ne prend pas le pointeur : le glissement se pilote sur la
   scene entiere, ce qui donne une prise de 528 px au lieu de 44. Le
   clavier, lui, passe toujours par le champ. */
.ba-poignee {
  position: absolute; inset: 0; z-index: 4;
  width: 100%; height: 100%;
  margin: 0; padding: 0;
  background: transparent; border: 0;
  -webkit-appearance: none; appearance: none;
  cursor: ew-resize;
  pointer-events: none;
  touch-action: pan-y;
}
.ba-poignee::-webkit-slider-runnable-track { height: 100%; background: transparent; }
.ba-poignee::-webkit-slider-thumb { -webkit-appearance: none; width: 2.75rem; height: 100%; background: transparent; }
.ba-poignee::-moz-range-track { height: 100%; background: transparent; }
.ba-poignee::-moz-range-thumb { width: 2.75rem; height: 100%; background: transparent; border: 0; }
.ba-poignee:focus-visible { outline: var(--focus-w) solid var(--navy); outline-offset: -3px; border-radius: 0; }

/* Sans script, la poignee ne ferait rien : on la retire, et la mention
   de repli prend la parole. */
html:not(.js) .ba-poignee,
html:not(.js) .ba-trait { display: none; }
/* Le repli porte `hidden` dans le document : il ne parait QUE si le
   script n'a pas tourne. Une regle d'auteur bat la feuille du
   navigateur, donc `display` reprend la main sur `[hidden]`. */
.ba-sans { display: none; color: var(--text-soft); max-width: 62ch; }
html:not(.js) .ba-sans { display: block; }
/* Sans script, `--ba-p` reste a 50 : le cadre montre les deux moities
   cote a cote, fixes. On perd le geste, jamais l'information — et c'est
   exactement ce que le repli annonce.  */

/* La legende : un titre court, une ligne, jamais un paragraphe. */
.ba-tete {
  display: grid; grid-template-columns: auto 1fr;
  align-items: baseline;
  gap: var(--e-1) var(--e-2);
  margin: 0;
}
.ba-tete .num {
  font-style: normal;
  font-size: var(--t-00); font-weight: 700;
  letter-spacing: var(--ls-etiquette);
  color: var(--text-soft);
}
.ba-tete b {
  font-family: var(--font-titre);
  font-weight: 440; font-size: var(--t-1);
  line-height: var(--lh-1); letter-spacing: var(--ls-1);
  color: var(--navy-dark);
}
.ba-tete span {
  grid-column: 2;
  font-size: var(--t-00);
  color: var(--text-soft);
}


/* ===================================================================
   4 · LES TREIZE APERCUS DE SECTEUR
   La scene porte EXACTEMENT le rapport de la prise de vue, 1440 x 900 :
   aucun rognage, aucune bande, la meme echelle aux treize. Les
   maquettes elles-memes sont habillees par `css/secteurs.css`.
   =================================================================== */

.secteurs-grille { display: grid; gap: var(--e-6); align-items: start; }
@media (min-width: 62em) {
  .secteurs-grille { grid-template-columns: 1fr 1.15fr; gap: var(--e-7); }
}

.secteur-groupe { display: grid; gap: var(--e-2); }
.secteur-groupe + .secteur-groupe {
  margin-top: var(--e-4);
  padding-top: var(--e-4);
  border-top: var(--filet) solid var(--line);
}
.secteur-groupe h3 {
  font-family: var(--font-texte);
  font-size: var(--t-00); font-weight: 700;
  letter-spacing: var(--ls-etiquette); text-transform: uppercase;
  color: var(--text-soft);
}
.pastilles { display: flex; flex-wrap: wrap; gap: var(--e-1); }
.pastilles button {
  display: inline-flex; align-items: center;
  min-height: var(--cible-min);
  padding: 0 var(--e-2);
  border: var(--filet) solid var(--line-strong);
  border-radius: var(--rayon);
  font-size: var(--t-00); font-weight: 600;
  color: var(--navy-dark);
  text-align: left;
  transition: background-color var(--t-etat), border-color var(--t-etat), color var(--t-etat);
}
.pastilles button:hover,
.pastilles button.is-on {
  border-color: var(--navy);
  background: var(--champagne-light);
}

/* La figure : le cartouche, la scene, la legende. La legende est un
   ETAGE de la plaque, pas un bandeau pose dessus. */
.sector-preview {
  position: relative;
  margin: 0;
  border: var(--filet) solid var(--line-strong);
  border-radius: var(--rayon-large);
  overflow: hidden;
  background: var(--silk);
  box-shadow: var(--ombre-pose);
  display: flex; flex-direction: column;
}
.sector-preview > .sec-chrome { flex: none; }
.sector-preview figcaption {
  flex: none;
  padding: var(--e-2) var(--e-3);
  background: var(--navy-dark);
  color: var(--pearl);
  font-size: var(--t-00);
  line-height: 1.5;
}

.mock-stage { position: relative; flex: none; aspect-ratio: 1440 / 900; overflow: hidden; }
.mock-stage .mock {
  position: absolute; inset: 0;
  display: grid; grid-template-rows: auto 1fr;
  /* `content-visibility: hidden` et non `visibility` : le contenu cache
     ne coute alors ni style ni mise en page. */
  content-visibility: hidden;
  opacity: 0;
}
.mock-stage .mock.is-on { content-visibility: visible; opacity: 1; }

/* La scene n'est vide que dans un seul cas : le script n'a pas clone le
   gabarit. Elle garde alors sa place et dit pourquoi, plutot que de
   laisser un trou gris. Avec le script, elle est remplie avant la
   premiere peinture et ce message ne parait jamais. */
.mock-stage:empty::after {
  content: "Les aperçus de métier demandent JavaScript. Les treize sites existent quand même : voir les neuf démonstrations complètes plus bas.";
  padding: var(--e-4);
  text-align: center;
  max-width: 46ch;
  margin-inline: auto;
  position: absolute; inset: 0;
  display: grid; place-items: center;
  font-size: var(--t-00); color: var(--text-soft);
}


/* ===================================================================
   5 · LES NEUF SITES DE DEMONSTRATION
   Une liste filetee, pas des pastilles : ce sont des DESTINATIONS, et
   une destination ne se confond pas avec un filtre.
   =================================================================== */

.demos { display: grid; border-top: var(--filet) solid var(--line); }
.demos li { border-bottom: var(--filet) solid var(--line); }
.demos a {
  display: grid; grid-template-columns: 1fr auto;
  align-items: baseline; gap: var(--e-2) var(--e-3);
  min-height: var(--cible);
  padding-block: var(--e-2);
  text-decoration: none;
  transition: padding-left var(--t-etat), color var(--t-etat);
}
.demos a:hover, .demos a:focus-visible { padding-left: var(--e-1); color: var(--navy); }
.demos-nom { font-size: var(--t-0); font-weight: 600; color: var(--navy-dark); }
.demos-dit { grid-column: 1; font-size: var(--t-00); color: var(--text-soft); }
.demos-voir {
  display: inline-flex; align-items: center; gap: var(--e-1);
  font-size: var(--t-00); font-weight: 700;
  letter-spacing: var(--ls-etiquette); text-transform: uppercase;
  white-space: nowrap;
  color: var(--navy-dark);
}
.demos-voir svg { width: 1rem; height: 1rem; transition: transform var(--t-etat); }
.demos a:hover .demos-voir svg { transform: translateX(3px); }
@media (min-width: 48em) { .demos-dit { grid-column: 1; } }


/* ===================================================================
   6 · LA VISITE 360 — les complements
   Tout le reste vient de `css/tour360.css`, charge tel quel. Ne sont
   ecrites ici que les deux formes qui appartiennent a la page.
   =================================================================== */

.tour { max-width: 62rem; }
.tour-cadre {
  border-radius: var(--rayon-large);
  overflow: hidden;
  box-shadow: var(--ombre-pose);
}
.tour-source { margin-top: var(--e-2); font-size: var(--t-00); color: var(--text-soft); }


/* ===================================================================
   7 · LE CALCULATEUR
   Le chiffre affiche est un montant d'ECONOMIES ESTIMEES, jamais un
   prix. La methode qui le produit reste sur la page, sous son propre
   titre : un chiffre sans sa methode ne se defend pas au telephone.
   =================================================================== */

.roi-grille { display: grid; gap: var(--e-6); align-items: start; }
@media (min-width: 62em) { .roi-grille { grid-template-columns: 1fr 0.85fr; gap: var(--e-7); } }

.roi-inputs { display: grid; gap: var(--e-2); align-content: start; }

.roi-presets { display: flex; flex-wrap: wrap; gap: var(--e-1); }
.roi-presets button {
  display: inline-flex; align-items: center;
  min-height: var(--cible-min);
  padding: 0 var(--e-2);
  border: var(--filet) solid var(--line-strong);
  border-radius: var(--rayon);
  font-size: var(--t-00); font-weight: 600;
  color: var(--navy-dark);
  transition: background-color var(--t-etat), border-color var(--t-etat), color var(--t-etat);
}
.roi-presets button:hover { border-color: var(--navy-light); background: var(--pearl); }
.roi-presets button[aria-pressed="true"] {
  background: var(--navy); border-color: var(--navy); color: var(--pearl);
}

.roi-sub {
  margin-top: var(--e-3);
  padding-top: var(--e-3);
  border-top: var(--filet) solid var(--line);
  font-size: var(--t-00); font-weight: 700;
  letter-spacing: var(--ls-etiquette); text-transform: uppercase;
  color: var(--text-soft);
}

.roi-field { display: grid; gap: var(--e-1); }
.roi-field .roi-top { display: flex; align-items: baseline; justify-content: space-between; gap: var(--e-2); }
.roi-field label { font-size: var(--t-00); color: var(--text-soft); cursor: pointer; }
/* `nowrap` : sous 400 px, « 42 $ » cassait entre le chiffre et le dollar. */
.roi-field output { font-size: var(--t-0); font-weight: 700; color: var(--text); white-space: nowrap; }

/* LE CURSEUR NE DISAIT PAS QU'IL ETAIT UN CURSEUR.  D-985
   « On ne voit vraiment pas bien comment déplacer. » Quatre defauts
   empiles, tous mesurables :
     1 · LA PISTE N'AVAIT AUCUNE PARTIE REMPLIE. Unie, `--marble`
         #E8E4E0, posee sur `bande--silk` #EEE5D9 — et le haut de cette
         feuille note deja que ces deux beiges ne se distinguent pas cote
         a cote. Rien ne disait ou on en etait, ni dans quel sens ca
         allait. La piste est maintenant navy a gauche de la poignee : la
         valeur SE VOIT avant de se lire.
     2 · AUCUN `:hover`, `:active` NI `:focus-visible` sur la poignee.
         Rien ne repondait au geste, ni a la souris, ni au doigt, ni au
         clavier. Une commande qui ne repond pas se lit comme une image.
     3 · AUCUNE BORNE ECRITE. Ni « 0 h » ni « 40 h » : on poussait sans
         savoir contre quoi. Les bornes vivent dans `.roi-bornes`.
     4 · 91 % DE LA HAUTEUR ETAIT TRANSPARENTE. 2,75 rem d'element pour
         6 px de piste — la cible tactile etait bonne, mais l'oeil ne
         voyait qu'un trait. La piste passe a 12 px et la poignee a 32.
   `--rempli` est pose par `js/main.js` a chaque calcul, y compris quand
   un profil deplace huit curseurs d'un coup. */
.roi-field input[type="range"] {
  --rempli: 0%;
  -webkit-appearance: none; appearance: none;
  width: 100%; height: 2.75rem;
  background: transparent;
  cursor: pointer;
}
.roi-field input[type="range"]::-webkit-slider-runnable-track {
  height: 12px; border-radius: var(--rayon-pilule);
  border: var(--filet) solid var(--line-strong);
  background: linear-gradient(to right,
              var(--navy) 0 var(--rempli), var(--marble) var(--rempli) 100%);
}
.roi-field input[type="range"]::-moz-range-track {
  height: 12px; border-radius: var(--rayon-pilule);
  border: var(--filet) solid var(--line-strong);
  background: linear-gradient(to right,
              var(--navy) 0 var(--rempli), var(--marble) var(--rempli) 100%);
}
.roi-field input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 2rem; height: 2rem; margin-top: -0.625rem;
  background: var(--navy); border: 3px solid var(--pearl);
  border-radius: 50%;
  box-shadow: 0 0 0 var(--filet) var(--navy-dark), var(--ombre-levee);
  transition: background-color var(--t-etat), box-shadow var(--t-etat);
}
.roi-field input[type="range"]::-moz-range-thumb {
  width: 2rem; height: 2rem;
  background: var(--navy); border: 3px solid var(--pearl);
  border-radius: 50%;
  box-shadow: 0 0 0 var(--filet) var(--navy-dark), var(--ombre-levee);
  transition: background-color var(--t-etat), box-shadow var(--t-etat);
}
/* LE HALO REPOND AU GESTE, ET IL EST TRANSPARENT : il ne peut donc pas
   masquer l'anneau de mise au point, qui reste celui de tout le site. */
.roi-field input[type="range"]:hover::-webkit-slider-thumb {
  background: var(--navy-dark);
  box-shadow: 0 0 0 var(--filet) var(--navy-dark), 0 0 0 0.5rem rgb(34 45 82 / 0.12);
}
.roi-field input[type="range"]:hover::-moz-range-thumb {
  background: var(--navy-dark);
  box-shadow: 0 0 0 var(--filet) var(--navy-dark), 0 0 0 0.5rem rgb(34 45 82 / 0.12);
}
.roi-field input[type="range"]:active::-webkit-slider-thumb {
  background: var(--navy-dark);
  box-shadow: 0 0 0 var(--filet) var(--navy-dark), 0 0 0 0.75rem rgb(34 45 82 / 0.18);
}
.roi-field input[type="range"]:active::-moz-range-thumb {
  background: var(--navy-dark);
  box-shadow: 0 0 0 var(--filet) var(--navy-dark), 0 0 0 0.75rem rgb(34 45 82 / 0.18);
}

/* LES BORNES S'ECRIVENT. « Poussez les curseurs » ne dit pas jusqu'ou. */
/* PAS DE CAPITALES ICI : `text-transform: uppercase` rendait « 0 h » en
   « 0 H », et une heure ne s'ecrit pas avec une majuscule. */
.roi-bornes {
  display: flex; justify-content: space-between;
  margin-top: -0.375rem;
  font-size: 0.8125rem; font-weight: 600;
  color: var(--text-soft);
  font-variant-numeric: tabular-nums;
}

/* Les deux panneaux replies. Le marqueur ne tourne pas : un plus
   devient un moins, comme partout ailleurs sur le site. */
.roi-details { border-top: var(--filet) solid var(--line); margin-top: var(--e-2); }
.roi-details > summary {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--e-2);
  min-height: var(--cible-min);
  padding-block: var(--e-2);
  cursor: pointer; list-style: none;
  font-size: var(--t-00); font-weight: 700;
  letter-spacing: var(--ls-etiquette); text-transform: uppercase;
  color: var(--text-soft);
}
.roi-details > summary::-webkit-details-marker { display: none; }
.roi-details > summary:hover { color: var(--navy-dark); }
.roi-details > summary svg { width: 1.25rem; height: 1.25rem; flex: 0 0 auto; color: var(--navy); }
.roi-details:not([open]) .icone-moins { display: none; }
.roi-details[open] .icone-plus { display: none; }
.roi-details > *:not(summary) { margin-top: var(--e-2); }
.roi-details[open] { padding-bottom: var(--e-3); }
.roi-methode { margin-top: var(--e-4); }
.roi-note { font-size: var(--t-00); line-height: 1.6; color: var(--text-soft); max-width: 62ch; }
.roi-note b { color: var(--text); font-weight: 600; }

/* Le panneau de resultat. */
.roi-panel {
  align-self: start;
  display: grid; gap: var(--e-3);
  padding: var(--e-4);
  background: var(--pearl);
  border: var(--filet) solid var(--line);
  border-radius: var(--rayon-large);
  box-shadow: var(--ombre-pose);
}
.roi-verdict { display: grid; gap: var(--filet); background: var(--line); border-radius: var(--rayon); overflow: hidden; }
.roi-vcell { display: grid; gap: 0.25rem; padding: var(--e-3); background: var(--silk); }
.roi-vcell .label { font-size: var(--t-00); color: var(--text-soft); }
.roi-vcell b {
  font-family: var(--font-titre);
  font-size: var(--t-3); line-height: 1;
  letter-spacing: var(--ls-3);
  color: var(--navy-dark);
  font-variant-numeric: tabular-nums;
}
/* Une seule des deux cellules est retournee : le montant annuel, parce
   que c'est le seul chiffre sur lequel le visiteur peut agir. */
.roi-vcell--accent { background: var(--navy-dark); }
.roi-vcell--accent .label { color: var(--champagne-light); }
.roi-vcell--accent b { color: var(--pearl); }

.roi-etat { display: grid; gap: var(--e-1); }
.roi-etat .roi-block {
  font-size: var(--t-00); font-weight: 700;
  letter-spacing: var(--ls-etiquette); text-transform: uppercase;
  color: var(--text-soft);
}
.roi-etat .num {
  justify-self: end;
  font-family: var(--font-titre);
  font-size: var(--t-2); line-height: 1;
  letter-spacing: var(--ls-2);
  color: var(--navy-dark);
  font-variant-numeric: tabular-nums;
}
/* La piste est une PISTE : un creux constant ou la valeur se pose. Deux
   barres nues de longueurs differentes ne diraient pas de quoi elles
   sont la part. */
/* LE COUT ANNUEL, SOUS SA PISTE.  D-985
   Il se lit apres les heures, pas avant : les heures sont ce que le
   visiteur a regle, le montant est ce qu'on en deduit. */
.roi-cout {
  justify-self: end;
  font-family: var(--font-titre);
  font-size: var(--t-1); line-height: 1.1;
  color: var(--navy-dark);
  font-variant-numeric: tabular-nums;
}
.roi-piste { display: block; height: 10px; background: var(--marble); border-radius: var(--rayon); overflow: hidden; }
.roi-piste s { display: block; height: 100%; width: 0; background: var(--navy-dark); text-decoration: none; }
.roi-etat + .roi-etat { padding-top: var(--e-2); border-top: var(--filet) solid var(--line); }
.roi-etat + .roi-etat .roi-piste s { background: var(--champagne-dark); }

.roi-actes {
  display: grid; gap: var(--e-1);
  padding-top: var(--e-3);
  border-top: 2px solid var(--line-strong);
}
.roi-sur { margin-top: var(--e-1); font-size: var(--t-00); color: var(--text-soft); }


/* ===================================================================
   8 · LE COMPARATIF A LA MAIN / AUTOMATISE
   Une seule barre par tache, en deux matieres, depuis la MEME origine :
   deux barres cote a cote ne se comparent pas, elles s'additionnent
   dans l'oeil.
   =================================================================== */

/* Trois enfants, deux colonnes : sans placement explicite, l'intitule du
   detail part seul a droite et le tableau retombe SOUS le resume. Le
   resume tient la colonne de gauche sur les deux rangees. */
.ecart-deux { display: grid; gap: var(--e-6); align-items: start; }
@media (min-width: 62em) {
  .ecart-deux {
    grid-template-columns: 0.9fr 1.1fr;
    grid-template-rows: auto 1fr;
    gap: var(--e-2) var(--e-7);
  }
  .ecart-deux > .ecart { grid-column: 1; grid-row: 1 / span 2; }
  .ecart-deux > .ecart-sous { grid-column: 2; grid-row: 1; }
  .ecart-deux > .vs { grid-column: 2; grid-row: 2; }
}

.ecart {
  padding: var(--e-4);
  background: var(--pearl);
  border: var(--filet) solid var(--line);
  border-radius: var(--rayon-large);
  box-shadow: var(--ombre-pose);
}
.ecart > .label { display: block; margin-bottom: var(--e-3); max-width: 46ch; color: var(--text); font-size: var(--t-00); }

.ecart-grand { display: grid; gap: var(--e-2); }
.ecart-piste { position: relative; height: 36px; border-radius: var(--rayon); overflow: hidden; }
.ecart-piste i { position: absolute; top: 0; bottom: 0; left: 0; display: block; }

.ecart-bornes { position: relative; display: block; margin: 0; min-height: 3.5rem; }
.ecart-borne { position: absolute; top: 0; display: grid; gap: 2px; font-size: var(--t-00); color: var(--text-soft); }
.ecart-borne b {
  font-family: var(--font-titre);
  font-size: var(--t-2); line-height: 1;
  letter-spacing: var(--ls-2);
  color: var(--navy-dark);
  font-variant-numeric: tabular-nums;
}
.ecart-borne--reste { left: 0; }
.ecart-borne--part { right: 0; text-align: right; }

.ecart-gain {
  margin-top: var(--e-3);
  padding-top: var(--e-2);
  border-top: var(--filet) solid var(--line-strong);
  text-align: right;
  font-size: var(--t-00); color: var(--text-soft);
}
.ecart-gain b {
  font-family: var(--font-titre);
  font-size: var(--t-4); line-height: var(--lh-4);
  letter-spacing: var(--ls-4);
  color: var(--navy-dark);
  font-variant-numeric: tabular-nums;
}

.ecart-acte {
  margin-top: var(--e-3);
  padding-top: var(--e-3);
  border-top: var(--filet) solid var(--line);
  display: grid; gap: var(--e-2); justify-items: start;
}
.ecart-acte .btn { width: 100%; }
.ecart-sur { font-size: var(--t-00); color: var(--text-soft); }

.ecart-sous {
  display: block;
  margin-bottom: var(--e-2);
  font-size: var(--t-00); font-weight: 700;
  letter-spacing: var(--ls-etiquette); text-transform: uppercase;
  color: var(--text-soft);
}

.vs { display: grid; border-top: var(--filet) solid var(--line); }
.vs-row {
  display: grid;
  gap: var(--e-1) var(--e-3);
  padding-block: var(--e-2);
  border-bottom: var(--filet) solid var(--line);
  align-items: center;
}
.vs-task { font-size: var(--t-00); font-weight: 600; color: var(--text); }
.vs-track { position: relative; height: 20px; border-radius: var(--rayon); overflow: hidden; }
.vs-track i { position: absolute; top: 0; bottom: 0; left: 0; display: block; }
/* Ce qui part : une trame a 45 degres, donc jamais confondue avec un
   aplat. Ce qui reste : un plein, pose PAR-DESSUS, meme origine. */
.vs-tout {
  width: var(--m, 0%);
  background-image: repeating-linear-gradient(45deg, var(--line-strong) 0 2px, transparent 2px 6px);
}
.vs-reste { width: var(--a, 0%); background: var(--navy-dark); }
.vs-gain { font-size: var(--t-00); color: var(--text-soft); justify-self: end; white-space: nowrap; font-variant-numeric: tabular-nums; }
.vs-gain b { font-family: var(--font-titre); font-size: var(--t-1); font-weight: 440; color: var(--navy-dark); letter-spacing: var(--ls-1); }

@media (min-width: 48em) {
  .vs-row { grid-template-columns: minmax(0, 15rem) minmax(0, 1fr) auto; }
  .vs-task { grid-row: 1; }
}


/* ===================================================================
   9 · LES DEUX GUIDES
   Aucun lien direct vers les PDF : ils partent par courriel contre des
   coordonnees. Un lien qui telecharge et un bouton qui demande une
   adresse ne se ressemblent pas — c'est un BOUTON.
   =================================================================== */

/* `minmax(0, …)` sur les deux colonnes : sans lui, le titre le plus long
   d'une couverture impose sa largeur minimale et ecrase la colonne de
   texte a deux mots par ligne. */
.guides { display: grid; gap: var(--e-6); align-items: center; }
@media (min-width: 62em) {
  .guides { grid-template-columns: minmax(0, 30rem) minmax(0, 1fr); gap: var(--e-9); }
}

/* LES DEUX COUVERTURES SONT DESSINEES ICI, PAS SERVIES EN IMAGE, ET
   C'EST UNE OBLIGATION. `images/doc-automatisation.webp` et
   `images/doc-ia.webp` portent le mot APED en pleine masse et l'accent
   minium : la couverture est l'ancienne identite, et la faire revenir
   est une regression, meme reduite a huit pixels. Les deux fichiers
   reprendront leur place le jour ou les PDF seront recomposes. */
.guides-couvertures { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--e-3); max-width: 30rem; }
.guide-couv {
  aspect-ratio: 600 / 776;
  display: grid; grid-template-rows: auto 1fr auto auto;
  gap: var(--e-2);
  padding: var(--e-3);
  background: var(--navy-dark);
  color: var(--pearl);
  border-radius: var(--rayon);
  box-shadow: var(--ombre-levee);
}
.guide-couv .guide-marque {
  font-size: var(--t-00); font-weight: 700;
  letter-spacing: var(--ls-etiquette); text-transform: uppercase;
  color: var(--champagne-light);
}
.guide-couv .guide-titre {
  align-self: end;
  font-family: var(--font-titre);
  font-weight: 440;
  font-size: var(--t-0); line-height: 1.25; letter-spacing: var(--ls-1);
  color: var(--pearl);
}
.guide-couv .guide-dit { font-size: var(--t-00); line-height: 1.5; color: var(--champagne-light); }
.guide-couv .guide-pages {
  padding-top: var(--e-2);
  border-top: 2px solid var(--champagne);
  font-size: var(--t-00); font-weight: 600;
  color: var(--champagne-light);
}
/* `.mention` d'`app.css` est en `--text-muted` : 3,83:1 sur marble, donc
   INTERDIT ici. La mention de cette bande porte sa propre classe plutot
   que de redefinir une classe partagee.  D-803 */
.guides-mention { margin-top: var(--e-3); font-size: var(--t-00); color: var(--text-soft); max-width: 52ch; }


/* ===================================================================
  10 · LES RECONSTITUTIONS « AVANT » — HORS SYSTEME D'IDENTITE
  ====================================================================
  CE QUI SUIT N'OBEIT A AUCUNE REGLE D'ADEXWEB, ET C'EST LE SUJET.

  Ces quatre blocs — `.v11`, `.ann`, `.tou`, `.gab` — imitent de vieux
  sites, un annuaire, une fiche d'office de tourisme et un gabarit
  achete. Ils portent donc, VOLONTAIREMENT : des couleurs en
  hexadecimal en dur, des degrades, des ombres portees, des coins
  arrondis, Verdana et Arial Black, un texte defilant. Aucun jeton de
  `css/tokens.css` n'y entre, et aucune de ces valeurs ne doit etre
  « corrigee » vers la palette : ce serait effacer la demonstration.

  Ils sont enfermes : chaque regle est prefixee par sa classe racine,
  et cette racine ne parait que dans une `.ba-vue--avant`.
  L'unite est le `cqw`, rapporte au `.ba-scene` qui les contient.

  Repris tels quels du commit `avant-adexweb`, `css/app.css` § 15
  (lignes 3438 a 4890), sans une valeur changee.
  =================================================================== */

/* == L'AVANT · 01 — 2008-2012, RECONSTITUE SUR PIECES. ==  D-213 */
/* LES INTERDITS DU SITE NE S'APPLIQUENT PAS ICI, ET C'EST LE SUJET.  D-518 */
.v11 {
  min-height: 118cqw;
  background: #ffffff;
  color: #000000;
  font-family: Verdana, Geneva, Arial, sans-serif;
  font-size: 1.1cqw;
  line-height: 1.5;
}
.v11-page { width: 90cqw; margin: 0 auto; border-collapse: collapse; table-layout: fixed; }
.v11-banniere {
  padding: 2.4cqw 2cqw;
  background: #1b3d6d;
  background-image: linear-gradient(#2a5a9e, #12294a);
  color: #ffffff;
  text-align: center;
}
.v11-nom { display: block; font-family: "Arial Black", Arial, sans-serif; font-size: 3.4cqw; letter-spacing: 0.02em; text-shadow: 1px 1px 0 #000; }
.v11-slogan { display: block; margin-top: 0.6cqw; font-style: italic; font-size: 1.4cqw; color: #ffd67a; }
.v11-onglets { padding: 0; background: #d8d8d8; background-image: linear-gradient(#f2f2f2, #c9c9c9); border-top: 1px solid #fff; border-bottom: 1px solid #8a8a8a; }
.v11-onglet { display: inline-block; padding: 0.9cqw 1.8cqw; border-right: 1px solid #b0b0b0; font-size: 1.2cqw; color: #14417a; text-decoration: underline; }
.v11-on { background: #ffffff; font-weight: bold; }
.v11-cote { width: 22cqw; padding: 1.6cqw; background: #eef1f6; border-right: 1px solid #b8c2d0; vertical-align: top; }
.v11-menu-t { margin: 0 0 1cqw; font-family: "Arial Black", Arial, sans-serif; font-size: 1.4cqw; color: #1b3d6d; }
.v11-lien { margin: 0 0 0.7cqw; font-size: 1.1cqw; color: #14417a; text-decoration: underline; }
.v11-compteur { margin: 2cqw 0 1.2cqw; padding: 0.8cqw; background: #000; color: #0f0; font-family: "Courier New", monospace; text-align: center; }
.v11-compteur b { display: block; font-size: 0.9cqw; color: #fff; font-weight: normal; }
.v11-compteur i { font-style: normal; font-size: 1.6cqw; letter-spacing: 0.24em; }
.v11-badges { display: flex; gap: 0.6cqw; }
.v11-badges i { flex: 1 1 auto; padding: 0.5cqw; border: 1px solid #7a7a7a; background: #dfe6ee; font-style: normal; font-size: 0.8cqw; text-align: center; line-height: 1.2; }
.v11-mini { margin: 1.2cqw 0 0; font-size: 0.85cqw; color: #555; line-height: 1.35; }
.v11-corps { padding: 1.8cqw 2cqw; vertical-align: top; background: #ffffff; }
/* LE TEXTE DEFILANT. `<marquee>` est obsolete, mais l'effet EST le  D-041 */
.v11-defile { overflow: hidden; margin: 0 0 1.4cqw; padding: 0.5cqw 0; background: #fff2c2; border: 1px solid #e0c96a; white-space: nowrap; }
.v11-defile span { display: inline-block; padding-left: 100%; font-weight: bold; font-size: 1.1cqw; color: #a83b00; }
@keyframes v11-defile { from { transform: translateX(0); } to { transform: translateX(-100%); } }
/* LE TEXTE DEFILANT N EST PAS CONDITIONNE A LA VISIBILITE.  D-543 */
/* C est la SEULE animation permanente du site, et `palier-check`
   s appuie dessus pour prouver que le palier 1 la fait tomber. La
   conditionner a `data-vif` rendait la sonde muette : elle lisait
   `none` de loin et appelait ca un echec. Une transformation sur un
   seul span, que le navigateur bride deja hors ecran. */
.v11-defile span { animation: v11-defile 16s linear infinite; }
.v11-h1 { margin: 0 0 1.4cqw; font-family: "Arial Black", Arial, sans-serif; font-size: 2.4cqw; color: #1b3d6d; }
/* LES BLOCS PHOTO DES RECONSTITUTIONS SONT DE VRAIES PHOTOS.  D-634 */
.v11-photo {
  height: 16cqw;
  margin-bottom: 1.4cqw;
  background: #9aa7b4 url("../images/realisations/avant-garage.webp") center / cover no-repeat;
  border: 3px double #7a8794;
}
.v11-p { margin: 0 0 1.4cqw; text-align: justify; font-size: 1.1cqw; }
.v11-p--centre { text-align: center; }
.v11-p--casse { color: #333; }
.v11-promo { margin: 0 0 1cqw; padding: 1cqw; border: 2px dashed #c00; background: #fff6f6; text-align: center; font-size: 1.1cqw; }
.v11-promo b { color: #c00; }
.v11-tel { margin: 1.4cqw 0 0; font-size: 1.3cqw; }
.v11-pdf { margin: 0 0 1.4cqw; }
.v11-flash { height: 10cqw; margin-bottom: 1.4cqw; border: 1px solid #999; background: #f4f4f4; display: grid; place-items: center; color: #777; font-size: 1.1cqw; }
.v11-pied { padding: 1.4cqw 2cqw; background: #eef1f6; border-top: 1px solid #b8c2d0; text-align: center; font-size: 0.95cqw; color: #444; line-height: 1.6; }
.v11-a { color: #14417a; text-decoration: underline; }

/* == BA 02 · DESIGN INTERIEUR. L'AVANT reconstitue une page de resultats
   d'annuaire specialise : filtres, 17 fiches, upsell, texte SEO, pied a
   trois colonnes. Radius, ombres et degrades sont AUTORISES ICI SEULEMENT
   — chaque regle est enfermee dans `.ba-vue--avant .ann`. Un seul orange,
   reserve au bouton d'inscription de l'annuaire. Toute longueur est en
   `cqw` (1cqw = 10 px de maquette), sauf les filets, qui restent a 1px. */

/* ---------- LE SOCLE ---------- */
.ba-vue--avant .ann {
  display: block;
  min-height: 118cqw;
  margin: 0;
  padding: 0;
  background: #ffffff;
  color: #34383d;
  font-family: Arial, Helvetica, sans-serif;
  font-size: 1.4cqw;
  line-height: 1.5;
  text-align: left;
}

/* ---------- L'EN-TETE DE L'ANNUAIRE ---------- */
/* Le nom en haut a gauche n'est pas celui de l'entreprise : c'est
   celui du proprietaire de la page. Tout part de la. */
.ba-vue--avant .ann-tete {
  display: flex;
  align-items: center;
  gap: 2.4cqw;
  padding: 1.6cqw 3cqw;
  background: #ffffff;
  border-bottom: 1px solid #e4e7ea;
  box-shadow: 0 0.2cqw 0.6cqw rgb(16 24 32 / 0.07);
  position: relative;
  z-index: 2;
}
.ba-vue--avant .ann-logo {
  flex: 0 0 auto;
  font-size: 2.1cqw;
  font-weight: 400;
  letter-spacing: -0.02cqw;
  color: #656c72;
  white-space: nowrap;
}
.ba-vue--avant .ann-logo b { font-weight: 700; color: #2b3035; }
.ba-vue--avant .ann-rech {
  flex: 1 1 auto;
  display: flex;
  align-items: stretch;
  min-width: 0;
  border: 1px solid #d5dade;
  border-radius: 0.5cqw;
  background: #ffffff;
  overflow: hidden;
}
.ba-vue--avant .ann-rech-txt {
  flex: 1 1 auto;
  padding: 0.95cqw 1.3cqw;
  font-size: 1.35cqw;
  color: #656c72;
  background: #fbfcfc;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.ba-vue--avant .ann-rech-btn {
  flex: 0 0 auto;
  padding: 0.95cqw 1.8cqw;
  font-size: 1.3cqw;
  font-weight: 700;
  color: #ffffff;
  background-color: #4a5760;
  background-image: linear-gradient(180deg, #56646e 0%, #414d56 100%);
}
.ba-vue--avant .ann-menu {
  flex: 0 0 auto;
  font-size: 1.3cqw;
  color: #656c72;
  white-space: nowrap;
}

/* ---------- LE TITRE — IL APPARTIENT A L'ANNUAIRE ---------- */
.ba-vue--avant .ann-bandeau {
  padding: 2.4cqw 3cqw 2.2cqw;
  background-color: #f6f7f8;
  background-image: linear-gradient(180deg, #fafbfb 0%, #f2f4f5 100%);
  border-bottom: 1px solid #e4e7ea;
}
.ba-vue--avant .ann-fil { font-size: 1.2cqw; color: #656c72; }
.ba-vue--avant .ann-fil b { font-weight: 400; color: #9aa2a8; }
.ba-vue--avant .ann-h1 {
  margin-top: 1cqw;
  font-size: 3cqw;
  font-weight: 700;
  line-height: 1.25;
  color: #2b3035;
}
.ba-vue--avant .ann-sous { margin-top: 0.8cqw; font-size: 1.4cqw; color: #656c72; }

/* ---------- LES TROIS FILTRES ---------- */
.ba-vue--avant .ann-filtres {
  display: flex;
  gap: 1.4cqw;
  padding: 1.8cqw 3cqw;
  background: #ffffff;
  border-bottom: 1px solid #eceef0;
}
.ba-vue--avant .ann-filtre {
  display: flex;
  align-items: center;
  gap: 1cqw;
  flex: 1 1 0;
  padding: 1cqw 1.4cqw;
  border: 1px solid #d9dee2;
  border-radius: 0.5cqw;
  background-color: #fbfcfc;
  background-image: linear-gradient(180deg, #ffffff 0%, #f3f5f6 100%);
  font-size: 1.3cqw;
  color: #52585e;
  white-space: nowrap;
}
.ba-vue--avant .ann-filtre b { margin-left: auto; font-weight: 400; color: #8b9298; }

/* ---------- LES FICHES — LA NOTRE EST LA QUATRIEME ---------- */
.ba-vue--avant .ann-liste {
  display: grid;
  gap: 1.6cqw;
  padding: 2.4cqw 3cqw;
  background: #ffffff;
}
.ba-vue--avant .ann-item {
  display: flex;
  gap: 2cqw;
  padding: 2cqw;
  background: #ffffff;
  border: 1px solid #e5e8eb;
  border-radius: 0.7cqw;
  box-shadow: 0 0.15cqw 0.5cqw rgb(16 24 32 / 0.06);
}
/* LA NOTRE. Une bordure un peu plus dense, rien de plus : dans un
   annuaire, personne ne se distingue — c'est justement le probleme. */
.ba-vue--avant .ann-item--moi {
  border-color: #adb5bc;
  box-shadow: 0 0.2cqw 0.7cqw rgb(16 24 32 / 0.13);
}
/* SIX INTERIEURS DIFFERENTS, UNE SEULE REQUETE.  D-634 */
.ba-vue--avant .ann-vig {
  flex: 0 0 14cqw;
  height: 14cqw;
  border-radius: 0.5cqw;
  background-color: #dfe3e6;
  background-image: url("../images/realisations/avant-design.webp");
  background-repeat: no-repeat;
  background-size: 100% 600%;
  background-position: 0 0%;
  border: 1px solid #e2e6e9;
}
.ba-vue--avant .ann-item:nth-child(2) .ann-vig { background-position: 0 20%; }
.ba-vue--avant .ann-item:nth-child(3) .ann-vig { background-position: 0 40%; }
.ba-vue--avant .ann-item:nth-child(4) .ann-vig { background-position: 0 60%; }
.ba-vue--avant .ann-item:nth-child(5) .ann-vig { background-position: 0 80%; }
.ba-vue--avant .ann-item:nth-child(6) .ann-vig { background-position: 0 100%; }
.ba-vue--avant .ann-corps {
  display: flex;
  flex-direction: column;
  gap: 0.7cqw;
  min-width: 0;
  flex: 1 1 auto;
}
.ba-vue--avant .ann-ligne { display: flex; align-items: baseline; gap: 1cqw; }
.ba-vue--avant .ann-nom { font-size: 1.9cqw; font-weight: 700; color: #2f3a42; }
.ba-vue--avant .ann-badge {
  padding: 0.25cqw 0.8cqw;
  border-radius: 0.3cqw;
  background: #eef0f2;
  font-size: 1.05cqw;
  letter-spacing: 0.07cqw;
  text-transform: uppercase;
  color: #656c72;
}
.ba-vue--avant .ann-cat { font-size: 1.3cqw; color: #656c72; }
.ba-vue--avant .ann-tags { display: flex; flex-wrap: wrap; gap: 0.6cqw; }
.ba-vue--avant .ann-tags span {
  padding: 0.35cqw 0.9cqw;
  border: 1px solid #e0e4e7;
  border-radius: 1.4cqw;
  background: #f6f7f8;
  font-size: 1.15cqw;
  color: #656c72;
}
.ba-vue--avant .ann-extrait {
  font-size: 1.35cqw;
  line-height: 1.55;
  color: #52585e;
}
/* LE LIEN NE MENE PAS CHEZ ELLE : il mene a une autre page de
   l'annuaire. C'est la seule sortie offerte par la fiche. */
.ba-vue--avant .ann-plus {
  margin-top: auto;
  font-size: 1.3cqw;
  font-weight: 700;
  color: #3f4e58;
}

/* ---------- LA PAGINATION — IL EN RESTE DEUX PAGES ---------- */
.ba-vue--avant .ann-pages {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 0.8cqw;
  padding: 0 3cqw 2.6cqw;
  background: #ffffff;
}
.ba-vue--avant .ann-pages b,
.ba-vue--avant .ann-pages span {
  padding: 0.85cqw 1.5cqw;
  border: 1px solid #dfe3e6;
  border-radius: 0.4cqw;
  background: #ffffff;
  font-size: 1.3cqw;
  font-weight: 400;
  color: #52585e;
}
.ba-vue--avant .ann-pages b {
  background: #eceef0;
  border-color: #c3cad0;
  font-weight: 700;
  color: #2b3035;
}

/* ---------- L'ENCART DE L'ANNUAIRE — LE SEUL ORANGE ---------- */
.ba-vue--avant .ann-promo {
  display: flex;
  align-items: center;
  gap: 2.4cqw;
  margin: 0 3cqw 2.8cqw;
  padding: 2.4cqw 2.6cqw;
  border: 1px solid #e8e2d8;
  border-radius: 0.8cqw;
  background-color: #fbf7f2;
  background-image: linear-gradient(180deg, #fefcf9 0%, #f7f1e8 100%);
}
.ba-vue--avant .ann-promo-txt { flex: 1 1 auto; min-width: 0; }
.ba-vue--avant .ann-promo-t { font-size: 1.8cqw; font-weight: 700; color: #2b3035; }
.ba-vue--avant .ann-promo-p { margin-top: 0.7cqw; font-size: 1.35cqw; color: #656c72; }
.ba-vue--avant .ann-promo-btn {
  flex: 0 0 auto;
  padding: 1.2cqw 2.4cqw;
  border-radius: 0.5cqw;
  /* La couleur PLEINE reste #bb5600 : le degrade n'est qu'un vernis,
     et le blanc dessus garde 4,7:1. */
  background-color: #bb5600;
  background-image: linear-gradient(180deg, #c25c00 0%, #a94b00 100%);
  box-shadow: 0 0.2cqw 0.5cqw rgb(140 60 0 / 0.28);
  font-size: 1.5cqw;
  font-weight: 700;
  color: #ffffff;
  white-space: nowrap;
}

/* ---------- LE TEXTE DE REFERENCEMENT DE L'ANNUAIRE ---------- */
/* Quarante pour cent de la page repond a des questions generales sur le
   metier — et conseille d'aller voir des realisations que la fiche, elle,
   ne montre nulle part. */
.ba-vue--avant .ann-texte {
  padding: 0.6cqw 3cqw 3.4cqw;
  background: #ffffff;
  border-top: 1px solid #eceef0;
}
.ba-vue--avant .ann-h2 {
  margin-top: 2.8cqw;
  font-size: 2.1cqw;
  font-weight: 700;
  line-height: 1.3;
  color: #2b3035;
}
.ba-vue--avant .ann-p {
  margin-top: 1.1cqw;
  font-size: 1.4cqw;
  line-height: 1.65;
  color: #52585e;
}
.ba-vue--avant .ann-puces {
  margin: 1.2cqw 0 0;
  padding-left: 2.4cqw;
  list-style: disc outside;
}
.ba-vue--avant .ann-puces li {
  margin-bottom: 0.7cqw;
  font-size: 1.4cqw;
  line-height: 1.6;
  color: #52585e;
}

/* ---------- LE PIED, TROIS COLONNES ---------- */
.ba-vue--avant .ann-pied {
  padding: 3.2cqw 3cqw 2.2cqw;
  background: #3a4046;
  color: #dfe3e6;
}
.ba-vue--avant .ann-cols {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 3cqw;
}
.ba-vue--avant .ann-col b {
  display: block;
  margin-bottom: 1.1cqw;
  font-size: 1.45cqw;
  font-weight: 700;
  color: #ffffff;
}
.ba-vue--avant .ann-col span {
  display: block;
  margin-bottom: 0.75cqw;
  font-size: 1.3cqw;
  color: #a8b0b6;
}
.ba-vue--avant .ann-bas {
  margin-top: 2.6cqw;
  padding-top: 1.7cqw;
  border-top: 1px solid rgb(255 255 255 / 0.16);
  font-size: 1.2cqw;
  color: #a8b0b6;
}

/* BA 04 — ENTREPRENEUR : le gabarit acheté de 2019 (.gab), et l’outil d’estimation (.ap-es-).
   1cqw = 10 px de maquette. Seul .gab a droit aux arrondis, aux ombres et aux dégradés — ils y sont enfermés. */

/* ============================================================
   L’AVANT — un gabarit acheté, propre, récent, et muet sur le
   seul chiffre qui intéresse le visiteur. Toutes les règles
   portent `.gab` deux fois : la vue AVANT remet `all: revert`
   sur `:where(*)` — même poids que `.gab` seul, donc l’ordre
   de source déciderait, et il n’est pas garanti.

   Toutes les longueurs sont en `cqw` (1cqw = 10 px de maquette),
   sauf les filets, qui restent en `1px` littéral. Seule exception :
   `letter-spacing`, laissé en `em` — il se mesure sur une
   `font-size` déjà écrite en `cqw`, donc il suit la maquette au
   même facteur. L’écrire en `cqw` le décrocherait de sa lettre.
   ============================================================ */

.gab.gab {
  min-height: 118cqw;
  background: #ffffff;
  color: #5a6472;
  font-family: Arial, Helvetica, sans-serif;
  font-size: 1.5cqw;
  line-height: 1.55;
  text-align: left;
}

/* -- 1 · la barre supérieure : RBQ, heures, téléphone -- */
.gab .gab-top {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 2cqw;
  padding: 0.9cqw 4cqw;
  background: #16233c;
  color: #b9c2d0;
  font-size: 1.25cqw;
  letter-spacing: 0.02em;
}
.gab .gab-top-tel { color: #ffb04a; font-weight: bold; }

/* -- 2 · l’en-tête : logo, six liens, bouton plein -- */
.gab .gab-tete {
  position: relative;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 3cqw;
  padding: 1.8cqw 4cqw;
  background: #ffffff;
  border-bottom: 1px solid #e6eaf0;
  box-shadow: 0 2px 8px rgb(22 35 60 / 0.09);
}
.gab .gab-logo { display: flex; align-items: center; gap: 1.2cqw; }
.gab .gab-logo-m {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 4.6cqw;
  height: 4.6cqw;
  border-radius: 6px;
  background-color: #24406e;
  background-image: linear-gradient(155deg, #2d4d80 0%, #16233c 100%);
  box-shadow: 0 2px 5px rgb(22 35 60 / 0.28);
  color: #ffffff;
  font-size: 1.9cqw;
  font-weight: bold;
  letter-spacing: 0.06em;
}
.gab .gab-logo-t { display: block; }
.gab .gab-logo-n {
  display: block;
  color: #16233c;
  font-size: 1.85cqw;
  font-weight: bold;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  line-height: 1.2;
}
.gab .gab-logo-s {
  display: block;
  color: #8b95a4;
  font-size: 1.05cqw;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
.gab .gab-menu { display: flex; flex-wrap: wrap; align-items: center; gap: 1.9cqw; }
.gab .gab-menu > span {
  color: #4a5566;
  font-size: 1.3cqw;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.gab .gab-menu > span.gab-on { color: #e8760f; }

/* -- le bouton orange, dégradé compris : c’est la signature du genre -- */
.gab .gab-btn {
  display: inline-block;
  padding: 1.1cqw 2.1cqw;
  border-radius: 4px;
  background-color: #e8760f;
  background-image: linear-gradient(#f28c1e 0%, #e0700c 100%);
  box-shadow: 0 2px 5px rgb(224 112 12 / 0.38);
  color: #ffffff;
  font-size: 1.25cqw;
  font-weight: bold;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  text-align: center;
}
.gab .gab-btn--gros { padding: 1.5cqw 3cqw; font-size: 1.5cqw; }
.gab .gab-btn--large { display: block; width: 100%; padding: 1.6cqw; font-size: 1.5cqw; }

/* -- 3 · le carrousel plein cadre, voile à 50 %, pastilles, flèches -- */
.gab .gab-carr { position: relative; height: 38cqw; overflow: hidden; background: #39434f; }
/* LE GABARIT ACHETE MONTRE DU STOCK, ET DU STOCK EST UNE PHOTO.
   Une maison en construction sous « REALISEZ LA MAISON DE VOS
   REVES » : c'est exactement ce qu'un gabarit livre, et le voile a
   50 % par-dessus est deja la pour le titre.  D-634 */
.gab .gab-carr-photo {
  position: absolute;
  inset: 0;
  background: #6d7a86 url("../images/realisations/avant-renov-ban.webp") center / cover no-repeat;
}
.gab .gab-carr-voile {
  position: absolute;
  inset: 0;
  background-image: linear-gradient(90deg, rgb(9 16 28 / 0.66) 0%, rgb(9 16 28 / 0.44) 100%);
}
.gab .gab-carr-txt {
  position: absolute;
  left: 9cqw;
  right: 9cqw;
  top: 50%;
  transform: translateY(-50%);
  text-align: center;
}
.gab .gab-carr-h {
  margin: 0 0 1.5cqw;
  color: #ffffff;
  font-size: 3.6cqw;
  font-weight: bold;
  line-height: 1.15;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  text-shadow: 0 2px 6px rgb(0 0 0 / 0.45);
}
.gab .gab-carr-p {
  margin: 0 auto 2.4cqw;
  max-width: 58cqw;
  color: #e6eaf0;
  font-size: 1.6cqw;
  line-height: 1.6;
}
.gab .gab-fleche {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 3.8cqw;
  height: 3.8cqw;
  border-radius: 50%;
  background: rgb(255 255 255 / 0.22);
  color: #ffffff;
  font-size: 2cqw;
  line-height: 1;
}
.gab .gab-fleche--g { left: 2.4cqw; }
.gab .gab-fleche--d { right: 2.4cqw; }
.gab .gab-puces {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 2.4cqw;
  display: flex;
  justify-content: center;
  gap: 0.9cqw;
}
.gab .gab-puces i { width: 1cqw; height: 1cqw; border-radius: 50%; background: rgb(255 255 255 / 0.45); }
.gab .gab-puces i.gab-on { background: #e8760f; }

/* -- les sections, et leurs titres soulignés d’un trait orange -- */
.gab .gab-sec { padding: 3.8cqw 4cqw; }
.gab .gab-sec--gris { background: #f4f7fa; }
.gab .gab-sec--fonce { background-color: #1b2b48; background-image: linear-gradient(#223454 0%, #16233c 100%); }
.gab .gab-sec-t {
  margin: 0 0 1cqw;
  color: #16233c;
  font-size: 2.5cqw;
  font-weight: bold;
  letter-spacing: 0.08em;
  text-align: center;
  text-transform: uppercase;
}
.gab .gab-sec-t::after {
  content: "";
  display: block;
  width: 6cqw;
  height: 3px;
  margin: 1.2cqw auto 0;
  border-radius: 2px;
  background: #e8760f;
}
.gab .gab-sec-s {
  margin: 0 auto 2.8cqw;
  max-width: 58cqw;
  color: #8b95a4;
  font-size: 1.45cqw;
  text-align: center;
}
.gab .gab-sec--fonce .gab-sec-t { color: #ffffff; }
.gab .gab-lien { display: inline-block; margin-top: 0.8cqw; color: #e8760f; font-size: 1.3cqw; font-weight: bold; }

/* -- 4 · les trois cartes à icône ronde -- */
.gab .gab-atouts { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 2.6cqw; }
.gab .gab-atout {
  padding: 2.6cqw 2.2cqw;
  border-radius: 8px;
  background: #ffffff;
  box-shadow: 0 3px 14px rgb(22 35 60 / 0.11);
  text-align: center;
}
.gab .gab-ico {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 6.4cqw;
  height: 6.4cqw;
  margin: 0 auto 1.6cqw;
  border-radius: 50%;
  background-color: #fdf0e0;
  background-image: linear-gradient(#fdf1e2 0%, #f8dcbb 100%);
  color: #e8760f;
  font-size: 2.6cqw;
  line-height: 1;
}
.gab .gab-atout b {
  display: block;
  margin-bottom: 0.9cqw;
  color: #16233c;
  font-size: 1.65cqw;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}
.gab .gab-atout p { margin: 0; color: #7b8698; font-size: 1.35cqw; line-height: 1.65; }

/* -- 5 · le bloc « à propos », deux colonnes -- */
.gab .gab-apropos { display: grid; grid-template-columns: 36cqw minmax(0, 1fr); gap: 3.6cqw; align-items: center; }
.gab .gab-apropos-img {
  height: 21cqw;
  border-radius: 8px;
  background: #8d97a3 url("../images/realisations/avant-renov-apropos.webp") center / cover no-repeat;
  box-shadow: 0 4px 16px rgb(22 35 60 / 0.16);
}
.gab .gab-h3 {
  margin: 0 0 1.2cqw;
  color: #16233c;
  font-size: 2.1cqw;
  font-weight: bold;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.gab .gab-apropos-c p { margin: 0 0 1.2cqw; font-size: 1.45cqw; line-height: 1.7; }

/* -- 6 · la grille de six services, cartes identiques -- */
.gab .gab-svc { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 2.4cqw; }
.gab .gab-svc-c {
  overflow: hidden;
  border-radius: 8px;
  background: #ffffff;
  box-shadow: 0 3px 14px rgb(22 35 60 / 0.11);
}
/* SIX CARTES DE SERVICE, SIX PHOTOS DE STOCK.  D-634 */
.gab .gab-svc-i {
  height: 9.5cqw;
  background-color: #8d97a3;
  background-image: url("../images/realisations/avant-renov-svc.webp");
  background-repeat: no-repeat;
  background-size: 100% 600%;
  background-position: 0 0%;
}
.gab .gab-svc-c:nth-child(2) .gab-svc-i { background-position: 0 20%; }
.gab .gab-svc-c:nth-child(3) .gab-svc-i { background-position: 0 40%; }
.gab .gab-svc-c:nth-child(4) .gab-svc-i { background-position: 0 60%; }
.gab .gab-svc-c:nth-child(5) .gab-svc-i { background-position: 0 80%; }
.gab .gab-svc-c:nth-child(6) .gab-svc-i { background-position: 0 100%; }
.gab .gab-svc-b { padding: 2cqw 2cqw 2.4cqw; }
.gab .gab-svc-b b {
  display: block;
  margin-bottom: 0.8cqw;
  color: #16233c;
  font-size: 1.55cqw;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.gab .gab-svc-b p { margin: 0; color: #7b8698; font-size: 1.3cqw; line-height: 1.6; }

/* -- 7 · « Pourquoi nous choisir ? », quatre puces sur fond marine -- */
.gab .gab-pq {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 2cqw 3.4cqw;
  max-width: 76cqw;
  margin: 0 auto;
}
.gab .gab-pq-l { display: flex; align-items: flex-start; gap: 1.3cqw; color: #ccd5e2; font-size: 1.4cqw; line-height: 1.6; }
.gab .gab-pq-l i {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.5cqw;
  height: 2.5cqw;
  margin-top: 0.2cqw;
  border-radius: 50%;
  background: #e8760f;
  color: #ffffff;
  font-size: 1.25cqw;
  font-style: normal;
  line-height: 1;
}
.gab .gab-pq-l b { color: #ffffff; }

/* -- 8 · six vignettes de réalisations -- */
.gab .gab-real { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 2cqw; }
/* LES SIX REALISATIONS SUIVENT LEURS SIX LEGENDES, DANS L'ORDRE :
   cuisine · salle de bain · sous-sol · agrandissement · toiture ·
   facade. Une vignette qui contredit sa legende est une faute qu'un
   visiteur voit sans savoir la nommer.  D-634 */
.gab .gab-real-v i {
  display: block;
  height: 11cqw;
  border-radius: 6px;
  background-color: #8d97a3;
  background-image: url("../images/realisations/avant-renov-real.webp");
  background-repeat: no-repeat;
  background-size: 100% 600%;
  background-position: 0 0%;
  box-shadow: 0 2px 9px rgb(22 35 60 / 0.14);
}
.gab .gab-real-v:nth-child(2) i { background-position: 0 20%; }
.gab .gab-real-v:nth-child(3) i { background-position: 0 40%; }
.gab .gab-real-v:nth-child(4) i { background-position: 0 60%; }
.gab .gab-real-v:nth-child(5) i { background-position: 0 80%; }
.gab .gab-real-v:nth-child(6) i { background-position: 0 100%; }
.gab .gab-real-v span { display: block; margin-top: 0.9cqw; color: #8b95a4; font-size: 1.2cqw; text-align: center; }

/* -- 9 · les témoignages : le seul serif italique de la maquette -- */
.gab .gab-temo { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 2.4cqw; }
.gab .gab-temo-c {
  padding: 2.6cqw 2.2cqw;
  border-radius: 8px;
  background: #ffffff;
  box-shadow: 0 3px 14px rgb(22 35 60 / 0.11);
  text-align: center;
}
.gab .gab-etoiles { margin: 0 0 1.2cqw; color: #f5a623; font-size: 1.5cqw; letter-spacing: 0.16em; }
.gab .gab-cite {
  margin: 0 0 1.4cqw;
  color: #5a6472;
  font-family: Georgia, "Times New Roman", serif;
  font-size: 1.45cqw;
  font-style: italic;
  line-height: 1.7;
}
.gab .gab-temo-c b { color: #16233c; font-size: 1.2cqw; letter-spacing: 0.07em; text-transform: uppercase; }

/* -- 10 · la FAQ en accordéon, quatre questions repliées -- */
.gab .gab-faq { max-width: 70cqw; margin: 0 auto; }
.gab .gab-faq-q {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2cqw;
  margin-bottom: 1.2cqw;
  padding: 1.7cqw 2.2cqw;
  border: 1px solid #e2e7ee;
  border-radius: 6px;
  background: #ffffff;
  box-shadow: 0 1px 4px rgb(22 35 60 / 0.07);
  color: #16233c;
  font-size: 1.45cqw;
  font-weight: bold;
}
.gab .gab-faq-q i { color: #e8760f; font-size: 2.2cqw; font-style: normal; line-height: 1; }

/* -- 11 · LE CŒUR DU PROBLÈME : un formulaire qui promet un rappel,
      et pas un seul chiffre à l’écran. -- */
.gab .gab-form {
  max-width: 66cqw;
  margin: 0 auto;
  padding: 2.8cqw;
  border-radius: 10px;
  background: #ffffff;
  box-shadow: 0 6px 22px rgb(22 35 60 / 0.15);
}
.gab .gab-form-g { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.5cqw; margin-bottom: 1.5cqw; }
.gab .gab-champ {
  display: block;
  padding: 1.35cqw 1.4cqw;
  border: 1px solid #d5dce5;
  border-radius: 4px;
  background: #fbfcfd;
  color: #a8b1bd;
  font-size: 1.35cqw;
}
.gab .gab-champ--zone { min-height: 8.5cqw; margin-bottom: 1.8cqw; }
.gab .gab-form-p { margin: 1.4cqw 0 0; color: #8b95a4; font-size: 1.2cqw; text-align: center; }

/* -- 12 · le pied de page à trois colonnes -- */
.gab .gab-pied {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 3cqw;
  padding: 3.6cqw 4cqw;
  background: #16233c;
  color: #b9c2d0;
  font-size: 1.35cqw;
}
.gab .gab-pied > div b {
  display: block;
  margin-bottom: 1.2cqw;
  color: #ffffff;
  font-size: 1.4cqw;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.gab .gab-pied > div p { margin: 0 0 0.5cqw; }
.gab .gab-bas { padding: 1.5cqw 4cqw; background: #0f1928; color: #7b8698; font-size: 1.15cqw; text-align: center; }

/* ------------------------------------------------------------
   LE SOCLE. Le reset est en `:where()` a specificite zero cote
   cible : n'importe quelle regle `.tou .tou-x` ci-dessous gagne,
   quel que soit l'ordre du decoupage de la feuille.
   ------------------------------------------------------------ */
.tou,
.tou *,
.tou *::before,
.tou *::after { box-sizing: border-box; }

.tou :where(p, dl, dt, dd, ul, ol, li, figure) { margin: 0; padding: 0; }
.tou :where(ul, ol) { list-style: none; }
.tou :where(i) { font-style: normal; }

.tou {
  --tou-bleu: #123c59;
  --tou-bleu-m: #1b6ea3;
  --tou-bleu-p: #e9f1f7;
  --tou-encre: #33424e;
  --tou-gris: #6d7f8c;
  --tou-pale: #9fb0bb;
  --tou-ligne: #d5e0e8;
  --tou-fond: #f2f6f9;

  min-height: 118cqw;
  background: #fff;
  color: var(--tou-encre);
  font-family: Arial, Helvetica, sans-serif;
  font-size: 1.5cqw;
  line-height: 1.55;
}
/* LA COLONNE DE L'OFFICE. 880 px dans une page de 1000. */
.tou .tou-c { width: 88cqw; margin: 0 auto; }

/* ------------------------------------------------------------
   LE BANDEAU « NAVIGATEUR DESUET ». Servi AVANT le contenu :
   la premiere chose que la page dit au client du restaurant
   parle du navigateur.
   ------------------------------------------------------------ */
.tou .tou-desuet {
  background: linear-gradient(#fffaea 0%, #ffeeb8 100%);
  border-bottom: 1px solid #e3c765;
  color: #6b4e00;
  font-size: 1.25cqw;
}
.tou .tou-desuet-in {
  display: flex;
  align-items: center;
  gap: 1.2cqw;
  padding: 0.9cqw 0;
}
.tou .tou-desuet-in b { font-weight: bold; }
.tou .tou-des-p { flex: 1 1 auto; }
.tou .tou-brw { display: inline-flex; gap: 0.6cqw; }
.tou .tou-brw i {
  width: 1.9cqw;
  height: 1.9cqw;
  border-radius: 50%;
  box-shadow: inset 0 -0.3cqw 0.5cqw rgba(0, 0, 0, .2);
}
.tou .tou-brw i:nth-child(1) { background: radial-gradient(circle at 34% 30%, #ffd483, #d9631a); }
.tou .tou-brw i:nth-child(2) { background: radial-gradient(circle at 34% 30%, #8fd0ff, #1a63a8); }
.tou .tou-brw i:nth-child(3) { background: radial-gradient(circle at 34% 30%, #ffe27a, #c9a300); }
.tou .tou-brw i:nth-child(4) { background: radial-gradient(circle at 34% 30%, #b9c6cf, #5e7280); }
.tou .tou-x { color: #9a7a2a; font-size: 1.4cqw; }

/* ------------------------------------------------------------
   LA BARRE UTILITAIRE, PUIS L'ENTETE DE L'OFFICE.
   ------------------------------------------------------------ */
.tou .tou-util {
  background: var(--tou-bleu);
  color: #cfe2ef;
  font-size: 1.15cqw;
}
.tou .tou-util-in {
  display: flex;
  justify-content: flex-end;
  gap: 1.8cqw;
  padding: 0.7cqw 0;
}
.tou .tou-lang b { color: #fff; font-weight: bold; }

.tou .tou-entete { border-bottom: 1px solid var(--tou-ligne); }
.tou .tou-entete-in {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2cqw;
  padding: 1.4cqw 0;
}
.tou .tou-logo { display: flex; align-items: center; gap: 1.2cqw; }
.tou .tou-logo-i {
  flex: 0 0 auto;
  width: 4.4cqw;
  height: 4.4cqw;
  border-radius: 1cqw;
  background: linear-gradient(135deg, #35a0cf 0%, #123c59 100%);
  box-shadow: 0 0.2cqw 0.6cqw rgba(18, 60, 89, .35);
}
.tou .tou-logo-t { display: grid; }
.tou .tou-logo-t b {
  font-size: 2.4cqw;
  font-weight: bold;
  line-height: 1.15;
  letter-spacing: -0.05cqw;
  color: var(--tou-bleu);
}
.tou .tou-logo-t span { font-size: 1.15cqw; color: var(--tou-gris); }
/* LE CHAMP DE RECHERCHE DE L'OFFICE — plus gros que le nom du
   restaurant, et il cherche dans TOUTE la region. */
.tou .tou-rech {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1cqw;
  width: 33cqw;
  padding: 1cqw 1.4cqw;
  border: 1px solid var(--tou-ligne);
  border-radius: 2.4cqw;
  background: var(--tou-fond);
  box-shadow: inset 0 0.1cqw 0.35cqw rgba(18, 60, 89, .1);
  color: #93a3ae;
  font-size: 1.25cqw;
}
.tou .tou-loupe {
  position: relative;
  flex: 0 0 auto;
  width: 1.6cqw;
  height: 1.6cqw;
  border: 2px solid #7b93a3;
  border-radius: 50%;
}
.tou .tou-loupe::after {
  content: "";
  position: absolute;
  right: -0.45cqw;
  bottom: -0.15cqw;
  width: 0.9cqw;
  height: 2px;
  background: #7b93a3;
  transform: rotate(45deg);
}

.tou .tou-menu {
  background: linear-gradient(#2180bc 0%, #145a86 100%);
  box-shadow: 0 0.2cqw 0.6cqw rgba(0, 0, 0, .22);
}
.tou .tou-menu-in { display: flex; }
.tou .tou-menu-in span {
  padding: 1.05cqw 1.5cqw;
  color: #eaf3f9;
  font-size: 1.3cqw;
}
.tou .tou-menu-in .tou-on {
  background: rgba(255, 255, 255, .18);
  border-radius: 0.6cqw 0.6cqw 0 0;
  color: #fff;
  font-weight: bold;
}

/* LE FIL D'ARIANE DE L'OFFICE. Le nom du restaurant est la
   quatrieme chose de la ligne, et la plus petite. */
.tou .tou-fil {
  background: var(--tou-fond);
  border-bottom: 1px solid var(--tou-ligne);
  font-size: 1.2cqw;
  color: var(--tou-gris);
}
.tou .tou-fil .tou-c { padding: 0.9cqw 0; }
.tou .tou-fil b {
  margin: 0 0.6cqw;
  color: #aebdc7;
  font-weight: 400;
}
.tou .tou-fil em { font-style: normal; color: var(--tou-encre); }

/* ------------------------------------------------------------
   LA BANNIERE. C'EST LA PHOTO D'UN AUTRE RESTAURANT — elle est
   heritee de la categorie parente, et la legende le dit en
   1,15cqw sous l'image. Aucun fichier : trois aplats et une
   trame, comme partout ailleurs dans cette section.
   ------------------------------------------------------------ */
.tou .tou-ban-ph {
  position: relative;
  display: flex;
  align-items: flex-end;
  overflow: hidden;
  height: 15cqw;
  padding-bottom: 1.6cqw;
  /* LA BANNIERE EST UNE VRAIE PHOTOGRAPHIE.  D-634 */
  background:
    linear-gradient(rgba(8, 22, 32, .34) 0%, rgba(8, 22, 32, 0) 42%, rgba(8, 22, 32, .62) 100%),
    url("../images/realisations/avant-resto-ban.webp") center / cover no-repeat,
    #4c3a27;
}
.tou .tou-ban-nom {
  position: relative;
  z-index: 1;
  width: 88cqw;
  margin: 0 auto;
  color: #fff;
  font-size: 2.5cqw;
  font-weight: bold;
  letter-spacing: -0.05cqw;
  text-shadow: 0 0.2cqw 0.6cqw rgba(0, 0, 0, .6);
}
.tou .tou-ban-leg {
  padding: 0.8cqw 0;
  background: var(--tou-fond);
  border-bottom: 1px solid var(--tou-ligne);
  font-size: 1.15cqw;
  color: var(--tou-gris);
}

/* ------------------------------------------------------------
   LE CORPS. Deux colonnes : la fiche, et les encarts de l'office.
   ------------------------------------------------------------ */
.tou .tou-corps {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 26cqw;
  gap: 3cqw;
  align-items: start;
  padding: 2cqw 0 2.6cqw;
}

/* LES DRAPEAUX ADMINISTRATIFS. « En vedette » et « Ferme
   temporairement » se contredisent, et personne au restaurant ne
   peut retirer ni l'un ni l'autre. */
.tou .tou-drapeaux {
  display: flex;
  flex-wrap: wrap;
  gap: 0.8cqw;
  margin-bottom: 1.2cqw;
}
.tou .tou-drap {
  padding: 0.45cqw 1.1cqw;
  border: 1px solid var(--tou-ligne);
  border-radius: 2cqw;
  background: #eef3f7;
  color: var(--tou-gris);
  font-size: 1.05cqw;
  font-weight: bold;
  letter-spacing: 0.06cqw;
  text-transform: uppercase;
}
.tou .tou-drap--ved {
  border-color: #d59b12;
  background: linear-gradient(#ffd86b, #f0b429);
  color: #5c3d00;
}
.tou .tou-drap--ferme {
  border-color: #f3b5ae;
  background: #fdecea;
  color: #a32116;
}

.tou .tou-h1 {
  font-size: 3.2cqw;
  font-weight: bold;
  line-height: 1.15;
  letter-spacing: -0.05cqw;
  color: var(--tou-bleu);
}
.tou .tou-sous {
  margin-top: 0.5cqw;
  font-size: 1.25cqw;
  color: var(--tou-gris);
}
.tou .tou-st {
  margin-top: 1.9cqw;
  padding-bottom: 0.6cqw;
  border-bottom: 1px solid var(--tou-ligne);
  font-size: 1.7cqw;
  font-weight: bold;
  color: var(--tou-bleu);
}
.tou .tou-p { margin-top: 1.2cqw; font-size: 1.45cqw; }
.tou .tou-note { margin-top: 0.8cqw; font-size: 1.1cqw; color: var(--tou-pale); }

/* LE TABLEAU DE LA FICHE. Quatorze champs, dont trois vides — et
   les trois vides sont exactement les trois que le client cherche :
   les heures, le menu, la reservation. */
.tou .tou-tab {
  overflow: hidden;
  margin-top: 1.2cqw;
  border: 1px solid var(--tou-ligne);
  border-radius: 0.8cqw;
  box-shadow: 0 0.1cqw 0.4cqw rgba(18, 60, 89, .08);
}
.tou .tou-lig {
  display: grid;
  grid-template-columns: 17cqw minmax(0, 1fr);
  gap: 1.2cqw;
  padding: 0.7cqw 1.4cqw;
  font-size: 1.3cqw;
}
.tou .tou-lig:nth-child(odd) { background: #f7fafc; }
.tou .tou-lig + .tou-lig { border-top: 1px solid #e8eef3; }
.tou .tou-cle { color: var(--tou-gris); }
.tou .tou-lien { color: #1259a8; text-decoration: underline; }
.tou .tou-vide { color: #a8b6c0; }
.tou .tou-note-i { font-size: 1.05cqw; color: var(--tou-pale); }

.tou .tou-cats {
  display: flex;
  flex-wrap: wrap;
  gap: 0.7cqw;
  margin-top: 1.2cqw;
}
.tou .tou-cat {
  padding: 0.55cqw 1.2cqw;
  border: 1px solid #c9dcea;
  border-radius: 2cqw;
  background: var(--tou-bleu-p);
  color: #1259a8;
  font-size: 1.15cqw;
}

/* LA CARTE. Un quadrillage de rues, une punaise, un bouton
   « agrandir » — et rien de ce qu'on vient chercher. */
.tou .tou-carte {
  position: relative;
  overflow: hidden;
  height: 14cqw;
  margin-top: 1.2cqw;
  border: 1px solid var(--tou-ligne);
  border-radius: 0.8cqw;
  box-shadow: inset 0 0 2cqw rgba(0, 0, 0, .07);
}
.tou .tou-carte-rues {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(105deg, transparent 0 46%, #cfe0ea 46% 52%, transparent 52%),
    repeating-linear-gradient(90deg, transparent 0 7cqw, #fff 7cqw 8cqw),
    repeating-linear-gradient(0deg, transparent 0 4.6cqw, #fff 4.6cqw 5.3cqw),
    linear-gradient(#eaeee5, #dfe6da);
}
.tou .tou-carte-pin {
  position: absolute;
  left: 41%;
  top: 34%;
  width: 2.2cqw;
  height: 2.2cqw;
  border: 2px solid #fff;
  border-radius: 50% 50% 50% 0;
  background: #d93025;
  box-shadow: 0 0.3cqw 0.6cqw rgba(0, 0, 0, .38);
  transform: rotate(-45deg);
}
.tou .tou-carte-btn {
  position: absolute;
  right: 1cqw;
  top: 1cqw;
  padding: 0.6cqw 1.1cqw;
  border: 1px solid #c3ced6;
  border-radius: 0.4cqw;
  background: #fff;
  box-shadow: 0 0.15cqw 0.4cqw rgba(0, 0, 0, .2);
  color: #1259a8;
  font-size: 1.1cqw;
}
.tou .tou-carte-att {
  position: absolute;
  left: 1cqw;
  bottom: 0.8cqw;
  font-size: 1cqw;
  color: #7d8b93;
}

.tou .tou-btns {
  display: flex;
  flex-wrap: wrap;
  gap: 0.9cqw;
  margin-top: 1.6cqw;
}
.tou .tou-btn {
  padding: 1cqw 1.6cqw;
  border: 1px solid #c3d3de;
  border-radius: 0.5cqw;
  background: linear-gradient(#fff, #eef3f7);
  box-shadow: 0 0.1cqw 0.3cqw rgba(18, 60, 89, .14);
  color: var(--tou-bleu);
  font-size: 1.25cqw;
  font-weight: bold;
}
/* LE BOUTON PLEIN EST CELUI DE L'OFFICE, PAS CELUI DU CLIENT :
   « ajouter a mon carnet de voyage » sert l'annuaire. Reserver une
   table n'existe nulle part sur cette page. */
.tou .tou-btn--plein {
  border-color: #12557f;
  background: linear-gradient(#2a8fbf, #14638f);
  color: #fff;
}

.tou .tou-tenue {
  display: flex;
  align-items: flex-start;
  gap: 1.2cqw;
  margin-top: 1.4cqw;
  padding: 1.1cqw 1.4cqw;
  border: 1px solid #cfe0ec;
  border-left: 4px solid #2a8fbf;
  border-radius: 0.6cqw;
  background: var(--tou-bleu-p);
  font-size: 1.2cqw;
  color: #3b4c58;
}
.tou .tou-tenue-i {
  flex: 0 0 auto;
  width: 2.2cqw;
  height: 2.2cqw;
  border-radius: 50%;
  background: #2a8fbf;
}
.tou .tou-tenue b { font-weight: bold; color: var(--tou-bleu); }

/* ------------------------------------------------------------
   LA COLONNE DE DROITE — les encarts de l'office.
   ------------------------------------------------------------ */
.tou .tou-late { display: grid; gap: 1.6cqw; }
.tou .tou-encart {
  overflow: hidden;
  border: 1px solid var(--tou-ligne);
  border-radius: 0.8cqw;
  background: #fff;
  box-shadow: 0 0.15cqw 0.5cqw rgba(18, 60, 89, .09);
}
.tou .tou-encart-t {
  padding: 0.9cqw 1.2cqw;
  border-bottom: 1px solid var(--tou-ligne);
  background: linear-gradient(#f9fbfc, #e9f1f7);
  font-size: 1.2cqw;
  font-weight: bold;
  color: var(--tou-bleu);
}
.tou .tou-enc-in {
  display: grid;
  gap: 0.6cqw;
  padding: 1.2cqw;
}
.tou .tou-enc-l { font-size: 1.2cqw; }
.tou .tou-enc-l b { font-weight: bold; }
.tou .tou-lig2 {
  display: flex;
  justify-content: space-between;
  gap: 1cqw;
  padding-bottom: 0.5cqw;
  border-bottom: 1px dotted #dde6ec;
  font-size: 1.15cqw;
}
.tou .tou-lig2 span { color: var(--tou-gris); }
.tou .tou-lig2 b { font-weight: bold; }
.tou .tou-pub {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 11cqw;
  padding: 0 1cqw;
  border: 1px dashed #c3d3de;
  border-radius: 0.5cqw;
  background: repeating-linear-gradient(45deg, #f5f9fb 0 1cqw, #eaf1f6 1cqw 2cqw);
  color: var(--tou-pale);
  font-size: 1.1cqw;
  text-align: center;
}
.tou .tou-pub--court { height: 7.5cqw; }

/* ------------------------------------------------------------
   LES AUTRES ETABLISSEMENTS DE LA CATEGORIE. Quatre vignettes au
   MEME gabarit : la fiche n'appartient pas au restaurant, elle
   appartient a la liste.
   ------------------------------------------------------------ */
.tou .tou-autres {
  padding: 2.4cqw 0 2.6cqw;
  border-top: 1px solid var(--tou-ligne);
  background: var(--tou-fond);
}
.tou .tou-st--centre {
  margin-top: 0;
  padding-bottom: 0;
  border-bottom: 0;
  text-align: center;
}
.tou .tou-vigs {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1.6cqw;
  margin-top: 1.8cqw;
}
.tou .tou-vig {
  display: grid;
  overflow: hidden;
  border: 1px solid var(--tou-ligne);
  border-radius: 0.8cqw;
  background: #fff;
  box-shadow: 0 0.2cqw 0.6cqw rgba(18, 60, 89, .11);
}
/* QUATRE SALLES, PAS QUATRE ASSIETTES : un annuaire montre le LIEU.
   Meme colonne de tuiles que les vignettes de l'annuaire, quatre
   rangs cette fois.  D-634 */
.tou .tou-vig-ph {
  height: 9cqw;
  background-color: #7a6144;
  background-image: url("../images/realisations/avant-resto-vig.webp");
  background-repeat: no-repeat;
  background-size: 100% 400%;
  background-position: 0 0%;
}
.tou .tou-vig-ph--b { background-position: 0 33.333%; }
.tou .tou-vig-ph--c { background-position: 0 66.667%; }
.tou .tou-vig-ph--d { background-position: 0 100%; }
.tou .tou-vig b {
  padding: 1cqw 1.1cqw 0;
  font-size: 1.3cqw;
  font-weight: bold;
  color: var(--tou-bleu);
}
.tou .tou-vig span {
  padding: 0 1.1cqw;
  font-size: 1.1cqw;
  color: var(--tou-gris);
}
.tou .tou-vig em {
  padding: 0.3cqw 1.1cqw 1.1cqw;
  font-size: 1.1cqw;
  font-style: normal;
  color: var(--tou-pale);
}

/* ------------------------------------------------------------
   L'INFOLETTRE DE L'OFFICE, PUIS SON PIED DE PAGE.
   ------------------------------------------------------------ */
.tou .tou-info {
  padding: 2.2cqw 0;
  background: linear-gradient(#2180bc, #123c59);
  color: #fff;
}
.tou .tou-info-in {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 2cqw;
}
.tou .tou-info-t { font-size: 2cqw; font-weight: bold; }
.tou .tou-info-p { margin-top: 0.3cqw; font-size: 1.25cqw; color: #cfe2ef; }
.tou .tou-info-f { display: flex; gap: 0.8cqw; }
.tou .tou-info-ch {
  width: 24cqw;
  padding: 1.1cqw 1.4cqw;
  border-radius: 0.5cqw;
  background: #fff;
  color: #93a3ae;
  font-size: 1.25cqw;
}
.tou .tou-info-b {
  padding: 1.1cqw 1.8cqw;
  border-radius: 0.5cqw;
  background: linear-gradient(#ffd86b, #f0b429);
  box-shadow: 0 0.2cqw 0.5cqw rgba(0, 0, 0, .28);
  color: #5c3d00;
  font-size: 1.25cqw;
  font-weight: bold;
}

.tou .tou-pied {
  padding: 2.4cqw 0 1.6cqw;
  background: #0e2f45;
  color: #b9cdda;
}
.tou .tou-pied-in {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 2cqw;
}
.tou .tou-pt {
  margin-bottom: 0.9cqw;
  font-size: 1.25cqw;
  font-weight: bold;
  color: #fff;
}
.tou .tou-pl { padding: 0.3cqw 0; font-size: 1.15cqw; }
.tou .tou-parts {
  display: flex;
  justify-content: center;
  gap: 1.2cqw;
  margin-top: 1.8cqw;
  padding-top: 1.6cqw;
  border-top: 1px solid rgba(255, 255, 255, .15);
}
/* LA BANDE DES PARTENAIRES N'EST PAS UNE PHOTO, ET NE PEUT PAS EN ETRE UNE : ce…  D-634 */
.tou .tou-parts i {
  position: relative;
  width: 12cqw;
  height: 4cqw;
  border-radius: 0.4cqw;
  background: rgba(255, 255, 255, .07);
}
.tou .tou-parts i::before {
  content: "";
  position: absolute;
  left: 1cqw;
  top: 1.05cqw;
  width: 1.9cqw;
  height: 1.9cqw;
  border-radius: 50%;
  background: rgba(255, 255, 255, .30);
}
.tou .tou-parts i::after {
  content: "";
  position: absolute;
  left: 3.5cqw;
  top: 1.5cqw;
  width: 7.2cqw;
  height: 1cqw;
  border-radius: 0.2cqw;
  background: rgba(255, 255, 255, .22);
}
.tou .tou-parts i:nth-child(2)::after { width: 5.4cqw; }
.tou .tou-parts i:nth-child(3)::after { width: 6.6cqw; }
.tou .tou-parts i:nth-child(5)::after { width: 5.9cqw; }
.tou .tou-copy {
  display: flex;
  justify-content: space-between;
  gap: 2cqw;
  margin-top: 2cqw;
  font-size: 1.05cqw;
  color: #7f97a7;
}

/* Le texte defilant doit RESTER LISIBLE a l'arret : sans le retrait du
   decalage de depart, la bande s'arrete vide. */
@media (prefers-reduced-motion: reduce) {
  .v11-defile span { padding-left: 0; animation: none !important; }
}

/* ===================================================================
   12 · LES PHOTOGRAPHIES
   Le public est visuel : il ne lit pas, il regarde. Une illustration se
   pose donc EN TETE de la colonne, avant la liste, jamais apres.
   Toutes portent leur `width`/`height` : sans elles, une image
   paresseuse decale la page en arrivant et le CLS quitte 0.  D-857
   =================================================================== */

.illus { margin: 0 0 var(--e-3); }
.illus img {
  width: 100%; height: auto;
  aspect-ratio: 3 / 2; object-fit: cover;
  border-radius: var(--rayon-large);
  box-shadow: var(--ombre-pose);
}
.illus--large { margin-bottom: var(--e-6); }
.illus--large img { aspect-ratio: 21 / 9; }

/* La bande de lieu ferme la page de contact : une seule image, pleine
   largeur, avec un mot dessus. Le voile est un aplat navy translucide —
   pas un degrade — pour que le texte tienne 4,5:1 sur n'importe quel
   pixel de la photographie, y compris le plus clair.  D-858 */
.bande-lieu { position: relative; isolation: isolate; }
.bande-lieu img {
  width: 100%; height: clamp(15rem, 34vw, 26rem);
  object-fit: cover; display: block;
}
.bande-lieu-mot {
  background: var(--navy-dark);
  color: var(--pearl);
  margin: 0;
  padding: var(--e-5) var(--gouttiere);
  font-family: var(--font-titre);
  font-size: var(--t-3); line-height: var(--lh-3); letter-spacing: var(--ls-3);
}
.bande-lieu-mot span {
  display: block;
  max-width: var(--page-max); margin-inline: auto;
}

/* La figure et la carte « ce qui est inclus » tiennent dans la MEME colonne.
   Sans enveloppe commune, la grille posait la carte en rangee 2 colonne 1,
   c'est-a-dire sous le texte : l'oeil descendait a gauche, remontait a
   droite, redescendait a gauche.  D-859 */
/* `.deux-colonnes` NE STYLAIT RIEN DU TOUT.  D-987
   La classe est posee sept fois — les cinq blocs de service, un bloc de
   `reference` et un de l'accueil — et elle n'avait AUCUNE regle dans la
   feuille. Aucune erreur nulle part : deux `div` empiles sont du HTML
   parfaitement valide. Le resultat se voyait, lui, et il portait un nom
   dans la bouche du proprietaire : « les services sont mal representes,
   il y a trop de texte, pas assez de design ». Le texte occupait sa
   demi-colonne de lecture, les 600 px de droite restaient vides sur toute
   sa hauteur, et le visuel tombait EN DESSOUS, en pleine largeur.
   Deux colonnes, donc, a partir de 62em — et une seule sous ce seuil,
   ou l'empilement etait deja le bon rendu.
   0,9 ET NON 1 : la colonne de gauche porte le texte courant, celle de
   droite un visuel et une carte. A parts egales, la ligne de lecture
   passait sous 45 caracteres.  D-987 */
.deux-colonnes { display: grid; gap: var(--e-6); align-items: start; }
@media (min-width: 62em) {
  .deux-colonnes { grid-template-columns: 1fr 0.9fr; gap: var(--e-7); }
}
.colonne-visuelle { display: grid; gap: var(--e-3); align-content: start; }

/* SUR TELEPHONE, L'APERCU PASSE AU-DESSUS DES PASTILLES.
   En dessous, un patron qui appuyait sur « Garage et mecanique » voyait le
   bouton changer de couleur et rien d'autre : l'image etait a un ecran et
   demi plus bas, et il concluait que c'etait brise. On place par LIGNE de
   grille, pas par `order` : `order` reordonne aussi l'ordre de PEINTURE
   (piege 77), et l'ordre du clavier suivrait le DOM, pas l'ecran.  D-866 */
@media (max-width: 61.99em) {
  .secteurs-grille { grid-template-rows: auto auto; }
  .secteurs-grille > .sector-preview,
  .secteurs-grille > figure { grid-row: 1; }
  .secteurs-grille > .secteur-groupes,
  .secteurs-grille > div:not(.sector-preview) { grid-row: 2; }
}

/* Une confirmation dans la page se VOIT : elle est le seul objet vert de
   l'ecran, elle a un cadre, et elle ne s'efface pas.  D-882 */
.form-status.is-ok {
  display: flex; align-items: flex-start; gap: var(--e-2);
  margin-top: var(--e-3);
  padding: var(--e-3);
  background: var(--ok-wash);
  border-left: 3px solid var(--ok);
  border-radius: var(--rayon);
  color: var(--ok);
  font-size: var(--t-0); font-weight: 600; line-height: 1.5;
}
.form-status.is-ok:focus-visible { outline-offset: 2px; }

/* LA POIGNEE DE L'IMAGE DU HERO EST UNE PROMESSE. On la voit, on tire, et
   c'est une image fixe : il ne se passe rien. Un patron l'a essaye et a
   ecrit « vous me montrez un bouton qui est juste une image ». On ne retire
   pas la poignee — elle est ce qui rend l'image comprehensible — on rend la
   promesse vraie : l'image entiere mene au comparateur vivant.  D-884 */
.hero-preuve-lien {
  display: block; position: relative;
  border-radius: var(--rayon-large);
  text-decoration: none;
}
.hero-preuve-acte {
  position: absolute; left: 50%; bottom: var(--e-2);
  transform: translateX(-50%);
  display: inline-flex; align-items: center; gap: var(--e-1);
  min-height: var(--cible-min);
  padding: 0 var(--e-3);
  background: var(--navy-dark); color: var(--pearl);
  border-radius: var(--rayon);
  font-size: var(--t-00); font-weight: 600;
  white-space: nowrap;
  box-shadow: var(--ombre-levee);
  transition: background-color var(--t-etat);
}
.hero-preuve-acte svg { width: 1rem; height: 1rem; }
.hero-preuve-lien:hover .hero-preuve-acte { background: var(--navy); }


/* ===================================================================
   20 · REMPLIR — les composants nes du verdict « les pages sont vides »
   ===================================================================
   Le proprietaire a note le site 3 sur 10 : « trop simple, trop vide,
   il manque les actions, les visuels, le mouvement et l'information ».
   Mesure a l'image, il avait raison sur les trois : l'accueil portait
   369 mots et UNE image sur 4 614 px, `automatisation` et `reference`
   n'en portaient aucune, et le contenu tenait dans la moitie gauche.

   Ce n'est pas un probleme de gout, c'est un probleme de DENSITE. Les
   composants qui suivent existent pour la remonter sans encombrer :
   chacun porte UNE idee, et chacun apporte un media ou un chiffre que
   le visiteur REGARDE au lieu de lire.  D-888
   =================================================================== */


/* -------------------------------------------------------------------
   20.1 · L'EN-TETE DE PAGE A DEUX COLONNES
   Un titre seul dans une colonne de gauche laisse 560 px de blanc a
   droite et repousse le contenu sous la ligne de flottaison. La
   colonne de droite porte trois reperes chiffres : ce n'est pas une
   seconde idee, c'est la preuve immediate de la premiere.
   ------------------------------------------------------------------- */

.entete-grille { display: grid; gap: var(--e-5); }
@media (min-width: 62em) {
  .entete-grille { grid-template-columns: 1.15fr 0.85fr; gap: var(--e-8); align-items: end; }
}
.entete-grille .tete { margin-bottom: 0; }
.entete-actes { margin-top: var(--e-4); }

.reperes {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: var(--e-2);
  padding-top: var(--e-3);
  border-top: var(--filet) solid var(--line);
}
.repere b {
  display: block;
  font-family: var(--font-titre); font-weight: 460;
  font-size: var(--t-2); line-height: 1.1; letter-spacing: var(--ls-2);
  color: var(--navy-dark);
}
.repere span {
  display: block; margin-top: var(--e-1);
  font-size: var(--t-00); line-height: 1.45; color: var(--text-soft);
}
.bande--navy .repere b { color: var(--pearl); }
.bande--navy .repere span { color: var(--champagne-light); }
.bande--navy .reperes { border-top-color: rgb(210 182 138 / 0.32); }


/* LE SOMMAIRE DE PAGE — la colonne de droite de l'en-tete quand la page
   contient PLUSIEURS choses. Il dit le nombre AVANT le nom : « 4 » se lit
   plus vite que « quatre comparaisons ». Chaque ligne est une ancre, donc
   une cible de 56 px, et `tools/liens-check.mjs` verifie qu'elle mene
   quelque part.  D-894 */
.entete-sommaire {
  display: grid; gap: 0;
  border-top: var(--filet) solid var(--line);
}
.entete-sommaire a {
  display: flex; align-items: baseline; gap: var(--e-2);
  min-height: var(--cible);
  padding-block: var(--e-1);
  border-bottom: var(--filet) solid var(--line);
  text-decoration: none;
  transition: padding-left var(--t-etat);
}
.entete-sommaire a:hover { padding-left: var(--e-1); }
.entete-sommaire b {
  flex: 0 0 3.25rem;
  font-family: var(--font-titre); font-weight: 460;
  font-size: var(--t-2); line-height: 1.15; letter-spacing: var(--ls-2);
  color: var(--navy-dark);
}
.entete-sommaire span { font-size: var(--t-00); color: var(--text-soft); }


/* -------------------------------------------------------------------
   20.2 · LE DUO — un texte et un media, cote a cote, en alternance
   La regle « une chose a la fois » ne dit pas « une colonne » : elle
   dit une IDEE. Un duo porte une idee sur deux colonnes, et remplit la
   largeur au lieu de laisser la droite vide.
   ------------------------------------------------------------------- */

.duo { display: grid; gap: var(--e-5); align-items: center; }
.duo + .duo {
  margin-top: var(--e-7);
  padding-top: var(--e-7);
  border-top: var(--filet) solid var(--line);
}
@media (min-width: 62em) {
  .duo { grid-template-columns: 1fr 1fr; gap: var(--e-8); }
  .duo--serre { grid-template-columns: 1.1fr 0.9fr; }
  /* L'ORDRE REORDONNE AUSSI LA PEINTURE, pas seulement la place.  Piege 34
     Ici rien ne se recouvre : les deux colonnes sont disjointes, et le
     lecteur d'ecran suit l'ordre du balisage, ou le texte vient toujours
     en premier. C'est le seul cas ou `order` est sans danger. */
  .duo--inverse > :first-child { order: 2; }
}
.duo-texte > * + * { margin-top: var(--e-3); }
.duo-media { margin: 0; }

/* LES ETAPES EN COURT — le rail vertical d'un duo. Ce n'est pas `.etapes`
   de la page `processus` : celui-la porte un livrable par etape et vit
   seul dans sa bande. Ici trois lignes, un numero, un fait.  D-902 */
.etapes-court { display: grid; gap: var(--e-4); margin-top: var(--e-5); }
.etapes-court li {
  display: grid; grid-template-columns: 2.5rem 1fr; gap: var(--e-2);
  padding-top: var(--e-3);
  border-top: var(--filet) solid var(--line-strong);
}
.etapes-court b {
  font-family: var(--font-texte);
  font-size: var(--t-00); font-weight: 700;
  letter-spacing: var(--ls-etiquette); color: var(--text-soft);
  padding-top: 0.35rem;
}
.etapes-court h3 {
  font-size: var(--t-1); line-height: var(--lh-1); letter-spacing: var(--ls-1);
  font-weight: 460;
}
.etapes-court p { margin-top: var(--e-1); color: var(--text-soft); }


/* -------------------------------------------------------------------
   20.3 · LA FIGURE — une photographie, une capture, avec sa legende
   Le rapport est TOUJOURS impose : sans lui, l'image arrive apres la
   mise en page et decale tout ce qui la suit. Le CLS reste a 0.
   ------------------------------------------------------------------- */

.figure { margin: 0; }
.figure img {
  display: block; width: 100%; height: auto;
  border-radius: var(--rayon-large);
  object-fit: cover;
}
.figure--16-9 img { aspect-ratio: 16 / 9; }
.figure--4-3  img { aspect-ratio: 4 / 3; }
.figure--3-2  img { aspect-ratio: 3 / 2; }
.figure--haute img { aspect-ratio: 4 / 5; }
.figure--ombre img { box-shadow: var(--ombre-levee); }
.figure--cadre img { border: var(--filet) solid var(--line-strong); }
.figure figcaption {
  margin-top: var(--e-2);
  font-size: var(--t-00); line-height: 1.5; color: var(--text-soft);
}
.figure figcaption b { color: var(--text); font-weight: 600; }


/* -------------------------------------------------------------------
   20.4 · L'ECRAN — le cadre de navigateur autour d'une capture
   Une capture d'ecran sans cadre se lit comme une illustration. Avec
   trois pastilles et une barre d'adresse muette, elle se lit comme un
   SITE — c'est exactement ce qu'on vend.
   ------------------------------------------------------------------- */

.ecran {
  margin: 0;
  border-radius: var(--rayon-large);
  overflow: hidden;
  border: var(--filet) solid var(--line-strong);
  background: var(--pearl);
  box-shadow: var(--ombre-levee);
}
.ecran-barre {
  display: flex; align-items: center; gap: 0.375rem;
  padding: 0.5rem 0.75rem;
  background: var(--marble);
  border-bottom: var(--filet) solid var(--line);
}
.ecran-barre i {
  width: 0.5rem; height: 0.5rem; border-radius: 50%;
  background: var(--line-strong);
}
.ecran-barre span {
  margin-left: 0.5rem;
  flex: 1 1 auto;
  height: 1rem;
  border-radius: 999px;
  background: var(--pearl);
}
.ecran img {
  display: block; width: 100%; height: auto;
  aspect-ratio: 16 / 10;
  object-fit: cover; object-position: top center;
}


/* -------------------------------------------------------------------
   20.5 · LA MOSAIQUE — plusieurs captures d'un coup
   Neuf sites de demonstration existent sur le disque et la page qui
   les annonce n'en montrait aucun. Une grille en montre six d'un
   regard : c'est le geste qui remplit le plus pour le moins de mots.
   ------------------------------------------------------------------- */

.mosaique {
  display: grid; gap: var(--e-3);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 15rem), 1fr));
}
.mosaique a, .mosaique figure { margin: 0; text-decoration: none; display: block; }
.mosaique img {
  display: block; width: 100%; height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover; object-position: top center;
  border-radius: var(--rayon-large);
  border: var(--filet) solid var(--line-strong);
  background: var(--marble);
  transition: transform var(--t-etat), box-shadow var(--t-etat);
}
.mosaique a:hover img { transform: translateY(-2px); box-shadow: var(--ombre-levee); }

/* UNE CAPTURE DE SITE SE MONTRE AU RAPPORT OU ELLE A ETE PRISE.
   Les douze captures font 1440 x 900 : rognees en 4/3 elles perdaient un
   sixieme de leur largeur, et le titre en pleine masse sortait du cadre —
   on voyait neuf abstractions au lieu de neuf premiers ecrans. Trois
   colonnes de 400 px plutot que cinq de 230 : a 230 px de large, un
   premier ecran ne se lit plus, il se devine.
   CE BLOC EST APRES `.mosaique img`, PAS AVANT : a specificite egale
   (0,1,1 contre 0,1,1), c'est le dernier ecrit qui gagne, et place plus
   haut il ne changeait rien du tout.  D-895 */
.mosaique--ecran { grid-template-columns: repeat(auto-fill, minmax(min(100%, 20rem), 1fr)); }
.mosaique--ecran img { aspect-ratio: 16 / 10; object-position: center top; }
.mosaique figcaption, .mosaique .mos-nom {
  display: flex; align-items: center; gap: var(--e-1);
  margin-top: var(--e-2);
  font-size: var(--t-00); font-weight: 600; color: var(--navy-dark);
}
.mosaique .mos-nom svg { width: 0.9375rem; height: 0.9375rem; transition: transform var(--t-etat); }
.mosaique a:hover .mos-nom svg { transform: translateX(3px); }
.mosaique .mos-dit { display: block; font-size: var(--t-00); font-weight: 400; color: var(--text-soft); }


/* -------------------------------------------------------------------
   20.6 · LA BANDE PHOTOGRAPHIQUE — pleine largeur, sur toute la fenetre
   Le texte NE SE POSE JAMAIS sur la photographie : il vit sur un
   panneau navy plein. Un contraste sur une image ne se mesure pas, et
   ce qui ne se mesure pas ne se defend pas devant l'outil de controle.
   ------------------------------------------------------------------- */

.bande-photo {
  position: relative;
  background: var(--navy-dark);
  overflow: hidden;
}
.bande-photo > img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  /* Le voile n'est pas la pour rendre le texte lisible — le panneau s'en
     charge — mais pour que la photo ne crie pas plus fort que lui. */
  opacity: 0.55;
}
.bande-photo-dedans {
  position: relative;
  padding-block: var(--e-8);
  display: grid; gap: var(--e-5);
  align-items: center;
}
@media (min-width: 62em) {
  .bande-photo-dedans { padding-block: var(--e-9); grid-template-columns: 1fr 1fr; gap: var(--e-7); }
  .bande-photo--droite .bande-photo-panneau { grid-column: 2; }
}

/* LES QUATRE METIERS DE LA BANDE — deux par deux, cadres en blanc.  D-907
   Une photographie posee sur une photographie ne se lit que si elle porte
   son propre bord : le cadre pearl de 4 px separe la vignette du fond
   assombri, et l'etiquette vit sur un socle navy plein — jamais sur
   l'image, dont le contraste ne se mesure pas. */
.bande-photo-metiers {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--e-2);
}
.bande-photo-metiers li {
  position: relative;
  border-radius: var(--rayon-large);
  overflow: hidden;
  border: 4px solid var(--pearl);
  box-shadow: var(--ombre-levee);
}
.bande-photo-metiers img {
  display: block; width: 100%; height: auto;
  aspect-ratio: 4 / 3; object-fit: cover;
}
.bande-photo-metiers span {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: var(--e-1) var(--e-2);
  background: var(--navy-dark); color: var(--pearl);
  font-size: var(--t-00); font-weight: 600; line-height: 1.35;
}
.bande-photo-panneau {
  background: var(--navy-dark);
  color: var(--pearl);
  padding: var(--e-5);
  border-radius: var(--rayon-large);
  border-left: 3px solid var(--champagne);
  box-shadow: var(--ombre-levee);
}
.bande-photo-panneau h2, .bande-photo-panneau h3 { color: var(--pearl); }
.bande-photo-panneau p { color: var(--champagne-light); margin-top: var(--e-2); }
.bande-photo-panneau .actes { margin-top: var(--e-4); }
/* LE FOND CHANGE, LA COULEUR DU TEXTE DOIT CHANGER AVEC LUI. Le sur-titre
   est en `--text-soft` et le bouton nu en `--navy-dark` : poses tels quels
   sur du navy, ils donnent 1,7:1 et 1,0:1 — un titre gris sombre sur bleu
   sombre, et un bouton parfaitement invisible. Meme faute qu'au pied,
   meme correction.  D-848, D-898 */
.bande-photo-panneau .sur-titre { color: var(--champagne-light); }
.bande-photo-panneau .sur-titre::after { background: var(--champagne); }
.bande-photo-panneau .btn--nu { color: var(--pearl); text-decoration-color: var(--champagne-dark); }
.bande-photo-panneau .btn--nu:hover { color: var(--champagne-light); }
/* LA MENTION DE LA PHOTOGRAPHIE. Deux fautes d'un coup dans sa premiere
   version : 12 px — sous le plancher de 15 que le site s'impose a tous les
   ecrans — et du blanc a 62 % pose DIRECTEMENT sur une image, dont le
   contraste ne se mesure pas. Elle porte donc son propre fond navy, comme
   le panneau, et le plancher de corps s'applique a elle comme au reste :
   une mention qui s'excuse d'exister en devenant illisible n'est plus une
   mention, c'est un petit caractere.  D-898 */
.bande-photo-credit {
  position: absolute; right: var(--e-2); bottom: var(--e-2);
  padding: 0.2rem 0.5rem;
  border-radius: var(--rayon);
  background: var(--navy-dark);
  font-size: var(--t-00); color: var(--champagne-light);
}


/* -------------------------------------------------------------------
   20.7 · LE RANG DE CHIFFRES — quatre faits, une ligne
   Chaque chiffre porte sa source ou n'existe pas.  Regle A, Q2.
   ------------------------------------------------------------------- */

.chiffres-rang {
  display: grid; gap: var(--e-4);
  grid-template-columns: repeat(2, 1fr);
}
@media (min-width: 48em) { .chiffres-rang { grid-template-columns: repeat(4, 1fr); } }
.chiffre-bloc b {
  display: block;
  font-family: var(--font-titre); font-weight: 460;
  font-size: var(--t-3); line-height: 1.05; letter-spacing: var(--ls-3);
  color: var(--navy-dark);
}
.chiffre-bloc span {
  display: block; margin-top: var(--e-1);
  font-size: var(--t-00); line-height: 1.5; color: var(--text-soft);
}
.bande--navy .chiffre-bloc b { color: var(--pearl); }
.bande--navy .chiffre-bloc span { color: var(--champagne-light); }


/* -------------------------------------------------------------------
   20.8 · LA MENTION DE DEMONSTRATION, EN UNE LIGNE
   L'aveu de `realisations` faisait CINQ lignes dans un cadre silk, en
   tete d'une page qui annonce « rien a lire : vous regardez ». La
   reserve reste entiere — entreprises fictives, ecrans montes,
   panoramas sous licence, aucun client nomme — mais elle tient sur une
   ligne et elle ne prend plus la place de ce qu'elle couvre.  D-889
   ------------------------------------------------------------------- */

.mention-demo {
  display: flex; align-items: flex-start; gap: var(--e-2);
  margin-top: var(--e-3);
  font-size: var(--t-00); line-height: 1.5;
  color: var(--text-soft);
}
.mention-demo svg { width: 1rem; height: 1rem; flex: 0 0 auto; margin-top: 0.2rem; color: var(--navy); }
.mention-demo b { color: var(--text); font-weight: 600; }
.mention-demo a { color: var(--navy-dark); }


/* -------------------------------------------------------------------
   20.9 · LA BANDE D'ACTIONS DE FIN DE PAGE
   Elle est la MEME sur les sept pages, injectee par `tools/pages.mjs`
   depuis `partiels/portes.html`, et l'action mise en avant change avec
   la page (`data-forte` pose par `tools/pages.mjs` d'apres le
   `data-porte` du `<body>`). Un visiteur qui arrive au bas d'une page
   ne doit jamais avoir a remonter pour agir.  D-890
   ------------------------------------------------------------------- */

.portes-fin { background: var(--silk); padding-block: var(--bande); }
.portes-fin .tete { margin-bottom: var(--e-4); }
.portes-rang {
  display: grid; gap: var(--e-2);
  grid-template-columns: repeat(2, 1fr);
}
@media (min-width: 48em) { .portes-rang { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 78em) { .portes-rang { grid-template-columns: repeat(6, 1fr); } }

.porte-carte {
  display: flex; flex-direction: column; gap: var(--e-1);
  min-height: 7.5rem;
  padding: var(--e-3);
  text-align: left;
  background: var(--pearl);
  border: var(--filet) solid var(--line);
  border-radius: var(--rayon-large);
  text-decoration: none;
  transition: border-color var(--t-etat), transform var(--t-etat), box-shadow var(--t-etat);
}
.porte-carte:hover {
  border-color: var(--navy-light);
  transform: translateY(-2px);
  box-shadow: var(--ombre-pose);
}
.porte-carte svg { width: 1.375rem; height: 1.375rem; color: var(--navy); }
.porte-carte b {
  font-size: var(--t-00); font-weight: 700; line-height: 1.3;
  color: var(--navy-dark);
}
.porte-carte span { font-size: var(--t-00); line-height: 1.4; color: var(--text-soft); }
/* La porte mise en avant par la page : elle est pleine, pas cadree. */
.porte-carte[data-forte] { background: var(--navy-dark); border-color: var(--navy-dark); }
.porte-carte[data-forte] svg { color: var(--champagne); }
.porte-carte[data-forte] b { color: var(--pearl); }
.porte-carte[data-forte] span { color: var(--champagne-light); }


/* -------------------------------------------------------------------
   20.10 · LE MOUVEMENT — un SECOND geste, pour les medias seulement
   Le geste du site est de 16 px et 500 ms : il est juste pour du texte
   et invisible sur une image de 560 px de haut. Une image entre de
   24 px et d'un centieme d'echelle : le deplacement du bord haut est
   alors de 24 + 3 = 27 px sur une image de 560, ce qui se VOIT.
   Aucune opacite n'est scrubbee sur un element qui porte du texte, et
   `prefers-reduced-motion` supprime le geste sans rien cacher.  D-891
   ------------------------------------------------------------------- */

/* `.entre.entre--media` ET PAS `.entre--media` SEUL. Le script n'observe
   que `.entre` : un element qui ne porte que le modificateur n'obtient
   jamais son `data-vu`, reste a opacite 0, et disparait POUR TOUJOURS.
   Neuf captures de sites se sont evanouies comme ca. La regle ne peut
   plus cacher ce que le script ne peut pas rallumer.  D-891 */
@media (prefers-reduced-motion: no-preference) {
  html.js .entre.entre--media { opacity: 0; transform: translateY(var(--m-distance-media)); }
  html.js .entre.entre--media[data-vu] {
    opacity: 1; transform: none;
    transition: opacity 620ms var(--m-courbe), transform 620ms var(--m-courbe);
    transition-delay: var(--m-retard, 0ms);
  }
  html.js .entre.entre--media[data-vu-net] { opacity: 1; transform: none; transition: none; }
}


/* ===================================================================
   21 · CE QUE `services` ET `automatisation` ONT DEMANDE EN PLUS
   ===================================================================
   Quatre pieces qui manquaient pour poser les composants de la section
   20 sur ces deux pages-la. Aucune ne redefinit quoi que ce soit.
   La cinquieme — deux modificateurs de mosaique — n'a pas ete reprise :
   elle refaisait `.mosaique--ecran` sous un autre nom, et deux noms pour
   la meme chose sont une derive, pas une option.  D-900
   =================================================================== */


/* -------------------------------------------------------------------
   A · L'EN-TETE QUAND SA COLONNE DE DROITE PORTE UNE IMAGE
   `automatisation` annoncait « le temps que vous perdez » sur 348 px
   de haut, sans une seule image de ce temps-la. La photographie prend
   donc toute la colonne de droite, et les trois reperes passent SOUS
   le titre, a gauche.  D-901

   Ils y sont parce que `.entete-grille` cale ses deux colonnes par le
   BAS : photo (3:2 sur 560 px = 373) contre titre seul (190) laissait
   180 px de blanc AU-DESSUS du titre — le trou qu'on est venu fermer,
   deplace d'un metre. Titre + reperes fait 344, la photo 373 : les
   deux colonnes se repondent.
   ------------------------------------------------------------------- */

.entete-dit { display: grid; align-content: end; }
.entete-dit .tete + .reperes { margin-top: var(--e-5); }


/* -------------------------------------------------------------------
   B · LE SOMMAIRE — ce qu'il y a VRAIMENT dans les 91 pages
   La page annoncait deux guides et n'en montrait que les couvertures :
   le visiteur devait croire sur parole. Les titres listes ici sont les
   `<h2>` reels de `documents/src/*.html`, recopies au caractere pres.
   Le filet champagne est DECORATIF — il ne porte ni texte ni sens, et
   le crochet navy porte, lui, l'information.  D-902
   ------------------------------------------------------------------- */

.sommaire { display: grid; gap: var(--e-1); margin-top: var(--e-2); }
.sommaire li {
  display: flex; align-items: flex-start; gap: var(--e-2);
  font-size: var(--t-00); line-height: 1.5;
  color: var(--text);
}
.sommaire li::before {
  content: ""; flex: 0 0 auto;
  width: 0.75rem; height: 0; margin-top: 0.68rem;
  border-top: 2px solid var(--champagne-dark);
}
.sommaire-titre {
  font-size: var(--t-00); font-weight: 700;
  letter-spacing: var(--ls-etiquette); text-transform: uppercase;
  color: var(--navy-dark);
}
.sommaire-suite { margin-top: var(--e-2); font-size: var(--t-00); color: var(--text-soft); }

/* DEUX MODIFICATEURS DE CALAGE, PARCE QUE LE CONTENU A CHANGE LES
   PROPORTIONS. `.duo` et `.guides` centrent leurs colonnes : c'est juste
   quand elles se repondent, et c'est un trou des qu'une devient deux
   fois plus haute que l'autre. Ici les deux sommaires ne partaient plus
   de la meme ligne, et les couvertures flottaient au milieu de 230 px
   de blanc. Ce sont des MODIFICATEURS ajoutes, pas des redefinitions :
   `.duo` et `.guides` gardent leur centrage partout ailleurs.  D-902 */
.duo--haut { align-items: start; }
@media (min-width: 62em) { .guides--dense { align-items: start; } }


/* -------------------------------------------------------------------
   C · LA LEGENDE D'UN CADRE DE NAVIGATEUR
   `.ecran` n'est pas une `.figure` : il n'a pas de `figcaption` stylee.
   Une capture sans legende laisse le visiteur deviner ce qu'il regarde,
   et c'est exactement la ou une demonstration se lit comme un client
   reel. La legende porte donc l'aveu, en une ligne.  D-903
   ------------------------------------------------------------------- */

.ecran-dit {
  margin-top: var(--e-2);
  font-size: var(--t-00); line-height: 1.5; color: var(--text-soft);
}
.ecran-dit b { color: var(--text); font-weight: 600; }


/* -------------------------------------------------------------------
   D · LE BLOC QUI MONTRE — sous un service qui vient de se decrire
   Un service qui se decrit sans rien montrer se lit comme une promesse.
   Le bloc est separe du texte par un filet, jamais par du vide : le
   verdict du proprietaire visait les trous de 200 a 400 px.  D-904
   ------------------------------------------------------------------- */

.montre {
  margin-top: var(--e-6);
  padding-top: var(--e-5);
  border-top: var(--filet) solid var(--line);
}
.montre-tete {
  display: flex; flex-wrap: wrap; align-items: baseline;
  justify-content: space-between; gap: var(--e-2);
  margin-bottom: var(--e-3);
}
.montre-tete .etiquette-demo { margin-bottom: 0; }
.montre-titre {
  font-size: var(--t-1); line-height: var(--lh-1); letter-spacing: var(--ls-1);
  color: var(--navy-dark);
}
.montre .actes { margin-top: var(--e-4); }

/* LE TITRE DESCEND DANS LA COLONNE DE TEXTE, ET L'ETIQUETTE MONTE SUR
   LE MEDIA. Poses au-dessus du duo, ils faisaient une bande de tete de
   plus, et la colonne de texte — deux fois plus courte que l'image —
   se centrait en laissant 150 px de vide de chaque cote. C'est
   exactement le trou que le proprietaire a reproche.  D-904
   L'etiquette qualifie L'IMAGE, pas le bloc : sa place est sur elle. */
.duo-media > .etiquette-demo { margin-bottom: var(--e-2); }


/* ===================================================================
   22 · CE QUE `processus`, `contact` ET `reference` ONT DEMANDE EN PLUS
   ===================================================================
   Onze pieces, ecrites en parallele de la section 21 pour que deux mains
   n'ecrivent pas le meme fichier. Deux d'entre elles bouchent des trous
   du SOCLE, pas des pages : le panneau de la bande photographique
   (22.4bis) et l'anneau de mise au point sur fond sombre (22.7bis).
   Ce dernier est un vrai defaut d'accessibilite du site entier —
   `css/base.css` ne renversait l'anneau que sous `.sur-fonce`, une classe
   qu'AUCUNE page ne porte.  D-930
   =================================================================== */


/* -------------------------------------------------------------------
   22.1 · LE PAS — l'etape, quand elle vit dans un `.duo`
   Les six etapes tenaient dans une colonne de 560 px : un `01` de
   15 px, un titre, deux phrases, et 560 px de blanc a droite. Le pas
   garde le texte a gauche et donne la droite a ce qu'on REGARDE.
   Le numero passe de 15 px de texte gris a une pastille navy : c'est
   le seul reperage de progression de la page, il doit se voir.  D-931
   ------------------------------------------------------------------- */

.pas-tete {
  display: flex; align-items: center; gap: var(--e-2);
  margin-bottom: var(--e-3);
}
.pas-num {
  display: grid; place-items: center;
  flex: 0 0 auto;
  width: 2.5rem; height: 2.5rem;
  border-radius: var(--rayon-large);
  background: var(--navy-dark);
  color: var(--pearl);
  font-family: var(--font-texte);
  font-size: var(--t-00); font-weight: 700;
  letter-spacing: var(--ls-etiquette);
  /* La lettre est centree a l'oeil : `letter-spacing` pousse a droite. */
  text-indent: var(--ls-etiquette);
}
.pas-quoi {
  font-size: var(--t-00); font-weight: 700;
  letter-spacing: var(--ls-etiquette); text-transform: uppercase;
  color: var(--text-soft);
}
/* Le pas n'est plus une ligne de `<ol>` : le filet du `.duo` le separe
   deja du suivant, celui de `.etape` ferait un double trait. */
.pas-liste { display: grid; list-style: none; margin: 0; padding: 0; }
.pas { list-style: none; }
.pas .etape-dit { max-width: 46ch; }
.pas .livrable { margin-top: var(--e-3); }

/* L'ECRAN AVEC SA LEGENDE. `.figure figcaption` d'`app.css` ne descend
   pas dans un `.ecran` : le cadre de navigateur n'est pas une `.figure`,
   il en contient une. */
.figure-ecran { margin: 0; }
.figure-ecran figcaption {
  margin-top: var(--e-2);
  font-size: var(--t-00); line-height: 1.5; color: var(--text-soft);
}
.figure-ecran figcaption b { color: var(--text); font-weight: 600; }
.figure-ecran figcaption a { color: var(--navy-dark); }


/* -------------------------------------------------------------------
   22.2 · LE JALON — la carte de faits, quand aucune image n'existe
   Trois des six etapes n'ont pas de photographie, et on n'en fabrique
   pas : monter une fausse « proposition ecrite » serait une piece
   inventee. La colonne de droite porte alors ce qu'un patron veut
   vraiment y lire — trois faits courts, deja vrais ailleurs dans la
   page, mais SCANNABLES. Ils ne lisent pas, ils regardent.  D-932
   ------------------------------------------------------------------- */

.jalon {
  margin: 0;
  padding: var(--e-5);
  background: var(--pearl);
  border: var(--filet) solid var(--line);
  border-radius: var(--rayon-large);
  box-shadow: var(--ombre-pose);
}
.bande--silk .jalon { border-color: transparent; }
.jalon-tete { display: flex; align-items: center; gap: var(--e-2); }
.jalon-tete svg { width: 1.5rem; height: 1.5rem; flex: 0 0 auto; color: var(--navy); }
.jalon-t {
  font-family: var(--font-titre); font-weight: 460;
  font-size: var(--t-1); line-height: var(--lh-1); letter-spacing: var(--ls-1);
  color: var(--navy-dark);
}
.jalon-liste { display: grid; gap: var(--e-2); margin-top: var(--e-3); list-style: none; }
.jalon-liste li {
  display: flex; align-items: flex-start; gap: var(--e-2);
  font-size: var(--t-00); line-height: 1.5;
  color: var(--text-soft);
}
.jalon-liste li svg { width: 1.0625rem; height: 1.0625rem; flex: 0 0 auto; margin-top: 0.16rem; color: var(--navy); }
.jalon-liste b { color: var(--text); font-weight: 600; }
.jalon > p { margin-top: var(--e-2); color: var(--text-soft); }
.jalon .actes { margin-top: var(--e-4); }


/* -------------------------------------------------------------------
   22.3 · LA FAQ A DEUX COLONNES
   Huit `<details>` nus sur 1 201 px, et rien a droite. Les questions
   gardent leurs 46 rem — au-dela, le `+` se retrouve a un demi-metre
   de la question qu'il ouvre — et la droite prend l'action : le
   numero, l'appel, le message. Une question sans reponse dans la
   liste doit trouver une porte sans remonter.  D-933
   ------------------------------------------------------------------- */

.faq-grille { display: grid; gap: var(--e-5); align-items: start; }
@media (min-width: 62em) {
  .faq-grille { grid-template-columns: minmax(0, 1.35fr) minmax(0, 0.65fr); gap: var(--e-8); }
  /* Le panneau suit la lecture des huit questions sans la doubler.
     6,5 rem = la barre collante (`position: sticky`, ~4,5 rem) plus une
     respiration : sous cette valeur le panneau passe DERRIERE la barre. */
  .faq-aide { position: sticky; top: 6.5rem; }
}
.faq-grille .questions { max-width: none; }


/* -------------------------------------------------------------------
   22.4 · L'ICONE DE LA TUILE
   Les cinq portes de `contact` etaient cinq pavés de texte : on les
   distinguait en les LISANT. L'icone est celle des six portes de bas
   de page (D-890), donc le meme signe pour la meme action d'un bout
   a l'autre du site.
   ------------------------------------------------------------------- */

/* La pastille est PLEINE, comme la porte mise en avant du bas de page
   (`.porte-carte[data-forte]`). Un carre marbre avec une icone navy
   dedans se lisait comme une tache grise a 1440 : sur un fond perle,
   #E8E4E0 ne separe rien. */
.tuile-icone {
  display: grid; place-items: center;
  width: 2.75rem; height: 2.75rem;
  border-radius: var(--rayon-large);
  background: var(--navy-dark);
  margin-bottom: var(--e-1);
  transition: background var(--t-etat);
}
.tuile-icone svg { width: 1.5rem; height: 1.5rem; color: var(--pearl); }
.tuile:hover .tuile-icone { background: var(--navy-light); }


/* -------------------------------------------------------------------
   22.4bis · LE PANNEAU DE LA BANDE PHOTOGRAPHIQUE EST UN FOND NAVY
   La section 20.6 peint le panneau en `--navy-dark` mais ne lui donne
   pas les regles de contexte sombre : `.sur-titre` y sortait a
   `--text-soft`, c'est-a-dire du gris fonce sur du navy, et
   `.btn--primaire` du navy sur du navy. Les valeurs sont celles que
   `.bande--navy` emploie deja depuis D-822.
   ------------------------------------------------------------------- */

.bande-photo-panneau .sur-titre { color: var(--champagne-light); }
.bande-photo-panneau .sur-titre::after { background: var(--champagne); }
.bande-photo-panneau .btn--primaire { background: var(--champagne); color: var(--navy-dark); }
.bande-photo-panneau .btn--primaire:hover { background: var(--champagne-light); }
.bande-photo-panneau .btn--second {
  background: transparent; color: var(--pearl);
  border-color: rgb(253 255 255 / 0.34);
}
.bande-photo-panneau .btn--second:hover { background: rgb(253 255 255 / 0.08); border-color: var(--pearl); }
.bande-photo-panneau .btn--nu { color: var(--champagne-light); text-decoration-color: var(--champagne-dark); }


/* -------------------------------------------------------------------
   22.5 · LE RAIL — un schema d'etapes, en ligne
   Quatre paragraphes empiles ne montrent pas une SUITE. Le rail la
   montre : quatre cases sur une ligne, reliees par un filet, chacune
   avec son icone et l'etiquette qui dit a QUI revient le travail.
   Le filet est champagne — il ne porte rien, il relie.  D-934
   ------------------------------------------------------------------- */

.rail {
  display: grid; gap: var(--e-3);
  grid-template-columns: 1fr;
  list-style: none;
}
@media (min-width: 48em) { .vitrine { grid-template-columns: repeat(2, 1fr); gap: var(--e-4); } }
@media (min-width: 62em) { .vitrine { grid-template-columns: repeat(4, 1fr); } }
@media (min-width: 62em) { .rail--3 { grid-template-columns: repeat(3, 1fr); } }

/* La case est une COLONNE : l'etiquette « a vous / a nous » tombe au
   bas de la carte, pas sous un texte de longueur variable. Quatre
   etiquettes a quatre hauteurs differentes ne se comparent pas d'un
   regard, et c'est tout ce qu'on leur demande. */
.rail-pas {
  position: relative;
  display: flex; flex-direction: column;
  padding: var(--e-4);
  background: var(--pearl);
  border: var(--filet) solid var(--line);
  border-radius: var(--rayon-large);
}
.rail-pas .rail-qui { margin-top: auto; align-self: flex-start; }
.bande--silk .rail-pas { border-color: transparent; box-shadow: var(--ombre-pose); }
.rail-pas > svg { width: 1.625rem; height: 1.625rem; color: var(--navy); }
.vitrine-num {
  display: block;
  margin-top: var(--e-2);
  font-size: var(--t-00); font-weight: 700;
  letter-spacing: var(--ls-etiquette);
  color: var(--text-soft);
}
.rail-nom {
  margin-top: 0.15rem;
  font-family: var(--font-titre); font-weight: 460;
  font-size: var(--t-1); line-height: var(--lh-1); letter-spacing: var(--ls-1);
  color: var(--navy-dark);
}
.rail-dit { margin-top: var(--e-1); font-size: var(--t-00); line-height: 1.5; color: var(--text-soft); }
.rail-qui {
  display: inline-block;
  margin-top: var(--e-3); margin-bottom: 0;
  padding: 0.2rem 0.55rem;
  border-radius: 999px;
  font-size: 0.8125rem; font-weight: 700;
  letter-spacing: var(--ls-etiquette); text-transform: uppercase;
  background: var(--marble); color: var(--navy-dark);
}
/* Celle qui est A VOUS est pleine : c'est la seule qu'on demande. */
.rail-qui--vous { background: var(--navy-dark); color: var(--pearl); }

/* LE FILET NE RELIE QUE SUR UNE VRAIE LIGNE. Sous 62 em le rail se
   plie en deux colonnes ou en une : un trait horizontal y relierait
   des cases qui ne se suivent pas. Piege 34 — l'ordre visuel n'est
   pas l'ordre du balisage des qu'une grille se replie. */
@media (min-width: 62em) {
  .rail-pas + .rail-pas::before {
    content: "";
    position: absolute; top: calc(var(--e-4) + 0.8rem); right: 100%;
    width: var(--e-4); height: var(--filet);
    background: var(--champagne-dark);
  }
}


/* -------------------------------------------------------------------
   22.6 · LA FRISE — trois moments dans l'ordre, a la verticale
   « Trente jours apres le paiement final » est la regle qui surprend
   le plus. Elle a sa bande et son titre (D-779) ; il lui manquait de
   se VOIR. Trois noeuds relies disent l'ordre en un regard.
   ------------------------------------------------------------------- */

.frise { display: grid; gap: 0; list-style: none; margin-top: var(--e-4); }
.frise-pas {
  position: relative;
  padding: 0 0 var(--e-4) var(--e-5);
}
.frise-pas:last-child { padding-bottom: 0; }
.frise-pas::before {
  content: "";
  position: absolute; left: 0; top: 0.4rem;
  width: 0.75rem; height: 0.75rem;
  border-radius: 50%;
  background: var(--pearl);
  border: 2px solid var(--navy);
}
.bande--silk .frise-pas::before { background: var(--silk); }
/* Le trait descend du noeud jusqu'au suivant, jamais sous le dernier. */
.frise-pas:not(:last-child)::after {
  content: "";
  position: absolute; left: calc(0.375rem - 1px); top: 1.35rem; bottom: 0;
  width: 2px;
  background: var(--champagne);
}
.frise-quand {
  font-size: var(--t-00); font-weight: 700;
  letter-spacing: var(--ls-etiquette); text-transform: uppercase;
  color: var(--text-soft);
}
.frise-quoi { margin-top: 0.15rem; color: var(--text); }
.frise-pas:last-child .frise-quoi { font-weight: 600; color: var(--navy-dark); }


/* -------------------------------------------------------------------
   22.7 · LE REPLI DES CONDITIONS
   LE BLOC ENTRE LES BORNES NE BOUGE PAS : le `<details>` est POSE
   AUTOUR, `tools/conditions.mjs verifier` compare ce qu'il y a entre
   les bornes et rien d'autre. Le texte reste dans le document — rien
   n'est charge apres coup, `Ctrl+F` et les outils le trouvent, et
   `tools/prix-check.mjs` ouvre tous les `<details>` avant de lire.

   UNE CONDITION QU'ON CACHE EST UN PETIT CARACTERE : la barre
   d'ouverture fait donc 4,5 rem, porte le mot « 13 articles », dit ce
   qu'ils contiennent, et se voit de l'autre bout de la page. Ce qui
   etait un mur de 5 115 px que personne ne lisait devient une porte
   que quelqu'un ouvre.  D-935
   ------------------------------------------------------------------- */

.cond-repli {
  border: var(--filet) solid var(--navy-dark);
  border-radius: var(--rayon-large);
  background: var(--pearl);
  overflow: hidden;
}
/* LA BARRE EST PLEINE, PAS UNE LIGNE CLAIRE. Sur un fond silk, un cadre
   perle avec un `+` gris se lit comme une carte, pas comme un bouton :
   photographie a 1440, personne ne voyait qu'il y avait a cliquer. En
   navy plein, avec le meme poids qu'un `.btn--primaire`, la porte est
   evidente. Perle sur navy-dark : 15,81:1. */
.cond-repli > summary {
  /* `flex-start`, pas `center` : sous 48 em le sous-titre passe a quatre
     lignes et le `+` se retrouvait a mi-hauteur d'un bloc de texte, loin
     du titre qu'il ouvre. */
  display: flex; align-items: flex-start; gap: var(--e-3);
  min-height: 4.5rem;
  padding: var(--e-3) var(--e-4);
  cursor: pointer;
  list-style: none;
  background: var(--navy-dark);
  color: var(--pearl);
}
.cond-repli > summary::-webkit-details-marker { display: none; }
.cond-repli > summary:hover { background: var(--navy-light); }
.cond-repli > summary > svg {
  width: 1.75rem; height: 1.75rem; flex: 0 0 auto; color: var(--champagne);
  margin-top: 0.3rem;   /* aligne le signe sur la PREMIERE ligne du titre */
}
.cond-repli-t {
  display: block;
  font-family: var(--font-titre); font-weight: 460;
  font-size: var(--t-2); line-height: var(--lh-2); letter-spacing: var(--ls-2);
  color: var(--pearl);
}
/* Champagne clair sur navy fonce : 10,88:1. Le champagne n'est jamais du
   texte SUR PERLE ; sur du navy il l'est deja depuis `.bande--navy`. */
.cond-repli-dit { display: block; margin-top: 0.1rem; font-size: var(--t-00); line-height: 1.5; color: var(--champagne-light); }
.cond-repli-mot { flex: 1 1 auto; }
.cond-repli:not([open]) .cond-repli-moins { display: none; }
.cond-repli[open] .cond-repli-plus { display: none; }
.cond-repli > .conditions { padding: var(--e-5) var(--e-4) var(--e-6); }


/* -------------------------------------------------------------------
   22.7bis · L'ANNEAU DE MISE AU POINT SUR UNE SURFACE SOMBRE
   `css/base.css` pose `outline: var(--focus-w) solid var(--navy)` sur
   TOUT, et ne le renverse que sous `.sur-fonce` et `.pied` — deux
   classes qu'aucune page ne porte aujourd'hui. Les surfaces sombres
   employees ici — la barre du repli, le panneau de la bande
   photographique, la bande de chiffres navy — auraient donc un anneau
   navy sur du navy, c'est-a-dire aucun anneau. Seuil du projet :
   « arrets au clavier sans anneau : 0 ».  D-936
   ------------------------------------------------------------------- */

.cond-repli > summary:focus-visible {
  outline: var(--focus-w) solid var(--champagne-light);
  /* `overflow: hidden` sur le `<details>` rognerait un decalage positif. */
  outline-offset: -4px;
}
.bande-photo-panneau :focus-visible,
.bande--navy :focus-visible { outline-color: var(--champagne-light); }


/* -------------------------------------------------------------------
   22.8 · LA LEGENDE D'UNE DEMONSTRATION, SOUS UNE MOSAIQUE
   Les neuf demonstrations sont des entreprises FICTIVES. L'aveu tient
   sur une ligne (`.mention-demo`, D-889) ; ici il faut en plus que
   chaque vignette dise son metier sans que le nom fictif passe pour
   un client.
   ------------------------------------------------------------------- */

.mosaique .mos-demo {
  display: block;
  /* 15 px, pas 13 : le site s'impose un plancher de corps a TOUTES les
     largeurs, et une mention de demonstration ecrite plus petit que ce
     qu'elle qualifie est un petit caractere. Le banc l'a signale
     vingt-quatre fois — six largeurs, quatre vignettes.  D-911 */
  font-size: var(--t-00); font-weight: 700;
  letter-spacing: var(--ls-etiquette); text-transform: uppercase;
  color: var(--text-soft);
}
/* SIX VIGNETTES SE RANGENT EN 3 + 3, PAS EN 4 + 2. `auto-fill` avec un
   minimum de 15 rem donnait quatre colonnes sur 1 120 px : la seconde
   rangee laissait deux trous a droite, et un trou se lit comme une
   image qui n'a pas charge. */
@media (min-width: 62em) {
  .mosaique--3 { grid-template-columns: repeat(3, 1fr); }
}


/* -------------------------------------------------------------------
   22.9 · DEUX AJUSTEMENTS DE PLACE
   ------------------------------------------------------------------- */

/* Le formulaire de contact plafonne a 44 rem et laissait 480 px de
   vide a sa droite. Dans un duo il n'a plus a plafonner : c'est la
   colonne qui tient la mesure. */
.duo .form-contact { max-width: none; }

/* Le numero geant vit dans la colonne de gauche de l'en-tete : sans
   marge il collait au chapo. */


/* ===================================================================
   23 · CE QUE LE CHANTIER « WOW » DE L'ACCUEIL A DEMANDE EN PLUS
   Deux sections neuves. Aucune ne redefinit quoi que ce soit.
   =================================================================== */

/* -------------------------------------------------------------------
   23.1 · LA VISITE 360 SUR L'ACCUEIL  D-924
   Le meme bloc `.tour` que sur Realisations, pose sur du navy et dans
   une grille a deux colonnes. `css/tour360.css` porte tout le reste :
   rien ici ne touche a la mecanique de la visite, seulement a la
   place qu'elle occupe.
   ------------------------------------------------------------------- */

.visite360-grille { display: grid; gap: var(--e-6); align-items: center; }
@media (min-width: 62em) {
  /* 1 / 1,45 : la visite est ce qu'on REGARDE, le texte se lit en
     quatre secondes. Meme arbitrage que le premier ecran (D-900). */
  .visite360-grille { grid-template-columns: 1fr 1.45fr; gap: var(--e-7); }
}
.visite360 .chapo { color: var(--champagne-light); }
.visite360-socle {
  margin-top: var(--e-4);
  display: grid; gap: var(--e-2);
  padding-top: var(--e-3);
  border-top: var(--filet) solid rgb(253 255 255 / 0.18);
}
.visite360-socle li { display: flex; align-items: flex-start; gap: var(--e-2); font-size: var(--t-00); color: rgb(253 255 255 / 0.80); }
.visite360-socle svg { width: 1.0625rem; height: 1.0625rem; color: var(--champagne); flex: 0 0 auto; margin-top: 0.15rem; }
.visite360-socle b { color: var(--pearl); font-weight: 600; }
.visite360 .actes { margin-top: var(--e-4); }
/* Sur navy, la mention de source ne peut pas rester en `--text-muted` :
   elle y tomberait sous 3:1. */
.visite360 .tour-source { color: rgb(253 255 255 / 0.72); }

/* -------------------------------------------------------------------
   23.2 · QUI ON EST  D-925
   Trois fiches, pas trois cartes : aucune ombre, aucun fond, un filet
   au-dessus. Une carte promet un contenu ; ici il n'y a qu'un prenom
   et un role, et une carte vide autour se lit comme un manque.
   ------------------------------------------------------------------- */

.nous-liste {
  margin-top: var(--e-6);
  display: grid; gap: var(--e-5);
  list-style: none;
}
@media (min-width: 48em) { .nous-liste { grid-template-columns: repeat(3, 1fr); gap: var(--e-6); } }

.nous-fiche {
  display: grid; gap: 0.25rem;
  padding-top: var(--e-3);
  border-top: 2px solid var(--navy);
}
.nous-initiale {
  font-family: var(--font-titre); font-style: italic;
  font-size: var(--t-3); line-height: 1;
  color: var(--champagne-dark);
  margin-bottom: var(--e-1);
}
.nous-nom {
  font-family: var(--font-titre);
  font-size: var(--t-2); line-height: var(--lh-2); letter-spacing: var(--ls-2);
  color: var(--navy-dark);
}
.nous-role { font-size: var(--t-00); line-height: 1.5; color: var(--text-soft); }

.nous-lieu {
  display: flex; align-items: flex-start; gap: var(--e-2);
  margin-top: var(--e-6);
  padding-top: var(--e-3);
  border-top: var(--filet) solid var(--line);
  font-size: var(--t-00); color: var(--text-soft);
  max-width: var(--colonne-texte);
}
.nous-lieu svg { width: 1.0625rem; height: 1.0625rem; color: var(--navy); flex: 0 0 auto; margin-top: 0.15rem; }


/* -------------------------------------------------------------------
   23.3 · LE DUEL — deux chiffres qui s'opposent  D-928
   (`.ecart` etait deja pris par la jauge de `automatisation.html` :
   ma paire y prenait son fond blanc, son filet et son ombre. Piege 102,
   deux fois le meme jour — on GREP avant de nommer.)
   Deux cartes blanches identiques a filet fin ne comparent rien : elles
   listent. Le contraste est porte par le FOND, et c'est la seule chose
   que l'oeil compare sans lire.
   ------------------------------------------------------------------- */

.duel { display: grid; gap: var(--e-2); }
@media (min-width: 30em) { .duel { grid-template-columns: 1fr 1fr; } }

.duel-cote {
  display: grid; align-content: start; gap: var(--e-1);
  padding: var(--e-4);
  border-radius: var(--rayon-large);
}
.duel-cote--main { background: var(--silk); color: var(--text); }
.duel-cote--auto { background: var(--navy-dark); color: var(--pearl); }

.duel-etiquette {
  font-size: var(--t-00); font-weight: 700;
  letter-spacing: var(--ls-etiquette); text-transform: uppercase;
}
/* Sur silk, le secondaire est `--text-soft` : `--text-muted` y tombe a
   3,88:1 et y est interdit (D-803). */
.duel-cote--main .duel-etiquette { color: var(--text-soft); }
.duel-cote--auto .duel-etiquette { color: var(--champagne); }

.duel-chiffre {
  font-family: var(--font-titre);
  font-size: var(--t-4); line-height: 1; letter-spacing: var(--ls-4);
  /* Les chiffres montent de zero : sans chasse fixe, la boite change de
     largeur a chaque image et le bloc entier tremble. `tabular-nums` est
     deja pose sur le corps, on le REDIT ici parce que ce compteur ne
     peut pas s'en passer. */
  font-variant-numeric: tabular-nums;
}
.duel-cote--main .duel-chiffre { color: var(--navy-dark); }
.duel-cote--auto .duel-chiffre { color: var(--pearl); }
@media (min-width: 62em) { .duel-chiffre { font-size: var(--t-5); } }

.duel-dit { font-size: var(--t-00); line-height: 1.5; }
.duel-cote--main .duel-dit { color: var(--text-soft); }
.duel-cote--auto .duel-dit { color: rgb(253 255 255 / 0.78); }

/* -------------------------------------------------------------------
   23.4 · UNE IMAGE SE POSE EN SE RAPPROCHANT  D-929
   Le fondu de 620 ms de `.entre--media` dit « ceci vient de paraitre ».
   Il ne dit rien d'une photographie de 1 248 px de large, ou 32 px de
   montee sur 700 de haut sont un frisson. La photo part a 1,06 dans son
   cadre qui rogne et se pose a 1 : le mouvement se voit sur toute la
   surface, pas seulement sur le bord haut.
   PORTEE VOLONTAIREMENT ETROITE — `.figure` seulement. Les cartes de la
   vitrine ont deja leur propre echelle au survol sur la meme propriete,
   et deux regles qui animent `transform` sur le meme element, c'est
   celle de plus forte specificite qui gagne pour toujours.
   ------------------------------------------------------------------- */

/* « DANS SON CADRE QUI ROGNE » — SAUF QUE RIEN NE ROGNAIT.  D-981
   Le commentaire ci-dessus l'affirmait ; `.figure` n'a jamais porte
   d'`overflow`. L'image partait donc a 1,08 et debordait de 26 px de
   chaque cote de sa colonne. Mesure : `tools/deborde-qui.mjs` trouve
   `scrollWidth` a 702 pour 700 sur `processus` et `reference`, et
   l'ancetre rend `overflow-x: visible`. Deux pixels, invisibles a l'oeil,
   mais le projet s'impose « aucun debordement de 320 a 1 920 ».
   POURQUOI PAS `overflow: hidden` SUR LA FIGURE : `.figure--ombre` pose
   son ombre sur l'IMAGE, et une figure qui rogne la mange ; la legende
   vit dans la meme boite (onze `figcaption` sur le site). Le cadre part
   donc de PLUS PETIT et se pose a 1 : le mouvement se voit toujours sur
   toute la surface, il ne sort simplement plus de la colonne. C'est deja
   le geste des cartes de la vitrine (0,94 → 1). */
@media (prefers-reduced-motion: no-preference) {
  html.js .figure.entre.entre--media img { transform: scale(var(--m-echelle-vers)); }
  html.js .figure.entre.entre--media[data-vu] img {
    transform: none;
    transition: transform var(--m-echelle) var(--m-courbe);
    transition-delay: var(--m-retard, 0ms);
  }
  html.js .figure.entre.entre--media[data-vu-net] img { transform: none; transition: none; }
}

/* LE PLAN DE LA VISITE EST PLUS PETIT SUR L'ACCUEIL QUE SUR REALISATIONS,
   ET C'EST UNE CIBLE TACTILE QUI LE DIT.  D-924
   `css/tour360.css` dimensionne le plan a `clamp(10rem, 28%, 14rem)` de
   la scene. Sur Realisations la scene fait toute la colonne ; ici elle
   n'en fait que la moitie droite, donc 28 % rendent 190 px, le plan
   tombe a 111 de haut et la piece « Terrasse » a 42 — deux pixels sous
   le plancher de 44. Releve par `tools/banc.mjs` a trois largeurs. On ne
   touche pas au systeme de proportions de la visite : on lui donne son
   maximum, qui est deja ecrit dans sa propre feuille. */
.visite360 .tour-map { width: clamp(13rem, 34%, 14rem); }
/* 13rem est un PLANCHER calcule, pas un tatonnement : la piece « Terrasse »
   occupe 37,14 % de la hauteur du plan, et le plan garde un rapport de
   240/140. Sa hauteur vaut donc 0,2167 fois la largeur du plan, et il faut
   203 px de plan pour rendre 44 px de cible. 13rem en donne 208. */

/* -------------------------------------------------------------------
   23.5 · L'ENTREE D'UNE CARTE DE SERVICE  D-935
   `tools/geste.mjs` a ARRETE : « moins de deux intervalles bougent, le
   geste ne se voit pas, donc il n'existe pas ». Il avait raison. La
   carte fait 578 px de haut, et le geste commun des medias la fait
   monter de 32 — cinq pour cent et demi de sa propre hauteur, sur une
   surface qui occupe le tiers de l'ecran. C'est la meme erreur que
   « 16 px ne se voyaient pas » (D-905), une taille de composant plus
   tard.
   56 px et 900 ms, et l'echelle porte sur le CADRE et non sur l'image :
   l'image a deja sa propre echelle au survol, et deux regles qui
   animent `transform` sur le meme element, c'est celle de plus forte
   specificite qui gagne pour toujours.
   La specificite monte a `.svc-carte.entre.entre--media` : a specificite
   egale c'est le dernier du fichier qui gagne, et le geste commun vit
   plus bas (§ 20).
   ------------------------------------------------------------------- */

@media (prefers-reduced-motion: no-preference) {
  html.js .svc-carte.entre.entre--media { transform: translateY(56px); }
  html.js .svc-carte.entre.entre--media[data-vu] {
    transform: none;
    transition: opacity 900ms var(--m-courbe), transform 900ms var(--m-courbe);
    transition-delay: var(--m-retard, 0ms);
  }
  html.js .svc-carte.entre.entre--media[data-vu-net] { transform: none; transition: none; }

  html.js .svc-carte.entre.entre--media .svc-vue { transform: scale(0.94); transform-origin: 50% 100%; }
  html.js .svc-carte.entre.entre--media[data-vu] .svc-vue {
    transform: none;
    transition: transform 900ms var(--m-courbe), box-shadow var(--t-etat);
    transition-delay: var(--m-retard, 0ms);
  }
  html.js .svc-carte.entre.entre--media[data-vu-net] .svc-vue { transform: none; transition: none; }
}


/* ===================================================================
   24 · CE QUE `contact` A DEMANDE EN PLUS  D-984
   « Il faut lui donner le plus de coeur possible, mettre en avant nos
   services, bien les montrer, avoir une animation, des transitions. La
   c'est pas beau comment c'est montre. » — 2 sur 10.
   La page ne vendait QUE des portes de contact : les cinq services n'y
   paraissaient nulle part, et trois medias tenaient 5 415 px de page,
   13,8 % de surface. Un patron qui arrive ici depuis une recherche voit
   cinq boutons et ne sait pas ce qu'on fait.
   AUCUN COMPOSANT NEUF : la carte de service est celle du rail de
   l'accueil, au signe pres — meme cadre de navigateur, meme panneau
   navy, meme geste d'entree, meme schema anime pour l'automatisation.
   Ce qui est ecrit ici est la GRILLE qui la range, et rien d'autre.
   =================================================================== */

.svc-grille { display: grid; gap: var(--e-4); }
@media (min-width: 62em) {
  .svc-grille { grid-template-columns: repeat(2, 1fr); gap: var(--e-5); }
  /* LE CINQUIEME PREND LES DEUX COLONNES, ET CE N'EST PAS UN RATTRAPAGE
     DE MISE EN PAGE. Cinq cartes sur deux colonnes laissent un trou ;
     celle qui le comble est « l'estimation sur votre site », la seule
     des cinq qu'un visiteur de la page CONTACT peut ouvrir tout de
     suite, en un clic, sans nous parler. */
  .svc-grille > :last-child { grid-column: 1 / -1; }
}

/* ===================================================================
   `.appel-lien` — CE QUI REMPLACE « APPELEZ-NOUS AU … ».  D-992

   Sept phrases du site finissaient par un numero souligne. Elles
   finissent maintenant par « Réservez trente minutes », et ce n'est
   PLUS un lien : c'est un `<button>` qui ouvre la modale de
   reservation. Il doit donc se lire comme le lien qu'il remplace —
   meme encre, meme soulignement champagne au survol — sans jamais
   ressembler a un bouton plein, qui volerait l'oeil a l'action
   principale de l'ecran ou il vit.
   `font: inherit` est OBLIGATOIRE : un `<button>` ne herite ni de la
   police ni de la taille de son paragraphe, et sans cette ligne la
   phrase change de fonte au milieu.
   =================================================================== */
.appel-lien {
  display: inline;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: var(--navy);
  font-weight: 600;
  cursor: pointer;
  text-decoration: underline;
  text-decoration-color: var(--champagne-dark);
  text-decoration-thickness: 2px;
  text-underline-offset: 0.18em;
}
.appel-lien:hover { text-decoration-color: var(--navy); }

/* DANS `.form-appel`, C'EST UNE PORTE DE SECOURS, PAS UNE MENTION.  D-992
   D-783 a payé une fois le fait qu'une porte de sortie posée dans le
   dernier écran d'un formulaire de sept ne paraissait qu'à la fin. Elle
   paraît maintenant aux sept — mais une porte qu'on ne peut pas TOUCHER
   au pouce n'en est pas une non plus. `inline-flex` + `min-height` lui
   donnent les 44 px sans la sortir de sa phrase : la ligne du paragraphe
   s'ouvre autour d'elle, le texte ne se casse pas. */
.form-appel .appel-lien {
  display: inline-flex; align-items: center;
  min-height: var(--cible-min);
}
