/* =====================================================================
   Webfaya — page d'accueil, charte 2026
   Construite à partir de css/tokens.css. Aucune couleur, aucune durée,
   aucun espacement n'est écrit en dur ici : tout passe par les jetons.

   Règles de la charte tenues dans ce fichier :
   — aucune ombre portée, nulle part ;
   — border-radius 0 sur les blocs, 999px sur les actions et étiquettes ;
   — aucun dégradé, aplats uniquement ;
   — titres en bas de casse, letter-spacing -.04em, line-height .88 ;
   — aucune animation au-delà de 600 ms ;
   — tout est coupé sous prefers-reduced-motion, bandeaux compris.
   ===================================================================== */

*, *::before, *::after { box-sizing: border-box; }

/* Pas d'overflow-x: hidden sur body : il en fait un conteneur de
   defilement, et `animation-timeline: scroll(root)` ne resout alors plus
   (timeline inactive, barre de progression figee). Le debordement
   horizontal est deja nul a 375, 768 et 1440px — cette securite coutait
   plus qu'elle ne rapportait. Les bandeaux defilants sont contenus par
   leur propre `overflow: hidden`. */

img { max-width: 100%; }

.wf-contenu {
  max-width: var(--wf-contenu-max);
  margin-inline: auto;
}

.wf-section {
  padding: var(--wf-section-y) var(--wf-section-x);
  /* `clip` et non `hidden` : `hidden` ferait de la section un conteneur
     de defilement et casserait les timelines de scroll. `clip` decoupe
     sans rien rendre defilable. Necessaire parce que les grands titres
     debordent pendant leur voyage. */
  overflow-x: clip;
}

/* Le numéro de section, en tête de chaque bloc. */
.wf-num {
  font-family: var(--wf-font-mono);
  font-size: var(--wf-t-mono);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--wf-encre-2);
}

/* L'italique d'accent. Une seule occurrence par écran : la charte
   l'impose, et c'est ce qui lui garde sa force. */
.wf-italique {
  font-family: var(--wf-font-accent);
  font-weight: 300;
  font-style: italic;
  letter-spacing: -.01em;
}

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.wf-saut {
  position: absolute;
  left: -9999px;
  z-index: 100;
  padding: 12px 18px;
  background: var(--wf-jungle);
  color: var(--wf-coco);
  border-radius: var(--wf-r-action);
}
.wf-saut:focus { left: var(--wf-section-x); top: 12px; }

/* =====================================================================
   En-tête
   Seul endroit du site où un fond flouté est autorisé.
   ===================================================================== */
.wf-entete {
  position: sticky;
  top: 0;
  z-index: 60;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 14px var(--wf-section-x);
  border-bottom: 1px solid rgba(18, 34, 26, .16);
}
/* Le fond flou est sur un pseudo-element, pas sur l'en-tete lui-meme :
   `backdrop-filter` fait de son element un bloc conteneur pour les
   descendants en `position: fixed`. Porte par .wf-entete, il reduisait le
   volet mobile — pourtant en `inset: 0` — a la hauteur de l'en-tete.
   Le pseudo-element n'a pas de descendant, le piege disparait. */
.wf-entete::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: rgba(250, 244, 232, .92);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}

.wf-logo {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--wf-jungle);
}
.wf-logo:hover { color: var(--wf-jungle); }
/* La braise du logotype vacille : c'est la seule animation permanente
   de l'en-tête. Elle vit à côté du mot, jamais dedans. */
.wf-braise-logo {
  width: 13px;
  height: 13px;
  background: var(--wf-braise);
  border-radius: 3px;
  animation: wf-flicker 2.6s steps(1, end) infinite;
}
.wf-mot {
  font-family: var(--wf-font-titre);
  font-weight: 800;
  font-size: 24px;
  letter-spacing: var(--wf-titre-tracking);
  text-transform: none;
}

.wf-nav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: clamp(12px, 2vw, 26px);
  font-family: var(--wf-font-mono);
  font-size: var(--wf-t-mono);
  letter-spacing: .06em;
  text-transform: uppercase;
}
/* :not() sur le bouton, sinon cette regle (0-1-1) ecrase la couleur de
   .wf-action-nav (0-1-0) et le texte du CTA tombe a 2,1:1 sur l'encre. */
.wf-nav a:not(.wf-action-nav) { color: var(--wf-encre-2); transition: color var(--wf-d-survol) var(--wf-c-entree); }
.wf-nav a:not(.wf-action-nav):hover { color: var(--wf-jungle); }

.wf-action {
  display: inline-block;
  border-radius: var(--wf-r-action);
  font-family: var(--wf-font-texte);
  letter-spacing: 0;
  text-transform: none;
  transition: background-color var(--wf-d-survol) var(--wf-c-entree),
              color var(--wf-d-survol) var(--wf-c-entree),
              border-color var(--wf-d-survol) var(--wf-c-entree);
}
.wf-action-nav {
  padding: 11px 16px;
  background: var(--wf-jungle);
  color: var(--wf-coco);
  font-size: 13px;
  font-weight: 600;
}
.wf-action-nav:hover { background: var(--wf-braise-foncee); color: var(--wf-coco); }

/* Menu mobile : volet plein écran depuis le haut. */
.wf-burger {
  display: none;
  padding: 10px 14px;
  background: none;
  border: 1px solid rgba(18, 34, 26, .3);
  border-radius: var(--wf-r-action);
  color: var(--wf-jungle);
  font-family: var(--wf-font-mono);
  font-size: var(--wf-t-mono);
  letter-spacing: .06em;
  text-transform: uppercase;
  cursor: pointer;
}

/* =====================================================================
   Hero
   ===================================================================== */
.wf-hero { padding: clamp(36px, 6vw, 88px) var(--wf-section-x) 0; }

.wf-annonce {
  display: flex;
  align-items: center;
  gap: 14px;
  font-family: var(--wf-font-mono);
  font-size: var(--wf-t-mono);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--wf-braise-foncee);
}
.wf-annonce-filet {
  flex: 1;
  height: 1px;
  background: rgba(181, 48, 11, .35);
}
.wf-annonce-fin { color: var(--wf-encre-2); }

.wf-hero-grille {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
  gap: clamp(20px, 3vw, 48px);
  align-items: center;
  margin-top: clamp(18px, 3vw, 32px);
}

.wf-h1 {
  font-size: var(--wf-t-hero);
  line-height: .86;
  letter-spacing: -.045em;
}
.wf-h1 span { display: block; }
.wf-h1 .wf-italique { font-size: .82em; color: var(--wf-braise-foncee); }

.wf-hero-texte {
  margin: clamp(20px, 3vw, 30px) 0 0;
  max-width: 44ch;
  font-size: var(--wf-t-texte);
  line-height: var(--wf-texte-leading);
  color: rgba(18, 34, 26, .82);
  text-wrap: pretty;
}

.wf-boutons {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 26px;
}
.wf-btn-plein,
.wf-btn-ligne {
  padding: 15px 24px;
  border-radius: var(--wf-r-action);
  font-size: 15px;
  transition: background-color var(--wf-d-survol) var(--wf-c-entree),
              color var(--wf-d-survol) var(--wf-c-entree),
              border-color var(--wf-d-survol) var(--wf-c-entree);
}
.wf-btn-plein {
  background: var(--wf-jungle);
  color: var(--wf-coco);
  font-weight: 600;
}
.wf-btn-plein:hover { background: var(--wf-braise-foncee); color: var(--wf-coco); }
.wf-btn-ligne {
  border: 1px solid rgba(18, 34, 26, .3);
  color: var(--wf-jungle);
  font-weight: 500;
}
.wf-btn-ligne:hover { border-color: var(--wf-braise-foncee); color: var(--wf-braise-foncee); }

