/* ============================================================================
   HABILLAGE DU FORMULAIRE DU PARTENAIRE
   ----------------------------------------------------------------------------
   Le partenaire injecte son questionnaire dans la page via son propre script.
   Le balisage, les questions, les libellés et le parcours sont les siens : ce
   fichier ne fait que poser par-dessus l'identité graphique du site. Aucune
   règle ici ne masque une question, ne change un texte ni ne touche un lien.

   À NE CHARGER QUE SUR LA PAGE QUI PORTE LE FORMULAIRE. Les 33 pages de
   contenu n'ont aucun champ de saisie : ces règles y seraient du poids mort
   livré à chaque visiteur. Même raisonnement que _maquette-formulaire.html,
   qui garde son style de saisie en interne plutôt que dans assets/style.css.

   RÉFÉRENCE DE STYLE : _maquette-formulaire.html (bloc .vrai). Les valeurs
   reprises telles quelles y sont signalées en commentaire. Si la maquette
   bouge, ce fichier doit bouger avec elle.

   DÉPENDANCE : cette feuille n'apporte aucune couleur en dur ; elle consomme
   les variables de :root déclarées dans assets/style.css. Elle se charge donc
   APRÈS style.css, jamais seule — testé : sans les variables, bordures, fonds
   et orange disparaissent d'un coup et le formulaire ressort nu.

   ⚠⚠ LE DOMAINE DOIT ÊTRE DÉCLARÉ CHEZ LE PARTENAIRE, SINON AUCUNE DEMANDE
   N'ABOUTIT. Établi le 07/11/2026 en interrogeant les deux serveurs.

   Le kit parle à DEUX serveurs, et ils ne se comportent pas pareil :

     api.companeo.com  — sert le questionnaire. Renvoie l'origine reçue,
                         normalisée en `https://<hôte>` (schéma forcé, port
                         perdu). Accepte donc n'importe quel domaine https.
                         D'où l'illusion : le formulaire S'AFFICHE partout.

     rest.companeo.com — REÇOIT les réponses (vérification de l'email,
                         envoi de la demande). Liste blanche. Testé avec
                         quatre origines : seule `https://www.b2bpro.fr`
                         est renvoyée. Pour toutes les autres — un tunnel,
                         securite-locaux.fr, un domaine inventé — il répond
                         `https://www.companeo.com`, le navigateur refuse de
                         lire la réponse, et le visiteur reste devant « Un
                         instant… » après avoir saisi son email.

   Cet en-tête affirmait le 06/11/2026 l'inverse — « ce n'est pas une liste
   blanche, aucune déclaration n'est à faire » —, sur la foi d'un test du
   SEUL api.companeo.com. C'était faux pour la moitié qui compte : celle qui
   reçoit les demandes. Constaté quand un vrai remplissage a tourné à vide.

   À FAIRE AVANT TOUTE MISE EN LIGNE : faire déclarer le domaine définitif
   par le partenaire, puis le vérifier en une commande, qui doit renvoyer
   le domaine lui-même et non www.companeo.com :

     curl -s -X OPTIONS -D - -o /dev/null \
       -H "Origin: https://securite-locaux.fr" \
       -H "Access-Control-Request-Method: POST" \
       https://rest.companeo.com/light_coupon/rfq | grep -i allow-origin

   Un serveur local est de toute façon rejeté par les deux : l'origine
   autorisée `https://localhost` ne correspond pas à `http://localhost:8841`.
   En attendant la déclaration, le « cinquième état » plus bas fait paraître
   le bouton de secours quand une attente dépasse 15 s.

   DEUX POINTS À NE PAS « NETTOYER » SANS RELIRE :
   - les raccourcis `font: 400 15px/1.3 inherit` sont INVALIDES (`inherit` n'a
     pas sa place dans l'emplacement « famille ») et le navigateur jette la
     déclaration entière, en silence. D'où les propriétés détaillées partout
     ci-dessous. Le même bug a été corrigé le 07/11/2026 dans style.css (deux
     occurrences, règles .parcours) et dans _maquette-formulaire.html (trois) ;
   - plusieurs `!important` sont nécessaires : la feuille du partenaire est
     chargée par son script APRÈS la nôtre, et certaines de ses règles sont
     plus spécifiques. Chaque `!important` est commenté.

   PRÉALABLE CONTRACTUEL : l'article 4.2 du contrat-cadre interdit de modifier
   le kit « sans accord écrit préalable ». Cette feuille ne modifie aucun
   fichier du partenaire — elle surcharge l'affichage depuis notre domaine —
   mais la distinction nous appartient, pas à eux. Ne pas mettre en ligne sans
   l'accord écrit demandé le 05/11/2026.
   ========================================================================== */

/* --- Remonter le formulaire -------------------------------------------------
   Cette feuille n'est chargée que par /demande-de-devis/ : ces réglages ne
   touchent aucune autre page.

   Mesuré sur un écran de 390 px : avant le premier choix du questionnaire,
   le visiteur traversait 534 px d'en-tête — fil d'Ariane, surtitre, titre,
   chapô, puis 34 px de marge. Sur un téléphone dont la zone visible fait
   650 à 700 px une fois le navigateur déduit, cela laissait le bouton
   « Continuer » hors de l'écran.

   Or cette page n'a pas à convaincre : on n'y arrive qu'en ayant cliqué
   « Demander des devis ». L'en-tête garde donc tout son texte — il situe et
   rassure — mais il cesse de respirer comme sur une page de lecture.
   Aucun mot n'est retiré ici, seulement de l'espace. */
