/* ==========================================================================
   Pro Rapport — feuille de style unique
   Mobile-first. Toutes les couleurs, tailles de police, espacements et
   rayons de bordure proviennent des variables ci-dessous : pour re-thémer
   le site, modifier uniquement ce bloc :root.
   ========================================================================== */

:root {
  /* --- Couleurs (palette v3, refonte premium) -----------------------------
     Esprit MoreApp (bleu marine + bleu vif + fonds lavande très clairs)
     fusionné à une pointe teal du secteur eau/assainissement. Les tokens
     existants (--c-primary, --c-accent, --c-bg-alt, --c-ink...) changent de
     VALEUR mais conservent leur RÔLE d'origine : tout le site déjà construit
     sur ces variables se re-thème automatiquement, sans toucher au CSS de
     composant. Seuls quelques tokens sont NOUVEAUX (--c-blue-vif, --c-teal*,
     --c-lien, --c-border-strong, --c-cta-light) pour les besoins ajoutés par
     cette refonte (mot-clé coloré, variété de sections, contours de champs).
     Contrastes vérifiés (calcul WCAG réel, pas une estimation) :
       --c-ink            sur --c-bg      : 15,6:1
       --c-ink-soft        sur --c-bg      : 6,4:1   / sur --c-bg-alt : 5,7:1
       --c-primary (navy)  sur --c-bg      : 15,5:1  / sur --c-bg-alt : 13,9:1
       blanc               sur --c-primary : 15,5:1
       blanc               sur --c-accent  : 4,6:1   (fond bouton réel ;
                                                --c-cta-light, plus vif, est
                                                réservé aux dégradés/halos
                                                décoratifs, jamais support de
                                                texte — il ne passe qu'à 3,4:1)
       blanc               sur --c-accent-dk : 7,3:1 (extrémité sombre du
                                                dégradé des boutons d'action —
                                                tout point intermédiaire entre
                                                --c-accent et --c-accent-dk
                                                reste ≥ 4,6:1, vérifié par
                                                échantillonnage)
       --c-blue-vif        sur --c-bg      : 4,6:1   (usage : gros titres
                                                gras ≥ --fs-500 uniquement,
                                                jamais en texte courant)
       --c-lien             sur --c-bg      : 6,7:1   (texte de lien standard)
       --c-teal             sur --c-bg      : 5,0:1
       --c-border-strong    sur --c-bg      : 3,2:1   (seuil UI 1.4.11, pour
                                                les contours de champs de
                                                formulaire — --c-border reste
                                                décoratif, sous ce seuil,
                                                toujours renforcé par une ombre)
       blanc/ink    sur --c-success/--c-error/--c-warning : ≥ 4,6:1 (inchangés)
     ------------------------------------------------------------------- */
  --c-ink: #16233D;          /* texte principal (teinté marine) */
  --c-ink-soft: #55606E;     /* texte secondaire */
  --c-primary: #0B2447;      /* marine profond — titres de marque, bandeaux forts, boutons secondaires */
  --c-primary-dk: #071A33;   /* survol de --c-primary, bandeaux pleine couleur les plus sombres */
  --c-accent: #C64F1F;       /* accent chaleureux — fond réel des boutons de conversion principaux */
  --c-accent-dk: #953911;    /* extrémité sombre du dégradé des boutons d'action (--c-accent → --c-accent-dk) */
  --c-cta-light: #E8622C;    /* variante vive de --c-accent, dégradés/halos décoratifs uniquement */
  --c-blue-vif: #2F6FED;     /* bleu vif MoreApp — mot-clé coloré des titres, gros éléments d'attention */
  --c-lien: #1D4ED8;         /* couleur de lien en texte courant (AA à toute taille) */
  --c-teal: #0E7C86;         /* secondaire secteur eau — icônes, badges, variété de sections */
  --c-teal-dk: #0A5F67;      /* survol/texte sur fond clair de --c-teal */
  --c-bg: #FFFFFF;
  --c-bg-alt: #EEF3FC;       /* lavande très clair — fonds de section alternés, cartes de chiffres */
  --c-bg-navy: var(--c-primary); /* alias explicite pour les bandeaux pleine couleur */
  --c-border: #DCE4F0;       /* décoratif — cartes/séparateurs, toujours doublé d'une ombre */
  --c-border-strong: #7590C0; /* fonctionnel — contours de champs de formulaire (contraste UI) */
  --c-success: #2F7A5C;
  --c-error: #C0392B;
  --c-warning: #9A6B0A;      /* avertissements non bloquants (distinct de --c-accent) */

  /* --- Typographie -------------------------------------------------------
     Pile système, hiérarchie large et affirmée façon MoreApp : titres plus
     grands et plus gras qu'en v2, tailles fluides via clamp(). Base 17px
     (mobile) → 18px (desktop). */
  --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --fs-100: clamp(0.875rem, 0.84rem + 0.2vw, 0.9375rem);   /* ~14–15px : petits textes */
  --fs-200: clamp(1.0625rem, 1rem + 0.3vw, 1.125rem);      /* ~17–18px : corps de texte */
  --fs-300: clamp(1.1875rem, 1.1rem + 0.5vw, 1.3125rem);   /* ~19–21px : intitulés, logo */
  --fs-400: clamp(1.4375rem, 1.25rem + 1.1vw, 1.75rem);    /* ~23–28px : h3 */
  --fs-500: clamp(1.875rem, 1.5rem + 2.2vw, 2.5rem);       /* ~30–40px : h2 */
  --fs-600: clamp(2.5rem, 1.7rem + 4.5vw, 4rem);           /* ~40–64px : h1, affirmé façon MoreApp */
  --fs-700: clamp(2.5rem, 2rem + 3vw, 3.75rem);            /* ~40–60px : gros chiffres animés (cartes chiffres-clés) */
  --fw-heading: 800;         /* graisse des titres h1/h2 (le système gère 800 sans webfont) */
  --lh-body: 1.65;
  --lh-heading: 1.12;
  --measure: 68ch; /* largeur de ligne confortable pour le texte courant */

  /* --- Espacements (échelle élargie pour plus d'air entre les groupes) --- */
  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 20px;
  --sp-5: 28px;
  --sp-6: 40px;
  --sp-7: 56px;
  --sp-8: 80px;
  --sp-9: 112px;   /* respiration verticale entre sections premium (vitrine) */

  /* --- Formes / effets ---------------------------------------------------- */
  --radius: 10px;             /* coins légèrement arrondis (composants existants, tunnel/espace/légal) */
  --radius-sm: 6px;           /* éléments compacts (badges, pastilles) */
  --radius-lg: 20px;          /* coins doux et généreux — cartes premium, cadres de maquettes, bandeaux */
  --transition: 180ms ease;   /* transitions douces (boutons, liens, tiroir nav) — composants existants */
  --tap-target: 44px;         /* taille de cible tactile minimale (burger) */
  --shadow-sm: 0 1px 2px rgba(11, 36, 71, 0.06), 0 1px 1px rgba(11, 36, 71, 0.04);
  --shadow-md: 0 8px 24px rgba(11, 36, 71, 0.10), 0 2px 8px rgba(11, 36, 71, 0.06);
  --shadow-lg: 0 24px 48px rgba(11, 36, 71, 0.16), 0 8px 16px rgba(11, 36, 71, 0.08); /* cadres de maquettes, cartes élevées au survol */
  --shadow-focus: 0 0 0 3px rgba(11, 36, 71, 0.22); /* halo de focus (--c-primary) */

  /* --- Mouvement (refonte premium) -----------------------------------------
     Tokens de durée/easing partagés par toutes les animations du site
     (scroll-reveal, header dynamique, micro-interactions, ambiance, carrousel,
     animation signature). Centralisés ici pour un tempo cohérent partout :
     plus dynamique que "Lassie" mais jamais précipité. */
  --ease-out-soft: cubic-bezier(0.22, 0.61, 0.36, 1);
  --ease-in-out-soft: cubic-bezier(0.45, 0, 0.2, 1);
  --dur-fast: 200ms;   /* micro-interactions (survol boutons/cartes) */
  --dur-base: 450ms;   /* révélations au scroll, transitions de composant */
  --dur-slow: 900ms;   /* transformations amples (morphing, header, intro) */

  /* --- Mise en page ------------------------------------------------------- */
  --container-max: 1180px;    /* largeur max des conteneurs d'en-tête/pied de page */
  --container-wide: 1320px;   /* largeur max des sections premium pleine largeur (vitrine) */
  --table-min-w: 640px;       /* largeur minimale avant défilement horizontal des tableaux */
}

/* ==========================================================================
   Réinitialisation & base
   ========================================================================== */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  color-scheme: light;
  -webkit-text-size-adjust: 100%;
}

@media (prefers-reduced-motion: no-preference) {
  html {
    scroll-behavior: smooth;
  }
}

body {
  margin: 0;
  background: var(--c-bg);
  color: var(--c-ink);
  font-family: var(--font-sans);
  font-size: var(--fs-200);
  line-height: var(--lh-body);
}

img,
svg,
video {
  display: block;
  max-width: 100%;
  height: auto;
}

/* Décalage de l'ancrage pour compenser l'en-tête collant lors des sauts
   internes (sommaire, retour en haut, lien d'évitement). */
[id] {
  scroll-margin-top: var(--sp-7);
}

/* L'attribut hidden natif doit toujours l'emporter sur toute règle de
   display déclarée par ailleurs (ex. display:grid/flex sur un composant) :
   même spécificité qu'un sélecteur de classe, donc sans ce !important un
   élément masqué peut rester visible si son display est redéfini ailleurs. */
[hidden] {
  display: none !important;
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ==========================================================================
   Typographie
   ========================================================================== */

h1, h2, h3, h4, h5, h6 {
  margin: 0 0 var(--sp-4);
  color: var(--c-ink);
  font-weight: 700;
  line-height: var(--lh-heading);
  letter-spacing: -0.01em;
}

h1 { font-size: var(--fs-600); font-weight: 800; letter-spacing: -0.02em; }
h2 { font-size: var(--fs-500); font-weight: 700; }
h3 { font-size: var(--fs-400); font-weight: 600; }
h4, h5, h6 { font-size: var(--fs-300); font-weight: 600; }

p {
  margin: 0 0 var(--sp-4);
  max-width: var(--measure);
}

li {
  max-width: var(--measure);
}

strong { font-weight: 700; }
em { font-style: italic; }

a {
  color: var(--c-primary);
  text-decoration: underline;
  text-underline-offset: 0.15em;
  text-decoration-thickness: 1px;
}

a:hover {
  color: var(--c-primary-dk);
}

ul, ol {
  margin: 0 0 var(--sp-4);
  padding-left: var(--sp-5);
}

/* ==========================================================================
   Accessibilité — focus, lien d'évitement, sr-only
   ========================================================================== */

a:focus-visible,
button:focus-visible,
input:focus-visible,
textarea:focus-visible,
select:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--c-ink);
  outline-offset: 2px;
}

/* Halo de focus plus élégant, spécifique aux champs de saisie (remplace le
   simple contour ci-dessus sur ces éléments précis — spécificité plus forte
   grâce aux :not() ; les boutons/liens/cases gardent le contour standard). */
input:not([type="checkbox"]):not([type="file"]):focus-visible,
textarea:focus-visible,
select:focus-visible {
  outline: none;
  border-color: var(--c-primary);
  box-shadow: var(--shadow-focus);
}

.skip-link {
  position: absolute;
  top: var(--sp-2);
  left: var(--sp-2);
  z-index: 1000;
  transform: translateY(-150%);
  background: var(--c-bg);
  color: var(--c-primary);
  border: 1px solid var(--c-border);
  border-radius: var(--radius);
  padding: var(--sp-2) var(--sp-4);
  text-decoration: none;
  font-weight: 600;
  box-shadow: var(--shadow-md);
  transition: transform var(--transition);
}

.skip-link:focus {
  transform: translateY(0);
}

.skip-link:focus-visible {
  outline: 2px solid var(--c-ink);
  outline-offset: 2px;
}

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

/* ==========================================================================
   Bandeau bêta (page d'accueil uniquement — voir index.html)
   ========================================================================== */

.bandeau-beta {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-4);
  background: var(--c-warning);
  color: var(--c-bg);
  text-decoration: none;
  font-size: var(--fs-100);
  font-weight: 600;
  text-align: center;
  transition: background-color var(--dur-fast) var(--ease-out-soft);
}

/* Teinte plus sombre calculée (-18% par canal) — vérifiée : blanc dessus
   reste à 6,39:1 (contre 4,69:1 au repos, déjà conforme AA). */
.bandeau-beta:hover {
  background: #7E5808;
}

.bandeau-beta-icone {
  display: flex;
  flex-shrink: 0;
}

.bandeau-beta-icone svg {
  width: 16px;
  height: 16px;
}

.bandeau-beta strong {
  font-weight: 800;
}

/* Sur mobile, le bandeau se limite au strict essentiel ("Site en phase de
   lancement") : le reste du message (déjà répété dans .notice-beta sur les
   pages qui en ont une, et de toute façon dans /contact.html au clic) coûte
   une ligne de hauteur précieuse tout en haut de l'écran, avant même le
   contenu de la page. */
@media (max-width: 799px) {
  .bandeau-beta-texte-detail {
    display: none;
  }
}

.bandeau-beta-fleche {
  flex-shrink: 0;
  transition: transform var(--dur-fast) var(--ease-out-soft);
}

.bandeau-beta:hover .bandeau-beta-fleche {
  transform: translateX(3px);
}

/* ==========================================================================
   En-tête
   ========================================================================== */

.site-header {
  position: sticky;
  top: 0;
  z-index: 900;
  background: var(--c-bg);
  box-shadow: 0 1px 0 var(--c-border), var(--shadow-sm);
  transition: box-shadow var(--dur-fast) var(--ease-out-soft);
}

/* En-tête compact au scroll (posé par assets/js/site-motion.js) : l'en-tête
   est déjà opaque au repos (le site n'a pas de hero plein cadre derrière),
   l'effet "devient compact" se joue donc sur le padding vertical et une
   ombre plus marquée plutôt que sur une transparence initiale. */
.site-header--scrolled {
  box-shadow: 0 1px 0 var(--c-border), var(--shadow-md);
}

.header-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  align-content: center;
  justify-content: space-between;
  gap: var(--sp-3);
  max-width: var(--container-max);
  margin-inline: auto;
  /* --entete-t (0 à 1) suit le scroll en direct sur .site-header — aucune
     transition ici : une valeur pilotée à chaque frame par le script ne
     doit jamais être retardée par une transition CSS, sous peine de courir
     après la position réelle du scroll. */
  padding: calc(var(--sp-4) - (var(--sp-4) - var(--sp-2)) * var(--entete-t, 0)) var(--sp-4);
}

/* Padding vertical resserré sur mobile (même logique de repli au scroll que
   la formule ci-dessus, juste avec des valeurs de départ plus petites) :
   avec le bandeau bêta déjà au-dessus, l'en-tête n'a pas besoin d'autant de
   respiration verticale que sur desktop pour rester lisible. */
@media (max-width: 799px) {
  .header-inner {
    padding-inline: var(--sp-3);
    padding-block: calc(var(--sp-3) - (var(--sp-3) - var(--sp-1)) * var(--entete-t, 0));
    /* Le gap partagé entre TOUTES les lignes empilées (.header-ligne /
       .header-slogan-mobile / .main-nav) ne peut pas suivre --entete-t à lui
       seul : une valeur unique de gap ne distingue pas "juste après le
       slogan" de "juste après le tiroir nav", qui doivent pouvoir varier
       indépendamment. Remplacé ci-dessous par un margin-top explicite sur
       chacune de ces deux lignes, qui elles PEUVENT suivre chacune leur
       propre état (scroll pour l'une, ouverture pour l'autre) — un essai
       avec une marge négative pour annuler ce gap n'a pas fonctionné : dans
       un conteneur flex multi-lignes, une marge négative ne réduit pas la
       hauteur automatique du conteneur, elle fait juste chevaucher visuellement
       la ligne suivante sans que .header-inner ne s'en trouve plus compact. */
    gap: 0;
  }
}

/* Regroupe logo + CTA + burger dans une ligne qui ne se replie JAMAIS,
   même sur les téléphones les plus étroits (correction d'un bug réel :
   avec .header-inner seul en flex-wrap, ce trio se répartissait sur 2 ou 3
   lignes dès que la somme de leurs largeurs dépassait la largeur de
   l'écran). Sur desktop, ce groupement redevient transparent
   (display:contents : la boîte disparaît, ses enfants réintègrent
   .header-inner comme avant) puisque .main-nav a alors la place de tenir
   sur la même ligne — order/flex-shrink existants sur .logo/.header-cta/
   .nav-toggle-label continuent de s'appliquer normalement dans les deux cas. */
.header-ligne {
  display: contents;
}

@media (max-width: 799px) {
  .header-ligne {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-1);
    flex-basis: 100%;
    order: 1;
    min-width: 0;
  }
}

.logo {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
  color: var(--c-primary);
  text-decoration: none;
  line-height: 1;
  min-width: 0;
}

@media (min-width: 800px) {
  .logo {
    order: 1;
  }
}

/* Bloc nom + slogan, empilé à droite de l'icône façon "wordmark + baseline"
   (un seul repère de marque, pas une bannière à part) — masqué sur mobile :
   à côté de l'icône (déjà grande), du bouton CTA et du bouton burger, ce
   bloc ferait déborder l'en-tête sur les petits écrans (calcul : logo +
   texte + CTA + burger dépasse la largeur d'un téléphone en portrait).
   Révélé dès que la nav complète elle-même apparaît (≥800px, largeur où la
   place ne manque plus). */
.logo-texte {
  display: none;
  flex-direction: column;
}

@media (min-width: 800px) {
  .logo-texte {
    display: flex;
  }
}

