/* ═══════════════════════════════════════════════════════════════════════════
   EasyPDF — bandeau de préinscription + modale. Feuille SÉPARÉE et NOUVELLE.
   ---------------------------------------------------------------------------
   POURQUOI UN FICHIER DE PLUS plutôt qu'un ajout dans `easypdf-v3.css` :
   `/assets/*` est servi `immutable, max-age=31536000` et le site est déployé
   depuis le 2026-08-02. M25 (laurent, 2026-08-03) : un contenu qui change change
   de nom. Modifier la feuille commune obligerait à la renommer et à répercuter
   dans les NEUF pages qui la référencent. Même raison que `carousel-v4.css`,
   `langtop-v4.css` et `reflow-v1.css`, qui existent exactement pour ça.

   ⚠️ ORDRE. Chargée APRÈS `easypdf-v3.css` et AVANT `reflow-v1.css` — cette
   dernière DOIT rester la dernière du <head> (trois de ses règles battent les
   autres à spécificité égale, c'est écrit dans `index.html`). Aucune règle
   ci-dessous ne redéfinit un sélecteur de `reflow-v1.css`.

   RÉUTILISE plutôt que réinvente : `.btn`, `.form`, `.fld`, `.hint`, `.req`,
   `.check-inline`, `.eyebrow`, `.lede` viennent d'`easypdf-v3.css`. Ce fichier
   n'ajoute que ce qui n'existe pas : le bandeau, l'animation d'appel, la modale,
   le champ `type=tel`, le `textarea`, les messages d'erreur par champ.

   ── L'ANIMATION D'APPEL, ET LA RAISON DE SA FORME ─────────────────────────
   laurent a demandé « très visible : bouton animé ». Une animation infinie sur
   un bouton est un harcèlement visuel : elle occupe la périphérie du regard
   pendant toute la lecture et ne s'arrête jamais. Celle-ci fait TROIS cycles,
   après un délai d'une seconde, puis se tait définitivement (`forwards`, pas
   d'itération infinie). Elle attire à l'arrivée et rend ensuite la page au
   lecteur.
   Elle se tait AUSSI, immédiatement :
     · sous `prefers-reduced-motion: reduce` — la règle est un @media qui ne
       déclare l'animation QUE sous `no-preference`, donc il n'y a rien à
       désactiver : elle n'existe pas. C'est plus sûr que de la neutraliser
       après coup, parce qu'on ne peut pas oublier une règle qu'on n'a pas
       écrite ;
     · au survol et au focus clavier — interagir suffit à la faire cesser.
   Elle n'anime NI la couleur du texte NI la géométrie du bouton : uniquement un
   halo posé en `::after`, `pointer-events:none`. La cible de pointeur ne bouge
   donc jamais (SC 2.5.8), et rien ne clignote entre 3 et 50 Hz (SC 2.3.1).
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── 1. Le bandeau ──────────────────────────────────────────────────────── */
.preinsc__card{
  background:var(--white); border:2px solid var(--ink); border-radius:var(--r);
  padding:clamp(1.4rem,4vw,2.4rem); box-shadow:0 6px 0 var(--sky-3);
  max-width:70ch;
}
.preinsc__card h2{margin-bottom:.7rem}
.preinsc__card .lede{max-width:60ch}
.preinsc__cta{margin-top:1.6rem}
.preinsc__card .cta-note{margin-top:1rem; max-width:56ch}

/* Le halo. `::after` est hors flux et ne reçoit aucun pointeur : il ne peut ni
   déplacer le bouton, ni intercepter un clic, ni changer sa taille de cible. */