.hero{padding-bottom:18px}
.hero .breadcrumb{padding-top:10px}
.hero .lede{margin-bottom:16px}
.embed{margin-top:12px}

/* --- Le cadre d'accueil, et ses trois états --------------------------------
   .embed-frame est dessiné en pointillés avec le filigrane « Emplacement
   réservé… » tant qu'il est vide. Même mécanique :has() que pour .mock et
   form.parcours dans assets/style.css.

   Trois états, et pas deux, parce que le formulaire arrive en deux temps :
   le <div id="companeoForm"> est dans notre HTML dès le départ, alors que
   #surveySlider n'existe qu'une fois le script du partenaire exécuté. Se
   caler sur #companeoForm laissait donc une boîte vide pendant le
   chargement — et, si le script est bloqué, pour toujours.

     1. pas de conteneur       → filigrane d'origine (les autres pages)
     2. conteneur, pas de form → « Chargement… » (ici, pendant 1 s environ)
     3. formulaire rendu       → cadre plein, plus de filigrane
     4. toujours rien après 8 s → le cadre se referme (voir plus bas)

   L'ordre compte : la règle 3 et la règle 2 ont la même spécificité, c'est
   la dernière écrite qui l'emporte quand les deux s'appliquent. */
.embed-frame:has(#companeoForm)::before{content:"Chargement du formulaire…"}
.embed-frame:has(#jsConfirmationCallback)::before{content:none}
.embed-frame:has(#jsConfirmationCallback){
  min-height:0;height:auto;
}

/* --- Quatrième état : renoncer ---------------------------------------------
   Si le script est bloqué par une extension, « Chargement du formulaire… »
   ne devient jamais vrai : le visiteur fixe 560 px de vide (420 sur mobile)
   sous une promesse qui ne sera pas tenue, et le bouton de secours — la
   seule issue qui lui reste — est repoussé hors de l'écran. Mesuré : il
   commençait à 999 px du haut de la page.

   Au bout de 8 s, on cesse donc de promettre. Le cadre se referme et le
   secours remonte juste sous le titre.

   Pourquoi une animation plutôt qu'un minuteur en JavaScript : ce site n'en
   écrit pas une ligne, et ce n'est pas pour en ajouter sur la seule page qui
   charge déjà un script étranger. Le délai est purement déclaratif.

   Pourquoi :not(:has(#jsConfirmationCallback)) : quand le formulaire arrive,
   le sélecteur cesse de s'appliquer et l'animation est abandonnée en l'état,
   même à mi-course — la règle 3 ci-dessus a déjà remis min-height à 0. Un
   formulaire lent n'est donc jamais amputé. */
@keyframes embedRenoncement{to{min-height:0}}
@keyframes embedRenoncementTexte{to{opacity:0;visibility:hidden}}
.embed-frame:has(#companeoForm):not(:has(#jsConfirmationCallback)){
  animation:embedRenoncement .45s ease 8s forwards;
}
.embed-frame:has(#companeoForm):not(:has(#jsConfirmationCallback))::before{
  animation:embedRenoncementTexte .45s ease 8s forwards;
}
/* Respecte le réglage système : pas de fondu, mais le repli doit avoir lieu
   — c'est une issue de secours, pas une décoration. */
@media (prefers-reduced-motion:reduce){
  .embed-frame:has(#companeoForm):not(:has(#jsConfirmationCallback)),
  .embed-frame:has(#companeoForm):not(:has(#jsConfirmationCallback))::before{
    animation-duration:1ms;
  }
}

/* Pas de cadre dans le cadre. La <section class="embed"> qui enveloppe le
   tout porte déjà la carte du site : bordure, coins arrondis, dégradé blanc
   → --soft, 26 px de marge intérieure, ombre portée. Sur les pages de guide,
   .embed-frame ajoute par-dessus ses pointillés et son fond blanc parce
   qu'il entoure une iframe — un document étranger, qu'on signale comme tel.

   Ici le formulaire est habillé par cette feuille : il EST du site. Lui
   laisser sa propre bordure donnait deux boîtes emboîtées et 44 px de marge
   cumulée (constaté à l'écran). On neutralise donc le décor du cadre sur
   cette page ; il ne sert plus qu'à deux choses, porter les états :has() et
   réserver la hauteur pendant le chargement. */
.embed-frame:has(#companeoForm){
  border:0;background:none;padding:0;overflow:visible;
}

/* En dessous de 700 px, style.css aplatit tout cadre sans iframe chargée :

     .embed-frame:not(:has(iframe[src])){min-height:0;height:auto}

   La règle visait le modèle iframe — ne pas réserver 640 px de vide sur
   mobile quand le marqueur d'URL n'a pas été remplacé. Mais cette page-ci
   n'a PAS d'iframe du tout : la condition y est vraie pour toujours, et le
   cadre de chargement tombait à 2 px de haut (constaté : deux bordures et
   rien entre). Le filigrane « Chargement… » est en position:absolute, il ne
   porte aucune hauteur ; le lien de secours remontait donc contre le titre,
   puis était chassé vers le bas à l'arrivée du formulaire.

   On réserve donc une boîte pendant l'attente. `:not(:has(#jsConfirmationCallback))`
   plutôt que de compter sur l'ordre des règles : les deux sélecteurs ont la
   même spécificité (1,1,0) et #companeoForm existe TOUJOURS, y compris après
   l'injection — le formulaire est construit dedans. Sans cette exclusion,
   la hauteur réservée s'appliquerait aussi au formulaire rendu. */
@media (max-width:700px){
  .embed-frame:has(#companeoForm):not(:has(#jsConfirmationCallback)){min-height:420px}
}

/* Le lien de secours reste affiché tant que le formulaire n'est pas là : si
   un bloqueur avale le script du partenaire, le visiteur a encore un chemin.
   Il disparaît dès que le formulaire est rendu.

   La classe est `.embed-fallback`, celle que style.css centre et marge déjà
   (avec son `.reassurance`) pour les pages de contenu : même bloc, même
   présentation, un seul endroit à maintenir. On n'ajoute ici que la condition
   de masquage propre à ce formulaire-ci. */
.embed-frame:has(#jsConfirmationCallback) ~ .embed-fallback{display:none}

/* --- Pourquoi #jsConfirmationCallback et pas #surveySlider ------------------
   Corrigé le 08/11/2026 après le premier parcours COMPLET (simulation locale
   du kit, voir README). Les états ci-dessus testaient la présence de
   #surveySlider, le formulaire. Mais à la fin du parcours, le kit REMPLACE le
   formulaire par sa page de confirmation : #surveySlider disparaît. Les
   règles en concluaient « le formulaire n'est pas là », et, sous la
   confirmation, juste après l'envoi :
     - le texte « Chargement du formulaire… » revenait par-dessus pendant 8 s ;
     - le bloc de secours « Le formulaire ne s'affiche pas ? Ouvrir le
       formulaire chez notre partenaire » s'affichait pour de bon.
   Le pire moment possible : celui où le visiteur vient de convertir.

   #jsConfirmationCallback est créé par le chargeur du kit (api.php) au même
   instant que le formulaire, et c'est dans lui que la confirmation se dessine.
   Il existe donc dès que le kit a rendu quelque chose, et le reste après la
   confirmation. Le cinquième état, lui, garde #surveySlider : il ne concerne
   que l'attente bloquée d'un formulaire affiché. */
/* --- Cinquième état : le formulaire s'affiche, mais l'envoi ne revient pas -
   Constaté le 07/11/2026, et c'est la panne qui compte : le questionnaire
   s'affiche sur n'importe quel domaine (api.companeo.com renvoie l'origine
   qu'on lui présente), mais l'adresse qui REÇOIT les réponses,
   rest.companeo.com, n'accepte que les domaines déclarés chez le
   partenaire. Ailleurs elle répond `www.companeo.com`, le navigateur refuse
   de lire sa réponse, et le visiteur — qui vient de remplir cinq écrans et
   de donner son email — reste devant « Un instant… » sans fin.

   Le kit signale lui-même ses attentes : `showWait` pose la classe
   `is-api-loading` sur <body>, `hideWait` la retire (lu dans survey.js).
   Observé sur une page bloquée : la classe reste posée, sans une bascule
   en dix secondes et sans nouvelle requête. Un délai CSS suffit donc.

   15 s : le plus long appel normal mesuré (check_coupon) durait 7,2 s.
   Le double laisse passer un réseau lent sans déranger personne. Passé ce
   délai, le bouton de secours paraît sous le formulaire : le visiteur peut
   finir sa demande chez le partenaire au lieu de partir.

   max-height plutôt que display : pendant les attentes normales (quelques
   secondes, à chaque écran), le bloc ne doit occuper AUCUNE place, sinon la
   page sauterait à chaque passage d'écran. La spécificité de ce sélecteur
   (body + classe + :has(#id)) dépasse celle de la règle ci-dessus, qui le
   masque ; quand l'attente finit, la classe tombe et la règle ci-dessus
   reprend la main. */
@keyframes secoursTardif{
  to{max-height:260px;opacity:1;margin-top:18px}
}
body.is-api-loading .embed-frame:has(#surveySlider) ~ .embed-fallback{
  display:block;
  max-height:0;overflow:hidden;opacity:0;margin-top:0;
  animation:secoursTardif .4s ease 15s forwards;
}
@media (prefers-reduced-motion:reduce){
  body.is-api-loading .embed-frame:has(#surveySlider) ~ .embed-fallback{
    animation-duration:1ms;
  }
}

/* ==========================================================================
   RACINE DU QUESTIONNAIRE
   ========================================================================== */

#surveySlider{
  /* `inherit` : on reprend la pile de polices du site plutôt que de la
     redéclarer, comme le fait .vrai dans la maquette. */
  font-family:inherit;
  color:var(--ink);
  /* Leur <form> porte un fond gris #f7f7f7 qui dessinait un rectangle sale
     à l'intérieur de notre cadre blanc. */
  background:none;
  max-width:620px;margin:0 auto;
  display:flex;flex-direction:column;
}

#surveySlider *{box-sizing:border-box}

/* ==========================================================================
   EN-TÊTE DE CHAQUE ÉTAPE
   ========================================================================== */

#surveySlider .surveySlider__header{
  background:none;border:0;padding:0;margin:0 0 16px;
}

/* Le surtitre est la phrase d'explication (« Votre code postal nous permet
   de… »). Le partenaire l'affiche sur un aplat bleu vif. On lui donne la
   forme de .answer-box : fond doux, filet vertical, pas d'aplat. */
#surveySlider .header__surtitle{
  background:var(--soft);
  border-left:3px solid var(--brand);
  border-radius:0 6px 6px 0;
  padding:12px 15px;margin:0 0 18px;
  font-size:14px;line-height:1.5;font-weight:400;
  color:var(--muted);
}

/* La question elle-même : calibrée sur h3 du site (18,5 px / 650 / --brand). */
#surveySlider .header__title{
  font-size:20.5px;font-weight:650;color:var(--brand);
  line-height:1.3;margin:0 0 8px;letter-spacing:-.25px;
  text-wrap:balance;
}

#surveySlider .header__categName,
#surveySlider .header__subtitle{
  font-size:14px;color:var(--muted);margin:0 0 4px;line-height:1.5;
}

