/* ---------------------------------------------------------------------------
   SITE PUBLIC — evidra.fr

   CE QUE CETTE FEUILLE N'EST PAS
   ------------------------------
   Elle ne redéfinit AUCUNE couleur, AUCUNE police, AUCUN mode sombre. Tout
   cela vient de style.css, chargée juste avant : ses jetons `--marque`,
   `--accent`, `--fond`, `--texte` basculent déjà seuls entre les deux thèmes,
   et la vitrine en hérite sans une ligne de plus. Une seconde définition de la
   charte aurait divergé au premier ajustement de teinte — c'est le défaut
   qu'on paie six mois plus tard, quand un écran sur deux a la bonne couleur.

   ⚠️⚠️ TOUT EST PRÉFIXÉ `.v-`, SANS EXCEPTION. style.css fait près de quatre
      mille lignes et possède déjà `.entete`, `.nav`, `.marque`, `.pied`,
      `.champ`, `.bouton`. Réemployer l'un de ces noms ici ne les REMPLACERAIT
      pas : les deux règles se superposeraient, et le résultat dépendrait de
      l'ordre de chargement — le genre de défaut qu'on ne trouve qu'en mesurant
      l'élément. Les seules classes non préfixées sont celles qu'on veut
      partager exprès : `theme-bascule`, `message`, `annonce-invisible`.

   ⚠️ MOBILITÉ DE PREMIER RANG, comme partout sur ce projet : zones tactiles de
      44 px, champs de saisie à 16 px (en dessous, iOS zoome tout seul dès
      qu'on touche le champ), et rien qui déborde à 390 px.
   ------------------------------------------------------------------------ */

/* ⚠️ `body.vitrine` et non `body` : l'extranet partage la même feuille de
   base, et une règle posée sur `body` tout court l'atteindrait aussi. */
body.vitrine {
  background: var(--fond);
}

/* Le pied doit rester en bas d'une page peu remplie — style.css le fait déjà
   pour l'extranet, mais son `main` porte la classe `.principal` que la vitrine
   n'a pas. */
body.vitrine > main {
  flex: 1;
}

/* ---------------------------------------------------------------------------
   LIEN D'ÉVITEMENT
   ---------------------------------------------------------------------------
   ⭐ Invisible tant qu'il n'a pas le focus, parfaitement visible dès qu'il
   l'a. Il ne doit PAS être masqué par `display:none` ni `visibility:hidden` :
   les deux le retirent de l'ordre de tabulation, et il ne pourrait plus jamais
   recevoir le focus — c'est-à-dire ne jamais servir. */
.v-evitement {
  position: absolute;
  left: 1rem;
  /* ⚠️ -6rem ET NON -4rem. À -4rem, le lien lui-même est bien hors de l'écran
     (il fait 3 rem de haut) mais SON OMBRE PORTÉE descend de 6 px et déborde
     de 22 px sous le bord supérieur : un liseré clair apparaissait en haut à
     gauche de la page, sur toutes les captures, sans qu'aucun élément visible
     ne l'explique. Vu sur le rendu, pas dans la feuille. */
  top: -6rem;
  z-index: 100;
  padding: .75rem 1.25rem;
  border-radius: var(--rayon);
  background: var(--fond);
  color: var(--accent);
  font-weight: 600;
  text-decoration: none;
  box-shadow: var(--ombre-relief);
  transition: top .18s ease;
}
.v-evitement:focus { top: 1rem; }

/* ---------------------------------------------------------------------------
   EN-TÊTE
   ---------------------------------------------------------------------------
   ⭐ `sticky`, jamais `fixed` : `fixed` sort du flux et oblige à compenser sa
   hauteur par une marge qu'il faut maintenir à la main à chaque changement de
   rembourrage. */
