/* Provolu — styles. Vanilla, aucun build, aucune dépendance. */

/* Une seule palette, tiree du logo : noir profond legerement violace,
   violet du ruban, halo. Pas de theme clair — la marque est sombre. */
:root {
  color-scheme: dark;
  --bg: #060812;
  --surface: rgba(255, 255, 255, 0.035);
  --text: #edf1f7;
  --muted: #a7afbf;
  /* `--sourd` VIT ICI DEPUIS LE 2026-08-31 (audit lea, mesure a l'ecran).
     Elle n'etait declaree que dans accueil.css, charge par la SEULE page
     d'accueil. Sur /realisations/ et /en/, `var(--sourd, #6f6a85)` tombait
     donc sur son repli : contraste mesure 3,97:1 sur le fond, sous les
     4,5:1 de WCAG AA — alors que le meme texte tenait 5,71:1 sur /.
     Le texte le plus touche etait la legende « Maquette illustrative — les
     donnees presentees sont fictives » : la ligne qui porte la frontiere
     D-050 etait la moins lisible du site. */
  --sourd: #8d96a8;
  --hairline: rgba(170, 190, 225, 0.14);
  --accent: #9fb6d8;
  --accent-clair: #c9d8ef;
  --accent-soft: rgba(159, 182, 216, 0.16);
  --glass: rgba(6, 3, 11, 0.68);
  --radius: 18px;
  --maxw: 1080px;
  /* HIGH-TECH LUXURY (audit Gemini, adapte par lea le 2026-09-14) : la
     texture de Gemini (glass, mono, lueur qui suit le curseur), pas sa
     teinte — le fond reste la nuit du site. `--etat` est la SEULE couleur
     vive : etat, focus, micro-animations. Jamais un titre, un lien, un
     bouton. Polices sans chargement externe (CSP style-src 'self'). */
  --carte: rgba(255, 255, 255, 0.03);
  --etat: #38bdf8;
  --etat-rgb: 56, 189, 248;
  /* Le rythme de la page basse, a la Fora (lea, 14 sept.) : UN pas vertical,
     UN rayon, UN rembourrage de carte. */
  --pas: clamp(3.5rem, 8vh, 5.5rem);
  --rayon: 16px;
  --carte-pad: clamp(1.25rem, 2.4vw, 1.75rem);
  --sans: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: "JetBrains Mono", "Fira Code", ui-monospace, SFMono-Regular, Menlo, monospace;
}
:focus-visible { outline: 2px solid var(--etat); outline-offset: 3px; }

* { box-sizing: border-box; margin: 0; padding: 0; }

html {
  scroll-behavior: smooth;
  scroll-padding-top: 5rem;
}

/* Sur mobile la barre du haut passe sur deux lignes : 5 rem ne suffisent plus
   et une ancre atterrit sous l'en-tete. */
@media (max-width: 640px) {
  html { scroll-padding-top: 7rem; }
}

body {
  font-family: var(--sans);
  background: var(--bg);
  color: var(--text);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Le halo du logo, en CSS : aucun fichier a charger, aucun decor. Fixe,
   donc il ne defile pas et ne coute rien a l'affichage. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(60rem 40rem at 50% -12%, rgba(120, 150, 200, 0.20), transparent 65%),
    radial-gradient(40rem 30rem at 85% 8%, rgba(201, 216, 239, 0.10), transparent 60%);
}

/* ---------- barre du haut ---------- */

.topbar {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.9rem clamp(1.25rem, 4vw, 2.5rem);
  background: var(--glass);
  -webkit-backdrop-filter: blur(20px) saturate(1.8);
  backdrop-filter: blur(20px) saturate(1.8);
  border-bottom: 1px solid var(--hairline);
}

/* Le mot-symbole reprend la casse du logo — « Provolu », pas « PROVOLU ». */
.wordmark {
  font-size: 1.15rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  text-decoration: none;
  color: #ffffff;
}

.topbar nav {
  display: flex;
  align-items: center;
  gap: clamp(0.75rem, 2.5vw, 1.75rem);
}

.topbar nav a {
  font-size: 0.92rem;
  color: var(--muted);
  text-decoration: none;
  transition: color 0.2s ease;
}

.topbar nav a:hover { color: var(--text); }

/* Gris comme les autres liens de section, depuis la revue de lea le
   2026-08-11. Sa regle : « deux accents dans six elements, c'est zero
   accent ». Le bouton Portail client porte maintenant l'emphase de la barre,
   et le vrai appel a l'action reste le bouton du hero. */
.nav-cta {
  font-weight: 500;
  transition: color 0.25s ease;
}

.nav-cta:hover,
.nav-cta:focus-visible {
  color: var(--text);
}

/* Le portail n'est pas une section de la page : c'est une porte vers une
   autre application, donc il se lit comme un objet et non comme un lien.
   En CONTOUR, jamais plein — plein, il concurrencerait le bouton du hero.
   Bordure a 0.60 d'alpha et non 0.14 : une bordure qui porte l'information
   doit tenir 3:1, contrairement a la pastille EN dont le libelle suffit. */
.nav-portail {
  color: var(--text) !important;
  font-weight: 500;
  background: rgba(170, 190, 225, 0.10);
  border: 1px solid rgba(170, 190, 225, 0.60);
  border-radius: 10px;
  padding: 7px 14px;
  transition: background 0.18s ease, border-color 0.18s ease;
}

.nav-portail:hover {
  background: rgba(170, 190, 225, 0.16);
  border-color: var(--accent-clair);
}

.nav-portail:focus-visible {
  outline: 2px solid var(--accent-clair);
  outline-offset: 2px;
}

.nav-portail + .nav-langue { margin-left: 3px; }

/* Le selecteur de langue reste visible sur mobile, contrairement aux liens de
   section : un visiteur anglophone qui ne le trouve pas quitte la page. C'est
   aussi pourquoi il n'est PAS descendu au pied de page (revue lea, 2026-08-11).
   Sans contour : deux objets bordes cote a cote se lisaient comme un controle
   segmente. Un seul objet borde dans la barre, c'est le bouton du portail. */
.nav-langue {
  display: inline-flex;
  align-items: center;
  min-height: 44px;            /* cible tactile, meme sans bordure visible */
  padding: 0 6px;
  font-size: 0.82rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  color: var(--muted) !important;
  transition: color 0.25s ease;
}

.nav-langue:hover,
.nav-langue:focus-visible {
  color: var(--accent-clair) !important;
}

.nav-langue:focus-visible {
  outline: 2px solid var(--accent-clair);
  outline-offset: 2px;
}

/* Sur petit ecran, les liens de section debordent. La page tient en un seul
   defilement : on ne garde que le contact. Pas de menu deroulant — il
   faudrait du JavaScript pour un gain nul. */
/* Le portail reste visible sur mobile : c'est la raison d'etre du site pour
   Sebastien, et un client a qui on donne l'adresse arrive souvent du telephone. */
@media (max-width: 640px) {
  .topbar nav a:not(.nav-cta):not(.nav-langue):not(.nav-portail) { display: none; }
  .nav-portail { font-size: 0.86rem; }
  .topbar nav { gap: 0.7rem; }
}

/* ---------- hero ---------- */

.hero {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: clamp(3rem, 8vh, 5.5rem) clamp(1.25rem, 4vw, 2.5rem) clamp(4rem, 10vh, 7rem);
  text-align: center;
}

/* Le symbole a son moment au centre du hero. Un logo de 30 px dans un coin
   ne fait pas identite ; ici il en fait une. Seul : le surtitre a ete retire
   le 2026-08-11, il affaiblissait l'impact. */
.hero-symbole {
  position: relative;
  width: clamp(96px, 13vw, 130px);
  margin: 0 auto 2.25rem;
  line-height: 0;
}

.hero-symbole img {
  width: 100%;
  height: auto;
  display: block;
}

/* L'impulsion qui traverse le ruban. Le masque reprend l'image elle-meme :
   la lumiere reste DANS la forme du P au lieu de balayer un rectangle. */
.hero-symbole::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  background: linear-gradient(105deg,
    transparent 38%, rgba(255, 255, 255, 0.85) 50%, transparent 62%);
  background-size: 280% 100%;
  -webkit-mask-image: url("/img/symbole-provolu.webp");
  mask-image: url("/img/symbole-provolu.webp");
  -webkit-mask-size: 100% 100%;
  mask-size: 100% 100%;
}

.eyebrow {
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--accent-clair);
  margin-bottom: 1.25rem;
}

/* Le degrade blanc → lavande du mot « Provolu » dans le logo. Une couleur
   pleine reste dessous : si le fond degrade n'est pas supporte, le titre
   s'affiche quand meme. */
/* LE TITRE A LA FORA — 2026-09-14 (PLAN-FORA.md, chantier 3). Graisse
   NORMALE, interlettrage serre, blanc chaud : mesure sur fora.so aux trois
   largeurs — 36 px a 375, 40 px a 1024, 56 px a 1440, toujours en 400. La
   finesse vient de la graisse et de l'interlettrage, pas d'une police rare.
   Le degrade blanc -> lavande part : la seule couleur du haut de page est le
   P. Une couleur pleine, lisible partout. */
.hero h1 {
  font-size: clamp(2.25rem, 3.9vw, 3.5rem);
  line-height: 1.22;
  letter-spacing: -0.04em;
  font-weight: 400;
  max-width: 22ch;
  margin: 0 auto;
  color: #f6f2f0;
}

.lede {
  max-width: 44ch;
  margin: 1.75rem auto 2.5rem;
  font-size: clamp(1.05rem, 1.6vw, 1.25rem);
  color: var(--muted);
}

/* Degrade assombri volontairement : le violet clair du logo ne tient pas
   le contraste AA sous du texte blanc. */
/* LE BOUTON A LA FORA — 2026-09-14 (PLAN-FORA.md, chantier 3). Pilule
   blanche a 86 %, texte nuit, aucune ombre, aucun degrade : mesure sur
   fora.so (fond blanc 80 %, texte noir, rayon 768 px, pas d'ombre). Un
   bouton blanc sur fond noir est le contraste le plus haut qui existe, et
   c'est la que Fora met son unique action. Le violet reste au P et aux
   accents ; il ne porte plus le bouton. Contraste #060812 sur blanc 86 %
   melange au fond : > 15:1. */
.cta {
  display: inline-block;
  padding: 0.8rem 1.7rem;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.86);
  color: #060812;
  text-decoration: none;
  font-weight: 500;
  font-size: 1rem;
  box-shadow: none;
  transition: transform 0.2s ease, background 0.2s ease;
}

/* L'ANNEAU DE FOCUS DES CTA — ajoute le 2026-08-31 (audit lea, verifie :
   `outline-style` valait `none` au focus). Les quatre boutons les plus
   importants du site — les deux du hero, l'envoi du formulaire, « Voir
   toutes les realisations » — etaient invisibles au clavier, alors que
   .nav-portail, .nav-langue et les champs avaient deja le leur. Meme
   traitement qu'eux : un anneau clair, decolle du bouton. */