.preinsc__btn{position:relative; isolation:isolate}
.preinsc__btn::after{
  content:""; position:absolute; inset:-6px; border-radius:var(--pill);
  border:2px solid var(--blue); opacity:0; pointer-events:none; z-index:-1;
}
@media(prefers-reduced-motion:no-preference){
  .preinsc__btn::after{animation:preinsc-halo 2.2s ease-out 1s 3 both}
  .preinsc__btn:hover::after,
  .preinsc__btn:focus-visible::after{animation:none; opacity:0}
  /* Amplitude délibérément faible : 6 px → 14 px, opacité 0 → .55 → 0. Le halo
     se voit du coin de l'œil, il n'appelle pas au secours. */
  @keyframes preinsc-halo{
    0%   {opacity:0;   inset:-6px}
    35%  {opacity:.55; inset:-10px}
    100% {opacity:0;   inset:-14px}
  }
}

/* ── 2. La modale ───────────────────────────────────────────────────────── */
/* `[hidden]` sur un conteneur en `display:flex` ne cache RIEN sans cette ligne :
   une règle d'auteur bat la feuille du navigateur. C'est le piège déjà payé sur
   `.btn[hidden]` et `.wz__fbtn[hidden]` dans `easypdf-v3.css`. */
.preinsc-modal[hidden]{display:none}
.preinsc-modal{
  position:fixed; inset:0; z-index:120;
  display:flex; align-items:center; justify-content:center;
  padding:clamp(.5rem,3vw,2rem);
}
.preinsc-modal__backdrop{
  position:absolute; inset:0; background:rgba(20,38,61,.62);
  -webkit-backdrop-filter:blur(2px); backdrop-filter:blur(2px);
}
.preinsc-modal__panel{
  position:relative; width:min(46rem,100%);
  /* `dvh` d'abord, `vh` en repli : sur mobile la barre d'URL rétractable fait
     dépasser une modale calée sur `vh`, et le bouton d'envoi passe sous le pli
     sans qu'aucun défilement ne le rattrape. */
  max-height:calc(100vh - 1rem);
  max-height:calc(100dvh - 1rem);
  overflow-y:auto; overscroll-behavior:contain;
  background:var(--sky); color:var(--ink);
  border:2px solid var(--ink); border-radius:var(--r);
  box-shadow:0 24px 60px -20px rgba(20,38,61,.6);
  padding:clamp(1.25rem,4vw,2.2rem);
}
/* SC 2.4.7 — L ANNEAU N EST PAS SUPPRIME, IL EST REMPLACE.
   Cette regle disait `outline:none` tout court. Le panneau recoit le focus par
   script a l ouverture de la modale, et l anneau natif y paraissait deplace —
   mais le retirer laissait un utilisateur au clavier sans aucun repere lorsqu il
   revenait sur le panneau par tabulation.
   Le defaut est reste INVISIBLE jusqu au 2026-08-09 parce que le gate a11y
   chargeait la page en file://, ou Chrome refuse de lire les regles d une
   feuille liee : il rendait un verdict sur des feuilles jamais lues. */
.preinsc-modal__panel:focus{outline:none;box-shadow:0 0 0 3px rgba(37,99,235,.35)}
/* Le panneau reçoit le focus à l'ouverture (`tabindex="-1"`). Un anneau sur un
   conteneur programmatique n'aide personne et lit comme un défaut visuel ;
   `:focus-visible` reste actif partout ailleurs. */
@media(prefers-reduced-motion:no-preference){
  .preinsc-modal__panel{animation:preinsc-in var(--t-slow) ease-out both}
  @keyframes preinsc-in{from{opacity:0; transform:translateY(10px)} to{opacity:1; transform:none}}
}
.preinsc-modal__head{display:flex; gap:1rem; align-items:flex-start; justify-content:space-between}
.preinsc-modal__head h2{font-size:clamp(1.4rem,1rem + 1.4vw,1.9rem)}
.preinsc-modal__close{
  flex:none; display:grid; place-items:center; width:48px; height:48px;
  background:var(--white); color:var(--ink); border:2px solid var(--line);
  border-radius:50%; cursor:pointer; font:inherit;
  transition:border-color var(--t-fast), background-color var(--t-fast);
}
.preinsc-modal__close:hover{border-color:var(--ink); background:var(--sky-2)}
.preinsc-modal__close svg{width:22px; height:22px; display:block}
.preinsc-modal__intro{margin-top:.7rem; max-width:62ch}