.wf-mascotte { display: grid; place-items: center; }
.wf-mascotte img {
  display: block;
  width: min(100%, 420px);
  height: auto;
  /* La charte l'exige : jamais déformée. */
  object-fit: contain;
  animation: wf-float 4.5s ease-in-out infinite;
}

/* Le reveil du hero : la pose endormie se dissout sur la pose eveillee,
   echo au titre « les sites qui dorment ». Les deux images sont recadrees
   sur une bbox commune, donc superposees au pixel pres.
   Selecteurs en `.wf-mascotte.wf-eveil img` (0-2-1) : `.wf-mascotte img`
   (0-1-1) gagnerait sinon, et le flottement resterait sur chaque image au
   lieu de passer au conteneur — les deux poses se desynchroniseraient. */
.wf-mascotte.wf-eveil { animation: wf-float 4.5s ease-in-out infinite; }
.wf-mascotte.wf-eveil > picture { grid-area: 1 / 1; display: block; }
.wf-mascotte.wf-eveil img { animation: none; }
.wf-mascotte.wf-eveil .wf-eveil-endormi {
  animation: wf-wake 9s ease-in-out infinite;
}

/* Barre de chargement du formulaire : 34 % de large, 1,4 s.
   La charte interdit le spinner rond et le pourcentage. */
.wf-form-barre {
  display: none;
  overflow: hidden;
  width: min(100%, 260px);
  height: 3px;
  margin-top: 14px;
  background: rgba(250, 244, 232, .22);
}
.wf-form-envoi[disabled] { opacity: .6; cursor: progress; }
form[data-etat="envoi"] .wf-form-barre { display: block; }
.wf-form-barre i {
  display: block;
  width: 34%;
  height: 100%;
  background: var(--wf-ambre);
  animation: wf-loader 1.4s ease-in-out infinite;
}

/* Les quatre visuels sous le hero. La maquette prévoyait des trames
   d'attente ; la charte interdit de les livrer. On y met les captures
   réelles des sites en ligne, au format 3/4 demandé. */
.wf-vitrine {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 190px), 1fr));
  gap: 10px;
  margin-top: clamp(28px, 4vw, 52px);
}
.wf-vitrine figure {
  position: relative;
  margin: 0;
  aspect-ratio: 3 / 4;
  overflow: hidden;
  background: var(--wf-jungle);
  border-radius: var(--wf-r-bloc);
}
.wf-vitrine figure:nth-child(2n) { margin-top: clamp(0px, 3vw, 30px); }
.wf-vitrine img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
  display: block;
}
.wf-vitrine figcaption {
  position: absolute;
  inset: auto 0 0 0;
  padding: 14px;
  background: var(--wf-jungle);
  font-family: var(--wf-font-mono);
  font-size: 9px;
  line-height: 1.6;
  text-transform: uppercase;
  color: rgba(250, 244, 232, .82);
}

/* =====================================================================
   Bandeaux défilants
   Un seul par page selon la charte. Le second, celui des clients, vit
   dans la même page : la charte l'autorise explicitement (30 s services,
   48 s clients) — voir README, section Interactions.
   ===================================================================== */
.wf-bandeau {
  overflow: hidden;
  padding: 13px 0;
  font-family: var(--wf-font-titre);
  font-weight: 800;
  letter-spacing: -.03em;
}
.wf-bandeau-braise {
  background: var(--wf-braise);
  color: var(--wf-jungle);
  margin-top: clamp(32px, 5vw, 72px);
  /* 19px et non 18 : l'encre sur la braise donne 3,36:1. En dessous de
     18,66px en gras, WCAG exige 4,5:1 ; au-dessus, 3:1 suffit. Un pixel
     de plus, invisible a l'oeil, et le bandeau est conforme partout. */
  font-size: clamp(19px, 2.4vw, 26px);
}
.wf-bandeau-jungle {
  background: var(--wf-jungle);
  color: var(--wf-coco);
  font-size: clamp(16px, 2vw, 22px);
}
/* Durees de repli, utilisees si le script ne tourne pas. Avec lui, la
   duree est recalculee a partir de la largeur pour une vitesse constante
   de 55 px/s sur toutes les pages.
   Les deux autres bandeaux de la charte. Le README en nomme quatre, avec
   une duree chacun : services 30 s, manifeste 42 s, chiffres 36 s,
   clients 48 s. Les deux premiers existaient seuls. */
.wf-bandeau-coco {
  background: var(--wf-coco);
  color: var(--wf-jungle);
  border-top: 1px solid rgba(18, 34, 26, .16);
  border-bottom: 1px solid rgba(18, 34, 26, .16);
  font-size: clamp(16px, 2vw, 22px);
}
.wf-bandeau-ambre {
  background: var(--wf-ambre);
  color: var(--wf-jungle);
  font-size: clamp(16px, 2vw, 22px);
}

.wf-piste {
  display: flex;
  width: max-content;
}
.wf-bandeau-braise .wf-piste { animation: wf-marquee 90s linear infinite; }
.wf-bandeau-coco   .wf-piste { animation: wf-marquee 92s linear infinite; }
.wf-bandeau-ambre  .wf-piste { animation: wf-marquee-rev 85s linear infinite; }
.wf-bandeau-jungle .wf-piste { animation: wf-marquee-rev 60s linear infinite; }
.wf-piste > div {
  display: flex;
  align-items: center;
  gap: 22px;
  padding-right: 22px;
  white-space: nowrap;
}
/* La charte pose `opacity: .55` sur les separateurs. Une fois l'opacite
   reellement composee, le losange tombe entre 2,1:1 et 3,2:1 selon le
   fond — sous le seuil a 16 px. On garde le retrait visuel en jouant sur
   la couleur plutot que sur l'opacite, qui, elle, passe a 1.
   Meme logique que le 19 px du bandeau braise : un ecart minime a la
   charte, documente, plutot qu'un texte illisible. */
.wf-losange { opacity: 1; }
.wf-bandeau-jungle .wf-losange { color: var(--wf-ambre); }
/* Sur la braise, l'encre jungle donne 3,36:1 — conforme a 19 px en gras
   (seuil 3), taille plancher de ce bandeau. */
.wf-bandeau-braise .wf-losange { color: var(--wf-jungle); }
/* Sur le coco, la braise a 55 % d'opacite tombe sous 4,5:1 des que la
   taille descend a 16 px (mobile). Braise foncee, pleine opacite :
   5,65:1, conforme a toutes les tailles. */
.wf-bandeau-coco .wf-losange { color: var(--wf-braise-foncee); opacity: 1; }
/* Sur l'ambre, la braise tombe a 1,9:1 : le losange reste en jungle,
   a pleine opacite (7,4:1). */
.wf-bandeau-ambre .wf-losange { color: var(--wf-jungle); }
.wf-piste img { display: block; height: 34px; width: auto; }

/* =====================================================================
   01 — Le studio
   ===================================================================== */
.wf-studio-grille {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr));
  gap: clamp(24px, 4vw, 64px);
}
.wf-h2 {
  margin-top: 16px;
  font-size: var(--wf-t-section);
  line-height: .9;
}
.wf-studio-col {
  display: flex;
  flex-direction: column;
  gap: 20px;
  align-self: center;
}
/* Enfants directs uniquement : sinon cette regle gagne (0-1-1) sur
   .wf-chiffre-val (0-1-0) et ecrase la taille des chiffres. */
.wf-studio-col > p {
  margin: 0;
  font-size: var(--wf-t-texte);
  line-height: 1.6;
  color: rgba(18, 34, 26, .82);
  text-wrap: pretty;
}
.wf-chiffres {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  gap: 16px;
  padding-top: 22px;
  border-top: 1px solid rgba(18, 34, 26, .18);
}
.wf-chiffre-val {
  font-family: var(--wf-font-titre);
  font-weight: 800;
  font-size: clamp(32px, 3.6vw, 48px);
  line-height: .9;
  letter-spacing: -.045em;
  color: var(--wf-braise-foncee);
}
.wf-chiffre-lib {
  font-family: var(--wf-font-mono);
  font-size: 9px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--wf-encre-2);
  margin-top: 6px;
}