.v-entete {
  position: sticky;
  top: 0;
  z-index: 20;
  background: color-mix(in srgb, var(--fond) 88%, transparent);
  /* Le flou d'arrière-plan n'est pas décoratif : sans lui, le texte de la page
     traverse la barre translucide au défilement et devient illisible.
     ⚠️ Un repli opaque est déclaré au-dessus pour les navigateurs qui ne
        savent pas flouter — la lisibilité ne dépend pas d'un effet. */
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--bord);
}
@supports not (backdrop-filter: blur(1px)) {
  .v-entete { background: var(--fond); }
}

.v-entete-interieur {
  max-width: 76rem;
  margin: 0 auto;
  padding: .6rem clamp(1rem, 4vw, 2rem);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

/* ⚠️⚠️ LA TYPOGRAPHIE EST CELLE DE `.marque` DE L'EXTRANET, VALEUR PAR VALEUR :
   gap .6rem, poids 600, interlettrage .16em. J'avais mis 700 et .01em — le nom
   se lisait donc autrement d'un site à l'autre, alors que c'est la SEULE chose
   qui doit se reconnaître au premier coup d'œil entre une vitrine et son espace
   client. Seule la TAILLE diffère (1,15 rem contre 1,3), parce que cet en-tête
   est plus bas ; l'identité tient à l'interlettrage, pas au corps.
   ⚠️ La couleur, elle, ne peut pas être copiée : `.marque` impose `#fff` pour
      son en-tête bleu. Ici le fond suit le thème, donc l'encre aussi. */
.v-marque {
  display: inline-flex;
  align-items: center;
  gap: .6rem;
  font-weight: 600;
  font-size: 1.15rem;
  letter-spacing: .16em;
  color: var(--titre);
  text-decoration: none;
  /* La zone tactile de la marque : c'est le retour à l'accueil, on le vise au
     pouce comme le reste. */
  min-height: 44px;
}
/* ⚠️⚠️ HAUTEUR IMPOSÉE, LARGEUR LIBRE — c'est la règle du projet, et je l'avais
   enfreinte. Le fichier fait 120 × 67 (ratio 1,79) ; forcé en carré, le losange
   était écrasé de 44 % en largeur. L'en-tête de l'extranet fait
   `height: 30px; width: auto`, la page de connexion `height: 56px; width: auto`.
   Il n'y a jamais eu de raison de faire autrement ici. */
.v-logo {
  height: 30px;
  width: auto;
  display: block;
}

/* ⚠️⚠️ LES DEUX VERSIONS SONT DANS LE DOCUMENT, LE CSS N'EN MONTRE QU'UNE —
   mêmes conditions, à la ligne près, que celles du bouton de thème dans
   style.css. Les écrire à l'identique est ce qui garantit qu'elles ne peuvent
   pas diverger : le jour où l'une changerait sans l'autre, le logo blanc
   s'afficherait sur fond blanc, exactement le défaut trouvé le 07/08 sur
   l'en-tête de l'extranet.
   ⛔ Et surtout PAS d'échange en JavaScript : le mauvais logo s'afficherait
     jusqu'à ce que le script tourne. */
.v-logo-sombre { display: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="clair"]) .v-logo-clair  { display: none; }
  :root:not([data-theme="clair"]) .v-logo-sombre { display: block; }
}
:root[data-theme="sombre"] .v-logo-clair  { display: none; }
:root[data-theme="sombre"] .v-logo-sombre { display: block; }
:root[data-theme="clair"]  .v-logo-clair  { display: block; }
:root[data-theme="clair"]  .v-logo-sombre { display: none; }

.v-nav {
  display: flex;
  align-items: center;
  gap: .35rem;
}
.v-nav a {
  padding: .5rem .7rem;
  border-radius: var(--rayon);
  color: var(--texte-doux);
  text-decoration: none;
  font-size: .95rem;
  font-weight: 500;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}
.v-nav a:hover { color: var(--titre); background: var(--fond-doux); }

.v-nav-client {
  border: 1px solid var(--bord-champ);
  color: var(--accent) !important;
  font-weight: 600 !important;
}

