/* ==========================================================================
   GROUPE IMPEC — styles-v5.css
   --------------------------------------------------------------------------
   Styles de la V5 : méga-menu, slogan, bande de preuve, cartes de services,
   procédé, notre entreprise, réalisations, témoignages, FAQ, soumission,
   carrières. Rythme clair/foncé.

   Les couleurs, rayons et espacements viennent tous de css/tokens-v5.css.
   On n'écrit jamais une couleur en dur ici : on appelle un jeton de rôle
   (--fond-page, --texte, --accent, --filet…). Voir l'en-tête des jetons
   pour la correspondance avec les anciens noms.

   TABLE DES MATIÈRES
     1.  Base et réinitialisation          11. Procédé
     2.  Accessibilité                     12. Notre entreprise
     3.  Éléments partagés                 13. Réalisations
     4.  En-tête + méga-menu               14. Témoignages
     5.  Menu mobile                       15. FAQ
     6.  Hero                              16. Soumission (formulaire)
     7.  Slogan                            17. Carrières
     8.  Services (cartes photo)           18. Pied de page
     9.  Autres services                   19. Responsive
     10. Secteurs (liste)                  20. prefers-reduced-motion
   ========================================================================== */

/* =========================================================================
   1. BASE ET RÉINITIALISATION
   ========================================================================= */
*,
*::before,
*::after {
  box-sizing: border-box;
}
html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}
body {
  margin: 0;
  background: var(--fond-page);
  color: var(--texte);
  font-family: var(--police-corps);
  font-size: var(--taille-corps);
  line-height: var(--interligne-corps);
  -webkit-font-smoothing: antialiased;
}
img {
  display: block;
  max-width: 100%;
  height: auto;
}
h1 {
  margin: 0;
  font-family: var(--police-affiche);
  font-weight: var(--graisse-titre);
  line-height: var(--interligne-titre);
  letter-spacing: -0.02em;
}

h2,
h3 {
  margin: 0;
  font-family: var(--police-titre);
  font-weight: var(--graisse-titre);
  line-height: var(--interligne-titre);
  letter-spacing: -0.03em;
}
p {
  margin: 0;
}
ul,
ol {
  margin: 0;
  padding: 0;
  list-style: none;
}
a {
  color: inherit;
  text-decoration: none;
}
button {
  font: inherit;
  cursor: pointer;
}

/* =========================================================================
   2. ACCESSIBILITÉ
   ========================================================================= */
.lien-evitement {
  position: absolute;
  top: -4rem;
  left: var(--espace-s);
  z-index: 300;
  padding: 0.7rem 1.1rem;
  background: var(--marine);
  color: #fff;
  border-radius: var(--rayon-xs);
  transition: top var(--transition);
}
.lien-evitement:focus {
  top: var(--espace-s);
}

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

:focus-visible {
  outline: 3px solid var(--marine);
  outline-offset: 2px;
  border-radius: 2px;
}
.hero :focus-visible,
.secteurs :focus-visible,
.temoignages :focus-visible,
.carrieres :focus-visible,
.pied :focus-visible,
.entete:not(.entete--solide) :focus-visible {
  outline-color: var(--accent);
}

/* =========================================================================
   3. ÉLÉMENTS PARTAGÉS
   ========================================================================= */

/* Centrage du contenu (fond pleine largeur, contenu limité à --largeur-max) */
:where(main > section:not(.hero), .hero__contenu, .entete__interieur, .pied) {
  padding-inline: max(var(--gouttiere), calc((100% - var(--largeur-max)) / 2));
}
/* Rythme vertical par défaut. Les sections qui ont leur propre respiration
   (hero, slogan, bande de preuve, carrières, et le bloc soudé
   Services + Autres services) sont exclues et traitées à leur endroit. */
main
  > section:not(.hero):not(.slogan):not(.proof-strip):not(.carrieres):not(
    .services
  ):not(.autres) {
  padding-block: var(--espace-section);
}

/* Étiquette « eyebrow » + trait de raclette doré */
.eyebrow {
  display: inline-flex;
  align-items: center;
  font-family: var(--police-detail);
  font-size: 1rem; /* noms de section plus grands */
  font-weight: 700;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--texte-doux);
}
.eyebrow::before {
  content: "";
  width: 2.25rem;
  height: 5px;
  margin-right: 0.75rem;
  background: var(--accent-chaud);
}

.eyebrow-fonce {
  display: inline-flex;
  align-items: center;
  font-family: var(--police-detail);
  font-size: 0.9rem; /* noms de section plus grands */
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--texte-doux);
}
.eyebrow-fonce::before {
  content: "";
  width: 2.25rem;
  height: 2px;
  margin-right: 0.75rem;
  background: var(--texte);
}

/* En-tête de section (uniforme sur toute la page) */
.section__entete {
  max-width: none;
  margin-bottom: var(--espace-m);
}
.section__titre {
  margin-top: var(--espace-s);
  font-size: var(--taille-h2);
  max-width: 24ch;
  text-wrap: balance; /* titres sur 1 à 2 lignes, équilibrées */
}
.section__intro {
  margin-top: var(--espace-m);
  max-width: 50ch;
  font-size: var(--taille-corps-grand);
  color: var(--texte-doux);
}

/* Variante : en-tête sur une rangée (titre à gauche, lien à droite) */
.section__entete--rangee {
  max-width: none;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--espace-m);
}

/* Boutons — trois tailles : .bouton--s · .bouton (défaut) · .bouton--l.
   Aucune taille ne doit plus être posée à la main ailleurs dans la feuille. */
.bouton {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: var(--bouton-m-padding);
  font-family: var(--police-bouton);
  font-size: var(--bouton-m-texte);
  font-weight: 400;
  line-height: 1;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  white-space: nowrap;
  border: 1px solid transparent;
  border-radius: var(--rayon-pilule);
  transition:
    transform var(--transition),
    background-color var(--transition),
    color var(--transition);
}
/* Tailles */
.bouton--s {
  padding: var(--bouton-s-padding);
  font-size: var(--bouton-s-texte);
}
.bouton--l {
  padding: var(--bouton-l-padding);
  font-size: var(--bouton-l-texte);
}

/* Couleurs */
.bouton--or {
  background: var(--accent);
  color: var(--texte-sur-accent);
}
.bouton--or:hover {
  background: var(--accent-chaud);
  transform: translateY(-2px);
}
.bouton--fantome {
  background: transparent;
  color: inherit;
  border-color: currentColor;
}
.bouton--fantome:hover {
  transform: translateY(-2px);
}
.bouton--indigo {
  background: var(--marine);
  color: #fff;
}
.bouton--indigo:hover {
  transform: translateY(-2px);
  color: var(--accent-chaud);
}

/* Lien « flèche » */
.lien-fleche {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-family: var(--police-detail);
  font-size: var(--taille-label);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--marine);
}
.lien-fleche::after {
  content: "\2192";
  transition: transform var(--transition);
}
.lien-fleche:hover::after {
  transform: translateX(4px);
}

/* Bloc d'image temporaire (dégradé de marque + étiquette mono) */
.media-placeholder {
  display: flex;
  align-items: flex-end;
  justify-content: flex-end;
  min-height: 200px;
  padding: var(--espace-s);
  border-radius: var(--rayon-media);
  color: rgba(255, 255, 255, 0.5);
  font-family: var(--police-detail);
  font-size: var(--taille-label);
  letter-spacing: 0.03em;
  text-align: right;
  background:
    linear-gradient(
      115deg,
      transparent 42%,
      rgba(201, 176, 116, 0.16) 50%,
      transparent 58%
    ),
    linear-gradient(140deg, var(--fond-sombre), var(--marine));
}

/* ===========================
   INTRO
   ---------------------------
   Animation entièrement en CSS, 3,45 s au total. Le JS ne l'anime pas ; il
   se borne à trois choses, toutes dans le script en ligne du <head> sauf la
   dernière :
     - décider si l'intro doit jouer      → classe .a-intro
     - la déclencher au bon moment        → classe .intro-demarree
     - retirer l'overlay à la fin         → main-v3.js

   main-v3.js EST PARTAGÉ AVEC LA V5 ET LA V6. Rien ici ne doit demander une
   retouche du JS : l'intro V7 est du CSS et une balise (.intro__voile).

   Deux règles de sécurité, à respecter pour toute modification :
     - Sans .a-intro, l'overlay n'existe pas et la page s'affiche
       normalement. Un échec du script ne peut donc jamais masquer la page.
     - Sans .intro-demarree, tout reste en pause : c'est ce qui garantit que
       le visiteur voit la séquence depuis sa première image. Le filet de
       sécurité de main-v3.js retire l'overlay au bout de 4,5 s quoi qu'il
       arrive.

   Ces deux garde-fous sont inchangés depuis la V5 : c'est la mécanique de
   démarrage, elle a fait ses preuves et rien ici ne la touche.

   ---------------------------
   CE QUI CHANGE PAR RAPPORT À LA V5

   La V5 était un lever de voile : un aplat marine s'efface, le mot se
   dissout au centre, le hero apparaît en fondu. La V7 en reprend le
   vocabulaire — aplat marine, lettres blanches — mais l'organise en deux
   temps nets :

     1. un rideau MARINE se lève et découvre la vidéo, PLEIN CADRE ;
     2. le mot s'inscrit en blanc, à 80 % de la largeur, EN HAUT et
        directement sur la vidéo — aucun fond derrière lui ;
     3. il s'efface sur place, PUIS la navigation descend et la vidéo
        redescend avec elle, retrouvant son cadrage sous la barre.

   Pendant les deux premiers temps, la navigation n'existe pas à l'écran et
   la vidéo touche les quatre bords : rien ne concurrence le mot.

   La lisibilité du blanc ne demande aucun artifice. Le haut du hero porte
   déjà son propre voile sombre (.hero::after, rgba(9, 10, 30, 0.5)) : le
   blanc y tient autour de 5:1 même sur un ciel clair, là où 3:1 suffisent
   pour du grand texte. Et comme ce voile vit À L'INTÉRIEUR de .hero, il
   monte avec la vidéo — il couvre donc aussi le bord haut.

   La cascade lettre par lettre est celle de la V5, au geste près. Ce qui
   disparaît : le trait bleu pâle, le bicolore des lettres, et l'entrée en
   fondu du hero — c'est le rideau qui le découvre, il n'a plus rien à
   animer.

   ---------------------------
   SÉQUENCE

     0,00 s  TEMPS MORT (0,12 s) : absorbe le coût de démarrage des
             animations. Sans ce répit, les premières images sont prises sur
             le début du rideau, qu'on découvre déjà entamé.
     0,12 s  le rideau marine monte et sort par le haut (0,80 s).
             La vidéo se découvre par le bas, plein cadre.
     0,92 s  RESPIRATION (0,08 s) : la vidéo seule, un instant
     1,00 s  le « G » entame sa montée, puis une lettre toutes les 0,07 s
     2,06 s  la dernière lettre est posée
     2,06 s  PALIER (0,26 s) : le mot est stable et lisible
     2,32 s  le mot S'EFFACE EN FONDU, sur place (0,50 s) — il ne se déplace
             pas, il ne rétrécit pas
     2,82 s  RESPIRATION (0,08 s) : la vidéo seule à nouveau
     2,90 s  ENSUITE SEULEMENT : la barre de navigation descend (0,80 s), et
             LA VIDÉO REDESCEND AVEC ELLE — même délai, même durée, même
             courbe. La barre semble pousser la vidéo à sa place.
     3,00 s  le contenu du hero et la barre mobile s'installent
     3,02 s  le contenu de la barre apparaît en cascade, de gauche à droite
     3,67 s  le contenu de la barre est au complet
     3,70 s  la barre est posée, la vidéo est recadrée sous elle
     3,86 s  le calque s'est effacé — fin, et retrait par le JS

   LES DEUX RESPIRATIONS ne sont pas du remplissage. Avant elles, chaque geste
   démarrait à la milliseconde où le précédent finissait : l'intro s'enchaînait
   sans jamais reprendre son souffle, et l'arrivée de la barre se lisait comme
   une conséquence de la disparition du mot plutôt que comme un temps à part.
   0,08 s de vidéo nue suffisent à séparer les intentions.

   ---------------------------
   TROIS CONTRAINTES DE CALAGE, si les durées bougent

   1. LA BARRE ET LE RECADRAGE DOIVENT FINIR AVANT LE CALQUE. main-v3.js pose
      .intro-sautee sur <html> au retrait de l'overlay — y compris à la fin
      normale, pas seulement au clic. Comme .intro-sautee coupe l'animation de
      la barre ET celle du hero, les deux doivent être terminées (3,70 s)
      avant l'animationend du calque (3,86 s). Sans cette marge, la barre se
      poserait d'un coup à mi-course et la vidéo sauterait à sa place.

   2. TOTAL SOUS ~3,9 s. Le filet de sécurité du JS retire l'overlay à 4,5 s,
      et ce compte à rebours démarre dès l'exécution du script alors que
      l'animation, elle, attend la première peinture. La marge de 0,64 s est
      ce qui absorbe cet écart sur une machine lente.

      C'EST LA CONTRAINTE LA PLUS DURE DE TOUTE LA SECTION, parce qu'elle est
      hors de portée : main-v3.js est partagé avec la V5 et la V6, ce 4,5 s
      ne peut pas bouger. Chaque geste rallongé se paie donc sur la marge ou
      sur un autre geste. La marge est déjà passée de 0,94 à 0,64 s en
      finançant le rideau (0,60 → 0,80 s), la descente (0,70 → 0,80 s) et deux
      respirations de 0,08 s ; le palier a rendu 0,12 s au passage.
      Si tu veux encore ralentir quelque chose, reprends le temps sur le
      palier ou sur l'écart entre lettres — jamais sur cette marge.

   3. TOUT NAÎT EN PAUSE. Chaque animation est déclarée « paused » sur sa
      propre règle, et son sélecteur figure dans la règle de libération plus
      bas. Un oubli et l'élément partirait avant les autres.

   ---------------------------
   LES CINQ RÉGLAGES

   Un seul nombre par intention — inutile d'aller chercher ailleurs :
     durée du rideau        → 0,80 s sur .intro__voile
     écart entre lettres    → 0,07 s sur .intro__lettre
     longueur du palier     → décalage entre 2,06 s et 2,32 s
     taille du mot          → --taille-logo (8vw : le mot fait 10 fois sa
                              police, donc 80 % de la largeur d'écran)
     hauteur du mot         → --mot-haut sur .a-intro .intro

   Et une seule courbe pour tous les grands déplacements —
   cubic-bezier(0.65, 0, 0.35, 1), symétrique : le rideau qui monte, la barre
   qui descend, la vidéo qui se recadre. La changer à un endroit sans la
   changer aux deux autres casserait l'unité de l'ensemble.

   La hauteur dont la vidéo remonte n'est pas un réglage : c'est celle de
   l'en-tête, --hauteur-entete + son filet de 1 px. Elle doit valoir
   exactement ça, sinon la vidéo ne se recale pas sous la barre.

   Rien n'anime de propriété de mise en page : seuls opacity et transform
   sont touchés, les deux étant composés par le GPU.
=========================== */

