/* =========================================================================
   SouthCode — feuille de style
   Aucune couleur littérale : tout passe par les variables de tokens.css,
   ce qui rend le contrôle de contraste automatique réellement exhaustif.
   ========================================================================= */

/* Angle partagé des halos lumineux. L'enregistrement CSS laisse le navigateur
   interpoler l'angle sans boucle JavaScript ; les composants gardent leur
   rendu plat si @property ou conic-gradient n'est pas disponible. */
@property --a {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}

/* --- Typographie ---------------------------------------------------------
   Deux fontes auto-hébergées, la limite du projet. Bricolage Grotesque porte
   les titres — elle a du caractère sans être décorative, et ses axes variables
   (graisse, chasse, taille optique) évitent d'embarquer plusieurs fichiers.
   JetBrains Mono porte les chiffres, les étiquettes et les métadonnées : c'est
   elle qui tient le ton « quelqu'un qui construit ».

   Les échelles sont fluides. Une échelle fixe imposerait des points de rupture
   typographiques en plus de ceux de la mise en page ; clamp() n'en impose aucun. */
:root {
  --titre: 'Bricolage Grotesque', 'Bricolage repli', -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
  --mono: 'JetBrains Mono', 'JetBrains repli', ui-monospace, "SF Mono", Menlo, monospace;

  /* Deux échelles de titre, et c'est une nécessité, pas un raffinement :
     « Vous ne perdez plus un appel » tient en quatre mots et supporte 5,5 rem ;
     la phrase de /afflux en fait seize et deviendrait un mur illisible.
     La taille d'un titre dépend de sa longueur, pas de son rang. */
  --t-hero: clamp(2.75rem, 1.6rem + 5.1vw, 5.5rem);   /* accroche courte */

  /* ⚠️ L'ÉCHELLE DES HÉROS VIT ICI, ET NULLE PART AILLEURS — 10 août 2026.
     Les cinq pages en déclaraient chacune une, dans leur propre feuille :
     clamp(3.1rem,7vw,7.8rem) sur /contact, clamp(4rem,6.3vw,8.2rem) sur
     /afflux, clamp(3.45rem,6vw,7.6rem) sur /sites-web, deux autres ailleurs —
     avec cinq chasses et cinq interlignes. Résultat : des héros qui ne se
     ressemblent pas d'une page à l'autre, et un accueil visiblement plus haut.
     Signalé par Raphaël, captures à l'appui.
     Un jeton partagé existait déjà (--t-hero, juste au-dessus) et aucune page ne
     l'employait. Le défaut n'était donc pas l'absence de source unique, mais que
     personne n'y puisait — d'où le test qui interdit désormais à une feuille de
     page de redéclarer une taille de titre de héros.

     Les valeurs ci-dessous sont MESURÉES, pas choisies : à 5 rem et 14ch, aucun
     titre du site ne dépasse quatre lignes et le plus haut fait 251 px. À la
     première tentative — 7,6 rem et 9ch — /realisations en faisait six, soit
     521 px de titre. C'est le rappel de la remarque écrite plus haut sur
     --t-hero : la taille tenable dépend de la longueur de la phrase. */
  --t-hero-page: clamp(3rem, .9rem + 4vw, 5rem);
  --t-hero-interligne: .87;
  --t-hero-chasse: 14ch;
  --t-hero-marge: 26px;
  /* ⚠️ Deuxième passe, 10 août 2026 — même défaut, deux propriétés oubliées.
     La première unification n'avait déplacé que la TAILLE. La chasse et
     l'approche du titre étaient restées dans accueil.css, et la taille du
     sous-titre dans trois feuilles de page. Mesuré à 1440 px avant correction :
     titre à 100 % de chasse sur l'accueil contre 92 % sur les quatre autres —
     Bricolage étant une police variable, 92 % ne « resserre » pas le texte, il
     en redessine les lettres : c'est une autre police à l'œil. Et le sous-titre
     affichait trois tailles pour cinq pages : 16,56 px sur l'accueil, 19,2 px
     sur /sites-web et /contact, 15 px sur /afflux et /realisations.
     Les valeurs retenues sont celles de l'accueil, qui porte le visuel E validé.
     Vérifié après coup : aucun titre ne gagne de ligne, la mesure --t-hero-chasse
     étant en ch, elle s'élargit avec l'axe de chasse et le retour à la ligne ne
     bouge pas (contrôlé sur les cinq pages à 1440 px et à 375 px). */
  --t-hero-graisse-chasse: 100%;
  --t-hero-approche: -.048em;
  --t-hero-lede: clamp(.98rem, 1.15vw, 1.08rem);
  /* Troisième passe, même journée : titre et sous-titre unifiés, le bouton
     d'appel restait à 13,5 px et 44 px de haut sur les quatre pages, contre
     15 px et 50 px sur l'accueil. Une fois le titre aligné, c'est l'écart le
     plus visible du bandeau — et c'est l'élément sur lequel le prospect clique.
     La LARGEUR ne suit pas : les 352 px de l'accueil sont ceux de sa colonne du
     visuel E, ils déborderaient la colonne de 335 px des autres pages sur
     mobile et repousseraient seuls le bouton secondaire à la ligne. */
  --t-hero-bouton: 15px;
  /* ⚠️ Le seul cran à part du site, et il ne concerne QUE le titre anglais de
     l'accueil. Sa structure en trois lignes forcées vient du visuel E validé et
     un test la verrouille ; « Your future customers » passe à deux lignes dès
     57 px dans la colonne de 540 px, ce qui en ferait quatre. Mesuré de 1101 à
     1440 px : ce cran tient les trois lignes partout. */
  --t-hero-page-en: clamp(2.6rem, .7rem + 3.2vw, 4rem);

  --t-h1: clamp(2rem, 1.35rem + 2.6vw, 3.25rem);      /* titre de page */
  --t-h2: clamp(1.95rem, 1.3rem + 2.9vw, 3.6rem);
  --t-h3: clamp(1.15rem, 1.02rem + .55vw, 1.4rem);
  --t-corps: 1.0625rem;
}

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

html {
  -webkit-text-size-adjust: 100%;
  /* ⚠️ color-scheme, ajouté le 6 août sur audit des Web Interface Guidelines
     de Vercel. Ce n'est PAS un doublon des jetons : il ne colore rien de ce
     que nous dessinons, il dit au navigateur de rendre ce que NOUS ne
     dessinons pas — barres de défilement, menus <select>, calendriers,
     champs natifs. Sans lui, un site sombre garde des ascenseurs blancs et
     des listes déroulantes claires, ce qui se voit surtout sous Windows.
     « light dark » et non « dark » seul : le site a les deux thèmes. */
  color-scheme: light dark;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 400 var(--t-corps)/1.6 var(--titre);
}