.cta:focus-visible {
  outline: 2px solid var(--accent-clair);
  outline-offset: 3px;
}

.cta:hover {
  transform: translateY(-1px);
  background: #ffffff;
}

/* ---------- sections ---------- */

.section {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: var(--pas) clamp(1.25rem, 4vw, 2.5rem);
}

/* Sur mobile, `9vh` de haut ET de bas entre deux sections finit par faire un
   trou : deux sections consecutives cumulent leurs marges. Le vide avant
   Contact devenait un ecran presque entier a faire defiler. */
@media (max-width: 640px) {
  .section { padding-top: 2.75rem; padding-bottom: 2.75rem; }
  #contact { padding-top: 1.5rem; }
}

/* Le surtitre mono — ici et non dans accueil.css : /contact/ et /ancien/
   ne chargent que cette feuille (defaut constate deux fois, 2026-08-30 et
   2026-09-14). Meme valeur qu'avant. */
.tag {
  font-family: var(--mono);
  font-size: 0.72rem; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--muted);
}
.tag--accent { color: var(--accent-clair); }
.entete {
  display: flex; justify-content: space-between; align-items: baseline;
  border-bottom: 1px solid var(--hairline);
  padding-bottom: 0.9rem;
  margin-bottom: 2.5rem;
}
.entete h2.tag {
  font-family: var(--mono);
  font-size: 0.72rem;
  font-weight: 400;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0;
}

.section h2 {
  font-size: clamp(1.6rem, 3.2vw, 2.25rem);
  letter-spacing: -0.015em;
  margin-bottom: clamp(1.75rem, 4vh, 2.75rem);
}

.grid-3, .grid-2 {
  display: grid;
  gap: 1.25rem;
}

.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-2 { grid-template-columns: repeat(2, 1fr); }

@media (max-width: 860px) {
  .grid-3, .grid-2 { grid-template-columns: 1fr; }
}

.card {
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  padding: 1.75rem;
  transition: border-color 0.25s ease, background 0.25s ease;
}

/* LE POINT A ETE REMPLACE le 2026-08-15 par une marque abstraite par
   realisation (voir « bibliotheque de realisations » plus bas). Le point
   disait « ceci est une realisation » ; il ne disait pas LAQUELLE. Des que
   la section est devenue une bibliotheque appelee a grandir, chaque entree a
   eu besoin d'une identite qui lui appartient et qu'on retrouve d'une page a
   l'autre. Les deux sections restent distinctes — filigrane large et flou en
   fond sur « Ce que nous faisons », petite marque nette en haut de carte sur
   les realisations. Ne pas filigraner les realisations : sept cartes traitees
   comme les trois du haut redeviendraient un motif. */

/* Filigranes — UNIQUEMENT sur « Ce que nous faisons ».
   Une grande marque abstraite en fond de carte, coupee par le bord, a 6 %
   d'opacite. Pas une petite icone decorative : celle-la se lit comme un
   gabarit, celle-ci comme une texture.
   « Realisations » n'en recoit PAS, volontairement : sept cartes filigranees
   deviennent un motif, et les deux sections se ressemblaient deja trop. */
#services .card {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}

#services .card::after {
  content: "";
  position: absolute;
  right: -34px;
  bottom: -38px;
  width: 172px;
  height: 172px;
  z-index: -1;
  opacity: 0.06;
  background-repeat: no-repeat;
  background-size: contain;
  filter: blur(0.3px) drop-shadow(0 0 14px rgba(159, 182, 216, 0.5));
  transition: opacity 0.4s ease;
}

#services .card:hover::after { opacity: 0.1; }

/* Marques abstraites, en SVG dans le CSS : aucun fichier a charger. */
#services .card:nth-child(1)::after {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' fill='none' stroke='%23c084fc' stroke-width='3'%3E%3Ccircle cx='50' cy='50' r='12' fill='%23c084fc'/%3E%3Ccircle cx='50' cy='50' r='27'/%3E%3Ccircle cx='50' cy='50' r='42' opacity='.55'/%3E%3C/svg%3E");
}

#services .card:nth-child(2)::after {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' fill='none' stroke='%23c084fc' stroke-width='3'%3E%3Crect x='12' y='12' width='32' height='32' rx='7'/%3E%3Crect x='56' y='12' width='32' height='32' rx='7' opacity='.5'/%3E%3Crect x='12' y='56' width='32' height='32' rx='7' opacity='.5'/%3E%3Crect x='56' y='56' width='32' height='32' rx='7' fill='%23c084fc' stroke='none'/%3E%3C/svg%3E");
}

#services .card:nth-child(3)::after {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' fill='none' stroke='%23c084fc' stroke-width='3' stroke-linecap='round'%3E%3Cpath d='M10 62 C32 62 30 24 52 24 C74 24 72 62 94 62'/%3E%3Cpath d='M10 82 C32 82 30 44 52 44 C74 44 72 82 94 82' opacity='.45'/%3E%3C/svg%3E");
}

.card:hover {
  border-color: rgba(170, 190, 225, 0.3);
  background: rgba(255, 255, 255, 0.055);
}

.card h3 {
  font-size: 1.12rem;
  letter-spacing: -0.01em;
  margin-bottom: 0.6rem;
}

.card p {
  color: var(--muted);
  font-size: 0.98rem;
}

.card h3 a {
  color: var(--text);
  text-decoration: none;
  border-bottom: 1px solid var(--hairline);
  transition: border-color 0.2s ease, color 0.2s ease;
}

.card h3 a:hover {
  color: var(--accent);
  border-color: var(--accent);
}

/* ---------- approche ---------- */

.steps {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1.25rem;
  counter-reset: etape;
}

@media (max-width: 860px) {
  .steps { grid-template-columns: 1fr; }
}

.steps li {
  counter-increment: etape;
  position: relative;
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  padding: 1.5rem;
}

/* Le numero se range dans le coin, sur la ligne du titre. Plus gros, plus
   discret en couleur : il numerote, il n'annonce pas.
   AUCUN box-shadow ici — un halo sur une boite de texte dessine un rectangle
   autour du chiffre, ce qui etait le defaut de la premiere version. */
.steps li::before {
  content: counter(etape, decimal-leading-zero);
  position: absolute;
  top: 1.5rem;
  right: 1.5rem;
  font-size: 1.15rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  line-height: 1;
  color: var(--accent-clair);
  opacity: 0.5;
}

.steps h3 { padding-right: 2.6rem; }

/* Meme surbrillance au survol que les autres cartes. Elle manquait ici : les
   quatre etapes se comportaient differemment du reste de la page sans raison. */
.steps li {
  transition: border-color 0.25s ease, background 0.25s ease;
}

.steps li:hover {
  border-color: rgba(170, 190, 225, 0.3);
  background: rgba(255, 255, 255, 0.055);
}

.steps h3 {
  font-size: 1.05rem;
  margin-bottom: 0.35rem;
}

.steps p {
  color: var(--muted);
  font-size: 0.95rem;
}

/* ---------- pages secondaires : acces, 404 ---------- */

.section-narrow {
  min-height: 60vh;
  padding-top: clamp(3rem, 12vh, 6rem);
}

.section-narrow h1 {
  font-size: clamp(1.9rem, 4vw, 2.75rem);
  letter-spacing: -0.02em;
  margin-bottom: 1rem;
}

.access-list {
  list-style: none;
  margin-top: 2rem;
  display: grid;
  gap: 0.75rem;
  max-width: 30rem;
}

.access-list li {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  padding: 1.1rem 1.4rem;
  transition: border-color 0.25s ease;
}

.access-list li:hover { border-color: rgba(170, 190, 225, 0.32); }

.access-list a {
  font-weight: 600;
  color: var(--text);
  text-decoration: none;
}

.access-list a:hover { color: var(--accent); }

.access-list span {
  font-size: 0.88rem;
  color: var(--muted);
}

/* ---------- le ciel ----------
   Des etoiles, pas une trame. La premiere version etait une grille reguliere
   de points identiques : ca se lisait comme du papier quadrille. Ici les
   positions sont irregulieres et les tailles varient.
   Le scintillement est en CSS, avec une phase differente par etoile — l'idee
   vient du fond de Nina, ou chaque grain porte sa propre phase et ou rien
   n'est jamais synchrone. Mais Nina tourne un canvas en boucle permanente ;
   ici, apres la creation, il n'y a AUCUNE boucle JavaScript. */

.ciel {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  overflow: hidden;
}

.etoile {
  position: absolute;
  border-radius: 50%;
  background: #dbe6fa;
  opacity: var(--o);
  will-change: opacity;
}

/* L'etoile la plus proche du curseur, et elle seule. Elle s'allume vite
   (0,25 s) et s'eteint lentement (0,9 s) : c'est l'extinction lente qui rend
   l'effet doux au lieu de nerveux quand la souris traverse le ciel.
   Aucun deplacement, aucune trainee — juste une etoile qui se remarque. */
.etoile.proche {
  opacity: 1;
  transform: scale(1.9);
  box-shadow: 0 0 7px rgba(219, 230, 250, 0.75);
  /* Sur une etoile qui scintille, l'animation ecraserait cette opacite : en
     CSS une animation prime toujours sur une regle normale. On la coupe le
     temps qu'elle soit la plus proche, elle reprend apres. */
  animation-name: none;
}

.etoile {
  transition: opacity 0.9s ease, transform 0.9s ease, box-shadow 0.9s ease;
}

.etoile.proche {
  transition: opacity 0.25s ease, transform 0.25s ease, box-shadow 0.25s ease;
}

/* La plupart du temps l'etoile se tient tranquille ; elle ne s'allume qu'un
   instant, tres bref, sur un cycle long. C'est ce qui fait « une etoile qui
   apparait » plutot que « des points qui clignotent ». */
@media (prefers-reduced-motion: no-preference) {
  .etoile.vive { animation: scintille var(--d) ease-in-out var(--r) infinite; }
}

@keyframes scintille {
  0%, 90%, 100% { opacity: var(--o); }
  95%           { opacity: 1; }
}

/* Sur mobile, le ciel reste mais ne scintille pas : moins de travail pour la
   batterie, et l'effet ne se voit pas sur un petit ecran de toute facon. */
@media (hover: none), (pointer: coarse) {
  .etoile.vive { animation: none; }
}

/* L'onde du portail : une seule traversee, declenchee au clic sur le mot
   « Provolu » du pied de page. Elle n'existe pas au repos. */
.onde-portail {
  position: fixed;
  inset: -25% -50%;
  z-index: -1;
  pointer-events: none;
  opacity: 0;
  background: radial-gradient(closest-side,
    rgba(159, 182, 216, 0.26), rgba(120, 150, 200, 0.10) 55%, transparent 78%);
}