/* Masqué par défaut : c'est le cas « pas d'intro ». */
.intro {
  display: none;
}

/* ---------------------------------------------------------------------
   DÉPART DE LA SÉQUENCE
   Toutes les animations naissent en pause — la pause est déclarée sur
   chaque règle qui pose une animation, jamais à distance. C'est délibéré :
   la propriété raccourcie « animation: » réinitialise animation-play-state
   à « running », si bien qu'un bloc de pause séparé et de même spécificité
   se ferait écraser selon sa position dans le fichier.

   Cette règle-ci libère tout d'un coup. Trois classes contre deux : elle
   l'emporte sur chaque déclaration quelle que soit leur place, l'ordre du
   fichier n'entre donc pas en ligne de compte.

   Le script du <head> pose .intro-demarree depuis un requestAnimationFrame,
   c'est-à-dire au moment où le navigateur peint réellement. Sans ce verrou,
   l'horloge démarre dès la résolution des styles — soit avant la première
   peinture si une feuille bloquante se fait attendre, et le visiteur
   découvre l'intro déjà entamée.

   La barre de navigation, son contenu ET LE HERO LUI-MÊME sont dans la
   liste : ils font partie de la chorégraphie, pas de la page. Le hero y est
   entré avec son recadrage — un oubli ici et la vidéo redescendrait avant la
   première peinture, donc jamais plein cadre.
   --------------------------------------------------------------------- */
.a-intro.intro-demarree .intro,
.a-intro.intro-demarree .intro__voile,
.a-intro.intro-demarree .intro__logo,
.a-intro.intro-demarree .intro__lettre,
.a-intro.intro-demarree .entete,
.a-intro.intro-demarree .entete__logo,
.a-intro.intro-demarree .megamenu__item,
.a-intro.intro-demarree .entete__actions,
.a-intro.intro-demarree .burger,
.a-intro.intro-demarree .hero,
.a-intro.intro-demarree .hero__contenu,
.a-intro.intro-demarree .hero__bascule-video,
.a-intro.intro-demarree .hero__defiler,
.a-intro.intro-demarree .barre-mobile {
  animation-play-state: running;
}

/* Le calque n'a plus aucun fond : le seul aplat de l'intro est le rideau
   d'ouverture, qui a sa propre balise (.intro__voile). Le mot est nu sur la
   vidéo. Ce qui reste ici, c'est le positionnement, les deux mesures du mot,
   et le repère de fin pour le JS.

   Le calque est au-dessus de tout (99999) : le « cliquer pour passer » vaut
   ainsi sur toute la surface, y compris sur la zone de l'en-tête. */
.a-intro .intro {
  position: fixed;
  inset: 0;

  display: flex;
  flex-direction: column;

  /* Le mot se tient EN HAUT. --mot-haut vaut la hauteur de l'en-tête plus un
     demi-rem : pendant l'intro l'en-tête n'est pas là, mais le mot se pose
     quand même là où il commencerait s'il y était — c'est ce qui donne à la
     barre l'air de venir prendre une place déjà dessinée. */
  justify-content: flex-start;
  align-items: center;
  padding-top: var(--mot-haut);

  z-index: 99999;

  overflow: hidden;

  cursor: pointer; /* cliquer pour passer */

  /* Taille de référence de l'intro. Le mot faisant 10 fois sa police de
     large, 8vw le pose à 80 % de la largeur d'écran.
     Plancher 1,5rem pour tenir sous 300 px ; plafond 12rem, qui ne mord
     qu'au-delà de 2400 px et garde la proportion sur les grands écrans. */
  --taille-logo: clamp(1.5rem, 8vw, 12rem);

  --mot-haut: calc(var(--hauteur-entete) + 0.5rem);

  /* Ce fondu n'est pas l'effet de sortie — c'est un filet, et le repère de
     fin pour le JS. L'effet, c'est le fondu du mot lui-même, qui a fini à
     2,66 s : il ne reste alors plus rien à effacer. Ne subsistent que deux
     rôles : nettoyer ce qui traînerait sur un écran inhabituel, et fournir
     l'animationend que main-v3.js attend pour retirer le calque.

     Fin à 3,56 s : APRÈS la pose de la barre et le recadrage de la vidéo
     (3,36 s tous les deux), et c'est impératif — le même animationend fait
     poser .intro-sautee, qui coupe ces deux animations. Voir la contrainte 1
     en tête de section. */
  animation: intro-sortie 0.16s 3.7s var(--sortie) forwards paused;
}

/* visibility en fin de course : même si le retrait JS n'a pas lieu,
   l'overlay cesse d'intercepter les clics. */
@keyframes intro-sortie {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
    visibility: hidden;
  }
}

/* ---------------------------------------------------------------------
   1. LE RIDEAU
   L'aplat marine plein cadre, et rien d'autre — c'est le seul fond de toute
   l'intro. Il monte et sort par le haut ; son bord bas balaie l'écran de bas
   en haut, découvrant la vidéo au fur et à mesure. Comme le hero est remonté
   sous l'en-tête pendant ce temps (voir « LE RECADRAGE DE LA VIDÉO » plus
   bas), ce qu'il découvre est une vidéo plein cadre, sans bande au-dessus.

   translateY et non « height » ou « top » : la hauteur et la position sont
   des propriétés de mise en page, les animer refait le calcul de tout le
   calque à chaque image. Le transform est composé par le GPU.

   La courbe est une ease-in-out franche. Le rideau ne se pose nulle part —
   il quitte le cadre — donc rien à décélérer à l'arrivée ; mais un départ
   sec depuis l'immobilité se lit comme un à-coup. Les deux extrémités sont
   donc arrondies, la vitesse est prise au milieu du trajet.

   « forwards » : passé 0,82 s il reste hors cadre. Sans quoi il retomberait
   en place à la fin de son animation et masquerait la page.
   --------------------------------------------------------------------- */
.intro__voile {
  position: absolute;
  inset: 0;

  background: var(--marine);

  /* Fait préparer la couche de composition avant que ça bouge : sans ça, la
     promotion se fait sur la première image animée, d'où un accroc au
     démarrage. Le calque étant retiré du DOM à la fin, ce coût ne dure pas. */
  will-change: transform;

  animation: intro-voile-monte 0.8s 0.12s cubic-bezier(0.65, 0, 0.35, 1)
    forwards paused;
}

@keyframes intro-voile-monte {
  from {
    transform: none;
  }
  to {
    transform: translateY(-100%);
  }
}

/* ---------------------------------------------------------------------
   2. LE MOT
   Blanc, nu sur la vidéo, et il s'efface SUR PLACE. Le fondu est porté ICI,
   sur le bloc, et jamais sur les lettres : leur propre transform porte déjà
   leur montée d'entrée, et un fondu par lettre ferait un effilochage là où
   on veut un mot qui s'éteint d'un coup.
   --------------------------------------------------------------------- */
.intro__logo {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: nowrap;

  font-family: var(--police-titre);
  font-weight: 700;

  font-size: var(--taille-logo);

  /* Blanc, comme en V5. Le mot n'a plus de fond à lui : il est posé sur la
     vidéo, dont le haut porte déjà le voile sombre de .hero::after. Le blanc
     y tient autour de 5:1, très au-dessus des 3:1 exigés pour du grand
     texte. La couleur est portée par le bloc — les lettres n'ont pas de
     bicolore à jouer, elles héritent. */
  color: var(--texte-inverse);

  letter-spacing: 0.18em;
  margin-right: -0.18em; /* compense l'interlettrage traînant, recentre */

  user-select: none;

  will-change: opacity;

  /* Il ne bouge pas en partant : plus de montée, plus de déplacement, plus
     de rétrécissement. Le mot s'éteint là où il s'est écrit, et c'est le
     silence qui suit qui laisse la place à la navigation. */
  animation: intro-mot-efface 0.5s 2.32s var(--sortie) forwards paused;
}

@keyframes intro-mot-efface {
  to {
    opacity: 0;
  }
}

.intro__lettre {
  display: inline-block;

  /* Même raison que sur le rideau : préparer la couche avant que ça bouge. */
  will-change: transform;

  /* Une seule animation, l'entrée. La sortie est portée par .intro__logo,
     qui éteint le mot d'un bloc — la V5 échelonnait la disparition lettre
     par lettre, ça n'a plus de sens dès lors qu'il s'éteint entier.

     Le 0,72 s en tête n'est pas un réglage de goût : c'est le moment où le
     rideau a fini de sortir. La première lettre monte sur une vidéo déjà
     découverte, jamais sur le marine.

     0,07 s d'écart pour 0,36 s de trajet — deux crans plus serré que les
     0,10 s de la V5. Ce n'est pas un choix esthétique : c'est une des trois
     coupes qui financent l'intro séquentielle (voir la contrainte 2 en tête
     de section). C'est ce 0,07 s qu'il faut bouger pour changer la cadence
     du mot, en reprenant le temps ailleurs. */
  animation: intro-lettre 0.36s calc(1s + var(--i) * 0.07s) ease-out both
    paused;
}

/* Entrée d'après la vidéo de référence : la lettre surgit par le bas,
   dépasse la ligne, puis redescend s'y poser. Le dépassement est ce qui
   donne le poids — sans lui on retombe sur un simple fondu.

   Deux courbes distinctes : une montée franche et décélérée, puis un
   retour plus posé. Une seule courbe sur tout le trajet donnerait un
   rebond mécanique.

   En em et non en px : la course suit la taille de police, donc le geste
   reste identique du téléphone au grand écran.

   Plus de « color » ici : la V5 faisait surgir la lettre en bleu pâle avant
   de la poser en blanc, ce qui coûtait un redessin par glyphe et par image.
   Le blanc tient du début à la fin sur la vidéo assombrie — l'animation ne
   touche donc plus que des propriétés composées par le GPU. */
@keyframes intro-lettre {
  0% {
    opacity: 0;
    transform: translateY(0.6em);
    animation-timing-function: cubic-bezier(0.22, 1, 0.36, 1);
  }
  55% {
    opacity: 1;
    transform: translateY(-0.22em);
    animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  }
  100% {
    opacity: 1;
    transform: translateY(0);
  }
}

/* En em : l'espace du logo suit la taille de police. */
.intro__espace {
  width: 0.5em;
}

/* ---------------------------------------------------------------------
   3. LA BARRE DE NAVIGATION QUI DESCEND
   Ces règles vivent dans la section INTRO et non plus bas avec l'en-tête :
   ce sont des temps de la séquence, ils se lisent avec le tableau du haut.
   Elles ne s'appliquent que sous .a-intro — sans intro, l'en-tête est
   simplement là, comme sur n'importe quelle page.

   L'en-tête garde sa place dans le flux : aucun passage en position fixed,
   donc aucun décalage de mise en page à l'arrivée. Son emplacement de 81 px
   n'est jamais visible pendant l'intro, puisque le hero est remonté par
   dessus — la vidéo occupe tout l'écran jusqu'au moment où la barre descend
   et la repousse à sa place.

   « backwards » et non « forwards », sur toutes les animations d'ici : à la
   fin, l'élément retrouve son état naturel sans transform résiduel. Deux
   bénéfices — un transform permanent sur .entete ferait d'elle le bloc
   conteneur du panneau du méga-menu ; et si le visiteur passe l'intro, la
   règle .intro-sautee plus bas coupe l'animation et tout se pose net.
   --------------------------------------------------------------------- */
.a-intro .entete {
  /* Départ à 2,90 s : le mot s'est éteint à 2,82 s, et on laisse 0,08 s de
     vidéo nue avant que la barre n'arrive. Cette respiration fait de son
     arrivée une décision et non une réaction — sans elle, les deux gestes se
     touchaient et l'œil les lisait comme un seul événement.

     LA COURBE EST LE POINT IMPORTANT. Elle était sur --courbe
     (cubic-bezier(0.2, 0.6, 0.2, 1)), très décélérante : relevé image par
     image, la barre avait parcouru 59 % du trajet au bout de 20 % du temps.
     Elle ne descendait pas, elle surgissait puis s'attardait. La courbe
     symétrique du rideau étale le mouvement — à mi-course, à mi-chemin — et
     le pose en décélérant sur la fin. C'est aussi ce qui unifie l'intro :
     rideau, barre et vidéo partagent désormais la même courbe.

     Le recadrage de la vidéo partage exactement ce délai, cette durée et
     cette courbe — les deux ne font qu'un seul mouvement, la barre paraît
     pousser l'image à sa place. */
  animation: entete-descente 0.8s 2.9s cubic-bezier(0.65, 0, 0.35, 1) backwards
    paused;
}