/* ⚠️ touch-action, même audit. Sur mobile, le navigateur attend ~300 ms après
   un appui pour voir si un second appui suit (double-tap = zoom). « manipulation »
   lui dit que ces éléments n'ont pas de geste de zoom : le délai disparaît et
   chaque bouton répond au premier contact. Posé sur les éléments
   INTERACTIFS seulement — l'appliquer au body désactiverait le double-tap de
   zoom sur le texte, ce qui est une régression d'accessibilité. */
a, button, summary, label, input, select, textarea {
  touch-action: manipulation;
} .statut, .site-footer, .logo, .repere,
.badge, .franchise-encadre, .mention-tva {
  font-family: var(--mono);
}

img { max-width: 100%; height: auto; }

/* --- Accessibilité : socle non négociable ------------------------------- */

.skip {
  position: absolute; left: -9999px;
  background: var(--amber); color: var(--on-amber);
  padding: 10px 16px; border-radius: 0 0 8px 0;
  font-weight: 650; text-decoration: none; z-index: 100;
}
.skip:focus { left: 0; top: 0; }

:focus-visible { outline: 2px solid var(--amber); outline-offset: 2px; }

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

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

/* ⚠️ L'ÉCHELLE DE L'EN-TÊTE VIT ICI, ET NULLE PART AILLEURS — 10 août 2026.
   Ces valeurs étaient enfermées derrière .site-header[data-nav-active=accueil]
   dans accueil.css, une feuille que seule la page d'accueil charge. Résultat
   mesuré à 1440 px : logo 25 px sur l'accueil contre 15,5 px ailleurs,
   navigation 16 px contre 12,5 px, statut 13 px contre 11,5 px, et deux
   sélecteurs de langue différents. C'est le bandeau du haut, celui qu'on voit
   sur CHAQUE page avant tout le reste, et il rapetissait dès qu'on quittait
   l'accueil. Signalé par Raphaël — troisième signalement du même défaut sous
   trois formes, après le titre puis le bouton du héros.
   Le verrou par attribut est retiré : la règle vaut pour tout le site. */
.site-header {
  display: flex; align-items: center; justify-content: space-between;
  gap: 20px; flex-wrap: wrap;
  position: relative;
  min-height: 73px;
  padding: 14px 32px;
  border-bottom: 1px solid var(--border);
}
.logo { font-size: 25px; line-height: 1; font-weight: 600; letter-spacing: -.02em; color: var(--text); text-decoration: none; }
.logo-marque { width: 32px; height: 26px; margin-right: 8px; }
.logo b { color: var(--amber); font-weight: 600; }
.logo span { color: var(--faint); font-weight: 500; display: inline-flex; align-items: baseline; }
.logo small { margin-left: 10px; font: 550 9px/1 var(--mono); letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }

/* Position absolue : la navigation est ancrée au tiers de la barre plutôt que
   poussée par le flux, sinon sa place bouge avec la longueur du logo et des
   libellés traduits. C'est le placement du visuel E, désormais commun. */
.site-header nav { display: flex; gap: clamp(12px, 1.8vw, 28px); position: absolute; left: 27%; }
.site-header nav a {
  position: relative; display: inline-flex; align-items: center; justify-content: center;
  min-width: 44px; min-height: 44px;
  font: 500 16px var(--mono);
  color: var(--muted); text-decoration: none;
  padding: 4px 3px; transition: color .18s ease;
}
.site-header nav a:hover { color: var(--text); }
/* LE SOULIGNEMENT ANIMÉ — un ::after qui grandit depuis la gauche plutôt que
   le box-shadow statique d'avant. Un seul mécanisme sert les deux états :
   au survol il grandit en 0,28 s, sur la page active il est déjà à sa taille
   finale — pas de « saut » à l'arrivée, juste rien à animer. */
.site-header nav a::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: -1px;
  height: 2px; border-radius: 1px;
  background: var(--amber);
  transform: scaleX(0); transform-origin: left;
  transition: transform .28s cubic-bezier(.16,1,.3,1);
}
.site-header nav a:hover::after,
.site-header nav a[aria-current="page"]::after { transform: scaleX(1); }
.site-header nav a[aria-current="page"] { color: var(--text); }
.site-header[data-nav-active="services"] [data-nav="services"],
.site-header[data-nav-active="sites-web"] [data-nav="services"],
.site-header[data-nav-active="afflux"] [data-nav="afflux"],
.site-header[data-nav-active="realisations"] [data-nav="realisations"],
.site-header[data-nav-active="tarifs"] [data-nav="tarifs"],
.site-header[data-nav-active="agence"] [data-nav="agence"] { color: var(--text); }
.site-header[data-nav-active="services"] [data-nav="services"]::after,
.site-header[data-nav-active="sites-web"] [data-nav="services"]::after,
.site-header[data-nav-active="afflux"] [data-nav="afflux"]::after,
.site-header[data-nav-active="realisations"] [data-nav="realisations"]::after,
.site-header[data-nav-active="tarifs"] [data-nav="tarifs"]::after,
.site-header[data-nav-active="agence"] [data-nav="agence"]::after { transform: scaleX(1); }

.entete-droite { display: flex; align-items: center; gap: 20px; margin: 0; max-width: none; }
.entete-action {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 44px; padding: 0 16px; border-radius: 8px;
  background: var(--amber); color: var(--on-amber);
  font: 650 12px/1 var(--mono); text-decoration: none;
}

/* L'INTERRUPTEUR DE LANGUE — un lien réel vers la page équivalente dans
   l'autre langue (navigation, pas une préférence à mémoriser), habillé en
   commutateur à deux positions. CSS pur, zéro JS : chaque partiel (fr/en)
   sait déjà quelle langue est active au moment où le serveur le rend, donc
   la position du curseur se code en dur dans SA version du partiel — pas
   besoin d'un état à calculer côté client pour deux valeurs qui ne changent
   jamais après le rendu. */
/* ⚠️ LES DEUX PASTILLES « FR | EN » REMPLACENT L'INTERRUPTEUR « English ⚪
   Français » SUR TOUT LE SITE — 10 août 2026, et c'est un revirement assumé.
   Le commentaire d'origine défendait les mots en toutes lettres : moins
   ambigus qu'un code à deux lettres pour un anglophone. L'argument tient
   toujours. Mais l'accueil, qui suit le visuel E, portait DÉJÀ les pastilles,
   et le site affichait donc deux commutateurs différents selon la page —
   exactement l'incohérence signalée. Entre deux formes correctes, une seule
   partout vaut mieux que la meilleure des deux à moitié.
   ⚠️ Ce qui rend le choix acceptable : le nom accessible ne vient PAS de ce
   qu'on voit. Le partiel porte un aria-label dans la langue de la page —
   « Passer en anglais » ou « Switch to French ». Masquer les mots ne retire donc rien
   au lecteur d'écran. Sans cet aria-label, ce changement serait une régression
   et ne devrait pas être fait. Pour revenir aux mots : rétablir ce bloc depuis
   l'historique et retirer le display:none ci-dessous. */