/* ---------------------------------------------------------------------------
   LE BOUTON DE THÈME
   ---------------------------------------------------------------------------
   ⚠️⚠️ IL N'AVAIT AUCUN STYLE ICI, ET ÇA SE VOYAIT. `style.css` ne lui donne
   que sa forme intérieure (rembourrage, rayon, taille d'icône) ; son
   apparence — fond transparent, encre claire, pas de bordure — lui vient sur
   l'extranet de la barre bleue qui l'entoure. Posé dans une barre claire qui
   ne dit rien, il retombait sur l'apparence NATIVE d'un `<button>` : cadre
   gris, fond gris, coins du système. À côté de trois liens de navigation
   soignés, il faisait pièce rapportée — c'est exactement ce que l'auteur a
   relevé.

   ⇒ Il reçoit donc le traitement des liens voisins, à l'identique : mêmes
   couleurs, même survol, même rayon. Un bouton d'icône dans une barre de
   navigation doit se comporter comme ses voisins, pas comme un formulaire.

   ⚠️ 44 px DANS LES DEUX SENS. Les liens tirent leur hauteur de leur texte ;
      celui-ci n'en a pas, et sans minimum il ferait 26 px — introuvable au
      pouce. */
.v-nav .theme-bascule {
  appearance: none;
  background: transparent;
  border: 0;
  color: var(--texte-doux);
  cursor: pointer;
  min-height: 44px;
  min-width: 44px;
  border-radius: var(--rayon);
}
.v-nav .theme-bascule:hover {
  color: var(--titre);
  background: var(--fond-doux);
}
.v-nav .theme-bascule:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
/* Les icônes de l'extranet font 18 px ; on ne change pas cette valeur, c'est
   elle qui fait que le même bouton se reconnaît d'un site à l'autre. */

/* ⚠️ SOUS 780 px LES ANCRES DISPARAISSENT, PAS L'ACCÈS CLIENT NI LE THÈME.
   Un menu replié (☰) pour trois ancres internes d'une page d'une seule page
   serait un bouton de plus à toucher pour arriver là où le défilement mène
   déjà. Ce qui doit rester joignable, c'est ce qui MÈNE AILLEURS. */
@media (max-width: 780px) {
  .v-nav a[href^="#"] { display: none; }
}

/* ---------------------------------------------------------------------------
   LA PROMESSE
   ------------------------------------------------------------------------ */
.v-hero {
  position: relative;
  overflow: hidden;
  background:
    radial-gradient(120% 90% at 15% 0%, color-mix(in srgb, var(--marque-clair) 70%, transparent), transparent 60%),
    var(--marque);
  color: #fff;
  /* ⚠️ `dvh` ET NON `vh` : sur téléphone la barre d'adresse se rétracte au
     défilement, et `vh` fige la hauteur sur la fenêtre la plus grande — la
     section dépasse alors d'une barre d'adresse à l'arrivée sur la page.
     Un MINIMUM, pas une hauteur : le contenu commande, la fenêtre suggère. */
  min-height: min(46rem, 88dvh);
  display: flex;
  align-items: center;
  padding: clamp(3rem, 9vw, 6rem) clamp(1rem, 4vw, 2rem);
}

