/* ==========================================================================
   Houdin Formation — design system
   Palette : navy (marque) + spark orange, langage "plaque technique"
   Display : Anton (police du logo) · Corps : Inter · Repères : IBM Plex Mono
   ========================================================================== */

:root{
  --navy-990:#060E18;   /* fond de scène : le cran sous navy-950, pour le hero */
  --navy-950:#0A1826;
  --navy-900:#0F2138;
  --navy-800:#16365A;
  --navy-700:#1E4771;
  --navy-600:#2C577F;

  --spark-500:#EE7111;
  --spark-600:#B25207;   /* orange d'etat : 4,6:1 en blanc dessus, 4,6:1 en texte sur creme */
  --spark-700:#A2490B;   /* orange lisible en TEXTE sur fond clair (5,4:1) */
  --spark-100:#FCE8D6;

  --on-spark:#0A1826;    /* texte sur aplat orange (5,98:1) — jamais de blanc */
  --dark-body:#C4CDD6;   /* corps de texte sur fond navy (10:1) */

  --paper:#F5F2EA;
  --paper-alt:#EAE5D8;
  --paper-line:#DAD4C4;

  --ink:#14202B;
  --ink-soft:#57636E;
  --ink-faint:#616C77;   /* était #8A94A0 = 3,08:1 ; calé pour passer AA aussi sur --paper */

  --white:#FFFFFF;
  --line:rgba(20,32,43,.12);
  --line-on-dark:rgba(255,255,255,.14);

  --font-display:'Anton', 'Arial Black', 'Helvetica Neue', sans-serif;
  --font-body:'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --font-mono:'IBM Plex Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace;

  --container:1180px;
  --radius-s:6px;
  --radius-m:12px;
  --radius-l:20px;

  --shadow-card:0 1px 2px rgba(10,24,38,.06), 0 12px 28px -14px rgba(10,24,38,.22);
  --shadow-lift:0 2px 4px rgba(10,24,38,.10), 0 24px 48px -18px rgba(10,24,38,.35);

  /* ----- mouvement -----
     Trois courbes, jamais de `linear`. `--ease-out` décélère franchement : c'est
     la courbe par défaut de tout ce qui entre à l'écran. `--ease-out-back`
     dépasse très légèrement la cible (1.34) : réservé aux objets qu'on veut
     sentir « se poser ». `--ease-in-out` pour ce qui fait l'aller-retour
     (survols, ouvertures/fermetures). */
  --ease-out:cubic-bezier(.22,1,.36,1);
  --ease-out-back:cubic-bezier(.34,1.28,.64,1);
  --ease-in-out:cubic-bezier(.65,0,.35,1);

  --dur-fast:180ms;    /* accusé de réception : survol, focus */
  --dur-base:280ms;    /* micro-interaction standard */
  --dur-slow:420ms;    /* changement d'état d'un bloc entier */
  --dur-reveal:560ms;  /* apparition au défilement — plafond fixé à 800ms */
}

/* ---------- reset ---------- */
*, *::before, *::after{ box-sizing:border-box; }
html{ scroll-behavior:smooth; }
/* Garde-fou anti-débordement horizontal, sur <body> UNIQUEMENT.
   Sur <html> : `overflow-x:hidden` en fait un conteneur de défilement et
   neutralise tout `position:sticky` ; `overflow-x:clip` se propage au viewport
   et casse le défilement programmatique (scrollTo/scrollBy) ainsi que les
   événements scroll et les IntersectionObserver. Rien ne doit toucher <html>. */
html{ max-width:100%; }
body{ max-width:100%; overflow-x:clip; }
body{
  margin:0;
  background:var(--paper);
  color:var(--ink);
  font-family:var(--font-body);
  font-size:16px;
  line-height:1.6;
  -webkit-font-smoothing:antialiased;
}
img{ max-width:100%; display:block; }
a{ color:inherit; text-decoration:none; }
ul{ margin:0; padding:0; list-style:none; }
h1,h2,h3,h4,p{ margin:0; }
button{ font:inherit; background:none; border:0; cursor:pointer; color:inherit; }
input, textarea{ font:inherit; }
.wrap{ max-width:var(--container); margin:0 auto; padding:0 24px; }

@media (prefers-reduced-motion: reduce){
  html{ scroll-behavior:auto; }
  *{ animation-duration:.001ms !important; animation-iteration-count:1 !important; transition-duration:.001ms !important; }
}

/* ---------- reveal-on-scroll ---------- */
/* Course plus courte et plus rapide : l'ancien réglage (.6s + 70ms de décalage)
   laissait des écrans entiers vides pendant la lecture. */
[data-reveal]{
  opacity:0;
  transform:translateY(14px);
  transition:opacity var(--dur-reveal) var(--ease-out),
             transform var(--dur-reveal) var(--ease-out);
}
[data-reveal].is-visible{ opacity:1; transform:none; }
[data-reveal-group] > *{ transition-delay:calc(var(--i, 0) * 60ms); }

/* Variantes directionnelles : la valeur de l'attribut donne la provenance.
   Utile pour faire converger deux colonnes l'une vers l'autre plutôt que de
   faire monter toute la page en bloc. */
[data-reveal="left"]{  transform:translateX(-22px); }
[data-reveal="right"]{ transform:translateX(22px); }
[data-reveal="scale"]{ transform:scale(.96); }
[data-reveal="fade"]{  transform:none; }
/* Un titre de section est un repère de lecture : il ne s'anime jamais. */
.section-head[data-reveal]{ opacity:1; transform:none; }

/* ---------- type scale ---------- */
.eyebrow{
  font-family:var(--font-mono);
  font-size:12px;
  letter-spacing:.14em;
  text-transform:uppercase;
  color:var(--spark-700);
  display:flex;
  align-items:center;
  gap:10px;
  margin:0 0 14px;
}
/* L'orange reste le signal (le filet), pas le support du texte. */
.eyebrow::before{ content:""; width:20px; height:2px; background:var(--spark-500); display:inline-block; flex:none; }
.on-dark .eyebrow,
.hero .eyebrow,
.page-hero .eyebrow{ color:var(--dark-body); }

h1, .h1{
  font-family:var(--font-display);
  font-weight:400;
  text-transform:uppercase;
  letter-spacing:.005em;
  /* 1.06 et non .98 : en capitales accentuées (ÉQUIPES, SÉCURITÉ) les accents
     de la ligne suivante venaient toucher la ligne du dessus. */
  line-height:1.06;
  font-size:clamp(38px, 6vw, 68px);
  text-wrap:balance;
}
h2, .h2{
  font-family:var(--font-display);
  font-weight:400;
  text-transform:uppercase;
  line-height:1.08;
  font-size:clamp(28px, 4vw, 42px);
  text-wrap:balance;
}
h3, .h3{
  font-family:var(--font-display);
  font-weight:400;
  text-transform:uppercase;
  font-size:20px;
  letter-spacing:.01em;
}
.lede{
  font-size:18px;
  line-height:1.65;
  color:var(--ink-soft);
  max-width:56ch;
  text-wrap:balance;
}
/* .hero et .page-hero ont un fond navy sans porter la classe .on-dark :
   sans ces sélecteurs, le chapô retombait sur --ink-soft, soit 2,64:1. */
.on-dark .lede,
.hero .lede,
.page-hero .lede{ color:var(--dark-body); }
.section-head{ max-width:720px; margin:0 0 48px; }
/* Le reset pose `margin:0` sur h2 et p ; .lede ne reprend sa marge haute que
   dans .page-hero et .reco-title. Dans un en-tête de section, le chapô se
   retrouvait donc collé au titre — d'autant plus visible sur mobile, où le
   titre passe sur deux ou trois lignes. Même valeur que .reco-title. */
.section-head .lede{ margin-top:14px; }
.section-head.center{ margin-inline:auto; text-align:center; }

/* ---------- buttons ---------- */
.btn{
  display:inline-flex;
  align-items:center;
  gap:10px;
  padding:15px 26px;
  border-radius:999px;
  font-family:var(--font-body);
  font-weight:700;
  font-size:15px;
  letter-spacing:.01em;
  transition:transform var(--dur-base) var(--ease-out-back),
              box-shadow var(--dur-base) var(--ease-out),
              background var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out);
  white-space:nowrap;
}
.btn svg{ width:16px; height:16px; flex:none; transition:transform var(--dur-base) var(--ease-out-back); }
/* Navy sur orange (5,98:1) et non blanc sur orange (3,00:1) : c'est à la fois
   la mise en conformité AA et le vrai code de la signalisation industrielle. */
.btn-primary{ background:var(--spark-500); color:var(--on-spark); box-shadow:0 10px 24px -10px rgba(238,113,17,.55); }
.btn-primary:hover{ background:var(--spark-600); color:var(--white); transform:translateY(-2px); box-shadow:0 14px 28px -10px rgba(200,92,8,.55); }
.btn-outline{ background:transparent; color:var(--navy-900); box-shadow:inset 0 0 0 1.5px var(--line); }
.btn-outline:hover{ box-shadow:inset 0 0 0 1.5px var(--navy-900); transform:translateY(-2px); }
.on-dark .btn-outline{ color:var(--white); box-shadow:inset 0 0 0 1.5px var(--line-on-dark); }
.on-dark .btn-outline:hover{ box-shadow:inset 0 0 0 1.5px #fff; }
/* .page-hero au même titre que .hero : les deux sont des aplats navy. Sans
   cette ligne, le bouton secondaire des pages de formation héritait de la
   variante claire, soit du navy-900 sur du navy-900 (1,2:1) : le numéro de
   téléphone était présent, cliquable, et invisible. */
.hero .btn-outline, .page-hero .btn-outline{ color:var(--white); box-shadow:inset 0 0 0 1.5px var(--line-on-dark); }
.hero .btn-outline:hover, .page-hero .btn-outline:hover{ box-shadow:inset 0 0 0 1.5px #fff; }
.btn-small{ padding:10px 18px; font-size:13px; }
.btn-block{ width:100%; justify-content:center; }
.btn:hover svg{ transform:translateX(4px); }
/* Le clic doit s'ancrer : le bouton redescend sous le doigt, plus vite qu'il n'est monté. */
.btn:active{ transform:translateY(0) scale(.985); transition-duration:90ms; }

/* ---------- header : barre flottante en pilule ---------- */
.site-header{
  position:sticky; top:0; z-index:100;
  padding:14px 24px 0;
  background:transparent;
  border-bottom:0;
  transition:padding var(--dur-slow) var(--ease-out);
}
/* Rétraction au défilement : la pilule se resserre et se pose. */
.site-header.is-scrolled{ padding-top:8px; }
.header-inner{
  display:flex; align-items:center; justify-content:space-between; gap:20px;
  /* .mobile-nav est un enfant de .site-header, qui crée son propre contexte
     d'empilement : sans ce z-index la pilule passe SOUS l'overlay et le
     burger devient inatteignable pour refermer le menu. */
  position:relative; z-index:2;
  padding:10px 10px 10px 20px;
  background:rgba(245,242,234,.82);
  backdrop-filter:blur(16px) saturate(1.5);
  -webkit-backdrop-filter:blur(16px) saturate(1.5);
  border:1px solid rgba(255,255,255,.55);
  border-radius:16px;
  box-shadow:0 10px 34px -14px rgba(6,14,24,.45);
  transition:padding var(--dur-slow) var(--ease-out),
              border-radius var(--dur-slow) var(--ease-out),
              box-shadow var(--dur-slow) var(--ease-out);
}
.site-header.is-scrolled .header-inner{
  padding-top:6px; padding-bottom:6px;
  border-radius:13px;
  box-shadow:0 12px 30px -12px rgba(6,14,24,.55);
  /* 0,82 suffisait au repos, sur le hero. Dès qu'un titre en Anton blanc de
     42 px passe dessous, il traverse : le flou d'arrière-plan n'efface pas un
     contraste pareil. La pilule s'opacifie donc une fois le défilement engagé. */
  background:rgba(245,242,234,.95);
  /* Et sous un fond à 95 %, un flou de 16 px ne se voit plus : il ne restait
     qu'un filtre d'arrière-plan recalculé à chaque image de défilement, sur
     l'élément précisément qui est fixe à l'écran. Le rayon tombe à 6 px — de
     quoi adoucir les 5 % qui traversent encore, sans le coût. */
  backdrop-filter:blur(6px) saturate(1.5);
  -webkit-backdrop-filter:blur(6px) saturate(1.5);
}
.site-header.is-scrolled .brand img{ height:32px; }
.brand{ display:flex; align-items:center; gap:12px; flex:none; min-height:44px; }
.brand img{ height:38px; width:auto; transition:height var(--dur-slow) var(--ease-out); }
.main-nav{ display:flex; align-items:center; gap:30px; }
.nav-link{
  font-size:14.5px; font-weight:600; color:var(--ink-soft);
  position:relative; padding:6px 0; transition:color var(--dur-fast) var(--ease-out);
}
.nav-link::after{
  content:""; position:absolute; left:0; right:100%; bottom:0; height:2px;
  background:var(--spark-500); transition:right var(--dur-base) var(--ease-out);
}
.nav-link:hover, .nav-link[aria-current="page"]{ color:var(--navy-900); }
.nav-link:hover::after, .nav-link[aria-current="page"]::after{ right:0; }
.header-cta{ display:flex; align-items:center; gap:14px; flex:none; }
.burger{ display:none; flex-direction:column; justify-content:center; align-items:center; gap:5px; width:44px; height:44px; padding:0; }
.burger span{ width:22px; height:2px; background:var(--navy-900);
  transition:transform var(--dur-base) var(--ease-in-out), opacity var(--dur-fast) var(--ease-in-out); }
.mobile-nav{ display:none; }

@media (max-width: 880px){
  /* fixed et non sticky : le verrou de défilement (body{overflow:hidden}) posé
     à l'ouverture de l'overlay casse le contexte du sticky et fait remonter la
     pilule hors de l'écran — le burger devenait alors inatteignable. */
  .site-header{ position:fixed; top:0; left:0; right:0; }
  /* Le header passant hors du flux, la remontée de -82px du héros n'a plus
     rien à compenser : le texte remontait sous la pilule. Le sélecteur est
     préfixé par `body` pour l'emporter en spécificité (0,1,1 contre 0,1,0) —
     la règle `.hero{ margin-top:-82px }` est déclarée PLUS BAS dans la
     feuille, une media query ne suffit donc pas à la neutraliser. */
  body .hero, body .page-hero{ margin-top:0; }
  .main-nav{ display:none; }
  .header-cta .btn-small{ display:none; }
  .burger{ display:flex; }
  /* Overlay plein écran : opacity/visibility uniquement, jamais de max-height
     (qui déclencherait un reflow à chaque image). */
  .mobile-nav{
    /* `flex-start` et non `center` : centré, le menu laissait deux cents pixels
       de vide sous la pilule et autant en bas. Il commence maintenant sous
       l'en-tête, et défile si son contenu dépasse la hauteur d'écran. */
    display:flex; flex-direction:column; justify-content:flex-start; gap:0;
    position:fixed; inset:0; z-index:1;
    background:var(--navy-990);
    padding:104px 28px 40px;
    overflow-y:auto; overscroll-behavior:contain;
    opacity:0; visibility:hidden;
    transition:opacity var(--dur-slow) var(--ease-out), visibility var(--dur-slow);
  }
  .mobile-nav.is-open{ opacity:1; visibility:visible; }
  /* Le lien « Nos formations » vit maintenant dans .mn-groupe : sans lui ajouter
     ce sélecteur, il perdait la fonte et la taille des autres entrées. */
  .mobile-nav > a,
  .mn-groupe > a{
    padding:16px 2px;
    font-family:var(--font-display); text-transform:uppercase;
    font-size:clamp(24px, 7vw, 34px); line-height:1.1; color:#fff;
    border-bottom:1px solid var(--line-on-dark);
  }
  .mobile-nav > a[aria-current="page"],
  .mn-groupe > a[aria-current="page"]{ color:var(--spark-500); }
  .mobile-nav .btn{ margin-top:26px; border-bottom:0; }
  .mobile-nav .btn-block{ width:100%; font-family:var(--font-body); font-size:15px; }

  /* « Nos formations » et son bouton de dépliage sur la même ligne. Le lien
     reste un lien vers la page ; c'est le chevron qui ouvre les catégories.
     Confondre les deux obligerait à choisir entre naviguer et déplier. */
  .mn-groupe{
    display:flex; align-items:center; gap:10px;
    border-bottom:1px solid var(--line-on-dark);
  }
  /* Sur un écran de 375 px, le titre en Anton et le bouton se disputaient la
     ligne et le chevron débordait du cadre. Le titre cède la place en premier. */
  .mn-groupe > a{ min-width:0; overflow-wrap:anywhere; }
  .mn-groupe > a{ flex:1; border-bottom:0 !important; }
  .mn-toggle{
    flex:none; width:44px; height:44px;
    display:flex; align-items:center; justify-content:center;
    background:transparent; border:1px solid var(--line-on-dark);
    border-radius:50%; color:#fff; cursor:pointer;
    transition:transform var(--dur-base) var(--ease-out),
               border-color var(--dur-fast) var(--ease-out);
  }
  .mn-toggle svg{ width:18px; height:18px; }
  .mn-toggle[aria-expanded="true"]{ transform:rotate(180deg); border-color:var(--spark-500); }

  /* Repliées par défaut. `grid-template-rows` de 0fr à 1fr anime la hauteur
     sans avoir à deviner un `max-height` : la valeur s'ajuste au contenu. */
  .mn-reco{
    display:grid; grid-template-rows:0fr;
    opacity:0; overflow:hidden;
    transition:grid-template-rows var(--dur-base) var(--ease-out),
               opacity var(--dur-fast) var(--ease-out),
               padding var(--dur-base) var(--ease-out);
    padding:0 2px;
  }
  .mn-reco > *{ min-height:0; }        /* sans quoi la ligne refuse de se fermer */
  .mobile-nav.reco-open .mn-reco{
    grid-template-rows:1fr; opacity:1; padding:14px 2px 18px;
  }

  /* Mise au point : tout ce qui suit les catégories s'estompe pendant qu'elles
     sont ouvertes, pour que le regard reste sur le choix en cours. */
  .mn-reco ~ *{
    transition:filter var(--dur-base) var(--ease-out), opacity var(--dur-base) var(--ease-out);
  }
  .mobile-nav.reco-open .mn-reco ~ *{ filter:blur(3px); opacity:.4; }

  .mn-liste{ display:flex; flex-wrap:wrap; gap:8px; }
  .mn-liste a{
    display:inline-flex; align-items:center; min-height:44px;
    font-family:var(--font-mono); font-size:12.5px; font-weight:600;
    letter-spacing:.06em; color:#fff;
    padding:8px 16px; border-radius:999px;
    border:1px solid var(--line-on-dark);
  }
  .mn-liste a:active{ background:var(--spark-500); color:var(--on-spark); }

  /* Téléphone et courriel à portée de pouce : sur un téléphone, l'appel est
     souvent l'action la plus directe. */
  .mn-contact{
    display:flex; flex-direction:column; gap:10px;
    margin-top:26px; padding-top:20px;
    border-top:1px solid var(--line-on-dark);
  }
  /* Ces deux lignes sont les seuls raccourcis d'appel et d'e-mail du menu :
     sans padding elles ne mesuraient que 22 px de haut, la moitié d'une pulpe
     de doigt. La hauteur minimale les porte au seuil des 44 px. */
  .mn-contact a{
    display:flex; align-items:center; min-height:44px;
    font-family:var(--font-mono); font-size:14px; color:#C4CDD6;
    overflow-wrap:anywhere;
  }
  /* Croix quand le menu est ouvert. */
  .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); }
}

