/* ===========================================================================
   joris-dce.fr — feuille unique de la page d'accueil, 19 septembre 2026

   Elle remplace à elle seule styles.css, carbon-ui.css, site-v25-responsive,
   shiny-buttons, cms-overrides et book-photo, soit 104 Ko accumulés par
   versions successives et pleins de « !important » qui se contredisaient.
   Les pages légales gardent l'ancienne pile, elles n'ont pas changé.

   ENCRE ET BLEU — la direction artistique, tranchée par Joris le 19 septembre
   2026 après avoir vu trois lumières et trois couleurs en maquette.

   **Le site passe au clair.** Il était noir de bout en bout. Un papier cassé
   se lit partout, au soleil comme sur un téléphone, et c'est lui qui fait
   sérieux, pas les effets. Seule l'ouverture reste dans l'encre, parce qu'une
   photo à contre-jour n'a rien à faire sur du papier.

   **Un seul thème, le clair.** Pas de bascule, pas de mode nuit qui suivrait
   le réglage du système : une page qui s'affiche d'une seule façon s'affiche
   toujours comme prévu, et chaque contraste ne se mesure qu'une fois.

   **Le bleu ne sert presque à rien**, sauf au geste que la personne doit
   faire. C'est ce qui reste quand on enlève, pas ce qu'on ajoute.

   **Trois bleus, et la raison est mesurable.** Le premier est le fond des
   boutons, avec du blanc posé dessus : 6,88 de contraste. Le deuxième est le
   bleu de texte sur le papier : 8,38, là où le seuil en demande 4,5. Le
   troisième est une version claire, réservée à ce qui vit sur l'encre, où les
   deux premiers s'éteindraient. Un seul bleu pour les trois usages rendrait
   la moitié du site illisible.

   Reprises de Layonnage : deux familles seulement, des angles courts à six
   pixels, un halo très bas derrière le titre, des chiffres qui portent une
   preuve, et beaucoup de vide vertical.
   =========================================================================== */

/* --- Les polices, servies d'ici -----------------------------------------
   **Plus aucun appel à Google au chargement.** Les deux familles venaient de
   fonts.googleapis.com, ce qui envoyait l'adresse IP de chaque visiteur à
   Google sans que la page confidentialité le dise. Un tribunal allemand a
   condamné exactement ce cas en janvier 2022. Les fichiers sont ceux que
   Google servait, sous licence SIL Open Font License : deux fichiers
   variables par famille, l'alphabet latin et son extension, qui couvrent à
   eux seuls toutes les graisses employées ici. */
