/* Devis guide : le parcours en etapes de la page /devis.
 *
 * Verse depuis la maquette d origine, retiree le 31.10.2026, qui portait tout en
 * ligne. Sur le site, la politique de securite refuse le script en ligne et
 * une feuille en ligne se recharge a chaque page : les deux deviennent des
 * fichiers.
 *
 * Les variables employees ici, pas, traits, teintes et fontes, viennent de
 * base.css : cette feuille ne definit rien qui lui appartienne.
 */
/* =========================================================================
   Formulaire guidé, une question par écran.

   Tout est construit sur les jetons du site : angles vifs, aucune ombre,
   filets d'un pixel, encre et papier, Familjen pour les questions et
   Schibsted pour le labeur. La sortie exponentielle --sortie et les durées
   --duree / --duree-courte sont celles du reste du site, pour que le module
   ne se lise pas comme une pièce rapportée.
   ========================================================================= */

/* --- La boîte de dialogue ------------------------------------------------
   <dialog> natif : le navigateur gère le piège de focus, la touche
   d'échappement et le fond modal. Même choix que la visionneuse du site. */
.devis {
  width: 100%;
  max-width: none;
  max-height: none;
  height: 100dvh;
  padding: 0;
  border: 0;
  background: var(--papier);
  color: var(--encre);
  overflow: hidden;
  transition: background-color 560ms var(--sortie);
}
/* Le crème marque l'arrivée, comme les bandes de respiration du site : on
   quitte les questions, on relit et on envoie. J'avais d'abord teinté chaque
   branche, mais le fond changeait alors trois fois en huit écrans, ce qui
   attirait l'oeil sur le décor au lieu de la question. */
.devis[data-arrivee] { background: var(--papier-2); }
.devis[data-arrivee] .devis__pied,
.devis[data-arrivee] .devis__tete { background: transparent; }
.devis::backdrop { background: rgb(20 19 16 / 0.92); }

/* L'ouverture du cadre est jouée par le script, pas ici : elle part du
   bouton cliqué, dont la position n'est connue qu'à l'exécution. Une
   animation déclarée en CSS ne peut pas en tenir compte, et si les deux
   tournaient ensemble leurs transformations se composeraient. Il ne reste
   donc ici que le voile, qui lui n'a rien à mesurer. */
.devis::backdrop { animation: voile-entre var(--duree) var(--sortie); }
@keyframes voile-entre { from { opacity: 0; } to { opacity: 1; } }

/* --- Ossature ----------------------------------------------------------- */
/* Quatre rangées pour quatre enfants : entête, rail, corps, pied. Avec trois
   rangées déclarées, le 1fr tombait sur le rail de deux pixels, qui gardait
   pour lui trois cents pixels de vide pendant que le contenu se tassait en
   dessous. */
.devis__cadre {
  display: grid;
  /* La colonne est declaree, et surtout autorisee a descendre sous la largeur
     minimale de son contenu. Sans minmax(0, 1fr), la piste implicite se cale
     sur l'element le plus large qu'elle contienne : sur un telephone de 390 px
     elle mesurait 415, et les quatre rangees debordaient toutes de 25 px, en
     tete comme en pied. */
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto auto 1fr auto;
  height: 100%;
  min-height: 0;
}

.devis__tete {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--pas-3);
  padding: var(--pas-2) var(--gouttiere);
  border-bottom: 1px solid var(--trait);
}
.devis__marque { display: flex; align-items: center; gap: 0.6rem; }
.devis__marque img { width: 34px; height: 34px; }
.devis__marque span {
  font-family: var(--f-logo);
  font-weight: 800;
  font-size: 1.1rem;
  letter-spacing: -0.025em;
}
.devis__fermer {
  width: 2.75rem; height: 2.75rem;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--trait); background: transparent; cursor: pointer;
  transition: background-color var(--duree-courte) var(--sortie),
              color var(--duree-courte) var(--sortie);
}
.devis__fermer:hover { background: var(--encre); color: var(--papier); }

/* Rail de progression : un segment par question plutôt qu'une barre continue.
   Une barre dit « vous avancez », des segments disent « il en reste trois »,
   ce qui est la seule information dont on ait besoin dans un formulaire. */
