@charset "UTF-8";
/* =========================================================================
   GORDAN POWER SARL - Design system
   -------------------------------------------------------------------------
   Identite construite autour du logo officiel, qui n'est jamais modifie.
   Les deux couleurs de marque sont echantillonnees directement sur le
   fichier logo : bleu marine #0A1E45 et or #D19A0C.

   Systeme de formes : angles vifs (rayon 2 a 3 px) sur tout le site, en
   echo au caractere technique du metier. Aucun coin arrondi generique.

   Dosage couleur : le bleu et le blanc portent la structure, les gris
   portent le texte secondaire, l'or reste un accent (filets, pictogrammes,
   mots-cles). L'or n'est jamais utilise comme couleur de texte courant sur
   fond clair : son contraste y est insuffisant.
   ========================================================================= */

/* -------------------------------------------------------------------------
   1. Polices auto-hebergees
   ------------------------------------------------------------------------- */
@font-face {
  font-family: 'Archivo';
  src: url('../fonts/archivo-400.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Archivo';
  src: url('../fonts/archivo-500.woff2') format('woff2');
  font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Archivo';
  src: url('../fonts/archivo-600.woff2') format('woff2');
  font-weight: 600; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Archivo';
  src: url('../fonts/archivo-700.woff2') format('woff2');
  font-weight: 700; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Plex Mono';
  src: url('../fonts/plexmono-500.woff2') format('woff2');
  font-weight: 500; font-style: normal; font-display: swap;
}

/* -------------------------------------------------------------------------
   2. Jetons de conception
   ------------------------------------------------------------------------- */
:root {
  /* Marque, echantillonnee sur le logo */
  --navy-950: #04102B;
  --navy-900: #071737;
  --navy-800: #0A1E45;
  --navy-700: #123059;
  --navy-600: #1B4076;

  /* Trois valeurs d'or, une par usage :
     600 est la seule employee pour du texte ou un pictogramme sur fond
     clair. Elle est volontairement foncee : a #A87D08 le contraste tombait
     a 3,75:1 sur blanc, sous le seuil WCAG AA de 4,5:1 pour du petit texte.
     500 sert aux filets et aux aplats, 400 aux fonds bleus. */
  --gold-600: #8A6605;
  --gold-500: #D19A0C;
  --gold-400: #E9B321;

  /* Neutres froids */
  --ink:       #131A29;
  --ink-soft:  #3B455C;
  --slate:     #5A6580;
  --line:      #DEE4EE;
  --line-soft: #EBEFF5;
  --surface:   #F4F6FA;
  --surface-2: #EAEEF5;
  --white:     #FFFFFF;

  /* Etats */
  --ok:    #1F7A3D;
  --warn:  #A66A00;
  --error: #B3261E;

  /* Vert WhatsApp, assombri pour qu'un libelle blanc y reste lisible.
     Declare une seule fois : le bouton flottant et le pictogramme des
     formulaires s'y referent tous deux. */
  --wa: #107A3D;

  /* Roles semantiques - mode clair */
  --bg:            var(--white);
  --bg-alt:        var(--surface);
  --bg-band:       var(--navy-800);
  --bg-band-deep:  var(--navy-950);
  --text:          var(--ink);
  --text-2:        var(--slate);
  --text-on-band:  #EEF2F9;
  --text-on-band-2:#A8B6CE;
  --border:        var(--line);
  --border-band:   rgba(255,255,255,.16);
  --accent:        var(--gold-500);
  --accent-strong: var(--gold-600);
  --card-bg:       var(--white);

  /* Formes, ombres, rythme */
  --r-sm: 2px;
  --r-md: 3px;
  --shadow-sm: 0 1px 2px rgba(10,30,69,.06), 0 2px 8px rgba(10,30,69,.05);
  --shadow-md: 0 2px 6px rgba(10,30,69,.07), 0 12px 32px rgba(10,30,69,.09);

  --container: 1240px;
  --gutter: clamp(1.25rem, .8rem + 1.6vw, 2.5rem);
  --section-y: clamp(3.75rem, 2.6rem + 4.2vw, 6.75rem);

  /* Hauteur de l'en-tete collant. Declaree une seule fois : la mise en page de
     l'en-tete, le decalage des ancres et le menu mobile s'y referent tous.
     Redefinie sous 1024 px, ou l'en-tete est plus bas. */
  --header-h: 72px;

  /* Zones sures des appareils a encoche et a barre gestuelle. Valent 0 partout
     ailleurs : la regle est sans effet sur un ecran classique. */
  --safe-t: env(safe-area-inset-top, 0px);
  --safe-r: env(safe-area-inset-right, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-l: env(safe-area-inset-left, 0px);

  --ease: cubic-bezier(.16, 1, .3, 1);
  --dur: .38s;

  /* Couches */
  --z-band: 1;
  --z-header: 100;
  --z-menu: 110;
  --z-fab: 90;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg:            #060D1C;
    --bg-alt:        #0A1428;
    --bg-band:       #0C1A38;
    --bg-band-deep:  #050B18;
    /* Sans cette ligne, --surface-2 gardait sa valeur claire (#EAEEF5) : la
       regle img { background: var(--surface-2) } dessinait alors une plaque
       gris clair derriere chaque image pendant son chargement, sur fond
       sombre. Le defaut se voyait surtout sur les logos a fond transparent. */
    --surface-2:     #131F3A;
    --text:          #E7ECF5;
    --text-2:        #9DAAC4;
    --text-on-band:  #EEF2F9;
    --text-on-band-2:#A8B6CE;
    --border:        #1D2A46;
    --border-band:   rgba(255,255,255,.14);
    --card-bg:       #0B142A;
    --accent:        var(--gold-400);
    --accent-strong: var(--gold-400);
    --shadow-sm: 0 1px 2px rgba(0,0,0,.4);
    --shadow-md: 0 12px 32px rgba(0,0,0,.45);
  }
}

/* -------------------------------------------------------------------------
   3. Base
   ------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Cale sur la hauteur reelle de l'en-tete collant, declaree en --header-h,
     plutot que sur une valeur fixe de 92 px qui decalait chaque ancre de 20 a
     28 px selon le format d'ecran. */
  scroll-padding-top: calc(var(--header-h) + .75rem);
  /* Le debordement horizontal se maitrise ici, sur l'element racine.
     Sur body, overflow-x: hidden forcait implicitement overflow-y: auto et
     creait un SECOND conteneur de defilement : source connue de sauts et de
     barres d'URL qui se replient mal sur Chrome Android et Safari iOS.
     overflow-x: clip coupe sans creer de conteneur de defilement ; le repli
     hidden ne sert qu'aux navigateurs qui ignorent clip. */
  overflow-x: hidden;
}
@supports (overflow: clip) {
  html { overflow-x: clip; }
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: 'Archivo', system-ui, -apple-system, 'Segoe UI', sans-serif;
  font-size: 1rem;
  font-weight: 400;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
@media (min-width: 768px) { body { font-size: 1.0625rem; } }

img, svg, video { max-width: 100%; height: auto; display: block; }
img { background: var(--surface-2); }

/* La regle ci-dessus impose display:block a tout svg, y compris au sprite
   d'icones marque hidden. Une feuille de style d'auteur primant sur celle du
   navigateur, le sprite se remettait a occuper 300 x 150 px en haut de page.
   Cette regle retablit le comportement attendu de l'attribut hidden. */
[hidden] { display: none !important; }

h1, h2, h3, h4 {
  margin: 0;
  font-weight: 700;
  line-height: 1.12;
  letter-spacing: -.02em;
  text-wrap: balance;
}
p { margin: 0; text-wrap: pretty; }
ul, ol { margin: 0; padding: 0; }
li { list-style: none; }

a { color: inherit; text-decoration: none; }

:focus-visible {
  outline: 3px solid var(--gold-500);
  outline-offset: 3px;
  border-radius: var(--r-sm);
}

::selection { background: var(--navy-800); color: #fff; }

.skip-link {
  position: absolute; left: 0; top: -100px;
  z-index: 200;
  padding: .85rem 1.25rem;
  background: var(--navy-800); color: #fff;
  font-weight: 600;
}
.skip-link:focus { top: 0; }

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

/* -------------------------------------------------------------------------
   4. Mise en page
   ------------------------------------------------------------------------- */
.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  /* Les marges laterales integrent les zones sures : en mode paysage sur un
     appareil a encoche, le texte ne passe plus sous la decoupe. */
  padding-left: calc(var(--gutter) + var(--safe-l));
  padding-right: calc(var(--gutter) + var(--safe-r));
}
.container--narrow { max-width: 860px; }

.section { padding-block: var(--section-y); }
.section--tight { padding-block: calc(var(--section-y) * .62); }

.band--surface { background: var(--bg-alt); }
.band--navy {
  position: relative;
  background: var(--bg-band);
  color: var(--text-on-band);
  z-index: var(--z-band);
}
.band--navy h1, .band--navy h2, .band--navy h3 { color: #fff; }
.band--navy p { color: var(--text-on-band-2); }
.band--deep { background: var(--bg-band-deep); }

.icon {
  width: 1em; height: 1em;
  flex: none;
  fill: currentColor;
  vertical-align: -.125em;
}

/* -------------------------------------------------------------------------
   5. Typographie de composition
   ------------------------------------------------------------------------- */
.display {
  font-size: clamp(2.05rem, 1.35rem + 2.9vw, 3.5rem);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -.028em;
}
.h2 {
  font-size: clamp(1.6rem, 1.15rem + 1.9vw, 2.4rem);
  font-weight: 700;
  letter-spacing: -.022em;
}
.h3 {
  font-size: clamp(1.15rem, 1.02rem + .5vw, 1.35rem);
  font-weight: 600;
  letter-spacing: -.012em;
  line-height: 1.3;
}
.lead {
  font-size: clamp(1.02rem, .96rem + .38vw, 1.2rem);
  line-height: 1.6;
  color: var(--text-2);
  max-width: 62ch;
}
.band--navy .lead { color: var(--text-on-band-2); }
.prose { max-width: 68ch; color: var(--text-2); }
.prose p + p { margin-top: 1.1em; }

/* Filet or : signature graphique reprise du soulignement du mot POWER
   dans le logo. Il marque les titres de niveau superieur. */
.rule-gold {
  width: 56px; height: 3px;
  background: var(--gold-500);
  border: 0;
  /* Le filet suit toujours un titre : sa marge haute fait partie de la regle,
     elle n'a pas a etre repetee sur chaque balise. */
  margin: 1.35rem 0;
}
.rule-gold--center { margin-inline: auto; }

/* Micro-libelle. Volontairement rare : au plus un par groupe de sections. */
.eyebrow {
  display: inline-block;
  font-family: 'Plex Mono', ui-monospace, monospace;
  font-size: .72rem;
  font-weight: 500;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--gold-600);
  margin-bottom: .9rem;
}
.band--navy .eyebrow { color: var(--gold-400); }
/* L'or 600 est calibre pour du texte sur fond CLAIR. En theme sombre, il
   tombait a 3,68:1 sur le fond du site, sous le seuil de 4,5:1 exige pour un
   texte de cette taille. L'or 400 y atteint 10,1:1. */
@media (prefers-color-scheme: dark) { .eyebrow { color: var(--gold-400); } }

.section-head { margin-bottom: clamp(2rem, 1.4rem + 1.8vw, 3.25rem); }
.section-head .lead { margin-top: 1rem; }

/* -------------------------------------------------------------------------
   6. Boutons
   ------------------------------------------------------------------------- */
.btn {
  --btn-bg: var(--navy-800);
  --btn-fg: #fff;
  --btn-bd: var(--navy-800);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .6rem;
  padding: .85rem 1.5rem;
  min-height: 48px;
  border: 1.5px solid var(--btn-bd);
  border-radius: var(--r-sm);
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-family: inherit;
  font-size: .95rem;
  font-weight: 600;
  letter-spacing: .002em;
  line-height: 1.15;
  text-align: center;
  white-space: nowrap;
  cursor: pointer;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease),
              color var(--dur) var(--ease), transform .12s ease;
}
.btn .icon { font-size: 1.15em; }
.btn:hover { --btn-bg: var(--navy-700); --btn-bd: var(--navy-700); }
.btn:active { transform: translateY(1px); }

