/* mlsign v7, /diffuser-ma-pub/ : le tunnel de qualification.
 *
 * Chargée par ce seul gabarit, et par lui seul : les onze autres pages n'ont
 * rien à faire du curseur ni des cartes de choix. Elle vient APRÈS
 * composants.css et elle en dépend : .bouton, .champ, .vh, .pot, .etiquette et
 * .lien y sont déjà écrits, on ne les recopie pas, on les complète.
 *
 * AUCUN HEX. La page est en zone jour, mais rien ici ne le sait : tout passe
 * par --fond, --texte, --bordure, --surface, --action… que la zone a rebindés.
 * Une valeur qui manque remonte dans design/tokens.json.
 *
 * LA LOI DE CE FICHIER : tout ce qui est vivant est sous `.qualif[data-tunnel]`.
 * `data-tunnel` n'est posé que par js/qualification.js, et seulement une fois son
 * initialisation finie. Sans script, sans cet attribut : les six écrans sont
 * empilés, les boutons de pas et la progression n'existent pas, le formulaire
 * est un formulaire. C'est l'état de repli, et il est complet.
 */

/* --- La scène ------------------------------------------------------------ */

/* La barre est fixe : sans cette compensation le h1 passe dessous. Même calcul
   que .manchette, sans le 100svh : cette page n'est pas un manifeste, elle est
   un plan de travail. */
/* LE LOGO NE BOUGE PLUS ENTRE LES ÉCRANS (16.08, constat de Nazaire : il
   était centré sur le premier écran puis se décalait). La cause : l'écran 0
   tient dans la fenêtre, les suivants non — la barre de défilement classique
   du desktop apparaissait et rétrécissait le viewport, et la pilule centrée
   en position fixe se recalait de la largeur du curseur. La glissière est
   posée en permanence sur cette page : le viewport ne change plus jamais de
   largeur. Sans effet au téléphone, où les barres sont en surimpression. */
html:has(body[data-page="demande"]) { overflow-y: scroll; }

/* La barre est revenue (16.08 au soir) et la progression respire dessous :
   1rem la collait à la pilule au desktop, constat de Nazaire. Le bas se
   resserre au téléphone : les 64 px de la vitesse commune faisaient scroller
   l'écran de l'occasion de 14 px dans le vide. */
.qualif {
  padding-block-start: calc(var(--barre-h) + clamp(1.5rem, 4svh, 3rem));
  padding-block-end: clamp(1.25rem, 3svh, 4rem);
}
/* --barre-h ne compte pas le décollement de 1rem de la pilule : au grand
   écran, le clamp commun laissait 19 px entre la pilule et la progression.
   Mesuré, pas estimé. */
@media (width >= 56.25rem) {
  .qualif { padding-block-start: calc(var(--barre-h) + 4.75rem); }
}

.qualif__scene {
  display: grid;
  gap: clamp(1.5rem, 1.2rem + 1.5vw, 2.5rem);
  max-inline-size: 44rem;
  margin-inline: auto;
}

/* Le formulaire est le tunnel entier, pas un panneau posé dedans : il ne
   reprend NI le fond NI le filet de .formulaire (composants.css), qui
   encadrent un bloc de coordonnées au milieu d'une page. Ici, un cadre
   dessinerait une boîte autour de six écrans successifs. Il ne porte que le
   flux de ses écrans, que .qualif__scene ne peut pas donner : la scène
   contient la progression, le formulaire et la porte de sortie, et ses six
   écrans doivent respirer entre eux, pas comme elle. */
.qualif__form {
  display: grid;
  align-content: start;
}

/* --- La progression. Décorative, et absente sans script. ----------------- */
/* La progression et la navigation sont des <p> : composants.css leur donne la
   mesure du dossier, 62ch, qui est la bonne largeur pour un texte et la
   mauvaise pour une barre et un bouton. Ils reprennent la largeur de la scène,
   celle des cartes qu'ils surmontent et qu'ils suivent. */
.qualif__progression { display: none; max-inline-size: none; }
.qualif[data-tunnel] .qualif__progression {
  display: flex;
  gap: 0.4rem;
}
.qualif__jalon {
  border-radius: var(--radius-pilule);
  block-size: 2px;
  flex: 1;
  background: var(--bordure);
}
.qualif__jalon[data-fait] { background: var(--texte); }

/* --- Un écran ------------------------------------------------------------ */

.qualif__ecran {
  display: grid;
  align-content: start;
  gap: 1.1rem;
}
/* Sans script les six écrans se suivent : il leur faut une frontière. Avec le
   script, un seul est à l'écran, et le filet n'a plus rien à séparer. */