/* =====================================================================
   02 — Offres (fond jungle)
   ===================================================================== */
.wf-jungle {
  background: var(--wf-jungle);
  color: var(--wf-coco);
}
.wf-jungle .wf-num { color: var(--wf-ambre); }

.wf-tete-offres {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 20px;
}
.wf-tete-offres p {
  margin: 0;
  max-width: 32ch;
  font-size: 15px;
  line-height: var(--wf-texte-leading);
  color: rgba(250, 244, 232, .85);
}

.wf-offres {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr));
  gap: 12px;
  margin-top: clamp(28px, 4vw, 52px);
}
/* Ligne de maintenance sous la grille : une quatrieme carte casserait
   le titre « Trois facons de mettre le feu », et l'abonnement n'est pas
   une prestation de meme nature que les trois autres. */
/* Lien de fin de carte. `margin-top: auto` le colle en bas : les trois
   cartes n'ont pas le meme nombre de puces, les liens doivent malgre tout
   s'aligner. Ambre et non braise : sur le jungle, la braise tombe a
   3,1:1 pour un texte de 11 px. */
.wf-offre-lien {
  margin-top: auto;
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--wf-font-mono);
  font-size: 11px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--wf-ambre);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  padding-bottom: 2px;
  transition: border-color var(--wf-d-survol) var(--wf-c-entree);
}
.wf-offre-lien:hover,
.wf-offre-lien:focus-visible { border-bottom-color: var(--wf-ambre); }

.wf-offre-suite {
  margin: 14px 0 0;
  padding: clamp(16px, 2vw, 22px) clamp(20px, 2.4vw, 30px);
  /* Couleurs du fond clair par defaut : ce bloc sert sous les offres
     (fond jungle) ET sous les travaux (fond coco). Ecrit en coco d'abord,
     il devenait invisible sur le coco. */
  border: 1px solid rgba(18, 34, 26, .22);
  border-radius: var(--wf-r-bloc);
  font-size: 14px;
  line-height: 1.6;
  color: var(--wf-encre-2);
}
.wf-offre-suite strong { color: var(--wf-jungle); font-weight: 600; }
.wf-offre-suite a { color: var(--wf-braise-foncee); }

.wf-jungle .wf-offre-suite {
  border-color: rgba(250, 244, 232, .22);
  color: rgba(250, 244, 232, .82);
}
.wf-jungle .wf-offre-suite strong { color: var(--wf-coco); }
.wf-jungle .wf-offre-suite a { color: var(--wf-braise-claire); }

/* Sous les travaux, le bloc suit la grille et non les cartes. */
.wf-travaux-renvoi { margin-top: clamp(20px, 3vw, 30px); }

.wf-offre {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: clamp(20px, 2.4vw, 30px);
  border: 1px solid rgba(250, 244, 232, .22);
  border-radius: var(--wf-r-bloc);
  transition: border-color var(--wf-d-survol) var(--wf-c-entree),
              background-color var(--wf-d-survol) var(--wf-c-entree);
}
.wf-offre:hover,
.wf-offre:focus-within {
  border-color: var(--wf-braise-claire);
  background: rgba(250, 244, 232, .04);
}
.wf-offre-tete {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-family: var(--wf-font-mono);
  font-size: var(--wf-t-mono);
  letter-spacing: .06em;
  text-transform: uppercase;
}
.wf-offre-num { color: rgba(250, 244, 232, .7); }
.wf-offre-prix { color: var(--wf-ambre); }
/* Objet 3D de la collection, en tete de carte.
   Le rendu porte ses propres ombres et degrades : c'est le seul endroit
   du site ou l'on sorte de la regle « aplats uniquement ». Il reste
   contenu dans l'illustration, jamais applique a un bloc. */
.wf-objet {
  width: clamp(88px, 9vw, 128px);
  height: auto;
  display: block;
  margin-bottom: 2px;
  transition: transform var(--wf-d-survol) var(--wf-c-entree);
}
.wf-offre:hover .wf-objet,
.wf-offre:focus-within .wf-objet { transform: rotate(-4deg); }

.wf-offre h3 {
  font-size: var(--wf-t-bloc);
  line-height: .94;
}
.wf-offre > p:not(.wf-offre-tete) {
  margin: 0;
  font-size: 15px;
  line-height: var(--wf-texte-leading);
  color: rgba(250, 244, 232, .85);
  text-wrap: pretty;
}
.wf-offre ul {
  margin: auto 0 0;
  padding: 16px 0 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 8px;
  border-top: 1px solid rgba(250, 244, 232, .18);
}
.wf-offre li {
  display: flex;
  gap: 10px;
  font-size: 14px;
  color: rgba(250, 244, 232, .85);
}
.wf-fleche { color: var(--wf-braise-claire); }

/* =====================================================================
   03 — Travaux
   ===================================================================== */
/* En-tete de la section Travaux. Elle remplace .wf-epingle-titre, retire
   avec le defilement horizontal : la charte decrit une grille de quatre
   cartes, pas un panneau epingle. */
.wf-tete-travaux { margin-bottom: clamp(26px, 4vw, 48px); }
.wf-tete-travaux .wf-h2 { margin-bottom: 0; }

.wf-travaux {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 290px), 1fr));
  gap: 12px;
}
.wf-projet {
  display: flex;
  flex-direction: column;
  border: 1px solid rgba(18, 34, 26, .2);
  border-radius: var(--wf-r-bloc);
  overflow: hidden;
  transition: border-color var(--wf-d-survol) var(--wf-c-entree);
}
.wf-projet:hover,
.wf-projet:focus-within { border-color: var(--wf-braise-foncee); }
.wf-projet-image {
  aspect-ratio: 4 / 3;
  background: var(--wf-jungle);
  overflow: hidden;
}
.wf-projet-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
  display: block;
}
.wf-projet-corps {
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  flex: 1;
}
.wf-projet-ligne {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}
.wf-projet h3 {
  font-size: 24px;
  letter-spacing: -.035em;
  line-height: 1;
}
.wf-projet-annee {
  font-family: var(--wf-font-mono);
  font-size: var(--wf-t-mono);
  color: var(--wf-encre-2);
}
.wf-projet-resume {
  margin: 0;
  font-size: 14px;
  line-height: 1.5;
  color: rgba(18, 34, 26, .82);
}
.wf-projet-tags {
  margin-top: auto;
  font-family: var(--wf-font-mono);
  font-size: 9px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--wf-braise-foncee);
}
.wf-projet-lien {
  display: inline-block;
  font-family: var(--wf-font-mono);
  font-size: 9px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--wf-braise-foncee);
}
/* Soulignement qui se déploie depuis la gauche, jamais d'agrandissement. */
.wf-projet-lien::after {
  content: "";
  display: block;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 180ms var(--wf-c-entree);
}
.wf-projet-lien:hover::after,
.wf-projet-lien:focus-visible::after { transform: scaleX(1); }

/* =====================================================================
   04 — Méthode
   ===================================================================== */
.wf-methode-grille {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
  gap: clamp(24px, 4vw, 56px);
}
.wf-methode-intro {
  margin: 18px 0 0;
  max-width: 36ch;
  font-size: 16px;
  line-height: 1.6;
  color: rgba(18, 34, 26, .82);
}
.wf-etapes { display: flex; flex-direction: column; }
.wf-etape {
  display: grid;
  grid-template-columns: 52px 1fr;
  gap: 16px;
  padding: 20px 0;
  border-top: 1px solid rgba(18, 34, 26, .18);
}
.wf-etape-num {
  font-family: var(--wf-font-mono);
  font-size: 12px;
  color: var(--wf-braise-foncee);
}
/* Les tetes de la collection 3D, posees dans les titres.
   Une expression = un message : le kit donne un contexte a chacune, on
   s'y tient. Alignees sur la ligne de base du texte, jamais deformees. */