#surveySlider .header__categName:empty,
#surveySlider .header__subtitle:empty,
#surveySlider .header__surtitle:empty{display:none}

/* ==========================================================================
   HAUTEURS IMPOSÉES PAR LE PARTENAIRE
   Leur feuille fixe une hauteur au conteneur de contenu, et leur script pose
   en plus une hauteur EN LIGNE sur .surveySlider__questionContainer (273 px
   mesurés sur l'étape 1, pour 175 px de contenu réel). Résultat : un trou
   blanc entre la dernière réponse et le bouton. On laisse la hauteur se
   calculer. Mesuré après correction : 233 px au lieu de 273.
   `!important` indispensable ici — on surcharge un style en ligne.
   ========================================================================== */

/* `overflow:auto` chez eux : une barre de défilement interne apparaissait
   dès que le contenu dépassait de quelques pixels la hauteur imposée. */
#surveySlider .surveySlider__content{height:auto!important;min-height:0!important;padding:0;overflow:visible}
#surveySlider .surveySlider__questionContainer{height:auto!important;min-height:0!important}

/* Marges internes du gabarit d'origine, qui doublent les nôtres. */
#surveySlider .contentForm,
#surveySlider .contentForm__form,
#surveySlider .floatingWrapper{margin:0!important;padding:0!important}