.qualif__ecran + .qualif__ecran {
  margin-block-start: clamp(2rem, 1.5rem + 2vw, 3.5rem);
  padding-block-start: clamp(2rem, 1.5rem + 2vw, 3.5rem);
  border-block-start: var(--hairline) solid var(--bordure);
}
.qualif[data-tunnel] .qualif__ecran + .qualif__ecran {
  margin-block-start: 0;
  padding-block-start: 0;
  border-block-start: 0;
}

.qualif__titre { font-size: var(--t-h2); }
/* Le titre reçoit le focus au changement d'écran : il annonce la question, ce
   qu'aucun bandeau de progression ne saurait faire aussi bien. Il ne porte pas
   d'anneau pour autant, il n'est pas un contrôle. */
.qualif__titre:focus { outline: none; }

.qualif__aide {
  max-inline-size: 52ch;
  color: var(--texte-secondaire);
}

/* La justification du minimum. Elle n'est pas encadrée, elle n'est pas colorée,
   elle n'est pas en encart : ce serait la faire lire comme une clause. Une
   raison opérationnelle se conteste moins bien qu'une condition de vente, à
   condition d'avoir l'air d'une raison. */
.qualif__justification {
  max-inline-size: 58ch;
  font-size: var(--t-petit);
  line-height: 1.5;
  color: var(--texte-secondaire);
}

.qualif__microcopie {
  max-inline-size: 58ch;
  font-size: var(--t-petit);
  line-height: 1.45;
  color: var(--texte-secondaire);
}

/* --- Les cartes de choix ------------------------------------------------- */

.cartes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
  gap: 0.75rem;
}

/* Le bouton radio est dans le label, en .vh : il reste focusable et lisible à
   voix haute, et c'est la carte entière qui se clique. */
.carte-choix {
  border-radius: var(--radius-ui);
  position: relative;
  display: grid;
  align-content: start;
  gap: 0.3rem;
  padding: 1rem 1.1rem;
  background: var(--surface);
  border: var(--hairline) solid var(--bordure);
  cursor: pointer;
  transition: background var(--duree) var(--ease),
              border-color var(--duree) var(--ease);
}
.carte-choix:hover { background: var(--survol); }
.carte-choix__titre { font-weight: var(--wght-titre); color: var(--texte); }
.carte-choix__corps {
  font-size: var(--t-petit);
  line-height: 1.45;
  color: var(--texte-secondaire);
}
/* L'inversion, comme les boutons : l'emphase du site passe par le contraste,
   jamais par une couleur d'accent posée en aplat. */
