/* =========================================================================
   TUNNEL DE COMMANDE
   -------------------------------------------------------------------------
   Le trafic vient de TikTok et d'Instagram, sur téléphone : ce fichier est
   écrit pour un pouce, et l'affichage large n'est qu'un élargissement.

   Deux règles tenues partout ici :

   1. **Zone tactile de 48 px minimum** sur tout ce qui se touche. En dessous,
      on rate la case et on abandonne — sur un tunnel à 250 €, une cible trop
      petite est un défaut de conversion, pas un détail de confort.

   2. **L'état d'un champ ne repose jamais sur la seule couleur.** Un champ en
      erreur porte un trait épais et un message écrit ; une option choisie
      porte une bordure pleine et un fond. Sur les huit pour cent d'hommes
      atteints de dyschromatopsie, le rouge seul ne dit rien.

   ⚠️ Ce fichier ne contient aucune animation de contenu et le tunnel n'a
   AUCUN script : l'acompte est écrit côté serveur, il ne bouge pas.
   ========================================================================= */

.checkout {
  background: var(--color-paper);
  padding-block: var(--space-6) var(--space-9);
}

.checkout__shell { max-width: 40rem; }

.checkout__title {
  font-family: var(--font-display);
  font-size: var(--title-s);
  font-weight: 700;
  letter-spacing: var(--tracking-tight);
  line-height: 1.05;
  color: var(--color-ink);
  margin: 0 0 var(--space-5);
}

/* -------------------------------------------------------------------------
   L'ANCRE — CE QU'ON ACHÈTE, ET À QUEL PRIX

   Première étape du tunnel : le visiteur peut arriver ici depuis une vidéo,
   sans avoir lu la page produit. La page lui demandait combien de bacs il
   voulait sans avoir jamais écrit le prix d'un bac — le seul montant à
   l'écran était l'acompte, et il se lisait comme un prix.
   ------------------------------------------------------------------------- */

.ancre {
  margin: calc(var(--space-5) * -1) 0 var(--space-6);
  padding: var(--space-4) 0;
  border-block: 1px solid var(--rule);
}

.ancre__quoi {
  margin: 0 0 var(--space-2);
  font-family: var(--font-util);
  font-size: var(--step--1);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--color-cool);
}

.ancre__prix {
  margin: 0;
  font-size: var(--step-1);
  color: var(--color-ink-muted);
}
.ancre__prix b {
  font-family: var(--font-display);
  font-size: var(--step-2);
  color: var(--color-ink);
}

.ancre__barre {
  margin-left: var(--space-2);
  text-decoration: line-through;
  font-size: var(--step--1);
  color: var(--color-cool);
}

.ancre__note {
  margin: var(--space-2) 0 0;
  font-size: var(--step--1);
  color: var(--color-cool);
}

/* L'indication qui précède un champ, et non celle qui le suit : elle doit
   être lue AVANT de choisir, pas après avoir cliqué. */
.field__hint--avant {
  margin-top: 0;
  margin-bottom: var(--space-3);
}
.field__hint--avant b { color: var(--color-ink); }

.checkout__lede {
  font-family: var(--font-body);
  font-size: var(--step-1);
  line-height: 1.55;
  color: var(--color-ink-muted);
  max-width: var(--measure);
  margin: 0 0 var(--space-6);
}

.checkout__aside {
  font-family: var(--font-body);
  font-size: var(--step--1);
  line-height: 1.6;
  color: var(--color-cool);
  margin-top: var(--space-7);
  padding-top: var(--space-5);
  border-top: 1px solid var(--rule);
}
.checkout__aside a { color: var(--color-ink); }

/* -------------------------------------------------------------------------
   MESSAGE D'ERREUR GLOBAL
   Un bandeau, pas une boîte de dialogue : il doit rester lisible quand la
   page est rechargée après un échec de paiement.
   ------------------------------------------------------------------------- */

.alert {
  font-family: var(--font-util);
  font-size: var(--step-0);
  line-height: 1.5;
  color: #7A2820;
  background: #FBEDEB;
  border-left: 3px solid #B4423A;
  padding: var(--space-4);
  margin: 0 0 var(--space-6);
}
.alert p { margin: 0; }

/* Le récapitulatif des refus, en tête de formulaire. Chaque ligne emmène au
   champ : sur un téléphone, le message qui explique le refus peut être à deux
   écrans plus bas, et personne ne fait défiler une page qui semble n'avoir
   rien changé. Le lien est souligné parce qu'il est un lien. */