@keyframes entete-descente {
  from {
    transform: translateY(-100%);
  }
}

/* ---------------------------------------------------------------------
   LE RECADRAGE DE LA VIDÉO
   Pendant toute l'intro, le hero est remonté de la hauteur exacte de
   l'en-tête : la vidéo touche donc le bord haut, plein cadre, et rien ne
   trahit l'emplacement de la future barre. Puis elle redescend AVEC la
   barre — même délai, même durée, même courbe — et retrouve précisément le
   cadrage dessiné, sous la navigation.

   81 px, et pas un de plus : --hauteur-entete (5rem) plus le filet de 1 px
   qui borde l'en-tête. C'est ce qui fait que la vidéo se recale pile, sans
   liseré ni recouvrement.

   « backwards » comme la barre, et pour la même raison : pendant le délai le
   hero porte l'état de départ (remonté), et à la fin il retrouve son état
   naturel SANS transform résiduel. Rien de permanent n'est écrit, aucune
   propriété de mise en page n'est touchée — un visiteur qui ne voit pas
   l'intro a exactement la même page.

   Un transform sur .hero en fait le bloc conteneur de ses enfants
   positionnés ; ils sont tous en absolute, donc rien ne bouge. Et le hero a
   overflow: hidden, la vidéo ne peut pas déborder ailleurs.

   Remonter le hero le déplace sans le grandir : il laisserait donc voir, sous
   son bord bas, une bande de la hauteur dont il a bougé. C'est pour cela que
   le hero fait désormais 100svh sans plafond (voir sa règle, section HÉROS) :
   il remplit la fenêtre, le décalage ne découvre rien. Une version
   précédente comblait cette bande avec une ombre portée animée — un
   bouche-trou qui ne traitait que les 81 px du décalage, pas ce qui dépassait
   au-delà sur les grandes fenêtres. La cause étant réglée, l'ombre a disparu.
   --------------------------------------------------------------------- */
/* ⚠️ L'ÉTAT DE DÉPART EST ÉCRIT ICI, PAS LAISSÉ AU « backwards ». C'est la
   correction du défaut que Patrik filmait : pendant toute l'intro le hero
   restait en bas, laissant voir la bande de 81 px réservée à la barre, puis
   SAUTAIT en haut à 2,9 s avant de redescendre.

   Relevé image par image sur sa vidéo, hauteur de la bande claire :
   9,6 s → 130 px · 10,0 s → 22 px · 10,6 s → 125 px. Le saut est là, net.

   La cause tient à une différence entre les deux animations, par ailleurs
   jumelles. Celle de la barre part de « translateY(-100%) » — une valeur qui
   se résout seule. Celle du hero partait d'un calc() sur --hauteur-entete :
   un keyframe qui dépend d'une variable CSS. Le remplissage « backwards » ne
   tenait pas cet état-là pendant le délai. L'animation, elle, jouait
   correctement une fois lancée — d'où le saut plutôt qu'une absence totale
   d'effet.

   La règle ordinaire, elle, résout var() sans difficulté. On y pose donc le
   départ, et le keyframe reçoit une arrivée explicite. Conséquence : il faut
   « forwards » et non plus « backwards », faute de quoi la fin de l'animation
   rendrait la main à la règle et le hero remonterait.

   Rien n'est piégé par le transform résiduel : le hero n'a aucun descendant
   en position fixed — vérifié — et ses enfants sont tous en absolute à
   l'intérieur.
   --------------------------------------------------------------------- */
.a-intro .hero {
  transform: translateY(calc(-1 * var(--intro-recadre, calc(var(--hauteur-entete) + 1px))));
  animation: hero-recadre 0.8s 2.9s cubic-bezier(0.65, 0, 0.35, 1) forwards
    paused;
}

@keyframes hero-recadre {
  from {
    transform: translateY(calc(-1 * var(--intro-recadre, calc(var(--hauteur-entete) + 1px))));
  }
  to {
    transform: translateY(0);
  }
}

/* Le contenu ne descend pas avec la barre d'un bloc : il s'y installe de
   gauche à droite, dans l'ordre de lecture, pendant que la barre finit sa
   course. Décalage de 0,04 s — assez pour qu'on sente le sens, trop peu pour
   qu'on compte les éléments. Tout est en place à 3,35 s, juste avant que la
   barre ne se pose (3,36 s). */
.a-intro .entete__logo,
.a-intro .megamenu__item,
.a-intro .entete__actions,
.a-intro .burger {
  animation: entete-contenu 0.35s var(--courbe) backwards paused;
}

.a-intro .entete__logo {
  animation-delay: 3.02s;
}
.a-intro .megamenu__item:nth-child(1) {
  animation-delay: 3.07s;
}
.a-intro .megamenu__item:nth-child(2) {
  animation-delay: 3.12s;
}
.a-intro .megamenu__item:nth-child(3) {
  animation-delay: 3.17s;
}
.a-intro .megamenu__item:nth-child(4) {
  animation-delay: 3.22s;
}
.a-intro .megamenu__item:nth-child(5) {
  animation-delay: 3.27s;
}
.a-intro .entete__actions,
.a-intro .burger {
  animation-delay: 3.32s;
}

@keyframes entete-contenu {
  from {
    opacity: 0;
    transform: translateY(-6px);
  }
}

/* ---------------------------------------------------------------------
   4. LE CONTENU DU HERO
   Le rideau découvre la VIDÉO, pas encore le discours. Tant que le mot est à
   l'écran, le hero ne montre que son film : sans ça, « DES BÂTIMENTS
   IMPECCABLES » se dresse en énorme juste sous « GROUPE IMPEC » et les deux
   titres se disputent le regard — l'intro perd son moment.

   Le contenu s'installe donc à 2,86 s, avec la barre et non avec le mot : le
   mot est parti, la page peut se présenter. Il monte de 10 px, dans le sens
   inverse de la barre qui descend — les deux se rejoignent.

   Le bouton pause de la vidéo est du lot : main-v3.js le dévoile dès que la
   lecture démarre, soit en plein milieu de l'intro. Sans cette règle il
   apparaîtrait seul dans un coin, avant tout le reste.

   La barre d'action mobile aussi : elle est en position fixe au bas de
   l'écran, dans la partie transparente du calque — elle se découvrait donc
   dès la levée du rideau, un aplat marine en bas d'un écran qui n'a pas fini
   de se présenter. Elle monte maintenant avec le reste.
   --------------------------------------------------------------------- */
.a-intro .hero__contenu,
.a-intro .hero__bascule-video,
.a-intro .hero__defiler,
.a-intro .barre-mobile {
  animation: hero-contenu 0.7s 3s var(--courbe) backwards paused;
}

@keyframes hero-contenu {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
}

/* Intro passée (clic, Échap, filet de sécurité) : on coupe tout, l'en-tête et
   le hero retrouvent leur état naturel immédiatement — le « backwards » de
   leurs animations fait qu'une coupure les repose exactement en place.
   main-v3.js pose aussi cette classe à la fin normale de la séquence — d'où
   la contrainte 1 en tête de section, qui veut que la barre ET le recadrage
   aient fini avant. */
.intro-sautee .entete,
.intro-sautee .entete__logo,
.intro-sautee .megamenu__item,
.intro-sautee .entete__actions,
.intro-sautee .burger,
.intro-sautee .hero,
.intro-sautee .hero__contenu,
.intro-sautee .hero__bascule-video,
.intro-sautee .hero__defiler,
.intro-sautee .barre-mobile {
  animation: none;
}

/* ⚠️ INDISSOCIABLE DE LA RÈGLE CI-DESSUS. Depuis que l'état de départ du hero
   est posé par une règle ordinaire et non plus par « backwards », couper
   l'animation ne suffit plus à le reposer : sans cette ligne, il resterait
   remonté de 81 px, à découvert sous la barre. Le transform doit tomber en
   même temps que l'animation. */
.intro-sautee .hero {
  transform: none;
}

/* Ceinture et bretelles : le script du <head> couvre déjà ce cas. */
@media (prefers-reduced-motion: reduce) {
  .a-intro .intro {
    display: none;
  }

  .a-intro .entete,
  .a-intro .entete__logo,
  .a-intro .megamenu__item,
  .a-intro .entete__actions,
  .a-intro .burger,
  .a-intro .hero,
  .a-intro .hero__contenu,
  .a-intro .hero__bascule-video,
  .a-intro .hero__defiler,
  .a-intro .barre-mobile {
    animation: none;
  }

  /* Même raison qu'après .intro-sautee : le départ du hero n'est plus porté
     par le remplissage de l'animation, donc le couper ne le repose pas. */
  .a-intro .hero {
    transform: none;
  }
}

/* =========================================================================
   4. EN-TÊTE + MÉGA-MENU
   ------------------------------------------------------------------------
   L'en-tête est opaque dès le chargement : il ne chevauche jamais le hero.
   .entete--solide (posée par le JS au défilement) ne fait plus que compacter
   la barre — fond et couleur de texte ne bougent plus.
   ========================================================================= */
.entete {
  position: sticky;
  top: 0;
  z-index: var(--z-entete);
  color: var(--texte);
  background: var(--fond-entete);
  backdrop-filter: blur(16px) saturate(1.4);
  border-bottom: 1px solid var(--filet);
  transition:
    background-color var(--transition),
    color var(--transition),
    box-shadow var(--transition);
}
.entete__interieur {
  display: flex;
  align-items: center;
  justify-content: space-between; /* logo à gauche · actions à droite */
  gap: var(--espace-m);
  min-height: var(--hauteur-entete);
  transition: min-height var(--transition);
  position: relative; /* pour centrer le méga-menu en absolu */
}
.entete--solide .entete__interieur {
  min-height: 4rem;
} /* en-tête plus compact au défilement (était égal à --hauteur-entete : sans effet) */

/* Logo : version couleur en permanence, puisque la barre est toujours claire.
   Le menu mobile ouvert a son propre logo blanc séparé (.menu-mobile__logo,
   en fin de feuille) — rien à voir avec celui-ci. */
.entete__logo {
  display: flex;
  align-items: center;
  flex-shrink: 0;
  justify-self: start;
  /* Respiration sous le logo : le padding rend l'item plus haut que la
     min-height de la barre, donc le logo remonte et dégage du vide en
     dessous. Réduit au défilement, pour garder l'en-tête compact. */
  padding-bottom: var(--espace-s);
  transition: padding-bottom var(--transition);
}
.entete--solide .entete__logo {
  padding-bottom: 0.5rem;
}
/* ⚠️ « width: auto » ÉVITÉ EXPRÈS — voir le commentaire jumeau, bien plus
   long, dans impec/css/habillage.css (même section). Bug trouvé le 7 août
   2026 : un logo aussi large que haut (446 × 159, ratio 2,805) se
   retrouvait écrasé bien en dessous de sa hauteur déclarée dès que la barre
   était resserrée, malgré flex-shrink: 0 sur .entete__logo. Largeur
   calculée explicitement depuis la hauteur (× 2,805031446540881) pour
   contourner l'ambiguïté plutôt que de la corriger. */
.entete__logo img {
  height: 72px;
  width: 202px;
  transition:
    height var(--transition),
    width var(--transition);
}
.entete--solide .entete__logo img {
  height: 42px;
  width: 117.81px;
}

/* Méga-menu : partie centrale de l'en-tête (logo · menu · actions) */
.megamenu {
  display: flex;
  justify-content: center;
  align-self: stretch; /* occupe toute la hauteur de l'en-tête */
}
.megamenu__liste {
  display: flex;
  align-items: stretch; /* items pleine hauteur, pour combler le vide sous le titre */
  height: 100%;
}
.megamenu__item {
  position: static; /* le panneau s'ancre sur .entete__interieur (pleine largeur) */
  display: flex;
  align-items: center; /* garde le titre centré verticalement */
  /* padding au lieu de gap : les zones de survol se touchent, pas d'espace mort */
  padding-inline: clamp(0.375rem, 0.8vw, 0.75rem);
}

.megamenu__trigger,
.megamenu__lien {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.5rem 0;
  background: none;
  border: 0;
  color: inherit;
  font-family: var(--police-corps);
  font-size: 1rem;
  font-weight: 700;
  position: relative;
  white-space: nowrap; /* chaque catégorie sur une seule ligne */
}
/* Soulignement doré animé (décoratif) */
.megamenu__trigger::after,
.megamenu__lien::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -2px;
  width: 100%;
  height: 2px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--transition);
}
.megamenu__item:hover .megamenu__trigger::after,
.megamenu__item:focus-within .megamenu__trigger::after,
.megamenu__lien:hover::after,
.megamenu__trigger[aria-expanded="true"]::after {
  transform: scaleX(1);
}

.chevron {
  width: 14px;
  height: 14px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  transition: transform var(--transition);
}
.megamenu__item:hover .chevron,
.megamenu__trigger[aria-expanded="true"] .chevron {
  transform: rotate(180deg);
}