.wf-tete {
  display: inline-flex;
  vertical-align: -.18em;
  margin-right: 10px;
}
.wf-tete-img {
  width: 1.15em;
  height: auto;
  object-fit: contain;
}
.wf-tete-titre {
  display: inline-flex;
  vertical-align: -.1em;
  margin-left: 14px;
}
.wf-tete-titre .wf-tete-img { width: .72em; }
/* Dans le bandeau : meme hauteur que les autres occurrences de la mascotte. */
.wf-piste img { display: block; height: 34px; width: auto; }

.wf-etape h3 {
  font-weight: 700;
  font-size: clamp(20px, 2.2vw, 26px);
  letter-spacing: -.03em;
  margin-bottom: 6px;
  line-height: 1;
}
.wf-etape p {
  margin: 0;
  font-size: 15px;
  line-height: var(--wf-texte-leading);
  color: rgba(18, 34, 26, .82);
}

/* =====================================================================
   05 — Questions (fond ambre)
   ===================================================================== */
.wf-ambre {
  background: var(--wf-ambre);
  color: var(--wf-jungle);
}
.wf-ambre .wf-num { color: var(--wf-jungle); }
.wf-faq-contenu { max-width: 1000px; margin-inline: auto; }
.wf-faq { border-top: 1px solid rgba(18, 34, 26, .28); }
.wf-question { border-bottom: 1px solid rgba(18, 34, 26, .28); }
.wf-question > summary {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 20px 2px;
  font-family: var(--wf-font-titre);
  font-weight: 700;
  font-size: clamp(18px, 2.2vw, 26px);
  letter-spacing: -.03em;
  line-height: 1.1;
  cursor: pointer;
  list-style: none;
}
.wf-question > summary::-webkit-details-marker { display: none; }
.wf-signe {
  flex: none;
  width: 32px; height: 32px;
  display: grid;
  place-items: center;
  border: 1px solid rgba(18, 34, 26, .4);
  border-radius: var(--wf-r-action);
  font-size: 18px;
  font-family: var(--wf-font-texte);
  transition: transform 200ms var(--wf-c-entree);
}
/* Le « + » pivote de 135° pour devenir un « – » : un seul caractère,
   aucun changement de contenu à annoncer au lecteur d'écran. */
.wf-question[open] .wf-signe { transform: rotate(135deg); }
.wf-reponse {
  margin: 0;
  padding: 0 2px 22px;
  max-width: 62ch;
  font-size: 16px;
  line-height: 1.6;
  text-wrap: pretty;
  animation: wf-rise var(--wf-d-apparition) var(--wf-c-entree) both;
}

/* =====================================================================
   06 — Contact (fond jungle)
   ===================================================================== */
.wf-contact-grille {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr));
  gap: clamp(24px, 4vw, 56px);
  align-items: center;
}
.wf-h2-contact {
  margin-top: 16px;
  font-size: clamp(38px, 7vw, 96px);
  line-height: .88;
  letter-spacing: -.045em;
}
.wf-h2-contact .wf-italique { color: var(--wf-ambre); }
.wf-contact-texte {
  margin: 22px 0 0;
  max-width: 46ch;
  font-size: var(--wf-t-texte);
  line-height: var(--wf-texte-leading);
  color: rgba(250, 244, 232, .85);
  text-wrap: pretty;
}
.wf-btn-coco {
  padding: 15px 24px;
  background: var(--wf-coco);
  color: var(--wf-jungle);
  border-radius: var(--wf-r-action);
  font-size: 15px;
  font-weight: 600;
  transition: background-color var(--wf-d-survol) var(--wf-c-entree),
              color var(--wf-d-survol) var(--wf-c-entree);
}
.wf-btn-coco:hover { background: var(--wf-ambre); color: var(--wf-jungle); }
.wf-btn-ligne-claire {
  padding: 15px 24px;
  border: 1px solid rgba(250, 244, 232, .35);
  color: var(--wf-coco);
  border-radius: var(--wf-r-action);
  font-size: 15px;
  font-weight: 500;
  transition: border-color var(--wf-d-survol) var(--wf-c-entree),
              color var(--wf-d-survol) var(--wf-c-entree);
}
.wf-btn-ligne-claire:hover { border-color: var(--wf-ambre); color: var(--wf-ambre); }

/* =====================================================================
   Pied de page
   ===================================================================== */
.wf-pied {
  padding: clamp(28px, 4vw, 48px) var(--wf-section-x);
}
.wf-pied-ligne {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  font-family: var(--wf-font-mono);
  font-size: var(--wf-t-mono);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--wf-encre-2);
}
.wf-pied-mot {
  font-family: var(--wf-font-titre);
  font-weight: 800;
  font-size: 20px;
  letter-spacing: var(--wf-titre-tracking);
  color: var(--wf-jungle);
  text-transform: none;
}
.wf-pied-liens { display: flex; flex-wrap: wrap; gap: 14px; }
.wf-pied a { color: var(--wf-encre-2); }
.wf-pied a:hover { color: var(--wf-braise-foncee); }
.wf-note-faya {
  margin: 18px 0 0;
  font-size: 13px;
  line-height: 1.6;
  color: var(--wf-encre-3);
  max-width: 58ch;
}

/* =====================================================================
   wf-hover-fill — le remplissage des actions au survol
   Reprise de la charte : le fond monte depuis le bas, il ne grossit pas.
   150 ms, la durée de survol prescrite.
   ===================================================================== */