.devis__rail {
  display: flex; gap: 3px;
  padding: 0 var(--gouttiere);
  height: 2px;
}
.devis__rail i {
  flex: 1;
  background: var(--trait);
  transform-origin: left;
  transition: background-color var(--duree) var(--sortie);
}
.devis__rail i[data-faite] { background: var(--encre); }
.devis__rail i[data-ici] {
  background: linear-gradient(to right, var(--encre) 50%, var(--trait) 50%);
  background-size: 200% 100%;
  background-position: 100% 0;
  animation: rail-remplit var(--duree) var(--sortie) forwards;
}
@keyframes rail-remplit { to { background-position: 0 0; } }

/* Le contenu se centre dans la hauteur disponible au lieu de se ranger sous
   un rembourrage fixe. Une question courte tombait sinon en haut d'un grand
   vide, et le rembourrage grandissait avec l'écran, donc le vide aussi.
   align-content plutôt que place-items : une étape plus haute que la fenêtre
   déborde alors vers le bas et reste atteignable au défilement. */
.devis__corps {
  position: relative;
  display: grid;
  align-content: center;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.devis__piste {
  width: 100%;
  max-width: 44rem;
  margin-inline: auto;
  padding: var(--pas-4) var(--gouttiere);
}

/* Deux rangées à gauche, une colonne à droite : le compteur et la signature
   s'empilent, les deux boutons gardent toute la hauteur. Avec les trois
   enfants sur une seule ligne en espacement réparti, la signature poussait
   les boutons au centre du pied, où ils ne se trouvent plus. */
.devis__pied {
  display: grid;
  grid-template-columns: 1fr auto;
  grid-template-areas:
    "compte    actions"
    "signature actions";
  align-items: center;
  column-gap: var(--pas-3);
  row-gap: 0.15rem;
  padding: var(--pas-2) var(--gouttiere);
  border-top: 1px solid var(--trait);
  background: var(--papier);
}
.devis__compte    { grid-area: compte; }
.devis__actions   { grid-area: actions; }
.devis__signature { grid-area: signature; }
.devis__compte {
  font-size: var(--t-etiquette); letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--encre-2);
  font-variant-numeric: tabular-nums;
}
.devis__actions { display: flex; gap: var(--pas-2); }

/* Le chiffre roule au lieu de se substituer d'un coup : c'est le seul endroit
   du module où quelque chose change sans que le visiteur l'ait demandé, et un
   remplacement sec s'y lit comme un défaut d'affichage. */
/* La fenetre qui cadre le chiffre doit faire exactement la hauteur d'une
   ligne, sinon elle en rogne le bas. Elle valait 1em pour un interligne
   herite de 1,6 : le chiffre depassait de sept pixels et se voyait coupe.
   Les deux valeurs sont donc accordees, et l'animation qui fait glisser un
   chiffre sur l'autre translate de cette meme hauteur. */
.compteur {
  display: inline-block; position: relative;
  min-width: 1ch; height: 1.2em; overflow: hidden;
  vertical-align: -0.26em;
}
.compteur > span { display: block; line-height: 1.2; }
.compteur > span[data-part] {
  position: absolute; inset: 0;
  animation: chiffre-sort 300ms var(--sortie) forwards;
}
.compteur > span[data-entre] { animation: chiffre-entre 300ms var(--sortie); }
@keyframes chiffre-sort  { to { transform: translateY(-100%); opacity: 0; } }
@keyframes chiffre-entre { from { transform: translateY(100%); opacity: 0; } }

/* --- Une étape ----------------------------------------------------------- */
.etape { display: none; }
.etape[data-actif] { display: block; }

.etape__numero {
  display: block;
  font-size: var(--t-etiquette); letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--encre-2);
  margin-bottom: var(--pas-1);
}
.etape__question {
  font-family: var(--f-titre);
  font-size: clamp(1.7rem, 3.6vw, 2.9rem);
  font-weight: 500; line-height: 1.08; letter-spacing: -0.026em;
  text-wrap: balance;
  margin: 0 0 var(--pas-2);
}
.etape__aide {
  font-size: var(--t-grand); line-height: 1.42; color: var(--encre-2);
  max-width: 40ch; margin: var(--pas-1) 0 var(--pas-3);
}