@font-face {
  font-family: "Bricolage Grotesque"; font-style: normal; font-weight: 600 800; font-display: swap;
  src: url("assets/fonts/bricolage-grotesque-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Bricolage Grotesque"; font-style: normal; font-weight: 600 800; font-display: swap;
  src: url("assets/fonts/bricolage-grotesque-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Public Sans"; font-style: normal; font-weight: 400 700; font-display: swap;
  src: url("assets/fonts/public-sans-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Public Sans"; font-style: normal; font-weight: 400 700; font-display: swap;
  src: url("assets/fonts/public-sans-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  /* **Le clair est catégorique.** Sans cette ligne, quelqu'un dont le système
     est en mode nuit reçoit des champs de saisie noirs et une barre de
     défilement sombre posés sur notre papier clair : le navigateur les peint
     lui même. Une page à moitié sombre est pire que les deux thèmes. */
  color-scheme: light;

  /* Les fonds, du plus clair au plus marqué. */
  --papier: #faf9f6;
  --feuille: #ffffff;
  --creux: #f1efe8;

  /* Les textes. Le noir pur fatigue, on garde une pointe de chaud. */
  --encre: #17171a;
  --encre-douce: #64646e;

  --trait: #e4e0d5;
  --trait-fort: #c3bdaa;

  /* Les trois bleus. Voir la mesure de chacun en tête de fichier. */
  --bleu: #2a4ecb;
  --bleu-vif: #3a5fe8;
  --bleu-texte: #1f3fae;
  --sur-bleu: #ffffff;

  /* Le métal du bouton, fabriqué en dégradé plutôt qu'en image : aucune
     licence, aucun fichier à charger, et il suit la taille de son bloc.
     **Son reflet reste sombre**, à 5,27 de contraste avec le blanc. Un reflet
     plus clair ferait disparaître le mot au milieu du bouton, et un bouton
     dont le texte s'efface n'est pas un effet, c'est un défaut. */
  --bleu-metal: linear-gradient(103deg, #1f3fae 0%, #2a4ecb 20%, #3a5fe8 40%,
                                #2a4ecb 60%, #2444b5 78%, #3a5fe8 100%);

  /* **La scène : ce qui vit sur l'encre.** L'ouverture, et la section des
     bons plans. Sur l'encre, les deux bleus du papier s'éteignent, et c'est
     une version claire qui prend le relais, à 7,77 de contraste. */
  --scene: #17171a;
  --sur-scene: #faf9f6;
  --sur-scene-doux: #a9a59a;
  --trait-scene: #2f2f36;
  --scene-carte: #1f1f24;
  --bleu-scene: #8aa8ff;

  --danger: #a3352a;
  --valide: #1a6b3f;

  --rayon: 6px;
  --rayon-grand: 10px;
  --ombre: 0 1px 2px rgba(23, 23, 26, 0.04), 0 18px 40px -26px rgba(23, 23, 26, 0.3);

  --titres: "Bricolage Grotesque", "Public Sans", system-ui, sans-serif;
  --lecture: "Public Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
}

* { box-sizing: border-box; }

/* **Les deux coupes, et il en faut bien deux.** L'ouverture et les bons plans
   sortent du cadre par une marge négative calculée en « vw », et cette unité
   compte la barre de défilement : il reste donc un ruban de quelques pixels à
   droite. Posée sur le seul « body », la coupe est remontée au navigateur qui
   rend alors « body » transparent à l'affaire, et la page se décalait encore
   de quatre pixels, mesurés sur la page rendue. Les deux lignes ensemble
   ferment le ruban.

   On coupe plutôt qu'on ne cache : « clip » ne fabrique pas de zone défilante,
   là où « hidden » en crée une et casse le défilement vers les ancres. */
html { scroll-behavior: smooth; overflow-x: clip; }

body {
  margin: 0;
  overflow-x: clip;
  background: var(--papier);
  color: var(--encre);
  font-family: var(--lecture);
  font-size: 1.02rem;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, .nombre, .hero-title, .marque {
  font-family: var(--titres);
  letter-spacing: -0.02em;
}

a { color: inherit; }
img { max-width: 100%; }

/* --- Accessibilité ------------------------------------------------------ */

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

.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  padding: 10px 16px; background: var(--bleu); color: var(--sur-bleu);
  font-weight: 700; border-radius: 0 0 var(--rayon) 0;
}
.skip-link:focus { left: 0; }

:focus-visible { outline: 2px solid var(--bleu); outline-offset: 3px; }

/* --- Le décor de fond ---------------------------------------------------
   Il n'y en a plus. Le site était noir et lui devait sa profondeur à un halo
   fixe ; sur du papier, un halo coloré ne fait que salir le blanc. Le vide
   porte la page mieux que n'importe quel dégradé. */

.ascendra-universal-background,
.ascendra-bg-carbon,
.ascendra-bg-glow,
.ascendra-bg-vignette { display: none; }

/* L'ouverture au logo. Elle dure moins d'une seconde et ne bloque rien. */
.brand-intro {
  position: fixed; inset: 0; z-index: 150; display: grid; place-items: center;
  background: var(--papier); animation: ouvrir 0.85s ease 0.25s forwards;
}
.brand-intro img { width: 62px; animation: respirer 0.85s ease both; }
@keyframes ouvrir { to { opacity: 0; visibility: hidden; } }
@keyframes respirer { from { opacity: 0; transform: scale(0.9); } to { opacity: 1; transform: none; } }

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

.site-header {
  position: sticky; top: 0; z-index: 60;
  background: rgba(255, 255, 255, 0.86);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--trait);
}

.navbar {
  max-width: 68rem; margin-inline: auto;
  padding: 0.7rem clamp(1rem, 4vw, 2rem);
  display: flex; align-items: center; gap: 0.75rem;
}

/* **Le logo porte seul la marque dans la barre.** Le nom écrit y vivait à
   côté de lui ; il faisait doublon avec le titre de la page et avec le pied,
   et il rétrécissait le monogramme. Le lien garde un nom accessible, sinon un
   lecteur d'écran annonce « lien image » sans dire où il mène. */
.brand { display: flex; align-items: center; flex-shrink: 0; text-decoration: none; }
.brand img { width: 40px; height: 40px; display: block; }
.footer-home img { width: 38px; height: 38px; display: block; }

/* **Le nom écrit, plutôt qu'une marque dessinée.** Dans une barre de site, un
   mot lisible bat toujours un symbole qu'il faut apprendre : personne n'a à
   deviner qui publie. Le J dessiné n'a pas disparu pour autant, il reprend la
   main là où un mot ne rentre pas, dans l'onglet et sur l'écran d'accueil d'un
   téléphone.
   Le point du i est en encre : c'est le seul détail, et il suffit. */
.logotype {
  font-family: var(--titres);
  font-weight: 800;
  font-size: 1.32rem;
  letter-spacing: -0.05em;
  line-height: 1;
  color: var(--bleu-texte);
  display: inline-block;
}
.logotype i { font-style: normal; color: var(--encre); }

.site-footer .logotype { font-size: 1.5rem; }

.nav-links { display: flex; gap: 0.25rem; margin-left: auto; }
.nav-links a {
  padding: 0.45rem 0.8rem; border-radius: var(--rayon);
  font-size: 0.88rem; font-weight: 600; color: var(--encre-douce);
  text-decoration: none; transition: color 0.18s ease, background 0.18s ease;
}
.nav-links a:hover { color: var(--encre); background: var(--creux); }

.menu-toggle { display: none; }

/* Les deux drapeaux */
.lang-switch {
  display: flex; gap: 3px; margin-left: auto; padding: 3px;
  border: 1px solid var(--trait); border-radius: 999px;
}
.nav-links + .lang-switch,
.lang-switch ~ .nav-links { margin-left: 0; }
.lang-btn {
  display: grid; place-items: center; width: 32px; height: 24px; padding: 0;
  border: 1px solid transparent; border-radius: 999px; background: none;
  cursor: pointer; opacity: 0.45; transition: opacity 0.18s ease;
}
.lang-btn svg { width: 19px; height: 13px; border-radius: 2px; display: block; }
.lang-btn:hover { opacity: 0.85; }
.lang-btn.is-active {
  opacity: 1; border-color: var(--bleu); background: rgba(42, 78, 203, 0.09);
}

/* --- La colonne de contenu ---------------------------------------------- */

.shell {
  max-width: 68rem; margin-inline: auto;
  padding: 0 clamp(1rem, 4vw, 2rem) 4rem;
  display: flex; flex-direction: column;
}

.section-panel { padding-block: clamp(3rem, 8vw, 5.5rem); }

/* **La séparation est un filet qui s'allume au milieu.** C'était un trait
   beige d'un pixel, d'un bord à l'autre de la page : il découpait sans rien
   dire. Le filet part maintenant de rien, passe au bleu en son centre et
   s'éteint de l'autre côté, avec un halo très bas posé dessus.

   Le bleu reste réservé au geste à faire, et un trait n'est pas un geste :
   c'est pour cela qu'il ne l'atteint qu'en son milieu, sur un huitième de la
   largeur, et que le halo se compte en centièmes d'opacité. Une séparation
   qui se remarque plus que le bouton juste au dessus serait un contresens. */
.section-panel + .section-panel { position: relative; border-top: 0; }
.section-panel + .section-panel::before {
  content: ""; position: absolute; top: 0; left: 50%; transform: translateX(-50%);
  width: min(52rem, 100%); height: 1px; pointer-events: none;
  background: linear-gradient(90deg,
    transparent 0%, var(--trait) 16%,
    rgba(42, 78, 203, 0.55) 50%,
    var(--trait) 84%, transparent 100%);
}
.section-panel + .section-panel::after {
  content: ""; position: absolute; top: -7px; left: 50%; transform: translateX(-50%);
  width: min(24rem, 70%); height: 14px; pointer-events: none;
  border-radius: 999px; filter: blur(7px);
  background: radial-gradient(closest-side, rgba(42, 78, 203, 0.28), transparent);
}

.section-heading { text-align: center; margin-bottom: clamp(1.8rem, 4vw, 2.8rem); }
.section-heading h2 {
  font-size: clamp(1.7rem, 4.2vw, 2.5rem); line-height: 1.1; margin: 0 0 0.6rem;
}
.section-heading p {
  margin: 0 auto; max-width: 48ch; color: var(--encre-douce);
  font-size: clamp(0.98rem, 2vw, 1.08rem);
}

/* --- L'ouverture --------------------------------------------------------
   La seule scène sombre de la page, avec celle des bons plans. Elle sort du
   cadre jusqu'aux bords de la fenêtre, et la frontière avec le papier est
   franche : un dégradé qui s'éteindrait dans le clair ferait une tache grise
   au milieu de rien. */

/* **L'ouverture tient dans un écran, et c'est tout l'enjeu.** Le retrait du
   haut montait à 19 rem, ce qui poussait le titre, le bouton et la ligne de
   réassurance sous la ligne de flottaison : il fallait faire défiler pour
   voir le geste à faire. Une page d'accueil dont le bouton ne se voit pas à
   l'arrivée perd les visiteurs qui ne défilent jamais.

   La photo garde de l'air au dessus d'elle grâce au retrait bas et au fait
   que la hauteur ne dépasse jamais un écran, moins la barre du haut. */
/* L'OUVERTURE EN DEUX COLONNES — 19 septembre 2026
   ------------------------------------------------
   Joris, en regardant la page finie : « je suis pas fan de la bannière du
   héros, et même sur téléphone. J'aime bien l'idée de mettre un mec en
   équilibre, mais ça met pas trop en valeur ».

   **Le défaut était de traiter la photo comme un fond.** Elle passait
   derrière un voile à 86 pour cent d'opacité pour que le titre reste
   lisible : on obtenait donc un mur gris sur les deux tiers de l'écran, une
   silhouette petite, à droite, coupée en haut par le cadrage, et le titre
   posé en travers du corps. La photo ne servait plus à rien, sauf à assombrir.

   **Elle redevient un objet qu'on regarde.** Le texte prend la colonne de
   gauche, la photo la colonne de droite, dans son cadre, entière, avec une
   lueur bleue derrière elle. Plus de voile, donc plus rien à compenser.

   **Et c'est la photo verticale qui sert partout.** Elle était réservée au
   téléphone ; c'est pourtant elle qui montre le sujet en entier, cadré au
   milieu, avec le contre jour qui le détache. La version paysage reste le
   fichier de partage, celui que les réseaux affichent en vignette. */
.hero {
  position: relative; isolation: isolate; overflow: hidden;
  margin-inline: calc(50% - 50vw);
  padding: clamp(3rem, 7vw, 5rem) clamp(1rem, 4vw, 2rem) clamp(3rem, 6vw, 4.2rem);
  min-height: min(44rem, calc(100svh - 4rem));
  display: grid; align-items: center;
  background: #0b0b0d;
  color: var(--sur-scene);
}

/* La trame de points, posée sur l'encre. Elle ne couvre pas toute la scène :
   un masque la concentre autour de la silhouette et l'éteint sous le texte,
   où elle ne ferait que gêner la lecture. */
.hero::before {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background-image: radial-gradient(rgba(255, 255, 255, 0.075) 1px, transparent 1px);
  background-size: 22px 22px;
  -webkit-mask-image: radial-gradient(58% 72% at 74% 50%, #000 0%, transparent 76%);
  mask-image: radial-gradient(58% 72% at 74% 50%, #000 0%, transparent 76%);
}

/* Les deux colonnes. Le texte prend un peu plus de place que la photo : c'est
   lui qui doit être lu en premier. */
.hero-grille {
  position: relative;
  width: 100%; max-width: 68rem; margin-inline: auto;
  display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.78fr);
  gap: clamp(1.5rem, 5vw, 3.5rem); align-items: center;
}

/* **Et ce n'est plus une photo du tout.** La photo encadrée a été essayée puis
   écartée par Joris le 19 septembre 2026 : « la bannière du héros, j'aime pas
   du tout, je préfère encore l'ancienne ». Ce qu'il voulait à la place, il l'a
   dit dans la même phrase : « un personnage en mode dessin, un peu comme tu
   m'as fait pour le PDF, mais un peu plus joli ».

   **C'est donc le dessin du guide, celui de l'étape du mur**, la silhouette
   qui tient la ligne droite, repeinte dans le papier du site et posée sur
   l'encre. Le pointillé du dos est du vide dans le fichier d'origine : il
   redevient ici un trait sombre qui dit l'alignement, ce que la photo ne
   montrait pas. La page d'accueil et le guide parlent enfin la même langue.

   Le fichier se refabrique depuis `assets/guides/croquis/croquis-mur.png` :
   recadrage de la figure de gauche, alpha conservé, couleur remplacée. */
.hero-illustration {
  position: relative; margin: 0;
  display: grid; place-items: center;
}
/* **Les pages du guide en éventail, depuis le 24 septembre 2026.** Joris a
   choisi sur maquette de montrer ce que le bouton télécharge plutôt que la
   silhouette seule : la couverture devant, le mur à gauche, l'équilibre à
   droite. Ce sont de vraies pages, refaites depuis le guide par
   outils/faire-apercu-guide.py ; elles ne se retouchent jamais à la main.
   La silhouette reste l'image de partage et le trait du guide. */
.hero-pages {
  position: relative; z-index: 1;
  width: min(30rem, 100%); height: clamp(21rem, 58vh, 27rem);
}
.hero-page {
  position: absolute; top: 50%; left: 50%;
  width: clamp(9.5rem, 17vw, 12.5rem); height: auto; display: block;
  border-radius: 4px; background: #fff;
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.08) inset,
              0 28px 50px -18px rgba(0, 0, 0, 0.85),
              0 0 0 1px rgba(255, 255, 255, 0.06);
}
.hero-page-gauche { transform: translate(-50%, -50%) translate(-62%, 4%) rotate(-9deg); }
.hero-page-droite { transform: translate(-50%, -50%) translate(62%, 4%) rotate(9deg); }
.hero-page-devant {
  z-index: 2; width: clamp(10.5rem, 18.5vw, 13.5rem);
  transform: translate(-50%, -50%) translateY(-2%);
}
/* Sur un écran moyen, la colonne rétrécit plus vite que les pages : l'éventail
   se resserre pour ne pas sortir de la fenêtre. */
@media (max-width: 78rem) {
  .hero-page-gauche { transform: translate(-50%, -50%) translate(-40%, 4%) rotate(-7deg); }
  .hero-page-droite { transform: translate(-50%, -50%) translate(40%, 4%) rotate(7deg); }
}
/* **Un anneau, parce qu'une silhouette seule flotte.** Le dessin est très
   étroit et très haut : posé au milieu d'une colonne, il n'a aucune assise et
   ressemble à un oubli. L'anneau lui donne un centre, et il reprend l'arc du
   J du logo. Il reste un trait d'un pixel, à peine allumé : ce qu'on doit
   regarder, c'est la silhouette. */
.hero-illustration::before {
  content: ""; position: absolute; z-index: 0; pointer-events: none;
  width: min(23rem, 88%); aspect-ratio: 1; border-radius: 50%;
  border: 1px solid rgba(138, 168, 255, 0.24);
}

/* **Le décor, et la limite qu'il ne franchit pas.** Joris, le 19 septembre
   2026 : « améliore un peu les éléments de fond, rajoute de la texture, pas
   juste une lueur bleue et un rond, sans en faire trop ». Trois choses s'y
   ajoutent donc, et rien de plus : un second anneau plus grand et deux fois
   plus faible, un horizon qui prolonge le trait de sol du dessin, et une
   trame de points sur l'encre.

   Toutes les trois se comptent en centièmes d'opacité et aucune ne bouge. Le
   test : en plissant les yeux, on doit voir la silhouette et le titre, pas le
   décor. Le jour où l'un d'eux se remarque en premier, il est trop fort. */
.hero-cercle {
  position: absolute; z-index: 0; pointer-events: none;
  width: min(31rem, 118%); aspect-ratio: 1; border-radius: 50%;
  border: 1px solid rgba(138, 168, 255, 0.10);
}

/* L'horizon part du trait de sol du dessin, qui occupe la dernière ligne du
   fichier : le bas de la figure et le bas de l'image sont donc le même
   endroit, et la ligne se prolonge des deux côtés sans calage à la main. */
.hero-illustration::after {
  content: ""; position: absolute; z-index: 0; pointer-events: none;
  left: 50%; bottom: 0; transform: translateX(-50%);
  width: min(32rem, 300%); height: 1px;
  background: linear-gradient(90deg,
    transparent 0%, rgba(138, 168, 255, 0.05) 18%,
    rgba(138, 168, 255, 0.34) 50%,
    rgba(138, 168, 255, 0.05) 82%, transparent 100%);
}
/* Le halo qui détache la silhouette de l'encre. Il est large et très flou :
   un cercle net derrière un dessin ferait une pastille, pas une lumière. */
.hero-lueur {
  position: absolute; z-index: 0; pointer-events: none;
  width: min(30rem, 100%); aspect-ratio: 1; border-radius: 50%;
  filter: blur(62px);
  background: radial-gradient(closest-side, rgba(58, 95, 232, 0.62), rgba(58, 95, 232, 0.18) 58%, transparent 78%);
}

/* **Ce n'est plus un voile, c'est le décor du fond.** Tant que la photo
   servait de fond, cette couche avait pour seul travail de l'assombrir
   jusqu'à ce que le titre passe dessus : d'où un dégradé à cinq arrêts qui
   montait à 86 pour cent d'opacité. La photo a son cadre maintenant, et le
   texte est posé sur l'encre : il ne reste que ce qui donne de la profondeur.

   Deux halos bleus, très bas, l'un en haut de la scène et l'autre derrière la
   colonne de texte. Ils ne se voient pas, ils se sentent : sans eux l'encre
   est un mur. */
.hero-overlay {
  position: absolute; inset: 0; z-index: -1;
  background:
    radial-gradient(60rem 26rem at 50% -8%, rgba(58, 95, 232, 0.22), transparent 66%),
    radial-gradient(38rem 30rem at 18% 62%, rgba(58, 95, 232, 0.13), transparent 70%),
    linear-gradient(180deg, rgba(11, 11, 13, 0) 55%, rgba(0, 0, 0, 0.35) 100%);
}

.hero-geometric-bg { display: none; }

/* Le texte est aligné à gauche : dans une colonne, un bloc centré donne des
   lignes en escalier et un bouton qui flotte au milieu de rien. */
.hero-content {
  position: relative; max-width: 37rem;
  text-align: left;
}

.badge {
  display: inline-flex; align-items: center; gap: 0.5rem;
  margin: 0 0 1.5rem; padding: 0.35rem 0.95rem 0.35rem 0.65rem;
  border: 1px solid rgba(255, 255, 255, 0.14); border-radius: 999px;
  background: rgba(0, 0, 0, 0.35);
  font-size: 0.92rem; line-height: 1.4; color: #ddd9d0;
}
/* **Le point respire, et c'est le seul mouvement permanent de la page.**
   Un halo s'en échappe puis se dissipe, toutes les trois secondes : le code
   universel du témoin allumé. Il ne déplace aucun texte, donc il ne gêne pas
   la lecture du titre, qui reste ce qu'on veut faire lire.

   Trois choix mesurés plutôt que réglés à l'œil : la pause des trente
   derniers pour cent laisse respirer entre deux battements, sinon c'est un
   clignotant ; le halo s'arrête à sept pixels, de quoi se voir sans déborder
   de la pilule ; et il part de 0,7 d'opacité, en dessous il passe inaperçu
   sur le fond sombre de l'ouverture. */
.badge .point {
  width: 7px; height: 7px; border-radius: 999px; background: var(--bleu-scene);
  flex-shrink: 0;
  animation: respire 3.2s ease-in-out infinite;
}

@keyframes respire {
  0% { box-shadow: 0 0 0 0 rgba(138, 168, 255, 0.7); }
  70%, 100% { box-shadow: 0 0 0 7px rgba(138, 168, 255, 0); }
}

/* **Le titre monte à la taille d'une affiche.** Il plafonnait à 3,5 rem, ce
   qui est une taille de section, pas d'ouverture : la photo occupait tout et
   la phrase passait derrière. À 4,6 rem c'est la phrase qu'on lit d'abord. */
/* **La colonne de gauche a pris un cran, le 19 septembre 2026.** Une fois la
   photo remplacée par un dessin étroit, le texte tenait tout le poids de
   l'ouverture et paraissait petit pour ce rôle : « augmente un peu la grosseur
   du texte à gauche ». Titre, phrase, badge et ligne de réassurance montent
   ensemble, sinon c'est le rapport entre eux qui casse. */
.hero-title {
  font-size: clamp(2.4rem, 6.8vw, 5.2rem); line-height: 0.98;
  letter-spacing: -0.045em;
  margin: 0 0 1.2rem; font-weight: 800;
  text-wrap: balance;
}

/* Sur l'encre, c'est la version claire du bleu qui sert : celle du papier s'y
   éteindrait. */
.accent { color: var(--bleu-scene); }

.hero-subline {
  margin: 0 0 1.9rem; max-width: 40ch;
  color: #d3cfc6; font-size: clamp(1.05rem, 2.4vw, 1.45rem);
  line-height: 1.5;
}

/* **Le bouton de l'ouverture télécharge, le lien fait défiler.** Le guide est
   gratuit et sans inscription : le chemin le plus court vers lui est un clic,
   pas un défilement jusqu'à un second bouton. Ceux qui veulent d'abord voir
   de quoi il parle ont le lien juste à côté, en texte, pour que le bleu plein
   reste réservé au geste principal. */
.hero-actions {
  display: flex; flex-wrap: wrap; align-items: center; gap: 1rem 1.6rem;
}
.hero-lien {
  color: var(--sur-scene); font-weight: 600; text-decoration: none;
  border-bottom: 1px solid rgba(250, 249, 246, 0.35); padding-bottom: 2px;
  transition: color 0.18s ease, border-color 0.18s ease;
}
.hero-lien:hover { color: var(--bleu-scene); border-color: var(--bleu-scene); }

.hero-compteur {
  margin: 0.35rem 0 0; font-size: 0.95rem; font-weight: 600; color: var(--bleu-scene);
}
.hero-rassure {
  margin: 1.1rem 0 0; font-size: 0.95rem; color: var(--sur-scene-doux);
}

/* --- Les gestes --------------------------------------------------------- */

.hero-cta, .primary-button, .secondary-button {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem;
  /* Ces deux lignes règlent un écart de hauteur entre un bouton et un lien
     posés côte à côte : un lien hérite de l'interligne du texte, un bouton
     part de celui du navigateur. On pose l'interligne pour les deux. */
  line-height: 1.25; vertical-align: middle;
  padding: 0.85rem 1.8rem; border-radius: var(--rayon);
  font-family: var(--titres); font-size: 1rem; font-weight: 700;
  text-decoration: none; border: 1px solid transparent; cursor: pointer;
  transition: filter 0.18s ease, transform 0.18s ease, border-color 0.18s ease;
}

.hero-cta, .primary-button {
  position: relative;
  overflow: hidden;
  background: var(--bleu-metal);
  color: var(--sur-bleu);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.22) inset,
              0 14px 28px -16px rgba(23, 33, 70, 0.7);
}
.hero-cta:hover, .primary-button:hover { filter: brightness(1.07); transform: translateY(-1px); }
.hero-cta:active, .primary-button:active { transform: translateY(1px); }

/* **Le reflet qui traverse au survol**, repris de Layonnage. Il ne passe
   qu'une fois par survol : un reflet en boucle deviendrait une guirlande, et
   le mouvement est réservé au geste que la personne fait. */
.hero-cta::after, .primary-button::after {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 28%;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.4), transparent);
  transform: translateX(-120%) skewX(-18deg);
  pointer-events: none;
}

.hero-cta:hover::after,
.primary-button:hover::after { animation: reflet 0.7s ease; }

@keyframes reflet {
  from { transform: translateX(-120%) skewX(-18deg); }
  to { transform: translateX(320%) skewX(-18deg); }
}

.hero-cta { font-size: 1.18rem; padding: 1.02rem 2.4rem; border-radius: 8px; }

.secondary-button {
  background: var(--feuille); color: var(--encre); border-color: var(--trait);
  font-size: 0.93rem; padding: 0.68rem 1.25rem;
}
.secondary-button:hover { border-color: var(--trait-fort); background: var(--creux); }

/* --- Les réseaux --------------------------------------------------------
   Ils vivent sur l'ouverture, donc sur l'encre : leurs couleurs sont celles
   de la scène, pas celles du papier. */

.social-row {
  display: flex; justify-content: flex-start; gap: 0.6rem; margin-top: 1.8rem;
}
.social-button {
  display: grid; place-items: center; width: 42px; height: 42px;
  border: 1px solid rgba(255, 255, 255, 0.16); border-radius: var(--rayon);
  background: rgba(0, 0, 0, 0.32); color: #ddd9d0;
  transition: color 0.18s ease, border-color 0.18s ease;
}
.social-button svg { width: 19px; height: 19px; fill: none; stroke: currentColor; stroke-width: 1.7; }
.social-button:hover { color: var(--bleu-scene); border-color: var(--bleu-scene); }

/* --- Les étapes du guide ------------------------------------------------ */

.etapes {
  list-style: none; margin: 0 auto; padding: 0; max-width: 46rem;
  display: grid; gap: 1px; background: var(--trait);
  border: 1px solid var(--trait); border-radius: var(--rayon-grand);
  overflow: hidden;
}
.etapes li {
  display: grid; grid-template-columns: 3.7rem 1fr; gap: 1.2rem; align-items: start;
  padding: 1.35rem 1.45rem; background: var(--feuille);
}

/* **Les icônes viennent de Gemini, et elles sont détourées.** Mes premiers
   dessins au trait tenaient techniquement mais restaient pauvres, et Joris
   avait raison de les trouver secs. Celles ci sont rendues à 256 pixels puis
   découpées, et surtout leur fond blanc a été transformé en transparence :
   un fond blanc posé sur une pastille colorée se verrait comme un timbre.
   Elles suivent donc leur support, ici la pastille bleu très clair.

   **Elles ont grossi d'un tiers le 19 septembre 2026.** À 2,9 rem de pastille
   et 1,7 rem de dessin, Joris ne distinguait plus le geste sur un écran
   d'ordinateur : un poignet plié et une main au sol se ressemblent à cette
   taille. Un pictogramme qu'il faut deviner ne sert à rien, autant ne rien
   mettre. La pastille passe donc à 3,7 rem, le dessin à 2,5, et la colonne de
   la liste suit. */
.etape-icone {
  display: grid; place-items: center; width: 3.7rem; height: 3.7rem;
  border-radius: var(--rayon); background: rgba(42, 78, 203, 0.07);
  border: 1px solid rgba(42, 78, 203, 0.18);
}
.etape-icone img {
  width: 2.5rem; height: 2.5rem; display: block;
}

.etape-texte { display: grid; gap: 0.2rem; }

/* Le numéro a quitté la pastille pour laisser la place au dessin, mais l'ordre
   est le propos même de cette page : il revient en étiquette. */
.etape-rang {
  font-family: var(--titres);
  font-size: 0.7rem; font-weight: 700; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--bleu-texte);
}
.etape-texte strong { font-size: 1.02rem; font-weight: 700; }
.etape-texte > span:last-child { color: var(--encre-douce); font-size: 0.94rem; line-height: 1.55; }

