/* =========================================================================
   FERVOLIS — Feuille de style principale
   ========================================================================= */

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; background: var(--bg-abyss); }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: 1.65;
  color: var(--text-soft);
  /* Transparent : <body> n'est pas positionné, son fond serait peint
     au-dessus des fonds en z-index négatif (body::before, .bg-grid,
     body::after, .bg-video-wrap). Le fond sombre est porté par <html>. */
  background: transparent;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
  padding-top: var(--dock-inset);
}

img, svg, video { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; cursor: pointer; background: none; border: none; }
ul { list-style: none; padding: 0; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 4px; }

/* ---------- Fond global : grain + lueurs haut de page ----------
   Les quatre fonds fixes (body::before, .bg-video-wrap, .bg-grid, body::after)
   prennent la hauteur du grand viewport (100lvh, repli 100vh) au lieu de
   `inset: 0` : sur iOS, `inset: 0` s'arrête au petit viewport et laisse une
   bande noire sous la barre d'outils flottante. Sur ordinateur, 100lvh = 100vh. */
body::before {
  content: ""; position: fixed; top: 0; left: 0; right: 0; height: 100vh; height: 100lvh; z-index: -2; pointer-events: none;
  background:
    radial-gradient(760px 420px at 50% 0%, rgba(255, 45, 35, .17), transparent 68%),
    radial-gradient(1100px 620px at 50% -4%, rgba(255, 0, 0, .13), transparent 58%),
    radial-gradient(800px 500px at 88% 6%, rgba(255, 40, 30, .07), transparent 55%);
}

/* ---------- Vidéo de fond scrubbée au scroll ---------- */
.bg-video-wrap { position: fixed; top: 0; left: 0; right: 0; height: 100vh; height: 100lvh; z-index: -3; overflow: hidden; pointer-events: none; background: var(--bg-abyss); }
.bg-video-wrap video { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Voile par-dessus la vidéo : UNIFORME (vignette symétrique) → aucune bande ni ligne
   entre le haut et le bas. Le texte est protégé par une ombre portée (voir plus bas). */
.bg-video-wrap::after { content: ""; position: absolute; inset: 0; background: radial-gradient(130% 130% at 50% 50%, rgba(5,6,9,.78) 0%, rgba(5,6,9,.88) 100%); }
@media (prefers-reduced-motion: reduce) { .bg-video-wrap video { /* image fixe, pas de scrub */ } }
/* Protection de lisibilité du texte par-dessus la vidéo (ombre douce + léger halo sombre) */
.hero-inner h1, .hero-inner .lead, .hero-inner .eyebrow,
.section-head h2, .section-head .lead, .section-head .eyebrow,
.manifesto p, .compare-note { text-shadow: 0 1px 2px rgba(0,0,0,.5), 0 2px 22px rgba(0,0,0,.45); }
/* Le texte dégradé (background-clip:text) ne prend pas text-shadow → on utilise drop-shadow */
.hero-inner .grad-text { filter: drop-shadow(0 2px 10px rgba(0,0,0,.55)); }
/* Corps de texte : léger contour sombre pour rester lisible par-dessus la vidéo
   (imperceptible sur les cartes à fond plein). */
main p, main li { text-shadow: 0 1px 3px rgba(0,0,0,.62); }

/* ---------- Image réelle remplaçant un schéma SVG (repli : le SVG si l'image manque) ---------- */
.swap-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: 3; border-radius: inherit; }
/* Grille technique rouge braise — visible mais moins agressive que l'orange d'origine */
body .bg-grid {
  position: fixed; top: 0; left: 0; right: 0; height: 100vh; height: 100lvh; z-index: -2; pointer-events: none; opacity: .5;
  background-image:
    linear-gradient(rgba(255,115,0,.42) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,115,0,.42) 1px, transparent 1px),
    linear-gradient(rgba(255,140,25,.12) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,140,25,.12) 1px, transparent 1px);
  background-size: 68px 68px, 68px 68px, 17px 17px, 17px 17px;
  -webkit-mask-image: radial-gradient(ellipse 145% 130% at 50% 45%, rgba(0,0,0,.85) 58%, rgba(0,0,0,.45) 85%, transparent 100%);
  mask-image: radial-gradient(ellipse 145% 130% at 50% 45%, rgba(0,0,0,.85) 58%, rgba(0,0,0,.45) 85%, transparent 100%);
}
/* Sur la page d'accueil (celle qui a la vidéo de fond), grille quasi absente
   pour laisser voir la vidéo en dessous. */