.logo-nom {
  font-size: var(--fs-400);
  font-weight: 800;
  letter-spacing: -0.01em;
  white-space: nowrap;
}

/* Composition "nom / trait / signature" façon masthead éditorial : un petit
   trait de couleur entre le wordmark et le slogan, plutôt qu'une icône
   littérale — plus sobre, plus typographique. Regroupés dans un seul bloc
   qui suit --entete-t comme le reste de l'en-tête (trait ET texte se
   réduisent/s'effacent ensemble au scroll, aucune transition ici — une
   valeur pilotée à chaque frame ne doit jamais courir après le scroll avec
   un retard de transition), pour ne pas manger d'espace vertical pendant la
   lecture. Reste dans le DOM même replié (overflow:hidden plutôt que
   display:none) : toujours accessible aux lecteurs d'écran. */
.logo-slogan-bloc {
  overflow: hidden;
  max-height: calc(3.4em * (1 - var(--entete-t, 0)));
  opacity: calc(1 - var(--entete-t, 0));
}

.logo-trait {
  display: block;
  width: 28px;
  height: 3px;
  margin: 6px 0 7px;
  border-radius: 999px;
  background: var(--c-teal);
}

/* Largeur bornée + retour à la ligne libre : se replie en 2 lignes sous le
   nom plutôt que de s'étirer sur toute la largeur de l'en-tête. */
.logo-slogan {
  display: block;
  max-width: 21rem;
  color: var(--c-ink-soft);
  font-size: var(--fs-100);
  font-weight: 600;
  letter-spacing: .015em;
  line-height: 1.4;
}

.logo-slogan strong {
  color: var(--c-teal-dk);
  font-weight: 800;
}

/* Logo provisoire (image carrée) : hauteur fixe, largeur automatique pour
   conserver ses proportions. À ajuster une fois le logo définitif livré. */
.logo img {
  display: block;
  height: calc(88px - 24px * var(--entete-t, 0));
  width: auto;
  flex-shrink: 0;
  transition: transform var(--dur-fast) var(--ease-out-soft);
}

/* Icône plus petite que sur desktop : sans le nom/slogan à côté (masqués,
   voir .logo-texte plus haut), une icône aussi grande qu'en desktop mangerait
   une part disproportionnée de la ligne logo/CTA/burger. Hauteur de BOÎTE
   fixe (ne suit plus --entete-t) : le burger, à 44px fixes lui aussi, plafonne
   de toute façon déjà la hauteur de cette ligne — faire rétrécir la boîte du
   logo seul au scroll ne réduisait donc pas l'en-tête, juste rendait le logo
   petit et disproportionné à côté du burger. L'agrandissement au scroll
   ci-dessous reste PUREMENT visuel (scale) : la boîte réservée dans le flux
   ne bouge pas, donc rien d'autre ne se déplace (burger, CTA, slogan). */
@media (max-width: 799px) {
  .logo img {
    height: 44px;
    /* Grandit encore un peu une fois l'en-tête compact (slogan replié) :
       l'icône occupe alors davantage de la hauteur libérée, au lieu de
       paraître perdue/petite dans un en-tête devenu plus court. */
    transform: scale(calc(1.5 + 0.4 * var(--entete-t, 0)));
  }

  .logo:hover img {
    transform: scale(calc((1.5 + 0.4 * var(--entete-t, 0)) * 1.04));
  }
}

.logo:hover img {
  transform: scale(1.04);
}

.logo:hover {
  color: var(--c-primary-dk);
}

/* Case à cocher réelle : masquée visuellement mais jamais avec display:none,
   pour rester focusable et annoncée par les lecteurs d'écran/clavier. */
.nav-toggle-input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  white-space: nowrap;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  border: 0;
}

.nav-toggle-label {
  order: 3;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--tap-target);
  height: var(--tap-target);
  flex-shrink: 0;
  border-radius: var(--radius);
  cursor: pointer;
  transition: background var(--transition);
}

.nav-toggle-label:hover {
  background: var(--c-bg-alt);
}

/* Le focus visible de la vraie checkbox est reporté sur le label associé. */
.nav-toggle-input:focus-visible + .nav-toggle-label {
  outline: 2px solid var(--c-ink);
  outline-offset: 2px;
}

.burger {
  position: relative;
  display: block;
  width: var(--sp-5);
  height: 2px;
  background: var(--c-ink);
  transition: background-color var(--transition);
}

.burger::before,
.burger::after {
  content: "";
  position: absolute;
  left: 0;
  width: var(--sp-5);
  height: 2px;
  background: var(--c-ink);
  transition: transform var(--transition);
}

.burger::before { top: calc(-1 * var(--sp-2)); }
.burger::after { top: var(--sp-2); }

/* Repli en croix (X) à l'ouverture — la barre du milieu s'efface, les deux
   autres se recentrent puis pivotent pour former le X. background-color
   plutôt qu'opacity : opacity sur .burger rendrait aussi ses pseudo-éléments
   (::before/::after, le X lui-même) transparents, puisqu'ils héritent son
   contexte d'opacité. Le sélecteur remonte jusqu'à .header-ligne (frère de
   la case à cocher, voir la restructuration du header pour le mobile)
   puisque .burger est niché plus profond que la simple fratrie directe. */
#nav-toggle:checked ~ .header-ligne .burger {
  background-color: transparent;
}

#nav-toggle:checked ~ .header-ligne .burger::before {
  transform: translateY(var(--sp-2)) rotate(45deg);
}

#nav-toggle:checked ~ .header-ligne .burger::after {
  transform: translateY(calc(-1 * var(--sp-2))) rotate(-45deg);
}

/* Tiroir nav mobile : repli/déploiement animé façon accordéon (grille dont
   la ligne passe de 0fr à 1fr — la technique CSS standard pour transitionner
   depuis/vers une hauteur "auto", impossible à animer directement). visibility
   reste synchronisée mais décalée : les liens ne redeviennent focusables/
   cliquables qu'une fois le tiroir réellement ouvert, et cessent de l'être
   dès la fermeture — jamais de lien invisible mais encore atteignable au
   clavier. */
.main-nav {
  order: 4;
  display: grid;
  grid-template-rows: 0fr;
  flex-basis: 100%;
  opacity: 0;
  visibility: hidden;
  overflow: hidden;
  /* .header-inner n'a plus de gap partagé sur mobile (voir plus haut) :
     fermé, ce tiroir n'a besoin d'aucun espace au-dessus de lui (il est à 0
     de hauteur, invisible) — l'espace n'apparaît qu'à l'ouverture, ci-dessous. */
  margin-top: 0;
  transition: grid-template-rows var(--transition),
              opacity var(--transition),
              visibility 0s linear 180ms,
              margin-top var(--transition);
}

/* Sélecteur de fratrie général : le HTML place la case avant le label et
   avant la nav, ce qui permet de révéler le tiroir sans JavaScript. */
#nav-toggle:checked ~ .main-nav {
  grid-template-rows: 1fr;
  opacity: 1;
  visibility: visible;
  /* Ouvert, l'espace au-dessus du tiroir redevient utile (desktop le remet
     à 0 explicitement plus bas, la nav y étant déjà en ligne). */
  margin-top: var(--sp-3);
  transition: grid-template-rows var(--transition),
              opacity var(--transition),
              visibility 0s linear 0s,
              margin-top var(--transition);
}

/* Le padding de la liste doit lui aussi retomber à 0 fermé : min-height:0 sur
   la <ul> (ci-dessous) laisse son CONTENU se réduire à rien, mais pas son
   propre padding — sans ce retrait, ~32px de padding restaient visibles même
   ligne réduite à 0fr, empêchant le tiroir de vraiment disparaître. */
#nav-toggle:checked ~ .main-nav ul {
  padding: var(--sp-3) 0 var(--sp-4);
}

/* Version mobile du slogan : sur desktop il vit niché sous le nom dans
   .logo-texte (masqué <800px, voir plus haut) — sur mobile, cette place
   n'existe plus (icône seule dans .header-ligne), donc une ligne dédiée,
   pleine largeur, juste sous logo/CTA/burger. Suit --entete-t comme le
   reste de l'en-tête (aucune transition : valeur pilotée à chaque frame). */
.header-slogan-mobile {
  order: 2;
  flex-basis: 100%;
  overflow: hidden;
  max-height: calc(2.8em * (1 - var(--entete-t, 0)));
  margin: 0;
  /* .header-inner n'a plus de gap partagé sur mobile (voir plus haut) :
     l'espace au-dessus de cette ligne vit ici, et se replie à 0 au même
     rythme que le slogan lui-même — jamais d'espace vide qui reste "coincé"
     sous la ligne logo/CTA/burger une fois le slogan disparu au scroll. */
  margin-top: calc(var(--sp-3) * (1 - var(--entete-t, 0)));
  opacity: calc(1 - var(--entete-t, 0));
  color: var(--c-ink-soft);
  font-size: var(--fs-100);
  font-weight: 600;
  letter-spacing: .015em;
  line-height: 1.4;
}

.header-slogan-mobile strong {
  color: var(--c-teal-dk);
  font-weight: 800;
}

@media (min-width: 800px) {
  .header-slogan-mobile {
    display: none;
  }
}

.main-nav ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  min-height: 0;
  overflow: hidden;
  transition: padding var(--transition);
}

.main-nav a {
  display: block;
  padding: var(--sp-3);
  color: var(--c-ink);
  text-decoration: none;
  border-radius: var(--radius);
  font-weight: 600;
  letter-spacing: 0.01em;
  transition: background var(--transition), color var(--transition);
}

.main-nav a:hover,
.main-nav a[aria-current="page"] {
  background: var(--c-bg-alt);
  color: var(--c-primary);
}

.header-cta {
  order: 2;
  flex-shrink: 1;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

@media (min-width: 800px) {
  .header-inner {
    flex-wrap: nowrap;
  }

  .nav-toggle-label {
    display: none;
  }

  /* Même sélecteur qu'en mobile (spécificité identique grâce à l'ID) afin
     que la nav reste TOUJOURS visible en ligne sur desktop, indépendamment
     de l'état de la case à cocher. */
  .main-nav,
  #nav-toggle:checked ~ .main-nav {
    order: 2;
    display: flex;
    flex-basis: auto;
    opacity: 1;
    visibility: visible;
    overflow: visible;
    margin-top: 0;
  }

  .main-nav ul,
  #nav-toggle:checked ~ .main-nav ul {
    flex-direction: row;
    align-items: center;
    padding: 0;
    gap: var(--sp-5);
  }

  /* Soulignement animé au survol (desktop uniquement — le tiroir mobile
     garde sa simple surbrillance de fond, plus adaptée à une liste
     empilée). Position absolute + scaleX plutôt qu'un width animé : évite
     tout recalcul de layout pendant la transition. */
  .main-nav a {
    position: relative;
    padding: var(--sp-2) var(--sp-1);
    overflow: visible;
  }

  .main-nav a::after {
    content: "";
    position: absolute;
    left: var(--sp-1);
    right: var(--sp-1);
    bottom: -2px;
    height: 2px;
    border-radius: 999px;
    background: var(--c-blue-vif);
    transform: scaleX(0);
    transform-origin: left center;
    transition: transform var(--dur-fast) var(--ease-out-soft);
  }

  .main-nav a:hover::after,
  .main-nav a:focus-visible::after,
  .main-nav a[aria-current="page"]::after {
    transform: scaleX(1);
  }

  /* Le remplissage de fond (pertinent pour le tiroir mobile empilé) cède la
     place au soulignement seul sur desktop : plus épuré, une seule
     indication à la fois (survol OU page courante) plutôt que deux
     superposées. */
  .main-nav a:hover,
  .main-nav a[aria-current="page"] {
    background: transparent;
  }

  .header-cta {
    order: 3;
  }
}

/* ==========================================================================
   Boutons
   ========================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-5);
  border: 1px solid var(--c-border);
  border-radius: var(--radius);
  background: var(--c-bg);
  color: var(--c-primary);
  font-family: inherit;
  font-size: var(--fs-200);
  font-weight: 700;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--transition), color var(--transition), border-color var(--transition), box-shadow var(--transition), filter var(--transition);
}

.btn:hover {
  background: var(--c-bg-alt);
  border-color: var(--c-primary);
  box-shadow: var(--shadow-sm);
}

.btn:focus-visible {
  outline: 2px solid var(--c-ink);
  outline-offset: 2px;
}

/* Bouton d'action principal — réservé au SEUL geste de conversion majeur du
   site ("Recevoir mon premier rapport offert") : forme pilule, seul bouton
   du site à la porter, pour qu'elle reste un signal visuel unique plutôt que
   diluée sur tous les boutons d'action (voir .btn-commander/.btn-choisir
   pour les actions secondaires des tuiles tarifs, volontairement plus
   discrètes). Fond uni --c-accent (pas de dégradé sombre, pas de halo teinté
   — rendu plus clair et plus calme) qui glisse en douceur vers --c-primary
   au survol/clic : une transition de teinte plutôt qu'un simple
   assombrissement, pour un effet "confiance" plutôt que "urgence". Tout
   point intermédiaire de ce glissement reste ≥ 4,6:1 pour du texte blanc
   (vérifié par échantillonnage : le passage du orange vers le marine ne fait
   qu'améliorer le contraste à chaque étape, jamais le contraire). */
.btn-accent {
  border-color: transparent;
  border-radius: 999px;
  background-color: var(--c-accent);
  color: var(--c-bg);
  box-shadow: var(--shadow-sm);
  transition: background-color var(--dur-base) var(--ease-out-soft),
              transform var(--dur-fast) var(--ease-out-soft),
              box-shadow var(--dur-fast) var(--ease-out-soft);
}

/* Survol vers --c-teal plutôt que --c-primary : un glissement de teinte
   nettement moins sombre (4,95:1 pour le texte blanc, contre 15,47:1 pour le
   marine) et moins abrupt à l'œil, tout en restant un vrai changement de
   couleur plutôt qu'un simple assombrissement. Vérifié par échantillonnage :
   chaque étape du dégradé --c-accent → --c-teal reste ≥ 4,5:1. */
.btn-accent:hover {
  background-color: var(--c-teal);
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
}

.btn-accent:active {
  background-color: var(--c-teal-dk);
  transform: translateY(0);
  box-shadow: var(--shadow-sm);
}

/* Boutons "rapport offert" (en-tête, hero, rappel final) : gardent le léger
   soulèvement au survol/clic de .btn-accent, mais SANS le glissement de
   teinte — volontairement plus discrets que les autres .btn-accent
   (formulaires, "Suivant"…) qui conservent leur retour de couleur habituel.
   Sélecteurs à deux classes : spécificité volontairement plus élevée que
   .btn-accent:hover/:active ci-dessus, pour ne pas dépendre de l'ordre des
   règles dans la feuille de style. */
.btn-accent.header-cta:hover,
.btn-accent.header-cta:active,
.btn-accent.hero-premium-cta:hover,
.btn-accent.hero-premium-cta:active,
.vitrine-cta-final .btn-accent:hover,
.vitrine-cta-final .btn-accent:active {
  background-color: var(--c-accent);
}

/* Boutons d'action secondaires des tuiles tarifs — délibérément plus petits
   et plus sobres que .btn-accent (règle du client : « moins gros, moins
   voyant, plus discret, mais compréhensible »), et volontairement
   DIFFÉRENTS l'un de l'autre pour ne jamais laisser croire qu'il s'agit du
   même type d'action : .btn-commander (achat à l'unité, contour seul) vs
   .btn-choisir (abonnement, fond teal plein) — le contour signale un geste
   simple et ponctuel, le fond plein un engagement qui mérite un peu plus de
   présence, sans jamais rivaliser avec le bouton d'action principal. */
.btn-sm {
  padding: var(--sp-2) var(--sp-4);
  font-size: var(--fs-100);
  border-radius: var(--radius);
}

.btn-commander {
  border-color: var(--c-border-strong);
  background: transparent;
  color: var(--c-primary);
  font-weight: 600;
  transition: background var(--dur-fast) var(--ease-out-soft),
              border-color var(--dur-fast) var(--ease-out-soft),
              color var(--dur-fast) var(--ease-out-soft);
}

.btn-commander:hover {
  background: var(--c-bg-alt);
  border-color: var(--c-primary);
}

.btn-commander:active {
  background: var(--c-border);
}

.btn-choisir {
  border-color: transparent;
  background-color: var(--c-teal);
  color: var(--c-bg);
  font-weight: 600;
  transition: background-color var(--dur-fast) var(--ease-out-soft),
              transform var(--dur-fast) var(--ease-out-soft);
}

.btn-choisir:hover {
  background-color: var(--c-teal-dk);
  transform: translateY(-1px);
}

.btn-choisir:active {
  transform: translateY(0);
}

.header-cta {
  padding: var(--sp-2) var(--sp-3);
  font-size: var(--fs-100);
  transition: background-color var(--dur-base) var(--ease-out-soft),
              box-shadow var(--dur-fast) var(--ease-out-soft),
              transform var(--dur-fast) var(--ease-out-soft);
}

.header-cta:hover {
  transform: translateY(-2px);
}

@media (min-width: 800px) {
  .header-cta {
    padding: var(--sp-3) var(--sp-5);
    font-size: var(--fs-200);
  }
}

/* ==========================================================================
   Pied de page
   ========================================================================== */

.site-footer {
  background: var(--c-bg-alt);
  border-top: 1px solid var(--c-border);
  padding: var(--sp-8) 0 var(--sp-5);
  color: var(--c-ink);
}

.footer-inner {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-6);
  max-width: var(--container-max);
  margin-inline: auto;
  padding: 0 var(--sp-4);
}

@media (min-width: 800px) {
  .footer-inner {
    grid-template-columns: repeat(3, 1fr);
  }
}

.footer-title {
  margin: 0 0 var(--sp-3);
  font-size: var(--fs-300);
  color: var(--c-ink);
}