.wf-btn-plein,
.wf-btn-ligne,
.wf-btn-coco,
.wf-btn-ligne-claire,
.wf-action-nav {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  /* `inline-flex` n'est pas cosmetique : `overflow: hidden` ne clippe pas
     une boite INLINE. Tant que ces boutons vivaient dans `.wf-boutons`
     (un conteneur flex), ils etaient blockifies et le remplissage de
     survol restait cache. Pose en lien nu dans un paragraphe, le meme
     bouton laissait deborder son `::before` ambre sous le texte. Dans un
     conteneur flex cette declaration ne change rien : un element flex est
     blockifie de toute facon. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-align: center;
}
.wf-btn-plein::before,
.wf-btn-ligne::before,
.wf-btn-coco::before,
.wf-btn-ligne-claire::before,
.wf-action-nav::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  transform: translateY(100%);
  transition: transform var(--wf-d-survol) var(--wf-c-entree);
}
.wf-btn-plein::before,
.wf-action-nav::before { background: var(--wf-braise-foncee); }
.wf-btn-ligne::before { background: var(--wf-jungle); }
.wf-btn-coco::before { background: var(--wf-ambre); }
.wf-btn-ligne-claire::before { background: var(--wf-coco); }

.wf-btn-plein:hover::before,
.wf-btn-plein:focus-visible::before,
.wf-btn-ligne:hover::before,
.wf-btn-ligne:focus-visible::before,
.wf-btn-coco:hover::before,
.wf-btn-coco:focus-visible::before,
.wf-btn-ligne-claire:hover::before,
.wf-btn-ligne-claire:focus-visible::before,
.wf-action-nav:hover::before,
.wf-action-nav:focus-visible::before { transform: translateY(0); }

/* Le texte doit rester lisible sur le fond qui monte. */
.wf-btn-ligne:hover,
.wf-btn-ligne:focus-visible { color: var(--wf-coco); border-color: var(--wf-jungle); }
.wf-btn-ligne-claire:hover,
.wf-btn-ligne-claire:focus-visible { color: var(--wf-jungle); border-color: var(--wf-coco); }

/* =====================================================================
   wf-clin — le clin d'œil du bloc Contact
   Deux images dessinées alternées, au rythme du GIF fourni : yeux
   ouverts 2 s, clin d'œil 220 ms, boucle de 3,12 s. `steps(1, end)`
   fait la bascule nette ; un fondu donnerait une paupière au ralenti.
   Remplace l'ancien wf-blink, qui écrasait toute la mascotte en scaleY
   faute d'avoir une vraie image de clin d'œil.
   La charte l'autorise « seulement quand elle est seule à l'écran » :
   elle l'est, une seule grande occurrence par section.
   ===================================================================== */
@keyframes wf-clin {
  0%      { opacity: 1; }
  64.1%   { opacity: 0; }
  71.2%   { opacity: 1; }
}
.wf-mascotte.wf-clin-oeil { animation: wf-float 4.5s ease-in-out infinite; }
.wf-mascotte.wf-clin-oeil > picture { grid-area: 1 / 1; display: block; }
.wf-mascotte.wf-clin-oeil img { animation: none; }
.wf-mascotte.wf-clin-oeil .wf-clin-ouvert {
  animation: wf-clin 3.12s steps(1, end) infinite;
}

/* =====================================================================
   Animations — bibliothèque de la charte, section 12
   ===================================================================== */
@keyframes wf-marquee {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-50%, 0, 0); }
}
@keyframes wf-marquee-rev {
  from { transform: translate3d(-50%, 0, 0); }
  to   { transform: translate3d(0, 0, 0); }
}
@keyframes wf-rise {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: none; }
}
/* ---------------------------------------------------------------------
   Animations reprises de la section 12 de la charte
   Elles y sont ecrites en boucle (retour a l'etat initial a 100 %) parce
   que la planche de demonstration les joue en continu. En production on
   garde le meme geste et la meme courbe, en aller simple.
   --------------------------------------------------------------------- */
@keyframes wf-drawer {
  from { transform: translateY(-100%); }
  to   { transform: none; }
}
@keyframes wf-wake {
  0%, 30%  { opacity: 1; }
  40%, 92% { opacity: 0; }
  100%     { opacity: 1; }
}
@keyframes wf-loader {
  from { transform: translateX(-100%); }
  to   { transform: translateX(300%); }
}

@keyframes wf-float {
  0%, 100% { transform: translateY(0) rotate(-2deg); }
  50%      { transform: translateY(-10px) rotate(2deg); }
}
@keyframes wf-flicker {
  0%, 100% { opacity: 1; }
  38% { opacity: .55; }
  52% { opacity: 1; }
  68% { opacity: .72; }
}

/* Entrée des lignes de titre et des blocs.
   `both` : l'élément finit toujours visible, même si le script échoue. */
.wf-entre { animation: wf-rise .5s var(--wf-c-entree) both; }

/* Les lignes du H1 meritent mieux qu'une montee : elles se decouvrent au
   volet, la signature des titres de la charte. Les insets negatifs de
   l'etat final comptent : avec un interlignage de titre a 0,88, les
   jambages depassent la boite de ligne — un inset(0) les raserait
   definitivement (le « q » de « qui dorment »). */
.wf-h1 .wf-entre {
  animation-name: wf-titre-volet;
  animation-duration: .55s;
}
@keyframes wf-titre-volet {
  from { clip-path: inset(-0.2em 0 100% 0); transform: translateY(16px); }
  to   { clip-path: inset(-0.2em -0.2em -0.4em -0.05em); transform: none; }
}

/* Puis le trait se dessine sous l'italique — wf-highlight de la charte,
   joue a l'arrivee. Il reste trace ensuite, comme sur les titres de
   section une fois leur plage de scroll passee. */
.wf-h1 .wf-italique { position: relative; }
.wf-h1 .wf-italique::after {
  content: "";
  position: absolute;
  left: 0;
  right: .04em;
  bottom: .03em;
  height: 3px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left center;
  animation: wf-trait-arrivee 420ms var(--wf-c-entree) both;
  animation-delay: calc(var(--wf-t0, 0s) + .72s);
}
@keyframes wf-trait-arrivee {
  to { transform: scaleX(1); }
}
/* Les delais de cascade sont plus bas : ils dependent de `--wf-t0`,
   qui les repousse tous quand le rideau d'arrivee joue. */

/* Apparition au scroll.
   Le masquage n'est actif que sous .wf-anim, classe posée par le script
   APRES qu'il a mis l'observateur en place — et retirée par un garde-fou
   au bout de 1,5 s. Autrement dit : un observateur qui ne se déclenche
   jamais ne peut pas laisser la page vide. */
.wf-anim .wf-apparait { opacity: 0; transform: translateY(16px); }
.wf-anim .wf-apparait.wf-vu {
  opacity: 1;
  transform: none;
  transition: opacity var(--wf-d-apparition) var(--wf-c-entree),
              transform var(--wf-d-apparition) var(--wf-c-entree);
}

/* =====================================================================
   Rideau d'arrivee
   Le volet de la charte, en plein ecran : 270 ms de pose sur la marque,
   puis 550 ms pour remonter, courbe des volets. Il n'existe que si le
   script a pose `.wf-rideau-actif` sur <html> — sans JS il n'apparait
   jamais, donc personne ne peut rester coince derriere.
   `forwards` : meme si un `animationend` se perd, le rideau finit en
   haut et n'y revient pas.
   ===================================================================== */
.wf-rideau { display: none; }
/* Le script pose `hidden` une fois le rideau remonte. Sans cette ligne,
   `.wf-rideau-actif .wf-rideau` (0-2-0) l'emporte sur le display:none du
   navigateur et le noeud reste dans la page — invisible parce que
   translate hors ecran, mais toujours present. */
.wf-rideau[hidden] { display: none !important; }

.wf-rideau-actif .wf-rideau {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(16px, 3vh, 26px);
  position: fixed;
  inset: 0;
  /* `inset: 0` exclut la barre de defilement : `100vw` l'inclut. */
  width: 100vw;
  z-index: 200;
  background: var(--wf-jungle);
  /* Rien n'est bloque : la page est deja montee derriere et l'ecran ne
     capte aucun clic. Echap, Entree ou Espace passent l'intro (script). */
  pointer-events: none;
  /* La sortie : un rideau franc qui remonte, pas un fondu. Elle demarre
     a 72 % de la duree totale et occupe les 28 % restants. -101 % et non
     -100 % : au pixel pres, un lisere jungle restait parfois visible en
     haut sur les hauteurs impaires. */
  animation: wf-rideau calc(var(--wf-intro-duree, 2.2s) * .28)
             cubic-bezier(.76, 0, .24, 1)
             calc(var(--wf-intro-duree, 2.2s) * .72) both;
}
@keyframes wf-rideau {
  from { transform: translateY(0); }
  to   { transform: translateY(-101%); }
}

/* La toile de fond : la planche d'etincelles du kit, centre volontairement
   vide pour laisser la place a la mascotte et au logotype. Elle monte de
   2 % pendant l'intro — assez pour respirer, trop peu pour distraire.
   `background-image` et non `<img>` : c'est un decor, il n'a rien a dire
   a un lecteur d'ecran, et il n'entre pas dans le calcul du LCP. */
.wf-rideau-actif .wf-rideau::before {
  content: "";
  position: absolute;
  inset: 0;
  background: url("../assets/marque/intro-fond.webp") center / cover no-repeat;
  animation: wf-intro-fond var(--wf-intro-duree, 2.2s) linear both;
}
@keyframes wf-intro-fond {
  from { transform: scale(1); }
  to   { transform: scale(1.02); }
}