.v-hero-fond {
  position: absolute;
  inset: 0;
  pointer-events: none;

  /* ⚠️⚠️ LE MASQUE N'EST PAS UN ORNEMENT : SANS LUI, LES VOIES TRAVERSENT LE
     TEXTE. Constaté sur le rendu réel, en clair comme en sombre — les traits
     passaient au milieu du chapô et sous les boutons, et un trait clair sur du
     texte clair, c'est du texte qu'on relit deux fois.
     Le dégradé creuse un trou au centre-gauche, là où vit le bloc de texte, et
     laisse le tracé plein aux bords. Il suit donc la mise en page au lieu de
     dépendre d'une position en pixels qui aurait cessé d'être juste au premier
     changement de taille de titre. */
  -webkit-mask-image: radial-gradient(78% 70% at 42% 52%, transparent 0%, rgba(0, 0, 0, .28) 46%, #000 82%);
          mask-image: radial-gradient(78% 70% at 42% 52%, transparent 0%, rgba(0, 0, 0, .28) 46%, #000 82%);
}
.v-hero-fond svg {
  width: 100%;
  height: 100%;
  /* Le tracé se devine, il ne concurrence jamais le titre. */
  opacity: .16;
}
.v-hero-fond path {
  fill: none;
  stroke: #fff;
  stroke-width: 2.5;
  stroke-linecap: round;
}
.v-hero-fond circle { fill: #fff; }

.v-hero-texte {
  position: relative;
  max-width: 46rem;
  margin: 0 auto;
  width: 100%;
}

.v-surtitre {
  margin: 0 0 1.25rem;
  font-size: .82rem;
  font-weight: 600;
  letter-spacing: .09em;
  text-transform: uppercase;
  /* ⚠️ 0,78 d'opacité sur du blanc pur donne encore 7,4:1 sur le bleu de
     marque : au-dessus du seuil AA pour un texte de cette taille. En dessous
     de 0,7, ce surtitre passerait sous la barre — c'est mesuré, pas estimé. */
  color: rgba(255, 255, 255, .78);
}

.v-hero h1 {
  margin: 0 0 1.5rem;
  /* De 2,1 rem sur un téléphone à 4,2 rem sur un grand écran, sans palier :
     un titre qui saute d'une taille à l'autre à un seuil arbitraire se voit
     au redimensionnement. */
  font-size: clamp(2.1rem, 6.2vw, 4.2rem);
  line-height: 1.06;
  letter-spacing: -.025em;
  font-weight: 700;
  color: #fff;
  /* Inter a une taille optique variable : à ce corps, elle resserre les formes
     comme le ferait une fonte de titrage dessinée pour. */
  font-variation-settings: 'opsz' 40;
  text-wrap: balance;
}

.v-chapo {
  margin: 0 0 2.25rem;
  font-size: clamp(1.05rem, 2.1vw, 1.25rem);
  line-height: 1.62;
  color: rgba(255, 255, 255, .9);
  max-width: 40rem;
  text-wrap: pretty;
}

.v-actions {
  display: flex;
  flex-wrap: wrap;
  gap: .85rem;
  margin: 0;
}

/* ---------------------------------------------------------------------------
   BOUTONS
   ---------------------------------------------------------------------------
   ⚠️ 44 px de haut, y compris à la souris. C'est la règle du projet, et elle
   ne se relâche pas sur la page qui reçoit des inconnus : c'est celle qu'on
   ouvre le plus souvent sur un téléphone, dans un hall, une main occupée. */
.v-bouton {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding: .8rem 1.6rem;
  border: 1px solid transparent;
  border-radius: var(--rayon);
  font-size: 1rem;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  transition: transform .12s ease, background-color .16s ease, border-color .16s ease;
}
.v-bouton:active { transform: translateY(1px); }

.v-bouton-plein {
  background: #fff;
  color: var(--marque);
}
.v-bouton-plein:hover { background: rgba(255, 255, 255, .88); }

.v-bouton-creux {
  background: transparent;
  color: #fff;
  border-color: rgba(255, 255, 255, .45);
}
.v-bouton-creux:hover { border-color: #fff; background: rgba(255, 255, 255, .1); }

/* Le bouton d'envoi du formulaire n'est pas sur fond bleu : il reprend les
   jetons de bouton du site, qui savent déjà s'inverser en mode sombre. */
.v-formulaire .v-bouton-plein {
  background: var(--bouton-fond);
  color: var(--bouton-encre);
  align-self: flex-start;
}
.v-formulaire .v-bouton-plein:hover { background: var(--bouton-fond-survol); }

/* ---------------------------------------------------------------------------
   SECTIONS
   ------------------------------------------------------------------------ */
.v-section {
  max-width: 72rem;
  margin: 0 auto;
  padding: clamp(3.5rem, 8vw, 6.5rem) clamp(1rem, 4vw, 2rem);
}

/* ⚠️⚠️ DESCENDANT, ET NON ENFANT DIRECT (`>`). Écrite en `> h2`, cette règle a
   cessé de s'appliquer à la seconde où le titre de la section « Ce que nous ne
   faisons pas » est passé dans un conteneur : il est retombé à la taille par
   défaut, deux fois plus petit que les autres, et rien ne le signalait — un
   sélecteur qui ne trouve plus sa cible ne produit aucune erreur, seulement un
   écran qui a l'air négligé. Vu sur le rendu, pas à la relecture.
   ⚠️ Aucun risque de portée trop large : il n'existe qu'un `h2` par section, et
      celui du bloc de contact a sa propre règle, plus spécifique. */
.v-section h2 {
  margin: 0 0 .75rem;
  font-size: clamp(1.6rem, 3.6vw, 2.4rem);
  line-height: 1.15;
  letter-spacing: -.02em;
  color: var(--titre);
  text-wrap: balance;
}

.v-section-chapo {
  margin: 0 0 2.5rem;
  max-width: 44rem;
  color: var(--texte-doux);
  font-size: 1.05rem;
}

/* ---------------------------------------------------------------------------
   LES SECTIONS QUI PORTENT UN FOND
   ---------------------------------------------------------------------------
   ⚠️⚠️ DEUX DÉFAUTS D'ALIGNEMENT TROUVÉS EN MESURANT LA PAGE RENDUE, pas en
      relisant la feuille. La première écriture était :
          .v-section-sobre > * { max-width: 72rem; margin-inline: auto; }
      · `margin-inline: auto` NE S'APPLIQUAIT PAS au titre. `.v-section > h2`
        pose déjà `margin: 0 0 .75rem` et pèse (0,1,1) contre (0,1,0) : la
        règle la plus spécifique gagne, et le raccourci `margin` réécrit les
        quatre côtés. Le titre restait donc collé à gauche pendant que la liste
        en dessous, elle, se centrait — deux alignements différents dans une
        même section.
      · Et même corrigé, le contenu aurait commencé 32 px plus à gauche que
        celui des autres sections : celles-ci bornent à 72 rem PADDING COMPRIS
        (box-sizing: border-box), alors qu'une section pleine largeur applique
        son padding en DEHORS des 72 rem de son enfant.
   ⇒ Un conteneur nommé, qui porte à lui seul la largeur ET le padding — le
      même calcul que les sections ordinaires, donc le même bord gauche. */
.v-section-sobre,
.v-contact {
  max-width: none;
  padding-inline: 0;
}
.v-section-interieur,
.v-contact-grille {
  max-width: 72rem;
  margin-inline: auto;
  padding-inline: clamp(1rem, 4vw, 2rem);
}
.v-section-sobre { background: var(--fond-doux); }

/* ---------------------------------------------------------------------------
   OÙ NOUS SOMMES INTERVENUS
   ---------------------------------------------------------------------------
   ⭐ SOBRE, ET C'EST VOULU. Ces noms n'ont pas besoin d'être décorés : ce sont
   eux, l'argument. Des cadres colorés ou des effets de survol les feraient
   passer pour un bandeau publicitaire, alors qu'ils doivent se lire comme un
   constat. La section est plus resserrée que les autres — elle se traverse,
   elle ne se médite pas.
   ------------------------------------------------------------------------ */
.v-references {
  padding-block: clamp(2.5rem, 5vw, 3.5rem);
}
.v-references h2 {
  /* Plus discret que les autres titres de section : c'est une étiquette posée
     au-dessus des noms, pas une promesse de plus. */
  font-size: clamp(1rem, 1.6vw, 1.1rem) !important;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--texte-doux) !important;
  margin-bottom: 1.5rem !important;
}

.v-refs {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 1.5rem clamp(1.5rem, 3vw, 2.5rem);
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  align-items: start;
}
.v-refs h3 {
  margin: 0 0 .35rem;
  font-size: 1.12rem;
  line-height: 1.3;
  letter-spacing: -.01em;
  color: var(--titre);
  text-wrap: balance;
}
.v-refs p {
  margin: 0;
  font-size: .92rem;
  line-height: 1.65;
  color: var(--texte-doux);
}
/* ⚠️ Le trait sépare sans encadrer. Un cadre autour de chaque nom donnerait
   une grille de vignettes — exactement le bandeau de logos qu'on a choisi de
   ne pas faire. */
.v-refs li { border-top: 1px solid var(--bord); padding-top: 1rem; }

/* ---------------------------------------------------------------------------
   LE CONSTAT
   ------------------------------------------------------------------------ */
.v-constats {
  list-style: none;
  margin: 2.5rem 0 0;
  padding: 0;
  display: grid;
  gap: clamp(1.5rem, 3vw, 2.5rem);
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
}
.v-constats li {
  /* Le filet d'accent porte le regard sans encadrer : trois boîtes à bordure
     grise, c'est exactement l'interface « qui fait 2015 » qu'on ne veut pas. */
  border-top: 3px solid var(--accent);
  padding-top: 1.25rem;
}
.v-constats h3 {
  margin: 0 0 .6rem;
  font-size: 1.12rem;
  line-height: 1.35;
  color: var(--titre);
}
.v-constats p { margin: 0; color: var(--texte-doux); }

/* ---------------------------------------------------------------------------
   LES TROIS MODES D'INTERVENTION
   ------------------------------------------------------------------------ */
.v-cartes {
  display: grid;
  gap: clamp(1.25rem, 2.5vw, 1.75rem);
  grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr));
}

.v-carte {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: clamp(1.5rem, 3vw, 2rem);
  border: 1px solid var(--bord);
  border-radius: calc(var(--rayon) * 2);
  background: var(--fond);
  box-shadow: var(--ombre);
  transition: box-shadow .2s ease, transform .2s ease, border-color .2s ease;
}
/* ⚠️ LE SURVOL NE FAIT PAS BOUGER LA GRILLE : seule la carte se soulève, d'un
   pixel, sur sa propre couche. Une carte qui grandit pousse ses voisines et
   fait sauter tout le bloc — le défaut relevé sur les tuiles de l'accueil. */
.v-carte:hover {
  transform: translateY(-2px);
  border-color: var(--accent);
  box-shadow: var(--ombre-relief);
}

.v-carte-numero {
  font-size: .8rem;
  font-weight: 700;
  letter-spacing: .12em;
  color: var(--accent);
  /* Les chiffres tabulaires : « 01 » et « 03 » occupent la même largeur, donc
     les trois cartes s'alignent exactement. */
  font-variant-numeric: tabular-nums;
}

.v-carte h3 {
  margin: .5rem 0 1rem;
  font-size: 1.28rem;
  line-height: 1.28;
  letter-spacing: -.012em;
  color: var(--titre);
  text-wrap: balance;
}
.v-carte p { margin: 0 0 .9rem; color: var(--texte-doux); }
.v-carte strong { color: var(--texte); }

.v-carte-pour {
  /* Poussée en bas de la carte : les trois mentions s'alignent quelle que soit
     la longueur des paragraphes au-dessus. */
  margin-top: auto !important;
  padding-top: 1rem;
  border-top: 1px solid var(--bord);
  font-size: .88rem;
  color: var(--texte-doux) !important;
}

/* ---------------------------------------------------------------------------
   LA MÉTHODE
   ---------------------------------------------------------------------------
   ⭐ C'est une <ol> : l'ordre est porté par le HTML, donc annoncé à qui écoute
   la page. Des chiffres écrits à la main dans le texte seraient muets. */
.v-etapes {
  list-style: none;
  counter-reset: etape;
  margin: 2.5rem 0 0;
  padding: 0;
  display: grid;
  gap: 0;
}
.v-etapes li {
  counter-increment: etape;
  position: relative;
  padding: 0 0 2.25rem 4.25rem;
}
.v-etapes li::before {
  content: counter(etape, decimal-leading-zero);
  position: absolute;
  left: 0;
  top: 0;
  width: 2.75rem;
  height: 2.75rem;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--accent);
  color: var(--fond);
  font-weight: 700;
  font-size: .95rem;
  font-variant-numeric: tabular-nums;
}
/* Le trait qui relie les étapes — il s'arrête à la dernière, sinon il pend
   dans le vide sous elle. */