/* …mais en remettant à zéro la marge du conteneur de champ, on a supprimé
   l'écart ENTRE DEUX champs. Invisible sur les étapes à un seul champ (code
   postal, e-mail) ; sur l'étape « coordonnées », qui en aligne quatre, les
   boîtes se touchaient bord à bord et leurs bordures formaient un pavé
   unique. On rend l'écart, et seulement là où il manque : 9 px, la même
   gouttière que `.contentList` pour la liste de choix. */
#surveySlider .floatingWrapper + .floatingWrapper{margin-top:9px!important}

/* ==========================================================================
   CORPS : LISTE DE CHOIX
   La maquette empile ses champs en colonne avec 11 px de gouttière
   (.vrai fieldset). On reprend ce rythme.
   ========================================================================== */

#surveySlider .contentList{
  display:flex;flex-direction:column;gap:9px;
  margin:0;padding:0;list-style:none;
}

#surveySlider .contentList__item{
  margin:0;padding:0;width:100%;float:none;list-style:none;
}

/* Le bouton radio natif est remplacé par une pastille dessinée sur le label :
   la zone cliquable couvre toute la ligne, ce qui est plus sûr au doigt. */
#surveySlider .item__input{
  position:absolute;opacity:0;width:1px;height:1px;
  margin:0;pointer-events:none;
}

#surveySlider .item__label{
  position:relative;
  display:flex;align-items:center;gap:11px;
  width:100%;
  /* Leur feuille fixe `height:58px` sur le label. Tant que l'intitulé tient
     sur une ligne cela ne se voit pas ; dès qu'il passe à deux ou trois
     lignes, le texte sort de la boîte par le bas. Mesuré à 320 px sur
     « Télésurveillance (alarme reliée à une société de surveillance) » :
     58,7 px de texte dans 58 px de boîte, soit 24,7 px de débordement.
     On laisse la hauteur suivre le contenu. Mesuré à 320 px après
     correction : 45,6 px à une ligne, 65,1 px à deux, 84,7 px à trois, et
     plus aucun débordement. Au-dessus de 520 px la ligne simple fait 48,3 px
     (le rembourrage y est de 13 px au lieu de 12). Dans les deux cas la
     ligne reste au-dessus de la cible tactile de 44 px. */
  height:auto;
  /* Bordure, rayon et fond : valeurs de `.vrai input` dans la maquette. */
  border:1px solid var(--line);border-radius:7px;background:var(--white);
  padding:15px 16px 15px 46px;
  /* Propriétés détaillées, pas le raccourci `font` — voir l'en-tête.
     16,5 px et non 15 : le corps du site est à 17 px / 1,65, et un
     questionnaire réglé en 15 px / 1,35 se lit comme une boîte de dialogue
     posée sur la page au lieu d'en faire partie. C'est ce décalage, plus
     que la police elle-même — identique des deux côtés —, qui faisait
     « pièce rapportée ». */
  font-family:inherit;font-size:16.5px;font-weight:400;line-height:1.45;
  color:var(--ink);
  cursor:pointer;
  transition:border-color .15s ease, background-color .15s ease;
}