/* La scene passe devant le decor. */
.wf-intro-scene,
.wf-intro-ligne-mot,
.wf-intro-pied { position: relative; z-index: 1; }

/* La braise vacille : opacite par paliers nets — steps(1, end), aucun
   lissage. C'est un clignotement de braise, pas une pulsation. */
.wf-intro-mascotte {
  display: block;
  width: clamp(86px, 12vw, 140px);
  height: auto;
  animation: wf-intro-vacille 1.1s steps(1, end) infinite;
}
@keyframes wf-intro-vacille {
  0%  { opacity: 1; }
  25% { opacity: .5; }
  50% { opacity: 1; }
  75% { opacity: .74; }
}

/* Le logotype sort de sa ligne : conteneur en overflow hidden, le mot
   monte de 26 px en devenant opaque. Le padding donne de l'air aux
   jambages du « y » et du « f », sinon le masque les rase. */
.wf-intro-ligne-mot { display: block; overflow: hidden; padding: .04em .08em .08em; }
.wf-intro-mot {
  display: block;
  font-family: var(--wf-font-titre);
  font-weight: 800;
  font-size: clamp(44px, 9vw, 104px);
  letter-spacing: -.045em;
  line-height: 1.02;
  color: var(--wf-coco);
  transform: translateY(26px);
  opacity: 0;
  animation: wf-intro-mot .7s cubic-bezier(.22, 1, .36, 1) .18s both;
}
@keyframes wf-intro-mot {
  to { transform: none; opacity: 1; }
}

/* Barre de chargement et devise : elles s'effacent ensemble entre 64 et
   84 % de la duree — elles partent avant le rideau. */
.wf-intro-pied {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 13px;
  animation: wf-intro-efface var(--wf-intro-duree, 2.2s) linear both;
}
@keyframes wf-intro-efface {
  0%, 64%   { opacity: 1; }
  84%, 100% { opacity: 0; }
}
.wf-intro-barre {
  display: block;
  width: clamp(180px, 24vw, 300px);
  height: 3px;
  /* Le seul coin arrondi permis par le brief. */
  border-radius: 999px;
  overflow: hidden;
  background: rgba(250, 244, 232, .24);
}
.wf-intro-barre i {
  display: block;
  height: 100%;
  background: var(--wf-braise);
  transform: scaleX(0);
  transform-origin: left center;
  animation: wf-intro-remplit var(--wf-intro-duree, 2.2s) cubic-bezier(.4, 0, .2, 1) both;
}
@keyframes wf-intro-remplit {
  to { transform: scaleX(1); }
}
.wf-intro-ligne {
  font-family: var(--wf-font-mono);
  font-size: clamp(9px, 1.2vw, 11px);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: rgba(250, 244, 232, .72);
}

/* La cascade du hero attend que le rideau soit parti : `--wf-t0` decale
   toutes les entrees d'un coup, sans toucher aux delais relatifs. */
.wf-entre { animation-delay: var(--wf-t0, 0s); }
.wf-d1 { animation-delay: calc(var(--wf-t0, 0s) + .06s); }
.wf-d2 { animation-delay: calc(var(--wf-t0, 0s) + .14s); }
.wf-d3 { animation-delay: calc(var(--wf-t0, 0s) + .22s); }
.wf-d4 { animation-delay: calc(var(--wf-t0, 0s) + .30s); }
.wf-d5 { animation-delay: calc(var(--wf-t0, 0s) + .38s); }
/* La cascade du hero demarre quand le rideau commence a decouvrir la
   page : a 85 % de la duree de l'intro, quelle qu'elle soit. */
.wf-rideau-actif { --wf-t0: calc(var(--wf-intro-duree, 2.2s) * .85); }

/* =====================================================================
   Points de rupture
   ===================================================================== */
@media (max-width: 768px) {
  /* Au-dessus du volet (z-index 70), sinon « Fermer » passe dessous et
     il ne reste que la touche Echap pour sortir. */
  .wf-burger { display: inline-block; position: relative; z-index: 80; }
  /* Le logo reste visible par-dessus le volet : l'en-tete ne doit pas
     disparaitre a moitie quand le menu s'ouvre. */
  .wf-logo { position: relative; z-index: 80; }
  .wf-nav {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 70;
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;
    gap: 22px;
    padding: var(--wf-section-x);
    background: var(--wf-coco);
    font-size: 14px;
  }
  /* La charte est explicite : « volet plein ecran depuis le haut, 450 ms
     cubic-bezier(.76,0,.24,1), liens en cascade 40 ms ». */
  .wf-nav.wf-ouvert {
    display: flex;
    padding-top: calc(var(--wf-section-x) + 48px);
    animation: wf-drawer 450ms var(--wf-c-volet) both;
  }
  .wf-nav.wf-ouvert > * { animation: wf-rise 300ms var(--wf-c-entree) both; }
  .wf-nav.wf-ouvert > *:nth-child(1) { animation-delay: 220ms; }
  .wf-nav.wf-ouvert > *:nth-child(2) { animation-delay: 260ms; }
  .wf-nav.wf-ouvert > *:nth-child(3) { animation-delay: 300ms; }
  .wf-nav.wf-ouvert > *:nth-child(4) { animation-delay: 340ms; }
  .wf-nav.wf-ouvert > *:nth-child(5) { animation-delay: 380ms; }
  .wf-nav a { font-size: 15px; }
  .wf-action-nav { font-size: 15px; }
}

@media (max-width: 480px) {
  .wf-vitrine { grid-template-columns: repeat(2, 1fr); }
  .wf-etape { grid-template-columns: 40px 1fr; gap: 12px; }
}

/* =====================================================================
   Mouvement réduit — non négociable, bandeaux compris
   ===================================================================== */
@media (prefers-reduced-motion: reduce) {
  .wf-piste,
  .wf-braise-logo,
  .wf-mascotte img,
  .wf-entre,
  .wf-nav.wf-ouvert,
  .wf-nav.wf-ouvert > *,
  .wf-mascotte.wf-eveil,
  .wf-mascotte.wf-clin-oeil,
  .wf-mascotte.wf-clin-oeil .wf-clin-ouvert,
  .wf-form-barre i,
  .wf-reponse { animation: none !important; }
  /* Sans le fondu, la pose endormie reste au-dessus : c'est l'etat de
     repos voulu, et l'image eveillee dessous n'est jamais visible. */
  .wf-mascotte.wf-eveil .wf-eveil-endormi { opacity: 1; }
  .wf-form-barre i { width: 100%; }
  .wf-entre { opacity: 1; transform: none; clip-path: none; }
  /* Le trait sous l'italique s'affiche trace, sans se dessiner. */
  .wf-h1 .wf-italique::after { animation: none !important; transform: none; }
  /* Pas de rideau, et aucun decalage de cascade a rattraper. */
  .wf-rideau-actif .wf-rideau { display: none; }
  .wf-intro-mascotte,
  .wf-intro-mot,
  .wf-rideau::before,
  .wf-intro-pied,
  .wf-intro-barre i { animation: none !important; }
  .wf-rideau-actif { --wf-t0: 0s; }
  .wf-anim .wf-apparait { opacity: 1; transform: none; }
  .wf-objet,
  .wf-btn-plein::before,
  .wf-btn-ligne::before,
  .wf-btn-coco::before,
  .wf-btn-ligne-claire::before,
  .wf-action-nav::before,
  .wf-signe,
  .wf-projet-lien::after,
  .wf-action,
  .wf-btn-plein,
  .wf-btn-ligne,
  .wf-btn-coco,
  .wf-btn-ligne-claire,
  .wf-offre,
  .wf-projet { transition: none !important; }
}

/* =====================================================================
   Formulaire de contact
   Posé sur fond jungle : tous les accents passent en variantes claires,
   comme l'exige la charte. Angles à 0 sur les champs, 999px sur l'action.
   ===================================================================== */
