/* ============================================================
   FUITO — formulaire.css
   LA FEUILLE DU FORMULAIRE DE DEMANDE, ET ELLE SEULE.

   ── POURQUOI CE FICHIER EXISTE (D-637) ──────────────────────
   Le formulaire de demande doit pouvoir s'afficher sur une page
   qui n'est PAS le site : la page WordPress de fuito.fr
   aujourd'hui, un abonné en marque blanche demain. Deux balises
   suffisent, et elles ne recopient rien :

       <link rel="stylesheet" href="https://app.fuito.fr/formulaire.css">
       <script src="https://app.fuito.fr/formulaire.js" defer></script>

   Une source, deux consommateurs : le site public (`styles.css`
   importe cette feuille en tête) et le site tiers (les deux
   balises ci-dessus, servies depuis `client/dist` par le greffon
   `client/build/formulaire-embarquable.js`).

   Recopier le formulaire dans la page hôte était l'autre voie ;
   elle est fermée et c'est MESURÉ : WordPress réécrit les `&&`
   du contenu en `&amp;&amp;`, et `formulaire.js` en contient dix.

   ── LES TROIS RÈGLES DE TENUE, ET CE QU'ELLES COÛTENT SINON ──

   1. AUCUN SÉLECTEUR NU. Cette feuille part chez des inconnus :
      un `label { … }` repeindrait toutes les étiquettes de la
      page hôte, un `input, textarea, select { … }` tous ses
      champs. Les trois qui existaient (`label`, `input, textarea,
      select`, `textarea`) sont donc rattachés à `.form-card`.
      Tout sélecteur de cette feuille commence par une classe du
      formulaire — gardé par
      `server/test/formulaire-embarquable.test.js` §2.

   2. ELLE TIENT SEULE. Les règles ci-dessous lisent `var(--brand)`,
      `--muted`, `--ice`… qui vivaient dans le `:root` de
      `styles.css`. Sur une page tierce, ce `:root` n'existe pas
      et tout serait sans couleur. Le bloc « JETONS » ci-dessous
      les porte donc — posés SUR `.form-card`, jamais sur `:root` :
      une feuille invitée n'impose rien à la page qui l'accueille.
      Les valeurs sont celles du `:root` de `styles.css`, à la
      virgule près, et la police celle de son `body` (D-866).
      Et rien de la page hôte n'entre dans la carte : c'est « LA
      CLOISON », juste après les jetons (D-866).

   3. LE SITE PUBLIC NE BOUGE PAS. Le rattachement à `.form-card`
      monte la spécificité de 0,1,0 à 0,2,0 : les règles gardent
      donc la main sur celles de `styles.css` quel que soit
      l'ordre de chargement, et c'est ce qui autorise l'`@import`
      EN TÊTE de `styles.css` plutôt qu'une seconde balise `<link>`
      dans cinquante pages. L'ordre RELATIF des règles ci-dessous
      est celui qu'elles avaient dans `styles.css` : c'est lui qui
      départage les spécificités égales (`.form-card .btn` puis
      `.form-card .form-submit`, comme `.btn` puis `.form-submit`).

   ── CE QUI N'EST PAS ICI, ET POURQUOI ───────────────────────
   `.contact-direct` est resté dans `styles.css` : c'est le
   paragraphe « Vous préférez parler tout de suite ? », VOISIN du
   formulaire dans la page, jamais dans `.form-card`. Le rattacher
   au conteneur l'aurait éteint sur le site.
   ============================================================ */

/* ---------- JETONS — la charte de la maison, ce qui remplace le `:root` de styles.css ----------
   Ajouté par D-637, absent du bloc d'origine. Sur le site, ces valeurs sont
   exactement celles que `:root` donnait déjà : le rendu ne peut pas changer.
   `--police` (D-866) est la pile de polices que `body` pose sur le site : la
   charte du formulaire est ICI, couleurs et police ensemble, et nulle part
   ailleurs dans cette feuille. Que ces valeurs restent celles de `styles.css`,
   `server/test/formulaire-embarquable.test.js` §4 bis le garde, jeton par
   jeton. */