/* Le partenaire positionne le TEXTE du choix en absolu (left:10px). Cela
   recouvrait la pastille et annulait le padding-left:44px du label : les
   ronds étaient dessinés mais invisibles. On remet le texte dans le flux
   pour que le flex du label fasse son travail.
   `!important` : leur règle arrive après la nôtre. */
#surveySlider .item__text__landing{
  position:static!important;left:auto!important;top:auto!important;
  width:auto!important;height:auto!important;
  display:block!important;flex:1 1 auto;
  font-family:inherit;font-size:16.5px;line-height:1.45;
  /* Les libellés du partenaire mélangent les casses (« CAMERAS et/ou
     VIDEOSURVEILLANCE » à côté de « Télésurveillance (alarme reliée…) »).
     On ne peut pas y toucher en CSS sans casser les sigles légitimes du
     questionnaire — SASU, SARL, RC — qu'un text-transform écraserait.
     Voir la normalisation en fin de page de /demande-de-devis/. */
}

#surveySlider .item__label::before{
  content:"";
  position:absolute;left:15px;top:50%;transform:translateY(-50%);
  width:17px;height:17px;border-radius:50%;
  border:1px solid #c3cedb;background:var(--white);
  transition:border-color .15s ease, border-width .15s ease;
}

#surveySlider .item__label:hover{
  border-color:var(--accent);background:var(--accent-soft);
}

#surveySlider .item__input:checked + .item__label{
  border-color:var(--accent);background:var(--accent-soft);
}

#surveySlider .item__input:checked + .item__label::before{
  border:5px solid var(--accent);
}

/* Le focus clavier doit rester visible : même traitement que
   `.vrai input:focus` (contour accent, 1 px de décalage). */
#surveySlider .item__input:focus-visible + .item__label{
  outline:2px solid var(--accent);outline-offset:1px;border-color:var(--accent);
}

/* `.item__picto` est leur INDICATEUR DE SÉLECTION : une pastille de 30 px,
   orange #f9a33d, frappée d'une coche. Vérifié en retirant cette règle et en
   relevant le `display` calculé choix par choix — `block` sur le choix coché,
   `none` sur les autres. (Le nom trompe : ce n'est pas la vignette de la
   réponse, laquelle est `.item__icon__landing`, masquée par leur propre
   feuille sur notre catégorie.)

   On le masque pour deux raisons.

   1. Il fait triple emploi. Notre habillage signale déjà le choix coché de
      trois façons : la pastille radio remplie (`.item__label::before`), la
      bordure accent et le fond `--accent-soft`. La coche n'ajoute aucune
      information — et elle l'ajoute dans l'orange du partenaire (#f9a33d),
      pas dans le nôtre (--accent, #c8781a), à côté duquel elle jure.
   2. Elle recouvrait le texte. On avait d'abord choisi de la déplacer à
      droite de la ligne plutôt que de la masquer, pour ne rien retirer de
      leur interface. Mesuré à 320 px : la pastille occupait x=227→257 alors
      que l'intitulé du choix courait jusqu'à x=258, le label n'ayant que
      13 px de marge à droite. La garder imposait de réserver ~44 px de marge
      à droite sur TOUS les choix — payés en largeur de texte sur petit
      écran, pour une redondance.

   ⚠ Si l'on retouche un jour l'état coché (pastille radio supprimée, fond
   accent abandonné), cette coche redevient le seul indicateur et ce
   `display:none` rend le formulaire inutilisable. Les deux vont ensemble. */
#surveySlider .item__picto{display:none!important}

/* Vignettes décoratives : conservées, mais désaturées pour ne pas
   concurrencer la couleur d'action. */
#surveySlider .item__icon__landing{
  filter:grayscale(1);opacity:.5;flex:0 0 auto;
}