.langue {
  text-decoration: none;
  display: inline-flex; align-items: center; gap: 18px;
  min-height: 44px;
  padding: 0;
  border: 0;
  background: transparent;
}
.langue-mot, .langue-piste { display: none; }
.langue::before, .langue::after { font: 600 15px var(--mono); }
.langue::before {
  content: 'FR';
  min-width: 68px; min-height: 42px;
  display: grid; place-items: center;
  border: 1px solid var(--border2);
  border-radius: 999px;
  color: var(--text);
  transition: border-color .18s ease;
}
.langue::after { content: 'EN'; color: var(--muted); }
.langue:hover::before { border-color: var(--muted); }
/* Le partiel anglais pose .langue--en : les deux pastilles s'inversent. */
.langue--en::before { content: 'EN'; }
.langue--en::after { content: 'FR'; }
.statut {
  display: inline-flex; align-items: center; gap: 7px; margin: 0;
  min-width: 190px; min-height: 42px;
  justify-content: center;
  padding: 0 18px;
  border: 1px solid var(--border2);
  border-radius: 8px;
  font: 500 13px var(--mono);
  color: var(--muted);
}
.pastille { width: 7px; height: 7px; border-radius: 50%; background: var(--green); display: inline-block; flex: none; }

/* Le repli de l'en-tête. En dessous de 1100 px la navigation absolue n'a plus
   la place d'être ancrée au tiers : elle repasse dans le flux. Valeurs reprises
   telles quelles du repli de l'accueil, qui les avait déjà éprouvées. */
/* 1140 et non 1100, et c'est mesuré : à 1101 px la navigation ANGLAISE, plus
   longue que la française, arrivait à 2 px du bloc de droite — elle ne se
   chevauchait pas, elle frôlait, ce qu'aucun test de chevauchement n'attrape.
   L'écart repasse à 16 px dès 1120 px. Repli à 1140 pour garder de la marge. */
@media (max-width: 1140px) {
  .site-header { padding-inline: 24px; }
  .logo { font-size: 21px; }
  .site-header nav { position: static; gap: 18px; }
  .site-header nav a { font-size: 13px; }
}
@media (max-width: 720px) {
  .site-header { padding-inline: 20px; }
  .entete-droite { gap: 10px; }
  .statut { display: none; }
  .logo small { display: none; }
  .entete-action { padding-inline: 12px; }
}

main { padding: 0; }

/* --- Héros -------------------------------------------------------------- */

.hero {
  display: grid; grid-template-columns: 1fr 1.02fr; gap: 40px;
  align-items: center;
  padding: 50px 40px 20px;
}

h1 {
  font-size: var(--t-h1); line-height: .98;
  letter-spacing: -.045em; font-weight: 700;
  /* La chasse resserrée est un axe variable de Bricolage : le titre gagne en
     densité sans qu'on change de fichier de police. */
  font-stretch: 92%;
  margin: 0 0 20px;
  /* max-width en em et non en ch : l'unité ch vaut la largeur du « 0 » de la
     police courante, donc la boîte du titre changeait de largeur au moment du
     remplacement de police, le texte se recoupait, et toute la page descendait.
     Mesuré : CLS 0,10 en ch, et le titre porte le LCP. L'em ne dépend que de
     la taille, jamais de la fonte. */
  max-width: 8.5em;
  text-wrap: balance;
}
h1 mark { background: none; color: var(--amber); }

/* LE BANDEAU DE HÉROS, IDENTIQUE SUR TOUTES LES PAGES. Une seule règle, un
   seul endroit. Les feuilles de page n'ont plus le droit d'y toucher — c'est
   vérifié par test/typographie.test.js. */
.accueil-hero h1,
.sites-hero h1,
.afflux-hero h1,
.contact-hero h1,
.page-hero h1 {
  font-size: var(--t-hero-page);
  line-height: var(--t-hero-interligne);
  max-width: var(--t-hero-chasse);
  margin: 0 0 var(--t-hero-marge);
  font-stretch: var(--t-hero-graisse-chasse);
  letter-spacing: var(--t-hero-approche);
}
/* Le sous-titre appartient au bandeau autant que le titre : trois tailles pour
   cinq pages se voyaient à l'œil nu au passage d'une page à l'autre. La mesure
   (max-width) reste propre à chaque page — c'est la largeur de sa colonne, pas
   une taille de police. */
.accueil-hero .lede,
.sites-hero .lede,
.afflux-hero .lede,
.contact-hero .lede,
.page-hero .lede {
  font-size: var(--t-hero-lede);
}

/* Le bouton d'appel du bandeau. Les cinq héros sont listés par :is() plutôt
   qu'en trois listes recopiées — même portée, un tiers des lignes.
   L'ombre et la saturation viennent aussi de l'accueil : appliquées aux MÊMES
   jetons, elles produisent exactement les mêmes pixels qu'un bouton déjà publié,
   donc exactement le même contraste. Ce n'est pas un risque nouveau. */
:is(.accueil-hero, .sites-hero, .afflux-hero, .contact-hero, .page-hero)
  :is(.bouton, .bouton-secondaire) {
  font-size: var(--t-hero-bouton);
  min-height: 50px;
  padding-inline: 22px;
}
:is(.accueil-hero, .sites-hero, .afflux-hero, .contact-hero, .page-hero) .bouton {
  box-shadow: 0 10px 34px color-mix(in srgb, var(--amber) 21%, transparent);
}
:is(.accueil-hero, .sites-hero, .afflux-hero, .contact-hero, .page-hero) .bouton::after {
  content: '→'; margin-left: 16px; font-size: 20px; line-height: 1;
}