body.vers-portail .onde-portail {
  animation: onde-portail 1.05s cubic-bezier(.33,.0,.2,1) both;
}

@keyframes onde-portail {
  0%   { opacity: 0;    transform: translateY(38%) scale(0.6); }
  22%  { opacity: 0.85; }
  100% { opacity: 0;    transform: translateY(-34%) scale(1.4); }
}

@media (prefers-reduced-motion: reduce) {
  body.vers-portail .onde-portail { animation: none; }
}

/* ---------- portail clients ---------- */

/* Une seule commande de navigation, et elle se voit. Le mot ET la croix :
   la croix seule laisse deviner, le mot seul se perd dans une barre. Hauteur
   44 px, le minimum pour une cible tactile qu'on atteint du pouce.
   L'action de compte (« Se deconnecter ») descend dans le contenu : deux
   commandes dans la barre se disputaient le meme geste. */
.fermer {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  min-height: 44px;
  padding: 0 0.5rem 0 1rem;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  color: var(--text) !important;
  text-decoration: none;
  font-size: 0.92rem;
  font-weight: 600;
  transition: border-color 0.25s ease, background 0.25s ease;
}

.fermer:hover,
.fermer:focus-visible {
  border-color: rgba(170, 190, 225, 0.5);
  background: rgba(255, 255, 255, 0.05);
}

.fermer-x {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.07);
  font-size: 1.25rem;
  line-height: 1;
}

/* Sur mobile la barre est etroite : la croix suffit, elle est universelle. */
@media (max-width: 480px) {
  .fermer-mot { display: none; }
  .fermer { padding: 0 0.4rem; }
}

.lien-sobre {
  color: var(--muted);
  font-size: 0.92rem;
}

.lien-sobre:hover { color: var(--text); }

.form-portail {
  display: grid;
  gap: 1rem;
  max-width: 22rem;
  margin-top: 2rem;
}

.champ { display: grid; gap: 0.4rem; }

.champ span {
  font-size: 0.85rem;
  color: var(--muted);
}

.champ input {
  font: inherit;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: 12px;
  padding: 0.7rem 0.9rem;
}

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

.form-portail .cta {
  justify-self: start;
  border: 0;
  cursor: pointer;
  font: inherit;
  font-weight: 600;
}

.form-portail .cta:disabled { opacity: 0.6; cursor: default; }

/* Rouge lisible sur noir : #ff6b6b tient le contraste, pas un rouge pur. */
.erreur {
  color: #ff8f8f;
  font-size: 0.92rem;
  margin: 0;
}

.message {
  color: #9fe6c4;
  font-size: 0.92rem;
  margin: 0;
  max-width: 34ch;
}

.oubli { margin-top: 1.1rem; }

.grille-espaces {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
  gap: 1rem;
  margin: 2rem 0 1.5rem;
}

.espace {
  display: grid;
  justify-items: center;
  gap: 0.35rem;
  text-align: center;
  text-decoration: none;
  padding: 1.6rem 1rem;
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  transition: border-color 0.25s ease, background 0.25s ease;
}

.espace:hover {
  border-color: rgba(170, 190, 225, 0.35);
  background: rgba(255, 255, 255, 0.055);
}

.espace-marque {
  width: 34px;
  height: 34px;
  color: var(--accent-clair);
  margin-bottom: 0.4rem;
}

.espace-marque svg { width: 100%; height: 100%; display: block; }

.espace-nom {
  font-weight: 600;
  font-size: 1.02rem;
  color: var(--text);
}

.espace-detail {
  font-size: 0.85rem;
  color: var(--muted);
}

.portail-note { margin-top: 2rem; font-size: 0.92rem; }

/* ---------- prose et contact ---------- */

.prose {
  max-width: 62ch;
  color: var(--muted);
  font-size: 1.05rem;
}

.prose + .prose { margin-top: 1rem; }

.contact-actions { margin-top: 1.75rem; }

/* ================= la bibliotheque de realisations =================
   Ajoutee le 2026-08-15. Deux surfaces pour un meme contenu :
   trois apercus sur l'accueil (#realisations) et les fiches completes sur
   /realisations/ et /en/work/.

   PAS DE GENERATEUR, et ce n'est pas de la paresse : le site n'a aucun build
   (D-039) et le contenu des realisations doit exister dans le HTML servi,
   sinon un moteur de recherche ne lit qu'une page vide. Rendre les cartes en
   JavaScript aurait rendu invisible exactement ce qu'on publie pour etre vu.
   Ajouter une huitieme realisation = un bloc <article class="real real-08">
   dans les deux pages + trois lignes de CSS ici (--marque, --teinte).

   UNE MARQUE PAR REALISATION, pas une icone de banque d'images. SVG en
   masque : la couleur vient du CSS (`--teinte`), donc chaque entree porte sa
   nuance sans dupliquer le fichier. Les nuances restent DANS la famille du
   logo — indigo, violet, lavande. Une carte verte ou ambre ferait une
   collection, pas une marque. */

.real-marque {
  display: block;
  width: 34px;
  height: 34px;
  flex: none;
}

/* Sans le masque, rien ne s'affiche — jamais un carre violet plein. */
@supports ((-webkit-mask-image: none) or (mask-image: none)) {
  .real-marque {
    background-color: var(--teinte, var(--accent-clair));
    -webkit-mask: var(--marque) center / contain no-repeat;
    mask: var(--marque) center / contain no-repeat;
  }
}

.real-01 { --teinte: #7d6dff;
  --marque: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' fill='none' stroke='%23fff' stroke-width='6' stroke-linecap='round'%3E%3Ccircle cx='18' cy='24' r='7' fill='%23fff' stroke='none'/%3E%3Cpath d='M38 24h48'/%3E%3Ccircle cx='18' cy='50' r='7' fill='%23fff' stroke='none'/%3E%3Cpath d='M38 50h48'/%3E%3Ccircle cx='18' cy='76' r='7'/%3E%3Cpath d='M38 76h30'/%3E%3C/svg%3E");
}
.real-02 { --teinte: #9a7bfd;
  --marque: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' fill='none' stroke='%23fff' stroke-width='6' stroke-linecap='round'%3E%3Crect x='9' y='13' width='44' height='74' rx='9'/%3E%3Cpath d='M23 36h16M23 54h16'/%3E%3Ccircle cx='84' cy='28' r='8' fill='%23fff' stroke='none'/%3E%3Ccircle cx='84' cy='54' r='8' fill='%23fff' stroke='none'/%3E%3Ccircle cx='84' cy='80' r='8' fill='%23fff' stroke='none'/%3E%3C/svg%3E");
}
.real-03 { --teinte: #b083fa;
  --marque: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' fill='none' stroke='%23fff' stroke-width='6' stroke-linecap='round'%3E%3Crect x='9' y='17' width='82' height='66' rx='11'/%3E%3Cpath d='M9 39h82'/%3E%3Ccircle cx='24' cy='28' r='4' fill='%23fff' stroke='none'/%3E%3Cpath d='M28 60h44'/%3E%3C/svg%3E");
}
.real-04 { --teinte: #c9d8ef;
  --marque: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' fill='none' stroke='%23fff' stroke-width='6' stroke-linecap='round'%3E%3Cpath d='M16 76a38 38 0 1 1 68 0'/%3E%3Cpath d='M50 70 70 42'/%3E%3Ccircle cx='50' cy='72' r='7' fill='%23fff' stroke='none'/%3E%3C/svg%3E");
}
.real-05 { --teinte: #cb95f9;
  --marque: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' fill='none' stroke='%23fff' stroke-width='6' stroke-linecap='round'%3E%3Ccircle cx='23' cy='27' r='11'/%3E%3Ccircle cx='77' cy='27' r='11'/%3E%3Ccircle cx='50' cy='77' r='11' fill='%23fff' stroke='none'/%3E%3Cpath d='M34 27h32M31 36l12 30M69 36 57 66'/%3E%3C/svg%3E");
}
.real-06 { --teinte: #d5a6f7;
  --marque: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' fill='none' stroke='%23fff' stroke-width='9' stroke-linecap='round'%3E%3Cpath d='M17 84V63M39 84V47M61 84V71M83 84V38'/%3E%3Ccircle cx='83' cy='19' r='8' fill='%23fff' stroke='none'/%3E%3C/svg%3E");
}
.real-08 { --teinte: #8f74fe; }  /* MyQuotaBag (2026-08-31) — teinte propre,
   entre real-01 et real-02 : la gamme reste une progression. Les classes
   real-0X portent la TEINTE d'un cas, jamais sa position : reordonner la
   page ne les change pas. */
.real-07 { --teinte: #dfb8f5;
  --marque: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' fill='none' stroke='%23fff' stroke-width='5' stroke-linecap='round'%3E%3Ccircle cx='50' cy='50' r='12' fill='%23fff' stroke='none'/%3E%3Ccircle cx='50' cy='50' r='33' opacity='.55'/%3E%3Ccircle cx='50' cy='17' r='8' fill='%23fff' stroke='none'/%3E%3Ccircle cx='79' cy='67' r='8' fill='%23fff' stroke='none'/%3E%3Ccircle cx='21' cy='67' r='8' fill='%23fff' stroke='none'/%3E%3C/svg%3E");
}

/* Le sommaire : sept ancres en haut de page. Chaque fiche occupe presque un
   ecran ; sans lui, on descend sans savoir combien il en reste ni ce qui
   vient. C'est aussi ce qui permet d'envoyer quelqu'un directement sur la
   bonne realisation. (revue lea, 2026-08-15) */
.real-sommaire {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 2rem;
}

.real-sommaire a {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 40px;
  padding: 0.35rem 0.9rem;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  font-size: 0.88rem;
  color: var(--muted);
  text-decoration: none;
  transition: border-color 0.25s ease, color 0.25s ease, background 0.25s ease;
}

.real-sommaire a:hover,
.real-sommaire a:focus-visible {
  color: var(--text);
  border-color: rgba(170, 190, 225, 0.45);
  background: rgba(255, 255, 255, 0.05);
}

.real-sommaire b {
  font-weight: 700;
  font-size: 0.76rem;
  letter-spacing: 0.06em;
  color: var(--teinte, var(--accent-clair));
}

/* ---------- l'apercu sur l'accueil ---------- */

/* Le texte d'introduction s'arrete avant les cartes : sur l'accueil on
   explique une fois, on montre trois fois, et on envoie vers la page. */
/* Le titre de la section tient sur deux lignes plutot qu'une seule qui va
   d'un bord a l'autre sur un grand ecran. */
#realisations h2, #work h2 { max-width: 26ch; }

.real-lede {
  max-width: 62ch;
  margin-bottom: clamp(1.75rem, 4vh, 2.5rem);
  color: var(--muted);
  font-size: 1.05rem;
}

.real-lede + .real-lede { margin-top: -1rem; }

/* LA CARTE ENTIERE EST LA CIBLE, pas seulement le titre. Le survol allumait
   la bordure d'un bloc dont un seul mot etait cliquable, et le soulignement
   du lien est a peine visible sur ce fond ; en tactile, ou il n'y a pas de
   survol du tout, la porte disparaissait completement. Le lien du titre
   s'etend sur toute la carte par un ::after transparent : cible tactile
   enorme, aucun JavaScript, et le titre reste le libelle lu par un lecteur
   d'ecran. (revue lea, 2026-08-15) */
.real-apercu { position: relative; }

.real-apercu h3 a::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: var(--radius);
}

