/* ──────────────────────────────────────────────────────────────
   « HIDDEN » VEUT DIRE CACHÉ. TOUJOURS.

   Vincent, 31 août, capture d'écran à l'appui : « le dimensionnement
   ici est toujours pas réglé ». Chaque modèle de la fenêtre s'affichait
   encore au complet — quantité, note, coûtant, spécifications — alors
   que le gabarit écrit bien « hidden » sur le volet.

   Le défaut n'était pas dans le gabarit, il était ici. Le navigateur
   cache [hidden] avec « display: none », mais c'est une règle de sa
   feuille à lui : la MOINDRE classe qui déclare un display la bat.
   « .pan-l-plus { display: grid } » suffisait, et rien ne le signalait
   — pas d'erreur, pas de console, juste une fenêtre trois fois trop
   longue devant un client.

   Cette règle-ci referme le piège pour toute la feuille, une fois. Elle
   porte !important parce que c'est exactement son travail : gagner
   contre n'importe quelle classe qui déclarerait un display, y compris
   celles qui n'existent pas encore.

   Vérifiée par outils/verifier-que-cache-veut-dire-cache.py
   ────────────────────────────────────────────────────────────── */
[hidden] { display: none !important; }

/* Prise de rendez-vous — Piscines VP.

   Deux sources, et elles ne se contredisent pas :

   La MISE EN PAGE vient du formulaire actuel, relevée au pixel — carte
   blanche à coins ronds, menus déroulants à bordure fine, libellés de
   14 px en demi-gras. Les clients la connaissent déjà.

   L'IDENTITÉ vient de piscinesvp.com — Poppins, le bleu #0077F9, les
   boutons en pilule et en majuscules. Le formulaire doit se reconnaître
   comme du Piscines VP dès la première seconde.

   Le comportement, lui, est pensé pour le pouce : 85 % des rendez-vous
   se prennent sur un téléphone, souvent debout à côté d'une piscine. Les
   zones tactiles montent à 50 px et le bouton principal se colle en bas.
   Sur écran large, tout retrouve la mise en page connue. */

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
    margin: 0;
    background: linear-gradient(180deg, #F7FBFF 0%, #E9F1FB 100%);
    background-attachment: fixed;
    color: var(--ink);
    font-family: var(--corps);
    font-size: 16px;
    line-height: 1.55;
    -webkit-font-smoothing: antialiased;
}

/* Ce que la barre d'action collée mange en bas d'écran. */
:root { --barre: 86px; }

a { color: var(--vp); }
a:focus-visible, button:focus-visible, input:focus-visible,
select:focus-visible, textarea:focus-visible {
    outline: 3px solid rgba(0, 119, 249, .32); outline-offset: 2px;
}

/* ── L'ossature ────────────────────────────────────────── */

.page { min-height: 100dvh; display: flex; flex-direction: column; }
/* LE HAUT AUSSI A SON ENCOCHE.  (D169)

   Le gabarit déclare `viewport-fit=cover` : la page s'étend sous la
   barre d'état et sous l'îlot dynamique. Le bas était compensé — c'est
   là que vit la barre d'action — mais le haut ne l'était pas.

   Résultat sur un iPhone récent : le titre de l'étape passait sous
   l'heure et sous l'îlot, et se lisait comme deux textes superposés.

   `env(safe-area-inset-top)` vaut zéro partout où il n'y a pas
   d'encoche : la règle ne coûte rien sur un ordinateur ou un vieux
   téléphone. */
.shell {
    width: 100%; max-width: 640px; margin: 0 auto;
    padding: env(safe-area-inset-top) 0 calc(var(--barre) + env(safe-area-inset-bottom));
    display: flex; flex-direction: column; flex: 1;
}

.logo {
    display: flex; align-items: center; gap: 10px; justify-content: center;
    text-decoration: none; color: var(--ink); padding: 22px 20px 16px;
}
.logo img { display: block; height: 40px; width: auto; }
.mark {
    width: 34px; height: 34px; border-radius: 10px;
    background: linear-gradient(135deg, var(--vp-clair), var(--vp-fonce));
    color: #fff; display: grid; place-items: center;
    font-weight: 800; font-size: 13px; letter-spacing: -.4px;
}
.wordmark { font-family: var(--titre); font-weight: 800; font-size: 15px; letter-spacing: -.01em; }

/* ── La carte ──────────────────────────────────────────── */

.card {
    background: var(--paper);
    border: 1px solid var(--bord-carte);
    border-radius: var(--r-carte) var(--r-carte) 0 0;
    box-shadow: var(--ombre);
    flex: 1; display: flex; flex-direction: column;
}

.card-head { padding: 28px 22px 0; text-align: center; }
.card-head h1 {
    font-family: var(--titre);
    font-size: 11px; font-weight: 700;
    letter-spacing: .16em; text-transform: uppercase;
    color: var(--vp); margin: 0;
}
.step-name {
    font-family: var(--titre);
    font-size: 25px; font-weight: 800; letter-spacing: -.025em;
    color: var(--ink); margin: 7px 0 0; line-height: 1.2;
    text-wrap: balance;
}