.footer-col p {
  color: var(--c-ink-soft);
  margin: 0 0 var(--sp-2);
  max-width: none;
}

/* Petit repère visuel WhatsApp accolé à une mention du mot dans du texte
   courant (pied de page, ligne de réassurance du hero…) — jamais seul,
   toujours à côté du mot qui l'explique déjà. */
.icone-whatsapp-inline {
  display: inline-block;
  vertical-align: -3px;
  margin-left: var(--sp-1);
}

.footer-col ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}

.footer-col a {
  color: var(--c-ink-soft);
  text-decoration: none;
}

.footer-col a:hover {
  color: var(--c-primary);
  text-decoration: underline;
}

.footer-bottom {
  max-width: var(--container-max);
  margin: var(--sp-6) auto 0;
  padding: var(--sp-5) var(--sp-4) 0;
  border-top: 1px solid var(--c-border);
  text-align: center;
  color: var(--c-ink-soft);
  font-size: var(--fs-100);
}

.footer-bottom p {
  max-width: none;
  margin: 0;
}

/* ==========================================================================
   Composants — pages en construction & pages légales
   ========================================================================== */

.page-placeholder {
  max-width: var(--measure);
  margin-inline: auto;
  padding: var(--sp-8) var(--sp-4);
  text-align: center;
}

.page-placeholder p {
  margin-inline: auto;
}

.legal-doc {
  max-width: var(--measure);
  margin-inline: auto;
  padding: var(--sp-7) var(--sp-4);
}

.legal-doc h2,
.legal-doc h3 {
  margin-top: var(--sp-7);
}

.doc-version {
  margin: 0 0 var(--sp-6);
  color: var(--c-ink-soft);
  font-style: italic;
  font-size: var(--fs-100);
}

.doc-note {
  margin: var(--sp-6) 0 0;
  color: var(--c-ink-soft);
  font-size: var(--fs-100);
}

.toc {
  display: block;
  background: var(--c-bg-alt);
  border: 1px solid var(--c-border);
  border-radius: var(--radius);
  padding: var(--sp-5);
  margin: 0 0 var(--sp-6);
  box-shadow: var(--shadow-sm);
}

.toc ol,
.toc ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
}

.toc li ol,
.toc li ul {
  margin-top: var(--sp-1);
  padding-left: var(--sp-5);
}

.toc a {
  text-decoration: none;
}

.toc a:hover {
  text-decoration: underline;
}

.table-scroll {
  overflow-x: auto;
  margin: var(--sp-5) 0;
  border: 1px solid var(--c-border);
  border-radius: var(--radius);
}

.table-scroll table {
  width: 100%;
  min-width: var(--table-min-w);
  border-collapse: collapse;
}

.table-scroll th,
.table-scroll td {
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--c-border);
  text-align: left;
}

.table-scroll thead {
  background: var(--c-bg-alt);
}

.table-scroll th {
  color: var(--c-ink);
  font-weight: 700;
}

.back-to-top {
  display: inline-block;
  margin-top: var(--sp-5);
  color: var(--c-ink-soft);
  font-size: var(--fs-100);
  text-decoration: none;
}

.back-to-top:hover {
  color: var(--c-primary);
  text-decoration: underline;
}

/* ==========================================================================
   Formulaires (styles de base génériques, pour les pages à venir)
   ========================================================================== */

label {
  display: block;
  margin-bottom: var(--sp-1);
  font-weight: 600;
}

input,
textarea,
select,
button {
  font-family: inherit;
  font-size: var(--fs-200);
}

input[type="text"],
input[type="email"],
input[type="tel"],
input[type="password"],
input[type="search"],
textarea,
select {
  width: 100%;
  padding: var(--sp-3);
  margin-bottom: var(--sp-4);
  /* --c-border-strong (pas --c-border, décoratif) : ces champs sont des
     composants d'interface fonctionnels, leur contour au repos doit
     atteindre le seuil de contraste non-textuel WCAG 1.4.11 (~3:1). */
  border: 1px solid var(--c-border-strong);
  border-radius: var(--radius);
  background: var(--c-bg);
  color: var(--c-ink);
  transition: border-color var(--transition), box-shadow var(--transition);
}

/* ==========================================================================
   Impression
   ========================================================================== */

@media print {
  .site-header,
  .site-footer,
  .skip-link,
  .nav-toggle-label,
  .back-to-top,
  .espace-nav {
    display: none !important;
  }

  * {
    background: var(--c-bg) !important;
    color: var(--c-ink) !important;
    box-shadow: none !important;
  }

  a {
    color: var(--c-ink) !important;
    text-decoration: underline;
  }

  .table-scroll {
    overflow-x: visible;
    border: none;
  }

  table {
    width: 100%;
  }

  tr {
    break-inside: avoid;
    page-break-inside: avoid;
  }
}

/* ==========================================================================
   Tunnel d'inscription (/inscription.html)
   Toutes les valeurs proviennent des variables :root définies en tête de
   fichier. Sections nouvelles uniquement : aucune règle ci-dessus n'est
   modifiée.
   ========================================================================== */

.tunnel {
  max-width: var(--container-max);
  margin-inline: auto;
  padding: var(--sp-7) var(--sp-4) var(--sp-8);
}

.tunnel-intro {
  max-width: var(--measure);
  margin: 0 auto var(--sp-7);
  text-align: center;
}

.tunnel-intro p {
  margin: 0 auto;
  color: var(--c-ink-soft);
}

/* --- Indicateur d'étapes (décoratif, l'information textuelle équivalente
   est portée par .etape-indicateur dans chaque écran, non masquée) --- */

.tunnel-etapes {
  display: flex;
  justify-content: center;
  gap: var(--sp-2);
  margin: 0 auto var(--sp-7);
  padding: 0;
  list-style: none;
}

.tunnel-etapes li {
  display: flex;
  flex: 0 0 var(--sp-8);
  align-items: center;
  justify-content: center;
  height: var(--sp-6);
  border: 1px solid var(--c-border);
  border-radius: var(--radius);
  background: var(--c-bg-alt);
  color: var(--c-ink-soft);
  font-size: var(--fs-100);
  font-weight: 700;
  transition: background var(--transition), color var(--transition), border-color var(--transition);
}

.tunnel-etapes li.est-actuelle {
  background: var(--c-primary);
  border-color: var(--c-primary);
  color: var(--c-bg);
}

.tunnel-etapes li.est-faite {
  border-color: var(--c-primary);
  color: var(--c-primary);
  background: var(--c-bg);
}

/* --- Écrans --- */

.ecran {
  max-width: var(--measure);
  margin-inline: auto;
}

/* Écran 1 : plus large que les autres écrans pour accueillir la mise en
   page à deux colonnes ci-dessous — seule exception à .ecran, qui reste
   la largeur par défaut (lecture confortable) pour les écrans 2 à 4. */
.ecran-large {
  max-width: var(--container-max);
}

.ecran-large-intro {
  max-width: var(--measure);
  margin: 0 0 var(--sp-6);
  color: var(--c-ink-soft);
}

/* --- Groupes de champs de l'écran 1 : deux colonnes sur desktop, chaque
   groupe se déverrouille progressivement une fois le précédent complet
   (voir gererSuivantEcran1 / actualiserVerrouillageGroupes dans le JS). --- */

.groupes-champs {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-5);
  align-items: start;
}

@media (min-width: 800px) {
  .groupes-champs {
    grid-template-columns: 1fr 1fr;
  }
}

.groupe-champs {
  margin: 0;
  border: 1px solid var(--c-border);
  border-radius: var(--radius);
  padding: var(--sp-5);
  background: var(--c-bg);
  box-shadow: var(--shadow-sm);
  transition: opacity var(--transition), filter var(--transition);
}

.groupe-champs legend {
  padding: 0;
  margin-bottom: var(--sp-4);
  font-size: var(--fs-300);
  font-weight: 700;
  color: var(--c-ink);
}

.groupe-champs--verrouille {
  opacity: 0.45;
  filter: grayscale(0.4);
  /* pointer-events est un filet de sécurité : l'attribut inert (posé/retiré
     en JS) est le mécanisme principal, il exclut aussi le groupe de l'ordre
     de tabulation et de l'arbre d'accessibilité. */
  pointer-events: none;
}

.groupe-champs:last-child {
  margin-bottom: 0;
}

.etape-indicateur {
  margin: 0 0 var(--sp-2);
  color: var(--c-ink-soft);
  font-size: var(--fs-100);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

/* Le focus programmatique au changement d'écran (goToScreen) ne doit
   jamais afficher de cadre : ces titres ne sont pas normalement encadrés,
   un contour qui apparaît puis disparaît au clic suivant lirait comme un
   artefact plutôt qu'un choix de design. */
.ecran h2[tabindex="-1"] {
  outline: none;
}

/* --- Champs --- */

.champ {
  margin-bottom: var(--sp-4);
}

.champ-ligne {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0 var(--sp-4);
}

@media (min-width: 800px) {
  .champ-ligne {
    grid-template-columns: 1fr 1fr;
  }
}

.champ-erreur {
  min-height: 1.2em;
  margin: var(--sp-2) 0 0;
  color: var(--c-error);
  font-size: var(--fs-100);
  font-weight: 600;
}

.champ-erreur:empty {
  margin: 0;
}

.champ-aide {
  margin: var(--sp-2) 0 0;
  color: var(--c-ink-soft);
  font-size: var(--fs-100);
}

.champ-compteur {
  text-align: right;
}

.champ-etat {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: 1.2em;
  margin: var(--sp-2) 0 var(--sp-3);
  font-size: var(--fs-100);
  font-weight: 600;
}

.champ-etat:empty {
  margin: 0;
  min-height: 0;
}

.champ-etat--chargement {
  color: var(--c-ink-soft);
}

.champ-etat--succes {
  color: var(--c-success);
}

.champ-etat--succes::before {
  content: "✓";
  font-weight: 700;
}

.champ-etat--erreur {
  color: var(--c-error);
}

.champ-etat--attention {
  color: var(--c-warning);
}

.siren-affiche {
  margin: 0 0 var(--sp-3);
  color: var(--c-ink-soft);
  font-size: var(--fs-100);
  font-family: ui-monospace, "SFMono-Regular", Consolas, monospace;
}

/* Ligne "Déjà inscrit : Oui/Non" (section devis, /tarifs.html) — n'existe
   que le temps où le JS la révèle (voir assets/js/tarifs.js), jamais
   visible par défaut ([hidden] déjà neutralisé globalement en tête de
   fichier). */
.siret-deja-inscrit {
  display: inline-flex;
  align-items: center;
  margin: 0 0 var(--sp-3);
  padding: var(--sp-1) var(--sp-3);
  border-radius: var(--radius-sm);
  background: var(--c-bg-alt);
  color: var(--c-ink-soft);
  font-size: var(--fs-100);
  font-weight: 600;
}

.siret-deja-inscrit--oui {
  background: rgba(47, 122, 92, 0.12);
  color: var(--c-success);
}

.tunnel input[type="file"] {
  width: 100%;
  font-family: inherit;
  font-size: var(--fs-200);
}

.tunnel input[aria-invalid="true"],
.tunnel select[aria-invalid="true"] {
  border-color: var(--c-error);
}

/* --- Dépôt de logo --- */

.dropzone {
  position: relative;
  border: 2px dashed var(--c-border-strong);
  border-radius: var(--radius);
  padding: var(--sp-5);
  text-align: center;
  background: var(--c-bg-alt);
  transition: border-color var(--transition), background var(--transition);
}

.dropzone--survol {
  border-color: var(--c-primary);
  background: var(--c-bg);
}

.dropzone input[type="file"] {
  margin: 0 0 var(--sp-2);
}

.dropzone-aide {
  margin: 0;
  color: var(--c-ink-soft);
  font-size: var(--fs-100);
}

.logo-apercu {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-3);
  margin-top: var(--sp-4);
}

.logo-apercu img {
  max-height: var(--sp-8);
  width: auto;
  border: 1px solid var(--c-border);
  border-radius: var(--radius);
  background: var(--c-bg);
}

/* --- Techniciens (écran 2) --- */

.technicien-ligne {
  border: 1px solid var(--c-border);
  border-radius: var(--radius);
  padding: var(--sp-4);
  margin-bottom: var(--sp-4);
  background: var(--c-bg);
  box-shadow: var(--shadow-sm);
  transition: border-color var(--transition), background var(--transition);
}

.technicien-ligne.row-conflict {
  border-color: var(--c-error);
  background: var(--c-bg-alt);
}

@supports (background: color-mix(in srgb, red, blue)) {
  .technicien-ligne.row-conflict {
    background: color-mix(in srgb, var(--c-error) 8%, var(--c-bg));
  }
}

.technicien-ligne-entete {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-bottom: var(--sp-3);
}

.technicien-titre {
  margin: 0;
  font-size: var(--fs-300);
}

.btn-supprimer-technicien {
  padding: var(--sp-1) var(--sp-3);
  font-size: var(--fs-100);
}

/* --- Boutons désactivés (le système de boutons existant ne définit pas cet
   état ; ajout additif, aucune règle .btn existante n'est modifiée) --- */

.tunnel .btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  box-shadow: none;
}

.tunnel .btn:disabled:hover {
  background: var(--c-bg);
  filter: none;
  box-shadow: none;
}

.tunnel .btn-accent:disabled:hover {
  background: var(--c-accent);
}

/* --- Messages de niveau écran --- */

.tunnel-message {
  margin: 0 0 var(--sp-4);
  padding: var(--sp-4);
  border: 1px solid var(--c-border);
  border-radius: var(--radius);
  background: var(--c-bg);
  box-shadow: var(--shadow-sm);
  font-size: var(--fs-100);
  font-weight: 600;
}

.tunnel-message--erreur {
  border-color: var(--c-error);
  color: var(--c-error);
}

.tunnel-message--attention {
  border-color: var(--c-warning);
  color: var(--c-ink);
}

.tunnel-message--succes {
  border-color: var(--c-success);
  color: var(--c-success);
}

.tunnel-message a {
  color: inherit;
}

/* --- Navigation entre écrans --- */

.tunnel-nav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-top: var(--sp-7);
}

/* --- Récapitulatif (écran 3) --- */

.recap-bloc {
  border: 1px solid var(--c-border);
  border-radius: var(--radius);
  padding: var(--sp-5);
  margin-bottom: var(--sp-5);
  background: var(--c-bg);
  box-shadow: var(--shadow-sm);
}

.recap-bloc-entete {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-bottom: var(--sp-4);
}

.recap-bloc-entete h3 {
  margin: 0;
}

.recap-liste {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-3) var(--sp-4);
  margin: 0;
}

@media (min-width: 800px) {
  .recap-liste {
    grid-template-columns: 1fr 1fr;
  }
}

.recap-liste dt {
  color: var(--c-ink-soft);
  font-size: var(--fs-100);
  font-weight: 700;
}

.recap-liste dd {
  margin: 0 0 var(--sp-3);
  word-break: break-word;
}

.recap-techniciens-liste {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}

.recap-techniciens-liste li {
  padding-bottom: var(--sp-2);
  border-bottom: 1px solid var(--c-border);
}

.recap-techniciens-liste li:last-child {
  border-bottom: none;
}

/* --- Engagements (écran 3) --- */

.engagements {
  margin: var(--sp-5) 0;
  padding: 0;
  border: 0;
}

.engagements legend {
  margin-bottom: var(--sp-3);
  padding: 0;
  color: var(--c-ink);
  font-size: var(--fs-300);
  font-weight: 700;
}

.engagement-case {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  margin-bottom: var(--sp-4);
  font-weight: 400;
  cursor: pointer;
}

.engagement-case input[type="checkbox"] {
  flex-shrink: 0;
  width: var(--sp-5);
  height: var(--sp-5);
  accent-color: var(--c-primary);
}

/* ==========================================================================
   Espace client (/espace.html)
   Interface à navigation latérale (desktop) / onglets scrollables (mobile) +
   panneau de contenu affichant une seule section à la fois. Toutes les
   valeurs proviennent des variables :root.
   ========================================================================== */

.espace {
  max-width: var(--container-max);
  margin-inline: auto;
  padding: var(--sp-7) var(--sp-4) var(--sp-8);
}

.espace-titre {
  text-align: center;
  margin-bottom: var(--sp-6);
}

/* --- États de haut niveau (chargement / erreur), un seul visible à la fois --- */

.espace-etat {
  max-width: var(--measure);
  margin: 0 auto;
  padding: var(--sp-7) 0;
  text-align: center;
}

/* Focus programmatique sur les conteneurs [tabindex="-1"] de cette page
   (état d'erreur, titre de fiche, titres de section, mini-formulaire) :
   jamais de cadre, ce sont des éléments qui ne sont pas normalement
   encadrés — un contour qui apparaît puis disparaît au clic suivant lirait
   comme un artefact plutôt qu'un choix de design.
   Seule exception : .espace-confirmation, qui a déjà une bordure dans son
   état normal (voir plus bas) — le focus n'y ajoute donc rien de surprenant. */
.espace [tabindex="-1"] {
  outline: none;
}

.espace-confirmation:focus {
  outline: 2px solid var(--c-ink);
  outline-offset: 2px;
}

/* --- Bloc 1 : en-tête de la fiche (toujours visible, au-dessus de la
   navigation par sections) --- */

.espace-entete-haut {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-4);
  margin-bottom: var(--sp-4);
}

.espace-entete-logo img {
  max-height: var(--sp-8);
  width: auto;
  border: 1px solid var(--c-border);
  border-radius: var(--radius);
  background: var(--c-bg);
}

.espace-entete-logo .champ-aide {
  margin: 0;
  max-width: 22ch;
}

.espace-entete-haut h2 {
  margin: 0 0 var(--sp-1);
}

.badge-statut {
  display: inline-block;
  padding: var(--sp-1) var(--sp-3);
  border-radius: 999px;
  font-size: var(--fs-100);
  font-weight: 700;
}