.real-apercu h3 a:focus-visible::after {
  outline: 2px solid var(--accent-clair);
  outline-offset: 3px;
}

.real-apercu .real-marque { margin-bottom: 1rem; }

/* Deux lignes reservees a la categorie, meme quand elle en tient une seule :
   sans cette reserve, « Donnees » remonte son titre d'une ligne et les trois
   cartes ne s'alignent plus. */
.real-apercu .real-categorie {
  margin-bottom: 0.5rem;
  min-height: 2.4em;
}

@media (max-width: 860px) {
  .real-apercu .real-categorie { min-height: 0; }
}

/* La rangee d'appel sous les apercus. Le lien vers la page complete ne se
   cache jamais derriere une carte : c'est la porte de la bibliotheque. */
.real-plus {
  margin-top: clamp(1.75rem, 4vh, 2.5rem);
}

/* ---------- la page complete ---------- */

.real-categorie {
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--teinte, var(--accent-clair));
}

.real-liste {
  display: grid;
  gap: 1.25rem;
}

.real {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  padding: 1.75rem 1.5rem;
  transition: border-color 0.25s ease, background 0.25s ease;
}

/* PAS DE :hover ICI, et c'est voulu. Une fiche de /realisations/ n'ouvre
   rien : allumer sa bordure au passage de la souris promettait un clic qui
   n'existe pas. Le survol reste reserve a ce qui est cliquable — les apercus
   de l'accueil. (revue lea, 2026-08-15) */

/* Le numero se range dans le coin, comme celui des etapes de « Notre
   approche » : meme langage, donc aucune convention nouvelle a apprendre. */
.real-numero {
  position: absolute;
  top: 1.75rem;
  right: 1.5rem;
  font-size: 1.15rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  line-height: 1;
  color: var(--teinte, var(--accent-clair));
  opacity: 0.5;
}

.real-tete { padding-right: 3rem; }

.real-tete .real-marque { margin-bottom: 1rem; }

.real h2 {
  font-size: clamp(1.45rem, 3vw, 1.9rem);
  letter-spacing: -0.015em;
  margin: 0.55rem 0 0.5rem;
}

.real-phrase {
  color: var(--text);
  font-size: 1.02rem;
  max-width: 58ch;
}

.real-corps {
  display: grid;
  gap: 1.5rem;
  margin-top: 1.4rem;
}

.real-texte p {
  color: var(--muted);
  font-size: 0.98rem;
  max-width: 62ch;
}

.real-texte p + p { margin-top: 0.85rem; }

.real-cote h3 {
  font-size: 0.82rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 0.7rem;
}

.real-apport {
  list-style: none;
  display: grid;
  gap: 0.4rem;
  font-size: 0.94rem;
  color: var(--muted);
}

.real-apport li {
  position: relative;
  padding-left: 1rem;
}

.real-apport li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--teinte, var(--accent-clair));
  opacity: 0.75;
}

/* Le benefice et la preuve traversent toute la carte, sous les deux colonnes.
   Places dans la colonne de droite, ils l'allongeaient bien au-dela du recit
   et laissaient un vide d'un tiers de carte en bas a gauche. Ce sont aussi
   les deux lignes qu'on retient : elles meritent la pleine largeur. */
.real-pied {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem 2rem;
  margin-top: 0.4rem;
  padding-top: 1.3rem;
  border-top: 1px solid var(--hairline);
}

.real-benefice {
  flex: 1 1 30ch;
  font-size: 1rem;
  color: var(--text);
}

/* La preuve est le seul endroit du site ou un chiffre a le droit d'exister,
   et seulement quand il est reel et demontrable. Une realisation sans chiffre
   verifiable n'en porte pas : mieux vaut aucune preuve qu'une preuve inventee. */
.real-preuve {
  display: inline-flex;
  align-items: baseline;
  gap: 0.6rem;
  flex-wrap: wrap;
  flex: 0 1 34ch;
  padding: 0.6rem 0.9rem;
  border: 1px solid rgba(170, 190, 225, 0.32);
  border-radius: 12px;
  background: rgba(159, 182, 216, 0.08);
  font-size: 0.92rem;
  color: var(--text);
}

.real-preuve b {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent-clair);
}

/* Sur grand ecran, le recit a gauche et ce qu'on retient a droite. Sous
   860 px tout s'empile dans l'ordre de lecture : recit, apport, benefice. */
@media (min-width: 860px) {
  .real { padding: 2.25rem 2.25rem; }
  .real-numero { top: 2.25rem; right: 2.25rem; font-size: 1.4rem; }
  /* 1,15fr et non 1,35 : le recit occupe moins de largeur, donc plus de
     lignes, et les deux colonnes finissent a peu pres a la meme hauteur.
     C'est ce qui ferme le vide en bas a gauche sans rien deplacer. */
  .real-corps {
    grid-template-columns: 1.15fr 1fr;
    gap: 2.5rem;
  }
  .real-cote {
    border-left: 1px solid var(--hairline);
    padding-left: 2rem;
  }
  .real-pied { margin-top: 0.6rem; padding-top: 1.6rem; }
}

/* Le fil de retour vers l'accueil, en haut de la page interieure. */
.fil {
  font-size: 0.9rem;
  color: var(--muted);
  margin-bottom: 1.25rem;
}

.fil a {
  color: var(--muted);
  text-decoration: none;
  border-bottom: 1px solid var(--hairline);
}

.fil a:hover { color: var(--text); }

.page-tete {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: clamp(2.5rem, 7vh, 4.5rem) clamp(1.25rem, 4vw, 2.5rem) 0;
}