/* -------------------------------------------------------------------------
   PANNEAU DU MÉGA-MENU (inspiré de broccolini.com)
   ------------------------------------------------------------------------
   Un seul panneau pour toutes les catégories : c'est lui qui porte l'aplat
   crème et la hauteur animée, de sorte qu'en passant d'une catégorie à
   l'autre le fond ne clignote jamais (le défaut du panneau par catégorie :
   deux fonds en fondu laissaient voir la page au travers).
   Il est enfant de .entete (qui est `sticky`, donc positionné) et déborde en
   pleine largeur de fenêtre, sous la barre. La barre passe elle aussi en
   crème à l'ouverture : les deux ne forment qu'un seul bloc.
   ------------------------------------------------------------------------- */
.megamenu__panneau {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  overflow: hidden;
  height: 0; /* piloté au pixel par le JS, pour animer la hauteur */
  background: var(--fond-page);
  color: var(--texte);
  border-bottom: 1px solid var(--filet);
  transition: height var(--transition-lent);
}
.megamenu__panneau[hidden] {
  display: none;
}

/* Une vue = une catégorie : rien d'autre que la liste verticale des
   sous-sections. Pas de photo — le panneau reste purement typographique. */
.megamenu__vue {
  display: block;
  /* Moins de blanc en haut qu'en bas : la barre pose déjà son propre écart
     sous les titres, alors qu'en bas rien ne retient l'œil. Un retrait égal
     des deux côtés paraissait creux au-dessus du premier lien. */
  padding-block: clamp(0.85rem, 1.2vw, 1.15rem) clamp(1.5rem, 2vw, 2rem);
  padding-inline: max(var(--gouttiere), calc((100% - var(--largeur-max)) / 2));
  /* Retrait gauche : les sous-sections démarrent sous le premier titre de la
     barre (« LAVAGE DE VITRES »), pas au bord de page. Toutes les catégories
     partagent ce bord — la colonne ne bouge pas d'une catégorie à l'autre.
     La valeur dépend de la largeur du logo, qui rétrécit au défilement : elle
     n'est pas calculable en CSS, c'est le JS qui pose --mega-retrait. Le
     `max()` reste comme repli si le script ne s'exécute pas. */
  padding-left: var(
    --mega-retrait,
    max(var(--gouttiere), calc((100% - var(--largeur-max)) / 2))
  );
}
.megamenu__vue[hidden] {
  display: none;
}
/* Le contenu entre en fondu à chaque changement de catégorie */
.megamenu__vue > * {
  animation: menu-apparition var(--transition-lent) both;
}
@keyframes menu-apparition {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
}

/* Liste verticale : le cœur du parti pris — de gros titres empilés */
.megamenu__sousliste {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  /* Compense le retrait interne des liens (voir plus bas) : le texte reste
     aligné au pixel sur « LAVAGE DE VITRES ». */
  margin-left: -0.5rem;
}
.megamenu__sousliste a {
  display: inline-block;
  /* Retrait horizontal permanent : l'aplat de survol a de quoi respirer et
     rien ne bouge au passage de la souris. Le retrait vertical reste minime :
     c'est lui, avec l'interligne, qui règle l'écart entre les sous-sections. */
  padding: 0.05em 0.5rem;
  border-radius: var(--rayon-xs);
  color: var(--marine);
  font-family: var(--police-titre);
  font-size: clamp(0.95rem, 1.6vw, 1.5rem);
  font-weight: 600;
  line-height: 1.12;
  letter-spacing: -0.01em;
  text-transform: uppercase;
  transition:
    background-color var(--transition),
    color var(--transition),
    transform var(--transition);
}
/* Les liens non survolés gardent leur bleu plein : sur la crème, les faire
   passer en retrait les rendait simplement gris et ternes. Seul le lien
   survolé change — c'est lui qui porte la distinction.

   Le bleu pâle est porté par le fond, pas par le texte : en couleur de
   texte, il tombe à 1,42:1 sur la crème (illisible, le minimum étant 3:1
   pour du grand texte). En aplat, c'est la convention des boutons du site —
   fond bleu pâle, texte marine — et le contraste remonte à 12,7:1. */
.megamenu__sousliste a:hover,
.megamenu__sousliste a:focus-visible {
  color: #65b3d6;
  transform: translateX(0.35rem);
}

/* (Les règles de l'en-tête ouvert sont en fin de fichier, après le bloc
   responsive : elles doivent gagner aussi bien en desktop qu'en mobile.) */

/* Voile : assombrit la page sous l'en-tête pendant l'ouverture */
.nav-voile {
  position: fixed;
  inset: 0;
  z-index: calc(var(--z-entete) - 1);
  background: rgba(4, 14, 20, 0.6);
  opacity: 0;
  visibility: hidden;
  transition:
    opacity var(--transition),
    visibility var(--transition);
}
.nav-voile.est-visible {
  opacity: 1;
  visibility: visible;
}

@media (prefers-reduced-motion: reduce) {
  .megamenu__panneau,
  .megamenu__vue > * {
    transition: none;
    animation: none;
  }
}

/* Actions de droite */
.entete__actions {
  display: flex;
  align-items: center;
  gap: var(--espace-m);
  flex-shrink: 0;
  justify-self: end;
}
/* Bouton de la nav : fond pêche au survol (au lieu du bleu foncé) */
.entete__actions .bouton--or:hover {
  background: var(--accent-chaud);
  color: var(--texte);
}
/* Bascule de langue : une seule étiquette, celle de la langue courante */
.entete__langue {
  padding: 0.25rem 0.1rem;
  background: none;
  border: 0;
  color: inherit;
  font-family: var(--police-detail);
  font-size: var(--taille-label);
  font-weight: 700;
  letter-spacing: var(--tracking-label);
  cursor: pointer;
  transition: color var(--transition);
}
.entete__langue:hover {
  color: var(--accent);
}
.entete__tel {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--police-detail);
  font-size: var(--taille-petite);
  font-weight: 700;
  color: currentColor;
  white-space: nowrap;
}
.entete__tel-point {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--accent);
  flex-shrink: 0;
  animation: pulsation-accent 2.4s ease-in-out infinite;
}
@keyframes pulsation-accent {
  0%,
  100% {
    box-shadow: 0 0 0 0 rgba(var(--bleu-pale-rvb), 0.55);
  }
  50% {
    box-shadow: 0 0 0 6px rgba(var(--bleu-pale-rvb), 0);
  }
}

/* Hamburger (masqué sur desktop) */
.burger {
  display: none;
  flex-direction: column;
  gap: 5px;
  padding: 0.5rem;
  background: none;
  border: 0;
  /* Les <button> n'héritent pas de `color` : sans ça, les trois barres
     restent noires — invisibles sur l'en-tête marine du menu ouvert. */
  color: inherit;
}
.burger span {
  display: block;
  width: 26px;
  height: 2px;
  background: currentColor;
  transition:
    transform var(--transition),
    opacity var(--transition);
}
.burger[aria-expanded="true"] span:nth-child(1) {
  transform: translateY(7px) rotate(45deg);
}
.burger[aria-expanded="true"] span:nth-child(2) {
  opacity: 0;
}
.burger[aria-expanded="true"] span:nth-child(3) {
  transform: translateY(-7px) rotate(-45deg);
}

/* =========================================================================
   5. MENU MOBILE
   ========================================================================= */
/* Même parti pris qu'en desktop : plein écran, aplat crème, liste verticale
   en gros titres bleus. Le menu mobile et le méga-menu se ressemblent enfin. */
.menu-mobile {
  position: fixed;
  /* Plein écran et glissé SOUS l'en-tête plutôt que calé dessous : la barre
     mesure 65 px une fois compactée, pas les 80 px de --hauteur-entete, et
     l'écart laissait voir une bande de page entre les deux — invisible quand
     tout était marine, franche sur la crème. Le retrait haut dégage la barre,
     qui est opaque et se superpose. */
  inset: 0;
  z-index: calc(var(--z-entete) - 1);
  padding: calc(var(--hauteur-entete) + var(--espace-l)) var(--gouttiere)
    var(--espace-xl);
  background: var(--fond-page);
  color: var(--texte);
  overflow-y: auto;
  display: flex;
  flex-direction: column;
}
.menu-mobile[hidden] {
  display: none;
}
.menu-mobile__titre {
  margin-top: var(--espace-l);
  margin-bottom: 0.5rem;
  font-family: var(--police-detail);
  font-size: var(--taille-label);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--texte-doux);
}
.menu-mobile__titre:first-child {
  margin-top: 0;
}
/* :not(.bouton) — sinon cette règle écrase le padding des deux boutons
   d'action du menu et les aplatit (ils perdaient tout retrait horizontal). */
.menu-mobile a:not(.bouton) {
  padding: 0.3rem 0;
  color: var(--marine);
  font-family: var(--police-titre);
  font-size: clamp(1.35rem, 6vw, 1.9rem);
  font-weight: 700;
  line-height: 1.24;
  text-transform: uppercase;
  border-bottom: 0;
  transition: color var(--transition);
}
.menu-mobile a:not(.bouton):active {
  color: var(--bleu-pale);
}
/* Sur la crème, le bleu pâle d'avant serait illisible : « Contact » se
   détache par son écart et son filet, pas par sa couleur. */
.menu-mobile__contact {
  margin-top: var(--espace-l);
  padding-top: var(--espace-l) !important;
  border-top: 1px solid var(--filet);
}
.menu-mobile__actions {
  display: flex;
  flex-direction: column;
  gap: var(--espace-s);
  margin-top: var(--espace-l);
  padding-top: var(--espace-l);
  border-top: 1px solid var(--filet);
}
.menu-mobile__actions .bouton {
  justify-content: center;
}
.menu-mobile__actions .bouton--fantome {
  color: var(--marine);
  border-color: var(--filet);
}

/* =========================================================================
   6. HERO
   ========================================================================= */
.hero {
  position: relative;
  display: flex;
  align-items: flex-end;

  /* Pleine hauteur de fenêtre, sans plafond. Il y en avait un —
     min(100svh, 880px) — et c'est lui qui laissait voir la section suivante
     sous le hero dès que la fenêtre dépassait 961 px : le hero s'arrêtait à
     880 px, le slogan commençait juste après, et son fond crème entrait dans
     le cadre. Pendant l'intro, où le hero est remonté sous l'en-tête et où
     l'écran ne doit montrer que la vidéo, ça se lisait comme une barre
     blanche en bas de page.
     Sous 880 px de haut le plafond ne mordait pas : rien ne change là. */
  min-height: 80svh;

  overflow: hidden;
  color: var(--texte-inverse);
  /* Plus de remontée sous l'en-tête : celui-ci est opaque, le hero commence
     donc juste en dessous. */
}
.hero__media {
  position: absolute;
  inset: 0;
  margin: 0;

  /* L'image de repli vit ici, pas seulement dans l'attribut poster : la
     vidéo se fond par-dessus, donc son opacité ne doit jamais pouvoir
     effacer l'image. Sans fichier vidéo, c'est cette image qu'on voit.
     Même URL que le poster : un seul téléchargement. */
  background: url("../assets/img/hero.jpg") center / cover no-repeat;
}
.hero__media img,
.hero__media video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* La vidéo se superpose au poster une fois prête. Le fondu évite le saut
   sec entre l'image fixe et la première image du film. */
.hero__video {
  opacity: 0;
  transition: opacity 0.6s ease;
}

/* Classe posée par main-v3.js quand la lecture a réellement démarré. */
.hero__video.est-active {
  opacity: 1;
}

/* Bouton pause / lecture. Coin haut droit : les coins bas sont déjà pris
   par les appels à l'action et par « Faites défiler ». */
/* Le display du bloc suivant l'emporterait sur la règle « hidden » du
   navigateur, et le bouton s'afficherait même sans vidéo. Le sélecteur
   d'attribut est plus spécifique que la simple classe : il gagne. */
.hero__bascule-video[hidden] {
  display: none;
}

.hero__bascule-video {
  position: absolute;
  z-index: 3;
  top: calc(var(--hauteur-entete) + 1rem);
  right: var(--gouttiere);

  display: grid;
  place-items: center;

  width: 2.75rem;
  height: 2.75rem;

  padding: 0;

  color: var(--texte-inverse);
  background: rgba(9, 10, 30, 0.45);
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: var(--rayon-pilule);

  cursor: pointer;

  backdrop-filter: blur(6px);

  transition:
    background-color var(--transition),
    border-color var(--transition);
}

.hero__bascule-video:hover {
  background: rgba(9, 10, 30, 0.7);
  border-color: rgba(255, 255, 255, 0.6);
}

/* --------------------------------------------------------------------------
   Le bouton s'efface au repos.

   Il n'est pas décoratif : une vidéo qui démarre seule doit pouvoir être
   arrêtée — c'est le critère WCAG 2.2.2. On ne le retire donc pas, on le rend
   discret. Il revient au survol du hero, et au focus clavier, ce qui le laisse
   atteignable par tous les moyens.

   pointer-events reste actif : le bouton répond au clic même pendant qu'il
   apparaît, sans attendre la fin du fondu.
   -------------------------------------------------------------------------- */
.hero__bascule-video {
  opacity: 0;
  transition:
    opacity var(--transition),
    background-color var(--transition),
    border-color var(--transition);
}

.hero:hover .hero__bascule-video,
.hero:focus-within .hero__bascule-video,
.hero__bascule-video:focus-visible {
  opacity: 1;
}

/* Sur un écran tactile, il n'y a pas de survol : le bouton reste visible,
   sinon il deviendrait inatteignable. */
@media (hover: none) {
  .hero__bascule-video {
    opacity: 1;
  }
}

.hero__bascule-video svg {
  width: 1.1rem;
  height: 1.1rem;
  fill: currentColor;
}

