/* ============================================================
   ENGIN — feuille de style
   Direction issue de la base UI/UX Pro Max :
     · structure  Trust & Authority + Conversion
     · accueil    Funnel (3-Step Conversion)
     · style      Minimalism & Swiss Style
     · palette    Professional navy + blue CTA
     · type       Inter
     · mouvement  Stagger List, 300-450 ms, back.out(1.4)
   Seule adaptation : l'accent d'action reste le vermillon de la
   marque plutôt que le bleu proposé — la règle de la base est
   « accent réservé au CTA », elle est respectée, et le vermillon
   tient 5,33:1 avec du blanc dessus.
   ============================================================ */

/* ─── JETONS ─────────────────────────────────────────────────
   Onze paires vérifiées au calcul avant d'être retenues.
   Aucune n'est en dessous de 4,5:1. */
:root {
  --nuit:        #0F172A;   /* fonds de rupture           */
  --encre:       #020617;   /* texte, 19,28:1 sur fond    */
  --fond:        #F8FAFC;
  --carte:       #FFFFFF;
  --attenue:     #475569;   /* 7,24:1                     */
  --filet:       #E2E8F0;
  --filet-fort:  #94A3B8;
  --bleu:        #0369A1;   /* 5,67:1 — la confiance      */
  --bleu-clair:  #38BDF8;   /* 8,33:1 sur nuit            */
  --bleu-pale:   #E0F2FE;
  --cta:         #C8330F;   /* réservé à l'action         */
  --cta-sombre:  #A82A0C;
  --cta-pale:    #FFF1ED;
  --succes:      #15803D;
  --or:          #B45309;

  --sur-nuit:    #E2E8F0;
  --filet-nuit:  rgba(226, 232, 240, 0.16);

  --police: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --mono:   ui-monospace, 'SF Mono', 'JetBrains Mono', Menlo, monospace;

  /* Échelle fluide. 16 px de base, jamais moins de 12 px nulle part. */
  --t-xs:   0.75rem;
  --t-sm:   0.875rem;
  --t-md:   1rem;
  --t-lg:   clamp(1.0625rem, 1rem + 0.3vw, 1.25rem);
  --t-xl:   clamp(1.375rem, 1.15rem + 1vw, 2rem);
  --t-2xl:  clamp(1.75rem, 1.25rem + 2.2vw, 3rem);
  --t-3xl:  clamp(2.25rem, 1.3rem + 4vw, 4.25rem);
  --t-4xl:  clamp(2.75rem, 1.2rem + 6.4vw, 6rem);

  /* Densité 4/10 — standard. */
  --e1: 4px;  --e2: 8px;  --e3: 12px; --e4: 16px; --e5: 24px;
  --e6: 32px; --e7: 48px; --e8: 64px; --e9: 96px; --e10: 128px;

  --marge: clamp(20px, 5vw, 64px);
  /* 1440 et non 1280 : sur une fenêtre de 2540 px, le cadre laissait
     631 px de vide de chaque côté. Les lignes de texte ne s'allongent
     pas — elles sont plafonnées en ch — seules les cartes s'élargissent.
     Le seuil exact est 1408 px (1280 + deux marges de 64) : en dessous,
     le cadre était déjà limité par les marges et non par ce plafond,
     donc rien ne change. Le nombre de colonnes, lui, ne bouge à
     aucune taille — les deux grilles concernées sont verrouillées. */
  --large: 1440px;
  --r-sm: 8px; --r-md: 14px; --r-lg: 22px; --r-full: 999px;

  --ombre-1: 0 1px 2px rgba(2, 6, 23, 0.06), 0 1px 3px rgba(2, 6, 23, 0.05);
  --ombre-2: 0 4px 12px -2px rgba(2, 6, 23, 0.08), 0 2px 6px -2px rgba(2, 6, 23, 0.05);
  --ombre-3: 0 20px 40px -18px rgba(2, 6, 23, 0.28), 0 4px 12px -6px rgba(2, 6, 23, 0.10);

  /* Le style Swiss demande des transitions courtes : 200-250 ms. */
  --vite:  0.2s cubic-bezier(0.4, 0, 0.2, 1);
  --pose:  0.3s cubic-bezier(0.4, 0, 0.2, 1);
  --sortie: cubic-bezier(0.16, 1, 0.3, 1);
}

/* ─── RÉINITIALISATION ───────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
/* Quand le lissage à la molette est actif, le défilement doux du
   navigateur doit se taire : deux lissages superposés donnent une
   page qui traîne. La seule ancre du site est le lien d'évitement,
   qui doit sauter d'un coup de toute façon. */
html.js-lisse { scroll-behavior: auto; }

body {
  background: var(--fond); color: var(--encre);
  font-family: var(--police); font-size: var(--t-md); line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  font-feature-settings: 'kern' 1, 'liga' 1, 'cv11' 1;
  overflow-x: hidden;
}
img, svg, canvas, video { display: block; max-width: 100%; }
img { height: auto; }
a { color: inherit; text-decoration: none; }
button, input, select, textarea { font: inherit; color: inherit; }
button { background: none; border: 0; cursor: pointer; }
ul, ol { list-style: none; }
:focus-visible { outline: 3px solid var(--bleu); outline-offset: 3px; border-radius: 3px; }
::selection { background: var(--cta); color: #FFF; }

/* Toute cible cliquable montre le doigt — règle de la liste de contrôle. */
a, button, summary, [role="button"], label[for] { cursor: pointer; }

.evitement {
  position: absolute; left: 16px; top: -100px; z-index: 999;
  background: var(--encre); color: #FFF; padding: 14px 22px;
  border-radius: var(--r-sm); transition: transform var(--vite);
}
.evitement:focus { transform: translateY(116px); }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

/* ─── TYPOGRAPHIE ────────────────────────────────────────── */
h1, h2, h3, h4 { line-height: 1.1; letter-spacing: -0.03em; font-weight: 800; text-wrap: balance; }
h1 { font-size: var(--t-3xl); letter-spacing: -0.04em; }
h2 { font-size: var(--t-2xl); }
h3 { font-size: var(--t-lg); letter-spacing: -0.02em; line-height: 1.3; }

.geant { font-size: var(--t-4xl); line-height: 1.02; letter-spacing: -0.045em; font-weight: 800; }
.sur-titre {
  display: inline-flex; align-items: center; gap: 10px;
  font: 700 var(--t-xs)/1 var(--mono);
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--bleu);
}
/* Le numéro de section, séparé par un filet — la signature d'OWDT. */
.sur-titre__num { display: inline-flex; align-items: center; gap: 10px; }
.sur-titre__num::after {
  content: ''; width: 26px; height: 1.5px; background: currentColor; opacity: 0.55;
}
.chapo { font-size: var(--t-lg); line-height: 1.55; color: var(--attenue); max-width: 52ch; text-wrap: pretty; }
.corps { color: var(--attenue); max-width: 68ch; text-wrap: pretty; }
.corps + .corps { margin-top: 0.85em; }
.corps strong, .chapo strong { color: var(--encre); font-weight: 700; }
.souligne { box-shadow: inset 0 -0.34em 0 var(--cta-pale); }

/* ─── STRUCTURE ──────────────────────────────────────────── */
.cadre { width: 100%; max-width: var(--large); margin-inline: auto; padding-inline: var(--marge); }
.bloc { padding-block: clamp(var(--e8), 8vw, var(--e10)); }
.bloc--serre { padding-block: clamp(var(--e7), 5vw, var(--e8)); }
.bloc--nuit {
  background: var(--nuit); color: #FFF;
  --encre: #FFFFFF; --attenue: var(--sur-nuit); --filet: var(--filet-nuit);
  --carte: #16233A; --bleu: var(--bleu-clair);
}
.bloc--bleu { background: var(--bleu-pale); }

.entete { max-width: 62ch; margin-bottom: clamp(var(--e6), 4vw, var(--e8)); }
.entete .sur-titre { display: block; margin-bottom: var(--e3); }
.entete h2 { margin-bottom: var(--e4); }

/* ─── EN-TÊTE ────────────────────────────────────────────────
   Reprise de la barre du premier site : un bandeau sombre en haut,
   puis une pastille flottante arrondie et centrée, avec un menu
   déroulant par métier. La hauteur du bandeau est mesurée par le
   script et injectée en variable — une valeur écrite en dur laisse
   toujours un filet de page visible entre les deux barres.
   ─────────────────────────────────────────────────────────── */