body:has(.bg-video-wrap) .bg-grid { opacity: .1; }
body::after { /* grain léger */
  content: ""; position: fixed; top: 0; left: 0; right: 0; height: 100vh; height: 100lvh; z-index: -1; pointer-events: none; opacity: .045;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ---------- Typographie ---------- */
h1, h2, h3, h4 { font-family: var(--font-display); color: var(--text); line-height: 1.08; font-weight: 600; letter-spacing: -.02em; }
h1 { font-size: var(--fs-h1); font-weight: 700; }
h2 { font-size: var(--fs-h2); }
h3 { font-size: var(--fs-h3); }
p { color: var(--text-muted); }
strong { color: var(--text); font-weight: 600; }

.eyebrow {
  display: inline-flex; align-items: center; gap: .55rem;
  font-family: var(--font-body); font-size: var(--fs-eyebrow); font-weight: 600;
  letter-spacing: .18em; text-transform: uppercase; color: var(--accent);
  margin-bottom: 1.1rem;
}
.eyebrow::before { content: ""; width: 26px; height: 1px; background: var(--grad-signature); }

.grad-text {
  background: var(--grad-text); -webkit-background-clip: text; background-clip: text;
  color: transparent;
}
.accent-text { color: var(--accent); }
.lead { font-size: var(--fs-lead); color: var(--text-soft); line-height: 1.6; }

/* ---------- Layout helpers ---------- */
.wrap { max-width: var(--maxw); margin-inline: auto; padding-inline: var(--gutter); }
.wrap-narrow { max-width: var(--maxw-narrow); margin-inline: auto; padding-inline: var(--gutter); }
section { padding-block: var(--section-y); position: relative; }
.section-head { max-width: 720px; margin-bottom: clamp(2.5rem, 1.5rem + 3vw, 4rem); }
.section-head.center { margin-inline: auto; text-align: center; }
.section-head .lead { margin-top: 1.1rem; }
.divider { height: 1px; background: linear-gradient(90deg, transparent, var(--line-strong), transparent); border: 0; }

/* ---------- Boutons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  font-family: var(--font-body); font-weight: 600; font-size: .92rem; letter-spacing: .01em;
  padding: .8rem 1.45rem; border-radius: var(--radius-btn); border: 1px solid transparent;
  transition: transform .45s var(--ease-fluid), box-shadow .45s var(--ease-fluid), background var(--t-med), border-color var(--t-med);
  will-change: transform; white-space: nowrap;
}
.btn svg { width: 1em; height: 1em; }
.btn-primary {
  color: #fff; background: linear-gradient(180deg, #FF0000 0%, #D40000 100%);
  border-color: rgba(255,80,80,.5);
  box-shadow: 0 0 36px var(--glow), 0 4px 20px rgba(0,0,0,.45);
}
.btn-primary:hover { transform: translateY(-2px) scale(1.02); box-shadow: 0 0 50px rgba(255,0,0,.66), 0 12px 32px rgba(0,0,0,.5); }
.btn-ghost {
  color: var(--text); background: rgba(255,255,255,.03);
  border: 1px solid var(--line-strong);
}
.btn-ghost:hover { transform: translateY(-2px); border-color: rgba(255,0,0,.35); background: rgba(255,0,0,.08); }
.btn-lg { padding: 1.05rem 2rem; font-size: 1.02rem; }
.btn-arrow { transition: transform var(--dur-med) var(--ease-expo); }
.btn:hover .btn-arrow { transform: translateX(4px); }

.link-arrow {
  display: inline-flex; align-items: center; gap: .5rem; font-weight: 600; color: var(--accent);
}
/* MOUV-7 : la flèche glisse (transform) au lieu d'élargir l'espace (gap) */
.link-arrow svg { transition: transform var(--dur-med) var(--ease-expo); }
.link-arrow:hover svg { transform: translateX(5px); }

/* ---------- Header — dock flottant qui rétrécit au scroll ---------- */
.site-header {
  position: fixed;
  top: var(--dock-top);
  left: 0;
  right: 0;
  z-index: 100;
  display: flex;
  justify-content: center;
  padding-inline: calc(var(--gutter) + var(--dock-scroll) * 4vw);
  height: auto;
  pointer-events: none;
  background: none;
  border: none;
}
.site-header .wrap {
  pointer-events: auto;
  width: min(100%, calc(var(--maxw) - var(--dock-scroll) * 320px));
  min-height: calc(var(--header-h) - var(--dock-scroll) * 14px);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(1.25rem - var(--dock-scroll) * .5rem);
  padding-inline: calc(clamp(1rem, 0.55rem + 1.4vw, 1.85rem) - var(--dock-scroll) * .5rem);
  border-radius: var(--radius-pill);
  background: rgba(8, 10, 14, calc(.10 + var(--dock-scroll) * .58));
  backdrop-filter: blur(calc(14px + var(--dock-scroll) * 14px)) saturate(calc(115% + var(--dock-scroll) * 50%));
  -webkit-backdrop-filter: blur(calc(14px + var(--dock-scroll) * 14px)) saturate(calc(115% + var(--dock-scroll) * 50%));
  border: 1px solid rgba(255, 255, 255, calc(.07 + var(--dock-scroll) * .07));
  box-shadow:
    0 calc(3px + var(--dock-scroll) * 10px) calc(16px + var(--dock-scroll) * 28px) rgba(0, 0, 0, calc(.18 + var(--dock-scroll) * .28)),
    inset 0 1px 0 rgba(255, 255, 255, calc(.04 + var(--dock-scroll) * .04));
  transition:
    width .35s var(--ease-out),
    min-height .35s var(--ease-out),
    padding .35s var(--ease-out),
    gap .35s var(--ease-out),
    background .25s var(--ease-out),
    border-color .25s var(--ease-out),
    box-shadow .35s var(--ease-out);
}
.site-header .brand,
.site-header .nav,
.site-header .burger { position: relative; z-index: 1; }
.brand {
  display: flex; align-items: center; gap: calc(.6rem - var(--dock-scroll) * .15rem);
  font-family: var(--font-display); font-weight: 700;
  font-size: calc(1.05rem - var(--dock-scroll) * .15rem);
  color: var(--text); letter-spacing: -.01em; flex-shrink: 0;
  transition: font-size .35s var(--ease-out), gap .35s var(--ease-out);
}
.brand img {
  /* logo recadré au plus près : 36px déplié, 30px replié, le mot « Fervolis » reste lisible */
  height: calc(36px - var(--dock-scroll) * 6px); width: auto;
  transition: height .35s var(--ease-out);
}
/* pied de page : symbole seul, à la place de l'ancien carré rouge */
.brand img.brand-icon { width: 26px; height: 26px; }
.brand .brand-fallback { display: inline-flex; align-items: center; gap: .5rem; }
.brand .brand-dot {
  width: calc(26px - var(--dock-scroll) * 8px);
  height: calc(26px - var(--dock-scroll) * 8px);
  border-radius: calc(8px - var(--dock-scroll) * 2px);
  background: linear-gradient(180deg, #FF1A1A, #D40000);
  box-shadow: 0 0 18px rgba(255,0,0,.45);
  display: grid; place-items: center;
  transition: width .35s var(--ease-out), height .35s var(--ease-out), border-radius .35s var(--ease-out);
}
.brand .brand-dot::after { content: ""; width: 9px; height: 9px; border-radius: 50%; background: var(--bg-abyss); }

.nav { display: flex; align-items: center; gap: calc(clamp(.8rem, 0.4rem + 1.2vw, 1.8rem) - var(--dock-scroll) * .4rem); transition: gap .35s var(--ease-out); }
.nav-links { display: flex; align-items: center; gap: calc(clamp(.2rem, 0.05rem + .6vw, .8rem) - var(--dock-scroll) * .15rem); transition: gap .35s var(--ease-out); }
.nav-links a {
  font-size: calc(.88rem - var(--dock-scroll) * .1rem);
  font-weight: 500; color: var(--text-muted);
  padding: calc(.4rem - var(--dock-scroll) * .12rem) calc(.75rem - var(--dock-scroll) * .2rem);
  border-radius: var(--radius-pill);
  transition: color var(--dur-short) var(--ease-soft), background var(--dur-short) var(--ease-soft), font-size .35s var(--ease-out), padding .35s var(--ease-out);
}
.nav-links a:hover { color: var(--text); background: rgba(255, 255, 255, .08); }
.nav-links a[aria-current="page"] { color: var(--text); background: rgba(255, 50, 40, .18); }
.nav-links a[aria-current="page"]::after { display: none; }

.site-header .btn-primary {
  padding: calc(.58rem - var(--dock-scroll) * .14rem) calc(1.1rem - var(--dock-scroll) * .3rem);
  font-size: calc(.84rem - var(--dock-scroll) * .1rem);
  border-radius: var(--radius-pill);
  box-shadow: 0 0 calc(20px - var(--dock-scroll) * 8px) rgba(255,0,0,calc(.3 - var(--dock-scroll) * .1)), 0 4px 12px rgba(0,0,0,.25);
  transition: padding var(--dur-med) var(--ease-expo), font-size var(--dur-med) var(--ease-expo), transform .25s var(--ease-out), box-shadow .25s var(--ease-out);
}
.site-header .btn-primary:hover {
  transform: translateY(-2px);
  box-shadow: 0 0 28px rgba(255,20,10,.45), 0 6px 16px rgba(0,0,0,.3);
}

.burger { display: none; width: 40px; height: 40px; border-radius: var(--radius-pill); border: 1px solid var(--line); position: relative; flex-shrink: 0; }
.burger span { position: absolute; left: 11px; right: 11px; height: 2px; background: var(--text); border-radius: 2px; transition: transform var(--t-med), opacity var(--t-fast); }
.burger span:nth-child(1) { top: 13px; }
.burger span:nth-child(2) { top: 19px; }
.burger span:nth-child(3) { top: 25px; }
.nav-open .burger span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.nav-open .burger span:nth-child(2) { opacity: 0; }
.nav-open .burger span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

@media (max-width: 860px) {
  .site-header .wrap { padding-inline: 1rem; }

  /* IMPORTANT — un `backdrop-filter` crée un BLOC CONTENEUR pour les descendants
     en `position: fixed`. Tant qu'il était porté par `.site-header .wrap`, le
     panneau `.nav` (fixed) se positionnait par rapport à la pilule du header et
     non par rapport à l'écran : le menu mobile était donc inutilisable.
     On déporte le flou sur un pseudo-élément, qui n'a pas cet effet sur `.nav`. */
  .site-header .wrap {
    position: relative;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
  .site-header .wrap::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    border-radius: inherit;
    pointer-events: none;
    /* Flou allégé : au-dessus d'une page qui défile, un backdrop-filter fort
       coûte très cher en compositing sur mobile. */
    backdrop-filter: blur(12px) saturate(130%);
    -webkit-backdrop-filter: blur(12px) saturate(130%);
  }

  .burger { display: block; z-index: 110; }
  .nav {
    position: fixed; top: 0; right: 0; bottom: auto; height: 100dvh; width: min(82vw, 360px);
    flex-direction: column; align-items: stretch; justify-content: flex-start; gap: 0;
    padding: calc(var(--dock-top) + var(--header-h) + 1.5rem) var(--gutter) 2rem;
    background: var(--bg-abyss); border-left: 1px solid var(--line);
    overflow-y: auto; transform: translateX(100%); z-index: 105;
    /* `visibility` : hors ouverture, le panneau ne doit être ni focusable au
       clavier ni susceptible de provoquer un débordement horizontal. */
    visibility: hidden;
    transition: transform var(--t-slow), visibility var(--t-slow);
    /* le scroll du panneau ne doit pas se propager à la page derrière */
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
  }
  .nav-open .nav { transform: translateX(0); visibility: visible; }
  .nav-links { flex-direction: column; align-items: stretch; gap: 0; width: 100%; }
  .nav-links a { padding: 1rem 0; border-bottom: 1px solid var(--line); font-size: 1.1rem; border-radius: 0; background: none; }
  .nav-links a:hover { background: none; }
  .nav-links a[aria-current="page"] { color: var(--accent); background: none; }
  .nav .btn { margin-top: 1.5rem; width: 100%; }
  .nav-scrim { position: fixed; inset: 0; background: rgba(0,0,0,.5); opacity: 0; visibility: hidden; transition: opacity var(--t-med), visibility var(--t-med); z-index: 90; }
  .nav-open .nav-scrim { opacity: 1; visibility: visible; }
}

/* Dock (desktop) : la barre de nav reste alignée et centrée dans la pilule,
   sans débord vertical. */
@media (min-width: 861px) {
  .site-header .nav { padding: 0; margin: 0; min-height: 0; align-self: center; }
}

/* ---------- Hero ---------- */
.hero {
  margin-top: calc(-1 * var(--dock-inset));
  padding-top: calc(var(--dock-inset) + clamp(4rem, 2rem + 8vw, 8rem));
  padding-bottom: clamp(4rem, 2rem + 7vw, 7rem);
  overflow: visible;
}
.hero-mesh {
  position: absolute;
  top: calc(-1 * var(--dock-inset) - 22%);
  left: -10%;
  right: -10%;
  height: calc(142% + var(--dock-inset));
  z-index: -1;
  pointer-events: none;
  filter: blur(64px);
  opacity: .88;
  /* Parallaxe souris : tout le champ de fumée se décale (--mx/--my posés par parallax.js) */
  transform: translate(calc(var(--mx,0) * 34px), calc(var(--my,0) * 26px));
  transition: transform .6s var(--ease-out);
}
/* Nuages de fumée rouge */
.hero-mesh .blob { position: absolute; border-radius: 48% 52% 55% 45% / 46% 54% 48% 52%; mix-blend-mode: screen; }
.hero-mesh .b1 { width: 56vw; height: 50vw; left: 0; top: -22%;
  background: radial-gradient(ellipse 58% 50% at 38% 42%, rgba(255,0,0,.52), rgba(255,40,25,.14) 50%, transparent 68%);
  animation: drift1 22s var(--ease-out) infinite alternate; }
.hero-mesh .b2 { width: 50vw; height: 48vw; right: -4%; top: -14%;
  background: radial-gradient(ellipse 52% 50% at 60% 40%, rgba(255,25,15,.48), rgba(255,70,50,.14) 48%, transparent 66%);
  animation: drift2 26s var(--ease-out) infinite alternate; }
.hero-mesh .b3 { width: 42vw; height: 40vw; left: 32%; top: 16%;
  background: radial-gradient(ellipse 50% 48% at 46% 40%, rgba(255,90,70,.36), rgba(255,0,0,.22) 42%, transparent 64%);
  animation: drift3 30s var(--ease-out) infinite alternate; }
@keyframes drift1 { to { transform: translate(8%, 12%) scale(1.15); } }
@keyframes drift2 { to { transform: translate(-10%, 8%) scale(1.1); } }
@keyframes drift3 { to { transform: translate(6%, -10%) scale(1.2); } }

/* Canvas 3D (Three.js) en fond de hero — au-dessus de la fumée, transparent */
.hero-canvas { position: absolute; inset: 0; z-index: -1; pointer-events: none; opacity: 0; transition: opacity 1.2s var(--ease-out); }
.hero-canvas.ready { opacity: 1; }
@media (max-width: 760px) { .hero-canvas { opacity: 0; } .hero-canvas.ready { opacity: .55; } }

.hero-net { position: absolute; inset: 0; z-index: -1; pointer-events: none; opacity: .45; }
.hero-net line { stroke: rgba(255,80,80,.10); stroke-width: 1; }
.hero-net circle { fill: rgba(255,40,40,.6); }

.hero-inner { max-width: 920px; position: relative; }
.hero h1 { margin-bottom: 1.5rem; }
.hero .lead { max-width: 620px; margin-bottom: 2.2rem; }
.hero-cta { display: flex; flex-wrap: wrap; gap: 1rem; align-items: center; }
.hero-note { margin-top: 1.6rem; font-size: var(--fs-small); color: var(--text-faint); display: inline-flex; align-items: center; gap: .55rem; }
.hero-note .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--accent-cyan); box-shadow: 0 0 10px var(--accent-cyan); }

/* ---------- Marquee ---------- */
.marquee { overflow: hidden; border-block: 1px solid var(--line); padding-block: 1.1rem; -webkit-mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent); mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent); }
.marquee-track { display: flex; gap: 3rem; width: max-content; animation: marquee 38s linear infinite; }
.marquee-track span { font-family: var(--font-display); font-weight: 500; font-size: 1.05rem; color: var(--text-faint); display: inline-flex; align-items: center; gap: 3rem; }
.marquee-track span::after { content: "◆"; color: var(--accent); font-size: .7rem; }
@keyframes marquee { to { transform: translateX(-50%); } }

/* ---------- Cards / grids ---------- */
.grid { display: grid; gap: 1.25rem; }
.grid-2 { grid-template-columns: repeat(2, 1fr); }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 880px) { .grid-3, .grid-4 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 600px) { .grid-2, .grid-3, .grid-4 { grid-template-columns: 1fr; } }

.card {
  background: linear-gradient(180deg, var(--surface), var(--bg-base));
  border: 1px solid var(--line); border-radius: var(--radius);
  padding: clamp(1.4rem, 1rem + 1vw, 2rem);
  position: relative; overflow: hidden;
  transition: transform var(--t-med), border-color var(--t-med), box-shadow var(--t-med);
}
.card::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit; padding: 1px;
  background: var(--grad-soft);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude;
  opacity: 0; transition: opacity var(--t-med); pointer-events: none;
}
.card:hover { transform: translateY(-4px); border-color: var(--line-strong); box-shadow: var(--shadow-md); }
.card:hover::before { opacity: 1; }
.card .card-icon {
  width: 46px; height: 46px; border-radius: 12px; display: grid; place-items: center; margin-bottom: 1.1rem;
  background: var(--grad-soft); border: 1px solid var(--line-strong); color: var(--accent);
}
.card .card-icon svg { width: 22px; height: 22px; }
.card h3 { margin-bottom: .6rem; }
.card p { font-size: .96rem; }
.card .card-num { font-family: var(--font-display); font-size: .8rem; font-weight: 600; color: var(--accent); letter-spacing: .15em; margin-bottom: .9rem; opacity: .8; }