.carte-choix:has(input:checked) {
  background: var(--texte);
  border-color: var(--texte);
}
.carte-choix:has(input:checked) .carte-choix__titre,
.carte-choix:has(input:checked) .carte-choix__corps { color: var(--fond); }
.carte-choix:has(input:focus-visible) {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

/* --- Les puces (choix en boutons) ---------------------------------------- */

.puces {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  padding: 0;
  border: 0;
  min-inline-size: 0;   /* un fieldset ne rétrécit pas tout seul */
}
.puces__legende {
  inline-size: 100%;
  padding: 0;
  margin-block-end: 0.55rem;
  font-size: var(--t-petit);
  color: var(--texte-secondaire);
}
.puce {
  border-radius: var(--radius-pilule);
  position: relative;
  display: inline-flex;
  align-items: center;
  min-block-size: 40px;
  padding: 0.4rem 0.9rem;
  background: var(--surface);
  border: var(--hairline) solid var(--bordure);
  font-size: 0.9rem;
  cursor: pointer;
  transition: background var(--duree) var(--ease),
              border-color var(--duree) var(--ease),
              color var(--duree) var(--ease);
}
.puce:hover { background: var(--survol); }
.puce:has(input:checked) {
  background: var(--texte);
  border-color: var(--texte);
  color: var(--fond);
}
.puce:has(input:focus-visible) {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}
/* Le mot de la puce. Il ne se colore pas lui-même : c'est .puce qui s'inverse
   quand sa case est cochée, et un color posé ici gagnerait contre l'inversion
   — le libellé resterait à l'encre sur l'aplat d'encre, c'est-à-dire
   invisible. Il ne porte donc que sa ligne. .case__mot, son voisin, en fait
   autant pour la même raison. */
.puce__mot { line-height: 1.3; }

/* --- Les cases à cocher qui restent des cases ---------------------------- */

/* Celles-ci ne sont pas des puces : « c'est urgent » et « je veux un QR » sont
   des ajouts, pas des réponses. Une case cochée le dit mieux qu'un bouton
   inversé. */
.case {
  display: flex;
  align-items: start;
  gap: 0.6rem;
  cursor: pointer;
}
.case input {
  inline-size: 1.05rem;
  block-size: 1.05rem;
  margin-block-start: 0.28rem;
  /* --texte et pas --action : l'action est le jaune depuis le 14.08, a 1,62:1
     sur le blanc, sous le 3:1 de WCAG 1.4.11 pour un etat de controle. C'est
     le principe deja ecrit plus haut dans ce fichier : l'emphase passe par
     l'inversion, jamais par une couleur d'accent posee en aplat, et
     .carte-choix comme .puce s'inversent deja a l'encre. */
  accent-color: var(--texte);
  flex: none;
}
.case__mot { font-size: var(--t-petit); line-height: 1.5; }

/* La date du prospect pressé, ouverte par sa case et par rien d'autre. Aucune
   ligne de JavaScript là-dedans : une divulgation qui dépend du script laisse,
   sans lui, une case cochée qui n'ouvre rien. (0,3,0), donc elle passe devant
   la règle de masquage de la fin du fichier. */
.champ--urgent { display: none; }
.qualif .case:has([data-urgent]:checked) + .champ--urgent { display: block; }

/* --- Le curseur ---------------------------------------------------------- */

.curseur {
  display: grid;
  gap: 0.6rem;
  padding: clamp(1rem, 0.8rem + 1vw, 1.5rem);
  background: var(--surface);
  border: var(--hairline) solid var(--bordure);
}

/* Le retour en direct. Il n'existe que si quelque chose peut le mettre à jour :
   sans script, il n'a rien à dire et il ne prend pas de place. */
.curseur__retour { display: none; }
.qualif[data-tunnel] .curseur__retour {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem;
  font-size: var(--t-lead);
  color: var(--texte);
}
.curseur__mot--fort { font-weight: var(--wght-titre); }
/* Le point separateur est ACCROCHE AU MOT QUI PRECEDE, pas posé devant le
   suivant : sur deux lignes, un séparateur en tête de ligne se lit comme une
   puce de liste. */
.curseur__mot:not(:last-child)::after {
  content: "\00a0\00b7";
  color: var(--texte-secondaire);
}

.curseur__rangee {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

/* Le bouton moins et le bouton plus. À la borne, le moins est `disabled` : il
   ne dit rien, il ne refuse rien, il ne bouge pas. C'est le premier des trois
   mécanismes, et il n'a pas de message parce qu'un message se négocie. */
.curseur__pas {
  border-radius: var(--radius-pilule);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 44px;
  block-size: 44px;
  flex: none;
  background: var(--fond);
  color: var(--texte);
  border: var(--hairline) solid var(--bordure-champ);
  font-size: 1.25rem;
  line-height: 1;
  transition: background var(--duree) var(--ease);
}
.curseur__pas:hover { background: var(--survol); }
.curseur__pas[disabled] {
  opacity: 0.4;
  cursor: default;
}
.curseur__pas[disabled]:hover { background: var(--fond); }

.curseur__glissiere {
  flex: 1;
  min-inline-size: 0;
  block-size: 44px;
  /* Meme arbitrage que .case input : le pouce et la piste remplie du range
     sortaient en jaune 1,62:1 sur la page de conversion. */
  accent-color: var(--texte);
  cursor: pointer;
}

.curseur__bornes {
  display: flex;
  justify-content: space-between;
  font-size: var(--t-micro);
  color: var(--texte-secondaire);
  /* Alignées sur la PISTE, pas sur la rangée (16.08, constat de Nazaire :
     « le 2 et le 10 ne sont pas alignés avec la barre ») : la glissière
     commence après le bouton moins — 44 px de cercle plus 0.75rem de
     gouttière — et finit autant avant le plus. Les bornes suivent.
     max-inline-size: none — c'est un <p>, la mesure commune de 62ch le
     coupait 165 px avant le bord droit de la piste. */
  max-inline-size: none;
  padding-inline: calc(44px + 0.75rem);
}

/* --- La porte de sortie -------------------------------------------------- */

/* Un <details> : elle s'ouvre sans script, et elle LAISSE PASSER. Rien ici ne
   valide, rien ne bloque, rien n'exige de justification. C'est le troisième
   mécanisme, celui qui évite qu'un prospect avec une bonne raison parte sans
   rien dire. */
.porte {
  font-size: var(--t-petit);
  color: var(--texte-secondaire);
}
.porte__appel {
  display: inline-block;
  padding-block: 0.25rem;
  cursor: pointer;
  list-style: none;
}
.porte__appel::-webkit-details-marker { display: none; }
.porte__lien {
  color: var(--texte);
  text-decoration: underline;
  text-underline-offset: 0.18em;
}
.porte__appel:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}
.porte .champ { margin-block-start: 0.6rem; }

/* --- Les champs ---------------------------------------------------------- */

/* .champ porte une marge haute dans composants.css, utile dans un formulaire
   en flux. Ici les écrans sont des grilles à `gap` : la marge doublerait
   l'écart. */
.qualif__ecran > .champ { margin-block-start: 0; }

.champ__requis { color: var(--texte-secondaire); }
/* `font-style: italic` A ÉTÉ RETIRÉ ICI. Switzer n'embarque pas de coupe
   italique dans le sous-ensemble de lancement, 400i est écarté, voir
   css/fonts.css, donc le navigateur en synthétisait une : une oblique
   géométrique, penchée au calcul, sur le seul formulaire du site, c'est-à-dire
   sur la page où atterrissent tous les CTA. La seule italique du site est celle
   de la serif, qui a son fichier, et elle porte le refrain, pas une mention de
   champ. Le secondaire suffit à ranger cette ligne sous son libellé. */
.champ__mention {
  color: var(--texte-secondaire);
}
.champ__erreur {
  margin-block-start: 0.35rem;
  font-size: var(--t-petit);
  line-height: 1.4;
  /* Braise brute : illisible sur la nuit. Éclaircie vers l'encre de la zone,
     comme .formulaire__accuse[data-echec] de composants.css. */
  color: color-mix(in srgb, var(--alerte) 55%, var(--texte));
}
.champ input[aria-invalid="true"],
.champ textarea[aria-invalid="true"] {
  border-color: color-mix(in srgb, var(--alerte) 55%, var(--texte));
}

/* --- La navigation ------------------------------------------------------- */

/* Elle n'existe pas sans script : ces boutons ne mènent nulle part tant que
   personne ne les écoute. Sans eux, la page garde son unique bouton d'envoi,
   celui de l'écran 5, et il est de type submit. */
.qualif__nav { display: none; max-inline-size: none; }
.qualif[data-tunnel] .qualif__nav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem;
  margin-block-start: 0.5rem;
}
/* L'écran 5 est le seul dont le bouton compte sans script. */
.qualif__nav--envoi {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem;
  max-inline-size: none;
}
.qualif[data-tunnel] .qualif__nav .qualif__pas,
.qualif__nav--envoi .qualif__envoyer { margin-inline-start: auto; }