.alert__list {
  margin: var(--space-2) 0 0;
  padding-left: 1.1em;
}
.alert__list li { margin-top: var(--space-1); }
.alert__list a { color: inherit; font-weight: 600; }

/* -------------------------------------------------------------------------
   FORMULAIRE
   ------------------------------------------------------------------------- */

.form { display: block; }

.form__legend {
  font-family: var(--font-util);
  font-size: var(--step--2);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--color-cool);
  margin: var(--space-7) 0 var(--space-4);
  padding-top: var(--space-4);
  border-top: 1px solid var(--rule);
}
.form__legend:first-of-type { margin-top: var(--space-2); }
/* Le titre « Installation » vit dans son bloc masquable : premier de son
   parent, il garderait la marge réduite du tout premier titre. */
.bloc-installation .form__legend:first-of-type { margin-top: var(--space-7); }
/* `.field` pose `display: block`, ce qui l'emporte sur `[hidden]` du
   navigateur : sans cette règle, le bloc masqué par le serveur s'affiche. */
.field[hidden] { display: none; }

/* Le récapitulatif d'erreurs renvoie au champ par une ancre : sans marge, le
   navigateur colle le champ au bord haut et son libellé passe au-dessus de
   l'écran — un champ rouge sans son nom (marcheur du 10 septembre). */
:target { scroll-margin-top: 4.5rem; }

.form__submit { width: 100%; margin-top: var(--space-6); }

.form__foot {
  font-family: var(--font-util);
  font-size: var(--step--1);
  line-height: 1.55;
  color: var(--color-cool);
  text-align: center;
  margin: var(--space-4) 0 0;
}

/* -------------------------------------------------------------------------
   CHAMPS
   ------------------------------------------------------------------------- */

.field {
  display: block;
  border: 0;
  padding: 0;
  margin: 0 0 var(--space-5);
}

.field__label {
  display: block;
  font-family: var(--font-util);
  font-size: var(--step--1);
  font-weight: 600;
  color: var(--color-ink);
  margin-bottom: var(--space-2);
  padding: 0;
}

/* « facultatif » doit se lire du premier coup : c'est ce qui évite qu'un
   client s'arrête pour aller chercher son SIRET — et ne revienne pas. */
.field__opt {
  font-weight: 400;
  font-size: var(--step--2);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--color-cool);
  margin-left: var(--space-2);
}

.field__input {
  display: block;
  width: 100%;
  min-height: 3rem;
  padding: var(--space-3);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius);
  background: #fff;
  color: var(--color-ink);
  font-family: var(--font-util);
  /* 16px pile : en dessous, iOS zoome à la mise au point et le formulaire
     part hors cadre. C'est la valeur, pas une préférence esthétique. */
  font-size: 1rem;
  line-height: 1.4;
}
.field__input:focus-visible {
  outline: 2px solid var(--color-volt);
  outline-offset: 1px;
  border-color: var(--color-volt);
}

.field__hint {
  font-family: var(--font-util);
  font-size: var(--step--1);
  line-height: 1.5;
  color: var(--color-cool);
  margin: var(--space-2) 0 0;
}

/* Le trait épais porte l'information autant que la couleur. */
.field--bad .field__input { border-color: #B4423A; border-width: 2px; }
.field__error {
  font-family: var(--font-util);
  font-size: var(--step--1);
  font-weight: 600;
  line-height: 1.5;
  color: #93332C;
  margin: var(--space-2) 0 0;
}

.field-pair { display: grid; gap: 0; }
@media (min-width: 34em) {
  .field-pair { grid-template-columns: 1fr 1fr; gap: 0 var(--space-4); }
  .field-pair .field--zip { grid-column: auto; }
}

/* -------------------------------------------------------------------------
   QUANTITÉ — cinq pastilles, chacune portant son acompte
   Le chiffre d'abord, l'étiquette en petit dessous : c'est la grammaire du
   reste du site, reprise ici pour que le tunnel n'ait pas l'air d'un autre
   produit que la page qui y mène.
   ------------------------------------------------------------------------- */

/* 3.4rem de largeur minimale, et c'est mesuré, pas choisi.
   Sur un écran de 390 px — un iPhone courant — la piste utile fait 350 px une
   fois les marges retirées, moins 32 px d'écarts : 63 px par pastille pour
   cinq. À 4,25rem (68 px) la cinquième tombait seule sur une deuxième ligne,
   ce qui la faisait lire comme une option à part. Vérifié en capture le
   12 août. */
.chips {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(3.4rem, 1fr));
  gap: var(--space-2);
}