/* ---------- Problème (split) ---------- */
.problem-grid { display: grid; grid-template-columns: 1.1fr .9fr; gap: clamp(2rem, 1rem + 4vw, 5rem); align-items: center; }
@media (max-width: 880px) { .problem-grid { grid-template-columns: 1fr; } }
.stat-stack { display: grid; gap: 1rem; }
.stat-row { display: flex; gap: 1rem; align-items: flex-start; padding: 1.2rem 1.3rem; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-sm); }
.stat-row .ico { flex: none; color: var(--accent); margin-top: .15rem; }
.stat-row .ico svg { width: 20px; height: 20px; }
.stat-row h4 { font-size: 1.02rem; margin-bottom: .25rem; }
.stat-row p { font-size: .92rem; }

/* ---------- Scroll télescopé (sticky) ---------- */
.telescope { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(2rem, 1rem + 4vw, 5rem); align-items: start; }
@media (max-width: 880px) { .telescope { grid-template-columns: 1fr; } }
.telescope-visual { position: sticky; top: calc(var(--dock-inset) + 3vh); height: min(70vh, 540px); border-radius: var(--radius-lg); border: 1px solid var(--line); overflow: hidden; background: radial-gradient(120% 120% at 30% 20%, var(--surface-2), var(--bg-abyss)); }
@media (max-width: 880px) { .telescope-visual { position: relative; top: 0; height: 300px; margin-bottom: 2rem; } }
.telescope-steps { display: grid; gap: clamp(2rem, 4vw, 4rem); }
.telescope-step { min-height: 42vh; display: flex; flex-direction: column; justify-content: center; transition: opacity var(--t-slow); }
:where(html.js) .telescope-step { opacity: .4; }
@media (max-width: 880px) { .telescope-step { min-height: auto; } :where(html.js) .telescope-step { opacity: 1; } }
:where(html.js) .telescope-step.is-active { opacity: 1; }
.telescope-step .step-num { font-family: var(--font-display); font-size: .82rem; font-weight: 600; letter-spacing: .2em; color: var(--accent); margin-bottom: .8rem; }
.telescope-step h3 { font-size: clamp(1.5rem, 1.1rem + 1.6vw, 2.2rem); margin-bottom: .8rem; }

/* Visuel télescope : panneaux empilés avec images plein cadre */
.tscene { position: absolute; inset: 0; overflow: hidden; border-radius: inherit; }
.tscene .layer {
  position: absolute; inset: 0;
  opacity: 0;
  transition: opacity .5s var(--ease-out);
}
.tscene .layer.is-active { opacity: 1; }
.tscene .layer img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

/* ---------- Pipeline (solution) ---------- */
.pipeline { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1rem; counter-reset: step; }
@media (max-width: 880px) { .pipeline { grid-template-columns: 1fr; } }
.pipe-step { position: relative; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: 1.6rem 1.4rem; }
.pipe-step .badge { width: 40px; height: 40px; border-radius: 11px; display: grid; place-items: center; font-family: var(--font-display); font-weight: 700; color: var(--accent-ink); background: var(--grad-signature); margin-bottom: 1rem; }
.pipe-step h3 { font-size: 1.1rem; margin-bottom: .5rem; }
.pipe-step p { font-size: .92rem; }
.pipe-step code { font-family: ui-monospace, "SFMono-Regular", Menlo, monospace; font-size: .85em; color: var(--text); overflow-wrap: anywhere; }
.pipe-step .arrow { position: absolute; right: -.85rem; top: 50%; transform: translateY(-50%); color: var(--accent); z-index: 2; }
@media (max-width: 880px) { .pipe-step .arrow { right: 50%; top: auto; bottom: -1.1rem; transform: translateX(50%) rotate(90deg); } }
.pipe-step:last-child .arrow { display: none; }

.flow-note { margin-top: 1.5rem; display: flex; gap: 1rem; flex-wrap: wrap; }
.chip { display: inline-flex; align-items: center; gap: .5rem; padding: .5rem .9rem; border-radius: var(--radius-pill); background: var(--surface); border: 1px solid var(--line); font-size: .85rem; color: var(--text-muted); }
.chip .d { width: 7px; height: 7px; border-radius: 50%; }
.chip .d.in { background: var(--accent-cyan); }
.chip .d.local { background: var(--accent-cyan); }
.chip .d.out { background: var(--accent-2); }

/* ---------- Vision / manifeste ---------- */
.manifesto { max-width: 880px; margin-inline: auto; }
.manifesto p { font-family: var(--font-display); font-weight: 400; font-size: clamp(1.4rem, 1rem + 1.8vw, 2.3rem); line-height: 1.4; color: var(--text-soft); letter-spacing: -.01em; margin-bottom: clamp(1.6rem, 1rem + 2vw, 2.6rem); }
.manifesto p .hl { color: var(--text); }
.manifesto .credo { display: grid; gap: 1px; background: var(--line); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; margin-top: 3rem; }
.manifesto .credo div { background: var(--bg-base); padding: 1.6rem; font-family: var(--font-body); font-size: 1rem; color: var(--text-muted); }
.manifesto .credo div strong { display: block; font-family: var(--font-display); color: var(--text); font-size: 1.1rem; margin-bottom: .4rem; }
@media (min-width: 700px) { .manifesto .credo { grid-template-columns: 1fr 1fr; } }

/* ---------- À propos ---------- */
.about-grid { display: grid; grid-template-columns: .8fr 1.2fr; gap: clamp(2rem, 1rem + 4vw, 4rem); align-items: start; }
@media (max-width: 820px) { .about-grid { grid-template-columns: 1fr; } }
.about-photo { aspect-ratio: 4/5; border-radius: var(--radius-lg); border: 1px solid var(--line); background: radial-gradient(120% 120% at 30% 10%, var(--surface-2), var(--bg-abyss)); display: grid; place-items: center; color: var(--text-faint); position: relative; overflow: hidden; }
.about-photo img { width: 100%; height: 100%; object-fit: cover; }
.about-photo .photo-fallback { display: none; place-items: center; text-align: center; font-size: .82rem; letter-spacing: .1em; line-height: 1.8; }
.about-photo .photo-fallback small { font-family: ui-monospace, Menlo, monospace; letter-spacing: 0; opacity: .6; }
.timeline { display: grid; gap: 0; margin-top: 2rem; }
.timeline li { position: relative; padding: 0 0 1.8rem 1.8rem; border-left: 1px solid var(--line); }
.timeline li:last-child { border-left-color: transparent; padding-bottom: 0; }
.timeline li::before { content: ""; position: absolute; left: -5px; top: 4px; width: 10px; height: 10px; border-radius: 50%; background: var(--grad-signature); box-shadow: 0 0 0 4px var(--bg-base); }
.timeline h4 { font-size: 1.02rem; margin-bottom: .3rem; }
.timeline p { font-size: .92rem; }

/* ---------- Formulaire ---------- */
.contact-grid { display: grid; grid-template-columns: 1fr 1.15fr; gap: clamp(2rem, 1rem + 4vw, 4rem); align-items: start; }
@media (max-width: 820px) { .contact-grid { grid-template-columns: 1fr; } }
.contact-aside .info-row { display: flex; gap: .9rem; align-items: flex-start; padding: 1.1rem 0; border-bottom: 1px solid var(--line); }
.contact-aside .info-row:last-child { border-bottom: 0; }
.contact-aside .info-row .ico { color: var(--accent); margin-top: .15rem; }
.contact-aside .info-row .ico svg { width: 20px; height: 20px; }
.contact-aside .info-row a { color: var(--text); font-weight: 500; }
.contact-aside .info-row small { color: var(--text-faint); }