/* Le bouton qui attend. Il n'est pas `disabled` : un bouton désactivé sort de
   l'ordre de tabulation, et son libellé, qui est justement le message, ne se
   lit plus. Il est `aria-disabled`, donc focusable et lisible, et le script
   refuse simplement d'avancer. */
/* IL N'EST PAS GRISÉ PAR L'OPACITÉ, et c'est le seul endroit du site où l'on
   s'écarte de .bouton[disabled]. Un aplat sombre à 55 % d'opacité donne du
   blanc sur gris à 3,5:1, sous le seuil AA : le libellé deviendrait illisible
   au moment précis où il porte le seul message qui compte. Il se vide donc au
   lieu de s'éteindre, et son texte reste à 7,12 sur papier. */
.bouton[aria-disabled="true"] {
  background: transparent;
  color: var(--texte-secondaire);
  border-color: var(--bordure);
  cursor: default;
}
.bouton[aria-disabled="true"]:hover {
  background: transparent;
  color: var(--texte-secondaire);
  border-color: var(--bordure);
}

/* Le retour en arrière n'a de sens qu'avec le pas à pas : sans script il n'y a
   pas d'écran précédent, les six sont là. */
.qualif__retour { display: none; }
.qualif[data-tunnel] .qualif__retour {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 3.75rem;
  block-size: 3.75rem;
  padding: 0;
  font-size: 1.9rem;
  line-height: 1;
  color: var(--texte);
  background: none;
  border: 1.5px solid var(--bordure-champ, var(--bordure));
  border-radius: 999px;
  cursor: pointer;
}
.qualif__retour:hover { border-color: var(--texte); }

.qualif__accuse {
  margin-block-start: 1rem;
  font-size: var(--t-petit);
  color: color-mix(in srgb, var(--alerte) 55%, var(--texte));
}