/* Entrée et sortie, orientées par le sens de navigation. */
.etape[data-actif] > * { animation: monte var(--duree) var(--sortie) backwards; }
.etape[data-actif] > *:nth-child(1) { animation-delay: 0ms; }
.etape[data-actif] > *:nth-child(2) { animation-delay: 45ms; }
.etape[data-actif] > *:nth-child(3) { animation-delay: 90ms; }
.etape[data-actif] > *:nth-child(4) { animation-delay: 135ms; }
.etape[data-actif][data-sens="arriere"] > * { animation-name: descend; }
.etape[data-sortie] { display: block; animation: quitte 200ms var(--sortie) forwards; }
.etape[data-sortie][data-sens="arriere"] { animation-name: quitte-bas; }

@keyframes monte   { from { opacity: 0; transform: translateY(18px); } to { opacity: 1; transform: none; } }
@keyframes descend { from { opacity: 0; transform: translateY(-18px); } to { opacity: 1; transform: none; } }
@keyframes quitte     { to { opacity: 0; transform: translateY(-14px); } }
@keyframes quitte-bas { to { opacity: 0; transform: translateY(14px); } }

/* Sur grand ecran, la question et la reponse se partagent la largeur au lieu
   d'empiler une colonne etroite au milieu du blanc. C'est la composition des
   tetes de page du site : l'intitule a gauche, ce qui repond a droite. */
@media (min-width: 900px) {
  .devis__piste { max-width: 68rem; }

  .etape[data-actif]:not([data-etape="fini"]):not([data-etape="reprise"]),
  .etape[data-sortie]:not([data-etape="fini"]):not([data-etape="reprise"]) {
    display: grid;
    grid-template-columns: minmax(0, 4fr) minmax(0, 5fr);
    column-gap: clamp(2rem, 4vw, 4.5rem);
    align-items: start;
  }
  .etape__numero   { grid-column: 1; grid-row: 1; }
  .etape__question { grid-column: 1; grid-row: 2; }
  .etape__aide     { grid-column: 1; grid-row: 3; margin-bottom: 0; }

  /* Sauf sur les deux ecrans que la grille ci-dessus laisse de cote : eux
     restent sur une seule colonne, et la phrase d'aide y est suivie de son
     contenu au lieu de finir une colonne. Sans cette reprise, elle collait au
     filet du tableau. Une regle ecrite pour une disposition s'appliquait a un
     ecran qui n'y entre jamais. */
  .etape[data-etape="reprise"] .etape__aide,
  .etape[data-etape="fini"] .etape__aide {
    margin-bottom: var(--pas-3);
  }
  /* Tout ce qui n'est pas de la parole va dans la colonne de reponse, sur
     toute sa hauteur : une etape sans phrase d'aide ne decale donc rien. */
  .etape > :not(.etape__numero):not(.etape__question):not(.etape__aide) {
    grid-column: 2;
    /* A partir de la rangee 2 : la reponse se cale sur la question, pas sur
       l'intitule en capitales qui la surmonte. Un span plutot qu'un -1 :
       sans grid-template-rows declare, -1 ne designe que la fin de la grille
       explicite, qui est vide, et la regle se repliait en rangee 1. */
    grid-row: 2 / span 5;
  }

  /* Le nom du salon et la date ne tiennent pas cote a cote dans une demi
     largeur : les deux listes y tombaient a cent pixels et « Année » se
     coupait. Ils s'empilent donc. */
  .etape[data-etape="salon"] .duo-champs { grid-template-columns: 1fr; }
}

/* --- Choix --------------------------------------------------------------- */
.choix { display: grid; gap: var(--pas-1); }
.choix--paire { grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr)); }

.choix__option {
  position: relative;
  display: flex; align-items: baseline; gap: var(--pas-2);
  padding: var(--pas-2) var(--pas-3);
  border: 1px solid var(--trait-fort);
  background: transparent;
  text-align: left;
  cursor: pointer;
  overflow: hidden;
  transition: border-color var(--duree-courte) var(--sortie),
              color var(--duree-courte) var(--sortie);
}
/* Le remplissage balaie depuis la gauche plutôt que d'apparaître d'un bloc. */
.choix__option::before {
  content: ""; position: absolute; inset: 0;
  background: var(--encre);
  transform: scaleX(0); transform-origin: left;
  transition: transform var(--duree-courte) var(--sortie);
}
.choix__option > * { position: relative; }
.choix__option:hover { border-color: var(--encre); }
.choix__option[aria-pressed="true"] { border-color: var(--encre); color: var(--papier); }
.choix__option[aria-pressed="true"]::before { transform: scaleX(1); }