/* ⚠️ L'ORANGE VIF EST DEVENU LE JETON, LE FILTRE A ÉTÉ SUPPRIMÉ — 10 août 2026.
   L'accueil peignait son mot surligné et son bouton avec
   `filter: saturate(1.65) brightness(1.13)` par-dessus --amber. Les autres
   pages n'avaient que le jeton nu : d'où deux oranges à l'écran pour une seule
   couleur dans les fichiers — vif sur l'accueil, brique ailleurs. Signalé.
   Le réflexe était d'étendre le filtre aux quatre autres pages. MESURÉ AVANT
   DE LE FAIRE, en thème clair :

     mot surligné   5,53:1 nu  →  3,43:1 filtré
     bouton         5,94:1 nu  →  3,69:1 filtré

   Les deux passent sous 4,5:1. Le filtre s'applique au rendu, après la
   cascade : le produit croisé de build.js lit #A6471A, le déclare bon, et le
   navigateur dessine autre chose. Le défaut vivait donc en ligne sur l'accueil
   sans que rien ne le voie, et l'étendre l'aurait multiplié par cinq.
   Le jeton porte désormais l'orange vif lui-même — même teinte que ce que le
   filtre produisait, assombri juste assez pour passer (4,53:1 sur le fond,
   4,87:1 sur blanc). Une couleur, aucun filtre, et le contrôle automatique la
   voit enfin. outils/verifier-contraste-mark.js interdit la réintroduction. */
/* L'accueil partage taille, interligne et marge avec les quatre autres. Il ne
   s'en écarte que par la mesure — ses trois lignes sont forcées dans le
   balisage, elles n'ont donc pas à être bornées. */
.accueil-hero h1 { max-width: none; }
/* Les deux seuls crans à part du site, et ils ne concernent QUE le titre
   anglais de l'accueil : sa structure en trois lignes forcées vient du visuel E
   validé et un test la verrouille. L'approche resserrée accompagne la taille
   réduite ; séparées, les trois lignes ne tiennent plus. */
html[lang=en] .accueil-hero h1 { font-size: var(--t-hero-page-en); letter-spacing: -.055em; }

.lede { font-size: 15px; line-height: 1.62; color: var(--muted); max-width: 47ch; margin: 0 0 18px; }
.lede b { color: var(--text); font-weight: 600; }

.actions { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; margin: 0; }
.bouton {
  display: inline-block; font-size: 13.5px; font-weight: 650;
  padding: 12px 22px; border-radius: 8px;
  background: var(--amber); color: var(--on-amber);
  border: 1px solid transparent;
  text-decoration: none; transition: transform .18s ease;
  min-height: 44px; line-height: 20px;
}
.bouton:hover { transform: translateY(-2px); }
.bouton-secondaire {
  display: inline-block; font-size: 13.5px; font-weight: 650;
  padding: 12px 20px; border-radius: 8px;
  border: 1px solid var(--border2); color: var(--text);
  text-decoration: none; min-height: 44px; line-height: 20px;
  transition: border-color .18s ease;
}
.bouton-secondaire:hover { border-color: var(--muted); }

/* La bordure conique apporte une lueur discrète aux actions importantes. Le
   fond reste le même jeton de couleur : seul le filet de 1 px est animé, donc
   le contraste du texte et la surface de clic ne changent jamais. */