.v-etapes li:not(:last-child)::after {
  content: '';
  position: absolute;
  left: 1.32rem;
  top: 3.1rem;
  bottom: .6rem;
  width: 2px;
  background: var(--bord);
}
.v-etapes li:last-child { padding-bottom: 0; }
.v-etapes h3 {
  margin: .4rem 0 .5rem;
  font-size: 1.15rem;
  line-height: 1.3;
  color: var(--titre);
}
.v-etapes p { margin: 0; color: var(--texte-doux); max-width: 46rem; }

/* ---------------------------------------------------------------------------
   LES LIMITES
   ------------------------------------------------------------------------ */
.v-limites {
  list-style: none;
  margin: 2.5rem 0 0;
  padding: 0;
  display: grid;
  gap: 1.25rem;
  grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr));
}
.v-limites li {
  padding: 1.25rem 1.4rem;
  border-radius: calc(var(--rayon) * 1.5);
  background: var(--fond);
  border: 1px solid var(--bord);
  color: var(--texte-doux);
}
.v-limites strong { display: block; margin-bottom: .4rem; color: var(--titre); }

/* ---------------------------------------------------------------------------
   CONTACT
   ------------------------------------------------------------------------ */
.v-contact { background: var(--fond-doux); }

.v-contact-grille {
  display: grid;
  gap: clamp(2rem, 5vw, 4rem);
  /* Le mot d'accueil à gauche, le formulaire à droite — mais seulement quand
     il y a la place pour les deux sans serrer les champs. */
  grid-template-columns: minmax(0, 1fr);
}
@media (min-width: 62rem) {
  .v-contact-grille { grid-template-columns: 22rem minmax(0, 1fr); align-items: start; }
}