.steps { display: flex; gap: 6px; margin: 22px 0 0; }
.dot { flex: 1; height: 3px; border-radius: 2px; background: #E5E7EB; transition: background .25s; }
.dot.done, .dot.now { background: var(--vp); }
.dot.now { opacity: .55; }

.card-body { padding: 26px 22px 30px; flex: 1; }

/* ── Champs ────────────────────────────────────────────── */

.fld { margin-bottom: 22px; }
.fld:last-of-type { margin-bottom: 0; }

.fld label, .fld > .legende {
    display: block; font-size: 14px; font-weight: 500;
    color: var(--ink-2); margin-bottom: 8px;
}
.req { color: var(--alerte); font-weight: 500; margin-left: 2px; }

.fld input[type="text"], .fld input[type="email"], .fld input[type="tel"],
.fld input[type="number"], .fld input[type="date"], .fld textarea {
    width: 100%; padding: 13px 15px; min-height: 50px;
    font-family: inherit; font-size: 16px; color: var(--ink);
    background: var(--paper); border: 1px solid var(--bord);
    border-radius: var(--r); outline: none;
    transition: border-color .15s, box-shadow .15s;
    -webkit-appearance: none; appearance: none;
}
.fld input:hover, .fld textarea:hover { border-color: #9CA3AF; }

/* Le menu déroulant : blanc, bordure fine, chevron gris — comme
   aujourd'hui, mais assez haut pour un pouce. */
.fld select {
    width: 100%; padding: 13px 44px 13px 15px; min-height: 50px;
    font-family: inherit; font-size: 16px; color: var(--ink);
    background-color: var(--paper);
    border: 1px solid var(--bord); border-radius: var(--r);
    outline: none; cursor: pointer;
    transition: border-color .15s, box-shadow .15s;
    -webkit-appearance: none; appearance: none;
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='9' fill='none'%3E%3Cpath d='M1 1.5 7 7.5l6-6' stroke='%236B7280' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat; background-position: right 16px center;
}
.fld select:hover { border-color: #9CA3AF; }
.fld select:focus { border-color: var(--vp); box-shadow: 0 0 0 3px rgba(0, 119, 249, .12); }
.fld select:invalid, .fld select option[value=""] { color: var(--ink-3); }

.fld textarea { min-height: 104px; resize: vertical; line-height: 1.55; }
.fld input:focus, .fld textarea:focus {
    border-color: var(--vp); box-shadow: 0 0 0 3px rgba(0, 119, 249, .12);
}
.fld input::placeholder, .fld textarea::placeholder { color: #9CA3AF; }
.fld input:disabled { background: #F3F4F6; color: var(--ink-3); border-color: #F3F4F6; }

.hint { font-size: 13px; color: var(--ink-3); margin: 7px 0 0; line-height: 1.45; }

/* Une note qu'il faut LIRE avant de répondre. Vincent, doc 5, sur « On
   cogne et on vous appelle d'abord » : « ici peut etre le mettre en
   rouge ? ». Elle porte un filet et un fond pâle en plus de la couleur —
   un rouge seul ne dit rien à quelqu'un qui distingue mal les couleurs, et
   c'est justement la note qu'il ne faut pas manquer. */
.hint-alerte {
    font-size: 13px;
    line-height: 1.45;
    margin: 7px 0 0;
    color: #A11212;
    background: #FEF2F2;
    border: 1px solid #F5C6C6;
    border-left: 3px solid #D42B2B;
    border-radius: 8px;
    padding: 8px 11px;
    font-weight: 600;
}
.err { font-size: 13px; color: var(--alerte); margin: 7px 0 0; }

.deux { display: grid; grid-template-columns: 1fr 1fr; gap: 0 14px; }
@media (max-width: 420px) { .deux { grid-template-columns: 1fr; } }

/* ── Choix avec prix : la grille du formulaire actuel ──── */

.choix { display: grid; gap: 10px; }

.choix label {
    display: grid; grid-template-columns: 20px 1fr auto; gap: 13px;
    align-items: center; margin: 0; min-height: 56px;
    padding: 14px 16px;
    background: var(--paper); border: 1px solid var(--bord);
    border-radius: var(--r); cursor: pointer;
    font-size: 15px; color: var(--ink);
    transition: border-color .14s, box-shadow .14s;
}
.choix label:hover { border-color: #9CA3AF; }
.choix label:has(input:checked) {
    border-color: var(--vp); box-shadow: 0 0 0 3px rgba(0, 119, 249, .12);
}
.choix input { position: absolute; opacity: 0; width: 0; height: 0; }

.puce {
    width: 20px; height: 20px; border-radius: 50%;
    border: 1.5px solid var(--bord); background: var(--paper);
    display: grid; place-items: center; flex: none; transition: border-color .14s;
}
.puce.carree { border-radius: 5px; }
.choix label:has(input:checked) .puce { border-color: var(--vp); }
.puce::after {
    content: ""; width: 10px; height: 10px; border-radius: 50%;
    background: var(--vp); transform: scale(0);
    transition: transform .16s cubic-bezier(.3, 1.5, .6, 1);
}
.puce.carree::after { border-radius: 2px; width: 9px; height: 9px; }
.choix label:has(input:checked) .puce::after { transform: scale(1); }

.choix .titre { display: block; font-weight: 500; line-height: 1.35; }
.choix .detail { display: block; font-size: 13px; color: var(--ink-3); margin-top: 2px; }
.choix .prix {
    font-size: 15px; font-weight: 600; color: var(--ink);
    font-variant-numeric: tabular-nums; white-space: nowrap;
}

/* R50/R56 -- le petit « ? » qui en dit plus. La description courte reste
   visible : un client ne doit jamais avoir à cliquer pour savoir ce qu'il
   achète. La version longue s'ouvre pour celui qui en veut plus. */
.choix .choix-item { min-width: 0; }
.long-descr { margin: 6px 2px 0; font-size: 13.5px; }
.long-descr summary {
    cursor: pointer; color: var(--vp); width: max-content;
    display: flex; align-items: center; gap: 7px;
    list-style: none; font-weight: 500; padding: 2px 4px;
}
.long-descr summary::-webkit-details-marker { display: none; }
.long-descr summary::before {
    content: "?"; width: 17px; height: 17px; border-radius: 50%;
    border: 1.5px solid currentColor; display: grid; place-items: center;
    font-size: 11px; font-weight: 700; flex: none;
}
.long-descr[open] summary { margin-bottom: 6px; }
.long-descr .texte-long {
    background: var(--champ); border: 1px solid var(--bord-doux);
    border-radius: var(--r); padding: 12px 14px;
    color: var(--ink-2); line-height: 1.55;
}

/* ── Les journées ──────────────────────────────────────── */

/* ── Le calendrier ──────────────────────────────────────────
   Un vrai mois, pas une rangée de pastilles. Les gens savent lire un
   calendrier depuis l'enfance : leur en donner un, c'est leur épargner
   l'effort de comprendre une invention. Les journées fermées restent
   visibles et muettes — un trou dans la grille est plus troublant qu'une
   case grise. */

.cal { border: 1px solid var(--bord); border-radius: var(--r); overflow: hidden; }

.cal-tete {
    display: flex; align-items: center; justify-content: space-between;
    gap: 10px; padding: 12px 12px 12px 16px;
    border-bottom: 1px solid var(--bord-doux); background: var(--champ);
}
.cal-mois {
    font-family: var(--titre); font-size: 16px; font-weight: 700;
    text-transform: capitalize; letter-spacing: -.01em;
}
.cal-fleche {
    width: 40px; height: 40px; flex: none; display: grid; place-items: center;
    background: var(--paper); border: 1px solid var(--bord); border-radius: 11px;
    color: var(--ink-2); font-size: 17px; cursor: pointer; line-height: 1;
    transition: border-color .14s, color .14s;
}
.cal-fleche:hover:not(:disabled) { border-color: var(--vp); color: var(--vp); }
.cal-fleche:disabled { opacity: .3; cursor: default; }
.cal-nav { display: flex; gap: 8px; }

.cal-sem {
    display: grid; grid-template-columns: repeat(7, minmax(0, 1fr));
    padding: 10px 8px 4px;
}
.cal-sem span {
    text-align: center; font-size: 11px; font-weight: 700;
    letter-spacing: .06em; text-transform: uppercase; color: var(--ink-3);
}

.cal-grille {
    display: grid; grid-template-columns: repeat(7, minmax(0, 1fr));
    gap: 5px; padding: 4px 8px 12px;
}

/* Une case vide : le mois ne commence pas un lundi. */
.cal-vide { aspect-ratio: 1; }

/* Une journée fermée. Présente, lisible, sans promesse. */
/* LA CASE NE POUSSE PAS SA COLONNE.  (D169)

   Sans `min-width: 0`, la largeur minimale d'une case est celle de son
   contenu le plus long — et le nom du secteur est en `white-space:
   nowrap`. Un secteur qui s'appelle « Est éloignée » demandait donc
   soixante pixels par colonne, sept colonnes n'entraient plus dans un
   téléphone, et les dernières se faisaient couper par le
   `overflow-x: clip` de la page.

   Vincent voyait un calendrier « compressé où il manque des jours ».
   Ils n'étaient pas manquants : ils étaient hors de l'écran, coupés en
   silence. Le défaut ne se voyait qu'avec un secteur au nom long —
   « Nord » passait, « Est éloignée » non. */
.cal-jour {
    position: relative; aspect-ratio: 1; min-height: 42px; margin: 0;
    min-width: 0;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 2px; border-radius: 11px;
    font-variant-numeric: tabular-nums;
    color: #C4CBD4; font-size: 15px;
}

/* Une journée offerte. */
.cal-jour.libre {
    color: var(--ink); font-weight: 600; cursor: pointer;
    background: var(--paper); border: 1px solid var(--bord);
    transition: border-color .14s, background .14s, color .14s;
}
.cal-jour.libre:hover { border-color: var(--vp); background: #F4F9FF; }
.cal-jour input { position: absolute; opacity: 0; width: 0; height: 0; }

.cal-jour.libre:has(input:checked) {
    background: var(--vp); border-color: var(--vp); color: #fff;
    box-shadow: 0 0 0 3px rgba(0, 119, 249, .16);
}

/* Aujourd'hui, même fermé : un repère pour se situer. */
.cal-jour.aujourdhui::after {
    content: ""; position: absolute; bottom: 6px; left: 50%;
    transform: translateX(-50%);
    width: 4px; height: 4px; border-radius: 50%; background: currentColor;
    opacity: .45;
}

/* Le point ambre des journées hors saison. */
.cal-jour .pastille {
    width: 5px; height: 5px; border-radius: 50%;
    background: var(--attention); flex: none;
}
.cal-jour.libre:has(input:checked) .pastille { background: #fff; }

.cal-legende {
    display: flex; flex-wrap: wrap; gap: 6px 18px;
    padding: 12px 16px; border-top: 1px solid var(--bord-doux);
    background: var(--champ); font-size: 12px; color: var(--ink-3);
}
.cal-legende span { display: inline-flex; align-items: center; gap: 7px; }
.cal-legende i {
    width: 9px; height: 9px; border-radius: 50%; flex: none;
    background: var(--attention);
}
.cal-legende i.libre { border-radius: 3px; background: var(--paper); border: 1px solid var(--bord); }
.cal-legende i.hors {
    border-radius: 3px; background: var(--champ);
    border: 1px dashed var(--bord);
}

/* ── AU TÉLÉPHONE : les journées d'un autre secteur ─────────
   Vincent : « avec la possibilité de booker une journée même si ce n'est
   pas dans son secteur, mais afficher lesquelles sont son secteur et les
   autres, où elles sont. »

   Elles restent CHOISISSABLES — c'est tout le propos. Le trait pointillé
   dit « ce n'est pas le sien » sans dire « c'est fermé » : une case
   éteinte se lit comme un refus, et l'équipe cesserait de les regarder. */
.cal-jour.libre.hors-secteur {
    background: var(--champ);
    border-style: dashed;
    color: var(--ink-2);
    font-weight: 500;
}
.cal-jour.libre.hors-secteur:hover { border-color: var(--vp); background: #F4F9FF; }
.cal-jour.libre.hors-secteur:has(input:checked) {
    background: var(--vp); border-style: solid; color: #fff;
}

/* Le nom du secteur sous le chiffre. Il se coupe plutôt que de déformer
   la case : le nom au long reste au survol et sous la grille. */
.cal-secteur {
    font-size: 8.5px; font-weight: 700; line-height: 1;
    letter-spacing: .02em; text-transform: uppercase;
    color: var(--ink-3);
    max-width: 100%; padding: 0 2px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cal-jour.libre.hors-secteur:has(input:checked) .cal-secteur { color: rgba(255, 255, 255, .85); }

/* Où sont les autres, regroupées. La grille dit qu'une journée existe
   ailleurs; elle ne dit pas lesquelles vont ensemble. « On passe à
   Blainville les 12, 19 et 26 » — c'est la phrase qu'on dit au client
   au téléphone. */
.cal-ailleurs {
    margin-top: 14px;
    border: 1px solid var(--bord); border-radius: 12px;
    background: var(--paper);
}
.cal-ailleurs > summary {
    cursor: pointer; padding: 11px 15px;
    font-size: 13.5px; font-weight: 600; color: var(--vp);
}
.cal-ailleurs ul {
    margin: 0; padding: 0 15px 13px; list-style: none;
    display: flex; flex-direction: column; gap: 8px;
}
.cal-ailleurs li {
    display: flex; gap: 10px; flex-wrap: wrap;
    padding-top: 8px; border-top: 1px solid var(--bord-doux);
    font-size: 13.5px;
}
.cal-ailleurs li b { flex: 0 0 auto; font-weight: 700; }
.cal-ailleurs li span { color: var(--ink-2); }

/* Dans quelle journée on l'ajoute. Au comptoir seulement — c'est ce menu
   qui décide dans quelle tournée le rendez-vous monte, alors il se voit. */
.cal-secteur-choix {
    margin-top: 16px; padding: 14px 16px;
    background: var(--champ);
    border: 1px solid var(--bord); border-left: 3px solid var(--vp);
    border-radius: 0 12px 12px 0;
}
.cal-secteur-choix label {
    display: block; margin-bottom: 7px;
    font-size: 14px; font-weight: 700;
}
/* D156 — 16 px, sinon iOS zoome la page au toucher. Ce menu-là sert au
   comptoir, donc souvent sur un téléphone, un client au bout du fil. */
.cal-secteur-choix select {
    width: 100%; padding: 11px 12px;
    font-size: 16px; font-family: inherit; color: var(--ink);
    background: var(--paper);
    border: 1px solid var(--bord); border-radius: 9px;
}
.cal-secteur-choix .hint { margin: 8px 0 0; font-size: 13px; color: var(--ink-2); }

.cal-hors {
    display: block; margin-top: 4px;
    font-size: 13px; color: var(--attention); font-weight: 600;
}

/* La journée retenue, écrite en toutes lettres sous la grille : un chiffre
   dans une case ne se relit pas, une phrase oui. */
.cal-choisie {
    margin-top: 14px; padding: 14px 16px;
    background: #F0F7FF; border: 1px solid #CFE4FF; border-radius: var(--r);
    font-size: 15px; color: var(--vp-fonce);
}
.cal-choisie b { font-weight: 700; text-transform: capitalize; }
.cal-choisie .sup { display: block; margin-top: 4px; font-size: 13px; color: var(--attention); }

.vide {
    padding: 32px 22px; text-align: center;
    background: var(--champ); border: 1px dashed var(--bord); border-radius: var(--r);
    color: var(--ink-2); font-size: 15px; line-height: 1.55;
}
.vide b { display: block; color: var(--ink); margin-bottom: 5px; font-size: 16px; }

/* ── Récapitulatif ─────────────────────────────────────── */

.recap { border: 1px solid var(--bord-carte); border-radius: var(--r); overflow: hidden; margin: 0; }
.recap-l {
    display: flex; justify-content: space-between; gap: 18px;
    padding: 13px 16px; border-top: 1px solid var(--bord-carte); font-size: 15px;
}
.recap-l:first-child { border-top: 0; }
.recap-l dt { color: var(--ink-3); margin: 0; font-size: 14px; }
.recap-l dd { margin: 0; text-align: right; color: var(--ink); }
.recap-l.total { background: var(--champ); font-weight: 700; }
.recap-l.total dd { font-variant-numeric: tabular-nums; }
.prix { font-weight: 600; font-variant-numeric: tabular-nums; }

/* ── Consentement ──────────────────────────────────────── */

.consent {
    display: grid; grid-template-columns: 22px 1fr; gap: 12px; align-items: start;
    padding: 15px 16px; background: var(--champ);
    border: 1px solid var(--bord-doux); border-radius: var(--r);
    font-size: 14px; line-height: 1.5; color: var(--ink-2); cursor: pointer;
}
.consent input { width: 20px; height: 20px; margin: 0; accent-color: var(--vp); }

/* ── Messages ──────────────────────────────────────────── */

.flash {
    border-radius: var(--r); padding: 14px 16px; margin-bottom: 20px;
    font-size: 14px; line-height: 1.5;
    background: #EFF6FF; color: #1E40AF; border: 1px solid #BFDBFE;
}
.flash.bad { background: var(--alerte-fond); color: #991B1B; border-color: #FECACA; }
.flash.ok { background: var(--ok-fond); color: #065F46; border-color: #A7F3D0; }
.flash b { display: block; margin-bottom: 3px; }
.flash div + div { margin-top: 4px; }

.avis {
    display: flex; gap: 10px; padding: 13px 16px;
    background: var(--attention-fond); border: 1px solid #FDE68A;
    border-radius: var(--r); font-size: 13.5px; color: var(--attention); line-height: 1.5;
}

/* ── Boutons ───────────────────────────────────────────── */

.actions {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 20;
    display: flex; align-items: center; gap: 12px;
    padding: 13px 20px calc(13px + env(safe-area-inset-bottom));
    background: rgba(255, 255, 255, .93);
    backdrop-filter: saturate(180%) blur(14px);
    -webkit-backdrop-filter: saturate(180%) blur(14px);
    border-top: 1px solid var(--bord-carte);
}

.btn { flex: 1; }

.btn-retour {
    flex: none; display: inline-flex; align-items: center; justify-content: center;
    width: 50px; height: 50px; border-radius: 50%;
    background: var(--paper); border: 1px solid var(--bord);
    color: var(--ink-2); text-decoration: none; font-size: 20px; line-height: 1;
}
.btn-retour:hover { border-color: #9CA3AF; }

.chev { font-size: 17px; line-height: 1; margin-top: -1px; }

.help { text-align: center; font-size: 13px; color: var(--ink-3); padding: 18px 20px 10px; margin: 0; }
.help a { color: var(--ink-2); text-decoration: none; }
.help a:hover { color: var(--vp); }

/* ── L'écran de fin ────────────────────────────────────── */

.fini { text-align: center; padding: 6px 0 6px; }
.coche {
    width: 68px; height: 68px; margin: 0 auto 18px; border-radius: 50%;
    background: linear-gradient(135deg, var(--vp-clair), var(--vp-fonce));
    display: grid; place-items: center;
    box-shadow: 0 12px 28px -12px rgba(0, 71, 247, .6);
    animation: pop .4s cubic-bezier(.3, 1.4, .6, 1) both;
}
.coche svg { width: 32px; height: 32px; }
@keyframes pop { from { transform: scale(.55); opacity: 0; } to { transform: scale(1); opacity: 1; } }

.fini h2 { font-family: var(--titre); font-size: 23px; font-weight: 800; letter-spacing: -.02em; margin: 0 0 8px; }
.fini > p { color: var(--ink-2); margin: 0 auto 20px; max-width: 34ch; font-size: 15px; }

/* ── Écran large : la mise en page connue ──────────────── */

@media (min-width: 660px) {
    :root { --barre: 0px; }

    .page { padding: 40px 20px 70px; }
    .shell { padding-bottom: 0; }

    .card { border-radius: var(--r-carte); flex: none; }
    .card-head { padding: 36px 40px 0; }
    /* D169 — reste d'une époque où le h1 ÉTAIT le titre. Depuis, le
       h1 est le petit surtitre bleu et `.step-name` porte le titre :
       trente pixels en majuscules espacées au-dessus d'un titre de
       vingt-cinq inversait la hiérarchie sur grand écran. C'est le
       titre qui grandit, pas son étiquette. */
    .step-name { font-size: 30px; }
    .card-body { padding: 30px 40px 36px; }

    .fld input, .fld select, .fld textarea { min-height: 46px; }
    .fld input[type="text"], .fld input[type="email"],
    .fld input[type="tel"], .fld input[type="number"] { padding: 11px 15px; }
    .fld select { padding: 11px 44px 11px 15px; }

    .actions {
        position: static; padding: 0; margin-top: 30px;
        background: none; backdrop-filter: none; -webkit-backdrop-filter: none;
        border: 0; justify-content: flex-end;
    }
    .btn { flex: none; min-width: 170px; }
    .btn-retour { margin-right: auto; width: 46px; height: 46px; }
}

@media (prefers-reduced-motion: reduce) {
    * { transition: none !important; animation: none !important; }
}

/* ── Le formulaire repris de l'ancien site ──────────────────
   Les questions viennent toutes de la base : un séparateur, un titre de
   groupe, un choix fermé pour la saison. Rien ici n'est propre à un
   service — c'est le même bloc pour les six. */

.legende {
    display: block; margin-bottom: 9px;
    font-family: var(--titre); font-size: 14px; font-weight: 600; color: #374151;
}

.separateur {
    border: 0; border-top: 1px solid #F3F4F6;
    margin: 26px 0 22px;
}

/* Un choix fermé reste lisible : on le grise, on ne le cache pas. Une
   option qui disparaît sans explication fait décrocher le téléphone. */
.choix label.ferme { opacity: .55; cursor: not-allowed; }
.choix label.ferme input { cursor: not-allowed; }
.ferme-mot { color: #92400E; font-weight: 600; }
.hint.ferme-mot { margin-top: 8px; }

/* D137 — « au début du formulaire, mais discrète ». Une ligne au-dessus du
   premier champ, pas un encadré : un bandeau qui parle de compte donnerait
   l'impression qu'il en faut un pour réserver. */
.deja-venu { margin: 0 0 18px; }

/* Une question cachée n'occupe pas de place — y compris avant que le
   script ait tourné, pour éviter le saut à l'affichage. */
.q[hidden], .choix label[hidden], .choix .choix-item[hidden] { display: none; }

/* ── Les blocs d'options ────────────────────────────────────
   Le reproche de Vincent : « pas super propre et très répétitif ». Il a
   raison — dix groupes de cases à cocher identiques les uns sous les
   autres, ça se lit comme une déclaration de revenus.

   La réponse n'est pas de décorer, c'est de découper. L'ancien formulaire
   avait déjà des séparateurs; on s'en sert pour faire de vrais blocs, avec
   du blanc entre eux et une teinte de fond qui les détache du reste. L'oeil
   voit alors quatre choses au lieu de dix. */

.groupe {
    background: var(--champ);
    border: 1px solid var(--bord-doux);
    border-radius: var(--r);
    padding: 18px 16px;
    margin-bottom: 18px;
}
.groupe:last-of-type { margin-bottom: 0; }

/* D139 — le titre de la section. Vincent : « divise mieux les sections
   d'extra, soumission etc. » Il ouvre le bloc au lieu de le surmonter :
   collé au bord du bloc, il appartient visiblement à ce qui suit. */
.groupe-titre {
    margin: 0 0 14px;
    font-size: 15px;
    font-weight: 700;
    color: var(--ink);
    letter-spacing: -0.01em;
}
.groupe > .fld { margin-bottom: 20px; }
.groupe > .fld:last-child { margin-bottom: 0; }

/* Dans un bloc, les rangées sont sur fond blanc : elles ressortent. */
.groupe .choix label { border-color: var(--bord-doux); }

/* L'étiquette « facultatif ». Sans elle, un client consciencieux croit
   devoir répondre aux dix blocs et abandonne au sixième. */
.facultatif {
    display: inline-block; margin-left: 8px; vertical-align: 1px;
    font-family: var(--titre);
    font-size: 10px; font-weight: 700; letter-spacing: .06em;
    text-transform: uppercase; color: var(--ink-3);
    background: var(--paper); border: 1px solid var(--bord-doux);
    border-radius: 5px; padding: 2px 6px;
}

/* Une rangée retenue se teinte, elle ne se contente pas d'un anneau. Sur
   un téléphone tenu à bout de bras, un anneau de trois pixels ne se voit
   pas. */
.choix label:has(input:checked) { background: #F4F9FF; }
.choix label:has(input:checked) .titre { color: var(--vp-fonce); font-weight: 600; }

/* Une case fermée pour la saison. */
.choix label.ferme, .choix label.ferme:hover {
    background: var(--champ); border-color: var(--bord-doux);
    opacity: .6; cursor: not-allowed;
}

/* Un groupe d'une seule case dont le libellé répète la question — l'ancien
   formulaire en a — n'a pas besoin de son titre deux fois. */
.fld.muette > .legende { display: none; }

/* ── La barre d'action, au pouce ────────────────────────────
   85 % des réservations se font au téléphone. Le bouton « Suivant » ne doit
   jamais demander de faire défiler pour être atteint. */

@media (max-width: 640px) {
    .actions {
        position: sticky; bottom: 0; z-index: 5;
        margin: 26px -22px -30px;
        padding: 14px 22px calc(14px + env(safe-area-inset-bottom));
        background: rgba(255, 255, 255, .94);
        backdrop-filter: blur(8px);
        border-top: 1px solid var(--bord-doux);
    }
}

/* ── L'avancement, en toutes lettres ────────────────────────
   Cinq points ne disent pas où on est ni combien il en reste. Une phrase
   le dit. */

.avancement {
    font-family: var(--titre);
    font-size: 11px; font-weight: 700; letter-spacing: .1em;
    text-transform: uppercase; color: var(--ink-3);
    margin: 18px 0 0;
}

/* ═══════════════════════════════════════════════════════════
   DENSITÉ

   Vincent, 29 août 2026 : « les cases forfait, c'est bien, mais
   il y a beaucoup d'endroits où c'est trop pour rien ».

   Il a mis le doigt sur une vraie distinction. Une carte de
   forfait porte un titre, quatre lignes de description et un
   prix : elle a besoin d'air, et c'est ce qui la rend choisissable
   d'un coup d'œil. Une case « Retrait des marches — 34,99 $ »
   porte six mots : lui donner le même volume ne la met pas en
   valeur, ça allonge la page et ça noie les forfaits.

   La règle est donc : l'espace suit le contenu. Une option sans
   description se resserre; une option qui explique garde sa place.
   ═══════════════════════════════════════════════════════════ */

/* Une option sans description : une ligne, pas une carte. */
.choix label:not(:has(.detail)) {
    padding: 10px 14px;
    align-items: center;
}

/* Les options se suivent de plus près. Un forfait reste distinct
   parce qu'il est haut, pas parce qu'il y a un vide autour. */
.choix { gap: 7px; }

/* Une description d'option : deux lignes de trop se lisent moins
   bien que deux lignes serrées. */
.choix .detail { line-height: 1.45; margin-top: 3px; }

/* Le rythme vertical général. Vingt-deux pixels entre chaque
   champ, sur une page qui en compte quinze, c'est trois cents
   pixels de vide — un écran de téléphone complet. */
.fld { margin-bottom: 17px; }
.groupe > .fld { margin-bottom: 16px; }

/* Les blocs se touchent d'un peu plus près. */
.groupe { padding: 16px 15px; margin-bottom: 15px; }

/* L'en-tête de la carte. Le titre reste grand — c'est la
   signature de la marque — mais il ne flotte plus. */
.card-head { padding: 22px 20px 0; }
.card-body { padding: 20px 20px 26px; }

/* Les champs de texte : 14 px de haut suffisent à viser au pouce.
   La cible reste au-dessus des 44 px recommandés. */
.fld input[type="text"], .fld input[type="email"], .fld input[type="tel"],
.fld input[type="number"], .fld input[type="date"], .fld select {
    padding-top: 12px; padding-bottom: 12px;
}
.fld textarea { min-height: 88px; }

.hint { margin-top: 5px; }

@media (max-width: 480px) {
    .card-body { padding: 18px 15px 22px; }
    .groupe { padding: 14px 12px; }
    .choix label:not(:has(.detail)) { padding: 10px 12px; }
}

/* ═══════════════════════════════════════════════════════════
   RETOURS DU 29 AOÛT — le formulaire relu de bout en bout
   ═══════════════════════════════════════════════════════════ */

/* ── R35 — le glissement horizontal parasite ────────────────
   Sur téléphone, la page bougeait de gauche à droite en défilant.
   Quelque chose dépasse la largeur de l'écran; plutôt que de
   chercher le coupable une fois, on ferme la porte pour de bon.
   Un formulaire n'a aucune raison de défiler latéralement. */

html, body { max-width: 100%; overflow-x: clip; }

/* Ce qui doit vraiment déborder — un tableau, un calendrier —
   défile dans sa propre boîte, jamais en emportant la page. */
.card, .groupe, .fld, .choix, .cal { min-width: 0; }
.fld input, .fld select, .fld textarea { max-width: 100%; }

/* ── R39 — prénom et nom côte à côte, même sur téléphone ────
   Deux champs de trois lettres l'un sous l'autre, ça fait deux
   lignes pour rien. Ils tiennent à 320 px. */

@media (max-width: 420px) {
    .deux { grid-template-columns: 1fr 1fr; gap: 0 10px; }
}

/* ── R40 — resserrer encore ─────────────────────────────────
   « Moins gros comme espacement mais tout aussi clair. » Ce qui
   donne la clarté, c'est le contraste entre le titre et le
   contenu, pas le vide autour. */

.fld { margin-bottom: 14px; }
.groupe { padding: 14px 14px; margin-bottom: 12px; }
.groupe > .fld { margin-bottom: 13px; }
.card-head { padding: 20px 20px 0; }
.card-body { padding: 18px 20px 24px; }
.fld label, .fld > .legende { margin-bottom: 6px; }
.choix { gap: 6px; }

/* ── R43 — les extras en petites cases dans un seul encadré ──
   Un encadré par option prenait toute la page pour dire « Retrait
   des marches — 34,99 $ ». Les options d'un même lot vivent
   maintenant dans le cadre du lot, séparées par un filet plutôt
   que par un cadre chacune.

   Les FORFAITS gardent leur carte : on en choisit un, il porte un
   texte, il mérite d'être pesé. Un extra se coche.  */

.fld.compact .choix { gap: 0; }
.fld.compact .choix label {
    border: 0; border-radius: 0;
    border-top: 1px solid var(--bord-doux);
    padding: 9px 2px;
    background: transparent;
}
.fld.compact .choix label:first-of-type { border-top: 0; }
.fld.compact .choix label:has(input:checked) {
    background: transparent;
    box-shadow: none;
}
.fld.compact .choix label:has(input:checked) .titre { font-weight: 700; color: var(--vp-fonce); }
.fld.compact .choix .detail { font-size: 12.5px; }

/* ── R45 — la soumission d'autres travaux sur deux colonnes ──
   Sept propositions l'une sous l'autre, c'est un écran complet
   pour une question facultative. */

@media (min-width: 560px) {
    .fld.deux-colonnes .choix { grid-template-columns: 1fr 1fr; gap: 0 18px; }
    .fld.deux-colonnes .choix label:nth-of-type(2) { border-top: 0; }
}

/* ── R44 — « si vous n'êtes pas joignable » doit sauter aux yeux
   La condition EST la question. Sans elle, le client croit qu'on
   va remplacer des pièces sans demander. */

.fld .condition {
    display: block;
    margin: 0 0 8px;
    padding: 8px 12px;
    border-radius: 8px;
    background: var(--attention-fond, #FDF4E3);
    border: 1px solid #F0D9A4;
    color: #7A4E00;
    font-size: 13.5px; font-weight: 600;
}

/* ── R49 — la fenêtre des conditions ────────────────────────
   Elle s'ouvre par-dessus, se ferme avec Échap, et n'allonge pas
   la page pour les neuf clients sur dix qui ne la liront pas. */

.fenetre {
    border: 0; padding: 0; max-width: 560px; width: calc(100% - 32px);
    border-radius: var(--r-carte, 22px);
    box-shadow: 0 30px 60px -20px rgba(11, 18, 32, .45);
}
.fenetre::backdrop { background: rgba(11, 18, 32, .55); }
.fenetre-in { padding: 26px 24px; max-height: 78vh; overflow-y: auto; }
.fenetre-in h2 { font-family: var(--titre); font-size: 20px; font-weight: 800; margin: 0 0 4px; }
.fenetre-in h3 {
    font-family: var(--titre); font-size: 12px; font-weight: 700;
    letter-spacing: .08em; text-transform: uppercase; color: var(--ink-3);
    margin: 20px 0 6px;
}
.fenetre-in p { margin: 0; font-size: 14.5px; line-height: 1.6; color: var(--ink-2); }
.fenetre-in form { margin-top: 24px; text-align: right; }

/* Un bouton qui a l'air d'un lien, parce que c'en est un pour
   l'œil — mais un bouton pour le clavier et le lecteur d'écran,
   puisqu'il n'amène nulle part. */
.lien {
    background: none; border: 0; padding: 0;
    font: inherit; color: var(--vp); text-decoration: underline;
    cursor: pointer;
}
.lien:hover { color: var(--vp-fonce); }

.accord { display: grid; gap: 12px; }

/* R89 -- le bandeau du comptoir : l'équipe réserve par le formulaire
   client, et sait qu'elle porte la casquette du client. */
.comptoir-bandeau {
    background: var(--ink, #111827); color: #fff;
    padding: 9px 16px; font-size: 13.5px; text-align: center;
}
.comptoir-bandeau a { color: #8FC0FF; margin-left: 8px; }

/* ── Le X d'une fenêtre ─────────────────────────────────────
   Vincent : « pour fermer les choses, il n'y a pas de X. » Ça valait
   aussi pour les conditions du formulaire de réservation, que le client
   ouvre puis doit refermer. */
.fenetre-x {
    position: sticky; top: 0; float: right; z-index: 2;
    display: grid; place-items: center;
    width: 38px; height: 38px; margin: -6px -8px 0 10px;
    border: 1px solid var(--bord); border-radius: 50%;
    background: var(--paper); color: var(--ink-3);
    cursor: pointer;
    /* Le contenu défile DERRIÈRE lui : sans cette ombre, le X se
       perd dans un paragraphe dense au moment où on le cherche. */
    box-shadow: 0 0 0 4px var(--paper), 0 2px 6px rgba(11, 18, 32, .10);
}
.fenetre-x:hover { color: var(--vp); border-color: var(--vp); }

/* ── LE RENDEZ-VOUS D'URGENCE ─────────────────────────────────────

   L'offre est discrète tant que le client n'en a pas besoin : elle vit
   SOUS le calendrier, jamais à côté du bouton « Suivant ». Un client qui
   trouve sa date ne doit pas croiser une porte à deux cents dollars.

   Elle devient franche une fois activée : le mode urgence change ce que
   le client voit, il doit donc savoir qu'il y est. */

.urg-offre {
    margin: 22px 0 0;
    padding: 15px 17px;
    border: 1px dashed var(--bord);
    border-radius: var(--r);
    background: var(--champ);
}
.urg-offre p { margin: 0 0 10px; font-size: 14.5px; color: var(--ink-2); }
.urg-offre form { margin: 0; }

/* En mode urgence, ce n'est plus une offre : c'est un état. La classe est
   posée par le gabarit et non déduite d'un sélecteur : « :has » sur une
   adresse de formulaire, c'est une règle qui casse au premier renommage de
   route, sans rien dire. */
.urg-offre.urg-active {
    border-style: solid;
    border-color: var(--attention);
    background: var(--attention-fond);
}

.btn-lien {
    display: inline-block;
    background: none;
    border: 0;
    padding: 0;
    font: inherit;
    font-weight: 600;
    color: var(--vp);
    text-decoration: underline;
    text-underline-offset: 3px;
    cursor: pointer;
}
.btn-lien:hover { color: var(--vp-fonce); }

.urg-points { margin: 10px 0 0; padding-left: 20px; }
.urg-points li { margin-bottom: 10px; line-height: 1.55; }

/* ── LA CASE À COCHER ────────────────────────────────────────

   « .check » n'existait que dans equipe.css, et la page de réservation
   ne charge pas cette feuille-là. Or c'est elle qui portait le
   « display: flex ». Sans lui, .urg-check plus bas règle un
   « align-items: flex-start » qui ne s'applique à rien, et la case du
   consentement — celle qui engage le client pour deux cents dollars —
   se retrouvait au-dessus de son texte au lieu d'être à côté.

   Aucune erreur, aucune console : juste la case la plus importante du
   parcours, mal posée, sur la page publique. */
.check {
    display: flex; gap: 10px; align-items: center;
    font-size: .93rem; color: var(--ink-2);
    cursor: pointer;
}
.check input { width: 18px; height: 18px; accent-color: var(--vp); }

/* Le paragraphe d'ouverture d'une page publique : plus grand que le
   corps, moins qu'un titre. Il n'avait aucune règle non plus. */
.intro { margin: 0 0 18px; font-size: 1.02rem; line-height: 1.6; }

/* La case du consentement respire : c'est le geste qui engage. */
.urg-check {
    margin-top: 18px;
    padding: 13px 15px;
    background: var(--champ);
    border: 1px solid var(--bord);
    border-radius: var(--r);
    align-items: flex-start;
}
.urg-check input { margin-top: 3px; flex: none; }

/* Une demande d'urgence n'est pas une réservation : la page de fin doit
   se lire autrement du premier coup d'œil, avant même le texte. Le vert
   veut dire « c'est fait », et ce ne l'est pas encore. */
.fini-attente .coche { background: var(--attention); }
.flash-attente { background: var(--attention-fond); border-color: var(--attention); }

/* ── La reconnaissance par courriel ─────────────────────
   Vincent, doc 5 : « rentrer le code sur une case qui apparaît juste en
   dessous ». Elle apparaît sous le champ du courriel, encadrée, pour
   qu'on voie tout de suite que ces deux cases-là vont ensemble. */
.reconnu {
    margin-top: 10px;
    padding: 12px 14px;
    background: #F5F9FF;
    border: 1px solid #DCE8FB;
    border-radius: 12px;
}
.reconnu label { display: block; font-size: 13px; font-weight: 600; margin-bottom: 6px; }
.reconnu input {
    width: 100%;
    max-width: 190px;
    letter-spacing: .22em;
    font-size: 17px;
    font-variant-numeric: tabular-nums;
    margin-bottom: 8px;
}
.reconnu .hint { margin-top: 8px; }

@media (max-width: 560px) {
    .reconnu input { max-width: 100%; }
}

/* ─────────────────────────────────────────────────────────────
   D151 — LE SÉLECTEUR DE LANGUE.

   Discret à dessein : il vit sous le pied de page, à la taille des
   liens d'aide. Un sélecteur de langue en évidence dans un formulaire
   de réservation attire un clic qui fait perdre le fil — la grande
   majorité des clients de Laval lisent le français, et ceux qui
   cherchent l'anglais le trouvent là où on met toujours ce genre de
   lien.

   La langue en cours n'est pas un lien : cliquer sur « Français »
   quand on lit déjà le français est un aller-retour pour rien.
   ───────────────────────────────────────────────────────────── */

.choix-langue {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 14px;
    padding: 4px 20px 18px;
    font-size: 13px;
}

.choix-langue a {
    color: var(--ink-3);
    text-decoration: none;
    border-bottom: 1px solid transparent;
    padding-bottom: 1px;
}

.choix-langue a:hover,
.choix-langue a:focus-visible {
    color: var(--vp);
    border-bottom-color: currentColor;
}

.choix-langue .langue-active {
    color: var(--ink-2);
    font-weight: 600;
}

/* ─────────────────────────────────────────────────────────────
   D154 — PASSER LA MAIN AU CLIENT.

   Elle a l'allure du bandeau du comptoir, et c'est voulu : les deux
   ne s'affichent que pour l'équipe, dans un écran qui appartient au
   client. Le même jaune dit « ceci n'est pas la page, c'est toi ».

   Elle est encadrée et non pleine largeur : le formulaire du client
   reste le sujet de la page. On propose une sortie, on ne détourne
   pas l'écran.
   ───────────────────────────────────────────────────────────── */

.passer-la-main {
    border: 1px solid #E6C84B;
    background: #FFFBEB;
    border-radius: 10px;
    padding: 14px 16px;
    margin: 0 0 20px;
}

.passer-la-main h2 {
    margin: 0 0 6px;
    font-size: 16px;
}

.passer-la-main p {
    margin: 0 0 12px;
    font-size: 13px;
    line-height: 1.5;
    color: #6B5B12;
}

.passer-la-main label {
    display: block;
    font-size: 13px;
    font-weight: 600;
    margin-bottom: 4px;
}

.passer-la-main input {
    width: 100%;
    padding: 10px 12px;
    border: 1px solid #D8C88A;
    border-radius: 8px;
    font: inherit;
    background: #fff;
}

.passer-boutons {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 10px;
}

.passer-boutons .btn { flex: 1 1 auto; }

.passer-note {
    margin: 10px 0 0;
    font-size: 12px;
    color: #8A7A2E;
}

/* ─────────────────────────────────────────────────────────────
   D154 — LA LISTE DES ADRESSES SUGGÉRÉES.

   Elle se pose SOUS le champ et pousse le reste du formulaire vers le
   bas plutôt que de flotter par-dessus. C'est délibéré : sur un
   téléphone, une liste flottante se retrouve à moitié sous le clavier,
   et on choisit une suggestion qu'on ne voit qu'à moitié.

   Chaque suggestion est un vrai bouton de 44 px : c'est le geste qu'on
   fait avec le pouce, dans une cour, parfois avec des gants.
   ───────────────────────────────────────────────────────────── */

.adr-liste {
    list-style: none;
    margin: 6px 0 0;
    padding: 0;
    border: 1px solid var(--bord, #D1D5DB);
    border-radius: 8px;
    overflow: hidden;
    background: #fff;
}

.adr-liste li + li { border-top: 1px solid var(--bord, #E5E7EB); }

.adr-choix {
    display: block;
    width: 100%;
    min-height: 44px;
    padding: 11px 14px;
    border: 0;
    background: none;
    font: inherit;
    text-align: left;
    color: var(--ink-1, #111827);
    cursor: pointer;
}

.adr-choix:hover,
.adr-choix:focus-visible {
    background: var(--fond-2, #F3F6FA);
    color: var(--vp, #0077F9);
    outline: none;
}

/* ─────────────────────────────────────────────────────────────
   D155 — L'ANNEAU DE FOCUS SUR L'ÉTIQUETTE, PUISQUE LA CASE EST
   CACHÉE.

   Tout le formulaire est bâti sur des boutons radio et des cases à
   cocher rendus invisibles — `opacity: 0; width: 0; height: 0` — pour
   qu'on dessine l'étiquette à leur place. C'est le bon motif, mais il a
   une contrepartie obligatoire : la règle de focus du haut de cette
   feuille s'applique alors à un élément de zéro pixel sur zéro.

   Qui navigue au clavier traversait donc le calendrier et les forfaits
   sans jamais voir où il se trouvait. Un formulaire de cinq étapes
   entièrement fait de cases, inutilisable au clavier de bout en bout.

   Le motif correct existait déjà à côté, dans portail.css — il n'avait
   simplement jamais traversé.

   `:has()` sert déjà quatre fois plus haut dans cette feuille : rien de
   nouveau à supporter.
   ───────────────────────────────────────────────────────────── */

.cal-jour.libre:has(input:focus-visible),
.choix label:has(input:focus-visible),
.consent:has(input:focus-visible),
.check:has(input:focus-visible),
.pan-coche:has(input:focus-visible) {
    outline: 3px solid rgba(0, 119, 249, .32);
    outline-offset: 2px;
}

/* ── L'erreur sous le champ qu'elle vise ─────────────────────

   Les refus s'empilaient en haut de la carte. Après un envoi refusé, le
   client lisait une liste, puis redescendait quinze questions pour
   deviner lequel des champs était en cause.

   La liste du haut reste — elle dit combien il y en a — mais chaque
   champ porte maintenant sa phrase, là où on la corrige. C'est ce que
   font GOV.UK et Stripe, et c'est la seule disposition qui marche au
   lecteur d'écran.
   ───────────────────────────────────────────────────────────── */

.err-champ {
    margin: 6px 0 0;
    color: #B42318;
    font-size: 13px;
    font-weight: 600;
}

.fld:has(.err-champ) input,
.fld:has(.err-champ) select,
.fld:has(.err-champ) textarea {
    border-color: #B42318;
}