.wf-contact-grille { align-items: start; }
.wf-mascotte-contact { margin-top: clamp(24px, 3vw, 40px); justify-items: start; }
.wf-mascotte-contact img { width: min(100%, 220px); }

.wf-form { display: flex; flex-direction: column; gap: clamp(14px, 1.8vw, 20px); }
.wf-form-ligne {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr));
  gap: clamp(14px, 1.8vw, 20px);
}
.wf-champ { display: flex; flex-direction: column; gap: 6px; }
.wf-champ label {
  font-size: .95rem;
  font-weight: 600;
  color: var(--wf-coco);
}
.wf-requis { color: var(--wf-braise-claire); }

.wf-form input[type="text"],
.wf-form input[type="email"],
.wf-form input[type="tel"],
.wf-form textarea {
  width: 100%;
  padding: 12px 14px;
  border: 1px solid rgba(250, 244, 232, .32);
  border-radius: var(--wf-r-bloc);
  background: rgba(250, 244, 232, .05);
  color: var(--wf-coco);
  font-family: var(--wf-font-texte);
  font-size: 1rem;
  line-height: 1.5;
  transition: border-color var(--wf-d-survol) var(--wf-c-entree),
              background-color var(--wf-d-survol) var(--wf-c-entree);
}
.wf-form textarea { resize: vertical; min-height: 110px; }
.wf-form input::placeholder,
.wf-form textarea::placeholder { color: rgba(250, 244, 232, .55); }
.wf-form input:hover,
.wf-form textarea:hover { border-color: rgba(250, 244, 232, .6); }
.wf-form input:focus-visible,
.wf-form textarea:focus-visible {
  border-color: var(--wf-ambre);
  background: rgba(250, 244, 232, .09);
}

.wf-aide { font-size: .85rem; color: rgba(250, 244, 232, .72); }

/* wf-shake : ±4px sur 400ms, une seule fois. Jamais de rebond. */
.wf-erreur {
  font-size: .85rem;
  font-weight: 600;
  color: var(--wf-braise-claire);
  min-height: 0;
}
.wf-erreur:empty { display: none; }
.wf-champ.is-erreur input,
.wf-champ.is-erreur textarea { border-color: var(--wf-braise-claire); }
.wf-champ.is-erreur { animation: wf-shake .4s var(--wf-c-entree) 1; }
@keyframes wf-shake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-4px); }
  40% { transform: translateX(4px); }
  60% { transform: translateX(-2px); }
  80% { transform: translateX(2px); }
}

.wf-consentement {
  display: grid;
  grid-template-columns: 20px 1fr;
  gap: 10px;
  align-items: start;
  font-weight: 400;
  font-size: .92rem;
  line-height: 1.55;
  color: rgba(250, 244, 232, .88);
  cursor: pointer;
}
.wf-consentement input { margin-top: 3px; accent-color: var(--wf-braise-claire); }
.wf-consentement a { color: var(--wf-braise-claire); text-decoration: underline; }
.wf-consentement a:hover { color: var(--wf-ambre); }

.wf-form-envoi { align-self: flex-start; border: 0; cursor: pointer; font-family: var(--wf-font-texte); }
.wf-form-envoi[disabled] { opacity: .6; cursor: progress; }

.wf-form-repli {
  margin: 0;
  padding: 12px 14px;
  border-top: 2px solid var(--wf-braise-claire);
  background: rgba(250, 244, 232, .06);
  font-size: .92rem;
  line-height: 1.55;
  color: var(--wf-coco);
}
.wf-form-repli a { color: var(--wf-braise-claire); text-decoration: underline; }

/* Le pot à miel doit rester invisible aux humains, jamais aux robots. */
.wf-pot-a-miel { position: absolute; left: -9999px; }

/* =====================================================================
   wf-toast — confirmation d'envoi
   Entrée 400ms, visible 4s, sortie 250ms. Spécifications du kit.
   ===================================================================== */
/* `display: flex` ci-dessous ecrase le `display: none` que le navigateur
   applique a l'attribut `hidden`. Sans cette ligne, le toast reste visible
   en permanence au lieu de n'apparaitre qu'apres l'envoi du formulaire.
   Elle doit rester AVANT la regle qui pose le flex. */
.wf-toast[hidden] { display: none; }

.wf-toast {
  position: fixed;
  left: 50%;
  bottom: clamp(16px, 3vw, 32px);
  z-index: 80;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 12px;
  max-width: min(92vw, 460px);
  padding: 14px 20px;
  background: var(--wf-jungle);
  color: var(--wf-coco);
  border-radius: var(--wf-r-action);
  font-size: .95rem;
  line-height: 1.45;
}
.wf-toast img { width: 26px; height: 26px; flex: none; }
.wf-toast.is-entrant { animation: wf-toast .4s var(--wf-c-entree) both; }
.wf-toast.is-sortant { animation: wf-toast-sortie .25s var(--wf-c-entree) both; }
@keyframes wf-toast {
  from { opacity: 0; transform: translateX(-50%) translateY(120%); }
  to   { opacity: 1; transform: translateX(-50%) translateY(0); }
}
@keyframes wf-toast-sortie {
  from { opacity: 1; transform: translateX(-50%) translateY(0); }
  to   { opacity: 0; transform: translateX(-50%) translateY(120%); }
}

@media (prefers-reduced-motion: reduce) {
  .wf-champ.is-erreur,
  .wf-toast.is-entrant,
  .wf-toast.is-sortant { animation: none !important; }
  .wf-toast { transform: translateX(-50%); opacity: 1; }
}

/* =====================================================================
   « Ce qui peut mal tourner »
   Cinq craintes, cinq reponses verifiables. Fond coco, comme les autres
   sections claires ; aucune ombre, angles a 0 sur les blocs.
   ===================================================================== */
.wf-confiance-intro {
  max-width: 62ch;
  margin: 18px 0 0;
  font-size: 16px;
  line-height: var(--wf-texte-leading);
  color: var(--wf-encre-2);
}
.wf-confiance-liste {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr));
  gap: 1px;
  margin-top: clamp(28px, 4vw, 52px);
  /* Le fond se voit dans la gouttiere de 1px : les filets separent les
     blocs sans qu'aucun ne porte de bordure a lui. */
  background: rgba(18, 34, 26, .18);
  border: 1px solid rgba(18, 34, 26, .18);
}
.wf-crainte {
  background: var(--wf-coco);
  padding: clamp(22px, 2.6vw, 32px);
}
.wf-crainte-num {
  margin: 0 0 12px;
  font-family: var(--wf-font-mono);
  font-size: var(--wf-t-mono);
  letter-spacing: .08em;
  color: var(--wf-braise-foncee);
}
.wf-crainte h3 {
  margin: 0 0 10px;
  font-family: var(--wf-font-titre);
  font-weight: 700;
  font-size: clamp(17px, 1.7vw, 21px);
  line-height: 1.2;
  letter-spacing: -.02em;
  color: var(--wf-jungle);
}
/* Enfants directs : sinon cette regle gagnerait sur .wf-crainte-num. */
.wf-crainte > p:not(.wf-crainte-num) {
  margin: 0;
  font-size: 15px;
  line-height: var(--wf-texte-leading);
  color: var(--wf-encre-2);
}
.wf-crainte a { color: var(--wf-braise-foncee); }
.wf-crainte strong { color: var(--wf-jungle); }

/* Les expressions des craintes sont un jeu d'icones, pas six mascottes
   concurrentes : l'avenant du kit l'autorise dans les titres. Un peu
   plus grandes qu'en ligne de texte, elles ouvrent chaque bloc. */
.wf-crainte h3 .wf-tete { margin-right: 8px; }
.wf-crainte h3 .wf-tete-img { width: 1.5em; }