/* ==========================================================================
   CORPS : CHAMPS DE SAISIE — LE « CHAMP FLOTTANT »
   Code postal, prénom, nom, téléphone, adresse.

   ATTENTION À LA STRUCTURE, elle n'est pas celle qu'on croit. Chez eux la
   boîte visible n'est PAS le champ, c'est son conteneur :

     div.contentForm__form.floatingWrapper   ← bordure, fond, rayon
       input.floating__input                 ← transparent, sans bordure
       label.floating__label                 ← le libellé qui remonte
       span.floating__icon.is-city           ← pictogramme (police d'icônes)
       div.floating__reset                   ← croix d'effacement
       div.floating__error                   ← message d'erreur

   Habiller l'input comme un champ normal dessinait donc une boîte DANS une
   boîte. On déplace l'habillage sur le conteneur et on laisse l'input nu.

   Leurs états sont des classes posées sur le conteneur : `fieldActive`
   (focus), `is-valid`, `is-error`. On les recolore, on ne les renomme pas.
   Leurs sélecteurs font trois classes (0,3,0) ; les nôtres commencent par
   #surveySlider (1,1,0) et passent devant sans `!important`.

   Le libellé flottant est animé par eux (translateY + font-size au passage
   en `fieldActive`). On garde l'animation, on n'ajuste que les deux
   positions de repos et d'arrivée pour qu'elles tombent sur notre padding.
   ========================================================================== */

#surveySlider .floatingWrapper{
  background:var(--white);
  border:1px solid var(--line);border-radius:6px;
  max-width:none;margin:0;outline:0;
  transition:border-color .15s ease, box-shadow .15s ease;
}

/* Au survol ils passent la bordure en bleu vif : on ne bouge pas. */
#surveySlider .floatingWrapper:hover{
  border:1px solid var(--line);background:var(--white);
}

/* Focus et champ valide : même signal, la couleur d'action du site. */
#surveySlider .floatingWrapper.fieldActive,
#surveySlider .floatingWrapper.fieldActive:hover,
#surveySlider .floatingWrapper.is-valid,
#surveySlider .floatingWrapper.is-valid.fieldActive,
#surveySlider .floatingWrapper.is-valid:hover{
  border:1px solid var(--accent);background:var(--white);
  box-shadow:0 0 0 2px var(--accent-soft);
}

#surveySlider .floatingWrapper.is-error,
#surveySlider .floatingWrapper.is-error:hover{
  border:1px solid #b91c1c;background:var(--white);
  box-shadow:0 0 0 2px #fef2f2;
}

/* Le champ lui-même : transparent, c'est le conteneur qui fait la boîte.
   Le padding haut laisse la place au libellé une fois remonté. */
#surveySlider .floating__input,
#surveySlider .floating__select{
  background:transparent;border:0;border-radius:0;box-shadow:none;
  color:var(--ink);
  font-family:inherit;font-size:16.5px;font-weight:400;
  height:56px;padding:22px 44px 7px;
  max-width:none;width:100%;
}

/* La liste déroulante est le seul champ dont le contenu peut passer à la
   ligne : leur feuille lui met `white-space:pre-wrap`, et l'option par
   défaut « Quelle est votre forme juridique ? » ne tient pas sur une ligne
   en dessous de ~520 px — il reste 199 px de large une fois retirés les
   44 px de part et d'autre. Avec `height:52px`, la deuxième ligne était
   coupée net par le bas : on lisait « Quelle est votre forme » et rien de
   plus. (Défaut antérieur au correctif de spécificité ci-dessous : la
   liste déroulante, elle, recevait bien cette règle depuis le début.)
   Même parti que pour les choix : la hauteur suit le contenu, le plancher
   reste à 52 px pour que les champs d'une ligne restent alignés entre eux.
   Mesuré à 375 px : 62 px au lieu de 52, plus rien de tronqué. */
#surveySlider .floating__select{height:auto;min-height:52px}

#surveySlider .floating__label{
  color:var(--muted);font-family:inherit;font-size:16.5px;
  top:19px;left:44px;
}

#surveySlider .floatingWrapper.fieldActive .floating__label{
  font-size:12px;color:var(--muted);transform:translateY(-12px);
}

#surveySlider .floatingWrapper.is-error .floating__label,
#surveySlider .floatingWrapper.is-error label{color:#991b1b}

/* Le <select> garde son libellé en haut en permanence. */
#surveySlider .floating__select + label{
  color:var(--muted);font-size:12px;top:7px;left:44px;
}

/* Pictogramme du champ : police d'icônes maison, en bleu vif #00a3e4.
   On le garde (c'est leur repère visuel) en gris neutre. */
#surveySlider .floating__icon{color:#9aa8b5;font-size:22px;left:14px}

#surveySlider .floating__reset{color:var(--muted)}

/* Message d'erreur : bandeau rouge vif chez eux, palette d'alerte du site
   chez nous. Le texte reste le leur. */
#surveySlider .floating__error{
  background:#fef2f2;color:#991b1b;border-top:1px solid #fecaca;
  font-size:13px;padding:8px 11px;width:100%;
}

/* La pastille d'état en coin de champ (coche ou croix). */
#surveySlider .floatingWrapper.is-valid::after{
  background-color:var(--accent);font-size:14px;padding:5px;top:-8px;right:-8px;
}
#surveySlider .floatingWrapper.is-error::after{
  background-color:#b91c1c;font-size:14px;padding:5px;top:-8px;right:-8px;
}