@supports (background: conic-gradient(from 0deg, #000, #fff)) {
  .bouton {
    background:
      linear-gradient(var(--amber), var(--amber)) padding-box,
      conic-gradient(from var(--a), transparent 0 22%, color-mix(in srgb, var(--cyan) 78%, transparent) 33%, transparent 46% 68%, color-mix(in srgb, var(--amber) 92%, transparent) 80%, transparent 93%) border-box;
  }
  .bouton-secondaire {
    border-color: transparent;
    background:
      linear-gradient(var(--surface), var(--surface)) padding-box,
      conic-gradient(from var(--a), transparent 0 22%, color-mix(in srgb, var(--cyan) 64%, transparent) 33%, transparent 46% 68%, color-mix(in srgb, var(--amber) 72%, transparent) 80%, transparent 93%) border-box;
  }
  @media (prefers-reduced-motion: no-preference) {
    .bouton, .bouton-secondaire { animation: southcode-halo 7s linear infinite; }
  }
}

@keyframes southcode-halo { to { --a: 1turn; } }

.conversation { list-style: none; margin: 0; padding: 14px 14px 4px; font-size: 12px; line-height: 1.58; }
.conversation li { margin-bottom: 11px; }
.repere {
  font-family: var(--mono);
  font-size: 10.5px; font-weight: 500; letter-spacing: .1em; text-transform: uppercase;
  color: var(--amber); margin: 0 0 10px;
}
/* L'INTERLIGNE DES TITRES — corrigé le 5 août 2026.
   h1 avait le sien (.98) ; h2 n'en avait aucun et héritait donc de celui du
   texte courant, 1,6. À 58 px, cela donnait 92 px par ligne : un titre de deux
   lignes occupait 184 px là où 125 suffisent. Multiplié par six titres, c'est
   la moitié du « vide » qu'on voyait sur la page. Un interligne est un rapport,
   pas une valeur : plus le corps grandit, plus il doit se resserrer. */
h2 { font-size: var(--t-h2); line-height: 1.08; letter-spacing: -.035em; font-weight: 680; text-wrap: balance; margin: 0 0 8px; }
.sous-titre { font-size: 15px; color: var(--muted); margin: 0 0 20px; max-width: 62ch; line-height: 1.6; }
.sous-titre b { color: var(--text); }

.franchise-encadre {
  margin: 14px 0 0; max-width: none;
  font-size: 11.8px; font-weight: 500; line-height: 1.65; color: var(--faint);
  border-left: 2px solid var(--amber); padding: 6px 0 6px 12px;
}
.franchise-encadre b { color: var(--amber); }
.badge {
  position: absolute; top: 20px; right: 20px; margin: 0;
  font-size: 9.5px; font-weight: 600; letter-spacing: .1em; text-transform: uppercase;
  padding: 4px 9px; border-radius: 5px;
  background: var(--bg); color: var(--green); border: 1px solid var(--border2);
  /* ⚠️ width: fit-content, et ce n'est pas une précaution théorique. L'étiquette
     se serrait sur son texte uniquement parce que position:absolute la
     rétrécit. Dès qu'une page la repasse en flux — .afflux-canal le fait pour
     la placer sous le numéro — le <p> redevient bloc, donc pleine largeur, et
     le cadre s'étire en longue barre grise par-dessus le 01/02/03. Signalé par
     Raphaël sur /afflux. Corrigé ici plutôt que chez l'appelant : la règle vaut
     pour toute page qui remettra un badge dans le flux. */
  width: fit-content;
}
.mention-tva { margin-top: 12px !important; font-size: 11px; color: var(--faint); }

/* --- Pages intérieures ----------------------------------------------------- */

/* Enveloppe générique : toute nouvelle section l'utilise, ce qui évite d'avoir
   à rallonger la liste des sélecteurs de la requête média mobile à chaque fois. */

/* =========================================================================
   SYSTÈME DE MISE EN PAGE  —  5 août 2026
   -------------------------------------------------------------------------
   CE QU'IL REMPLACE. Chaque section portait « padding: 34px 40px », la même
   valeur pour toutes, et 8 px seulement entre deux sections consécutives.
   Résultat : aucun rythme vertical, aucune hiérarchie, et tout élément qui
   devait déborder de la colonne de texte devait le faire en position absolue
   — avec un z-index inventé au cas par cas. C'est la cause des cinq rustines
   du 5 août, pas leur symptôme.

   LA GRILLE NOMMÉE. Chaque section est une grille de cinq pistes. Un enfant
   atterrit dans « contenu » sans rien déclarer ; celui qui doit traverser
   toute la largeur déclare « grid-column: pleine » — une ligne, plus de
   position absolue, plus de z-index à négocier.

   ⚠️ Les suffixes -start et -end font partie de la GRAMMAIRE CSS, pas d'une
   convention libre : c'est eux qui permettent d'écrire « grid-column: contenu »
   au lieu de « contenu-start / contenu-end ». Nommés -debut/-fin, le nom court
   ne résout rien et le navigateur crée une colonne implicite où tout s'entasse.

     pleine   ├────────────────────────────────────────────┤  bord à bord
     large    │    ├──────────────────────────────────┤    │  tableaux, cartes
     contenu  │        ├──────────────────────┤           │  texte, titres
   ========================================================================= */

:root {
  /* Échelle d'espacement, fluide. Une seule source pour tout le rythme du
     site : changer une valeur ici recale toutes les pages. */
  --e-1: clamp(8px, 1vw, 12px);
  --e-2: clamp(16px, 2vw, 22px);
  --e-3: clamp(26px, 3.2vw, 38px);
  --e-4: clamp(44px, 5.5vw, 68px);
  /* --e-5 resserré le 5 août 2026 : 104 px de haut PLUS 104 px de bas entre
     deux sections faisaient plus de 200 px de blanc, et sur une page de sept
     sections c'est un demi-écran de vide cumulé. C'est le rythme du site, pas
     un détail local — d'où la correction ici, dans la seule source. */
  --e-5: clamp(56px, 6.2vw, 82px);
  --e-6: clamp(80px, 9vw, 122px);
  --marge: clamp(22px, 4vw, 56px);
  --contenu: 66rem;
}

.section {
  display: grid;
  grid-template-columns:
    [pleine-start] minmax(var(--marge), 1fr)
    [large-start]  minmax(0, 7rem)
    [contenu-start] min(100% - var(--marge) * 2, var(--contenu)) [contenu-end]
    minmax(0, 7rem)  [large-end]
    minmax(var(--marge), 1fr) [pleine-end];
  /* Le rythme vertical. C'est lui qui fait qu'un site respire ou non. */
  padding: var(--e-5) 0;
  row-gap: var(--e-2);
}
.section > * { grid-column: contenu; }
.section > .large,
.section > .etapes,
.section > .faq { grid-column: large; }

/* Deux sections voisines ne cumulent pas leurs marges : la seconde reprend au
   demi-pas. Sans cette règle on obtient soit un trou, soit un accolement. */
.section + .section { padding-top: var(--e-3); }

/* En-tête de section : le contraste d'échelle est ici, et c'est le levier
   visuel le moins cher du site. Une étiquette minuscule en monospace contre
   un titre très grand — l'œil sait immédiatement où il est. */
.section > .repere + h2,
.section > h2 { margin-bottom: var(--e-1); }
.section > .sous-titre { margin-bottom: var(--e-2); }

.fond-surface {
  background: var(--surface);
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}
.section.fond-surface + .section { padding-top: var(--e-5); }

.page-entete { padding: 46px 40px 26px; }
.page-entete h1 { max-width: 24ch; }
.page-entete .lede { max-width: 58ch; }
.page-entete .actions { margin-top: 4px; }

.texte-large {
  font-size: 13.8px; line-height: 1.68; color: var(--muted);
  max-width: 74ch; margin: 0 0 14px;
}
.texte-large b { color: var(--text); font-weight: 600; }

/* --- Étapes ----------------------------------------------------------------- */

.etapes {
  list-style: none; margin: 6px 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px;
}
.etapes li {
  border: 1px solid var(--border); border-radius: 11px;
  padding: 20px 22px 22px; background: var(--bg);
}
.etapes h3 { font-size: 15px; letter-spacing: -.02em; font-weight: 640; margin: 0 0 8px; }
.etapes p { font-size: 12.8px; line-height: 1.6; color: var(--muted); margin: 0; }
.etapes p b { color: var(--text); font-weight: 600; }

/* --- Questions fréquentes ---------------------------------------------------- */

.faq {
  display: grid; grid-template-columns: 1fr 1fr; gap: 14px 30px;
  margin-top: 6px;
}
.faq article { border-top: 1px solid var(--border); padding-top: 14px; }
.faq h3 { font-size: 14px; letter-spacing: -.02em; font-weight: 640; margin: 0 0 7px; }
.faq p { font-size: 12.8px; line-height: 1.62; color: var(--muted); margin: 0; max-width: 56ch; }
.faq p b { color: var(--text); font-weight: 600; }

/* --- Appel à l'action -------------------------------------------------------- */

.appel { border-top: 1px solid var(--border); padding-top: 30px; }
.appel h2 { max-width: 22ch; }
.appel .actions { margin-top: 18px; }

/* --- Pages légales ----------------------------------------------------------- */

.page-legale h2 { font-size: 17.5px; letter-spacing: -.025em; margin: 28px 0 12px; }
.page-legale > h2:first-child { margin-top: 0; }
.page-legale h3 { font-size: 14px; font-weight: 640; letter-spacing: -.015em; margin: 22px 0 7px; }
.page-legale .contact-infos { max-width: 62ch; margin-bottom: 26px; }
.page-legale .franchise-encadre { max-width: 74ch; margin-top: 6px; }
.page-legale code {
  font: 500 12.3px var(--mono);
  background: var(--raised); border: 1px solid var(--border);
  border-radius: 4px; padding: 1px 5px;
}

.formulaire p { margin: 0 0 16px; max-width: 46ch; }
.formulaire label {
  display: block; margin-bottom: 6px;
  font: 500 12.5px var(--mono);
  color: var(--muted);
}
.formulaire .facultatif { color: var(--faint); font-weight: 400; }

.formulaire input[type="text"], .formulaire input[type="email"],
.formulaire input[type="tel"], .formulaire textarea, .formulaire select {
  width: 100%; padding: 11px 13px; min-height: 44px;
  font: 400 14px/1.5 -apple-system, BlinkMacSystemFont, "Inter", "Segoe UI", Helvetica, Arial, sans-serif;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--border2); border-radius: 8px;
  transition: border-color .18s ease;
}
.formulaire textarea { resize: vertical; min-height: 130px; }
.formulaire input:hover, .formulaire textarea:hover { border-color: var(--muted); }
.formulaire ::placeholder { color: var(--faint); }