/* Nom, adresse, telephone au pied de chaque page. Ils doivent etre
   rigoureusement identiques a la fiche Google Business : une incoherence
   entre les deux fait perdre des places dans le pack local. */
.wf-pied-nap { color: var(--wf-encre-2); }
.wf-pied-nap a { color: var(--wf-encre-2); text-decoration: none; border-bottom: 1px solid rgba(18, 34, 26, .3); }
.wf-pied-nap a:hover,
.wf-pied-nap a:focus-visible { color: var(--wf-braise-foncee); border-bottom-color: var(--wf-braise-foncee); }

/* =====================================================================
   Sélecteur de langue
   Trois codes courts dans l'en-tête. La langue active n'est pas un lien :
   un lien vers la page qu'on regarde deja n'apporte rien et brouille la
   navigation au clavier.
   ===================================================================== */
.wf-langues {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  margin-left: 14px;
  font-family: var(--wf-font-mono);
  font-size: 10px;
  letter-spacing: .08em;
}
.wf-langues a,
.wf-langue-active {
  padding: 5px 7px;
  border-radius: 999px;
  text-decoration: none;
  line-height: 1;
}
.wf-langues a { color: var(--wf-encre-2); }
.wf-langues a:hover,
.wf-langues a:focus-visible { color: var(--wf-jungle); background: rgba(18, 34, 26, .08); }
.wf-langue-active { background: var(--wf-jungle); color: var(--wf-coco); }

@media (max-width: 768px) {
  /* Dans le volet, les langues passent en fin de liste et s'étalent. */
  .wf-langues { margin: 8px 0 0; font-size: 12px; }
  .wf-langues a,
  .wf-langue-active { padding: 8px 12px; }
}

/* =====================================================================
   Les trois routes de contact
   Le visiteur choisit son rythme : un message immédiat, un brief court,
   ou un brief complet. Fond jungle, donc bordures et encre en coco.
   ===================================================================== */
.wf-routes { margin-top: clamp(26px, 4vw, 44px); }
.wf-routes-titre {
  margin: 0 0 14px;
  font-family: var(--wf-font-mono);
  font-size: var(--wf-t-mono);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--wf-ambre);
}
.wf-route {
  display: grid;
  grid-template-columns: auto 1fr;
  column-gap: 16px;
  row-gap: 4px;
  padding: 16px 0;
  border-top: 1px solid rgba(250, 244, 232, .22);
  text-decoration: none;
  transition: background-color var(--wf-d-survol) var(--wf-c-entree);
}
.wf-route:last-of-type { border-bottom: 1px solid rgba(250, 244, 232, .22); }
.wf-route:hover,
.wf-route:focus-visible { background: rgba(250, 244, 232, .05); }
.wf-route-duree {
  grid-row: 1 / 3;
  align-self: start;
  min-width: 7.5em;
  font-family: var(--wf-font-mono);
  font-size: var(--wf-t-mono);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--wf-ambre);
  padding-top: 4px;
}
.wf-route-nom {
  font-family: var(--wf-font-titre);
  font-weight: 800;
  font-size: clamp(18px, 2vw, 23px);
  letter-spacing: -.025em;
  color: var(--wf-coco);
}
.wf-route-texte {
  font-size: 14px;
  line-height: 1.55;
  color: rgba(250, 244, 232, .82);
  max-width: 52ch;
}
.wf-routes-note {
  margin: 16px 0 0;
  font-size: 14px;
  line-height: 1.6;
  color: rgba(250, 244, 232, .78);
  max-width: 58ch;
}
.wf-routes-note strong { color: var(--wf-coco); }

@media (max-width: 620px) {
  /* En colonne, la durée passe au-dessus du nom. */
  .wf-route { grid-template-columns: 1fr; }
  .wf-route-duree { grid-row: auto; padding-top: 0; }
}

/* Ligne d'appui d'un engagement.
   La section a ete retournee : l'engagement est monte en <h3>, et la
   crainte qu'il leve est descendue ici, en petit. Elle doit se lire
   comme une note, jamais comme un titre — sinon on retombe sur le
   defaut d'origine, six inquietudes qui sautent aux yeux avant les six
   reponses. */
.wf-crainte-crainte {
  margin: 0 0 10px !important;
  font-family: var(--wf-font-mono);
  font-size: var(--wf-t-mono);
  line-height: 1.6;
  letter-spacing: var(--wf-mono-tracking);
  color: var(--wf-encre-2);
}

/* =====================================================================
   Micro-interactions — passe de finition du 21/09/2026
   Quatre gestes, tous sous les 600 ms de la charte, tous neutralises
   par le bloc de mouvement reduit en fin de feuille.
   ===================================================================== */

/* --- La fleche des liens avance d'un cran au survol ------------------
   Micro-interaction de la famille : elle dit « ca s'ouvre par la ».
   4 px, pas plus — au-dela, la fleche a l'air de fuir le libelle. */
.wf-fleche {
  display: inline-block;
  transition: transform var(--wf-d-survol) var(--wf-c-entree);
}
a:hover .wf-fleche,
a:focus-visible .wf-fleche { transform: translateX(4px); }

/* --- La reponse de FAQ se pose au lieu d'apparaitre d'un bloc --------
   240 ms : le deplie natif de <details> est instantane et sec. On ne
   touche pas a la hauteur (le navigateur la gere), seulement a
   l'arrivee du texte. */
@keyframes wf-faq-ouverture {
  from { opacity: 0; transform: translateY(-4px); }
}
.wf-question[open] .wf-reponse {
  animation: wf-faq-ouverture var(--wf-d-apparition) var(--wf-c-entree);
}

/* --- Soulignement des liens de contenu : le trait s'epaissit ---------
   Reprise notee dans la planche de references (Bonhomme, Grapheine) :
   un degrade en fond dont on anime la hauteur, plus fin que le
   text-decoration natif et animable. Le trait reste visible au repos —
   un lien de paragraphe sans soulignement n'est reperable que par des
   personnes qui distinguent bien les couleurs. */
.wf-lien-texte,
.wf-consentement a,
.wf-form-repli a,
.wf-reponse a,
.wf-crainte a,
.wf-offre-suite a {
  text-decoration: none;
  background-image: linear-gradient(currentColor, currentColor);
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 100% 1px;
  transition: background-size var(--wf-d-survol) var(--wf-c-entree);
}
.wf-lien-texte:hover, .wf-lien-texte:focus-visible,
.wf-consentement a:hover, .wf-consentement a:focus-visible,
.wf-form-repli a:hover, .wf-form-repli a:focus-visible,
.wf-reponse a:hover, .wf-reponse a:focus-visible,
.wf-crainte a:hover, .wf-crainte a:focus-visible,
.wf-offre-suite a:hover, .wf-offre-suite a:focus-visible {
  background-size: 100% 2px;
}

/* --- Transition entre les pages --------------------------------------
   Fondu croise natif entre deux pages du site (Chrome et derives ; les
   autres naviguent comme avant, il n'y a rien a rattraper). 180 ms : le
   fondu par defaut du navigateur traine un peu pour un site aussi
   rapide. Le rideau d'arrivee, lui, ne joue qu'une fois par session —
   les deux ne se superposent donc jamais. */
@view-transition { navigation: auto; }
::view-transition-old(root),
::view-transition-new(root) { animation-duration: 180ms; }

@media (prefers-reduced-motion: reduce) {
  @view-transition { navigation: none; }
  .wf-fleche,
  a:hover .wf-fleche,
  a:focus-visible .wf-fleche { transition: none; transform: none; }
  .wf-question[open] .wf-reponse { animation: none; }
  .wf-lien-texte, .wf-consentement a, .wf-form-repli a,
  .wf-reponse a, .wf-crainte a, .wf-offre-suite a { transition: none; }
}