/* --- Avant tout : la sortie ---------------------------------------------
   Le guide la place en tête, avant les quatre étapes : tant qu'on ne sait pas
   sortir, la peur bloque tout le reste. L'accueil la montrait nulle part. Elle
   passe donc au-dessus de la liste, avec son croquis et le geste en une
   phrase. Pas de bleu plein : ce n'est pas le geste à faire sur la page, c'est
   celui à faire au sol. */
.avant-tout {
  max-width: 46rem; margin: 0 auto 1.1rem;
  display: grid; grid-template-columns: 13rem 1fr; gap: 1.3rem; align-items: center;
  padding: 1.1rem 1.35rem;
  background: var(--feuille); border: 1px solid var(--trait);
  border-left: 3px solid var(--bleu); border-radius: var(--rayon-grand);
}
.avant-tout-croquis { width: 100%; height: auto; display: block; }
.avant-tout-texte { display: grid; gap: 0.3rem; }
.avant-tout-rang {
  margin: 0; font-family: var(--titres); font-size: 0.7rem; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--bleu-texte);
}
.avant-tout h3 { margin: 0; font-size: 1.1rem; }
.avant-tout p { margin: 0; font-size: 0.94rem; line-height: 1.55; }
.avant-tout .avant-tout-note { color: var(--encre-douce); font-size: 0.88rem; }