/* Le champ piège se masque sans display:none : certains robots détectent
   display:none et sautent le champ, ce qui annulerait le filtre. */
.piege { position: absolute; left: -9999px; }

.consentement label {
  display: flex; gap: 10px; align-items: flex-start;
  min-height: 44px;
  font-family: inherit; font-size: 12.8px; line-height: 1.55;
  color: var(--muted); cursor: pointer;
}
.consentement input[type="checkbox"] { width: 18px; height: 18px; margin: 1px 0 0; flex: none; accent-color: var(--amber); }
.consentement a { color: var(--amber); }

.faq h3 a {
  display: inline-flex; align-items: center;
  min-width: 44px; min-height: 44px;
}
.contact-infos { margin: 0 0 20px; font-size: 12.8px; line-height: 1.6; }
.contact-infos dt {
  font: 600 10.5px var(--mono);
  letter-spacing: .11em; text-transform: uppercase;
  color: var(--faint); margin-top: 14px;
}
.contact-infos dt:first-child { margin-top: 0; }
.contact-infos dd { margin: 4px 0 0; color: var(--muted); }
.contact-infos a { color: var(--amber); }

/* --- Pied de page --------------------------------------------------------- */

.site-footer {
  display: flex; align-items: center; justify-content: space-between;
  gap: 14px; flex-wrap: wrap;
  padding: 17px 40px 21px;
  border-top: 1px solid var(--border);
  font-size: 11px; font-weight: 500; color: var(--faint);
}
.site-footer p { margin: 0; max-width: none; }
.site-footer .liens { display: flex; align-items: center; gap: 16px; }

/* ⚠️ TAILLE DE CIBLE — SORTIE DE LA REQUÊTE MÉDIA LE 10 AOÛT 2026.
   Ces déclarations ne s'appliquaient qu'en dessous de 860 px : le commentaire
   d'origine disait « l'aspect du bureau, validé sur maquette, n'est pas
   touché ». L'intention était juste, la borne ne l'était pas. Mesuré sur
   ordinateur à 1440 px :

     mentions légales               106 × 18 px
     Me parler de votre entreprise  192 × 15 px
     ☾ thème sombre                 118 × 32 px
     logo southcode                 181 × 26 px

   Les deux premières sont sous 24 px, c'est-à-dire sous le MINIMUM du WCAG 2.2
   AA (2.5.8), qui ne connaît pas de dérogation « bureau ». Un écran tactile de
   1440 px de large existe — tout portable convertible en est un — et la souris
   n'est pas le seul dispositif de pointage. La règle vaut donc partout.
   La composition ne bouge pas : ces liens gagnent de la hauteur autour de leur
   texte, pas de la largeur, et la ligne du pied de page était déjà plus haute
   que 44 px du fait de son interlignage. */
.logo,
.site-header nav a,
.site-footer .liens a,
.contact-infos dd a,
.langue { display: inline-flex; align-items: center; min-height: 44px; }
/* Le bouton de thème porte sa hauteur dans SA règle, plus bas : une seconde
   déclaration ici serait écrasée par elle — c'est ce qui s'est produit à la
   première tentative, le bouton restait à 32 px. */
.site-footer a { color: var(--faint); }

#bascule-theme {
  font: 500 11px var(--mono);
  color: var(--muted); background: transparent;
  border: 1px solid var(--border2); border-radius: 999px;
  padding: 6px 12px; cursor: pointer;
  /* 44 et non 32 : c'est une cible de pointage, soumise au WCAG 2.2 AA comme
     les liens voisins. Elle vaut à toutes les largeurs. */
  display: inline-flex; align-items: center; min-height: 44px;
  transition: color .18s ease, border-color .18s ease;
}
#bascule-theme:hover { color: var(--text); border-color: var(--muted); }

/* --- Réduction du mouvement ------------------------------------------------ */

@media (prefers-reduced-motion: reduce) {
  /* Coupure CIBLÉE, et c'est une correction d'audit du 5 août.
     La version précédente supprimait TOUTE transition et TOUTE animation. Elle
     emportait aussi les retours utiles — le changement de couleur au focus, la
     bordure qui s'allume au survol — qui ne sont pas de la décoration mais de
     l'information d'état. WCAG 2.3.3 demande de retirer le mouvement superflu,
     pas tout retour visuel.

     Règle appliquée : ce qui DÉPLACE disparaît, ce qui change une COULEUR reste. */
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-property: color, background-color, border-color, outline-color, opacity !important;
    transition-duration: .12s !important;
  } .bouton:hover,
  .logo:hover .logo-marque{ transform: none !important; }
}

/* --- Mobile ---------------------------------------------------------------- */

@media (max-width: 860px) {
  .hero, .etapes, .faq{ grid-template-columns: 1fr; }

  /* La taille de cible a quitté cette requête média — voir la règle commune
     plus haut. Elle ne valait qu'en dessous de 860 px. */

  /* Ne sont volontairement pas élargis : les liens situés à l'intérieur d'une
     phrase — « En savoir plus », une adresse email dans un paragraphe, le lien
     vers la CNIL. Les grossir casserait l'interlignage du texte, et la règle
     de taille de cible du WCAG 2.2 les exempte explicitement. La case de
     consentement du formulaire n'est pas concernée non plus : son <label>
     enveloppe le champ, la zone réellement cliquable est la ligne entière. */
  .hero { gap: 28px; }
  .faq p { max-width: none; }
}

@media (max-width: 720px) {
  .site-header, .hero, .section, .site-footer { padding-left: 20px; padding-right: 20px; }
  .site-header nav { gap: 16px; order: 3; width: 100%; }
}

/* --- Mouvement -----------------------------------------------------------
   L'état par défaut d'un élément est son état LISIBLE. La classe .a-reveler
   n'est posée que par mouvement.js, et seulement si le visiteur n'a pas
   demandé moins de mouvement. Écrire opacity:0 ici, dans la feuille, laisserait
   une page vide à qui a coché la case — c'est le bogue classique du défilement
   animé, et il se prévient par l'ordre des choses, pas par une exception. */

.a-reveler { opacity: 0; transform: translateY(14px); }
.a-reveler.revele {
  opacity: 1; transform: none;
  transition: opacity .55s cubic-bezier(.2,.7,.3,1), transform .55s cubic-bezier(.2,.7,.3,1);
}
/* Cascade sur une liste : chaque élément part un cran après le précédent. */
.a-reveler:nth-child(2) { transition-delay: .07s; }
.a-reveler:nth-child(3) { transition-delay: .14s; }
.a-reveler:nth-child(4) { transition-delay: .21s; }