.badge-statut--actif {
  background: var(--c-bg-alt);
  color: var(--c-success);
  border: 1px solid var(--c-success);
}

.badge-statut--suspendu {
  background: var(--c-bg-alt);
  color: var(--c-error);
  border: 1px solid var(--c-error);
}

.espace-fiche-entete {
  margin-bottom: var(--sp-6);
  padding-bottom: var(--sp-6);
  border-bottom: 1px solid var(--c-border);
}

/* --- Mise en page à deux zones : navigation + contenu --- */

.espace-layout {
  display: flex;
  flex-direction: column;
  gap: var(--sp-6);
  align-items: flex-start;
}

.espace-nav {
  display: flex;
  flex-direction: row;
  gap: var(--sp-2);
  width: 100%;
  padding-bottom: var(--sp-3);
  margin-bottom: var(--sp-1);
  border-bottom: 1px solid var(--c-border);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.espace-nav-item {
  flex: 0 0 auto;
  display: block;
  padding: var(--sp-3) var(--sp-4);
  border: none;
  border-radius: var(--radius);
  background: transparent;
  color: var(--c-ink-soft);
  font-family: inherit;
  font-size: var(--fs-200);
  font-weight: 600;
  text-align: left;
  white-space: nowrap;
  cursor: pointer;
  transition: background var(--transition), color var(--transition);
}

.espace-nav-item:hover {
  background: var(--c-bg-alt);
  color: var(--c-ink);
}

.espace-nav-item[aria-current="page"] {
  background: var(--c-bg-alt);
  color: var(--c-primary);
}

.espace-contenu {
  width: 100%;
  min-width: 0;
}

.espace-section-titre {
  margin-bottom: var(--sp-6);
}

@media (min-width: 900px) {
  .espace-layout {
    flex-direction: row;
    align-items: flex-start;
    gap: var(--sp-7);
  }

  .espace-nav {
    flex-direction: column;
    width: 240px;
    flex-shrink: 0;
    overflow-x: visible;
    padding-bottom: 0;
    padding-right: var(--sp-4);
    border-bottom: none;
    border-right: 1px solid var(--c-border);
    position: sticky;
    top: calc(var(--sp-8) + var(--sp-4));
  }

  .espace-nav-item[aria-current="page"] {
    box-shadow: inset 3px 0 0 var(--c-primary);
  }
}

/* --- Sections de contenu (une seule visible à la fois, via [hidden]) --- */

.espace-bloc {
  max-width: var(--measure);
}

/* --- Bloc 2 : ligne de synthèse — pastille discrète, plus d'encadré --- */

.espace-synthese {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-top: var(--sp-5);
  font-size: var(--fs-300);
  font-weight: 700;
}

.espace-synthese::before {
  content: "";
  flex-shrink: 0;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: currentColor;
}

.espace-synthese--ok {
  color: var(--c-success);
}

.espace-synthese--vide {
  color: var(--c-ink-soft);
}

/* --- Bloc 3 : tuiles d'achat --- */

.tuile-groupe-titre {
  margin: var(--sp-6) 0 var(--sp-4);
  font-size: var(--fs-300);
  color: var(--c-ink);
}

.espace-tuiles {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-4);
  margin: 0 0 var(--sp-6);
}

@media (min-width: 640px) {
  .espace-tuiles {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 1300px) {
  .espace-tuiles {
    grid-template-columns: repeat(3, 1fr);
  }
}

.tuile-achat {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  border: 1px solid var(--c-border);
  border-radius: var(--radius);
  padding: var(--sp-5);
  background: var(--c-bg);
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--transition), border-color var(--transition);
}

.tuile-achat:hover {
  box-shadow: var(--shadow-md);
  border-color: var(--c-primary);
}

.tuile-achat h3,
.tuile-achat h4 {
  margin: 0;
  font-size: var(--fs-200);
  font-weight: 700;
  color: var(--c-ink-soft);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.tuile-prix {
  margin: 0;
  color: var(--c-ink-soft);
  font-weight: 600;
  font-size: var(--fs-100);
}

/* Hiérarchie inversée pour les formules d'abonnement : le nombre de
   rapports inclus est l'élément le plus visible de la tuile, le prix reste
   présent mais nettement secondaire (voir .tuile-prix ci-dessus). */
.tuile-quota {
  margin: 0;
  font-size: var(--fs-500);
  font-weight: 800;
  color: var(--c-primary);
  line-height: 1.1;
}

.tuile-quota-label {
  display: block;
  margin: 0 0 var(--sp-1);
  font-size: var(--fs-100);
  font-weight: 600;
  color: var(--c-ink-soft);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.tuile-achat .btn {
  margin-top: auto;
}

.badge-formule-actuelle {
  margin: auto 0 0;
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--radius);
  background: var(--c-bg-alt);
  color: var(--c-primary);
  font-weight: 700;
  text-align: center;
}

/* --- Bloc 4 : sous-blocs « Mes informations » --- */

.espace-sous-bloc {
  border: 1px solid var(--c-border);
  border-radius: var(--radius);
  padding: var(--sp-5);
  margin-bottom: var(--sp-5);
  background: var(--c-bg);
  box-shadow: var(--shadow-sm);
}

.espace-sous-bloc h3 {
  margin-top: 0;
}

/* Équivalent, scopé à .espace, des règles .tunnel input[type="file"] et
   .tunnel .btn:disabled du tunnel d'inscription. */
.espace input[type="file"] {
  width: 100%;
  font-family: inherit;
  font-size: var(--fs-200);
}

.espace input[aria-invalid="true"],
.espace select[aria-invalid="true"] {
  border-color: var(--c-error);
}

.espace .btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  box-shadow: none;
}

.espace .btn:disabled:hover {
  background: var(--c-bg);
  filter: none;
  box-shadow: none;
}

.espace .btn-accent:disabled:hover {
  background: var(--c-accent);
}

/* --- Panneaux de confirmation intégrés (jamais de window.confirm()) --- */

.espace-confirmation {
  margin-top: var(--sp-4);
  padding: var(--sp-4);
  border: 1px solid var(--c-accent);
  border-radius: var(--radius);
  background: var(--c-bg-alt);
}

.espace-confirmation p {
  margin: 0 0 var(--sp-3);
  font-weight: 600;
}

.espace-confirmation-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
}

/* --- Bloc 5 : techniciens --- */

.espace-techniciens-liste {
  list-style: none;
  margin: 0 0 var(--sp-4);
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}

.espace-techniciens-liste .technicien-ligne p {
  margin: 0;
  color: var(--c-ink-soft);
}

.espace-mini-form {
  margin-top: var(--sp-4);
  padding: var(--sp-4);
  border: 1px solid var(--c-border);
  border-radius: var(--radius);
  background: var(--c-bg-alt);
}

.espace-mini-form-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
}

/* --- Bloc 8 : pied de page dédié (toujours visible, sous la navigation) --- */

.espace-pied {
  margin-top: var(--sp-7);
  padding-top: var(--sp-6);
  border-top: 1px solid var(--c-border);
}

.espace-pied p {
  color: var(--c-ink-soft);
}

/* ==========================================================================
   Page « Retrouver mon accès » (/acces.html)
   Section additive : aucune règle ci-dessus n'est modifiée. Réutilise les
   styles de champ/erreur/bouton déjà définis plus haut dans ce fichier
   (.champ, .champ-erreur, input[type="text"], .btn, .btn-accent…).
   ========================================================================== */

.acces-page {
  max-width: var(--measure);
  margin: 0 auto;
  padding: var(--sp-7) var(--sp-4) var(--sp-8);
}

.acces-page form {
  margin-top: var(--sp-5);
}

/* Le système de boutons existant ne définit pas l'état désactivé (voir déjà
   le même besoin comblé pour .tunnel plus haut) ; ajout additif équivalent,
   scoped à cette page. */
.acces-page .btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  box-shadow: none;
}

.acces-page .btn-accent:disabled:hover {
  background: var(--c-accent);
  filter: none;
}

/* Conteneur non encadré par défaut (le message affiché à l'intérieur,
   .acces-message, a lui sa propre bordure) : jamais de cadre au focus
   programmatique, pour ne pas faire apparaître un contour surprenant
   autour d'un élément qui n'en a normalement pas. */
.acces-resultat[tabindex] {
  outline: none;
}

.acces-message {
  max-width: var(--measure);
  margin: var(--sp-5) 0 0;
  padding: var(--sp-4);
  border: 1px solid var(--c-border);
  border-radius: var(--radius);
  background: var(--c-bg);
  box-shadow: var(--shadow-sm);
  font-size: var(--fs-100);
  font-weight: 600;
}

.acces-message--succes {
  border-color: var(--c-success);
  color: var(--c-success);
}

.acces-message--attention {
  border-color: var(--c-warning);
  color: var(--c-ink);
}

.acces-message--erreur {
  border-color: var(--c-error);
  color: var(--c-error);
}

.acces-message--attente {
  color: var(--c-ink-soft);
  font-weight: 400;
}

/* ===== Tunnel + Espace premium (sobre) =====
   /inscription.html, /espace.html, /acces.html sont des OUTILS (tunnel
   d'inscription, espace client, récupération d'accès), pas des pages de
   vente : la palette et la typographie se re-thèment déjà automatiquement
   via les tokens :root (rien à redéfinir pour la couleur — voir les règles
   .tunnel/.espace/.acces-page déjà définies plus haut dans ce fichier).
   Section strictement additive : aucune règle existante ci-dessus n'est
   modifiée, seulement complétée par des sélecteurs plus spécifiques scopés
   à .tunnel / .espace / .acces-page, qui appliquent la nouvelle échelle de
   rayons/ombres (--radius-lg, --shadow-lg) aux cartes et panneaux
   principaux, et une hiérarchie typographique plus affirmée (--fw-heading)
   sur les titres d'écran/section. Volontairement sobre, sur demande client
   explicite : pas de carrousel, pas d'animation signature, pas d'ambiance
   flottante. Le seul mouvement ajouté est la révélation douce déjà en
   place ([data-reveal], voir plus haut dans ce fichier), posée avec
   parcimonie côté HTML sur les écrans/sections qui basculent déjà via
   [hidden] — aucune règle CSS supplémentaire n'est nécessaire pour ça, le
   contrat [data-reveal] existant s'applique tel quel. */

/* --- Hiérarchie typographique : titres d'écran/section plus affirmés --- */

.tunnel h2,
.espace h2 {
  font-weight: var(--fw-heading);
}

/* --- Cartes et panneaux principaux : coins plus doux (--radius-lg) ---
   .technicien-ligne et .dropzone sont partagés entre le tunnel et l'espace
   (mêmes classes, deux pages) : les deux contextes sont listés. .tuile-achat
   est en plus partagée avec /tarifs.html : le sélecteur reste scopé à
   .espace pour ne changer que son usage dans l'espace client, jamais la
   vitrine. */

.tunnel .groupe-champs,
.tunnel .recap-bloc,
.tunnel .technicien-ligne,
.tunnel .dropzone,
.espace .technicien-ligne,
.espace .espace-sous-bloc,
.espace .tuile-achat,
.espace .espace-mini-form,
.espace .espace-confirmation,
.espace .dropzone {
  border-radius: var(--radius-lg);
}

/* La page « Retrouver mon accès » n'a pas de carte visuelle autour de son
   formulaire à l'origine (voir .acces-page plus haut) : on lui en donne
   une, sobre, pour l'aligner sur le traitement « panneau » des deux autres
   outils. */
.acces-page form {
  border: 1px solid var(--c-border);
  border-radius: var(--radius-lg);
  padding: var(--sp-5);
  background: var(--c-bg);
  box-shadow: var(--shadow-sm);
}

/* Panneaux de confirmation / mini-formulaire de l'espace client : un peu
   plus de présence (aucune ombre définie dans leur règle d'origine) — ce
   sont des portes de sortie sensibles (retrait d'un technicien, changement
   d'email) qui méritent d'être visuellement plus posées que le reste. */
.espace-confirmation,
.espace-mini-form {
  box-shadow: var(--shadow-md);
}

/* Récapitulatif (écran 3 du tunnel) : dernière relecture avant engagement,
   un peu plus d'élévation que les autres cartes du tunnel. */
.tunnel .recap-bloc {
  box-shadow: var(--shadow-md);
}

/* Étape courante du fil d'Ariane : légère élévation en plus de la couleur
   pleine déjà utilisée pour la distinguer des étapes à venir/passées. */
.tunnel-etapes li.est-actuelle {
  box-shadow: var(--shadow-md);
}

/* --- Élévation au survol des actions principales (--shadow-lg) ---
   Réservé aux boutons de conversion et aux tuiles d'achat : ce sont les
   éléments les plus importants de ces trois outils (passer à l'écran
   suivant, créer l'espace, enregistrer, acheter/changer de formule,
   recevoir son lien). :not(:disabled) évite tout conflit avec la règle
   .btn:disabled:hover existante (box-shadow: none), qui reste inchangée. */

.tunnel .btn-accent:hover:not(:disabled),
.espace .btn-accent:hover:not(:disabled),
.acces-page .btn-accent:hover:not(:disabled) {
  box-shadow: var(--shadow-lg);
}

.espace .tuile-achat:hover {
  box-shadow: var(--shadow-lg);
}

/* ==========================================================================
   Pages vitrine — Tarifs, Contact (/tarifs.html, /contact.html)
   Sections additives : aucune règle ci-dessus n'est modifiée. Réutilise
   strictement .btn/.btn-accent/.champ/.champ-erreur/.tuile-achat/
   .tuile-quota/.tuile-quota-label/.tuile-prix/.table-scroll/.acces-message
   déjà définis plus haut dans ce fichier ; toutes les valeurs proviennent des
   variables :root.
   ========================================================================== */

/* --- Conteneur générique centré, réutilisé par Contact et Devis (même
   traitement que .acces-page, sous un nom neutre car partagé entre
   plusieurs pages vitrine) --- */

.vitrine-page {
  max-width: var(--measure);
  margin: 0 auto;
  padding: var(--sp-7) var(--sp-4) var(--sp-8);
}

.vitrine-page form {
  margin-top: var(--sp-5);
}

/* Bandeau "site en version bêta" — réutilisé sur /contact.html et sur les
   pages compte désactivées (/inscription.html, /espace.html, /acces.html).
   --c-warning : même couleur que .tunnel-message--attention, un vrai statut
   temporaire plutôt qu'une erreur ou un succès. */
.notice-beta {
  max-width: var(--measure);
  margin: var(--sp-5) auto 0;
  padding: var(--sp-6) var(--sp-5);
  border: 1px solid var(--c-warning);
  border-radius: var(--radius-lg);
  background: var(--c-bg);
  box-shadow: var(--shadow-sm);
  text-align: center;
}

.notice-beta h2 {
  margin: 0 0 var(--sp-3);
  color: var(--c-warning);
}

.notice-beta p {
  margin: 0 auto var(--sp-3);
  color: var(--c-ink-soft);
}

.notice-beta p:last-of-type {
  margin-bottom: 0;
}

.notice-beta .btn {
  margin-top: var(--sp-3);
}

/* Variante avec pictogramme (page Contact — la destination de tous les CTA
   désactivés, elle mérite un peu plus de présence visuelle que le simple
   bandeau centré réutilisé sur les pages compte). N'affecte que cette
   variante : les 3 autres pages gardent le bandeau centré sans icône. */
.notice-beta--avec-icone {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-4);
  text-align: left;
}

.notice-beta-icone {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: var(--c-warning);
  color: var(--c-bg);
}

.notice-beta-icone svg {
  width: 24px;
  height: 24px;
}

.notice-beta--avec-icone p {
  margin: 0;
}

.vitrine-page .btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  box-shadow: none;
}

.vitrine-page .btn-accent:disabled:hover {
  background: var(--c-accent);
  filter: none;
}

/* Focus programmatique (ex. message de confirmation Devis) : jamais de
   cadre, même convention que .espace [tabindex="-1"] et .acces-resultat. */
.vitrine-page [tabindex="-1"] {
  outline: none;
}

/* --- Contact (/contact.html) --- */

.contact-intro {
  color: var(--c-ink-soft);
  font-size: var(--fs-300);
}

.contact-moyens {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-4);
  margin: 0;
}

@media (min-width: 560px) {
  .contact-moyens {
    grid-template-columns: 1fr 1fr;
  }
}

/* Chaque moyen de contact est un lien à part entière (toute la carte est
   cliquable, pas seulement le texte de l'adresse/numéro) : cible tactile
   plus grande, cohérent avec le reste du site (.chiffre-carte, .tuile-achat…
   suivent déjà ce principe de carte-lien entièrement interactive). */
.contact-moyen {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  min-width: 0;
  padding: var(--sp-5);
  border-radius: var(--radius);
  background: var(--c-bg);
  text-decoration: none;
  transition: transform var(--dur-fast) var(--ease-out-soft),
              box-shadow var(--dur-fast) var(--ease-out-soft);
}

.contact-moyen:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
}

.contact-moyen-icone {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  color: var(--c-bg);
}

.contact-moyen-icone svg {
  width: 20px;
  height: 20px;
}

.contact-moyen:nth-child(1) .contact-moyen-icone { background: var(--c-lien); }
.contact-moyen:nth-child(2) .contact-moyen-icone { background: var(--c-teal-dk); }