/* --- Les chiffres ------------------------------------------------------- */

.chiffres-titre {
  max-width: 46rem; margin: 2.2rem auto 0.7rem;
  font-size: 0.74rem; font-weight: 700; letter-spacing: 0.1em;
  color: var(--encre-douce); text-transform: uppercase;
}
.chiffres {
  max-width: 46rem; margin: 0 auto;
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 1px;
  background: var(--trait); border: 1px solid var(--trait);
  border-radius: var(--rayon-grand); overflow: hidden;
}
.chiffres > div { background: var(--feuille); padding: 1rem 1.2rem; }
.nombre {
  display: block; font-size: 1.85rem; font-weight: 800; line-height: 1.05;
  letter-spacing: -0.04em; color: var(--encre); font-variant-numeric: tabular-nums;
}
/* Le premier chiffre est celui qui compte : le nombre d'étapes. Lui seul
   porte la couleur, sinon quatre bleus alignés ne désignent plus rien. */
.chiffres > div:first-child .nombre { color: var(--bleu-texte); }
.quoi { display: block; margin-top: 0.15rem; font-size: 0.82rem; color: var(--encre-douce); line-height: 1.35; }

.guide-telecharger { margin: 2rem 0 0; text-align: center; }
.guide-note {
  max-width: 46ch; margin: 1rem auto 0; text-align: center;
  font-size: 0.88rem; color: var(--encre-douce);
}