.form-card {
    --brand: #2E5FAC;
    --brand-dark: #1E4380;
    --aqua: #56A8F0;
    --deep: #12294F;
    --ice: #EDF4FC;
    --ink: #1C3352;
    --muted: #5A7395;
    --erreur: #b91c1c;
    --radius: 20px;
    --shadow: 0 8px 24px rgba(46, 95, 172, 0.10);
    --shadow-hover: 0 16px 40px rgba(46, 95, 172, 0.18);
    --police: 'Nunito', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}

/* ---------- LA CLOISON : RIEN DE LA PAGE HÔTE N'ENTRE DANS LA CARTE — D-866 ----------
   Le patron, point 1006-2 (A) : posé chez un partenaire, le formulaire garde
   TOUJOURS l'apparence de la maison, quel que soit le site hôte.

   ── LA CAUSE (MESURÉE) ──
   Une page hôte atteint la carte par DEUX chemins, et la feuille n'en fermait
   aucun en entier : elle reprenait ce qui avait été VU chez un hôte d'essai
   (les marges, `box-sizing`, la couleur des étiquettes et du lien), propriété
   par propriété — une liste de ce qu'on a déjà vu passer ne ferme que ce
   qu'on a déjà vu passer. Un thème qui vise `body`, `label`, `input`,
   `button` (le banc `client/test/formulaire-se-pose-d-une-balise.test.mjs`
   §3) repeignait encore 25 propriétés sur neuf éléments de la carte.

    1. L'HÉRITAGE. Police, taille, interlignage, espacement des lettres,
       majuscules… s'héritent : la carte prenait ceux du `body` de l'hôte.
       Sur le site, c'était `styles.css` qui les donnait — la carte ne les
       tenait pas d'elle-même.
    2. LES RÈGLES DE L'HÔTE qui visent les éléments nus (`label`, `input`,
       `div`…) : elles tombent sur les éléments de la carte, et toute
       propriété que la feuille ne pose pas leur reste acquise (la largeur
       des champs, les majuscules des étiquettes et du bouton).

   ── LE REMÈDE : UNE CLOISON, À UN ENDROIT ──
    · Sur la carte, `all: initial` coupe l'héritage À LA RACINE, et la carte
      pose elle-même ce que le `body` du site lui donnait : la police de la
      charte (`--police`), la couleur d'encre, l'interlignage. `display:
      block` rend à la `div` ce que `initial` lui retire.
    · Sur tout ce qu'elle contient, pseudo-éléments compris (`::before`,
      `::after`, `::placeholder`), `all: revert` rend chaque propriété à la
      valeur du NAVIGATEUR. La cloison s'écrit `.form-card :not(html)` : elle
      vise tout élément (aucun n'est `html` dans la carte) et pèse 0,1,1 — le
      plus lourd possible sans passer devant cette feuille, dont chaque règle
      commence par `.form-card` suivi d'un élément ou d'une classe (0,1,1 au
      moins) et vient APRÈS elle. Elle bat donc un thème qui vise un élément
      nu (`label`, 0,0,1) comme celui qui vise une classe que la carte porte
      aussi (`.btn` d'un thème Bootstrap, 0,1,0) ; un simple `.form-card *`
      (0,1,0) perdait ce second cas à l'ordre de chargement.
    · Puis on rétablit, DANS LA CARTE, ce que `styles.css` donnait au
      formulaire sur le site et que la cloison vient de reprendre : `* {
      margin: 0; padding: 0; box-sizing: border-box; }`, `a { color: inherit
      }`, `img { max-width: 100% }`, et l'anneau `:focus-visible` au clavier
      — mêmes valeurs, même effet. Sur le site, le rendu ne change donc pas,
      et c'est mesuré (carnet, D-866).

   Le Shadow DOM était l'autre voie ; il est écarté parce qu'il ôte la carte
   du `document` : `#contactForm` n'y serait plus trouvé par
   `document.getElementById`, ni par le banc, ni par une page qui porte
   encore l'ancien squelette (§4) — et il laisse passer l'héritage de la
   même façon.

   ── CE QUE LA CLOISON NE FERME PAS, ET C'EST NOMMÉ ──
    · Une règle de l'hôte PLUS FORTE qu'un élément nu (`.entry-content
      label`, `input[type=text]`, un `!important`) sur une propriété que la
      feuille ne pose pas elle-même. La cloison bat les thèmes qui visent
      les éléments ; elle ne prétend pas battre tout sélecteur.
    · Les tailles en `rem` se lisent sur la racine de la page hôte : un thème
      qui pose `html { font-size: 62.5% }` réduit le texte de la carte.
    · La police elle-même : la feuille la NOMME, elle ne la télécharge pas.
      Chez un hôte qui ne charge pas Nunito, la carte prend la suivante de la
      pile de la charte, jamais celle de l'hôte.

   ── LA LANGUE N'EST PAS UNE APPARENCE ──
   `all: initial` efface aussi la langue que l'attribut `lang` de la page
   donne au rendu (`-webkit-locale`, Chromium et WebKit) : mesuré sur la page
   du site, c'était le SEUL écart de la carte — 1 140 valeurs, `"fr"` devenu
   `auto`, sur 1,9 million de propriétés calculées à 390 et 1 440 px. La
   langue règle les césures, les guillemets, le choix des glyphes : elle
   appartient au texte, pas au thème. La carte la reprend donc de sa page,
   comme avant la cloison — et le banc navigateur §5 la compare à celle du
   `body` du site. */