.page-tete h1 {
  font-size: clamp(2rem, 5vw, 3.1rem);
  line-height: 1.12;
  letter-spacing: -0.02em;
  max-width: 20ch;
  color: #ffffff;
  background: linear-gradient(180deg, #ffffff 30%, #c9d8ef 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

.page-tete .prose { margin-top: 1.5rem; }

/* La page interieure n'a pas de hero anime : elle s'ouvre en une fois, sans
   sequence. Une bibliotheque se consulte, elle ne se met pas en scene. */
@media (prefers-reduced-motion: no-preference) {
  .page-tete > * { animation: monte 0.7s cubic-bezier(.22,.61,.36,1) both; }
  .page-tete .prose { animation-delay: 0.12s; }
}

/* ---------- pied de page ---------- */

.footer {
  border-top: 1px solid var(--hairline);
  margin-top: clamp(2rem, 6vh, 4rem);
  padding: 2.5rem clamp(1.25rem, 4vw, 2.5rem);
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 2rem;
  justify-content: space-between;
  font-size: 0.9rem;
  color: var(--muted);
}

.wordmark-small {
  font-weight: 600;
  font-size: 0.95rem;
  color: var(--text);
}

.footer a {
  color: var(--muted);
  text-decoration: none;
  border-bottom: 1px solid var(--hairline);
}

.footer a:hover { color: var(--text); }

/* Pied de page : ce qui identifie a gauche, la signature a droite.
   Les losanges d'acces direct ont ete retires le 2026-08-11 — c'est le mot
   « Provolu » a droite qui ouvre le portail, sans rien annoncer. */
.footer-bloc {
  display: flex;
  align-items: baseline;
  gap: 1.25rem;
}

.footer-droite { justify-content: flex-end; }

/* Meme gris que « Quebec, Canada » : l'adresse informe, elle n'appelle pas. */
.footer-courriel {
  color: var(--muted) !important;
  border-bottom: 0 !important;
}

.footer-courriel:hover { color: var(--text) !important; }

.footer a.wordmark-small {
  border-bottom: 0;
  text-decoration: none;
  transition: color 0.25s ease;
}

.footer a.wordmark-small:hover { color: var(--accent-clair); }

/* ================= la choregraphie =================
   Une seule regle : ca joue UNE fois, puis c'est immobile. Aucune boucle,
   nulle part. Le site doit avoir l'air pense, pas anime.

   Tout est en CSS, y compris les revelations au defilement
   (`animation-timeline`). Un navigateur qui ne le supporte pas affiche la
   page complete et parfaitement fixe — c'est une degradation vers l'etat
   qu'on veut de toute facon, jamais vers du contenu invisible. C'est ce qui
   permet de garder zero JavaScript sur le site. */

@media (prefers-reduced-motion: no-preference) {

  /* --- l'ouverture, au chargement --- */

  .hero > * { animation: monte 0.8s cubic-bezier(.22,.61,.36,1) both; }
  .hero-symbole { animation: symbole-entre 1.9s cubic-bezier(.22,.61,.36,1) both; }
  .hero h1   { animation-delay: 0.34s; }
  .hero .lede { animation-delay: 0.46s; }
  .hero .cta  { animation-delay: 0.58s; }

  @keyframes monte {
    from { opacity: 0; transform: translateY(12px); }
    to   { opacity: 1; transform: none; }
  }

  /* Le P arrive, puis deux petites respirations — il grossit et redescend,
     deux fois, de moins de 4 %. Assez pour qu'on sente quelque chose, pas
     assez pour qu'on dise « ca bouge ». */
  @keyframes symbole-entre {
    0%   { opacity: 0; transform: translateY(16px) scale(0.94); }
    38%  { opacity: 1; transform: translateY(0) scale(1.035); }
    55%  { transform: scale(0.992); }
    72%  { transform: scale(1.019); }
    88%  { transform: scale(0.998); }
    100% { opacity: 1; transform: none; }
  }

  /* Deux reflets dans le ruban, ralentis encore de moitie (5s -> 7,5s).
     `both` fige l'etat final a opacity 0 : le reflet ne revient jamais. */
  .hero-symbole::after {
    animation: impulsion 7.5s ease-in-out 1.1s both;
  }

  @keyframes impulsion {
    0%   { opacity: 0; background-position: 180% 0; }
    14%  { opacity: 0.55; }
    38%  { opacity: 0; background-position: -80% 0; }
    50%  { opacity: 0; background-position: 180% 0; }
    62%  { opacity: 0.34; }
    88%, 100% { opacity: 0; background-position: -80% 0; }
  }

  /* UNE SEULE vague. La version precedente en faisait deux — elle passait,
     revenait, et ca se remarquait. Une traversee, puis plus rien. */
  body::after {
    content: "";
    position: fixed;
    inset: -20% -50%;
    z-index: -1;
    pointer-events: none;
    opacity: 0;
    background: radial-gradient(closest-side,
      rgba(120, 150, 200, 0.22), rgba(109, 91, 255, 0.09) 55%, transparent 78%);
    animation: onde 4.4s ease-out 1.3s both;
  }

  @keyframes onde {
    0%   { opacity: 0;    transform: translateY(-40%) scale(0.55); }
    16%  { opacity: 0.5; }
    100% { opacity: 0;    transform: translateY(46%) scale(1.5); }
  }

  /* --- les revelations, au defilement --- */

  @supports (animation-timeline: view()) {
    /* Deux animations sur la meme carte : elle monte, et son contour s'allume
       une fois. Le decalage se fait par la PLAGE, pas par un delai — avec une
       animation pilotee par le defilement, un `animation-delay` ne veut rien
       dire. Les cartes d'une meme rangee entrent a l'ecran ensemble ; sans ce
       decalage elles s'allumeraient toutes d'un coup. */
    .card, .steps li, .real {
      animation: monte 0.6s ease both, contour 0.9s ease both;
      animation-timeline: view(), view();
      animation-range: entry 5% cover 22%, entry 6% cover 26%;
    }

    .card:nth-child(2), .steps li:nth-child(2) {
      animation-range: entry 5% cover 22%, entry 11% cover 31%;
    }
    .card:nth-child(3), .steps li:nth-child(3) {
      animation-range: entry 5% cover 22%, entry 16% cover 36%;
    }
    .card:nth-child(4), .steps li:nth-child(4) {
      animation-range: entry 5% cover 22%, entry 21% cover 41%;
    }

    /* Les realisations arrivent une par une, jamais en rangee : le decalage
       par nth-child ne s'applique donc pas a elles. Chacune occupe presque
       tout l'ecran, elle se revele quand c'est son tour. */

    /* Discret : le contour passe par un violet tenu, jamais par un flash, et
       revient exactement a son etat de repos. Une seule fois. */
    @keyframes contour {
      0%   { border-color: var(--hairline); }
      45%  { border-color: rgba(201, 216, 239, 0.45); }
      100% { border-color: var(--hairline); }
    }

    /* La marque de la realisation se leve juste apres sa carte. Aucune ombre :
       un box-shadow sur une forme masquee dessine le rectangle du masque, pas
       la forme. C'est la lecon du point qu'elle remplace, appliquee a
       l'envers. */
    .real-marque {
      animation: reveil-marque 0.7s ease both;
      animation-timeline: view();
      animation-range: entry 12% cover 30%;
    }

    @keyframes reveil-marque {
      from { opacity: 0; transform: translateY(5px); }
      to   { opacity: 1; transform: none; }
    }

    /* Le numero monte simplement. Aucune ombre. */
    .steps li::before {
      animation: reveil-numero 0.7s ease both;
      animation-timeline: view();
      animation-range: entry 12% cover 30%;
    }

    @keyframes reveil-numero {
      from { opacity: 0; transform: translateY(6px); }
      to   { opacity: 0.5; transform: none; }
    }

    /* LE FILAMENT A ETE RETIRE le 2026-08-11. L'idee etait jolie sur papier —
       un trait violet descendant au rythme du defilement — mais a l'usage
       c'est une ligne qui bouge au milieu de l'ecran pendant qu'on lit.
       Sebastien : « c'est desagreable ». Ne pas le remettre : ce qui distrait
       de la lecture perd, meme quand c'est la plus belle idee du lot. */
  }
}

/* ═══ LE BANDEAU DE L'ARCHIVE (/ancien/) — 2026-08-30 ═══
   Il vit ici et NON dans accueil.css : /ancien/ ne charge que cette
   feuille. Ecrit d'abord avec la classe `.tag`, il n'avait aucun style —
   `.tag` n'existe que dans accueil.css, que cette page ne charge pas.
   Defaut releve par lea et iris a l'audit de la bascule. Une regle qui ne
   s'applique jamais est pire qu'une regle absente : on la croit posee. */
#bandeau-archive {
  margin: 0;
  padding: 0.7rem clamp(1.25rem, 4vw, 2.5rem);
  background: var(--accent-soft);
  border-bottom: 1px solid var(--hairline);
  color: var(--muted);
  font-size: 0.9rem;
  line-height: 1.45;
  text-align: center;
}
#bandeau-archive a { color: var(--accent-clair); }


/* ================================================================
   LA SALVE EDITORIALE DU 2026-08-31 (brief maitre) — hero a deux
   gestes, trois vitrines visuelles, formulaire de contact.
   Dans styles.css parce que ces blocs servent la vraie page ET la
   version anglaise : une seule ecriture, deux pages.
   ================================================================ */

/* --- le hero : deux CTA cote a cote, le second en retrait --- */
.hero-actions { display: flex; gap: 0.9rem; justify-content: center; flex-wrap: wrap; }

/* ================= la scene du haut : montagnes, nuages, le P =================
   Reprise le 2026-09-14 en fin d'apres-midi, sur la demande de Sebastien :
   « juste les montagnes avec le P ». Ce qu'on voit en arrivant : deux
   reliefs, des nuages, et le P DEJA LA entre les deux — mais voile par deux
   nuages posés devant lui. Rien d'autre : pas de titre dans la scene.
   Quand on descend : les deux nuages du devant se tassent vers l'exterieur
   et se dissipent, le P se degage, monte et grandit un peu ; le relief
   proche DESCEND pendant que les lointains montent — la camera s'eleve
   au-dessus de la crete, c'est ce qui rend les deux vitesses perceptibles ;
   un nuage bas traverse devant le relief proche ; les etoiles s'eteignent. Le titre arrive apres, dans
   .hero-suite, a la descente.

   MECANIQUE (scene.js) : une progression p de 0 a 1 sur la hauteur du
   voyage (.scene-haut, 210vh) pendant que la scene reste collee (.scene-fixe,
   100vh). Chaque plan monte de data-y x p et derive de data-x x p — des
   deplacements TOTAUX, pas des vitesses par pixel. Les nuages .voile-p
   perdent toute leur opacite sur les 60 premiers % du voyage. Rien ne bouge
   quand on arrete. Sans JS ou en mouvement reduit : la composition fixe
   ci-dessous, les opacites par --o — le P reste voile, c'est voulu, la
   scene est belle immobile aussi. Les images sont celles de Sebastien
   (marque/), telles quelles, converties en WebP alpha. */
.hero.scene-haut {
  max-width: none;
  padding: 0;
  height: 210vh;
  min-height: 1200px;
  overflow: visible;
  isolation: auto;
}
.vraie .hero.scene-haut { overflow: visible; }
.scene-haut > * { max-width: none; margin: 0; }
.scene-fixe {
  position: sticky;
  top: 0;
  height: 100vh;
  min-height: 650px;
  overflow: hidden;
  isolation: isolate;
  background: radial-gradient(ellipse at 50% 48%, #172133 0, #0b101e 35%, #060812 72%);
}
.scene-plans { position: absolute; inset: 0; pointer-events: none; }
/* L'OUVERTURE N'EST PAS SECHE (Sebastien, 14 au soir) : tout est la — les
   montagnes, les nuages, le P voile — et tout se leve ENSEMBLE, en un seul
   fondu de 1,6 s. Pas d'apparition plan par plan. */
@media (prefers-reduced-motion: no-preference) {
  .scene-plans { animation: scene-nait 1.6s ease both; }
  @keyframes scene-nait { from { opacity: 0; } to { opacity: 1; } }
}
.scene-etoiles { position: absolute; inset: 0; z-index: 0; }
.scene-etoiles i {
  position: absolute;
  border-radius: 50%;
  background: #dbe6fa;
  width: var(--t, 1.4px);
  height: var(--t, 1.4px);
  opacity: var(--o, 0.5);
}
.plan {
  position: absolute;
  height: auto;
  max-width: none;
  opacity: var(--o);
  will-change: transform, opacity;
}
.plan-miroir { position: absolute; inset: 0; transform: scaleX(-1); pointer-events: none; }
.nuage { -webkit-mask-image: radial-gradient(ellipse at center, #000 28%, transparent 69%); mask-image: radial-gradient(ellipse at center, #000 28%, transparent 69%); }
/* du fond vers l'avant : un nuage haut et lointain · les deux reliefs
   lointains · LE P · les deux nuages qui le voilent · le relief proche · un
   nuage bas · le voile du bas */
.nuage-a     { --o: .16; width: 50%;  left: -8%;  bottom: 58%;  z-index: 1; filter: brightness(.60); }
.mont-loin   { --o: .82; width: 110%; left: -12%; bottom: 16%;  z-index: 2; filter: brightness(.66) contrast(.78) saturate(.7); }
.mont-loin-d { --o: .55; width: 82%;  left: -30%; bottom: 20%;  z-index: 2; filter: brightness(.52) contrast(.78) saturate(.7); }
.p-glace     { --o: .95; width: 21%;  left: 39.5%; bottom: 19%; z-index: 3; filter: drop-shadow(0 0 28px rgba(160, 190, 240, 0.28)); transform-origin: 50% 60%; }
.nuage-b     { --o: .80; width: 62%;  left: 14%;  bottom: 17%;  z-index: 4; filter: brightness(.80); }
.nuage-c     { --o: .84; width: 78%;  left: 22%;  bottom: 4%;  z-index: 4; filter: brightness(.74); transform-origin: 50% 50%; }
/* la nappe de brume entre les deux chaines : elle suit la crete proche a
   mi-vitesse et couvre le pied fondu du relief lointain quand ils se separent */
.brume       { --o: 1;   width: 150%; left: -25%; height: 34%; bottom: 14%; z-index: 4; background: radial-gradient(ellipse 50% 50% at 50% 60%, rgba(150, 166, 194, 0.30) 0, rgba(120, 135, 165, 0.16) 40%, transparent 100%); }
.mont-proche { --o: 1;   width: 100%; left: 0;    bottom: -2%; z-index: 5; filter: brightness(.50) contrast(1.02); }
.nuage-d     { --o: .34; width: 58%;  left: 78%;  bottom: 2%;   z-index: 6; filter: brightness(.55); }
.scene-voile {
  position: absolute; inset: 0; z-index: 7;
  background: linear-gradient(#06081200 45%, #06081216 62%, #060812b8 87%, #060812 100%);
}
.scene-indice {
  position: absolute; bottom: 30px; left: 0; width: 100%; z-index: 12;
  text-align: center; font-size: 0.68rem; letter-spacing: 0.14em; text-transform: uppercase;
  color: #9aa9c0;
}
.scene-indice span {
  display: inline-block; width: 1px; height: 26px; vertical-align: middle; margin-right: 12px;
  background: linear-gradient(#d3e0f7, transparent);
}
/* LE HERO APRES LA SCENE : le titre, la phrase, le bouton — sur le noir,
   centres, une hauteur d'ecran. Ils se revelent (.venir) quand la section
   entre, comme les autres sections de la vraie page. */
.hero.hero-suite {
  position: relative;
  z-index: 1;
  min-height: 82vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  padding: clamp(4rem, 10vh, 7rem) 1.25rem clamp(3rem, 8vh, 5rem);
  background: var(--bg);
}
.hero-suite h1 { max-width: none; }
.hero-suite h1 span { display: block; color: #b6c7e1; }
.hero-suite .lede { max-width: 46ch; }
@media (max-width: 700px) {
  .hero.scene-haut { height: 170vh; min-height: 1050px; }
  .scene-fixe { min-height: 660px; }
  .nuage-a     { width: 90%;  left: -30%; bottom: 72%; }
  .mont-loin   { width: 300%; left: -80%; bottom: 17%; }
  .mont-loin-d { width: 260%; left: -150%; bottom: 21%; }
  .p-glace     { width: 46%;  left: 27%;  bottom: 39%; }
  .nuage-b     { width: 140%; left: -40%; bottom: 35%; }
  .nuage-c     { width: 175%; left: -30%; bottom: 22%; }
  .brume       { width: 220%; left: -60%; height: 34%; bottom: 14%; background: radial-gradient(ellipse 50% 50% at 50% 60%, rgba(150, 166, 194, 0.34) 0, rgba(120, 135, 165, 0.17) 40%, transparent 100%); }
  .mont-proche { width: 320%; left: -110%; bottom: -1%; }
  .nuage-d     { width: 110%; left: 70%;  bottom: 0; }
  .scene-voile { background: linear-gradient(transparent 70%, #06081244 86%, #060812cc 100%); }
  .hero.hero-suite { min-height: 70vh; }
}
.vraie .hero-suite + .respire-noir { height: 8vh; }

/* ================= le texte qui s'allume (Fora, « Intro ») =================
   Les mots de la phrase signature passent du gris au blanc a mesure qu'on
   descend, sous une pastille dont le point pulse. scene.js decoupe les mots ;
   sans JS, le texte est blanc d'emblee. */
.mot { color: #505b70; transition: color 0.2s; }
.mot.on { color: #e7edf8; }
.pastille::before {
  content: ""; display: inline-block; width: 7px; height: 7px; border-radius: 50%;
  background: #eef2f8; margin-right: 0.6rem; vertical-align: middle;
  animation: pastille-bat 2.4s ease-in-out infinite;
}
@keyframes pastille-bat { 0%, 100% { opacity: 0.25; } 50% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .pastille::before { animation: none; opacity: 1; } .mot { color: #e7edf8; } }

/* ================= la fin premium : la fin des montagnes, puis le noir absolu =================
   Sebastien, 14 au soir : « le pied de page c'est correct, mais le bas de
   page, on va etre dans le noir absolu. Le haut, on va voir la fin des
   montagnes, qu'on va remettre un petit. » Donc : une bande ou ne depassent
   que les sommets, le P petit au-dessus, un voile vers le noir, et tout ce
   qui suit sur #000. Memes fichiers que le haut, deja charges. */
.fin-premium { position: relative; overflow: hidden; isolation: isolate; margin-top: clamp(2rem, 6vh, 4rem); background: #000; }
.scene-fin::before { content: ""; position: absolute; inset: 0 0 auto 0; height: 30%; background: linear-gradient(var(--bg), transparent); z-index: 1; }
.scene-fin { position: relative; height: clamp(420px, 68vh, 680px); overflow: hidden; pointer-events: none; z-index: 0;
  background: radial-gradient(ellipse at 50% 100%, #172133 0, #0b101e 45%, #060812 75%, #000 100%); }
.scene-fin .plan { position: absolute; }
.scene-fin .fin-loin   { --o: .6;  width: 150%; left: -30%; bottom: -16%; filter: brightness(.5) contrast(.92); }
.scene-fin .fin-proche { --o: .95; width: 140%; left: -20%; bottom: -30%; filter: brightness(.56) contrast(1); }
.scene-fin .fin-p      { --o: .9; width: 11%;  left: 44.5%; bottom: 46%; filter: drop-shadow(0 0 22px rgba(160, 190, 240, 0.25)); }
.scene-fin .fin-nuage  { --o: .22; width: 70%; left: 50%; bottom: -10%; filter: brightness(.6); }
/* le haut du voile est de la couleur de la page, pas noir : sinon une ligne
   nette separait le contact de la fin (pellicule du 14). Le noir absolu
   arrive par le bas. */
.scene-fin .scene-voile { position: absolute; inset: 0; background: linear-gradient(var(--bg) 0%, #06081200 30%, #00000000 55%, #000 100%); }
.fin-appel { position: relative; z-index: 2; text-align: center; padding: clamp(3rem, 8vh, 5rem) 1.25rem clamp(5rem, 12vh, 8rem); background: #000; }
.fin-appel h2 { font-size: clamp(2rem, 4.2vw, 3.2rem); font-weight: 400; letter-spacing: -0.045em; margin-bottom: 1rem; }
.fin-appel p { color: var(--muted); margin-bottom: 1.6rem; }
.fin-premium .footer { position: relative; z-index: 2; background: #000; margin-top: 0; }
@media (max-width: 700px) {
  .scene-fin .fin-loin { width: 230%; left: -65%; bottom: -12%; }
  .scene-fin .fin-proche { width: 240%; left: -70%; bottom: -22%; }
  .scene-fin .fin-p { width: 24%; left: 38%; bottom: 48%; }
}

/* ================= « Reduire au necessaire » reste, la ligne passe au blanc-bleu =================
   Sebastien, 14 au soir : « je garderais ce qu'on avait fait, le reduit au
   necessaire ; la ligne mauve, on la met en blanc-bleu ». La section vit
   dans accueil.css (elle sert aussi l'intro, qu'on ne touche pas) ; ici, on
   ne retinte que sa copie de la vraie page. */
.vraie .ligne {
  background: linear-gradient(90deg,
    rgba(111, 137, 179, 0.25) 0%, #6f89b3 14%, #8aa6cf 34%,
    var(--accent) 52%, #c9d8ef 72%, #e6eefb 88%, rgba(233, 240, 252, 0.3) 100%);
}
.vraie .etapes .noeud { box-shadow: 0 0 14px rgba(159, 182, 216, 0.5); }
/* le courriel de la fin : son soulignement suit la palette */
.vraie .final .courriel { border-bottom-color: rgba(170, 190, 225, 0.5); }
/* le P glace de la fin : sa lueur suit — bleutee, plus mauve */
.vraie .p-vraie .marque-finale { filter: drop-shadow(0 0 30px rgba(160, 190, 240, 0.45)); }

/* ================= le cube libre (« Faire revivre le cube ») =================
   Il flotte par-dessus tout, ne bloque aucun clic, degoutte sans bruit. */
.cube-libre {
  position: fixed;
  top: 0; left: 0;
  width: 58px;
  margin: -29px 0 0 -29px;
  z-index: 60;
  pointer-events: none;
  filter: drop-shadow(0 6px 14px rgba(0, 0, 0, 0.45));
  animation: cube-nait 0.7s cubic-bezier(.22,.61,.36,1) both;
}
.cube-libre img { width: 100%; height: auto; display: block; }
.cube-libre.part { animation: cube-part 0.7s ease both; }
@keyframes cube-nait { from { opacity: 0; scale: 0.6; } to { opacity: 1; scale: 1; } }
@keyframes cube-part { to { opacity: 0; scale: 0.6; } }
.goutte-libre {
  position: absolute; left: 50%; top: 92%;
  width: 4px; height: 7px; margin-left: -2px;
  border-radius: 50% 50% 55% 55%;
  background: rgba(219, 230, 250, 0.85);
  opacity: 0;
}
.goutte-libre.tombe { animation: goutte-tombe 1.1s ease-in both; }
@keyframes goutte-tombe { 0% { opacity: 0; transform: translateY(0); } 15% { opacity: 0.9; } 100% { opacity: 0; transform: translateY(70px); } }
@media (prefers-reduced-motion: reduce) { .cube-libre, .goutte-libre.tombe { animation: none; } }

/* ================= le formulaire a la Fora =================
   « Let's talk. » Titre centre, une phrase, trois champs soulignes sans
   cadre, un bouton. Le bloc est centre (Fora : 720 px, centre). */
.bloc-contact { text-align: center; max-width: 720px; }
.formulaire { text-align: left; margin-top: 2.4rem; gap: 1.6rem; }
.formulaire label span { font-size: 0.82rem; letter-spacing: 0.04em; text-transform: none; color: var(--muted); }
.bloc-contact .formulaire .cta { justify-self: center; }
.contact-pied { justify-content: center; }
.formulaire input,
.formulaire textarea {
  width: 100%;
  padding: 0.7rem 0;
  border-radius: 0;
  border: 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.18);
  background: transparent;
  color: var(--text, #edf1f7);
  font: inherit;
  transition: border-color 0.2s ease;
}
.formulaire input:focus-visible,
.formulaire textarea:focus-visible {
  outline: none;
  border-bottom-color: #c9d8ef;
  box-shadow: none;
}

/* ================= defis complexes (PLAN-FORA.md, chantier 4) ================= */
.defi-corps {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
  gap: clamp(1.6rem, 4vw, 3.2rem);
  align-items: center;
  margin-top: 2.2rem;
}
.defi-texte p { color: var(--muted); max-width: 44ch; }
.defi-texte p + p { margin-top: 0.9rem; }
.defi-schema {
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-radius: 18px;
  padding: clamp(1rem, 2.4vw, 1.6rem);
  background: rgba(255, 255, 255, 0.035);
}
.defi-schema svg { width: 100%; height: auto; display: block; }
.defi-schema .boite { fill: rgba(255, 255, 255, 0.05); stroke: rgba(255, 255, 255, 0.22); }
.defi-schema .boite-forte { fill: rgba(255, 255, 255, 0.10); stroke: rgba(255, 255, 255, 0.5); }
.defi-schema .fil { stroke: rgba(255, 255, 255, 0.34); fill: none; }
.defi-schema text { fill: var(--text); font-size: 11px; font-family: inherit; }
.defi-schema .sourd { fill: var(--sourd); font-size: 9.5px; }
.defi-echelle { margin-top: 1.2rem; font-size: 0.9rem; color: var(--sourd); }
@media (max-width: 860px) { .defi-corps { grid-template-columns: 1fr; } }

/* ================= questions frequentes (PLAN-FORA.md, chantier 4) =================
   <details> natif : aucun JavaScript, ouvert au clavier, lu par tout le
   monde. Une seule question ouverte a la fois n'est PAS impose : deux
   reponses cote a cote se comparent. */
.faq { max-width: 760px; margin: 0 auto; }
.faq details {
  border-top: 1px solid rgba(255, 255, 255, 0.10);
}
.faq details:last-child { border-bottom: 1px solid var(--hairline); }
.faq summary {
  cursor: pointer;
  list-style: none;
  padding: 1.15rem 2.4rem 1.15rem 0;
  font-size: 1.08rem;
  font-weight: 500;
  color: var(--text);
  position: relative;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: "+";
  position: absolute;
  right: 0.2rem;
  top: 50%;
  transform: translateY(-50%);
  font-weight: 300;
  font-size: 1.5rem;
  color: var(--sourd);
  transition: transform 0.25s ease;
}
.faq details[open] summary::after { transform: translateY(-50%) rotate(45deg); }
.faq summary:focus-visible { outline: 2px solid var(--accent-clair); outline-offset: 3px; border-radius: 6px; }
.faq details p { color: var(--muted); padding: 0 2.4rem 1.3rem 0; max-width: 62ch; }
/* le second bouton : blanc a 10 %, comme le secondaire de Fora — il existe,
   il ne concurrence pas le premier */
.cta-second {
  background: rgba(255, 255, 255, 0.10);
  border: 1px solid rgba(255, 255, 255, 0.10);
  color: var(--text);
  box-shadow: none;
}
.cta-second:hover { background: rgba(255, 255, 255, 0.16); }

/* --- les trois vitrines : l'image EST la preuve --- */
.vitrines { display: grid; gap: 3rem; margin-top: 2.4rem; }
/* LES VITRINES S'EMPILENT (C-154, chantier 4, 2026-09-02). Chaque carte est
   collante sous la barre ; la suivante monte et se pose dessus, decalee de
   14 px par rang. Zero JavaScript. La carte a besoin d'une SURFACE pour que
   l'empilement se lise — un fond presque opaque, pas un fond plein : les
   degrades fixes du body restent visibles autour. Sur telephone, l'image est
   bornee a 40 vh pour que la carte tienne dans l'ecran (sinon la pile
   masque son propre contenu). */
.vitrines { --pile-haut: 5.4rem; padding-bottom: 0; }
.vitrine {
  display: grid;
  grid-template-columns: minmax(0, 8fr) minmax(0, 3fr);
  gap: clamp(1.4rem, 3vw, 2.6rem);
  align-items: center;
  position: sticky;
  top: var(--pile-haut);
  padding: var(--carte-pad);
  border-radius: var(--rayon);
  /* OPAQUE, pas presque : a 0,94 le texte de la carte du dessous
     transparaissait (« Fluxorama », « Voir la demarche ») — constate a la
     pellicule du 2026-09-02. La vraie page n'a pas de canvas d'etoiles :
     un fond plein ici ne cache rien qui compte. */
  background: rgb(12, 16, 26);
  border: 1px solid var(--hairline);
}
/* DECALAGE ZERO — 2026-09-14 (PLAN-FORA.md). Fora empile ses trois cartes
   au meme `top` (120 px, mesure) : la suivante recouvre exactement la
   precedente, aucune reduction, aucun flou. Les 14 px par rang du 2
   septembre etaient une interpretation ; la pile parfaite est plus sobre. */
.vitrine:nth-child(2) { top: var(--pile-haut); }
.vitrine:nth-child(3) { top: var(--pile-haut); }
.vitrine.inverse .vitrine-visuel { order: 2; }
.vitrine.inverse .vitrine-texte { order: 1; }
.vitrine-visuel {
  border-radius: calc(var(--rayon) - 4px);
  overflow: hidden;
  border: 1px solid var(--hairline);
  line-height: 0;
}
.vitrine-visuel img { width: 100%; height: auto; display: block; transition: transform 0.9s cubic-bezier(.22,.61,.36,1); }
.vitrine:hover .vitrine-visuel img { transform: scale(1.035); }
.vitrine-texte h3 {
  font-size: 1.25rem; font-weight: 500;
  margin: 0.7rem 0 0.6rem;
  letter-spacing: -0.01em;
}
.vitrine-texte p { color: var(--muted, #a7afbf); max-width: 38ch; }
/* LA MENTION DE MAQUETTE, sur l'accueil (2026-08-31). Meme registre que la
   legende de /realisations/ — mono, capitales, discrete — mais un cran plus
   grande (0,72 rem contre 0,66) : c'est la ligne qui empeche une maquette
   d'etre lue comme une preuve, elle doit rester lisible. Avec `--sourd`
   desormais declaree ici, elle tient 5,71:1 sur le fond. */
/* SELECTEUR DESCENDANT VOULU : `.vitrine-texte p` (0,1,1) battait
   `.vitrine-mention` seul (0,1,0) et la mention repartait en texte courant.
   La COULEUR est laissee a `--muted` (heritee de la regle du dessus,
   7,33:1 sur le fond) : `--sourd` aurait ete plus discret, mais cette
   ligne-ci doit se lire — c'est elle qui empeche une maquette de passer
   pour une preuve. Seuls la fonte, la casse et l'espacement la mettent en
   retrait. */
.vitrine-texte .vitrine-mention {
  margin-top: 0.7rem;
  font-family: var(--mono, monospace);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  max-width: 38ch;
}
.vitrine-lien {
  display: inline-block;
  margin-top: 0.9rem;
  color: var(--accent-clair, #c9d8ef);
  text-decoration: none;
  font-weight: 600;
}
.vitrine-lien:hover { text-decoration: underline; text-underline-offset: 5px; }
@media (max-width: 860px) {
  .vitrine { grid-template-columns: 1fr; }
  .vitrine-visuel img { max-height: 40vh; object-fit: cover; }
  /* la barre du haut passe sur deux lignes au telephone (~92 px) : la pile
     se cale dessous, comme scroll-padding-top plus haut */
  .vitrines { --pile-haut: 7rem; }
  .vitrine.inverse .vitrine-visuel { order: 0; }  /* l'image d'abord, partout */
  .vitrine.inverse .vitrine-texte { order: 1; }
}

/* --- le formulaire de contact (Netlify Forms) --- */
.bloc-contact { max-width: 620px; margin: clamp(3rem, 8vh, 5rem) auto 0; }
.bloc-contact h3 { font-size: clamp(1.6rem, 3vw, 2.3rem); letter-spacing: -0.02em; }
.bloc-contact > .prose { margin-top: 0.9rem; }
.formulaire { display: grid; gap: 1.1rem; margin-top: 1.6rem; text-align: left; }
.formulaire .champs { display: grid; grid-template-columns: 1fr 1fr; gap: 1.1rem; }
@media (max-width: 640px) { .formulaire .champs { grid-template-columns: 1fr; } }
.formulaire label { display: grid; gap: 0.45rem; }
.formulaire label span {
  font-family: var(--mono, monospace);
  font-size: 0.68rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--sourd, #6f6a85);
}
/* (les champs : voir « le formulaire a la Fora », plus haut — l'ancien
   cadre arrondi a ete retire le 2026-09-14 au soir) */
.formulaire .cta { justify-self: start; border: 0; cursor: pointer; }
/* le piege a robots : hors ecran, jamais display:none (un robot le verrait) */
.cache-miel { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; margin: 0; }
.contact-pied { display: flex; gap: 1.4rem; align-items: baseline; margin-top: 1.6rem; flex-wrap: wrap; }

/* --- le pied de page : lien discret, meme registre que le reste --- */
/* SOULIGNE AU REPOS depuis le 2026-08-31 (audit lea, verifie : la couleur
   calculee etait IDENTIQUE a celle du texte voisin, et text-decoration
   valait `none`). « Politique de confidentialite » n'etait donc signale par
   rien avant le survol — WCAG 1.4.1 : la couleur ne peut pas etre le seul
   moyen de distinguer un lien, et ici il n'y avait meme pas de couleur. */
/* `.footer a` (0,1,1) BATTAIT `.pied-lien` (0,1,0) — d'ou le selecteur
   descendant. Ce que `.footer a` donnait deja : une `border-bottom` en
   `--hairline`, c'est-a-dire du violet a 14 % d'opacite — presque rien a
   l'oeil. Le lien « Politique de confidentialite » n'etait donc signale par
   aucune couleur ni aucun soulignement franc (WCAG 1.4.1). On remplace la
   bordure fantome par un vrai soulignement, dans la couleur du texte. */
.footer .pied-lien {
  color: inherit;
  border-bottom: 0;
  text-decoration: underline;
  text-underline-offset: 4px;
}
.footer .pied-lien:hover { color: var(--accent-clair, #c9d8ef); }

/* --- les visuels de /realisations/ (2026-08-31) --- */
.real-visuel {
  margin: 0 0 1.4rem;
  border-radius: 14px;
  overflow: hidden;
  border: 1px solid rgba(170, 190, 225, 0.16);
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.45);
}
.real-visuel img { width: 100%; height: auto; display: block; }
.real-visuel figcaption {
  padding: 0.5rem 0.9rem;
  font-family: var(--mono, monospace);
  font-size: 0.66rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--sourd, #6f6a85);
  background: rgba(255, 255, 255, 0.02);
}


/* ================= la refonte de conversion — 2026-09-14 (audit Gemini) =================
   Textes de sophie, UI de lea, formulaire de thomas, cadre d'elodie. Ce
   bloc porte : les badges de confiance du hero, les services sans icones,
   les cas d'ingenierie dans les vitrines, les temoignages, le bloc contact
   reduit a un bouton, et la page /contact/ en trois volets. */

/* --- les badges de confiance, sous le hero : une ligne nue, mono --- */
.confiance {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: .4rem 1.1rem; margin: 1.6rem auto 0; padding: 0; list-style: none;
  font-family: var(--mono); font-size: .72rem; letter-spacing: .12em;
  text-transform: uppercase; color: var(--muted);
}
.confiance li + li::before { content: "·"; margin-right: 1.1rem; color: var(--sourd); }
.hero-actions .cta-second { background: rgba(255, 255, 255, 0.10); color: var(--text); box-shadow: none; }

/* --- les services : carte glass, grand numero en mono, aucune icone --- */
.vraie .cap {
  position: relative;
  display: grid;
  grid-template-columns: minmax(5ch, 1fr) minmax(0, 52ch);
  gap: clamp(1.5rem, 4vw, 4rem);
  align-items: start;
  padding: clamp(2rem, 5vh, 3.4rem) clamp(1.4rem, 3vw, 2.4rem);
  background: var(--carte);
  border: 1px solid var(--hairline);
  border-radius: 22px;
}
.vraie .cap + .cap { margin-top: 1.2rem; border-top: 1px solid var(--hairline); }
.vraie .cap .marque, .vraie .cap .fil-electrique, .vraie .cap .halo-ligne { display: none; }
.vraie .cap .no {
  font-family: var(--mono); font-weight: 400;
  font-size: clamp(2.6rem, 6vw, 4.4rem); line-height: 1;
  letter-spacing: -0.02em; color: var(--sourd);
}
.vraie .cap h3 { font-size: 1.25rem; font-weight: 500; letter-spacing: -0.01em; margin-bottom: .7rem; }
.vraie .cap p { color: var(--muted); font-size: 1.05rem; }
.vraie .cap .concret { margin-top: .8rem; color: var(--text); font-size: 1rem; }
.vraie .cap .concret::before, .card .concret::before { content: "→ "; color: var(--sourd); }
.card .concret { margin-top: .8rem; color: var(--text); font-size: 1rem; }
@media (max-width: 640px) { .vraie .cap { grid-template-columns: 1fr; gap: .8rem; } }

/* --- la lueur qui suit le curseur : un anneau, par masque, cyan a .28 --- */
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .vraie .cap::after, .vitrine::after, .temoin::after {
    content: ""; position: absolute; inset: -1px; padding: 1px;
    border-radius: inherit; pointer-events: none; opacity: 0;
    background: radial-gradient(240px circle at var(--mx, 50%) var(--my, 50%),
      rgba(var(--etat-rgb), .28), transparent 70%);
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor; mask-composite: exclude;
    transition: opacity .7s ease;
  }
  .vraie .cap:hover::after, .vitrine:hover::after, .temoin:hover::after { opacity: 1; }
}

/* --- les cas d'ingenierie dans les vitrines --- */
.vitrine { grid-template-columns: minmax(0, 6fr) minmax(0, 5fr); }
.vitrine-texte .cas-tagline { color: var(--text); font-size: 1.05rem; max-width: 40ch; }
.cas { display: grid; gap: .8rem; margin-top: 1.1rem; }
.cas > div { display: grid; grid-template-columns: 9ch 1fr; gap: .8rem; align-items: baseline; }
.cas dt { font-family: var(--mono); font-size: .72rem; letter-spacing: .16em; text-transform: uppercase; color: var(--sourd); }
.cas dd { color: var(--muted); font-size: .95rem; max-width: 44ch; }
.cas dd.stack { font-family: var(--mono); font-size: .8rem; color: var(--muted); }
.cas ul { list-style: none; padding: 0; display: grid; gap: .3rem; }
.cas ul li { font-size: .92rem; color: var(--text); }
.cas ul li::before { content: "—"; color: var(--sourd); margin-right: .5rem; }
.cas ul li b { font-family: var(--mono); font-weight: 400; font-size: .72rem; letter-spacing: .1em; text-transform: uppercase; color: var(--sourd); margin-right: .4rem; }
@media (max-width: 860px) { .cas > div { grid-template-columns: 1fr; gap: .25rem; } }

/* --- les temoignages : trois cartes glass, prenom et role seulement --- */
.temoignages { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1.1rem; margin-top: 2rem; }
.temoin {
  position: relative; padding: var(--carte-pad); border-radius: var(--rayon);
  background: var(--carte); border: 1px solid var(--hairline);
  display: grid; gap: 1rem; align-content: start;
}
.temoin blockquote { font-size: 1.05rem; line-height: 1.5; color: var(--text); }
.temoin blockquote::before { content: "« "; color: var(--sourd); }
.temoin blockquote::after { content: " »"; color: var(--sourd); }
.temoin figcaption { font-family: var(--mono); font-size: .72rem; letter-spacing: .1em; text-transform: uppercase; color: var(--muted); }
.temoin figcaption b { font-weight: 400; color: var(--text); }
@media (max-width: 860px) { .temoignages { grid-template-columns: 1fr; } }

/* --- comment on collabore : trois phases, pas de cartes bordees (Fora : un H2, une
   phrase, trois blocs titre + description ; lea, 2026-09-14) --- */
.collabo-titre { font-size: clamp(1.5rem, 2.6vw, 2.1rem); letter-spacing: -0.02em; max-width: 24ch; margin-top: 1.6rem; }
.phases { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(1.4rem, 3vw, 2.6rem); margin-top: 2.4rem; }
.phase .no { font-family: var(--mono); font-size: .72rem; letter-spacing: .16em; color: var(--sourd); }
.phase h4 { font-size: 1.25rem; font-weight: 500; letter-spacing: -0.01em; margin: .6rem 0 .6rem; }
.phase p { color: var(--muted); font-size: 1rem; line-height: 1.55; max-width: 34ch; }
.phase .duree { margin-top: .8rem; font-family: var(--mono); font-size: .78rem; letter-spacing: .04em; color: var(--text); }
.collabo-prix { margin-top: 2.6rem; padding-top: 1.6rem; border-top: 1px solid var(--hairline); display: grid; gap: .5rem; }
.collabo-prix p { color: var(--muted); max-width: 52ch; }
.collabo-prix dl { display: grid; grid-template-columns: max-content 1fr; column-gap: 1.2rem; row-gap: .45rem; }
.collabo-prix dt { font-family: var(--mono); font-size: .72rem; letter-spacing: .1em; text-transform: uppercase; color: var(--sourd); align-self: baseline; }
.collabo-prix dd { color: var(--text); }
.collabo-fin { margin-top: 2.2rem; display: flex; flex-wrap: wrap; align-items: center; gap: 1rem 1.6rem; }
.collabo-fin p { color: var(--text); font-size: 1.05rem; max-width: 30ch; }
@media (max-width: 860px) { .phases { grid-template-columns: 1fr; } .collabo-prix dl { grid-template-columns: 1fr; row-gap: .15rem; } .collabo-prix dd { margin-bottom: .5rem; } }

/* --- le bloc contact de l'accueil : un bouton, pas un formulaire ouvert --- */
.bloc-contact .contact-actions { margin-top: 2rem; display: flex; gap: .9rem; justify-content: center; flex-wrap: wrap; }

/* --- /contact/ : le formulaire en trois volets --- */
.page-contact main { max-width: 760px; margin: 0 auto; padding: 0 clamp(1.25rem, 4vw, 2.5rem) clamp(4rem, 10vh, 7rem); }
.page-contact .page-tete { padding-left: 0; padding-right: 0; }
.page-contact .page-tete .surtitre { margin-bottom: 1rem; }
.cadrage { margin-top: clamp(2rem, 5vh, 3rem); display: grid; gap: 1.6rem; }
.cadrage fieldset { min-inline-size: 0; border: 1px solid var(--hairline); border-radius: 22px; background: var(--carte); padding: clamp(1.4rem, 3vw, 2.2rem); display: grid; gap: 1.2rem; }
.cadrage, .cadrage * { min-width: 0; }
.page-contact main, .page-contact body { overflow-x: clip; }
html.js .cadrage fieldset:not(.active) { display: none; }
.cadrage legend { float: left; width: 100%; padding: 0; margin-bottom: .6rem; display: grid; gap: .5rem; }
.cadrage legend .tag { font-family: var(--mono); }
.cadrage legend .legende { font-size: clamp(1.4rem, 2.6vw, 1.9rem); letter-spacing: -0.02em; color: var(--text); }
.cadrage legend:focus { outline: none; }
.jalons { list-style: none; padding: 0; display: grid; grid-template-columns: repeat(3, 1fr); gap: .6rem; }
.jalons li { display: grid; gap: .35rem; padding-top: .7rem; border-top: 1px solid var(--hairline); color: var(--sourd); }
.jalons li[aria-current="step"] { border-top-color: var(--etat); color: var(--text); }
.jalons li.fait { border-top-color: var(--accent); color: var(--muted); }
.jalon-num { font-family: var(--mono); font-size: .72rem; letter-spacing: .12em; }
.jalon-nom { font-size: .9rem; }
.choix-liste { display: grid; gap: .6rem; }
.choix-ligne { grid-template-columns: repeat(3, 1fr); }
.choix { display: flex; gap: .8rem; align-items: center; padding: .9rem 1rem; border: 1px solid var(--hairline); border-radius: 14px; cursor: pointer; transition: border-color .3s ease, background .3s ease; }
.choix:hover { border-color: rgba(170, 190, 225, 0.3); }
.choix:has(input:checked) { border-color: var(--etat); background: rgba(var(--etat-rgb), .06); }
.choix input { accent-color: var(--etat); width: 1.1rem; height: 1.1rem; margin: 0; flex: none; }
.choix span { color: var(--text); font-size: 1rem; }
.cadrage .champs { display: grid; grid-template-columns: 1fr 1fr; gap: 1.1rem; }
.cadrage label:not(.choix) { display: grid; gap: .45rem; }
.cadrage label:not(.choix) span { font-size: .82rem; letter-spacing: .04em; color: var(--muted); }
.cadrage input:not([type="radio"]):not([type="checkbox"]) {
  width: 100%; padding: .85rem 1rem; border-radius: 12px;
  border: 1px solid var(--hairline); background: rgba(255, 255, 255, 0.02); color: var(--text); font: inherit;
}
.cadrage input:not([type="radio"]):not([type="checkbox"]):focus-visible { border-color: var(--etat); outline: none; box-shadow: 0 0 0 3px rgba(var(--etat-rgb), .18); }
.cadrage .cta { justify-self: start; border: 0; cursor: pointer; }
.cadrage .suite { font-size: .9rem; color: var(--sourd); max-width: 52ch; }
.nav-etapes { display: flex; gap: .8rem; justify-content: space-between; }
.nav-etapes .cta { border: 0; cursor: pointer; }
.nav-etapes [data-suivant] { margin-left: auto; }
.page-contact .contact-pied { margin-top: 2.5rem; display: flex; gap: 1.2rem; flex-wrap: wrap; align-items: center; }
@media (max-width: 640px) {
  .choix-ligne, .etapes .champs { grid-template-columns: 1fr; }
  .jalon-nom { display: none; }
}

/* --- UNE SEULE ECHELLE DE TITRES SUR LA PAGE BASSE (lea, 14 sept., mesure Fora :
   40 px, graisse 400). Selecteurs scopes par id : les memes classes habillent
   l'intro, qu'on ne touche pas. --- */
.vraie #v-demarche h2, .vraie #v-reduire .titre-reel, .vraie #final h2, .collabo-titre, .bloc-contact h3, .fin-appel h2 {
  font-size: clamp(1.9rem, 3.2vw, 2.5rem); font-weight: 400; letter-spacing: -0.03em; line-height: 1.15;
}
/* --- une voix sous chaque vitrine --- */
.vitrine .temoin { margin-top: 1.1rem; padding: 1rem 1.1rem; gap: .6rem; }
.vitrine .temoin blockquote { font-size: .95rem; line-height: 1.5; }
.vitrine .temoin + .vitrine-lien { margin-top: 1rem; display: inline-block; }