/* --- Le matériel --------------------------------------------------------
   Trois cartes, jamais plus : au delà, la page cesse d'être une
   recommandation et devient un catalogue, et le visiteur cesse de croire
   qu'on lui conseille quelque chose.

   Chaque carte porte le rang de l'étape qu'elle sert, parce qu'un objet ne
   se recommande pas seul : il répond à un problème que le guide a décrit
   quelques centimètres plus haut. */

#materiel[hidden] { display: none; }

.materiel-grille {
  display: flex; flex-wrap: wrap; gap: 0.9rem;
  justify-content: center;
  max-width: 62rem; margin-inline: auto;
}

.materiel-carte {
  flex: 0 1 19.5rem; min-width: 0;
  display: flex; flex-direction: column; gap: 0.4rem;
  padding: 1.35rem;
  border: 1px solid var(--trait); border-radius: var(--rayon-grand);
  background: var(--feuille); text-decoration: none;
  transition: border-color 0.18s ease, transform 0.18s ease;
}
.materiel-carte:hover { border-color: var(--bleu); transform: translateY(-2px); }

/* La photo prend toute la largeur de la carte, bord à bord, et toutes les
   cartes gardent le même cadre pour que les titres restent alignés. */
.materiel-photo {
  display: block; align-self: stretch; aspect-ratio: 4 / 3; overflow: hidden;
  margin: -1.35rem -1.35rem 0.6rem;
  border-radius: var(--rayon-grand) var(--rayon-grand) 0 0;
  background: #f3f3f5;
}
.materiel-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* **Un seul fond pour toutes les cartes, le gris clair de la fiche Eric Flag.**
   Les photos de marque arrivent sur blanc pur ou sur gris, et côte à côte la
   différence se voit. Plutôt que de retoucher les fichiers, une photo marquée
   « fond blanc » se multiplie avec le cadre : son blanc prend le gris, le
   produit ne change pas. Demandé par Joris le 24 septembre 2026, pour que les
   photos du matériel se ressemblent. */
.materiel-photo-blanche img { mix-blend-mode: multiply; }