/* Une seule icône à la fois, selon l'état porté par .est-en-pause. */
.hero__bascule-video .hero__icone-lecture,
.hero__bascule-video.est-en-pause .hero__icone-pause {
  display: none;
}

.hero__bascule-video.est-en-pause .hero__icone-lecture {
  display: block;
}
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  /* 0,2 au milieu laissait le H1 blanc passer sur les nuages lumineux */
  background: linear-gradient(
    to top,
    rgba(9, 10, 30, 0.85),
    rgba(9, 10, 30, 0.42) 55%,
    rgba(9, 10, 30, 0.5)
  );
}
.hero__contenu {
  position: relative;
  z-index: 2;
  width: 100%;
  padding-block: 0 clamp(3.5rem, 7vw, 6rem);
}
.hero .eyebrow {
  color: var(--creme);
}
.hero .eyebrow {
  font-weight: 900;
  font-size: large;
}
/* Le slogan et l'accroche ont échangé leurs balises — le H1 est passé sur
   l'accroche, qui porte les mots-clés. Ces deux règles héritaient jusqu'ici
   leur police de la balise h1 ; elles la déclarent maintenant elles-mêmes,
   pour que le rendu reste rigoureusement identique. */
.hero__titre {
  margin-top: var(--espace-l);
  max-width: 16ch;

  font-family: var(--police-affiche);
  font-weight: var(--graisse-titre);
  letter-spacing: -0.02em;

  font-size: var(--taille-hero);
  line-height: 0.8;
  overflow-wrap: break-word;
  text-wrap: balance;
}
.hero__titre strong {
  color: var(--accent);
  font-weight: 800;
}
.hero__accroche {
  max-width: 60ch;
  margin-top: var(--espace-l);

  /* Devenue le h1 : sans ces trois lignes elle passerait en Bebas Neue,
     serrée et en graisse de titre. */
  font-family: var(--police-corps);
  letter-spacing: normal;

  font-size: var(--taille-h3);
  line-height: 1.3;

  color: var(--texte-inverse);
  font-weight: 600;
}
.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--espace-s);
  margin-top: var(--espace-l);
}
.hero__defiler {
  position: absolute;
  z-index: 2;
  right: var(--gouttiere);
  bottom: clamp(3.5rem, 7vw, 6rem);
}
.hero__defiler .eyebrow {
  color: var(--texte-inverse-doux);
}

/* =========================================================================
   7. SLOGAN (transition après le hero)
   ========================================================================= */
.slogan {
  background: var(--fond-page);
  text-align: center;
  padding-block: var(--espace-moment);
  display: flex;
  flex-direction: column;
  align-items: center;
}
.slogan__ligne {
  width: clamp(4rem, 6vw, 5rem);
  height: 3px;
  margin-bottom: var(--espace-l);

  background: var(--accent-chaud);
  border-radius: var(--rayon-pilule);
}
.slogan__texte {
  font-family: var(--police-titre);
  font-size: var(--taille-slogan);
  font-weight: 800;
  line-height: 0.92;
  letter-spacing: -0.04em;
  text-transform: uppercase;
  text-align: center;
  text-wrap: balance;
}
.slogan__texte em {
  font-style: italic;
  color: var(--texte);
} /* tout le texte en bleu, accent en italique */
.slogan__description {
  max-width: 44rem;
  margin-top: var(--espace-l);

  color: var(--texte-doux);
  font-size: var(--taille-corps-grand);
  line-height: var(--interligne-corps);
  text-align: center;
  text-wrap: balance;
}

/* ==========================================================================
   PROOF STRIP
   ========================================================================== */

.proof-strip {
  padding: 0;
  margin: 0;
  background: var(--fond-sombre);
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  align-items: stretch;
  color: #fff;
}
.proof-item {
  min-height: 145px;
  padding: 29px 3vw;

  display: flex;
  flex-direction: column;
  justify-content: center;

  border-right: 1px solid var(--filet-inverse);
}

.proof-item:last-child {
  border-right: 0;
}

.proof-item:first-child {
  background: var(--accent);
  color: var(--texte-sur-accent);
  align-self: stretch;
  height: 100%;
}

/* Le premier bloc est un <a> (voir le HTML) : il faut lui retirer les
   décorations de lien et lui rendre les couleurs de la tuile, que sa règle
   ci-dessus donne déjà — mais que la feuille de style du navigateur écrase
   sur un <a>. Le reste (flex, padding, hauteur) vient de .proof-item. */
a.proof-item {
  color: var(--texte-sur-accent);
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--transition);
}
/* Au survol : le même passage à --accent-chaud que les boutons .bouton--or,
   pour que la tuile se comporte comme le reste des appels à l'action. Pas de
   translateY ici : une tuile pleine largeur qui se soulève décolle du bandeau,
   là où un bouton isolé le supporte. */
a.proof-item:hover {
  background: var(--accent-chaud);
}

.proof-item strong {
  font-family: var(--police-titre);
  font-size: clamp(1.55rem, 2vw, 1.85rem);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.02em;
}

/* Description : c'est une phrase, pas une étiquette. Donc police de corps,
   graisse normale, pas d'interlettrage et une taille lisible. */
.proof-item span {
  margin-top: 0.6rem;

  font-family: var(--police-corps);
  font-size: var(--taille-petite);
  font-weight: 400;
  letter-spacing: 0;

  line-height: 1.55;
  color: var(--texte-inverse-doux);
}

/* Le premier bloc est sur un aplat --accent : il lui faut le gris « sur accent » */
.proof-item:first-child span {
  color: var(--texte-sur-accent-doux);
}

@media (max-width: 900px) {
  .proof-strip {
    grid-template-columns: 1fr 1fr;
  }

  .proof-item:nth-child(2) {
    border-right: 0;
  }

  .proof-item:nth-child(-n + 2) {
    border-bottom: 1px solid var(--filet-inverse);
  }
}

@media (max-width: 640px) {
  .proof-strip {
    grid-template-columns: 1fr;
  }

  .proof-item {
    border-right: 0;
    border-bottom: 1px solid var(--filet-inverse);
  }

  .proof-item:last-child {
    border-bottom: 0;
  }
}

/* =========================================================================
   8. SERVICES (cartes épurées : photo + titre + lien)
   ========================================================================= */
.services__grille {
  display: flex;
  flex-direction: column;
  gap: var(--espace-m);
}

.services__ligne {
  display: grid;
  grid-template-columns: 55% 45%;
  gap: var(--espace-m);
}

.services__ligne--inverse {
  grid-template-columns: 45% 55%;
}

@media (max-width: 900px) {
  .services__ligne,
  .services__ligne--inverse {
    grid-template-columns: 1fr;
  }
}

.carte-service {
  position: relative;
  overflow: hidden;
  border-radius: var(--rayon-carte);
  height: 360px; /* toutes les cartes à la même hauteur */
  transition:
    transform 0.35s ease,
    box-shadow 0.35s ease;
}

.carte-service:hover {
  transform: translateY(-6px);

  box-shadow:
    0 0 0 2px var(--accent-chaud),
    0 18px 40px rgba(0, 0, 0, 0.18);
}

.carte-service a {
  position: relative;
  display: block;
  height: 100%;
  color: #fff;
}

.carte-service img {
  position: absolute;
  inset: 0;

  width: 100%;
  height: 100%;

  object-fit: cover;
  transition: transform 0.8s ease;
}

/* Le haut du voile était à 0,05 : l'étiquette blanche disparaissait sur les
   ciels clairs. Il faut ~0,3 en haut pour qu'elle tienne sur n'importe
   quelle photo, sans pour autant assombrir toute l'image. */
.carte-service__overlay {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to top,
    rgba(0, 0, 0, 0.85) 0%,
    rgba(0, 0, 0, 0.5) 45%,
    rgba(0, 0, 0, 0.32) 75%,
    rgba(0, 0, 0, 0.3) 100%
  );
  z-index: 1;
}

.carte-service:hover img {
  transform: scale(1.06);
}

.carte-service__contenu {
  position: absolute;
  inset: 0;
  z-index: 2;

  display: flex;
  flex-direction: column;
  justify-content: flex-end;

  padding: 2.5rem;
}

.carte-service__numero {
  position: absolute;
  top: 2rem;
  left: 2rem;

  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.9);
}

.carte-service :is(h2, h3) {
  margin: 0;

  font-family: var(--police-titre);
  /* Exception voulue : titres de cartes plus grands que le h3 uniforme
     (photos en grand → titres plus présents). */
  font-size: clamp(2rem, 2.8vw, 3rem);
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: -0.02em;

  color: #fff;
  max-width: 85%;
}

.carte-service p {
  margin: 0.45rem 0 0;

  max-width: 85%;

  font-size: 0.95rem;
  line-height: 1.55;

  color: rgba(255, 255, 255, 0.88);
}

.carte-service .lien-fleche {
  margin-top: 0.9rem;

  display: inline-flex;
  align-items: center;
  gap: 0.45rem;

  font-size: 0.72rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-weight: 700;

  color: var(--accent-chaud);
}

.carte-service:hover .lien-fleche {
  transform: translateX(6px);
}

@media (max-width: 900px) {
  .carte-service {
    min-height: 420px;
  }

  .carte-service p {
    max-width: 100%;
  }
}

/* =========================================================================
   9. (Section « Autres services » retirée — devenue la 6e carte de Services)
   ========================================================================= */

/* =========================================================================
   10. SECTEURS (grande liste éditoriale, fond foncé)
   ========================================================================= */
.secteurs {
  background: var(--accent);
  color: var(--texte);
}
.secteurs .eyebrow {
  color: var(--texte);
}
.secteurs .section__titre {
  color: var(--fond-sombre);
}

.secteurs__ligne a {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: var(--espace-m);
  padding-block: clamp(0.85rem, 1.8vw, 1.35rem);
  transition: padding-left var(--transition);
}
.secteurs__ligne a:hover {
  padding-left: var(--espace-s);
}
.secteurs__nom {
  grid-row: 1;
  font-family: var(--police-titre);
  font-weight: 700;
  font-size: var(--taille-liste);
  color: #fff;
  letter-spacing: -0.02em;
  transition: color var(--transition);
}
.secteurs__ligne a:hover .secteurs__nom {
  color: var(--accent-chaud);
}
.secteurs__desc {
  grid-row: 2;
  grid-column: 1;
  max-width: 46ch;
  color: var(--texte-inverse-doux);
  font-size: var(--taille-corps);
  max-height: 0;
  opacity: 0;
  overflow: hidden;
  transition:
    max-height var(--transition),
    opacity var(--transition),
    margin-top var(--transition);
}
.secteurs__ligne a:hover .secteurs__desc,
.secteurs__ligne a:focus-visible .secteurs__desc {
  max-height: 4rem;
  opacity: 1;
  margin-top: 0.5rem;
}
.secteurs__fleche {
  grid-column: 2;
  grid-row: 1 / span 2;
  color: var(--accent-chaud);
  font-size: 1.5rem;
  transition: transform var(--transition);
}
.secteurs__ligne a:hover .secteurs__fleche {
  transform: translateX(6px);
}

/* =========================================================================
   9b. AUTRES SERVICES (services complémentaires — 3 cartes paysage)
   ========================================================================= */
.autres {
  background: var(--fond-alterne);
}
.autres__grille {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: var(--espace-m);
}
.carte-autre {
  position: relative;
  aspect-ratio: 16 / 10; /* paysage : toujours plus large que haut */
  border-radius: var(--rayon-carte);
  overflow: hidden;
  background: var(
    --gris-perle
  ); /* placeholder gris — remplacer par une image */
  transition: transform var(--transition);
}
.carte-autre:hover {
  transform: translateY(-4px);
}
.carte-autre__media {
  position: absolute;
  inset: 0;
  margin: 0;
  display: grid;
  place-items: start center; /* icône placeholder en haut, hors de la zone de texte */
  padding-top: 13%;
  color: rgba(22, 23, 63, 0.3);
}
.carte-autre__media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.carte-autre__icone {
  width: 38px;
  height: 38px;
}
/* Voile bas pour la lisibilité du texte superposé (placeholder ou photo) */
.carte-autre::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    0deg,
    rgba(11, 14, 28, 0.82),
    rgba(11, 14, 28, 0.08) 55%,
    transparent 78%
  );
}
.carte-autre__corps {
  position: absolute;
  z-index: 2;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.4rem;
  padding: clamp(1.1rem, 2vw, 1.6rem);
  color: #fff;
}
.carte-autre__corps :is(h2, h3) {
  font-size: var(--taille-h3);
  color: #fff;
}
.carte-autre__corps p {
  max-width: 34ch;
  font-size: var(--taille-petite);
  color: rgba(255, 255, 255, 0.85);
}
.carte-autre__corps .lien-fleche {
  margin-top: 0.3rem;
  color: var(--accent-chaud);
}

/* =========================================================================
   11. PROCÉDÉ
   ========================================================================= */

.procede__entete {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(320px, 1fr);
  gap: clamp(3rem, 6vw, 7rem);
  align-items: end;
  margin-bottom: clamp(3rem, 5vw, 4rem);
}

.procede__gauche {
  display: flex;
  flex-direction: column;
}

.procede .section__titre {
  margin-top: 1rem;
  max-width: 20ch;
}

.procede__droite {
  display: flex;
  align-items: flex-end;
}

.procede .section__intro {
  margin: 0;
  max-width: 32ch;

  font-size: 1.1rem;
  line-height: 1.7;
  color: var(--texte-doux);
}

.procede__cadre {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
}