.chips__label {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  min-height: 3.4rem;
  padding: var(--space-2);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius);
  background: #fff;
  cursor: pointer;
  text-align: center;
  transition: border-color .15s var(--ease), background-color .15s var(--ease);
}

.chips__n {
  font-family: var(--font-display);
  font-size: var(--step-2);
  font-weight: 700;
  line-height: 1;
  color: var(--color-ink);
}

.chips__input:checked + .chips__label {
  border-color: var(--color-navy);
  border-width: 2px;
  background: var(--color-navy);
}
.chips__input:checked + .chips__label .chips__n   { color: #fff; }

/* Le focus doit se voir sur la PASTILLE : la case elle-même est en sr-only,
   son contour ne serait visible nulle part. */
.chips__input:focus-visible + .chips__label {
  outline: 2px solid var(--color-volt);
  outline-offset: 2px;
}

/* -------------------------------------------------------------------------
   OPTIONS DE LIVRAISON
   ------------------------------------------------------------------------- */

.options { display: grid; gap: var(--space-3); }

.options__label {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--space-1) var(--space-4);
  align-items: baseline;
  min-height: 3.5rem;
  padding: var(--space-4);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius);
  background: #fff;
  cursor: pointer;
  transition: border-color .15s var(--ease);
}

.options__name {
  font-family: var(--font-util);
  font-size: var(--step-0);
  font-weight: 600;
  color: var(--color-ink);
}
.options__price {
  font-family: var(--font-util);
  font-size: var(--step-0);
  font-weight: 700;
  color: var(--color-ink);
  white-space: nowrap;
}
.options__desc {
  grid-column: 1 / -1;
  font-family: var(--font-util);
  font-size: var(--step--1);
  line-height: 1.5;
  color: var(--color-cool);
}

/* Le mode de livraison hors contexte disparaît avec son bouton.
   En Île-de-France, cocher l'installation remplace la grille par la ligne
   « nous apportons et nous posons » ; ailleurs, cette ligne n'existe pas.
   Le bouton masqué est `disabled` côté HTML — le cacher ici ne suffirait
   pas, un radio caché mais coché partirait quand même avec le formulaire. */
.options__input:disabled + .options__label { display: none; }

.options__input:checked + .options__label {
  border-color: var(--color-navy);
  border-width: 2px;
  /* La bordure passe de 1 à 2 px : sans compensation, la carte saute d'un
     pixel au clic et la liste tressaute sous le doigt. */
  padding: calc(var(--space-4) - 1px);
}
.options__input:focus-visible + .options__label {
  outline: 2px solid var(--color-volt);
  outline-offset: 2px;
}

/* -------------------------------------------------------------------------
   CASES À COCHER
   ------------------------------------------------------------------------- */

.check {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-3);
  align-items: start;
  padding: var(--space-3) 0;
  cursor: pointer;
}

.check__input {
  /* 1.375rem = 22px de case, mais la zone touchable réelle est portée par le
     label entier, qui fait toute la largeur. */
  width: 1.375rem; height: 1.375rem;
  margin: 1px 0 0;
  accent-color: var(--color-navy);
  flex: none;
}
.check__input:focus-visible { outline: 2px solid var(--color-volt); outline-offset: 2px; }

.check__text {
  font-family: var(--font-util);
  font-size: var(--step-0);
  line-height: 1.5;
  color: var(--color-ink);
}
.check__text small {
  display: block;
  font-size: var(--step--1);
  line-height: 1.55;
  color: var(--color-cool);
  margin-top: var(--space-2);
}

/* -------------------------------------------------------------------------
   RÉCAPITULATIF ET TOTAUX
   `tabular-nums` est réservé à ces colonnes, et à elles seules : en mode
   tabulaire la virgule prend la largeur d'un chiffre et se détache du
   nombre. Sur un total, l'alignement le vaut ; dans une phrase, non.
   ------------------------------------------------------------------------- */

.recap {
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: #fff;
  padding: var(--space-4);
  margin-bottom: var(--space-6);
}