.v-contact-mot h2 {
  margin: 0 0 1rem;
  font-size: clamp(1.6rem, 3.6vw, 2.2rem);
  line-height: 1.15;
  letter-spacing: -.02em;
  color: var(--titre);
}
.v-contact-mot p { color: var(--texte-doux); }

.v-contact-tel a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: clamp(1.35rem, 3.2vw, 1.75rem);
  font-weight: 700;
  letter-spacing: .01em;
  color: var(--accent);
  text-decoration: none;
  font-variant-numeric: tabular-nums;
}
.v-contact-tel a:hover { text-decoration: underline; }
.v-contact-note { font-size: .92rem; }

/* ---------------------------------------------------------------------------
   FORMULAIRE
   ------------------------------------------------------------------------ */
.v-formulaire {
  display: flex;
  flex-direction: column;
  gap: 1.15rem;
  padding: clamp(1.5rem, 3.5vw, 2.25rem);
  border: 1px solid var(--bord);
  border-radius: calc(var(--rayon) * 2);
  background: var(--fond);
  box-shadow: var(--ombre);
}

.v-champ { display: flex; flex-direction: column; gap: .4rem; }
.v-champ label {
  font-size: .93rem;
  font-weight: 600;
  color: var(--titre);
}
.v-requis { color: var(--erreur); }