.materiel-rang {
  font-family: var(--titres);
  font-size: 0.7rem; font-weight: 700; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--bleu-texte);
}
.materiel-carte strong { font-family: var(--titres); font-size: 1.08rem; letter-spacing: -0.01em; }
.materiel-pourquoi { font-size: 0.9rem; line-height: 1.5; color: var(--encre-douce); }

.materiel-cta {
  margin-top: auto; padding-top: 0.85rem; border-top: 1px solid var(--trait);
  font-size: 0.88rem; font-weight: 700; color: var(--bleu-texte);
  display: flex; align-items: center; gap: 0.35rem;
}
.materiel-cta b { transition: transform 0.18s ease; }
.materiel-carte:hover .materiel-cta b { transform: translateX(3px); }

/* **La mention n'est pas une note de bas de page.** Un lien partenaire doit
   être signalé comme tel, et le dire franchement vaut mieux que le cacher :
   c'est ce qui fait qu'on croit le reste de la page. */
.materiel-mention {
  max-width: 46ch; margin: clamp(1.4rem, 3vw, 2rem) auto 0;
  text-align: center; font-size: 0.86rem; color: var(--encre-douce);
}

/* --- Qui je suis --------------------------------------------------------
   La photo tient une colonne étroite et le texte l'autre. Sur téléphone elle
   passe au dessus, recadrée en paysage : un portrait vertical pleine largeur
   pousserait le texte hors de l'écran avant qu'on en lise un mot. */

/* **La section est posée sur une feuille**, et non à même le papier. Les deux
   colonnes flottaient au milieu du vide entre deux sections encadrées : elles
   étaient le seul bloc de la page sans contour, et ça se voyait comme un trou
   plutôt que comme une respiration. */
.moi {
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
  gap: clamp(1.4rem, 4vw, 2.8rem);
  align-items: center;
  max-width: 58rem;
  margin-inline: auto;
  background: var(--feuille);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-grand);
  padding: clamp(1.2rem, 3vw, 2rem);
}

.moi-photo { margin: 0; }

.moi-photo img {
  width: 100%;
  /* **Sans cette ligne, la photo mesure deux mille pixels de haut.** Les
     attributs « width » et « height » de la balise valent une règle CSS de
     spécificité nulle : celle ci fixait donc la hauteur à 2048, et le rapport
     posé juste en dessous ne servait plus à rien, puisqu'il demande qu'une des
     deux dimensions soit libre. Mesuré sur la page rendue. */
  height: auto;
  aspect-ratio: 3 / 4;
  object-fit: cover;
  object-position: center 22%;
  border-radius: var(--rayon-grand);
  display: block;
}

/* **Le nom se lit avant le texte.** La colonne de droite était trois
   paragraphes de même taille, de même gris, collés les uns aux autres : un
   pavé que l'œil saute. Joris, le 19 septembre 2026 : « je mettrais Joris
   comme un peu en titre, en bleu ». Il a raison au delà du style, car une
   page « qui suis je » sans nom visible ne présente personne.

   Le nom prend donc la taille d'un titre et le bleu du papier, une ligne de
   métier passe dessous en petites capitales, et les paragraphes respirent. */
.moi-nom {
  margin: 0; font-family: var(--titres);
  font-size: clamp(1.7rem, 4vw, 2.3rem); font-weight: 800;
  letter-spacing: -0.03em; line-height: 1; color: var(--bleu-texte);
}
.moi-role {
  margin: 0.55rem 0 0; font-size: 0.74rem; font-weight: 700;
  letter-spacing: 0.13em; text-transform: uppercase; color: var(--encre-douce);
}
/* Le filet reprend la séparation des sections, en plus court : le bleu du
   nom se prolonge de quelques centimètres puis s'éteint. */
.moi-filet {
  width: 4.5rem; height: 2px; margin: 1rem 0 1.15rem; border: 0; border-radius: 2px;
  background: linear-gradient(90deg, var(--bleu), rgba(42, 78, 203, 0));
}

.moi-texte p { margin: 0 0 1rem; }
/* La première phrase porte le propos : elle se lit un cran plus grand. */
.moi-texte .moi-chapo { font-size: 1.08rem; line-height: 1.6; }
.moi-texte p:last-child { margin-bottom: 0; color: var(--encre-douce); }

@media (max-width: 46rem) {
  .moi { grid-template-columns: 1fr; }
  /* **Le cadrage du téléphone montrait le torse et coupait le visage.** En
     16 / 10, une photo verticale perd les deux tiers de sa hauteur, et le
     point de fuite à 20 pour cent tombait sous le menton. Joris, le
     19 septembre 2026 : « ma photo est pas bien centrée, on pourrait la
     remonter ». Le cadre passe en portrait doux et remonte à 8 pour cent :
     le visage est dedans, le buste aussi, rien d'autre. */
  .moi-photo img { aspect-ratio: 4 / 5; object-position: center 8%; }
}

/* --- Les partenaires, dans la clairière ---------------------------------
   **La deuxième scène de la page.** Le site est clair de bout en bout, et
   trois cartes de plus sur le même papier se seraient fondues dans les
   étapes du guide. L'encre les détache sans rien ajouter : c'est un choix de
   mise en page, pas le retour du thème sombre.

   Elle sort du cadre jusqu'aux bords de la fenêtre, comme l'ouverture. */

#bons-plans {
  margin-inline: calc(50% - 50vw);
  padding-inline: clamp(1rem, 4vw, 2rem);
  background: var(--scene);
  color: var(--sur-scene);
}
/* Les deux bords de la scène sombre ne portent aucune séparation : l'encre
   fait la coupure toute seule, et un filet posé dessus ferait une bavure. */
#bons-plans.section-panel + .section-panel,
.section-panel + #bons-plans.section-panel { border-top: 0; }
#bons-plans.section-panel + .section-panel::before,
#bons-plans.section-panel + .section-panel::after,
.section-panel + #bons-plans.section-panel::before,
.section-panel + #bons-plans.section-panel::after { display: none; }
#bons-plans .section-heading p { color: var(--sur-scene-doux); }

/* **La grille tient quel que soit le nombre de cartes, pair ou impair.**
   Avec « 1fr », les cartes se partageaient toute la largeur disponible : à
   trois elles étaient justes, à deux elles s'étiraient en deux pavés trop
   larges, et une carte seule occupait un tiers de page collé à gauche.

   On borne donc la largeur d'une carte au lieu de la laisser s'étirer, et on
   centre ce qui reste. Trois cartes font trois colonnes, deux font deux
   colonnes centrées, une seule fait une carte centrée à sa vraie taille. Le
   jour où il y en a quatre ou cinq, elles se rangent d'elles mêmes. */
.partner-grid {
  display: flex; flex-wrap: wrap; gap: 0.9rem;
  justify-content: center;
  max-width: 62rem; margin-inline: auto;
}

/* **Une largeur bornée, et le reste se centre tout seul.** Avec des colonnes
   en « 1fr », les cartes se partageaient toute la largeur : à trois elles
   étaient justes, à deux elles s'étiraient en pavés, et une carte seule
   occupait un tiers de page collée à gauche.

   La grille avec « auto-fit » corrigeait l'étirement mais gardait une piste
   vide au bout, dont l'espacement décalait le centrage de sept pixels, mesurés
   sur la page rendue. Une rangée souple n'a pas ce défaut : elle ne compte que
   les cartes qui existent. Trois, deux, une ou cinq, la rangée reste centrée
   et les cartes gardent la même taille. */