.recap__row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-4);
  padding-bottom: var(--space-3);
  margin-bottom: var(--space-3);
  border-bottom: 1px solid var(--rule);
}
.recap__row:last-of-type { border-bottom: 0; }

/* ⚠️ `flex: 0 1 auto` et non `flex: none`. Avec `none`, un libellé un peu long
   — « Solde à régler avant l'expédition » — ne cédait pas un pixel et écrasait
   la colonne de droite : le montant se brisait alors en « 589 / 6,00 / € »,
   sur trois lignes, parce que `.recap__val` autorise la coupure n'importe où
   (nécessaire pour les adresses email). Entre un libellé qui passe à la ligne
   et un nombre coupé en morceaux, c'est toujours le libellé qui cède. */
.recap__key {
  font-family: var(--font-util);
  font-size: var(--step--2);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--color-cool);
  flex: 0 1 auto;
  min-width: 0;
}
.recap__val {
  font-family: var(--font-util);
  font-size: var(--step-0);
  color: var(--color-ink);
  text-align: right;
  overflow-wrap: anywhere;
}
.recap__val--mono { font-weight: 700; letter-spacing: .04em; }

/* `overflow-wrap: anywhere` existe pour les adresses email, qui doivent bien
   se couper quelque part. Un montant, jamais. */
.recap__val--montant { white-space: nowrap; overflow-wrap: normal; }

/* « Modifier » est DANS LE FLUX, et c'est une correction.
   Il était posé en absolu dans le coin haut-droit du bloc — et une raison
   sociale un peu longue passait dessous : « Studio Coiffure Bastille » et
   « Modifier » se chevauchaient, rendant les deux illisibles. Constaté en
   capture mobile le 12 août.
   Un élément positionné en absolu par-dessus du texte de longueur inconnue est
   une collision qui attend son client. Ici la ligne suit, elle ne survole
   plus. */
.recap__edit {
  display: block;
  margin-top: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px solid var(--rule);
  font-family: var(--font-util);
  font-size: var(--step--1);
  font-weight: 600;
  color: var(--color-volt);
  text-align: right;
  text-decoration: underline;
  /* Zone tactile : le lien fait toute la largeur du bloc, on ne le rate pas. */
  min-height: 1.5rem;
}

.recap--final .recap__row:first-child .recap__val { font-size: var(--step-1); }

.total {
  border-top: 1px solid var(--rule-strong);
  margin-top: var(--space-6);
  padding-top: var(--space-4);
}

/* ⚠️ **Pas de `tabular-nums` ici, et c'est un revirement mesuré.**
   La règle y était, sur la colonne de droite seulement, pour aligner les
   décimales. Elle produisait « 6 396 , 00 € TTC » : en mode tabulaire, la
   virgule prend la largeur d'un chiffre et se détache de ses centimes. Sur le
   dernier écran avant le paiement, c'est le total de la commande qui devient
   illisible.

   L'alignement qu'elle apportait était de toute façon déjà là : `.total__row`
   est un flex en `space-between`, les montants finissent donc tous sur le même
   bord droit. Et ils ont tous deux décimales. Le mode tabulaire ne corrigeait
   rien qui ne l'était pas — il ne restait que son défaut. */

.total__row {
  display: flex;
  justify-content: space-between;
  gap: var(--space-4);
  font-family: var(--font-util);
  font-size: var(--step-0);
  line-height: 1.5;
  color: var(--color-ink-muted);
  padding-block: var(--space-2);
}

/* Un montant ne se coupe pas. Sur 390 px, « 5 980,00 € HT » se repliait en
   « 5 980,00 € » puis « HT » à la ligne, et le signe moins de la remise
   restait seul au-dessus de sa valeur : un tableau de prix illisible au moment
   exact où le client vérifie ses chiffres. C'est le libellé qui doit céder. */
.total__row > :last-child { white-space: nowrap; flex: none; }
.total__row > :first-child { min-width: 0; }

.total__row--sum {
  font-size: var(--step-1);
  font-weight: 700;
  color: var(--color-ink);
  border-top: 1px solid var(--rule);
  margin-top: var(--space-2);
  padding-top: var(--space-3);
}
.total__row--rest { font-size: var(--step--1); color: var(--color-cool); }