@media (prefers-reduced-motion: reduce) {
  /* Ceinture et bretelles : mouvement.js ne pose pas .a-reveler dans ce cas,
     mais si une classe passait quand même, rien ne doit rester caché.
     La coupure générale des transitions et animations est déjà faite plus
     haut (« Réduction du mouvement ») — ne pas la redoubler ici, un second
     bloc plus permissif l'affaiblirait au lieu de la renforcer. */
  .a-reveler, .a-reveler.revele { opacity: 1; transform: none; }
}

/* =========================================================================
   TRANSITIONS DE VUE ENTRE PAGES  —  @view-transition
   -------------------------------------------------------------------------
   Trois lignes de CSS, et un site statique de 20 pages cesse de « recharger » :
   il se transforme. C'est natif depuis 2025, sans une ligne de JavaScript et
   sans bibliothèque — donc sans dépendance, sans requête tierce, sans risque
   de chaîne d'approvisionnement.

   Pourquoi ça vaut le coup ici : le prospect qui passe de l'accueil aux tarifs
   ne doit pas avoir l'impression de quitter une page pour en attendre une
   autre. La continuité visuelle est ce qui distingue un site fait sur mesure
   d'un empilement de gabarits.

   Dégradation : un navigateur qui ne connaît pas @view-transition navigue
   normalement. Rien à prévoir.
   ========================================================================= */

@view-transition { navigation: auto; }

/* Les éléments qui PERSISTENT d'une page à l'autre sont nommés : le navigateur
   les fait glisser d'une position à l'autre au lieu de les refondre. */
.logo { view-transition-name: logo; }
.site-header nav { view-transition-name: navigation; }
.site-footer { view-transition-name: pied; }

::view-transition-group(logo),
::view-transition-group(navigation),
::view-transition-group(pied) { animation-duration: .38s; }

/* Le corps de page, lui, se croise en fondu court — assez pour lier, assez
   court pour ne jamais donner l'impression d'attendre. */
::view-transition-old(root) { animation: vt-sortie .22s cubic-bezier(.4,0,1,1) both; }
::view-transition-new(root) { animation: vt-entree .34s cubic-bezier(0,0,.2,1) both; }

@keyframes vt-sortie { to { opacity: 0; transform: translateY(-8px); } }
@keyframes vt-entree { from { opacity: 0; transform: translateY(10px); } }

@media (prefers-reduced-motion: reduce) {
  /* La transition de vue est du mouvement : elle disparaît comme le reste. */
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) { animation: none !important; }
}

/* --- La marque -----------------------------------------------------------
   Le signe est celui du favicon : une invite de terminal, chevron et curseur.
   Il est écrit en SVG dans la page, donc il hérite de currentColor — il suit
   le thème et le survol sans qu'on ait à produire deux fichiers.

   Il n'a PAS été généré : un logo doit rester vectoriel. Une image générée ne
   tient pas à 16 px, ne change pas de couleur avec le thème, et devient floue
   dès qu'on l'agrandit. */

.logo { display: inline-flex; align-items: center; gap: 10px; }
.logo-marque { flex: none; color: var(--amber); transition: color .2s ease, transform .3s cubic-bezier(.16,1,.3,1); }
.logo:hover .logo-marque { transform: translateX(2px); }
.logo span { color: var(--text); }
.logo span b { color: var(--amber); font-weight: 600; }
@keyframes barre-pousse { from { transform: scaleY(.06); } to { transform: none; } }

/* --- Le flux ------------------------------------------------------------
   Le canevas occupe le héros d'Afflux, derrière le bloc de conversation.
   Il ne porte aucun texte : le contraste des titres reste celui du fond de
   page, jamais celui d'une image en mouvement. C'est ce qui permet une
   animation dense sans jamais mettre la lisibilité en jeu. */

.hero { position: relative; }

/* Le voile sous la colonne de texte. C'est lui qui rend le flux plein-cadre
   acceptable : le titre et le paragraphe reposent sur le fond de page opaque,
   jamais sur des particules en mouvement. Le contraste mesuré reste celui de
   --text sur --bg, soit 16,5:1 — la présence du flux ne l'entame pas.

   C'est la traduction littérale de la règle 14 : « impose un voile
   assombrissant » — sauf qu'ici le voile n'assombrit pas une vidéo claire,
   il rétablit le fond sous le texte. */
.hero::before {
  content: '';
  position: absolute; inset: 0 auto 0 0;
  width: min(58%, 780px);
  background: linear-gradient(to right, var(--bg) 0%, var(--bg) 58%, transparent 100%);
  /* Au-DESSUS du flux, en-DESSOUS du texte. Un pseudo-élément ::before est
     peint avant les enfants : sans z-index explicite, le canevas repassait
     par-dessus le voile et les particules traversaient les paragraphes. */
  z-index: 1; pointer-events: none;
}
@media (max-width: 860px) { .hero::before { display: none; } }

.section > details {
  grid-column: contenu;
  border-bottom: 1px solid var(--border);
}
.section > details:first-of-type { border-top: 1px solid var(--border); }

.section > details > summary {
  display: flex; align-items: baseline; gap: 14px;
  padding: 20px 4px;
  cursor: pointer;
  font-size: var(--t-h3); font-weight: 650; letter-spacing: -.02em;
  color: var(--text);
  list-style: none;                 /* la puce par défaut de Safari */
  min-height: 44px;
  transition: color .18s ease;
}
.section > details > summary::-webkit-details-marker { display: none; }
.section > details > summary:hover { color: var(--amber); }
.section > details > summary:focus-visible { outline: 2px solid var(--amber); outline-offset: 3px; }

/* Le signe d'ouverture, dessiné et non un glyphe : le plancher de qualité
   interdit un caractère Unicode en guise d'icône. */
.section > details > summary::before {
  content: '';
  flex: none; width: 11px; height: 11px; margin-top: .34em;
  border-right: 2px solid var(--amber); border-bottom: 2px solid var(--amber);
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform .22s cubic-bezier(.16,1,.3,1);
}
.section > details[open] > summary::before { transform: rotate(225deg) translate(-2px, -2px); }

/* ═══════════════════════════════════════════════════════════════════════════
   LE CALCUL DE PERTE — rétabli le 20 août 2026.
   Ce bloc et calcul.js avaient été écrits, puis supprimés le 13 août comme code
   mort : aucune page ne les appelait. Ils n'étaient pas morts, ils étaient
   ORPHELINS — construits pour /afflux et l'accueil, jamais branchés. Même
   histoire que la classe « nuit ».
   Le principe vaut d'être répété : le visiteur règle SES chiffres, donc aucune
   moyenne de marché n'est avancée, donc il n'y a aucune source à défendre — et
   le résultat lui est incontestable puisqu'il vient de le produire.
   ═══════════════════════════════════════════════════════════════════════════ */