.procede__etape {
  position: relative;

  padding: clamp(2.2rem, 4vw, 3rem) clamp(1.6rem, 2vw, 2rem)
    clamp(3rem, 4vw, 3.5rem);

  border-top: 1px solid var(--filet);
  border-bottom: 1px solid var(--filet);
  border-left: 1px solid var(--filet);

  transition:
    transform 0.3s ease,
    background-color 0.3s ease;
}

.procede__etape:first-child {
  border-left: 0;
}

.procede__etape::before {
  content: "";
  position: absolute;
  top: -1px;
  left: 0;
  width: 100%;
  height: 2px;

  background: var(--accent-chaud);

  transform: scaleX(0);
  transform-origin: left;

  transition: transform 0.35s ease;
}

.procede__etape:hover::before {
  transform: scaleX(1);
}

.procede__etape::after {
  content: "";
  position: absolute;
  bottom: -1px;
  left: 0;
  width: 100%;
  height: 2px;

  background: var(--accent-chaud);

  transform: scaleX(0);
  transform-origin: left;

  transition: transform 0.35s ease;
}

.procede__etape:hover::after {
  transform: scaleX(1);
}

.procede__num {
  display: inline-flex;
  align-items: center;
  justify-content: center;

  width: 33px;
  height: 33px;

  margin-bottom: 2.25rem;

  background: var(--accent-chaud); /* bleu pastel */
  border-radius: var(--rayon-pilule);

  font-family: var(--police-detail);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--texte); /* bleu */
}

.procede__num::after {
  content: attr(data-num);

  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);

  font-family: var(--police-detail);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.14em;

  color: var(--accent-chaud);
}

.procede__etape h3 {
  margin: 0 0 0.9rem;

  font-family: var(--police-titre);
  font-size: var(--taille-h3);
  font-weight: 700;
  line-height: 1.05;

  /* Réserve deux lignes : « Planification » et « Suivi » tiennent sur une
     ligne, les deux autres sur deux. Sans ça les paragraphes des quatre
     colonnes démarraient à 32 px d'écart. */
  min-height: 2.1em;

  color: var(--texte);

  transition: color 0.3s ease;
}

.procede__etape p {
  max-width: 22ch;

  font-size: 1rem;
  line-height: 1.7;

  color: var(--texte-doux);
}

.procede__etape:hover {
  transform: translateY(-4px);
}

@media (max-width: 900px) {
  .procede .section__entete {
    grid-template-columns: 1fr;
    gap: 2rem;
  }

  .procede .section__titre {
    max-width: 100%;
  }

  .procede__cadre {
    grid-template-columns: 1fr;
  }

  .procede__etape {
    border-left: 0;
    border-top: 1px solid var(--filet);
  }

  .procede__etape:first-child {
    border-top: 0;
  }
}

/* =========================================================================
   12. NOTRE ENTREPRISE (image + liste numérotée + chiffres, fond clair)
   ========================================================================= */
.entreprise {
  background: var(--fond-alterne);
}

/* Rangée haute : image à gauche, texte à droite */
.entreprise__haut {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: stretch;
}
.entreprise__media {
  margin: 0;
  border-radius: var(--rayon-media);
  overflow: hidden;
}
.entreprise__media img {
  width: 100%;
  height: 100%;
  min-height: 340px;
  object-fit: cover;
}

/* Le titre garde le style partagé, sans la contrainte de largeur en 24ch */
.entreprise__titre {
  max-width: none;
}

/* Liste numérotée, façon v4 : numéro doré + filet horizontal par item */
.entreprise__engagements {
  list-style: none;
  margin: var(--espace-l) 0 0;
  padding: 0;
  border-top: 1px solid var(--accent-chaud);
}
.entreprise__engagements li {
  display: grid;
  grid-template-columns: 3.25rem 1fr;
  gap: var(--espace-m);
  padding: var(--espace-m) 0;
  border-bottom: 1px solid var(--accent-chaud);
}
.entreprise__num {
  display: inline-flex;
  align-items: center;
  justify-content: center;

  width: 33px;
  height: 33px;

  padding: 0 0.6rem;

  background: var(--accent-chaud);
  border-radius: var(--rayon-pilule);

  font-family: var(--police-detail);
  font-size: 0.8rem;
  font-weight: 800;
  letter-spacing: var(--tracking-label);
  color: var(--texte);

  margin-top: 0.35rem;
}
.entreprise__engagements h3 {
  font-size: var(--taille-h3);
  margin: 0 0 var(--espace-xs);
  color: var(--texte);
}
.entreprise__engagements p {
  margin: 0;
  color: var(--texte-doux);
}
.entreprise__chiffres {
  margin-top: var(--espace-l);
  padding-top: var(--espace-m);
}
.entreprise__chiffres dl {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: var(--espace-l);
  margin: 0;
}
.entreprise__chiffres dl > div {
  min-width: 0;
}
.entreprise__chiffres dt {
  margin-bottom: var(--espace-xs);
}
.entreprise__chiffres dd {
  margin: 0;
  font-family: var(--police-chiffres); /* Syne, comme la v2 */
  font-weight: 800;
  font-size: clamp(1.75rem, 3vw, 2.5rem);
  color: var(--texte);
  overflow-wrap: anywhere;
}

/* Empilement mobile : image au-dessus, texte en dessous */
@media (max-width: 760px) {
  .entreprise__haut {
    grid-template-columns: 1fr;
    gap: var(--espace-l);
  }
  .entreprise__media img {
    min-height: 240px;
  }
}

/* =========================================================================
   13. RÉALISATIONS (galerie de projets)
   ========================================================================= */
.realisations {
  background: var(--fond-page);
}
/* Galerie de 3 photos : une grande (2 rangées) à gauche, deux à droite */
.realisations__galerie {
  display: grid;
  grid-template-columns: 2fr 1fr;
  gap: var(--espace-m);
}
.realisations__photo {
  margin: 0;
  border-radius: var(--rayon-media);
  overflow: hidden;
}
.realisations__photo--grande {
  grid-row: 1 / span 2;
}
.realisations__photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform var(--transition-lent);
}
.realisations__photo:not(.realisations__photo--grande) {
  aspect-ratio: 16 / 10;
}
.realisations__photo:hover img {
  transform: scale(1.04);
}

/* =========================================================================
   14. TÉMOIGNAGES (carrousel, fond foncé)
   ========================================================================= */
.temoignages {
  background: var(--fond-sombre);
  color: var(--texte-inverse);
  text-align: center;
}
.temoignages .section__entete {
  max-width: none;
  text-align: left; /* étiquette « Avis clients » à gauche, titre centré */
  margin-bottom: var(--espace-l);
}
.temoignages .eyebrow {
  color: var(--accent-chaud);
}
.temoignages .section__titre {
  color: var(--creme);
  text-align: left; /* étiquette ET titre alignés à gauche */
  max-width: none;
  margin-top: var(--espace-m);
}

/* Un seul avis à la fois (voulu), mais les quatre occupent la MÊME cellule
   de grille : la scène prend la hauteur du plus long et la page ne saute
   plus à chaque rotation. On masque par visibilité, pas par display, pour
   garder la place réservée — et ça permet un fondu. */
.temoignages__scene {
  display: grid;
  max-width: 90ch;
  margin-inline: auto;
}
.temoignage {
  grid-area: 1 / 1;
  transition: opacity 320ms ease-out;
}
/* transition: none sur l'état masqué → l'avis sortant disparaît net, seul
   l'entrant fait un fondu. Sans ça les deux textes se superposent pendant
   toute la durée du fondu, et plus rien n'est lisible. */
.temoignage[hidden] {
  display: block;
  visibility: hidden;
  opacity: 0;
  transition: none;
}
/* Pas d'opacité : sur le fond marine elle mélangeait le pêche vers le gris.
   Le guillemet est maintenant en pêche plein. */
.temoignage__guillemet {
  display: block;
  font-family: var(--police-titre);
  font-size: 7rem;
  line-height: 0.55;
  color: var(--accent-chaud);
  margin-bottom: 0;
}
.temoignage p {
  font-family: var(--police-titre);
  font-weight: 600;
  font-size: clamp(1.4rem, 3vw, 2.25rem);
  line-height: 1.3;
  color: #fff;
}
.temoignage footer {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.6rem;
  margin-top: var(--espace-l);
}
.temoignage__etoiles {
  color: var(--accent-chaud);
  letter-spacing: 3px;
  font-size: 0.95rem;
}
.temoignage cite {
  font-family: var(--police-detail);
  font-size: var(--taille-label);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--texte-inverse-doux);
  font-style: normal;
}
.temoignages__controles {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--espace-m);
  margin-top: var(--espace-xl);
}
.temoignages__bouton {
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 50%;
  border: 1px solid var(--filet-inverse);
  background: transparent;
  color: #fff;
  font-size: 1.25rem;
  line-height: 1;
  transition:
    background-color var(--transition),
    color var(--transition);
}
.temoignages__bouton:hover {
  background: var(--accent);
  color: var(--texte);
  border-color: var(--accent);
}
.temoignages__points {
  display: flex;
}
/* La puce reste petite, mais la zone cliquable fait 44 px : la cible
   tactile passe la norme sans changer le dessin. */
.temoignages__points button {
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  background: transparent;
  display: grid;
  place-items: center;
}
.temoignages__points button::after {
  content: "";
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--filet-inverse);
  transition:
    background-color var(--transition),
    transform var(--transition);
}
.temoignages__points button[aria-selected="true"]::after {
  background: var(--accent-chaud);
  transform: scale(1.25);
}

/* =========================================================================
   15. FAQ (accordéon natif <details>)
   ========================================================================= */
.faq {
  background: var(--fond-page);
}
.faq__liste {
  max-width: none;
}
.faq__item {
  border-top: 1px solid var(--filet);
}
.faq__item:last-child {
  border-bottom: 1px solid var(--filet);
}
.faq__item summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--espace-m);
  padding-block: var(--espace-m);
  font-family: var(--police-titre);
  font-weight: 600;
  font-size: 26px;
  color: var(--marine);
}
.faq__item summary::-webkit-details-marker {
  display: none;
}

/* Les questions sont désormais des h3 — la page en ligne les a en h4, elles
   n'étaient ici aucun titre du tout. « font: inherit » leur rend exactement
   l'apparence qu'avait le texte nu du <summary> : sans cela, la règle globale
   h2/h3 leur imposerait sa graisse et son interlettrage. */
.faq__item summary h3 {
  margin: 0;
  font: inherit;
  letter-spacing: inherit;
  color: inherit;
}
.faq__item summary::after {
  content: "+";
  color: var(--accent);
  font-size: 1.6em;
  line-height: 1;
  transition: transform var(--transition);
}
.faq__item[open] summary::after {
  content: "\2013";
}
.faq__item p {
  padding-bottom: var(--espace-m);
  max-width: 70ch;
  color: var(--texte-doux);
}

/* =========================================================================
   16. SOUMISSION (texte + coordonnées + formulaire style « souligné »)
   ========================================================================= */
.soumission {
  background: var(--fond-alterne);
}
.soumission__grille {
  display: grid;
  grid-template-columns: 0.85fr 1.15fr;
  gap: clamp(2.5rem, 5vw, 5rem);
  align-items: start;
}

/* La colonne gauche est bien plus courte que le formulaire : on la rend
   collante pour qu'elle accompagne la saisie au lieu de laisser un vide.

   Un essai d'étirement — align-items: stretch et coordonnées poussées au bas —
   a été tenté puis ABANDONNÉ : Patrik a trouvé le résultat moins bon. Le
   collant de la maquette est le comportement voulu. */
@media (min-width: 901px) {
  .soumission__intro {
    position: sticky;
    top: calc(var(--hauteur-entete) + var(--espace-m));
  }
}

/* Colonne texte + coordonnées */
.soumission__titre {
  margin-top: var(--espace-m);
  font-size: var(--taille-h2);
  color: var(--marine);
}
.soumission__desc {
  margin-top: var(--espace-m);
  max-width: 38ch;
  color: var(--texte-doux);
}
/* =========================================================================
   COORDONNÉES — SOUMISSION
   ========================================================================= */

.soumission__contacts {
  display: flex;
  flex-direction: column;
  align-items: flex-start;

  gap: 0.75rem;

  margin-top: var(--espace-l);
}

/* Ligne individuelle */

.soumission__ligne {
  display: flex;
  align-items: center;

  gap: 0.85rem;

  padding: 0;

  font-size: var(--taille-petite);
  color: var(--texte);
}

/* Icône */

.soumission__icone {
  display: grid;
  place-items: center;

  flex: 0 0 38px;

  width: 38px;
  height: 38px;

  border: 2px solid var(--filet);
  border-radius: 30px;

  background: rgba(255, 255, 255, 0.45);

  color: var(--marine);
}

/* SVG */

.soumission__icone svg {
  display: block;

  width: 17px !important;
  height: 17px !important;

  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Liens — l'icône vit maintenant DEDANS (voir elements-champs.php), donc le
   lien reprend le rôle de rangée flex que tenait .soumission__ligne. */

.soumission__ligne a {
  display: flex;
  align-items: center;
  gap: 0.85rem;

  color: var(--texte);
  text-decoration: none;
  font-weight: 600;

  transition: color var(--transition);
}

/* Boîte du formulaire */
.formulaire {
  padding: clamp(1.5rem, 3vw, 2.5rem);
  background: var(--fond-carte);
  border: var(--bordure-carte);
  border-radius: var(--rayon-carte);
}
.formulaire__champ {
  margin-bottom: var(--espace-m);
}
.formulaire__rangee {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--espace-m);
}
.formulaire label {
  display: block;
  margin-bottom: 0.5rem;
  font-family: var(--police-detail);
  font-size: var(--taille-label);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--texte-doux);
}
.formulaire .optionnel {
  text-transform: none;
  letter-spacing: 0;
  opacity: 0.7;
}