.choix__cle {
  font-size: var(--t-etiquette); letter-spacing: 0.1em;
  color: var(--trait-fort); font-variant-numeric: tabular-nums;
}
.choix__option[aria-pressed="true"] .choix__cle { color: var(--papier-3); }
.choix__nom { font-family: var(--f-titre); font-size: var(--t-h3); font-weight: 500; }
.choix__note { display: block; font-size: var(--t-petit); color: var(--encre-2); margin-top: 0.3rem; }
.choix__option[aria-pressed="true"] .choix__note { color: var(--papier-3); }

/* --- Champs -------------------------------------------------------------- */
.duo-champs { display: grid; gap: var(--pas-3); grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr)); }
.duo-champs + .duo-champs { margin-top: var(--pas-3); }
/* Deux blocs de reponse dans la meme colonne ne doivent pas se toucher. */
.repondre > * + * { margin-top: var(--pas-3); }

/* Les fleches natives du champ nombre sont dessinees par le systeme : rondes,
   grises, etrangeres au monde. On les retire, le clavier et la molette
   continuent de fonctionner. */
.devis input[type="number"] { appearance: textfield; -moz-appearance: textfield; }
.devis input[type="number"]::-webkit-outer-spin-button,
.devis input[type="number"]::-webkit-inner-spin-button { appearance: none; margin: 0; }
.devis .champ { margin-bottom: 0; }

/* Le message d'erreur descend sous le champ au lieu d'apparaître : le
   déplacement du contenu qui suit doit se voir, sinon le visiteur croit que
   la page a sauté. */
.devis .champ__erreur { animation: erreur-entre 260ms var(--sortie); }
@keyframes erreur-entre {
  from { opacity: 0; transform: translateY(-5px); }
  to   { opacity: 1; transform: none; }
}

/* Erreur sur un groupe de choix : même message, même couleur que sur un champ.
   Le message vit dans le groupe, qui est une grille : il prend donc toute la
   largeur, sans quoi il se logerait dans une colonne d'options. */
.choix__erreur {
  display: block;
  grid-column: 1 / -1;
  font-size: var(--t-petit); color: var(--alerte);
  margin-top: var(--pas-1);
  animation: erreur-entre 260ms var(--sortie);
}

/* Mois et année en deux listes plutôt qu'en champ de type month : le sélecteur
   natif impose son propre calendrier, bleu et arrondi, qu'aucune feuille ne
   peut habiller. Les listes, elles, portent déjà l'habillage du site. */
.date-salon { display: grid; grid-template-columns: 1fr 1fr; gap: var(--pas-2); }
.date-salon .champ__select { display: block; }
.date-salon select { width: 100%; }

/* --- Dépôt de document --------------------------------------------------- */
/* Le depot se tient comme un champ : aligne a gauche, filet plein d'un pixel,
   angles vifs. Le pointille est la convention du glisser-deposer, mais c'est
   le seul trait discontinu du systeme et il jurait a cote des autres reponses.
   Le libelle et le bouton disent deja ce qu'il faut faire. */
.depot {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--pas-2) var(--pas-3);
  border: 1px solid var(--trait-fort);
  padding: var(--pas-3);
  transition: border-color var(--duree-courte) var(--sortie),
              background-color var(--duree-courte) var(--sortie);
}
.depot[data-survol] { border-color: var(--encre); background: var(--papier-2); }
.depot__dire { flex: 1 1 12rem; }
.depot__titre { display: block; font-family: var(--f-titre); font-size: var(--t-h3); font-weight: 500; }
.depot__regles { font-size: var(--t-petit); color: var(--encre-2); margin: 0.15rem 0 0; }
.depot input[type="file"] { position: absolute; width: 1px; height: 1px; opacity: 0; }