/* **Pas de « flex-grow », et c'est la clé.** Avec lui, les cartes réclament
   l'espace libre de leur rangée, et la largeur maximale les empêche de le
   prendre : l'espace reste là, mais le centrage ne s'applique plus. À quatre
   cartes, la quatrième se collait à gauche sous une rangée de trois, mesuré
   sur la page rendue. Sans lui, chaque carte garde sa largeur et chaque
   rangée se centre, y compris la dernière quand elle est incomplète. */
.partner-card {
  flex: 0 1 19.5rem;
  min-width: 0;
}

.partner-card {
  display: flex; flex-direction: column; gap: 0.9rem;
  padding: 1.35rem;
  border: 1px solid var(--trait-scene); border-radius: var(--rayon-grand);
  background: var(--scene-carte); text-decoration: none;
  transition: border-color 0.18s ease, transform 0.18s ease;
}
.partner-card:hover { border-color: var(--bleu-scene); transform: translateY(-2px); }

.partner-logo {
  display: grid; place-items: center; width: 46px; height: 46px;
  border-radius: var(--rayon); background: rgba(255, 255, 255, 0.06);
  flex-shrink: 0;
}
.partner-logo img { width: 30px; height: 30px; object-fit: contain; }

.partner-copy { display: grid; gap: 0.2rem; flex: 1; }
.partner-copy strong { font-family: var(--titres); font-size: 1.08rem; font-weight: 700; }
.partner-copy small { font-size: 0.88rem; line-height: 1.5; color: var(--sur-scene-doux); }
.partner-copy small b { color: var(--bleu-scene); font-weight: 700; }

.partner-cta {
  margin-top: auto; padding-top: 0.85rem; border-top: 1px solid var(--trait-scene);
  font-size: 0.88rem; font-weight: 700; color: var(--bleu-scene);
  display: flex; align-items: center; gap: 0.35rem;
}
.partner-cta b { transition: transform 0.18s ease; }
.partner-card:hover .partner-cta b { transform: translateX(3px); }

/* **Ce qui ne rapporte rien au visiteur descend sous son propre intertitre.**
   La section s'appelle « bons plans » : une carte où il ne gagne rien y abîme
   la confiance qu'il accorde aux deux autres. Elle reste sur la page, mais
   elle dit ce qu'elle est. */
.bloc-soutien {
  max-width: 62rem;
  margin: clamp(2rem, 5vw, 3rem) auto 0;
  padding-top: clamp(1.4rem, 3vw, 2rem);
  border-top: 1px solid var(--trait-scene);
}
.bloc-soutien[hidden] { display: none; }

.bloc-soutien-titre {
  margin: 0 0 1rem;
  font-family: var(--titres);
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--sur-scene-doux);
}

/* Le bloc de soutien hérite de la même règle : une carte seule y est centrée
   à sa vraie taille, sans réglage particulier à maintenir. */

/* --- Le formulaire ------------------------------------------------------ */

/* **Le formulaire est posé sur une feuille, avec une lueur derrière.** Il
   flottait à même le papier, sans contour : deux champs et un bouton au
   milieu du vide ressemblaient à une fin de page, pas à une invitation.
   Joris, le 19 septembre 2026 : « me contacter, je lui mettrais un bloc
   aussi, avec des lueurs bleues ».

   La lueur vit derrière la feuille, pas dessous le texte : le bloc est opaque
   et n'en laisse dépasser que le pourtour. Elle se peint donc dans le plan du
   fond de page, c'est pour cela qu'elle porte un rang négatif. */
.contact-bloc {
  position: relative;
  max-width: 44rem; margin-inline: auto;
  padding: clamp(1.3rem, 3.5vw, 2.3rem);
  background: var(--feuille);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-grand);
  box-shadow: var(--ombre);
}
.contact-bloc::before {
  content: ""; position: absolute; inset: -26px; z-index: -1; pointer-events: none;
  border-radius: 26px; filter: blur(26px);
  background:
    radial-gradient(60% 55% at 50% 0%, rgba(42, 78, 203, 0.26), transparent 70%),
    radial-gradient(70% 60% at 50% 100%, rgba(42, 78, 203, 0.14), transparent 72%);
}

.contact-form { max-width: 40rem; margin-inline: auto; display: grid; gap: 0.9rem; }
.form-grid { display: grid; gap: 0.9rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr)); }
.contact-form label { display: grid; gap: 0.35rem; }
.contact-form label > span { font-size: 0.84rem; font-weight: 600; color: var(--encre-douce); }
.contact-form input,
.contact-form textarea {
  width: 100%; padding: 0.7rem 0.85rem;
  border: 1px solid var(--trait); border-radius: var(--rayon);
  background: var(--feuille); color: var(--encre);
  font-family: inherit; font-size: 0.97rem;
}
.contact-form textarea { resize: vertical; min-height: 8rem; }
.contact-form input::placeholder,
.contact-form textarea::placeholder { color: #9b968a; }
.contact-form input:focus, .contact-form textarea:focus { border-color: var(--bleu); outline: none; }
.form-honeypot { position: absolute; left: -9999px; opacity: 0; }
.form-status { margin: 0; font-size: 0.9rem; color: var(--valide); }
.form-status[hidden] { display: none; }

/* Le bouton d'envoi était calé à gauche pendant que le titre, le formulaire et
   les deux boutons de courrier étaient centrés : un seul élément de travers
   dans une colonne centrée se voit plus qu'une page entière mal alignée. */
#contact-submit { justify-self: center; }

.mail-actions {
  display: flex; gap: 0.6rem; justify-content: center; margin-top: 1.1rem; flex-wrap: wrap;
}

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

/* --- Le pied de page ----------------------------------------------------
   **Ce qui en est parti.** « SYSTÈME EN LIGNE » était un reste de l'ancienne
   direction cyber, et le compteur de visites comptait les passages de ce
   navigateur là : il affichait soixante à Joris et un à tout le monde. Un
   chiffre faux vaut moins que pas de chiffre.

   À la place, un pied qui sert : où aller, comment écrire, et les deux pages
   légales qu'un site avec un formulaire doit rendre accessibles. */

.site-footer {
  border-top: 1px solid var(--trait); margin-top: 1rem;
  padding: clamp(2rem, 5vw, 3rem) 0 0;
  display: grid;
  gap: clamp(1.6rem, 4vw, 2.4rem) 2rem;
  grid-template-columns: minmax(0, 1.6fr) repeat(2, minmax(0, 1fr));
  align-items: start;
}

.footer-marque { display: grid; gap: 0.45rem; justify-items: start; }
.footer-nom { margin: 0; font-family: var(--titres); font-weight: 700; font-size: 1.05rem; letter-spacing: -0.02em; }
.footer-quoi { margin: 0; font-size: 0.88rem; color: var(--encre-douce); max-width: 34ch; line-height: 1.5; }

.footer-colonne { display: grid; gap: 0.4rem; align-content: start; }

.footer-titre {
  margin: 0 0 0.2rem;
  font-family: var(--titres);
  font-size: 0.7rem; font-weight: 700; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--encre-douce);
}

.footer-colonne a {
  display: inline-flex; align-items: center; gap: 0.5rem;
  font-size: 0.9rem; color: var(--encre); text-decoration: none;
  width: fit-content;
}
/* **Sans cette ligne, « Matériel » réapparaît dans le pied de page.** La
   section est masquée tant qu'aucun lien partenaire n'est validé, et
   content-loader.js pose l'attribut « hidden » sur les liens qui la visent.
   Cet attribut ne vaut qu'un « display: none » de la feuille du navigateur :
   la règle ci dessus, plus forte, le rallumait. Le visiteur cliquait et
   n'arrivait nulle part. */