/* -------------------------------------------------------------------------
   LES DEUX ÉCHÉANCES

   Le total de la commande répond à « combien ça coûte ». Ces deux lignes
   répondent à « combien part de mon compte, et quand » — et c'est la seule
   question qu'on se pose, la carte à la main. Elles sont donc plus lourdes
   visuellement que le tableau au-dessus, pas moins.

   Celle d'aujourd'hui porte le fond papier et le filet volt : c'est le seul
   montant sur lequel on clique.
   ------------------------------------------------------------------------- */

.echeances {
  margin-top: var(--space-4);
  border-top: 1px solid var(--rule-strong);
  padding-top: var(--space-4);
  display: grid;
  gap: var(--space-2);
}

.echeance {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-4);
  padding: var(--space-3) var(--space-4);
  font-family: var(--font-util);
}

.echeance--maintenant {
  background: var(--color-plate);
  border-left: 3px solid var(--color-volt);
  border-radius: var(--radius);
}

.echeance__quoi {
  display: flex;
  flex-direction: column;
  gap: .15em;
  font-size: var(--step-0);
  font-weight: 600;
  color: var(--color-ink);
  min-width: 0;
}

.echeance__quoi small {
  font-size: var(--step--2);
  font-weight: 400;
  line-height: 1.4;
  color: var(--color-cool);
}

.echeance__combien {
  flex: none;
  font-size: var(--step-1);
  font-weight: 700;
  color: var(--color-ink);
}

.echeance--maintenant .echeance__combien { color: var(--color-volt); }

/* -------------------------------------------------------------------------
   L'ENGAGEMENT

   Encadré, mais sans dramatisation : ni rouge, ni pictogramme d'alerte. Ce
   n'est pas un avertissement, c'est le contrat — et il est symétrique.
   ------------------------------------------------------------------------- */

/* La période d'arrivée, juste au-dessus de l'engagement.
   Volontairement PLUS DISCRÈTE que lui : c'est une information, pas une clause.
   Elle est là parce que la page produit n'annonce plus aucun délai depuis le
   13 août — les dates ne se lisent qu'où elles engagent — et parce que
   l'article 8 des CGV, accepté juste en dessous, fonde le délai sur une période
   « annoncée ». Sans elle, l'acheteur accepterait une clause dans le vide. */
.arrivee {
  margin: var(--space-5) 0 calc(-1 * var(--space-2));
  font-family: var(--font-util);
  font-size: var(--step--1);
  line-height: 1.6;
  color: var(--color-cool);
}
.arrivee b { color: var(--color-ink); font-weight: 600; }

.engagement {
  margin: var(--space-5) 0 var(--space-4);
  padding: var(--space-4);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius);
  font-size: var(--step--1);
  line-height: 1.6;
  color: var(--color-ink-muted);
}
.engagement b { color: var(--color-ink); }
.engagement a { color: var(--color-volt); }

.total__pending {
  font-family: var(--font-util);
  font-size: var(--step--1);
  color: var(--color-cool);
  margin: 0;
}

/* -------------------------------------------------------------------------
   LA SUITE, APRÈS PAIEMENT
   Trois lignes datées. Ce qui n'est pas dit ici devient un appel.
   ------------------------------------------------------------------------- */

.steps {
  list-style: none;
  margin: var(--space-7) 0 0;
  padding: 0;
  counter-reset: etape;
  border-top: 1px solid var(--rule);
}

.steps__item {
  counter-increment: etape;
  display: grid;
  grid-template-columns: 1.75rem 1fr;
  gap: var(--space-1) var(--space-3);
  padding: var(--space-4) 0;
  border-bottom: 1px solid var(--rule);
}
.steps__item::before {
  content: counter(etape);
  grid-row: 1 / 3;
  font-family: var(--font-util);
  font-size: var(--step--1);
  font-weight: 700;
  color: var(--color-cool);
  padding-top: 2px;
}

.steps__what {
  font-family: var(--font-util);
  font-size: var(--step-0);
  font-weight: 600;
  color: var(--color-ink);
}
.steps__why {
  font-family: var(--font-body);
  font-size: var(--step--1);
  line-height: 1.55;
  color: var(--color-ink-muted);
}

@media (hover: hover) {
  .chips__label:hover,
  .options__label:hover { border-color: var(--color-ink); }
}

/* Le récapitulatif par variantes (étape 2) : chaque combinaison
   livraison × installation est rendue par le serveur et cachée par l'attribut
   `hidden` ; le script de la page montre la bonne. Quand une variante est
   visible, la ligne d'attente disparaît. */
.total--live .total__pending { display: none; }