/* --- L'écran de confirmation --------------------------------------------- */

.qualif__fin {
  border-radius: var(--radius);
  display: grid;
  align-content: start;
  gap: 1rem;
  padding: clamp(1.5rem, 1.2rem + 1.5vw, 2.5rem);
  background: var(--surface);
  border: var(--hairline) solid var(--bordure);
}
.qualif__fin:focus { outline: none; }
.qualif__attente { color: var(--texte-secondaire); }
.qualif__fin .bouton { justify-self: start; }

/* --- Le focus, partout où il se voit ------------------------------------- */
.qualif :where(input, textarea, button, summary, a):focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

/* --- Mouvement ------------------------------------------------------------ */

/* Le changement d'écran GLISSE SUR LE CÔTÉ depuis le 16.08 (consigne de
   Nazaire : « il faut que ça slide quand on sélectionne quelque chose ») —
   l'arbitrage inverse d'hier est renversé. Le sens suit le geste : on
   avance, l'écran entre par la droite ; on revient, par la gauche.
   data-sens est reposé par js/qualification.js à chaque passage pour
   relancer l'animation. Sous mouvement réduit, socle.css annule tout. */
@media (prefers-reduced-motion: no-preference) {
  .qualif[data-tunnel] .qualif__ecran[data-sens="avance"] {
    animation: qualif-avance 260ms var(--ease) both;
  }
  .qualif[data-tunnel] .qualif__ecran[data-sens="recul"] {
    animation: qualif-recul 260ms var(--ease) both;
  }
}
@keyframes qualif-avance {
  from { opacity: 0; transform: translateX(36px); }
  to   { opacity: 1; transform: none; }
}
@keyframes qualif-recul {
  from { opacity: 0; transform: translateX(-36px); }
  to   { opacity: 1; transform: none; }
}

/* --- L'avancée automatique (16.08) --------------------------------------- */

/* Sur les écrans à choix unique, le tunnel avance dès la sélection : le
   bouton continuer ne se montre plus, mais IL N'EST PAS RETIRÉ. Masqué à la
   manière d'un lien d'évitement, il revient dès qu'un clavier le prend au
   focus : sans lui, qui navigue à la tabulation resterait enfermé, et son
   libellé-obstacle continue de dire ce qui manque. Sans JavaScript le
   formulaire est complet et empilé : la classe n'existe pas, tous les
   boutons sont là. */
.qualif[data-tunnel] .qualif__nav--auto [data-pas]:not(:focus-visible) {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* --- La flèche de retour ---------------------------------------------------
   « Revenir en arrière » est une flèche depuis le 16.08 (le mot voyage en
   aria-label et title), agrandie deux fois dans la soirée : cercle de 60 px,
   glyphe 1,9rem. SA DÉFINITION VIT PLUS HAUT, dans la règle sous
   [data-tunnel] : une seconde règle à plus faible spécificité perdait le
   glyphe et le cercle en silence, payé une fois. */

/* --- Les dernières précisions (16.08 au soir) ------------------------------ */

/* Le site et la question ouverte paraissent dès qu'UNE carte est choisie,
   n'importe laquelle (dernier réglage du 16.08) : deux champs libres qui
   accompagnent le choix sans le précéder — l'écran s'ouvre court, une page.
   Pur :has : le repli sans script fait exactement pareil. */
.qualif__precisions { display: none; }
.qualif__ecran:has(input[name="visuel"]:checked) .qualif__precisions {
  display: grid;
  gap: 1.1rem;
}

/* --- La hauteur naturelle (16.08 au soir) --------------------------------- */

/* L'égalisation des hauteurs (les six écrans empilés dans une cellule de
   grille) a vécu une demi-journée : elle clouait le pied, LE PIED N'EXISTE
   PLUS sur cette page, et son seul effet restant était du vide scrollable
   sous les écrans courts au téléphone (« il ne faut pas pouvoir scroller
   dans le vide », Nazaire). Chaque étape reprend sa hauteur : le formulaire
   et c'est tout, une page ergonomique par écran. */

/* --- Le masquage, en dernier mot ----------------------------------------- */

/* PLACÉE ICI, ET PAS AILLEURS. Elle est à égalité de spécificité (0,2,0) avec
   les règles qui rallument la progression, la navigation et le retour du
   curseur sous `[data-tunnel]` : à égalité, c'est l'ordre de source qui
   tranche, et il faut que ce soit celle-ci qui gagne. Sans cette place, un
   élément que le script vient de masquer se rallumait tout seul. */
.qualif [hidden] { display: none; }