.footer-colonne a[hidden] { display: none; }

/* **Les deux façons de me joindre portent leur signe.** Instagram et une
   adresse e mail écrits en toutes lettres se ressemblaient, alignés sous le
   même titre. Le dessin dit lequel est lequel avant même la lecture, et ce
   sont les deux mêmes tracés que dans l'ouverture : un seul jeu de signes
   pour toute la page. */
.footer-icone {
  width: 17px; height: 17px; flex-shrink: 0;
  fill: none; stroke: currentColor; stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round;
  color: var(--encre-douce);
}
.footer-colonne a:hover .footer-icone { color: var(--bleu-texte); }
.footer-colonne a:hover { color: var(--bleu-texte); text-decoration: underline; }

/* La dernière ligne : elle traverse toute la largeur, sous un filet. */
.footer-droits,
.footer-legal {
  grid-column: 1 / -1;
  margin: 0;
  padding-top: clamp(1.2rem, 3vw, 1.8rem);
  border-top: 1px solid var(--trait);
  font-size: 0.82rem; color: var(--encre-douce);
}

/* Le script des mentions légales ajoute sa barre après le copyright : les deux
   partagent donc la même ligne, et seul le premier porte le filet. */
.footer-legal {
  display: flex; gap: 1.2rem;
  border-top: 0; padding-top: 0.5rem;
}
.footer-legal a { color: var(--encre-douce); text-decoration: none; }
.footer-legal a:hover { color: var(--bleu-texte); text-decoration: underline; }

@media (max-width: 46rem) {
  .site-footer { grid-template-columns: 1fr 1fr; }
  .footer-marque { grid-column: 1 / -1; }
}

/* --- Le retour en haut -------------------------------------------------- */

.back-to-top {
  position: fixed; right: 1.1rem; bottom: 1.1rem; z-index: 70;
  width: 42px; height: 42px; border-radius: var(--rayon);
  border: 1px solid var(--trait); background: rgba(255, 255, 255, 0.94);
  color: var(--encre); font-size: 1.1rem; cursor: pointer;
  box-shadow: var(--ombre);
  opacity: 0; visibility: hidden; transition: opacity 0.22s ease, visibility 0.22s ease;
}
.back-to-top.is-visible { opacity: 1; visibility: visible; }
.back-to-top:hover { border-color: var(--bleu); color: var(--bleu-texte); }

/* --- Téléphone ---------------------------------------------------------- */

@media (max-width: 760px) {
  /* **Une seule colonne, le texte puis la photo.** Le geste à faire, le
     bouton, reste au dessus de la ligne de flottaison ; la photo se déroule
     juste après, à sa taille, sans rien recouvrir. Le cadre s'allonge un peu
     parce qu'un téléphone est haut : la silhouette y gagne. */
  /* **Le téléphone n'a pas d'image d'ouverture du tout.** Le dessin y a été
     essayé deux fois, sous le texte puis au dessus : « je suis pas du tout fan
     de la version téléphone », Joris, le 19 septembre 2026, « à la limite j'en
     mettrais pas, pas ici en tout cas, pas en tout début ». Sur un écran
     étroit, une silhouette très haute mange la moitié de la vue et repousse le
     bouton ; le message la porte mieux tout seul. Elle reste sur l'ordinateur,
     où la colonne de droite est vide sans elle. */
  .hero-grille { grid-template-columns: 1fr; gap: 1.4rem; }
  .hero-illustration { display: none; }
  .hero { padding-block: clamp(3rem, 11vw, 4.5rem); }
  .hero-title { font-size: clamp(2.2rem, 9vw, 3rem); }
  .hero-subline { margin-bottom: 1.4rem; }
  .social-row { margin-top: 1.4rem; }

  /* ---- TOUT AU MILIEU ----------------------------------------------------
     Joris, le même jour : « sur le téléphone, tu me centres tous les textes au
     milieu, tous les blocs, tout au milieu ». Sur un écran large, aligner à
     gauche donne une colonne franche et des lignes qui commencent au même
     endroit ; sur un écran étroit, chaque bloc fait déjà toute la largeur, et
     ce sont les fins de ligne en escalier qu'on voit. Le centre range tout.

     Les champs de saisie sont la seule exception : leur libellé est centré
     comme le reste, mais ce qu'on tape reste à gauche, sinon le texte danse
     sous les doigts pendant la frappe. */
  .hero-content { text-align: center; }
  .hero-subline { margin-inline: auto; }
  .social-row { justify-content: center; }
  .hero-actions { justify-content: center; }

  .etapes li { grid-template-columns: 1fr; justify-items: center; gap: 0.8rem; text-align: center; }
  .chiffres-titre, .chiffres > div { text-align: center; }
  .avant-tout { grid-template-columns: 1fr; justify-items: center; text-align: center; border-left: 1px solid var(--trait); border-top: 3px solid var(--bleu); }
  .avant-tout-croquis { max-width: 15rem; }

  .moi { justify-items: center; }
  .moi-texte { text-align: center; }
  /* Le filet s'éteint des deux côtés quand il est au milieu : le dégradé qui
     part du bleu pour finir en rien penchait tout le bloc vers la gauche. */
  .moi-filet {
    margin-inline: auto;
    background: linear-gradient(90deg, rgba(42, 78, 203, 0), var(--bleu), rgba(42, 78, 203, 0));
  }

  .partner-card, .materiel-carte { align-items: center; text-align: center; }
  .partner-cta, .materiel-cta { justify-content: center; align-self: stretch; }
  .bloc-soutien-titre { text-align: center; }

  .contact-form label > span { text-align: center; }

  .site-footer { justify-items: center; text-align: center; }
  .footer-marque, .footer-colonne { justify-items: center; }
  .footer-quoi { margin-inline: auto; }
  .footer-legal { justify-content: center; }

  .menu-toggle {
    display: grid; gap: 4px; padding: 9px; margin-left: 0.25rem;
    border: 1px solid var(--trait); border-radius: var(--rayon);
    background: none; cursor: pointer;
  }
  .menu-toggle span { display: block; width: 18px; height: 2px; background: var(--encre); }

  .nav-links {
    position: absolute; top: 100%; left: 0; right: 0;
    flex-direction: column; gap: 0; margin: 0; padding: 0.5rem;
    background: rgba(255, 255, 255, 0.98); border-bottom: 1px solid var(--trait);
    display: none;
  }
  .nav-links.open { display: flex; }
  .nav-links a { padding: 0.75rem 0.9rem; }

  .lang-switch { margin-left: auto; }

  /* Le retrait du haut montait à 15 rem pour dégager la photo de fond, qui
     n'est plus derrière le texte : il redevient une marge ordinaire, et la
     hauteur minimale disparaît pour que la section fasse la taille de ce
     qu'elle contient. */
  .hero { padding-top: clamp(2.5rem, 9vw, 4rem); min-height: 0; }
  .hero-content { max-width: none; }
  .chiffres { grid-template-columns: repeat(2, 1fr); }
  .footer-right { text-align: left; }
  #contact-submit { justify-self: stretch; }
}

@media (min-width: 52rem) {
  .chiffres { grid-template-columns: repeat(4, 1fr); }
}

/* --- Mouvement réduit --------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
  .brand-intro { display: none; }
}