.form-card {
    all: initial;
    -webkit-locale: inherit;
    display: block;
    box-sizing: border-box;
    font-family: var(--police);
    color: var(--ink);
    line-height: 1.65;
}
.form-card :not(html) { all: revert; margin: 0; padding: 0; box-sizing: border-box; }
.form-card :not(html)::before,
.form-card :not(html)::after,
.form-card :not(html)::placeholder { all: revert; }
.form-card a { color: inherit; }
.form-card img { max-width: 100%; }
.form-card :focus-visible { outline: 3px solid var(--aqua); outline-offset: 2px; }

/* ---------- LE BOUTON PILULE, RATTACHÉ AU FORMULAIRE ----------
   `.btn` est le bouton de TOUT le site (le héros, la bande d'appel, les
   pages de ville) : il ne peut pas quitter `styles.css`, et il ne peut pas
   non plus partir NU chez un hôte, où il repeindrait ses propres boutons.
   C'est la seule règle de ce lot qui existe à deux endroits, et elle ne peut
   pas ne pas l'être. Pour qu'elle ne DÉRIVE pas — un défaut, pas une
   précaution (CLAUDE.md, P-127) —, `server/test/formulaire-embarquable.test.js`
   §4 compare les deux déclaration par déclaration et rougit à la première
   différence.
   Les valeurs viennent de `site/public/styles.css`, § « Boutons pilule ». */
.form-card .btn {
    display: inline-block;
    background: var(--brand);
    color: #fff;
    border: 2px solid var(--brand);
    padding: 12px 28px;
    border-radius: 999px;
    font-weight: 800;
    font-size: 0.95rem;
    font-family: inherit;
    cursor: pointer;
    text-decoration: none;
    transition: all .25s;
}
.form-card .btn:hover {
    background: var(--brand-dark);
    border-color: var(--brand-dark);
    transform: translateY(-2px);
    box-shadow: var(--shadow-hover);
}

/* Le formulaire n'a pas pu se poser : ce n'est pas une faute du visiteur, pas de rouge. */
.form-card .form-message.info { background: var(--ice); color: var(--ink); }

/* Ce qui reste à poser, en tête de la suite, et la référence de la fin (D-1806) :
   le bandeau du dépôt se lisait comme une fin. */
.form-card .arbre-reste { display: block; font-size: 1rem; font-weight: 800; color: var(--brand); margin: 0 0 4px; }

/* ---------- LE BLOC DÉPLACÉ DEPUIS `styles.css` ----------
   Ce qui suit vient tel quel du § « Formulaire » de `site/public/styles.css`,
   au seul rattachement `.form-card` près. Déplacé, jamais recopié : la feuille
   du site ne le porte plus. */