.fichiers { list-style: none; margin: var(--pas-3) 0 0; padding: 0; }
.fichier {
  display: flex; align-items: center; gap: var(--pas-2);
  padding: 0.7rem var(--pas-2);
  border: 1px solid var(--trait);
  margin-bottom: var(--pas-1);
  animation: monte 320ms var(--sortie);
}
.fichier--refuse { border-color: var(--alerte); color: var(--alerte); animation: refus 420ms var(--sortie); }
.fichier__nom { flex: 1; font-size: var(--t-petit); overflow-wrap: anywhere; }
.fichier__poids { font-size: var(--t-etiquette); color: var(--encre-2); font-variant-numeric: tabular-nums; }
.fichier--refuse .fichier__poids { color: var(--alerte); }
.fichier__retirer {
  border: 0; background: transparent; cursor: pointer; color: inherit;
  padding: 0.2rem; line-height: 0;
}
@keyframes refus {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-6px); }
  45% { transform: translateX(5px); }
  70% { transform: translateX(-3px); }
}

/* --- Reprise d'un brouillon ---------------------------------------------- */
.reprise-fiche {
  border-top: 1px solid var(--trait);
  margin-bottom: var(--pas-3);
}
/* Les lignes respirent un peu plus que celles du recapitulatif : sur cet
   ecran elles sont seules et se lisent d'un coup d'oeil, pas parcourues. */
.reprise-fiche p {
  display: flex; gap: var(--pas-2); justify-content: space-between;
  padding: 0.95rem 0; margin: 0;
  border-bottom: 1px solid var(--trait);
  font-size: var(--t-petit);
}
.reprise-fiche b { font-weight: 500; }
.reprise-fiche span { color: var(--encre-2); text-align: right; }
.reprise-note {
  font-size: var(--t-petit); color: var(--encre-2);
  max-width: 52ch; margin: 0 0 var(--pas-4);
}
.reprise-actions { display: flex; flex-wrap: wrap; gap: var(--pas-2); }

/* --- Récapitulatif ------------------------------------------------------- */
.recap { border-top: 1px solid var(--trait); margin-top: var(--pas-3); }
/* Chaque ligne ramène à la question qui l'a produite. Sans cela, corriger la
   surface depuis le récapitulatif demande six fois « Retour ». */
.recap__ligne {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.6fr) auto;
  align-items: baseline;
  gap: var(--pas-2);
  width: 100%;
  padding: 0.85rem var(--pas-2) 0.85rem 0;
  border: 0; border-bottom: 1px solid var(--trait);
  background: transparent; color: inherit; text-align: left;
  font: inherit; cursor: pointer;
  transition: background-color var(--duree-courte) var(--sortie),
              padding-left var(--duree-courte) var(--sortie);
}
.recap__ligne:hover, .recap__ligne:focus-visible {
  background: var(--papier);
  padding-left: var(--pas-2);
}
.recap__cle { font-size: var(--t-etiquette); letter-spacing: 0.1em; text-transform: uppercase; color: var(--encre-2); }
.recap__val { font-size: var(--t-texte); }
.recap__corriger {
  font-size: var(--t-etiquette); letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--encre-2);
  opacity: 0; transform: translateX(-4px);
  transition: opacity var(--duree-courte) var(--sortie),
              transform var(--duree-courte) var(--sortie);
}
.recap__ligne:hover .recap__corriger,
.recap__ligne:focus-visible .recap__corriger { opacity: 1; transform: none; }
@media (max-width: 599px) {
  .recap__ligne { grid-template-columns: 1fr auto; gap: 0.2rem var(--pas-2); }
  .recap__val { grid-column: 1; }
  .recap__corriger { grid-column: 2; grid-row: 1 / span 2; opacity: 1; transform: none; }
}
/* Sans pointeur fin, le survol n'existe pas : la mention reste visible. */
@media (hover: none) { .recap__corriger { opacity: 1; transform: none; } }

/* --- L'envoi -------------------------------------------------------------
   Le recapitulatif part ligne a ligne vers le haut, puis le bloc entier suit.
   Pas de gerbe ni de lueur : ce monde n'a ni couleur ni ombre. Ce qui dit
   « c'est parti », c'est que la feuille qu'on relisait quitte l'ecran. */
