/* Parallak V2 — feuille de style autonome (sans Tailwind)
   Fonts : src/fonts/gf/ (Manrope variable, Playfair Display)
   Tokens : charte src/brand-guidelines.md
*/

/* ---------- Fonts ---------- */
@font-face { font-family: "Manrope"; src: url("src/fonts/gf/manrope-latin.woff2") format("woff2"); font-weight: 300 800; font-display: swap; }
@font-face { font-family: "Playfair Display"; src: url("src/fonts/gf/playfair-latin.woff2") format("woff2"); font-weight: 400 600; font-style: normal; font-display: swap; }
@font-face { font-family: "Playfair Display"; src: url("src/fonts/gf/playfair-italic-latin.woff2") format("woff2"); font-weight: 400 600; font-style: italic; font-display: swap; }

/* ---------- Tokens ---------- */
:root {
  --brand: #0005F8;
  --brand-dark: #0000CC;
  --brand-light: #4D51FF;
  --brand-pale: #E9EAFF;
  --ink: #0A0A0A;
  --ink-2: #1C1C22;
  --night: #07071A;
  --night-2: #0D0D26;
  --surface: #F2F2F2;
  --paper: #FAFAF8;
  --muted: #5F5F66;
  --muted-dark: rgba(255,255,255,.62);
  --line: rgba(10,10,10,.10);
  --line-dark: rgba(255,255,255,.12);
  --radius: 22px;
  --radius-lg: 32px;
  --shadow-brand: 0 24px 60px -20px rgba(0,5,248,.35);
  --shadow-soft: 0 20px 60px -30px rgba(10,10,10,.25);
  --shadow-device: 0 40px 80px -30px rgba(0,0,0,.55), 0 0 0 1px rgba(255,255,255,.06);
  --font-body: "Manrope", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-display: "Playfair Display", Georgia, serif;
  --ease-out: cubic-bezier(.16,1,.3,1);
  --ease-io: cubic-bezier(.65,0,.35,1);
  --nav-h: 66px;
  --pad: clamp(20px, 4.4vw, 60px);
  --wrap: 1160px;
  --bar-h: 0px;
  --wall-gap: 18px;
}

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-padding-top: calc(var(--nav-h) + 12px); }
body {
  margin: 0; font-family: var(--font-body); color: var(--ink); background: var(--surface);
  line-height: 1.55; font-size: 16px; -webkit-font-smoothing: antialiased; overflow-x: clip;
  padding-bottom: var(--bar-h);
}
body.is-locked { overflow: hidden; }
img, picture, video, svg { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; padding: 0; }
h1, h2, h3, h4 { margin: 0; font-weight: 500; line-height: 1.05; letter-spacing: -.015em; }
p { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }
:focus-visible { outline: 3px solid var(--brand-light); outline-offset: 3px; border-radius: 6px; }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }
[hidden] { display: none !important; }

