/* ==========================================================================
   fon10.studio — feuille de style
   Jetons (couleurs, rayons, polices) en tête : c'est ici que l'on personnalise.
   ========================================================================== */
/* ---------- Polices hébergées sur le site (29/09/2026) ----------
   Avant : Google Fonts (une feuille de style sur fonts.googleapis.com, puis les fichiers sur fonts.gstatic.com) :
   deux connexions de plus AVANT le premier affichage, ~1,9 s de « requêtes bloquantes » selon PageSpeed.
   Mêmes fichiers (polices variables, une par jeu de caractères), mêmes plages que Google ; licence OFL.
   Les deux fichiers « latin » sont préchargés dans le <head>. */
@font-face { font-family: 'Inter'; font-style: normal; font-weight: 400 600; font-display: swap; src: url('../fonts/inter-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: 'Inter'; font-style: normal; font-weight: 400 600; font-display: swap; src: url('../fonts/inter-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: 'Sora'; font-style: normal; font-weight: 500 800; font-display: swap; src: url('../fonts/sora-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: 'Sora'; font-style: normal; font-weight: 500 800; font-display: swap; src: url('../fonts/sora-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; }

:root {
  --bg: #070810;
  --bg-2: #0b0d19;
  --surface: rgba(255, 255, 255, .035);
  --surface-2: rgba(255, 255, 255, .06);
  /* fonds de cartes : quasi opaques, pour que le réseau de fond ne transparaisse pas */
  --card-bg: linear-gradient(180deg, rgba(22, 25, 46, .96), rgba(12, 14, 27, .975));
  --card-bg-2: rgba(15, 17, 32, .96);
  --line: rgba(255, 255, 255, .09);
  --txt: #eef0f8;
  --muted: #b9c0d6;   /* gris des textes secondaires, éclairci à la demande du fondateur */
  --p: #7c5cff;
  --p2: #22d3ee;
  --p3: #f472b6;
  --grad: linear-gradient(135deg, #7c5cff 0%, #22d3ee 100%);
  --glow: 0 0 0 1px rgba(124, 92, 255, .35), 0 24px 60px -20px rgba(124, 92, 255, .55);
  --r: 22px;
  --r-sm: 14px;
  --hdr: 72px;
  --font-h: "Sora", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-b: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  --ease: cubic-bezier(.2, .8, .2, 1);
  --spring: cubic-bezier(.22, 1.35, .32, 1);
  /* système de mouvement : cinq durées, deux courbes de plus (voir README) */
  --t-fast: .15s; --t-base: .3s; --t-slow: .6s; --t-cine: 1.2s;
  --ease-in: cubic-bezier(0, 0, .2, 1); --ease-out: cubic-bezier(.4, 0, 1, 1);
  --container: 1180px;
}

/* ---------- Base ---------- */
*, *::before, *::after { box-sizing: border-box; }
/* overflow-x: clip sur la racine : les blocs en attente d'entrée (translatés ou agrandis hors écran)
   ne peuvent jamais créer de défilement horizontal, même sur iOS où body seul ne suffit pas */
html { scroll-padding-top: var(--hdr); -webkit-text-size-adjust: 100%; overflow-x: clip; }
html.native-scroll { scroll-behavior: smooth; }
html.lenis, html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }
.lenis.lenis-stopped { overflow: hidden; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--txt);
  font: 400 16px/1.65 var(--font-b);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(60% 50% at 85% 0%, rgba(124, 92, 255, .14), transparent 60%),
    radial-gradient(50% 40% at 10% 95%, rgba(34, 211, 238, .10), transparent 60%);
}
img, svg { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
h1, h2, h3, h4 { font-family: var(--font-h); line-height: 1.12; margin: 0 0 .5em; letter-spacing: -.02em; }
h2 { font-size: clamp(1.7rem, 1.1rem + 2.3vw, 2.7rem); font-weight: 700; text-transform: uppercase; letter-spacing: .01em; }
h3 { font-size: 1.35rem; font-weight: 600; }
p { margin: 0 0 1em; }
ul, ol { list-style: none; margin: 0; padding: 0; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
:focus-visible { outline: 2px solid var(--p2); outline-offset: 3px; border-radius: 6px; }
.container { width: min(var(--container), 100% - 48px); margin-inline: auto; }
.container--narrow { --container: 820px; }
.grad { background: var(--grad); -webkit-background-clip: text; background-clip: text; color: transparent; }
.skip { position: absolute; left: 12px; top: -60px; z-index: 200; padding: 10px 16px; border-radius: 8px; background: var(--p); color: #fff; }
.skip:focus { top: 12px; }

/* ---------- Barre de progression ---------- */
.progress { position: fixed; top: 0; left: 0; right: 0; height: 3px; z-index: 120; pointer-events: none; }
.progress span { display: block; height: 100%; background: var(--grad); transform: scaleX(var(--p, 0)); transform-origin: 0 50%; }

/* ---------- Réseau de particules (fond de page, dessiné par particles.js) ---------- */
.fx-canvas { position: fixed; inset: 0; z-index: -1; pointer-events: none; opacity: 0; }

/* ---------- Le voyage : tunnels 3D entre les sections (voyage.js) ---------- */
.voyage-canvas { position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; z-index: -1; pointer-events: none; opacity: 0; }
.voyage { position: relative; height: 150vh; pointer-events: none; }
.voyage[data-voyage="ecran"] { height: 190vh; }   /* un passage plus long et plus lent pour les écrans */
.voyage.is-static { height: 0; overflow: hidden; }
/* Un halo radial sombre derrière la légende : opaque au centre, fondu très progressif vers les
   bords. Pas de flou d'arrière-plan : sa zone laisse toujours une bordure visible. */
.voyage__caption::before {
  content: ""; position: absolute; left: 50%; top: 50%; z-index: -1; pointer-events: none;
  width: calc(min(130vw, 1200px) * var(--cs, 1)); height: calc(460px * var(--cs, 1)); transform: translate(-50%, -50%);
  background: radial-gradient(ellipse at center, rgba(7, 8, 16, .96) 0%, rgba(7, 8, 16, .88) 22%, rgba(7, 8, 16, .55) 45%, rgba(7, 8, 16, .18) 62%, rgba(7, 8, 16, 0) 76%);
}
/* La légende grossit avec le défilement par sa TAILLE DE POLICE (--cs, posé par voyage.js), pas par un
   transform : le texte reste net à toute échelle, jusqu'à ce qu'on le traverse */
.voyage__caption {
  position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); width: max-content;
  /* Sur téléphone la légende passe à la ligne : la largeur maximale grossit avec la police (× --cs),
     donc les retours à la ligne sont les MÊMES à toute échelle — le texte reste figé pendant qu'on entre dedans */
  max-width: calc(92vw * var(--cs, 1)); padding: 0 calc(24px * var(--cs, 1));
  z-index: 0; margin: 0; text-align: center;   /* centrée sur l'écran : elle grossit autour de son centre sans bouger */
  font-family: var(--font-h); font-weight: 800; font-size: calc(clamp(1.4rem, 1rem + 2.2vw, 2.8rem) * var(--cs, 1)); letter-spacing: .01em; text-transform: uppercase;
  text-shadow: 0 0 40px rgba(124, 92, 255, .6);
  opacity: 0;
}
.voyage__caption small { display: block; margin-top: .35em; font: 500 calc(clamp(.95rem, .9rem + .3vw, 1.15rem) * var(--cs, 1)) var(--font-b); letter-spacing: 0; text-transform: none; color: var(--muted); text-shadow: none; }
@media (min-width: 760px) { .voyage__caption { white-space: nowrap; max-width: none; } }
.voyage.is-active .voyage__caption { opacity: 1; transform: none; }
@media (max-width: 760px) { .voyage { height: 100vh; } .voyage[data-voyage="ecran"] { height: 130vh; } }

/* ---------- En-tête ---------- */
.header {
  position: fixed; top: 0; left: 0; right: 0; z-index: 100;
  height: var(--hdr);
  border-bottom: 1px solid transparent;
  transition: background .4s, border-color .4s;
}
/* Le verre (backdrop-filter) est sur un pseudo-élément, PAS sur .header : un filtre sur l'en-tête en ferait
   le bloc conteneur du menu mobile (position: fixed), qui se retrouverait écrasé à 0 px de haut dès que la page
   a défilé. Le pseudo-élément, lui, n'est l'ancêtre de rien. */
.header::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  -webkit-backdrop-filter: blur(16px) saturate(160%); backdrop-filter: blur(16px) saturate(160%);
}
/* Verre et flou PERMANENTS : dès le haut de page, la barre est un voile sombre translucide sur la scène */
.header { background: rgba(7, 8, 16, .55); border-color: rgba(255, 255, 255, .06); }
.header.is-scrolled { background: rgba(7, 8, 16, .72); border-color: var(--line); }
.header__inner { height: 100%; display: flex; align-items: center; justify-content: space-between; gap: 24px; }
.brand { display: inline-flex; align-items: center; }

.nav { display: flex; align-items: center; gap: 28px; }
.nav__list { display: flex; gap: 4px; }
.nav__link { position: relative; display: block; padding: 8px 12px; font-weight: 500; color: var(--muted); transition: color .25s; }
.nav__link::after {
  content: ""; position: absolute; left: 12px; right: 12px; bottom: 3px; height: 2px; border-radius: 2px;
  background: var(--grad); transform: scaleX(0); transform-origin: 0 50%; transition: transform .3s var(--ease);
}
.nav__link:hover, .nav__link.is-active { color: var(--txt); }
.nav__link:hover::after, .nav__link.is-active::after { transform: scaleX(1); }
.nav__cta { padding: 10px 18px; font-size: .9rem; }
.burger { display: none; }
/* Sélecteur de langue : la pastille des sites clients (FR EN), l'actif en dégradé */
.lang { display: inline-flex; gap: 2px; padding: 3px; border-radius: 999px; border: 1px solid var(--line); background: var(--surface); flex: none; }
.lang__link { padding: 6px 10px; border-radius: 999px; font-family: var(--font-h); font-size: .74rem; font-weight: 700; letter-spacing: .06em; color: var(--muted); transition: color .2s, background .2s; }
.lang__link:hover { color: var(--txt); }
.lang__link.is-active { background: var(--grad); color: #fff; }

/* ---------- Boutons ---------- */
.btn {
  position: relative; display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  padding: 13px 24px; border-radius: 999px;
  font-family: var(--font-h); font-weight: 600; font-size: .95rem; line-height: 1; white-space: nowrap;
  transition: transform .3s var(--ease), box-shadow .3s, background .3s, border-color .3s;
}
.btn svg { width: 18px; height: 18px; transition: transform .3s var(--ease); }
.btn--primary { color: #fff; background: var(--grad); box-shadow: 0 10px 30px -10px rgba(124, 92, 255, .7); }
.btn--primary:hover { box-shadow: 0 16px 40px -10px rgba(34, 211, 238, .6); }
.btn--primary:hover svg { transform: translateX(4px); }
.btn--ghost { color: var(--txt); border: 1px solid var(--line); background: var(--surface); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px); }
.btn--ghost:hover { border-color: rgba(255, 255, 255, .28); background: var(--surface-2); }
.btn--lg { padding: 16px 28px; font-size: 1rem; }

/* ---------- Héros ---------- */
.hero {
  position: relative; min-height: 100vh; display: flex; align-items: center;
  /* même marge au-dessus (sous la barre) et en dessous : le contenu est centré entre la barre et le bas de l'écran */
  padding: calc(var(--hdr) + 104px) 0 104px; overflow: hidden;   /* 104 : l'invite « Découvrir » (81 px avec son retrait) tient dessous */
}
@supports (min-height: 100svh) { .hero { min-height: 100svh; } }
/* La scène est FIXE : en descendant, la caméra plonge dans l'icosaèdre (scene.js), puis
   main.js l'estompe et la masque (is-gone) une fois le héros passé */
.hero__scene { position: fixed; top: 0; left: 0; width: 100%; height: 100vh; z-index: 0; pointer-events: none; }
.hero__scene.is-gone { visibility: hidden; }
.hero__runway { height: 110vh; pointer-events: none; }   /* plus de piste : la plongée dans la sphère s'étale sur plus de défilement */
@media (max-width: 1023px) { .hero__runway { height: 30vh; } }
#hero-canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.hero__fallback { position: absolute; inset: 0; display: none; overflow: hidden; }
html.no-webgl .hero__fallback { display: block; }
.hero__fallback i { position: absolute; border-radius: 50%; filter: blur(70px); opacity: .55; animation: float 14s ease-in-out infinite; }
.hero__fallback i:nth-child(1) { width: 46vw; height: 46vw; right: -8vw; top: 6vh; background: #7c5cff; }
.hero__fallback i:nth-child(2) { width: 34vw; height: 34vw; right: 18vw; bottom: -6vh; background: #22d3ee; animation-delay: -5s; }
.hero__fallback i:nth-child(3) { width: 22vw; height: 22vw; left: -6vw; bottom: 10vh; background: #f472b6; animation-delay: -9s; opacity: .35; }
@keyframes float { 0%, 100% { transform: translate3d(0, 0, 0) scale(1); } 50% { transform: translate3d(-4vw, 5vh, 0) scale(1.08); } }
.hero__veil {
  position: absolute; inset: 0;
  background:
    radial-gradient(60% 60% at 25% 50%, rgba(7, 8, 16, .55), transparent 70%),
    linear-gradient(to bottom, rgba(7, 8, 16, .35), rgba(7, 8, 16, 0) 25%, rgba(7, 8, 16, .92) 100%);
}
.hero__inner { position: relative; z-index: 1; }

/* ---------- Le terminal du héros ---------- */
/* La colonne occupe toute la largeur disponible à droite du texte, jusqu'au bord de l'écran */
.hero { --cl: max(24px, calc((100vw - var(--container)) / 2)); --hero-text-w: min(760px, calc(min(var(--container), 100vw - 48px) - 380px)); }
.hero__term {
  position: fixed; top: calc(50% - 60px); z-index: 1;
  left: calc(var(--cl) + var(--hero-text-w) + 48px); right: 24px;
  transform: translateY(-50%); transform-origin: 50% 50%;   /* en face du bloc de texte (au-dessus des compteurs) */
  pointer-events: none; will-change: transform, opacity;
}
.hero__term.is-gone { visibility: hidden; }
/* Sans cadre : ni bordure, ni barre, ni ombre — seule la colonne de commandes */
.term { border-radius: 16px; background: transparent; overflow: hidden; }
.term__bar { display: none; }
.term__bar {
  align-items: center; gap: 8px; padding: 12px 14px;
  background: rgba(255, 255, 255, .04); border-bottom: 1px solid rgba(255, 255, 255, .08);
  font: 500 .78rem var(--font-b); color: var(--muted);
}
.term__bar i { width: 11px; height: 11px; border-radius: 50%; background: #ff5f57; }
.term__bar i:nth-child(2) { background: #febc2e; }
.term__bar i:nth-child(3) { background: #28c840; }
.term__bar span { margin-left: 8px; }
/* Colonne haute et étroite ; les lignes montent, s'effacent en fondu en haut (masque) et
   arrivent en fondu en bas (animation) */
.term__body {
  height: min(400px, 50vh); padding: 18px 16px 14px; display: flex; flex-direction: column; justify-content: flex-end; overflow: hidden;
  font: clamp(12.5px, 0.85vw, 16px)/1.8 "Cascadia Code", "JetBrains Mono", "Fira Code", Consolas, "SF Mono", monospace; color: #dfe4f5;
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 28%, #000 100%);
  mask-image: linear-gradient(to bottom, transparent 0, #000 28%, #000 100%);
}
.term__line { white-space: pre-wrap; word-break: break-word; animation: term-in .6s ease-out; }
.term__line--cmd { color: #fff; }
.term__line--cmd::before { content: "$ "; color: var(--p2); font-weight: 700; }
.term__line--ok { color: #34d399; }
.term__line--step { color: #c4b5fd; }
.term__line--info { color: var(--muted); }
.term__line--url { color: #67e8f9; }
.term__line--warn { color: #fbbf24; }
.term__caret { display: inline-block; width: 8px; height: 1.05em; margin-left: 2px; vertical-align: -3px; background: var(--p2); animation: caret 1s steps(2, jump-none) infinite; }
@keyframes caret { 50% { opacity: 0; } }
@keyframes term-in { from { opacity: 0; transform: translateY(10px); } }
@media (max-width: 1023px) { .hero__term { display: none; } }
/* Sur grand écran le texte du héros laisse la place au terminal : jamais de chevauchement */
@media (min-width: 1024px) {
  .hero .hero__title { max-width: var(--hero-text-w); font-size: clamp(2.1rem, 1.2rem + 3.2vw, 3.6rem); }
  html[lang="en"] .hero .hero__title { font-size: clamp(2.1rem, 1.2rem + 2.9vw, 3.2rem); }   /* « built, maintained and hosted » tient sur sa ligne */
  .hero .hero__lead { max-width: min(600px, var(--hero-text-w)); }
}
.eyebrow {
  display: inline-flex; align-items: center; gap: 10px; margin: 0;
  padding: 8px 14px; border-radius: 999px; border: 1px solid var(--line); background: rgba(7, 8, 16, .45);
  font-size: .85rem; color: var(--muted); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
}
/* L'anneau qui pulse est un pseudo-élément agrandi et effacé (transform + opacity, animés par la carte graphique),
   plus une ombre animée : une ombre se redessine sur le fil principal à CHAQUE image, et c'était une des
   animations qui empêchaient la page de se calmer au chargement (PageSpeed, 29/09). Même rendu : anneau de
   4 px à 20 % qui s'élargit à 8 px en s'effaçant. */
.eyebrow__dot { position: relative; width: 8px; height: 8px; border-radius: 50%; background: var(--p2); }
.eyebrow__dot::after { content: ""; position: absolute; inset: -4px; border-radius: 50%; background: rgba(34, 211, 238, .2); animation: pulse 2.2s infinite; }
@keyframes pulse { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.5); opacity: 0; } }
.hero__title { max-width: 940px; margin: 24px 0 20px; font-size: clamp(2.1rem, 1.2rem + 4vw, 4rem); font-weight: 800; letter-spacing: -.03em; }
.hero__lead { max-width: 620px; font-size: clamp(1.05rem, 1rem + .4vw, 1.22rem); color: var(--muted); }
.hero__cta { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 30px; }
.stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 18px; margin-top: 64px; padding-top: 32px; border-top: 1px solid var(--line); }
.stats li { display: flex; flex-direction: column; gap: 4px; }
.stats strong { font-family: var(--font-h); font-weight: 700; font-size: clamp(1.6rem, 1.2rem + 1.2vw, 2.2rem); line-height: 1.1; background: var(--grad); -webkit-background-clip: text; background-clip: text; color: transparent; }
.stats span { font-size: .88rem; color: var(--muted); }
.stats strong span { font: inherit; color: inherit; }
.scroll-hint--old { position: absolute; left: 50%; bottom: 28px; z-index: 1; width: 26px; height: 42px; border: 2px solid rgba(255, 255, 255, .3); border-radius: 14px; transform: translateX(-50%); }
.scroll-hint--old span { position: absolute; left: 50%; top: 8px; width: 4px; height: 8px; margin-left: -2px; border-radius: 2px; background: var(--p2); animation: wheel 1.8s infinite; }
@keyframes wheel { 0% { transform: translateY(0); opacity: 1; } 70% { transform: translateY(14px); opacity: 0; } 100% { opacity: 0; } }

/* ---------- Sections ---------- */
.section { position: relative; padding: clamp(72px, 8vw, 110px) 0; }
/* Une section suivie d'un tunnel s'arrête juste sous son dernier bloc : le tunnel prend le relais
   au bas de l'écran pendant que ce bloc remonte, sans bande vide entre les deux */
.section:has(+ .voyage) { padding-bottom: 40px; }
.section--alt { background: linear-gradient(180deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, .025) 50%, rgba(255, 255, 255, 0)); }
/* Ligne de données en tête des sections alternées : un trait fin et un éclat qui le parcourt */
.section--alt::before {
  content: ""; position: absolute; top: 0; left: 8%; right: 8%; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(124, 92, 255, .45), rgba(34, 211, 238, .45), transparent);
}
.section--alt::after {
  content: ""; position: absolute; top: 0; left: 8%; width: 140px; height: 1px;
  background: linear-gradient(90deg, transparent, #fff, transparent); opacity: 0;
  animation: sweep 7s linear infinite;
}
@keyframes sweep { from { transform: translateX(-140px); opacity: 0; } 8% { opacity: .9; } 92% { opacity: .9; } to { transform: translateX(84vw); opacity: 0; } }
.section__head { max-width: 860px; margin: 0 auto 52px; text-align: center; }
.section__head .section__lead { max-width: 680px; margin-inline: auto; }
.section__lead { color: var(--muted); font-size: 1.08rem; }
.tag {
  display: inline-block; margin: 0 0 14px; padding: 6px 12px; border-radius: 999px;
  font-size: .76rem; font-weight: 600; letter-spacing: .08em; text-transform: uppercase;
  color: var(--p2); background: rgba(34, 211, 238, .1); border: 1px solid rgba(34, 211, 238, .25);
}

/* ---------- Cartes 3D (inclinaison au survol) ---------- */
[data-tilt] {
  transform: perspective(1000px) translateY(var(--lift, 0px)) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg)) scale(var(--sz, 1));
  transition: transform .12s ease-out, border-color .3s, box-shadow .3s;
  transform-style: preserve-3d;
}
[data-tilt].is-reset { transition: transform .8s var(--ease), border-color .3s, box-shadow .3s; }
.glare {
  position: absolute; inset: 0; border-radius: inherit; z-index: 0; pointer-events: none;
  background: radial-gradient(520px circle at var(--gx, 50%) var(--gy, 50%), rgba(255, 255, 255, .14), transparent 45%);
  opacity: 0; transition: opacity .35s;
}
[data-tilt]:hover .glare { opacity: 1; }

/* Circuit imprimé animé en haut à droite des cartes de service : des impulsions
   lumineuses parcourent les pistes, de l'extérieur vers la carte */
.card__circuit {
  position: absolute; top: 0; right: 0; width: 190px; height: 110px; pointer-events: none;
  clip-path: inset(0 round 0 var(--r) 0 0); --z: 4px;
}
.card__circuit path { fill: none; stroke: rgba(255, 255, 255, .09); stroke-width: 1.2; stroke-linecap: round; stroke-linejoin: round; }
.card__circuit circle { fill: rgba(255, 255, 255, .2); }
/* Les impulsions attendent la fin de l'éclat sur le chiffre (22 % du cycle), puis partent du cadre
   dans les pistes, légèrement décalées entre elles */
/* Motif 26 / 400 : avec un décalage de 466 aucun tiret n'est sur la piste (le premier attend à −40),
   puis le décalage descend jusqu'à 260 sur tout le reste du cycle : le tiret entre par le cadre,
   parcourt la piste et en sort par le bout. Il ne s'arrête jamais en route et n'est jamais garé. */
.card__circuit .pulse {
  stroke: var(--p2); stroke-width: 2; stroke-dasharray: 26 400; stroke-dashoffset: 466;
  animation: pulse-line var(--T, 3.4s) linear infinite; animation-delay: var(--pd, 0s);
}
.card__circuit .pulse:nth-child(8) { --pd: .08s; stroke: #a78bfa; }
.card__circuit .pulse:nth-child(9) { --pd: .16s; }
/* la propagation démarre à 16 % du cycle, juste après le second battement, et dure jusqu'à la fin du cycle */
@keyframes pulse-line { 0%, 16% { stroke-dashoffset: 466; } 100% { stroke-dashoffset: 260; } }

.card {
  position: relative; display: flex; flex-direction: column; height: 100%;
  padding: 34px 30px; border-radius: var(--r);
  background: var(--card-bg);
  border: 1px solid var(--line);
}
.card:hover { border-color: rgba(124, 92, 255, .45); box-shadow: var(--glow); }
/* Services : l'inclinaison 3D reste au survol de la carte ; quand le curseur atteint le BOUTON,
   la carte se remet à plat et grossit pour se mettre en avant (lisibilité) — classe posée par main.js */
.card--service.is-focus {
  transform: scale(1.045) !important;
  transition: transform .45s var(--spring), border-color .3s, box-shadow .3s;
  box-shadow: 0 0 0 1px rgba(124, 92, 255, .5), 0 30px 70px -24px rgba(124, 92, 255, .7);
}
.services__item { position: relative; }
.services__item:hover { z-index: 2; }
.card--featured { background: linear-gradient(180deg, rgba(50, 40, 108, .96), rgba(14, 24, 44, .975)); border-color: rgba(124, 92, 255, .4); }
.card__icon {
  width: 56px; height: 56px; border-radius: 16px; display: grid; place-items: center; margin-bottom: 22px;
  background: var(--grad); color: #fff; box-shadow: 0 10px 24px -10px rgba(124, 92, 255, .8);
  --z: 40px;
}
.card__icon svg { width: 28px; height: 28px; }
/* Numéro plein, centré dans le cadre « puce » du circuit (centre du cadre : 54 px du bord droit, 45 px du haut).
   Un éclat traverse le chiffre au début de chaque cycle (--T), puis les impulsions partent dans les pistes. */
.card__num {
  /* une boîte aux dimensions exactes du cadre (x 94-178, y 12-78 du SVG), chiffre centré dedans :
     pas de transform, la cascade des enfants de carte impose le sien */
  position: absolute; top: 12px; right: 12px; width: 84px; height: 66px; display: grid; place-items: center; padding-top: 3px;
  font-family: var(--font-h); font-weight: 800; font-size: 3.4rem; line-height: 1; letter-spacing: -.04em;
  background: var(--grad); -webkit-background-clip: text; background-clip: text; color: transparent;
  animation: num-beat var(--T, 3.4s) ease-out infinite;   /* le chiffre s'illumine sur les deux battements */
}
@keyframes num-beat { 0%, 100% { filter: brightness(1); } 3% { filter: brightness(1.7); } 7% { filter: brightness(1.05); } 11% { filter: brightness(1.55); } 16% { filter: brightness(1); } }
/* Le cadre bat comme un cœur (lub-dub) : le trait s'éclaire deux fois et deux ondes s'échappent du contour */
.card__circuit .chip { stroke: rgba(124, 92, 255, .45); stroke-width: 1.4; animation: chip-beat var(--T, 3.4s) ease-out infinite; }
.card__circuit .chip-echo { transform-box: fill-box; transform-origin: center; opacity: 0; stroke-width: 1.2; animation: chip-echo var(--T, 3.4s) ease-out infinite; }
.card__circuit .chip-echo--2 { animation-delay: calc(var(--T, 3.4s) * .08); }
@keyframes chip-beat {
  0%, 100% { stroke: rgba(124, 92, 255, .45); stroke-width: 1.4; }
  3% { stroke: #e9e4ff; stroke-width: 2.6; }
  7% { stroke: rgba(124, 92, 255, .6); stroke-width: 1.6; }
  11% { stroke: #e9e4ff; stroke-width: 2.6; }
  16% { stroke: rgba(124, 92, 255, .45); stroke-width: 1.4; }
}
@keyframes chip-echo { 0% { transform: scale(1); opacity: .9; stroke: #c4b5fd; } 16% { transform: scale(1.3); opacity: 0; } 100% { transform: scale(1.3); opacity: 0; } }
/* Les pastilles au bout des pistes s'allument quand l'impulsion les atteint */
.card__circuit circle, .card__circuit rect { animation: pad-flash var(--T, 3.4s) ease-out infinite; }
@keyframes pad-flash { 0%, 70%, 100% { fill: rgba(255, 255, 255, .2); } 80% { fill: #22d3ee; } 94% { fill: rgba(255, 255, 255, .2); } }
.card__circuit rect { fill: rgba(255, 255, 255, .22); }
.services__item:nth-child(2) .card { --T: 3.9s; }
.services__item:nth-child(3) .card { --T: 4.4s; }
.services__item:nth-child(4) .card { --T: 4.9s; }
.card--service h3 { font-size: 1.45rem; --z: 30px; }
.card--service > p { color: var(--muted); --z: 20px; }
.checks { display: grid; gap: 10px; margin: 16px 0 26px; --z: 16px; }
.checks li { position: relative; padding-left: 30px; font-size: .95rem; }
/* Coches : un cercle en dégradé qui surgit, puis la coche blanche qui se dessine, ligne après ligne.
   La coche est posée au centre du cercle (10px, 13px) puis remontée de 1,5 px : c'est le décalage
   que la rotation de 45° donne au centre visuel du trait. */
.checks li::before {
  content: ""; position: absolute; left: 0; top: 3px; width: 20px; height: 20px; border-radius: 50%;
  background: var(--grad); box-shadow: 0 6px 14px -6px rgba(124, 92, 255, .9);
  transform: scale(0); transition: transform .5s var(--spring); transition-delay: calc(.3s + var(--k, 0) * 80ms);
}
.checks li::after {
  content: ""; position: absolute; left: 10px; top: 13px; width: 9px; height: 5px;
  border-left: 2.2px solid #fff; border-bottom: 2.2px solid #fff;
  transform-origin: 50% 50%; transform: translate(-50%, -50%) translateY(-1.5px) rotate(-45deg) scale(0);
  transition: transform .35s var(--spring); transition-delay: calc(.45s + var(--k, 0) * 80ms);
}
.checks li:nth-child(2) { --k: 1; }
.checks li:nth-child(3) { --k: 2; }
.checks li:nth-child(4) { --k: 3; }
.checks li:nth-child(5) { --k: 4; }
.is-in .checks li::before { transform: scale(1); }
.is-in .checks li::after { transform: translate(-50%, -50%) translateY(-1.5px) rotate(-45deg) scale(1); }
/* Bouton plein (dégradé, texte blanc) : le fantôme cyan se perdait sur les cartes sombres */
.card__link {
  display: flex; justify-content: center; align-items: center; gap: 8px; margin-top: auto;
  padding: 15px 22px; border-radius: 999px; font-family: var(--font-h); font-weight: 700; font-size: .98rem; text-align: center;
  color: #fff; border: 0; background: var(--grad); box-shadow: 0 12px 30px -14px rgba(124, 92, 255, .9), 0 0 0 1px rgba(255, 255, 255, .08) inset; --z: 24px;
}
.card__link:hover { color: #fff; filter: brightness(1.12); box-shadow: 0 18px 40px -14px rgba(124, 92, 255, 1), 0 0 24px -6px rgba(34, 211, 238, .6); }
.card__link span { transition: transform .3s var(--ease); }
.card__link:hover span { transform: translateX(4px); }

/* Icônes animées des trois services : pages empilées (création), engrenages (maintenance), cube (hébergement) */
.card__icon--cube, .card__icon--anim { background: none; box-shadow: none; perspective: 600px; }
.ico-layers { position: relative; width: 30px; height: 30px; transform-style: preserve-3d; animation: layers-tilt 5s ease-in-out infinite; }
.ico-layers i {
  position: absolute; inset: 0; border-radius: 6px; border: 1.5px solid rgba(255, 255, 255, .75);
  background: linear-gradient(135deg, rgba(124, 92, 255, .9), rgba(34, 211, 238, .9)); box-shadow: 0 0 0 1px rgba(7, 8, 16, .6);
}
.ico-layers i:nth-child(1) { transform: translateZ(-11px); opacity: .5; }
.ico-layers i:nth-child(2) { transform: translateZ(0); opacity: .75; animation: layer-blink 3s ease-in-out -1s infinite; }
.ico-layers i:nth-child(3) { transform: translateZ(11px); animation: layer-blink 3s ease-in-out infinite; }
@keyframes layers-tilt { 0%, 100% { transform: rotateX(58deg) rotateZ(-40deg); } 50% { transform: rotateX(48deg) rotateZ(-28deg); } }
@keyframes layer-blink { 0%, 100% { filter: brightness(1); } 50% { filter: brightness(1.6); } }
/* Engrenages 3D : chaque roue est un empilement de sept disques dentés (extrusion),
   vue en perspective ; la grande et la petite tournent en sens inverse */
.ico-gear3d { position: relative; width: 42px; height: 42px; transform-style: preserve-3d; animation: gear-float 6s ease-in-out infinite; }
.gear { position: absolute; transform-style: preserve-3d; }
.gear--big { width: 30px; height: 30px; left: 0; top: 3px; animation: gear-spin 9s linear infinite; }
.gear--small { width: 19px; height: 19px; right: -1px; bottom: 0; animation: gear-spin 9s linear infinite reverse; animation-delay: -.7s; }
.gear i {
  position: absolute; inset: 0; border-radius: 50%;
  background: radial-gradient(circle, #070810 0 24%, transparent 25%), radial-gradient(circle, #3b2f8f 0 58%, transparent 59%), repeating-conic-gradient(from 0deg, #2f2670 0 20deg, transparent 20deg 45deg);
  -webkit-mask: radial-gradient(circle, #000 0 70%, transparent 71%); mask: radial-gradient(circle, #000 0 70%, transparent 71%);
}
.gear--small i { background: radial-gradient(circle, #070810 0 22%, transparent 23%), radial-gradient(circle, #0e5b66 0 56%, transparent 57%), repeating-conic-gradient(from 22deg, #0b4650 0 22deg, transparent 22deg 60deg); }
.gear i:nth-child(1) { transform: translateZ(-7px); }
.gear i:nth-child(2) { transform: translateZ(-4.7px); }
.gear i:nth-child(3) { transform: translateZ(-2.4px); }
.gear i:nth-child(4) { transform: translateZ(0); }
.gear i:nth-child(5) { transform: translateZ(2.4px); }
.gear i:nth-child(6) { transform: translateZ(4.7px); }
.gear i:nth-child(7) { transform: translateZ(7px); }
.gear--big i:nth-child(7) { background: radial-gradient(circle, #070810 0 24%, transparent 25%), radial-gradient(circle, #8b6cff 0 58%, transparent 59%), repeating-conic-gradient(from 0deg, #22d3ee 0 20deg, transparent 20deg 45deg); }
.gear--small i:nth-child(7) { background: radial-gradient(circle, #070810 0 22%, transparent 23%), radial-gradient(circle, #2fe0f5 0 56%, transparent 57%), repeating-conic-gradient(from 22deg, #a78bfa 0 22deg, transparent 22deg 60deg); }
@keyframes gear-spin { to { transform: rotateZ(360deg); } }
@keyframes gear-float { 0%, 100% { transform: rotateX(56deg) rotateZ(-18deg); } 50% { transform: rotateX(48deg) rotateZ(-10deg) translateY(-2px); } }
/* Pile de serveurs (hébergement) : trois unités en 3D, face avant + dessus, voyants qui clignotent */
.ico-gauge { width: 48px; height: 31px; overflow: visible; filter: drop-shadow(0 0 6px rgba(124, 92, 255, .55)); }
.ico-gauge__arc { fill: none; stroke: url(#ico-gauge-grad); stroke-width: 4.5; stroke-linecap: round; }
.ico-gauge__ticks { fill: none; stroke: rgba(255, 255, 255, .75); stroke-width: 1.8; stroke-linecap: round; }
.ico-gauge__needle { stroke: #fff; stroke-width: 2.6; stroke-linecap: round; transform-origin: 20px 22px; animation: gauge-swing 3.6s ease-in-out infinite; filter: drop-shadow(0 0 3px rgba(255, 255, 255, .6)); }
.ico-gauge__pin { fill: #fff; }
@keyframes gauge-swing { 0%, 100% { transform: rotate(-70deg); } 45% { transform: rotate(58deg); } 60% { transform: rotate(40deg); } }
.ico-servers { position: relative; width: 34px; height: 36px; transform-style: preserve-3d; animation: servers-sway 6s ease-in-out infinite; }
.ico-servers i {
  position: absolute; left: 0; right: 0; height: 9px; border-radius: 2px; transform-style: preserve-3d;
  background: linear-gradient(90deg, rgba(255, 255, 255, .45) 0 2px, transparent 2px 5px, rgba(255, 255, 255, .45) 5px 7px, transparent 7px), linear-gradient(135deg, #7c5cff, #22d3ee);
  border: 1px solid rgba(255, 255, 255, .6); box-shadow: 0 4px 8px -3px rgba(0, 0, 0, .7);
}
.ico-servers i:nth-child(1) { top: 2px; }
.ico-servers i:nth-child(2) { top: 14px; }
.ico-servers i:nth-child(3) { top: 26px; }
.ico-servers i::before {
  content: ""; position: absolute; left: -1px; right: -1px; top: -1px; height: 10px; border-radius: 2px;
  background: linear-gradient(90deg, rgba(255, 255, 255, .8), rgba(255, 255, 255, .5));
  transform-origin: top; transform: rotateX(-90deg);
}
.ico-servers i::after {
  content: ""; position: absolute; right: 3px; top: 2.5px; width: 3px; height: 3px; border-radius: 50%;
  background: #fff; box-shadow: 0 0 4px #fff; animation: led 1.6s steps(2, jump-none) infinite;
}
.ico-servers i:nth-child(2)::after { animation-duration: 2.3s; background: #a5f3fc; box-shadow: 0 0 4px #a5f3fc; }
.ico-servers i:nth-child(3)::after { animation-duration: 1.1s; }
@keyframes led { 50% { opacity: .15; } }
@keyframes servers-sway { 0%, 100% { transform: rotateX(-24deg) rotateY(-28deg); } 50% { transform: rotateX(-18deg) rotateY(-20deg) translateY(-2px); } }

/* ---------- Services ---------- */
.services { display: grid; grid-template-columns: 1fr; gap: 24px; perspective: 1400px; }
/* quatre services : deux par rangée dès la tablette, jamais d'orphelin */
@media (min-width: 672px) { .services { grid-template-columns: 1fr 1fr; } }
.why { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 20px; margin-top: 64px; }
.why li {
  display: grid; gap: 8px; padding: 24px; border-radius: var(--r-sm);
  border: 1px solid var(--line); background: var(--card-bg-2);
}
.why li:hover { border-color: rgba(34, 211, 238, .45); box-shadow: 0 16px 40px -20px rgba(34, 211, 238, .5); }
.why svg { width: 26px; height: 26px; color: var(--p2); }
.why strong { font-family: var(--font-h); font-size: 1.02rem; }
.why span { color: var(--muted); font-size: .92rem; }

/* ---------- Méthode ---------- */
/* isolation + z-index : le trait reste SOUS les pastilles même quand les étapes portent un transform */
.steps { position: relative; max-width: 820px; margin: 0 auto; isolation: isolate; }
.steps::before { content: ""; position: absolute; left: 31px; top: 0; bottom: 0; width: 2px; background: var(--line); z-index: 0; }
.steps::after {
  content: ""; position: absolute; left: 31px; top: 0; width: 2px; height: var(--fill, 0%); z-index: 0;
  box-shadow: 0 0 12px rgba(124, 92, 255, .8);
  /* flux de données : des éclats blancs descendent le long du trait rempli */
  background-image: linear-gradient(180deg, rgba(255, 255, 255, 0) 0, rgba(255, 255, 255, .95) 50%, rgba(255, 255, 255, 0) 100%), var(--grad);
  background-size: 100% 70px, 100% 100%; background-repeat: repeat-y, no-repeat;
  animation: flow-down 1.4s linear infinite;
}
@keyframes flow-down { to { background-position: 0 70px, 0 0; } }
/* align-items: center → la pastille est centrée sur la hauteur de sa carte */
.step { position: relative; z-index: 1; display: grid; grid-template-columns: 64px 1fr; gap: 28px; align-items: center; padding-bottom: 44px; }
.step:last-child { padding-bottom: 0; }
.step__num {
  position: relative; z-index: 1; width: 64px; height: 64px; border-radius: 50%; display: grid; place-items: center;
  font-family: var(--font-h); font-weight: 700; color: var(--muted);
  background: var(--bg-2); border: 2px solid var(--line);
  opacity: 0; transform: scale(.4) rotate(-90deg);
  transition: transform .9s var(--spring) .1s, opacity .4s ease .1s, border-color .4s, box-shadow .4s, color .4s;
}
.step.is-in .step__num { opacity: 1; transform: none; }
/* Un dégradé de couleur d'une étape à l'autre, du violet au cyan (--sc, triplet RVB), repris par
   la pastille, le contour de la carte et le halo quand l'étape s'allume */
.step:nth-child(1) { --sc: 124, 92, 255; }
.step:nth-child(2) { --sc: 99, 132, 255; }
.step:nth-child(3) { --sc: 67, 172, 250; }
.step:nth-child(4) { --sc: 34, 211, 238; }
/* fond teinté posé SUR un fond opaque : la pastille doit cacher le trait qui passe derrière */
.step.is-active .step__num { border-color: rgb(var(--sc)); color: #fff; background: linear-gradient(rgba(var(--sc), .22), rgba(var(--sc), .22)), var(--bg-2); box-shadow: 0 0 0 6px rgba(var(--sc), .15), 0 0 30px rgba(var(--sc), .5); }
.step__body { padding: 18px 26px 24px; border-radius: var(--r-sm); border: 1px solid var(--line); background: var(--card-bg-2); transform-origin: 0 50%; transition: transform .45s var(--spring), border-color .4s, box-shadow .4s; }
/* Quand la pastille s'allume, le contour de la carte s'allume avec elle */
.step.is-active .step__body { border-color: rgba(var(--sc), .6); box-shadow: 0 0 0 1px rgba(var(--sc), .25), 0 0 28px -4px rgba(var(--sc), .45), 0 18px 40px -22px rgba(var(--sc), .5); }
.step.is-active .step__body h3 { color: rgb(var(--sc)); }
/* Au survol (souris seulement), la carte grossit depuis son bord gauche et passe devant ses voisines */
@media (hover: hover) {
  .step:hover { z-index: 2; }
  .step:hover .step__body { transform: scale(1.04); border-color: rgba(var(--sc), .8); box-shadow: 0 0 0 1px rgba(var(--sc), .35), 0 0 34px -4px rgba(var(--sc), .55), 0 24px 48px -20px rgba(var(--sc), .6); }
  .step:hover .step__body h3 { color: rgb(var(--sc)); }
}
.step__body h3 { margin-bottom: 6px; }
.step__body p { color: var(--muted); margin: 0; }

/* ---------- Atouts ---------- */
.atouts { display: grid; grid-template-columns: 1fr; gap: 18px; }
@media (min-width: 1024px) { .atouts { grid-template-columns: repeat(4, minmax(0, 1fr)); } }   /* douze atouts : trois rangées pleines */
.atout {
  display: grid; gap: 10px; align-content: start; padding: 24px 20px; border-radius: var(--r-sm);
  border: 1px solid var(--line); background: var(--card-bg);
}
/* Une couleur par atout (--ac, triplet RVB) : icône, survol et onde d'arrivée l'utilisent */
.atout:nth-child(1) { --ac: 167, 139, 250; }   /* agents IA : violet clair */
.atout:nth-child(2) { --ac: 34, 211, 238; }    /* SEO : cyan */
.atout:nth-child(3) { --ac: 52, 211, 153; }    /* SSL : vert */
.atout:nth-child(4) { --ac: 248, 113, 113; }   /* anti-DDoS : rouge */
.atout:nth-child(5) { --ac: 163, 230, 53; }    /* pare-feu : vert tilleul */
.atout:nth-child(6) { --ac: 251, 191, 36; }    /* monitoring : ambre */
.atout:nth-child(7) { --ac: 244, 114, 182; }   /* plugins : rose */
.atout:nth-child(8) { --ac: 96, 165, 250; }    /* standards : bleu */
.atout:nth-child(9) { --ac: 251, 146, 60; }    /* vitesse : orange */
.atout:nth-child(10) { --ac: 45, 212, 191; }   /* RGPD : turquoise */
.atout:nth-child(11) { --ac: 129, 140, 248; }  /* analytics : indigo */
.atout:nth-child(12) { --ac: 232, 121, 249; }  /* modulaire : fuchsia */
.atout:hover { border-color: rgba(var(--ac), .5); box-shadow: 0 0 0 1px rgba(var(--ac), .3), 0 24px 60px -20px rgba(var(--ac), .45); }
.atout__icon {
  width: 52px; height: 52px; border-radius: 14px; display: grid; place-items: center;
  color: rgb(var(--ac)); background: rgba(var(--ac), .12); border: 1px solid rgba(var(--ac), .32);
}
.atout h3 { font-size: 1.02rem; margin: 4px 0 0; }
.atout p { margin: 0; color: var(--muted); font-size: .88rem; line-height: 1.55; }
/* Icônes vectorielles animées */
.ico { width: 26px; height: 26px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; overflow: visible; }
.ico * { transform-box: fill-box; transform-origin: center; }
.ico-spark path { fill: currentColor; stroke: none; animation: spark 2.4s ease-in-out infinite; }
.ico-spark .s2 { animation-delay: -.8s; }
.ico-spark .s3 { animation-delay: -1.6s; }
@keyframes spark { 0%, 100% { transform: scale(.55); opacity: .5; } 50% { transform: scale(1.1); opacity: 1; } }
.ico-seo .b { transform-origin: center bottom; animation: bars 2.2s ease-in-out infinite; }
.ico-seo .b2 { animation-delay: -.5s; }
.ico-seo .b3 { animation-delay: -1s; }
@keyframes bars { 0%, 100% { transform: scaleY(.35); } 50% { transform: scaleY(1); } }
.ico-lock .shackle { animation: shackle 2.6s ease-in-out infinite; }
.ico-ddos .hit { animation: ddos-hit 1.8s ease-in infinite; }
.ico-ddos .h2 { animation-delay: .3s; } .ico-ddos .h3 { animation-delay: .6s; }
@keyframes ddos-hit { 0% { transform: translateX(-2px); opacity: 0; } 20% { opacity: 1; } 70% { transform: translateX(3px); opacity: 1; } 85%, 100% { transform: translateX(3px); opacity: 0; } }
.ico-wall .pkt { animation: wall-bounce 1.6s ease-in-out infinite; }
@keyframes wall-bounce { 0%, 100% { transform: translateX(2px); opacity: .5; } 45% { transform: translateX(-2.5px); opacity: 1; } 55% { transform: translateX(-2.5px) scale(1.3); opacity: 1; } }
@keyframes shackle { 0%, 60%, 100% { transform: translateY(0); } 30% { transform: translateY(-3px); } }
.ico-pulse .beat { stroke-dasharray: 34; stroke-dashoffset: 34; animation: beat 2.4s linear infinite; }
.ico-pulse .blip { animation: blip 2.4s ease-out infinite; }
@keyframes beat { 0% { stroke-dashoffset: 34; opacity: 1; } 70% { stroke-dashoffset: 0; opacity: 1; } 100% { stroke-dashoffset: 0; opacity: 0; } }
@keyframes blip { 0%, 100% { transform: scale(.7); opacity: .4; } 10% { transform: scale(1.3); opacity: 1; } 40% { transform: scale(.7); opacity: .4; } }
.ico-plug .plug { animation: plug 2.4s ease-in-out infinite; }
@keyframes plug { 0%, 100% { transform: translateY(-2.5px); } 50% { transform: translateY(0); } }
.ico-code .slash { animation: slash 2.2s ease-in-out infinite; }
.ico-code .tick { stroke-dasharray: 8; stroke-dashoffset: 8; animation: draw 2.2s ease-in-out infinite; }
@keyframes slash { 0%, 100% { transform: translateX(-2px); opacity: .5; } 50% { transform: translateX(2px); opacity: 1; } }
.ico-gauge .needle { transform-box: view-box; transform-origin: 12px 16px; animation: needle 3s ease-in-out infinite; }
@keyframes needle { 0%, 100% { transform: rotate(-70deg); } 50% { transform: rotate(60deg); } }
.ico-shield .check { stroke-dasharray: 9; stroke-dashoffset: 9; animation: draw 2.8s ease-in-out infinite; }
@keyframes draw { 0%, 15% { stroke-dashoffset: 9; } 45%, 75% { stroke-dashoffset: 0; } 100% { stroke-dashoffset: 9; } }
.ico-modules .mod { animation: module 3s ease-in-out infinite; }
@keyframes module { 0% { transform: translate(6px, 6px); opacity: 0; } 35%, 80% { transform: translate(0, 0); opacity: 1; } 100% { transform: translate(6px, 6px); opacity: 0; } }
.ico-stats .bar { transform-origin: center bottom; animation: grow 2.6s ease-in-out infinite; }
.ico-stats .b2 { animation-delay: .2s; }
.ico-stats .b3 { animation-delay: .4s; }
.ico-stats .b4 { animation-delay: .6s; }
@keyframes grow { 0%, 100% { transform: scaleY(.3); opacity: .6; } 40%, 70% { transform: scaleY(1); opacity: 1; } }

/* ---------- Références ---------- */
.works { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 420px), 1fr)); gap: 24px; perspective: 1400px; }
.work { position: relative; display: flex; flex-direction: column; height: 100%; border-radius: var(--r); border: 1px solid var(--line); background: var(--card-bg-2); }
.work:hover { border-color: rgba(var(--wc, 34, 211, 238), .45); box-shadow: 0 24px 60px -24px rgba(var(--wc, 34, 211, 238), .5); }
/* L'écran de chaque référence : un halo à la couleur du site (--wc, triplet RVB) et une maquette
   d'appareil — navigateur ou téléphone — qui contient la vraie capture du site */
.work__screen { position: relative; height: 268px; overflow: hidden; border-radius: var(--r) var(--r) 0 0; padding: 30px 30px 0; display: flex; align-items: flex-end; --z: 30px;
  background: radial-gradient(80% 80% at 50% 100%, rgba(var(--wc, 124, 92, 255), .38), transparent 70%); }
.mock {
  position: relative; width: 100%; height: 100%; display: flex; flex-direction: column; overflow: hidden;
  border-radius: 12px 12px 0 0; background: #0f1225; border: 1px solid rgba(255, 255, 255, .14); border-bottom: 0;
  box-shadow: 0 30px 60px -20px rgba(0, 0, 0, .8); transition: transform .6s var(--ease);
}
.work:hover .mock { transform: translateY(-6px); }
/* Navigateur : barre de fenêtre (trois pastilles, adresse avec cadenas) puis la capture, qui défile lentement au survol */
.mock__chrome { display: flex; align-items: center; gap: 12px; padding: 9px 12px; background: #151936; border-bottom: 1px solid rgba(255, 255, 255, .08); flex: none; }
.mock__bar { display: flex; gap: 5px; }
.mock__bar i { width: 9px; height: 9px; border-radius: 50%; background: rgba(255, 255, 255, .22); }
.mock__bar i:nth-child(1) { background: #f26b62; } .mock__bar i:nth-child(2) { background: #f0b73d; } .mock__bar i:nth-child(3) { background: #45c25a; }
.mock__url { flex: 1; display: flex; align-items: center; gap: 6px; height: 20px; padding: 0 10px; border-radius: 10px; background: rgba(255, 255, 255, .07);
  font-size: .68rem; font-weight: 500; letter-spacing: .01em; color: var(--muted); white-space: nowrap; overflow: hidden; }
.mock__url svg { width: 10px; height: 10px; flex: none; fill: rgba(255, 255, 255, .55); }
.mock__shot { display: block; width: 100%; flex: 1; min-height: 0; object-fit: cover; object-position: 50% 0; transition: object-position 3.2s ease-in-out; }   /* ancrée au CENTRE haut : sur écran étroit on voit le milieu de la page, pas son bord gauche */
.work:hover .mock--browser .mock__shot { object-position: 50% 100%; }
/* Téléphone : cadre arrondi, île dynamique et barre d'état dessinées, l'écran de l'app en dessous */
.mock--phone { width: 208px; margin: 0 auto; padding: 8px 8px 0; border-radius: 36px 36px 0 0; background: #07091a; border: 1px solid rgba(255, 255, 255, .18);
  box-shadow: inset 0 0 0 2px #1a1f3d, 0 30px 60px -20px rgba(0, 0, 0, .85); }
.mock--phone .mock__shot { flex: none; height: auto; margin-top: 30px; border-radius: 0; }
.mock__island { position: absolute; top: 18px; left: 50%; width: 62px; height: 18px; margin-left: -31px; border-radius: 10px; background: #05060d; z-index: 2; }
.mock__status { position: absolute; top: 8px; left: 8px; right: 8px; height: 31px; z-index: 1; border-radius: 28px 28px 0 0; background: #0f1120; display: flex; align-items: center; justify-content: space-between; padding: 6px 22px 0 26px; }
.mock__status b { font-family: var(--font-h); font-size: .66rem; font-weight: 600; color: #fff; }
.mock__status i { width: 20px; height: 9px; border-radius: 3px; border: 1px solid rgba(255, 255, 255, .55); box-shadow: inset 0 0 0 1.5px #0f1120, inset 14px 0 0 #fff; }
.mock picture { display: contents; }   /* le <picture> ne compte pas dans la colonne : l'image reste l'élément flexible */
.mock--browser .mock__island, .mock--browser .mock__status { display: none; }
/* Sur téléphone, le visiteur voit les sites comme il les verrait lui-même : la maquette de navigateur
   devient un téléphone (même cadre que l'application) et la capture est la version MOBILE du site */
@media (max-width: 671px) {
  .work__screen { height: 300px; }
  .mock--browser { width: 208px; margin: 0 auto; padding: 8px 8px 0; border-radius: 36px 36px 0 0; background: #07091a; border: 1px solid rgba(255, 255, 255, .18); box-shadow: inset 0 0 0 2px #1a1f3d, 0 30px 60px -20px rgba(0, 0, 0, .85); }
  .mock--browser .mock__chrome { display: none; }
  .mock--browser .mock__island { display: block; }
  .mock--browser .mock__status { display: flex; }
  .mock--browser .mock__shot { flex: none; height: auto; margin-top: 30px; border-radius: 0; object-position: 50% 0; }
}
.work__meta { padding: 22px 26px 26px; --z: 20px; }
.work__cat { display: block; margin-bottom: 8px; font-size: .76rem; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--p2); }
.work__meta h3 { font-size: 1.2rem; }
.work__meta p { margin: 0; font-size: .95rem; color: var(--muted); }
.work__link { display: inline-flex; align-items: center; gap: 5px; margin-top: 14px; font-size: .84rem; font-weight: 600; color: var(--p2); }
.work__link span { font-size: .9em; transition: transform .3s var(--spring); }
.work__link:hover span { transform: translate(2px, -2px); }

.marquee {
  margin-top: 64px; padding: 18px 0; overflow: hidden;
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
  -webkit-mask: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent); mask: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
}
.marquee__track { display: flex; width: max-content; animation: marquee 30s linear infinite; }
.marquee span { padding: 0 26px; font-family: var(--font-h); font-weight: 600; color: var(--muted); white-space: nowrap; opacity: .85; }
.marquee:hover .marquee__track { animation-play-state: paused; }
@keyframes marquee { to { transform: translateX(-50%); } }

/* ---------- FAQ ---------- */
.faq { display: grid; gap: 12px; }
.faq__item { border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--card-bg-2); overflow: hidden; transition: border-color .3s; }
.faq__item[open] { border-color: rgba(124, 92, 255, .4); }
.faq__item summary { position: relative; list-style: none; cursor: pointer; padding: 20px 56px 20px 24px; font-family: var(--font-h); font-weight: 600; font-size: 1.02rem; }
.faq__item summary::-webkit-details-marker { display: none; }
.faq__item summary::after {
  content: ""; position: absolute; right: 24px; top: 50%; width: 11px; height: 11px;
  border-right: 2px solid var(--p2); border-bottom: 2px solid var(--p2);
  transform: translateY(-70%) rotate(45deg); transition: transform .35s var(--ease);
}
.faq__item[open] summary::after { transform: translateY(-30%) rotate(-135deg); }
.faq__body { padding: 0 24px 22px; color: var(--muted); animation: fadeUp .45s var(--ease); }
.faq__body p { margin: 0; }
@keyframes fadeUp { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }

/* ---------- Contact ---------- */
.contact { display: grid; grid-template-columns: 1fr 1.2fr; gap: 56px; align-items: start; }
.contact__info .section__lead { margin-bottom: 28px; }
.contact__list { display: grid; gap: 14px; }
.contact__list li { display: flex; align-items: center; gap: 14px; color: var(--muted); }
.contact__list svg { width: 22px; height: 22px; flex: none; color: var(--p2); }
.contact__list a:hover { color: var(--txt); }
.form {
  display: grid; gap: 18px; padding: 34px; border-radius: var(--r);
  border: 1px solid var(--line); background: var(--card-bg);
}
.form__row { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
.field { display: grid; gap: 8px; }
.field > span { font-size: .85rem; font-weight: 500; color: var(--muted); }
.field input, .field select, .field textarea {
  width: 100%; padding: 13px 14px; border-radius: 12px;
  border: 1px solid var(--line); background: rgba(7, 8, 16, .6); color: var(--txt); font: inherit;
  transition: border-color .25s, box-shadow .25s;
}
.field textarea { resize: vertical; min-height: 130px; }
.field input:focus, .field select:focus, .field textarea:focus { outline: 0; border-color: var(--p); box-shadow: 0 0 0 4px rgba(124, 92, 255, .18); }
.field select {
  color-scheme: dark;   /* la liste déroulante native suit le thème sombre (fond, texte, surbrillance) */
  appearance: none; -webkit-appearance: none; padding-right: 40px;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='m6 9 6 6 6-6' fill='none' stroke='%239aa1b9' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-repeat: no-repeat; background-position: right 14px center; background-size: 18px;
}
.field select option { background: #0c0e1a; color: var(--txt); }
/* Liste déroulante dessinée par nous (Chrome et Edge récents, « select personnalisable ») : le panneau,
   les lignes, le survol et la coche reprennent les couleurs du site ; ailleurs, la liste native en sombre */
@supports (appearance: base-select) {
  .field select, .field select::picker(select) { appearance: base-select; }
  .field select::picker-icon { display: none; }   /* notre chevron reste en image de fond */
  .field select::picker(select) {
    margin-top: 6px; padding: 6px; border: 1px solid var(--line); border-radius: 12px;
    background: rgba(12, 14, 26, .98); box-shadow: 0 24px 60px -24px rgba(0, 0, 0, .9), 0 0 0 1px rgba(124, 92, 255, .12);
    -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px);
  }
  .field select option { padding: 10px 12px; border-radius: 8px; background: transparent; color: var(--txt); cursor: pointer; transition: background .15s, color .15s; }
  .field select option:hover, .field select option:focus-visible { background: rgba(124, 92, 255, .18); outline: 0; }
  .field select option:checked { background: rgba(124, 92, 255, .28); color: #fff; }
  .field select option:disabled { display: none; }   /* « Choisir… » reste dans le champ, pas dans la liste */
  .field select option::checkmark { color: var(--p2); }
}
.form.was-validated :invalid { border-color: #f87171; }
.form__error { margin: 0; color: #f87171; font-size: .9rem; }
.form__note { margin: 0; font-size: .82rem; color: var(--muted); }
.form__ok { margin: 0; color: #34d399; font-size: .9rem; }
/* Pot de miel : hors écran, jamais display:none (les robots sautent ce qui est masqué ainsi) */
.hp { position: absolute; left: -9999px; top: 0; width: 1px; height: 1px; overflow: hidden; }
.btn.is-busy { opacity: .7; pointer-events: none; }

/* ---------- Pied de page ---------- */
.footer { padding: 64px 0 28px; border-top: 1px solid var(--line); background: rgba(0, 0, 0, .25); }
.footer__grid { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 24px 32px; }
.footer ul { display: flex; flex-wrap: wrap; gap: 8px 24px; color: var(--muted); font-size: .95rem; }
.footer a:hover { color: var(--txt); }
.footer__brand p { max-width: 320px; margin: 16px 0 0; color: var(--muted); }
.footer__bottom { display: flex; justify-content: space-between; flex-wrap: wrap; gap: 8px; margin-top: 36px; padding-top: 22px; border-top: 1px solid var(--line); font-size: .85rem; color: var(--muted); }
.footer__bottom p { margin: 0; }

/* ---------- Retour en haut, toast ---------- */
.totop {
  position: fixed; right: 22px; bottom: 22px; z-index: 90; width: 48px; height: 48px; border-radius: 50%;
  display: grid; place-items: center; background: var(--grad); color: #fff;
  box-shadow: 0 10px 30px -10px rgba(124, 92, 255, .8);
  opacity: 0; visibility: hidden; transform: translateY(12px);
  transition: opacity .3s, transform .3s var(--ease), visibility 0s .3s;
}
.totop.is-visible { opacity: 1; visibility: visible; transform: none; transition: opacity .3s, transform .3s var(--ease); }
.totop svg { width: 22px; height: 22px; }
.toast {
  position: fixed; left: 50%; bottom: 28px; z-index: 130; max-width: min(92vw, 520px);
  padding: 14px 20px; border-radius: 14px; font-size: .95rem;
  background: #12152b; border: 1px solid var(--line); box-shadow: 0 20px 50px -20px #000;
  opacity: 0; visibility: hidden; transform: translate(-50%, 20px);
  transition: opacity .3s, transform .3s var(--ease), visibility 0s .3s;
}
.toast.is-visible { opacity: 1; visibility: visible; transform: translate(-50%, 0); transition: opacity .3s, transform .3s var(--ease); }

/* ---------- Apparitions / disparitions au défilement ----------
   data-reveal = up (défaut) | left | right | zoom-in | zoom-out | tilt | flip | blur
   .is-in      : visible ; .is-settled : entrée terminée, le transform suit le défilement sans délai
   .is-above   : sorti par le haut (disparition) ; sans classe : sorti par le bas (état d'entrée)
   --py / --sz : parallaxe et zoom pilotés par data-scroll (main.js) */
[data-reveal] {
  opacity: 0; transform: translate3d(0, 48px, 0);
  transition: opacity .5s ease, transform .9s var(--ease), filter .5s ease, border-color .3s, box-shadow .3s;
  transition-delay: calc(var(--d, 0) * 90ms);
}
[data-reveal="left"] { transform: translate3d(-72px, 0, 0); }
[data-reveal="right"] { transform: translate3d(72px, 0, 0); }
[data-reveal="zoom-in"] { transform: scale(.6) translate3d(0, 40px, 0); transition-timing-function: ease, var(--spring), ease; }
[data-reveal="zoom-out"] { transform: scale(1.22); filter: blur(10px); }
[data-reveal="tilt"] { transform: perspective(1200px) rotateX(18deg) translate3d(0, 50px, 0); transform-origin: 50% 0; }
[data-reveal="flip"] { transform: perspective(1200px) rotateY(-38deg) scale(.9); transform-origin: 50% 50%; }
[data-reveal="blur"] { transform: translate3d(0, 24px, 0) scale(.96); filter: blur(14px); }
/* Fondu pur, sans déplacement : pour les blocs dont le conteneur porte déjà le mouvement (services) */
[data-reveal="fade"] { transform: none; transition-duration: .8s; }
[data-reveal="fade"].is-above { transform: none; }
/* Cartes : vol en 3D depuis le bas, la gauche ou la droite (data-from), atterrissage avec rebond ;
   le balayage lumineux, l'onde de bord et la cascade du contenu sont définis plus bas */
[data-reveal="card"] {
  transform: perspective(1200px) translate3d(0, 120px, -180px) rotateX(-26deg) scale(.86);
  transform-origin: 50% 100%;
  transition-duration: .45s, .95s, .45s, .3s, .3s; transition-timing-function: ease, var(--spring), ease, ease, ease;
}
[data-reveal="card"][data-from="left"] { transform: perspective(1200px) translate3d(-160px, 30px, -180px) rotateY(32deg) scale(.86); transform-origin: 0 50%; }
[data-reveal="card"][data-from="right"] { transform: perspective(1200px) translate3d(160px, 30px, -180px) rotateY(-32deg) scale(.86); transform-origin: 100% 50%; }
/* Rideau : le bloc se dévoile de gauche à droite (arguments, FAQ) et se referme vers la droite en sortant */
[data-reveal="wipe"] {
  opacity: 1; clip-path: inset(0 100% 0 0 round var(--r-sm)); transform: translate3d(-28px, 0, 0);
  transition: clip-path 1s var(--ease), transform 1s var(--ease), opacity .4s ease, filter .4s ease, border-color .3s, box-shadow .3s;
}
/* Tuiles : le bloc se rabat depuis le haut, avec rebond (atouts) */
[data-reveal="flip-x"] {
  transform: perspective(1000px) rotateX(-82deg) translate3d(0, -14px, 0); transform-origin: 50% 0;
  transition-duration: .4s, .95s, .4s, .3s, .3s; transition-timing-function: ease, var(--spring), ease, ease, ease;
}
/* Écran : le bloc sort de l'écran, trop grand et surexposé, puis se pose (références) */
[data-reveal="screen"] { transform: scale(1.4); filter: blur(12px) brightness(2); transition-duration: .5s, .95s, .7s, .3s, .3s; }
/* L'état visible est FIXE (aucune variable) : une cible qui bouge pendant l'entrée ferait
   repartir la transition à chaque image. Le zoom au défilement (--sz) est appliqué sur
   la carte intérieure, qui hérite de la variable posée sur l'enveloppe. */
[data-reveal].is-in { opacity: 1; filter: none; transform: none; }
[data-reveal="wipe"].is-in { clip-path: inset(0 0 0 0 round var(--r-sm)); }
/* Zoom d'une section à l'autre (data-zoom="in|out" sur le conteneur, piloté par main.js) */
[data-zoom] { transform-origin: 50% 50%; will-change: transform, opacity; }
[data-reveal].is-settled { transition-duration: .5s, 0s, .5s, .3s, .3s; transition-delay: 0s; }
[data-reveal].is-above { opacity: 0; transform: translate3d(0, -64px, 0) scale(.94); transition-duration: .5s; transition-timing-function: ease; }
[data-reveal="card"].is-above { transform: perspective(1200px) translate3d(0, -110px, -220px) rotateX(24deg) scale(.88); transform-origin: 50% 0; }
[data-reveal="wipe"].is-above { opacity: 1; filter: none; clip-path: inset(0 0 0 100% round var(--r-sm)); transform: translate3d(28px, -16px, 0); }
[data-reveal="flip-x"].is-above { transform: perspective(1000px) rotateX(72deg) translate3d(0, -30px, 0); transform-origin: 50% 100%; }
[data-reveal="screen"].is-above { transform: scale(.7); filter: blur(8px) brightness(.4); }

/* Contenu des cartes : les enfants arrivent en cascade après la carte (--n = rang, --z = relief 3D) */
:is(.card, .work, .atout, .step__body, .why > li) > * {
  opacity: var(--co, 0);
  transform: translate3d(0, var(--cy, 18px), var(--z, 0px));
  transition: opacity .4s ease, transform .6s var(--spring), background .3s, color .3s, border-color .3s, box-shadow .3s;
  transition-delay: calc(.06s + var(--n, 0) * 55ms), calc(.06s + var(--n, 0) * 55ms), 0s, 0s, 0s, 0s;
}
:is(.card, .work, .atout, .step__body, .why > li) > :nth-child(2) { --n: 1; }
:is(.card, .work, .atout, .step__body, .why > li) > :nth-child(3) { --n: 2; }
:is(.card, .work, .atout, .step__body, .why > li) > :nth-child(4) { --n: 3; }
:is(.card, .work, .atout, .step__body, .why > li) > :nth-child(5) { --n: 4; }
:is(.card, .work, .atout, .step__body, .why > li) > :nth-child(6) { --n: 5; }
:is(.card, .work, .atout, .step__body, .why > li) > :nth-child(7) { --n: 6; }
:is(.card, .work, .atout, .step__body, .why > li) > :nth-child(8) { --n: 7; }
.card > .glare, .card > .card__circuit, .work > .glare { --co: 1; --cy: 0px; transition-delay: 0s; }
.is-in :is(.card, .work, .step__body) > *, :is(.why > li, .atout).is-in > * { --co: 1; --cy: 0px; }

/* Balayage lumineux qui traverse la carte, et onde qui s'échappe de son bord, à chaque arrivée */
.card, .work, .atout, .step__body, .why > li, .faq__item { position: relative; }
:is(.card, .work, .atout, .step__body, .why > li, .faq__item)::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none; opacity: 0;
  background: linear-gradient(180deg, transparent 36%, rgba(255, 255, 255, .28) 50%, rgba(34, 211, 238, .16) 56%, transparent 68%);
  background-size: 100% 300%; background-position: 0 100%;
}
/* Un accent différent par section : balayage sur les services, onde sur les atouts,
   allumage d'écran sur les références ; les étapes ont leur pastille, les rideaux se suffisent */
.is-in .card::after { animation: card-scan 1.1s .3s ease-out; }
.atout.is-in { animation: atout-ring 1s .25s ease-out; }
@keyframes atout-ring {
  0% { box-shadow: 0 0 0 0 rgba(var(--ac, 124, 92, 255), .7); }
  100% { box-shadow: 0 0 0 9px rgba(var(--ac, 124, 92, 255), 0); }
}
.is-in .work { animation: crt-on 1s .15s ease-out; }
@keyframes crt-on { 0% { filter: brightness(2.4) contrast(1.5) saturate(1.6); } 22% { filter: brightness(.6); } 42% { filter: brightness(1.7); } 100% { filter: none; } }
@keyframes card-scan { 0% { opacity: 0; background-position: 0 100%; } 20% { opacity: 1; } 100% { opacity: 0; background-position: 0 0%; } }
@keyframes card-ring {
  0% { box-shadow: 0 0 0 0 rgba(124, 92, 255, .65), 0 0 0 0 rgba(34, 211, 238, .45); }
  100% { box-shadow: 0 0 0 28px rgba(124, 92, 255, 0), 0 0 0 48px rgba(34, 211, 238, 0); }
}

/* ---------- Écrans ---------- */
/* Sous 1024 px la barre de navigation ne tient plus sur une ligne (les six entrées + le bouton) :
   menu replié derrière le bouton burger, comme sur téléphone */
@media (max-width: 1023px) {
  .nav__pill { display: none; }
  .header__inner { gap: 12px; }
  .lang { margin-left: auto; }
  .burger {
    display: inline-flex; flex-direction: column; justify-content: center; gap: 5px;
    width: 44px; height: 44px; border-radius: 12px; border: 1px solid var(--line); background: var(--surface);
  }
  .burger span { display: block; width: 20px; height: 2px; margin: 0 auto; background: var(--txt); transition: transform .3s, opacity .3s; }
  body.nav-open .burger span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
  body.nav-open .burger span:nth-child(2) { opacity: 0; }
  body.nav-open .burger span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }
  /* Menu déroulant à la Divi : un panneau qui descend sous la barre (pas un voile plein écran), liseré
     dégradé en haut, entrées empilées et alignées à gauche, séparées par un trait, bouton en bas */
  .nav {
    position: fixed; top: var(--hdr); left: 0; right: 0; bottom: auto; max-height: calc(100vh - var(--hdr)); overflow-y: auto;
    flex-direction: column; align-items: stretch; gap: 0; padding: 4px 0 20px;
    background: rgba(7, 8, 16, .78); -webkit-backdrop-filter: blur(18px) saturate(160%); backdrop-filter: blur(18px) saturate(160%);
    border-top: 3px solid transparent; border-image: var(--grad) 1;
    box-shadow: 0 30px 60px -20px rgba(0, 0, 0, .85);
    opacity: 0; visibility: hidden; transform: translateY(-10px);
    transition: opacity .3s, transform .3s, visibility 0s .3s;
  }
  body.nav-open .nav { opacity: 1; visibility: visible; transform: none; transition: opacity .3s, transform .3s; }
  body.nav-open .header { background: rgba(7, 8, 16, .78); border-color: transparent; }
  .nav__list { flex-direction: column; align-items: stretch; gap: 0; padding: 0 clamp(20px, 5vw, 32px); }
  .nav__link { display: block; padding: 15px 4px; font-family: var(--font-h); font-size: .95rem; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--txt); border-bottom: 1px solid var(--line); }
  .nav__link::after { display: none; }
  .nav__link.is-active, .nav__link:hover { color: var(--p2); }
  .nav__cta { margin: 18px clamp(20px, 5vw, 32px) 0; padding: 14px 26px; font-size: 1rem; justify-content: center; }
}
@media (max-width: 760px) {
  .hero { padding-top: calc(var(--hdr) + 28px); padding-bottom: 80px; }
  .hero__title br { display: none; }
  .hero__veil { background: linear-gradient(to bottom, rgba(7, 8, 16, .4), rgba(7, 8, 16, .6) 45%, rgba(7, 8, 16, .95) 100%); }
  .stats { grid-template-columns: 1fr; gap: 14px; margin-top: 40px; }
  .stats li { display: grid; grid-template-columns: 110px 1fr; align-items: center; gap: 4px 12px; }
  .stats li i { grid-column: 1 / -1; }
  .scroll-hint { display: none; }
  .section__head { margin-bottom: 40px; }
  .card { padding: 28px 24px; }
  .contact { grid-template-columns: 1fr; gap: 36px; }
  .form { padding: 24px; }
  .form__row { grid-template-columns: 1fr; }
  .step { grid-template-columns: 48px 1fr; gap: 16px; padding-bottom: 32px; }
  .step__num { width: 48px; height: 48px; font-size: .9rem; }
  .steps::before, .steps::after { left: 23px; }
  .footer__grid { flex-direction: column; align-items: flex-start; gap: 24px; }
  .footer ul { gap: 8px 22px; }
  .footer__bottom { justify-content: center; text-align: center; }
}

/* ---------- Tablette et petit portable ---------- */
/* Entre 672 et 1023 px, les grilles passent à deux colonnes sans orphelin : la carte seule
   d'une rangée se centre à la largeur des autres, et le contact s'empile */
@media (min-width: 672px) and (max-width: 1023px) {
  .why { grid-template-columns: 1fr 1fr; }
  .atouts { grid-template-columns: 1fr 1fr; }
  .works { grid-template-columns: 1fr 1fr; }
  .contact { grid-template-columns: 1fr; gap: 40px; }
}
/* Sous 1024 px, la dernière ligne du pied de page laisse la place au bouton « remonter » (fixe, en bas à droite) */
@media (max-width: 1023px) { .footer__bottom { padding-bottom: 64px; } }

/* ---------- Sections différées ----------
   Sous le héros, une section n'est mise en page qu'à l'approche de l'écran (content-visibility: auto) : la
   première mise en page de la page ENTIÈRE (1 241 éléments, dont 514 SVG) bloquait un téléphone plus d'une
   seconde d'un seul tenant (PageSpeed, 29/09). Tant qu'elle n'a jamais été affichée, une section prend la
   hauteur estimée ci-dessous (mesurée le 29/09) ; ensuite le navigateur retient sa hauteur réelle (auto).
   main.js ne lit la position des blocs que dans les sections proches (4 bis), et met tout en page le temps
   d'un saut vers une ancre (html.cv-tout). Vérifié : aucune section n'a d'élément fixe, collant ou débordant. */
.section { content-visibility: auto; contain-intrinsic-height: auto 1000px; }
/* hauteurs de CONTENU (sans les marges intérieures de la section, que le navigateur ajoute) */
#services { contain-intrinsic-height: auto 1800px; }
#methode { contain-intrinsic-height: auto 910px; }
#atouts { contain-intrinsic-height: auto 1080px; }
#references { contain-intrinsic-height: auto 2120px; }
#faq { contain-intrinsic-height: auto 660px; }
#contact { contain-intrinsic-height: auto 540px; }
@media (max-width: 1023px) {
  #services { contain-intrinsic-height: auto 2350px; }
  #atouts { contain-intrinsic-height: auto 1650px; }
  #references { contain-intrinsic-height: auto 2340px; }
  #faq { contain-intrinsic-height: auto 670px; }
  #contact { contain-intrinsic-height: auto 760px; }
}
@media (max-width: 671px) {
  #services { contain-intrinsic-height: auto 4150px; }
  #methode { contain-intrinsic-height: auto 1240px; }
  #atouts { contain-intrinsic-height: auto 3100px; }
  #references { contain-intrinsic-height: auto 4500px; }
  #faq { contain-intrinsic-height: auto 950px; }
  #contact { contain-intrinsic-height: auto 1010px; }
}
html.cv-tout .section { content-visibility: visible; }

/* ---------- Hors de l'écran, les animations en boucle s'arrêtent ----------
   main.js (10 ter) pose .is-offscreen sur les cartes, atouts, sections à balayage, bandeau, pied de page
   et héros quand ils quittent l'écran : leurs animations sont suspendues (pas retirées, elles reprennent
   au même instant de leur cycle). Sans ça, ~75 animations infinies recalculaient la page à chaque image. */
.is-offscreen, .is-offscreen::before, .is-offscreen::after,
.is-offscreen *, .is-offscreen *::before, .is-offscreen *::after { animation-play-state: paused !important; }

/* ---------- Mouvement réduit ---------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; scroll-behavior: auto !important; }
  [data-reveal] { opacity: 1; transform: none; filter: none; }
  :root .hero__title .w { animation: none; transform: none; filter: none; }
  :is(.card, .work, .atout, .step__body, .why > li) > *, .step__num { opacity: 1; transform: none; }
  .ico *, .ico-layers, .ico-layers i, .ico-gear3d, .gear { animation: none !important; }
  [data-zoom] { transform: none !important; opacity: 1 !important; }
  [data-reveal="wipe"] { clip-path: none; }
  .voyage { height: 0; overflow: hidden; }
  .voyage-canvas { display: none; }
  .hero__scene { position: absolute; height: 100%; }
  :is(.card, .work, .atout, .step__body, .why > li, .faq__item), :is(.card, .work, .atout, .step__body, .why > li, .faq__item)::after { animation: none !important; }
  [data-tilt] { transform: none !important; }
  .marquee__track, .card__circuit .pulse, .section--alt::after, .steps::after, .ico-servers, .ico-servers i::after { animation: none; }
  .fx-canvas { display: none; }
}

/* ==========================================================================
   Pistes UI/UX validées le 27/09 : barre compacte et pastille, repères de section, appel flottant,
   héros (mots, confiance, compteurs, invite), prix des services, filtres et faits des références,
   formulaire à libellés flottants et état de succès, bascule « moins d'animations ».
   ========================================================================== */
/* ---- Barre : compacte après défilement, se retire quand on descend dans une longue section ---- */
.header { transition: background .4s, border-color .4s, height var(--t-base) var(--ease), transform var(--t-base) var(--ease); }
.header.is-scrolled { --hdr: 56px; }
.header.is-hidden { transform: translateY(-100%); }
body.nav-open .header.is-hidden { transform: none; }
/* pastille qui glisse sous le lien actif (grand écran) */
.nav__list { position: relative; }
.nav__pill { position: absolute; left: 0; top: 0; height: 100%; width: 0; border-radius: 999px; background: rgba(124, 92, 255, .22); box-shadow: inset 0 0 0 1px rgba(124, 92, 255, .5); opacity: 0; pointer-events: none; }
.nav__list.is-ready .nav__pill { opacity: 1; transition: transform .28s var(--spring), width .28s var(--spring); }
.nav__link { z-index: 1; }
@media (min-width: 1024px) {
  .nav__link::after { display: none; }
  .nav__link.is-active { color: #fff; }
  .progress { display: none; }   /* les repères de section prennent le relais de la barre de progression */
}
/* ---- Repères de section, bord droit ---- */
.dots { position: fixed; right: 18px; top: 50%; z-index: 90; display: flex; flex-direction: column; align-items: flex-end; gap: 14px; transform: translateY(-50%); opacity: 0; visibility: hidden; transition: opacity .3s, visibility 0s .3s; }
.dots.is-visible { opacity: 1; visibility: visible; transition: opacity .3s; }
.dots__link { display: flex; align-items: center; gap: 10px; color: var(--muted); font-size: .72rem; text-decoration: none; }
.dots__link span { opacity: 0; transform: translateX(6px); padding: 3px 8px; border-radius: 999px; background: var(--card-bg-2); border: 1px solid rgba(255, 255, 255, .12); transition: opacity var(--t-fast), transform var(--t-fast); }
.dots__link::after { content: ""; width: 6px; height: 6px; border-radius: 50%; background: rgba(255, 255, 255, .25); transition: width var(--t-fast), height var(--t-fast), background var(--t-fast), box-shadow var(--t-fast); }
.dots__link:hover span { opacity: 1; transform: none; color: var(--txt); font-weight: 600; }
@media (min-width: 1440px) { .dots__link.is-active span { opacity: 1; transform: none; color: var(--txt); font-weight: 600; } }   /* le nom de la section active : seulement quand la marge le loge sans toucher le contenu */
.dots__link.is-active::after { width: 10px; height: 10px; background: var(--grad); box-shadow: 0 0 0 4px rgba(124, 92, 255, .22); }
@media (max-width: 1023px) { .dots { display: none; } }
/* ---- Appel flottant, à gauche de « remonter » ---- */
.cta-float { position: fixed; right: 82px; bottom: 22px; z-index: 90; display: inline-flex; align-items: center; gap: 10px; padding: 12px 18px 12px 14px; border-radius: 999px; background: var(--grad); color: #fff; font-family: var(--font-h); font-weight: 600; font-size: .9rem; text-decoration: none; box-shadow: 0 16px 40px -10px rgba(34, 211, 238, .6); opacity: 0; visibility: hidden; transform: translateY(12px); transition: opacity .3s, transform .3s var(--ease), visibility 0s .3s; }
.cta-float.is-visible { opacity: 1; visibility: visible; transform: none; transition: opacity .3s, transform .3s var(--ease); }
.cta-float svg { width: 16px; height: 16px; }
.cta-float:hover { color: #fff; filter: brightness(1.12); }
@media (max-width: 760px) { .cta-float { right: 78px; bottom: 18px; padding: 12px 16px 12px 14px; font-size: .84rem; } }
/* ---- Héros ---- */
/* Le titre est VISIBLE dès le premier affichage : il entre flou et décalé puis se met au net, au lieu de partir
   d'une opacité nulle. Un texte à opacité 0 n'est pas compté comme affiché : le LCP de PageSpeed attendait la
   fin de l'animation (≈ 2,7 s sur téléphone, mesuré le 29/09). Au premier passage, le rideau le couvre de toute façon. */
.hero__title .w { display: inline-block; transform: translateY(.35em); filter: blur(10px); animation: word-in var(--t-slow) var(--ease) forwards; animation-delay: calc(.15s + var(--i, 0) * 55ms); }
@keyframes word-in { to { transform: none; filter: none; } }
.hero__cta .btn--primary { box-shadow: 0 0 0 6px rgba(124, 92, 255, .14), 0 16px 40px -10px rgba(34, 211, 238, .45); }
.btn__ring { display: inline-grid; place-items: center; width: 22px; height: 22px; border-radius: 50%; border: 1px solid rgba(255, 255, 255, .2); transition: transform .3s var(--spring), border-color .2s; }
.btn__ring svg { width: 11px; height: 11px; }
.btn--ghost:hover .btn__ring { transform: translate(2px, -2px); border-color: rgba(255, 255, 255, .5); }
.trust { display: flex; align-items: center; flex-wrap: wrap; gap: 10px 22px; margin-top: 30px; font-size: .72rem; letter-spacing: .08em; text-transform: uppercase; color: #8f97b3; }
.trust__list { display: flex; flex-wrap: wrap; gap: 6px 22px; font-family: var(--font-h); font-size: .9rem; font-weight: 700; letter-spacing: 0; text-transform: none; color: var(--muted); }
.stats { grid-template-columns: repeat(3, 1fr); gap: 24px; margin-top: 28px; }
.stats li i { display: block; margin-top: 10px; height: 3px; border-radius: 2px; background: rgba(255, 255, 255, .08); overflow: hidden; }
.stats li i::after { content: ""; display: block; height: 100%; width: 100%; background: linear-gradient(90deg, #7c5cff, #22d3ee); transform: scaleX(0); transform-origin: 0 50%; transition: transform var(--t-cine) var(--ease) .4s; }
.stats.is-in li i::after { transform: none; }
.hero__term { pointer-events: auto; }
.scroll-hint { position: absolute; left: 50%; bottom: 22px; z-index: 1; display: flex; flex-direction: column; align-items: center; gap: 8px; transform: translateX(-50%); font-size: .66rem; letter-spacing: .14em; text-transform: uppercase; color: #8f97b3; text-decoration: none; }
.scroll-hint:hover { color: var(--txt); }
.scroll-hint i { width: 1px; height: 34px; background: linear-gradient(180deg, var(--p2), transparent); transform-origin: 50% 0; animation: hint-flow 1.8s ease-in-out infinite; }
@keyframes hint-flow { 0% { transform: scaleY(0); opacity: 1; } 55% { transform: scaleY(1); opacity: 1; } 100% { transform: scaleY(1); opacity: 0; } }
@media (max-width: 760px) { .scroll-hint { display: none; } .stats { grid-template-columns: 1fr; } }   /* la règle 3 colonnes ci-dessus passait devant celle du téléphone */
/* ---- Services : survol de la carte ---- */
.card--service:hover { border-color: rgba(124, 92, 255, .55); }
.card--service:hover .card__circuit path:not(.pulse):not(.chip) { stroke: rgba(255, 255, 255, .18); }
.card--service:hover .card__circuit .chip { stroke: rgba(167, 139, 250, .9); }
/* ---- Références : filtres avec compte, faits au survol ---- */
.works__filters { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; width: max-content; max-width: 100%; margin: -16px auto 36px; padding: 5px; border-radius: 24px; border: 1px solid var(--line); background: var(--surface); }
.works__filters button { padding: 8px 16px; border: 0; border-radius: 999px; background: transparent; color: var(--muted); font: inherit; font-size: .85rem; font-weight: 500; cursor: pointer; transition: color var(--t-fast), background var(--t-fast); }
.works__filters button:hover { color: var(--txt); }
.works__filters button[aria-pressed="true"] { background: var(--grad); color: #fff; font-family: var(--font-h); font-weight: 600; }
.works__item.is-out { opacity: 0 !important; transform: scale(.96) !important; transition: opacity var(--t-base), transform var(--t-base) !important; }
/* Les trois faits d'une référence : une rangée de puces dans la fiche, juste avant « Voir le site » */
.work__facts { margin: 14px 0 0; padding: 0; list-style: none; display: flex; flex-wrap: wrap; gap: 6px; }
.work__facts li { display: inline-flex; align-items: center; padding: 5px 10px; border-radius: 999px; background: rgba(124, 92, 255, .14); border: 1px solid rgba(124, 92, 255, .4); font-size: .76rem; font-weight: 600; color: #c4b5fd; }
.work__facts li:nth-child(2) { background: rgba(34, 211, 238, .12); border-color: rgba(34, 211, 238, .35); color: #67e8f9; }
.work__facts li:nth-child(3) { background: rgba(52, 211, 153, .14); border-color: rgba(52, 211, 153, .4); color: #6ee7b7; }
/* ---- Formulaire : libellés flottants, messages par champ, envoi, succès ---- */
.field { position: relative; display: block; }
.field > span { position: absolute; left: 14px; top: 17px; max-width: calc(100% - 28px); overflow: hidden; text-overflow: ellipsis; font-size: .95rem; font-weight: 500; color: #8f97b3; pointer-events: none; white-space: nowrap; transition: top var(--t-fast), font-size var(--t-fast), color var(--t-fast); }
.field > span em { font-style: normal; font-weight: 400; color: #6b7290; }
.field :is(input, select, textarea) { padding: 24px 14px 10px; }
.field textarea { min-height: 150px; }
.field :is(input, textarea):focus + span, .field :is(input, textarea):not(:placeholder-shown) + span, .field select + span { top: 8px; font-size: .68rem; letter-spacing: .02em; }
.field :is(input, textarea):focus + span, .field select:focus + span { color: var(--p2); }
.field :is(input, textarea):not(:placeholder-shown) + span em, .field :is(input, textarea):focus + span em { display: none; }
.field__msg { display: block; margin-top: 6px; font-size: .8rem; color: #f87171; }
.field__count { position: absolute; right: 12px; bottom: 10px; font-size: .7rem; color: #6b7290; }
.field.is-invalid :is(input, select, textarea) { border-color: rgba(248, 113, 113, .7); box-shadow: 0 0 0 4px rgba(248, 113, 113, .15); }
.field.is-invalid :is(input, select, textarea) + span { color: #f87171; }
.btn .spin { animation: spin 1s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
.form__success { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 10px; padding: 12px 0; }
.form__success[hidden] { display: none; }
.form.is-sent > :not(.form__success) { display: none; }
.form__success .ok { width: 64px; height: 64px; border-radius: 50%; background: linear-gradient(135deg, #34d399, #22d3ee); display: grid; place-items: center; box-shadow: 0 0 0 10px rgba(52, 211, 153, .14); animation: pop .5s var(--spring); }
.form__success .ok svg { width: 30px; height: 24px; }
.form__success .ok path { stroke-dasharray: 40; stroke-dashoffset: 40; animation: draw-ok .4s .25s ease-out forwards; }
.form__success h3 { margin: 4px 0 0; font-size: 1.3rem; }
.form__success p { margin: 0; max-width: 420px; color: var(--muted); }
@keyframes draw-ok { to { stroke-dashoffset: 0; } }
@keyframes pop { from { transform: scale(.4); opacity: 0; } }
/* ---- Bascule « Moins d'animations » ---- */
.motion-toggle { background: none; border: 0; padding: 0; color: var(--muted); font: inherit; cursor: pointer; text-decoration: underline dotted; text-underline-offset: 3px; }
.motion-toggle:hover { color: var(--txt); }
/* La même chose quand le visiteur a choisi « Moins d'animations » (bascule du pied de page, classe posée en tête de page) */
html.reduce-motion *, html.reduce-motion *::before, html.reduce-motion *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; scroll-behavior: auto !important; }
html.reduce-motion [data-reveal] { opacity: 1; transform: none; filter: none; }
html.reduce-motion .hero__title .w { animation: none; transform: none; filter: none; }
html.reduce-motion :is(.card, .work, .atout, .step__body, .why > li) > *, html.reduce-motion .step__num { opacity: 1; transform: none; }
html.reduce-motion .ico *, html.reduce-motion .ico-layers, html.reduce-motion .ico-layers i, html.reduce-motion .ico-gear3d, html.reduce-motion .gear { animation: none !important; }
html.reduce-motion [data-zoom] { transform: none !important; opacity: 1 !important; }
html.reduce-motion [data-reveal="wipe"] { clip-path: none; }
html.reduce-motion .voyage { height: 0; overflow: hidden; }
html.reduce-motion .voyage-canvas { display: none; }
html.reduce-motion .hero__scene { position: absolute; height: 100%; }
html.reduce-motion :is(.card, .work, .atout, .step__body, .why > li, .faq__item), html.reduce-motion :is(.card, .work, .atout, .step__body, .why > li, .faq__item)::after { animation: none !important; }
html.reduce-motion [data-tilt] { transform: none !important; }
html.reduce-motion .marquee__track, html.reduce-motion .card__circuit .pulse, html.reduce-motion .section--alt::after, html.reduce-motion .steps::after, html.reduce-motion .ico-servers, html.reduce-motion .ico-servers i::after { animation: none; }
html.reduce-motion .fx-canvas { display: none; }


/* ---- Bandeau du héros : un mot à la fois, qui bat comme un cœur (même cadence que le point, 2,2 s) ----
   Les mots partagent une même cellule de grille : la pastille garde la largeur du plus long, rien ne saute. */
.eyebrow__words { display: inline-grid; text-align: left; }
.eyebrow__words > span { grid-area: 1 / 1; opacity: 0; transform: scale(.96); transition: opacity .12s, transform .12s; }   /* le mot sortant part avant que le suivant n'arrive : jamais deux mots superposés */
.eyebrow__words > span.is-on { transition: opacity .25s .12s, transform .25s .12s; }
.eyebrow__words > span.is-on { opacity: 1; transform: none; animation: word-beat 2.2s ease-in-out infinite; transform-origin: 0 50%; }
@keyframes word-beat { 0%, 24%, 100% { transform: scale(1); } 6% { transform: scale(1.12); } 12% { transform: scale(1); } 18% { transform: scale(1.07); } }
/* mouvement réduit : les cinq mots, séparés par des points, sans battement */
@media (prefers-reduced-motion: reduce) { .eyebrow__words { display: inline; } .eyebrow__words > span { opacity: 1; transform: none; animation: none; } .eyebrow__words > span:not(:last-child)::after { content: " · "; } }
html.reduce-motion .eyebrow__words { display: inline; } html.reduce-motion .eyebrow__words > span { opacity: 1; transform: none; animation: none; } html.reduce-motion .eyebrow__words > span:not(:last-child)::after { content: " · "; }
/* ---- Barre entre 1024 et 1199 px : tout tient sur une ligne (liens et bouton resserrés) ---- */
@media (min-width: 1024px) and (max-width: 1199px) {
  .header__inner { gap: 14px; }
  .nav { gap: 14px; }
  .nav__link { padding: 8px 9px; font-size: .9rem; }
  .nav__cta { padding: 9px 14px; font-size: .82rem; }
  .lang__link { padding: 5px 8px; }
}
/* ---- Sur ordinateur, tout le héros tient dans la fenêtre (barre du navigateur comprise) ----
   Marge du haut réduite et proportionnelle à la hauteur d'écran ; en bas, juste la place de l'invite.
   Écran peu haut (≤ 960 px de fenêtre) : les espacements internes se resserrent. */
@media (min-width: 1024px) {
  .hero { padding: calc(var(--hdr) + clamp(20px, 3.5vh, 64px)) 0 clamp(76px, 9vh, 104px); }
  .scroll-hint { bottom: 14px; }
  .scroll-hint i { height: 26px; }
}
@media (min-width: 1024px) and (max-height: 960px) {
  .hero .hero__title { margin: 14px 0 14px; font-size: clamp(2.1rem, 1.2rem + 2.8vw, 3.3rem); }
  .hero__lead { font-size: 1.05rem; }
  .hero__cta { margin-top: 22px; }
  .trust { margin-top: 20px; }
  .stats { margin-top: 20px; padding-top: 22px; }
}
@media (min-width: 1024px) and (max-height: 720px) {
  .hero { padding-top: calc(var(--hdr) + 14px); padding-bottom: 64px; }
  .eyebrow { padding: 6px 12px; }
  .hero .hero__title { margin: 10px 0 10px; font-size: clamp(2rem, 1rem + 2.3vw, 2.7rem); }
  .hero__lead { font-size: .96rem; line-height: 1.5; }
  .hero__cta { margin-top: 16px; }
  .hero__cta .btn--lg { padding: 13px 24px; }
  .trust { margin-top: 14px; }
  .stats { margin-top: 14px; padding-top: 14px; }
  .stats strong { font-size: 1.6rem; }
  .stats li i { margin-top: 6px; }
  .scroll-hint { bottom: 8px; gap: 5px; }
  .scroll-hint i { height: 20px; }
}

/* ==========================================================================
   Passe « site primé » (27/09) : préchargeur, grain, curseur, rendus 3D des services,
   titres révélés par masque, grand bandeau typographique, contact sur fond de verre.
   ========================================================================== */
/* ---- Préchargeur : première visite de la session ; le logo se dessine, le compteur file, le rideau monte ---- */
.loader { display: none; }
html.has-loader .loader {
  display: grid; place-items: center; position: fixed; inset: 0; z-index: 1000; background: var(--bg);
  clip-path: inset(0 0 0 0); transition: clip-path .85s cubic-bezier(.76, 0, .24, 1);
  animation: loader-safety .01s 4s forwards;   /* filet : si le script ne tourne pas, le rideau disparaît quand même */
}
html.has-loader .loader.is-done { clip-path: inset(0 0 100% 0); }
@keyframes loader-safety { to { visibility: hidden; } }
.loader__inner { display: flex; flex-direction: column; align-items: center; gap: 18px; }
.loader__logo { width: min(250px, 62vw); height: auto; display: block; }
/* démarrage « pixel » : l'image se découvre de haut en bas en 37 crans, une rangée du robot par cran (≈ 1 s).
   Un seul élément animé : animer chaque rectangle les rastérisait à part et laissait des traits noirs entre rangées. */
.loader__logo { clip-path: inset(0 0 100% 0); animation: px-rangs .96s steps(37, end) forwards; }
@keyframes px-rangs { to { clip-path: inset(0 0 0 0); } }
.loader__count { font: 700 .8rem var(--font-h); letter-spacing: .3em; color: var(--muted); font-variant-numeric: tabular-nums; }
/* le héros attend la levée du rideau */
html.has-loader .hero [data-reveal] { transition-delay: calc(1.15s + var(--d, 0) * 90ms); }
/* Les blocs du héros sont VISIBLES dès le premier affichage (même raison que le titre : un bloc à opacité 0 n'est
   pas compté comme affiché, le paragraphe d'accroche devenait le LCP à 5 s sur téléphone) : ils entrent flous
   et décalés puis se mettent au net. En quittant l'écran par le haut (.is-above), ils s'effacent comme avant. */
.hero [data-reveal]:not(.is-above) { opacity: 1; }
@media (prefers-reduced-motion: no-preference) {
  html:not(.reduce-motion) .hero [data-reveal]:not(.is-in):not(.is-above) { filter: blur(12px); }
}
html.has-loader .hero__title .w { animation-delay: calc(1.25s + var(--i, 0) * 55ms); }

/* ---- Grain de pellicule, très léger, sur toute la page ---- */
body::after {
  content: ""; position: fixed; inset: -50%; z-index: 150; pointer-events: none; opacity: .055;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  animation: grain 1.2s steps(6) infinite;
}
@keyframes grain { 0%, 100% { transform: translate(0, 0); } 20% { transform: translate(-3%, 2%); } 40% { transform: translate(2%, -3%); } 60% { transform: translate(-2%, -2%); } 80% { transform: translate(3%, 3%); } }

/* ---- Services : le rendu 3D flotte en haut de la carte et sort en relief avec l'inclinaison ---- */
.card__art { position: relative; width: 196px; height: 196px; margin: -58px 0 -6px -34px; --z: 70px; pointer-events: none; }   /* l'objet déborde du haut de la carte : il « sort du cadre » */
.card__art img { display: block; width: 100%; height: 100%; object-fit: contain; filter: drop-shadow(0 18px 28px rgba(124, 92, 255, .35)); animation: art-float 6s ease-in-out infinite; transition: filter .4s; }
.services__item:nth-child(2) .card__art img { animation-delay: -1.5s; }
.services__item:nth-child(3) .card__art img { animation-delay: -3s; }
.services__item:nth-child(4) .card__art img { animation-delay: -4.5s; }
@keyframes art-float { 0%, 100% { transform: translateY(0) rotate(0); } 50% { transform: translateY(-9px) rotate(-2deg); } }
.card--service:hover .card__art img { filter: drop-shadow(0 22px 36px rgba(34, 211, 238, .45)) brightness(1.08); }
@media (max-width: 760px) { .card__art { width: 156px; height: 156px; margin: -44px 0 -4px -26px; } }

/* ---- Titres de section : chaque mot monte d'un masque (le dégradé reste d'un seul bloc) ---- */
.section__head h2 .wm { display: inline-block; overflow: hidden; vertical-align: bottom; padding-bottom: .1em; margin-bottom: -.1em; }
.section__head h2 .wm > * { display: inline-block; transform: translateY(110%); transition: transform .95s var(--ease); transition-delay: calc(.08s + var(--i, 0) * 65ms); }
.section__head.is-in h2 .wm > * { transform: none; }

/* ---- Contact : formulaire dépoli ---- */
#contact .form { background: rgba(14, 16, 30, .6); -webkit-backdrop-filter: blur(22px) saturate(150%); backdrop-filter: blur(22px) saturate(150%); border-color: rgba(255, 255, 255, .12); }

/* ---- Mouvement réduit : rien ne bouge de lui-même ---- */
@media (prefers-reduced-motion: reduce) {
  body::after, .card__art img { animation: none; }
  .section__head h2 .wm > * { transform: none; transition: none; }
}
html.reduce-motion body::after, html.reduce-motion .card__art img { animation: none; }
html.reduce-motion .section__head h2 .wm > * { transform: none; transition: none; }
/* ---- Logo fon10.studio (outils/logo.php) : pixel-art net à toute taille, clignement des yeux ---- */
.brand__logo { display: block; height: 38px; width: auto; transition: height .3s var(--ease); }
.header.is-scrolled .brand__logo { height: 32px; }
.brand__logo--pied { height: 34px; }
.logo__yeux { transform-box: fill-box; transform-origin: 50% 50%; animation: cligne 5s infinite; }
@keyframes cligne { 0%, 93%, 100% { transform: scaleY(1); } 95% { transform: scaleY(.15); } }
.brand:hover .logo__yeux { animation-duration: 1.4s; }
@media (max-width: 400px) { .brand__logo { height: 28px; } .header.is-scrolled .brand__logo { height: 26px; } }
@media (max-width: 370px) { .brand__logo, .header.is-scrolled .brand__logo { height: 24px; } }
@media (prefers-reduced-motion: reduce) { .logo__yeux { animation: none; } .loader__logo { animation: none; clip-path: none; } }
html.reduce-motion .logo__yeux { animation: none; }