.etape[data-envoi] { pointer-events: none; }
.etape[data-envoi] .recap__ligne {
  animation: ligne-part 380ms var(--sortie) forwards;
  animation-delay: calc(var(--i, 0) * 38ms);
}
.etape[data-envoi] .etape__numero,
.etape[data-envoi] .etape__question,
.etape[data-envoi] .etape__aide {
  animation: parole-part 320ms var(--sortie) forwards;
}
@keyframes ligne-part   { to { opacity: 0; transform: translateY(-26px); } }
@keyframes parole-part  { to { opacity: 0; transform: translateY(-14px); } }

/* Le rail se remplit d'un trait pendant que la feuille s'en va. */
.devis[data-envoi] .devis__rail i { background: var(--encre); }

/* --- Confirmation --------------------------------------------------------
   L'écran final n'a plus de pied pour le caler : sans centrage vertical il
   tombe sous le rembourrage de la piste et flotte dans le vide. On sort donc
   du flux de la piste pour occuper toute la hauteur restante. */
.fini {
  display: grid;
  justify-items: center;
  gap: var(--pas-3);
  text-align: center;
  max-width: 34rem;
  margin-inline: auto;
  padding: 0;
}
.fini .etape__question { margin: 0; }
.fini .etape__aide { margin: 0; max-width: 40ch; }

/* La suite concrète : ce que le visiteur fait s'il ne veut pas attendre. */
.fini__suite {
  width: 100%;
  margin-top: var(--pas-2);
  padding-top: var(--pas-3);
  border-top: 1px solid var(--trait-fort);
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: var(--pas-2) var(--pas-4);
  font-size: var(--t-petit);
}
.fini__suite a {
  display: inline-flex; align-items: center; gap: 0.45em;
  color: var(--encre); text-decoration: none;
  border-bottom: 1px solid var(--trait-fort);
  padding-bottom: 0.15em;
  transition: border-color var(--duree-courte) var(--sortie);
}
.fini__suite a:hover { border-bottom-color: var(--encre); }
.fini__actions { margin-top: var(--pas-2); }
.fini__trait { stroke-dasharray: 60; stroke-dashoffset: 60; animation: trace 620ms var(--sortie) 180ms forwards; }
.fini__cercle { stroke-dasharray: 208; stroke-dashoffset: 208; animation: trace 760ms var(--sortie) forwards; }
@keyframes trace { to { stroke-dashoffset: 0; } }

/* --- Mouvement réduit ----------------------------------------------------
   Tout s'immobilise, rien ne disparaît : une panne d'animation ne doit
   jamais cacher un contenu. */
@media (prefers-reduced-motion: reduce) {
  .devis::backdrop,
  .etape[data-actif] > *, .etape[data-sortie],
  .fichier, .fini__trait, .fini__cercle,
  .devis__rail i[data-ici], .compteur > span,
  .devis .champ__erreur, .choix__erreur,
  .etape[data-envoi] .recap__ligne, .etape[data-envoi] .etape__numero,
  .etape[data-envoi] .etape__question, .etape[data-envoi] .etape__aide { animation: none !important; }
  .fini__trait, .fini__cercle { stroke-dashoffset: 0; }
  .devis__rail i[data-ici] { background: var(--encre); }
  .devis, .devis__rail i, .choix__option::before { transition: none; }
}


/* --- Ce que la maquette n'avait pas --------------------------------------
   La maquette simulait l'envoi. Ce qu'il fallait vraiment envoyer, et ce
   qui peut vraiment être refusé, s'habille ici. */

/* Vérification anti-robot, posée sur le récapitulatif. Elle ne s'affiche
   que si un fournisseur est configuré : sans clé, rien n'est rendu et la
   marge ne doit pas rester. */
.devis__captcha {
  margin-top: var(--pas-3);
}

/* Le refus que le visiteur ne peut pas lever seul : jeton périmé, quota
   atteint, panne d'envoi. Il reste sous le récapitulatif au lieu de passer
   dans une alerte qui s'efface, parce qu'on a besoin de le relire. */
.devis__avis {
  margin-top: var(--pas-3);
  padding: var(--pas-2);
  border-left: 3px solid var(--alerte);
  background: var(--papier-2);
  font-size: var(--t-petit);
  line-height: 1.55;
  color: var(--encre);
}
.devis__avis[hidden] { display: none; }

/* Un champ qui suit un groupe de choix dans la même colonne. Remplace un
   style écrit dans le balisage, que la politique de sécurité du site
   interdit. */
.champ--suit-choix { margin-top: var(--pas-3); }