.form-card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-lg); padding: clamp(1.4rem, 1rem + 1.5vw, 2.4rem); }
.field { margin-bottom: 1.2rem; }
.field label { display: block; font-size: .88rem; font-weight: 500; color: var(--text-soft); margin-bottom: .5rem; }
.field label .req { color: var(--accent); }
.field input, .field textarea {
  width: 100%; padding: .85rem 1rem; font: inherit; color: var(--text);
  background: var(--bg-abyss); border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
.field textarea { resize: vertical; min-height: 130px; }
.field input::placeholder, .field textarea::placeholder { color: var(--text-faint); }
.field input:focus, .field textarea:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(255,0,0,.18); }
.field.invalid input, .field.invalid textarea { border-color: #ff6b6b; }
.field .err { display: none; color: #ff8585; font-size: .82rem; margin-top: .4rem; }
.field.invalid .err { display: block; }

/* honeypot */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.consent { display: flex; gap: .7rem; align-items: flex-start; margin-bottom: 1.4rem; }
.consent input { margin-top: .25rem; width: 18px; height: 18px; accent-color: var(--accent); flex: none; }
.consent label { font-size: .86rem; color: var(--text-muted); line-height: 1.5; }
.consent a { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; }

.form-status { display: none; padding: .9rem 1.1rem; border-radius: var(--radius-sm); font-size: .9rem; margin-bottom: 1.2rem; }
.form-status.show { display: block; }
.form-status.success { background: rgba(255, 138, 90, .12); border: 1px solid rgba(255, 138, 90, .4); color: var(--accent-cyan); }
.form-status.error { background: rgba(255,107,107,.1); border: 1px solid rgba(255,107,107,.4); color: #ff9d9d; }
.form-status a { color: inherit; text-decoration: underline; text-underline-offset: 2px; font-weight: 600; }

/* ---------- Test anti-robot hCaptcha ---------- */
/* Le widget est une iframe fournie par hCaptcha : on ne peut pas la styler,
   on l'intègre donc proprement dans le rythme du formulaire. */
.captcha-wrap { margin-bottom: 1.2rem; }
.captcha-wrap #hcaptcha-box[hidden] { display: none; }
.captcha-wrap iframe { max-width: 100%; }
/* Le widget hCaptcha fait 302 px de large : sur très petit écran, on le laisse
   déborder proprement plutôt que casser la grille du formulaire. */
@media (max-width: 380px) {
  .captcha-wrap { overflow-x: auto; }
}
.btn[aria-busy="true"] { opacity: .7; pointer-events: none; }
.btn .spinner { width: 1em; height: 1em; border: 2px solid rgba(10,12,18,.4); border-top-color: var(--accent-ink); border-radius: 50%; animation: spin .7s linear infinite; display: none; }
.btn[aria-busy="true"] .spinner { display: inline-block; }
@keyframes spin { to { transform: rotate(360deg); } }

/* ---------- CTA band ---------- */
.cta-band { position: relative; overflow: hidden; border-radius: var(--radius-lg); border: 1px solid var(--line-strong); padding: clamp(2.5rem, 2rem + 4vw, 5rem); text-align: center; background: radial-gradient(120% 160% at 50% 0%, rgba(255,0,0,.18), transparent 60%), var(--surface); }
.cta-band h2 { margin-bottom: 1rem; max-width: 18ch; margin-inline: auto; }
.cta-band p { max-width: 52ch; margin: 0 auto 2rem; }

/* ---------- Legal pages ---------- */
.legal { max-width: 820px; margin-inline: auto; }
.legal h2 { font-size: 1.35rem; margin: 2.5rem 0 .9rem; }
.legal h3 { font-size: 1.1rem; margin: 1.6rem 0 .5rem; }
.legal p, .legal li { color: var(--text-muted); margin-bottom: .8rem; }
.legal ul { list-style: disc; padding-left: 1.3rem; }
.legal ul li { margin-bottom: .5rem; }
.legal a { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; }
.legal .updated { color: var(--text-faint); font-size: .9rem; }

/* page hero (interior) — halos qui remontent au-dessus du dock */
.page-hero {
  margin-top: calc(-1 * var(--dock-inset));
  padding-top: calc(var(--dock-inset) + clamp(3.5rem, 2rem + 6vw, 6rem));
  padding-bottom: clamp(2rem, 1rem + 3vw, 3.5rem);
  position: relative;
  overflow: visible;
}
.page-hero .hero-mesh {
  position: absolute;
  top: calc(-1 * var(--dock-inset) - 10%);
  left: -10%;
  right: -10%;
  height: calc(160% + var(--dock-inset));
  opacity: .6;
}

/* ---------- Footer ---------- */
.site-footer { border-top: 1px solid var(--line); background: var(--bg-abyss); padding-block: clamp(3rem, 2rem + 3vw, 4.5rem) 2rem; margin-top: var(--section-y); }
.footer-top { display: grid; grid-template-columns: 1.4fr 1fr 1fr; gap: 2rem; margin-bottom: 3rem; }
@media (max-width: 760px) { .footer-top { grid-template-columns: 1fr 1fr; } .footer-brand-col { grid-column: 1 / -1; } }
.footer-brand-col p { font-size: .92rem; max-width: 36ch; margin-top: 1rem; }
.footer-col h4 { font-family: var(--font-body); font-size: .78rem; letter-spacing: .16em; text-transform: uppercase; color: var(--text-faint); margin-bottom: 1rem; }
.footer-col a { display: block; font-size: .92rem; color: var(--text-muted); padding: .35rem 0; transition: color var(--t-fast); }
.footer-col a:hover { color: var(--text); }
.footer-bottom { display: flex; flex-wrap: wrap; gap: 1rem; justify-content: space-between; align-items: center; padding-top: 1.8rem; border-top: 1px solid var(--line); }
.footer-bottom p { font-size: .84rem; color: var(--text-faint); }
.footer-disclaimer { font-size: .8rem; color: var(--text-faint); max-width: 70ch; margin-top: 1rem; line-height: 1.6; }

/* ---------- Bloc social mis en valeur (page contact) ---------- */
.contact-social { margin-top: 1.6rem; padding-top: 1.4rem; border-top: 1px solid var(--line); }
.contact-social > strong { display: block; color: var(--text); font-family: var(--font-display); font-size: 1rem; margin-bottom: .9rem; }
.contact-social .footer-social { flex-wrap: wrap; gap: .7rem; }
.contact-social .footer-social a { width: 46px; height: 46px; border-radius: 13px; }
.contact-social .footer-social a svg { width: 21px; height: 21px; }

/* ---------- Liens sociaux (footer) — boutons logo + couleurs réelles au survol ---------- */
.footer-social { display: flex; align-items: center; gap: .6rem; }
.footer-social a {
  position: relative; overflow: hidden;
  width: 42px; height: 42px; display: grid; place-items: center;
  border-radius: 12px; border: 1px solid var(--line-strong);
  background: rgba(255,255,255,.03); color: var(--text-muted);
  transition: transform var(--dur-med) var(--ease-expo), color .25s var(--ease-out),
              border-color .35s var(--ease-out), box-shadow var(--dur-med) var(--ease-expo);
}
.footer-social a svg { width: 19px; height: 19px; position: relative; z-index: 1;
  transition: transform var(--dur-med) var(--ease-expo); }
/* remplissage couleur qui monte depuis le bas au survol */
.footer-social a::before {
  content: ""; position: absolute; inset: 0; z-index: 0;
  background: linear-gradient(180deg, #FF2A2A, #D40000);
  transform: translateY(101%); transition: transform var(--dur-med) var(--ease-expo);
}
.footer-social a:hover, .footer-social a:focus-visible {
  transform: translateY(-5px); color: #fff;
  outline: none;
}
.footer-social a:hover::before, .footer-social a:focus-visible::before { transform: translateY(0); }
.footer-social a:hover svg, .footer-social a:focus-visible svg { transform: scale(1.15) rotate(-4deg); }

/* Couleurs spécifiques par réseau */
.footer-social a[data-social="linkedin"]::before {
  background: linear-gradient(180deg, #0A66C2, #004182);
}
.footer-social a[data-social="linkedin"]:hover, .footer-social a[data-social="linkedin"]:focus-visible {
  border-color: rgba(10, 102, 194, .6);
  box-shadow: 0 12px 26px -8px rgba(10, 102, 194, .55), 0 0 0 1px rgba(10, 102, 194, .4);
}

.footer-social a[data-social="instagram"]::before {
  background: linear-gradient(135deg, #833AB4, #FD1D1D, #F77737);
}
.footer-social a[data-social="instagram"]:hover, .footer-social a[data-social="instagram"]:focus-visible {
  border-color: rgba(225, 48, 108, .6);
  box-shadow: 0 12px 26px -8px rgba(225, 48, 108, .55), 0 0 0 1px rgba(225, 48, 108, .4);
}

.footer-social a[data-social="x"]::before {
  background: linear-gradient(180deg, #1a1a1a, #000);
}
.footer-social a[data-social="x"]:hover, .footer-social a[data-social="x"]:focus-visible {
  border-color: rgba(255, 255, 255, .3);
  box-shadow: 0 12px 26px -8px rgba(0, 0, 0, .7), 0 0 0 1px rgba(255, 255, 255, .2);
}

.footer-social a[data-social="portfolio"]::before {
  background: linear-gradient(180deg, #00D4AA, #00A080);
}
.footer-social a[data-social="portfolio"]:hover, .footer-social a[data-social="portfolio"]:focus-visible {
  border-color: rgba(0, 212, 170, .6);
  box-shadow: 0 12px 26px -8px rgba(0, 212, 170, .55), 0 0 0 1px rgba(0, 212, 170, .4);
}

.footer-social a[data-social="email"]::before {
  background: linear-gradient(180deg, #FF2A2A, #D40000);
}
.footer-social a[data-social="email"]:hover, .footer-social a[data-social="email"]:focus-visible {
  border-color: rgba(255, 40, 30, .55);
  box-shadow: 0 12px 26px -8px rgba(255, 0, 0, .6), 0 0 0 1px rgba(255, 40, 30, .4);
}

@media (prefers-reduced-motion: reduce) {
  .footer-social a, .footer-social a svg, .footer-social a::before { transition: none; }
  .footer-social a:hover { transform: none; }
}

/* ---------- Scroll reveal ----------
   Visible par défaut. Masqué puis révélé seulement si le JavaScript tourne
   (classe « js » posée sur <html> par le script en tête de page). */
:where(html.js) .reveal { opacity: 0; transform: translateY(24px); transition: opacity var(--dur-long) var(--ease-expo), transform var(--dur-long) var(--ease-expo); }
:where(html.js) .reveal.in { opacity: 1; transform: none; }
:where(html.js) .reveal[data-delay="1"] { transition-delay: .08s; }
:where(html.js) .reveal[data-delay="2"] { transition-delay: .16s; }
:where(html.js) .reveal[data-delay="3"] { transition-delay: .24s; }

/* ---------- Reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; scroll-behavior: auto !important; }
  :where(html.js) .reveal { opacity: 1 !important; transform: none !important; transition: none !important; }
  .hero-mesh .blob { animation: none; }
  .marquee-track { animation: none; }
  :where(html.js) .telescope-step { opacity: 1 !important; }
}

/* ---------- Utilities ---------- */
.mt-0 { margin-top: 0; } .mt-2 { margin-top: 2rem; }
.center { text-align: center; }
.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; }

/* =========================================================================
   ITÉRATION 2 — composants additionnels
   ========================================================================= */

/* ---------- Barre de progression de lecture ---------- */
.read-progress { position: fixed; top: 0; left: 0; height: 2px; width: 0; z-index: 200; background: linear-gradient(90deg, #FF1A1A, #FF7A5A); box-shadow: 0 0 12px rgba(255,0,0,.6); transition: width .1s linear; pointer-events: none; }

/* ---------- Tableau comparatif ---------- */
.compare-wrap { margin-top: 2.5rem; }
.compare { width: 100%; border-collapse: separate; border-spacing: 0; font-size: .92rem; }
.compare th, .compare td { padding: 1rem 1.1rem; text-align: left; vertical-align: top; border-bottom: 1px solid var(--line); }
.compare thead th { font-family: var(--font-display); font-size: .82rem; font-weight: 600; color: var(--text); letter-spacing: .01em; background: var(--surface); border-bottom-color: var(--line-strong); }
.compare tbody th { font-weight: 600; color: var(--text-soft); width: 22%; }
.compare td { color: var(--text-muted); }
.compare .col-us { color: var(--text); font-weight: 600; }
/* Colonne Fervolis surlignée */
.compare th.col-us, .compare td.col-us { background: rgba(255,0,0,.07); border-left: 1px solid rgba(255,0,0,.28); border-right: 1px solid rgba(255,0,0,.28); }
.compare thead th.col-us { color: var(--accent); border-top: 1px solid rgba(255,0,0,.28); border-top-left-radius: var(--radius-sm); border-top-right-radius: var(--radius-sm); }
.compare tbody tr:last-child td.col-us { border-bottom: 1px solid rgba(255,0,0,.28); border-bottom-left-radius: var(--radius-sm); border-bottom-right-radius: var(--radius-sm); }
.compare-note { margin-top: 1.4rem; font-size: 1.02rem; color: var(--text-soft); }
.compare-note strong { color: var(--accent); }

@media (max-width: 760px) {
  /* Empilement en cartes : chaque ligne devient une carte, chaque cellule porte son libellé */
  .compare thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0,0,0,0); }
  .compare, .compare tbody, .compare tr, .compare th, .compare td { display: block; width: auto; }
  .compare tr { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: .5rem .9rem; margin-bottom: 1rem; }
  .compare tbody th { width: auto; color: var(--text); font-size: 1.02rem; padding: .7rem 0 .3rem; border-bottom: 1px solid var(--line); }
  .compare td { display: flex; justify-content: space-between; gap: 1rem; padding: .55rem 0; border-bottom: 1px dashed var(--line); }
  .compare td:last-child { border-bottom: 0; }
  .compare td::before { content: attr(data-label); flex: 0 0 42%; color: var(--text-faint); font-size: .82rem; }
  .compare td.col-us { background: rgba(255,0,0,.07); border-radius: var(--radius-sm); border: 1px solid rgba(255,0,0,.28); padding: .55rem .7rem; margin-top: .3rem; }
}

/* ---------- Schéma "mesh" / MCP ---------- */
.mesh-schema { position: relative; border: 1px solid var(--line); border-radius: var(--radius-lg); background: radial-gradient(120% 120% at 50% 0%, var(--surface-2), var(--bg-abyss)); padding: clamp(1.4rem, 1rem + 2vw, 2.6rem); overflow: hidden; }
.mesh-schema svg { width: 100%; height: auto; display: block; }
.mesh-legend { display: flex; flex-wrap: wrap; gap: 1rem 1.6rem; justify-content: center; margin-top: 1.4rem; }
.mesh-legend span { display: inline-flex; align-items: center; gap: .5rem; font-size: .85rem; color: var(--text-muted); }
.mesh-legend i { width: 12px; height: 12px; border-radius: 4px; display: inline-block; }

/* ---------- Console (maquette interface) ---------- */
.console { position: relative; border: 1px solid var(--line-strong); border-radius: var(--radius-lg); overflow: hidden; background: var(--surface); box-shadow: var(--shadow-lg); }
.console-bar {
  /* trois points façon Mac : une ligne à changer pour basculer leurs couleurs */
  --dot-r: #ff5f57; --dot-y: #febc2e; --dot-g: #28c840;
  display: flex; align-items: center; gap: .6rem; padding: .8rem 1rem; background: var(--surface-2); border-bottom: 1px solid var(--line);
}
.console-bar .dot { width: 11px; height: 11px; border-radius: 50%; background: var(--surface-3); flex-shrink: 0; }
.console-bar .dot.r { background: var(--dot-r); } .console-bar .dot.y { background: var(--dot-y); } .console-bar .dot.g { background: var(--dot-g); }
.console-bar .url { margin-left: .6rem; font-size: .8rem; color: var(--text-faint); font-family: ui-monospace, "SFMono-Regular", Menlo, monospace; }
.console-pane { background: var(--bg-base); padding: 1.2rem 1.3rem; }
.console-pane h4 { font-size: .78rem; letter-spacing: .14em; text-transform: uppercase; color: var(--text-faint); margin-bottom: .9rem; font-family: var(--font-body); font-weight: 600; }
.console-doc { font-family: ui-monospace, "SFMono-Regular", Menlo, monospace; font-size: .82rem; line-height: 1.9; color: var(--text-soft); }
.console-foot { display: flex; align-items: center; gap: .6rem; padding: .9rem 1.3rem; border-top: 1px solid var(--line); background: var(--surface); font-size: .82rem; color: var(--text-muted); }

/* Démonstration du masquage (solution.html#console) */
.demo-masquage { margin: 0; }
.demo-toggle {
  order: 1; margin-left: auto; padding: .25rem .8rem; border-radius: var(--radius-pill);
  border: 1px solid var(--line-strong); font-size: .76rem; font-weight: 600; color: var(--text-muted);
  transition: color var(--t-fast), border-color var(--t-fast);
}
.demo-toggle:hover { color: var(--text); border-color: var(--text-faint); }
.demo-toggle[hidden] { display: none; }
/* clair, masqué et couche vivante dans la même cellule : la hauteur suit le plus haut */
.demo-stage { display: grid; }
.demo-layer { grid-area: 1 / 1; min-width: 0; overflow-wrap: anywhere; transition: opacity .5s var(--ease); }
.demo-layer p + p { margin-top: .9em; }
.demo-sizer { visibility: hidden; }
.demo-layer.is-fading { opacity: 0; }
.demo-ent {
  padding: .05em .35em; border-radius: 5px; border: 1px solid transparent; overflow-wrap: anywhere;
  -webkit-box-decoration-break: clone; box-decoration-break: clone;
  transition: color .3s var(--ease), background-color .3s var(--ease), border-color .3s var(--ease);
}
.demo-ent.is-found { color: var(--accent-cyan); background: rgba(255, 138, 90, .12); border-color: rgba(255, 138, 90, .45); }
.demo-ent.is-masked { color: var(--text); font-weight: 600; background: var(--surface-3); border-color: rgba(255, 138, 90, .35); }
.demo-legend { margin-top: .9rem; font-size: .88rem; color: var(--text-faint); max-width: 72ch; }

/* ---------- "Ce que nous masquons" ---------- */
.mask-list { display: flex; flex-wrap: wrap; gap: .65rem; margin-top: 1.4rem; }
.mask-tag { display: inline-flex; align-items: center; gap: .5rem; padding: .5rem .9rem; border-radius: var(--radius-pill); background: var(--surface); border: 1px solid var(--line); font-size: .88rem; color: var(--text-soft); }
.mask-tag svg { width: 15px; height: 15px; color: var(--accent); }

/* ---------- FAQ (accordéon natif) ---------- */
.faq { display: grid; gap: .8rem; max-width: 820px; margin-inline: auto; }
.faq details { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; transition: border-color var(--t-med); }
.faq details[open] { border-color: var(--line-strong); }
.faq summary { list-style: none; cursor: pointer; display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: 1.15rem 1.3rem; font-family: var(--font-display); font-weight: 600; font-size: 1.04rem; color: var(--text); }
.faq summary::-webkit-details-marker { display: none; }
.faq summary:hover { color: var(--accent); }
.faq summary .ico { flex: none; width: 22px; height: 22px; position: relative; }
.faq summary .ico::before, .faq summary .ico::after { content: ""; position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%); background: var(--accent); border-radius: 2px; }
.faq summary .ico::before { width: 13px; height: 2px; }
.faq summary .ico::after { width: 2px; height: 13px; transition: transform var(--t-med); }
.faq details[open] summary .ico::after { transform: translate(-50%,-50%) scaleY(0); }
.faq .faq-a { padding: 0 1.3rem 1.25rem; color: var(--text-muted); font-size: .96rem; line-height: 1.65; }

/* ---------- Cas d'usage : ligne "niveau : critique → console" ---------- */
.usecase-mask { margin-top: 1rem; padding-top: .9rem; border-top: 1px solid var(--line); font-size: .88rem; color: var(--text-muted); }
.usecase-mask strong { display: inline-flex; align-items: center; gap: .4rem; color: var(--accent); font-size: .76rem; letter-spacing: .08em; text-transform: uppercase; }
.usecase-mask strong::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--accent-cyan); box-shadow: 0 0 8px var(--accent-cyan); }

/* ---------- Freins / réponses (objections) ---------- */
.frein .label-q { display: inline-flex; align-items: center; gap: .45rem; font-size: .74rem; letter-spacing: .12em; text-transform: uppercase; color: var(--text-faint); font-weight: 700; margin-bottom: .55rem; }
.frein .label-q::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--text-faint); }
.frein h3 { margin-bottom: .55rem; }
.frein .answer { margin-top: 1.1rem; padding-top: 1rem; border-top: 1px solid var(--line); }
.frein .answer .label-a { display: inline-flex; align-items: center; gap: .45rem; font-size: .74rem; letter-spacing: .12em; text-transform: uppercase; color: var(--accent); font-weight: 700; margin-bottom: .5rem; }
.frein .answer .label-a::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 8px var(--glow); }
.frein .answer p { color: var(--text-soft); }

/* ---------- "De la peur à l'avance" — mini frise ---------- */
.step-flow { display: grid; grid-template-columns: 1fr auto 1fr auto 1fr; align-items: stretch; gap: 1rem; margin-top: 2.5rem; }
.step-flow .sf { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: 1.4rem 1.3rem; text-align: left; }
.step-flow .sf .sf-k { font-family: var(--font-display); font-size: .76rem; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; margin-bottom: .6rem; }
.step-flow .sf.k-fear .sf-k { color: var(--text-faint); }
.step-flow .sf.k-step .sf-k { color: var(--accent); }
.step-flow .sf.k-gain .sf-k { color: var(--accent-cyan); }
.step-flow .sf h4 { font-size: 1.05rem; margin-bottom: .4rem; }
.step-flow .sf p { font-size: .9rem; }
.step-flow .flow-arrow { display: grid; place-items: center; color: var(--accent); }
.step-flow .flow-arrow svg { width: 22px; height: 22px; }
/* Responsive APRÈS les règles de base pour l'emporter dans la cascade */
@media (max-width: 760px) { .step-flow { grid-template-columns: 1fr; } .step-flow .flow-arrow { display: none; } }

/* ---------- Bloc éditorial mis en avant (souveraineté) ---------- */
.note-block { border-left: 2px solid var(--accent); background: linear-gradient(90deg, rgba(255,0,0,.06), transparent 70%); padding: 1.1rem 1.4rem; border-radius: 0 var(--radius) var(--radius) 0; margin: 2rem 0; }
.note-block p { color: var(--text-soft); margin: 0; }

/* ---------- Blog / Insights ---------- */
.blog-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1.5rem;
}
@media (max-width: 760px) { .blog-grid { grid-template-columns: 1fr; } }

.blog-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
  transition: transform var(--t-med), border-color var(--t-med), box-shadow var(--t-med);
}
.blog-card:hover {
  transform: translateY(-4px);
  border-color: var(--line-strong);
  box-shadow: var(--shadow-md);
}
.blog-card:focus-within {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.blog-card-link {
  display: block;
  text-decoration: none;
  color: inherit;
}
.blog-card-link:focus { outline: none; }

.blog-card-img {
  position: relative;
  height: 180px;
  background: linear-gradient(135deg, var(--surface-2), var(--bg-abyss));
  display: flex;
  align-items: flex-start;
  justify-content: flex-start;
  padding: 1rem;
}
.blog-tag {
  display: inline-block;
  padding: .35rem .75rem;
  background: rgba(255, 50, 40, .18);
  border: 1px solid rgba(255, 50, 40, .3);
  border-radius: var(--radius-pill);
  font-size: .75rem;
  font-weight: 600;
  color: var(--accent);
  text-transform: uppercase;
  letter-spacing: .08em;
}

.blog-card-body {
  padding: 1.5rem;
}
.blog-card-body time {
  display: block;
  font-size: .82rem;
  color: var(--text-faint);
  margin-bottom: .6rem;
}
.blog-card-body h2 {
  font-size: 1.25rem;
  line-height: 1.3;
  margin-bottom: .75rem;
  transition: color var(--t-fast);
}
.blog-card:hover h2 { color: var(--accent); }
.blog-card-body p {
  font-size: .95rem;
  color: var(--text-muted);
  line-height: 1.6;
  margin-bottom: 1rem;
}
.blog-read {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  font-weight: 600;
  font-size: .9rem;
  color: var(--accent);
}
/* MOUV-7 : la flèche glisse (transform) au lieu d'élargir l'espace (gap) */
.blog-read svg { transition: transform var(--dur-med) var(--ease-expo); }
.blog-card:hover .blog-read svg { transform: translateX(5px); }

/* ---------- Article (page individuelle) ---------- */
.article-header {
  padding-top: clamp(2rem, 1.5rem + 3vw, 4rem);
  padding-bottom: clamp(2rem, 1.5rem + 2vw, 3rem);
  border-bottom: 1px solid var(--line);
  margin-bottom: clamp(2rem, 1.5rem + 2vw, 3rem);
}
.article-back {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  font-size: .9rem;
  color: var(--text-muted);
  margin-bottom: 1.5rem;
  transition: color var(--t-fast);
}
.article-back:hover { color: var(--accent); }
.article-header .blog-tag { margin-bottom: 1rem; }
.article-header h1 {
  font-size: clamp(1.8rem, 1.4rem + 2vw, 2.8rem);
  line-height: 1.15;
  margin-bottom: 1rem;
}
.article-meta {
  font-size: .9rem;
  color: var(--text-faint);
}
.article-meta time { color: var(--text-muted); }

.article-body {
  padding-bottom: clamp(3rem, 2rem + 4vw, 5rem);
}
.article-body .lead {
  font-size: clamp(1.1rem, 1rem + .5vw, 1.25rem);
  color: var(--text-soft);
  margin-bottom: 2rem;
  line-height: 1.7;
}
.article-body h2 {
  font-size: clamp(1.3rem, 1.1rem + 1vw, 1.7rem);
  margin-top: 2.5rem;
  margin-bottom: 1rem;
}
.article-body h3 {
  font-size: clamp(1.1rem, 1rem + .5vw, 1.3rem);
  margin-top: 2rem;
  margin-bottom: .75rem;
}
.article-body p {
  margin-bottom: 1.25rem;
  line-height: 1.75;
}
.article-body ul, .article-body ol {
  margin-bottom: 1.25rem;
  padding-left: 1.5rem;
}
.article-body ul { list-style: disc; }
.article-body ol { list-style: decimal; }
.article-body li {
  margin-bottom: .5rem;
  line-height: 1.7;
}
.article-body blockquote {
  margin: 2rem 0;
  padding: 1.25rem 1.5rem;
  border-left: 3px solid var(--accent);
  background: var(--surface);
  border-radius: 0 var(--radius) var(--radius) 0;
  font-style: italic;
  color: var(--text-soft);
}
.article-body blockquote p { margin-bottom: 0; }
.article-body strong { color: var(--text); }
.article-body em { color: var(--text-soft); }
/* Marqueurs type [FVL_IBAN_1_A7K2QX] dans le corps des articles */
.article-body code {
  font-family: ui-monospace, "SFMono-Regular", Menlo, monospace;
  font-size: .9em; padding: .08em .4em; border-radius: 5px;
  background: rgba(255,255,255,.06); border: 1px solid var(--line-strong); color: var(--text-soft);
  overflow-wrap: anywhere; /* marqueurs longs : jamais de défilement horizontal */
}
/* Encadré « note / avertissement » (ex. scénario illustratif, non-conseil juridique) */
.article-body .article-note {
  font-size: .92rem; color: var(--text-muted); line-height: 1.65;
  padding: 1rem 1.2rem; margin: 1.5rem 0; border-left: 2px solid var(--accent);
  background: linear-gradient(90deg, rgba(255,0,0,.05), transparent 70%);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}

.article-cta {
  margin-top: 3rem;
  padding: 2rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  text-align: center;
}
.article-cta p {
  margin-bottom: 1.25rem;
  color: var(--text-soft);
}

/* =========================================================================
   OPTIMISATIONS MOBILE (smartphones)
   ========================================================================= */

/* ---------- Petits écrans (< 600px) ---------- */
@media (max-width: 600px) {
  /* Dock mobile plus compact */
  .site-header .wrap {
    padding-inline: .85rem;
    gap: .75rem;
  }
  .brand { gap: .45rem; }
  .brand img { height: 28px; }
  .brand .brand-dot { width: 22px; height: 22px; }
  
  /* Hero mobile */
  .hero { padding-bottom: clamp(2.5rem, 2rem + 4vw, 4rem); }
  .hero-inner h1 { font-size: clamp(2rem, 1.4rem + 3vw, 3rem); }
  .hero .lead { font-size: 1rem; }
  .hero-cta { flex-direction: column; gap: .75rem; }
  .hero-cta .btn { width: 100%; justify-content: center; }
  .hero-note { font-size: .8rem; flex-wrap: wrap; }
  
  /* Page hero mobile */
  .page-hero h1 { font-size: clamp(1.8rem, 1.3rem + 2.5vw, 2.6rem); }
  .page-hero .lead { font-size: .95rem; }
  
  /* Sections */
  .section-head h2 { font-size: clamp(1.6rem, 1.2rem + 2vw, 2.2rem); }
  .section-head .lead { font-size: .95rem; }
  
  /* Cards */
  .card { padding: 1.2rem; }
  .card h3 { font-size: 1.1rem; }
  
  /* Blog cards mobile */
  .blog-card-img { height: 140px; }
  .blog-card-body { padding: 1.2rem; }
  .blog-card-body h2 { font-size: 1.1rem; }
  .blog-card-body p { font-size: .9rem; }
  
  /* Boutons */
  .btn-lg { padding: .9rem 1.5rem; font-size: .95rem; }
  
  /* CTA band */
  .cta-band { padding: clamp(1.8rem, 1.5rem + 2vw, 3rem); }
  .cta-band h2 { font-size: clamp(1.5rem, 1.2rem + 1.5vw, 2rem); }
  
  /* Footer mobile */
  .footer-top { grid-template-columns: 1fr; gap: 1.5rem; }
  .footer-col { text-align: center; }
  .footer-col a { padding: .5rem 0; }
  .footer-bottom { flex-direction: column; text-align: center; gap: .75rem; }
  .footer-disclaimer { text-align: center; }
  
  /* Formulaire */
  .form-card { padding: 1.2rem; }
  .field input, .field textarea { padding: .75rem .9rem; font-size: 16px; }
  
  /* Manifesto */
  .manifesto p { font-size: clamp(1.1rem, 1rem + 1vw, 1.5rem); }
  
  /* Step flow en colonne */
  .step-flow .sf { padding: 1.1rem 1rem; }
  .step-flow .sf h4 { font-size: .95rem; }
  .step-flow .sf p { font-size: .85rem; }
  
  /* Telescope */
  .telescope-visual { height: 240px; }
  .telescope-step h3 { font-size: clamp(1.2rem, 1rem + 1vw, 1.6rem); }
  
  /* FAQ */
  .faq summary { padding: 1rem; font-size: .95rem; }
  .faq .faq-a { padding: 0 1rem 1rem; font-size: .9rem; }
  
  /* Console mock */
  .console-pane { padding: 1rem; }
  .console-doc { font-size: .75rem; line-height: 1.7; }
}

/* ---------- Très petits écrans (< 380px) ---------- */
@media (max-width: 380px) {
  :root {
    --gutter: 1rem;
  }
  
  .site-header .wrap { padding-inline: .7rem; }
  .brand span:not(.brand-dot) { display: none; }
  
  .hero-inner h1 { font-size: 1.75rem; }
  .page-hero h1 { font-size: 1.5rem; }
  
  .btn { padding: .7rem 1rem; font-size: .85rem; }
  .btn-lg { padding: .8rem 1.2rem; font-size: .9rem; }
  
  .card { padding: 1rem; }
  .blog-card-body { padding: 1rem; }
  .blog-card-body h2 { font-size: 1rem; }
}

/* ---------- Amélioration touch ---------- */
@media (hover: none) and (pointer: coarse) {
  /* Désactiver les effets hover sur touch */
  .blog-card:hover { transform: none; }
  .card:hover { transform: none; }
  .btn:hover { transform: none; }
  
  /* Taille minimum des zones tactiles (44px) */
  .nav-links a { min-height: 44px; display: flex; align-items: center; }
  .burger { min-width: 44px; min-height: 44px; }
  .consent input { width: 22px; height: 22px; }
}

/* ---------- Safe area (encoche iPhone) ---------- */
@supports (padding: env(safe-area-inset-bottom)) {
  .site-footer { padding-bottom: calc(2rem + env(safe-area-inset-bottom)); }
  .nav { padding-bottom: calc(2rem + env(safe-area-inset-bottom)); }
}

/* =========================================================================
   CORRECTIFS MOBILE — passe complémentaire
   Tout ce qui suit est enfermé dans des media queries `max-width` ou dans
   `(pointer: coarse)` : l'affichage sur ordinateur n'est pas touché.
   ========================================================================= */

@media (max-width: 860px) {
  /* Filet de sécurité contre le défilement horizontal : `overflow-x` posé sur
     <body> seul n'est pas fiable sur iOS Safari, il faut aussi <html>.
     Sans risque ici : le seul `position: sticky` du site (.telescope-visual)
     repasse en `relative` dès 880px. */
  html { overflow-x: hidden; }
  /* Les ancres internes ne doivent pas passer sous le dock flottant. */
  html { scroll-padding-top: calc(var(--dock-inset) + 1rem); }

  /* Les nuages de fumée : `blur(64px)` appliqué à des surfaces de ~56vw est
     l'un des effets les plus coûteux qui soient pour un GPU de téléphone.
     On réduit le rayon et la taille — le rendu visuel reste très proche. */
  .hero-mesh { filter: blur(38px); opacity: .7; transform: none; }
  .hero-mesh .b1 { width: 78vw; height: 62vw; }
  .hero-mesh .b2 { width: 70vw; height: 58vw; }
  .hero-mesh .b3 { width: 60vw; height: 50vw; }
  .page-hero .hero-mesh { opacity: .45; }

  /* Le maillage SVG animé (une balise <animate> par nœud) est purement
     décoratif et anime en continu : on l'éteint sur mobile. */
  .hero-net { display: none; }

  /* Titres : le français produit des mots longs (« ré-identification »,
     « confidentialité ») qui débordent des petites largeurs. */
  h1, h2, h3, h4 { overflow-wrap: break-word; hyphens: auto; }

  /* La pilule du dock ne doit jamais pousser le burger hors de l'écran. */
  .site-header .wrap { gap: .6rem; }
  .brand { min-width: 0; }
  .brand img { flex-shrink: 0; }
}

@media (max-width: 600px) {
  /* La bande défilante : 3rem d'écart entre les mots mange l'écran. */
  .marquee-track { gap: 1.6rem; }
  .marquee-track span { font-size: .92rem; gap: 1.6rem; }

  /* Maquette de console : ces deux barres sont en `flex` sans retour à la
     ligne, leur texte débordait horizontalement. */
  .console-bar { flex-wrap: wrap; row-gap: .35rem; padding: .7rem .85rem; }
  .console-bar .url { order: 2; margin-left: 0; flex-basis: 100%; font-size: .72rem; }
  .console-foot { flex-wrap: wrap; row-gap: .45rem; padding: .8rem 1rem; font-size: .78rem; }

  /* La démo coupe les marqueurs n'importe où (.demo-layer, .demo-ent) :
     aucun défilement horizontal à 320 px. */
  .console-doc { overflow-wrap: anywhere; }

  /* Réseaux sociaux : le pied de page passe en colonne centrée, la rangée
     d'icônes doit suivre. */
  .footer-social { justify-content: center; }
  .footer-bottom { justify-content: center; }

  /* Frise verticale : on récupère de la largeur utile. */
  .timeline li { padding-left: 1.3rem; padding-bottom: 1.4rem; }

  /* Bandeau d'appel à l'action : 18ch bride inutilement le titre en étroit. */
  .cta-band h2 { max-width: none; }

  /* Blocs éditoriaux et citations : moins de rembourrage latéral. */
  .note-block { padding: 1rem 1.1rem; }
  .article-body blockquote { padding: 1rem 1.1rem; margin: 1.5rem 0; }
  .article-cta { padding: 1.4rem 1.2rem; }

  /* Étapes du pipeline : la flèche pivotée réclame de la place entre les cartes. */
  .pipeline { gap: 2rem; }
}

/* ---------- Ergonomie tactile ---------- */
@media (hover: none) and (pointer: coarse) {
  /* Cibles d'au moins 44 px (recommandation WCAG 2.5.8 / Apple HIG). */
  .btn { min-height: 44px; }
  .footer-col a { min-height: 44px; display: flex; align-items: center; }
  .faq summary { min-height: 44px; }
  .link-arrow, .blog-read, .article-back { min-height: 44px; display: inline-flex; }

  /* Effets de survol restants : sans souris ils restent « collés » après un
     appui, ce qui fige les éléments en position haute. */
  .footer-social a:hover { transform: none; }
  .footer-social a:hover svg { transform: none; }
  .card:hover::before { opacity: 0; }
  .btn-primary:hover, .btn-ghost:hover { transform: none; }
}

/* Le centrage du pied de page appartient au petit écran, pas au tactile en
   général : une tablette en affichage large garde ses colonnes alignées. */
@media (max-width: 600px) and (pointer: coarse) {
  .footer-col a { justify-content: center; }
}

/* =========================================================================
   HEADER MOBILE — deux pastilles flottantes
   Sur ordinateur, la pilule du dock est remplie par les cinq liens de
   navigation et le bouton « Prendre contact » : elle est équilibrée. Sur
   téléphone la navigation part dans le panneau burger et il ne reste qu'un
   logo et un burger dans une capsule large de tout l'écran — 98 px de
   contenu pour 346 px de capsule, soit ~68 % de vide, qui se déformait en
   plus au défilement.
   On dissout donc la capsule et on donne son propre fond à chacun des deux
   éléments : le vocabulaire « dock flottant » du site est conservé, le vide
   disparaît. Bloc borné à 860 px : l'affichage sur ordinateur est intact.
   ========================================================================= */

@media (max-width: 860px) {
  /* La rangée ne fait plus que la hauteur d'une pastille (44 px) : le décalage
     du contenu sous le header (--dock-inset) se resserre d'autant. */
  :root { --header-h: 52px; }

  /* ---------- La capsule disparaît : simple rangée transparente ---------- */
  .site-header { padding-inline: var(--gutter); }
  .site-header .wrap {
    width: 100%;
    min-height: 0;
    padding-inline: 0;
    gap: 1rem;
    background: none;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    /* Plus aucune déformation au défilement : largeur, hauteur, marges et
       espacements ne dépendent plus de --dock-scroll. nav.js cesse par
       ailleurs de faire basculer cette variable sous 861 px. */
    transition: none;
    /* La rangée est invisible : elle ne doit plus intercepter les appuis sur
       toute la largeur de l'écran, seulement sur les deux pastilles. */
    pointer-events: none;
  }
  /* Ce pseudo-élément ne portait le flou que pour la capsule (il évitait que
     `backdrop-filter` sur .wrap ne devienne le bloc conteneur du panneau .nav
     en position fixed — cf. commentaire ligne 245). Sans capsule, il n'a plus
     d'objet, et le flou passe sur chaque pastille, qui n'a pas de descendant
     en position fixed. */
  .site-header .wrap::before { display: none; }

  /* ---------- Pastille du logo ---------- */
  .site-header .brand {
    pointer-events: auto;
    gap: .45rem;
    padding: .38rem .8rem;
    border-radius: var(--radius-pill);
    background: rgba(8, 10, 14, .55);
    backdrop-filter: blur(14px) saturate(140%);
    -webkit-backdrop-filter: blur(14px) saturate(140%);
    border: 1px solid rgba(255, 255, 255, .09);
    box-shadow: 0 4px 18px rgba(0, 0, 0, .3), inset 0 1px 0 rgba(255, 255, 255, .05);
    transition: none;
  }
  .brand img { height: 34px; transition: none; }

  /* ---------- Pastille du burger ---------- */
  .site-header .burger {
    pointer-events: auto;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background: rgba(8, 10, 14, .55);
    backdrop-filter: blur(14px) saturate(140%);
    -webkit-backdrop-filter: blur(14px) saturate(140%);
    border: 1px solid rgba(255, 255, 255, .09);
    box-shadow: 0 4px 18px rgba(0, 0, 0, .3), inset 0 1px 0 rgba(255, 255, 255, .05);
    /* Au-dessus du panneau de navigation. Les règles de la ligne 182
       (`.site-header .burger`, spécificité 0-2-0) l'emportent sur les
       `z-index: 110 / 105` déclarés plus bas sur `.burger` et `.nav` (0-1-0) :
       les deux se retrouvaient à z-index 1 dans le contexte d'empilement de
       .site-header, et c'est l'ordre du HTML qui plaçait le panneau devant le
       burger. Résultat, le burger disparaissait sous le panneau à l'ouverture
       et l'animation en croix restait invisible. */
    z-index: 3;
  }
  /* ---------- LE correctif décisif : sortir le panneau du flux ----------
     `.nav` reçoit bien `position: fixed` ligne 269 — mais avec la spécificité
     0-1-0, alors que `.site-header .nav` ligne 182 pose `position: relative`
     avec 0-2-0. Une media query n'ajoute pas de spécificité : c'est `relative`
     qui l'emportait, et le panneau restait DANS le flux de la pilule, avec son
     `height: 100dvh`. La pilule étant un conteneur flex, elle prenait donc la
     hauteur entière de l'écran — d'où la capsule géante, arrondie à 999 px,
     avec le logo centré verticalement, qui occupait toute la page.
     On repose la valeur ici, à spécificité égale mais plus loin dans le
     fichier, ce qui suffit à l'emporter. */
  .site-header .nav { position: fixed; }

  /* Empilement : le panneau au-dessus du contenu, le burger au-dessus du
     panneau. Le panneau reste cliquable malgré le `pointer-events: none`
     hérité de .wrap. */
  .site-header .nav { pointer-events: auto; z-index: 2; }

  /* Barres du burger recentrées pour la nouvelle taille (44 px au lieu de 40) :
     centres à 16 / 22 / 28 px, écart de 6 px conservé — les `translateY(±6px)`
     de l'état ouvert continuent donc de former une croix centrée. */
  .burger span { left: 13px; right: 13px; }
  .burger span:nth-child(1) { top: 15px; }
  .burger span:nth-child(2) { top: 21px; }
  .burger span:nth-child(3) { top: 27px; }
}

/* ---------- Safe area gauche / droite / haut (viewport-fit=cover) ----------
   Avec viewport-fit=cover, la page passe sous l'encoche en paysage : les
   marges latérales ne descendent jamais sous l'encart de sécurité. Le haut est
   pris dans --dock-top (tokens.css). Sur ordinateur, env() vaut 0 : rien ne
   change. Bloc en fin de fichier pour l'emporter sur les media queries. */
@supports (padding: max(0px, env(safe-area-inset-left))) {
  .wrap, .wrap-narrow {
    padding-left: max(var(--gutter), env(safe-area-inset-left));
    padding-right: max(var(--gutter), env(safe-area-inset-right));
  }
  .site-header {
    padding-left: max(calc(var(--gutter) + var(--dock-scroll) * 4vw), env(safe-area-inset-left));
    padding-right: max(calc(var(--gutter) + var(--dock-scroll) * 4vw), env(safe-area-inset-right));
  }
  @media (max-width: 860px) {
    .site-header {
      padding-left: max(var(--gutter), env(safe-area-inset-left));
      padding-right: max(var(--gutter), env(safe-area-inset-right));
    }
    .nav { padding-right: max(var(--gutter), env(safe-area-inset-right)); }
  }
}

/* ---------- Fond porté par la racine sur écran tactile (FOND-1) ----------
   Sur iPhone, tout élément en `position: fixed` s'arrête au-dessus de la
   barre d'outils de Safari, même en 100lvh : la grille, la lueur et le grain
   laissaient une bande noire en bas. Seul le fond de <html> peint tout le
   canevas (sous la barre d'outils, sous la barre d'état, pendant le rebond).
   Sur écran tactile, le fond passe donc là, en couches de haut en bas :
   lueur (ancrée en haut, défile avec la page), grain, grille. Les opacités
   des anciens calques (grain .045, grille .5 ou .1 sur l'accueil) sont
   intégrées aux couleurs. La grille défile avec la page : c'est voulu.
   Sur ordinateur (survol et pointeur fin), rien ne change. */
@media (hover: none), (pointer: coarse) {
  html {
    --fond-grille-fort: rgba(255,115,0,.21);
    --fond-grille-fin: rgba(255,140,25,.06);
    --fond-images:
      radial-gradient(760px 420px at 50% 0%, rgba(255, 45, 35, .17), transparent 68%),
      radial-gradient(1100px 620px at 50% -4%, rgba(255, 0, 0, .13), transparent 58%),
      radial-gradient(800px 500px at 88% 6%, rgba(255, 40, 30, .07), transparent 55%),
      url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.045'/%3E%3C/svg%3E"),
      linear-gradient(var(--fond-grille-fort) 1px, transparent 1px),
      linear-gradient(90deg, var(--fond-grille-fort) 1px, transparent 1px),
      linear-gradient(var(--fond-grille-fin) 1px, transparent 1px),
      linear-gradient(90deg, var(--fond-grille-fin) 1px, transparent 1px);
    /* Sur iOS, 100vh vaut le grand viewport : même boîte que l'ancien body::before. */
    --fond-tailles: 100% 100vh, 100% 100vh, 100% 100vh, 160px 160px, 68px 68px, 68px 68px, 17px 17px, 17px 17px;
    --fond-repetitions: no-repeat, no-repeat, no-repeat, repeat, repeat, repeat, repeat, repeat;
    --fond-positions: 50% 0, 50% 0, 50% 0, 0 0, 0 0, 0 0, 0 0, 0 0;
    background-color: var(--bg-abyss);
    background-image: var(--fond-images);
    background-size: var(--fond-tailles);
    background-repeat: var(--fond-repetitions);
    background-position: var(--fond-positions);
  }
  /* Accueil : grille quasi absente (ancienne opacité .1), la vidéo reste fixe
     et le canevas prend le relais sous la barre d'outils. */
  html:has(.bg-video-wrap) {
    --fond-grille-fort: rgba(255,115,0,.042);
    --fond-grille-fin: rgba(255,140,25,.012);
  }
  body::before, body::after, body .bg-grid { display: none; }
}

/* ---------- Voile du menu sur le canevas (FOND-2) ----------
   Le voile fixe (.nav-scrim) s'arrête lui aussi au-dessus de la barre
   d'outils de Safari : une bande claire restait en bas, menu ouvert. On
   assombrit donc le canevas lui-même, en ajoutant une couche rgba(0,0,0,.5)
   en tête du fond de <html> ; .nav-scrim reste pour la partie haute.
   La couche est un pavé de 1 px répété : menu ouvert, <body> passe en
   `position: fixed` (verrou de défilement de nav.js) et <html> n'a plus de
   hauteur, un 100 % ne couvrirait rien. Sur ordinateur, rien ne change. */
@media (hover: none), (pointer: coarse) {
  html:has(> body.nav-open) {
    background-image: linear-gradient(rgba(0,0,0,.5), rgba(0,0,0,.5)), var(--fond-images);
    background-size: 1px 1px, var(--fond-tailles);
    background-repeat: repeat, var(--fond-repetitions);
    background-position: 0 0, var(--fond-positions);
  }
}

/* ---------- Bandeau « entreprise en création » (S3A-1) ----------
   Information transitoire, dans le flux sous le dock : ni fixe, ni
   refermable. Premier enfant de <main>, avant le héros ; le héros remonte
   sous le dock (marge négative), d'où position + z-index pour rester
   au-dessus de ses halos. À retirer avec le balisage BANDEAU-CREATION. */
.bandeau-creation { position: relative; z-index: 2; }
.bandeau-creation p {
  max-width: 100%;
  margin: .2rem auto 0;
  padding: .45rem .9rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  color: var(--text-faint);
  font-size: .8125rem;
  line-height: 1.5;
  text-align: center;
  text-shadow: none;
  overflow-wrap: break-word;
}
/* DEV-1 : la mention MENTION-DEV réutilise le même bloc, juste après.
   Chaque bloc est autonome (son propre conteneur entre ses commentaires) :
   l'un retiré, l'autre reste seul ; les deux retirés, rien ne s'affiche.
   Deux bandeaux qui se suivent : léger écart entre les deux. */
.bandeau-creation + .bandeau-creation p { margin-top: .3rem; }
.bandeau-creation a { color: var(--text-muted); text-decoration: underline; text-underline-offset: 2px; white-space: nowrap; }
.bandeau-creation a:hover { color: var(--text); }

/* DEV-2 : précision discrète près des offres (solution.html) et du
   formulaire (contact.html), à retirer avec son balisage MENTION-DEV. */
.mention-dev {
  max-width: 70ch;
  margin: 1.25rem 0 0;
  color: var(--text-faint);
  font-size: .875rem;
  line-height: 1.55;
}
.form-card > .mention-dev { margin: 0 0 1.25rem; }

/* =========================================================================
   S3b — MOUVEMENT ET FLUIDITÉ
   Règles communes : on n'anime que transform, opacity (et clip-path) ;
   tout est enfermé dans (prefers-reduced-motion: no-preference) ou annulé
   en reduced-motion ; sans JavaScript, tout reste visible.
   ========================================================================= */

/* ---------- MOUV-2 : transitions entre les pages ----------
   Transitions de documents natives (Chrome, Edge, Safari récents) ; les
   autres navigateurs naviguent normalement. Le dock reçoit un nom de
   transition dédié (« dock ») seulement pendant le changement de page :
   classe .vt-nav posée par le petit script en tête (pageswap / pagereveal).
   Nommé en permanence, il deviendrait une « racine de fond » et le flou de
   sa pilule ne verrait plus la page derrière lui. Le dock reste donc en
   place ; seul le contenu fait un fondu court avec un léger glissement. */
@media (prefers-reduced-motion: no-preference) {
  @view-transition { navigation: auto; }
  html.vt-nav .site-header { view-transition-name: dock; }
  ::view-transition-old(root) { animation: vt-sortie var(--dur-short) var(--ease-soft) both; }
  ::view-transition-new(root) { animation: vt-entree 280ms var(--ease-expo) both; }
  ::view-transition-group(dock) { animation-duration: 280ms; animation-timing-function: var(--ease-expo); }
}
@keyframes vt-sortie { to   { opacity: 0; transform: translateY(-6px); } }
@keyframes vt-entree { from { opacity: 0; transform: translateY(10px); } }

/* ---------- MOUV-3 : apparitions au défilement en CSS natif ----------
   Là où le navigateur connaît animation-timeline: view(), c'est le
   défilement lui-même qui anime les .reveal : montée de 18 px et fondu,
   terminés quand l'élément a parcouru 220 px dans l'écran. reveal.js
   détecte la même fonction et n'observe alors plus les .reveal : les deux
   mécanismes ne s'additionnent jamais. Ailleurs (Firefox, anciens Safari),
   reveal.js garde son comportement. Toujours sous html.js (S2S-1).
   La montée passe par la propriété individuelle `translate` (famille
   transform, composée sur le GPU) : `transform` reste libre pour le survol
   des cartes et des boutons. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    :where(html.js) .reveal {
      opacity: 1;
      transform: none;
      animation: reveal-defilement linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 220px;
    }
    :where(html.js) .reveal[data-delay="1"] { animation-range: entry 24px entry 244px; }
    :where(html.js) .reveal[data-delay="2"] { animation-range: entry 48px entry 268px; }
    :where(html.js) .reveal[data-delay="3"] { animation-range: entry 72px entry 292px; }
  }
}
@keyframes reveal-defilement {
  from { opacity: 0; translate: 0 18px; }
  to   { opacity: 1; translate: none; }
}

/* ---------- MOUV-4 : titres qui se révèlent mot par mot ----------
   motion.js remplace le contenu du titre par un .sr-only (la phrase, pour
   les lecteurs d'écran) et une copie aria-hidden découpée en .mot. Un mot
   simple (.mot-bloc) passe en inline-block sur grand écran seulement : sous
   861 px les titres ont `hyphens: auto`, qu'un inline-block empêcherait ;
   les mots y restent en ligne et apparaissent en fondu seul (translate est
   sans effet sur une boîte en ligne). Les retours à la ligne sont donc
   ceux du titre d'origine. Cascade : --i (rang du mot) × --pas (≤ 40 ms,
   total < 700 ms), après --split-base. Un titre .split-pret qui n'a pas
   encore reçu .split-joue attend, mots masqués (h2 hors de l'écran). */
.mot { display: inline; }
@media (min-width: 861px) { .mot-bloc { display: inline-block; } }
.split-visuel { user-select: none; -webkit-user-select: none; }
@media (prefers-reduced-motion: no-preference) {
  :where(html.js) .split-pret .mot {
    animation: mot-entree 420ms var(--ease-expo) backwards;
    animation-delay: calc(var(--split-base, 0ms) + var(--i, 0) * var(--pas, 40ms));
  }
  :where(html.js) .split-pret:not(.split-joue) .mot { animation-play-state: paused; }
}
@keyframes mot-entree {
  from { opacity: 0; translate: 0 .3em; }
  to   { opacity: 1; translate: none; }
}

/* ---------- MOUV-5 : arrivée du héros ----------
   Au chargement, le contenu du héros entre en séquence : sur-titre (0 ms),
   titre (80 ms, mot par mot via MOUV-4), paragraphe (200 ms), boutons
   (300 ms), le reste (380 ms) ; 450 ms chacun : tout est en place avant
   900 ms. Animation CSS au temps, pas au script : si motion.js ne tourne
   pas, elle se termine quand même, contenu visible. Sans JavaScript (pas de
   html.js) ou en reduced-motion : aucune animation. Titre non découpé
   (script absent ou arrivé tard) : il apparaît d'un bloc à 350 ms ; ce délai
   laisse à motion.js le temps de le découper avant qu'il ne se montre. */
@media (prefers-reduced-motion: no-preference) {
  :where(html.js) :is(.hero-inner, .page-hero > .wrap, .page-hero > .wrap-narrow, .article-header > .wrap-narrow) > :not(.hero-inner) {
    animation: heros-entree 450ms var(--ease-expo) 380ms backwards;
  }
  :where(html.js) :is(.hero-inner, .page-hero > .wrap, .page-hero > .wrap-narrow, .article-header > .wrap-narrow) > :is(.eyebrow, .article-back, .blog-tag) { animation-delay: 0ms; }
  :where(html.js) :is(.hero-inner, .page-hero > .wrap, .page-hero > .wrap-narrow, .article-header > .wrap-narrow) > :is(.lead, .article-meta) { animation-delay: 200ms; }
  :where(html.js) :is(.hero-inner, .page-hero > .wrap, .page-hero > .wrap-narrow, .article-header > .wrap-narrow) > .hero-cta { animation-delay: 300ms; }
  :where(html.js) :is(.hero-inner, .page-hero > .wrap, .page-hero > .wrap-narrow, .article-header > .wrap-narrow) > h1 { animation-delay: 350ms; --split-base: 80ms; }
  :where(html.js) :is(.hero-inner, .page-hero > .wrap, .page-hero > .wrap-narrow, .article-header > .wrap-narrow) > h1.split-pret { animation: none; }
}
@keyframes heros-entree {
  from { opacity: 0; translate: 0 14px; }
  to   { opacity: 1; translate: none; }
}

/* ---------- MOUV-6 : lueur qui suit le pointeur ----------
   Ordinateur seulement. motion.js pose --mx / --my (px) sur la carte, la
   carte d'article ou la fenêtre de démonstration survolée, et la classe
   .lueur-on. ::after : lueur orange braise (opacité ≤ 0,10) centrée sur le
   pointeur ; ::before : la bordure s'éclaire du côté du pointeur. Les deux
   n'animent que leur opacité (fondu à l'entrée et à la sortie). Valeurs par
   défaut au centre : sans le script, l'anneau de survol des .card reste
   celui d'avant. */
@media (hover: hover) and (pointer: fine) {
  .card, .blog-card, .demo-masquage .console { --mx: 50%; --my: 50%; isolation: isolate; }
  .blog-card { position: relative; }
  .card::after, .blog-card::after, .demo-masquage .console::after,
  .blog-card::before, .demo-masquage .console::before {
    content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
    opacity: 0; transition: opacity var(--dur-med) var(--ease-soft);
  }
  .card::before, .card::after, .blog-card::before, .blog-card::after,
  .demo-masquage .console::before, .demo-masquage .console::after { z-index: 3; }
  .card::after, .blog-card::after, .demo-masquage .console::after {
    background: radial-gradient(420px circle at var(--mx) var(--my), rgba(255, 138, 90, .10), transparent 62%);
  }
  .card::before, .blog-card::before, .demo-masquage .console::before {
    padding: 1px;
    background:
      radial-gradient(260px circle at var(--mx) var(--my), rgba(255, 138, 90, .5), transparent 70%),
      var(--grad-soft);
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor; mask-composite: exclude;
  }
  .lueur-on::before, .lueur-on::after { opacity: 1; }
}

/* ---------- MOUV-7 : boutons vivants ----------
   Partout : léger enfoncement au clic, flèches qui glissent au survol
   (règles .btn-arrow, .link-arrow, .blog-read plus haut, en transform).
   Ordinateur : les boutons principaux du contenu suivent le pointeur qui
   s'approche (--ax / --ay posés par motion.js, 6 px au plus, propriété
   `translate`, indépendante du `transform` du survol), puis reviennent avec
   un rebond doux. Le focus clavier n'est jamais déplacé : un bouton
   :focus-visible garde translate: none, et son contour reste celui du site. */
@media (prefers-reduced-motion: no-preference) {
  .btn:active, .site-header .btn:active { transform: scale(.97); transition-duration: 90ms; }
}
@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
  main .btn-primary {
    translate: var(--ax, 0px) var(--ay, 0px);
    transition: transform .45s var(--ease-fluid), box-shadow .45s var(--ease-fluid), background var(--t-med), border-color var(--t-med),
                translate 160ms var(--ease-expo);
  }
  main .btn-primary.aimant-retour {
    transition: transform .45s var(--ease-fluid), box-shadow .45s var(--ease-fluid), background var(--t-med), border-color var(--t-med),
                translate 700ms cubic-bezier(.34, 1.56, .64, 1);
  }
  main .btn-primary:focus-visible { translate: none; }
}