/* ---------- footer ---------- */
.site-footer{ background:var(--navy-950); color:#B9C4CF; }
/* Deux zones, et non cinq colonnes rigides. La grille d'origine imposait
   `1.5fr 1fr 1fr 1fr 1fr` jusqu'à 820 px : à 900 px, cinq colonnes de 121 px
   devaient afficher « R482 — Engins de chantier », qui se repliait sur trois
   lignes. Puis la bascule à deux colonnes faisait passer la hauteur de 446 à
   760 px d'un coup, sans palier intermédiaire.
   Ici la marque a sa colonne, et les liens forment leur propre grille fluide
   qui se replie d'elle-même de quatre à une colonne, sans point de rupture. */
/* `padding-block` et non `padding` : ces éléments portent aussi la classe
   .wrap, dont le `padding:0 24px` serait écrasé par la forme raccourcie. Le
   contenu du pied de page se collait au bord gauche de l'écran dès que la
   largeur passait sous 1120 px — invisible en grand écran, où la marge vient du
   centrage et non du padding. */
.footer-top{
  padding-block:64px 40px;
  display:grid;
  grid-template-columns:minmax(230px, 1fr) minmax(0, 2.5fr);
  gap:48px;
}
.footer-links{
  display:grid;
  grid-template-columns:repeat(auto-fit, minmax(150px, 1fr));
  gap:34px 30px;
}
/* 150 px, c'est la largeur qui tient sur un téléphone — et c'est le bon
   arbitrage là-bas : deux colonnes serrées valent mieux qu'une colonne unique
   qui rallonge le pied de page de trois cents pixels. Passé cette largeur en
   revanche, la même valeur faisait tenir quatre colonnes de 158 à 181 px, où
   cinq libellés sur quinze se repliaient sur deux lignes — « R482 — Engins de
   chantier », « jeremy@houdin-formation.com » — alors que la place existait.
   À 185 px, plus aucune césure, de la tablette au grand écran, pour soixante
   pixels de hauteur en plus. Et entre 600 et 900 px le pied de page y gagne
   même en compacité : trois colonnes qui cassent occupent plus de place que
   deux colonnes qui ne cassent pas. */
@media (min-width: 461px){
  .footer-links{ grid-template-columns:repeat(auto-fit, minmax(185px, 1fr)); }
}
.footer-brand img{ height:40px; margin-bottom:14px; }
.footer-brand p{ font-size:14px; line-height:1.7; max-width:34ch; color:#8FA0AF; }
/* Ces titres de colonnes etaient des h4 : le document passait donc de h2 a h4
   sans h3, un saut de niveau que le RGAA refuse (9.1.3). Ce sont des sections
   de premier niveau du pied de page, pas des sous-sections du dernier titre du
   contenu : h2 est le niveau juste. `font-weight` et `line-height` sont repris
   explicitement, sinon la regle `h2, .h2` degraisserait le texte et le tasserait. */
.footer-col h2{
  font-family:var(--font-mono); font-size:11px; letter-spacing:.14em; text-transform:uppercase;
  color:var(--spark-500); margin-bottom:16px;
  font-weight:700; line-height:inherit;
}
/* `jeremyhoudin95@gmail.com` est un mot insécable de près de 180 px : dans une
   colonne de cette largeur il débordait, quelle que soit la taille d'écran.
   `anywhere` autorise la coupure — sur une adresse, mieux vaut deux lignes
   qu'un texte qui sort de sa colonne. */
.footer-col a, .footer-col p{
  display:block; font-size:14.5px; color:#C4CDD6; padding:10px 0;
  overflow-wrap:anywhere;
}
.footer-col a:hover{ color:#fff; }
/* Le filet était posé sur la bordure de l'élément, or celui-ci porte aussi
   .wrap : il partait donc du bord du conteneur et non de celui du contenu —
   24 px trop à gauche et 24 px trop à droite, et jusqu'au bord de l'écran sous
   1180 px. Un trait de séparation doit s'aligner sur ce qu'il sépare : il est
   maintenant peint par un pseudo-élément calé sur la gouttière. */
.footer-bottom{
  position:relative; padding-block:22px;
  display:flex; justify-content:space-between; align-items:center; gap:16px; flex-wrap:wrap;
  font-family:var(--font-mono); font-size:12px; color:#8FA0AF;   /* était 4,29:1 */
}
.footer-bottom::before{
  content:""; position:absolute; top:0; left:24px; right:24px;
  height:1px; background:var(--line-on-dark);
}
/* Un seul point de rupture, et il ne concerne que la mise en colonne de la
   marque : passé ce seuil elle passe au-dessus, et les liens récupèrent toute
   la largeur — ce qui les compacte au lieu de les allonger. */
@media (max-width: 860px){
  .footer-top{ grid-template-columns:1fr; gap:40px; }
}
/* Sur un téléphone, le pied de page mesurait 1128 px de haut : presque trois
   écrans. La zone tactile des liens reste à 40 px de haut malgré le padding
   réduit, grâce à la hauteur de ligne. */
@media (max-width: 560px){
  .footer-col a, .footer-col p{ padding:8px 0; }
  /* Le padding réduit ramenait la zone tactile à 39 px : on la rétablit sans
     rendre le pied de page plus haut qu'il ne l'était avec 10 px de padding. */
  .footer-col a{ display:flex; align-items:center; min-height:44px; }
  .footer-links{ gap:26px 24px; }
  .footer-top{ padding-block:52px 32px; }
}

/* ---------- section shells ---------- */
.section{ padding:96px 0; position:relative; overflow:hidden; }
/* Conservee : utilisee par les pages formation-caces-r48x en cours
   d'ecriture dans le dossier principal. */
.section-tight{ padding:64px 0; }
.on-light{ background:var(--paper); color:var(--ink); }
.on-alt{ background:var(--paper-alt); color:var(--ink); }
.on-dark{ background:var(--navy-950); color:#EDEFEF; }
.on-dark h1, .on-dark h2, .on-dark h3{ color:#fff; }

.blueprint-grid{
  position:absolute; inset:0; pointer-events:none;
  background-image:
    linear-gradient(rgba(255,255,255,.045) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.045) 1px, transparent 1px);
  background-size:44px 44px;
  -webkit-mask-image:linear-gradient(180deg, rgba(0,0,0,.9), transparent 85%);
          mask-image:linear-gradient(180deg, rgba(0,0,0,.9), transparent 85%);
}

/* ---------- hero ---------- */
.hero{
  position:relative;
  background:linear-gradient(158deg, var(--navy-900) 0%, var(--navy-990) 72%);
  color:#fff;
  padding:96px 0 104px;
  margin-top:-82px;          /* la pilule flotte par-dessus la scène */
  padding-top:178px;
}
/* Lumière rasante : une seule source douce, façon éclairage d'atelier. */
.hero::after{
  content:""; position:absolute; inset:0; pointer-events:none;
  background:radial-gradient(120% 80% at 78% 18%, rgba(120,160,205,.20), transparent 58%);
}
.hero > .wrap{ position:relative; z-index:1; }
.hero-inner{ display:grid; grid-template-columns:1.1fr .9fr; gap:56px; align-items:center; }
.hero-badges{ display:flex; flex-wrap:wrap; gap:10px; margin-top:28px; }
.hero-badge{
  font-family:var(--font-mono); font-size:12px; letter-spacing:.06em;
  color:#C4CDD6; border:1px solid var(--line-on-dark); border-radius:999px;
  padding:7px 14px; display:flex; align-items:center; gap:8px;
}
.hero-badge b{ color:var(--spark-500); font-weight:600; }
/* Variante posée sur fond clair (page À propos) : l'orange vif n'y tient pas. */
.hero-badge.light{ color:var(--ink-soft); border-color:var(--line); }
.hero-badge.light b{ color:var(--spark-700); }
.hero-cta{ display:flex; gap:14px; margin-top:34px; flex-wrap:wrap; }
.hero-visual{ position:relative; display:flex; justify-content:center; }

/* ---------- plaque constructeur (objet héros) ----------
   Reprend la géométrie du logo : coin supérieur gauche chanfreiné,
   fond navy, filet clair. Porte de l'information, pas de la décoration. */
.machine-plate{
  position:relative;
  width:100%; max-width:430px; margin-left:auto;
  background:linear-gradient(152deg, var(--navy-800), var(--navy-950) 72%);
  border:1px solid rgba(255,255,255,.16);
  border-radius:32px 12px 12px 12px;
  padding:24px 26px 22px;
  box-shadow:0 2px 4px rgba(0,0,0,.2), 0 34px 60px -26px rgba(0,0,0,.75);
}
.machine-plate::before,
.machine-plate::after{
  content:""; position:absolute; bottom:13px; width:8px; height:8px; border-radius:50%;
  background:radial-gradient(circle at 34% 30%, #8B99A7, #253647);
  box-shadow:inset 0 -1px 1px rgba(0,0,0,.5);
}
.machine-plate::before{ left:14px; }
.machine-plate::after{ right:14px; }

.plate-head{
  display:flex; justify-content:space-between; align-items:baseline; gap:12px;
  border-bottom:1px solid rgba(255,255,255,.22); padding-bottom:13px;
}
.plate-head strong{
  font-family:var(--font-display); font-size:17px; letter-spacing:.05em;
  text-transform:uppercase; color:#fff;
}
.plate-head span{
  font-family:var(--font-mono); font-size:11px; letter-spacing:.12em;
  text-transform:uppercase; color:#93A2B1;
}
.plate-row{
  display:grid; grid-template-columns:60px 1fr auto; gap:14px; align-items:baseline;
  padding:11px 0; border-bottom:1px dashed rgba(255,255,255,.14);
}
.plate-row b{
  font-family:var(--font-mono); font-size:12.5px; font-weight:600;
  letter-spacing:.04em; color:var(--spark-500);
}
.plate-row span{ font-size:14px; color:#DCE3EA; }
.plate-row i{
  font-style:normal; font-family:var(--font-mono); font-size:11px;
  letter-spacing:.05em; color:#93A2B1;
}
.plate-foot{ display:flex; flex-wrap:wrap; gap:8px; margin-top:16px; padding-top:2px; }
.plate-chip{
  font-family:var(--font-mono); font-size:10.5px; font-weight:600;
  letter-spacing:.06em; text-transform:uppercase;
  padding:5px 9px; border-radius:4px;
  background:var(--spark-500); color:var(--on-spark);
}
.plate-chip.ghost{
  background:transparent; color:var(--dark-body);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.24);
}
@media (max-width: 900px){
  .hero-inner{ grid-template-columns:1fr; gap:40px; }
  /* order:-1 faisait passer la plaque décorative AU-DESSUS du h1 : sur mobile,
     le premier écran ne montrait qu'un logo, titre et CTA sous la ligne de flottaison. */
  .hero-visual{ order:0; }
  .machine-plate{ margin-left:0; max-width:none; }
  .hero{ padding-top:118px; padding-bottom:72px; }
}
@media (max-width: 420px){
  .plate-row{ grid-template-columns:54px 1fr; }
  .plate-row i{ display:none; }   /* la 3e colonne saute avant de casser la mise en page */
}

/* ---------- bande de faits ----------
   Asymétrique à dessein : deux chiffres qui pèsent à gauche, trois faits en
   appui à droite. Une grille de quatre cellules égales aurait obligé à trouver
   deux chiffres de plus, et c'est ainsi qu'on invente des « 100 % ». */
.facts-band{
  background:var(--navy-950);
  border-top:1px solid var(--line-on-dark);
  border-bottom:1px solid var(--line-on-dark);
  padding:34px 0;
}
.facts-inner{
  display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  gap:38px; align-items:center;
}
.facts-figures{ display:flex; gap:46px; flex-wrap:wrap; }
.fact{ display:flex; align-items:baseline; gap:8px; flex-wrap:wrap; max-width:22ch; }
.fact .stat-num{
  font-family:var(--font-display);
  font-size:clamp(38px,4.6vw,58px);
  line-height:.9; color:var(--spark-500);
}
.fact-unit{
  font-family:var(--font-mono); font-size:14px; font-weight:600;
  color:var(--spark-500); letter-spacing:.02em;
}
.fact-label{
  flex:1 1 100%; margin-top:8px;
  font-size:14px; line-height:1.45; color:var(--dark-body);
}
/* Filets plutôt que puces : on est dans un registre de fiche technique. */
.facts-notes{ list-style:none; margin:0; padding:0; }
.facts-notes li{
  font-family:var(--font-mono); font-size:12.5px; line-height:1.5;
  color:#9AA7B2; padding:9px 0; border-top:1px solid var(--line-on-dark);
}
.facts-notes li:first-child{ border-top:0; padding-top:0; }
.facts-notes li:last-child{ padding-bottom:0; }
@media (max-width: 860px){
  .facts-inner{ grid-template-columns:1fr; gap:26px; }
  .facts-figures{ gap:34px; }
}

/* ---------- cards: formations ----------
   Grille de 6 : 3 cartes en span 2 puis 2 en span 3. Cinq cartes dans une
   grille de 3 laissaient un trou permanent en deuxième rangée. */
.cards-grid{ display:grid; grid-template-columns:repeat(6,1fr); gap:24px; }
.cards-grid > .reco-card{ grid-column:span 2; }
.cards-grid > .reco-card:nth-child(4),
.cards-grid > .reco-card:nth-child(5){ grid-column:span 3; }
@media (max-width: 980px){
  .cards-grid{ grid-template-columns:repeat(2,1fr); }
  .cards-grid > .reco-card,
  .cards-grid > .reco-card:nth-child(4),
  .cards-grid > .reco-card:nth-child(5){ grid-column:auto; }
}
@media (max-width: 640px){ .cards-grid{ grid-template-columns:1fr; } }

.reco-card{
  background:var(--white);
  border:1px solid var(--line);
  border-radius:4px;
  padding:28px;
  display:flex; flex-direction:column; gap:14px;
  box-shadow:var(--shadow-card);
  transition:transform var(--dur-base) var(--ease-out),
              box-shadow var(--dur-base) var(--ease-out),
              border-color var(--dur-base) var(--ease-out);
  position:relative;
}
.reco-card:hover{ transform:translateY(-5px); box-shadow:var(--shadow-lift); border-color:var(--navy-700); }
/* La carte « habilitation électrique » se distingue par sa pastille de code,
   déjà orange, et non plus par un liseré : le trait latéral coloré est le
   marqueur générique par excellence. */
.reco-card.accent{ border-color:var(--spark-500); }
.reco-code{
  align-self:flex-start;
  font-family:var(--font-mono); font-size:12px; font-weight:600; letter-spacing:.08em;
  background:var(--navy-950); color:var(--spark-500);
  padding:5px 10px; border-radius:6px;
}
.reco-card.accent .reco-code,
.reco-code.accent{ background:var(--spark-100); color:var(--spark-700); }  /* était 3,54:1 */
.reco-icon{ width:40px; height:40px; color:var(--navy-800); }
.reco-card h3{ font-size:19px; }
.reco-desc{ color:var(--ink-soft); font-size:15px; line-height:1.6; flex:1; }
.reco-link{ display:inline-flex; align-items:center; gap:6px; font-weight:700; font-size:14px; color:var(--navy-900); margin-top:4px; }
.reco-link svg{ width:14px; height:14px; transition:transform var(--dur-fast) var(--ease-out-back); }
.reco-card:hover .reco-link svg{ transform:translateX(4px); }
/* « Voir le détail » est le seul chemin vers la page de formation, et il ne
   mesurait que 22 px de haut. Plutôt que de le grossir — il perdrait son rôle
   de discrète mention de fin de carte — on étend sa zone active à la carte
   entière : c'est déjà elle que le doigt vise. La carte ne contient aucun
   autre lien, rien n'est donc recouvert. */
.reco-link::after{ content:""; position:absolute; inset:0; border-radius:inherit; }

/* ---------- vitrine 3D (embed Sketchfab piloté au défilement) ---------- */
.showcase-3d{ background:var(--navy-990); padding:88px 0; position:relative; overflow:hidden; }
.showcase-3d .section-head{ margin-inline:auto; text-align:center; margin-bottom:38px; }
/* ---------- scène 3D : le modèle se diffuse dans la page ----------
   Pas de cadre, pas de fond propre. Ce qui tient l'objet, c'est une lumière
   rasante derrière lui et une ombre au sol — comme la plaque constructeur du
   hero, l'objet flotte sur le navy au lieu d'être posé dans une boîte. */
.stage3d{
  position:relative;
  min-height:clamp(340px, 46vw, 520px);
  display:grid; place-items:center;
  margin-top:8px;
}
.stage3d-glow{
  position:absolute; inset:-8% -12%;
  background:
    radial-gradient(46% 52% at 50% 42%, rgba(120,160,205,.20), transparent 70%),
    radial-gradient(30% 34% at 62% 30%, rgba(238,113,17,.13), transparent 72%);
  pointer-events:none;
}
/* Ombre portée : donne le sol sans dessiner de sol. */
.stage3d-floor{
  position:absolute; left:50%; bottom:12%; transform:translateX(-50%);
  width:min(52%, 470px); height:34px;
  background:radial-gradient(50% 50% at 50% 50%, rgba(0,0,0,.55), transparent 72%);
  filter:blur(6px); pointer-events:none;
}
.stage3d-scene{
  position:relative; width:100%; height:100%;
  display:grid; place-items:center; grid-template-areas:"pile";
}
/* Les pièces se superposent dans la même cellule : le fondu enchaîné se joue
   sans décalage de mise en page. */
.stage3d-piece{
  grid-area:pile;
  width:100%; display:flex; justify-content:center;
  transition:opacity var(--dur-slow) var(--ease-out),
             transform var(--dur-slow) var(--ease-out);
}
.stage3d-piece.is-entrant{ opacity:0; transform:translateY(10px) scale(.97); }
.stage3d-piece.is-sortant{ opacity:0; transform:scale(1.03); pointer-events:none; }

.stage3d-piece model-viewer{
  width:min(100%, 760px);
  height:clamp(320px, 44vw, 500px);
  background:transparent;
  --poster-color:transparent;
}
/* Le schéma tient lieu de modèle tant qu'aucun .glb n'est déposé. */
.stage3d-schema{ width:min(100%, 780px); height:auto; }

/* L'iframe Sketchfab est appelée avec transparent=1 : sans fond propre, elle
   se fond dans la section au lieu de former une vignette rapportée. */
/* Tous les modèles ne se valent pas : `transparent=1` rend le fond du lecteur
   transparent, mais reste sans effet si l'auteur a posé un plan de fond dans sa
   propre scène. La chargeuse R482 arrivait ainsi en rectangle noir franc au
   milieu du navy, là où le chariot R489 flottait librement.
   Un masque en fondu efface les bords : le rectangle se dissout dans la page au
   lieu de s'y découper. Sans effet visible sur les modèles déjà transparents. */
.stage3d-piece.is-iframe{
  -webkit-mask-image:radial-gradient(closest-side, #000 58%, rgba(0,0,0,.55) 82%, transparent 99%);
  mask-image:radial-gradient(closest-side, #000 58%, rgba(0,0,0,.55) 82%, transparent 99%); width:100%; }
.stage3d-piece iframe{
  width:min(100%, 860px); height:clamp(330px, 46vw, 520px);
  border:0; display:block; margin-inline:auto; background:transparent;
}

.viewer-credit{
  text-align:center; margin:10px 0 0;
  font-size:12px; color:#8FA0B2; min-height:1em;
}
.viewer-credit a{ color:var(--dark-body); text-decoration:underline; text-underline-offset:2px; }
.viewer-credit a:hover{ color:#fff; }

.stage3d-note{
  text-align:center; margin:6px 0 0;
  font-family:var(--font-mono); font-size:11.5px; letter-spacing:.07em;
  text-transform:uppercase; color:#8FA0B2;
}

/* ---------- sélecteur d'engin ---------- */
.model-switch{
  display:flex; justify-content:center; gap:10px; flex-wrap:wrap;
  margin-top:26px;
}
.model-switch button{
  display:flex; flex-direction:column; align-items:flex-start; gap:2px;
  padding:10px 18px;
  border:1px solid var(--line-on-dark);
  border-radius:14px 4px 4px 4px;          /* le chanfrein de marque, en petit */
  color:var(--dark-body);
  transition:border-color var(--dur-fast) var(--ease-out),
             background var(--dur-fast) var(--ease-out),
             color var(--dur-fast) var(--ease-out),
             transform var(--dur-base) var(--ease-out-back);
}
.model-switch button:hover{ border-color:rgba(255,255,255,.34); transform:translateY(-2px); }
.model-switch .me-code{
  font-family:var(--font-mono); font-size:12px; font-weight:600; letter-spacing:.08em;
}
.model-switch .me-nom{ font-size:12.5px; opacity:.72; }
/* L'engin actif porte l'orange : un seul élément sélectionné à la fois, le
   signal reste un signal. */
.model-switch button[aria-selected="true"]{
  background:var(--spark-500); color:var(--on-spark);
  border-color:var(--spark-500);
  box-shadow:0 10px 24px -12px rgba(238,113,17,.6);
}
.model-switch button[aria-selected="true"] .me-nom{ opacity:.85; }

@media (max-width:640px){
  .stage3d{ min-height:300px; }
  /* Le libellé disparu, il ne reste que le code sur une ligne : sans hauteur
     minimale le bouton retombait à 38 px. */
  .model-switch button{ padding:9px 16px; min-height:44px; justify-content:center; }
  .model-switch .me-nom{ display:none; }   /* le code suffit à choisir */
}
@media (max-width:640px){
  .showcase-3d{ padding:64px 0; }
}

/* ---------- feature grid ---------- */
.features-grid{ display:grid; grid-template-columns:repeat(4,1fr); gap:28px; }
@media (max-width: 980px){ .features-grid{ grid-template-columns:1fr 1fr; } }
@media (max-width: 560px){ .features-grid{ grid-template-columns:1fr; } }
.feature{ display:flex; flex-direction:column; gap:12px; }
.feature-icon{ width:44px; height:44px; color:var(--spark-500); }
.feature h3{ font-size:17px; }
.feature p{ font-size:14.5px; color:var(--ink-soft); line-height:1.6; }
.on-dark .feature p{ color:var(--dark-body); }   /* était 2,92:1 */
.feature p a{ color:var(--spark-700); text-decoration:underline; text-underline-offset:3px; }
.on-dark .feature p a{ color:#fff; }
/* En fin de phrase, ce lien est un lien de lecture — sa hauteur suit celle de
   la ligne, et c'est très bien sur un écran de bureau où l'on vise au curseur.
   Au doigt, 17 px ne se vise pas : sur petit écran il quitte le fil du
   paragraphe et devient une ligne à lui, avec la garde des 44 px. */
/* Même traitement pour les liens qui closent un paragraphe sans ponctuation
   après eux : sur écran tactile ils quittent le fil du texte et deviennent une
   ligne d'action à part entière. La règle ne vaut que pour ces deux-là — un
   lien suivi d'un point final laisserait le point seul sur la ligne suivante. */
@media (max-width:900px){
  .feature p a,
  .reco-visual-lede > a:last-child{
    display:flex; align-items:center; min-height:44px;
    margin-top:2px; font-weight:600;
  }
}

/* ---------- steps ---------- */
.steps{ display:grid; grid-template-columns:repeat(3,1fr); gap:28px; counter-reset:step; }
@media (max-width: 780px){ .steps{ grid-template-columns:1fr; } }
/* Variante empilée (colonne étroite de la page contact). */
.steps.stack{ grid-template-columns:1fr; gap:16px; margin-top:24px; }
.step{ position:relative; padding:28px 24px; border:1px solid var(--line); border-radius:var(--radius-m); }
.on-dark .step{ border-color:var(--line-on-dark); }
/* Les .step sont posés sur fond clair (--paper-alt) : l'orange vif n'y tenait
   que 2,38:1. Il reste en --spark-500 dans un contexte sombre. */
.step-num{ font-family:var(--font-mono); font-size:13px; color:var(--spark-700); display:block; margin-bottom:14px; }
.on-dark .step-num{ color:var(--spark-500); }
.step h3{ margin-bottom:8px; font-size:18px; }
.step p{ color:var(--ink-soft); font-size:14.5px; line-height:1.6; }
.on-dark .step p{ color:#B9C4CF; }

/* ---------- CTA band ---------- */
.cta-band{
  background:var(--spark-500); color:var(--on-spark); padding:64px 0; text-align:center;
  position:relative; overflow:hidden;
}
.cta-band h2{ color:var(--on-spark); }
.cta-band .lede{ color:rgba(10,24,38,.92); margin-inline:auto; }
.cta-band .btn-primary{ background:var(--navy-950); color:var(--white); box-shadow:0 10px 24px -10px rgba(10,24,38,.5); }
.cta-band .btn-primary:hover{ background:var(--navy-900); color:var(--white); }
.cta-band .btn-outline{ color:var(--navy-950); box-shadow:inset 0 0 0 1.5px rgba(10,24,38,.4); }
.cta-band .btn-outline:hover{ box-shadow:inset 0 0 0 1.5px var(--navy-950); }
.cta-actions{ display:flex; gap:14px; justify-content:center; margin-top:28px; flex-wrap:wrap; }

/* ---------- contact cards ---------- */
.contact-grid{ display:grid; grid-template-columns:repeat(3,1fr); gap:20px; }
@media (max-width: 780px){ .contact-grid{ grid-template-columns:1fr; } }
.contact-card{
  display:flex; align-items:center; gap:16px; padding:22px;
  background:var(--white); border:1px solid var(--line); border-radius:var(--radius-m);
  transition:transform var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out);
}
.contact-card:hover{ transform:translateY(-3px); box-shadow:var(--shadow-card); }
.contact-card .ci{ width:44px; height:44px; flex:none; border-radius:10px; background:var(--navy-950); color:var(--spark-500); display:flex; align-items:center; justify-content:center; }
.contact-card .ci svg{ width:20px; height:20px; }
.contact-label{ display:block; font-family:var(--font-mono); font-size:11px; letter-spacing:.08em; text-transform:uppercase; color:var(--ink-faint); }
.contact-value{ display:block; font-weight:700; font-size:15px; margin-top:2px; }

/* ---------- form ---------- */
.form-card{ background:var(--white); border:1px solid var(--line); border-radius:var(--radius-l); padding:36px; box-shadow:var(--shadow-card); }
.form-row{ display:grid; grid-template-columns:1fr 1fr; gap:18px; }
@media (max-width:600px){ .form-row{ grid-template-columns:1fr; } }
.field{ display:flex; flex-direction:column; gap:8px; margin-bottom:18px; }
.field label{ font-size:13px; font-weight:700; color:var(--ink); }
.field input, .field select, .field textarea{
  padding:13px 14px; border:1.5px solid var(--line); border-radius:var(--radius-s);
  background:var(--paper); color:var(--ink);
  transition:border-color var(--dur-fast) var(--ease-out), background var(--dur-fast) var(--ease-out);
}
.field input:focus, .field select:focus, .field textarea:focus{
  outline:none; border-color:var(--navy-700); background:#fff;
}
.field textarea{ resize:vertical; min-height:120px; }
.form-note{ font-size:13px; color:var(--ink-faint); margin-top:6px; }

/* ---------- about page ---------- */
.about-hero{ display:grid; grid-template-columns:.8fr 1.2fr; gap:56px; align-items:center; }
@media (max-width:900px){ .about-hero{ grid-template-columns:1fr; } }
.monogram-plate{
  aspect-ratio:1; border-radius:var(--radius-l); background:var(--navy-950);
  display:flex; align-items:center; justify-content:center; position:relative; overflow:hidden;
  box-shadow:var(--shadow-lift);
}
.monogram-plate img{ width:60%; }
.value-grid{ display:grid; grid-template-columns:repeat(3,1fr); gap:24px; }
@media (max-width:780px){ .value-grid{ grid-template-columns:1fr; } }
.value-card{ padding:26px; border:1px solid var(--line); border-radius:var(--radius-m); background:var(--white); }
.value-card .n{ font-family:var(--font-mono); color:var(--ink-faint); font-size:13px; }

/* ---------- blog ---------- */
.article{ max-width:720px; margin:0 auto; padding:56px 0; border-top:1px solid var(--line); }
.article:first-of-type{ border-top:0; padding-top:0; }
.article-meta{ font-family:var(--font-mono); font-size:12px; letter-spacing:.06em; color:var(--ink-faint); display:flex; gap:14px; margin-bottom:14px; text-transform:uppercase; }
.article h2{ font-size:clamp(24px,3.2vw,32px); margin-bottom:18px; }
.article p{ margin-bottom:16px; color:var(--ink-soft); font-size:16px; line-height:1.75; }
.article p strong{ color:var(--ink); }
.article ul{ margin:0 0 16px; padding-left:0; }
.article li{ list-style:none; padding-left:26px; position:relative; margin-bottom:10px; color:var(--ink-soft); }
.article li::before{ content:""; position:absolute; left:0; top:9px; width:8px; height:2px; background:var(--spark-500); }

/* Liens en plein texte dans un article. Le reset ligne 83 met color:inherit et
   text-decoration:none : sans cette règle, un lien de maillage interne est
   strictement indiscernable du texte qui l'entoure. --spark-500 ne convient
   pas ici (2,68:1 sur --paper, sous le seuil AA) ; --navy-700 donne 8,55:1,
   et le soulignement porte la distinction sans dépendre de la couleur.
   :not(.btn) laisse les boutons « Lire l'article complet » intacts. */
.article p a:not(.btn), .article li a:not(.btn){
  color:var(--navy-700); text-decoration:underline;
  text-underline-offset:3px; text-decoration-thickness:1px;
  transition:color .2s ease, text-decoration-color .2s ease;
}
.article p a:not(.btn):hover, .article li a:not(.btn):hover{
  color:var(--navy-900); text-decoration-thickness:2px;
}
.tag-row{ display:flex; gap:8px; margin-top:20px; flex-wrap:wrap; }
.tag{ font-family:var(--font-mono); font-size:11px; letter-spacing:.06em; text-transform:uppercase; padding:5px 10px; border-radius:999px; background:var(--paper-alt); color:var(--ink-soft); }

/* ---------- misc ---------- */
/* Lu par les lecteurs d'écran, invisible à l'œil. `display:none` ne convient
   pas : il retirerait aussi le texte de la vocalisation. */
.sr-only{
  position:absolute; width:1px; height:1px; margin:-1px; padding:0;
  overflow:hidden; clip:rect(0 0 0 0); clip-path:inset(50%); white-space:nowrap; border:0;
}

.skip-link{
  position:absolute; left:-999px; top:0; background:var(--navy-950); color:#fff;
  padding:12px 18px; z-index:200; border-radius:0 0 8px 0;
}
.skip-link:focus{ left:0; }
/* L'anneau de focus doit atteindre 3:1 contre le fond qu'il touche. L'orange
   vif ne tient ce seuil que sur le navy : sur le creme de la page il tombe a
   2,7:1 et sur les cartes blanches a 3,0:1. Le ton fonce sert donc de defaut,
   et l'orange vif reste reserve aux sections sombres, ou il est a 6,0:1. */
:focus-visible{ outline:2px solid var(--spark-700); outline-offset:2px; }
.on-dark :focus-visible,
.hero :focus-visible,
.page-hero :focus-visible,
.site-footer :focus-visible,
.facts-band :focus-visible,
.showcase-3d :focus-visible,
.mobile-nav :focus-visible{ outline-color:var(--spark-500); }

/* Anneau bicolore sur les boutons. L'anneau orange par défaut disparaissait sur
   .btn-primary, qui est lui-même orange : un utilisateur au clavier perdait la
   trace du focus sur le bouton le plus important du site. Le trait blanc tranche
   sur l'orange du bouton, le halo navy tranche sur le crème de la page — la paire
   fonctionne sur les trois fonds du site. */
.btn:focus-visible{
  outline:2px solid #fff;
  outline-offset:0;
  box-shadow:0 0 0 4px var(--navy-990);
}
.on-dark .btn:focus-visible,
.hero .btn:focus-visible,
.page-hero .btn:focus-visible{ box-shadow:0 0 0 4px var(--spark-500); }

/* Huitième état, jusqu'ici absent : le bouton d'envoi n'avait aucune apparence
   désactivée, et rien n'empêchait un second clic pendant l'ouverture du client
   de messagerie. */
.btn:disabled, .btn[aria-disabled="true"]{
  opacity:.5; cursor:not-allowed; transform:none; box-shadow:none;
}
.page-hero{
  background:linear-gradient(158deg, var(--navy-900) 0%, var(--navy-990) 78%);
  color:#fff; position:relative;
  margin-top:-82px;                /* la pilule flotte par-dessus */
  padding:150px 0 64px;
}
.page-hero::after{
  content:""; position:absolute; inset:0; pointer-events:none;
  background:radial-gradient(110% 80% at 80% 12%, rgba(120,160,205,.16), transparent 60%);
}
.page-hero > .wrap{ position:relative; z-index:1; }
@media (max-width:900px){ .page-hero{ padding:112px 0 52px; } }
/* Le header reste sticky/fixed par-dessus : sans ça, une ancre comme
   formations.html#r482 arrive avec le badge et le titre masqués dessous. */
:target{ scroll-margin-top:158px; }
@media (max-width:880px){
  :target{ scroll-margin-top:140px; }
}
/* La grille vivait dans un style inline sur contact.html, que seul un !important
   pouvait contrer. Elle est ici, donc les media queries fonctionnent normalement. */
.contact-layout{
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:48px;
  align-items:start;
}
@media (max-width:860px){
  .contact-layout{ grid-template-columns:1fr; }
}
.page-hero h1{ font-size:clamp(32px,5vw,52px); }
.page-hero .lede{ margin-top:16px; }
.breadcrumb{
  font-family:var(--font-mono); font-size:12px; color:#8FA0AF;
  margin-bottom:18px; letter-spacing:.04em;
  display:flex; align-items:center; gap:8px; flex-wrap:wrap;
}
.breadcrumb a{ color:inherit; text-decoration:underline; text-underline-offset:3px; }
.breadcrumb a:hover{ color:#fff; }
.breadcrumb [aria-current="page"]{ color:#C4CDD6; }
/* Un fil d'Ariane est une navigation, pas un lien de lecture au fil d'une
   phrase : l'exemption des liens en ligne ne joue pas ici, et ses entrées ne
   faisaient que 19 px de haut. Sur écran tactile elles passent à 44 px ; la
   marge basse se resserre d'autant, le bloc ne gagne que treize pixels. */
@media (max-width:900px){
  .breadcrumb{ margin-bottom:6px; }
  .breadcrumb a{ display:inline-flex; align-items:center; min-height:44px; }
}

/* ==========================================================================
   PHASE 3 — mouvement
   Règles suivies partout ici : on n'anime que `transform` et `opacity`,
   jamais `width`/`height`/`top`/`left` (celles-ci déclenchent un recalcul de
   mise en page à chaque image). Durées : 180-420 ms pour les micro-interactions,
   560 ms pour les apparitions, 800 ms de plafond absolu. Aucune courbe `linear`.
   Le bloc `prefers-reduced-motion` en fin de section neutralise l'ensemble.
   ========================================================================== */

/* ---------- entrée du héros ----------
   Le héros est au-dessus de la ligne de flottaison : il ne peut pas être révélé
   au défilement, il s'anime au chargement. La cascade suit l'ordre de lecture. */
@keyframes rise-in{
  from{ opacity:0; transform:translateY(16px); }
  to  { opacity:1; transform:none; }
}
@keyframes plate-in{
  from{ opacity:0; transform:translateY(24px) scale(.985); }
  to  { opacity:1; transform:none; }
}

.hero-inner > div > .eyebrow,
.hero-inner > div > h1,
.hero-inner > div > .lede,
.hero-inner > div > .hero-cta{
  animation:rise-in 620ms var(--ease-out) backwards;
}
.hero-inner > div > .eyebrow  { animation-delay:60ms; }
.hero-inner > div > h1        { animation-delay:140ms; }
.hero-inner > div > .lede     { animation-delay:240ms; }
.hero-inner > div > .hero-cta { animation-delay:340ms; }

/* La plaque arrive après le texte : c'est l'objet, pas le message. */
.machine-plate{ animation:plate-in 640ms var(--ease-out) 200ms backwards; }
/* `nth-of-type` compte les <div> frères, pas les `.plate-row` : `.plate-head`
   occupe la position 1. Les cinq lignes sont donc en positions 2 à 6. */
.plate-row{ animation:rise-in 440ms var(--ease-out) backwards; }
.plate-row:nth-of-type(2){ animation-delay:400ms; }
.plate-row:nth-of-type(3){ animation-delay:440ms; }
.plate-row:nth-of-type(4){ animation-delay:480ms; }
.plate-row:nth-of-type(5){ animation-delay:520ms; }
.plate-row:nth-of-type(6){ animation-delay:560ms; }
.plate-foot{ animation:rise-in 440ms var(--ease-out) 620ms backwards; }

/* Survol d'une ligne de plaque : le repère s'allume, la ligne avance d'un cran.
   `padding-left` serait une animation de mise en page — on décale en transform. */
.plate-row{
  transition:transform var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}
.machine-plate:hover .plate-row{ opacity:.62; transition:opacity var(--dur-base) var(--ease-out); }
.machine-plate .plate-row:hover{ opacity:1; transform:translateX(4px); }
.plate-row b{ transition:color var(--dur-fast) var(--ease-out); }
.plate-row:hover b{ color:var(--spark-500); }

/* ---------- barre de progression de lecture ----------
   Injectée par le script, jamais dans le HTML : cinq pages à maintenir.
   `scaleX` sur une barre de largeur fixe — aucun recalcul de mise en page. */
.read-progress{
  position:fixed; top:0; left:0; right:0; height:3px;
  z-index:101;                 /* au-dessus du header (100) */
  pointer-events:none;
  background:rgba(255,255,255,.06);
  opacity:0; transition:opacity var(--dur-slow) var(--ease-out);
}
.read-progress.is-active{ opacity:1; }
.read-progress > span{
  display:block; height:100%; transform-origin:0 50%;
  transform:scaleX(var(--p, 0));
  background:linear-gradient(90deg, var(--spark-600), var(--spark-500));
}
/* Pendant l'overlay mobile, la page ne défile plus : la barre n'a plus de sens. */
body.nav-is-open .read-progress{ opacity:0; }

/* ---------- compteurs ----------
   Chiffres à chasse fixe : sans cela, la largeur du nombre saute à chaque
   image pendant le décompte et fait tressauter tout le bandeau. */
.stat-num{ font-variant-numeric:tabular-nums; font-feature-settings:"tnum" 1; }

/* ---------- transitions de page ----------
   Amélioration progressive : les navigateurs sans View Transitions ignorent
   simplement ces règles et naviguent normalement. */
@view-transition{ navigation:auto; }
::view-transition-old(root){ animation:vt-out 200ms var(--ease-in-out) both; }
::view-transition-new(root){ animation:vt-in  320ms var(--ease-out) both; }
@keyframes vt-out{ to  { opacity:0; transform:translateY(-8px); } }
@keyframes vt-in { from{ opacity:0; transform:translateY(10px); } }
/* Le header ne doit pas participer au fondu : il est identique d'une page à
   l'autre, le voir clignoter à chaque navigation trahit le rechargement. */
.site-header{ view-transition-name:site-header; }
::view-transition-group(site-header){ animation-duration:0ms; }

/* ---------- garde-fou d'accessibilité ----------
   Le reset global (`transition-duration:.001ms`) ne couvre pas les
   `animation-delay` : une cascade de 840 ms resterait invisible aussi longtemps.
   On remet tout à zéro explicitement. */
@media (prefers-reduced-motion: reduce){
  .hero-inner > div > *,
  .machine-plate, .plate-row, .plate-foot{
    animation:none !important; opacity:1 !important; transform:none !important;
  }
  .machine-plate:hover .plate-row{ opacity:1; }
  .read-progress{ display:none; }
  @view-transition{ navigation:none; }
}

/* ==========================================================================
   PHASE 4 — champ de parallaxe
   Des objets dérivent vers le haut à mesure qu'on descend, à des vitesses
   différentes : c'est ce décalage qui crée la profondeur, pas le mouvement
   lui-même. Le vocabulaire est celui de la marque — plaques chanfreinées
   reprises du logo, et l'étincelle à quatre branches — jamais des formes
   décoratives génériques : sur un site d'expertise industrielle, des bulles
   floues sonneraient faux.

   Tout repose sur une seule variable, `--sy` (défilement en pixels), posée une
   fois par image sur <html>. Chaque objet la multiplie par son propre
   coefficient. Aucun calcul par objet en JS, et rien d'autre que `transform`.
   ========================================================================== */

.parallax-field{
  position:absolute; inset:0; z-index:0;
  overflow:hidden; pointer-events:none;
  /* Isole le repeindre des objets du reste de la section. */
  contain:paint;
}
/* Les contenus doivent rester au-dessus du champ. */
.hero > .wrap, .page-hero > .wrap, .showcase-3d > .wrap{ position:relative; z-index:1; }

.px-shape{
  position:absolute;
  top:var(--y); left:var(--x);
  width:var(--s); height:var(--s);
  opacity:var(--o);
  /* translate3d, et non translateY : force la composition sur le GPU, le
     défilement reste fluide même avec plusieurs objets par section. */
  transform:translate3d(0, calc(var(--sy, 0) * var(--k) * -1px), 0) rotate(var(--r));
}

/* Plaque : le chanfrein supérieur gauche du logo, repris à l'identique. */
.px-plate{
  border:1.5px solid rgba(255,255,255,.20);
  border-radius:2px;
  clip-path:polygon(34% 0, 100% 0, 100% 100%, 0 100%, 0 22%);
  background:linear-gradient(150deg, rgba(255,255,255,.05), transparent 70%);
}
.px-plate.solid{ background:rgba(255,255,255,.035); border-color:rgba(255,255,255,.13); }

/* Étincelle à quatre branches, l'accent du logo. */
.px-spark{
  background:var(--spark-500);
  clip-path:polygon(50% 0, 58% 42%, 100% 50%, 58% 58%, 50% 100%, 42% 58%, 0 50%, 42% 42%);
}

/* Le champ n'a de sens que sur les fonds sombres : sur le papier clair, ces
   objets deviendraient des taches. */
.on-light .parallax-field{ display:none; }

@media (prefers-reduced-motion: reduce){
  /* On ne masque pas le champ — il fait partie de la composition. On fige
     seulement la dérive : les objets restent à leur position de repos. */
  .px-shape{ transform:rotate(var(--r)) !important; }
}
/* Sous 700 px la profondeur ne se lit plus, et chaque objet coûte une couche
   de composition sur un processeur mobile. */
@media (max-width: 700px){
  .parallax-field{ display:none; }
}

/* ==========================================================================
   PAGES JURIDIQUES
   Colonne étroite : ces textes se lisent, ils ne se survolent pas.
   ========================================================================== */
/* `.wrap` centre son contenu ; en réduisant seulement max-width, la colonne
   juridique se serait recentrée au milieu de la page, désalignée du titre et
   de tout le reste du site. On la recale sur le bord gauche de la grille. */
.legal{ max-width:74ch; margin-left:0; }
.legal h2{
  font-size:22px; margin-top:52px; padding-top:22px;
  border-top:1px solid var(--line);
}
.legal h2:first-child{ margin-top:0; padding-top:0; border-top:0; }
.legal p{ margin-top:14px; color:var(--ink-soft); }
.legal a{ color:var(--spark-700); text-decoration:underline; text-underline-offset:3px; }

/* Page d'erreur : un lien noyé dans un paragraphe doit rester repérable
   autrement que par la position, d'où le soulignement comme ailleurs. */
.page-aide{ margin-top:30px; }
.page-aide a{ color:var(--spark-700); text-decoration:underline; text-underline-offset:3px; }
.legal a:hover{ color:var(--spark-600); }

.legal-list{ margin:18px 0 0; display:grid; grid-template-columns:minmax(190px,auto) 1fr; gap:2px 28px; }
.legal-list dt{
  font-family:var(--font-mono); font-size:12px; letter-spacing:.06em;
  text-transform:uppercase; color:var(--ink-faint); padding:12px 0;
  border-top:1px solid var(--line);
}
.legal-list dd{ margin:0; padding:12px 0; border-top:1px solid var(--line); }
@media (max-width:640px){
  .legal-list{ grid-template-columns:1fr; gap:0; }
  .legal-list dd{ border-top:0; padding-top:0; padding-bottom:16px; }
}

.legal-table{ width:100%; border-collapse:collapse; margin-top:18px; font-size:14.5px; }
.legal-table th, .legal-table td{
  text-align:left; vertical-align:top; padding:12px 14px 12px 0;
  border-bottom:1px solid var(--line);
}
.legal-table th{
  font-family:var(--font-mono); font-size:11.5px; letter-spacing:.06em;
  text-transform:uppercase; color:var(--ink-faint); font-weight:500;
}
.legal-table td{ color:var(--ink-soft); }
/* Un tableau ne doit jamais élargir la page : il défile dans sa propre boîte. */
.legal-table{ display:block; overflow-x:auto; }

.legal-bullets{ margin-top:14px; display:grid; gap:12px; }
.legal-bullets li{
  padding-left:18px; position:relative; color:var(--ink-soft); font-size:15px;
}
.legal-bullets li::before{
  content:""; position:absolute; left:0; top:9px;
  width:6px; height:6px; background:var(--spark-500); border-radius:1px;
}
.legal-note{
  display:block; margin-top:8px; font-size:13.5px; line-height:1.6;
  color:var(--ink-faint); font-style:italic;
}

.schema-grid{
  display:grid; grid-template-columns:1fr 1fr; gap:28px; margin-top:44px;
}
@media (max-width:900px){ .schema-grid{ grid-template-columns:1fr; gap:22px; } }

/* Le chanfrein haut-gauche est la géométrie du logo, reprise sur la plaque
   constructeur du hero et sur le cadre du visualiseur. */
.schema-card{
  background:linear-gradient(168deg, rgba(30,71,113,.28) 0%, rgba(10,24,38,.5) 70%);
  border:1px solid var(--line-on-dark);
  border-radius:24px 8px 8px 8px;
  padding:22px 22px 26px;
  position:relative;
}

.schema-head{ display:flex; align-items:center; gap:12px; margin-bottom:4px; }
.schema-badge{
  font-family:var(--font-mono); font-weight:600; font-size:15px;
  background:var(--spark-500); color:var(--on-spark);
  width:34px; height:34px; border-radius:8px;
  display:flex; align-items:center; justify-content:center; flex:none;
}
.schema-head h3{ font-size:19px; margin:0; }
.schema-sub{
  font-family:var(--font-mono); font-size:11.5px; letter-spacing:.07em;
  text-transform:uppercase; color:var(--spark-500); margin:2px 0 0;
}

.schema-figure{
  margin:16px 0 0; background:rgba(6,14,24,.55);
  border:1px solid rgba(255,255,255,.07); border-radius:10px;
  overflow:hidden;
}
.schema-figure svg{ display:block; width:100%; height:auto; }

/* Matrice de caractéristiques : une grille de données, pas des cartons. */
.schema-specs{ display:grid; grid-template-columns:minmax(96px,auto) 1fr; gap:0 20px; margin:16px 0 0; }
.schema-specs dt{
  font-family:var(--font-mono); font-size:10.5px; letter-spacing:.08em;
  text-transform:uppercase; color:#8FA0B2;
  padding:10px 0; border-top:1px dashed rgba(255,255,255,.13);
}
.schema-specs dd{
  margin:0; padding:10px 0; border-top:1px dashed rgba(255,255,255,.13);
  font-size:14px; color:#E4E9EE;
}
@media (max-width:480px){
  .schema-specs{ grid-template-columns:1fr; }
  .schema-specs dd{ border-top:0; padding-top:0; padding-bottom:12px; }
}
/* ==========================================================================
   Page formations — fiche technique par recommandation
   Remplace les quatre cartons blancs identiques par une plaque à chanfrein
   portant une matrice de données : même contenu, registre « constructeur ».
   ========================================================================== */

.reco-plate{
  background:var(--white);
  border:1px solid var(--line);
  border-bottom:3px solid var(--navy-800);   /* le filet épais d'une plaque rivetée */
  border-radius:26px 6px 6px 6px;            /* chanfrein haut-gauche du logo */
  padding:28px 30px 24px;
  box-shadow:var(--shadow-card);
}
.reco-plate.is-electric{ border-bottom-color:var(--spark-500); }

/* gap:0 et non gap:0 28px — avec une gouttière, chaque cellule porte son
   propre filet et la ligne pointillée se brise au milieu. La respiration
   passe par le padding du <dt>, ce qui garde un trait continu. */
.reco-specs{ display:grid; grid-template-columns:minmax(140px,auto) 1fr; gap:0; margin:0; }
.reco-specs dt{
  font-family:var(--font-mono); font-size:11px; letter-spacing:.08em;
  text-transform:uppercase; color:var(--ink-faint);
  padding:14px 28px 14px 0; border-top:1px dashed var(--paper-line);
}
.reco-specs dd{
  margin:0; padding:14px 0; border-top:1px dashed var(--paper-line);
  font-size:15px; line-height:1.55; color:var(--ink);
}
.reco-specs dt:first-of-type, .reco-specs dd:first-of-type{ border-top:0; padding-top:0; }
@media (max-width:640px){
  .reco-specs{ grid-template-columns:1fr; gap:0; }
  .reco-specs dt{ padding:14px 0 4px; }
  .reco-specs dd{ border-top:0; padding-top:0; padding-bottom:16px; }
  .reco-plate{ padding:22px 20px 18px; }
}

/* Confirmation d'envoi du formulaire. Masquée tant que rien n'a été soumis :
   elle n'existe dans le document qu'une fois le message préparé. */
.form-status{
  margin-top:16px; padding:14px 16px;
  background:var(--spark-100); border:1px solid rgba(238,113,17,.35);
  border-radius:6px; font-size:14.5px; line-height:1.55; color:var(--ink);
}
.form-status a{ color:var(--spark-700); font-weight:600; text-decoration:underline; }

/* ---------- rôles typographiques ----------
   Ces quatre classes remplacent une soixantaine de `style=""` posés au fil des
   pages, où le même texte d'accompagnement existait en 14, 14.5, 15.5, 16 et
   16.5 px. Une taille par rôle, décidée ici et nulle part ailleurs : c'est la
   condition pour que la hiérarchie reste lisible quand une page évolue. */
.text-soft{
  margin-top:16px; font-size:16px; line-height:1.7; color:var(--ink-soft);
}
.text-sm{
  font-size:14.5px; line-height:1.6; color:var(--ink-soft);
}
.on-dark .text-soft, .on-dark .text-sm{ color:var(--dark-body); }

/* Deux échelons de titre secondaire, pour les colonnes et les blocs internes :
   un h2 de colonne ne doit pas peser autant qu'un h2 de section pleine. */
.h2-compact{ font-size:clamp(24px, 2.6vw, 28px); }
.h3-compact{ font-size:16px; letter-spacing:.02em; }

.footer-logo{ height:52px; width:auto; margin-bottom:14px; }

/* ---------- page Formations : deux colonnes ----------
   Le ruban vertical d'origine (titre, fiche pleine largeur, note, bouton, bande
   sombre traversante, cinq fois de suite) ne donnait au lecteur aucun point
   d'ancrage, et noyait le bouton entre un paragraphe et un bloc sombre.
   Deux colonnes aux rôles distincts : à gauche ce qu'on lit pour comprendre,
   à droite ce qu'on regarde pour décider. */
.reco-block{ padding:84px 0; }
.reco-block + .reco-block{ border-top:1px solid var(--paper-line); }
.reco-title{ margin-bottom:36px; }
.reco-title h2{ margin-top:14px; }
.reco-title .lede{ margin-top:14px; max-width:62ch; }

.reco-cols{
  display:grid; grid-template-columns:minmax(0,1.35fr) minmax(0,1fr);
  gap:44px; align-items:start;
}
/* Collante : la fiche et son bouton accompagnent la lecture au lieu de défiler
   hors de vue. 104px = hauteur de l'en-tête flottant plus une respiration. */
.reco-aside{ position:sticky; top:104px; }

/* Le bouton fait corps avec la fiche : il en est la conclusion, à la même place
   pour les cinq formations, et seule action de sa colonne. */
.reco-cta{ margin-top:22px; }
.reco-cta .btn{ width:100%; justify-content:center; }
.reco-cta-note{
  margin-top:10px; font-family:var(--font-mono); font-size:11.5px;
  color:var(--ink-faint); text-align:center; letter-spacing:.03em;
}

/* Le schéma garde le fond sombre dont ses tracés ont besoin, mais borné à sa
   colonne : la bande qui traversait l'écran cinq fois hachait la lecture. */
.reco-visual{
  background:var(--navy-990); color:#fff;
  border-radius:20px 6px 6px 6px; padding:26px 26px 30px; margin-top:26px;
}
.reco-visual h3{ color:#fff; }
.reco-visual-head{
  font-family:var(--font-display); text-transform:uppercase;
  font-size:19px; letter-spacing:.01em;
}
.reco-visual-lede{
  margin-top:10px; font-size:14.5px; line-height:1.65; color:var(--dark-body);
}
.reco-visual-lede a{ color:#fff; text-decoration:underline; text-underline-offset:3px; }
.reco-visual .schema-grid{
  display:grid; grid-template-columns:repeat(auto-fit,minmax(230px,1fr));
  gap:18px; margin-top:22px;
}
.reco-visual .schema-card{
  background:rgba(255,255,255,.04); border:1px solid var(--line-on-dark);
  border-radius:10px; padding:16px;
}
@media (max-width: 980px){
  .reco-cols{ grid-template-columns:1fr; gap:32px; }
  .reco-aside{ position:static; }
  .reco-block{ padding:60px 0; }
}

/* La BT est la seule formation dont les cartes portent des données sous le
   schéma : sans resserrement, son bloc dépassait les autres de 40 %. */
.reco-visual .schema-specs{ font-size:12px; line-height:1.45; margin-top:12px; }
.reco-visual .schema-specs dt{ padding-top:7px; }
.reco-visual .schema-specs dd{ padding-top:7px; }

/* ==========================================================================
   Page Formations — sommaire et rail
   --------------------------------------------------------------------------
   La barre collante « Aller à » est supprimée. Elle occupait 60 px de hauteur
   en permanence, se superposait au contenu sous l'en-tête, et ne servait qu'une
   seule fois : au moment de choisir sa formation. Deux objets la remplacent,
   chacun avec un rôle net.

   1. Le sommaire, en tête de page : on y choisit, puis la page rend tout
      l'écran au contenu.
   2. Le rail, en marge : cinq repères hors du flux qui disent où l'on se
      trouve et permettent de sauter, sans coûter un pixel de hauteur.
   ========================================================================== */

/* Le sommaire annonce la première formation : les séparer de 158 px — 74 ici
   plus 84 de padding du bloc suivant — cassait ce lien et donnait une bande
   vide au milieu de l'écran. */
.sommaire{ background:var(--paper); padding:0 0 46px; }
.sommaire + .reco-block{ padding-top:52px; }

/* Cinq colonnes, pas quatre. Une grille en `auto-fit` laissait la cinquième
   entrée orpheline sur une seconde ligne, avec un vide large de trois cellules
   à sa droite. Cinq recommandations, cinq colonnes : le nombre est connu et ne
   changera pas, autant l'écrire. */
.som-grid{
  list-style:none; margin:0; padding:0;
  display:grid; grid-template-columns:repeat(5, 1fr); gap:14px;
}
@media (max-width:1080px){ .som-grid{ grid-template-columns:repeat(3, 1fr); } }
@media (max-width:760px){  .som-grid{ grid-template-columns:repeat(2, 1fr); } }
@media (max-width:460px){  .som-grid{ grid-template-columns:1fr; } }

.som-grid a{
  display:flex; flex-direction:column; gap:9px; height:100%;
  padding:20px 18px 22px;
  background:var(--white);
  border:1px solid var(--paper-line);
  border-radius:8px;
  transition:border-color var(--dur-fast) var(--ease-out),
             transform var(--dur-fast) var(--ease-out);
}
.som-grid a:hover{ border-color:var(--navy-800); transform:translateY(-2px); }

/* L'icône fait le travail que le texte fait mal : on reconnaît une silhouette
   d'engin plus vite qu'on ne lit « R486 ». Elle reprend celle de l'accueil,
   pour que le même engin porte le même signe d'une page à l'autre. */
.som-icon{
  width:30px; height:30px; color:var(--navy-800); flex:none;
  transition:color var(--dur-fast) var(--ease-out);
}
.som-grid a:hover .som-icon{ color:var(--spark-600); }

.som-code{
  font-family:var(--font-mono); font-size:11.5px; font-weight:600;
  letter-spacing:.09em; color:var(--spark-700);
}
.som-code.accent{ color:var(--spark-600); }
.som-nom{
  font-family:var(--font-display); text-transform:uppercase;
  font-size:17px; line-height:1.15; color:var(--ink);
}
.som-note{
  font-size:13px; line-height:1.5; color:var(--ink-soft);
  margin-top:auto; padding-top:8px;
}

.rail{
  position:fixed; right:26px; top:50%; transform:translateY(-50%); z-index:40;
  display:flex; flex-direction:column; gap:4px;
  opacity:0; pointer-events:none;
  transition:opacity .35s var(--ease-out);
}
body.rail-on .rail{ opacity:1; pointer-events:auto; }
.rail a{
  display:flex; align-items:center; justify-content:flex-end; gap:10px;
  padding:7px 2px; color:var(--ink-faint);
}
.rail i{
  width:22px; height:2px; background:currentColor; flex:none;
  transition:width var(--dur-base) var(--ease-out), background var(--dur-base) var(--ease-out);
}
.rail b{
  font-family:var(--font-mono); font-size:11px; font-weight:600;
  letter-spacing:.08em; color:var(--ink);
  opacity:0; transform:translateX(6px);
  transition:opacity var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}
.rail a:hover b, .rail a:focus-visible b, .rail a[aria-current="true"] b{
  opacity:1; transform:none;
}
.rail a:hover i{ width:34px; }
.rail a[aria-current="true"] i{ width:34px; background:var(--spark-500); }
.rail a[aria-current="true"]{ color:var(--spark-500); }

/* Sous 1180 px, la marge n'existe plus : le rail chevaucherait le texte.
   Le sommaire en tête de page assure seul la navigation. */
@media (max-width:1180px){ .rail{ display:none; } }
@media (prefers-reduced-motion: reduce){
  .rail, .rail i, .rail b, .som-grid a::after{ transition:none; }
}

/* ==========================================================================
   Panneau « Nos formations »
   --------------------------------------------------------------------------
   Reprend le principe du menu déroulant d'Apple, demandé par le client : au
   survol d'une entrée de navigation, un panneau descend et donne accès aux cinq
   recommandations sans quitter la page où l'on se trouve.

   Deux règles tenues :
     · le lien reste un lien. Sans JavaScript, « Nos formations » mène toujours
       à la page — le panneau est un raccourci, pas un passage obligé ;
     · il s'ouvre au survol ET au clavier, et se ferme à Échap. Un menu qui ne
       répond qu'à la souris exclut la moitié de ses utilisateurs.
   ========================================================================== */

/* `static` et non `relative` : le panneau doit se centrer sur la barre entière,
   comme chez Apple, et non sur le lien survolé — sinon il déborde d'un côté.
   Son ancrage est donc .header-inner, qui est déjà positionné. */
.nav-drop{ position:static; }

.megamenu{
  position:absolute; top:calc(100% + 18px); left:50%;
  width:min(940px, calc(100vw - 48px));
  transform:translate(-50%, -10px);
  background:var(--paper);
  border:1px solid var(--paper-line);
  border-radius:16px;
  box-shadow:0 26px 60px -22px rgba(6,14,24,.55);
  padding:26px;
  opacity:0; visibility:hidden; pointer-events:none;
  transition:opacity var(--dur-base) var(--ease-out),
             transform var(--dur-base) var(--ease-out),
             visibility 0s linear var(--dur-base);
  z-index:120;
}
.nav-drop.is-open .megamenu{
  opacity:1; visibility:visible; pointer-events:auto;
  transform:translate(-50%, 0);
  transition-delay:0s;
}

/* Zone tampon invisible entre le lien et le panneau : sans elle, le menu se
   referme dès que la souris traverse l'espace qui les sépare. */
.megamenu::before{
  content:""; position:absolute; left:0; right:0; top:-20px; height:20px;
}

/* Une entrée par ligne, et non cinq colonnes : la description ajoutée sous le
   nom demande de la largeur, pas de la hauteur. À 176 px de colonne, « Conducteur
   accompagnant, catégories 1 et 2 » tombait sur quatre lignes. */
.mm-grid{ display:flex; flex-direction:column; gap:2px; }
.mm-grid a{
  display:grid; grid-template-columns:auto minmax(0,1fr) minmax(0,1.05fr);
  align-items:center; gap:16px;
  padding:12px 14px; border-radius:10px;
  transition:background var(--dur-fast) var(--ease-out);
}
.mm-grid a:hover, .mm-grid a:focus-visible{ background:var(--white); }
.mm-icon{ width:26px; height:26px; color:var(--navy-800); flex:none; }
.mm-grid a:hover .mm-icon{ color:var(--spark-600); }
.mm-texte{ display:flex; flex-direction:column; gap:3px; min-width:0; }
.mm-code{
  font-family:var(--font-mono); font-size:11px; font-weight:600;
  letter-spacing:.09em; color:var(--spark-700);
}
.mm-nom{
  font-family:var(--font-display); text-transform:uppercase;
  font-size:15px; line-height:1.2; color:var(--ink);
}
/* La description reste en retrait : elle départage deux recommandations
   voisines, elle ne se lit pas d'abord. */
.mm-note{
  font-size:13px; line-height:1.45; color:var(--ink-soft); min-width:0;
}
/* Sous 1080 px la troisième colonne étrangle les deux autres : la description
   passe sous le nom plutôt que de réduire le titre à un mot par ligne. */
@media (max-width:1080px){
  .mm-grid a{ grid-template-columns:auto minmax(0,1fr); }
  .mm-note{ grid-column:2; margin-top:2px; }
}
.mm-pied{
  display:flex; justify-content:space-between; align-items:center; gap:16px;
  margin-top:18px; padding-top:16px; border-top:1px solid var(--paper-line);
  font-size:13.5px; color:var(--ink-soft); flex-wrap:wrap;
}
.mm-pied a{ font-weight:600; color:var(--spark-700); }
.mm-pied a:hover{ text-decoration:underline; }

/* Le panneau suppose une barre de navigation horizontale : sous 980 px elle
   laisse place au menu plein écran, qui liste déjà les formations. */
@media (max-width:980px){
  .megamenu{ display:none; }
  /* Le voile est créé en JavaScript sur toutes les tailles, alors qu'il ne
     sert que le mégamenu. Laissé dans l'arbre, un `backdrop-filter` plein
     écran retient une couche de composition GPU en permanence — sur mobile,
     pour un menu qui ne s'ouvrira jamais. */
  .mm-voile{ display:none; }
}
@media (prefers-reduced-motion: reduce){
  .megamenu{ transition:opacity .01ms, visibility .01ms; transform:translate(-50%, 0); }
}

/* Voile de mise au point.
   L'effet recherché n'est pas un panneau translucide mais une page qui recule :
   le contenu derrière est flouté et légèrement assombri, de sorte que le menu
   soit la seule chose nette à l'écran. `backdrop-filter` agit sur ce qui est
   derrière le voile, donc sur toute la page — l'en-tête et le panneau doivent
   passer au-dessus pour rester nets. */
.mm-voile{
  position:fixed; inset:0; z-index:110;
  background:rgba(6,14,24,.22);
  backdrop-filter:blur(16px) saturate(.9);
  -webkit-backdrop-filter:blur(16px) saturate(.9);
  opacity:0; pointer-events:none;
  transition:opacity var(--dur-base) var(--ease-out);
}
body.mm-open .mm-voile{ opacity:1; pointer-events:auto; }

/* L'en-tête passe devant le voile le temps de l'ouverture ; le panneau, qui est
   son enfant, suit. Sans cela la barre de navigation serait floutée elle aussi,
   et le menu paraîtrait détaché de son point de départ. */
body.mm-open .site-header{ z-index:130; }

@media (prefers-reduced-motion: reduce){
  .mm-voile{ transition:opacity .01ms; }
}

/* ==========================================================================
   Pages de formation (une par recommandation)
   --------------------------------------------------------------------------
   Gabarit commun aux cinq recommandations. La page des formations présente et
   oriente ; celle-ci répond, section par section, aux questions qu'un
   responsable se pose avant de demander un devis : quelles catégories, quel
   programme, quels prérequis, que vaut le certificat.
   ========================================================================== */

/* ---------- en-tête de page ----------
   Deux colonnes de rôles distincts, comme sur la page des formations : à
   gauche ce qui situe et amène à l'action, à droite la fiche que le lecteur
   vient chercher. Sous 900 px la fiche passe dessous, jamais à côté : à
   moins de 300 px de large, ses deux colonnes de définitions se cassent. */
.form-hero-inner{
  display:grid; grid-template-columns:minmax(0,1.15fr) minmax(0,.85fr);
  gap:52px; align-items:start;
}
@media (max-width:900px){
  .form-hero-inner{ grid-template-columns:1fr; gap:34px; }
}

/* Le code de la recommandation en Anton, à la taille d'un titre : c'est le
   repère que cherche l'œil sur une page de catalogue, et le seul élément
   commun aux cinq pages. */
.form-code{
  font-family:var(--font-display); text-transform:uppercase;
  font-size:clamp(30px,4.4vw,44px); line-height:1; letter-spacing:.01em;
  color:var(--spark-500); margin-bottom:10px;
}
.form-hero h1{ text-wrap:balance; }
.form-hero-actions{
  display:flex; gap:14px; flex-wrap:wrap; margin-top:30px;
}

/* Fiche d'identité : la plaque constructeur du site, en version sombre. Le
   filet orange en pied remplace le filet navy de la version claire, qui
   disparaîtrait sur ce fond. */
.fiche-plate{
  background:rgba(255,255,255,.05);
  border:1px solid var(--line-on-dark);
  border-bottom:3px solid var(--spark-500);
  border-radius:26px 6px 6px 6px;
  padding:24px 26px 22px;
  backdrop-filter:blur(2px);
  -webkit-backdrop-filter:blur(2px);
}
/* Ces fiches se répètent le long de la page. Sous 900 px, un flou de 2 px
   derrière un fond blanc à 5 % ne se distingue pas à l'œil, mais chaque fiche
   coûte sa propre couche : sur mobile on garde le fond, on retire le filtre. */
@media (max-width:900px){
  .fiche-plate{ backdrop-filter:none; -webkit-backdrop-filter:none; }
}
.fiche-head{
  display:flex; justify-content:space-between; align-items:baseline; gap:14px;
  padding-bottom:16px; border-bottom:1px solid var(--line-on-dark);
  flex-wrap:wrap;
}
.fiche-head strong{
  font-family:var(--font-display); text-transform:uppercase;
  font-size:16px; letter-spacing:.02em; color:#fff; font-weight:400;
}
.fiche-head span{
  font-family:var(--font-mono); font-size:11.5px; letter-spacing:.08em;
  color:var(--spark-500);
}
/* Même matrice que .reco-specs, calée pour un fond sombre. gap:0 : la
   gouttière briserait le filet pointillé au milieu de chaque ligne. */
.fiche-specs{
  display:grid; grid-template-columns:minmax(96px,auto) 1fr; gap:0; margin:16px 0 0;
}
.fiche-specs dt{
  font-family:var(--font-mono); font-size:10.5px; letter-spacing:.08em;
  text-transform:uppercase; color:#8FA0AF;
  padding:13px 22px 13px 0; border-top:1px dashed var(--line-on-dark);
}
.fiche-specs dd{
  margin:0; padding:13px 0; border-top:1px dashed var(--line-on-dark);
  font-size:14.5px; line-height:1.5; color:#fff;
}
.fiche-specs dt:first-of-type, .fiche-specs dd:first-of-type{ border-top:0; padding-top:0; }
.fiche-note{
  margin-top:18px; padding-top:14px; border-top:1px solid var(--line-on-dark);
  font-family:var(--font-mono); font-size:11.5px; letter-spacing:.03em;
  color:var(--dark-body);
}
@media (max-width:520px){
  .fiche-specs{ grid-template-columns:1fr; }
  .fiche-specs dt{ padding:14px 0 3px; }
  .fiche-specs dd{ border-top:0; padding-top:0; padding-bottom:14px; }
}

/* ---------- chapô : le texte porte, la colonne de droite énumère ---------- */
.form-intro{
  display:grid; grid-template-columns:minmax(0,1.25fr) minmax(0,1fr);
  gap:48px; align-items:start;
}
@media (max-width:900px){ .form-intro{ grid-template-columns:1fr; gap:30px; } }
.form-intro a{ color:var(--spark-700); text-decoration:underline; text-underline-offset:3px; }

.form-points{ display:flex; flex-direction:column; gap:0; }
.form-points li{
  padding:18px 0; border-top:1px solid var(--paper-line);
  font-size:15px; line-height:1.6; color:var(--ink-soft);
}
.form-points li:first-child{ border-top:0; padding-top:0; }
.form-points b{ color:var(--ink); font-weight:700; }

/* ---------- les catégories ----------
   Une table technique, pas une grille de tuiles : neuf catégories réparties en
   six familles n'ont pas le même poids, et des cartes de taille égale
   auraient donné à la catégorie 7 l'importance de la catégorie 3. Le code de
   famille tient la colonne de gauche, le détail occupe la droite. */
.cat-table{ margin-top:8px; }
/* Le rang déborde de 26 px de chaque côté par une marge négative, que son
   padding compense exactement : le texte reste sur la grille, mais le bloc a
   la place de peindre un fond au survol sans que rien ne se déplace sous le
   curseur. */
.cat-rang{
  position:relative;
  display:grid; grid-template-columns:minmax(0,.62fr) minmax(0,1fr);
  gap:36px; padding:32px 24px;
  /* 24 px et non 26 : c'est exactement le padding de .wrap. Au-delà, le rang
     dépasse le conteneur dès que la fenêtre descend à la largeur maximale de
     la grille (1024 px), et son ombre se fait couper au bord de l'écran. */
  margin-inline:-24px;
  border-radius:var(--radius-m);
}
/* Le filet de séparation passe sur un pseudo-élément : porté par la bordure,
   il se serait élargi de 52 px avec le rang et aurait dépassé la colonne de
   texte. */
.cat-rang::after{
  content:""; position:absolute; top:0; left:24px; right:24px;
  height:1px; background:var(--paper-line);
  transition:opacity var(--dur-fast) var(--ease-out);
}
.cat-rang:first-child::after{ display:none; }
@media (max-width:820px){
  .cat-rang{ grid-template-columns:1fr; gap:14px; padding:26px 20px; margin-inline:-20px; }
  .cat-rang::after{ left:20px; right:20px; }
}

.cat-codes{
  display:inline-block;
  font-family:var(--font-mono); font-size:12.5px; font-weight:600; letter-spacing:.08em;
  background:var(--navy-950); color:var(--spark-500);
  padding:5px 11px; border-radius:6px; margin-bottom:12px;
}
.cat-tete h3{
  font-family:var(--font-display); text-transform:uppercase;
  font-size:clamp(18px,2vw,21px); line-height:1.15; color:var(--ink);
  text-wrap:balance;
}
/* Signale les deux familles qui concentrent la demande. Une mention écrite
   plutôt qu'une pastille de couleur : elle se lit, elle s'entend, et elle ne
   demande pas au lecteur de deviner ce que veut dire un point orange. */
.cat-tag{
  margin-top:10px;
  font-family:var(--font-mono); font-size:11px; letter-spacing:.07em;
  text-transform:uppercase; color:var(--spark-700);
}
.cat-desc{ font-size:15.5px; line-height:1.65; color:var(--ink-soft); }
.cat-defs{
  display:grid; grid-template-columns:minmax(44px,auto) 1fr; gap:0;
  margin:18px 0 0;
}
.cat-defs dt{
  font-family:var(--font-mono); font-size:13px; font-weight:600; color:var(--navy-800);
  padding:12px 20px 12px 0; border-top:1px dashed var(--paper-line);
}
.cat-defs dd{
  margin:0; padding:12px 0; border-top:1px dashed var(--paper-line);
  font-size:14.5px; line-height:1.55; color:var(--ink);
}
.cat-defs dt:first-of-type, .cat-defs dd:first-of-type{ border-top:0; padding-top:0; }
/* Les familles les plus demandées reçoivent le fond blanc et un retrait :
   elles se détachent de la table sans changer de gabarit. */
.cat-rang.is-vedette{
  background:var(--white);
  box-shadow:var(--shadow-card);
  margin-block:14px;
}
.cat-rang.is-vedette::after,
.cat-rang.is-vedette + .cat-rang::after{ display:none; }

/* ---------- programme ----------
   Deux colonnes égales : théorie et pratique pèsent autant l'une que l'autre
   dans un CACES®, et le test porte sur les deux. */
.prog-cols{
  display:grid; grid-template-columns:repeat(auto-fit,minmax(300px,1fr)); gap:40px;
}
.prog-titre{
  font-family:var(--font-display); text-transform:uppercase;
  font-size:20px; letter-spacing:.02em; color:var(--ink);
  padding-bottom:14px; border-bottom:2px solid var(--navy-800);
}
.prog-liste{ margin-top:20px; display:flex; flex-direction:column; gap:0; }
.prog-liste li{
  position:relative; padding:13px 0 13px 26px;
  border-top:1px dashed var(--paper-line);
  font-size:15px; line-height:1.6; color:var(--ink);
}
.prog-liste li:first-child{ border-top:0; }
/* Le tiret de liste est tracé en CSS plutôt qu'écrit : une puce typographique
   se retrouverait dans le presse-papier à la copie du texte. */
.prog-liste li::before{
  content:""; position:absolute; left:0; top:22px;
  width:13px; height:2px; background:var(--spark-500);
}
.prog-note{
  margin-top:34px; padding:18px 22px;
  background:var(--white); border:1px solid var(--paper-line); border-radius:var(--radius-s);
  font-size:14.5px; line-height:1.65; color:var(--ink-soft);
  max-width:70ch;
}

/* ---------- prérequis et déroulé ---------- */
.deroule-layout{
  display:grid; grid-template-columns:minmax(0,1fr) minmax(0,.85fr);
  gap:56px; align-items:start;
}
@media (max-width:900px){ .deroule-layout{ grid-template-columns:1fr; gap:40px; } }

.check-liste{ margin-top:22px; display:flex; flex-direction:column; gap:0; }
.check-liste li{
  position:relative; padding:15px 0 15px 32px;
  border-top:1px solid var(--paper-line);
  font-size:15.5px; line-height:1.6; color:var(--ink);
}
.check-liste li:first-child{ border-top:0; }
/* Coche dessinée en bordures : deux traits d'un carré pivoté à 45°. Aucun
   fichier à charger, et elle suit la couleur du texte si le thème change. */
.check-liste li::before{
  content:""; position:absolute; left:2px; top:20px;
  width:11px; height:6px;
  border-left:2px solid var(--spark-600);
  border-bottom:2px solid var(--spark-600);
  transform:rotate(-45deg);
}

/* ---------- questions fréquentes ----------
   <details> natif : ouverture au clavier sans une ligne de script, et la
   recherche du navigateur déplie d'elle-même la réponse trouvée. Un accordéon
   maison perd les deux. */
.faq{ max-width:78ch; }
.faq-item{ border-top:1px solid var(--paper-line); }
.faq-item:last-child{ border-bottom:1px solid var(--paper-line); }
.faq-item summary{
  display:flex; align-items:flex-start; justify-content:space-between; gap:20px;
  padding:22px 0; cursor:pointer; list-style:none;
  font-size:17px; font-weight:600; line-height:1.45; color:var(--ink);
  transition:color var(--dur-fast) var(--ease-out);
}
.faq-item summary::-webkit-details-marker{ display:none; }
.faq-item summary:hover{ color:var(--navy-800); }
/* Le chevron est un carré dont on ne garde que deux côtés, pivoté : il tourne
   d'un quart de tour à l'ouverture. `transform` seul, donc composé par le GPU. */
.faq-item summary::after{
  content:""; flex:none; margin-top:6px;
  width:9px; height:9px;
  border-right:2px solid var(--spark-600);
  border-bottom:2px solid var(--spark-600);
  transform:rotate(45deg);
  transition:transform var(--dur-base) var(--ease-out);
}
.faq-item[open] summary::after{ transform:rotate(-135deg); }
.faq-item[open] summary{ color:var(--navy-900); }
.faq-corps{ padding:0 0 24px; max-width:68ch; }
.faq-corps p{
  font-size:15.5px; line-height:1.7; color:var(--ink-soft);
}
.faq-corps p + p{ margin-top:14px; }
.faq-corps a{ color:var(--spark-700); text-decoration:underline; text-underline-offset:3px; }
@media (prefers-reduced-motion: reduce){
  .faq-item summary::after{ transition:none; }
}

/* ---------- passerelle vers les autres recommandations ----------
   En pied de page de formation : celui qui n'a pas trouvé sa machine ici doit
   pouvoir sauter à la bonne page sans repasser par le catalogue. */
.autres-titre{
  font-family:var(--font-mono); font-size:11.5px; letter-spacing:.09em;
  text-transform:uppercase; color:var(--ink-faint); font-weight:600;
  margin-bottom:18px;
}
.autres-liste{
  display:grid; grid-template-columns:repeat(auto-fit,minmax(190px,1fr)); gap:10px;
}
.autres-liste a{
  display:flex; align-items:baseline; gap:10px;
  padding:16px 18px;
  background:var(--white); border:1px solid var(--paper-line); border-radius:8px;
  transition:border-color var(--dur-fast) var(--ease-out),
             transform var(--dur-fast) var(--ease-out);
}
.autres-liste a:hover{ border-color:var(--navy-800); transform:translateY(-2px); }
.autres-code{
  font-family:var(--font-mono); font-size:12px; font-weight:600; letter-spacing:.07em;
  color:var(--spark-700); flex:none;
}
.autres-nom{ font-size:14.5px; color:var(--ink); }
@media (prefers-reduced-motion: reduce){
  .autres-liste a{ transition:none; }
}

/* ==========================================================================
   Page Nos formations — catalogue
   --------------------------------------------------------------------------
   La page ne déroule plus les cinq programmes : elle présente, oriente, et
   laisse chaque page de formation faire son travail. Deux objets suffisent,
   une vedette et quatre tuiles, parce que la demande n'est pas répartie
   également entre les cinq recommandations.
   ========================================================================== */

.cat-vedette{
  display:grid; grid-template-columns:minmax(0,1.45fr) minmax(0,1fr);
  gap:44px; align-items:start;
  background:var(--white);
  border:1px solid var(--paper-line);
  border-bottom:3px solid var(--navy-800);
  border-radius:var(--radius-l) var(--radius-s) var(--radius-s) var(--radius-s);
  padding:38px 40px 36px;
  margin-bottom:28px;
}
@media (max-width:900px){
  .cat-vedette{ grid-template-columns:1fr; gap:28px; padding:28px 24px 26px; }
}
/* L'icône était à gauche du titre, en drapeau : le titre partait alors 62 px
   plus à droite que le paragraphe et le bouton placés dessous, et la carte
   avait deux bords gauches. Tout s'aligne maintenant sur un seul axe, comme
   dans les tuiles qui la suivent. */
.vedette-corps{ display:flex; flex-direction:column; align-items:flex-start; }
.vedette-tete{ margin-bottom:16px; }
.vedette-icone{ width:44px; height:44px; color:var(--navy-800); margin-bottom:14px; }
.vedette-code{
  display:inline-block; margin-bottom:8px;
  font-family:var(--font-mono); font-size:12px; font-weight:600; letter-spacing:.08em;
  background:var(--navy-950); color:var(--spark-500);
  padding:5px 11px; border-radius:6px;
}
.vedette-tete h2{ font-size:clamp(22px,2.8vw,30px); line-height:1.12; text-wrap:balance; }
.vedette-corps .btn{ margin-top:26px; }

/* Même matrice de données que les fiches du site, en version resserrée : trois
   lignes, celles qu'on compare d'une recommandation à l'autre. */
/* Centrée et non calée en haut : la colonne de gauche est plus haute d'environ
   150 px, et la fiche alignée sur son sommet laissait tout ce vide sous elle,
   au bas de la carte. */
.vedette-specs{
  display:grid; grid-template-columns:minmax(94px,auto) 1fr; gap:0; margin:0;
  align-self:center;
  background:var(--paper); border-radius:var(--radius-s); padding:22px 24px;
}
.vedette-specs dt{
  font-family:var(--font-mono); font-size:10.5px; letter-spacing:.08em;
  text-transform:uppercase; color:var(--ink-faint);
  padding:12px 20px 12px 0; border-top:1px dashed var(--paper-line);
}
.vedette-specs dd{
  margin:0; padding:12px 0; border-top:1px dashed var(--paper-line);
  font-size:14.5px; line-height:1.5; color:var(--ink);
}
.vedette-specs dt:first-of-type, .vedette-specs dd:first-of-type{ border-top:0; padding-top:0; }
@media (max-width:520px){
  .vedette-specs{ grid-template-columns:1fr; }
  .vedette-specs dt{ padding:12px 0 3px; }
  .vedette-specs dd{ border-top:0; padding-top:0; padding-bottom:12px; }
}

/* Deux colonnes et non quatre : à 280 px de large, le nom d'une recommandation
   passe sur trois lignes et la tuile ne dit plus rien d'utile. */
.cat-grille{ display:grid; grid-template-columns:repeat(2,1fr); gap:24px; }
/* 620 et non 820 : à 768 px de large, deux colonnes donnent des tuiles de
   348 px, ce qui reste confortable. Une colonne unique les étirait sur 720 px
   pour trois lignes de texte, et l'œil perdait le début de la ligne suivante. */
@media (max-width:620px){ .cat-grille{ grid-template-columns:1fr; } }

.cat-tuile{
  display:flex; flex-direction:column; gap:12px;
  background:var(--white);
  border:1px solid var(--paper-line);
  border-radius:var(--radius-m);
  padding:28px 28px 24px;
  transition:border-color var(--dur-fast) var(--ease-out),
             transform var(--dur-fast) var(--ease-out);
}
.cat-tuile:hover{ border-color:var(--navy-800); transform:translateY(-3px); }
/* L'habilitation électrique n'est pas un CACES® : le filet orange en pied la
   distingue des quatre recommandations, sans la sortir de la grille. */
.cat-tuile.is-electric{ border-bottom:3px solid var(--spark-500); }
.cat-icone{ width:38px; height:38px; color:var(--navy-800); }
.cat-tuile-code{
  align-self:flex-start;
  font-family:var(--font-mono); font-size:11.5px; font-weight:600; letter-spacing:.08em;
  background:var(--navy-950); color:var(--spark-500);
  padding:4px 10px; border-radius:6px;
}
.cat-tuile-code.accent{ background:var(--spark-100); color:var(--spark-700); }
.cat-tuile h3{
  font-family:var(--font-display); text-transform:uppercase;
  font-size:19px; line-height:1.15; color:var(--ink); text-wrap:balance;
}
.cat-tuile > p{ font-size:14.5px; line-height:1.6; color:var(--ink-soft); }

.tuile-specs{
  display:grid; grid-template-columns:minmax(80px,auto) 1fr; gap:0;
  margin:6px 0 0; padding-top:14px; border-top:1px dashed var(--paper-line);
}
.tuile-specs dt{
  font-family:var(--font-mono); font-size:10.5px; letter-spacing:.07em;
  text-transform:uppercase; color:var(--ink-faint); padding:5px 16px 5px 0;
}
.tuile-specs dd{ margin:0; padding:5px 0; font-size:14px; color:var(--ink); }

/* `margin-top:auto` colle le lien au bas de la tuile : les quatre tuiles n'ont
   pas la même hauteur de texte, et un lien flottant au milieu de l'une d'elles
   casserait la ligne de lecture horizontale. */
.tuile-lien{
  margin-top:auto; padding-top:18px;
  display:inline-flex; align-items:center; gap:8px;
  font-weight:700; font-size:14.5px; color:var(--navy-900);
}
.tuile-lien svg{
  width:15px; height:15px; flex:none;
  transition:transform var(--dur-fast) var(--ease-out-back);
}
.cat-tuile:hover .tuile-lien svg{ transform:translateX(4px); }
.tuile-lien:hover{ color:var(--spark-700); }

@media (prefers-reduced-motion: reduce){
  .cat-tuile, .tuile-lien svg{ transition:none; }
}

/* ---------- désambiguïsation ----------
   Question à gauche, réponse à droite, séparées par un filet : le lecteur
   balaie la colonne des questions et ne lit que celle qui le concerne. Trois
   cartes côte à côte l'auraient obligé à tout lire pour trouver la sienne. */
.choix{
  display:grid; grid-template-columns:minmax(0,.72fr) minmax(0,1fr);
  gap:36px; padding:30px 0;
  border-top:1px solid var(--paper-line);
}
.choix:first-child{ border-top:0; padding-top:6px; }
@media (max-width:820px){
  .choix{ grid-template-columns:1fr; gap:12px; padding:24px 0; }
}
.choix-q{
  font-family:var(--font-display); text-transform:uppercase;
  font-size:clamp(17px,2vw,20px); line-height:1.2; color:var(--ink);
  text-wrap:balance;
}
.choix-r{ font-size:15.5px; line-height:1.7; color:var(--ink-soft); }
/* Les liens appartiennent à la réponse, pas à la question : sans cette
   consigne la grille les renvoie à la ligne suivante, colonne de gauche,
   c'est-à-dire sous le titre et à des centaines de pixels du texte qu'ils
   prolongent. */
.choix-liens{
  display:flex; flex-wrap:wrap; gap:8px; margin-top:16px;
  grid-column:2;
}
@media (max-width:820px){
  .choix-liens{ grid-column:1; margin-top:12px; }
  /* Ces puces sont le seul chemin vers la fiche de la recommandation citée :
     sept pixels de padding ne leur donnaient que 35 px de haut. */
  .choix-liens a{ display:inline-flex; align-items:center; min-height:44px; }
}
.choix-liens a{
  font-family:var(--font-mono); font-size:12px; font-weight:600; letter-spacing:.04em;
  color:var(--navy-900);
  padding:7px 13px; border-radius:999px;
  border:1px solid var(--line);
  background:var(--white);
  transition:border-color var(--dur-fast) var(--ease-out),
             color var(--dur-fast) var(--ease-out);
}
.choix-liens a:hover{ border-color:var(--navy-800); color:var(--spark-700); }
@media (prefers-reduced-motion: reduce){
  .choix-liens a{ transition:none; }
}

/* Espacements repris des attributs style= posés au fil de la rédaction. Les
   sortir du HTML n'est pas cosmétique : un seul style="" dans une page oblige
   la politique de sécurité à autoriser style-src 'unsafe-inline', ce qui
   désarme la protection pour toute la page. */
.form-intro h2 + .text-soft{ margin-top:14px; }
.vedette-corps .text-soft{ margin-top:0; }
.check-liste + .h2-compact{ margin-top:44px; }

/* ==========================================================================
   Mise au point au survol
   --------------------------------------------------------------------------
   Le principe est déjà celui du menu déroulant, où la page recule derrière le
   panneau, et celui du menu mobile, où tout ce qui suit les catégories
   s'estompe pendant qu'on choisit. Il est étendu ici aux deux endroits où le
   lecteur compare des éléments de même nature : les formations du catalogue et
   les familles de catégories.

   Ce que le liseré seul ne faisait pas : désigner. Un cadre plus foncé dit
   « cet élément a changé d'état » ; l'estompage des voisins dit « c'est
   celui-ci que vous regardez ». Sur une grille dense, la seconde information
   est la plus utile.

   `:has()` porte tout : aucune classe à poser en JavaScript, et sur un
   navigateur qui l'ignore il ne se passe rien de plus qu'avant.
   ========================================================================== */

@media (hover: hover) and (pointer: fine){

  /* ---- catalogue : vedette et tuiles se répondent ---- */
  .catalogue:has(.cat-tuile:hover) .cat-vedette,
  .catalogue:has(.cat-vedette:hover) .cat-grille,
  .cat-grille:has(.cat-tuile:hover) .cat-tuile:not(:hover){
    filter:blur(2.5px);
    opacity:.42;
  }
  .cat-vedette, .cat-grille, .cat-tuile{
    transition:filter var(--dur-base) var(--ease-out),
               opacity var(--dur-base) var(--ease-out),
               border-color var(--dur-fast) var(--ease-out),
               transform var(--dur-fast) var(--ease-out);
  }

  /* ---- familles de catégories, sur les pages de formation ---- */
  .cat-table:has(.cat-rang:hover) .cat-rang:not(:hover){
    filter:blur(2.5px);
    opacity:.42;
  }
  .cat-rang{
    transition:filter var(--dur-base) var(--ease-out),
               opacity var(--dur-base) var(--ease-out),
               background var(--dur-base) var(--ease-out),
               box-shadow var(--dur-base) var(--ease-out);
  }

  /* Le fond blanc du survol est peint par un pseudo-élément débordant plutôt
     que par un padding ajouté à la volée : un padding qui apparaît au survol
     déplacerait le texte sous le curseur. Ici rien ne bouge, seul le fond
     arrive. Les rangs déjà en vedette gardent le leur, ils sont blancs en
     permanence. */
  /* Le fond arrive sur le rang lui-même. Un pseudo-élément en z-index négatif
     passait derrière l'aplat de la section, qui ne crée pas de contexte
     d'empilement : il était peint, mais invisible. */
  .cat-rang:not(.is-vedette):hover{
    background:var(--white);
    box-shadow:var(--shadow-card);
  }
  /* Le filet traverserait la carte blanche : il s'efface le temps du survol,
     sur le rang concerné comme sur celui qui le suit. */
  .cat-rang:not(.is-vedette):hover::after,
  .cat-rang:hover + .cat-rang::after{ opacity:0; }
}

/* Le flou est un effet de mise au point, pas une information : on le retire.
   L'estompage reste, lui : il désigne l'élément actif et c'est justement ce
   que l'on cherchait à dire. */
@media (prefers-reduced-motion: reduce){
  .cat-vedette, .cat-grille, .cat-tuile, .cat-rang,
  .cat-rang:not(.is-vedette)::before{ transition:none; }
  .catalogue:has(.cat-tuile:hover) .cat-vedette,
  .catalogue:has(.cat-vedette:hover) .cat-grille,
  .cat-grille:has(.cat-tuile:hover) .cat-tuile:not(:hover),
  .cat-table:has(.cat-rang:hover) .cat-rang:not(:hover){ filter:none; opacity:.5; }
}

/* ==========================================================================
   Petits écrans : rythme, cibles tactiles, retour au toucher
   --------------------------------------------------------------------------
   Trois défauts mesurés sur un écran de 375 px, et non supposés :

     1. Les sections gardaient leurs 96 px de padding haut et bas, soit 192 px
        de vide entre deux sections : près d'un quart d'écran à faire défiler
        pour ne rien lire. Le blanc qui aère un écran de 1440 px encombre un
        écran de poche.

     2. Plusieurs cibles tombaient sous 44 px de haut : 38 px pour les codes de
        formation du menu, 41 px pour « Voir le programme ». C'est le seuil en
        dessous duquel un doigt rate sa cible, et il ne se voit pas à la souris.

     3. Aucun retour au toucher. Le survol, qui désigne l'élément visé sur un
        écran d'ordinateur, n'existe pas ici : sans rien à la place, le doigt
        appuie et il ne se passe rien jusqu'au changement de page.
   ========================================================================== */

@media (max-width: 700px){

  /* ---- rythme vertical ---- */
  .section{ padding:56px 0; }
  .section-tight{ padding:40px 0; }
  .section-head{ margin-bottom:28px; }
  .cat-vedette{ margin-bottom:18px; padding:24px 20px 22px; }
  .cat-grille{ gap:16px; }
  .cat-tuile{ padding:22px 20px 20px; }
  .cat-table{ margin-top:0; }
  .cat-rang{ padding:22px 20px; }
  .cat-rang.is-vedette{ margin-block:10px; }
  .choix{ padding:20px 0; }
  .prog-cols{ gap:30px; }
  .deroule-layout{ gap:32px; }
  .faq-item summary{ padding:18px 0; }

  /* ---- cibles tactiles ----
     44 px de haut au minimum, obtenus par le padding : agrandir la police
     aurait déséquilibré la typographie pour un problème qui n'est pas de
     lisibilité mais de précision du doigt. */
  .mn-liste a{ padding:12px 16px; }
  .tuile-lien{ padding:16px 0 6px; }
  .choix-liens a{ padding:11px 16px; }
  .autres-liste a{ padding:18px; }
  .rail{ display:none; }

  /* ---- retour au toucher ----
     Remplace le survol, absent sur écran tactile. Le bloc s'enfonce très
     légèrement sous le doigt : le geste est accusé avant même que la page ne
     change, ce qui évite le double appui par doute. */
  .cat-tuile:active,
  .cat-vedette:active,
  .autres-liste a:active,
  .choix-liens a:active{
    transform:scale(.985);
    transition-duration:90ms;
  }
  .cat-rang:not(.is-vedette):active{
    background:var(--white);
    box-shadow:var(--shadow-card);
  }
}

/* Sous 400 px, le padding latéral de 24 px prend 13 % de la largeur utile.
   Il descend à 18, et les blocs qui débordaient de 24 suivent, sans quoi ils
   dépasseraient le conteneur. */
@media (max-width: 400px){
  /* `padding-inline` et non la forme raccourcie : `padding:0 18px` remet à
     zéro le padding vertical de tout élément qui cumule .wrap et une autre
     classe. C'est ce qui arrivait au pied de page sous 400 px — .footer-top
     perdait ses 52/32 px et .footer-bottom ses 22 px, soit 128 px de
     respiration effacés d'un coup, sur la largeur des iPhone SE justement.
     Le piège est déjà signalé plus haut, à propos de .footer-top ; il se
     referme ici aussi. */
  .wrap{ padding-inline:18px; }
  .footer-bottom::before{ left:18px; right:18px; }
  .cat-rang{ padding:22px 18px; margin-inline:-18px; }
  .cat-rang::after{ left:18px; right:18px; }
  .cat-vedette{ padding:22px 18px 20px; }
  .cat-tuile{ padding:20px 18px 18px; }
}

/* Palier tablette : entre 700 et 1000 px, l'écran n'est ni un téléphone ni un
   bureau. Les 96 px de padding y restent trop généreux, sans qu'il faille
   descendre aux 56 px du mobile. */
@media (min-width: 701px) and (max-width: 1000px){
  .section{ padding:72px 0; }
  .section-head{ margin-bottom:36px; }
}

/* Les boutons portent `white-space:nowrap`, ce qui leur va tant que le libellé
   est court. « Demander un devis habilitation BT », le plus long du site,
   réclamait 333 px sur un écran de 320 et poussait toute la page hors cadre.
   Sous 420 px, le texte peut donc revenir à la ligne : mieux vaut un bouton sur
   deux lignes qu'une page entière décalée vers la droite. */
@media (max-width: 420px){
  .btn{ white-space:normal; text-align:center; }
  .form-hero-actions .btn,
  .cta-actions .btn{ width:100%; justify-content:center; }
}

/* ---------- bandeau de références (« ils nous font confiance ») ----------
   Deux séries identiques dans une piste deux fois plus large que le cadre :
   la translation de -50 % ramène la seconde exactement là où commençait la
   première, donc la boucle ne laisse voir aucun raccord. Les deux séries
   doivent rester rigoureusement identiques, gouttières comprises — d'où le
   demi-écart en padding de chaque série, qui reconstitue l'écart plein au
   point de jonction.

   Le fondu des bords est un masque, pas un filtre. Un `blur` sur un élément
   animé en continu se recalcule à chaque image, et c'est précisément ce que
   la feuille a cessé de faire ailleurs (en-tête, fiches de formation, voile
   du mégamenu). Le masque, lui, ne coûte rien par image. */
.refs-rail{
  position:relative; overflow:hidden; margin-top:36px;
  -webkit-mask-image:linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
          mask-image:linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
}
.refs-piste{ display:flex; width:max-content; animation:refs-defile 38s linear infinite; }
.refs-serie{ display:flex; align-items:center; gap:18px; padding:0 9px; margin:0; list-style:none; }
.refs-item{ flex:none; }
@keyframes refs-defile{ from{ transform:translate3d(0,0,0); } to{ transform:translate3d(-50%,0,0); } }

/* Survol et focus clavier suspendent le défilement ; le bouton le fige pour
   de bon. WCAG 2.2.2 : un mouvement automatique de plus de cinq secondes doit
   pouvoir être arrêté, et le survol seul ne répond ni au clavier ni au doigt. */
.refs-rail:hover .refs-piste,
.refs-rail:focus-within .refs-piste{ animation-play-state:paused; }
.refs-piste[data-fige="1"]{ animation-play-state:paused; }

/* La plaque accueille un logo client : même cadre que les cartes du site,
   dimensions fixes pour que des logos de proportions très différentes
   s'alignent quand même. `contain` préserve chaque rapport d'origine, sans
   jamais déformer une marque. */
.refs-plaque{
  display:flex; align-items:center; justify-content:center;
  width:200px; height:82px; padding:0 22px;
  background:var(--white); border:1px solid var(--line); border-radius:var(--radius-m);
}

/* Les logos clients arrivent dans des couleurs qui n'ont aucun rapport entre
   elles ni avec le navy et l'orange du site. Le passage en gris les fait
   tenir ensemble et empêche le bandeau de virer au patchwork ; la couleur
   revient au survol, là où le défilement s'arrête justement. Le filtre ne
   joue qu'au survol d'une plaque, jamais en continu. */
/* Deux plafonds, pas un seul : borné en hauteur uniquement, un logo très
   allongé occuperait toute la plaque quand un logo carré y flotterait, et la
   bande paraîtrait faite de marques d'importance inégale. Le plafond de
   largeur rétablit un poids optique comparable d'une plaque à l'autre. */
.refs-plaque img{
  max-width:76%; max-height:46px;
  width:auto; height:auto; object-fit:contain;
  filter:grayscale(1); opacity:.62;
  transition:opacity .2s ease, filter .2s ease;
}
.refs-plaque:hover img,
.refs-plaque:focus-within img{ filter:grayscale(0); opacity:1; }

/* GABARIT — l'état de la plaque tant qu'aucun logo n'est fourni. Même cadre,
   mêmes dimensions que la plaque remplie : le jour où les logos arrivent,
   rien ne bouge dans la mise en page, seul le contenu change. Le numéro
   d'emplacement n'est là que pour rendre le défilement lisible, huit plaques
   identiques ne laissant rien voir du mouvement. */
.refs-plaque--vide{ justify-content:flex-start; gap:14px; }
.refs-plaque--vide svg{ flex:none; color:var(--paper-line); }
.refs-mots{ display:flex; flex-direction:column; gap:7px; flex:1; }
.refs-mots i{ display:block; height:8px; border-radius:4px; background:var(--paper-alt); }
.refs-mots i:last-child{ width:60%; background:var(--paper-line); }
.refs-num{ font-family:var(--font-mono); font-size:11px; color:var(--paper-line); flex:none; }
.refs-note{ font-family:var(--font-mono); font-size:12px; letter-spacing:.04em; color:var(--ink-faint); }

/* Le rail garde sa hauteur avant même que les images soient décodées : sans
   ce plancher, la bande se déplierait sous le titre au chargement. */
.refs-rail{ min-height:82px; }

/* space-between sert les deux états sans règle supplémentaire : avec la note
   du gabarit, elle tient la gauche et le bouton la droite ; une fois les vrais
   logos posés la note disparaît, et le bouton reste seul à droite plutôt que
   de flotter au centre sous un titre aligné à gauche. */
.refs-barre{ display:flex; align-items:center; justify-content:space-between; gap:16px; margin-top:20px; }
.refs-pause{
  display:inline-flex; align-items:center; gap:8px;
  font-family:var(--font-mono); font-size:12px; letter-spacing:.06em; text-transform:uppercase;
  color:var(--ink-soft); background:transparent; cursor:pointer;
  border:1px solid var(--line); border-radius:999px; padding:9px 16px;
  min-height:44px; transition:color .2s ease, border-color .2s ease;
}
.refs-pause:hover{ color:var(--ink); border-color:var(--ink); }
.refs-pause svg{ width:13px; height:13px; flex:none; }

/* Tablette : la plaque perd un cran, le fondu des bords se resserre pour
   qu'une plaque entière reste lisible de chaque côté. */
@media (max-width: 900px){
  .refs-plaque{ width:176px; height:76px; padding:0 18px; }
  .refs-plaque img{ max-height:42px; }
  .refs-serie{ gap:14px; padding:0 7px; }
}

/* Mobile : sous 560 px le cadre ne montre plus que deux plaques. Le fondu
   passe de 10 % à 6 % de chaque bord, sinon il mange la plaque du milieu. */
@media (max-width: 560px){
  .refs-plaque{ width:152px; height:70px; padding:0 16px; }
  .refs-plaque img{ max-height:38px; }
  .refs-serie{ gap:12px; padding:0 6px; }
  .refs-rail{
    min-height:70px; margin-top:28px;
    -webkit-mask-image:linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
            mask-image:linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
  }
  /* Le libellé du bouton passe sous la note plutôt que de la comprimer. */
  .refs-barre{ margin-top:16px; flex-direction:column; align-items:flex-start; gap:12px; }
  .refs-plaque--vide{ gap:11px; }
}

/* Mouvement réduit : plus rien ne défile tout seul. La piste étant plus large
   que le cadre, les dernières plaques deviendraient alors inatteignables —
   le rail redevient donc une bande que l'on parcourt au doigt ou à la
   molette. Le masque tombe, sinon il laisserait croire à une coupure, la
   série en double disparaît puisqu'elle ne sert qu'à la boucle, et le bouton
   de pause n'a plus d'objet. */
@media (prefers-reduced-motion: reduce){
  .refs-piste{ animation:none; width:auto; }
  .refs-pause{ display:none; }
  .refs-rail{
    overflow-x:auto; scrollbar-width:thin;
    -webkit-mask-image:none; mask-image:none;
  }
  .refs-serie[aria-hidden="true"]{ display:none; }
}