/* --- Filet de sécurité -----------------------------------------------------
   Si une étape sert un champ hors du gabarit « flottant », il doit quand
   même ressembler à `.vrai input` dans la maquette.

   ⚠ LE `:not()` N'EST PAS DÉCORATIF, il répare un bug de spécificité que ce
   filet avait lui-même introduit. Un sélecteur d'attribut compte comme une
   classe : `#surveySlider input[type=tel]` vaut (1,1,1) et battait donc
   `#surveySlider .floating__input`, qui vaut (1,1,0). Tous les champs du
   questionnaire — qui portent bien la classe `floating__input` — recevaient
   ce filet au lieu de leur mise en forme : padding 11px 13px au lieu de
   20px 44px 6px, hauteur 43,5 px au lieu de 52. Conséquences mesurées à
   320 px sur l'étape « code postal » : le texte saisi commençait à x=58
   alors que le pictogramme occupe x=59→81 — saisie sous l'icône — et le
   libellé flottant, posé à left:44px, ne tombait plus en face du texte.
   `#surveySlider select` (1,0,1) perdait déjà face à `.floating__select`,
   c'est pour cela que seule la liste déroulante s'affichait correctement.

   Exclure explicitement les deux classes vaut mieux que de renforcer la
   spécificité en face : ce bloc est un filet pour les champs HORS gabarit
   flottant, autant que son sélecteur le dise. */
#surveySlider input[type=text]:not(.floating__input),
#surveySlider input[type=tel]:not(.floating__input),
#surveySlider input[type=email]:not(.floating__input),
#surveySlider input[type=number]:not(.floating__input),
#surveySlider input[type=search]:not(.floating__input),
#surveySlider select:not(.floating__select),
#surveySlider textarea:not(.floating__input){
  font-family:inherit;font-size:16.5px;font-weight:400;line-height:1.4;
  color:var(--ink);
  border:1px solid var(--line);border-radius:6px;
  background:var(--white);padding:11px 13px;width:100%;
  -webkit-appearance:none;appearance:none;
  box-shadow:none;height:auto;
}

#surveySlider select{
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'><path d='M1 1l5 5 5-5' fill='none' stroke='%239aa8b5' stroke-width='2'/></svg>");
  background-repeat:no-repeat;background-position:right 13px center;background-size:11px;
  padding-right:34px;
}

#surveySlider input:focus,
#surveySlider select:focus,
#surveySlider textarea:focus{
  outline:2px solid var(--accent);outline-offset:1px;border-color:var(--accent);
}

#surveySlider ::placeholder{color:#9aa8b5;opacity:1}

/* Libellé de champ : 13 px / 650 / --brand, comme `.vrai label>b`. */
#surveySlider label>b,
#surveySlider .field__label{
  font-size:13px;font-weight:650;color:var(--brand);
}

/* Message d'erreur du partenaire : palette d'alerte de la maquette. */
#surveySlider .error,
#surveySlider .is-error,
#surveySlider [class*="error"]:not(input):not(select){
  background:#fef2f2;border:1px solid #fecaca;color:#991b1b;
  border-radius:6px;padding:9px 11px;font-size:13px;
}

#surveySlider input.is-error,
#surveySlider input[aria-invalid="true"]{border-color:#b91c1c}

/* ==========================================================================
   BOUTONS
   `.vrai button[type=submit]` : 650 15px/1, rayon 7, padding 13, fond accent,
   survol brightness(1.07). Le partenaire pose un bouton « précédent » à côté,
   que la maquette ne connaît pas : on lui donne l'allure de `.vrai .retour`.
   ========================================================================== */

#surveySlider .surveySlider__cta{
  margin-top:22px;padding:0;border:0;background:none;
}

#surveySlider .cta__content{
  display:flex;align-items:center;gap:10px;
}

#surveySlider .button__next{
  font-family:inherit;font-size:16px;font-weight:650;line-height:1;
  cursor:pointer;
  background:var(--accent-hover);background-image:none;color:var(--white);
  border:1px solid transparent;border-radius:7px;
  padding:13px 26px;
  /* Pas `flex:1 1 auto` : étiré sur toute la largeur, « Continuer » flottait
     perdu au milieu d'une barre orange de 600 px. */
  flex:0 1 auto;min-width:200px;width:auto;height:auto;
  text-transform:none;letter-spacing:0;box-shadow:none;
  transition:filter .15s ease;
}

#surveySlider .button__next:hover{filter:brightness(1.07)}
#surveySlider .button__next:focus-visible{outline:2px solid var(--brand);outline-offset:2px}

/* La flèche du gabarit d'origine : le libellé « Continuer » se suffit. */
#surveySlider .button__next > span{display:none}

/* Dans le DOM, « suivant » vient AVANT « précédent ». Visuellement l'inverse
   est attendu. On réordonne à l'affichage sans toucher à leur balisage —
   l'ordre de tabulation reste le leur. */
#surveySlider .button__prev{
  order:-1;
  font-family:inherit;font-size:15px;font-weight:600;line-height:1;
  cursor:pointer;
  background:none;background-image:none;color:var(--muted);
  border:1px solid var(--line);border-radius:7px;
  width:44px;height:44px;flex:0 0 auto;
  box-shadow:none;opacity:.8;
  transition:opacity .15s ease, border-color .15s ease;
}

#surveySlider .button__prev:hover{opacity:1;border-color:var(--muted)}

/* ==========================================================================
   PROGRESSION
   ========================================================================== */