.contact-moyen-texte {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.contact-moyen-label {
  min-width: 0;
  color: var(--c-ink-soft);
  font-size: var(--fs-100);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* min-width:0 sur .contact-moyen-texte (colonne flex parente) ne suffit pas
   à lui seul : cet élément est LUI-MÊME un item flex de cette colonne, avec
   sa propre protection de largeur minimale automatique (taille du contenu,
   ici l'adresse email non sécable) — sans min-width:0 ici aussi, le texte
   déborde de la carte au lieu de se replier via overflow-wrap. */
.contact-moyen-valeur {
  min-width: 0;
  color: var(--c-ink);
  font-size: var(--fs-300);
  font-weight: 700;
  overflow-wrap: break-word;
  transition: color var(--dur-fast) var(--ease-out-soft);
}

.contact-moyen:hover .contact-moyen-valeur {
  text-decoration: underline;
}

/* --- Devis (section intégrée dans /tarifs.html) --- */

.devis-confirmation {
  max-width: var(--measure);
  margin: var(--sp-5) 0 0;
  padding: var(--sp-4);
  border: 1px solid var(--c-success);
  border-radius: var(--radius);
  background: var(--c-bg);
  box-shadow: var(--shadow-sm);
  color: var(--c-success);
  font-weight: 600;
}

/* --- Tarifs (/tarifs.html) ---
   Les deux sections « Rapports à l'unité » / « Abonnements mensuels » et
   leur alternance de fond réutilisent directement .vitrine-section /
   .vitrine-section--alt / .vitrine-section-inner / .vitrine-hero /
   .vitrine-section-titre (voir plus bas, section « Page d'accueil —
   vitrine ») : rien à redéfinir ici, seuls les éléments propres aux tuiles
   de tarifs suivent. */

.tuile-detail {
  margin: 0;
  color: var(--c-ink-soft);
  font-size: var(--fs-100);
}

.tarifs-devis-note {
  max-width: var(--measure);
  margin: var(--sp-2) 0 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-3);
  color: var(--c-ink-soft);
}

.tarifs-mentions {
  margin: var(--sp-2) 0 0;
}

.tarifs-mentions p {
  margin: 0 0 var(--sp-1);
  color: var(--c-ink-soft);
  font-size: var(--fs-100);
}

/* ==========================================================================
   Page d'accueil — vitrine (/index.html)
   Section additive : aucune règle ci-dessus n'est modifiée. Alternance de
   fond --c-bg / --c-bg-alt entre sections pour les séparer visuellement,
   comme déjà pratiqué ailleurs sur le site (ex. .site-footer). Toutes les
   valeurs proviennent des variables :root.
   ========================================================================== */

.vitrine-section {
  padding: var(--sp-8) var(--sp-4);
  background: var(--c-bg);
}

.vitrine-section--alt {
  background: var(--c-bg-alt);
}

/* Hero (1ʳᵉ section de /index.html) : moins de vide au-dessus du titre que
   le padding générique ci-dessus — remonte le contenu, et aide la section à
   tenir dans la hauteur d'écran visible sur ordinateur (voir aussi le
   padding-block réduit et le plafond de taille du titre à 900px+ plus bas).
   Sélecteur à deux classes : passe volontairement devant .vitrine-section
   ci-dessus quel que soit l'ordre des règles dans le fichier. */
.vitrine-section.vitrine-section--hero {
  padding-top: var(--sp-5);
}

@media (max-width: 799px) {
  .vitrine-section.vitrine-section--hero {
    padding-top: var(--sp-4);
  }
}

.vitrine-section-inner {
  max-width: var(--container-max);
  margin-inline: auto;
}

/* --- Bloc 1 : héros --- */

/* Réduit l'espace qui s'accumulerait sinon (padding de section + padding du
   bandeau) devant un contenu court, ex. le "Tarifs" de /tarifs.html. */
.vitrine-section--intro-compacte {
  padding-bottom: var(--sp-5);
}

/* Bandeau d'introduction de /tarifs.html — même dégradé marine animé que
   .reassurance-bandeau (page d'accueil) : reprend délibérément ce langage
   visuel déjà établi sur le site, pour une cohérence de bout en bout plutôt
   qu'un nouveau motif isolé. Contenu et repli identiques à
   .devis-bandeau plus bas sur cette même page (carte marine arrondie) —
   les deux bandeaux de la page se répondent visuellement. */
.tarifs-hero-bandeau {
  max-width: var(--container-max);
  margin: 0 auto;
  padding: var(--sp-7) var(--sp-5);
  border-radius: var(--radius-lg);
  background: linear-gradient(120deg, var(--c-primary) 0%, var(--c-primary-dk) 50%, var(--c-primary) 100%);
  background-size: 220% 220%;
  text-align: center;
}

.tarifs-hero-bandeau {
  animation: reassuranceGradientDrift 16s var(--ease-in-out-soft) infinite;
}

.tarifs-hero-bandeau h1 {
  color: var(--c-bg);
  margin-bottom: var(--sp-3);
}

/* Une seule phrase, volontairement : les prix précis et le premier rapport
   offert sont déjà écrits plus bas (tuiles, .tarifs-mentions) — inutile de
   les répéter ici. Ce bandeau se contente de poser le choix (unité vs
   abonnement) et l'absence d'engagement. */
.tarifs-hero-bandeau p {
  max-width: var(--measure);
  margin: 0 auto;
  color: var(--c-bg);
  opacity: .92;
  font-size: var(--fs-300);
}

/* display:flex + gap plutôt que .btn + .btn{margin-left} (repli plus bas) :
   .btn est en inline-flex, donc les 2 boutons s'enchaînaient déjà en ligne
   et se repliaient naturellement sur mobile — mais un simple margin-left ne
   crée un espace qu'entre boutons CÔTE À CÔTE, jamais entre boutons
   empilés l'un sous l'autre une fois repliés (ils se retrouvaient collés).
   gap couvre les deux directions en une seule propriété, et
   justify-content:center centre explicitement le groupe. */
.vitrine-hero-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: var(--sp-3);
  margin-top: var(--sp-6);
}

.vitrine-reassurance {
  margin: var(--sp-4) 0 0;
  color: var(--c-ink-soft);
  font-size: var(--fs-100);
}

/* --- Bloc 3 : comment ça marche --- */

.vitrine-section-titre {
  max-width: var(--measure);
  margin: 0 auto var(--sp-7);
  text-align: center;
}

/* Trois puces au-dessus du titre "Comment ça marche", dans les mêmes trois
   couleurs que les 3 cartes d'étape juste en dessous (--etape-accent,
   assets/css/style.css section "Carrousel étapes") : annonce visuellement
   "3 étapes" avant même de les lire, plutôt qu'une puce décorative
   générique sans lien avec le contenu réel. */
.titre-etapes-puces {
  display: flex;
  justify-content: center;
  gap: var(--sp-2);
  margin-bottom: var(--sp-3);
}

.titre-etapes-puce {
  width: 10px;
  height: 10px;
  border-radius: 50%;
}

.titre-etapes-puce:nth-child(1) { background: var(--c-teal-dk); }
.titre-etapes-puce:nth-child(2) { background: var(--c-lien); }
.titre-etapes-puce:nth-child(3) { background: var(--c-accent-dk); }

/* Les deux titres de section les plus importants de /tarifs.html — les deux
   façons de commander — légèrement plus affirmés que le h2 générique
   ci-dessus : plus gras, avec un petit trait de couleur en dessous. Même
   taille que les autres .vitrine-section-titre du site (cohérence de
   l'échelle typographique), la distinction se joue sur le poids et l'accent
   plutôt que sur la taille. */
#titre-unitaire,
#titre-abonnements {
  font-weight: 800;
  position: relative;
  padding-bottom: var(--sp-3);
}

#titre-unitaire::after,
#titre-abonnements::after {
  content: "";
  position: absolute;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 56px;
  height: 4px;
  border-radius: 999px;
  background: var(--c-primary);
}

/* .vitrine-etapes/.vitrine-etape (grille statique à 3 colonnes) ont été
   remplacées par le carrousel au scroll .etapes-scroll-* (voir plus bas,
   section "Carrousel au scroll — Comment ça marche"). .vitrine-texte (bloc
   "problème"), .vitrine-benefices/-benefice et .vitrine-formules/-formule
   (v1) sont eux aussi supprimés ici : plus référencés par aucune page
   depuis la fusion du hero (v2) puis la refonte premium. Seule
   .vitrine-formules-cta survit (encore utilisée par le lien "Découvrir nos
   formules et tarifs" d'index.html), conservée ci-dessous. */

.vitrine-formules-cta {
  text-align: center;
}

/* --- Bloc 6 : rappel final --- */

.vitrine-cta-final {
  max-width: var(--measure);
  margin-inline: auto;
  text-align: center;
}

.vitrine-cta-final p {
  margin-inline: auto;
  color: var(--c-ink-soft);
}

.vitrine-cta-final .vitrine-hero-actions {
  margin-top: var(--sp-5);
}

/* ==========================================================================
   Révélation au scroll — toutes pages (refonte premium)
   Contrat : [data-reveal]/[data-reveal-item] visibles par défaut. Seul
   .js-reveal (posé par assets/js/scroll-reveal.js quand IntersectionObserver
   existe et que le mouvement n'est pas réduit) active l'état
   masqué-puis-révélé. Sans JS, rien ne dépend du script pour être visible.
   [data-reveal-item] ajoute un effet de cascade via --reveal-i (calculé en
   JS, rang parmi les [data-reveal-item] frères) : utilisé pour les groupes
   de cartes/étapes/bénéfices. Sert aussi d'« intro » naturelle pour tout
   élément déjà dans le viewport au chargement (le hero notamment) : même
   mécanisme, pas de script séparé.
   ========================================================================== */

[data-reveal],
[data-reveal-item] {
  opacity: 1;
  transform: none;
}

.js-reveal [data-reveal],
.js-reveal [data-reveal-item] {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity var(--dur-base) var(--ease-out-soft),
              transform var(--dur-base) var(--ease-out-soft);
}

.js-reveal [data-reveal-item] {
  transition-delay: calc(var(--reveal-i, 0) * 90ms);
}

.js-reveal [data-reveal].est-revele,
.js-reveal [data-reveal-item].est-revele {
  opacity: 1;
  transform: translateY(0);
}

/* ==========================================================================
   Tarifs v2 — savings badge + section devis
   Section additive : aucune règle existante ci-dessus n'est modifiée. Toutes
   les valeurs proviennent des variables :root définies en tête de fichier.
   ========================================================================== */

/* Courte phrase d'intro entre un .vitrine-section-titre et le contenu qui
   suit (grille de tuiles, formulaire…) — même traitement que .vitrine-hero p
   (couleur, largeur de lecture confortable) mais centrée comme le titre
   qu'elle accompagne. Utilisée sur /tarifs.html (sections « à l'unité »,
   « abonnements ») et réutilisable ailleurs sans modification. */
.vitrine-section-intro {
  max-width: var(--measure);
  margin: 0 auto var(--sp-6);
  color: var(--c-ink-soft);
  text-align: center;
}

/* Les deux .vitrine-section-intro qui portent le plus de sens à elles
   seules (elles ne sont pas de simples sous-titres décoratifs, mais
   qualifient le visiteur ou présentent l'exemple de rapport) : plus grandes
   que le texte d'intro générique du site, sans toucher aux autres. */
.vitrine-section-intro--grande {
  font-size: var(--fs-300);
}

/* Badge d'économie affiché sous le prix de chaque formule d'abonnement
   (/tarifs.html). Une mention discrète, pas un argument visuel dominant :
   fond légèrement teinté, texte réduit, pastille compacte plutôt que pleine
   largeur — le quota et le prix restent les éléments principaux de la tuile
   (voir .tuile-quota / .tuile-prix). */
.tuile-economie {
  align-self: flex-start;
  margin: 0;
  padding: var(--sp-1) var(--sp-3);
  border-radius: var(--radius);
  background: var(--c-bg-alt);
  color: var(--c-accent);
  font-size: var(--fs-100);
  font-weight: 700;
}

/* Intro de la section « Besoin d'un devis sur mesure ? » (#devis, sur
   /tarifs.html) : même traitement que .vitrine-section-intro ci-dessus. */
.vitrine-devis-intro {
  max-width: var(--measure);
  margin: 0 auto var(--sp-6);
  color: var(--c-ink-soft);
  text-align: center;
}

/* Micro-interaction hover sur les tuiles de tarification/abonnement : la
   règle .tuile-achat:hover (plus haut dans ce fichier) gère déjà box-shadow
   et border-color, on ne les redéclare pas ici pour éviter tout doublon — on
   ajoute seulement un léger soulèvement. La liste "transition" doit être
   réécrite en entier (une propriété transition ne se complète pas par une
   seconde déclaration séparée), d'où cette redéclaration de .tuile-achat qui
   reprend les deux transitions existantes et y ajoute celle du transform. */
.tuile-achat {
  transition: box-shadow var(--transition), border-color var(--transition), transform 150ms ease;
}

.tuile-achat:hover {
  transform: translateY(-2px);
}

/* Le reste de cette section ("Accueil v2" : .vitrine-hero--animee,
   .vitrine-reassurance-liste/-item, .vitrine-benefice, .vitrine-formule,
   l'ancien .hero-anim) a été entièrement remplacé par la refonte premium
   (.hero-premium, .chiffre-carte, etc.) — supprimé pour éviter le CSS mort,
   aucune de ces classes n'étant plus référencée par le HTML. */

/* ==========================================================================
   ===== Tarifs/Contact premium =====
   Sections additives pour /tarifs.html et /contact.html : aucune règle
   existante ci-dessus n'est modifiée. Toutes les valeurs proviennent des
   variables :root définies en tête de fichier. Objectif : que les trois
   sections de /tarifs.html (« à l'unité », « abonnements », « devis ») soient
   visuellement différenciées (règle client), tout en réutilisant strictement
   .tuile-achat/.espace-tuiles/.champ/.btn déjà définis plus haut — seuls des
   modificateurs (classes en double tiret) et de nouveaux conteneurs premium
   sont ajoutés ici.
   ========================================================================== */

/* --- Rapports à l'unité : accent teal (« variété de section », voir
   design-system.md §1), coins généreux et légère élévation au survol comme
   les tuiles d'abonnement, mais hiérarchie propre : sur ces cartes, c'est le
   PRIX qui est l'élément que le visiteur regarde en premier (il n'y a pas de
   "quota" à mettre en avant comme sur les abonnements) — .tuile-prix, discret
   par défaut pour les autres usages de cette classe (abonnements, espace
   client), est donc surchargé ici pour devenir l'élément visuel dominant de
   la carte, à la manière de .tuile-quota plus haut. Le pseudo-élément
   (bandeau teal) devient un badge-pastille contenant le nombre de photos,
   plus riche visuellement qu'un simple trait. */
.tuile-achat--unite {
  border-radius: var(--radius-lg);
  transition: box-shadow var(--dur-fast) var(--ease-out-soft),
              border-color var(--dur-fast) var(--ease-out-soft),
              transform var(--dur-fast) var(--ease-out-soft);
}

.tuile-achat--unite:hover {
  transform: translateY(-4px);
  border-color: var(--c-teal);
}

.tuile-achat--unite .tuile-detail {
  display: inline-flex;
  align-items: center;
  padding: var(--sp-1) var(--sp-3);
  border-radius: 999px;
  background: var(--c-bg-alt);
  color: var(--c-teal-dk);
  font-weight: 700;
  font-size: var(--fs-100);
}

.tuile-achat--unite .tuile-prix {
  margin-top: auto;
  padding-top: var(--sp-3);
  color: var(--c-primary);
  font-size: var(--fs-500);
  font-weight: 800;
  line-height: 1.1;
}

/* Le bouton "Commander" suit directement le prix (déjà poussé en bas de
   carte par son margin-top:auto ci-dessus) : la règle générique .tuile-achat
   .btn { margin-top: auto } — pensée pour les tuiles d'abonnement, où c'est
   le bouton qui pousse tout seul — donnerait ici un vide entre le prix et le
   bouton, les deux se disputant l'espace libre. Un simple espacement fixe
   suffit, le prix ayant déjà fait le travail. */
.tuile-achat--unite .btn {
  margin-top: var(--sp-2);
}

/* --- Abonnements mensuels : tuiles premium, coins généreux et légère
   élévation au survol (--radius-lg / --shadow-lg, tokens dédiés aux cartes
   premium — voir design-system.md §3). La transition est réécrite en entier
   avec les tokens de mouvement partagés (--dur-fast / --ease-out-soft),
   cohérents avec le reste du site ; elle remplace celle de .tuile-achat pour
   ces cartes précises uniquement (même sélecteur de classe, donc même
   spécificité : la règle la plus bas dans la feuille de style l'emporte). */
.tuile-achat--abonnement {
  border-radius: var(--radius-lg);
  transition: box-shadow var(--dur-fast) var(--ease-out-soft),
              border-color var(--dur-fast) var(--ease-out-soft),
              transform var(--dur-fast) var(--ease-out-soft);
}

.tuile-achat--abonnement:hover {
  transform: translateY(-4px);
  border-color: var(--c-primary);
  box-shadow: var(--shadow-lg);
}

/* --- Devis sur mesure : bandeau plein --c-primary (texte blanc) au-dessus
   d'un panneau premium blanc contenant le formulaire — l'alternance de
   sections premium explicitement décrite en design-system.md §1
   (blanc ↔ lavande ↔ bandeau plein marine), pas encore utilisée ailleurs sur
   le site avant cette page. */
.devis-bandeau {
  max-width: var(--container-max);
  margin: 0 auto var(--sp-6);
  padding: var(--sp-6) var(--sp-5);
  border-radius: var(--radius-lg);
  background: var(--c-primary);
  text-align: center;
}

.devis-bandeau .vitrine-section-titre {
  color: var(--c-bg);
  margin-bottom: var(--sp-3);
}

.devis-bandeau .vitrine-devis-intro {
  color: var(--c-bg);
  opacity: 0.92;
  margin-bottom: 0;
}

.devis-panel {
  max-width: var(--measure);
  margin: 0 auto;
  padding: var(--sp-6);
  background: var(--c-bg);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}

/* --- Contact (/contact.html) : plateau englobant (lavande, en retrait)
   autour des deux cartes de contact individuelles (blanches, cliquables) —
   voir .contact-moyen plus haut dans ce fichier. */