/* Champs « soulignés » (une seule ligne de base), comme la maquette v13 */
.formulaire input,
.formulaire select,
.formulaire textarea {
  width: 100%;
  padding: 0.75rem 0;
  font-family: var(--police-corps);
  font-size: var(--taille-corps);
  color: var(--texte);
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--filet);
  border-radius: 0;
  transition: border-color var(--transition);
}
.formulaire input::placeholder,
.formulaire textarea::placeholder {
  color: var(--texte-doux);
  opacity: 0.6;
}
.formulaire input:focus,
.formulaire select:focus,
.formulaire textarea:focus {
  outline: none;
  border-bottom-color: var(--marine);
}
.formulaire textarea {
  resize: vertical;
  min-height: 4rem;
}
.form-note {
  margin-top: var(--espace-s);
  font-family: var(--police-detail);
  font-size: var(--taille-label);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--texte-doux);
}

/* Zone de dépôt de fichiers (liste remplie par js/main.js) */
.upload-zone {
  position: relative;
  margin-top: 0.25rem;
  padding: var(--espace-l) var(--espace-m);
  text-align: center;
  cursor: pointer;
  border: 1px dashed var(--filet);
  border-radius: var(--rayon-s);
  background: var(--fond-alterne);
  transition:
    border-color var(--transition),
    background-color var(--transition);
}
.upload-zone:hover,
.upload-zone.survol {
  border-color: var(--marine);
  background: #fff;
}
.upload-zone input[type="file"] {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  cursor: pointer;
}
.upload-zone__icone {
  display: block;
  width: 28px;
  height: 28px;
  margin: 0 auto 0.5rem;
  color: var(--texte-doux);
}
.upload-zone__icone svg {
  width: 100%;
  height: 100%;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.5;
}
.upload-zone__label {
  font-size: var(--taille-petite);
  font-weight: 500;
  color: var(--texte);
}
.upload-zone__label span {
  color: var(--marine);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.upload-zone__hint {
  margin-top: 0.35rem;
  font-family: var(--police-detail);
  font-size: var(--taille-label);
  color: var(--texte-doux);
}
.upload-zone__fichiers {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 0.75rem;
}
.upload-zone__tag {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  max-width: 220px;
  padding: 0.35rem 0.7rem;
  background: var(--fond-carte);
  border: 1px solid var(--filet);
  border-radius: var(--rayon-xs);
  font-size: 0.8rem;
  color: var(--texte);
}
.upload-zone__tag .nom {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* =========================================================================
   17. CARRIÈRES (bandeau, fond indigo)
   ========================================================================= */
.carrieres {
  background: var(--fond-page); /* bleu clair, comme la maquette */
  color: var(--texte);
  border-top: 2px solid var(--accent-chaud);
  padding-block: var(--espace-bandeau);
}
.carrieres__contenu {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--espace-m);
  flex-wrap: wrap;
}
.carrieres__contenu > div {
  flex: 2 1 40rem;
  min-width: 0;
}
.carrieres .eyebrow {
  color: var(--texte-doux);
}
.carrieres .section__titre {
  color: var(--marine);
  max-width: 60ch; /* titre sur 2 lignes */
  font-size: var(--taille-bandeau); /* sous les titres de section */
}
.carrieres .section__intro {
  color: var(--texte-doux);
  margin-bottom: 0;
}
.carrieres .bouton {
  flex-shrink: 0;
}

/* =========================================================================
   18. PIED DE PAGE
   ========================================================================= */

.pied {
  background: var(--fond-sombre);
  color: var(--texte-inverse-doux);
  padding-block: var(--espace-l);
}

/* =========================================================================
   GRILLE PRINCIPALE
   Logo / réseaux | Téléphone + courriel | Navigation
   ========================================================================= */

.pied__grille {
  display: grid;
  grid-template-columns:
    220px
    430px
    minmax(300px, 1fr);

  column-gap: 1rem;
  align-items: start;

  padding-block: var(--espace-l);
}
/* =========================================================================
   LOGO
   ========================================================================= */

.pied__contact {
  min-width: 0;
}

.pied__logo {
  display: inline-block;
}

.pied__logo img {
  display: block;
  width: auto;
  height: 64px;
}

/* =========================================================================
   RÉSEAUX SOCIAUX
   ========================================================================= */

.pied__social {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem;

  margin-top: var(--espace-l);
}

/* Les icônes restent sur la première ligne */
.pied__social a:not(.pied__cta) {
  flex: 0 0 50px;
}

.pied__social a {
  display: grid;
  place-items: center;

  width: 50px;
  height: 50px;

  border: 2px solid var(--filet-inverse);
  border-radius: 30px;

  color: var(--texte-inverse);

  transition:
    background-color var(--transition),
    border-color var(--transition),
    color var(--transition);
}

.pied__social a:hover {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--texte-sur-accent);
}