/* ── 3. Le formulaire ───────────────────────────────────────────────────── */
/* `.form` d'`easypdf-v3.css` porte déjà la carte blanche, la bordure et les
   champs `text`/`email`. On ajoute ce qu'il ne connaît pas. */
.preinsc-form{margin-top:1.5rem; max-width:none}
.preinsc-form input[type=tel],
.preinsc-form textarea{
  width:100%; font:inherit; font-size:1rem; padding:.78rem .9rem; color:var(--ink);
  background:var(--white); border:2px solid var(--line); border-radius:var(--r-sm); min-height:48px;
}
.preinsc-form textarea{min-height:7.5rem; resize:vertical; line-height:1.55}
.preinsc-form input[type=tel]:hover,
.preinsc-form textarea:hover{border-color:var(--ink-3)}
.preinsc-form input[type=tel]:focus-visible,
.preinsc-form textarea:focus-visible{border-color:var(--blue); outline-offset:1px}
/* Un champ en erreur ne se signale JAMAIS par la seule couleur (SC 1.4.1) : le
   message texte sous le champ est la signalisation, la bordure ne fait que la
   renforcer. */
.preinsc-form [aria-invalid=true]{border-color:var(--red)}
.preinsc-form__requis{font-size:.875rem; color:var(--ink-3); margin-bottom:1.4rem}
.preinsc-err{margin-top:.4rem; font-size:.875rem; color:var(--red-ink); font-weight:640; line-height:1.45}
.preinsc-err:empty{display:none}

/* Deux colonnes seulement quand la place existe réellement. Sous 620 px et sous
   pseudo-locale +40 %, tout retombe en une colonne : rien n'est tronqué. */
.preinsc-form__duo{display:grid; gap:0}
@media(min-width:620px){
  .preinsc-form__duo{grid-template-columns:1fr 1fr; gap:0 1.1rem}
}

/* Le résumé d'erreurs, en tête de formulaire. Il porte `role="alert"` UNIQUEMENT
   au moment où il se remplit — voir `preinscription-v1.js` : une région
   assertive posée en permanence interromprait un lecteur d'écran à chaque
   frappe. */
.preinsc-form__resume{
  margin-bottom:1.4rem; padding:.9rem 1.1rem;
  border:2px solid var(--red); background:var(--red-soft); border-radius:var(--r-sm);
  color:var(--ink); font-size:.9375rem; line-height:1.5; font-weight:640;
}
.preinsc-form__resume[hidden]{display:none}

.preinsc-captcha{min-height:1px}
.preinsc-captcha__slot{margin-top:.5rem}
/* Le widget se rend dans une iframe de 300×65 px environ. La réserve empêche le
   contenu qui suit de sauter au moment où il arrive. */
.preinsc-captcha__slot:not(:empty){min-height:65px}
.preinsc-captcha__absent{
  margin-top:.5rem; padding:.8rem 1rem; border:2px dashed var(--ink-3);
  border-radius:var(--r-sm); color:var(--ink-2); font-size:.9375rem; line-height:1.5;
}

.preinsc-form__submit{margin-top:1.8rem; display:flex; flex-wrap:wrap; gap:1rem; align-items:center}
.preinsc-status{margin-top:.9rem; font-size:.9375rem; color:var(--ink-2); line-height:1.5; min-height:1.4em}
.preinsc-status:empty{min-height:0}
.preinsc-note{margin-top:1.6rem; font-size:.8125rem; color:var(--ink-3); line-height:1.55; max-width:70ch}

/* Le témoin d'envoi. Réutilise `@keyframes spin` d'`easypdf-v3.css`, qui n'est
   déclaré que sous `no-preference` : sous `reduce`, le disque est simplement
   immobile, il ne disparaît pas — l'état « envoi en cours » reste visible. */