.contact-carte {
  margin: var(--sp-6) 0 0;
  padding: var(--sp-5);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-lg);
  background: var(--c-bg-alt);
  box-shadow: var(--shadow-md);
}

/* ===== Pages légales premium ===== */
/* /cgv.html, /confidentialite.html, /mentions-legales.html
   La palette, les tableaux, le sommaire, les liens « retour en haut » et le
   texte courant se re-thèment déjà automatiquement via les tokens :root mis
   à jour plus haut dans ce fichier (.legal-doc, .table-scroll, .toc,
   .doc-version, .doc-note, .back-to-top, h1–h3, a, ...) : rien à redéfinir
   pour la couleur. Seule la hiérarchie des titres manquait pour un document
   long — h2 (Article/section de premier niveau) et h3 (sous-section)
   partageaient le même poids et le même espacement au-dessus, ce qui aplatit
   la lecture. Ajout strictement additif, sans nouvelle couleur : h2 passe à
   la graisse premium --fw-heading avec un peu plus d'air au-dessus pour
   marquer une nouvelle section, h3 reste plus proche de son h2 parent pour
   se lire comme une sous-partie. */

.legal-doc h2 {
  margin-top: var(--sp-8);
  font-weight: var(--fw-heading);
}

.legal-doc h3 {
  margin-top: var(--sp-6);
}

/* ===== Accueil premium =====
   Refonte visuelle complète de /index.html (page la plus importante du
   site). Section strictement additive : aucune règle existante plus haut
   dans ce fichier n'est modifiée. Le contenu/argumentaire de chaque section
   est inchangé (validé par ailleurs) — seules la mise en page, les
   composants visuels et les micro-interactions sont nouveaux. Classes
   propres à cette section (préfixes hero-premium-/benefice-/chiffre-/
   reassurance-bandeau-/cta-final-), sans collision avec les classes
   .vitrine-* déjà en usage sur cette page et sur /tarifs.html.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Mot-clé coloré dans les grands titres (façon MoreApp) — cf. design-system
   section 2. Toujours à l'intérieur d'un titre ≥ --fs-500 en gras (usage
   conforme aux règles de contraste de --c-blue-vif, section 1).
   -------------------------------------------------------------------------- */
.mot-cle {
  color: var(--c-blue-vif);
}

/* --------------------------------------------------------------------------
   1. Héros — deux colonnes (texte / animation signature), façon MoreApp.
   Les 5 éléments marqués [data-reveal-item] (titre, texte, CTA, réassurance,
   animation) sont des frères directs de .hero-premium : la cascade de
   assets/js/scroll-reveal.js calcule --reveal-i sur ce même groupe, pour un
   effet d'intro cohérent au chargement, sans script séparé.
   Mobile (par défaut) : grille à une colonne, les 5 éléments s'empilent tout
   simplement dans l'ordre du document. Desktop (≥900px, même seuil que le
   reste du site) : deux colonnes 11fr/9fr, texte à gauche sur 4 lignes,
   animation à droite centrée verticalement sur toute la hauteur du bloc.
   -------------------------------------------------------------------------- */
.hero-premium {
  display: grid;
  grid-template-columns: 1fr;
  row-gap: var(--sp-4);
  max-width: var(--measure);
  margin-inline: auto;
  padding-block: var(--sp-5);
  text-align: center;
}

/* Rythme vertical resserré sur mobile : avec le bandeau bêta et l'en-tête
   déjà empilés au-dessus (voir leurs propres réductions plus haut), chaque
   pixel compte pour rapprocher la phrase de réassurance ("Aucun logiciel…")
   du haut d'écran visible sans défilement. */
@media (max-width: 799px) {
  .hero-premium {
    row-gap: var(--sp-3);
    padding-block: var(--sp-4);
  }
}

.hero-premium-titre {
  /* Espace le titre (très grand, 3 lignes) du paragraphe qui suit : le
     row-gap du parent seul (pensé pour les écarts entre TOUS les éléments
     du hero) ne suffisait pas à ce niveau de taille de texte, le tout
     restait collé en un seul pavé. */
  margin: 0 0 var(--sp-5);
}

.hero-premium-texte {
  margin: 0 auto;
  color: var(--c-ink-soft);
  font-size: var(--fs-300);
}

/* Marque, en plus du retour à la ligne, la bascule "ancienne façon" (rouge
   barré) → "nouvelle façon" (surlignage teal) : un repère visuel discret
   plutôt qu'un simple blanc, pour que ce passage se ressente comme une
   vraie transition et pas juste une coupure. Purement décoratif
   (aria-hidden) : le texte qui suit porte déjà tout le sens. */
.hero-transition {
  display: inline-block;
  margin-top: var(--sp-2);
  margin-right: var(--sp-1);
  color: var(--c-teal-dk);
  font-weight: 800;
}

/* Phrase clé du titre — soulignement plein, épais, dans la couleur accent :
   capte le regard dès le premier coup d'œil, sans le moindre padding qui
   décalerait le texte par rapport aux deux lignes au-dessus (elles restent
   toutes alignées sur le même bord gauche). text-decoration plutôt qu'un
   trait dessiné en overlay : se réajuste tout seul, correctement, ligne par
   ligne, si la phrase se replie sur deux lignes à certaines largeurs
   d'écran — jamais besoin de mesurer quoi que ce soit. */
.hero-phrase-vedette {
  display: inline-block;
  margin-top: var(--sp-3);
  text-decoration: underline;
  text-decoration-color: var(--c-accent);
  text-decoration-thickness: 4px;
  text-underline-offset: 6px;
}

/* Mise en avant "négative" (l'ancienne façon de faire, qu'on abandonne) :
   même rouge que les erreurs de formulaire (--c-error), sans barré — signal
   volontairement différent du soulignement ci-dessus et du surlignage
   ci-dessous, pour ne jamais mélanger les trois. */
.phrase-negative {
  color: var(--c-error);
}

/* Mise en avant "positive" (la promesse du service) : surlignée façon
   marqueur, teinte confiance/efficacité (--c-teal). Fond en dur en repli,
   color-mix() en amélioration progressive — même convention que
   .technicien-ligne.row-conflict plus haut dans ce fichier. */
.phrase-positive {
  padding: .05em .3em;
  border-radius: var(--radius-sm);
  background: #DDEDEE;
  color: var(--c-teal-dk);
  font-weight: 700;
}

@supports (background: color-mix(in srgb, red, blue)) {
  .phrase-positive {
    background: color-mix(in srgb, var(--c-teal) 14%, var(--c-bg));
  }
}

.hero-premium-cta {
  justify-self: center;
  margin-top: var(--sp-3);
}

.hero-premium-reassurance {
  margin: 0;
  color: var(--c-ink-soft);
  font-size: var(--fs-100);
}

.hero-premium-anim {
  min-width: 0;
}

@media (min-width: 900px) {
  .hero-premium {
    grid-template-columns: 11fr 9fr;
    grid-template-rows: repeat(4, auto);
    column-gap: var(--sp-7);
    row-gap: var(--sp-3);
    max-width: var(--container-max);
    /* Moins que le padding-block générique du hero (--sp-5) : la section
       tient plus facilement dans la hauteur d'écran visible sur ordinateur
       sans avoir à faire défiler pour voir le CTA et la maquette. */
    padding-block: var(--sp-4);
    align-items: center;
    text-align: left;
  }

  .hero-premium-titre {
    grid-column: 1;
    grid-row: 1;
    /* Plafond propre à ce titre (plus bas que --fs-600 par défaut) : sur 3
       lignes, la taille générique du h1 rendait la section trop haute pour
       tenir à l'écran. N'affecte que ce titre, jamais les autres h1 du
       site. */
    font-size: clamp(2.25rem, 1.4rem + 3.2vw, 3.25rem);
  }
  .hero-premium-texte { grid-column: 1; grid-row: 2; margin-inline: 0; max-width: none; }
  .hero-premium-cta { grid-column: 1; grid-row: 3; justify-self: start; margin-top: var(--sp-5); }
  .hero-premium-reassurance { grid-column: 1; grid-row: 4; }

  .hero-premium-anim {
    grid-column: 2;
    grid-row: 1 / span 4;
  }
}

/* Ambiance : flottement très lent et discret, permanent (pas besoin d'avoir
   scrollé), amplitude faible. Neutralisé automatiquement par la règle
   globale prefers-reduced-motion déjà en tête de ce fichier. */
@keyframes heroPremiumFloat {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-10px); }
}

.hero-premium-anim {
  animation: heroPremiumFloat 11s var(--ease-in-out-soft) infinite;
}

/* --------------------------------------------------------------------------
   2. Comment ça marche — carrousel au scroll (composant fourni tel quel,
   voir bloc « Maquette de conversation / Maquette de rapport / Animation
   héros scroll-driven » et « Carrousel étapes » ci-dessous). Rien à ajouter
   ici : la section réutilise déjà .vitrine-section--alt (voir plus haut).
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   3. Bénéfices — cartes premium sur fond blanc (radius-lg, ombre douce,
   élévation au survol). Volontairement blanche pour trancher avec la
   section « Comment ça marche » (bandeau lavande) juste au-dessus et la
   section « chiffres-clés » (cartes lavande) juste en dessous : jamais deux
   sections identiques de suite. Un accent de couleur différent par carte
   (marine / teal / accent) pour varier le rythme visuel sans surcharger.
   -------------------------------------------------------------------------- */
.benefices-grille {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-5);
  margin: 0 0 var(--sp-6);
  padding: 0;
  list-style: none;
}

@media (min-width: 700px) {
  .benefices-grille {
    grid-template-columns: repeat(3, 1fr);
  }
}

.benefice-carte {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sp-3);
  height: 100%;
  padding: var(--sp-6) var(--sp-5);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-lg);
  background: var(--c-bg);
  box-shadow: var(--shadow-sm);
  transition: transform var(--dur-fast) var(--ease-out-soft),
              box-shadow var(--dur-fast) var(--ease-out-soft),
              border-color var(--dur-fast) var(--ease-out-soft);
}

.benefice-carte:hover {
  transform: translateY(-6px);
  box-shadow: var(--shadow-lg);
  border-color: var(--c-primary);
}

.benefice-icone {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  border-radius: 50%;
}

.benefice-carte--primary .benefice-icone { background: var(--c-primary); }
.benefice-carte--teal .benefice-icone { background: var(--c-teal); }
.benefice-carte--accent .benefice-icone { background: var(--c-accent); }

.benefice-carte h3 {
  margin: 0;
  font-size: var(--fs-400);
  color: var(--c-ink);
}

.benefice-carte p {
  margin: 0;
  color: var(--c-ink-soft);
  max-width: none;
}

/* --------------------------------------------------------------------------
   4. Chiffres-clés — bandeau à 2 chiffres, volontairement PAS une troisième
   variante du motif "grille de cartes à icône" déjà vu ailleurs (comment ça
   marche, réassurance, moyens de contact) : un seul panneau, à coins
   presque droits (--radius, pas --radius-lg — jamais l'arrondi "bulle" des
   cartes), habillé d'un dégradé marine → bleu (--c-lien, jamais de vert/teal
   ici : la teinte devait rester clairement BLEUE) qui lui donne une vraie
   présence colorée sans reprendre le marine SEUL de .reassurance-bandeau
   juste en dessous. Le bleu atteint sa pleine teinte dès 65% du dégradé
   (pas 100%) pour arriver plus tôt visuellement, plutôt que de rester
   cantonné à un coin (dérive lente, même keyframe reassuranceGradientDrift,
   pour rester dans le même langage de mouvement que le reste du site).
   Contenu — deux gros chiffres nus, sans icône ni carte — sur ce fond
   sombre plutôt que dans une case séparée. Structure différente aussi bien
   en version téléphone (empilée, trait horizontal) qu'en version ordinateur
   (côte à côte, trait vertical) : jamais juste "la grille de cartes qui se
   replie en colonne". Contrastes texte blanc vérifiés (calcul réel) :
   sur --c-primary 15,5:1 · sur --c-primary-dk 17,4:1 · sur --c-lien
   6,7:1 — largement AA à tout point du dégradé. min-width:0 sur
   .chiffres-bandeau-stat (piège classique flex : sans lui, le stat au texte
   plus long refuse de se réduire à sa part de 50% et pousse le trait/l'autre
   stat hors du centre réel du bandeau). */
.chiffres-bandeau {
  display: flex;
  align-items: stretch;
  justify-content: center;
  gap: var(--sp-8);
  padding: var(--sp-7) var(--sp-6);
  border-radius: var(--radius);
  background: linear-gradient(120deg, var(--c-primary) 0%, var(--c-primary-dk) 20%, var(--c-lien) 65%);
  background-size: 140% 140%;
  animation: reassuranceGradientDrift 16s var(--ease-in-out-soft) infinite;
}

.chiffres-bandeau-stat {
  /* Repère de positionnement des emoji décoratifs absolus (voir plus bas),
     + isolation : leur z-index reste cantonné à ce bloc, sans effet de bord
     sur le trait ni le dégradé du panneau. */
  position: relative;
  isolation: isolate;
  display: flex;
  flex: 1 1 0;
  min-width: 0;
  flex-direction: column;
  align-items: center;
  /* .chiffres-bandeau (align-items:stretch) étire chaque stat à la hauteur
     de la plus grande des deux — sans ce justify-content, le contenu d'un
     stat plus court (une seule ligne de chiffre) restait plaqué en haut de
     sa propre boîte étirée au lieu d'être centré dedans. */
  justify-content: center;
  /* padding-top RÉSERVE une bande pour les emoji flottants : le texte réel
     ne peut jamais y entrer, donc aucun chevauchement possible à AUCUNE
     largeur — garantie géométrique, indépendante de la hauteur d'étirement
     flex ou de la largeur changeante du compteur JS. padding-bottom
     IDENTIQUE en contrepartie : un padding asymétrique (haut seul)
     aurait décalé le contenu centré vers le bas de la moitié de sa valeur —
     symétrique, il ne fait que réduire l'espace de centrage sans
     déplacer son milieu. */
  padding-block: var(--sp-5);
  gap: var(--sp-2);
  max-width: 34ch;
  margin-inline: auto;
  text-align: center;
}

.chiffres-bandeau-trait {
  flex-shrink: 0;
  align-self: stretch;
  width: 1px;
  background: rgba(255, 255, 255, .25);
}

/* Respiration très légère sur le chiffre (échelle, pas de lumière) — une
   lueur (text-shadow blanc) s'est révélée bien trop intense/« aveuglante »
   en usage réel sur ce fond déjà lumineux (bleu vif) ; une variation
   d'échelle discrète reste perceptible sans jamais agresser l'œil.
   Amplitude volontairement faible (2,5%) : à cette taille de texte, même un
   petit pourcentage déplace beaucoup de pixels. Effet différent de la
   respiration en opacité du sous-texte juste en dessous (rythme et
   mécanisme distincts), pour que l'œil distingue "la donnée" de "son
   explication". */
@keyframes chiffresValeurRespire {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.025); }
}

/* min-height (2 lignes, la hauteur finale de "Jusqu'à 1 998 €/mois" une
   fois replié) + centrage interne : le compteur animé (data-count-to)
   grandit progressivement de "0" à sa valeur finale, passant par du texte
   sur UNE seule ligne avant de finir sur DEUX une fois assez large. Sans
   cette réserve d'espace, cette bascule 1→2 lignes changeait la hauteur
   naturelle du stat pendant le comptage, ce qui redimensionnait aussi
   .chiffres-bandeau-stat--5min (étiré à la même hauteur, voir plus haut) et
   faisait "sauter" son contenu du haut vers le centre en cours d'animation.
   Réserver la hauteur finale dès le départ rend cette hauteur stable du
   premier au dernier instant, sur les deux chiffres. */
.chiffres-bandeau-valeur {
  /* Passe devant la couche d'emoji décoratifs (z-index:0, voir plus bas) —
     ceinture ET bretelles avec la bande de réserve padding-top ci-dessus. */
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0;
  min-height: calc(2 * 1.05em);
  font-size: var(--fs-600);
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: -0.02em;
  color: var(--c-bg);
  font-variant-numeric: tabular-nums;
  animation: chiffresValeurRespire 4.5s var(--ease-in-out-soft) infinite;
}

/* Respiration lente et discrète du sous-texte — rythme volontairement
   différent (plus lent, amplitude plus faible) de la lueur du chiffre
   ci-dessus : un texte de lecture ne doit jamais bouger assez pour gêner,
   juste assez pour rester "vivant". */
@keyframes chiffresTexteRespire {
  0%, 100% { opacity: .68; }
  50%      { opacity: 1; }
}

.chiffres-bandeau-texte {
  position: relative;
  z-index: 1;
  margin: 0;
  color: var(--c-bg);
  font-size: var(--fs-200);
  animation: chiffresTexteRespire 6s var(--ease-in-out-soft) infinite;
}

/* Fait ressortir "économie" : blanc plein + soulignement plutôt qu'une
   couleur distincte (--c-lien n'est vérifié que sur fond clair — sur ce
   dégradé sombre, le blanc reste la seule teinte de texte sûre à tout
   point du dégradé). */
.chiffres-bandeau-texte strong {
  color: var(--c-bg);
  font-weight: 800;
  text-decoration: underline;
  text-decoration-color: rgba(255, 255, 255, .6);
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
}