/* --- Le verdict ---------------------------------------------------------- */
.verdict { border-left: 1px solid var(--border2); padding-left: 34px; align-self: center; }
.verdict-somme {
  font: 640 clamp(38px, 4.4vw, 52px)/1 -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, sans-serif;
  letter-spacing: -.04em; color: var(--amber); font-variant-numeric: tabular-nums; margin: 0;
}
.verdict-legende { font-size: 14px; color: var(--muted); margin: 8px 0 0; max-width: 30ch; }

/* Deux barres proportionnelles — le même langage visuel que les durées de
   soin de la démonstration institut. La comparaison se voit avant de se lire. */
.barres { margin: 24px 0 0; }
.barre-ligne { margin: 0 0 14px; }
.barre-ligne:last-child { margin-bottom: 0; }
.barre-etiquette { gap: 12px; font-size: 12.5px; color: var(--muted); margin: 0 0 5px; }
.barre-etiquette b { font: 640 14px var(--mono); color: var(--text); font-variant-numeric: tabular-nums; }
.barre-piste { display: block; height: 10px; border-radius: 5px; background: var(--raised); overflow: hidden; }
/* --- Le calcul de perte -------------------------------------------------
   Le prospect règle ses propres chiffres. Aucune moyenne empruntée, donc
   aucune source à défendre — et un résultat qu'il ne peut pas contester,
   puisqu'il vient de le produire. Des curseurs plutôt que des champs : on
   fait glisser, on voit la somme bouger, et l'argument se démontre tout seul. */
.calcul {
  display: grid; grid-template-columns: 1.05fr 1fr; gap: 40px;
  background: var(--surface); border: 1px solid var(--border2);
  border-radius: 14px; padding: 30px 32px;
}

/* Trois rangées suivent le même patron — libellé à gauche, valeur à droite,
   alignées sur la ligne de base. Déclaré une fois plutôt que trois. */
.curseur-tete, .curseur-bornes, .barre-etiquette {
  display: flex; justify-content: space-between; align-items: baseline;
}

.curseur { margin: 0 0 26px; }
.curseur:last-child { margin-bottom: 0; }
.curseur-tete { gap: 16px; margin: 0 0 4px; }
.curseur-tete label { font-size: 13.5px; line-height: 1.45; color: var(--muted); max-width: 34ch; }
.curseur-valeur {
  font: 640 25px var(--mono);
  color: var(--amber); font-variant-numeric: tabular-nums; letter-spacing: -.02em; white-space: nowrap;
}
.curseur-bornes {
  font: 500 11.5px var(--mono); color: var(--faint); margin: -2px 0 0;
}


/* La piste se remplit jusqu'à la valeur : deux arrêts nets, pas un dégradé
   décoratif — c'est la seule façon d'obtenir un remplissage sur WebKit.

   ⚠️ Un pseudo-élément ne se factorise JAMAIS devant une liste de sélecteurs :
   il ne s'accroche qu'au dernier. Il faut le répéter sur chaque membre. Cette
   règle a déjà cassé ces curseurs deux fois — le 5 août au matin par un sed
   qui élargissait le sélecteur, et l'après-midi par un sed qui le rétrécissait. */
.calcul input[type="range"] {
  -webkit-appearance: none; appearance: none;
  width: 100%; height: 44px; margin: 0; background: transparent; cursor: pointer;
}
.calcul input[type="range"]::-webkit-slider-runnable-track {
  height: 6px; border-radius: 3px;
  background: linear-gradient(to right,
    var(--amber) var(--rempli, 0%), var(--border2) var(--rempli, 0%));
}
.calcul input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 20px; height: 20px; border-radius: 50%; margin-top: -7px;
  background: var(--amber); border: 3px solid var(--surface);
}
.calcul input[type="range"]::-moz-range-track { height: 6px; border-radius: 3px; background: var(--border2); }
.calcul input[type="range"]::-moz-range-progress { height: 6px; border-radius: 3px; background: var(--amber); }
.calcul input[type="range"]::-moz-range-thumb {
  width: 20px; height: 20px; border: 3px solid var(--surface); border-radius: 50%;
  background: var(--amber);
}
.calcul input[type="range"]:focus-visible { outline: 2px solid var(--amber); outline-offset: 6px; border-radius: 4px; }

/* La barre se remplit par une mise à l'échelle et non par sa largeur : animer
   « width » force un recalcul complet de la mise en page à chaque image, alors
   qu'une transformation est composée par la carte graphique. Détecté par le
   détecteur mécanique d'impeccable, corrigé le 5 août. */
.barre-remplie {
  display: block; height: 100%; border-radius: 5px; background: var(--amber);
  width: 100%; transform-origin: left center;
  transform: scaleX(var(--part, 0));
  transition: transform .25s ease;
}
.verdict-note { font-size: 13.5px; line-height: 1.55; color: var(--muted); margin: 20px 0 0; }
.verdict-note b { color: var(--text); font-weight: 650; }

/* Sous 860 px la comparaison passe l'une sous l'autre. Cette requête est
   volontairement ICI et non dans celle du haut de fichier : à spécificité
   égale c'est l'ordre qui tranche, et .calcul est déclaré au-dessus. */
@media (max-width: 860px) {
  .calcul { grid-template-columns: 1fr; gap: 28px; padding: 24px 22px; }
  .verdict {
    border-left: none; border-top: 1px solid var(--border2);
    padding-left: 0; padding-top: 26px;
  }
}


/* Pied de page — deux règles de crédibilité du Stanford Web Credibility Project
   (Fogg, 4 500 personnes) : rendre le contact facile, et montrer que le site
   est tenu à jour. La date vient de la construction, jamais d'une saisie. */
.site-footer__joindre { margin: 6px 0 0; color: var(--muted); font-size: 13.5px; }
.site-footer__joindre a { color: var(--text); text-decoration: underline; text-underline-offset: 3px; }
.site-footer__revision { color: var(--faint); font-size: 12.5px; }

/* Sous chaque bouton qui demande une décision : ce à quoi Raphaël s'engage en
   retour. Le délai de réponse est le levier le mieux documenté de la recherche
   commerciale (Oldroyd/MIT 2007 ; HBR 2011, 42 h de moyenne sur 2 241
   entreprises) — et ici ce n'est pas une statistique empruntée, c'est une
   promesse tenue par une seule personne. */
.appel-delai { margin: 16px 0 0; color: var(--muted); font-size: 13.5px; }