.preinsc-spinner{
  width:20px; height:20px; flex:none; border-radius:50%;
  border:3px solid var(--sky-3); border-top-color:var(--blue);
}
@media(prefers-reduced-motion:no-preference){.preinsc-spinner{animation:spin .9s linear infinite}}

/* ── 4. L'écran de succès ───────────────────────────────────────────────── */
.preinsc-ok[hidden]{display:none}
.preinsc-ok{
  margin-top:1.5rem; padding:clamp(1.2rem,3vw,1.8rem);
  background:var(--white); border:2px solid var(--ink); border-radius:var(--r);
  box-shadow:0 6px 0 var(--sky-3);
}
.preinsc-ok h3{margin-bottom:.6rem; font-size:1.25rem}
.preinsc-ok p{color:var(--ink-2); max-width:56ch}
.preinsc-ok__cta{margin-top:1.4rem}

/* ── 5. 320 px ──────────────────────────────────────────────────────────── */
/* Aucun `overflow-x:hidden` : `reflow-v1.css` le refuse nommément, et masquer un
   débordement le rend invisible au harnais sans le corriger. */
@media(max-width:400px){
  .preinsc-modal{padding:.4rem}
  .preinsc-modal__panel{padding:1rem}
  .preinsc-form__submit .btn{width:100%}
}


/* ─── CTA de preinscription dans la barre — 2026-08-07 ──────────────────────
   Demande de laurent : « bouton anime CTA fort », au centre de la barre.

   L'animation est une PULSATION D'OMBRE, pas un deplacement : un element qui
   bouge dans une barre fixe deplace la cible d'un clic en cours, et fait rater
   le bouton a qui vise. L'ombre attire l'oeil sans changer la geometrie.

   ⚠ `prefers-reduced-motion` COUPE l'animation, il ne l'attenue pas. Une
   animation qu'on ne peut pas arreter est un defaut d'accessibilite, pas un
   atout — et le contrat exige WCAG 2.2 AA. Le bouton reste parfaitement
   visible sans elle : c'est la couleur qui porte l'appel, l'animation ne fait
   que l'appuyer. */
.hdr__cta--preinsc {
  margin-inline: auto;          /* le centre de la barre, entre le logo et le menu */
  white-space: nowrap;
}

@keyframes cta-pulse-ombre {
  0%, 100% { box-shadow: 0 0 0 0 rgba(37, 99, 235, 0.55); }
  50%      { box-shadow: 0 0 0 0.55rem rgba(37, 99, 235, 0); }
}

.cta-pulse {
  animation: cta-pulse-ombre 2.4s ease-out infinite;
}

/* La pulsation s'arrete des qu'on interagit : elle appelle, elle ne harcele
   pas celui qui a deja repondu. */
.cta-pulse:hover,
.cta-pulse:focus-visible {
  animation: none;
}

@media (prefers-reduced-motion: reduce) {
  .cta-pulse { animation: none; }
}

/* ─── La ligne qui dit pourquoi le bouton est éteint — 2026-08-07 ────────────
   Ton NEUTRE, pas rouge : `.preinsc-err` signale une faute commise, celle-ci
   annonce une étape restante. Les peindre pareil apprendrait à lire une
   consigne comme un reproche — et, à la longue, à ne plus lire les vraies
   erreurs. */
.preinsc-hint {
  margin: 0.55rem 0 0;
  font-size: 0.875rem;
  line-height: 1.45;
  color: #55606e;
  text-align: center;
}
.preinsc-hint[hidden] { display: none; }

@media (prefers-color-scheme: dark) {
  .preinsc-hint { color: #9aa6b4; }
}

/* Un bouton désactivé doit SE VOIR désactivé : sans cela, le visiteur clique,
   rien ne se passe, et il conclut que le site est cassé plutôt que d'aller
   chercher ce qui manque. */
.preinsc-form__submit .btn:disabled {
  opacity: 0.55;
  cursor: not-allowed;
  animation: none;    /* une pulsation sur un bouton mort appelle vers le vide */
}