.pied__social svg {
  display: block;

  width: 20px !important;
  height: 20px !important;

  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.pied__cta {
  flex-basis: 100%;

  width: 166px;
  max-width: 166px;

  margin-top: var(--espace-s);
  margin-left: 0;

  padding-inline: 1rem;

  white-space: nowrap;
}

/* =========================================================================
   TÉLÉPHONE + COURRIEL

   Alignés verticalement avec les boutons des réseaux sociaux.
   ========================================================================= */

.pied__coordonnees {
  display: flex;
  align-items: center;
  gap: 1.5rem;

  /* Alignement avec le haut des réseaux sociaux */
  margin-top: calc(64px + var(--espace-l) + 7px);

  padding: 0;
}

/* Chaque contact : icône + texte */

.pied__bloc {
  display: flex;
  align-items: center;

  gap: 1rem;

  min-width: 0;
}

/* SVG téléphone / courriel */

.pied__bloc > svg {
  display: block;
  flex: 0 0 50px;

  width: 50px !important;
  height: 50px !important;

  padding: 13px;

  border: 2px solid var(--filet-inverse);
  border-radius: 30px;

  fill: none !important;
  stroke: var(--texte-inverse);
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Texte */

.pied__bloc h3 {
  margin: 0 0 0.3rem;

  font-family: var(--police-detail);
  font-size: var(--taille-label);
  font-weight: 700;
  letter-spacing: var(--tracking-label);

  text-transform: uppercase;

  color: var(--accent-chaud);
}

.pied__bloc p {
  margin: 0;

  font-size: var(--taille-petite);
  line-height: 1.5;

  color: var(--texte-inverse);
}

.pied__bloc a {
  color: var(--texte-inverse);
  text-decoration: none;

  transition: color var(--transition);
}

.pied__bloc a:hover {
  color: var(--accent);
}

/* =========================================================================
   NAVIGATION
   ========================================================================= */

.pied__nav {
  transform: translateX(1.5rem);
}

.pied__nav ul {
  display: flex;
  flex-direction: column;

  margin: 0;
  padding: 0;

  list-style: none;
}

.pied__nav li {
  margin: 0;
  padding: 0;
}

.pied__nav a {
  display: inline-block;

  font-family: var(--police-titre);
  font-size: clamp(1.2rem, 2.8vw, 2.3rem);
  font-weight: 700;

  line-height: 1.14;
  letter-spacing: -0.02em;

  text-transform: uppercase;
  text-decoration: none;

  color: var(--creme);

  transition:
    color var(--transition),
    transform var(--transition);
}

.pied__nav a:hover {
  color: var(--accent);
  transform: translateX(10px);
}

/* =========================================================================
   BANDEAU HEURES + TERRITOIRE
   ========================================================================= */

.pied__bandeau {
  display: grid;
  grid-template-columns: 0.8fr 1.7fr;

  border-top: 1px solid var(--filet-inverse);
  border-bottom: 1px solid var(--filet-inverse);
}

/* Bloc individuel */

.pied__info {
  display: flex;
  align-items: center;

  gap: 1.25rem;

  min-width: 0;

  padding-block: 1.5rem;
}

/* Séparation verticale */

.pied__info + .pied__info {
  padding-left: clamp(2rem, 5vw, 5rem);

  border-left: 1px solid var(--filet-inverse);
}

/* SVG heures / territoire */

.pied__info > svg {
  display: block;
  flex: 0 0 34px;

  width: 34px !important;
  height: 34px !important;

  min-width: 34px;
  max-width: 34px;

  min-height: 34px;
  max-height: 34px;

  fill: none !important;
  stroke: var(--texte-inverse);

  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Texte bandeau */

.pied__info h3 {
  margin: 0 0 0.25rem;

  font-family: var(--police-detail);
  font-size: var(--taille-label);
  font-weight: 700;

  letter-spacing: var(--tracking-label);
  text-transform: uppercase;

  color: var(--accent-chaud);
}

.pied__info p {
  margin: 0;

  font-size: var(--taille-petite);
  line-height: 1.5;

  color: var(--texte-inverse);
}

/* =========================================================================
   BAS DU FOOTER
   ========================================================================= */

.pied__bas {
  display: flex;
  align-items: center;
  justify-content: space-between;

  flex-wrap: wrap;

  gap: var(--espace-s);

  padding-top: var(--espace-l);

  font-family: var(--police-detail);
  font-size: var(--taille-label);
  letter-spacing: 0.02em;

  color: var(--texte-inverse-doux);
}

.pied__legal {
  display: flex;
  flex-wrap: wrap;
  gap: var(--espace-m);
}

.pied__legal a {
  color: var(--texte-inverse-doux);
  text-decoration: none;

  transition: color var(--transition);
}

.pied__legal a:hover {
  color: var(--accent-chaud);
}

/* =========================================================================
   TABLETTE
   ========================================================================= */

@media (max-width: 1100px) {
  .pied__grille {
    grid-template-columns: 1fr 1.5fr;
  }

  .pied__nav {
    grid-column: 1 / -1;

    padding-top: var(--espace-m);
  }

  /* Le +7px manquait ici : la règle de base (plus haut) l'a, cette version
     tablette l'avait perdu en route. Résultat mesuré le 7 août 2026 — Patrik,
     capture à l'appui — téléphone/courriel calés 7 px trop haut par rapport
     aux réseaux sociaux, alors que les deux sont parfaitement alignés en
     bureau. Même formule que la règle de base, pour rester le même objet. */
  .pied__coordonnees {
    margin-top: calc(64px + var(--espace-l) + 7px);
  }
}

/* =========================================================================
   MOBILE
   ========================================================================= */

/* Un élément de grille ou de flex vaut min-width:auto par défaut : il refuse
   de devenir plus étroit que son contenu. Le courriel « info@groupeimpec.com »
   étant une chaîne insécable de vingt caractères, tout le pied de page était
   poussé 47 px hors de l'écran sur mobile. min-width:0 lève ce plancher, et
   overflow-wrap autorise la coupure du courriel s'il reste trop long. */
.pied__grille > *,
.pied__coordonnees,
.pied__contact {
  min-width: 0;
}

.pied__contact a {
  overflow-wrap: anywhere;
}

/* Le titre du hero a un plancher de 6rem dans son clamp. À 96 px,
   « IMPECCABLES » réclame 376 px pour 350 disponibles sur un écran de
   390 : le mot se coupait en plein milieu, « IMPECCABLE » puis « S » seul
   sur la ligne suivante.

   Ce palier redescend le plancher et donne plus de poids au terme relatif,
   pour que la taille suive vraiment la largeur au lieu de rester bloquée au
   minimum. Le plafond de 6rem rejoint exactement le plancher d'origine à
   700 px : la transition est continue, et le bureau n'est pas touché. */
@media (max-width: 700px) {
  :root {
    --taille-hero: clamp(3.5rem, 16vw, 6rem);
  }

  /* « Faites défiler » disparaît sur téléphone. Sur un grand écran c'est une
     invitation utile ; sur un écran étroit, où le geste de défilement va de
     soi et où la place manque, ce n'est plus que de l'encombrement. */
  .hero__defiler {
    display: none;
  }

  /* « Nous joindre » passe sous les réseaux sociaux au lieu de se ranger à
     leur droite.

     Le flex-basis:100% du bouton était déjà là, mais sans effet : le retour
     à la ligne se calcule sur la taille plafonnée par max-width, soit 166 px,
     qui tenait à côté des trois icônes. Lever ce plafond suffit à provoquer
     le passage à la ligne. */
  .pied__cta {
    width: 100%;
    max-width: none;

    margin-top: var(--espace-m);
  }
}

/* Sur les très petits écrans, le grand bouton réclamait 314 px pour 280
   disponibles : 2,75rem de rembourrage de chaque côté ne passent plus. On
   resserre plutôt que de réduire la police, pour garder la zone tactile. */
@media (max-width: 400px) {
  .bouton--l {
    padding-inline: var(--espace-m);
  }
}

/* =========================================================================
   BARRE D'ACTION MOBILE
   -------------------------------------------------------------------------
   Masquée par défaut, y compris pour l'impression et les lecteurs d'écran
   sur grand écran : elle ne doit exister qu'en portrait, sur mobile et
   tablette. Le z-index la place sous le menu mobile (200) et sous l'intro
   (99999), mais au-dessus du contenu.
   ========================================================================= */
.barre-mobile {
  display: none;
}

/* ⚠️ CORRIGÉ le 7 août 2026 — même correctif que impec/css/habillage.css :
   « orientation: portrait » excluait la barre dès que la largeur dépassait
   la hauteur. Retiré, elle apparaît maintenant sur tout écran ≤ 1024 px. */
@media (max-width: 1024px) {
  .barre-mobile {
    position: fixed;
    inset: auto 0 0;
    z-index: 150;

    display: grid;
    /* minmax(0, 1fr) et non 1fr : « 1fr » vaut « minmax(auto, 1fr) », et
       ce minimum « auto » empêche une colonne de descendre sous la largeur
       de son contenu. Le numéro étant en nowrap, sa colonne restait plus
       large que l'autre. Le zéro lève ce plancher et rend les deux moitiés
       rigoureusement égales. */
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: var(--espace-s);
    align-items: stretch;

    padding: var(--espace-s);
    /* env() protège du repère d'accueil des iPhone ; la valeur de repli
       s'applique partout ailleurs. */
    padding-bottom: calc(var(--espace-s) + env(safe-area-inset-bottom, 0px));

    background: var(--fond-sombre);
    border-top: 1px solid var(--filet-inverse);
  }

  /* Sans cette réserve, la barre masquerait la fin du pied de page. */
  body {
    padding-bottom: calc(5.5rem + env(safe-area-inset-bottom, 0px));
  }

  .barre-mobile a {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;

    /* 48 px : la cible tactile recommandée. Ne pas descendre en dessous. */
    min-height: 48px;
    padding-inline: var(--espace-m);

    font-family: var(--police-bouton);
    font-size: 1rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    white-space: nowrap;

    border-radius: var(--rayon-pilule);
  }

  .barre-mobile__tel {
    color: var(--texte-inverse);
    border: 1px solid var(--filet-inverse);
  }

  .barre-mobile__tel svg {
    width: 18px;
    height: 18px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.8;
    stroke-linecap: round;
    stroke-linejoin: round;
  }

  .barre-mobile__soumission {
    color: var(--texte-sur-accent);
    background: var(--accent);
  }

  /* Même bascule que .bouton--or et .service-btn au survol — ajoutée le
     7 août 2026, cette pilule n'en avait aucune. Copie exacte de
     habillage.css. */
  .barre-mobile__soumission:hover,
  .barre-mobile__soumission:focus-visible {
    background: var(--accent-chaud);
  }

  /* Sous 400 px le libellé entier débordait de 25 px : on ne garde que
     « Soumission ». Le nom accessible reste complet grâce à aria-label. */
  @media (max-width: 400px) {
    .barre-mobile__long {
      display: none;
    }

    /* Une fois les colonnes à parts égales, chacune ne dispose plus que de
       138 px sur un écran de 320. Le numéro en réclamait 153 : on resserre
       le rembourrage et la police plutôt que de le laisser tronquer. */
    .barre-mobile a {
      padding-inline: var(--espace-xs);
      font-size: 0.875rem;
      letter-spacing: 0.02em;
    }

    .barre-mobile__tel {
      gap: 0.35rem;
    }

    .barre-mobile__tel svg {
      width: 16px;
      height: 16px;
    }
  }

  /* Le menu mobile ouvert occupe l'écran : la barre n'a plus lieu d'être. */
  body.menu-ouvert .barre-mobile {
    display: none;
  }
}

@media (max-width: 700px) {
  .pied__grille {
    grid-template-columns: 1fr;

    gap: var(--espace-l);
  }

  /* Contacts */

  .pied__coordonnees {
    /* Le bloc est en display:flex : « grid-template-columns » n'avait donc
       aucun effet, et les contacts restaient côte à côte en débordant de
       l'écran. C'est flex-direction qui les empile. */
    flex-direction: column;
    align-items: stretch;

    gap: var(--espace-m);

    margin-top: 0;
  }

  /* Navigation */

  .pied__nav {
    grid-column: auto;

    padding-top: 0;

    /* Le décalage de 1,5rem, décoratif sur grand écran, poussait la
       navigation hors du cadre sur mobile. */
    transform: none;
  }

  .pied__nav a {
    font-size: clamp(1.5rem, 7vw, 2rem);
  }

  /* Bandeau */

  .pied__bandeau {
    grid-template-columns: 1fr;
  }

  .pied__info {
    padding-block: var(--espace-m);
  }

  .pied__info + .pied__info {
    padding-left: 0;

    border-left: 0;
    border-top: 1px solid var(--filet-inverse);
  }

  /* Bas */

  .pied__bas {
    flex-direction: column;
    align-items: flex-start;

    gap: var(--espace-m);

    padding-top: var(--espace-m);
  }

  .pied__legal {
    flex-direction: column;

    gap: var(--espace-xs);
  }
}
/* =========================================================================
   19. RESPONSIVE
   ========================================================================= */

/* Bascule vers le menu mobile (méga-menu et actions masqués) */
/* =========================================================================
   EN-TÊTE — PALIER INTERMÉDIAIRE
   -------------------------------------------------------------------------
   Voir le commentaire jumeau, bien plus long, dans impec/css/habillage.css
   (même section) et DEPLOIEMENT.md section 17 pour l'historique complet et
   le détail des mesures. Copie identique ici, comme toujours pour ce couple
   de fichiers.

   Résumé : portait à l'origine deux paliers fixes (1560 puis 1330 px).
   Patrik a signalé, capture à l'appui, que l'espace gagné au milieu de cette
   plage ne profitait à rien — tout restait déjà à sa valeur la plus petite
   bien avant le plancher réel. Refondu le 7 août 2026 : chaque propriété
   garde SA plage d'origine (1560 ou 1330 px, selon le palier qui la touchait
   avant) mais interpole maintenant avec `clamp(min, calc(pente), max)` —
   les bornes sont EXACTEMENT les anciennes valeurs des deux paliers, donc ni
   le plancher mesuré (~1180 px) ni le seuil du burger ne changent.

   Deux plages, pas une seule de 1560 à 1210 : le premier palier d'origine ne
   touchait jamais la police du bouton ni celle du téléphone (seul le second,
   sous 1330 px, s'y attaquait). Un dégradé unique les aurait fait rétrécir
   plus tôt qu'avant entre 1330 et 1560 — le contraire du but.

   « .megamenu__trigger, .megamenu__lien » ne figure plus ici : sa règle de
   base porte « font-size: 1rem !important », qui rendait ce réglage sans
   aucun effet depuis son ajout (confirmé en mesurant 16px rendu, jamais
   0.62rem). Retiré plutôt que laissé comme code mort trompeur — le plancher
   mesuré l'a toujours été avec ce texte à 16px.

   ⚠️ RÉÉQUILIBRÉ le 7 août 2026, deuxième retour de Patrik — voir le
   commentaire jumeau, bien plus long, dans impec/css/habillage.css pour le
   détail des trois demandes (bouton/numéro moins petits, liens du milieu
   qui rétrécissent à la place, flèches de menu collées à leur propre lien).
   Copie identique ici. */
@media (max-width: 1560px) {
  .entete__interieur {
    gap: clamp(0.1rem, calc(-1.283rem + 1.829vw), 0.5rem);
  }

  /* Le logo reprend le plus de place quand la barre se resserre : c'est lui
     qui varie le plus, 56 px → 32 px. Largeur calculée depuis CETTE MÊME
     expression de hauteur (× 2,805031446540881) — voir la remarque sur
     « width: auto » plus haut dans ce fichier. */
  .entete__logo img {
    height: clamp(32px, calc(-3.186rem + 6.857vw), 56px);
    width: calc(clamp(32px, calc(-3.186rem + 6.857vw), 56px) * 2.805031446540881);
  }

  /* ⚠️ .entete--solide (survol au défilement, 42px hors de cette zone) doit
     RESTER plus petit que l'état du haut — voir le commentaire jumeau dans
     impec/css/habillage.css pour le détail. × 0,75 : au raccord (1560px),
     56 × 0,75 = 42, exactement l'ancienne valeur fixe — aucune coupure. */
  .entete--solide .entete__logo img {
    height: calc(clamp(32px, calc(-3.186rem + 6.857vw), 56px) * 0.75);
    width: calc(clamp(32px, calc(-3.186rem + 6.857vw), 56px) * 0.75 * 2.805031446540881);
  }

  /* Police des liens du menu — !important nécessaire, voir le commentaire
     jumeau dans habillage.css. Absente avant le 7 août 2026 (2e passage). */
  .megamenu .megamenu__trigger,
  .megamenu .megamenu__lien {
    font-size: clamp(0.85rem, calc(0.331rem + 0.686vw), 1rem) !important;
  }

  /* Gouttière lien ↔ flèche, rétrécie en même temps que la police. */
  .megamenu .megamenu__trigger,
  .megamenu .megamenu__lien {
    gap: clamp(0.22rem, calc(-0.229rem + 0.594vw), 0.35rem);
  }

  /* Plancher relevé de 0 à 3,52px — voir le commentaire jumeau dans
     habillage.css : c'était la vraie cause des flèches trop proches du
     lien suivant. */
  .megamenu__item {
    padding-inline: clamp(0.22rem, calc(-0.402rem + 0.823vw), 0.4rem);
  }

  .entete__actions {
    gap: clamp(0.1rem, calc(-1.283rem + 1.829vw), 0.5rem);
  }

  /* Plancher relevé de 5,6px à 8px (var(--espace-xs)). */
  .entete__actions .bouton {
    padding-inline: clamp(0.5rem, calc(-1.229rem + 2.286vw), 1rem);
  }
}

/* Police du bouton et du téléphone : plage 1330 → 1210, pas 1560 → 1210 —
   voir l'explication plus haut. */
@media (max-width: 1330px) {
  /* Plancher relevé de 13,12px à 15px. */
  .entete__actions .bouton {
    font-size: clamp(0.9375rem, calc(-1.205rem + 2.833vw), 1.15rem);
  }

  /* Le téléphone ne rétrécit plus du tout dans cette zone — demandé par
     Patrik. Reste à var(--taille-petite) = 15px ; plus de règle ici. */
}

@media (max-width: 1210px) {
  .megamenu,
  .entete__actions {
    display: none;
  }
  /* En mobile : logo à gauche, hamburger à droite */
  .entete__interieur {
    display: flex;
    justify-content: space-between;
  }
  .burger {
    display: flex;
  }
}

/* Tablette */
@media (max-width: 900px) {
  .soumission__grille {
    grid-template-columns: 1fr;
    gap: var(--espace-l);
  }
  .services__grille {
    grid-template-columns: 1fr 1fr;
  }
  .procede__etape {
    border-left: 0;
    border-top: 1px solid var(--filet);
  }
  .procede__etape:first-child {
    border-top: 0;
  }
}

/* Mobile */
@media (max-width: 640px) {
  .formulaire__rangee {
    grid-template-columns: 1fr;
  }
  .formulaire {
    padding: var(--espace-m);
  }
  .services__grille {
    grid-template-columns: 1fr;
  }
  .realisations__galerie {
    grid-template-columns: 1fr;
  }
  .realisations__photo--grande {
    grid-row: auto;
    aspect-ratio: 16 / 10;
  }
  .secteurs__desc {
    max-height: none;
    opacity: 1;
    margin-top: 0.5rem;
  } /* toujours visible sur mobile */
}

/* =========================================================================
   19b. RÉVÉLATION AU DÉFILEMENT
   ------------------------------------------------------------------------
   La classe .reveal est posée par js/main-v3.js, jamais dans le HTML :
   sans JS, rien n'est masqué et la page reste entièrement lisible.
   Les éléments visés sont des CONTENEURS (rangées, grilles), jamais les
   cartes elles-mêmes — celles-ci ont déjà un transform au survol qui
   entrerait en conflit.
   ========================================================================= */
.reveal {
  opacity: 0;
  transform: translateY(14px);
  transition:
    opacity 520ms cubic-bezier(0.2, 0.6, 0.2, 1),
    transform 520ms cubic-bezier(0.2, 0.6, 0.2, 1);
  transition-delay: var(--reveal-delai, 0ms);
}
.reveal.est-visible {
  opacity: 1;
  transform: none;
}

/* =========================================================================
   20. PRÉFÉRENCE « MOUVEMENT RÉDUIT »
   ========================================================================= */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  /* Rien ne doit rester masqué si le mouvement est désactivé */
  .reveal {
    opacity: 1;
    transform: none;
  }
}

/* =========================================================================
   21. BLOC SOUDÉ : SERVICES + AUTRES SERVICES
   ------------------------------------------------------------------------
   Intention : les deux ne forment qu'une seule section, « Autres services »
   étant une sous-section de « Nos services ». Pour que ça se lise vraiment,
   il faut les trois à la fois :
     1. une respiration interne réduite (--espace-sous-section)
     2. le MÊME fond des deux côtés — sinon le changement de couleur
        recrée une frontière et annule le point 1
     3. un titre de sous-section plus petit que les titres de section
   Le fond commun est le bleu brume : l'alternance de la page reste juste
   (slogan brume · preuve marine · SERVICES brume · procédé crème · …).
   ========================================================================= */
.services,
.autres {
  background: var(--fond-alterne);
}
.services {
  padding-block: var(--espace-section) var(--espace-sous-section);
}
.autres {
  padding-block: var(--espace-sous-section) var(--espace-section);
}

/* Titre de sous-section : un cran sous .section__titre */
.autres .section__titre {
  font-size: var(--taille-bandeau);
}

/* =========================================================================
   22. EN-TÊTE PENDANT L'OUVERTURE DU MENU
   ------------------------------------------------------------------------
   La barre prend le crème du panneau : les deux ne forment plus qu'un seul
   bloc, sans la couture qu'imposait le blanc translucide de l'en-tête.
   Le logo ne change pas — le fond reste clair, la version couleur tient.
   Placé en toute fin de feuille pour gagner sur le bloc responsive.
   ========================================================================= */
.entete--menu,
.entete--solide.entete--menu {
  color: var(--texte);
  background: var(--fond-page);
  backdrop-filter: none;
  border-bottom-color: transparent;
}