/* Emoji « posés », jamais en pastille : pas de fond, pas de bordure, pas de
   radius, pas de mot-étiquette. Le glyphe seul, incliné comme un
   autocollant collé de travers, détaché du dégradé par un simple
   drop-shadow marine (aucune « bulle » créée : l'ombre est portée par la
   forme du glyphe, pas par une boîte).

   Composition : un emoji en haut à gauche, l'autre en bas à droite, sur les
   DEUX stats — diagonale opposée aux deux coins du bloc plutôt que les deux
   emoji groupés au même endroit. Toujours dans la bande padding-block:
   var(--sp-5) réservée en haut ET en bas sur .chiffres-bandeau-stat (voir
   plus haut) : non-collision garantie géométriquement, pas par un calcul de
   hauteur d'étirement flex. Filet de sécurité en plus : z-index 0 ici
   contre z-index 1 sur le chiffre et le sous-texte, le texte réel passe
   toujours devant.

   Deux jeux de keyframes (pas juste deux, quatre) : les émoji du HAUT
   dérivent/balancent vers le HAUT (s'éloignent du texte, encore plus haut
   dans le padding) ; ceux du BAS dérivent/balancent vers le BAS (miroir
   exact, s'éloignent vers le padding du dessous) — jamais l'inverse, qui
   les aurait rapprochés du texte à l'instant du pic d'animation.

   Le compteur JS (stat 2) ne perturbe rien : les emoji sont ancrés sur le
   BLOC (largeur stable, flex: 1 1 0), pas sur la boîte du chiffre dont la
   largeur varie pendant le comptage — aucun glissement latéral parasite.

   --emoji-rot porte l'angle de repos propre à chaque emoji, réutilisé dans
   les keyframes. prefers-reduced-motion est déjà neutralisé globalement
   (règle en tête de fichier) : à l'arrêt, les emoji gardent leur
   inclinaison « posée de travers » sans jamais bouger. */
.chiffres-bandeau-emoji {
  position: absolute;
  z-index: 0;
  display: block;
  line-height: 1;
  pointer-events: none;
  user-select: none;
  font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", "Segoe UI Symbol", sans-serif;
  filter: drop-shadow(0 3px 8px rgba(11, 36, 71, .35));
  transform: rotate(var(--emoji-rot, 0deg));
}

/* Rythme "dérive" (haut) : translation verticale dominante vers le HAUT
   (5px), rotation quasi imperceptible (3°) — l'objet flotte vers le padding
   du dessus, jamais vers le texte. */
@keyframes chiffresEmojiDeriveHaut {
  0%, 100% { transform: translateY(0)    rotate(var(--emoji-rot, 0deg)); }
  50%      { transform: translateY(-5px) rotate(calc(var(--emoji-rot, 0deg) + 3deg)); }
}

/* Rythme "dérive" (bas) : miroir exact, vers le BAS. */
@keyframes chiffresEmojiDeriveBas {
  0%, 100% { transform: translateY(0)   rotate(var(--emoji-rot, 0deg)); }
  50%      { transform: translateY(5px) rotate(calc(var(--emoji-rot, 0deg) + 3deg)); }
}

/* Rythme "balancier" (haut) : rotation dominante (5°), translation minime
   vers le HAUT (3px) — l'objet oscille sans jamais descendre vers le texte. */
@keyframes chiffresEmojiBalancierHaut {
  0%, 100% { transform: translateY(0)    rotate(var(--emoji-rot, 0deg)); }
  50%      { transform: translateY(-3px) rotate(calc(var(--emoji-rot, 0deg) - 5deg)); }
}

/* Rythme "balancier" (bas) : miroir exact, vers le BAS. */
@keyframes chiffresEmojiBalancierBas {
  0%, 100% { transform: translateY(0)   rotate(var(--emoji-rot, 0deg)); }
  50%      { transform: translateY(3px) rotate(calc(var(--emoji-rot, 0deg) - 5deg)); }
}

/* --- Stat 1 "5 min" --- */

/* ⏳ haut-gauche */
.chiffres-bandeau-emoji--sablier {
  --emoji-rot: -12deg;
  top: -8px;
  left: 3%;
  font-size: 27px;
  animation: chiffresEmojiDeriveHaut 5.4s var(--ease-in-out-soft) 0s infinite;
}

/* ✅ bas-droite */
.chiffres-bandeau-emoji--coche {
  --emoji-rot: 10deg;
  bottom: -6px;
  right: 4%;
  font-size: 22px;
  opacity: .95;
  transform-origin: 50% 0%;
  animation: chiffresEmojiBalancierBas 4.6s var(--ease-in-out-soft) .8s infinite;
}

/* --- Stat 2 "économie" --- */

/* 💸 haut-gauche */
.chiffres-bandeau-emoji--billet {
  --emoji-rot: 13deg;
  top: -10px;
  left: 2%;
  font-size: 29px;
  transform-origin: 50% 100%;
  animation: chiffresEmojiBalancierHaut 6.2s var(--ease-in-out-soft) .4s infinite;
}

/* 📆 bas-droite */
.chiffres-bandeau-emoji--calendrier {
  --emoji-rot: -10deg;
  bottom: -4px;
  right: 5%;
  font-size: 20px;
  opacity: .95;
  animation: chiffresEmojiDeriveBas 5s var(--ease-in-out-soft) 1.4s infinite;
}

@media (max-width: 760px) {
  .chiffres-bandeau {
    flex-direction: column;
    gap: var(--sp-6);
    padding-block: var(--sp-6);
  }

  .chiffres-bandeau-trait {
    width: 60%;
    height: 1px;
    align-self: center;
  }

  /* Panneau empilé : chaque stat occupe toute la largeur, les deux jeux
     d'emoji ne peuvent plus se croiser. Même composition (haut-gauche /
     bas-droite, mêmes rythmes, mêmes rôles) — seules l'échelle et
     l'amplitude des débordements sont réduites pour rester proportionnées
     à une colonne étroite. */
  .chiffres-bandeau-emoji--sablier    { top: -4px;    left: 2%;  font-size: 23px; }
  .chiffres-bandeau-emoji--coche      { bottom: -4px; right: 5%; font-size: 18px; }
  .chiffres-bandeau-emoji--billet     { top: -6px;    left: 2%;  font-size: 25px; }
  .chiffres-bandeau-emoji--calendrier { bottom: -2px; right: 6%; font-size: 17px; }
}

/* Réutilisée depuis .maquette-conversation__badge-icone, seule survivance de
   l'ancien badge "OFFERT" (supprimé avec .chiffre-badge) à s'appuyer sur
   cette animation — gardée pour cette raison. */
@keyframes chiffreBadgePulse {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.06); }
}

/* --------------------------------------------------------------------------
   5. Réassurance — bandeau plein --c-primary, texte blanc : rupture nette
   avec les sections claires qui précèdent. Cartes en --c-primary-dk (plus
   sombre que le fond du bandeau, uniquement des tokens existants) pour se
   détacher sans jamais introduire de couleur hors palette. Icônes en trait
   clair (--c-bg) sur pastille --c-primary, pour rester lisibles sur fond
   sombre.
   -------------------------------------------------------------------------- */
.reassurance-bandeau {
  padding: var(--sp-8) var(--sp-4);
  background: linear-gradient(120deg, var(--c-primary) 0%, var(--c-primary-dk) 50%, var(--c-primary) 100%);
  background-size: 220% 220%;
}

/* Ambiance : dégradé qui dérive très lentement dans le bandeau — jamais
   figé, jamais clignotant, amplitude de mouvement faible (positions de
   fond seulement, aucune forme ne bouge). */
@keyframes reassuranceGradientDrift {
  0%, 100% { background-position: 0% 50%; }
  50%      { background-position: 100% 50%; }
}

.reassurance-bandeau {
  animation: reassuranceGradientDrift 16s var(--ease-in-out-soft) infinite;
}

.reassurance-bandeau-titre {
  color: var(--c-bg);
}

.reassurance-bandeau-liste {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-5);
  margin: 0;
  padding: 0;
  list-style: none;
}

@media (min-width: 640px) {
  .reassurance-bandeau-liste {
    grid-template-columns: repeat(3, 1fr);
  }
}

.reassurance-bandeau-carte {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sp-3);
  padding: var(--sp-5);
  background: var(--c-primary-dk);
  border-radius: var(--radius-lg);
  transition: transform var(--dur-fast) var(--ease-out-soft),
              box-shadow var(--dur-fast) var(--ease-out-soft);
}

.reassurance-bandeau-carte:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lg);
}

.reassurance-bandeau-icone {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: var(--c-primary);
}

.reassurance-bandeau-carte h3 {
  margin: 0;
  color: var(--c-bg);
  font-size: var(--fs-300);
}

.reassurance-bandeau-carte p {
  margin: 0;
  max-width: none;
  color: var(--c-bg);
  font-size: var(--fs-100);
}

/* --------------------------------------------------------------------------
   6. Rappel final — carte élevée sur fond blanc, pour clore la page sur une
   note douce après le bandeau marine. Réutilise .vitrine-cta-final (texte
   déjà stylé) pour la chair, cette classe n'ajoute que l'écrin visuel.
   -------------------------------------------------------------------------- */
.cta-final-carte {
  padding: var(--sp-8) var(--sp-6);
  background: var(--c-bg-alt);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
}

/* ==========================================================================
   Maquette de conversation — illustration stylisée (vocal + photos reçus,
   récapitulatif renvoyé pour validation). Reconstitution graphique originale
   en HTML/SVG, ne reprend ni l'interface ni la marque d'aucune messagerie
   tierce : pas de vert, pas de logo, pas de tuyau de bulle façon "chat
   officiel" (les bulles se distinguent par un coin resserré côté avatar,
   voir .maquette-conversation__bulle). Composant purement décoratif,
   toujours marqué aria-hidden="true" côté HTML.
   Disposition façon vraie conversation cliente : le technicien (qui envoie,
   depuis son téléphone) est à DROITE, en bulle pleine (le style "message
   envoyé") ; Pro Rapport (qui répond) est à GAUCHE, en bulle claire (le
   style "message reçu") — l'inverse casserait la lecture immédiate de qui
   parle à qui pour un visiteur habitué à WhatsApp/iMessage. */

.maquette-conversation {
  width: 100%;
  max-width: 33rem;
  margin-inline: auto;
  padding: var(--sp-6) var(--sp-5);
  background: var(--c-bg-alt);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}

/* Identifie visuellement la maquette comme une conversation WhatsApp, sans
   passer par du texte : le composant reste 100% décoratif (voir plus haut),
   l'information réelle est déjà portée par le hero au-dessus. */
.maquette-conversation__plateforme {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  margin-bottom: var(--sp-5);
  padding: var(--sp-1) var(--sp-3);
  border-radius: 999px;
  background: var(--c-bg);
  border: 1px solid var(--c-border);
  box-shadow: var(--shadow-sm);
  color: var(--c-ink-soft);
  font-size: var(--fs-100);
  font-weight: 700;
}

.maquette-conversation__plateforme img {
  display: block;
  flex-shrink: 0;
}

.maquette-conversation__fil {
  display: flex;
  flex-direction: column;
  gap: var(--sp-5);
}

.maquette-conversation__message {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-width: 0;
}

.maquette-conversation__message--technicien {
  flex-direction: row-reverse;
}

.maquette-conversation__avatar {
  flex: 0 0 auto;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.maquette-conversation__avatar--technicien { background: var(--c-teal); }
.maquette-conversation__avatar--rapport { background: var(--c-primary); }

.maquette-conversation__colonne {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sp-1);
  min-width: 0;
  max-width: 82%;
}

.maquette-conversation__message--technicien .maquette-conversation__colonne {
  align-items: flex-end;
}

.maquette-conversation__expediteur {
  font-size: var(--fs-100);
  font-weight: 600;
  color: var(--c-ink-soft);
  padding-inline: var(--sp-2);
}

.maquette-conversation__bulle {
  border-radius: var(--radius-lg);
  padding: var(--sp-4);
}

.maquette-conversation__bulle--rapport {
  background: var(--c-bg);
  border: 1.5px solid var(--c-border);
  border-end-start-radius: var(--radius-sm);
}

.maquette-conversation__bulle--technicien {
  background: var(--c-primary);
  color: var(--c-bg);
  border-end-end-radius: var(--radius-sm);
}

.maquette-conversation__audio {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
}

.maquette-conversation__audio-icone {
  display: flex;
  flex: 0 0 auto;
}

.maquette-conversation__onde {
  display: flex;
  align-items: flex-end;
  gap: 3px;
  height: 22px;
  flex: 1 1 auto;
  min-width: 90px;
}

.maquette-conversation__onde-barre {
  display: block;
  width: 3px;
  border-radius: 2px;
  background: var(--c-bg);
  transform-origin: bottom center;
  animation: maquetteConversationOnde var(--dur-slow) var(--ease-in-out-soft) infinite;
}

.maquette-conversation__onde-barre:nth-child(1) { height: 8px;  animation-delay: 0ms; }
.maquette-conversation__onde-barre:nth-child(2) { height: 14px; animation-delay: 90ms; }
.maquette-conversation__onde-barre:nth-child(3) { height: 22px; animation-delay: 180ms; }
.maquette-conversation__onde-barre:nth-child(4) { height: 12px; animation-delay: 270ms; }
.maquette-conversation__onde-barre:nth-child(5) { height: 18px; animation-delay: 360ms; }
.maquette-conversation__onde-barre:nth-child(6) { height: 9px;  animation-delay: 450ms; }
.maquette-conversation__onde-barre:nth-child(7) { height: 15px; animation-delay: 540ms; }

@keyframes maquetteConversationOnde {
  0%, 100% { transform: scaleY(.25); }
  50%      { transform: scaleY(1.15); }
}

/* Flottement indépendant de chaque bulle (amplitude modeste : le composant
   flotte déjà dans son ensemble via .hero-premium-anim/heroPremiumFloat —
   ce mouvement plus petit, décalé dans le temps entre les deux messages,
   ajoute une couche de vie sans donner un résultat désordonné). */
@keyframes maquetteConversationFlotte {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-5px); }
}

.maquette-conversation__message {
  animation: maquetteConversationFlotte 7.5s var(--ease-in-out-soft) infinite;
}

.maquette-conversation__message--rapport {
  animation-duration: 8.5s;
  animation-delay: 1.2s;
}

/* Pulsation discrète du badge de validation reçue — même keyframe que les
   chiffres-clés animés (chiffreBadgePulse), pour rester cohérent avec le
   reste du langage d'ambiance du site plutôt que d'inventer un nouveau
   rythme. */
.maquette-conversation__badge-icone {
  animation: chiffreBadgePulse 6s var(--ease-in-out-soft) infinite;
}

.maquette-conversation__duree {
  font-size: var(--fs-100);
  color: var(--c-bg);
  opacity: .8;
  font-variant-numeric: tabular-nums;
  flex: 0 0 auto;
}

.maquette-conversation__vignettes {
  display: flex;
  gap: var(--sp-2);
  margin-top: var(--sp-3);
}

.maquette-conversation__vignette {
  display: block;
  width: 44px;
  height: 44px;
  padding: 6px;
  background: var(--c-bg);
  border: 1.5px solid var(--c-border);
  border-radius: var(--radius-sm);
}

.maquette-conversation__badge {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--fs-100);
  font-weight: 700;
  margin-bottom: var(--sp-2);
}

.maquette-conversation__badge-icone {
  display: flex;
  flex: 0 0 auto;
}

.maquette-conversation__texte {
  margin: 0;
  max-width: none;
  color: inherit;
  font-size: var(--fs-200);
  line-height: 1.5;
}

.maquette-conversation__heure {
  font-size: var(--fs-100);
  color: var(--c-ink-soft);
  padding-inline: var(--sp-2);
}

@media (max-width: 420px) {
  .maquette-conversation { padding: var(--sp-5) var(--sp-4); }
  .maquette-conversation__colonne { max-width: 86%; }
}

@media (prefers-reduced-motion: reduce) {
  .maquette-conversation__onde-barre {
    animation: none !important;
  }
}

/* ==========================================================================
   Section "Un rapport professionnel, prêt à transmettre" (page d'accueil,
   entre le hero et "Comment ça marche"). 4 VRAIES pages d'exemple de rapport
   (assets/img/page-rapport-1..4.png), assets/js/rapport-reveal.js dédié.

   1. .rapport-chemin — trait + flèche décoratifs (SVG, pathLength=100 pour
      un dasharray/dashoffset en unités 0-100 indépendantes de la géométrie
      réelle de la courbe), dont la longueur tracée suit EN DIRECT la
      position de scroll, dans les deux sens (grandit en descendant, rétrécit
      en remontant) — écrite en JS via des styles en ligne à chaque frame
      (jamais de transition CSS ici : elle ferait "traîner" le trait derrière
      le scroll). Par défaut (sans JS, mouvement réduit, ou navigateur trop
      ancien) : déjà entièrement tracé, flèche visible — un rendu statique
      complet, cohérent sans script.
   2. .rapport-pile-wrap / .rapport-pile-scroll / .rapport-reveal-page /
      .rapport-pile-fleche — pile de pages navigable par deux boutons
      (précédente/suivante), jamais par le scroll : un clic fait glisser et
      s'estomper la page courante pour révéler la suivante en dessous (même
      registre visuel que l'ancienne version scroll-driven, mais piloté par
      un état discret — assets/js/rapport-reveal.js bascule simplement les
      classes .est-active/.est-passee, la transition CSS ci-dessous fait le
      reste). Sans JS : repli en liste empilée classique, chaque page
      pleinement visible avec sa légère bascule de repos
      (--rapport-rotation) — les boutons restent hidden dans le HTML, jamais
      révélés, aucune dépendance au script pour un rendu correct.
   ========================================================================== */

.rapport-chemin {
  display: flex;
  justify-content: center;
  max-width: 200px;
  margin: 0 auto var(--sp-5);
}

.rapport-chemin svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}

.rapport-chemin-trait {
  fill: none;
  stroke: var(--c-primary);
  stroke-width: 6;
  stroke-linecap: round;
  stroke-dasharray: 100;
  stroke-dashoffset: 0;
  filter: drop-shadow(0 3px 6px rgba(11, 36, 71, .3));
}