#surveySlider .cta__progressbar{margin-top:18px}

#surveySlider progress{
  display:block;width:100%;height:4px;border:0;border-radius:2px;
  background:var(--line);appearance:none;-webkit-appearance:none;
}
#surveySlider progress::-webkit-progress-bar{background:var(--line);border-radius:2px}
#surveySlider progress::-webkit-progress-value{background:var(--accent);border-radius:2px}
#surveySlider progress::-moz-progress-bar{background:var(--accent);border-radius:2px}

/* ==========================================================================
   PIED : BANDEAU DES FOURNISSEURS
   Le partenaire affiche les logos de ses clients. On les garde — les retirer
   serait une modification de son contenu — mais on les désature pour qu'ils
   ne passent pas pour une recommandation de notre part.
   ========================================================================== */

#surveySlider .surveySlider__topFooter{
  margin-top:20px;padding-top:16px;border-top:1px solid var(--line);
}

/* .surveySlider__footer ne contient qu'un `&nbsp;` sur les étapes vues, mais
   c'est l'emplacement de leur mention de traitement des données sur la
   dernière. On ne le masque donc pas — on supprime seulement sa marge
   basse, qui creusait un vide de 15 px au pied du cadre. */
#surveySlider .surveySlider__footer{margin:10px 0 0}

#surveySlider .surveySlider__topFooter p,
#surveySlider .surveySlider__footer p{
  font-size:13px;line-height:1.6;color:var(--muted);text-align:center;margin:0 0 10px;
}

#surveySlider .carous ul{
  display:flex;flex-wrap:wrap;justify-content:center;align-items:center;
  gap:18px!important;margin:0;padding:0;list-style:none;
}

/* Leur feuille contraint li ET img à un carré, ce qui écrase des logos qui
   sont presque tous en format paysage : ils devenaient illisibles.
   On borne la hauteur ET la largeur, et on laisse le ratio tranquille. */
#surveySlider .carous li{margin:0;width:auto!important;height:auto!important}
#surveySlider .carous img{
  max-height:40px!important;max-width:72px!important;
  width:auto!important;height:auto!important;
  object-fit:contain;
  filter:grayscale(1);opacity:.55!important;
}

#surveySlider .surveySlider__footer{
  margin-top:10px;font-size:12px;color:var(--muted);
}

/* ==========================================================================
   PETITS ÉCRANS
   ========================================================================== */

/* --- Écrans 6 et 8, retirés --------------------------------------------------
   Le script « ÉCRANS RETIRÉS » de /demande-de-devis/ franchit ces deux écrans
   (vente croisée, option marketing) en quelques dixièmes de seconde. Pendant
   ce temps, on ne les montre pas : le visiteur ne voit pas une question lui
   apparaître puis s'envoler.

   Pas plus de 4 s, et c'est la sécurité du dispositif : si le script échoue,
   la question redevient visible et le visiteur y répond lui-même. Un écran
   masqué SANS limite serait un cul-de-sac invisible.

   Le chargeur du kit (.sa_loader_container) est épargné : pendant la
   validation de l'écran 8, c'est lui qui dit au visiteur que ça avance. */
@keyframes ecranRetire{from{visibility:hidden}to{visibility:visible}}
#surveySlider.slide_qa > :not(.sa_loader_container),
#surveySlider.slide_rgpd > :not(.sa_loader_container){
  animation:ecranRetire 0s linear 4s both;
}

/* --- Liens des mentions légales du partenaire ----------------------------
   Les écrans 6 et 7 affichent, juste avant la validation, le texte des CGU
   et des droits RGPD. Ses liens (« CGU », privacy@…, « en savoir plus »)
   arrivent avec un style EN LIGNE dans les données du kit :
   `style="color: #00a3e4"` — 2,85:1 sur blanc, sous le minimum AA de 4,5:1,
   sur le texte que le visiteur est censé lire avant de s'engager.
   Un style en ligne bat toute règle de feuille ; seul `!important` le
   surmonte. On ne vise que les liens de texte : les boutons du kit sont des
   <button>, pas des <a>. --brand sur blanc : 13,89:1. Repéré le 07/11/2026 en
   balayant le contraste DANS le questionnaire, que le premier balayage
   avait exclu. */
#surveySlider a[href]:not([class*="button"]){
  color:var(--brand)!important;
  text-decoration:underline!important;
  text-underline-offset:2px;
}

@media (max-width:520px){
  /* Rien à réduire sur .embed-frame : il n'a plus de marge intérieure propre
     depuis qu'on lui a retiré son décor (voir « Pas de cadre dans le cadre »).
     C'est .embed, la carte du site, qui porte le rembourrage — et style.css
     le resserre déjà à 20px 16px sous 700 px. */
  #surveySlider .header__title{font-size:19px}
  #surveySlider .item__label{padding:13px 14px 13px 42px;font-size:16px}
  #surveySlider .item__text__landing{font-size:16px}
  #surveySlider .cta__content{gap:8px}
  #surveySlider .button__next{padding:13px 18px;min-width:0;flex:1 1 auto}
  #surveySlider .carous img{max-height:28px!important;max-width:60px!important}
}