.v-champ input,
.v-champ textarea {
  /* ⚠️⚠️ 16 px EXACTEMENT, ET PAS EN rem RÉDUITS. En dessous de 16 px, iOS
     zoome automatiquement sur le champ dès qu'on le touche, et la page reste
     zoomée ensuite. C'est un comportement du système, non négociable. */
  font: 16px/1.5 'InterVariable', system-ui, sans-serif;
  color: var(--texte);
  background: var(--fond);
  /* La bordure d'un champ est le SEUL indicateur de l'endroit où l'on peut
     écrire : c'est un composant d'interface au sens de WCAG 1.4.11, qui exige
     3:1. D'où `--bord-champ` (3,21:1) et non `--bord` (1,34:1). */
  border: 1px solid var(--bord-champ);
  border-radius: var(--rayon);
  padding: .7rem .85rem;
  min-height: 48px;
  width: 100%;
}
.v-champ textarea { min-height: 8rem; resize: vertical; }

.v-champ input:focus-visible,
.v-champ textarea:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
  border-color: var(--accent);
}

.v-champ-double {
  display: grid;
  gap: 1.15rem;
  grid-template-columns: minmax(0, 1fr);
}
@media (min-width: 34rem) {
  .v-champ-double { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.v-aide {
  margin: 0;
  font-size: .87rem;
  color: var(--texte-doux);
}

/* ⚠️ LE MESSAGE D'ERREUR NE PASSE PAS QUE PAR LA COULEUR. Le rouge seul est
   invisible pour une partie des daltoniens et ne se prononce pas du tout — le
   champ porte donc aussi `aria-invalid`, et la phrase dit ce qui ne va pas
   plutôt que « champ invalide ». WCAG 1.4.1 : la couleur ne peut être le seul
   véhicule d'une information. */
.v-erreur {
  margin: 0;
  font-size: .88rem;
  font-weight: 500;
  color: var(--erreur-texte);
}
.v-champ:has(.v-erreur) input,
.v-champ:has(.v-erreur) textarea {
  border-color: var(--erreur);
}

.v-mentions-form {
  margin: 0;
  font-size: .85rem;
  line-height: 1.5;
  color: var(--texte-doux);
}

/* ⚠️⚠️ LE PIÈGE À ROBOTS — masqué à l'ŒIL, présent pour le PROGRAMME.
   Ni `display:none` ni `type="hidden"` : les robots à formulaires ignorent le
   premier et ne remplissent pas le second. Ce qu'ils remplissent, c'est un
   champ texte ordinaire qu'ils trouvent dans le HTML. Il est donc sorti de la
   vue par la position, pas retiré du document.
   ⚠️ `aria-hidden` et `tabindex="-1"` sont posés dans le gabarit : sans eux,
      c'est la personne qui navigue au clavier ou à la voix qui tomberait dans
      le piège tendu aux machines. */
.v-piege {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* ---------------------------------------------------------------------------
   PIED
   ------------------------------------------------------------------------ */
.v-pied {
  border-top: 1px solid var(--bord);
  background: var(--fond);
  padding: 2.5rem clamp(1rem, 4vw, 2rem);
}
.v-pied-interieur {
  max-width: 72rem;
  margin: 0 auto;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}
.v-pied-marque { margin: 0; font-weight: 700; color: var(--titre); }
.v-pied-liens { display: flex; flex-wrap: wrap; gap: .25rem 1rem; }
.v-pied-liens a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--texte-doux);
  font-size: .92rem;
}

.v-messages {
  max-width: 72rem;
  margin: 1.5rem auto 0;
  padding: 0 clamp(1rem, 4vw, 2rem);
}

/* ---------------------------------------------------------------------------
   APPARITION AU DÉFILEMENT
   ---------------------------------------------------------------------------
   ⭐ EN CSS SEUL, par `animation-timeline: view()` — aucun observateur
   d'intersection, aucun script, donc rien à charger ni à faire tourner.

   ⚠️⚠️ SOUS `@supports`, ET C'EST INDISPENSABLE. Un navigateur qui ne connaît
      pas les animations liées au défilement ignore `animation-timeline` mais
      applique quand même `opacity: 0` — le contenu resterait invisible pour
      toujours. La règle entière est donc conditionnée au support de la
      propriété qui la rend réversible.

   ⚠️ `prefers-reduced-motion` : chez qui a demandé moins d'animation, rien ne
      bouge et rien n'est masqué. Le mouvement est un ornement ; le texte, non. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .v-constats li,
    .v-carte,
    .v-etapes li,
    .v-limites li {
      animation: v-apparait linear both;
      animation-timeline: view();
      animation-range: entry 5% cover 22%;
    }
  }
}
@keyframes v-apparait {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}