/* Signature de l'atelier qui a fait le site. Elle occupe la troisième
   cellule du pied, à droite sur grand écran, et passe sous les boutons sur
   petit : en ligne avec eux, elle mangerait la place du bouton d'envoi. */
.devis__signature {
  font-size: 0.75rem;
  letter-spacing: 0.02em;
  color: var(--encre-2);
  text-decoration: none;
  /* Deux demandes contraires se rejoignent ici. Le controle d'accessibilite
     exige 4,5 de contraste a cette taille, et l'encre seconde a soixante-dix
     pour cent tombait a #888984 sur blanc, soit 3,52. Leandre, lui, voulait
     la signature plus douce encore.

     Baisser l'opacite aurait satisfait l'un en aggravant l'autre. Ce qui fait
     reellement saillir cette ligne n'est pas sa teinte mais son soulignement,
     un filet fort sous un texte de douze pixels. Le filet passe donc au trait
     clair et le texte remonte a quatre-vingt-deux pour cent, soit #74746F et
     4,70 de contraste : la ligne se lit moins qu'avant tout en devenant
     lisible pour qui voit mal. Valeur mesuree et non estimee, 0,80 ne donnait
     que 4,45. */
  opacity: 0.82;
  transition: opacity var(--duree-courte) var(--sortie);
}
.devis__signature span { border-bottom: 1px solid var(--trait); }
.devis__signature:hover,
.devis__signature:focus-visible { opacity: 1; }

@media (max-width: 599px) {
  .devis__signature { font-size: 0.7rem; }

  /* Le pied ne tenait pas sur un telephone. Mesure a 390 px : 350 px
     disponibles, et la rangee en demandait 369. Deux corrections, pas une.

     La signature passe sous le reste, sur toute la largeur : coincee dans ce
     qui restait de la colonne de gauche, elle se brisait en trois lignes.

     Et les boutons se resserrent. « Retour » est masque a la premiere etape
     mais occupe tout de meme sa place, par choix : le voir disparaitre
     ferait sauter « Continuer » d'une etape a l'autre. A deux boutons de
     1,75em de respiration laterale, il ne restait plus de quoi ecrire
     « 1 SUR 5 » sans le casser en trois lignes lui aussi. */
  .devis__pied {
    grid-template-areas:
      "compte    actions"
      "signature signature";
  }

  .devis__compte { white-space: nowrap; }

  .devis__actions .bouton { padding-inline: var(--pas-2); }
}

/* --- Calendrier ----------------------------------------------------------
   Ouvert par la quatrieme reponse de l'echeance, « une date precise ».

   Tout y suit la charte : angles vifs, filets d'un pixel, aucune ombre, et
   la teinte pleine reservee au seul jour retenu. Un calendrier est une
   grille de chiffres, c'est-a-dire exactement ce que ce systeme sait faire ;
   il n'avait besoin d'aucune forme nouvelle. */

/* Le depliage passe par les rangees de grille : de 0fr a 1fr, une hauteur
   automatique s'anime, ce qu'une hauteur en pixels ne permet pas sans la
   mesurer en JavaScript. L'enfant porte le debordement, sinon le contenu
   depasserait pendant la course. */
.calendrier {
  display: grid;
  grid-template-rows: 0fr;
  margin-top: var(--pas-3);
  opacity: 0;
  transition: grid-template-rows var(--duree) var(--sortie),
              opacity var(--duree-courte) var(--sortie),
              margin-top var(--duree) var(--sortie);
}
.calendrier[hidden] { display: none; }
.calendrier[data-ouvert] { grid-template-rows: 1fr; opacity: 1; }
.calendrier__interieur { overflow: hidden; min-height: 0; }

.calendrier__cadre {
  border: 1px solid var(--trait-fort);
  background: var(--papier);
  padding: var(--pas-2);
}

/* --- Entete : le mois entre deux fleches -------------------------------- */
.calendrier__tete {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--pas-1);
  margin-bottom: var(--pas-2);
}
.calendrier__mois {
  text-align: center;
  font-family: var(--f-titre);
  font-size: var(--t-corps);
  font-weight: 500;
  /* Le mois change de longueur d'un mois a l'autre : sans hauteur fixe, la
     ligne sautait d'un pixel entre « mai » et « septembre ». */
  line-height: 1.6;
}