/* Chevron ouvert (pas un triangle plein) qui reprend l'épaisseur et le
   arrondi du trait lui-même : lu comme le prolongement naturel de la ligne
   plutôt que comme une forme rapportée par-dessus. La courbe se termine par
   un segment bien vertical (voir le "L" final de .rapport-chemin-trait,
   index.html) pour que ce chevron, orienté droit vers le bas, s'aligne
   exactement avec la direction réelle d'arrivée du trait. */
.rapport-chemin-pointe {
  fill: none;
  stroke: var(--c-primary);
  stroke-width: 6;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 1;
  transform-box: fill-box;
  transform-origin: 50% 90%;
  filter: drop-shadow(0 3px 6px rgba(11, 36, 71, .3));
}

.rapport-pile-scroll {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-8);
  max-width: 30rem;
  margin: var(--sp-7) auto 0;
  padding-inline: var(--sp-4);
}

.rapport-reveal-page {
  margin: 0;
  width: 100%;
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 1px solid var(--c-border);
  border-top: 5px solid var(--rapport-couleur-marque, var(--c-border));
  box-shadow: var(--shadow-lg);
  background: var(--c-bg);
  transform: rotate(var(--rapport-rotation, 0deg));
  transition: transform var(--dur-base) var(--ease-in-out-soft),
              opacity var(--dur-base) var(--ease-in-out-soft),
              box-shadow var(--dur-fast) var(--ease-out-soft),
              border-color var(--dur-fast) var(--ease-out-soft);
}

/* Un liseré de couleur différent par page (mêmes teintes que les puces de
   "Comment ça marche", pour rester dans le même langage visuel) : rend
   concrète la promesse "aux couleurs de votre logo" juste au-dessus — au
   lieu de recolorer artificiellement les captures d'écran réelles (aurait
   l'air cassé sur du texte/des photos), on montre la personnalisation là où
   c'est honnête de le faire : le cadre. */
.rapport-reveal-page:nth-child(1) { --rapport-rotation: -1.4deg; --rapport-couleur-marque: var(--c-teal-dk); }
.rapport-reveal-page:nth-child(2) { --rapport-rotation: 1.1deg; --rapport-couleur-marque: var(--c-lien); }
.rapport-reveal-page:nth-child(3) { --rapport-rotation: -0.9deg; --rapport-couleur-marque: var(--c-accent-dk); }
.rapport-reveal-page:nth-child(4) { --rapport-rotation: 1.6deg; --rapport-couleur-marque: var(--c-primary); }
.rapport-reveal-page:nth-child(5) { --rapport-rotation: -1.7deg; --rapport-couleur-marque: var(--c-teal); }

.rapport-reveal-page img {
  display: block;
  width: 100%;
  height: auto;
}

/* border-right/-bottom/-left plutôt que le raccourci border-color : le
   liseré de couleur du haut (--rapport-couleur-marque) doit rester visible
   même au survol, pas être écrasé par le marine du survol. */
.rapport-reveal-page:hover {
  transform: rotate(0deg) translateY(-4px) scale(1.015);
  border-right-color: var(--c-primary);
  border-bottom-color: var(--c-primary);
  border-left-color: var(--c-primary);
  box-shadow: 0 20px 40px rgba(11, 36, 71, .18), var(--shadow-lg);
}

/* --- Mode "carrousel" : une page visible, navigation par boutons -------- */
/* Grille plutôt que positionnement absolu : les flèches occupent leurs
   propres colonnes/lignes, jamais superposées à la pile — un vrai
   emplacement réservé, pas un décalage approximatif par-dessus l'image.
   Mobile (peu de largeur disponible) : flèches côte à côte SOUS la pile.
   Dès 640px (plus de largeur) : flèches de part et d'autre de la pile. */
.rapport-pile--actif {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-areas:
    "pile pile"
    "prec suiv";
  align-items: center;
  justify-items: center;
  gap: var(--sp-5);
  max-width: 24rem;
  margin-inline: auto;
}

@media (min-width: 640px) {
  .rapport-pile--actif {
    grid-template-columns: auto minmax(0, 24rem) auto;
    grid-template-areas: "prec pile suiv";
    max-width: none;
    justify-content: center;
  }
}

.rapport-pile--actif .rapport-pile-scroll {
  grid-area: pile;
  position: relative;
  width: 100%;
  max-width: 24rem;
  aspect-ratio: 978 / 1388;
  margin: var(--sp-7) 0 0;
  padding-inline: 0;
}

.rapport-pile--actif .rapport-reveal-page {
  position: absolute;
  inset: 0;
}

/* Empilement de repos : la page 0 au-dessus, la 3 en dessous — c'est
   l'ordre naturel de révélation, il n'a jamais besoin d'être recalculé en
   JS, seules les classes .est-active/.est-passee changent l'opacité et la
   position de chaque page. */
.rapport-pile--actif .rapport-reveal-page:nth-child(1) { z-index: 5; }
.rapport-pile--actif .rapport-reveal-page:nth-child(2) { z-index: 4; }
.rapport-pile--actif .rapport-reveal-page:nth-child(3) { z-index: 3; }
.rapport-pile--actif .rapport-reveal-page:nth-child(4) { z-index: 2; }
.rapport-pile--actif .rapport-reveal-page:nth-child(5) { z-index: 1; }

.rapport-pile--actif .rapport-reveal-page:hover {
  transform: rotate(var(--rapport-rotation, 0deg));
  border-right-color: var(--c-border);
  border-bottom-color: var(--c-border);
  border-left-color: var(--c-border);
  box-shadow: var(--shadow-lg);
}

.rapport-pile--actif .rapport-reveal-page.est-active:hover {
  transform: rotate(0deg) translateY(-4px) scale(1.015);
  border-right-color: var(--c-primary);
  border-bottom-color: var(--c-primary);
  border-left-color: var(--c-primary);
  box-shadow: 0 20px 40px rgba(11, 36, 71, .18), var(--shadow-lg);
}

.rapport-pile--actif .rapport-reveal-page.est-passee {
  transform: translateY(130px) scale(.94) rotate(var(--rapport-rotation, 0deg));
  opacity: 0;
  pointer-events: none;
}

.rapport-pile-fleche {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  padding: 0;
  border: 1px solid var(--c-border-strong);
  border-radius: 50%;
  background-color: var(--c-bg);
  color: var(--c-primary);
  box-shadow: var(--shadow-md);
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-out-soft),
              color var(--dur-fast) var(--ease-out-soft),
              border-color var(--dur-fast) var(--ease-out-soft),
              box-shadow var(--dur-fast) var(--ease-out-soft),
              transform var(--dur-fast) var(--ease-out-soft),
              opacity var(--dur-fast) var(--ease-out-soft);
}

.rapport-pile-fleche svg {
  width: 22px;
  height: 22px;
}

.rapport-pile-fleche--prec { grid-area: prec; }
.rapport-pile-fleche--suiv { grid-area: suiv; }

.rapport-pile-fleche:hover {
  background-color: var(--c-primary);
  color: var(--c-bg);
  border-color: var(--c-primary);
  box-shadow: var(--shadow-lg);
}

.rapport-pile-fleche--prec:hover { transform: translateX(-3px); }
.rapport-pile-fleche--suiv:hover { transform: translateX(3px); }

.rapport-pile-fleche:active {
  box-shadow: var(--shadow-sm);
}

.rapport-pile-fleche--prec:active { transform: translateX(-1px) scale(.94); }
.rapport-pile-fleche--suiv:active { transform: translateX(1px) scale(.94); }

.rapport-pile-fleche:focus-visible {
  outline: 2px solid var(--c-lien);
  outline-offset: 2px;
}

.rapport-pile-fleche:disabled {
  opacity: .35;
  box-shadow: var(--shadow-sm);
  cursor: default;
}

.rapport-pile-fleche:disabled:hover {
  background-color: var(--c-bg);
  color: var(--c-primary);
  border-color: var(--c-border-strong);
  transform: none;
}

.rapport-pile-compteur {
  margin: var(--sp-4) 0 0;
  text-align: center;
  font-size: var(--fs-100);
  font-weight: 600;
  letter-spacing: .02em;
  color: var(--c-ink-soft);
}

/* ==========================================================================
   Comment ça marche — carrousel au scroll (page d'accueil, /index.html)
   Esprit "lassie.ai" : les 3 étapes se succèdent au fil du scroll, la carte
   active se met en évidence pendant que les deux autres s'estompent et
   reculent. Progressive enhancement strict :

   - Par défaut (sans JS, JS désactivé, navigateur trop ancien), le balisage
     est une liste .etapes-scroll-liste tout à fait classique : 3 cartes
     visibles, empilées sur une colonne puis en 3 colonnes dès 800px (même
     seuil que l'ancien .vitrine-etapes), sans aucune dépendance au script.
   - Seule la classe .etapes-scroll--actif, posée par
     assets/js/etapes-scroll.js sur le conteneur .etapes-scroll lui-même
     (jamais sur <html> : comportement scopé à ce composant, comme
     .hero-anim--play), active la mise en scène "pinned" : piste de scroll
     plus haute que l'écran, carte active épinglée et mise en avant, les deux
     autres masquées derrière elle.
   - Cette classe n'est posée que si prefers-reduced-motion n'est pas actif ;
     même effet à toute largeur d'écran. En cas de mouvement réduit ou sans
     JS, la liste reste la version empilée classique et la cascade
     [data-reveal-item] (assets/js/scroll-reveal.js, déjà en place)
     s'applique normalement.
   - Le script pilote deux valeurs sur .etapes-scroll : la custom property
     --etapes-progress (0→1 continu, calculée sur la hauteur de la piste de
     scroll, consommée directement ci-dessous par la jauge via
     transform: scaleX()) et l'attribut data-etapes-active (index entier de
     l'étape active, 0/1/2 — une valeur de custom property ne pouvant pas
     être testée dans un sélecteur CSS, cet attribut est le relais qui pilote,
     via des sélecteurs :nth-child, la mise en évidence de la carte active et
     le recul des deux autres).
   ========================================================================== */

.etapes-scroll-liste {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-5);
  margin: 0;
  padding: 0;
  list-style: none;
}

@media (min-width: 800px) {
  .etapes-scroll-liste {
    grid-template-columns: repeat(3, 1fr);
  }
}

/* Une couleur d'identité propre à chaque étape (icône + accents), portée
   par des custom properties sur le <li> pour cascader naturellement vers
   tout son contenu (carte, titre, badge numéro) sans dupliquer trois jeux
   de règles quasi identiques. --etape-accent reste toujours un token déjà
   validé ≥ 4,5:1 en texte courant (jamais --c-blue-vif brut, réservé aux
   très gros titres gras — voir design-system.md) : l'étape 2 utilise
   --c-lien, de la même famille chromatique, mais sûr à toute taille. */
.etapes-scroll-etape:nth-child(1) { --etape-accent: var(--c-teal-dk); }
.etapes-scroll-etape:nth-child(2) { --etape-accent: var(--c-lien); }
.etapes-scroll-etape:nth-child(3) { --etape-accent: var(--c-accent-dk); }

.etapes-scroll-etape {
  min-width: 0;
}

.etapes-scroll-carte {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sp-5);
  height: 100%;
  padding: var(--sp-6) var(--sp-5) var(--sp-5);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-lg);
  background: var(--c-bg);
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--dur-base) var(--ease-out-soft),
              border-color var(--dur-base) var(--ease-out-soft),
              transform var(--dur-fast) var(--ease-out-soft),
              opacity var(--dur-slow) var(--ease-in-out-soft);
}

.etapes-scroll-carte:hover {
  box-shadow: var(--shadow-lg);
  border-color: var(--etape-accent, var(--c-primary));
  transform: translateY(-3px);
}

.etapes-scroll-visuel {
  position: relative;
  flex-shrink: 0;
  width: 100px;
  height: 100px;
}

.etapes-scroll-icone {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  box-shadow: var(--shadow-md);
  transition: transform var(--dur-base) var(--ease-out-soft);
}

.etapes-scroll-carte:hover .etapes-scroll-icone {
  transform: scale(1.06) rotate(-3deg);
}

/* Puce numéro : pastille blanche à cheval sur le cercle, texte dans la
   couleur d'identité de l'étape plutôt qu'un disque plein — plus léger
   visuellement que l'ancienne version, tout en restant bien lisible. */
.etapes-scroll-num {
  position: absolute;
  right: -8px;
  top: -8px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 34px;
  height: 34px;
  padding-inline: var(--sp-2);
  border-radius: 999px;
  border: 2px solid var(--c-bg);
  background: var(--c-bg);
  box-shadow: var(--shadow-sm);
  color: var(--etape-accent, var(--c-primary));
  font-size: var(--fs-200);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

.etapes-scroll-corps {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}

.etapes-scroll-corps h3 {
  margin: 0;
  font-size: var(--fs-400);
  font-weight: 800;
  color: var(--c-ink);
}

.etapes-scroll-corps p {
  margin: 0;
  color: var(--c-ink-soft);
  max-width: none;
}

/* Fait ressortir l'idée clé de chaque étape, dans la couleur d'identité de
   sa carte (--etape-accent) plutôt qu'un gras neutre — cohérent avec le
   reste du code couleur par étape (pastille, contour au survol). */
.etapes-scroll-corps p strong {
  color: var(--etape-accent, var(--c-primary));
  font-weight: 700;
}

/* Jauge de progression + puces : purement décoratives, masquées par défaut,
   ne s'affichent qu'en mode "pilote" (voir plus bas). */
.etapes-scroll-jauge,
.etapes-scroll-puces {
  display: none;
}

.etapes-scroll-puce {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--c-border);
  transition: background var(--dur-base) var(--ease-out-soft),
              transform var(--dur-base) var(--ease-out-soft);
}

/* --- Mode "pilote" : mise en évidence au scroll ---------------------------
   N'agit que sous .etapes-scroll--actif (posée par le script) — même effet
   à toute largeur d'écran (téléphone, tablette, ordinateur), plus de repli
   spécifique en dessous d'un seuil de largeur.

   Volontairement plus simple qu'un carrousel épinglé (position:sticky +
   pile de cartes superposées dans la même cellule de grille) : cette
   première version s'est révélée cassée en usage réel (les 3 cartes se
   superposaient au lieu de se succéder — l'attribut data-etapes-active ne
   suffisait pas à lui seul à garantir l'affichage d'une seule carte à la
   fois dans toutes les configurations). Ici, les 3 cartes restent dans le
   flux NORMAL du document, jamais superposées ni retirées du flux : chacune
   est seulement mise en évidence à tour de rôle via la classe
   .etapes-scroll-etape--active, posée directement sur la carte concernée
   par assets/js/etapes-scroll.js (IntersectionObserver, pas de calcul de
   position continu). Une superposition visuelle est donc structurellement
   impossible, quel que soit l'état du script. */
.etapes-scroll--actif .etapes-scroll-sticky {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding-block: var(--sp-6);
}

.etapes-scroll--actif .etapes-scroll-liste {
  display: flex;
  flex-direction: column;
  gap: var(--sp-8);
  width: 100%;
  max-width: 620px;
  margin-inline: auto;
}

.etapes-scroll--actif .etapes-scroll-carte {
  opacity: .55;
  transform: scale(.96);
  transition: opacity var(--dur-fast) var(--ease-out-soft),
              transform var(--dur-fast) var(--ease-out-soft),
              box-shadow var(--dur-base) var(--ease-out-soft),
              border-color var(--dur-base) var(--ease-out-soft);
}

/* Carte active : mise en évidence (échelle pleine, opacité pleine). */
.etapes-scroll--actif .etapes-scroll-etape--active .etapes-scroll-carte {
  opacity: 1;
  transform: scale(1);
  border-color: var(--c-primary);
  box-shadow: var(--shadow-lg);
}

.etapes-scroll--actif .etapes-scroll-jauge {
  display: block;
  width: 100%;
  max-width: 200px;
  height: 3px;
  margin: var(--sp-6) auto 0;
  border-radius: 999px;
  background: var(--c-border);
  overflow: hidden;
}

/* Remplissage piloté par --etapes-progress (0/0.5/1 selon la carte
   active, posée en JS) : la source n'étant plus un scroll continu mais un
   index discret, une transition rend le mouvement du remplissage fluide
   d'une étape à l'autre plutôt qu'un saut instantané. */
.etapes-scroll--actif .etapes-scroll-jauge-remplissage {
  display: block;
  height: 100%;
  width: 100%;
  transform: scaleX(var(--etapes-progress, 0));
  transform-origin: left center;
  background: var(--c-blue-vif);
  transition: transform var(--dur-slow) var(--ease-out-soft);
}

.etapes-scroll--actif .etapes-scroll-puces {
  display: flex;
  justify-content: center;
  gap: var(--sp-2);
  margin-top: var(--sp-3);
}

.etapes-scroll--actif[data-etapes-active="0"] .etapes-scroll-puce:nth-child(1),
.etapes-scroll--actif[data-etapes-active="1"] .etapes-scroll-puce:nth-child(2),
.etapes-scroll--actif[data-etapes-active="2"] .etapes-scroll-puce:nth-child(3) {
  background: var(--c-primary);
  transform: scale(1.35);
}

/* --- Repli explicite : mouvement réduit -----------------------------------
   Le script ne pose jamais .etapes-scroll--actif si prefers-reduced-motion
   est actif (contrat JS ci-dessous), mais on neutralise aussi ici toute
   conséquence visuelle si la classe se retrouvait posée malgré tout : aucun
   effet de mise en évidence, les 3 étapes restent toutes visibles et
   lisibles à égalité. */
@media (prefers-reduced-motion: reduce) {
  .etapes-scroll--actif .etapes-scroll-carte {
    opacity: 1 !important;
    transform: none !important;
  }

  .etapes-scroll--actif .etapes-scroll-jauge,
  .etapes-scroll--actif .etapes-scroll-puces {
    display: none !important;
  }
}