.topbar {
  position: relative; z-index: 1001;
  background: var(--nuit); color: #9FB3C8;
  padding: 7px max(var(--marge), calc((100% - var(--large)) / 2));
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--e4); flex-wrap: wrap;
  font-family: var(--mono); font-size: var(--t-xs);
  letter-spacing: 0.1em; text-transform: uppercase;
}
.topbar a { color: #DCE7F2; }
.topbar a:hover { color: var(--bleu-clair); }
.topbar__nav, .topbar__links { display: flex; gap: var(--e5); align-items: center; flex-wrap: wrap; }
.topbar__links a:last-child { color: #FF9E7A; font-weight: 600; }
@media (max-width: 860px) { .topbar__promo { display: none; } }
@media (max-width: 640px) { .topbar__nav { display: none; } }

.tete {
  position: fixed; z-index: 1000;
  top: calc(var(--h-bandeau, 34px) + 12px);
  left: 50%; transform: translateX(-50%);
  width: min(1240px, calc(100% - 2 * var(--marge)));
  padding: 12px 12px 12px var(--e5);
  display: flex; align-items: center; gap: var(--e4);
  background: var(--carte);
  border: 1px solid var(--filet);
  border-radius: var(--r-full);
  box-shadow: 0 20px 44px -20px rgba(2, 6, 23, 0.24), 0 2px 8px rgba(2, 6, 23, 0.05);
  transition: box-shadow var(--pose), transform var(--pose);
}
/* Au défilement le bandeau est parti : la pastille prend sa place. */
.tete[data-defile="oui"] {
  transform: translateX(-50%) translateY(calc(-1 * var(--h-bandeau, 34px)));
  box-shadow: 0 26px 54px -22px rgba(2, 6, 23, 0.30), 0 3px 10px rgba(2, 6, 23, 0.08);
}
/* La page démarre sous la pastille. */
.heros { padding-top: calc(var(--h-bandeau, 34px) + 92px); }

.marque { display: inline-flex; align-items: center; gap: 10px; flex: none; min-height: 44px; }
.marque svg { height: 30px; width: auto; }

/* ── Diaphragme animé ─────────────────────────────────────────────
   L'obturateur fait un tour complet, pas 60°. La symétrie
   géométrique des six lames est bien à 60°, mais chacune porte une
   couleur différente : à 60° le dégradé a tourné d'un cran et le logo
   ne retombe PAS sur lui-même. Il sauterait au relâchement du survol.
   360° est la seule valeur qui revient exactement à l'état de départ.

   transform-box: view-box place le repère de la transformation sur
   le viewBox du SVG, ce qui permet de tourner autour de son centre
   (100 100). Sans cette ligne, chaque lame pivoterait autour de sa
   propre boîte et le diaphragme exploserait.

   Tout est en CSS : le mot ENGIN reste lisible pendant l'animation,
   et rien ne dépend du script. */
/* ── Rotation continue ────────────────────────────────────────────
   Portée par le SVG, pas par les lames. C'est ce qui évite le
   conflit : la rotation lente vit sur le parent, l'obturateur du
   survol vit sur les enfants, et les deux se composent au lieu de
   s'écraser. Sur un même élément, la seconde animation aurait repris
   la main et le logo aurait sauté au relâchement.

   Un tour en 34 s, soit 10,6°/s : sur un logo de 30 px, le mouvement
   se sent sans se voir. Il se met en pause au survol pour laisser
   l'obturateur se lire, et parce que WCAG 2.2.2 demande un moyen
   d'interrompre tout mouvement de plus de cinq secondes. */
.diaphragme { animation: diaph-tour 34s linear infinite; }
.marque:hover .diaphragme,
.marque:focus-visible .diaphragme { animation-play-state: paused; }
@keyframes diaph-tour { to { transform: rotate(360deg); } }

.diaphragme .lame {
  transform-box: view-box;
  transform-origin: 100px 100px;
  animation: lame-ouverture 0.7s cubic-bezier(0.22, 1, 0.36, 1) both;
  animation-delay: calc(var(--i) * 55ms);
}
@keyframes lame-ouverture {
  from { transform: rotate(-40deg) scale(0.5); opacity: 0; }
  to   { transform: rotate(0deg) scale(1); opacity: 1; }
}

.marque:hover .diaphragme .lame,
.marque:focus-visible .diaphragme .lame {
  animation: lame-obturateur 0.85s cubic-bezier(0.65, 0, 0.35, 1) both;
  animation-delay: calc(var(--i) * 22ms);
}
@keyframes lame-obturateur {
  0%   { transform: rotate(0deg) scale(1); }
  38%  { transform: rotate(132deg) scale(0.72); }
  100% { transform: rotate(360deg) scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  .diaphragme,
  .diaphragme .lame,
  .marque:hover .diaphragme .lame,
  .marque:focus-visible .diaphragme .lame { animation: none; }
}
.marque__nom { font-weight: 800; font-size: 1.15rem; letter-spacing: -0.04em; }

.tete__nav { flex: 1; display: flex; align-items: center; gap: var(--e4); justify-content: flex-end; }
.menu { margin-inline: auto; display: flex; align-items: center; gap: clamp(10px, 1.6vw, 26px); }

.nav-cat { position: relative; }
.nav-cat__btn {
  position: relative; display: inline-flex; align-items: center; gap: 5px;
  min-height: 40px; padding-block: 6px;
  font-size: var(--t-sm); font-weight: 600; color: var(--attenue);
  transition: color var(--vite);
}
.nav-cat__btn::after {
  content: ''; position: absolute; left: 0; right: 18px; bottom: 2px;
  height: 2px; background: var(--cta);
  transform: scaleX(0); transform-origin: 0 50%;
  transition: transform 0.34s var(--sortie);
}
.nav-cat__btn:hover, .nav-cat[data-ouvert="true"] .nav-cat__btn { color: var(--encre); }
.nav-cat__btn:hover::after, .nav-cat[data-ouvert="true"] .nav-cat__btn::after { transform: scaleX(1); }
.nav-cat__chev { width: 14px; height: 14px; transition: transform var(--vite); }
.nav-cat[data-ouvert="true"] .nav-cat__chev { transform: rotate(180deg); }

.nav-panneau {
  position: absolute; left: 0; top: calc(100% + 16px); z-index: 60;
  width: min(340px, 86vw);
  background: var(--carte); border: 1px solid var(--filet);
  border-radius: var(--r-md); padding: var(--e4);
  box-shadow: 0 30px 60px -20px rgba(2, 6, 23, 0.26), 0 3px 10px rgba(2, 6, 23, 0.06);
}
.nav-panneau[hidden] { display: none; }
.nav-cat:last-of-type .nav-panneau { left: auto; right: 0; }
.nav-panneau__intro {
  font-size: var(--t-xs); color: var(--attenue); line-height: 1.5;
  padding-bottom: var(--e3); margin-bottom: var(--e2);
  border-bottom: 1px solid var(--filet);
}
.nav-panneau__liste { display: flex; flex-direction: column; gap: 2px; }
.nav-item {
  display: grid; gap: 1px; padding: 9px 10px; border-radius: var(--r-sm);
  transition: background-color var(--vite);
}
.nav-item:hover { background: var(--fond); }
.nav-item__nom { font-size: var(--t-sm); font-weight: 600; }
.nav-item__sub { font-size: var(--t-xs); color: var(--attenue); }
.nav-item--tete { background: var(--bleu-pale); margin-bottom: var(--e2); }
.nav-item--tete .nav-item__nom { color: var(--bleu); }

.nav-cta {
  display: inline-flex; align-items: center; min-height: 40px;
  background: var(--cta); color: #FFFFFF;
  border-radius: var(--r-full); padding: 9px 18px;
  font-weight: 700; font-size: var(--t-xs);
  transition: background-color var(--vite);
}
.nav-cta:hover { background: var(--cta-sombre); }

.tete__outils { display: flex; align-items: center; gap: var(--e2); flex: none; }
.pastille {
  display: inline-flex; align-items: center; min-height: 36px;
  border: 1px solid var(--filet-fort); border-radius: var(--r-sm);
  padding: 6px 11px; font: 600 var(--t-xs)/1.2 var(--mono);
  letter-spacing: 0.12em; text-transform: uppercase;
  transition: background-color var(--vite), color var(--vite), border-color var(--vite);
}
.pastille:hover { background: var(--bleu); color: #FFFFFF; border-color: var(--bleu); }

.burger {
  display: none; flex-direction: column; justify-content: space-between;
  width: 26px; height: 17px;
}
.burger span { display: block; width: 100%; height: 2px; border-radius: 2px; background: var(--encre);
               transition: transform 0.35s var(--sortie), opacity var(--vite); }
.burger[aria-expanded="true"] span:nth-child(1) { transform: translateY(7.5px) rotate(45deg); }
.burger[aria-expanded="true"] span:nth-child(2) { opacity: 0; transform: scaleX(0); }
.burger[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7.5px) rotate(-45deg); }

.tiroir {
  display: none; position: fixed; inset: 0; z-index: 999;
  background: var(--fond); overflow-y: auto;
  flex-direction: column; align-items: center; justify-content: center; gap: var(--e2);
  padding: var(--e8) var(--marge);
  opacity: 0; pointer-events: none; transition: opacity var(--pose);
}
.tiroir[data-ouvert="oui"] { opacity: 1; pointer-events: auto; }
.tiroir a { font-size: var(--t-lg); font-weight: 700; letter-spacing: -0.025em; min-height: 44px;
            display: inline-flex; align-items: center; }
.tiroir a:hover { color: var(--bleu); }
.tiroir__cat { font: 700 var(--t-xs)/1 var(--mono); letter-spacing: 0.14em;
               text-transform: uppercase; color: var(--attenue); margin-top: var(--e5); }

/* La mesure a donné 1068 px de contenu : en dessous de 1180 px la
   pastille déborderait, on bascule donc sur le menu plein écran. */
@media (max-width: 1180px) {
  .menu { display: none; }
  .burger { display: flex; }
  .tiroir { display: flex; }
}

/* ─── BOUTONS ────────────────────────────────────────────── */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  min-height: 48px; padding: 13px 24px; border-radius: var(--r-full);
  font-size: var(--t-sm); font-weight: 700; letter-spacing: -0.01em;
  border: 2px solid transparent; white-space: nowrap;
  transition: background-color var(--vite), border-color var(--vite),
              color var(--vite), transform var(--vite), box-shadow var(--vite);
}
.btn svg { width: 16px; height: 16px; flex: none; transition: transform var(--pose); }
.btn:hover svg { transform: translateX(3px); }
.btn--action {                    /* l'accent est réservé à ceci */
  background: var(--cta); color: #FFF; border-color: var(--cta);
  box-shadow: var(--ombre-2);
  position: relative; overflow: hidden; isolation: isolate;
  --lueur: 255, 92, 43;
  animation: btn-halo 5s ease-in-out infinite;
}
.btn--action:hover { background: var(--cta-sombre); border-color: var(--cta-sombre); box-shadow: var(--ombre-3); }

/* ── Halo et balayage sur le bouton d'action ──────────────────────
   Porté du composant React « CosmicGlowButton ». Deux écarts, tous
   deux imposés par la mesure plutôt que par le goût :

   · Le balayage conique passe SOUS le libellé, donc il change son
     contraste. À 22 % d'un blanc — la valeur du composant d'origine
     — le blanc du texte tombe à 3,78:1 sur le CTA. La teinte du halo
     est donc un orange de la même famille, #FF5C2B, et le balayage
     est à 0,20 : le blanc tient 4,76:1.
   · Le halo n'est pas un élément flouté mais une ombre portée.
     overflow:hidden est nécessaire pour découper le balayage à la
     forme de la pilule, et il rognerait un élément posé autour ;
     une box-shadow, elle, se dessine hors de la boîte et échappe au
     rognage.

   Réservé à .btn--action : un halo sur tous les boutons détruirait
   la hiérarchie qu'il est censé servir. */
.btn--action > * { position: relative; z-index: 1; }
.btn--action::before {
  content: ''; position: absolute; z-index: 0; pointer-events: none;
  top: 50%; left: 50%; width: 240%; aspect-ratio: 1; translate: -50% -50%;
  background: conic-gradient(from 90deg at 50% 50%,
              transparent 0deg, rgb(var(--lueur)) 120deg, transparent 240deg);
  opacity: 0.20;
  animation: btn-balayage 5s linear infinite;
}
/* Au survol l'animation cède la main : une ombre animée l'emporte sur
   toute déclaration normale, y compris celle du :hover. */
.btn--action:hover {
  animation: none;
  box-shadow: var(--ombre-3), 0 0 26px 5px rgba(var(--lueur), 0.45);
}
.btn--action:hover::before { animation-duration: 2.4s; }

@keyframes btn-balayage { to { rotate: 360deg; } }
@keyframes btn-halo {
  0%, 100% { box-shadow: var(--ombre-2), 0 0 0 0 rgba(var(--lueur), 0); }
  50%      { box-shadow: var(--ombre-2), 0 0 24px 4px rgba(var(--lueur), 0.38); }
}
@media (prefers-reduced-motion: reduce) {
  .btn--action, .btn--action::before, .btn--action:hover::before { animation: none; }
  .btn--action::before { opacity: 0.14; }
}
.btn--calme { background: var(--carte); color: var(--encre); border-color: var(--filet-fort); }
.btn--calme:hover { border-color: var(--encre); }
.btn--nu { padding-inline: 6px; color: var(--bleu); }
.btn--nu:hover { color: var(--encre); }
.bloc--nuit .btn--calme { background: transparent; color: #FFF; border-color: rgba(255,255,255,0.42); }
.bloc--nuit .btn--calme:hover { border-color: #FFF; }

.duo-btn { display: flex; flex-wrap: wrap; gap: var(--e3); }

/* ─── HÉROS — bandeau inséré à découpe diagonale ───────────
   Le bloc de couleur ne touche pas les bords : il est inséré dans la
   gouttière, arrondi, et son bord bas est coupé en biais. C'est cette
   coupe qui fait l'accroche — une bande rectangulaire pleine largeur
   ne se remarque pas.
   Le fond coloré vit dans un élément à part, découpé au clip-path ;
   le contenu, lui, n'est pas découpé et peut donc déborder de la
   diagonale, ce que font les mockups.
   ─────────────────────────────────────────────────────────── */
.heros { position: relative; padding-block: var(--e5) 0; }

.bandeau {
  position: relative; isolation: isolate;
  display: grid; grid-template-columns: minmax(0, 0.74fr) minmax(0, 1.26fr);
  gap: clamp(var(--e4), 2vw, var(--e6));
  align-items: center;
  padding: clamp(var(--e6), 5vw, var(--e9)) clamp(var(--e5), 4vw, var(--e8));
  padding-bottom: clamp(var(--e8), 11vw, 250px);  /* place pour la diagonale et les mockups */
  color: #FFFFFF;
}
.bandeau__fond {
  position: absolute; inset: 0; z-index: -1;
  /* Sombre à gauche — sous le texte — clair à droite, derrière les
     mockups. #0369A1 est la teinte la plus claire sur laquelle du
     blanc tient encore 4,5:1 ; le dégradé ne va jamais au-delà dans
     la zone de texte. */
  background: linear-gradient(112deg, #0B3C63 0%, #075985 34%, #0369A1 68%, #0284C7 100%);
  border-radius: var(--r-lg);
  /* Bord bas en biais : le coin gauche remonte, le droit descend. */
  clip-path: polygon(0 0, 100% 0, 100% 100%, 0 84%);
}
.bandeau__fond::after {
  content: ''; position: absolute; inset: auto -10% -6% -6%; height: 66%;
  background: radial-gradient(ellipse at 22% 100%, rgba(2, 6, 23, 0.42), transparent 60%);
  pointer-events: none;
}

/* Rayons, comme sur la référence : ils tournent très lentement
   derrière le visuel et signent le bloc sans rien encombrer. */
/* Le canvas épouse exactement la forme du dégradé : mêmes rayon et
   même découpe en biais, sinon un coin du plasma dépasserait. Il naît
   transparent ; le script le révèle une fois la première image tirée. */
.bandeau__shader {
  position: absolute; inset: 0; z-index: -1; display: block;
  width: 100%; height: 100%; pointer-events: none;
  border-radius: var(--r-lg);
  clip-path: polygon(0 0, 100% 0, 100% 100%, 0 84%);
  opacity: 0; transition: opacity 1.1s ease-out;
}
.bandeau__shader[data-vu] { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .bandeau__shader { display: none; } }

.bandeau__rayons {
  position: absolute; z-index: -1; pointer-events: none;
  right: 4%; top: 6%; width: clamp(280px, 34vw, 520px); aspect-ratio: 1;
  color: rgba(255, 255, 255, 0.5);
  animation: tourne 90s linear infinite;
}
.bandeau__rayons svg { width: 100%; height: 100%; }
@keyframes tourne { to { transform: rotate(360deg); } }

.bandeau__texte { display: grid; justify-items: start; gap: var(--e5); position: relative; z-index: 2; }
.heros__titre {
  font-size: clamp(1.8rem, 0.6rem + 2.8vw, 3rem);
  line-height: 1.08; letter-spacing: -0.04em; font-weight: 800;
  max-width: 100%; color: #FFFFFF;
  /* Une hauteur minimale réservée : le segment retapé change de
     longueur en permanence, et sans cette réserve tout le bloc
     sauterait d'une ligne à chaque cycle. */
  min-height: calc(4 * 1.08em);   /* quatre lignes réservées */
}
.heros__titre .ligne {
  display: block; overflow: hidden;
  padding-bottom: 0.1em; margin-bottom: -0.1em;
}
.heros__titre .ligne > span { display: block; will-change: transform; }

/* Le segment que la machine à écrire retape. Il est en italique et
   plus clair : 5,17:1 au pire endroit du dégradé, 9,94:1 au meilleur. */
/* Le segment retapé. Pas de `nowrap` : mesuré, il faisait déborder
   toutes les variantes hors de la colonne, droit sous le mockup.
   Le point reste collé à son mot de toute façon — aucune espace ne
   les sépare — donc il ne peut pas partir seul à la ligne. */
.heros__titre em { font-style: italic; color: #E0F2FE; font-weight: 700; }


/* Trait dessiné sous un mot du titre. Le SVG est en position absolue
   pour ne pas participer au flux : il ne peut pas décaler la ligne. */
.mot-souligne { position: relative; text-decoration: none; display: inline-block; }
.trait-titre {
  position: absolute; left: -2%; right: -2%; bottom: -0.14em;
  width: 104%; height: 0.3em; overflow: visible;
  /* Le vermillon de la marque tombe à 1,22:1 sur le bandeau bleu :
     il serait invisible. Un trait est un élément graphique, seuil
     3:1 — cet ambre tient 4,51:1 au pire endroit du dégradé. */
  color: #FCD34D;
}
/* Sur fond clair, le trait reprend le vermillon de la marque. */
.bloc:not(.bloc--nuit) .trait-titre { color: var(--cta); }

.heros .dispo {
  background: rgba(255, 255, 255, 0.14); border-color: rgba(255, 255, 255, 0.30);
  color: #FFFFFF; backdrop-filter: blur(6px);
}

/* Étiquettes en pastilles, comme sur la référence — mais cliquables :
   ce sont les quatre métiers, autant qu'elles mènent quelque part. */
.etiquettes { display: flex; flex-wrap: wrap; gap: var(--e2); position: relative; z-index: 4; }
.etiquettes a {
  display: inline-flex; align-items: center; gap: 8px; min-height: 44px;
  padding: 10px 18px; border-radius: var(--r-full);
  background: #FFFFFF; color: #0B3C63;
  font-size: var(--t-sm); font-weight: 700; white-space: nowrap;
  box-shadow: 0 6px 14px rgba(2, 6, 23, 0.18);
  transition: transform var(--vite), box-shadow var(--vite), color var(--vite);
}
.etiquettes svg { width: 13px; height: 13px; transition: transform var(--pose); }
.etiquettes a:hover { transform: translateY(-2px); box-shadow: 0 10px 22px rgba(2,6,23,0.26); color: var(--cta-sombre); }
.etiquettes a:hover svg { transform: translateX(3px); }

/* Les mockups débordent la diagonale, en bas à droite. Ils ne
   dépassent JAMAIS vers la gauche : c'est ce débordement qui les
   faisait passer par-dessus les pastilles. */
.bandeau__visuel { position: relative; z-index: 2; min-width: 0; }
.scene {
  position: relative;
  /* Boîte de scène à ratio fixe : les deux appareils sont posés en
     absolu dedans, ce qui rend la composition indépendante de la
     hauteur des images. Le débord reste borné en pixels — un
     pourcentage grandit avec l'écran et finit par sortir de la page.
     Vérifié de 1280 à 3440 px : 19 px de marge au pire. */
  width: calc(100% + clamp(24px, 7.5vw, 240px));
  aspect-ratio: 1.28;
}
.scene figure { position: absolute; margin: 0; }
/* Le portable est détouré : plus de plan de bureau gris en rectangle. */
.scene__pc  { left: 0;  bottom: 16%; width: 80%;
              filter: drop-shadow(0 46px 64px rgba(2, 6, 23, 0.42)); }
/* Le téléphone domine et déborde sous la scène : la marge basse du
   bandeau (158 px à 1440) absorbe les 12 % de dépassement. */
.scene__tel { right: 0; bottom: -12%; width: 58%;
              filter: drop-shadow(0 40px 60px rgba(2, 6, 23, 0.5)); }
.scene figure img { width: 100%; height: auto; display: block; }

@media (max-width: 900px) {
  .scene { aspect-ratio: 1.18; }
  .scene__pc  { width: 82%; bottom: 18%; }
  .scene__tel { width: 54%; bottom: -8%; }
}

.sous-bandeau {
  display: grid; gap: var(--e5); justify-items: start;
  padding-top: clamp(var(--e6), 4vw, var(--e7));
  /* Les cartes de réassurance suivent maintenant les boutons : la
     marge basse leur revient, sinon elles collent au panneau des
     tarifs et semblent lui appartenir. */
  padding-bottom: clamp(var(--e5), 3vw, var(--e6));
  max-width: 68ch;
}
.heros__chapo { color: var(--attenue); }
/* Retours à la ligne voulus dans l'accroche. Ils disparaissent sous
   720 px : à cette largeur le texte se replie déjà tout seul, et une
   coupure forcée y laisserait une ligne orpheline. */
.saut-ligne { display: none; }
@media (min-width: 721px) { .saut-ligne { display: inline; } }

/* ─── Les trois engagements, mis en cartes ─────────────────
   Ils remontent sur la diagonale du bandeau : c'est ce chevauchement
   qui les met en valeur, bien plus qu'une bordure. Chacun sa couleur,
   texte blanc — les trois paires tiennent entre 5,9 et 7,6:1. */
.heros .credit {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(var(--e3), 1.4vw, var(--e4));
  /* Plus de remontée : les cartes passaient par-dessus l'accroche et
     coupaient sa dernière ligne. Elles suivent le bandeau, à quoi
     leur couleur suffit à les rattacher. */
  margin-top: clamp(var(--e4), 2vw, var(--e5));
  position: relative; z-index: 3;
  margin-bottom: clamp(var(--e7), 6vw, var(--e9));
}
.credit__carte {
  border-radius: var(--r-md);
  padding: clamp(var(--e4), 2.2vw, var(--e6));
  color: #FFFFFF;
  display: grid; align-content: start; gap: 6px;
  box-shadow: 0 18px 34px -14px rgba(2, 6, 23, 0.34), 0 3px 8px rgba(2, 6, 23, 0.10);
  transition: transform var(--pose), box-shadow var(--pose);
}
.credit__carte:hover {
  transform: translateY(-4px);
  box-shadow: 0 26px 46px -16px rgba(2, 6, 23, 0.40), 0 4px 10px rgba(2, 6, 23, 0.12);
}
.credit__carte--1 { background: linear-gradient(150deg, #0B4F7E 0%, #075985 100%); }  /* 7,56:1 */
.credit__carte--2 { background: linear-gradient(150deg, #C13410 0%, #A82A0C 100%); }  /* 7,00:1 */
.credit__carte--3 { background: linear-gradient(150deg, #197C3D 0%, #146C34 100%); }  /* 6,51:1 */

/* Un filet clair en haut de chaque carte : il attrape la lumière et
   décolle la carte du fond, comme les tuiles de la constellation. */
.credit__carte { position: relative; overflow: hidden; }

/* Un filet clair en haut de chaque carte : il attrape la lumière et
   décolle la carte du fond, comme les tuiles de la constellation. */
.credit__carte::before {
  content: ''; position: absolute; inset: 0 0 auto; height: 1px;
  background: rgba(255, 255, 255, 0.42);
}

.heros .credit__val {
  font-size: clamp(1.9rem, 1rem + 2.2vw, 3rem);
  font-weight: 800; letter-spacing: -0.045em; line-height: 1; color: #FFFFFF;
}
/* 14 px pour une ligne de réassurance, c'était trop petit : c'est
   elle qui explique le chiffre, pas l'inverse. Blanc plein plutôt
   qu'à 90 % — le gain de contraste est gratuit. */
.heros .credit__lab { color: #FFFFFF; font-size: var(--t-md); line-height: 1.45; }

@media (max-width: 1180px) {
  .bandeau { grid-template-columns: 1fr; padding-bottom: clamp(var(--e7), 12vw, 150px); }
  .heros__titre { min-height: 0; }
  .bandeau__fond { clip-path: polygon(0 0, 100% 0, 100% 100%, 0 92%); }
  .bandeau__rayons { right: -8%; top: -4%; opacity: 0.6; }
  .scene { width: 100%; margin-bottom: clamp(-90px, -8vw, -40px);
           display: flex; align-items: flex-end; gap: var(--e3); }
  .scene__pc { width: 70%; }
  .scene__tel { position: static; width: 28%; }
}
@media (max-width: 620px) {
  .heros .credit { grid-template-columns: 1fr; margin-top: var(--e5); }
  .etiquettes a { padding: 10px 14px; }
}
@media (prefers-reduced-motion: reduce) { .bandeau__rayons { animation: none; } }

/* ─── PREUVE ─────────────────────────────────────────────── */
.preuve { display: grid; gap: var(--e5); grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.preuve__item {
  background: var(--carte); border: 1px solid var(--filet); border-radius: var(--r-md);
  padding: var(--e5); box-shadow: var(--ombre-1);
}
.preuve__val { font-size: var(--t-2xl); font-weight: 800; letter-spacing: -0.04em; line-height: 1; color: var(--bleu); }
.preuve__lab { color: var(--attenue); font-size: var(--t-sm); margin-top: var(--e2); }

/* ─── FUNNEL : trois étapes ──────────────────────────────── */
.etapes-f { display: grid; gap: var(--e5); grid-template-columns: repeat(3, 1fr); counter-reset: ef; }
@media (max-width: 900px) { .etapes-f { grid-template-columns: 1fr; } }
.etape-f {
  position: relative; background: var(--carte); border: 1px solid var(--filet);
  border-radius: var(--r-md); padding: var(--e6);
  display: grid; gap: var(--e3); align-content: start;
  box-shadow: var(--ombre-1);
  transition: transform var(--pose), box-shadow var(--pose), border-color var(--vite);
}
.etape-f:hover { transform: translateY(-3px); box-shadow: var(--ombre-2); border-color: var(--filet-fort); }
.etape-f__num {
  display: inline-grid; place-items: center; width: 40px; height: 40px; border-radius: 50%;
  font: 800 var(--t-sm)/1 var(--police); color: #FFF; background: var(--encre);
}
.etape-f--1 .etape-f__num { background: var(--cta); }
.etape-f--2 .etape-f__num { background: var(--or); }
.etape-f--3 .etape-f__num { background: var(--succes); }
.etape-f h3 { margin-top: var(--e2); }
.etape-f__mini {
  display: inline-flex; align-items: center; gap: 7px; min-height: 44px;
  color: var(--bleu); font-weight: 700; font-size: var(--t-sm); margin-top: auto;
}
.etape-f__mini svg { width: 15px; height: 15px; transition: transform var(--pose); }
.etape-f:hover .etape-f__mini svg { transform: translateX(3px); }

.symptomes { display: grid; gap: var(--e3); margin-top: var(--e5); }
.symptome { display: grid; grid-template-columns: 22px 1fr; gap: var(--e3); align-items: start; color: var(--attenue); }
.symptome svg { width: 20px; height: 20px; color: var(--cta); margin-top: 2px; }

/* ─── SERVICES ───────────────────────────────────────────── */
/* Sous 1101 px, auto-fit donne déjà 3 colonnes : la règle ci-dessous
   ne change donc rien pour ces tailles, elle empêche seulement la
   quatrième colonne d'apparaître entre 1392 et 1600 px. Cinq services
   s'y affichaient en 4 + 1, puis en 3 + 2 au-delà — la même page
   changeait de forme selon la fenêtre. */
.services { display: grid; gap: var(--e5); grid-template-columns: repeat(auto-fit, minmax(270px, 1fr)); }
@media (min-width: 1101px) { .services { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

/* ─── Les cinq métiers sur l'accueil ──────────────────────────────
   Grille à gauche, discours à droite. Le discours est écrit en
   premier dans le balisage — un titre doit précéder les liens qu'il
   annonce — et « order » le renvoie à droite à l'écran. Sous 900 px
   tout repasse en colonne, discours d'abord. */
.offre { display: grid; gap: clamp(var(--e6), 4vw, var(--e8));
         grid-template-columns: minmax(0, 1fr) minmax(0, 0.92fr);
         align-items: center; }
.offre > * { min-width: 0; }
.offre__dire  { order: 2; }
/* Le titre géant monte à 104 px : « interlocuteur » ferait alors
   608 px dans une colonne qui en offre 492. On le ramène à 51 px,
   ce qui laisse 298 px au mot le plus long. */
.offre__dire .titre-geant { font-size: clamp(1.9rem, 3.4vw, 3.2rem);
                            line-height: 1.02; max-width: 17ch; }
.offre__dire .corps { max-width: 46ch; }
.offre__grille { order: 1; display: grid; gap: var(--e4);
                 grid-template-columns: repeat(2, minmax(0, 1fr)); }
/* Cinq cartes dans deux colonnes : la dernière prend la ligne entière
   plutôt que de laisser un vide. */
.offre__grille > :last-child { grid-column: 1 / -1; }

.svc {
  display: flex; flex-direction: column; gap: var(--e2);
  padding: clamp(var(--e4), 1.6vw, var(--e5));
  background: var(--carte); border: 1px solid var(--filet);
  border-radius: var(--r-md); box-shadow: var(--ombre-1);
  transition: transform var(--pose), box-shadow var(--pose), border-color var(--vite);
}
.svc:hover { transform: translateY(-4px); box-shadow: var(--ombre-3); border-color: var(--bleu); }
.svc__ico { color: var(--bleu); margin-bottom: var(--e1); }
.svc__ico svg { width: 30px; height: 30px; display: block; transition: transform var(--pose); }
.svc:hover .svc__ico svg { transform: translateY(-2px) scale(1.09); }

/* ── Décor de la chorégraphie ─────────────────────────────────────
   Deux couches purement décoratives, invisibles au repos, que le
   script anime. Elles ne portent aucun contenu : si le script ne
   tourne pas, la carte reste exactement ce qu'elle est. */
.svc { position: relative; overflow: hidden; }
/* La lame est exclue : elle doit rester absolue sous le contenu. */
.svc > :not(.svc__lame) { position: relative; z-index: 1; }

/* Le reflet suit le pointeur, via deux variables posées en JS. */
.svc::after {
  content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  opacity: 0; transition: opacity var(--vite);
  background: radial-gradient(240px circle at var(--mx, 50%) var(--my, 50%),
              rgba(3, 105, 161, 0.13), transparent 62%);
}
.svc:hover::after, .svc:focus-visible::after { opacity: 1; }
/* Le survol est repris par le script au pointeur ; au clavier il n'y
   a pas de pointeur, donc le relief doit venir de la CSS. */
.svc:focus-visible { box-shadow: var(--ombre-3); border-color: var(--bleu); }
.svc:focus-visible .svc__ico svg { transform: translateY(-2px) scale(1.09); }

/* La lame de lumière qui traverse la carte à l'assemblage. */
.svc__lame {
  position: absolute; top: -20%; left: -55%; width: 42%; height: 140%;
  z-index: 0; pointer-events: none; opacity: 0;
  transform: skewX(-16deg);
  background: linear-gradient(100deg, transparent,
              rgba(56, 189, 248, 0.42), rgba(255, 255, 255, 0.5), transparent);
}

@media (prefers-reduced-motion: reduce) {
  .svc, .svc__ico svg { transition: none; }
  .svc:hover { transform: none; }
  .svc:hover .svc__ico svg { transform: none; }
  .svc::after, .svc__lame { display: none; }
}
.svc__titre { font-size: var(--t-md); font-weight: 700; letter-spacing: -0.015em; }
.svc__texte { color: var(--attenue); font-size: var(--t-sm); line-height: 1.55; }

/* ── Ce qui dit « c'est un lien » ─────────────────────────────────
   Une carte au fond blanc avec un titre et un texte ressemble à un
   encadré d'information. Trois signaux la rendent cliquable :
   le prix — qui est aussi la raison de cliquer —, une flèche
   toujours visible, et un titre qui se souligne à l'approche. */
.svc > * { min-width: 0; }
.svc__pied {
  margin-top: auto; padding-top: var(--e4);
  border-top: 1px solid var(--filet);
  display: flex; align-items: center; justify-content: space-between; gap: var(--e3);
}
.svc__prix {
  font-size: var(--t-sm); font-weight: 700; color: var(--bleu);
  letter-spacing: -0.01em;
}
.svc__fleche {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: 50%; flex: none;
  border: 1px solid var(--filet); color: var(--bleu);
  transition: background-color var(--vite), border-color var(--vite),
              color var(--vite), transform var(--pose);
}
.svc__fleche svg { width: 16px; height: 16px; }
.svc:hover .svc__fleche, .svc:focus-visible .svc__fleche {
  background: var(--bleu); border-color: var(--bleu); color: #FFFFFF;
  transform: translateX(3px);
}
.svc__titre { text-decoration: underline 2px transparent; text-underline-offset: 4px;
              transition: text-decoration-color var(--vite); }
.svc:hover .svc__titre, .svc:focus-visible .svc__titre { text-decoration-color: var(--bleu); }
@media (prefers-reduced-motion: reduce) {
  .svc__fleche, .svc__titre { transition: none; }
  .svc:hover .svc__fleche { transform: none; }
}

@media (max-width: 900px) {
  .offre { grid-template-columns: 1fr; }
  .offre__dire { order: 1; } .offre__grille { order: 2; }
}
@media (max-width: 520px) { .offre__grille { grid-template-columns: 1fr; } }
.service {
  background: var(--carte); border: 1px solid var(--filet); border-radius: var(--r-md);
  overflow: hidden; display: flex; flex-direction: column;
  box-shadow: var(--ombre-1);
  transition: transform var(--pose), box-shadow var(--pose), border-color var(--vite);
}
.service:hover { transform: translateY(-4px); box-shadow: var(--ombre-3); border-color: var(--filet-fort); }
.service__vue { aspect-ratio: 16 / 10; overflow: hidden; background: var(--bleu-pale); }
.service__vue img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.5s var(--sortie); }
.service:hover .service__vue img { transform: scale(1.04); }
/* Même principe : le prix se cale en bas de la carte, sinon il suit
   un chapô de longueur variable. */
.service__corps { padding: var(--e5); display: flex; flex-direction: column; gap: var(--e2); flex: 1; }
.service__titre { font-size: var(--t-lg); font-weight: 700; letter-spacing: -0.02em; }
.service__texte { color: var(--attenue); font-size: var(--t-sm); }
.service__prix { font-size: var(--t-sm); font-weight: 700; color: var(--bleu); margin-top: auto; padding-top: var(--e3); }

/* ─── RÉALISATIONS ───────────────────────────────────────── */
/* Même verrou que pour .services. Sans lui, l'élargissement du cadre
   ferait passer les six études de cas à 4 colonnes entre 1568 et
   2100 px, puis retour à 3 au-delà : la page changerait de forme selon
   la fenêtre. Sous 1101 px, auto-fit donne déjà 3 colonnes ou moins,
   la règle y est donc sans effet. */
.cas { display: grid; gap: var(--e5); grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
@media (min-width: 1101px) { .cas { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
/* Une seule boîte : l'image encadrée d'un côté et le texte nu de
   l'autre donnaient deux objets flottants au lieu d'une carte. Le
   cadre entoure maintenant l'ensemble, l'image vient à fleur de bord
   et le texte respire dans son propre rembourrage. */
.cas__item {
  display: flex; flex-direction: column;
  background: var(--carte); border: 1px solid var(--filet);
  /* le fond de la carte doit s'opposer à celui du panneau : blanc sur
     un fond gris, gris sur le panneau papier qui est blanc. */
  border-radius: var(--r-md); overflow: hidden; box-shadow: var(--ombre-1);
  transition: transform var(--pose), box-shadow var(--pose), border-color var(--vite);
}
.cas__item:hover { transform: translateY(-4px); box-shadow: var(--ombre-3); border-color: var(--bleu-pale); }
.cas__vue { display: block; border-bottom: 1px solid var(--filet); }
.cas__vue img { display: block; width: 100%; aspect-ratio: 16 / 10;
                object-fit: cover; object-position: top center; }
.cas__corps { display: flex; flex-direction: column; flex: 1;
              padding: clamp(var(--e4), 1.8vw, var(--e5)); }
.panneau--papier .cas__item { background: var(--fond); border-color: #D7DEE7; }
.panneau--papier .cas__vue { border-bottom-color: #D7DEE7; }
.panneau--papier .cas__item:hover { background: var(--carte); }
/* Titre puis étiquette empilés : sur une seule ligne partagée,
   « IDENTITÉ ET SITE · NETTOYAGE PROFESSIONNEL » (371 px) débordait
   des 258 px utiles à 1101. Sur sa propre ligne elle passe sur deux
   lignes proprement et garde le métier, qui distingue les projets. */
/* Rythme : l'étiquette colle au titre, le chapô s'en détache, et
   la ligne de lecture est chassée en bas pour aligner les pieds de
   carte quels que soient les chapôs. */
.cas__tag { font: 600 var(--t-xs)/1.3 var(--mono); color: var(--attenue);
            letter-spacing: 0.08em; text-transform: uppercase; margin-bottom: var(--e2); }
.cas__titre { font-size: var(--t-lg); font-weight: 700; letter-spacing: -0.02em;
              margin-bottom: var(--e3); }
.cas__chapo { color: var(--attenue); font-size: var(--t-sm); line-height: 1.65; }
.cas__lire { margin-top: auto; padding-top: var(--e4);
             display: inline-flex; align-items: center; gap: var(--e2);
             font-weight: 700; font-size: var(--t-sm); color: var(--bleu); }
.cas__lire svg { width: 16px; height: 16px; transition: transform var(--vite); }
.cas__item:hover .cas__lire svg { transform: translateX(4px); }

/* ─── TARIFS ─────────────────────────────────────────────── */
.tarifs {
  display: grid; gap: var(--e4); align-items: stretch;
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
@media (max-width: 1100px) { .tarifs { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 720px)  { .tarifs { grid-template-columns: 1fr; } }
.tarif {
  background: var(--carte); border: 1px solid var(--filet); border-radius: var(--r-lg);
  padding: clamp(var(--e5), 3vw, var(--e7)); box-shadow: var(--ombre-1); position: relative;
  /* minmax(0, 1fr) est indispensable : une colonne implicite « auto »
     prend la largeur max-content du plus large enfant. Le bouton étant
     insécable, la colonne gonflait au-delà de la carte et poussait
     paragraphes et listes hors du cadre. */
  /* Colonne flexible plutôt que grille : le bouton peut alors être
     poussé en bas par margin-top:auto, ce qui aligne les trois appels
     à l'action sur une même ligne quelle que soit la longueur des
     listes. min-width:0 remplace le minmax(0,1fr) qui empêchait un
     enfant insécable d'élargir la carte. */
  display: flex; flex-direction: column; gap: var(--e4);
}
.tarif > * { min-width: 0; }
.tarif .btn { margin-top: auto; }

/* À trois colonnes le texte se resserre : on descend d'un cran plutôt
   que de laisser les listes se hacher en mots isolés. Placé APRÈS la
   règle de base, sinon il ne s'applique jamais. */
@media (min-width: 1101px) {
  .tarif { padding: clamp(var(--e5), 2.2vw, var(--e6)); }
  .tarif__prix { font-size: var(--t-xl); }
  .tarif__liste li { font-size: var(--t-xs); }
}
.tarif--phare { border-color: var(--bleu); border-width: 2px; box-shadow: var(--ombre-3); }
.tarif__ruban {
  position: absolute; top: -13px; left: clamp(var(--e5), 3vw, var(--e7));
  background: var(--bleu); color: #FFF; border-radius: var(--r-full);
  padding: 5px 14px; font: 700 var(--t-xs)/1.4 var(--police);
}
.tarif__nom { font-size: var(--t-xl); font-weight: 800; letter-spacing: -0.03em; }
.tarif__delai { font: 600 var(--t-xs)/1 var(--mono); letter-spacing: 0.1em; text-transform: uppercase; color: var(--attenue); }
.tarif__prix { font-size: var(--t-2xl); font-weight: 800; letter-spacing: -0.04em; line-height: 1; }
.tarif__prix small { font-size: var(--t-sm); font-weight: 600; color: var(--attenue); letter-spacing: 0; }
.tarif__liste { display: grid; gap: var(--e3); }
.tarif__liste li { display: grid; grid-template-columns: 20px 1fr; gap: var(--e3); align-items: start;
                   font-size: var(--t-sm); color: var(--attenue); }
.tarif__liste svg { width: 18px; height: 18px; color: var(--succes); margin-top: 2px; }
.tarif .btn {
  width: 100%; white-space: normal; text-wrap: balance;
  line-height: 1.3; padding-inline: var(--e4);
  /* Filet de sécurité : si un libellé passait un jour à deux lignes,
     la hauteur commune empêche la carte de se désaligner. */
  min-height: 52px;
}

/* ─── MÉTHODE ────────────────────────────────────────────── */
.methode { display: grid; gap: 0; }
.m-etape {
  display: grid; grid-template-columns: 64px minmax(0, 1fr) minmax(0, 1.3fr);
  gap: var(--e4) var(--e5); padding-block: var(--e5);
  border-top: 1px solid var(--filet); align-items: start;
}
.m-etape:last-child { border-bottom: 1px solid var(--filet); }
.m-num { font: 800 var(--t-lg)/1 var(--police); color: var(--bleu); }

/* ── Fil de la méthode ────────────────────────────────────────────
   Le décor entier est conditionné à [data-fil], que seul le script
   pose. Sans JS, aucune rail n'est dessinée : mieux vaut pas de fil
   du tout qu'un fil vide sur toute la hauteur.

   La rampe passe au centre des pastilles : elles font 40 px dans une
   colonne de 64, donc leur centre est à 20 px et le trait de 2 px se
   place à 19. */
.methode[data-fil] { position: relative; --rempli: 0%; }
.methode[data-fil]::before,
.methode[data-fil]::after {
  content: ''; position: absolute; left: 19px; top: 0; width: 2px;
  border-radius: 2px; pointer-events: none;
}
.methode[data-fil]::before { bottom: 0; background: var(--filet-fort); opacity: 0.4; }
.methode[data-fil]::after  { height: var(--rempli); background: var(--bleu); }

.methode[data-fil] .m-num {
  position: relative; z-index: 1;
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; border-radius: 50%;
  background: var(--carte); border: 2px solid var(--filet-fort);
  transition: background-color var(--vite), border-color var(--vite),
              color var(--vite), transform var(--pose);
}
.methode[data-fil] .m-etape[data-atteint] .m-num {
  background: var(--bleu); border-color: var(--bleu); color: #FFFFFF;
  transform: scale(1.06);
}
@media (max-width: 860px) {
  .methode[data-fil]::before, .methode[data-fil]::after { left: 15px; }
  .methode[data-fil] .m-num { width: 32px; height: 32px; font-size: var(--t-sm); }
}
@media (prefers-reduced-motion: reduce) {
  .methode[data-fil] .m-num { transition: none; }
}
.m-titre { font-size: var(--t-lg); font-weight: 700; letter-spacing: -0.02em; }
.m-delai { font: 600 var(--t-xs)/1 var(--mono); letter-spacing: 0.1em; text-transform: uppercase;
           color: var(--attenue); margin-top: 6px; }
@media (max-width: 860px) { .m-etape { grid-template-columns: 44px 1fr; } .m-etape > p:last-child { grid-column: 2; } }

/* ─── AVIS — jamais masqués ──────────────────────────────── */
.avis { display: grid; gap: var(--e5); grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.avis__carte {
  background: var(--carte); border: 1px solid var(--filet); border-radius: var(--r-md);
  padding: var(--e5); display: grid; gap: var(--e3); align-content: start; box-shadow: var(--ombre-1);
}
.etoiles { display: flex; gap: 3px; color: var(--or); }
.etoiles svg { width: 17px; height: 17px; }
.avis__texte { color: var(--attenue); font-size: var(--t-sm); line-height: 1.65; }
.avis__qui { font-size: var(--t-sm); font-weight: 700; }
.avis__ou { font-size: var(--t-xs); color: var(--attenue); }
.avis__vide {
  border: 1px dashed var(--filet-fort); border-radius: var(--r-md);
  padding: var(--e6); text-align: center; color: var(--attenue); font-size: var(--t-sm);
  grid-column: 1 / -1; max-width: 62ch; margin-inline: auto;
}

/* ─── ZONE DESSERVIE ─────────────────────────────────────── */
.zone { display: grid; gap: clamp(var(--e6), 4vw, var(--e8)); grid-template-columns: minmax(0,1fr) minmax(0,1.1fr);
        align-items: center; }
@media (max-width: 900px) { .zone { grid-template-columns: 1fr; } }
.carte-geo { border-radius: var(--r-lg); overflow: hidden; border: 1px solid var(--filet);
             background: var(--carte); box-shadow: var(--ombre-2); }
.carte-geo svg { width: 100%; height: auto; }
/* ── Bande défilante des communes ─────────────────────────────────
   Deux listes identiques dans une piste, translatée de -50 % : la
   boucle est sans couture parce qu'à mi-course la seconde occupe
   exactement la place de la première. Le survol met en pause plutôt
   que d'inverser le sens — inverser fait sauter l'animation, et une
   pause laisse surtout le temps de lire un nom. */
.bande {
  overflow: hidden; padding-block: var(--e5);
  border-block: 1px solid var(--filet);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
}
.bande__piste { display: flex; width: max-content; animation: bande-defile 60s linear infinite; }
.bande:hover .bande__piste { animation-play-state: paused; }
.bande__liste { display: flex; align-items: center; gap: clamp(var(--e5), 3vw, var(--e7)); padding-inline: clamp(var(--e5), 3vw, var(--e7)) 0; }
.bande__liste li {
  display: flex; align-items: center; gap: clamp(var(--e5), 3vw, var(--e7));
  font: 600 var(--t-xs)/1 var(--mono); letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--attenue); white-space: nowrap;
}
.bande__liste li::after {
  content: ''; width: 5px; height: 5px; border-radius: 50%;
  background: var(--bleu); opacity: 0.55;
}
@keyframes bande-defile { to { transform: translateX(-50%); } }
@media (prefers-reduced-motion: reduce) {
  .bande__piste { animation: none; width: auto; }
  .bande { -webkit-mask-image: none; mask-image: none; }
  .bande__liste[aria-hidden] { display: none; }
  .bande__liste { flex-wrap: wrap; gap: var(--e3) var(--e5); }
  .bande__liste li { gap: var(--e3); }
}

.communes { display: flex; flex-wrap: wrap; gap: var(--e2); margin-top: var(--e5); }
.communes li {
  border: 1px solid var(--filet); border-radius: var(--r-full);
  padding: 7px 14px; font-size: var(--t-sm); color: var(--attenue); background: var(--carte);
}

/* ─── QUESTIONS ──────────────────────────────────────────── */
.faq { display: grid; gap: var(--e3); max-width: 78ch; }
.faq details {
  background: var(--carte); border: 1px solid var(--filet); border-radius: var(--r-md);
  transition: border-color var(--vite), box-shadow var(--vite);
}
.faq details[open] { border-color: var(--filet-fort); box-shadow: var(--ombre-1); }
.faq summary {
  display: flex; justify-content: space-between; align-items: center; gap: var(--e4);
  padding: var(--e4) var(--e5); min-height: 60px; list-style: none;
  font-weight: 700; font-size: var(--t-md); letter-spacing: -0.01em;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: ''; flex: none; width: 14px; height: 14px; background: currentColor;
  transition: transform var(--pose);
  -webkit-mask: no-repeat center/contain url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 5v14M5 12h14' stroke='%23000' stroke-width='2.6' stroke-linecap='round'/%3E%3C/svg%3E");
          mask: no-repeat center/contain url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 5v14M5 12h14' stroke='%23000' stroke-width='2.6' stroke-linecap='round'/%3E%3C/svg%3E");
}
.faq details[open] summary::after { transform: rotate(135deg); }
.faq__rep { padding: 0 var(--e5) var(--e5); color: var(--attenue); line-height: 1.68; }

/* ─── APPEL FINAL ────────────────────────────────────────── */
.appel { text-align: center; display: grid; justify-items: center; gap: var(--e5); }
.appel h2 { max-width: 18ch; }
.appel .chapo { text-align: center; }
.rassure { display: flex; flex-wrap: wrap; gap: var(--e3) var(--e5); justify-content: center;
           font-size: var(--t-sm); color: var(--attenue); }
.rassure li { display: inline-flex; align-items: center; gap: 8px; }
.rassure svg { width: 16px; height: 16px; color: var(--succes); }

/* ─── FORMULAIRE ─────────────────────────────────────────── */
.form { display: grid; gap: var(--e4); }
.champ { display: grid; gap: 7px; }
.champ label { font-size: var(--t-sm); font-weight: 600; }
.champ .aide { font-size: var(--t-xs); color: var(--attenue); }
.champ input, .champ select, .champ textarea {
  min-height: 48px; padding: 12px 15px;
  border: 1px solid var(--filet-fort); border-radius: var(--r-sm);
  background: var(--carte); transition: border-color var(--vite), box-shadow var(--vite);
}
.champ textarea { min-height: 140px; resize: vertical; }
.champ input:focus, .champ select:focus, .champ textarea:focus {
  outline: none; border-color: var(--bleu); box-shadow: 0 0 0 3px rgba(3, 105, 161, 0.18);
}
.champ [aria-invalid="true"] { border-color: var(--cta); box-shadow: 0 0 0 3px rgba(200, 51, 15, 0.16); }
/* ── Champs vivants ───────────────────────────────────────────────
   Les étiquettes restent au-dessus des champs : les faire flotter
   dans le champ les fait disparaître dès qu'on écrit, et c'est une
   régression, pas une amélioration. Ce qui bouge, c'est l'étiquette
   qui prend l'accent, un trait qui se tire sous le champ, et une
   coche quand le champ devient valide. */
.champ { position: relative; }
.champ label { transition: color var(--vite); }
.champ:focus-within > label { color: var(--bleu); }

/* Le trait se tire du centre. Il est posé sur le conteneur, pas sur
   le champ : un input ne peut pas porter de pseudo-élément. */
.champ::after {
  content: ''; position: absolute; left: 50%; bottom: 0; height: 2px; width: 0;
  background: var(--bleu); border-radius: 2px;
  transform: translateX(-50%); transition: width var(--pose);
  pointer-events: none;
}
.champ:focus-within::after { width: calc(100% - 4px); }
.champ:has([aria-invalid="true"])::after { background: var(--cta); width: calc(100% - 4px); }

/* Coche discrète sur un champ rempli et valide, jamais avant la
   première sortie du champ — sinon on gronde quelqu'un qui écrit. */
.champ [data-vu-valide="oui"] { border-color: var(--succes); }
.champ__coche {
  position: absolute; right: 14px; bottom: 14px; width: 17px; height: 17px;
  color: var(--succes); opacity: 0; transform: scale(0.6);
  transition: opacity var(--vite), transform var(--pose); pointer-events: none;
}
.champ__coche[data-actif] { opacity: 1; transform: scale(1); }
.champ:has(textarea) .champ__coche { bottom: auto; top: 44px; }

.compteur {
  justify-self: end; font: 600 var(--t-xs)/1 var(--mono); color: var(--attenue);
  transition: color var(--vite);
}
.compteur[data-etat="proche"] { color: var(--or); }
.compteur[data-etat="plein"] { color: var(--cta-sombre); }

/* États du bouton d'envoi. */
.form .btn[data-etat] { pointer-events: none; }
.form .btn[data-etat="envoi"] { opacity: 0.72; }

@media (prefers-reduced-motion: reduce) {
  .champ::after, .champ__coche, .champ label { transition: none; }
}
.erreur { font-size: var(--t-sm); font-weight: 600; color: var(--cta-sombre); }
.erreur[hidden] { display: none; }
.piege { position: absolute; left: -9999px; }
.resume {
  border: 2px solid var(--cta); background: var(--cta-pale);
  border-radius: var(--r-md); padding: var(--e5); display: grid; gap: var(--e3);
}
.resume[hidden] { display: none; }
.resume h2 { font-size: var(--t-lg); color: var(--cta-sombre); }
.resume a { color: var(--cta-sombre); text-decoration: underline; font-size: var(--t-sm); }
.resume li + li { margin-top: var(--e2); }

/* ─── PIED ───────────────────────────────────────────────── */
.pied { background: var(--nuit); color: #FFF; padding-block: var(--e8) var(--e5); }
.pied a { color: var(--sur-nuit); }
.pied a:hover { color: #FFF; }
.pied__grille { display: grid; gap: var(--e6); grid-template-columns: 2fr repeat(3, 1fr); }
@media (max-width: 900px) { .pied__grille { grid-template-columns: 1fr 1fr; } }
@media (max-width: 560px) { .pied__grille { grid-template-columns: 1fr; } }
.pied__col { display: grid; gap: var(--e2); align-content: start; }
.pied__col p { font: 700 var(--t-xs)/1 var(--mono); letter-spacing: 0.12em;
               text-transform: uppercase; color: var(--bleu-clair); margin-bottom: var(--e2); }
.pied__col a { display: inline-flex; align-items: center; min-height: 36px; font-size: var(--t-sm); }
.pied__bas { display: flex; flex-wrap: wrap; gap: var(--e3) var(--e5); justify-content: space-between;
             margin-top: var(--e7); padding-top: var(--e5); border-top: 1px solid var(--filet-nuit);
             font-size: var(--t-xs); color: var(--sur-nuit); }

/* ─── PAGES INTÉRIEURES ──────────────────────────────────── */
.tete-page { padding-block: clamp(var(--e7), 5vw, var(--e9)) 0; }
/* L'écart sous l'image d'en-tête n'a plus lieu d'être : le premier
   panneau arrive maintenant avec un bord en vague, qui fait lui-même
   la séparation. */
.fil { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-bottom: var(--e4);
       font: 600 var(--t-xs)/1 var(--mono); letter-spacing: 0.08em; color: var(--attenue); }
.fil a { display: inline-flex; align-items: center; min-height: 32px; }
.fil a:hover { color: var(--bleu); }
.article { max-width: 72ch; }
.article h2 { font-size: var(--t-xl); margin-top: var(--e8); margin-bottom: var(--e4); }
.article h2:first-child { margin-top: 0; }
.article p { color: var(--attenue); margin-bottom: var(--e4); line-height: 1.72; }
.article ul { display: grid; gap: var(--e3); margin-bottom: var(--e5); }
.article li { padding-left: var(--e4); border-left: 3px solid var(--bleu-pale); color: var(--attenue); }
.article li strong { color: var(--encre); }
.encart { background: var(--cta-pale); border-left: 4px solid var(--cta);
          border-radius: 0 var(--r-md) var(--r-md) 0; padding: var(--e5); margin-block: var(--e6); }
.encart p { color: var(--encre); }
.encart p:last-child { margin-bottom: 0; }
.encart .sur-titre { color: var(--cta-sombre); display: block; margin-bottom: var(--e3); }

.duo { display: grid; gap: clamp(var(--e6), 4vw, var(--e8)); grid-template-columns: repeat(2, minmax(0,1fr));
       align-items: center; }
@media (max-width: 900px) { .duo { grid-template-columns: 1fr; } }
.media { border-radius: var(--r-md); overflow: hidden; border: 1px solid var(--filet); background: var(--carte); }
.media img { width: 100%; }

/* Planche d'identité dans une étude de cas : elle déborde la
   colonne de texte (72ch) sans jamais dépasser le cadre, d'où le
   min() plutôt qu'une marge négative qui casserait en dessous. */
.media figcaption { padding: var(--e3) var(--e4); font-size: var(--t-xs);
  line-height: 1.5; color: var(--attenue); border-top: 1px solid var(--filet); }
.article .media--large { margin-block: var(--e5) var(--e6); }
@media (min-width: 1000px) {
  .article .media--large { width: min(940px, calc(100vw - 2 * var(--e7))); }
}
.faits { display: grid; gap: var(--e4); grid-template-columns: repeat(4, 1fr);
         padding-block: var(--e5); border-block: 1px solid var(--filet); }
@media (max-width: 700px) { .faits { grid-template-columns: repeat(2, 1fr); } }
.fait__lab { font: 600 var(--t-xs)/1 var(--mono); letter-spacing: 0.1em; text-transform: uppercase; color: var(--attenue); }
.fait__val { font-weight: 700; margin-top: 6px; }

.billets { display: grid; gap: var(--e5); grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.billet {
  background: var(--carte); border: 1px solid var(--filet); border-radius: var(--r-md);
  padding: var(--e5); display: grid; gap: var(--e3); align-content: start; box-shadow: var(--ombre-1);
  transition: transform var(--pose), box-shadow var(--pose), border-color var(--vite);
}
.billet:hover { transform: translateY(-3px); box-shadow: var(--ombre-2); border-color: var(--filet-fort); }
.billet__titre { font-size: var(--t-lg); font-weight: 700; letter-spacing: -0.02em; }
.billet__chapo { color: var(--attenue); font-size: var(--t-sm); }

/* ─── MOUVEMENT ──────────────────────────────────────────
   Les blocs n'ont plus d'état de départ en CSS non plus. */
.progres { position: fixed; inset: 0 0 auto 0; height: 3px; z-index: 70;
           background: var(--cta); transform: scaleX(0); transform-origin: 0 50%; pointer-events: none; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important; animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  .dispo__point::after, .aura span { animation: none; }
}

/* Réserve pour que l'en-tête collant ne masque pas la cible du focus. */
[id] { scroll-margin-top: 96px; }

@media print {
  .tete, .tiroir, .progres, .scene, .btn { display: none !important; }
  body { background: #FFF; color: #000; font-size: 11pt; }
  a::after { content: ' (' attr(href) ')'; font-size: 8pt; color: #555; }
}

/* ═══════════════════════════════════════════════════════════
   LA CONSTELLATION
   Mécanique reprise du modèle : tuiles positionnées sur une grille
   de 600 × 660, traits qui se dessinent, entrée élastique depuis le
   centre, inclinaison 3D au survol. Les positions et le SVG des
   traits partagent le même repère : ils ne peuvent pas se
   désaligner quand on déplace une tuile.
   ═══════════════════════════════════════════════════════════ */
.entete--centre { margin-inline: auto; text-align: center; }
.entete--centre .corps { margin-inline: auto; }

.constel {
  position: relative; width: min(600px, 100%);
  aspect-ratio: 600 / 660; margin-inline: auto;
  perspective: 1500px;
}
.constel__plan {
  position: absolute; inset: 0;
  transform-style: preserve-3d; will-change: transform;
}
.constel__traits { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.constel__traits path {
  fill: none; stroke: rgba(125, 211, 252, 0.5);
  stroke-width: 1.6; stroke-linecap: round;
}

.tuile {
  position: absolute;
  left: calc(var(--x) / 600 * 100%);
  top:  calc(var(--y) / 660 * 100%);
  transform: translate(-50%, -50%);
  display: grid; place-items: center;
  border-radius: 22px; text-decoration: none;
  transform-style: preserve-3d;
}
.tuile__in {
  display: grid; place-items: center; gap: 8px;
  width: 100%; height: 100%; padding: 10px;
  border-radius: inherit;
  transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1),
              box-shadow 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
  will-change: transform;
}
.tuile__ico { width: 34px; height: 34px; }
.tuile__nom {
  font-size: 11px; font-weight: 700; letter-spacing: -0.01em;
  text-align: center; line-height: 1.15; max-width: 13ch;
}
.tuile--grand { width: 116px; height: 108px; }
.tuile--pastille { width: 58px; height: 58px; border-radius: 50%; }
.tuile--pastille .tuile__ico { width: 22px; height: 22px; }
.tuile--noyau { width: 140px; height: 128px; border-radius: 26px; z-index: 3; }
.tuile--noyau .tuile__ico { width: 44px; height: 44px; }
.tuile--noyau .tuile__nom { font-size: 13px; letter-spacing: 0.06em; }

/* Les fonds sont posés sur .tuile__in, pas sur .tuile : c'est lui qui
   bouge au survol, la boîte de positionnement ne bouge jamais. */
.tuile--bleu .tuile__in {
  background: linear-gradient(165deg, #0EA5E9 0%, #0369A1 60%, #075985 100%);
  color: #FFFFFF;
  box-shadow: inset 0 2px 0 rgba(255,255,255,0.28), inset 0 -3px 0 rgba(0,0,0,0.22),
              0 12px 24px rgba(3,105,161,0.34), 0 24px 48px rgba(2,6,23,0.26);
}
.tuile--clair .tuile__in {
  background: linear-gradient(165deg, #F8FAFC 0%, #E0F2FE 60%, #BAE6FD 100%);
  color: #0F172A;
  box-shadow: inset 0 2px 0 rgba(255,255,255,0.9), inset 0 -3px 0 rgba(2,6,23,0.10),
              0 12px 24px rgba(2,6,23,0.20), 0 24px 48px rgba(2,6,23,0.16);
}
.tuile--nuit .tuile__in {
  background: linear-gradient(165deg, #334155 0%, #1E293B 55%, #0B1220 100%);
  color: #E2E8F0;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.18), inset 0 -2px 0 rgba(0,0,0,0.45),
              0 10px 20px rgba(2,6,23,0.42);
}
.tuile--chaud .tuile__in {
  background: linear-gradient(165deg, #E85A34 0%, #C8330F 60%, #A82A0C 100%);
  color: #FFFFFF;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.26), inset 0 -2px 0 rgba(0,0,0,0.30),
              0 10px 22px rgba(200,51,15,0.42);
}
.tuile--noyau .tuile__in {
  background: linear-gradient(165deg, #F8FAFC 0%, #E2E8F0 100%);
  color: #0F172A;
  box-shadow: inset 0 3px 0 rgba(255,255,255,1), inset 0 -4px 0 rgba(2,6,23,0.12),
              0 18px 34px rgba(2,6,23,0.34), 0 40px 70px rgba(2,6,23,0.24);
}

a.tuile:hover .tuile__in, a.tuile:focus-visible .tuile__in { transform: translateY(-9px) scale(1.06); }
a.tuile:hover .tuile__ico { transform: scale(1.1) rotate(-4deg); }
.tuile__ico { transition: transform 0.5s cubic-bezier(0.34, 1.56, 0.64, 1); }

/* Flottement : une période différente par tuile, sinon l'ensemble
   respire à l'unisson et ça se voit tout de suite. */
.tuile:not(.tuile--noyau) .tuile__in { animation: flotte var(--dur, 5s) ease-in-out infinite var(--d, 0s); }
.tuile:nth-child(3n) .tuile__in   { --dur: 5.6s; }
.tuile:nth-child(3n+1) .tuile__in { --dur: 4.4s; }
@keyframes flotte { 50% { transform: translateY(-7px); } }
a.tuile:hover .tuile__in { animation-play-state: paused; }

@media (max-width: 620px) {
  .tuile--grand { width: 92px; height: 88px; }
  .tuile--grand .tuile__ico { width: 26px; height: 26px; }
  .tuile--grand .tuile__nom { font-size: 9.5px; }
  .tuile--pastille { width: 44px; height: 44px; }
  .tuile--noyau { width: 108px; height: 100px; }
}

/* La constellation s'affiche telle quelle, complète et cliquable,
   même sans script. GSAP pose le trait à dessiner puis le dessine. */
@media (prefers-reduced-motion: reduce) {
  .tuile .tuile__in { animation: none; }
}

/* ─── Mots découpés au build ─────────────────────────────────
   Le masque est indispensable : sans overflow caché, le mot glisse
   par-dessus la ligne du dessous au lieu de sortir de sa boîte. */
.w { display: inline-block; overflow: hidden; vertical-align: top;
     padding-bottom: 0.1em; margin-bottom: -0.1em; }
.w > span { display: inline-block; will-change: transform; }

/* ═══════════════════════════════════════════════════════════
   PANNEAUX
   Chaque section devient un bloc inséré dans la gouttière, à coins
   arrondis, avec son propre fond. Les gouttières blanches entre les
   panneaux sont ce qui donne le rythme : une page en aplats pleine
   largeur ne respire pas.

   Quatre traitements, alternés :
     · papier   fond de page, pour les sections denses
     · ciel     nappe bleutée, respiration claire
     · aube     nappe chaude, pour marquer un moment fort
     · nuit     noir profond, pour les sections à peu d'éléments

   Les nappes sont faites de radial-gradients superposés : aucune
   image, aucun poids ajouté, et le rendu reste net à toute taille.
   La teinte la plus claire de chaque nappe a été relevée puis
   vérifiée : l'encre y tient 15,3:1 au pire.
   ═══════════════════════════════════════════════════════════ */
.panneau {
  position: relative; isolation: isolate;
  border-radius: clamp(18px, 2.2vw, 34px);
  /* Le plafond horizontal est à --e8 (64) et non --e9 (96) : au-delà
     de 1600 px le cadre est déjà bloqué à 1280, et un rembourrage qui
     continue de croître rétrécissait la colonne de lecture au lieu de
     l'élargir. Sous 1600, 4vw n'atteint pas 64 : rien ne change. */
  padding: clamp(var(--e7), 7vw, 140px) clamp(var(--e5), 4vw, var(--e8));
  margin-bottom: clamp(var(--e4), 1.4vw, var(--e5));
  overflow: hidden;
}
.panneau > * { position: relative; z-index: 1; }

/* ── Panneaux pleine largeur au-delà de 1408 px ───────────────────
   Au-dessus de ce seuil le cadre est plafonné, donc chaque panneau
   flottait au milieu de l'écran avec 600 px de blanc de part et
   d'autre. Le panneau déborde maintenant jusqu'aux bords, et son
   rembourrage remet le CONTENU exactement là où il était : les
   lignes de texte ne bougent pas d'un pixel.

   Les pourcentages d'une marge se calculent sur le bloc conteneur —
   ici le cadre — d'où le calc(50% - 50vw) qui pousse chaque bord à
   la moitié de la fenêtre. --barre compense la barre de défilement,
   que 100vw inclut mais que l'écran n'affiche pas ; sans elle le
   contenu serait décalé d'une demi-barre. La valeur de repli 0px
   garde la règle valide si le script ne tourne pas.

   Ce n'est pas une nouveauté du site : les sections .bloc--bleu et
   .bloc--nuit des autres pages sont pleine largeur depuis toujours.
   Cette règle aligne l'accueil et les pages service sur elles. */
/* ── Panneaux pleine largeur, à toutes les tailles ────────────────
   Ces règles étaient réservées aux fenêtres de plus de 1408 px. Elles
   valent maintenant partout : un site doit avoir la même allure sur
   un téléphone et sur un 32 pouces.

   Sur mobile le gain est double — la bande de couleur touche les
   bords, et le contenu garde exactement la largeur qu'il avait,
   parce que le rembourrage du panneau compense le débordement au
   pixel près. Vérifié de 320 à 3840 px. */
.panneau, .bande {
  margin-inline: calc(50% - 50vw + var(--barre, 0px) / 2);
  padding-inline: calc(50vw - 50% - var(--barre, 0px) / 2 + clamp(var(--e5), 4vw, var(--e8)));
  border-radius: 0;
  margin-bottom: 0;
}
/* La bande n'a pas de rembourrage propre : elle est faite pour
   défiler d'un bord à l'autre, on lui rend donc ses zéros. */
.bande { padding-inline: 0; }

/* ── Bord supérieur en vague ────────────────────────────────────
   Un masque à deux couches plutôt qu'une image de fond : la vague
   découpe le panneau lui-même, donc elle fonctionne aussi bien sur
   un aplat que sur les fonds en dégradé de « ciel » et « aube » —
   ce qu'une vague dessinée dans une couleur fixe ne saurait pas
   faire.

   Couche 1 : la vague, étirée sur toute la largeur.
   Couche 2 : un aplat pour tout le reste de la hauteur.
   Le +1px de recouvrement évite un cheveu blanc à la jonction.

   preserveAspectRatio='none' laisse la courbe s'aplatir quand
   l'écran s'élargit : une vague qui garderait ses proportions
   deviendrait une montagne sur 2500 px. */
.panneau {
  --vague-h: clamp(40px, 4.5vw, 88px);
  --vague: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1440 100' preserveAspectRatio='none'><path d='M0,52 C180,14 360,18 540,44 C760,77 900,88 1080,66 C1240,46 1340,20 1440,30 L1440,100 L0,100 Z' fill='black'/></svg>");
  -webkit-mask-image: var(--vague), linear-gradient(black, black);
          mask-image: var(--vague), linear-gradient(black, black);
  -webkit-mask-size: 100% var(--vague-h), 100% calc(100% - var(--vague-h) + 1px);
          mask-size: 100% var(--vague-h), 100% calc(100% - var(--vague-h) + 1px);
  -webkit-mask-position: top left, bottom left;
          mask-position: top left, bottom left;
  -webkit-mask-repeat: no-repeat, no-repeat;
          mask-repeat: no-repeat, no-repeat;
  /* La vague mord sur le haut du panneau, et le panneau suivant
     remonte pour recouvrir son bas de la même hauteur. On rend donc
     au contenu, des deux côtés, ce que la courbe lui prend — sans
     quoi il ne restait que 8 px entre le dernier mot et la vague sur
     un téléphone. */
  padding-top: calc(clamp(var(--e7), 7vw, 140px) + var(--vague-h));
  padding-bottom: calc(clamp(var(--e7), 7vw, 140px) + var(--vague-h));
}

/* Sans cette remontée, la vague creusait dans le vide : elle découpe
   le haut du panneau, et c'est le fond de page qui apparaissait dans
   le creux — d'où la bande blanche entre deux couleurs. En remontant
   chaque panneau de la hauteur exacte de sa vague, le creux laisse
   voir le panneau du DESSUS. Plus aucun trou.

   Réservé à un panneau qui en suit un autre : le premier de la page
   et celui qui suit la bande des communes doivent, eux, émerger du
   fond de page. */
.panneau + .panneau { margin-top: calc(var(--vague-h) * -1); }
.bande + .panneau { margin-top: 0; }

/* ── L'appel final reste une carte détachée ───────────────────────
   Le seul panneau qui ne suit pas la règle, et c'est voulu : un bloc
   de contact qui se décolle du flux se remarque davantage qu'une
   bande de plus.

   Il annule donc le débordement, retrouve ses coins arrondis et perd
   sa vague. Son rembourrage bas redevient normal : la compensation
   sert à protéger le texte du panneau qui recouvre, or plus rien ne
   le recouvre — d'où les 228 px de noir mort qu'on voyait.

   .panneau.appel plutôt que .appel : il faut deux classes pour
   l'emporter sur « .bande + .panneau », qui en vaut deux aussi. */
.panneau.appel {
  margin-inline: 0;
  margin-top: clamp(var(--e6), 4vw, var(--e8));
  margin-bottom: clamp(var(--e6), 4vw, var(--e8));
  padding-inline: clamp(var(--e5), 4vw, var(--e8));
  padding-top: clamp(var(--e7), 7vw, 140px);
  padding-bottom: clamp(var(--e7), 7vw, 140px);
  border-radius: clamp(18px, 2.2vw, 34px);
  -webkit-mask-image: none;
          mask-image: none;
}
/* Un filet qui court d'un bord à l'autre n'a plus de sens : seul
   celui du haut sépare encore deux panneaux clairs. */
.panneau--papier { border-inline: 0; border-bottom: 0; }
/* Le premier panneau ne doit plus être décollé de l'en-tête. */
.tete-page + .cadre { margin-top: 0; }


.panneau--papier { background: var(--carte); border: 1px solid var(--filet); }

/* Le vermillon de marque tombe à 4,05:1 sur le point le plus clair de
   la nappe chaude. Il n'y est pas employé en texte aujourd'hui, mais
   la règle est posée pour que ça reste vrai si on l'y met demain :
   sur les nappes, --cta bascule sur sa variante assombrie. */
.panneau--ciel, .panneau--aube { --cta: var(--cta-sombre); }

.panneau--ciel {
  background:
    radial-gradient(64% 78% at 12% 18%, #BFE0F7 0%, transparent 62%),
    radial-gradient(58% 70% at 86% 26%, #FFE3D8 0%, transparent 60%),
    radial-gradient(70% 84% at 62% 92%, #DCEEFB 0%, transparent 66%),
    #EAF4FC;
}
.panneau--aube {
  background:
    radial-gradient(58% 74% at 8% 26%, #FFC8B0 0%, transparent 60%),
    radial-gradient(62% 76% at 92% 34%, #E4D7F2 0%, transparent 62%),
    radial-gradient(74% 86% at 52% 96%, #F2D3E8 0%, transparent 68%),
    #FFD9C2;
}
.panneau--nuit {
  background: #0A0F1A; color: #FFFFFF;
  --encre: #FFFFFF; --attenue: #CBD5E1; --filet: rgba(255,255,255,0.14);
  --carte: #141C2B; --bleu: var(--bleu-clair);
}
.panneau--nuit::after {            /* halo froid, très discret */
  content: ''; position: absolute; inset: -30% -10% auto; height: 80%; z-index: 0;
  background: radial-gradient(ellipse at 30% 0%, rgba(56,189,248,0.16), transparent 62%);
  pointer-events: none;
}

/* ─── Titres de section, à l'échelle d'OWDT ──────────────── */
.titre-geant {
  font-size: clamp(2.6rem, 1rem + 6vw, 6.5rem);
  line-height: 0.96; letter-spacing: -0.045em; font-weight: 800;
  max-width: 16ch;
}
.panneau .entete { max-width: none; margin-bottom: clamp(var(--e6), 5vw, var(--e9)); }
.panneau .entete .corps { margin-top: var(--e4); max-width: 58ch; }

/* Une variante en deux colonnes : titre à gauche, lien à droite,
   comme les en-têtes « Commentary / See All Articles ». */
.entete--reparti {
  display: flex; flex-wrap: wrap; gap: var(--e5);
  align-items: flex-end; justify-content: space-between;
}
/* Le titre géant porte déjà son propre gabarit (16ch de SA police).
   Caper le conteneur à 60ch le mesurait au corps du texte, soit
   534 px : le titre n'avait plus que 5,1 em et cassait après chaque
   mot. On cape donc le paragraphe, pas le bloc. */
.entete--reparti > div { min-width: 0; }
.entete--reparti > div:first-child { flex: 1 1 30ch; max-width: none; }
.entete--reparti > div + div { flex: 0 0 auto; }
.entete--reparti > div > .corps,
.entete--reparti > div > .chapo { max-width: 58ch; }

/* ─── Lien fléché, flèche dans un cercle ─────────────────── */
.lien-rond {
  display: inline-flex; align-items: center; gap: 12px; min-height: 44px;
  font-weight: 700; font-size: var(--t-md); letter-spacing: -0.01em;
  color: var(--encre);
}
.lien-rond__cercle {
  display: inline-grid; place-items: center; flex: none;
  width: 34px; height: 34px; border-radius: 50%;
  border: 1.6px solid currentColor;
  transition: background-color var(--vite), color var(--vite), transform var(--pose);
}
.lien-rond__cercle svg { width: 15px; height: 15px; }
.lien-rond:hover .lien-rond__cercle,
.lien-rond:focus-visible .lien-rond__cercle {
  background: var(--encre); color: var(--carte); transform: translateX(3px);
}
.panneau--nuit .lien-rond:hover .lien-rond__cercle { background: #FFFFFF; color: #0A0F1A; }
.lien-rond--petit { font-size: var(--t-sm); }
.lien-rond--petit .lien-rond__cercle { width: 28px; height: 28px; }
.lien-rond--petit .lien-rond__cercle svg { width: 13px; height: 13px; }

/* Une rangée de liens fléchés, comme la section « Expertise ». */
.rang-liens {
  display: flex; flex-wrap: wrap;
  gap: clamp(var(--e4), 3vw, var(--e8)) clamp(var(--e5), 4vw, var(--e9));
}

/* ─── Rangées à filets, comme « Commentary » ─────────────── */
.rangs-filet { border-top: 1.5px solid currentColor; }
.rang-filet {
  display: grid; align-items: start;
  grid-template-columns: 88px minmax(0, 1fr) auto;
  gap: var(--e3) var(--e5);
  padding-block: clamp(var(--e4), 2.4vw, var(--e6));
  border-bottom: 1.5px solid currentColor;
}
.rang-filet__cat {
  font-size: var(--t-sm); color: var(--attenue); padding-top: 3px;
}
.rang-filet__titre {
  font-size: var(--t-lg); font-weight: 700; letter-spacing: -0.02em;
}
.rang-filet__texte {
  color: var(--attenue); font-size: var(--t-sm); margin-top: var(--e3); max-width: 62ch;
}
.rang-filet__lien { grid-row: 1; grid-column: 3; }
@media (max-width: 780px) {
  .rang-filet { grid-template-columns: 1fr; }
  .rang-filet__lien { grid-row: auto; grid-column: 1; }
}

/* ─── Ajustements des composants dans les panneaux ─────────── */
/* Les cartes internes prennent le fond du panneau, pas le blanc de
   page : sur une nappe colorée, un blanc pur ferait tache. */
.panneau--ciel .preuve__item,
.panneau--aube .preuve__item,
.panneau--ciel .tarif,
.panneau--aube .tarif,
.panneau--ciel .avis__carte,
.panneau--aube .avis__carte {
  background: rgba(255, 255, 255, 0.72);
  border-color: rgba(2, 6, 23, 0.10);
  backdrop-filter: blur(6px);
}
.panneau--nuit .etape-f,
.panneau--nuit .service,
.panneau--nuit .tarif { background: var(--carte); border-color: var(--filet); }
.panneau--nuit .faq details { background: var(--carte); border-color: var(--filet); }
.panneau--nuit .faq details[open] { border-color: rgba(255,255,255,0.34); }

/* Le titre d'une rangée à filets se souligne au survol : c'est un
   lien, il doit se comporter comme tel. */
.rang-filet__titre a { background-image: linear-gradient(currentColor, currentColor);
  background-size: 0 1.5px; background-repeat: no-repeat; background-position: 0 100%;
  transition: background-size var(--pose); padding-bottom: 2px; }
.rang-filet:hover .rang-filet__titre a { background-size: 100% 1.5px; }

/* La constellation respire dans son panneau. */
.panneau--nuit .constel { margin-top: clamp(var(--e6), 5vw, var(--e8)); }

/* L'appel final, centré dans son panneau. */
.appel { text-align: center; display: grid; justify-items: center; gap: var(--e5); }
.appel .titre-geant, .appel h2 { max-width: 18ch; }
.appel .chapo { text-align: center; }

/* La carte de zone reste lisible sur un fond blanc de panneau. */
.panneau--papier .communes li { background: var(--fond); }

/* Sur les nappes, les filets de séparation sont sombres, pas gris
   clair : un filet gris sur un fond coloré disparaît. */
.panneau--ciel .rangs-filet, .panneau--ciel .rang-filet,
.panneau--aube .rangs-filet, .panneau--aube .rang-filet { border-color: rgba(2, 6, 23, 0.22); }

/* Les voiles de ces deux panneaux montent jusqu'à #BFE0F7 et #FFC8B0,
   où le bleu de marque ne tient plus que 4,30:1 et 4,00:1 — sous le
   seuil de 4,5. Le sur-titre et le numéro d'étape tombent précisément
   sur le voile pêche d'« aube », centré en haut à gauche. On assombrit
   donc le jeton sur ces deux fonds : 4,93:1 au pire, la teinte reste
   celle de la marque. */
.panneau--ciel, .panneau--aube { --bleu: #025B8A; }
.panneau--nuit .rangs-filet, .panneau--nuit .rang-filet { border-color: rgba(255, 255, 255, 0.22); }
.panneau--papier .rangs-filet, .panneau--papier .rang-filet { border-color: rgba(2, 6, 23, 0.16); }

@media (max-width: 620px) {
  /* Le rembourrage et les coins arrondis ont été retirés d'ici : un
     padding-inline en valeur fixe écrasait le calcul qui recentre le
     contenu des panneaux pleine largeur, et le rayon de 16 px
     ramenait des cartes flottantes sur mobile alors que la vague
     suppose des bandes jointives. Le clamp de base donne déjà 24 px
     à cette taille — la valeur que cette règle posait. */
  .titre-geant { font-size: clamp(2rem, 7vw, 2.8rem); }
}

/* ─── Pour qui c'est fait ────────────────────────────────────
   Quatre secteurs, chacun avec ce qui change concrètement. La ligne
   « ce qui change » est ce qui distingue cette section d'une liste
   de clientèles : elle dit un effet, pas une catégorie. */
.secteurs {
  display: grid; gap: var(--e4);
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}
.secteur {
  background: rgba(255, 255, 255, 0.72);
  border: 1px solid rgba(2, 6, 23, 0.10);
  border-radius: var(--r-md);
  padding: clamp(var(--e5), 2.6vw, var(--e6));
  /* Colonne flexible plutôt que grille : c'est ce qui permet de
     chasser la ligne de pied vers le bas. Les cartes ont déjà la même
     hauteur — la grille les étire — mais leurs textes n'ont pas le
     même nombre de lignes, donc le trait de séparation tombait à trois
     hauteurs différentes. */
  display: flex; flex-direction: column; gap: var(--e2);
  backdrop-filter: blur(6px);
  transition: transform var(--pose), box-shadow var(--pose);
}
.secteur:hover { transform: translateY(-3px); box-shadow: var(--ombre-2); }
/* ── Disque numéroté ──────────────────────────────────────────────
   Le disque déborde du coin haut-droit et la carte le rogne. Il est
   posé AVANT le contenu dans le balisage mais aria-hidden : le
   numéro est décoratif, l'ordre de lecture reste titre puis texte.

   overflow:hidden était déjà nécessaire au rognage ; le fond
   translucide de la carte le rendait possible sans retouche. */
.secteur { position: relative; overflow: hidden; }
.secteur__disque {
  position: absolute; top: -28px; right: -20px;
  width: 96px; height: 96px; border-radius: 50%;
  background: var(--bleu);
  transition: transform var(--pose), background-color var(--vite);
}
.secteur__disque > span {
  position: absolute; left: 26px; bottom: 22px;
  font: 800 1.35rem/1 var(--police); color: #FFFFFF;   /* 5,93:1 sur --bleu */
  letter-spacing: -0.02em;
}
.secteur:hover .secteur__disque { transform: scale(1.08); }
.secteur__ico { color: var(--bleu); display: block; margin-bottom: var(--e3); }
.secteur__ico svg { width: 30px; height: 30px; display: block; }
/* Le titre ne doit pas courir sous le disque. */
.secteur__titre { padding-right: 58px; }
@media (prefers-reduced-motion: reduce) {
  .secteur__disque { transition: none; }
  .secteur:hover .secteur__disque { transform: none; }
}
.secteur__titre { font-size: var(--t-lg); font-weight: 700; letter-spacing: -0.025em; }
.secteur__texte { color: var(--attenue); font-size: var(--t-sm); }
.secteur__effet {
  font-size: var(--t-sm); font-weight: 600; color: var(--encre);
  margin-top: auto; padding-top: var(--e4);
  border-top: 1px solid rgba(2, 6, 23, 0.12);
}

/* La franchise sur les refus : elle vaut plus qu'un argument de vente.
   Un prestataire qui dit non est un prestataire qu'on croit quand il
   dit oui. */
.franchise {
  display: grid; gap: var(--e5) clamp(var(--e6), 5vw, var(--e9));
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
  align-items: center;
  margin-top: clamp(var(--e6), 4vw, var(--e8));
  padding-top: clamp(var(--e5), 3vw, var(--e6));
  border-top: 1.5px solid rgba(2, 6, 23, 0.22);
}
@media (max-width: 860px) { .franchise { grid-template-columns: 1fr; } }
.franchise__titre { font-size: var(--t-xl); letter-spacing: -0.03em; margin-bottom: var(--e3); }
.franchise__chiffres { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--e4); }
.franchise__chiffres dt {
  font-size: var(--t-2xl); font-weight: 800; letter-spacing: -0.045em;
  line-height: 1; color: var(--bleu);
}
.franchise__chiffres dd { color: var(--attenue); font-size: var(--t-sm); margin-top: 6px; }

/* ─── Ce qui est compris ─────────────────────────────────────
   Une liste à deux colonnes plutôt que des cartes : le contenu est
   homogène et surtout textuel, une grille de cartes y ajouterait des
   bordures sans rien clarifier. */
.inclus {
  display: grid; gap: clamp(var(--e5), 3vw, var(--e6)) clamp(var(--e6), 5vw, var(--e9));
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}
.inclus__item {
  display: grid; grid-template-columns: 34px minmax(0, 1fr); gap: var(--e4);
  align-items: start;
  padding-top: var(--e4); border-top: 1px solid var(--filet);
}
.inclus__coche {
  display: inline-grid; place-items: center; width: 34px; height: 34px;
  border-radius: 50%; background: var(--bleu-pale); color: var(--bleu);
}
.inclus__coche svg { width: 18px; height: 18px; }
.inclus__titre { font-size: var(--t-lg); font-weight: 700; letter-spacing: -0.025em; margin-bottom: 6px; }
.inclus__texte { color: var(--attenue); font-size: var(--t-sm); line-height: 1.6; }
/* La note attire l'œil sur le seul point que les concurrents ne
   peuvent pas cocher : la propriété des fichiers. */
.inclus__note {
  margin-top: var(--e3); padding-left: var(--e3);
  border-left: 3px solid var(--cta);
  font-size: var(--t-sm); font-weight: 600; color: var(--encre);
}

/* ═══ FORMULE SUBSIDIÉ ET BARÈME DE LA PRIME ═══════════════════
   Aucune règle ici ne masque de contenu : le barème est lisible
   sans JavaScript, et le tableau reste un tableau pour les
   lecteurs d'écran (th scope, caption). */
.subside {
  display: grid; gap: clamp(var(--e5), 3vw, var(--e7));
  grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr);
  align-items: start;
}
@media (max-width: 980px) { .subside { grid-template-columns: 1fr; } }

.tarif--subside { border-color: var(--cta); box-shadow: var(--ombre-2); }
.tarif__ruban--calme { background: var(--nuit); color: #FFF; }

.bareme table {
  width: 100%; border-collapse: collapse; background: var(--carte);
  border: 1px solid var(--filet); border-radius: var(--r-md); overflow: hidden;
}
.bareme caption {
  caption-side: top; text-align: left; color: var(--attenue);
  font-size: var(--t-sm); line-height: 1.5; margin-bottom: var(--e4);
}
.bareme { --filet-bareme: #8494A8; }   /* 3,10:1 sur blanc */
.bareme th, .bareme td {
  padding: var(--e4); text-align: left; vertical-align: top;
  font-size: var(--t-sm); line-height: 1.5;
  border-bottom: 1px solid var(--filet-bareme);
}
.bareme thead th {
  font-size: var(--t-xs); text-transform: uppercase; letter-spacing: .06em;
  font-weight: 700; color: var(--attenue); background: var(--fond);
}
.bareme tbody tr:last-child th, .bareme tbody tr:last-child td { border-bottom: 0; }
.bareme td { color: var(--attenue); }
.bareme__taux { font-size: var(--t-md); font-weight: 800; color: var(--encre); white-space: nowrap; }
.bareme__chiffre { text-align: right; white-space: nowrap; }
.bareme__reste { font-weight: 700; color: var(--encre); }
.bareme__note {
  margin-top: var(--e4); font-size: var(--t-xs); line-height: 1.6;
  color: var(--attenue); max-width: 60ch;
}
/* Sous 520 px le tableau devient une pile de fiches. Les en-têtes de
   colonne ne disparaissent pas : chaque cellule réaffiche la sienne
   depuis data-col, sinon les montants se retrouveraient sans libellé. */
@media (max-width: 520px) {
  .bareme thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .bareme tbody tr { display: block; padding: var(--e4); border-bottom: 1px solid var(--filet-bareme); }
  .bareme tbody tr:last-child { border-bottom: 0; }
  .bareme tbody th, .bareme tbody td { display: block; border: 0; padding: 0; }
  .bareme tbody td { margin-top: var(--e3); }
  .bareme tbody td[data-col]::before {
    content: attr(data-col); display: block;
    font-size: var(--t-xs); text-transform: uppercase; letter-spacing: .06em;
    font-weight: 700; color: var(--attenue); margin-bottom: 2px;
  }
  .bareme__chiffre { text-align: left; }
}

/* Paragraphes suivis d'une page éditoriale */
.prose { max-width: 74ch; }
.prose .corps + .corps { margin-top: var(--e4); }

/* ═══ BANDEAU PRIME — pleine largeur ═══════════════════════════
   Rupture volontaire : le bandeau sort du .cadre pour toucher les
   deux bords, comme une bannière institutionnelle. La lueur ambre
   est bornée à 18 % — au-delà, le fond remonte et le texte blanc
   passe sous les seuils. Point le plus clair mesuré : #3D3928,
   blanc à 11,57:1. */
.b-prime {
  position: relative; isolation: isolate;
  padding-block: clamp(var(--e7), 7vw, 130px);
  margin-block: clamp(var(--e6), 4vw, var(--e8));
  overflow: hidden;
  --encre: #FFFFFF;
  --attenue: #CBD5E1;
  color: #FFFFFF;
}
.b-prime__fond {
  position: absolute; inset: 0; z-index: 0;
  background:
    radial-gradient(52% 68% at 22% 26%, rgba(252,211,77,0.18) 0%, transparent 64%),
    radial-gradient(46% 60% at 80% 78%, rgba(200,51,15,0.16) 0%, transparent 62%),
    radial-gradient(70% 90% at 50% 50%, rgba(252,211,77,0.07) 0%, transparent 70%),
    #131720;
}
.b-prime__grille {
  position: relative; z-index: 1;
  display: grid; gap: clamp(var(--e5), 4vw, var(--e8));
  grid-template-columns: minmax(0, 0.42fr) minmax(0, 1fr);
  align-items: center;
}
@media (max-width: 900px) { .b-prime__grille { grid-template-columns: 1fr; } }

.b-prime__marque { text-align: center; }
.b-prime__calcul {
  display: inline-block; text-align: center;
  padding: clamp(var(--e5), 3vw, var(--e6)) clamp(var(--e5), 4vw, var(--e7));
  border: 1px solid rgba(252, 211, 77, 0.34); border-radius: var(--r-md);
}
.b-prime__quoi {
  font-size: var(--t-xs); letter-spacing: .1em; text-transform: uppercase;
  font-weight: 700; color: #CBD5E1; margin-bottom: var(--e4);
}
.b-prime__calcul dl { margin: 0; }
.b-prime__calcul dt {
  font-size: var(--t-xs); letter-spacing: .08em; text-transform: uppercase;
  font-weight: 600; color: #CBD5E1;
}
.b-prime__calcul dd { margin: 0 0 var(--e4); }
.b-prime__calcul dd:last-child { margin-bottom: 0; }
.b-prime__avant {
  font-size: clamp(1.5rem, 2.6vw, 2rem); font-weight: 700;
  color: #A8B4C4;                         /* 5,51:1 au pire */
  letter-spacing: -0.02em; line-height: 1.15;
}
.b-prime__avant s { text-decoration-thickness: 2px; text-decoration-color: #FCD34D; }
/* La flèche est décorative : le lien entre les deux montants est
   déjà porté par les intitulés de la liste de définitions. */
.b-prime__calcul dd.b-prime__avant::after {
  content: ''; display: block; width: 2px; height: 26px;
  margin: var(--e3) auto 0; background: rgba(252, 211, 77, 0.5);
}
.b-prime__apres {
  font-size: clamp(2.6rem, 5.4vw, 4rem); font-weight: 800;
  color: #FCD34D;                          /* 8,03:1 au pire */
  letter-spacing: -0.04em; line-height: 1;
}
.b-prime__sous {
  margin-top: var(--e3); font-size: var(--t-xs);
  color: #CBD5E1; letter-spacing: .04em;
}
.b-prime .sur-titre { display: block; color: #FCD34D; margin-bottom: var(--e3); }
.b-prime__titre {
  font-size: var(--t-2xl); line-height: 1.1; letter-spacing: -0.03em;
  font-weight: 400; color: #FFFFFF; text-wrap: balance; margin-bottom: var(--e4);
}
.b-prime__titre strong { font-weight: 800; }
.b-prime__texte { color: #E2E8F0; max-width: 60ch; margin-bottom: var(--e5); line-height: 1.6; }
.b-prime .btn--calme { background: transparent; color: #FFF; border-color: rgba(255,255,255,0.42); }
.b-prime .btn--calme:hover { border-color: #FFF; }
.b-prime__bascule {
  margin-top: var(--e5); padding-top: var(--e5);
  border-top: 1px solid rgba(255,255,255,0.24);
  font-size: var(--t-sm); line-height: 1.6; color: #E2E8F0; max-width: 62ch;
}
.b-prime__bascule a { color: #FCD34D; text-decoration: underline; text-underline-offset: 3px; white-space: nowrap; }
.b-prime__note { margin-top: var(--e3); font-size: var(--t-xs); line-height: 1.6; color: #CBD5E1; max-width: 62ch; }

/* ═══ GARDE-FOU DES GRILLES À COLONNE IMPLICITE ════════════════
   Une grille sans grid-template-columns crée une colonne « auto »,
   dont la largeur minimale est le max-content de son plus large
   enfant. Dès qu'un descendant est insécable — nos boutons le sont —
   la colonne gonfle au-delà du conteneur et pousse TOUT le contenu
   hors du cadre. C'est ce qui faisait déborder la carte Sur-mesure.

   La liste ci-dessous est celle des grilles qui contiennent
   réellement un élément insécable dans les pages produites ; elle a
   été relevée sur le HTML, pas devinée. */
.appel,
.billet,
.cas__item,
/* .service est sortie de cette liste : elle est passée en colonne
   flexible, où grid-template-columns n'a aucun effet. Ses enfants
   sont bornés par min-width: 0 juste au-dessus. */
.champ,
.form,
.sous-bandeau,
.bandeau__texte { grid-template-columns: minmax(0, 1fr); }

/* Les boutons pleine largeur doivent pouvoir passer à la ligne :
   un libellé long ne doit jamais imposer sa largeur à son conteneur. */
.cas__item .btn, .service .btn, .billet .btn,
.appel .btn, .form .btn { white-space: normal; text-wrap: balance; line-height: 1.3; }

/* ═══ CARTES DE TARIFS DANS UN PANNEAU SOMBRE ══════════════════
   C'est le fond qui s'assombrit, pas la surface de lecture. Une
   carte comporte huit puces à parcourir ligne à ligne ; du texte
   clair sur fond sombre y fatigue davantage — le halo autour des
   lettres gêne surtout les personnes astigmates.

   .panneau--nuit redéfinit --carte en #141C2B et --bleu en
   #38BDF8. Les deux sont faux ici : il faut remettre les jetons
   clairs à l'intérieur de la carte, sinon le ruban « Recommandé »
   tombe à 2,14:1 et la bordure de la carte phare avec lui. */
.panneau--nuit .tarif {
  --encre: #020617;
  --attenue: #475569;
  --carte: #FFFFFF;
  --filet: #E2E8F0;
  --bleu: #0369A1;                 /* blanc dessus : 5,93:1 */
  background: #FFFFFF;
  border-color: #E2E8F0;
  color: #020617;
  box-shadow: 0 24px 48px rgba(0, 0, 0, 0.34);
}
.panneau--nuit .tarif--phare { border-color: #0369A1; }
.panneau--nuit .tarif__ruban { background: #0369A1; color: #FFFFFF; }
.panneau--nuit .tarif__delai,
.panneau--nuit .tarif__prix small { color: #475569; }

/* Le vert de réussite tombe à 3,82:1 sur le fond sombre. On garde le
   jeton sur les fonds clairs et on éclaircit sur les fonds sombres. */
.sur-titre--accent { color: var(--succes); }
.panneau--nuit .sur-titre--accent { color: #4ADE80; }   /* 10,99:1 sur #0A0F1A */


/* ═══ PANNEAU « COMMENT DÉMARRER » — LE BLEU DU HÉROS ══════════
   Même famille que le bandeau d'en-tête, pour que la page s'ouvre
   sur une seule couleur au lieu de deux.

   Le dégradé du héros finit à #0284C7, où le blanc ne tient plus
   que 4,10:1. Ici il est borné à #0369A1 — exactement la limite que
   s'impose déjà la zone de texte du héros — ce qui garantit 5,93:1
   au blanc sur le point le plus clair du panneau.

   .panneau--nuit reste posé : c'est lui qui porte le texte blanc et
   les jetons clairs remis dans les cartes. Seuls le fond et deux
   couleurs qui ne passaient plus sont repris ici. */
.panneau--hero {
  background: linear-gradient(112deg, #0B3C63 0%, #075985 38%, #0369A1 100%);
  --attenue: #E2E8F0;              /* 4,81:1 au pire, contre 4,00 avant */
}
/* Le halo cyan de .panneau--nuit éclaircirait le coin haut-gauche,
   c'est-à-dire précisément là où se trouve le titre. */
.panneau--hero::after { background: none; }
.panneau--hero .sur-titre--accent { color: #FDE68A; }   /* 4,76:1 au pire */

/* ═══ CARTES CLAIRES SUR LE PANNEAU BLEU ═══════════════════════
   Même principe que les cartes de tarifs : le fond s'assombrit, pas
   la surface de lecture. .panneau--nuit redéfinit --carte et --filet
   en versions sombres ; on remet les jetons clairs dans la carte. */
.panneau--nuit .service--clair {
  --encre: #020617;
  --attenue: #475569;
  --carte: #FFFFFF;
  --filet: #E2E8F0;
  background: #FFFFFF;
  border-color: #E2E8F0;
  color: #020617;
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.26);
}
.panneau--nuit .service--clair .service__prix { color: #0369A1; }   /* 5,93:1 */

/* Les paragraphes d'une page service, dans un panneau. */
.panneau .prose { max-width: 74ch; }
.panneau .prose .corps + .corps { margin-top: var(--e4); }

/* ═══ LES TROIS TEMPS DE FABRICATION ═══════════════════════════
   Trois scènes dessinées, posées sur des cartes blanches pour
   rester lisibles quel que soit le fond du panneau — papier, aube
   ou ciel. Les couleurs du SVG viennent d'ici : un var() placé
   dans un attribut de présentation SVG est ignoré. */
.fabrique {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: var(--e5);
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
@media (max-width: 980px) { .fabrique { grid-template-columns: 1fr; } }

.fabrique__pas {
  /* min-width: 0 remplace le minmax(0,1fr) de la grille : sans lui, un
     enfant en white-space: nowrap imposerait sa largeur à la carte. */
  display: flex; flex-direction: column; gap: var(--e3);
  background: var(--carte); border: 1px solid var(--filet);
  border-radius: var(--r-md); padding: var(--e5);
  box-shadow: var(--ombre-1);
}
.fabrique__vue {
  display: block; margin: calc(var(--e5) * -1) calc(var(--e5) * -1) var(--e4);
  border-bottom: 1px solid var(--filet);
  background: var(--fond);
  border-radius: var(--r-md) var(--r-md) 0 0; overflow: hidden;
}
.fabrique__pas > *, .service > *, .service__corps > *, .secteur > * { min-width: 0; }
.v-svg { display: block; width: 100%; height: auto; }
/* Une capture prend la place d'une scène dessinée sans rien changer
   au gabarit : même rapport 1,6 et même cadrage. */
.fabrique__vue img { display: block; width: 100%; height: auto; }

.fabrique__num {
  font: 700 var(--t-xs)/1 var(--mono); letter-spacing: 0.12em;
  color: var(--cta-sombre);
}
.fabrique__titre { font-size: var(--t-lg); font-weight: 800; letter-spacing: -0.02em; }
.fabrique__texte { font-size: var(--t-sm); line-height: 1.6; color: var(--attenue); }
.fabrique__note {
  margin-top: auto; padding-top: var(--e3); font: 600 var(--t-xs)/1 var(--mono);
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--attenue);
}

/* — palette des scènes — */
.v-surface     { fill: #FFFFFF; stroke: #CBD5E1; stroke-width: 1; }
.v-filet       { stroke: #CBD5E1; stroke-width: 1; fill: none; }
.v-filet-plein { fill: none; stroke: #94A3B8; stroke-width: 1.6; }
.v-point       { fill: #CBD5E1; }
.v-calque      { fill: #E2E8F0; }
.v-calque--actif { fill: #7DD3FC; }
.v-bloc        { fill: #E8EEF5; }
.v-bloc--fort  { fill: #0369A1; }
.v-bloc--clair { fill: #BAE6FD; }
.v-bloc--action{ fill: #C8330F; }
.v-selection   { fill: none; stroke: #0369A1; stroke-width: 1.6; }
.v-poignee     { fill: #FFFFFF; stroke: #0369A1; stroke-width: 1.6; }
.v-curseur     { fill: #020617; }
.v-epingle circle { fill: #C8330F; }
.v-epingle text   { fill: #FFFFFF; font: 700 11px/1 var(--police); }
.v-bulle       { fill: #0F172A; stroke: none; }
.v-bulle-ligne { fill: #64748B; }
.v-valide      { fill: #15803D; }
.v-coche       { fill: none; stroke: #FFFFFF; stroke-width: 3.2; stroke-linecap: round; stroke-linejoin: round; }
.v-url         { fill: #F1F5F9; stroke: #CBD5E1; stroke-width: 1; }
.v-url-txt     { fill: #475569; font: 600 7px/1 var(--mono); }

/* ═══ POURQUOI UN SITE — cinq raisons ══════════════════════════
   Trois colonnes puis deux, plutôt qu'une grille rigide : à cinq
   éléments, un reste toujours seul sur sa rangée. auto-fit règle
   le problème sans média-requête. */
.raisons {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: var(--e5);
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}
.raison {
  display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--e2);
  align-content: start;
  background: var(--carte); border: 1px solid var(--filet);
  border-radius: var(--r-md); padding: var(--e5);
  box-shadow: var(--ombre-1);
}
.raison__num {
  font: 800 var(--t-sm)/1 var(--mono); letter-spacing: 0.1em;
  color: var(--cta-sombre); margin-bottom: var(--e2);
}
.raison__titre { font-size: var(--t-md); font-weight: 800; letter-spacing: -0.02em; line-height: 1.25; }
.raison__texte { font-size: var(--t-sm); line-height: 1.6; color: var(--attenue); }

/* ═══ LA FORMULE MISE EN AVANT SE VOIT ═════════════════════════
   Elle portait déjà un ruban, une bordure bleue et un bouton plein,
   mais restait à la même hauteur et sur le même blanc que les
   autres. On la sort du rang sans la grandir : agrandir une carte
   dans une grille à colonnes égales déforme la rangée entière. */
.tarif--phare {
  /* Pas de décalage vertical : il soulevait aussi le bouton et
     désalignait les trois appels à l'action. Le ruban, la bordure,
     le liseré et le bouton plein suffisent à la distinguer. */
  border-width: 2px;
  box-shadow: 0 34px 60px -20px rgba(2, 6, 23, 0.42), 0 6px 16px rgba(2, 6, 23, 0.12);
}
/* Un liseré coloré en haut de carte, dans la continuité du ruban. */
.tarif--phare::before {
  content: ''; position: absolute; inset: 0 0 auto; height: 4px;
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  background: var(--bleu);
}
/* Sur le panneau sombre, le liseré reprend le bleu remis dans la carte. */
.panneau--nuit .tarif--phare::before { background: #0369A1; }

/* ═══ APRÈS LES DOUZE MOIS ═════════════════════════════════════
   Cette précision vivait dans la carte Sérénité et lui ajoutait
   267 px : la colonne dépassait les deux autres de près de 300 px.
   Sortie sous la grille, elle harmonise les trois cartes et se lit
   mieux — c'est une réponse à une objection, pas un argument de
   vente qui doit peser au moment du prix. */
.apres {
  margin-top: clamp(var(--e5), 3vw, var(--e6));
  display: grid; gap: clamp(var(--e4), 3vw, var(--e6));
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  align-items: start;
  padding: clamp(var(--e5), 3vw, var(--e6));
  background: var(--carte); border: 1px solid var(--filet);
  border-radius: var(--r-md);
}
@media (max-width: 860px) { .apres { grid-template-columns: 1fr; } }
.apres__titre {
  font: 700 var(--t-xs)/1.4 var(--mono); letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--cta-sombre); margin-bottom: var(--e3);
}
.apres__note { font-size: var(--t-sm); line-height: 1.6; color: var(--attenue); }
.apres__liste { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--e3); }
.apres__liste li {
  font-size: var(--t-sm); line-height: 1.5; color: var(--encre);
  padding-left: 16px; position: relative;
}
.apres__liste li::before {
  content: ''; position: absolute; left: 0; top: 0.55em;
  width: 6px; height: 6px; border-radius: 50%; background: var(--bleu);
}
/* ═══ RAPPEL DE PRIX SUR UNE PAGE SERVICE ══════════════════════
   Trois lignes, pas trois cartes : la page service rappelle les
   tarifs sans refaire la grille de l'accueil. C'est cette grille
   dupliquée qui rendait les deux pages jumelles. */
.rappel { margin: 0; display: grid; gap: 0; }
.rappel__ligne {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--e2) var(--e5); align-items: baseline;
  padding-block: var(--e5);
  border-top: 1px solid var(--filet);
}
.rappel__ligne:last-child { border-bottom: 1px solid var(--filet); }
.rappel__nom { font-size: var(--t-lg); font-weight: 800; letter-spacing: -0.02em; }
.rappel__prix {
  margin: 0; font-size: var(--t-lg); font-weight: 800;
  letter-spacing: -0.02em; white-space: nowrap; text-align: right;
}
.rappel__note {
  grid-column: 1 / -1; margin: 0;
  font-size: var(--t-sm); line-height: 1.5; color: var(--attenue);
}
@media (max-width: 560px) {
  .rappel__ligne { grid-template-columns: 1fr; }
  .rappel__prix { text-align: left; }
}

/* ═══ TRIPTYQUE RESPONSIVE ═════════════════════════════════════
   Trois appareils de face, alignés sur une même ligne de sol.
   Volontairement à plat : le héros est photographique, en débord
   et en perspective ; deux visuels du même site ne doivent pas se
   ressembler. Le PNG est détouré, il se pose sur n'importe quel
   fond de panneau. */
.triptyque {
  margin: clamp(var(--e6), 4vw, var(--e7)) 0 0;
  max-width: 100%;
}
.triptyque img {
  display: block; width: 100%; height: auto;
  filter: drop-shadow(0 24px 40px rgba(2, 6, 23, 0.16));
}
.triptyque figcaption {
  margin-top: var(--e4);
  font: 600 var(--t-xs)/1.5 var(--mono);
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--attenue);
}