.form-card {
    max-width: 640px;
    margin: 0 auto;
    background: #fff;
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    border: 1px solid rgba(46, 95, 172, 0.08);
    padding: 36px 32px;
}
.form-card .form-obligatoire { font-size: 0.85rem; color: var(--muted); margin-bottom: 18px; }
.form-card .form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
.form-card .form-group { margin-bottom: 18px; display: flex; flex-direction: column; }
.form-card label { font-weight: 800; margin-bottom: 6px; font-size: 0.92rem; }
.form-card input, .form-card textarea, .form-card select {
    padding: 12px 14px;
    border: 2px solid rgba(46, 95, 172, 0.15);
    border-radius: 12px;
    font-family: inherit;
    font-size: 1rem;
    color: var(--ink);
    background: #fff;
    transition: all .25s;
}
.form-card input:focus, .form-card textarea:focus, .form-card select:focus {
    outline: none;
    border-color: var(--brand);
    box-shadow: 0 0 0 4px rgba(46, 95, 172, 0.12);
}
.form-card textarea { min-height: 130px; resize: vertical; }
.form-card .form-submit { width: 100%; margin-top: 8px; font-size: 1.05rem; padding: 14px; border: none; }
.form-card .form-note { text-align: center; font-size: 0.85rem; color: var(--muted); margin-top: 12px; }
.form-card .form-rgpd { font-size: 0.78rem; color: var(--muted); margin-top: 16px; line-height: 1.5; }
.form-card .form-rgpd .lien-detail { color: var(--brand); font-weight: 700; }
.form-card .hp { position: absolute; left: -9999px; opacity: 0; height: 0; overflow: hidden; }
.form-card .form-message {
    display: none;
    padding: 14px 18px;
    border-radius: 12px;
    margin-bottom: 18px;
    font-weight: 700;
}
.form-card .form-message.show { display: block; }
.form-card .form-message.success { background: rgba(16, 185, 129, 0.12); color: #067a55; }
.form-card .form-message.error { background: rgba(220, 38, 38, 0.10); color: var(--erreur); }

/* ---------- Ce que la définition du CRM peut demander (D-291) ----------
   Le formulaire des pages n'est plus écrit à la main : il vient de la
   définition réglée dans le CRM (`formulairePublic.definitionActive()`). Deux
   formes n'existaient donc pas encore ici, et un champ que le patron ajoute
   au paramétrage les emploie sans qu'on repasse par cette feuille :

    · `.form-aide` — le texte d'aide d'un champ (« Ce que vous avez déjà
      tenté… »), rattaché par `aria-describedby`. Sans cette règle il
      s'affichait en paragraphe de corps de page, aussi gros que la question ;
    · `.form-case` — une case à cocher et son libellé sur la même ligne
      (types « Oui / non » et « Choix multiples »). `.form-group` est un bloc
      flex en colonne : sans cette règle, la case et son texte s'empilaient. */
.form-card .form-aide { margin: 6px 0 0; font-size: 0.85rem; color: var(--muted); line-height: 1.45; }
.form-card .form-case {
    display: flex;
    align-items: center;
    gap: 10px;
    font-weight: 500;
    font-size: 0.95rem;
    /* 44 px de haut au doigt : la cible tactile minimale du reste du site. */
    min-height: 44px;
    margin-bottom: 0;
}
.form-card .form-case input[type='checkbox'] { width: 20px; height: 20px; flex: 0 0 auto; padding: 0; }

/* Erreur de validation, rattachée à son champ par aria-describedby. */
.form-card .champ-erreur { margin: 6px 0 0; font-size: 0.85rem; color: var(--erreur); }
.form-card .form-group input[aria-invalid='true'],
.form-card .form-group select[aria-invalid='true'],
.form-card .form-group textarea[aria-invalid='true'] {
    border-color: var(--erreur);
    border-width: 2px;
}

/* ---------- Formulaire dynamique : l'arbre des questions ----------
   Posé par formulaire.js, jamais présent dans le HTML livré : sans
   JavaScript, le formulaire reste celui d'hier et aucune de ces règles
   ne s'applique à quoi que ce soit. */
.form-card .arbre { margin-bottom: 26px; }
.form-card .arbre-etape { margin-bottom: 22px; }
.form-card .arbre-question { font-weight: 800; font-size: 0.95rem; margin: 0 0 10px; }
.form-card .arbre-choix { display: grid; gap: 10px; }
.form-card .arbre-reponse {
    display: block;
    width: 100%;
    min-height: 44px;
    text-align: left;
    padding: 12px 16px;
    background: #fff;
    border: 2px solid rgba(46, 95, 172, 0.15);
    border-radius: 12px;
    color: var(--ink);
    font-family: inherit;
    font-size: 0.98rem;
    line-height: 1.35;
    cursor: pointer;
    transition: all .2s;
}
.form-card .arbre-reponse:hover { border-color: var(--brand); background: var(--ice); }
/* La réponse cochée : le contour entier passe à la couleur de marque plutôt
   que de reposer sur une seule pastille — le contraste ne dépend donc pas de
   la seule couleur, et `aria-checked` porte l'information pour qui n'en voit
   aucune. */
.form-card .arbre-reponse[aria-checked='true'] {
    background: var(--brand);
    border-color: var(--brand);
    color: #fff;
    font-weight: 700;
}
/* Le rappel de la branche choisie, une fois la première question repliée. */
.form-card .arbre-choisi {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px;
    margin: 0 0 22px;
    padding: 12px 16px;
    background: var(--ice);
    border-radius: 12px;
}
.form-card .arbre-choisi-texte { font-weight: 700; }
.form-card .arbre-changer {
    margin-left: auto;
    min-height: 40px;
    padding: 0 16px;
    background: #fff;
    border: 2px solid rgba(46, 95, 172, 0.2);
    border-radius: 999px;
    color: var(--brand);
    font-weight: 800;
    font-size: 0.82rem;
    font-family: inherit;
    cursor: pointer;
}
.form-card .arbre-changer:hover { border-color: var(--brand); background: var(--ice); }
.form-card .arbre-compte, .form-card .arbre-facultatif { font-size: 0.86rem; color: var(--muted); margin: 0 0 16px; }
.form-card .arbre-facultatif { margin: -4px 0 20px; }
/* Ce qui n'est pas encore atteint dans le fil des questions. `!important` :
   la règle doit l'emporter sur le `display` propre de chaque bloc masqué
   (`.form-row` est une grille, `.form-group` un bloc flex). */
.form-card .arbre-masque { display: none !important; }
/* UNE LIGNE — des champs qui se posent ensemble (D-1607 : le complément
   d'adresse, Bâtiment · Escalier · Étage · Appartement). Côte à côte à toutes
   les largeurs, au téléphone compris : ce sont quatre repères courts (« B »,
   « 2 », « 3e », « 14 »), et les empiler en ferait quatre questions.
   `minmax(0, 1fr)` : une case ne déborde jamais de sa colonne. */
.form-card .form-ligne { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 8px; }
.form-card .form-ligne .form-group { margin-bottom: 12px; min-width: 0; }
.form-card .form-ligne label { font-size: 0.8rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.form-card .form-ligne input { min-width: 0; width: 100%; padding: 12px 8px; }

/* ---------- Le parcours en trois étapes — D-626 ----------
   POSÉ PAR `formulaire.js`, SAUF LES BOÎTES. Les `.form-etape` sont dans le
   HTML livré (le générateur les engendre) et n'ont AUCUN style qui les cache :
   sans JavaScript, les trois se lisent à la suite et le formulaire est celui
   d'hier. Tout le reste — la barre, la navigation, la zone des photos —
   n'existe que si le script a tourné. C'est la même règle que l'arbre. */
.form-card .form-etape { margin: 0; }
.form-card .form-etape-masquee { display: none !important; }
/* Ce que le script cache sans le retirer : le bouton d'envoi avant la dernière
   étape, « Revenir » sur la première. `display:none` sort aussi de l'ordre de
   tabulation, ce qui est voulu — un bouton qu'on ne voit pas ne doit pas se
   ramasser à la touche Tab. */
.form-card .form-cache { display: none !important; }

.form-card .form-progression-bloc { margin: 0 0 22px; }
.form-card .form-progression {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    gap: 8px;
    margin: 0;
    padding: 0;
    list-style: none;
}
/* Chaque pas porte son RANG et son TITRE en toutes lettres : une barre qui ne
   se lit qu'à la couleur ne se lit pas sur un téléphone en plein soleil, ni
   par qui ne distingue pas le vert du gris. Le trait au-dessus n'est qu'un
   appoint. */
.form-card .form-pas {
    border-top: 4px solid rgba(46, 95, 172, 0.15);
    padding-top: 8px;
    min-height: 44px;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.form-card .form-pas-rang { font-size: 0.72rem; font-weight: 800; color: var(--muted); }
.form-card .form-pas-titre { font-size: 0.82rem; line-height: 1.25; color: var(--muted); }
.form-card .form-pas.est-fait { border-top-color: var(--aqua); }
.form-card .form-pas.est-courant { border-top-color: var(--brand); }
.form-card .form-pas.est-courant .form-pas-rang,
.form-card .form-pas.est-courant .form-pas-titre { color: var(--brand); font-weight: 800; }
.form-card .form-pas-annonce {
    margin: 10px 0 0;
    font-size: 0.85rem;
    font-weight: 700;
    color: var(--ink);
}

.form-card .form-nav { display: flex; gap: 12px; margin-top: 8px; }
.form-card .form-nav .btn { flex: 1 1 0; min-height: 48px; border: none; }
/* « Revenir » est un retour en arrière : il ne doit pas se disputer le regard
   avec « Continuer », mais il garde les 44 px de plancher tactile. */
.form-card .form-retour {
    background: #fff;
    color: var(--brand);
    border: 2px solid rgba(46, 95, 172, 0.25) !important;
}
.form-card .form-retour:hover { background: var(--ice); border-color: var(--brand) !important; }

/* ---------- L'étape des photos ---------- */
.form-card .form-photos-titre { font-weight: 800; font-size: 0.95rem; margin: 0 0 4px; }
.form-card .form-photos-liste {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    list-style: none;
    margin: 14px 0 0;
    padding: 0;
}
.form-card .form-photo { position: relative; }
.form-card .form-photo img {
    width: 84px;
    height: 84px;
    object-fit: cover;
    border-radius: 12px;
    border: 2px solid rgba(46, 95, 172, 0.15);
    display: block;
}
/* Le bouton qui retire une photo tient les 44 px du plancher tactile : sur un
   téléphone, une croix de 20 px se rate une fois sur trois, et la rater efface
   la mauvaise photo. */
.form-card .form-photo-retirer {
    position: absolute;
    top: -12px;
    right: -12px;
    width: 44px;
    height: 44px;
    border-radius: 999px;
    border: 2px solid #fff;
    background: var(--deep);
    color: #fff;
    font-size: 1.1rem;
    line-height: 1;
    font-family: inherit;
    cursor: pointer;
}
.form-card .form-photos-ajout {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-height: 48px;
    margin-top: 14px;
    padding: 12px 22px;
    border: 2px dashed rgba(46, 95, 172, 0.35);
    border-radius: 14px;
    color: var(--brand);
    font-weight: 800;
    font-size: 0.92rem;
    cursor: pointer;
}
.form-card .form-photos-ajout:hover { background: var(--ice); border-color: var(--brand); }
/* Le champ de fichier natif reste dans le document — sinon le clic sur
   l'étiquette n'ouvre rien —, mais il ne s'affiche pas : c'est l'étiquette qui
   porte le geste, et elle, on peut la dessiner. */
.form-card .form-photos-ajout input[type='file'] {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}
.form-card .form-photos-etat { margin: 10px 0 0; font-size: 0.85rem; color: var(--muted); }
/* ---------- Au téléphone ----------
   Venait de la requête `@media (max-width: 768px)` de `styles.css`, en fin de
   fichier : les deux colonnes de `.form-row` s'empilent. Elle est ici parce
   qu'elle habille le formulaire, et nulle part ailleurs. */
@media (max-width: 768px) {
    .form-card .form-row { grid-template-columns: 1fr; }
}