.skip { position: fixed; top: -100px; left: 16px; z-index: 1000; background: var(--ink); color: #fff; padding: 12px 18px; border-radius: 999px; }
.skip:focus { top: 16px; }

.grain {
  position: fixed; inset: 0; z-index: 900; pointer-events: none; opacity: .045; mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/></filter><rect width='160' height='160' filter='url(%23n)' opacity='.9'/></svg>");
}

/* ---------- Typo ---------- */
.display { font-family: var(--font-display); font-weight: 500; letter-spacing: -.02em; line-height: 1.02; text-wrap: balance; }
.display em { font-style: italic; color: var(--brand); font-weight: 400; }
.on-dark .display em { color: var(--brand-light); }
.h1 { font-size: clamp(34px, 5.1vw, 66px); }
.h2 { font-size: clamp(28px, 3.5vw, 46px); }
.h3 { font-size: clamp(21px, 2vw, 28px); line-height: 1.14; }
.lead { font-size: clamp(17px, 1.35vw, 20px); line-height: 1.6; color: var(--muted); max-width: 62ch; }
.on-dark .lead { color: var(--muted-dark); }
.lead strong { color: var(--ink); font-weight: 700; }
.on-dark .lead strong { color: #fff; }
.eyebrow {
  display: inline-flex; align-items: center; gap: 10px; font-size: 12px; font-weight: 800; letter-spacing: .16em; text-transform: uppercase; color: var(--brand);
}
.eyebrow::before { content: ""; width: 22px; height: 2px; background: currentColor; border-radius: 2px; }
.on-dark .eyebrow { color: var(--brand-light); }
.kicker { font-size: 12px; font-weight: 800; letter-spacing: .14em; text-transform: uppercase; color: var(--muted); }
.num { font-variant-numeric: tabular-nums; }

/* Mots forts locaux */
mark.hl {
  background: none; color: inherit; font-weight: 700; padding: 0 .08em;
  background-image: linear-gradient(120deg, rgba(77,81,255,.55), rgba(77,81,255,.55));
  background-repeat: no-repeat; background-size: 0% .3em; background-position: 0 100%; box-decoration-break: clone; -webkit-box-decoration-break: clone;
  transition: background-size 1s var(--ease-out) .5s;
}
.hero .lead mark.hl { color: #fff; }
.is-in mark.hl, html:not(.js) mark.hl { background-size: 100% .3em; }

/* ---------- Layout ---------- */
.wrap { width: min(var(--wrap), 100% - 2 * var(--pad)); margin-inline: auto; }
.section { padding: clamp(56px, 6.4vw, 96px) 0; position: relative; }
.section-head { max-width: 760px; margin-bottom: clamp(28px, 3.4vw, 46px); display: grid; gap: 14px; }
.section-head.is-tight { margin-bottom: clamp(20px, 2.6vw, 34px); }
.on-dark { background: var(--night); color: #fff; }
.row { display: flex; flex-wrap: wrap; gap: 14px; align-items: center; }

/* ---------- Boutons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px; font-weight: 700; font-size: 15px; line-height: 1;
  padding: 16px 24px; border-radius: 999px; border: 1.5px solid transparent; transition: transform .35s var(--ease-out), background .25s, color .25s, box-shadow .35s, border-color .25s;
  white-space: nowrap; position: relative; isolation: isolate;
}
.btn svg { width: 18px; height: 18px; transition: transform .35s var(--ease-out); }
.btn:hover svg { transform: translateX(4px); }
.btn-lg { padding: 19px 30px; font-size: 16px; }
.btn-sm { padding: 12px 18px; font-size: 14px; }
.btn-primary { background: var(--brand); color: #fff; box-shadow: var(--shadow-brand); }
.btn-primary:hover { background: var(--brand-dark); transform: translateY(-2px); box-shadow: 0 30px 70px -20px rgba(0,5,248,.5); }
.btn-ghost { border-color: var(--line); color: var(--ink); background: rgba(255,255,255,.55); }
.btn-ghost:hover { border-color: var(--ink); transform: translateY(-2px); }
.on-dark .btn-ghost { border-color: rgba(255,255,255,.22); color: #fff; background: rgba(255,255,255,.04); }
.on-dark .btn-ghost:hover { border-color: #fff; background: rgba(255,255,255,.08); }
.btn-ink { background: var(--ink); color: #fff; }
.btn-ink:hover { background: var(--brand); transform: translateY(-2px); }


.step-link { display: inline-flex; align-items: center; gap: 6px; font-weight: 700; font-size: 15px; color: var(--brand); border-bottom: 1.5px solid transparent; transition: border-color .25s; }
.step-link svg { width: 16px; height: 16px; }
.step-link:hover { border-color: currentColor; }

/* ---------- Navigation ---------- */
.nav {
  position: fixed; top: 0; left: 0; right: 0; z-index: 500; height: var(--nav-h);
  color: #fff; transition: background .4s, color .3s, border-color .4s, box-shadow .4s;
  border-bottom: 1px solid transparent;
}
.nav-inner { width: min(var(--wrap), 100% - 2 * var(--pad)); margin-inline: auto; height: 100%; display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 24px; }
.nav-inner > :last-child { justify-self: end; }
.nav-logo { display: block; height: 22px; flex: 0 0 auto; justify-self: start; }
.nav-logo img { height: 100%; width: auto; }
.nav .logo-light { display: none; }
.nav.is-light { color: var(--ink); }
.nav.is-light .logo-dark { display: none; }
.nav.is-light .logo-light { display: block; }
.nav.is-scrolled.is-dark { background: rgba(7,7,26,.72); backdrop-filter: blur(18px) saturate(1.4); -webkit-backdrop-filter: blur(18px) saturate(1.4); border-color: var(--line-dark); }
.nav.is-scrolled.is-light { background: rgba(250,250,248,.78); backdrop-filter: blur(18px) saturate(1.4); -webkit-backdrop-filter: blur(18px) saturate(1.4); border-color: var(--line); }
.nav-links { display: flex; gap: 4px; }
.nav-links a { padding: 10px 14px; border-radius: 999px; font-weight: 600; font-size: 15px; opacity: .8; transition: opacity .25s, background .25s; position: relative; }
.nav-links a:hover, .nav-links a.is-current { opacity: 1; }
.nav-links a::after { content: ""; position: absolute; left: 14px; right: 14px; bottom: 6px; height: 2px; border-radius: 2px; background: currentColor; transform: scaleX(0); transform-origin: left; transition: transform .4s var(--ease-out); }
.nav-links a.is-current::after, .nav-links a:hover::after { transform: scaleX(1); }
.nav-actions { display: flex; align-items: center; gap: 10px; }
.nav-tel { display: inline-flex; align-items: center; gap: 8px; white-space: nowrap; font-weight: 700; font-size: 15px; padding: 10px 12px; opacity: .85; font-variant-numeric: tabular-nums; }
.nav-tel svg { width: 16px; height: 16px; }
.nav-tel:hover { opacity: 1; }
.nav.is-light .nav-cta { box-shadow: none; }
/* Le bouton du menu porte son nom au lieu d une icone a traits : sur un telephone
   on lit « Menu », puis « Fermer » une fois ouvert. Nils ne voulait plus de
   l icone (2026-09-05 : « l icone je ne me trouve pas plus beau »). */
.nav-burger { display: none; align-items: center; justify-content: center; height: 38px; min-width: 84px; padding: 0 18px; border-radius: 999px;
              border: none; background: var(--brand); color: #fff; opacity: 1;
              box-shadow: 0 3px 12px rgba(0, 5, 248, .30);
              font-size: 13.5px; font-weight: 700; letter-spacing: -.01em;
              transition: background .3s var(--ease-out), box-shadow .3s var(--ease-out); }
/* Le bouton est une pastille bleue pleine, et non plus un contour dans la couleur
   du texte ambiant. Un contour en currentColor devenait blanc sur une section
   claire et disparaissait (Nils, 2026-09-05 : « l'icone je ne me trouve pas plus
   beau », « le reste blanc sur blanc »). Rempli, il se voit sur tout fond et il
   n'a plus besoin de la couleur de la barre pour exister. */
.nav-burger[aria-expanded="true"] { background: rgba(255, 255, 255, .14); box-shadow: none; }
.burger-txt { display: grid; }
.burger-txt > span { grid-area: 1 / 1; transition: opacity .25s; }
.burger-txt .w-open, .nav-burger[aria-expanded="true"] .burger-txt .w-shut { opacity: 0; }
.nav-burger[aria-expanded="true"] .burger-txt .w-open { opacity: 1; }
/* Le panneau du menu est sombre : quand il est ouvert, la barre du haut doit
   redevenir transparente et repasser en blanc, quelle que soit la section sous
   laquelle elle se trouvait. Les deux selecteurs sont ecrits en entier parce
   qu'une regle a trois classes l'emportait sinon sur celle-ci : sur une section
   claire, la barre restait blanche et le logo comme le bouton de fermeture, eux
   aussi blancs, disparaissaient (Nils, 2026-09-05 : « On ne voit plus le logo et
   l'icone pour fermer, le reste blanc sur blanc »). */
body.menu-open .nav,
body.menu-open .nav.is-scrolled.is-light,
body.menu-open .nav.is-scrolled.is-dark { color: #fff; background: transparent; backdrop-filter: none; -webkit-backdrop-filter: none; border-color: transparent; }
body.menu-open .nav .logo-light { display: none; }
body.menu-open .nav .logo-dark { display: block; }

.nav-sheet {
  position: fixed; inset: 0; z-index: 450; background: var(--night); color: #fff; display: flex; flex-direction: column; justify-content: space-between;
  padding: calc(var(--nav-h) + 24px) var(--pad) max(28px, env(safe-area-inset-bottom)); overflow: hidden;
  clip-path: circle(0 at calc(100% - 44px) 36px); visibility: hidden; transition: clip-path .7s var(--ease-io), visibility 0s .7s;
}
.nav-sheet.is-open { clip-path: circle(150% at calc(100% - 44px) 36px); visibility: visible; transition: clip-path .8s var(--ease-io), visibility 0s; }
.nav-sheet::before { content: ""; position: absolute; inset: auto -20% -30% auto; width: 80vw; height: 80vw; border-radius: 50%; background: radial-gradient(circle, rgba(0,5,248,.55), transparent 65%); filter: blur(30px); }
.sheet-mark { position: absolute; right: -6%; top: 12%; width: 62vw; max-width: 380px; opacity: .06; pointer-events: none; }
.sheet-links { display: grid; gap: 4px; position: relative; }
.sheet-links a {
  display: flex; align-items: baseline; gap: 16px; font-family: var(--font-display); font-size: clamp(34px, 9vw, 56px); line-height: 1.15; padding: 6px 0; border-bottom: 1px solid var(--line-dark);
  opacity: 0; transform: translateY(24px); transition: opacity .5s var(--ease-out), transform .6s var(--ease-out);
}
.sheet-links a small { font-family: var(--font-body); font-size: 12px; font-weight: 800; letter-spacing: .14em; color: var(--brand-light); }
.nav-sheet.is-open .sheet-links a { opacity: 1; transform: none; transition-delay: calc(.25s + var(--i) * .06s); }
.sheet-foot { display: grid; gap: 14px; justify-items: start; position: relative; }
.sheet-foot .btn { width: 100%; }
.sheet-tel { display: inline-flex; align-items: center; gap: 10px; min-height: 44px; font-weight: 700; font-size: 18px; }
.sheet-tel svg { width: 18px; height: 18px; }
.sheet-where { font-size: 13px; color: var(--muted-dark); }

/* ---------- Hero ---------- */
/* La marge haute du hero est nommee une fois (--hero-top) et RETRANCHEE de la hauteur
   demandee a la grille : sans cela, marge et hauteur minimale s'additionnaient et le
   premier ecran depassait toujours d'une centaine de pixels. */
.hero { --hero-top: clamp(24px, 3.4vh, 56px); --clients-h: 148px; position: relative; overflow: hidden; padding-top: calc(var(--nav-h) + var(--hero-top)); background: var(--night); }
.hero::before {
  content: ""; position: absolute; inset: -20% -10% auto auto; width: 70vw; height: 70vw; max-width: 1100px; max-height: 1100px; border-radius: 50%; pointer-events: none;
  background: radial-gradient(circle at 60% 40%, rgba(0,5,248,.55), rgba(0,5,248,.12) 40%, transparent 65%); filter: blur(40px);
}
/* Grain : une tuile SVG de 160 px en data-URI, rasterisee une seule fois par le
   navigateur, repetee en mosaique. Zero fichier, zero requete, zero JS. */
.hero::after {
  content: ""; position: absolute; inset: 0; pointer-events: none; opacity: .5; mix-blend-mode: soft-light;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/></filter><rect width='160' height='160' filter='url(%23n)'/></svg>");
  background-size: 160px 160px;
}
.hero-grid { position: relative; z-index: 1; display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); gap: clamp(28px, 4.4vw, 68px); align-items: center; min-height: calc(100svh - var(--nav-h) - var(--hero-top) - var(--clients-h)); }
/* Le retrait supplementaire d'un `clamp(0px, 2vh, 24px)` qui figurait ici laissait
   entre 19 et 24 pixels de la section suivante, claire, sous la bande des clients :
   c'est la bande blanche vue par Nils le 2026-09-05 en bas du premier ecran
   d'ordinateur. Le premier ecran occupe maintenant exactement la fenetre. */
.hero-copy { display: grid; gap: clamp(15px, 2.4vh, 26px); justify-items: start; padding-bottom: clamp(0px, 2vh, 24px); min-width: 0; }
.hero-badges { display: flex; flex-wrap: wrap; gap: 8px; }
.hero-badges .chip { white-space: nowrap; }
.chip {
  display: inline-flex; align-items: center; gap: 8px; padding: 8px 14px 8px 10px; border-radius: 999px; font-size: 13px; font-weight: 600;
  border: 1px solid var(--line-dark); background: rgba(255,255,255,.05); color: rgba(255,255,255,.85); backdrop-filter: blur(6px);
}
.chip svg { width: 15px; height: 15px; flex: 0 0 auto; }
.chip .flag { width: 18px; height: 12px; border-radius: 2px; box-shadow: 0 0 0 1px rgba(255,255,255,.25); }
.chip-status { border-color: rgba(77,81,255,.5); background: rgba(0,5,248,.18); }
.chip-status.is-open svg { color: #4ADE80; }
.chip-status.is-closed svg { color: #FBBF24; }
.h1 { color: #fff; max-width: 100%; font-size: clamp(34px, min(5.1vw, 7.2vh), 66px); }
.rotator { display: inline-grid; text-align: left; max-width: 100%; }
.rotator > span { grid-area: 1 / 1; color: var(--brand-light); font-style: italic; font-weight: 400; opacity: 0; transform: translateY(.5em) rotate(1.5deg); transform-origin: left bottom; transition: opacity .5s var(--ease-out), transform .7s var(--ease-out); will-change: transform; }
.rotator > span.is-in { opacity: 1; transform: none; }
.rotator > span.is-out { opacity: 0; transform: translateY(-.5em) rotate(-1.5deg); }
.hero-ctas { display: flex; flex-wrap: wrap; gap: 12px; }
.hero-ctas .btn { white-space: nowrap; }
.hero-proof { display: flex; flex-wrap: wrap; gap: 10px 20px; font-size: 14px; color: var(--muted-dark); font-weight: 600; }
.hero-proof li { display: inline-flex; align-items: center; gap: 8px; white-space: nowrap; }
.hero-proof svg { width: 15px; height: 15px; color: #4ADE80; }

/* Wall : deux formats, deux types de colonnes (16:10 pour les écrans, 9:18 pour les téléphones) */
/* Le mur ne depasse jamais la place que le premier ecran lui laisse : sa
   hauteur est bornee par celle de la fenetre, barre et bandeau deduits. */
.wall { position: relative; height: min(78vh, 760px, calc(100svh - var(--nav-h) - var(--hero-top) - var(--clients-h) - 24px)); min-height: 420px; }
.wall-mask {
  position: absolute; inset: -6% -14% -6% -4%; perspective: 1600px; perspective-origin: 40% 40%;
  -webkit-mask-image: linear-gradient(180deg, transparent, #000 14%, #000 84%, transparent), linear-gradient(90deg, transparent, #000 14%, #000 92%, transparent);
  -webkit-mask-composite: source-in; mask-image: linear-gradient(180deg, transparent, #000 14%, #000 84%, transparent), linear-gradient(90deg, transparent, #000 14%, #000 92%, transparent); mask-composite: intersect;
}
.wall-plane { position: absolute; inset: 0; display: grid; grid-template-columns: 1.25fr .78fr 1.25fr; gap: var(--wall-gap); transform: rotateX(10deg) rotateY(-16deg) rotateZ(5deg) scale(1.08); transform-style: preserve-3d; transform-origin: 50% 50%; }
/* Le contenu de chaque colonne est duplique une fois par le JS. La remontee se fait
   sur une distance mesuree EN PIXELS ENTIERS (--loop, posee par le JS une fois les
   images chargees) et non en pourcentage : une hauteur en pourcentage tombait sur
   une fraction de pixel, et la reprise finissait par sauter au bout de quelques
   tours. La distance est recalculee au chargement et a chaque redimensionnement. */
.wall-col { display: flex; flex-direction: column; gap: var(--wall-gap); will-change: transform; --loop: 50%; }
.wall-col-desk { animation: wall-up 52s linear infinite; }
.wall-col-desk:last-child { animation-duration: 60s; animation-delay: -20s; }
.wall-col-phone { animation: wall-up 46s linear infinite reverse; }
@keyframes wall-up { from { transform: none; } to { transform: translateY(calc(-1 * var(--loop))); } }
.wall-card { position: relative; flex: 0 0 auto; border-radius: 12px; overflow: hidden; background: var(--ink-2); box-shadow: var(--shadow-device); }
.wall-card img { width: 100%; height: 100%; object-fit: cover; object-position: top; }
.wall-card.is-desk { aspect-ratio: 16 / 10; border: 4px solid #17171f; border-bottom-width: 12px; }
.wall-card.is-phone { aspect-ratio: 9 / 18; border-radius: 26px; border: 7px solid #17171f; }
.wall-card.is-phone::before { content: ""; position: absolute; top: 8px; left: 50%; width: 36%; height: 14px; border-radius: 10px; background: #17171f; transform: translateX(-50%); z-index: 1; }
.wall-card .tag {
  position: absolute; left: 8px; bottom: 8px; z-index: 1; padding: 5px 9px; border-radius: 999px; font-size: 10.5px; font-weight: 700; letter-spacing: .02em;
  background: rgba(7,7,26,.72); color: #fff; backdrop-filter: blur(6px); white-space: nowrap; max-width: calc(100% - 16px); overflow: hidden; text-overflow: ellipsis;
}
.wall-card.is-phone .tag { left: 50%; transform: translateX(-50%); bottom: 12px; }

/* Bandeau clients : fondu vers la nuit du hero, jamais vers le blanc */
.clients { position: relative; z-index: 1; border-top: 1px solid var(--line-dark); padding: 28px 0 34px; background: linear-gradient(180deg, transparent, rgba(0,5,248,.08)); }
.clients-head { margin-bottom: 18px; }
.clients-fade { -webkit-mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent); mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent); overflow: hidden; }
.clients-track { display: flex; gap: 0; width: max-content; animation: marquee 48s linear infinite; }
.clients:hover .clients-track { animation-play-state: paused; }
@keyframes marquee { to { transform: translateX(-50%); } }
.client { display: inline-flex; align-items: baseline; gap: 10px; padding: 0 34px; font-family: var(--font-display); font-size: clamp(20px, 2vw, 28px); color: #fff; white-space: nowrap; position: relative; }
.client::after { content: ""; position: absolute; right: -3px; top: 50%; width: 6px; height: 6px; border-radius: 50%; background: var(--brand-light); transform: translateY(-50%); }
.client small { font-family: var(--font-body); font-size: 12px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--muted-dark); }

/* ---------- Réalisations : scrollytelling ---------- */
.story { background: var(--paper); }
.story-grid { display: grid; grid-template-columns: minmax(0, .95fr) minmax(0, 1.15fr); gap: clamp(32px, 5vw, 80px); align-items: start; }
.story-steps { display: grid; }
.step { padding: clamp(60px, 14vh, 140px) 0; display: grid; gap: 18px; justify-items: start; opacity: .28; transition: opacity .5s; border-bottom: 1px solid var(--line); }
.step:first-child { padding-top: 12px; }
.step:last-child { border-bottom: 0; }
.step.is-active { opacity: 1; }
.step-index { display: inline-flex; align-items: center; gap: 10px; font-size: 12px; font-weight: 800; letter-spacing: .14em; text-transform: uppercase; color: var(--muted); }
.step-index b { color: var(--brand); font-size: 13px; }
.step p { color: var(--muted); max-width: 54ch; }
.step-facts { display: flex; flex-wrap: wrap; gap: 8px; }
.fact { padding: 8px 12px; border-radius: 999px; background: #fff; border: 1px solid var(--line); font-size: 13px; font-weight: 600; color: var(--ink); }
.fact b { color: var(--brand); font-weight: 800; margin-right: 4px; }
.step-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 16px; margin-top: 6px; }

.story-stage { position: sticky; top: calc(var(--nav-h) + 20px); }
.stage {
  position: relative; border-radius: var(--radius-lg); background: radial-gradient(120% 90% at 80% 0%, #1A1A4A, var(--night) 55%); overflow: hidden; height: min(calc(100vh - var(--nav-h) - 40px), 660px);
  min-height: 500px; box-shadow: 0 50px 100px -40px rgba(7,7,26,.55);
}
.stage::before { content: ""; position: absolute; inset: 0; background-image: linear-gradient(rgba(255,255,255,.04) 1px, transparent 1px), linear-gradient(90deg, rgba(255,255,255,.04) 1px, transparent 1px); background-size: 48px 48px; -webkit-mask-image: radial-gradient(ellipse at 50% 100%, #000, transparent 75%); mask-image: radial-gradient(ellipse at 50% 100%, #000, transparent 75%); }
.stage-bar { position: absolute; top: 22px; left: 26px; right: 26px; z-index: 5; display: flex; align-items: center; gap: 16px; color: #fff; font-size: 13px; }
.stage-count { font-weight: 800; letter-spacing: .1em; color: var(--muted-dark); font-variant-numeric: tabular-nums; }
.stage-count b { color: #fff; }
.stage-name { font-weight: 700; flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.stage-segs { display: flex; gap: 5px; }
.stage-segs i { width: 22px; height: 3px; border-radius: 3px; background: rgba(255,255,255,.18); transition: background .4s, width .4s; }
.stage-segs i.is-on { background: var(--brand-light); width: 34px; }
/* Une seule composition pour les cinq realisations, et rien d'autre dans le cadre :
   une fenetre de navigateur qui occupe toute la hauteur a gauche, un telephone
   pose devant en bas a droite. Toutes les tailles se calculent sur la HAUTEUR de
   la scene (cqh), jamais sur sa largeur. */
.scene { --ph: 74cqh; position: absolute; inset: 58px 26px 26px; opacity: 0; visibility: hidden; transition: opacity .5s var(--ease-out), visibility 0s .5s; container-type: size; }
.scene.is-active { opacity: 1; visibility: visible; transition: opacity .6s var(--ease-out) .1s, visibility 0s; }

.screen {
  position: absolute; left: 0; top: 0; bottom: 0; right: calc(var(--ph) * 9 / 19 - 6cqh);
  display: grid; grid-template-rows: 30px minmax(0, 1fr); border-radius: 14px; overflow: hidden;
  background: #14141F; border: 1px solid rgba(255,255,255,.1); box-shadow: var(--shadow-device);
  transform: translateY(26px) scale(.98); opacity: 0; transition: transform .9s var(--ease-out), opacity .7s var(--ease-out), box-shadow .4s;
}
.scene.is-active .screen { transform: none; opacity: 1; }
.screen .bar { display: flex; align-items: center; gap: 6px; padding: 0 12px; background: #1C1C28; }
.screen .bar i { width: 8px; height: 8px; border-radius: 50%; background: #3A3A4C; }
.screen .bar em { flex: 1; margin-left: 10px; padding: 3px 12px; border-radius: 999px; background: rgba(255,255,255,.06); font-size: 11px; font-style: normal; font-weight: 600; color: rgba(255,255,255,.55); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.screen .win { position: relative; overflow: hidden; background: #fff; container-type: size; }
.screen .win img { width: 100%; height: auto; display: block; }
/* La page entiere defile toute seule tant que la scene est visible : c'est ce qui
   remplace la capture figee, sans demander un geste au visiteur. */
.scene.is-active .screen .win img { animation: page-scroll 18s var(--ease-io) infinite alternate; }
@keyframes page-scroll { from { transform: none; } to { transform: translateY(calc(-100% + 100cqh)); } }
.screen .visit { position: absolute; right: 12px; bottom: 12px; z-index: 3; display: inline-flex; align-items: center; gap: 7px; padding: 9px 15px; border-radius: 999px; background: var(--brand); color: #fff; font-size: 13px; font-weight: 700; opacity: 0; transform: translateY(8px); transition: opacity .3s, transform .3s var(--ease-out); }
.screen .visit svg { width: 15px; height: 15px; }
.screen:hover .visit, .screen:focus-visible .visit { opacity: 1; transform: none; }
.screen:hover { box-shadow: 0 50px 90px -30px rgba(0,5,248,.45), 0 0 0 1px rgba(77,81,255,.5); }
.screen:focus-visible { outline-offset: 6px; }

/* Les deux contenus telephone se fondent l'un dans l'autre au meme emplacement :
   un seul appareil a l'ecran, jamais deux cadres qui se disputent la place. */
.phone-slot { position: absolute; right: 0; bottom: 0; height: var(--ph); aspect-ratio: 9 / 19; }
.device { position: absolute; inset: 0; overflow: hidden; background: #0B0B14; box-shadow: var(--shadow-device); container-type: size; }
.device img, .device video { width: 100%; height: 100%; object-fit: cover; object-position: top; }
.device::after { content: ""; position: absolute; inset: 0; border-radius: inherit; box-shadow: inset 0 0 0 1px rgba(255,255,255,.08); pointer-events: none; }
/* Cette regle ne vaut que pour les deux telephones qui alternent dans la scene
   du grand ecran. Sans le prefixe .device elle atteignait aussi la vignette
   telephone des cartes du carrousel telephone, qui restait donc invisible :
   c est le « bug » des cartes signale par Nils le 2026-09-05. */
.device.phone { border-radius: 30px; border: 7px solid #1C1C28; box-shadow: 0 44px 80px -28px rgba(0,0,0,.85), var(--shadow-device); opacity: 0; visibility: hidden; transform: translateY(22px) scale(.97); transition: opacity .7s var(--ease-out), transform .8s var(--ease-out), visibility 0s .8s; }
.phone::before { content: ""; position: absolute; top: 8px; left: 50%; width: 34%; height: 14px; border-radius: 10px; background: #1C1C28; transform: translateX(-50%); z-index: 2; }
.scene.is-active .device.phone.is-on { opacity: 1; visibility: visible; transform: none; transition: opacity .7s var(--ease-out) .25s, transform .8s var(--ease-out) .25s, visibility 0s; }
.device.phone:hover { box-shadow: 0 50px 90px -30px rgba(0,5,248,.45), 0 0 0 1px rgba(77,81,255,.5); }
.device.phone:focus-visible { outline-offset: 6px; }


/* Réalisations mobile : rail */
.story-mobile { display: none; }
.rail { display: flex; gap: 16px; overflow-x: auto; scroll-snap-type: x mandatory; scroll-padding-inline: var(--pad); padding: 8px var(--pad) 24px; margin-inline: calc(-1 * var(--pad)); scrollbar-width: none; -webkit-overflow-scrolling: touch; }
.rail::-webkit-scrollbar { display: none; }
.card { flex: 0 0 min(86%, 420px); scroll-snap-align: center; display: grid; gap: 12px; padding: 16px; border-radius: var(--radius); background: #fff; border: 1px solid var(--line); box-shadow: var(--shadow-soft); align-content: start; text-align: center; justify-items: center; transform: scale(.96); opacity: .7; transition: transform .5s var(--ease-out), opacity .5s; }
.card.is-active { transform: none; opacity: 1; }
.card h3 { font-size: 22px; line-height: 1.15; }
.card p { font-size: 15px; color: var(--muted); }
.card .step-actions { justify-content: center; margin-top: 4px; }
/* Meme composition que sur grand ecran : la page qui defile a gauche, un
   telephone a droite, dans toutes les cartes du rail. */
.card-media { width: 100%; display: grid; grid-template-columns: 1fr .46fr; gap: 10px; align-items: end; }
.frame { position: relative; width: 100%; overflow: hidden; background: #0B0B14; box-shadow: var(--shadow-device); }
.frame img, .frame video { width: 100%; height: 100%; object-fit: cover; object-position: top; }
.frame.browser { aspect-ratio: 4 / 3; border-radius: 10px; border: 3px solid #1C1C28; border-top-width: 14px; }
.frame.browser::before { content: ""; position: absolute; top: -10px; left: 8px; width: 24px; height: 5px; border-radius: 5px; background: repeating-linear-gradient(90deg, #5a5a70 0 5px, transparent 5px 9px); }
.frame.browser .win { position: absolute; inset: 0; overflow: hidden; background: #fff; container-type: size; }
.frame.browser .win img { width: 100%; height: auto; }
.card.is-active .frame.browser .win img { animation: page-scroll 16s var(--ease-io) infinite alternate; }
.frame.phone { aspect-ratio: 9 / 19; border-radius: 20px; border: 5px solid #1C1C28; }
.rail-nav { display: flex; align-items: center; gap: 14px; justify-content: center; font-size: 13px; color: var(--muted); }
.rail-count { font-weight: 800; letter-spacing: .1em; font-variant-numeric: tabular-nums; }
.rail-count b { color: var(--ink); }
.rail-dots { display: flex; gap: 6px; }
.rail-dots i { width: 8px; height: 8px; border-radius: 4px; background: rgba(10,10,10,.15); transition: width .4s var(--ease-out), background .3s; }
.rail-dots i.is-on { width: 26px; background: var(--brand); }
.rail-hint { font-weight: 600; }

/* ---------- Tous les sites ---------- */
.sites-section { background: var(--surface); padding-top: 0; }
.sites { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(18px, 2.2vw, 28px); }
.site { display: grid; gap: 12px; align-content: start; }
.browser { position: relative; width: 100%; display: block; border-radius: 16px; overflow: hidden; background: #0B0B14; box-shadow: 0 30px 60px -30px rgba(10,10,10,.45); text-align: left; transition: transform .5s var(--ease-out), box-shadow .5s; }
.browser:hover { transform: translateY(-4px); box-shadow: 0 40px 70px -30px rgba(0,5,248,.4); }
.browser .bar { display: flex; align-items: center; gap: 6px; height: 34px; padding: 0 14px; background: #1C1C28; }
.browser .bar i { width: 9px; height: 9px; border-radius: 50%; background: #3a3a50; }
.browser .bar i:first-child { background: #ff5f57; } .browser .bar i:nth-child(2) { background: #febc2e; } .browser .bar i:nth-child(3) { background: #28c840; }
.browser .bar em { margin-left: 10px; flex: 1; font-style: normal; font-size: 12px; font-weight: 600; color: rgba(255,255,255,.55); background: rgba(255,255,255,.06); border-radius: 6px; padding: 4px 10px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.browser .win { display: block; aspect-ratio: 16 / 10.5; overflow: hidden; container-type: size; position: relative; }
.browser .win img { width: 100%; height: auto; transition: transform 1s var(--ease-io); }
.hover-scroll:hover .win img { transform: translateY(calc(-100% + 100cqh)); transition: transform 12s linear; }
/* L'apercu mene directement au site en ligne : le calque qui apparait au survol
   dit ou l'on va, la fenetre entiere est cliquable. */
.browser .visit { position: absolute; right: 12px; bottom: 12px; z-index: 2; display: inline-flex; align-items: center; gap: 7px; padding: 8px 14px; border-radius: 999px; background: var(--brand); color: #fff; font-size: 12.5px; font-weight: 700; opacity: 0; transform: translateY(6px); transition: opacity .3s, transform .4s var(--ease-out); }
.browser .visit svg { width: 13px; height: 13px; }
.browser:hover .visit, .browser:focus-visible .visit { opacity: 1; transform: none; }
/* Le titre, le sous-titre et les deux actions s'empilent : plus rien a comprimer
   ni a faire deborder sur petit ecran, contrairement a l'ancienne ligne en flex. */
.site-meta { display: grid; gap: 2px; padding: 0 2px; }
.site-meta h3 { font-size: 17px; font-weight: 700; letter-spacing: -.01em; }
.site-meta p { font-size: 13px; color: var(--muted); }
.site-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 18px; margin-top: 9px; }
.site-link {
  font: inherit; font-size: 13px; font-weight: 700; color: var(--brand); background: none; border: 0; padding: 0 0 2px;
  cursor: pointer; display: inline-flex; align-items: center; gap: 6px; border-bottom: 1.5px solid rgba(0,5,248,.2); transition: border-color .25s, color .25s;
}
.site-link:hover { border-color: var(--brand); }
.site-link svg { width: 11px; height: 11px; }
.soon { font-size: 13px; font-weight: 700; color: var(--muted); }

/* Carte d'appel « Votre entreprise ? » : meme famille visuelle que les cartes de
   site, posee sur toute la derniere rangee pour ne pas laisser de trou. */
.site-cta { grid-column: 1 / -1; }
.cta-card {
  display: grid; grid-template-columns: minmax(0, 300px) 1fr auto; align-items: center; gap: clamp(18px, 3vw, 40px);
  padding: 14px 24px 14px 14px; border-radius: 18px; background: #fff; border: 1.5px solid var(--line);
  transition: border-color .35s, transform .5s var(--ease-out), box-shadow .5s;
}
.cta-card:hover { border-color: var(--brand); transform: translateY(-3px); box-shadow: 0 30px 60px -35px rgba(0,5,248,.5); }
.cta-img { display: block; border-radius: 12px; overflow: hidden; background: var(--brand-pale); aspect-ratio: 16 / 10.5; }
.cta-img img { width: 100%; height: 100%; object-fit: cover; display: block; }
.cta-txt { display: grid; gap: 4px; }
.cta-txt b { font-size: clamp(20px, 2.2vw, 26px); font-weight: 800; letter-spacing: -.02em; }
.cta-txt span { font-size: 14px; color: var(--muted); }
.cta-go { display: grid; place-items: center; width: 46px; height: 46px; border-radius: 50%; background: var(--brand); color: #fff; flex: 0 0 auto; transition: transform .4s var(--ease-out); }
.cta-go svg { width: 18px; height: 18px; }
.cta-card:hover .cta-go { transform: translateX(4px); }

/* ---------- Services ---------- */
.services { overflow: hidden; }
.services::before { content: ""; position: absolute; left: -10%; bottom: -30%; width: 60vw; height: 60vw; max-width: 900px; max-height: 900px; border-radius: 50%; background: radial-gradient(circle, rgba(0,5,248,.4), transparent 65%); filter: blur(40px); pointer-events: none; }
.svc { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; position: relative; }
.svc-card { position: relative; display: grid; gap: 14px; align-content: start; padding: 28px; border-radius: var(--radius); background: rgba(255,255,255,.04); border: 1px solid var(--line-dark); transition: background .3s, border-color .3s, transform .5s var(--ease-out); }
.svc-card:hover { background: rgba(255,255,255,.07); border-color: rgba(77,81,255,.55); transform: translateY(-4px); }
.svc-card.is-lead { grid-row: span 2; background: linear-gradient(160deg, rgba(0,5,248,.9), rgba(0,0,204,.75)); border-color: transparent; box-shadow: var(--shadow-brand); }
.svc-card.is-lead:hover { background: linear-gradient(160deg, rgba(0,5,248,1), rgba(0,0,204,.9)); }
.svc-card.is-lead .svc-ic { background: rgba(255,255,255,.14); color: #fff; }
.svc-card.is-lead h3 { font-family: var(--font-display); font-size: clamp(30px, 3vw, 44px); font-weight: 500; margin-top: auto; }
.svc-card.is-lead p { color: rgba(255,255,255,.85); font-size: 16px; }
.svc-ic { width: 46px; height: 46px; border-radius: 14px; display: grid; place-items: center; background: rgba(77,81,255,.14); color: var(--brand-light); }
.svc-ic svg { width: 22px; height: 22px; }
.svc-card h3 { font-size: 20px; font-weight: 700; letter-spacing: -.01em; }
.svc-card p { color: var(--muted-dark); font-size: 15px; }
/* Les tuiles ne portent plus de chiffre : elles renvoient au seul endroit
   ou les tarifs sont ecrits, pour ne pas dire deux fois le meme prix. */
.svc-more { margin-top: auto; padding-top: 8px; display: inline-flex; align-items: center; gap: 7px; font-size: 14px; font-weight: 700; color: #fff; }
.svc-more svg { width: 15px; height: 15px; transition: transform .35s var(--ease-out); }
.svc-more:hover svg { transform: translateX(4px); }
.svc-card.is-lead .svc-more { color: #fff; }
/* Bandeau de cloture : la section s'arretait sur la derniere carte, sans rien dire
   de l'engagement ni ou aller ensuite. */
.svc-foot {
  position: relative; margin-top: clamp(28px, 3.4vw, 44px); padding: clamp(24px, 3vw, 36px);
  border-radius: var(--radius); border: 1px solid var(--line-dark); background: rgba(255,255,255,.04);
  display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(0, .9fr) auto; align-items: center; gap: clamp(20px, 3vw, 44px);
}
.svc-foot-txt { display: grid; gap: 8px; }
.svc-foot-txt p { color: var(--muted-dark); font-size: 15px; }
.svc-foot-proof { display: grid; gap: 10px; font-size: 14px; font-weight: 600; color: rgba(255,255,255,.9); }
.svc-foot-proof li { display: flex; align-items: center; gap: 10px; }
.svc-foot-proof svg { width: 15px; height: 15px; flex: 0 0 auto; color: #4ADE80; }
.svc-foot-ctas { display: grid; gap: 10px; }

/* ---------- Chiffres ---------- */
.stats-section { background: var(--paper); }
.stats { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px; }
.stat { padding: 28px; border-radius: var(--radius); background: #fff; border: 1px solid var(--line); display: grid; gap: 10px; align-content: start; }
.stat b { font-family: var(--font-display); font-size: clamp(44px, 4.6vw, 68px); line-height: 1; color: var(--brand); font-weight: 500; letter-spacing: -.03em; }
.stat span { font-size: 15px; color: var(--muted); }

/* ---------- Prix ----------
   La section portait deux grandes cartes, dix pavés de modules et deux cartes
   « systèmes » : trop de cadres empilés. Tout est ramené à une seule densité,
   des bordures fines et un seul accent de couleur, le bleu de la sélection. */
.prix { background: var(--surface); }
.pricing-top { display: grid; grid-template-columns: 1.15fr 1fr; gap: 16px; align-items: stretch; margin-bottom: 28px; }
.price-card { position: relative; display: grid; gap: 14px; align-content: start; padding: clamp(22px, 2.4vw, 32px); border-radius: var(--radius); background: #fff; border: 1px solid var(--line); }
.price-card.is-hero { background: var(--night); color: #fff; border-color: transparent; overflow: hidden; }
.price-card.is-hero::before { content: ""; position: absolute; right: -20%; top: -40%; width: 70%; aspect-ratio: 1; border-radius: 50%; background: radial-gradient(circle, rgba(0,5,248,.7), transparent 65%); filter: blur(30px); pointer-events: none; }
.price-card > * { position: relative; }
.price-card.is-hero .kicker { color: var(--brand-light); }
.amount { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.amount .num { font-family: var(--font-display); font-size: clamp(40px, 4vw, 58px); line-height: 1; letter-spacing: -.03em; }
.price-card:not(.is-hero) .amount .num { color: var(--brand); }
.amount small { font-size: 13px; font-weight: 600; color: var(--muted); }
.price-card.is-hero .amount small { color: var(--muted-dark); }
.price-card .desc { font-size: 15px; color: var(--muted); }
.price-card.is-hero .desc { color: var(--muted-dark); }
.inc { display: grid; gap: 7px; }
.inc li { display: flex; gap: 10px; align-items: flex-start; font-size: 14px; }
.inc svg { width: 15px; height: 15px; flex: 0 0 auto; margin-top: 4px; color: var(--brand); }
.price-card.is-hero .inc svg { color: #4ADE80; }
.price-card .foot { font-size: 12px; color: var(--muted-dark); }
.price-card .row { margin-top: auto; display: grid; gap: 8px; justify-items: start; }
.price-card:not(.is-hero) > .btn { justify-self: start; margin-top: auto; }

.composer { display: grid; grid-template-columns: minmax(0, 1fr) minmax(260px, 290px); gap: 22px; align-items: start; }

/* Un seul panneau blanc plutot qu'une mosaique de cartes : les lignes se
   suivent, separees par un simple filet, et trois intertitres disent a quoi
   chaque groupe sert. */
.modules { background: #fff; border: 1px solid var(--line); border-radius: var(--radius); padding: 8px 22px 18px; }
.module-head { padding: 16px 0 6px; display: grid; gap: 4px; }
.module-head h3 { font-family: var(--font-display); font-size: clamp(21px, 2vw, 27px); font-weight: 500; }
.module-head p { color: var(--muted); font-size: 14px; max-width: 52ch; }
/* La promesse « ca n'engage a rien » est affichee, pas sous-entendue. */
.mod-group {
  margin: 18px 0 2px; font-size: 11px; font-weight: 800; letter-spacing: .14em; text-transform: uppercase;
  color: var(--brand); border-top: 1px solid var(--line); padding-top: 16px;
}

/* Une ligne de module : le nom et le prix sur la meme ligne, la phrase
   d'explication dessous, sans encadrement lourd. */
.module {
  position: relative; display: grid; grid-template-columns: 1fr auto; grid-template-areas: "name tarif" "desc desc";
  column-gap: 14px; row-gap: 3px; padding: 12px 12px 13px; margin: 0 -12px; border-radius: 12px;
  cursor: pointer; transition: background-color .2s;
}
.module + .module { box-shadow: inset 0 1px 0 var(--line); }
.module:hover { background: var(--surface); }
.module input { position: absolute; opacity: 0; pointer-events: none; }
.module .name { grid-area: name; font-weight: 700; font-size: 15px; display: flex; align-items: center; gap: 10px; }
.module .name::before {
  content: ""; width: 18px; height: 18px; flex: 0 0 auto; border-radius: 6px; border: 1.5px solid var(--line);
  background: no-repeat center / 11px url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'><path d='m5 13 4 4L19 7'/></svg>");
  background-color: transparent; transition: background-color .2s, border-color .2s;
}
.module .name .alt { font-weight: 600; font-size: 12px; color: var(--muted); }
.module .desc { grid-area: desc; font-size: 13px; line-height: 1.45; color: var(--muted); padding-left: 28px; }
.module .tarif { grid-area: tarif; font-weight: 800; font-size: 16px; letter-spacing: -.02em; white-space: nowrap; }
.module .tarif small { font-size: 11px; font-weight: 600; color: var(--muted); margin-left: 3px; }
.module .check { display: none; }
.module:has(input:checked) { background: var(--brand-pale); box-shadow: none; }
.module:has(input:checked) + .module, .module:has(input:checked) + .addon { box-shadow: none; }
.module:has(input:checked) .name::before { background-color: var(--brand); border-color: var(--brand); }
.module:has(input:checked) .tarif { color: var(--brand); }
.module:has(input:focus-visible) { outline: 3px solid var(--brand-light); outline-offset: 2px; }

/* Le referencement suivi n'est pas une ligne a part : c'est une option de la
   mise a jour, decalee sous elle et sans filet. */
.addon {
  display: grid; grid-template-columns: 1fr auto; align-items: center; column-gap: 12px;
  margin: 2px 0 4px 28px; padding: 9px 12px; border-radius: 10px; background: var(--surface);
  cursor: pointer; transition: background-color .2s;
}
.addon[hidden] { display: none; }
.addon:hover { background: var(--brand-pale); }
.addon input { position: absolute; opacity: 0; pointer-events: none; }
.addon .name { display: flex; align-items: center; gap: 10px; font-size: 13px; color: var(--ink); }
.addon .name::before {
  content: ""; width: 15px; height: 15px; flex: 0 0 auto; border-radius: 5px; border: 1.5px solid var(--line);
  background: no-repeat center / 9px url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'><path d='m5 13 4 4L19 7'/></svg>");
  background-color: transparent; transition: background-color .2s, border-color .2s;
}
.addon .tarif { font-weight: 700; font-size: 13px; white-space: nowrap; color: var(--ink); }
.addon .tarif small { font-size: 10px; font-weight: 600; margin-left: 3px; }
.addon:has(input:checked) { background: var(--brand-pale); }
.addon:has(input:checked) .name, .addon:has(input:checked) .tarif { color: var(--brand); }
.addon:has(input:checked) .name::before { background-color: var(--brand); border-color: var(--brand); }
.addon:has(input:focus-visible) { outline: 3px solid var(--brand-light); outline-offset: 2px; }

.total { position: sticky; top: calc(var(--nav-h) + 16px); display: grid; gap: 10px; padding: 20px; border-radius: var(--radius); background: var(--ink); color: #fff; }
.total .kicker { color: var(--muted-dark); }
.total .big { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.total .big #tot { font-family: var(--font-display); font-size: clamp(36px, 3.2vw, 46px); line-height: 1; letter-spacing: -.03em; }
.total .big small { font-size: 13px; color: var(--muted-dark); font-weight: 600; }
.total .strike { font-size: 17px; color: var(--muted-dark); text-decoration: line-through; align-self: center; }
.total .lines { display: grid; gap: 5px; font-size: 13px; }
.total .lines li { display: flex; justify-content: space-between; gap: 12px; padding-bottom: 5px; border-bottom: 1px solid var(--line-dark); }
.total .lines li.empty { color: var(--muted-dark); border: 0; }
.total .lines li.discount { color: #4ADE80; font-weight: 700; }
.total .hint { font-size: 12px; color: var(--muted-dark); }
.total .hint.is-free { color: #4ADE80; font-weight: 600; }
.plan-free { font-size: 12px; color: var(--muted-dark); margin-top: 2px; }
.total .btn { width: 100%; }
/* Tant que rien n'est coche, le bouton reste present mais discret. */
.total .btn.is-empty { background: rgba(255,255,255,.12); color: #fff; }
.total .btn.is-empty:hover { background: rgba(255,255,255,.2); }

/* Les deux offres sur devis tiennent en une bande, pas en deux grandes cartes. */
.systems { display: grid; grid-template-columns: 1fr 1fr; gap: 0; margin-top: 24px; border: 1px solid var(--line); border-radius: var(--radius); background: #fff; overflow: hidden; }
.system-card { display: grid; gap: 8px; align-content: start; padding: clamp(20px, 2.2vw, 28px); }
.system-card + .system-card { border-left: 1px solid var(--line); }
.system-card h3 { font-size: 17px; font-weight: 700; letter-spacing: -.01em; font-family: var(--font-body); }
.system-card p { color: var(--muted); font-size: 14px; }
.tag-price { font-weight: 800; font-size: 15px; }
.tag-price small { font-size: 12px; font-weight: 600; color: var(--muted); }

/* ---------- Méthode ---------- */
.process { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px; position: relative; }
.pstep { position: relative; display: grid; gap: 10px; align-content: start; padding: 28px; border-radius: var(--radius); background: #fff; border: 1px solid var(--line); }
.pstep .n { width: 44px; height: 44px; border-radius: 50%; display: grid; place-items: center; background: var(--brand); color: #fff; font-weight: 800; font-size: 16px; margin-bottom: 6px; }
.pstep .when { font-size: 12px; font-weight: 800; letter-spacing: .12em; text-transform: uppercase; color: var(--brand); }
.pstep h3 { font-size: 20px; font-weight: 700; letter-spacing: -.01em; }
.pstep p { font-size: 15px; color: var(--muted); }

/* ---------- Nils ---------- */
.nils { background: var(--paper); }
.about { display: grid; grid-template-columns: minmax(0, .8fr) minmax(0, 1.2fr); gap: clamp(32px, 5vw, 80px); align-items: center; }
.portrait { position: relative; border-radius: var(--radius-lg); overflow: hidden; aspect-ratio: 4 / 5; box-shadow: var(--shadow-soft); }
.portrait img {
  /* L'image porte elle-meme son rapport de forme et une hauteur automatique.
     Une image en `height: 100%` a l'interieur d'un bloc dont la hauteur ne vient
     que d'un `aspect-ratio` s'effondre a zero sur Safari iOS : la photo de Nils
     disparaissait sur son telephone alors qu'elle etait bien chargee
     (Nils, 2026-09-05 : « ma photo a disparu ? »). Ici la hauteur vient de
     l'image, donc plus rien ne peut s'effondrer. */
  display: block; width: 100%; height: auto; aspect-ratio: 4 / 5; object-fit: cover;
}
.portrait .badge { position: absolute; left: 16px; bottom: 16px; display: inline-flex; align-items: center; gap: 10px; padding: 8px 14px 8px 8px; border-radius: 999px; background: rgba(250,250,248,.92); backdrop-filter: blur(8px); font-size: 13px; font-weight: 700; }
.portrait .badge img { width: 28px; height: 28px; border-radius: 50%; }
.portrait .badge .flag { width: 18px; height: 12px; border-radius: 2px; }
.about-copy { display: grid; gap: 20px; }
.about-copy > p { color: var(--muted); max-width: 60ch; }
.about-copy .quote { font-family: var(--font-display); font-size: clamp(22px, 2.2vw, 30px); line-height: 1.3; color: var(--ink); font-style: italic; max-width: 30ch; }
.about-facts { display: flex; flex-wrap: wrap; gap: 28px; padding: 18px 0; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.about-facts li { display: grid; gap: 2px; }
.about-facts b { font-family: var(--font-display); font-size: 32px; color: var(--brand); line-height: 1; font-weight: 500; }
.about-facts span { font-size: 13px; color: var(--muted); font-weight: 600; }

/* ---------- FAQ ---------- */
.faq { background: var(--surface); }
.faq-grid { display: grid; grid-template-columns: minmax(0, .8fr) minmax(0, 1.2fr); gap: clamp(32px, 5vw, 80px); align-items: start; }
.faq-side { display: grid; gap: 18px; position: sticky; top: calc(var(--nav-h) + 24px); }
.faq-list { display: grid; gap: 10px; }
.faq-list details { border-radius: 18px; background: #fff; border: 1px solid var(--line); transition: border-color .3s; }
.faq-list details[open] { border-color: rgba(0,5,248,.35); }
.faq-list summary { list-style: none; cursor: pointer; display: flex; justify-content: space-between; align-items: center; gap: 16px; padding: 20px 22px; font-weight: 700; font-size: 17px; }
.faq-list summary::-webkit-details-marker { display: none; }
.plus { position: relative; width: 26px; height: 26px; flex: 0 0 auto; border-radius: 50%; border: 1.5px solid var(--line); transition: transform .4s var(--ease-out), background .3s, border-color .3s; }
.plus::before, .plus::after { content: ""; position: absolute; left: 50%; top: 50%; width: 10px; height: 1.5px; background: currentColor; transform: translate(-50%, -50%); }
.plus::after { transform: translate(-50%, -50%) rotate(90deg); }
details[open] .plus { transform: rotate(45deg); background: var(--brand); border-color: var(--brand); color: #fff; }
.answer { padding: 0 22px 22px; color: var(--muted); font-size: 15px; line-height: 1.65; max-width: 70ch; }

/* ---------- Contact ---------- */
.contact { overflow: hidden; }
.contact::before { content: ""; position: absolute; right: -10%; top: -20%; width: 60vw; height: 60vw; max-width: 900px; max-height: 900px; border-radius: 50%; background: radial-gradient(circle, rgba(0,5,248,.45), transparent 65%); filter: blur(40px); pointer-events: none; }
.contact-grid { position: relative; display: grid; grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr); gap: clamp(32px, 5vw, 80px); align-items: start; }
.contact-copy { display: grid; gap: 22px; }
.contact-ways { display: grid; gap: 8px; margin-top: 8px; }
.way { display: grid; grid-template-columns: 48px 1fr; align-items: center; gap: 16px; padding: 14px 16px; border-radius: 18px; border: 1px solid var(--line-dark); background: rgba(255,255,255,.03); transition: background .3s, border-color .3s, transform .4s var(--ease-out); }
.way:hover { background: rgba(255,255,255,.07); border-color: rgba(77,81,255,.6); transform: translateX(4px); }
.way .ic { width: 48px; height: 48px; border-radius: 14px; display: grid; place-items: center; background: rgba(77,81,255,.16); color: var(--brand-light); }
.way .ic svg { width: 22px; height: 22px; }
.way-text { display: grid; gap: 2px; min-width: 0; }
.way-text b { font-size: 16px; font-weight: 800; overflow-wrap: anywhere; }
.way-sub { font-size: 13px; color: var(--muted-dark); }

.form { display: grid; gap: 16px; padding: clamp(24px, 3vw, 40px); border-radius: var(--radius-lg); background: #fff; color: var(--ink); box-shadow: 0 50px 100px -40px rgba(0,0,0,.6); position: relative; }
.form > h3 { font-family: var(--font-display); font-size: clamp(26px, 2.6vw, 36px); font-weight: 500; }
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.field { display: grid; gap: 8px; }
.field label, .field .label { font-size: 13px; font-weight: 700; letter-spacing: .02em; }
.field .opt { font-weight: 500; color: var(--muted); }
.field input, .field textarea { width: 100%; font: inherit; font-size: 16px; padding: 14px 16px; border-radius: 14px; border: 1.5px solid var(--line); background: var(--paper); color: var(--ink); transition: border-color .25s, box-shadow .25s; }
.field input:focus, .field textarea:focus { outline: 0; border-color: var(--brand); box-shadow: 0 0 0 4px rgba(0,5,248,.12); }
.field input.is-invalid, .field textarea.is-invalid { border-color: #DC2626; }
.field textarea { min-height: 110px; resize: vertical; }
/* Cinq cartes de choix a la place des quatorze pastilles : une seule intention se
   coche, chacune dit en une ligne ce qu'elle recouvre. */
/* `grid-auto-rows: 1fr` egalise toutes les rangees : sans lui, une case dont le
   texte passe sur deux lignes etait plus haute que ses voisines, et l'alignement
   sautait selon la largeur de l'ecran (Nils, 2026-09-05). Le label devient une
   grille pour que sa boite interieure remplisse toute la case. */
.wants { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; grid-auto-rows: 1fr; }
.want { position: relative; cursor: pointer; display: grid; }
.want.is-wide { grid-column: 1 / -1; }
.want input { position: absolute; opacity: 0; pointer-events: none; }
.want-in { display: grid; gap: 3px; padding: 14px 16px; border-radius: 16px; background: #fff; border: 1.5px solid var(--line); transition: border-color .25s, box-shadow .25s, transform .25s var(--ease-out); }
.want-in b { font-size: 15px; font-weight: 700; letter-spacing: -.01em; }
.want-in em { font-style: normal; font-size: 13px; line-height: 1.35; color: var(--muted); }
.want:hover .want-in { border-color: var(--brand-light); transform: translateY(-2px); box-shadow: var(--shadow-soft); }
.want input:checked + .want-in { border-color: var(--brand); box-shadow: inset 0 0 0 1px var(--brand); }
.want input:checked + .want-in b { color: var(--brand); }
.want input:focus-visible + .want-in { outline: 3px solid var(--brand-light); outline-offset: 2px; }
.consent { display: flex; gap: 12px; align-items: flex-start; font-size: 13px; color: var(--muted); }
.consent input { margin-top: 3px; width: 18px; height: 18px; flex: 0 0 auto; accent-color: var(--brand); }
.consent a { text-decoration: underline; }
.form > .btn { justify-self: start; }
.form-status { font-size: 14px; font-weight: 600; min-height: 1em; }
.form-status.is-error { color: #DC2626; }
/* Le message de reception remplace le formulaire au lieu de se poser par-dessus :
   en couvrant un formulaire de 1 000 pixels de haut, il laissait un immense
   rectangle blanc vide autour de trois lignes de texte. */
.form-ok { display: none; border-radius: inherit; background: #fff; padding: clamp(30px, 3.4vw, 52px) clamp(20px, 2.6vw, 40px); justify-items: center; text-align: center; gap: 16px; }
.form-ok h3 { font-size: clamp(30px, 3vw, 44px); }
.form-ok p { color: var(--muted); max-width: 42ch; margin-inline: auto; }
.form.is-sent > *:not(.form-ok) { display: none; }
.form.is-sent .form-ok { display: grid; }
.ok-mark { display: grid; place-items: center; width: 62px; height: 62px; margin-bottom: 2px; }
.ok-mark svg { width: 100%; height: 100%; fill: none; stroke: var(--brand); stroke-width: 2.5; stroke-linecap: round; stroke-linejoin: round; }
.ok-mark circle { stroke: var(--brand-pale); stroke-width: 3; stroke-dasharray: 126; stroke-dashoffset: 126; animation: ok-draw .8s var(--ease-io) forwards; }
.ok-mark path { stroke-dasharray: 30; stroke-dashoffset: 30; animation: ok-draw .5s var(--ease-io) .5s forwards; }
@keyframes ok-draw { to { stroke-dashoffset: 0; } }
.ok-ways { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; margin-top: 8px; }
/* Le formulaire est blanc a l'interieur d'une section sombre : sans cette reprise,
   le bouton clair heritait du texte blanc de la section et devenait invisible. */
.form .btn-ghost { border-color: var(--line); color: var(--ink); background: rgba(255,255,255,.55); }
.form .btn-ghost:hover { border-color: var(--ink); background: #fff; }

.plan-box { display: grid; gap: 8px; padding: 16px 18px; border-radius: 18px; background: var(--brand-pale); border: 1.5px solid rgba(0,5,248,.25); }
.plan-box.is-flash { animation: flash .9s var(--ease-out); }
@keyframes flash { from { box-shadow: 0 0 0 6px rgba(0,5,248,.25); } to { box-shadow: 0 0 0 0 rgba(0,5,248,0); } }
.plan-head { display: flex; justify-content: space-between; align-items: center; }
.plan-head .kicker { color: var(--brand); }
.plan-clear { font-size: 13px; font-weight: 700; color: var(--muted); text-decoration: underline; }
.plan-name { font-weight: 800; font-size: 17px; }
.plan-detail { font-size: 14px; color: var(--muted); }
.plan-mode { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 4px; }
.plan-mode label { position: relative; display: inline-flex; align-items: center; gap: 8px; padding: 8px 12px; border-radius: 999px; background: #fff; border: 1.5px solid var(--line); font-size: 13px; font-weight: 700; cursor: pointer; }
.plan-mode input { position: absolute; opacity: 0; pointer-events: none; }
.plan-mode label:has(input:checked) { border-color: var(--brand); color: var(--brand); }
.plan-mode label::before { content: ""; width: 10px; height: 10px; border-radius: 50%; border: 1.5px solid var(--line); }
.plan-mode label:has(input:checked)::before { background: var(--brand); border-color: var(--brand); }

/* ---------- Footer ----------
   L'ancien pied de page enchainait un logo, un numero et quatre colonnes de liens,
   sans rien qui rassure. Il s'ouvre maintenant sur une derniere invitation, puis
   sur les quatre preuves que l'entreprise existe vraiment. */
.footer { background: var(--night); color: #fff; padding: 0 0 32px; border-top: 1px solid var(--line-dark); }
.footer-call-band {
  display: grid; grid-template-columns: minmax(0, 1.2fr) auto; align-items: center; gap: clamp(24px, 4vw, 60px);
  padding: clamp(36px, 4.6vw, 60px) 0 clamp(32px, 4vw, 48px);
}
.footer-call-txt { display: grid; gap: 10px; }
.footer-call-txt .eyebrow { color: var(--brand-light); }
.footer-call-txt .display { font-family: var(--font-display); font-size: clamp(26px, 3.2vw, 42px); font-weight: 500; line-height: 1.12; letter-spacing: -.02em; }
.footer-call-txt .display em { font-style: italic; color: var(--brand-light); }
.footer-call-sub { font-size: 15px; color: var(--muted-dark); max-width: 46ch; }
.footer-call-actions { display: grid; gap: 12px; justify-items: stretch; }
.footer-call { display: inline-flex; align-items: center; gap: 14px; padding: 10px 20px 10px 10px; border-radius: 999px; border: 1px solid var(--line-dark); transition: border-color .3s, background .3s; }
.footer-call:hover { border-color: var(--brand-light); background: rgba(255,255,255,.04); }
.footer-call.is-wa svg { background: #25D366; color: var(--night); }
.footer-call.is-wa:hover { border-color: #25D366; }
.footer-call svg { width: 36px; height: 36px; padding: 10px; border-radius: 50%; background: var(--brand); flex: 0 0 auto; }
.footer-call span { display: grid; }
.footer-call b { font-size: 16px; font-variant-numeric: tabular-nums; }
.footer-call small { font-size: 12px; color: var(--muted-dark); }

.footer-trust {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1px;
  background: var(--line-dark); border: 1px solid var(--line-dark); border-radius: var(--radius); overflow: hidden;
}
.footer-trust li { display: flex; align-items: flex-start; gap: 12px; padding: 20px; background: var(--night); }
.footer-trust svg { width: 17px; height: 17px; flex: 0 0 auto; margin-top: 2px; color: #4ADE80; }
.footer-trust .flag { width: 20px; height: 14px; border-radius: 2px; color: inherit; margin-top: 3px; }
.footer-trust span { display: grid; gap: 3px; font-size: 13px; color: var(--muted-dark); line-height: 1.4; }
.footer-trust b { font-size: 14px; color: #fff; font-weight: 700; }

.footer-grid { display: grid; grid-template-columns: 1.7fr 1fr 1fr 1fr; gap: 32px; padding: clamp(36px, 4vw, 54px) 0; }
.footer-brand { display: grid; gap: 14px; font-size: 14px; color: var(--muted-dark); max-width: 40ch; align-content: start; }
.footer-logo { height: 24px; width: auto; justify-self: start; }
.footer-adr { font-size: 13px; }
/* Trois pastilles rondes, comme en V1 : les reseaux se reconnaissent a l'icone,
   et WhatsApp reprend sa place a cote d'Instagram et de Facebook. */
.footer-social { display: flex; gap: 10px; margin-top: 2px; }
.footer-grid .footer-social a { display: grid; place-items: center; width: 40px; height: 40px; border-radius: 50%; background: rgba(255,255,255,.08); color: #fff; transition: background .25s, transform .25s var(--ease-out); }
.footer-grid .footer-social a svg { display: block; width: 19px; height: 19px; }
.footer-grid .footer-social a:hover { background: var(--brand); transform: translateY(-3px); }
.footer-grid .footer-social a.is-wa:hover { background: #25D366; color: var(--night); }
.footer-grid h4 { font-size: 11px; font-weight: 800; letter-spacing: .14em; text-transform: uppercase; color: var(--brand-light); margin-bottom: 12px; }
.footer-grid div > a { display: block; padding: 5px 0; font-size: 14px; color: var(--muted-dark); transition: color .25s, transform .3s var(--ease-out); }
.footer-grid div > a:hover { color: #fff; transform: translateX(3px); }
.footer-bottom { display: flex; justify-content: space-between; align-items: center; gap: 16px; flex-wrap: wrap; padding-top: 26px; border-top: 1px solid var(--line-dark); font-size: 13px; color: var(--muted-dark); }
.footer-up { color: var(--muted-dark); border-bottom: 1px solid transparent; transition: color .25s, border-color .25s; }
.footer-up:hover { color: #fff; border-color: var(--brand-light); }

/* ---------- Barre mobile ---------- */
.mobile-bar { display: none; }

/* ---------- Modales ---------- */
dialog { border: 0; padding: 0; max-width: none; max-height: none; background: transparent; color: var(--ink); }
dialog::backdrop { background: rgba(7,7,26,.82); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); }
.modal { width: min(1120px, 100vw - 32px); margin: auto; }
.modal[open] { animation: modal-in .5s var(--ease-out); }
@keyframes modal-in { from { opacity: 0; transform: translateY(24px) scale(.98); } }
.modal-inner { position: relative; display: grid; gap: 28px; padding: clamp(24px, 3vw, 44px); border-radius: var(--radius-lg); background: var(--paper); max-height: calc(100vh - 32px); max-height: calc(100dvh - 32px); overflow: auto; }
.modal-close { position: fixed; top: 16px; right: 16px; z-index: 5; width: 46px; height: 46px; border-radius: 50%; display: grid; place-items: center; background: var(--ink); color: #fff; transition: transform .4s var(--ease-out), background .25s; }
.modal .modal-close { position: sticky; top: 0; justify-self: end; margin-bottom: -46px; }
.modal-close svg { width: 20px; height: 20px; }
.modal-close:hover { transform: rotate(90deg); background: var(--brand); }
.modal-head { display: grid; gap: 10px; max-width: 760px; }
.modal-head h3 { font-size: clamp(28px, 3.4vw, 46px); }
.modal-place { font-size: 14px; font-weight: 700; color: var(--muted); }
.modal-body { display: grid; grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr); gap: 32px; align-items: start; }
.modal-text { display: grid; gap: 18px; }
.modal-text > p { color: var(--muted); line-height: 1.65; }
.modal-facts { display: flex; flex-wrap: wrap; gap: 8px; }
.modal-facts li { padding: 8px 12px; border-radius: 999px; background: #fff; border: 1px solid var(--line); font-size: 13px; font-weight: 600; }
.modal-facts li b { color: var(--brand); margin-right: 4px; }
.modal-delivered { display: grid; gap: 8px; }
.modal-delivered li { display: flex; gap: 10px; align-items: flex-start; font-size: 15px; }
.modal-delivered li::before { content: ""; width: 16px; height: 16px; flex: 0 0 auto; margin-top: 4px; border-radius: 50%; background: var(--brand) url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20 6 9 17l-5-5' fill='none' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/></svg>") center / 10px no-repeat; }
.modal-gallery { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; align-items: start; }
.g-item { position: relative; border-radius: 14px; overflow: hidden; background: #0B0B14; box-shadow: var(--shadow-soft); text-align: left; transition: transform .4s var(--ease-out); display: block; width: 100%; }
.g-item:hover { transform: translateY(-3px); }
.g-item img, .g-item video { width: 100%; height: 100%; object-fit: cover; object-position: top; }
.g-item.is-wide { grid-column: span 2; aspect-ratio: 16 / 9; }
.g-item figcaption { position: absolute; left: 0; right: 0; bottom: 0; padding: 26px 12px 10px; font-size: 12px; font-weight: 700; color: #fff; background: linear-gradient(transparent, rgba(7,7,26,.85)); }
.g-item .play { position: absolute; left: 50%; top: 50%; width: 46px; height: 46px; border-radius: 50%; background: rgba(250,250,248,.92); color: var(--brand); display: grid; place-items: center; transform: translate(-50%, -50%); }
.g-item .play svg { width: 20px; height: 20px; margin-left: 2px; }

.zoom { width: 100vw; height: 100vh; height: 100dvh; margin: 0; display: none; grid-template-rows: 1fr auto; place-items: center; gap: 14px; padding: 60px 16px 24px; background: transparent; }
.zoom[open] { display: grid; }
.zoom::backdrop { background: #07071A; }
/* Visionneuse : le site d un client s ouvre par-dessus le notre, dans un cadre,
   avec toujours la porte de sortie vers un vrai onglet. */
.siteview { width: min(1280px, 100vw - 24px); max-width: none; height: calc(100dvh - 40px); padding: 0; border: 0; border-radius: 18px; overflow: hidden; background: var(--night); color: #fff; box-shadow: 0 40px 100px rgba(0,0,0,.5); }
.siteview::backdrop { background: rgba(7,7,26,.78); backdrop-filter: blur(4px); }
.sv-bar { display: flex; align-items: center; gap: 12px; padding: 10px 12px 10px 18px; border-bottom: 1px solid rgba(255,255,255,.12); }
.sv-name { font-weight: 800; font-size: 15px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sv-url { flex: 1; min-width: 0; font-size: 12.5px; color: rgba(255,255,255,.55); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sv-out { display: inline-flex; align-items: center; gap: 7px; padding: 9px 14px; border-radius: 999px; background: var(--brand); color: #fff; font-size: 13.5px; font-weight: 700; white-space: nowrap; }
.sv-out svg { width: 14px; height: 14px; }
.sv-out:hover { background: var(--brand-light, #4D51FF); }
.sv-close { display: grid; place-items: center; width: 38px; height: 38px; border: 0; border-radius: 50%; background: rgba(255,255,255,.1); color: #fff; cursor: pointer; }
.sv-close svg { width: 18px; height: 18px; }
.sv-close:hover { background: rgba(255,255,255,.2); }
.sv-frame { position: relative; height: calc(100% - 59px); background: #fff; }
.sv-frame iframe { width: 100%; height: 100%; border: 0; display: block; }
.sv-note { position: absolute; left: 50%; bottom: 22px; transform: translateX(-50%); margin: 0; padding: 11px 16px; border-radius: 12px; background: rgba(7,7,26,.92); color: #fff; font-size: 13.5px; text-align: center; max-width: calc(100% - 32px); }

.zoom-body { max-width: min(1200px, 100vw - 32px); max-height: calc(100vh - 130px); max-height: calc(100dvh - 130px); overflow: auto; border-radius: 12px; box-shadow: 0 40px 100px rgba(0,0,0,.6); scrollbar-width: thin; scrollbar-color: rgba(255,255,255,.4) transparent; }
.zoom-body img { width: min(1200px, 100vw - 32px); height: auto; }
.zoom-body.is-portrait img, .zoom-body video { width: auto; max-width: min(92vw, 520px); max-height: calc(100vh - 130px); max-height: calc(100dvh - 130px); }
.zoom-body.is-video { border-radius: 26px; background: #000; }
.zoom-cap { color: rgba(255,255,255,.75); font-size: 14px; font-weight: 600; text-align: center; padding: 0 16px; }
.zoom-cap.is-long::after { content: " · faites défiler pour voir la page entière"; color: rgba(255,255,255,.45); font-weight: 500; }

/* ---------- Reveal ---------- */
html.js .reveal { opacity: 0; transform: translateY(18px); transition: opacity .8s var(--ease-out), transform 1s var(--ease-out); transition-delay: var(--d, 0s); }
html.js .reveal.is-in { opacity: 1; transform: none; }
/* ---------- Survols : une seule grammaire pour toutes les cartes ----------
   La carte se leve, son ombre s'ouvre, son titre passe au bleu de la marque et sa
   fleche glisse. C'etait le comportement de la version precedente du site, que
   plusieurs sections avaient perdu. */
.stat, .pstep, .price-card, .system-card, .faq-list details, .site {
  transition: transform .5s var(--ease-out), box-shadow .5s, border-color .35s;
}
.stat:hover, .pstep:hover, .price-card:not(.is-hero):hover, .faq-list details:hover {
  transform: translateY(-4px); box-shadow: 0 34px 60px -34px rgba(0,5,248,.35); border-color: rgba(0,5,248,.35);
}
.price-card.is-hero:hover { transform: translateY(-4px); box-shadow: 0 44px 80px -34px rgba(0,5,248,.6); }
.system-card:hover { background: var(--brand-pale); }
.pstep:hover h3, .stat:hover span, .site:hover .site-meta h3 { color: var(--brand); }
.stat, .pstep, .system-card, .site-meta h3 { transition-property: transform, box-shadow, border-color, color, background; }
.site:hover { transform: translateY(-3px); }
.btn svg, .site-link svg { transition: transform .35s var(--ease-out); }
.btn:hover svg, .site-link:hover svg { transform: translateX(3px); }

/* ---------- Ecran d'envoi du formulaire ----------
   Nils, 2026-09-05 : « le plus important le systeme de contact, on n'a pas le
   droit au bug » et « ajoute un magnifique ecran de chargement [...] si on est
   trop rapide il faut que ca laisse le temps de process mentalement ».
   Le motif du fond est la parallaxe qui donne son nom a la marque : trois plans
   de cartes glissent a trois vitesses, le plus lointain le plus flou. Au centre,
   la maquette du visiteur se dessine avec SES informations, ce qui rend l'attente
   utile au lieu de la meubler. La derniere etape n'apparait qu'apres la reponse
   reelle du serveur : l'ecran ne promet jamais un envoi qui n'a pas eu lieu. */
.sending {
  position: fixed; inset: 0; z-index: 900; display: grid; place-items: center;
  padding: var(--pad); overflow: hidden; color: #fff;
  background: radial-gradient(120% 90% at 50% 8%, #12123A 0%, var(--night) 62%, #04040F 100%);
  opacity: 0; transition: opacity .5s var(--ease-out);
}
.sending[hidden] { display: none; }
.sending.is-in { opacity: 1; }
.sending.is-out { opacity: 0; transition-duration: .4s; }

/* Les trois plans du fond. Chacun repete ses cartes deux fois : la bande fait
   200 % de large et se decale de moitie, le raccord est donc invisible. */
.sending-depth { position: absolute; inset: 0; pointer-events: none; }
.sending-band { position: absolute; left: 0; display: flex; gap: 26px; width: max-content; will-change: transform; }
.sending-band i {
  display: block; width: 190px; height: 118px; border-radius: 14px; flex: 0 0 auto;
  background: linear-gradient(150deg, rgba(77,81,255,.22), rgba(255,255,255,.05));
  border: 1px solid rgba(255,255,255,.09);
}
.sending-band:nth-child(1) { top: 8%;  filter: blur(9px); opacity: .17; animation: send-drift 46s linear infinite; }
.sending-band:nth-child(2) { top: 39%; filter: blur(4px); opacity: .13; animation: send-drift 32s linear infinite reverse; }
.sending-band:nth-child(3) { top: 72%; filter: blur(14px); opacity: .20; animation: send-drift 60s linear infinite; }
.sending-band:nth-child(2) i { width: 260px; height: 160px; }
.sending-band:nth-child(3) i { width: 320px; height: 200px; }
@keyframes send-drift { from { transform: translateX(0); } to { transform: translateX(-50%); } }

.sending-stage { position: relative; display: grid; justify-items: center; gap: 22px; width: min(560px, 100%); text-align: center; }
.sending-kicker {
  font-size: 11px; font-weight: 800; letter-spacing: .18em; text-transform: uppercase;
  color: var(--brand-light);
}

/* La maquette. Le cadre se trace, puis chaque bloc se pose a son tour. */
.mock { position: relative; width: 100%; aspect-ratio: 360 / 236; }
.mock-trace { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.mock-trace rect, .mock-trace line { fill: none; stroke: var(--brand-light); stroke-width: 1.5; }
.mock-outline { stroke-dasharray: 1160; stroke-dashoffset: 1160; animation: mock-draw 1.15s var(--ease-io) forwards; }
.mock-rule { stroke-dasharray: 360; stroke-dashoffset: 360; animation: mock-draw .5s var(--ease-io) .9s forwards; opacity: .5; }
@keyframes mock-draw { to { stroke-dashoffset: 0; } }

.mock-body { position: absolute; inset: 0; }
.mock-body > * { position: absolute; opacity: 0; transform: translateY(8px); transition: opacity .6s var(--ease-out), transform .6s var(--ease-out); }
.mock-dots { top: 12px; left: 16px; display: flex; gap: 6px; }
.mock-dots i { width: 7px; height: 7px; border-radius: 50%; background: rgba(255,255,255,.28); }
.mock-url {
  top: 10px; left: 50%; transform: translate(-50%, 8px); padding: 3px 14px; border-radius: 999px;
  background: rgba(255,255,255,.07); font-size: 11px; color: rgba(255,255,255,.55);
}
.mock-title {
  top: 58px; left: 22px; right: 150px; text-align: left;
  font-family: var(--font-display); font-size: 26px; line-height: 1.1; letter-spacing: -.01em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mock-sub {
  top: 94px; left: 22px; right: 150px; text-align: left;
  font-size: 12.5px; line-height: 1.35; color: rgba(255,255,255,.62);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.mock-lines { top: 131px; left: 22px; right: 150px; display: grid; gap: 8px; }
.mock-lines i { height: 5.5px; border-radius: 999px; background: rgba(255,255,255,.15); }
.mock-lines i:last-child { width: 62%; }
.mock-shot {
  top: 52px; right: 22px; width: 112px; height: 96px; border-radius: 10px;
  background: linear-gradient(150deg, rgba(0,5,248,.55), rgba(77,81,255,.18));
  border: 1px solid rgba(255,255,255,.12);
}
.mock-cta { bottom: 30px; left: 22px; width: 108px; height: 26px; border-radius: 999px; background: var(--brand); }
.mock-ghost { bottom: 30px; left: 142px; width: 78px; height: 26px; border-radius: 999px; border: 1px solid rgba(255,255,255,.22); }

.mock.is-s1 .mock-dots, .mock.is-s1 .mock-url { opacity: 1; transform: translateY(0); }
.mock.is-s1 .mock-url { transform: translate(-50%, 0); }
.mock.is-s2 .mock-title, .mock.is-s2 .mock-sub, .mock.is-s2 .mock-lines { opacity: 1; transform: translateY(0); }
.mock.is-s3 .mock-shot, .mock.is-s3 .mock-cta, .mock.is-s3 .mock-ghost { opacity: 1; transform: translateY(0); }
.mock.is-done .mock-trace rect, .mock.is-done .mock-trace line { stroke: rgba(255,255,255,.28); transition: stroke .6s; }
.mock.is-done .mock-shot { background: linear-gradient(150deg, #4D51FF, rgba(0,5,248,.45)); }
/* Un eclat traverse le bloc image tant que l'envoi n'est pas confirme : c'est le
   seul signe qui dit « ca travaille », et il s'arrete des que c'est parti. */
.mock-shot::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit; overflow: hidden;
  background: linear-gradient(105deg, transparent 38%, rgba(255,255,255,.30) 50%, transparent 62%);
  background-size: 260% 100%; animation: mock-sheen 2.1s var(--ease-io) infinite;
}
.mock.is-done .mock-shot::after { animation: none; opacity: 0; }
@keyframes mock-sheen { from { background-position: 130% 0; } to { background-position: -130% 0; } }

/* Le dessin se mesure en pourcentage de SA PROPRE largeur : il garde exactement
   les memes proportions d'un telephone de 320 pixels a un grand ecran, sans
   qu'aucune valeur soit a redire par palier. Les valeurs en pixels ci-dessus
   restent le repli des navigateurs qui ignorent les requetes de conteneur. */
@supports (container-type: inline-size) {
  .mock { container-type: inline-size; }
  .mock-dots { top: 3.33cqw; left: 4.44cqw; gap: 1.67cqw; }
  .mock-dots i { width: 1.94cqw; height: 1.94cqw; }
  .mock-url { top: 2.78cqw; padding: .83cqw 3.89cqw; font-size: 3.06cqw; }
  .mock-title { top: 16.1cqw; left: 6.1cqw; right: 41.7cqw; font-size: 7.22cqw; }
  .mock-sub { top: 26.1cqw; left: 6.1cqw; right: 41.7cqw; font-size: 3.47cqw; }
  .mock-lines { top: 36.4cqw; left: 6.1cqw; right: 41.7cqw; gap: 2.22cqw; }
  .mock-lines i { height: 1.53cqw; }
  .mock-shot { top: 14.4cqw; right: 6.1cqw; width: 31.1cqw; height: 26.7cqw; border-radius: 2.78cqw; }
  .mock-cta { bottom: 8.33cqw; left: 6.1cqw; width: 30cqw; height: 7.22cqw; }
  .mock-ghost { bottom: 8.33cqw; left: 39.4cqw; width: 21.7cqw; height: 7.22cqw; }
}

.sending-step { font-size: 16px; line-height: 1.45; color: rgba(255,255,255,.9); min-height: 2.9em; max-width: 34ch; }
.sending-bar { width: 172px; height: 2px; border-radius: 2px; background: rgba(255,255,255,.14); overflow: hidden; }
.sending-bar span { display: block; height: 100%; width: 0; border-radius: 2px; background: var(--brand-light); transition: width .9s linear; }

@media (prefers-reduced-motion: reduce) {
  html.js .reveal { opacity: 1; transform: none; transition: none; }
  .stat, .pstep, .price-card, .system-card, .faq-list details, .site, .btn svg { transition: none !important; }
  .wall-col, .clients-track { animation: none !important; }
  /* L'ecran d'envoi garde ses etapes ecrites, mais rien ne bouge : ni les plans
     du fond, ni le trace du cadre, qui s'affiche d'un coup. */
  .sending-band { animation: none !important; }
  .mock-outline, .mock-rule { animation: none !important; stroke-dashoffset: 0; }
  .mock-body > *, .sending, .sending-bar span { transition: none !important; }
  .mock-shot::after { animation: none !important; opacity: 0; }
  .ok-mark circle, .ok-mark path { animation: none !important; stroke-dashoffset: 0; }
  .rotator > span { transition: none; }
  .device, .scene, .card, .browser { transition: none !important; }
  .hover-scroll:hover .win img { transition: none; }
  .screen .win img, .frame.browser .win img { animation: none !important; }
}

/* Le numero de telephone disparait de la barre bien avant la bascule mobile :
   entre 960 et 1100 px, logo, liens et bouton depassaient la largeur utile et la
   barre se chevauchait. */
@media (max-width: 1180px) {
  .nav-tel { display: none; }
  .nav-links a { padding: 10px 10px; font-size: 14px; }
}

/* ---------- Tablette ---------- */
@media (max-width: 1100px) {
  .sites { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .svc { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .process { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .footer-grid { grid-template-columns: 1fr 1fr; }
  .footer-trust { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 960px) {
  /* Les carrousels respirent davantage sur le bord gauche que le reste de la
     page : cale a 18 px, la premiere carte paraissait collee au bord. */
  :root { --nav-h: 60px; --bar-h: 80px; --wall-gap: 12px; --rail-pad: 26px; }
  .section { padding: clamp(44px, 9vw, 64px) 0; }
  .nav-links, .nav-cta { display: none; }
  /* Le menu principal disparait sur telephone, donc il ne prend plus de cellule
     dans la grille de la barre : sans cette ligne le bouton du menu se retrouvait
     au milieu de l ecran au lieu de sa place a droite (Nils, 2026-09-05). */
  .nav-inner { grid-template-columns: 1fr auto; }
  .nav-logo { height: 17px; }
  .nav-burger { display: inline-flex; }
  /* Le collage est net sous la barre de navigation : sans ce degrade, le logo
     et le bouton du menu se posaient parfois sur une maquette claire et
     devenaient illisibles. Il s'efface des que la barre prend son propre fond
     au defilement. */
  .nav.is-dark:not(.is-scrolled)::after {
    content: ""; position: absolute; inset: 0 0 auto; z-index: -1; pointer-events: none;
    height: calc(var(--nav-h) + 44px);
    background: linear-gradient(180deg, rgba(7,7,26,.9) 0%, rgba(7,7,26,.66) 46%, rgba(7,7,26,0) 100%); }
  /* --- Premier ecran sur telephone, refait le 2026-09-05 ---
     La bande d images ecrasee sous le texte perdait tout le relief qu elle a sur
     ordinateur. Le mur passe donc EN FOND, bord a bord, avec son plan incline et
     son defilement intacts ; un voile sombre le calme et le texte se pose dessus,
     aligne a gauche. On ouvre sur ce qu on fabrique au lieu d une colonne de texte
  /* --- Premier ecran du telephone, quatrieme version, 2026-09-05 ---
     Nils tranche : « c'etait bien au dessus du wall avec le blur. Le souci
     c'etait la mise en page layout du texte et boutons ». Le collage revient
     donc EN FOND, floute, avec le texte pose dessus : c'est ce qu'il veut.
     Ce qui change est la mise en page du bloc de texte lui-meme, qui etait le
     vrai probleme : un titre qui reservait deux lignes et creusait un trou de
     cinquante pixels sous lui, une phrase de quatre lignes, deux boutons de
     largeurs inegales serres cote a cote a douze points, puis deux preuves sur
     deux lignes et trois etiquettes encadrees sur deux lignes, soit quatre
     rangees de reassurance empilees en bas. */
  .hero { --hero-top: 16px; }
  .hero-grid { display: block; position: relative; padding-bottom: 20px;
    min-height: calc(100svh - var(--nav-h) - var(--hero-top) - 10px); }
  /* --- Cinquieme version, 2026-09-05 : le bloc s'ancre en BAS ---
     La quatrieme version posait tout le texte en haut de l'ecran et laissait
     sous lui un vide flou de pres de quatre cents pixels, soit un bon tiers du
     telephone : c'etait ca, le manque d'harmonie. Le texte descend donc au bas
     de l'ecran, comme le bandeau d'une affiche, et le vide libere remonte en
     haut ou le collage l'occupe deja. Le pouce gagne au passage : les deux
     actions arrivent dans sa zone naturelle. */
  .hero-copy { position: relative; z-index: 2; justify-items: stretch; text-align: left;
    gap: 0; align-content: end;
    padding-top: clamp(70px, 16vh, 150px);
    padding-bottom: clamp(16px, 3.2vh, 34px);
    min-height: calc(100svh - var(--nav-h) - var(--hero-top) - 34px); }
  /* Le rythme vertical n'est plus uniforme : le titre et sa phrase forment un
     bloc serre, l'espace se depense ensuite avant les actions. */
  .hero-copy > .lead { margin-top: clamp(10px, 1.8vh, 16px); }
  .hero-copy > .hero-ctas { margin-top: clamp(18px, 3.4vh, 32px); }
  .hero-copy > .hero-proof { margin-top: clamp(13px, 2.4vh, 20px); }
  .hero-copy > .hero-badges { margin-top: clamp(11px, 2vh, 16px);
    padding-top: clamp(10px, 1.8vh, 15px); border-top: 1px solid rgba(255,255,255,.13); }
  /* Ordre de lecture attendu sur un telephone : le titre, la phrase qui
     l explique, les boutons, les preuves, les etiquettes en dernier. */
  .hero-copy > .h1 { order: 1; }
  .hero-copy > .lead { order: 2; }
  .hero-copy > .hero-ctas { order: 3; }
  .hero-copy > .hero-proof { order: 4; }
  .hero-copy > .hero-badges { order: 5; }
  /* Le voile sombre monte desormais DU BAS, la ou le texte se trouve, et
     s'efface vers le haut pour laisser voir le collage. La quatrieme version
     mettait sa zone la plus opaque au milieu de l'ecran, donc dans le vide. */
  .hero-copy::before {
    content: ""; position: absolute; z-index: -1; pointer-events: none;
    inset: 0 calc(-1 * var(--pad)) calc(-1 * clamp(16px, 3.2vh, 34px)); border-radius: 0;
    background: linear-gradient(to top, rgba(7,7,26,.93) 0px, rgba(7,7,26,.9) 340px, rgba(7,7,26,.8) 430px, rgba(7,7,26,.5) 500px, rgba(7,7,26,0) 570px);
    backdrop-filter: blur(9px) saturate(.85); -webkit-backdrop-filter: blur(9px) saturate(.85);
    -webkit-mask-image: linear-gradient(to top, #000 0px, #000 430px, transparent 570px);
    mask-image: linear-gradient(to top, #000 0px, #000 430px, transparent 570px);
  }
  /* Le titre est calibre pour que la plus longue de ses fins tournantes,
     « prise de rendez-vous. », tienne sur une seule ligne. Sans cela il
     reservait en permanence la hauteur de deux lignes et laissait sous lui un
     trou de cinquante pixels : c'etait le vide du milieu de l'ecran. */
  .hero .h1 { font-size: clamp(28px, 7.9vw, 44px); }
  /* Le collage defile en permanence derriere le texte : aucun reglage de voile
     ne peut garantir la lisibilite, puisque ce qui passe dessous change toutes
     les secondes. Une ombre douce portee par le texte lui-meme la garantit,
     elle, quelle que soit la maquette qui arrive. */
  .hero .h1, .hero .lead, .hero-proof, .hero-badges {
    text-shadow: 0 1px 2px rgba(7,7,26,.55), 0 4px 22px rgba(7,7,26,.85); }
  /* La phrase tient en trois lignes au lieu de quatre. */
  /* La phrase reste calee sur le bord gauche du titre. Sans ces deux lignes,
     des que l'ecran depassait 41 caracteres de large (un grand telephone), la
     grille la recentrait et elle partait en retrait du titre. */
  .hero .lead { font-size: 14px; line-height: 1.5; max-width: 42ch; color: rgba(255,255,255,.92);
    justify-self: start; margin-inline: 0; }
  .lead-plus { display: none; }
  /* --- Les boutons ---
     Cote a cote, ils faisaient deux largeurs inegales, un texte reduit a douze
     points et demi et une fleche supprimee faute de place. Sur un telephone
     chaque action prend donc toute la largeur, l'une sous l'autre, a leur
     taille normale : c'est la disposition que tout le monde attend et le pouce
     n'a plus a viser. */
  /* Cinquieme version : une seule pilule pleine. Deux pastilles de meme
     taille l'une sur l'autre donnaient deux fois le meme poids a deux actions
     qui n'ont pas la meme importance, et pesaient cent quinze pixels a elles
     deux. La demande de maquette garde le bouton ; voir les realisations
     devient un lien souligne, discret, centre dessous. */
  .hero-ctas { display: grid; grid-template-columns: 1fr; width: 100%; gap: 0; }
  .hero-ctas .btn-primary { width: 100%; justify-content: center; white-space: nowrap;
    padding: 16px 16px; font-size: 16px; }
  .hero-ctas .btn-primary svg { display: inline-block; width: 16px; height: 16px; }
  .on-dark .hero-ctas .btn-ghost {
    justify-self: center; width: auto; margin-top: 13px;
    padding: 4px 2px; border: 0; background: none; box-shadow: none;
    font-size: 14.5px; font-weight: 600; color: rgba(255,255,255,.78);
    text-decoration: underline; text-underline-offset: 5px;
    text-decoration-color: rgba(255,255,255,.32); }
  /* --- Les cinq lignes de reassurance ---
     Elles occupaient quatre rangees : deux preuves cochees, puis trois
     etiquettes encadrees qui se cassaient en deux plus une. Les preuves
     passent sur une seule rangee, et les etiquettes perdent leur cadre pour
     devenir une mention discrete : le bas du bloc ne pese plus. */
  /* Les deux preuves tiennent sur UNE seule ligne : le corps du texte suit la
     largeur de l'ecran plutot que de renvoyer la seconde mention en dessous
     (Nils, 2026-09-05 : « il faudrait que ca soit la sur la meme ligne en mode
     mobile »). */
  .hero-proof { display: flex; justify-content: space-between; flex-wrap: nowrap;
    gap: 0 12px; font-size: clamp(9.5px, 2.85vw, 12.5px); }
  .hero-proof li { gap: 5px; min-width: 0; }
  .hero-proof svg { width: 13px; height: 13px; flex: 0 0 auto; }
  /* Les trois mentions tenaient sur deux lignes, la derniere restant seule en
     dessous, et rien ne separait les deux premieres : trois petits textes gris
     se lisaient comme une bouillie (Nils, 2026-09-05). La mention du lieu part,
     puisque la phrase d'accroche dit deja « des Monts du Lyonnais » deux lignes
     plus haut ; les deux qui restent, la disponibilite et le label France Num,
     tiennent sur une ligne des 320 pixels et un point les separe. */
  /* Les deux mentions se rangent aux deux bords, comme les preuves juste au
     dessus : la ligne s'arretait au milieu et paraissait mal posee (Nils,
     2026-09-05 : « c'est mal centre en mode mobile »). Les deux lignes tombent
     desormais exactement sur les memes bords gauche et droit. */
  .hero-badges { justify-content: space-between; flex-wrap: nowrap;
    gap: 0 10px; line-height: 1.45; }
  .hero-badges .chip-lieu { display: none; }
  .hero-badges .chip { font-size: 11px; padding: 0; gap: 5px;
    background: none; border: 0; color: rgba(255,255,255,.55); }
  .hero-badges .chip svg { width: 11px; height: 11px; opacity: .75; }
  /* Le point est porte PAR l'etiquette, donc il ne peut jamais se retrouver seul
     en debut de ligne si la mise en page vient a passer sur deux lignes. */
  /* Plus de point separateur : l'ecart entre les deux bords le remplace. */
  .hero-badges .chip:not(:last-child)::after { content: none; }
  /* Le collage redevient le fond du premier ecran, bord a bord, sous le texte. */
  .wall { position: absolute; z-index: 0; top: 0; bottom: 0; height: auto;
    left: calc(-1 * var(--pad)); right: calc(-1 * var(--pad)); width: auto;
    min-height: 0; max-height: none; margin-top: 0; }
  /* Le plan recule : sans elargir sa fenetre, l'inclinaison laissait une bande
     sombre entre la barre de navigation et la premiere rangee de maquettes. */
  .wall-mask { inset: -17% -13% -2% -13%; perspective-origin: 50% 34%; }
  /* Le flou garde la matiere et la couleur des maquettes tout en rendant
     chaque ligne du texte lisible : c'est la condition posee par Nils. */
  /* Sixieme version, 2026-09-05. Nils : « ca fait vide en haut ». Le flou etait
     pose sur TOUT le collage, donc le haut de l'ecran ne montrait plus qu'une
     texture sombre sans rien a lire : de la matiere, pas du contenu. Le collage
     redevient NET. Le flou ne sert plus qu'a la lisibilite du texte et il est
     porte par le panneau du texte lui-meme, qui ne trouble donc que ce qui
     passe derriere lui. Le plan recule aussi d'un cran pour montrer plus de
     maquettes : ce sont elles, le premier argument. */
  .wall-plane { grid-template-columns: 1.05fr .68fr 1.05fr; filter: none;
    transform: rotateX(13deg) rotateZ(-4deg) scale(.86); transform-origin: 50% 40%; }
  /* Le haut de l'ecran n'a plus de texte a proteger : le voile s'y allege pour
     que le collage redevienne ce qu'on regarde en premier. */
  .wall::after { content: ""; position: absolute; inset: -10% -20%; pointer-events: none; z-index: 1;
    background: linear-gradient(180deg, rgba(7,7,26,.4) 0%, rgba(7,7,26,.06) 22%, rgba(7,7,26,.08) 46%, rgba(7,7,26,.4) 78%, rgba(7,7,26,.74) 94%, var(--night) 100%); }
  .wall-card .tag { display: none; }
  .clients { padding: 22px 0 26px; }
  .hero { --clients-h: 0px; }
  .clients-head { text-align: center; }
  .story-grid { display: none; }
  .story-mobile { display: grid; gap: 10px; }

  /* --- Cartes du carrousel des realisations, refaites le 2026-09-05 ---
     La demonstration etait invisible : le navigateur tenait dans une demi-carte
     et la vignette telephone ne s affichait pas du tout. Desormais la capture
     occupe toute la largeur et defile toute seule, le telephone se pose par
     dessus, en bas a droite, et sa video tourne des que la carte est au centre.
     Les cartes ne changent plus de taille : seule leur intensite varie. */
  .card { flex-basis: min(86%, 420px); transform: none; opacity: .62; text-align: left; justify-items: start; padding: 14px 14px 18px; }
  .card.is-active { opacity: 1; }
  .card h3 { font-size: 20px; }
  .card p { font-size: 14.5px; }
  .card .step-actions { justify-content: flex-start; }
  .story-mobile .card-media { position: relative; display: block; padding-bottom: 16px; }
  .story-mobile .card-media .frame.browser { width: 100%; aspect-ratio: 16 / 11; }
  .story-mobile .card-media .frame.phone { position: absolute; right: 4px; bottom: 0; width: 29%; z-index: 2;
    box-shadow: 0 18px 34px -14px rgba(0,0,0,.55); }
  .section-head { justify-items: center; text-align: center; margin-inline: auto; }
  .lead { margin-inline: auto; }
  /* Sur telephone, les sites defilent lateralement : empiles, ils faisaient a eux
     seuls plus de trois ecrans de defilement. */
  .sites-rail { margin-inline: calc(-1 * var(--pad)); margin-block: -16px -8px; padding-block: 16px 8px; padding-inline: var(--rail-pad); overflow-x: auto; scroll-snap-type: x mandatory; scroll-padding-inline: var(--rail-pad); scrollbar-width: none; }
  .sites-rail::-webkit-scrollbar { display: none; }
  .sites { display: flex; gap: 12px; width: max-content; padding-bottom: 10px; }
  .site { flex: 0 0 min(80vw, 330px); scroll-snap-align: start; }
  .site-meta { justify-items: center; text-align: center; }
  /* Sur telephone, chaque lien doit se toucher au doigt : 44 px de haut au moins. */
  .site-actions { gap: 8px 14px; justify-content: center; }
  .site-link, .step-link, .svc-more { min-height: 44px; align-items: center; }
  .btn-sm { min-height: 44px; }
  .footer-adr { min-height: 44px; display: inline-flex; align-items: center; }
  .footer-grid a, .footer-bottom a { min-height: 40px; display: inline-flex; align-items: center; }
  .site-cta { flex-basis: min(80vw, 330px); }
  .cta-card { grid-template-columns: 1fr; text-align: center; justify-items: center; padding: 14px 14px 20px; gap: 14px; height: 100%; align-content: start; }
  .cta-img { width: 100%; }
  .cta-txt { justify-items: center; }
  .cta-go { display: none; }
  .hover-scroll .win img { transform: none !important; }
  .svc-rail { margin-inline: calc(-1 * var(--pad)); margin-block: -16px -8px; padding-block: 16px 8px; padding-inline: var(--rail-pad); overflow-x: auto; scroll-snap-type: x mandatory; scroll-padding-inline: var(--rail-pad); scrollbar-width: none; }
  .svc-rail::-webkit-scrollbar { display: none; }
  .svc { display: flex; gap: 12px; width: max-content; padding-bottom: 10px; }
  .svc-card { flex: 0 0 min(78vw, 320px); scroll-snap-align: start; text-align: center; justify-items: center; }
  .svc-foot { grid-template-columns: 1fr; text-align: center; justify-items: center; }
  /* La bande d appel s aligne a gauche comme le reste du pied de page : centree,
     elle donnait trois blocs de texte flottants et un rendu amateur
     (Nils, 2026-09-05 : « le footer est encore tres moche »). */
  .footer-call-band { grid-template-columns: 1fr; text-align: left; justify-items: stretch; }
  .footer-call-txt { justify-items: start; }
  /* Les trois moyens de contact prennent toute la largeur : centres, ils avaient
     trois largeurs differentes et la colonne paraissait bancale. */
  .footer-call-actions { width: 100%; justify-items: stretch; }
  .footer-call { justify-content: flex-start; }
  /* Le pied de page est aligne a gauche de bout en bout sur petit ecran. */
  .footer-trust { grid-template-columns: 1fr 1fr; }
  .footer-grid { text-align: left; justify-items: stretch; }
  .footer-brand { justify-items: start; }
  .footer-bottom { justify-content: flex-start; text-align: left; }
  .svc-foot-proof { justify-items: center; }
  .svc-foot-ctas { width: 100%; }
  .svc-card.is-lead { flex-basis: min(82vw, 340px); }
  .svc-card.is-lead h3 { margin-top: 0; }
  .stats { grid-template-columns: 1fr 1fr; gap: 10px; }
  .stat { padding: 20px; text-align: center; justify-items: center; }
  .stat b { font-size: 40px; }
  /* Les deux formules se comparent en glissant lateralement, comme les sites. */
  .pricing-rail { margin-inline: calc(-1 * var(--pad)); margin-block: -16px -8px; padding-block: 16px 8px; padding-inline: var(--rail-pad); overflow-x: auto; scroll-snap-type: x mandatory; scroll-padding-inline: var(--rail-pad); scrollbar-width: none; }
  .pricing-rail::-webkit-scrollbar { display: none; }
  /* Dans un rail horizontal, l ombre et le decalage d apparition d une carte
     sortaient de la boite de defilement, qui les rognait en haut. */
  html.js .sites-rail .reveal, html.js .svc-rail .reveal, html.js .pricing-rail .reveal { transform: none; }
  /* L apparition est plus courte et sans attente sur telephone : les delais en
     cascade donnaient l impression que les cartes arrivaient en retard. */
  html.js .reveal { transform: translateY(10px); transition-duration: .4s, .5s; transition-delay: 0s; }
  .pricing-top { display: flex; gap: 12px; width: max-content; padding-bottom: 10px; align-items: stretch; }
  /* --- Section des prix sur telephone, refaite le 2026-09-05 ---
     Nils : « la section prix est dur a comprendre en mode mobile ». Trois causes
     mesurees : tout etait centre, donc l oeil n avait aucune ligne de depart ;
     le total arrivait tout en bas, apres neuf lignes d options, donc on cochait
     sans voir le prix bouger ; et la carte des tarifs remplissait presque tout
     l ecran, donc rien ne montrait qu une deuxieme carte suivait.
     Reponse : alignement a gauche partout, total colle en haut du composeur pour
     qu il reste sous les yeux pendant qu on coche, cartes retrecies pour laisser
     voir l amorce de la suivante. */
  .price-card { flex: 0 0 min(78vw, 320px); scroll-snap-align: start; text-align: left; justify-items: start; padding: 20px 18px 22px; gap: 11px; }
  .price-card .inc { gap: 7px; }
  .price-card .inc li { text-align: left; font-size: 13.5px; }
  .price-card .row { justify-content: flex-start; }
  .price-card > .btn, .price-card .row .btn { width: 100%; justify-content: center; }
  /* Colonne souple et non grille : un element colle (sticky) place dans une
     grille reste prisonnier de sa seule rangee et ne colle donc jamais. En
     colonne souple, il coulisse le long de toute la liste des options. */
  /* `align-items: start` vient de la version ordinateur : en colonne souple il
     rend chaque bloc aussi large que son contenu, et la barre du total tombait
     a 309 pixels au lieu des 354 de la colonne (Nils, 2026-09-05 : « votre
     selection [...] ne prend pas toute la largeur de l ecran »). */
  .composer { display: flex; flex-direction: column; gap: 12px; align-items: stretch; }
  .modules { padding: 4px 16px 12px; }
  .module-head { text-align: left; padding: 14px 0 4px; }
  .module-head p { margin: 0; max-width: none; font-size: 13.5px; }
  /* Sur telephone, la phrase d'explication reste visible en permanence :
     la hauteur des lignes ne saute plus au moment ou l'on coche. */
  .module { padding: 11px 10px 12px; margin: 0 -10px; row-gap: 1px; column-gap: 10px; }
  .module .name { font-size: 14.5px; }
  .module .desc { padding-left: 28px; padding-top: 2px; font-size: 12.5px; line-height: 1.35; }
  .addon { margin-left: 28px; }
  .addon .name { font-size: 12.5px; }
  /* Le total remonte AVANT la liste des options et s y accroche : le montant
     reste visible pendant qu on coche, ce qui est tout l interet du composeur.
     Il se colle sous la barre du haut, jamais en bas, ou il entrerait en
     conflit avec la barre d appel qui flotte deja au bas de l ecran. */
  .total { order: -1; position: sticky; top: calc(var(--nav-h) + 6px); z-index: 5;
    grid-template-columns: 1fr auto; align-items: center; gap: 0 14px;
    text-align: left; justify-items: start; padding: 12px 14px;
    box-shadow: 0 18px 34px -22px rgba(0,0,0,.7); }
  .total .kicker { grid-column: 1; font-size: 9.5px; letter-spacing: .1em; white-space: nowrap; }
  /* Le montant, son prix barre et la mention « /mois » tiennent sur UNE ligne :
     laisses libres de passer a la ligne, ils cassaient la barre en trois etages. */
  .total .big { grid-column: 1; gap: 5px; flex-wrap: nowrap; align-items: baseline; }
  .total .big #tot { font-size: 28px; }
  .total .big small { font-size: 11px; }
  .total .strike { font-size: 13px; }
  /* Le detail chiffre des options n a pas sa place dans une barre collante de
     deux lignes : il reste dans la liste juste dessous, et il part en entier
     avec le formulaire de contact. */
  .total .lines, .total .hint { display: none; }
  /* Le libelle du bouton change selon la selection et devient long (« En parler,
     sans engagement ») : sans retour a la ligne autorise, il gardait sa largeur
     d une seule ligne et recouvrait le montant. */
  .total .btn { grid-column: 2; grid-row: 1 / span 2; width: auto; max-width: 40vw; padding: 10px 13px; font-size: 12px; line-height: 1.2; text-align: center; white-space: normal; }
  .systems { grid-template-columns: 1fr; margin-top: 16px; }
  .system-card + .system-card { border-left: 0; border-top: 1px solid var(--line); }
  .system-card { text-align: left; justify-items: start; padding: 18px; }
  /* La methode tient en deux colonnes de deux etapes plutot qu'en colonne unique. */
  .process { grid-template-columns: 1fr 1fr; gap: 10px; }
  .pstep { text-align: center; justify-items: center; padding: 18px 13px; gap: 7px; }
  .pstep .n { width: 34px; height: 34px; font-size: 14px; margin-bottom: 2px; }
  .pstep h3 { font-size: 17px; }
  .pstep p { font-size: 14px; }
  .about { grid-template-columns: 1fr; gap: 26px; }
  .portrait { max-width: 250px; margin-inline: auto; width: 100%; }
  .about-copy { text-align: center; justify-items: center; }
  .about-facts { justify-content: center; text-align: center; }
  /* Les deux boutons du portrait tiennent cote a cote sur telephone plutot que
     l un sous l autre (Nils, 2026-09-05). Deux colonnes egales, texte autorise
     a revenir a la ligne dans le bouton : « Me parler de votre activite » ne
     tient pas sur une seule ligne dans 170 pixels. */
  .about-copy .row { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; width: 100%; justify-content: stretch; align-items: stretch; }
  .about-copy .row .btn { width: 100%; white-space: normal; text-align: center; padding: 13px 12px; font-size: 13.5px; line-height: 1.25; }
  .faq-grid { grid-template-columns: 1fr; gap: 24px; }
  .faq-side { position: static; text-align: center; justify-items: center; }
  .faq-side .row { justify-content: center; }
  .faq-list { gap: 7px; }
  .faq-list summary { padding: 15px 17px; font-size: 15.5px; gap: 12px; }
  .answer { padding: 0 17px 18px; font-size: 14.5px; }
  /* --- Contact sur telephone, degraisse le 2026-09-05 ---
     Nils : « le formulaire de contact est encore un peu trop massif ». La section
     faisait 1995 pixels de haut, soit deux ecrans et demi rien que pour prendre
     un nom et un metier. Le titre, les quatre moyens de contact, les champs et
     les cinq cartes de choix sont resserres, et tout s aligne a gauche comme le
     reste du site sur telephone. */
  .contact-grid { grid-template-columns: 1fr; gap: 20px; }
  .contact-copy { text-align: left; justify-items: start; gap: 12px; }
  .contact-copy .h2 { font-size: 30px; }
  .contact-copy .lead { font-size: 15px; }
  .contact-ways { width: 100%; gap: 6px; margin-top: 2px; }
  .way { text-align: left; grid-template-columns: 36px 1fr; gap: 11px; padding: 9px 12px; border-radius: 14px; }
  .way .ic { width: 36px; height: 36px; border-radius: 11px; }
  .way .ic svg { width: 18px; height: 18px; }
  .way-text b { font-size: 14.5px; }
  .way-sub { font-size: 12px; line-height: 1.3; }

  .form { padding: 18px 16px 20px; gap: 13px; }
  .form > h3 { font-size: 26px; }
  .field { gap: 5px; }
  .field label, .field .label { font-size: 12.5px; }
  .field input, .field textarea { padding: 11px 13px; border-radius: 12px; }
  .field textarea { min-height: 84px; }
  .wants { gap: 8px; }
  .want-in { padding: 10px 13px; border-radius: 13px; gap: 2px; }
  .want-in b { font-size: 14.5px; }
  .want-in em { font-size: 12.5px; }
  .form { padding: 20px 18px; gap: 13px; }
  .form-row { grid-template-columns: 1fr; gap: 13px; }
  .form > .btn { justify-self: stretch; }
  /* La reserve laissee sous la page pour la barre d appel flottante appartient
     au pied de page, pas au corps : posee sur le corps, elle se peignait en gris
     clair et laissait une bande blanche de 80 pixels sous le pied de page noir,
     tout en bas du telephone (mesure le 2026-09-05 : le pied s arretait a 764 px
     dans un ecran de 844). */
  body { padding-bottom: 0; }
  /* La barre d appel s efface des l entree dans le pied de page : la reserve de
     hauteur qu elle exigeait s y voyait en bande vide, alors qu elle est utile
     sous la derniere question de la FAQ, ou la barre flotte encore. */
  .footer { padding-bottom: 36px; }
  .section.faq { padding-bottom: calc(28px + var(--bar-h)); }

  /* --- Pied de page du telephone, version dediee, 2026-09-05 ---
     Nils : « le footer est encore tres moche, fais en une version purement
     mobile ». Ce qui n allait pas, mesure a 390 px : la grille de liens faisait
     752 pixels de haut a elle seule, ses deux colonnes n avaient pas le meme
     nombre de liens donc l une se terminait 400 pixels avant l autre, et chaque
     lien reservait 40 pixels de hauteur meme quand il en occupait 20.
     La reponse n est pas de retoucher cette grille mais de la remplacer : sur un
     telephone les liens de pied de page se lisent en flux, comme une phrase qui
     revient a la ligne, sous un intitule discret. La hauteur tombe de 752 a
     environ 330 pixels et il n y a plus un seul trou. */
  /* Le bloc d appel se resserre : titre plus court a lire, bouton pleine
     largeur, puis le telephone et WhatsApp cote a cote en deux pastilles.
     Empiles, ils faisaient trois grands blocs bleus les uns sous les autres
     alors que la barre du bas propose deja les memes gestes. */
  .footer-call-band { padding: 28px 0 24px; gap: 18px; }
  .footer-call-txt .display { font-size: 25px; }
  .footer-call-sub { font-size: 14px; }
  .footer-call-actions { grid-template-columns: 1fr 1fr; gap: 9px; }
  .footer-call-actions > .btn { grid-column: 1 / -1; width: 100%; }
  .footer-call { padding: 9px 12px 9px 9px; gap: 9px; }
  .footer-call svg { width: 30px; height: 30px; padding: 8px; }
  .footer-call b { font-size: 13.5px; }
  .footer-call small { display: none; }

  .footer-trust { grid-template-columns: 1fr; gap: 0; background: transparent; border: 0; border-radius: 0; }
  .footer-trust li { padding: 12px 0; border-top: 1px solid var(--line-dark); align-items: flex-start; gap: 11px; }
  .footer-trust li:first-child { border-top: 0; padding-top: 0; }
  .footer-trust span { gap: 1px; }
  /* Les pictogrammes n ont pas tous la meme forme : une colonne de largeur fixe
     les met sur un meme axe vertical, sinon le drapeau decalait sa ligne. */
  .footer-trust svg, .footer-trust .flag { width: 18px; margin-top: 3px; }

  .footer-grid { grid-template-columns: 1fr; text-align: left; gap: 0; padding: 22px 0 4px; }
  .footer-brand { max-width: none; text-align: left; gap: 10px; padding-bottom: 20px; }
  .footer-logo { height: 18px; }
  .footer-brand p { font-size: 13.5px; }
  /* Chaque groupe de liens : son intitule sur sa propre ligne, puis les liens
     a la suite, qui reviennent a la ligne quand la largeur manque. */
  .footer-grid > div:not(.footer-brand) { display: flex; flex-wrap: wrap; align-items: baseline; gap: 7px; padding: 15px 0; border-top: 1px solid var(--line-dark); }
  .footer-grid h4 { flex: 0 0 100%; font-size: 10.5px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--brand-light); margin-bottom: 3px; }
  /* Chaque lien devient une etiquette bordee. En flux simple, les liens se
     lisaient comme une phrase continue (« Monts du Lyonnais Saint-Martin-en-Haut »)
     et on ne voyait plus ou l un s arretait (Nils, 2026-09-05 : « je trouve le
     footer maladroit en mode mobile »). */
  .footer-grid div > a { display: inline-flex; align-items: center; min-height: 34px; padding: 6px 13px; font-size: 13px; line-height: 1.2; color: rgba(255,255,255,.88); background: rgba(255,255,255,.05); border: 1px solid var(--line-dark); border-radius: 999px; }
  .footer-grid div > a:hover { transform: none; }
  /* Les etiquettes s'etirent pour remplir leur ligne entiere : sans cela, chaque
     ligne s'arretait ou le texte finissait et le bord droit du pied de page
     partait en dents de scie (Nils, 2026-09-05 : « ce n'est pas centre sur la
     droite »). Le bord gauche et le bord droit tombent maintenant au meme
     endroit sur toutes les lignes. */
  .footer-grid div > a { flex: 1 1 auto; justify-content: center; text-align: center; }
  .footer-grid .footer-social { margin-top: 4px; }
  .footer-grid .footer-social a { width: 42px; height: 42px; padding: 0; background: rgba(255,255,255,.08); border: 0; }
  /* Nils demande de centrer le pied de page en mode mobile (2026-09-05, 18h22 :
     « centre le footer en mode mobile »), ce qui reprend l alignement a gauche
     pose plus haut le meme jour pour d autres raisons (etiquettes en dents de
     scie, colonne bancale). Seule la bande d appel (.footer-call-band) reste
     a gauche : elle n a pas ete visee par cette demande et son alignement
     vient d un retour explicite du jour meme (« le footer est encore tres
     moche »). Le corps du texte de chaque badge reste lisible a gauche a
     l interieur de son propre bloc ; c est le bloc entier qui se centre. */
  .footer-trust li { justify-content: center; text-align: left; }
  .footer-grid { text-align: center; justify-items: center; }
  .footer-brand { text-align: center; justify-items: center; }
  .footer-grid > div:not(.footer-brand) { justify-content: center; }
  .footer-grid h4 { text-align: center; }
  .footer-grid div > a { flex: 0 1 auto; }
  /* Les cinq cartes de choix passent sur une seule colonne : deux de front
     rendaient les libelles illisibles sur un telephone. */
  .wants { grid-template-columns: 1fr; }
  .footer-bottom { flex-direction: column; align-items: center; text-align: center; gap: 6px; padding-top: 18px; }
  .mobile-bar { position: fixed; left: 12px; right: 12px; bottom: max(12px, env(safe-area-inset-bottom)); z-index: 400; display: flex; gap: 10px; padding: 8px; border-radius: 999px; background: rgba(7,7,26,.86); backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px); box-shadow: 0 20px 50px -20px rgba(0,0,0,.6); transform: translateY(140%); transition: transform .5s var(--ease-out); }
  /* Une fenetre ouverte (menu, apercu de site, agrandissement) efface la barre. */
  body.is-locked .mobile-bar { transform: translateY(140%); }
  .mobile-bar.is-visible { transform: none; }
  .mobile-bar .btn-primary { flex: 1; box-shadow: none; }
  .btn-tel, .btn-wa { width: 52px; height: 52px; padding: 0; border-radius: 50%; background: rgba(255,255,255,.1); color: #fff; flex: 0 0 auto; }
  .btn-wa { background: #25D366; color: var(--night); }
  .btn-tel svg, .btn-wa svg { width: 20px; height: 20px; }
  .btn-tel:hover svg, .btn-wa:hover svg { transform: none; }
  .modal-body { grid-template-columns: 1fr; }
  .modal-head { text-align: center; justify-items: center; }
  .modal-text { text-align: center; justify-items: center; }
  .modal-facts { justify-content: center; }
  .modal-delivered li { text-align: left; }
  .modal-text .row { justify-content: center; }
  .zoom-body { max-height: calc(100vh - 150px); max-height: calc(100dvh - 150px); }
  /* Ecran d'envoi sur telephone : la maquette se resserre pour que ses blocs
     restent proportionnes quand la largeur descend a 280 pixels. */
  .sending-stage { gap: 18px; }
  .sending-step { font-size: 15px; }
  .ok-ways .btn { width: 100%; justify-content: center; }
}

@media (max-width: 520px) {
  :root { --pad: 18px; }
  .siteview { width: 100vw; height: 100dvh; border-radius: 0; }
  /* Au doigt, la case de consentement et son texte forment une seule cible. */
  .consent { font-size: 13.5px; padding: 4px 0; }
  .consent input { width: 24px; height: 24px; margin-top: 1px; }
  .sv-name { display: none; }
  .sv-out { padding: 8px 12px; font-size: 12.5px; }
  body { font-size: 16px; }
  .h1 { font-size: clamp(34px, 10vw, 42px); }
  .h2 { font-size: clamp(30px, 8.6vw, 38px); }
  .hero { --hero-top: 14px; }
  .chip { font-size: 11.5px; padding: 6px 10px 6px 8px; }
  .btn-lg { padding: 17px 22px; font-size: 15px; }
  .hero-ctas .btn { white-space: normal; }
  .hero-proof { flex-wrap: nowrap; gap: 0 12px; justify-content: space-between; }
  .hero-proof li { font-size: inherit; }
  .client { font-size: 19px; padding: 0 22px; }
  .card { flex-basis: 88%; padding: 14px; }
  .module .tarif { font-size: 15px; }
  .modal { width: 100vw; }
  .modal-inner { border-radius: 24px 24px 0 0; max-height: 100dvh; }
  .modal-gallery { grid-template-columns: 1fr 1fr; gap: 8px; }
}

/* ------------------------------------------------------------------
   Allegement pour les petits appareils (Nils, 2026-09-05)
   Sur telephone, les sections basses ne sont ni dessinees ni chargees
   tant qu'elles n'approchent pas de l'ecran. Le navigateur reserve la
   hauteur annoncee ci-dessous, donc la barre de defilement ne saute
   pas. Les captures qu'elles contiennent ne sont telechargees qu'a ce
   moment-la : c'est ce qui fait tomber le poids d'ouverture de la page.
   ------------------------------------------------------------------ */
@media (max-width: 760px) {
  /* Limite volontairement aux deux seules sections vraiment lourdes : celle des
     autres sites realises, qui porte six captures pleine page, et les questions
     frequentes tout en bas. Les sections legeres n'y gagnaient rien et faisaient
     apparaitre un a-coup au moment ou elles entraient a l'ecran. */
  #sites { content-visibility: auto; contain-intrinsic-size: auto 2400px; }
  #faq   { content-visibility: auto; contain-intrinsic-size: auto 1400px; }
}

/* ------------------------------------------------------------------
   Fluidite sur telephone milieu de gamme (Nils, 2026-09-05 :
   « C'est vraiment laggy sur mon A54 5G pour te dire »)
   Ce qui suit ne change rien sur ordinateur. Sur telephone, on retire
   les effets que le processeur graphique d'un appareil milieu de gamme
   recalcule a chaque image affichee : le voile de grain melange au
   fond, le flou derriere la barre de navigation, le flou derriere les
   bandes de l'ecran d'envoi, et le lent defilement interne des captures
   de sites. La mise en page, elle, ne bouge pas.
   ------------------------------------------------------------------ */
@media (max-width: 760px) {
  /* Un voile plein ecran en mode de fusion force le navigateur a
     recomposer toute la page a chaque defilement. */
  .grain { display: none; }
  .hero::after { display: none; }

  /* Le flou d'arriere-plan est l'effet le plus couteux du lot : il est
     recalcule en continu sous une barre qui reste a l'ecran. On le
     remplace par un fond franc, visuellement tres proche. */
  /* Le « body:not(.menu-open) » n'est pas decoratif : sans lui, ces deux regles
     sont plus fortes que celle qui rend la barre transparente quand le menu est
     ouvert. Sur une section claire, la barre restait donc blanche pendant que le
     logo et le bouton passaient en blanc : plus rien n'etait visible
     (Nils, 2026-09-05 : « On ne voit plus le logo et l'icone pour fermer »). */
  body:not(.menu-open) .nav.is-scrolled.is-dark { backdrop-filter: none; -webkit-backdrop-filter: none; background: #07071A; }
  body:not(.menu-open) .nav.is-scrolled.is-light { backdrop-filter: none; -webkit-backdrop-filter: none; background: #FAFAF8; }
  .mobile-bar { backdrop-filter: none; -webkit-backdrop-filter: none; background: rgba(7,7,26,.96); }
  /* Le voile du texte d'accueil cumulait un flou d'arriere-plan ET un masque
     en degrade : c'est la combinaison la plus lourde de la page. Le degrade
     sombre suffit a garder le texte lisible sans le flou. */
  .hero-copy::before { backdrop-filter: none; -webkit-backdrop-filter: none; }
  .chip { backdrop-filter: none; -webkit-backdrop-filter: none; }

  /* Trois bandes floutees qui derivent en permanence pendant l'envoi du
     formulaire : le flou disparait, le mouvement reste. */
  .sending-band { filter: none !important; }

  /* Les captures de sites font plusieurs milliers de pixels de haut ;
     les faire defiler sans fin a l'interieur de leur cadre repeint une
     grande surface en continu. Sur telephone, la capture reste fixe. */
  .scene.is-active .screen .win img,
  .card.is-active .frame.browser .win img { animation: none; }

  /* Une promesse de transformation gardee en permanence occupe de la
     memoire graphique pour rien quand l'element ne bouge pas. */
  .rotator > span { will-change: auto; }
}