/* Les deux fleches reprennent le meme chevron que les listes deroulantes,
   tourne d'un quart de tour. Une icone de plus dans le sprite pour une
   rotation que le navigateur fait gratuitement n'aurait rien apporte. */
.calendrier__fleche {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.2rem; height: 2.2rem;
  border: 1px solid var(--trait);
  background: var(--papier);
  color: var(--encre);
  cursor: pointer;
  transition: border-color var(--duree-courte) var(--sortie),
              background-color var(--duree-courte) var(--sortie);
}
.calendrier__fleche[data-pas="-1"] .icone { transform: rotate(90deg); }
.calendrier__fleche[data-pas="1"]  .icone { transform: rotate(-90deg); }
.calendrier__fleche:hover { border-color: var(--trait-fort); background: var(--papier-2); }
.calendrier__fleche:focus-visible { outline: 2px solid var(--encre); outline-offset: 1px; }
.calendrier__fleche[disabled] { opacity: 0.35; cursor: default; }
.calendrier__fleche[disabled]:hover { border-color: var(--trait); background: var(--papier); }

/* --- Initiales des jours et grille -------------------------------------- */
.calendrier__initiales,
.calendrier__grille {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
}
.calendrier__initiales {
  gap: 1px;
  padding-bottom: var(--pas-1);
  margin-bottom: var(--pas-1);
  border-bottom: 1px solid var(--trait);
  font-size: var(--t-etiquette);
  letter-spacing: 0.08em;
  text-align: center;
  color: var(--encre-2);
}
.calendrier__grille { gap: 1px; }

.calendrier__jour {
  aspect-ratio: 1;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid transparent;
  background: none;
  font-size: var(--t-petit);
  font-variant-numeric: tabular-nums;
  color: var(--encre);
  cursor: pointer;
  transition: border-color var(--duree-courte) var(--sortie),
              background-color var(--duree-courte) var(--sortie),
              color var(--duree-courte) var(--sortie);
}
.calendrier__jour--vide { cursor: default; }
.calendrier__jour[disabled] { color: var(--trait-fort); cursor: default; }
.calendrier__jour:not([disabled]):hover { border-color: var(--trait-fort); background: var(--papier-2); }
.calendrier__jour:focus-visible { outline: 2px solid var(--encre); outline-offset: -1px; }

/* Aujourd'hui se marque d'un filet sous le chiffre, pas d'un aplat : l'aplat
   est reserve au jour choisi, et deux aplats dans une grille se disputent le
   regard. */
.calendrier__jour[data-aujourdhui] { box-shadow: none; text-decoration: underline;
  text-underline-offset: 0.3em; text-decoration-thickness: 1px; }
.calendrier__jour[aria-selected="true"],
.calendrier__jour[aria-selected="true"]:hover {
  background: var(--encre);
  border-color: var(--encre);
  color: var(--papier);
  text-decoration: none;
}

/* --- Le mouvement --------------------------------------------------------
   Les jours n'apparaissent pas d'un bloc : ils montent en cascade, une
   douzaine de millisecondes d'ecart, comme les lignes du recapitulatif. Le
   decalage vient de --i, pose par le script sur chaque case. La cascade
   entiere tient sous les 480ms d'une entree.

   Au changement de mois, la grille glisse du cote d'ou vient le nouveau
   mois : le sens est l'information, il dit qu'on avance ou qu'on recule. */
.calendrier__grille .calendrier__jour {
  animation: jour-entre 320ms var(--sortie) backwards;
  animation-delay: calc(var(--i, 0) * 11ms);
}
@keyframes jour-entre {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}
.calendrier__grille[data-sens="avant"] .calendrier__jour { animation-name: jour-entre-droite; }
.calendrier__grille[data-sens="arriere"] .calendrier__jour { animation-name: jour-entre-gauche; }
@keyframes jour-entre-droite {
  from { opacity: 0; transform: translateX(14px); }
  to   { opacity: 1; transform: none; }
}
@keyframes jour-entre-gauche {
  from { opacity: 0; transform: translateX(-14px); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .calendrier { transition: none; }
  .calendrier__grille .calendrier__jour { animation: none !important; }
  .calendrier__fleche, .calendrier__jour { transition: none; }
}