.btn--gold {
  --btn-bg: var(--gold-500);
  --btn-fg: var(--navy-950);
  --btn-bd: var(--gold-500);
}
.btn--gold:hover { --btn-bg: var(--gold-400); --btn-bd: var(--gold-400); }

/* Contour sur fond clair */
.btn--outline {
  --btn-bg: transparent;
  --btn-fg: var(--navy-800);
  --btn-bd: var(--navy-800);
}
.btn--outline:hover { --btn-bg: var(--navy-800); --btn-fg: #fff; }
@media (prefers-color-scheme: dark) {
  .btn--outline { --btn-fg: #DCE4F2; --btn-bd: #46567A; }
  .btn--outline:hover { --btn-bg: #17263F; --btn-fg: #fff; --btn-bd: #17263F; }
}

/* Contour sur bandeau bleu */
.btn--onband {
  --btn-bg: transparent;
  --btn-fg: #fff;
  --btn-bd: rgba(255,255,255,.5);
}
.btn--onband:hover { --btn-bg: rgba(255,255,255,.12); --btn-bd: #fff; }

.btn--light {
  --btn-bg: #fff;
  --btn-fg: var(--navy-800);
  --btn-bd: #fff;
}
.btn--light:hover { --btn-bg: #E9EEF7; --btn-bd: #E9EEF7; }

/* Variante WhatsApp. Le vert est celui, assombri, déjà retenu pour le bouton
   flottant : le libellé blanc y atteint 5,42:1, et la couleur reste la même
   dans les deux thèmes, comme la marque WhatsApp elle-même. */
.btn--wa {
  --btn-bg: var(--wa);
  --btn-fg: #fff;
  --btn-bd: var(--wa);
}
.btn--wa:hover { --btn-bg: #0C6231; --btn-bd: #0C6231; }

.btn--wide { width: 100%; }
.btn--sm { min-height: 42px; padding: .6rem 1.1rem; font-size: .875rem; }

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: .75rem;
}

/* Sous 520 px, la largeur utile descend sous celle de certains libelles.
   Le bouton passe alors sur deux lignes : c'est preferable a un libelle
   tronque ou a une page qui defile horizontalement. */
@media (max-width: 520px) {
  .btn { white-space: normal; }
}

/* Un element de grille a par defaut min-width:auto : son contenu le plus
   large impose la largeur de la piste, ce qui peut faire deborder toute la
   page. On neutralise ce comportement partout ou l'on met en grille. */
.split > *,
.form > *,
.form-grid > *,
.groups > *,
.grid > *,
.process > *,
.project-block__head > *,
.footer-grid > * { min-width: 0; }

/* Lien flechee discret */
.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  font-weight: 600;
  font-size: .95rem;
  color: var(--navy-800);
  border-bottom: 1.5px solid var(--gold-500);
  padding-bottom: 2px;
  transition: gap var(--dur) var(--ease), color var(--dur) var(--ease);
}
.link-arrow:hover { gap: .75rem; color: var(--navy-600); }
.band--navy .link-arrow { color: #fff; }
@media (prefers-color-scheme: dark) { .link-arrow { color: #DCE4F2; } }

/* -------------------------------------------------------------------------
   7. En-tete et navigation
   ------------------------------------------------------------------------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: var(--z-header);
  background: color-mix(in srgb, var(--bg) 92%, transparent);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--border);
}
@supports not (backdrop-filter: blur(4px)) {
  .site-header { background: var(--bg); }
}

.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.25rem;
  height: var(--header-h);
}
@media (max-width: 1023px) { :root { --header-h: 64px; } }

.brand { display: flex; align-items: center; gap: .65rem; flex: none; }
/* La plaque blanche qui encadrait le symbole a ete retiree. Elle n'etait pas
   un parti pris graphique : elle masquait le fond blanc opaque du fichier
   PNG, herite du logo source en JPEG. Le symbole est desormais detoure
   (voir tools\build-brand-assets.ps1), il se pose donc directement sur le
   fond de l'en-tete, clair comme sombre. */
.brand__mark { display: block; flex: none; }
.brand__mark img { height: 40px; width: 40px; background: none; }
@media (max-width: 1023px) { .brand__mark img { height: 34px; width: 34px; } }

.brand__text { display: flex; flex-direction: column; gap: 2px; line-height: 1; }
.brand__text strong {
  font-size: 1.02rem;
  font-weight: 700;
  letter-spacing: -.012em;
  color: var(--navy-800);
}
.brand__text > span {
  font-family: 'Plex Mono', ui-monospace, monospace;
  font-size: .58rem;
  font-weight: 500;
  letter-spacing: .3em;
  color: var(--gold-600);
}
/* Le nom de l'entreprise est l'element le plus important de l'en-tete : il ne
   disparait que sur les ecrans vraiment etroits, ou il ne tiendrait plus. */
@media (max-width: 330px) { .brand__text { display: none; } }
@media (prefers-color-scheme: dark) {
  .brand__text strong { color: #fff; }
  .brand__text > span { color: var(--gold-400); }
}

.nav { display: none; }
@media (min-width: 1024px) {
  .nav {
    display: flex;
    align-items: center;
    gap: clamp(.3rem, -.4rem + 1.1vw, 1rem);
    margin-left: auto;
  }
}
.nav__link {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  padding: .5rem .55rem;
  font-size: .925rem;
  font-weight: 500;
  color: var(--text);
  white-space: nowrap;
  border-bottom: 2px solid transparent;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.nav__link:hover { color: var(--navy-700); border-bottom-color: var(--gold-500); }
.nav__link[aria-current="page"] { color: var(--navy-800); border-bottom-color: var(--gold-500); }
@media (prefers-color-scheme: dark) {
  .nav__link:hover, .nav__link[aria-current="page"] { color: #fff; }
}

.header-actions { display: flex; align-items: center; gap: .6rem; }
@media (max-width: 1023px) { .header-actions .btn { display: none; } }

/* Le numéro dans l’en-tête n’apparaît qu’à partir de 1200 px. Entre 1024 et
   1200 px, la navigation complète et deux boutons ne tiennent pas sur une
   ligne : le second passerait à la ligne et casserait la hauteur de
   l’en-tête. En dessous de 1024 px, la barre d’actions du bas d’écran porte
   déjà l’appel. */
.header-call { display: none; }
@media (min-width: 1200px) { .header-call { display: inline-flex; } }

/* Sous-menu Services */
.has-sub { position: relative; }
.sub {
  position: absolute;
  top: calc(100% + 10px);
  left: 50%;
  translate: -50% 0;
  min-width: 290px;
  padding: .5rem;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-top: 3px solid var(--gold-500);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-md);
  opacity: 0;
  visibility: hidden;
  translate: -50% 8px;
  transition: opacity .22s var(--ease), translate .22s var(--ease), visibility .22s;
}
.has-sub:hover .sub,
.has-sub:focus-within .sub {
  opacity: 1; visibility: visible; translate: -50% 0;
}
@media (prefers-reduced-motion: reduce) { .sub { transition: none; } }
.sub__link {
  display: flex;
  align-items: center;
  gap: .7rem;
  padding: .6rem .7rem;
  font-size: .9rem;
  font-weight: 500;
  border-radius: var(--r-sm);
  transition: background var(--dur) var(--ease);
}
.sub__link:hover { background: var(--bg-alt); }
.sub__link .icon { font-size: 1.15rem; color: var(--gold-600); }
@media (prefers-color-scheme: dark) { .sub__link .icon { color: var(--gold-400); } }

/* Bouton menu mobile */
.menu-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 46px; height: 46px;
  padding: 0;
  background: transparent;
  border: 1.5px solid var(--border);
  border-radius: var(--r-sm);
  color: var(--text);
  font-size: 1.4rem;
  cursor: pointer;
}
@media (min-width: 1024px) { .menu-toggle { display: none; } }

/* Menu mobile */
.mobile-menu {
  position: fixed;
  inset: 0;
  z-index: var(--z-menu);
  display: flex;
  flex-direction: column;
  background: var(--bg);
  visibility: hidden;
  opacity: 0;
  transition: opacity .28s var(--ease), visibility .28s;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.mobile-menu[data-open="true"] { visibility: visible; opacity: 1; }
@media (prefers-reduced-motion: reduce) { .mobile-menu { transition: none; } }

.mobile-menu__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 64px;
  padding-inline: var(--gutter);
  border-bottom: 1px solid var(--border);
  flex: none;
}
.mobile-menu__body { padding: 1.25rem var(--gutter) 2rem; }
.mobile-menu__link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: .95rem 0;
  font-size: 1.05rem;
  font-weight: 600;
  border-bottom: 1px solid var(--border);
}
.mobile-menu__link .icon { color: var(--gold-600); font-size: 1.1rem; }
.mobile-menu__group { padding: .35rem 0 .6rem 1rem; border-left: 2px solid var(--gold-500); margin: .5rem 0 .5rem .1rem; }
.mobile-menu__group a {
  display: block;
  padding: .5rem 0;
  font-size: .95rem;
  color: var(--text-2);
}
.mobile-menu__cta { display: grid; gap: .65rem; margin-top: 1.5rem; }

body[data-menu-open="true"] { overflow: hidden; }

/* -------------------------------------------------------------------------
   8. Fil d'Ariane
   ------------------------------------------------------------------------- */
.breadcrumb {
  padding-block: .9rem;
  font-size: .82rem;
  color: var(--text-2);
  border-bottom: 1px solid var(--border);
}
.breadcrumb ol { display: flex; flex-wrap: wrap; align-items: center; gap: .45rem; }
.breadcrumb .icon { font-size: .8rem; opacity: .55; }
.breadcrumb a:hover { color: var(--navy-700); text-decoration: underline; }
.breadcrumb [aria-current="page"] { color: var(--text); font-weight: 500; }

/* -------------------------------------------------------------------------
   9. Hero
   ------------------------------------------------------------------------- */
.hero {
  position: relative;
  background: var(--bg-band);
  color: var(--text-on-band);
  overflow: hidden;
}
/* -------------------------------------------------------------------------
   Hero illustre : la photo occupe toute la largeur, le texte passe dessus.

   La photo n'est pas un fond CSS mais un vrai <img> : cela permet de servir
   trois largeurs selon l'ecran et une declinaison WebP, ce qu'une propriete
   background-image ne sait pas faire. Elle est sortie du flux et calee sur
   toute la section.

   La lisibilite ne repose jamais sur la photo elle-meme - une photo claire,
   sombre ou chargee donnerait le meme resultat - mais sur les deux voiles
   posees par-dessus. C'est ce qui permet de changer d'image sans retoucher
   quoi que ce soit.
   ------------------------------------------------------------------------- */
/* La photo est sortie du flux : c'est le TEXTE qui donne sa hauteur au hero,
   et la photo qui s'y adapte. Laissee dans le flux, l'image imposait sa propre
   hauteur intrinseque - 1 707 px pour une photo verticale - et le hero
   devenait deux fois plus haut que l'ecran, boutons rejetes sous le pli.
   Meme principe que .page-hero--image, plus bas dans cette feuille. */
.hero--image { position: relative; overflow: hidden; }
.hero--image > picture {
  position: absolute;
  inset: 0;
  display: block;
}
.hero__bg {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Cadrage sur le haut du sujet : le bas de la photo montre le sol, le haut
     montre le geste et l'appareillage. */
  object-position: 50% 28%;
  background: var(--navy-900);
}

/* Voile principal, horizontal : opaque a gauche ou se trouve le texte, ouvert
   a droite ou la photo reste lisible. */
.hero--image > picture::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(100deg,
      var(--navy-950) 0%,
      color-mix(in srgb, var(--navy-950) 88%, transparent) 38%,
      color-mix(in srgb, var(--navy-800) 55%, transparent) 72%,
      color-mix(in srgb, var(--navy-800) 35%, transparent) 100%),
    /* Second voile, vertical et leger : il assoit le bas de l'image sur la
       bande de choix d'intention qui suit, et evite une cassure nette. */
    linear-gradient(to bottom,
      color-mix(in srgb, var(--navy-950) 30%, transparent) 0%,
      transparent 40%,
      color-mix(in srgb, var(--navy-950) 45%, transparent) 100%);
}

/* Sur telephone, la photo est vue en bande verticale etroite et le texte
   couvre toute la largeur : le voile horizontal ne suffit plus, il devient
   un aplat quasi uniforme. */
@media (max-width: 767px) {
  .hero--image > picture::after {
    background:
      linear-gradient(to bottom,
        color-mix(in srgb, var(--navy-950) 82%, transparent) 0%,
        color-mix(in srgb, var(--navy-950) 74%, transparent) 55%,
        color-mix(in srgb, var(--navy-950) 88%, transparent) 100%);
  }
  .hero__bg { object-position: 50% 22%; }
}

/* Sur un bandeau uni, l'accroche en #B9C6DC atteint 9,5:1. Posee sur une
   photo, elle tombe a 4,7:1 - conforme, mais sans marge : une image plus
   claire la ferait passer sous le seuil. On l'eclaircit donc uniquement dans
   le hero illustre, pour que le remplacement de la photo reste sans
   consequence sur la lisibilite. Mesure apres correction : 6,2:1. */
.hero--image .hero__lead { color: #CBD6E6; }

.hero__inner {
  position: relative;
  z-index: 2;
  display: grid;
  align-content: center;
  padding-block: clamp(3rem, 2rem + 5vw, 7rem);
  /* Le texte ne s'etale pas sur toute la largeur : au-dela, la photo
     disparait entierement derriere lui et le hero perd son sujet. */
  max-width: min(100%, 62rem);
}
@media (min-width: 900px) {
  .hero__inner > div { max-width: 34rem; }
}
/* Le titre du hero est volontairement plus contenu que .display : mesure
   faite, il doit tenir en trois lignes au maximum de 900 a 1920 px. */
.hero__title {
  color: #fff;
  font-size: clamp(1.85rem, 1.15rem + 2.1vw, 2.8rem);
}
.hero__title em {
  font-style: normal;
  color: var(--gold-400);
}
.hero__lead {
  margin-top: 1.35rem;
  color: #B9C6DC;
  font-size: clamp(1rem, .95rem + .35vw, 1.15rem);
  max-width: 52ch;
}
.hero__cta { margin-top: 2rem; }

/* .hero__grid et .hero__media, qui portaient le hero en deux colonnes avec sa
   photo en vignette, ont ete retires : plus aucune page ne les utilise depuis
   le passage a la photo pleine largeur. Ils sont recuperables dans
   l'historique du depot si la composition precedente devait revenir. */

/* Bande de choix d'intention, directement sous le hero */
.intent-bar { border-bottom: 1px solid var(--border); background: var(--bg-alt); }
.intent-bar__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
@media (min-width: 1024px) { .intent-bar__grid { grid-template-columns: repeat(6, minmax(0, 1fr)); } }
.intent {
  display: flex;
  flex-direction: column;
  gap: .45rem;
  padding: 1rem .75rem;
  border-right: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  font-size: .875rem;
  font-weight: 600;
  color: var(--text);
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.intent:hover { background: var(--card-bg); color: var(--navy-700); }
.intent .icon { font-size: 1.5rem; color: var(--gold-600); }
@media (prefers-color-scheme: dark) {
  .intent .icon { color: var(--gold-400); }
  .intent:hover { color: #fff; }
}
@media (min-width: 1024px) { .intent-bar__grid > :last-child { border-right: 0; } }

/* -------------------------------------------------------------------------
   9 bis. En-tete des pages interieures
   ------------------------------------------------------------------------- */
.page-hero {
  position: relative;
  background: var(--bg-band);
  color: var(--text-on-band);
  overflow: hidden;
}
/* Variante illustree : la photo reste lisible sous un voile bleu profond.
   L'image est un vrai <img> et non un fond CSS. Passer par une variable
   personnalisee resoudrait l'URL par rapport a la feuille de style et non
   par rapport a la page, ce qui casse les chemins relatifs. Un <img> permet
   en outre de servir des variantes selon la largeur d'ecran. */
.page-hero__bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: .28;
  background: none;
}
.page-hero--image::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(100deg, var(--bg-band) 22%, rgba(10,30,69,.7) 100%);
}
.page-hero__inner {
  position: relative;
  z-index: 2;
  padding-block: clamp(2.5rem, 1.9rem + 2.6vw, 4.25rem);
  max-width: 46rem;
}
.page-hero h1 {
  color: #fff;
  font-size: clamp(1.85rem, 1.35rem + 2vw, 2.85rem);
}
.page-hero .lead { color: #B9C6DC; margin-top: 1.15rem; }
.page-hero .btn-row { margin-top: 1.9rem; }

/* -------------------------------------------------------------------------
   9 ter. Panneaux et regroupements de prestations
   ------------------------------------------------------------------------- */
.panel {
  padding: clamp(1.4rem, 1.1rem + 1.1vw, 2.15rem);
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-top: 3px solid var(--gold-500);
  border-radius: var(--r-md);
}
.band--navy .panel {
  background: rgba(255,255,255,.05);
  border-color: var(--border-band);
  border-top-color: var(--gold-400);
}

/* Prestations regroupees par famille plutot qu'en longue liste a puces */
.groups {
  display: grid;
  gap: clamp(1.15rem, .9rem + 1vw, 1.75rem);
  grid-template-columns: minmax(0,1fr);
}
@media (min-width: 700px)  { .groups { grid-template-columns: repeat(2, minmax(0,1fr)); } }
@media (min-width: 1100px) { .groups--3 { grid-template-columns: repeat(3, minmax(0,1fr)); } }

.group h3 {
  display: flex;
  align-items: center;
  gap: .6rem;
  font-size: 1rem;
  margin-bottom: .9rem;
  padding-bottom: .7rem;
  border-bottom: 2px solid var(--gold-500);
}
.group h3 .icon { font-size: 1.3rem; color: var(--gold-600); }
.band--navy .group h3 .icon { color: var(--gold-400); }
@media (prefers-color-scheme: dark) { .group h3 .icon { color: var(--gold-400); } }
.group ul { display: grid; gap: .45rem; }
.group li { font-size: .92rem; color: var(--text-2); padding-left: 1rem; position: relative; }
.group li::before {
  content: "";
  position: absolute;
  left: 0; top: .72em;
  width: 5px; height: 1px;
  background: var(--gold-500);
}
.band--navy .group li { color: var(--text-on-band-2); }

/* Pages soeurs, en fin de page de service */
.related {
  display: grid;
  gap: 1px;
  background: var(--border);
  border: 1px solid var(--border);
  grid-template-columns: minmax(0,1fr);
}
@media (min-width: 640px)  { .related { grid-template-columns: repeat(2, minmax(0,1fr)); } }
@media (min-width: 1024px) { .related { grid-template-columns: repeat(4, minmax(0,1fr)); } }
.related a {
  display: flex;
  align-items: center;
  gap: .7rem;
  padding: 1.1rem 1.15rem;
  background: var(--card-bg);
  font-size: .92rem;
  font-weight: 600;
  transition: background var(--dur) var(--ease);
}
.related a:hover { background: var(--bg-alt); }
.related .icon { font-size: 1.25rem; color: var(--gold-600); flex: none; }
@media (prefers-color-scheme: dark) { .related .icon { color: var(--gold-400); } }

/* -------------------------------------------------------------------------
   10. Cartes de poles
   ------------------------------------------------------------------------- */
.grid { display: grid; gap: 1px; }
.grid--poles {
  background: var(--border);
  border: 1px solid var(--border);
  grid-template-columns: minmax(0, 1fr);
}
@media (min-width: 640px)  { .grid--poles { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1024px) { .grid--poles { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.pole {
  display: flex;
  flex-direction: column;
  gap: .75rem;
  padding: clamp(1.4rem, 1.1rem + 1vw, 2.1rem);
  background: var(--card-bg);
  transition: background var(--dur) var(--ease);
}
.pole:hover { background: var(--bg-alt); }

/* Illustration en tête de carte.

   La carte est une boîte à padding. Sans les marges négatives ci-dessous,
   l’image s’arrêterait avant les bords et se lirait comme une vignette posée
   dans la carte, au lieu d’en être l’en-tête. La marge reprend exactement la
   valeur du padding de .pole : si l’une change, l’autre doit suivre. */
.pole__media {
  margin: calc(-1 * clamp(1.4rem, 1.1rem + 1vw, 2.1rem));
  margin-bottom: .4rem;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  background: var(--bg-alt);
}
.pole__media img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
  transition: scale .5s var(--ease);
}
.pole:hover .pole__media img { scale: 1.04; }
@media (prefers-reduced-motion: reduce) {
  .pole:hover .pole__media img { scale: 1; }
}
.pole__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 46px; height: 46px;
  background: var(--navy-800);
  color: var(--gold-400);
  border-radius: var(--r-sm);
  font-size: 1.5rem;
  margin-bottom: .35rem;
}
.pole__num {
  font-family: 'Plex Mono', ui-monospace, monospace;
  font-size: .72rem;
  letter-spacing: .14em;
  color: var(--text-2);
}
.pole p { color: var(--text-2); font-size: .945rem; }
.pole .link-arrow { margin-top: auto; padding-top: 1rem; align-self: flex-start; }

/* Sur telephone les six cartes s'empilent : chaque pixel economise ici se
   multiplie par six. Le pictogramme passe sur la ligne du titre plutot que
   de consommer une ligne a lui seul. */
@media (max-width: 639px) {
  .pole {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    gap: .35rem .85rem;
    padding: 1.15rem 1.25rem 1.3rem;
  }
  /* L’illustration occupe toute la largeur, au-dessus de la ligne
     pictogramme + titre, et annule le padding de la carte pour aller d’un
     bord à l’autre. La valeur reprend exactement le padding ci-dessus : si
     l’un change, l’autre doit suivre. */
  .pole__media {
    grid-column: 1 / -1;
    margin: -1.15rem -1.25rem .2rem;
    aspect-ratio: 2 / 1;
  }

  /* Aucune ligne n’est imposée au pictogramme ni au titre : ils se placent
     d’eux-mêmes sur la première ligne libre. C’est ce qui permet à une carte
     avec illustration et à une carte sans illustration de se disposer
     correctement avec les mêmes règles — une ligne fixe aurait fait entrer
     le titre en collision avec l’image. */
  .pole__icon {
    width: 40px; height: 40px;
    font-size: 1.3rem;
    margin-bottom: 0;
  }
  .pole h3 { grid-column: 2; }
  .pole p { grid-column: 1 / -1; font-size: .9rem; }
  .pole .link-arrow { grid-column: 1 / -1; padding-top: .55rem; }
}

/* -------------------------------------------------------------------------
   10 bis. Chiffres cles
   ------------------------------------------------------------------------- */
.stats {
  display: grid;
  gap: 1px;
  background: var(--border);
  border: 1px solid var(--border);
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
@media (min-width: 820px) { .stats { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.stat {
  background: var(--card-bg);
  padding: clamp(1.15rem, .95rem + .8vw, 1.7rem);
}
.stat__n {
  display: block;
  font-family: 'Plex Mono', ui-monospace, monospace;
  font-size: clamp(1.65rem, 1.3rem + 1.5vw, 2.35rem);
  font-weight: 500;
  letter-spacing: -.03em;
  line-height: 1;
  color: var(--navy-800);
}
.stat__l {
  display: block;
  margin-top: .5rem;
  font-size: .85rem;
  line-height: 1.4;
  color: var(--text-2);
}
.band--navy .stats { background: var(--border-band); border-color: var(--border-band); }
.band--navy .stat { background: rgba(255,255,255,.04); }
.band--navy .stat__n { color: var(--gold-400); }
.band--navy .stat__l { color: var(--text-on-band-2); }
@media (prefers-color-scheme: dark) { .stat__n { color: var(--gold-400); } }

/* -------------------------------------------------------------------------
   10 ter. Marques mises en oeuvre et references
   ------------------------------------------------------------------------- */
/* Une colonne sur mobile : a deux colonnes, la troisieme reference laisserait
   une cellule vide, ce qui se voit immediatement. */
.refs {
  display: grid;
  gap: 1px;
  background: var(--border);
  border: 1px solid var(--border);
  grid-template-columns: minmax(0, 1fr);
}
@media (min-width: 700px) { .refs { grid-template-columns: repeat(3, minmax(0, 1fr)); } }


/* Trois rangees de hauteur imposee, identiques d'une carte a l'autre :
   l'identite, la nature, le role. C'est ce qui garantit l'homogeneite - les
   libelles s'alignent au pixel meme si l'un tient sur deux lignes et l'autre
   sur une, et meme si les logos ont des proportions differentes. */
.ref {
  display: grid;
  grid-template-rows: auto auto 1fr;
  gap: .55rem;
  background: var(--card-bg);
  padding: 1.6rem 1.15rem;
  text-align: center;
}

/* Zone d'identite. Sa hauteur ne depend pas de son contenu : un logo large et
   plat, un logo carre ou un simple nom compose occupent la meme place. C'est
   la condition pour que trois cartes restent rigoureusement alignees. */
.ref__logo {
  display: grid;
  place-items: center;
  min-height: 52px;
}
.ref__logo img {
  max-height: 40px;
  width: auto;
  max-width: 100%;
  object-fit: contain;
  background: none;
}

/* En theme sombre, les logos de marque posent un probleme qui n'a pas de
   solution parfaite : Legrand est noir et gris, Schneider vert fonce. Sur le
   fond sombre du site, les deux disparaissent presque.

   Les recolorer en blanc serait plus elegant, mais deformerait des logos qui
   ne nous appartiennent pas et dont les chartes encadrent l'usage. On pose
   donc une plaque claire discrete sous chacun : c'est ce que font la plupart
   des sites, et cela laisse chaque marque intacte.

   La plaque est reservee AUX LOGOS DE TIERS. Notre propre symbole, lui, a une
   declinaison blanche prevue pour les fonds sombres. */
@media (prefers-color-scheme: dark) {
  .ref__logo:has(img) {
    background: #fff;
    border-radius: var(--r-sm);
    padding: .5rem .75rem;
  }
}

/* Nom compose, tant que le fichier officiel du logo n'est pas disponible. */
.ref__wordmark {
  font-size: clamp(1rem, .92rem + .35vw, 1.15rem);
  font-weight: 700;
  letter-spacing: -.015em;
  line-height: 1.2;
  color: var(--text);
  text-wrap: balance;
}

/* Nature du lien : c'est elle qui evite de faire passer un fabricant et une
   entreprise de travaux pour deux partenariats de meme ordre. */
.ref__nature {
  font-family: 'Plex Mono', ui-monospace, monospace;
  font-size: .68rem;
  font-weight: 500;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--gold-600);
}
@media (prefers-color-scheme: dark) { .ref__nature { color: var(--gold-400); } }

.ref__role {
  font-size: .82rem;
  line-height: 1.45;
  color: var(--text-2);
}

/* Aligner les rangees D'UNE CARTE A L'AUTRE, et pas seulement a l'interieur
   de chacune. Sans cela, un libelle qui passe sur deux lignes dans une carte
   decale tout ce qui le suit, et les trois cartes cessent de se repondre -
   c'etait exactement le defaut constate sur ce bloc.

   subgrid fait partager aux cartes les rangees de leur grille parente : la
   nature et le role s'alignent alors au pixel, quelle que soit la longueur des
   textes ou la hauteur des logos. Applique a partir de 700 px seulement : en
   dessous les cartes sont empilees, il n'y a plus rien a aligner.

   CE BLOC DOIT RESTER APRES .ref. Place avant, sa declaration
   grid-template-rows: subgrid etait ecrasee par le grid-template-rows de .ref,
   de meme specificite mais declare plus bas : le subgrid ne s'appliquait pas,
   et l'alignement paraissait correct par simple effet de align-items: stretch.

   Sans subgrid, chaque carte garde sa grille interne : le bloc reste correct,
   simplement moins rigoureux. */
@supports (grid-template-rows: subgrid) {
  @media (min-width: 700px) {
    .refs { grid-template-rows: auto auto auto; }
    .ref  {
      grid-row: span 3;
      grid-template-rows: subgrid;
      /* Le gap vertical vient desormais de la grille parente : on ne le
         redeclare pas ici, sinon il s'ajouterait a celui des rangees. */
      row-gap: .55rem;
    }
  }
}

/* Liste de prestations */
.checklist { display: grid; gap: .6rem; }
.checklist li {
  display: flex;
  gap: .65rem;
  align-items: flex-start;
  font-size: .945rem;
  color: var(--text-2);
}
.checklist .icon {
  font-size: 1.05rem;
  color: var(--gold-600);
  margin-top: .28em;
}
.band--navy .checklist li { color: var(--text-on-band-2); }
.band--navy .checklist .icon { color: var(--gold-400); }
@media (prefers-color-scheme: dark) { .checklist .icon { color: var(--gold-400); } }

.checklist--2col { grid-template-columns: minmax(0,1fr); }
@media (min-width: 700px) { .checklist--2col { grid-template-columns: repeat(2, minmax(0,1fr)); column-gap: 2rem; } }

/* -------------------------------------------------------------------------
   11. Parcours d'accompagnement
   ------------------------------------------------------------------------- */
/* Deux colonnes des 460 px : sur telephone, sept etapes empilees faisaient
   defiler l'equivalent de deux ecrans pour une seule section. */
.process { display: grid; gap: 0; }
@media (min-width: 380px)  { .process { grid-template-columns: repeat(2, minmax(0,1fr)); } }
@media (min-width: 1100px) { .process { grid-template-columns: repeat(4, minmax(0,1fr)); } }

/* Le parcours compte sept etapes : sur deux ou quatre colonnes, la derniere
   resterait seule en bout de ligne. On lui fait occuper la place libre
   plutot que de laisser une cellule vide. */
@media (min-width: 380px) and (max-width: 1099px) {
  .process > :last-child { grid-column: 1 / -1; }
}
@media (min-width: 1100px) {
  .process > :last-child { grid-column: span 2; }
}

/* Les deux regles ci-dessus rattrapent la septieme etape du parcours de la
   page d'accueil, qui resterait seule en bout de ligne. Elles deviennent
   nuisibles des que le nombre d'etapes tombe juste : a quatre etapes, la
   derniere s'etalerait sur toute la largeur en deux colonnes, et reclamerait
   une cinquieme colonne inexistante en quatre colonnes. Cette variante les
   neutralise pour les parcours dont le compte se divise sans reste. */
.process--pair > :last-child { grid-column: auto; }

.step {
  position: relative;
  padding: 1.35rem 1.15rem 1.5rem;
  border-top: 3px solid var(--border-band);
  transition: border-color var(--dur) var(--ease);
}
.step:hover { border-top-color: var(--gold-500); }
.step__n {
  display: block;
  font-family: 'Plex Mono', ui-monospace, monospace;
  font-size: .78rem;
  font-weight: 500;
  letter-spacing: .18em;
  color: var(--gold-400);
  margin-bottom: .7rem;
}
.step h3 { color: #fff; font-size: 1.08rem; margin-bottom: .5rem; }
.step p { font-size: .9rem; color: var(--text-on-band-2); }

/* -------------------------------------------------------------------------
   12. Chaine integree (offre de bout en bout)
   ------------------------------------------------------------------------- */
.chain {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
  align-items: stretch;
}
.chain li {
  display: flex;
  align-items: center;
  gap: .5rem;
  padding: .6rem .9rem;
  background: var(--card-bg);
  /* Sans cette declaration, le texte heritait de .band--navy, qui l'eclaircit
     pour un fond bleu : on obtenait du blanc casse (#EEF2F9) sur la pastille
     blanche du composant, soit 1,12:1 - illisible. Le defaut touchait les six
     verbes de la signature sur A propos et la chaine de la page Installation,
     en theme clair, celui de la plupart des visiteurs. Une pastille qui pose
     son propre fond doit poser sa propre couleur de texte. */
  color: var(--text);
  border: 1px solid var(--border);
  border-left: 3px solid var(--gold-500);
  border-radius: var(--r-sm);
  font-size: .875rem;
  font-weight: 600;
}
.chain .icon { color: var(--gold-600); font-size: 1rem; }
@media (prefers-color-scheme: dark) { .chain .icon { color: var(--gold-400); } }

/* -------------------------------------------------------------------------
   12 bis. Synoptique
   -------------------------------------------------------------------------
   Schema technique construit en HTML et en CSS plutot qu'en image.

   POURQUOI PAS UNE IMAGE. Un synoptique dessine large reste lisible sur
   ordinateur et devient une trame grise sur telephone : reduit a 375 px, un
   dessin de 1000 px affiche son texte a 6 px. Ici, les etages se reorganisent
   en colonne et le texte garde sa taille. Il reste par ailleurs selectionnable,
   traduisible, et lu par les lecteurs d'ecran - ce qu'aucune image ne permet.

   Les traits de liaison sont purement decoratifs : ils portent aria-hidden et
   ne sont pas annonces. La lecture vocale suit l'ordre du document, qui est
   deja l'ordre du flux d'energie.
   ------------------------------------------------------------------------- */
.syno {
  display: grid;
  gap: .9rem;
  grid-template-columns: minmax(0, 1fr);
  align-items: stretch;
}
/* A partir de 1000 px, les quatre etages tiennent cote a cote, separes par
   leurs traits de liaison. En dessous, tout s'empile et les traits pivotent. */
@media (min-width: 1000px) {
  .syno {
    grid-template-columns: minmax(0,1fr) auto minmax(0,1fr) auto minmax(0,1fr) auto minmax(0,1fr);
    gap: 1rem;
  }
}

.syno__col { display: grid; gap: .7rem; align-content: start; }

.syno__etage {
  font-family: 'Plex Mono', ui-monospace, monospace;
  font-size: .7rem;
  font-weight: 500;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--gold-400);
}

.syno__bloc {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: .15rem .7rem;
  padding: .95rem 1.05rem;
  background: rgba(255,255,255,.05);
  border: 1px solid var(--border-band);
  border-left: 3px solid var(--gold-500);
  border-radius: var(--r-sm);
}
.syno__bloc .icon { grid-row: 1 / span 2; align-self: center; font-size: 1.5rem; color: var(--gold-400); }
.syno__bloc strong { font-size: .95rem; font-weight: 600; color: #fff; line-height: 1.3; }
.syno__bloc span { font-size: .82rem; line-height: 1.45; color: var(--text-on-band-2); }

/* Etage facultatif : present seulement si le site en est equipe. Le trait
   discontinu le dit sans avoir a l'ecrire une seconde fois. */
.syno__bloc--option { border-left-style: dashed; opacity: .78; }
/* Etage sur lequel repose la promesse de l'installation. */
.syno__bloc--fort { background: rgba(233,179,33,.10); border-left-width: 4px; }

/* Trait de liaison. Vertical dans la version empilee, horizontal des que les
   etages passent cote a cote. La pointe est dessinee en bordures, sans image
   ni pseudo-contenu textuel qui serait lu a voix haute. */
.syno__lien {
  justify-self: center;
  align-self: center;
  width: 2px;
  height: 26px;
  background: linear-gradient(var(--gold-500), rgba(209,154,12,.25));
  position: relative;
}
.syno__lien::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: -1px;
  translate: -50% 0;
  border: 5px solid transparent;
  border-top-color: var(--gold-500);
}
@media (min-width: 1000px) {
  .syno__lien {
    width: 34px;
    height: 2px;
    margin-top: 2.1rem;
    align-self: start;
    background: linear-gradient(to right, var(--gold-500), rgba(209,154,12,.25));
  }
  .syno__lien::after {
    left: auto; bottom: auto;
    right: -1px; top: 50%;
    translate: 0 -50%;
    border-top-color: transparent;
    border-left-color: var(--gold-500);
  }
}
@media (prefers-reduced-motion: no-preference) {
  .syno__bloc { transition: border-left-color var(--dur) var(--ease), background var(--dur) var(--ease); }
}
.syno__legende { margin-top: 1.75rem; max-width: 62ch; color: var(--text-on-band-2); }

/* -------------------------------------------------------------------------
   13. Domaines d'intervention
   ------------------------------------------------------------------------- */
.grid--sectors {
  display: grid;
  gap: 1px;
  background: var(--border);
  border: 1px solid var(--border);
  grid-template-columns: repeat(2, minmax(0,1fr));
}
@media (min-width: 700px)  { .grid--sectors { grid-template-columns: repeat(3, minmax(0,1fr)); } }
@media (min-width: 1024px) { .grid--sectors { grid-template-columns: repeat(4, minmax(0,1fr)); } }

.sector {
  display: flex;
  flex-direction: column;
  gap: .55rem;
  padding: 1.35rem 1.1rem;
  background: var(--card-bg);
  font-size: .9rem;
  font-weight: 600;
}
.sector .icon { font-size: 1.6rem; color: var(--navy-700); }
.sector span { color: var(--text-2); font-weight: 400; font-size: .82rem; line-height: 1.45; }
@media (prefers-color-scheme: dark) { .sector .icon { color: var(--gold-400); } }

/* -------------------------------------------------------------------------
   14. Realisations
   ------------------------------------------------------------------------- */
.grid--projects {
  display: grid;
  gap: clamp(1rem, .7rem + 1.1vw, 1.75rem);
  grid-template-columns: minmax(0,1fr);
}
@media (min-width: 640px)  { .grid--projects { grid-template-columns: repeat(2, minmax(0,1fr)); } }
@media (min-width: 1024px) { .grid--projects { grid-template-columns: repeat(3, minmax(0,1fr)); } }

.project {
  display: flex;
  flex-direction: column;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  overflow: hidden;
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease),
              transform var(--dur) var(--ease);
}
.project:hover {
  border-color: var(--navy-600);
  box-shadow: var(--shadow-md);
  transform: translateY(-3px);
}
@media (prefers-reduced-motion: reduce) { .project:hover { transform: none; } }
/* Format plus large sur telephone : les trois fiches s'empilant, une image
   en 4/3 y occupait presque un ecran a elle seule. */
.project__media { aspect-ratio: 16 / 10; overflow: hidden; }
@media (min-width: 640px) { .project__media { aspect-ratio: 4 / 3; } }
.project__media img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: scale .5s var(--ease);
}
.project:hover .project__media img { scale: 1.04; }
@media (prefers-reduced-motion: reduce) { .project:hover .project__media img { scale: 1; } }
.project__body { padding: 1.15rem 1.25rem 1.35rem; display: flex; flex-direction: column; gap: .5rem; flex: 1; }
.project__meta {
  font-family: 'Plex Mono', ui-monospace, monospace;
  font-size: .72rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--text-2);
}
.project h3 { font-size: 1.05rem; }
.project p { font-size: .9rem; color: var(--text-2); }

.gallery {
  display: grid;
  gap: .5rem;
  grid-template-columns: repeat(2, minmax(0,1fr));
}
@media (min-width: 768px) { .gallery { grid-template-columns: repeat(4, minmax(0,1fr)); } }

/* Chaque vignette est un bouton : l'agrandissement est atteignable au
   clavier sans code supplementaire. */
.gallery__item {
  display: block;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  overflow: hidden;
  cursor: zoom-in;
  transition: border-color var(--dur) var(--ease), transform .18s ease;
}
.gallery__item:hover { border-color: var(--navy-600); }
.gallery__item:active { transform: scale(.985); }
.gallery img {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  display: block;
}

/* -------------------------------------------------------------------------
   14 ter. Photographies d’illustration

   POURQUOI UN COMPOSANT DISTINCT DE .project.

   Ces images montrent le métier — un panneau, un tableau, un geste. Elles ne
   documentent aucun chantier GORDAN POWER : ce sont des photographies de
   banque d’images, retenues pour leur justesse technique.

   .project sert la galerie des réalisations, où chaque photo engage
   l’entreprise. Mélanger les deux composants reviendrait à rendre possible,
   un jour, qu’une illustration se retrouve présentée comme une référence.
   La séparation n’est donc pas cosmétique : c’est elle qui tient la
   distinction dans le temps, quand la page sera reprise par quelqu’un qui
   n’aura pas ce commentaire en tête.
   ------------------------------------------------------------------------- */
.photos {
  display: grid;
  gap: clamp(1rem, .7rem + 1.1vw, 1.75rem);
  grid-template-columns: minmax(0, 1fr);
}
@media (min-width: 640px) {
  .photos--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .photos--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 1024px) {
  .photos--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.photo { display: flex; flex-direction: column; gap: .75rem; margin: 0; }
.photo__media {
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border-radius: var(--r-sm);
  /* Un fond sous l’image : tant qu’elle n’est pas arrivée, le bloc a déjà sa
     couleur et sa place, plutôt qu’un rectangle vide qui se remplit d’un
     coup. */
  background: var(--bg-alt);
}
.photo__media img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Variante verticale : un onduleur mural, une armoire, un mât se lisent mal
   dans un cadre horizontal. */
.photo--haute .photo__media { aspect-ratio: 3 / 4; }
.photo__legende {
  font-size: .9rem;
  line-height: 1.5;
  color: var(--text-2);
}
.photo__legende strong { color: var(--text); font-weight: 600; }

/* Bandeau bleu : la légende doit y rester lisible. */
.band--navy .photo__legende,
.band--deep .photo__legende { color: var(--text-on-band-2); }
.band--navy .photo__legende strong,
.band--deep .photo__legende strong { color: #fff; }

/* -------------------------------------------------------------------------
   14 bis. Visionneuse
   ------------------------------------------------------------------------- */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 120;
  display: grid;
  grid-template-rows: auto 1fr auto;
  background: rgba(4, 16, 43, .96);
  opacity: 0;
  visibility: hidden;
  transition: opacity .25s var(--ease), visibility .25s;
}
.lightbox[data-open="true"] { opacity: 1; visibility: visible; }
@media (prefers-reduced-motion: reduce) { .lightbox { transition: none; } }

.lightbox__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: .85rem clamp(1rem, .8rem + 1vw, 1.75rem);
  border-bottom: 1px solid rgba(255,255,255,.14);
}
.lightbox__count {
  font-family: 'Plex Mono', ui-monospace, monospace;
  font-size: .78rem;
  letter-spacing: .12em;
  color: #A8B6CE;
}
.lightbox__figure {
  margin: 0;
  min-height: 0;
  display: grid;
  grid-template-rows: 1fr auto;
  gap: .9rem;
  padding: clamp(.75rem, .5rem + 1vw, 1.5rem);
}
.lightbox__figure img {
  min-height: 0;
  max-width: 100%;
  max-height: 100%;
  margin: 0 auto;
  object-fit: contain;
  border-radius: var(--r-sm);
  background: none;
}
.lightbox__figure figcaption {
  text-align: center;
  font-size: .9rem;
  color: #C3CEE2;
  max-width: 70ch;
  margin-inline: auto;
}
.lightbox__nav {
  display: flex;
  justify-content: center;
  gap: .75rem;
  padding: 0 1rem clamp(1rem, .8rem + 1vw, 1.75rem);
}
.lightbox button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  min-height: 46px;
  padding: .6rem 1.15rem;
  font-family: inherit;
  font-size: .9rem;
  font-weight: 600;
  color: #fff;
  background: transparent;
  border: 1.5px solid rgba(255,255,255,.45);
  border-radius: var(--r-sm);
  cursor: pointer;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.lightbox button:hover { background: rgba(255,255,255,.14); border-color: #fff; }
.lightbox button[disabled] { opacity: .4; cursor: default; }
.lightbox button[disabled]:hover { background: transparent; border-color: rgba(255,255,255,.45); }
.lightbox__close { border-color: transparent !important; }

/* Fiche de chantier detaillee, utilisee sur la page Realisations */
.project-block {
  padding-top: clamp(1.75rem, 1.4rem + 1.4vw, 2.75rem);
  border-top: 3px solid var(--navy-800);
}
.project-block + .project-block { margin-top: clamp(2.5rem, 2rem + 2vw, 4rem); }
@media (prefers-color-scheme: dark) { .project-block { border-top-color: var(--gold-500); } }

.project-block__head {
  display: grid;
  gap: 1rem 2.5rem;
  align-items: start;
  margin-bottom: 1.5rem;
}
@media (min-width: 900px) {
  .project-block__head { grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); }
}
.project-block h2 { font-size: clamp(1.35rem, 1.15rem + .8vw, 1.75rem); margin-bottom: .75rem; }
.project-block p { color: var(--text-2); max-width: 62ch; }

.tags { display: flex; flex-wrap: wrap; gap: .45rem; }
.tag {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  padding: .3rem .7rem;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  font-family: 'Plex Mono', ui-monospace, monospace;
  font-size: .7rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-2);
}
.tag .icon { font-size: .95rem; color: var(--gold-600); }
@media (prefers-color-scheme: dark) { .tag .icon { color: var(--gold-400); } }

/* -------------------------------------------------------------------------
   15. Blocs editoriaux alternes
   ------------------------------------------------------------------------- */
.split {
  display: grid;
  gap: clamp(1.75rem, 1rem + 3.2vw, 3.5rem);
  align-items: center;
}
@media (min-width: 900px) {
  .split { grid-template-columns: repeat(2, minmax(0,1fr)); }
  .split--reverse > :first-child { order: 2; }
}
.split__media {
  border-radius: var(--r-md);
  overflow: hidden;
  aspect-ratio: 4 / 3;
}
.split__media img { width: 100%; height: 100%; object-fit: cover; }

/* Encadre d'appel */
.callout {
  padding: clamp(1.35rem, 1.1rem + .9vw, 2rem);
  background: var(--bg-alt);
  border-left: 3px solid var(--gold-500);
  border-radius: 0 var(--r-md) var(--r-md) 0;
}
.callout p { color: var(--text-2); }
.band--navy .callout {
  background: rgba(255,255,255,.05);
  border-left-color: var(--gold-400);
}

/* -------------------------------------------------------------------------
   15 bis. Fiche d'identite legale
   ------------------------------------------------------------------------- */
.facts { display: grid; gap: 0; }
.facts > div {
  display: grid;
  gap: .2rem 1.5rem;
  padding: .85rem 0;
  border-bottom: 1px solid var(--border);
}
@media (min-width: 600px) {
  .facts > div { grid-template-columns: minmax(0, 12rem) minmax(0, 1fr); align-items: baseline; }
}
.facts dt {
  font-size: .78rem;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--text-2);
}
.facts dd {
  margin: 0;
  font-size: .98rem;
  font-weight: 500;
}
.facts dd.is-pending { color: var(--text-2); font-weight: 400; font-style: italic; }

/* -------------------------------------------------------------------------
   16. FAQ
   ------------------------------------------------------------------------- */
.faq { border-top: 1px solid var(--border); }
.faq details {
  border-bottom: 1px solid var(--border);
}
.faq summary {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1.25rem;
  padding: 1.15rem 0;
  font-size: 1rem;
  font-weight: 600;
  cursor: pointer;
  list-style: none;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary .icon {
  flex: none;
  font-size: 1.1rem;
  color: var(--gold-600);
  margin-top: .2em;
  transition: rotate .28s var(--ease);
}
.faq details[open] summary .icon { rotate: 180deg; }
.faq__answer { padding: 0 0 1.35rem; color: var(--text-2); max-width: 72ch; font-size: .95rem; }
@media (prefers-color-scheme: dark) { .faq summary .icon { color: var(--gold-400); } }

/* -------------------------------------------------------------------------
   17. Formulaires
   ------------------------------------------------------------------------- */
.form { display: grid; gap: 1.15rem; }
.form-grid {
  display: grid;
  gap: 1.15rem;
  grid-template-columns: minmax(0,1fr);
}
@media (min-width: 700px) { .form-grid--2 { grid-template-columns: repeat(2, minmax(0,1fr)); } }

/* Engagement de delai, sur la page Contact. Volontairement distinct de
   .form-intro : il affirme quelque chose, la ou l'autre explique un
   fonctionnement. */
.pledge {
  display: flex;
  align-items: flex-start;
  gap: .7rem;
  padding: 1rem 1.15rem;
  background: color-mix(in srgb, var(--ok) 7%, transparent);
  border: 1px solid color-mix(in srgb, var(--ok) 28%, transparent);
  border-radius: var(--r-sm);
  font-size: .9rem;
  line-height: 1.5;
  color: var(--text-2);
}
.pledge .icon { font-size: 1.25rem; color: var(--ok); flex: none; margin-top: .1em; }
.pledge strong { color: var(--text); font-weight: 600; }
@media (prefers-color-scheme: dark) { .pledge .icon { color: #6BD68F; } }

/* Note d'ouverture des formulaires. Elle annonce le mode d'envoi avant que le
   visiteur ne remplisse quoi que ce soit : le site ne transmet rien lui-meme,
   il prepare un message que l'on envoie par WhatsApp ou par e-mail. Decouvrir
   cela apres dix champs remplis est le meilleur moyen de perdre la demande. */
.form-intro {
  display: flex;
  align-items: flex-start;
  gap: .7rem;
  padding: .9rem 1.05rem;
  background: var(--bg-alt);
  border-left: 3px solid var(--gold-500);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  font-size: .875rem;
  line-height: 1.5;
  color: var(--text-2);
}
.form-intro .icon { font-size: 1.25rem; color: var(--wa); flex: none; margin-top: .1em; }
.form-intro strong { color: var(--text); font-weight: 600; }

.field { display: grid; gap: .4rem; }
.field > label {
  font-size: .875rem;
  font-weight: 600;
  color: var(--text);
}
.field .req { color: var(--error); font-weight: 700; }
/* Meme cause que pour .eyebrow : le rouge d'erreur est calibre pour du fond
   clair et tombait a 2,97:1 en theme sombre. Le rouge clair, deja employe par
   .error-text dans ce theme, y atteint 9,6:1. */
@media (prefers-color-scheme: dark) { .field .req { color: #FF9B93; } }
.field .hint { font-size: .8rem; color: var(--text-2); }

.field input,
.field select,
.field textarea {
  width: 100%;
  padding: .8rem .9rem;
  min-height: 48px;
  font-family: inherit;
  /* 16 px minimum : en dessous, Safari sur iPhone zoome sur le champ des
     qu'on le touche, et la page reste agrandie apres la saisie. */
  font-size: 1rem;
  color: var(--text);
  background: var(--card-bg);
  border: 1.5px solid var(--border);
  border-radius: var(--r-sm);
  transition: border-color .2s var(--ease), box-shadow .2s var(--ease);
}
.field textarea { min-height: 132px; resize: vertical; line-height: 1.6; }
.field select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='%235A6580'%3E%3Cpath d='M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,53.66,90.34L128,164.69l74.34-74.35a8,8,0,0,1,11.32,11.32Z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right .85rem center;
  background-size: 1.1rem;
  padding-right: 2.6rem;
}
.field input::placeholder,
.field textarea::placeholder { color: #7A859C; opacity: 1; }
@media (prefers-color-scheme: dark) {
  .field input::placeholder, .field textarea::placeholder { color: #8593AE; }
}

/* Champ rempli d'apres l'adresse d'arrivee : un clic sur « Demander un devis
   materiel » arrive avec le service deja choisi. L'attribut etait pose par
   gps.js depuis l'origine, mais aucun style ne lui correspondait : le visiteur
   ne voyait pas ce qui avait ete prerempli pour lui.
   Le repere passe par la bordure et une ombre interne, jamais par
   background-image : les listes deroulantes s'en servent deja pour leur
   fleche, qui aurait disparu. */
.field [data-prefilled] {
  border-color: var(--gold-500);
  box-shadow: inset 3px 0 0 var(--gold-500);
}

.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--navy-600);
  box-shadow: 0 0 0 3px rgba(27,64,118,.22);
}
.field input[aria-invalid="true"],
.field select[aria-invalid="true"],
.field textarea[aria-invalid="true"] { border-color: var(--error); }

.field .error-text {
  display: none;
  align-items: center;
  gap: .35rem;
  font-size: .82rem;
  font-weight: 500;
  color: var(--error);
}
.field .error-text[data-shown="true"] { display: flex; }
@media (prefers-color-scheme: dark) { .field .error-text { color: #FF9B93; } }

.field input[type="file"] {
  padding: .55rem .6rem;
  font-size: .875rem;
}
.field input[type="file"]::file-selector-button {
  margin-right: .8rem;
  padding: .5rem .85rem;
  font-family: inherit;
  font-size: .85rem;
  font-weight: 600;
  color: var(--navy-800);
  background: var(--bg-alt);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  cursor: pointer;
}
@media (prefers-color-scheme: dark) {
  .field input[type="file"]::file-selector-button { color: #DCE4F2; }
}

/* Le selecteur reprend .field > label pour rester prioritaire sur lui :
   la case de consentement n'est pas un libelle de champ classique. */
.consent,
.field > label.consent {
  display: flex;
  gap: .7rem;
  align-items: flex-start;
  font-size: .85rem;
  font-weight: 400;
  color: var(--text-2);
  cursor: pointer;
}
.consent input {
  width: 20px; height: 20px;
  min-height: 0;
  flex: none;
  margin-top: .15rem;
  accent-color: var(--navy-700);
}
.consent input[aria-invalid="true"] {
  outline: 2px solid var(--error);
  outline-offset: 2px;
}

/* Retours de formulaire */
.form-status {
  display: none;
  gap: .7rem;
  align-items: flex-start;
  padding: 1rem 1.15rem;
  border-radius: var(--r-sm);
  font-size: .92rem;
  border: 1.5px solid;
}
.form-status[data-state="success"],
.form-status[data-state="error"] { display: flex; }
.form-status[data-state="success"] {
  color: var(--ok);
  border-color: color-mix(in srgb, var(--ok) 40%, transparent);
  background: color-mix(in srgb, var(--ok) 8%, transparent);
}
.form-status[data-state="error"] {
  color: var(--error);
  border-color: color-mix(in srgb, var(--error) 40%, transparent);
  background: color-mix(in srgb, var(--error) 8%, transparent);
}
.form-status .icon { font-size: 1.25rem; flex: none; margin-top: .1em; }
@media (prefers-color-scheme: dark) {
  .form-status[data-state="success"] { color: #6BD68F; }
  .form-status[data-state="error"] { color: #FF9B93; }
}

.btn[data-loading="true"] { pointer-events: none; opacity: .75; }
.btn[data-loading="true"] .btn__spinner { display: inline-block; }
.btn__spinner { display: none; animation: spin 1s linear infinite; }
@keyframes spin { to { rotate: 360deg; } }
@media (prefers-reduced-motion: reduce) { .btn__spinner { animation: none; } }

/* -------------------------------------------------------------------------
   18. Coordonnees
   ------------------------------------------------------------------------- */
.contact-list { display: grid; gap: 1.1rem; }
.contact-list li { display: flex; gap: .9rem; align-items: flex-start; }
.contact-list .icon { font-size: 1.3rem; color: var(--gold-600); margin-top: .15em; flex: none; }
.contact-list strong { display: block; font-size: .78rem; text-transform: uppercase; letter-spacing: .1em; color: var(--text-2); font-weight: 600; }
.contact-list a, .contact-list span { font-size: 1.02rem; font-weight: 500; }
.contact-list a:hover { color: var(--navy-700); text-decoration: underline; }
.band--navy .contact-list .icon { color: var(--gold-400); }
.band--navy .contact-list strong { color: var(--text-on-band-2); }
/* Le pied de page n'est pas un .band--navy mais un fond sombre a part entiere.
   Sans cette regle, ces intitules heritaient de --text-2, une couleur prevue
   pour du texte sur fond CLAIR : le contraste tombait a 3,24:1 sur le bleu
   profond du pied de page, sous le seuil WCAG AA de 4,5:1. */
.site-footer .contact-list strong { color: var(--text-on-band-2); }
@media (prefers-color-scheme: dark) { .contact-list .icon { color: var(--gold-400); } }

/* -------------------------------------------------------------------------
   19. Pied de page
   ------------------------------------------------------------------------- */
.site-footer {
  background: var(--bg-band-deep);
  color: var(--text-on-band-2);
  font-size: .92rem;
  /* Le fond du pied de page se prolonge sous la barre gestuelle plutot que de
     laisser apparaitre une bande blanche en bas d'ecran. */
  padding-bottom: var(--safe-b);
}
.footer-grid {
  display: grid;
  gap: 2.25rem;
  padding-block: clamp(2.75rem, 2rem + 2.6vw, 4rem);
  grid-template-columns: minmax(0,1fr);
}
@media (min-width: 700px)  { .footer-grid { grid-template-columns: repeat(2, minmax(0,1fr)); } }
@media (min-width: 1024px) { .footer-grid { grid-template-columns: 1.5fr 1fr 1fr 1.2fr; } }

/* Declinaison blanche du logo : plus besoin de l'encadrer d'une plaque
   blanche, qui lui donnait un air d'autocollant colle sur le bleu.

   Hauteur portee de 92 a 132 px. Le logo officiel empile quatre lignes de
   texte sous le symbole : GORDAN, POWER, SARL, puis la ligne de metiers.
   A 92 px, le mot GORDAN mesurait environ 7 px de haut et la ligne de metiers
   se reduisait a une trame grise. Le pied de page a la place ; l'y priver
   revenait a afficher un logo que personne ne peut lire. */
.footer-logo {
  height: 132px;
  width: auto;
  background: none;
  margin-bottom: 1.35rem;
}
/* Sur les ecrans les plus etroits, on redescend : le logo ne doit pas
   repousser les coordonnees trop bas dans la page. */
@media (max-width: 420px) {
  .footer-logo { height: 112px; }
}

.site-footer h3 {
  font-size: .78rem;
  text-transform: uppercase;
  letter-spacing: .13em;
  color: #fff;
  font-weight: 600;
  margin-bottom: 1.1rem;
}
.footer-links { display: grid; gap: .6rem; }
.footer-links a { color: var(--text-on-band-2); transition: color var(--dur) var(--ease); }
.footer-links a:hover { color: var(--gold-400); }

.footer-legal {
  display: flex;
  flex-wrap: wrap;
  gap: .6rem 1.5rem;
  justify-content: space-between;
  align-items: center;
  padding-block: 1.35rem;
  border-top: 1px solid var(--border-band);
  font-size: .82rem;
}
.footer-legal p { color: #8195B4; }
.legal-ids {
  display: flex;
  flex-wrap: wrap;
  gap: .35rem 1.1rem;
  font-family: 'Plex Mono', ui-monospace, monospace;
  font-size: .74rem;
  letter-spacing: .04em;
  color: #8195B4;
  margin-top: 1.15rem;
}

/* -------------------------------------------------------------------------
   20. Bouton WhatsApp flottant
   ------------------------------------------------------------------------- */
.wa-fab {
  position: fixed;
  /* Decale au-dessus de la barre gestuelle et hors de l'encoche en paysage. */
  right: calc(clamp(.9rem, .5rem + 1vw, 1.5rem) + var(--safe-r));
  bottom: calc(clamp(.9rem, .5rem + 1vw, 1.5rem) + var(--safe-b));
  z-index: var(--z-fab);
  display: inline-flex;
  align-items: center;
  gap: .55rem;
  padding: .8rem 1.1rem;
  /* Vert assombri par rapport au vert WhatsApp d'origine. Sur #1EA95A, le
     libelle blanc n'atteignait que 3,05:1, sous le seuil de 4,5:1 - et ce
     dans les DEUX themes, la couleur etant fixe. Le defaut passait inapercu
     parce qu'on reconnait ce bouton a sa forme et a son pictogramme avant de
     le lire. #107A3D reste un vert WhatsApp identifiable et porte le contraste
     a 5,42:1. */
  background: var(--wa);
  color: #fff;
  font-size: .9rem;
  font-weight: 600;
  border-radius: 999px;
  box-shadow: 0 8px 26px rgba(4,16,43,.32);
  transition: background var(--dur) var(--ease), transform .14s ease;
}
.wa-fab .icon { font-size: 1.4rem; }
.wa-fab:hover { background: #0C6231; }
.wa-fab:active { transform: translateY(1px); }
.wa-fab__label { display: none; }
@media (min-width: 640px) { .wa-fab__label { display: inline; } }

/* Sous 1024 px, la barre d’actions du bas d’écran porte déjà WhatsApp, avec
   une cible bien plus large. Garder les deux ferait se chevaucher une pastille
   et une barre au même endroit de l’écran, pour la même action. */
@media (max-width: 1023px) { .wa-fab { display: none; } }

/* -------------------------------------------------------------------------
   20 bis. Barre d’actions du bas d’écran (téléphone et tablette)

   POURQUOI. Au-dessous de 1024 px, l’en-tête masque ses boutons faute de
   place : le visiteur n’a plus, sous les yeux, ni le numéro, ni le devis. Or
   la majorité des visites arrivent d’un téléphone, et la demande commerciale
   part le plus souvent d’un appel ou d’un message WhatsApp, pas d’un
   formulaire.

   La barre reste donc affichée en permanence, à portée du pouce. Trois
   cibles d’un tiers de largeur sur 60 px de haut : très au-delà des 44 px
   recommandés pour un contact tactile, et atteignables sans changer la prise
   en main du téléphone.
   ------------------------------------------------------------------------- */
.action-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: var(--z-fab);
  display: none;
  background: var(--bg);
  border-top: 1px solid var(--border);
  /* Repose sur la barre gestuelle du téléphone au lieu de passer dessous. */
  padding-bottom: var(--safe-b);
  padding-left: var(--safe-l);
  padding-right: var(--safe-r);
  box-shadow: 0 -6px 24px rgba(4,16,43,.14);
}
@media (max-width: 1023px) { .action-bar { display: grid; grid-template-columns: repeat(3, 1fr); } }

/* Le menu mobile et la visionneuse occupent tout l’écran : la barre n’a plus
   lieu d’être par-dessus, et masquerait leurs propres commandes du bas. */
body[data-menu-open="true"] .action-bar { display: none; }

.action-bar__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .18rem;
  min-height: 60px;
  padding: .5rem .35rem;
  font-size: .78rem;
  font-weight: 600;
  line-height: 1.1;
  text-align: center;
  color: #fff;
  transition: background var(--dur) var(--ease);
}
.action-bar__item .icon { font-size: 1.32rem; }
.action-bar__item:active { transform: none; }

.action-bar__item--devis { background: var(--gold-500); color: var(--navy-950); }
.action-bar__item--devis:hover { background: var(--gold-400); }
.action-bar__item--wa    { background: var(--wa); }
.action-bar__item--wa:hover { background: #0C6231; }
.action-bar__item--tel   { background: var(--navy-800); }
.action-bar__item--tel:hover { background: var(--navy-700); }

/* Le pied de page se termine juste derrière la barre : sans cette réserve,
   ses dernières lignes resteraient cachées dessous, quelle que soit la
   longueur de la page. */
@media (max-width: 1023px) {
  .site-footer { padding-bottom: calc(var(--safe-b) + 60px); }
}

/* -------------------------------------------------------------------------
   21. Revelation au defilement (motion volontairement sobre)
   ------------------------------------------------------------------------- */
/* Auparavant, .reveal partait a opacity: 0 et seul le JavaScript revelait les
   blocs. Consequence : script bloque, erreur de chargement ou connexion coupee
   en cours de route, et une grande partie de la page restait DEFINITIVEMENT
   invisible. Sur une connexion mobile instable, ce n'est pas un cas d'ecole.

   Deux solutions etaient possibles. Rendre le contenu visible par defaut et
   laisser le JavaScript le masquer : ecarte, car gps.js est charge en differe,
   le contenu se serait affiche puis efface, produisant un clignotement.

   Retenu : un filet de securite en CSS pur. Les blocs partent masques, mais
   une animation les revele d'office au bout de 4 secondes. Si gps.js demarre
   normalement - c'est-a-dire toujours, sauf incident - il pose data-anim sur
   <html>, ce qui retire le filet et rend la main a la revelation au
   defilement. Aucun clignotement, et aucune page vide en cas de panne. */
@media (prefers-reduced-motion: no-preference) {
  .reveal {
    opacity: 0;
    transform: translateY(18px);
    transition: opacity .6s var(--ease), transform .6s var(--ease);
    animation: gps-reveal-failsafe 0s linear 4s forwards;
  }
  .reveal[data-visible="true"] { opacity: 1; transform: none; }
  [data-anim] .reveal { animation: none; }
}
@keyframes gps-reveal-failsafe { to { opacity: 1; transform: none; } }

/* -------------------------------------------------------------------------
   22. Utilitaires
   ------------------------------------------------------------------------- */
.stack-sm > * + * { margin-top: .75rem; }
.stack   > * + * { margin-top: 1.25rem; }
.stack-lg > * + * { margin-top: 2rem; }
.mt-auto { margin-top: auto; }
.text-center { text-align: center; }
.max-56 { max-width: 56ch; }
.max-60 { max-width: 60ch; }
.mx-auto { margin-inline: auto; }

/* Echelle d'espacement.
   Ces classes remplacent les attributs style= ecrits dans les balises. Ce
   n'est pas qu'une question de proprete : la politique de securite du site
   (Content-Security-Policy, dans .htaccess) interdit les styles en ligne.
   Un style ecrit dans une balise serait purement et simplement ignore par
   le navigateur. Voir le controle correspondant dans tools\check-site.ps1. */
.mt-sm  { margin-top: 1.15rem; }
.mt-md  { margin-top: 1.5rem; }
.mt-lg  { margin-top: 1.75rem; }
.mt-xl  { margin-top: 2rem; }
.mt-2xl { margin-top: 2.75rem; }

.mb-sm  { margin-bottom: .6rem; }
.mb-md  { margin-bottom: 1.15rem; }
.mb-lg  { margin-bottom: 1.5rem; }
.mb-2xl { margin-bottom: 2.75rem; }

.text-muted { color: var(--text-2); }
.note { font-size: .85rem; color: var(--text-2); }

/* Rangee de boutons centree, utilisee dans les appels a l'action */
.btn-row--center { justify-content: center; margin-top: 2rem; }

/* Colonnes alignees en haut plutot qu'au centre */
.split--top { align-items: start; }

/* Grille de secteurs qui s'ajuste au nombre d'elements */
.grid--auto-fit { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.mono {
  font-family: 'Plex Mono', ui-monospace, monospace;
  font-size: .78rem;
  letter-spacing: .1em;
  text-transform: uppercase;
}

/* Impression : le site sert aussi de reference lors des rendez-vous */
@media print {
  .site-header, .wa-fab, .action-bar, .mobile-menu, .intent-bar { display: none !important; }
  body { font-size: 11pt; color: #000; background: #fff; }
  .band--navy, .site-footer { background: #fff !important; color: #000 !important; }
  .band--navy h1, .band--navy h2, .band--navy h3 { color: #000 !important; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: .8em; }
}
