/* Feuille de styles commune à index.html et formation.html.
   Extraite du <style> inline pour que les deux pages partagent
   exactement le même socle : dupliquer le bloc aurait garanti une
   dérive entre les deux dès la première retouche. */
  /* Stardom — display serif haut contraste, graisse unique 400.
     Fichier local, donc pas de font-display:swap nécessaire côté CDN. */
  @font-face{
    font-family:'Stardom';
    src:url('fonts/stardom-400.woff2') format('woff2');
    font-weight:400;
    font-style:normal;
    font-display:swap;
  }

  :root{
    --ink:#05070a;
    --panel:#0c1119;
    --steel-line:#1e2933;
    /* #5b7186 à l'origine : 3,99:1 sur --ink et 3,74:1 sur --panel, sous
       le seuil AA de 4,5. Remonté à 4,76:1 / 5,07:1. L'écart visuel est
       imperceptible, y compris sur --chrome-grad dont c'est la borne
       sombre. */
    --steel-mid:#6b8299;
    --chrome-hi:#eef4fb;
    --ice:#8fb4d9;
    --tally:#ff3b3b;
    --text-hi:#eef3ff;
    --text-mid:#a6b3c4;
    --text-low:#7c8a9c;
    --glass-fill:rgba(140,165,190,0.045);
    --glass-fill-strong:rgba(140,165,190,0.08);
    --glass-border:rgba(150,175,200,0.14);
    --glass-border-strong:rgba(200,220,240,0.28);
    --chrome-grad:linear-gradient(135deg,var(--chrome-hi),var(--ice) 55%,var(--steel-mid));
    --tag-blue:#4da6ff;
    --tag-blue-rgb:77,166,255; /* mêmes canaux, pour les rgba() */
    /* Confirmation de copie : le bleu du site, pas un vert de succès
       générique. Pointe le token, il suit si --tag-blue change. */
    --copy-ok:var(--tag-blue);
    --radius-lg:20px;
    --radius-md:12px;
    --radius-sm:6px;
    --ease:cubic-bezier(.22,.9,.32,1);
    --ease-in-out:cubic-bezier(.77,0,.175,1);
  }

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

  body{
    background:
      radial-gradient(1400px 900px at 50% -20%, rgba(140,175,210,0.10), transparent 60%),
      var(--ink);
    color:var(--text-hi);
    font-family:'Inter',sans-serif;
    -webkit-font-smoothing:antialiased;
    overflow-x:hidden;
  }

  h1,h2,h3,.display{font-family:'Big Shoulders Display',sans-serif;letter-spacing:0.01em;text-transform:uppercase;}
  .mono{font-family:'IBM Plex Mono',monospace;letter-spacing:0.08em;}

  a{color:inherit;text-decoration:none;}
  img,video{display:block;max-width:100%;}

  a:focus-visible,button:focus-visible{outline:2px solid var(--ice);outline-offset:3px;border-radius:4px;}

  /* ---------- MONITOR ATMOSPHERE ---------- */
  .bg-pattern{
    position:fixed;inset:0;z-index:0;pointer-events:none;
    --mx:50%; --my:40%; --m-strength:0;
    background-image:
      linear-gradient(to right, rgba(150,175,200,0.07) 1px, transparent 1px),
      linear-gradient(to bottom, rgba(150,175,200,0.07) 1px, transparent 1px);
    background-size:32px 32px;
    -webkit-mask-image:radial-gradient(ellipse at center, black, transparent);
    mask-image:radial-gradient(ellipse at center, black, transparent);
  }
  /* halo réactif : mêmes lignes, en bleu, révélées sous le curseur */
  .bg-pattern::before{
    content:'';position:absolute;inset:0;
    background-image:
      linear-gradient(to right, rgba(120,190,255,0.55) 1px, transparent 1px),
      linear-gradient(to bottom, rgba(120,190,255,0.55) 1px, transparent 1px);
    background-size:32px 32px;
    opacity:var(--m-strength);
    -webkit-mask-image:radial-gradient(circle 230px at var(--mx) var(--my),
      rgba(0,0,0,1) 0%, rgba(0,0,0,0.55) 38%, rgba(0,0,0,0.15) 62%, transparent 78%);
    mask-image:radial-gradient(circle 230px at var(--mx) var(--my),
      rgba(0,0,0,1) 0%, rgba(0,0,0,0.55) 38%, rgba(0,0,0,0.15) 62%, transparent 78%);
    transition:opacity .4s var(--ease);
  }
  /* nappe lumineuse diffuse sous le curseur */
  .bg-pattern::after{
    content:'';position:absolute;inset:0;
    opacity:var(--m-strength);
    background:radial-gradient(circle 260px at var(--mx) var(--my),
      rgba(77,166,255,0.10) 0%, rgba(77,166,255,0.045) 42%, transparent 72%);
    transition:opacity .4s var(--ease);
  }
  /* extinction par inactivité : fondu plus lent que l'allumage */
  .bg-pattern.is-idle::before,.bg-pattern.is-idle::after{transition-duration:1.2s;}
  @media (hover:none),(pointer:coarse){ .bg-pattern::before,.bg-pattern::after{display:none;} }
  .vignette{
    position:fixed;inset:0;z-index:0;pointer-events:none;
    background:radial-gradient(circle at 50% 40%, transparent 40%, rgba(0,0,0,0.55) 100%);
  }
  .scanlines{
    position:fixed;inset:0;z-index:0;pointer-events:none;opacity:0.35;
    background:repeating-linear-gradient(to bottom, rgba(255,255,255,0.025) 0px, rgba(255,255,255,0.025) 1px, transparent 1px, transparent 3px);
  }
  @media (prefers-reduced-motion:reduce){ .scanlines{opacity:0.2;} }
  @media (prefers-reduced-motion:reduce){
    *,*::before,*::after{
      animation-duration:0.01ms !important;
      animation-iteration-count:1 !important;
      transition-duration:120ms !important;
    }
  }

  /* ---------- SCRUB RAIL (signature element) ---------- */
  .scrub-rail{
    position:fixed;top:0;right:18px;height:100vh;width:24px;z-index:60;
    display:flex;flex-direction:column;align-items:center;
    pointer-events:none;
  }
  .scrub-rail .track{position:relative;width:1px;height:100%;background:var(--steel-line);}
  .scrub-rail .playhead{
    position:absolute;left:50%;top:0;width:9px;height:9px;
    transform:translate(-50%,-50%);border-radius:2px;rotate:45deg;
    background:var(--chrome-grad);
    box-shadow:0 0 10px rgba(143,180,217,0.7);
  }
  .scrub-rail .tc{
    position:fixed;bottom:16px;right:14px;font-size:11px;color:var(--text-low);
    letter-spacing:0.1em;
  }
  @media (max-width:720px){ .scrub-rail{display:none;} }

  .wrap{position:relative;z-index:1;max-width:1180px;margin:0 auto;padding:0 32px;}

  /* ---------- NAV ---------- */
  header{
    position:sticky;top:0;z-index:50;
    backdrop-filter:blur(18px) saturate(140%);
    background:rgba(5,7,10,0.6);
    border-bottom:1px solid var(--steel-line);
  }
  nav{
    display:flex;align-items:center;justify-content:space-between;
    padding:18px 32px;max-width:1180px;margin:0 auto;
  }
  .logo{font-size:16px;font-weight:600;display:flex;align-items:center;gap:11px;letter-spacing:0.06em;}

  /* ---------- LOGO : badge verre bleu + chrome ---------- */
  .logo-badge{
    --badge-size:34px;
    position:relative;flex-shrink:0;
    width:var(--badge-size);height:var(--badge-size);
    border-radius:10px;
    display:grid;place-items:center;
    overflow:hidden;isolation:isolate;
    background:
      radial-gradient(120% 100% at 50% 0%, rgba(120,180,255,0.22), transparent 60%),
      linear-gradient(165deg, #16283f 0%, #0a1420 48%, #060b12 100%);
    box-shadow:
      inset 0 1px 0 rgba(190,225,255,0.30),
      inset 0 0 0 1px rgba(120,180,255,0.16),
      inset 0 -8px 14px -8px rgba(77,166,255,0.55),
      0 6px 18px -8px rgba(77,166,255,0.55),
      0 0 22px -6px rgba(77,166,255,0.30);
    transition:box-shadow .4s var(--ease), transform .4s var(--ease);
  }
  /* anneau spéculaire qui tourne lentement (matière polie) */
  .logo-badge::before{
    content:'';position:absolute;inset:-40%;z-index:0;
    background:conic-gradient(from 0deg,
      transparent 0deg, rgba(77,166,255,0.55) 42deg,
      rgba(190,225,255,0.9) 60deg, rgba(77,166,255,0.5) 78deg,
      transparent 130deg, transparent 360deg);
    opacity:0.45;
    animation:badge-spin 7s linear infinite;
  }
  @keyframes badge-spin{to{transform:rotate(360deg);}}
  /* masque intérieur : ne laisse l'anneau visible que sur le liseré */
  .logo-badge::after{
    content:'';position:absolute;inset:1px;z-index:1;border-radius:9px;
    background:linear-gradient(165deg, #16283f 0%, #0a1420 48%, #060b12 100%);
  }
  .logo-mark{
    position:relative;z-index:2;
    width:118%;height:118%;
    object-fit:cover;
    display:block;
    mix-blend-mode:screen;
    filter:saturate(1.5) contrast(1.12) brightness(1.12)
           drop-shadow(0 0 7px rgba(77,166,255,0.75));
    transition:filter .4s var(--ease), transform .5s var(--ease);
  }
  /* reflet spéculaire qui balaie la surface */
  .logo-glint{
    position:absolute;inset:0;z-index:3;pointer-events:none;border-radius:inherit;
    overflow:hidden;
  }
  .logo-glint::before{
    content:'';position:absolute;top:-60%;left:-120%;
    width:60%;height:220%;
    background:linear-gradient(90deg, transparent, rgba(255,255,255,0.55), transparent);
    transform:rotate(18deg);
    animation:badge-glint 6s var(--ease) 1.5s infinite;
  }
  @keyframes badge-glint{
    0%{left:-120%;} 18%{left:170%;} 100%{left:170%;}
  }
  .logo:hover .logo-badge{
    transform:translateY(-1px);
    box-shadow:
      inset 0 1px 0 rgba(190,225,255,0.45),
      inset 0 0 0 1px rgba(120,180,255,0.30),
      inset 0 -8px 14px -8px rgba(77,166,255,0.75),
      0 8px 22px -8px rgba(77,166,255,0.75),
      0 0 30px -4px rgba(77,166,255,0.45);
  }
  .logo:hover .logo-mark{
    filter:saturate(1.7) contrast(1.15) brightness(1.25)
           drop-shadow(0 0 11px rgba(77,166,255,0.95));
    transform:scale(1.06);
  }
  .logo-badge.is-small{--badge-size:24px;border-radius:7px;margin-right:9px;}
  .logo-badge.is-small::after{inset:1px;border-radius:6px;}
  .logo-text{
    background:linear-gradient(180deg, #ffffff 0%, #cfe4ff 42%, var(--tag-blue) 100%);
    -webkit-background-clip:text;background-clip:text;color:transparent;
  }

  .navlinks{display:flex;gap:34px;font-size:13px;color:var(--text-mid);font-family:'IBM Plex Mono',monospace;letter-spacing:0.03em;position:relative;}
  .navlinks a{transition:color .25s var(--ease);position:relative;}
  .navlinks a::after{
    content:'';position:absolute;left:0;bottom:-6px;width:100%;height:1px;
    background:var(--tag-blue);transform:scaleX(0);transform-origin:left;
    transition:transform .3s var(--ease);
  }
  .navlinks a.is-active{color:var(--text-hi);}
  .mobile-menu a.is-active{color:var(--text-hi);}
  .nav-indicator{
    position:absolute;left:0;bottom:-6px;height:1px;width:0;
    background:var(--tag-blue);
    transition:transform .4s var(--ease-in-out), width .4s var(--ease-in-out), opacity .25s var(--ease);
    opacity:0;pointer-events:none;
  }
  @media (max-width:720px){
    .navlinks{display:none;}
    nav .btn-ghost{min-height:44px;padding:12px 20px;}
  }

  /* ---------- MOBILE NAV DRAWER ---------- */
  .nav-toggle{
    display:none;width:44px;height:44px;border-radius:6px;
    align-items:center;justify-content:center;
    background:var(--glass-fill);border:1px solid var(--glass-border);
    cursor:pointer;flex-shrink:0;
  }
  .nav-toggle svg{width:18px;height:18px;stroke:var(--text-hi);}
  @media (max-width:720px){.nav-toggle{display:flex;}}
  .mobile-menu{
    position:absolute;top:100%;left:0;right:0;
    display:flex;flex-direction:column;
    clip-path:inset(0 0 100% 0);opacity:0;pointer-events:none;
    background:rgba(5,7,10,0.92);backdrop-filter:blur(18px) saturate(140%);
    border-bottom:1px solid transparent;
    transition:clip-path .4s var(--ease), opacity .3s var(--ease), border-color .4s var(--ease);
  }
  .mobile-menu.is-open{clip-path:inset(0 0 0 0);opacity:1;border-bottom-color:var(--steel-line);pointer-events:auto;}
  .mobile-menu a{
    padding:16px 32px;font-size:14px;color:var(--text-mid);
    font-family:'IBM Plex Mono',monospace;letter-spacing:0.03em;
    border-top:1px solid var(--steel-line);min-height:44px;display:flex;align-items:center;
  }
  .mobile-menu a:focus-visible{color:var(--text-hi);}

  /* ---------- GLASS PANEL BASE ---------- */
  .glass{
    position:relative;
    background:var(--panel);
    border:1px solid var(--glass-border);
    border-radius:var(--radius-lg);
    overflow:hidden;
  }

  /* ---------- HERO (viewport HUD) ---------- */
  .hero{padding:64px 0 70px;position:relative;}
  @keyframes hero-in{from{opacity:0;transform:translateY(24px);}to{opacity:1;transform:translateY(0);}}
  .hero .eyebrow{animation:hero-in .6s var(--ease) both;}
  .hero h1{animation:hero-in .6s var(--ease) .08s both;}
  .hero p.lead{animation:hero-in .6s var(--ease) .16s both;}
  .hero .cta-row{animation:hero-in .6s var(--ease) .24s both;}
  .hero .hero-stats{animation:hero-in .6s var(--ease) .32s both;}
  .viewport{
    position:relative;
    border:1px solid var(--steel-line);
    border-radius:var(--radius-sm);
    padding:46px 40px 54px;
    /* stacking context local : garde le ::before (z-index:-1) devant
       .bg-pattern. NB : surtout pas isolation:isolate ici — la spec
       en fait un "Backdrop Root", ce qui viderait le backdrop-filter. */
    z-index:0;
  }
  /* flou seul : floute la grille et les orbs derrière le cadre.
     z-index négatif = peinte avant le contenu du viewport, donc
     jamais par-dessus le texte. */
  .viewport::before{
    content:'';
    position:absolute;inset:0;z-index:-1;
    border-radius:inherit;
    backdrop-filter:blur(6px);
    -webkit-backdrop-filter:blur(6px);
    /* légère lueur autour du cadre. Portée par le ::before et non par
       .viewport, dont le box-shadow est déjà animé par vp-focus. */
    box-shadow:
      0 0 24px -4px rgba(143,180,217,0.16),
      0 0 60px -10px rgba(77,166,255,0.13);
    pointer-events:none;
  }
  /* coins en SVG : le tracé d'ouverture se fait en stroke-dashoffset */
  .vp-corner{
    position:absolute;width:20px;height:20px;pointer-events:none;overflow:visible;
  }
  .vp-corner path{
    fill:none;stroke:var(--steel-mid);stroke-width:2;
    stroke-linecap:round;stroke-linejoin:round;
  }
  .vp-corner.tl{top:-1px;left:-1px;}
  .vp-corner.tr{top:-1px;right:-1px;}
  .vp-corner.bl{bottom:-1px;left:-1px;}
  .vp-corner.br{bottom:-1px;right:-1px;}
  .vp-hud-top,.vp-hud-bottom{
    position:absolute;left:16px;right:16px;display:flex;justify-content:space-between;
    font-family:'IBM Plex Mono',monospace;font-size:11px;color:var(--text-low);letter-spacing:0.06em;
  }
  .vp-hud-top{top:14px;}
  .vp-hud-bottom{bottom:14px;}
  .vp-hud-top .rec{color:var(--tally);}
  .vp-hud-top .rec::before{content:'●';margin-right:5px;animation:pulse-rec 1.6s linear infinite;display:inline-block;}
  @keyframes pulse-rec{0%,100%{opacity:1;}50%{opacity:0.25;}}

  /* --- Idle : balayage de scan lent dans le viewport --- */
  .vp-scan{
    position:absolute;inset:0;border-radius:inherit;overflow:hidden;
    pointer-events:none;z-index:0;
  }
  .vp-scan::after{
    content:'';position:absolute;left:0;right:0;top:0;height:34%;
    background:linear-gradient(to bottom,
      transparent 0%,
      rgba(143,180,217,0.035) 45%,
      rgba(190,220,255,0.075) 72%,
      rgba(190,220,255,0.14) 88%,
      transparent 100%);
    animation:vp-sweep 11s cubic-bezier(.55,0,.45,1) infinite;
  }
  @keyframes vp-sweep{
    0%   {transform:translateY(-120%);opacity:0;}
    12%  {opacity:1;}
    76%  {opacity:1;}
    88%  {transform:translateY(320%);opacity:0;}
    100% {transform:translateY(320%);opacity:0;}
  }

  /* --- Idle : respiration des coins (tally), en cascade --- */
  .vp-corner path{animation:corner-breathe 5.5s var(--ease) infinite;}
  .vp-corner.tl path{animation-delay:3.2s;}
  .vp-corner.tr path{animation-delay:3.7s;}
  .vp-corner.bl path{animation-delay:4.2s;}
  .vp-corner.br path{animation-delay:4.7s;}
  @keyframes corner-breathe{
    0%,100%{stroke:var(--steel-mid);filter:none;}
    45%{stroke:var(--tag-blue);filter:drop-shadow(0 0 5px rgba(143,180,217,0.55));}
  }

  /* --- Idle : focus pull, démarre une fois toute la séquence jouée --- */
  .viewport{animation:vp-focus 9s var(--ease) 2.6s infinite;}
  @keyframes vp-focus{
    0%,100%{box-shadow:inset 0 0 0 0 rgba(143,180,217,0);}
    50%{box-shadow:inset 0 0 34px -18px rgba(143,180,217,0.5);}
  }



  /* --- Idle : timecode + tally du HUD --- */
  .vp-hud-top .tc,.vp-hud-bottom .tc{color:var(--text-mid);font-variant-numeric:tabular-nums;}
  @media (max-width:600px){ .vp-hud-top .tc{display:none;} }
  .vp-hud-bottom .playing{animation:hud-flicker 4.5s steps(1,end) infinite;}
  @keyframes hud-flicker{0%,92%{opacity:1;}94%{opacity:0.35;}96%{opacity:1;}98%{opacity:0.5;}100%{opacity:1;}}

  .eyebrow{
    display:inline-flex;align-items:center;gap:8px;
    font-family:'IBM Plex Mono',monospace;
    font-size:11.5px;color:var(--tag-blue);
    letter-spacing:0.08em;
    margin-bottom:22px;
  }
  .eyebrow::before{content:'[';color:var(--steel-mid);}
  .eyebrow::after{content:']';color:var(--steel-mid);}

  .hero h1{
    font-size:clamp(40px,7vw,78px);
    line-height:0.98;
    font-weight:700;
    max-width:780px;
    margin-bottom:22px;
  }
  .hero h1 em{
    font-style:normal;
    background:var(--chrome-grad);
    -webkit-background-clip:text;background-clip:text;color:transparent;
  }
  /* ============================================================
     "premium." — accent bleu plein, point focal du hero
     Réglages : couleurs et durées en variables, ci-dessous.
     ============================================================ */
  /* Balayage : la bande reste hors du mot les 2/3 du cycle, puis le
     traverse. Un sweep permanent deviendrait un clignotement de fond. */
  @keyframes pw-sweep{
    0%, 62%  { background-position:95% 0, 0 0, 0 0; }
    100%     { background-position: 5% 0, 0 0, 0 0; }
  }

  /* Survol : une passe chrome lente, qui démarre AU BORD du mot.
     Le repos garde ses 62 % d'attente (sinon c'est un clignotement),
     le survol non — l'utilisateur a provoqué l'effet, il doit le voir
     immédiatement. `linear` et non `ease-in-out` : un reflet qui glisse
     sur une surface va à vitesse constante, il n'accélère pas. */
  @keyframes pw-sweep-hover{
    0%   { background-position:95% 0, 0 0, 0 0; }
    100% { background-position: 5% 0, 0 0, 0 0; }
  }

  .hero h1 .premium-word{
    /* — matière — */
    --pw-glow:143,180,217;     /* lueur (RGB brut) */
    /* Bleu du mot = celui de l'eyebrow "[ MOTION DESIGN STUDIO ]".
       On pointe le token, pas la valeur : les deux ne peuvent plus
       diverger si --tag-blue change. */
    --pw-accent:var(--tag-blue);
    /* — durées — */
    --pw-hover:300ms;          /* réponse au survol */
    --pw-ease:cubic-bezier(0.16, 1, 0.3, 1);

    /* ---- BANC D'ESSAI TYPO -------------------------------------
       Changer UNIQUEMENT les 4 variables ci-dessous, puis recharger.
       Décommenter un des blocs préréglés pour tester une candidate.
       (--pw-size compense les différences de hauteur d'x : chaque
        police n'a pas la même corpulence à taille égale.)          */
    /* Big Shoulders Display : strictement la typo de "VERSION".
       Le mot se détache par la matière (texture, balayage, bloom),
       pas par un changement de police. */
    --pw-font:inherit;         /* police du mot */
    --pw-weight:inherit;       /* graisse */
    --pw-tracking:inherit;     /* letter-spacing */
    --pw-size:1em;             /* taille relative au h1 */
    --pw-case:inherit;         /* uppercase | lowercase | none */
    --pw-italic:normal;        /* normal | italic */

    /* Stardom (Fontshare, local — voir @font-face en haut du <style>)
    --pw-font:'Stardom',serif; --pw-weight:400; --pw-tracking:0.02em;
    --pw-size:0.88em; --pw-case:inherit; --pw-italic:normal; */

    /* Playfair Display — serif haut contraste
    --pw-font:'Playfair Display',serif; --pw-weight:700;
    --pw-tracking:0.02em; --pw-size:1em; --pw-case:uppercase; */

    /* Anton — condensé très lourd, très affirmé
    --pw-font:'Anton',sans-serif; --pw-weight:400; --pw-tracking:0.01em; --pw-size:0.92em; */

    /* Bebas Neue — condensé net, plus léger qu'Anton
    --pw-font:'Bebas Neue',sans-serif; --pw-weight:400; --pw-tracking:0.02em; --pw-size:1.02em; */

    /* Archivo Black — grotesque gras et large, casse le rythme condensé
    --pw-font:'Archivo Black',sans-serif; --pw-weight:400; --pw-tracking:-0.01em; --pw-size:0.78em; */

    /* Syne — display géométrique atypique, signature "studio"
    --pw-font:'Syne',sans-serif; --pw-weight:800; --pw-tracking:-0.01em; --pw-size:0.82em; */

    /* Instrument Serif italique — contraste éditorial fort
    --pw-font:'Instrument Serif',serif; --pw-weight:400; --pw-italic:italic;
    --pw-tracking:0em; --pw-size:1.05em; --pw-case:none; */

    /* Playfair Display italique — luxe classique
    --pw-font:'Playfair Display',serif; --pw-weight:700; --pw-italic:italic;
    --pw-tracking:0em; --pw-size:0.9em; --pw-case:none; */
    /* ------------------------------------------------------------ */

    position:relative;
    display:inline-block;
    user-select:none;
    /* Typo pilotée par les variables du banc d'essai ci-dessus.
       Par défaut (`inherit`) : strictement la typo de "version" —
       le mot se détache par la couleur d'accent et le bloom. */
    font-family:var(--pw-font);
    font-weight:var(--pw-weight);
    font-style:var(--pw-italic);
    letter-spacing:var(--pw-tracking);
    text-transform:var(--pw-case);
    font-size:var(--pw-size);
    /* garde-fou anti-rognage : le bloom (drop-shadow ~26px) déborde
       de la boîte du mot ; on lui réserve la place et on compense en
       marge pour ne rien décaler. */
    padding:0.14em 0.10em;
    margin:-0.14em -0.10em;

    /* ---- MATIÈRE : chrome bleuté + balayage spéculaire -----------------
       Deux calques peints DANS la silhouette des glyphes
       (background-clip:text), du plus haut au plus bas :
         1. le sweep — bande de lumière oblique qui traverse le mot ;
         2. la rampe métal — le corps de la matière.

       Pas d'arête franche à mi-hauteur : à cette taille de titre elle se
       lit comme un trait collé en travers du mot, pas comme un reflet.
       Le métal est obtenu autrement — par une descente de valeur continue
       (ciel pâle en haut, bleu profond au pied) et un glint LARGE et
       FAIBLE placé en haut du tiers médian. Large + faible = matière ;
       étroit + fort = autocollant.

       Le texte est transparent, ce sont les calques qui font la couleur ;
       les drop-shadow du bloom suivent l'alpha peint, silhouette exacte. */
    --pw-m-hi:color-mix(in srgb, var(--pw-accent) 20%, white);
    --pw-m-lo:color-mix(in srgb, var(--pw-accent) 72%, #072135);
    --pw-sweep-a:0.42;         /* intensité du balayage — poussée au survol */

    background-image:
      /* 1. balayage : reflet mobile. Son intensité est une variable,
            c'est elle que le survol pousse (--pw-sweep-a). */
      linear-gradient(105deg,
        transparent 38%,
        rgba(255,255,255, calc(var(--pw-sweep-a) * 0.15)) 45%,
        rgba(255,255,255, var(--pw-sweep-a)) 50%,
        rgba(255,255,255, calc(var(--pw-sweep-a) * 0.15)) 55%,
        transparent 62%),
      /* 2. glint fixe : 24 % de haut, alpha faible — un souffle de
            lumière, pas une bande */
      linear-gradient(177deg,
        transparent 30%,
        rgba(255,255,255,0.16) 42%,
        rgba(255,255,255,0.20) 46%,
        rgba(255,255,255,0.05) 54%,
        transparent 62%),
      /* 3. rampe : descente continue, sans rupture */
      linear-gradient(177deg,
        var(--pw-m-hi) 0%,
        color-mix(in srgb, var(--pw-accent) 45%, white) 30%,
        color-mix(in srgb, var(--pw-accent) 85%, white) 52%,
        var(--pw-accent) 70%,
        var(--pw-m-lo) 100%);
    background-size:260% 100%, auto, auto;
    /* 95 % = bande juste hors du mot, côté droit. Avec background-size
       260 %, la fenêtre où la bande traverse réellement le glyphe va de
       ~19 % à ~81 % ; sortir de [5 %, 95 %] ne fait que du voyage à vide. */
    background-position:95% 0, 0 0, 0 0;
    background-repeat:no-repeat, no-repeat, no-repeat;
    -webkit-background-clip:text;
            background-clip:text;
    color:transparent;
    -webkit-text-fill-color:transparent;

    /* Le sweep tourne en CSS et non dans la boucle rAF : il n'écrit que
       background-position, jamais une --pw-*, donc aucun conflit de
       cascade avec le style inline posé par premiumLight(). */
    animation:pw-sweep 7s ease-in-out infinite;

    /* ---- SOURCE LUMINEUSE PILOTÉE (voir IIFE premiumLight en bas) ----
       Le JS écrit ces 5 variables image par image. Au repos elles valent
       les valeurs ci-dessous, donc le mot reste correct sans JS.
       --pw-lx/--pw-ly : direction de l'ombre portée, en px. La lumière
         venant du curseur, l'ombre part à l'opposé.
       --pw-int : 0 = repos, 1 = curseur au contact. Pilote la chaleur
         et l'ampleur du bloom.                                        */
    --pw-lx:0px;
    --pw-ly:0px;
    --pw-int:0;
    --pw-rx:0deg;
    --pw-ry:0deg;
    --pw-scale:1;
    --pw-hot:var(--tag-blue-rgb); /* bleu chaud, ne sort qu'avec --pw-int */

    /* Lueur portée par la silhouette des glyphes : aucune boîte,
       donc aucun masque (overflow des lignes de titre) ne peut la
       trancher — c'est ce qui produisait l'effet "sélection".
       Les 3 couches se décalent à des vitesses différentes (1 / 2.2 / 3) :
       c'est la parallaxe qui donne l'épaisseur, pas un simple offset. */
    filter:
      drop-shadow(0 1px 0 rgba(6,22,40,0.85))
      drop-shadow(var(--pw-lx) var(--pw-ly) 10px
                  rgba(var(--pw-glow), calc(0.30 + 0.20 * var(--pw-int))))
      drop-shadow(calc(var(--pw-lx) * 2.2) calc(var(--pw-ly) * 2.2) 26px
                  rgba(var(--pw-glow), 0.20))
      drop-shadow(calc(var(--pw-lx) * 3) calc(var(--pw-ly) * 3) 38px
                  rgba(var(--pw-hot), calc(0.45 * var(--pw-int))));

    transform:perspective(620px)
              rotateX(var(--pw-rx)) rotateY(var(--pw-ry))
              scale(var(--pw-scale));

    /* Pas de transition sur filter/transform : le lissage est fait en JS
       (lerp par frame). Superposer une transition CSS par-dessus ajoute
       un second amortissement et le mot traîne derrière le curseur. */
    will-change:filter, transform;
  }

  /* Sans JS (ou JS en échec) : une lumière fixe plausible, jamais un
     mot plat. Les variables gardent leurs valeurs par défaut. */
  @media (prefers-reduced-motion:reduce){
    .hero h1 .premium-word{
      --pw-lx:0px; --pw-ly:0px; --pw-int:0;
      --pw-rx:0deg; --pw-ry:0deg; --pw-scale:1;
      transform:none;
      will-change:auto;
      /* Le métal reste (c'est de la matière, pas du mouvement),
         le balayage part. */
      animation:none;
      background-position:95% 0, 0 0, 0 0;
    }
  }

  /* Mobile : le mot suit le titre, aucun débordement ni césure.
     (le titre est en clamp(), donc rien à recalculer ici) */
  @media (max-width:600px){
    .hero h1 .premium-word{
      /* Pas de curseur sur mobile : le JS ne s'attache pas, la lumière
         reste fixe. Bloom allégé, ni parallaxe ni inclinaison. */
      filter:
        drop-shadow(0 1px 0 rgba(6,22,40,0.85))
        drop-shadow(0 0 8px rgba(var(--pw-glow),0.28));
      transform:none;
      will-change:auto;
    }
  }

  /* Contraste élevé (Windows High Contrast / forced-colors) :
     on rend la main au système. */
  @media (forced-colors: active){
    .hero h1 .premium-word,
    .hero h1 .premium-dot{
      background:none;
      -webkit-text-fill-color:currentColor;
      color:CanvasText;
      filter:none;
      animation:none;
    }
  }

  /* Le point final : blanc plein, sans gradient ni clip.
     Le halo reste bleu (accent) : c'est lui qui rattache le point au
     mot, sinon un point blanc isolé se lit comme une coquille. */
  .hero h1 .premium-dot{
    color:#fff;
    -webkit-text-fill-color:#fff;
    filter:drop-shadow(0 0 8px rgba(var(--tag-blue-rgb),0.55));
  }

  .hero p.lead{
    font-size:16.5px;color:var(--text-mid);max-width:520px;line-height:1.6;margin-bottom:40px;font-family:'Inter',sans-serif;text-transform:none;
  }

  .cta-row{display:flex;flex-wrap:wrap;gap:16px;align-items:center;}
  .btn{
    display:inline-flex;align-items:center;justify-content:center;gap:10px;
    max-width:100%;min-width:0;
    padding:15px 26px;border-radius:4px;
    font-size:13.5px;font-weight:500;font-family:'IBM Plex Mono',monospace;letter-spacing:0.03em;
    transition:transform .15s var(--ease), background .3s var(--ease), border-color .3s var(--ease);
  }
  /* ---- Bouton "verre bleu" (d'après le motif Uiverse de TaniaDou),
     recoloré sur --tag-blue. Trois calques :
       ::before             remplissage au repos
       ::after              même remplissage, révélé au survol
       .btn-border::before  filet de 1px en dégradé, tracé par masque

     Deux écarts assumés par rapport à l'original :
     • `isolation:isolate` au lieu des `z-index:-1`. Un z-index négatif
       fait passer les calques DERRIÈRE le fond du parent ; ça ne tient
       que sur un aplat, or le hero a un dégradé et des orbs animés.
       L'isolation crée un contexte d'empilement local et les calques
       restent sous le label sans jamais sortir du bouton.
     • `mask-composite:exclude` ajouté à côté du `-webkit-mask-composite:
       xor` : sans lui, pas de filet sur Firefox.
     Le masque XOR ne peint que l'anneau de 1px délimité par le padding —
     c'est ce qui permet un contour en dégradé, impossible avec
     border-color qui n'accepte qu'une couleur unie. ---- */
  .btn-frame{
    --bf-tint:var(--tag-blue-rgb);  /* teinte du verre */
    --bf-deep:6,44,74;              /* bleu profond, bas du dégradé */
    --bf-edge:168,214,255;          /* filet et lueur interne */
    --bf-radius:8px;
    position:relative;
    isolation:isolate;
    border:none;
    border-radius:var(--bf-radius);
    background:transparent;
    color:#eaf4ff;font-weight:700;
    cursor:pointer;
    transition:transform .15s var(--ease), box-shadow .3s var(--ease);
  }
  .btn-frame::before,
  .btn-frame::after{
    content:'';position:absolute;inset:0;
    border-radius:inherit;
    background:
      linear-gradient(180deg,
        rgba(var(--bf-deep),0) 0%,
        rgba(var(--bf-deep),0.42) 100%),
      rgba(var(--bf-tint),0.20);
    box-shadow:inset 0 0 12px rgba(var(--bf-edge),0.34);
    z-index:0;
    pointer-events:none;
  }
  /* Le calque de survol est identique au calque de repos : il se
     superpose au lieu de le remplacer, et la densité double. Faire
     varier l'opacité d'un seul calque ne donnerait pas le même verre. */
  .btn-frame::after{opacity:0;transition:opacity .3s ease-in;}
  .btn-frame:hover::after,
  .btn-frame:focus-visible::after{opacity:1;}

  .btn-frame .btn-border{
    position:absolute;inset:0;
    border-radius:inherit;
    z-index:1;
    pointer-events:none;
  }
  .btn-frame .btn-border::before{
    content:'';position:absolute;inset:0;
    border-radius:inherit;
    padding:1px;
    background:
      linear-gradient(180deg,
        rgba(var(--bf-edge),0.30) 0%,
        rgba(var(--bf-edge),0) 100%),
      linear-gradient(0deg,
        rgba(var(--bf-edge),0.38),
        rgba(var(--bf-edge),0.38));
    -webkit-mask:linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
            mask:linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    -webkit-mask-composite:xor;
            mask-composite:exclude;
    pointer-events:none;
  }
  .btn-frame:hover,
  .btn-frame:focus-visible{box-shadow:0 0 22px rgba(var(--bf-tint),0.28);}
  .btn-frame .btn-label{position:relative;z-index:2;display:inline-flex;align-items:center;justify-content:center;gap:0;max-width:100%;min-width:0;}

  /* ---- Bouton mail scindé : gauche = mailto, droite = copie ----
     Le markup ne peut pas être un seul <a> : un <button> imbriqué dans
     un lien est invalide et inaccessible. D'où le conteneur <div> qui
     porte l'habillage verre, et deux enfants indépendants.
     Au repos la moitié "copier" est repliée (max-width:0) et le site
     ressemble au bouton d'avant ; elle se déplie au survol du conteneur
     ET au focus clavier, sinon la copie serait inatteignable sans
     souris. ---- */
  .mail-split{
    /* Calé sur .social-btn (50×50, --radius-md) : le bouton mail est
       dans la même rangée qu'Instagram et TikTok, toute autre taille
       casse l'alignement de la ligne. */
    --bf-radius:var(--radius-md);
    padding:0;
    /* .btn pose gap:10px pour espacer icône et texte. Ici les deux
       moitiés doivent se toucher : sans ce gap:0, les 10px s'insèrent
       entre elles et la moitié gauche paraît plus large que l'autre. */
    gap:0;
    height:50px;
    display:inline-flex;
    align-items:stretch;
    overflow:hidden;                 /* les moitiés suivent l'arrondi */
  }
  .mail-part{
    position:relative;z-index:2;
    display:inline-flex;align-items:center;justify-content:center;
    width:50px;height:50px;flex:none;
    padding:0;
    font:inherit;color:inherit;
    background:none;border:none;
    cursor:pointer;
  }
  .mail-ico{
    width:15px;height:15px;flex:none;display:block;
    fill:none;stroke:currentColor;stroke-width:1.5;
    stroke-linecap:round;stroke-linejoin:round;
  }
  /* Enveloppe → flèche sortante au survol de la moitié gauche.
     Les deux icônes sont empilées en absolu dans une boîte de 15px :
     l'échange se fait par opacité, sans que la largeur du bouton bouge
     (un display:none/block ferait sauter le texte à chaque survol).
     Elles glissent en diagonale, dans l'axe de la flèche : le mouvement
     dit la même chose que le pictogramme. */
  .mail-ico-swap{position:relative;width:15px;height:15px;flex:none;}
  .mail-ico-swap .mail-ico{
    position:absolute;inset:0;
    transition:opacity .22s var(--ease), transform .22s var(--ease);
  }
  .mail-ico-swap .ico-arrow{opacity:0;transform:translate(-3px,3px);}
  .mail-go:hover .ico-mail,
  .mail-go:focus-visible .ico-mail{opacity:0;transform:translate(3px,-3px);}
  .mail-go:hover .ico-arrow,
  .mail-go:focus-visible .ico-arrow{opacity:1;transform:none;}
  .mail-go:hover,
  .mail-go:focus-visible{color:var(--tag-blue);}

  .mail-copy{
    width:0;
    opacity:0;overflow:hidden;
    /* la séparation n'apparaît qu'une fois la moitié dépliée, sinon un
       filet de 1px flotterait au bord droit au repos */
    border-left:1px solid transparent;
    transition:width .38s var(--ease),
               opacity .24s var(--ease), border-color .38s var(--ease),
               color .2s var(--ease);
  }
  .mail-split:hover .mail-copy,
  .mail-split:focus-within .mail-copy,
  .mail-split.is-copied .mail-copy{
    width:50px;                    /* identique à .mail-go */
    opacity:1;
    border-left-color:rgba(var(--bf-edge),0.30);
  }
  .mail-copy:hover,
  .mail-copy:focus-visible{color:var(--tag-blue);}
  /* Bascule d'icône animée : les deux sont empilées, l'échange se fait
     en opacité + échelle. La coche se TRACE en plus (stroke-dashoffset) :
     `pathLength="1"` normalise la longueur du tracé, on peut donc écrire
     dasharray/offset en 1 sans mesurer le chemin.
     Le décalage de 90 ms sur le tracé laisse la coche apparaître d'abord,
     sinon les deux effets se marchent dessus et on ne voit ni l'un ni
     l'autre. */
  /* Les icônes tournent en sens opposés : celle qui sort part à +45°,
     celle qui entre vient de −45°. Le croisement se lit comme une seule
     pièce qui bascule, pas comme deux images qui se remplacent. */
  .mail-copy .mail-ico{
    transition:opacity .25s ease, transform .3s cubic-bezier(.34,1.56,.64,1);
  }
  .mail-copy .ico-check{opacity:0;transform:rotate(-45deg) scale(.5);}
  .mail-split.is-copied .mail-copy .ico-copy{opacity:0;transform:rotate(45deg) scale(.5);}
  .mail-split.is-copied .mail-copy .ico-check{opacity:1;transform:rotate(0deg) scale(1);}
  .mail-split.is-copied .mail-copy{
    color:var(--copy-ok);
    animation:mail-pulse .4s ease;
  }
  .mail-copy:active{transform:scale(.9);}
  @keyframes mail-pulse{
    0%{transform:scale(1);}
    40%{transform:scale(1.15);}
    100%{transform:scale(1);}
  }

  /* Tooltip "Copié !".
     Il vit dans .mail-wrap et non dans le bouton : .mail-split et
     .mail-copy portent tous deux overflow:hidden (nécessaire au dépliage
     de la moitié droite), qui l'auraient tranché net. */
  .mail-wrap{
    position:relative;display:inline-flex;
    /* --bf-edge est défini sur .btn-frame, donc sur .mail-split ; le
       tooltip en est le frère et n'y aurait pas accès. Sans ça la
       bordure retombe sur currentColor et vire au blanc. */
    --bf-edge:168,214,255;
  }
  .mail-tip{
    position:absolute;bottom:calc(100% + 10px);right:14px;
    padding:7px 12px;border-radius:8px;
    font-size:12px;font-weight:500;white-space:nowrap;
    color:#eaf4ff;
    background:rgba(10,26,42,0.94);
    border:1px solid rgba(var(--bf-edge),0.28);
    -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);
    box-shadow:0 6px 18px rgba(0,0,0,0.45);
    opacity:0;transform:translateY(6px) scale(.85);
    pointer-events:none;z-index:5;
    transition:opacity .2s ease, transform .25s cubic-bezier(.34,1.56,.64,1),
               background .25s ease, color .25s ease, border-color .25s ease;
  }

  /* Les deux textes occupent la MÊME cellule de grille : ils se
     superposent sans se pousser, et l'échange se fait en opacité.
     La largeur de la bulle, elle, est animée en JS (mesure des deux
     textes) — c'est la seule façon de passer d'une adresse longue à
     "Copié !" sans saut brutal. */
  .mail-tip-inner{
    display:grid;grid-template-columns:minmax(0,1fr);
    justify-items:center;overflow:hidden;
    transition:width .3s cubic-bezier(.4,0,.2,1);
  }
  .mail-tip-text{
    grid-area:1 / 1;
    transition:opacity .25s ease, transform .3s cubic-bezier(.34,1.56,.64,1),
               filter .25s ease;
  }
  .mail-tip-copied{opacity:0;transform:translateY(6px) scale(.7);filter:blur(2px);}
  .mail-tip-default{opacity:1;transform:none;filter:none;}
  .mail-split.is-copied ~ .mail-tip .mail-tip-default{
    opacity:0;transform:translateY(-6px) scale(.7);filter:blur(2px);
  }
  .mail-split.is-copied ~ .mail-tip .mail-tip-copied{
    opacity:1;transform:none;filter:none;
  }

  /* Affichage au survol de la SEULE moitié "copier" : :has() permet de
     remonter du bouton au conteneur pour atteindre le tooltip, qui en
     est le frère. */
  .mail-split:has(.mail-copy:hover) ~ .mail-tip,
  .mail-split:has(.mail-copy:focus-visible) ~ .mail-tip{
    opacity:1;transform:translateY(0) scale(1);
  }
  /* Pointe : un carré tourné à 45° dont on ne borde que deux côtés.
     Un triangle en `border` ne peut pas porter de contour, il aurait
     coupé le liseré tout autour de la bulle. */
  .mail-tip::after{
    content:'';position:absolute;top:100%;left:auto;right:16px;
    width:8px;height:8px;margin-top:-5px;
    background:rgba(10,26,42,0.94);
    border-right:1px solid rgba(var(--bf-edge),0.28);
    border-bottom:1px solid rgba(var(--bf-edge),0.28);
    transform:rotate(45deg);
    transition:background .25s ease, border-color .25s ease;
  }
  /* État copié : la bulle vire au bleu du site, quel que soit le survol. */
  .mail-split.is-copied ~ .mail-tip{
    opacity:1;transform:translateY(0) scale(1);
    background:var(--copy-ok);
    border-color:var(--copy-ok);
    color:#04121f;font-weight:600;
    animation:mail-tip-bounce .35s cubic-bezier(.34,1.56,.64,1);
  }
  .mail-split.is-copied ~ .mail-tip::after{
    background:var(--copy-ok);
    border-color:var(--copy-ok);
  }
  @keyframes mail-tip-bounce{
    0%{transform:translateY(0) scale(.9);}
    50%{transform:translateY(-3px) scale(1.08);}
    100%{transform:translateY(0) scale(1);}
  }

  @media (prefers-reduced-motion:reduce){
    .mail-ico, .mail-copy, .mail-tip{
      transition:none !important;
      animation:none !important;
    }
  }
  .btn-frame:hover .btn-arrow,
  .btn-frame:focus-visible .btn-arrow{transform:translateY(0);width:13px;opacity:1;margin-right:7px;}

  .btn-primary{
    position:relative;overflow:hidden;
    background:linear-gradient(180deg,#242424,#000000);
    color:#f2f4f7;font-weight:600;
    text-shadow:0 1px 3px rgba(0,0,0,0.85), 0 1px 10px rgba(0,0,0,0.5);
    box-shadow:
      0 0 0 1px rgba(0,0,0,0.4),
      0 20px 12px -4px rgba(0,0,0,0.15),
      0 9px 9px -3px rgba(0,0,0,0.18),
      0 2px 5px 0 rgba(0,0,0,0.2),
      inset 0 1px 0 rgba(255,255,255,0.06);
    transition:transform .15s var(--ease), box-shadow .2s var(--ease);
  }
  .btn-primary:hover{
    box-shadow:
      0 0 0 1px rgba(0,0,0,0.5),
      0 12px 6px -2px rgba(0,0,0,0.08),
      0 8px 5px -2px rgba(0,0,0,0.12),
      0 4px 4px 0 rgba(0,0,0,0.16),
      0 1px 2px 0 rgba(0,0,0,0.22),
      inset 0 1px 0 rgba(255,255,255,0.1);
  }
  .btn-primary .shader-mount{
    position:absolute;inset:0;z-index:0;border-radius:inherit;overflow:hidden;pointer-events:none;
  }
  .btn-primary .shader-mount canvas{display:block;width:100%;height:100%;}
  .btn-primary::after{
    content:'';position:absolute;inset:2px;z-index:1;border-radius:inherit;
    background:linear-gradient(135deg, rgba(255,255,255,0.14), rgba(0,0,0,0.35) 55%, rgba(255,255,255,0.08));
    backdrop-filter:blur(10px) saturate(160%);
    -webkit-backdrop-filter:blur(10px) saturate(160%);
    border:1px solid rgba(255,255,255,0.14);
    box-shadow:inset 0 1px 1px rgba(255,255,255,0.3), inset 0 -4px 8px -4px rgba(255,255,255,0.1);
    pointer-events:none;
  }
  .btn-tint-blue{background:linear-gradient(180deg,#1d2733,#000000);}
  .btn-tint-blue::after{background:linear-gradient(135deg, rgba(140,190,255,0.16), rgba(0,10,25,0.35) 55%, rgba(140,190,255,0.09));}
  .btn-primary .btn-label{position:relative;z-index:2;display:inline-flex;align-items:center;justify-content:center;gap:0;max-width:100%;min-width:0;overflow-wrap:anywhere;}
  .btn-arrow{
    display:inline-flex;align-items:center;justify-content:center;
    width:0;opacity:0;overflow:hidden;flex:0 0 auto;
    transform:translateY(-4px);
    transition:transform .28s var(--ease), width .28s var(--ease), opacity .28s var(--ease), margin .28s var(--ease);
  }
  .btn-arrow svg{width:13px;height:13px;display:block;stroke:currentColor;stroke-width:1.6;fill:none;stroke-linecap:round;stroke-linejoin:round;}
  .btn-ripple{
    position:absolute;z-index:3;width:20px;height:20px;border-radius:50%;
    background:radial-gradient(circle, rgba(255,255,255,0.4) 0%, rgba(255,255,255,0) 70%);
    transform:translate(-50%,-50%) scale(0);opacity:0.6;
    pointer-events:none;
    animation:btn-ripple .6s ease-out forwards;
  }
  @keyframes btn-ripple{
    from{transform:translate(-50%,-50%) scale(0);opacity:0.6;}
    to{transform:translate(-50%,-50%) scale(4);opacity:0;}
  }
  .btn-ghost{
    border:1px solid var(--glass-border);
    background:var(--glass-fill);
    color:var(--text-hi);
  }
  .btn-primary .status-dot{
    position:relative;z-index:2;
    width:6px;height:6px;border-radius:50%;flex-shrink:0;
    background:var(--ice);box-shadow:0 0 6px var(--ice);
    animation:pulse-rec 1.6s linear infinite;
  }

  .hero-stats{
    display:flex;gap:0;margin-top:56px;
    border-top:1px solid var(--steel-line);
    max-width:640px;flex-wrap:wrap;
  }
  .stat{padding:18px 28px 0 0;margin-right:28px;border-right:1px solid var(--steel-line);}
  .stat:last-child{border-right:none;}
  .stat b{display:block;font-family:'Big Shoulders Display',sans-serif;font-size:30px;font-weight:700;color:var(--text-hi);}
  .stat span{font-size:11.5px;color:var(--text-low);font-family:'IBM Plex Mono',monospace;letter-spacing:0.04em;text-transform:uppercase;}

  /* ---------- SCROLL REVEAL ---------- */
  .reveal{opacity:0;transform:translateY(28px);transition:opacity .6s var(--ease), transform .6s var(--ease);}
  .reveal.is-visible{opacity:1;transform:translateY(0);}

  /* Le bloc contact arrive en fin de page, après une longue descente : la
     cadence de 0,6s des sections précédentes y paraît expédiée. Ralenti
     pour qu'il se pose au lieu de surgir. Spécificité 0,2,0 pour passer
     devant .reveal. */
  .contact-panel.reveal{
    transition:opacity 1.2s var(--ease), transform 1.2s var(--ease);
  }

  /* Travaux : entrée en zoom plutôt qu'en glissement vertical.
     Sélecteur en 0,2,0 (.work-card.reveal) pour passer devant la règle
     `.work-card{transition:... transform .2s}` définie plus bas dans le
     bloc de survol — sinon le zoom durerait 200 ms au lieu de 900.
     Départ à 0.86 : en dessous la vidéo se lit comme une vignette qui
     grossit, au-dessus le mouvement ne se voit plus. */
  .work-card.reveal{
    opacity:0;
    transform:scale(0.86);
    transition:opacity .9s var(--ease), transform .9s var(--ease);
  }
  .work-card.reveal.is-visible{
    opacity:1;
    transform:scale(1);
  }

  /* Tuiles Formation : montée plus lente que le reveal générique (.6s),
     pour que chaque tuile ait le temps d'exister avant la suivante.
     Spécificité 0,2,0 — même raison que pour .work-card : une règle de
     survol plus bas impose une transition courte sur transform. */
  .formation-module.reveal{
    transition:opacity .8s var(--ease), transform .8s var(--ease);
  }

  /* ---------- SECTION HEADS ---------- */
  section{padding:64px 0;position:relative;}
  .section-head{max-width:640px;margin-bottom:48px;}
  .section-head h2{font-size:clamp(30px,4.4vw,44px);font-weight:700;margin-bottom:12px;}
  .section-head p{color:var(--text-mid);font-size:15px;line-height:1.65;font-family:'Inter',sans-serif;text-transform:none;}

  /* Titre de section tenu sur UNE ligne (Tarifs).
     Deux verrous à lever : le max-width:640px du bloc, qui provoquait
     le retour à la ligne, et le clamp() du h2 dont le plancher en vw
     est trop haut pour cette longueur (42 caractères).
     Le 4.7vw est calé sur la chasse de Big Shoulders (~0.42em par
     caractère en capitales) : 42 × 0.42 ≈ 17.6 em de large, donc la
     ligne tient tant que font-size ≤ largeur_dispo / 17.6.
     Le paragraphe garde sa mesure de lecture, lui. */
  .section-head-wide{max-width:none;}
  .section-head-wide h2{
    white-space:nowrap;
    font-size:clamp(16px, 4.7vw, 44px);
  }
  .section-head-wide p{max-width:640px;}

  /* ---------- WORK LIST (empilé un par un) ---------- */
  .work-list{
    display:grid;
    grid-template-columns:repeat(3, 1fr);
    gap:24px;
  }
  @media (max-width:1000px){ .work-list{grid-template-columns:repeat(2, 1fr);} }
  @media (max-width:600px){ .work-list{grid-template-columns:1fr;} }
  .work-card{
    position:relative;
    perspective:800px;
    width:100%;
    height:260px;
  }
  @media (max-width:600px){ .work-card{height:220px;} }

  .work-card .media{
    position:absolute;inset:0;
    border-radius:var(--radius-md);
    overflow:hidden;
    transition:transform .45s var(--ease-in-out), box-shadow .3s var(--ease);
    backface-visibility:hidden;-webkit-backface-visibility:hidden;
  }
  .work-card video{
    position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  }
  /* ---- Agrandissement de la vidéo (lightbox, pas de plein écran) ---- */
  .vlb{
    position:fixed;inset:0;z-index:200;
    display:flex;align-items:center;justify-content:center;
    padding:5vh 5vw;
    background:rgba(4,7,12,0.86);
    backdrop-filter:blur(10px) saturate(120%);
    -webkit-backdrop-filter:blur(10px) saturate(120%);
    opacity:0;visibility:hidden;
    /* le voile monte au rythme du trajet de la vidéo (760 ms) */
    transition:opacity .68s cubic-bezier(0.33,0.9,0.2,1),
               visibility .68s cubic-bezier(0.33,0.9,0.2,1);
  }
  .vlb.is-open{opacity:1;visibility:visible;}
  .vlb-stage{
    position:relative;
    max-width:min(1100px, 90vw);max-height:90vh;
    border-radius:var(--radius-md);
    border:1px solid var(--glass-border-strong);
    box-shadow:0 40px 90px -30px rgba(0,0,0,0.9),
               0 0 60px -20px rgba(77,166,255,0.45);
    overflow:hidden;background:#000;
    /* pas de transform ici : le trajet vignette → centre est piloté
       par le FLIP en Web Animations API */
  }
  /* fondu du voile pendant le retour vers la vignette */
  .vlb.is-open.is-closing{opacity:0;transition:opacity .7s cubic-bezier(0.33,0.9,0.2,1);}
  .vlb-stage video{display:block;width:100%;height:100%;object-fit:contain;}
  .vlb-close{
    position:absolute;top:10px;right:10px;z-index:2;
    width:36px;height:36px;padding:0;
    display:grid;place-items:center;border-radius:9px;
    border:1px solid rgba(200,225,255,0.22);
    background:rgba(8,13,20,0.6);
    backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);
    color:var(--text-hi);cursor:pointer;
    transition:border-color .25s var(--ease), color .25s var(--ease), background .25s var(--ease);
  }
  .vlb-close:hover{border-color:var(--tag-blue);color:var(--tag-blue);background:rgba(12,22,36,0.85);}
  .vlb-close:focus-visible{outline:2px solid var(--tag-blue);outline-offset:2px;}
  .vlb-close svg{width:16px;height:16px;stroke:currentColor;stroke-width:1.8;fill:none;stroke-linecap:round;}
  .work-card .frame{
    position:absolute;inset:0;
    border:1px solid var(--steel-line);
    transition:border-color .3s var(--ease);
    pointer-events:none;
  }
  .work-card .info{
    position:absolute;left:0;right:0;bottom:0;padding:18px 20px;
    display:flex;justify-content:space-between;align-items:flex-end;
    transform:translateZ(0);
    transition:transform .4s var(--ease-in-out);
    backface-visibility:hidden;-webkit-backface-visibility:hidden;
    z-index:2;
  }
  .work-card .info .name{font-family:'Big Shoulders Display',sans-serif;font-size:19px;font-weight:700;text-shadow:0 2px 8px rgba(0,0,0,0.8);transition:text-shadow .3s var(--ease-in-out);-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;}
  .work-card .info .tag{font-size:11.5px;color:var(--tag-blue);text-shadow:0 2px 6px rgba(0,0,0,0.8);text-transform:uppercase;letter-spacing:0.09em;font-family:'IBM Plex Mono',monospace;transition:text-shadow .3s var(--ease-in-out);-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;}
  /* Bouton plein écran : apparaît au survol de la carte, toujours
     visible au focus clavier et sur appareils sans survol. */
  /* Commandes flottantes d'une vignette : "agrandir" à droite, "son" à
     gauche. Style commun factorisé — elles doivent apparaître et
     disparaître exactement de la même façon, sinon le coin de la carte
     se met à clignoter en deux temps au survol. */
  .media-btn{
    position:absolute;top:12px;z-index:3;
    width:34px;height:34px;padding:0;
    display:grid;place-items:center;
    border-radius:9px;
    border:1px solid rgba(200,225,255,0.22);
    background:rgba(8,13,20,0.55);
    backdrop-filter:blur(8px) saturate(140%);
    -webkit-backdrop-filter:blur(8px) saturate(140%);
    color:var(--text-hi);cursor:pointer;
    opacity:0;transform:translateY(-4px);
    transition:opacity .25s var(--ease), transform .25s var(--ease),
               border-color .25s var(--ease), background .25s var(--ease);
  }
  .fs-btn{right:12px;}
  .snd-btn{left:12px;}
  /* Même traitement que les libellés .name / .tag de la vignette : une
     ombre portée qui s'approfondit quand la carte est survolée. Le
     drop-shadow est l'équivalent du text-shadow pour une icône tracée. */
  .media-btn svg{width:15px;height:15px;display:block;stroke:currentColor;
    stroke-width:1.6;fill:none;stroke-linecap:round;stroke-linejoin:round;
    filter:drop-shadow(0 2px 6px rgba(0,0,0,0.8));
    transition:filter .3s var(--ease-in-out);}
  .work-card:hover .media-btn,
  .media-btn:focus-visible{opacity:1;transform:translateY(0);}
  .work-card:hover .media-btn svg{filter:drop-shadow(0 10px 18px rgba(0,0,0,0.7));}
  /* Le focus garde l'accent bleu : c'est un indicateur d'accessibilité,
     il doit rester distinct du reste. */
  .media-btn:focus-visible{outline:2px solid var(--tag-blue);outline-offset:2px;}
  .media-btn:hover{background:rgba(12,22,36,0.8);border-color:var(--glass-border-strong);}
  /* Pas d'état coloré ni d'affichage permanent sur .snd-btn : elle se
     comporte exactement comme .fs-btn, visible au seul survol de la
     carte. L'état du son est porté par l'icône (haut-parleur barré ou
     non), pas par la couleur. */
  @media (hover:none){ .media-btn{opacity:1;transform:none;} }

  .work-card .glare{
    position:absolute;inset:0;z-index:1;border-radius:inherit;pointer-events:none;
    background:radial-gradient(circle at var(--gx,50%) var(--gy,50%), rgba(255,255,255,0.28), transparent 55%);
    mix-blend-mode:overlay;opacity:0;transition:opacity .3s var(--ease);
  }

  /* ---------- ABOUT ----------
     Le panneau est traité comme une fiche de production : barre HUD,
     repères de coin, grille technique en fond, fiche technique
     numérotée à droite, bandeau clients en pied. */
  .about-panel{
    --ab-accent:77,166,255;
    --ab-pad:48px;

    position:relative;padding:0;overflow:hidden;
    background:
      radial-gradient(90% 70% at 92% -12%, rgba(var(--ab-accent),0.13), transparent 62%),
      radial-gradient(70% 60% at 0% 108%, rgba(var(--ab-accent),0.07), transparent 68%),
      linear-gradient(168deg, #0e1520 0%, var(--panel) 58%);
    box-shadow:inset 0 1px 0 rgba(200,225,255,0.06);
  }
  .about-hud{
    position:relative;z-index:1;
    display:flex;align-items:center;justify-content:space-between;gap:16px;
    padding:15px var(--ab-pad);
    border-bottom:1px solid var(--steel-line);
    font-family:'IBM Plex Mono',monospace;font-size:11.5px;
    letter-spacing:0.14em;color:var(--steel-mid);
  }
  .ab-hud-left{display:inline-flex;align-items:center;gap:9px;color:var(--text-mid);}
  /* L'eyebrow porte partout ailleurs une marge basse de 22px et une
     taille de 11.5px, calibrées pour un début de section. Dans la barre
     HUD il est aligné sur une ligne : on neutralise la marge et on cale
     la taille sur celle du HUD. */
  .ab-hud-eyebrow{margin-bottom:0;font-size:inherit;letter-spacing:inherit;}
  .about-body{
    position:relative;z-index:1;
    display:grid;grid-template-columns:1.12fr 0.88fr;gap:52px;
    padding:44px var(--ab-pad) 40px;
    align-items:start;
  }

  /* — colonne texte — */
  .about-copy h2{
    font-size:clamp(28px,3.8vw,40px);font-weight:700;line-height:1.05;
    margin-bottom:22px;position:relative;
  }
  /* le mot accentué : bleu + halo, seul point de couleur du titre */
  .about-copy h2 em{
    font-style:normal;color:var(--tag-blue);
    text-shadow:0 0 26px rgba(var(--ab-accent),0.55);
  }
  .about-copy h2::after{
    content:'';display:block;width:72px;height:2px;margin-top:18px;border-radius:2px;
    background:linear-gradient(90deg, var(--tag-blue), rgba(var(--ab-accent),0));
  }
  /* chapô : la première phrase porte, le reste suit en corps */
  .about-panel p{
    color:var(--text-mid);line-height:1.75;font-size:15.5px;margin-bottom:16px;
    font-family:'Inter',sans-serif;text-transform:none;max-width:58ch;
  }
  .about-panel p.about-lede{
    font-size:18.5px;line-height:1.55;
    color:var(--text-hi);font-weight:500;
    max-width:34ch;margin-bottom:18px;
  }
  .about-signature{
    font-family:'IBM Plex Mono',monospace;font-size:13px;color:var(--tag-blue);
    margin-top:22px;letter-spacing:0.05em;
  }

  /* — fiche technique — */
  .about-side{
    display:flex;flex-direction:column;
    padding:8px 22px 10px;
    border:1px solid var(--glass-border);border-radius:var(--radius-md);
    background:rgba(140,165,190,0.04);
    backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
  }
  .ab-side-title{
    display:block;padding:14px 0 6px;
    font-family:'IBM Plex Mono',monospace;font-size:11.5px;
    letter-spacing:0.16em;text-transform:uppercase;color:var(--steel-mid);
  }
  .about-item{
    display:grid;grid-template-columns:auto 1fr;gap:14px;align-items:start;
    padding:16px 0;
    border-top:1px solid var(--steel-line);
    /* opacity listée ici aussi : cette règle écrase le `transition`
       de .reveal, sans quoi l'apparition au scroll serait sèche */
    transition:opacity .6s var(--ease), transform .45s var(--ease);
  }
  /* Tuile d'icône : même vocabulaire que .addon-ico (suppléments), en
     plus compact pour tenir dans l'interligne serré de la fiche. */
  .about-item .n{
    flex:none;
    width:28px;height:28px;
    display:inline-flex;align-items:center;justify-content:center;
    border-radius:var(--radius-sm);
    color:var(--steel-mid);
    background:var(--glass-fill);
    border:1px solid var(--glass-border);
    transition:color .35s var(--ease), background .35s var(--ease),
               border-color .35s var(--ease);
  }
  .about-item .n svg{
    width:15px;height:15px;display:block;
    fill:none;stroke:currentColor;stroke-width:1.4;
    stroke-linecap:round;stroke-linejoin:round;
  }
  @media (hover:hover){
    .about-item:hover .n{
      color:var(--tag-blue);
      background:rgba(var(--tag-blue-rgb),0.10);
      border-color:rgba(var(--tag-blue-rgb),0.28);
    }
  }
  .about-item .k{
    font-size:11.5px;color:var(--text-low);text-transform:uppercase;
    letter-spacing:0.12em;margin-bottom:6px;
    font-family:'IBM Plex Mono',monospace;
  }
  .about-item .v{
    font-size:15px;color:var(--text-hi);line-height:1.45;
    font-family:'Inter',sans-serif;text-transform:none;
  }

  /* — pied : clients + relance — */
  .about-clients{display:flex;align-items:center;gap:12px;}
  .ac-logo{
    width:34px;height:34px;border-radius:9px;overflow:hidden;flex:0 0 auto;
    border:1px solid var(--glass-border);background:#0a0f16;
    /* désaturés au repos : les logos ne concurrencent pas le bleu */
    filter:grayscale(1) brightness(0.85);opacity:0.6;
    transition:filter .35s var(--ease), opacity .35s var(--ease),
               border-color .35s var(--ease), transform .35s var(--ease);
  }
  .ac-logo img{width:100%;height:100%;object-fit:cover;display:block;}
  .ac-logo.ac-contain img{object-fit:contain;padding:5px;}
  /* ---- CTA « Démarrer un projet » (À propos) -----------------------
     Bouton à lueur, adapté de Uiverse (cssbuttons-io). Le violet
     d'origine (#d9b0ff / #643d88) est remplacé par le bleu d'accent :
     c'est le seul CTA lumineux de la page, il doit rester dans la
     palette — un second accent chromatique ferait deux marques.
     Les valeurs de lueur sont aussi divisées par deux environ : sur le
     fond noir du site, un halo de 4em/2em bavait sur trois paragraphes.
     La couleur du texte ne descend PAS en dessous de #cfe6ff : à l'état
     de repos ce bouton porte du texte sur fond bleu translucide, et
     l'original (texte clair sur violet moyen) passait sous 4,5:1. */
  .glow-btn{
    --glow:var(--tag-blue);
    --glow-spread:rgba(var(--tag-blue-rgb),0.55);
    --glow-face:rgba(var(--tag-blue-rgb),0.13);
    position:relative;isolation:isolate;
    display:inline-flex;align-items:center;
    padding:0.85em 2.1em;
    border:2px solid var(--glow);border-radius:var(--radius-md);
    background:var(--glow-face);
    color:#e6f3ff;
    font-family:'IBM Plex Mono',monospace;
    font-size:13px;font-weight:500;letter-spacing:0.06em;
    text-transform:uppercase;text-decoration:none;
    text-shadow:0 0 0.5em rgba(var(--tag-blue-rgb),0.75);
    box-shadow:
      0 0 0.9em 0.1em rgba(var(--tag-blue-rgb),0.45),
      0 0 2.4em 0.5em var(--glow-spread),
      inset 0 0 0.7em 0.15em rgba(var(--tag-blue-rgb),0.4);
    user-select:none;-webkit-user-select:none;
    transition:color .3s var(--ease), background .3s var(--ease),
               box-shadow .3s var(--ease), transform .3s var(--ease);
  }
  /* Reflet projeté au sol : le halo écrasé sous le bouton, qui donne
     l'impression d'une source lumineuse posée sur une surface.
     z-index négatif et isolation sur le parent — sans ça il passerait
     par-dessus le texte du bouton. */
  .glow-btn::after{
    content:'';pointer-events:none;
    position:absolute;top:118%;left:0;width:100%;height:100%;z-index:-1;
    background:var(--glow-spread);
    filter:blur(1.4em);opacity:0.55;
    transform:perspective(1.5em) rotateX(35deg) scale(1,0.6);
    transition:opacity .3s var(--ease);
  }
  @media (hover:hover){
    /* Inversion : le fond prend la couleur de la lueur, le texte passe
       en fond de page. Contraste maximal au moment où l'on vise. */
    .glow-btn:hover{
      color:var(--ink);
      background:var(--glow);
      box-shadow:
        0 0 1em 0.15em rgba(var(--tag-blue-rgb),0.6),
        0 0 3em 1em var(--glow-spread),
        inset 0 0 0.7em 0.15em rgba(255,255,255,0.35);
      text-shadow:none;
    }
    .glow-btn:hover::after{opacity:0.8;}
    .glow-btn:hover .about-cta-arrow{transform:translateX(3px);}
  }
  .glow-btn:active{
    transform:translateY(1px);
    box-shadow:
      0 0 0.5em 0.1em rgba(var(--tag-blue-rgb),0.5),
      0 0 1.6em 0.8em var(--glow-spread),
      inset 0 0 0.45em 0.15em rgba(var(--tag-blue-rgb),0.45);
  }
  .glow-btn:focus-visible{outline:2px solid #cfe6ff;outline-offset:3px;}

  /* Le CTA vit dans la colonne de texte, sous la signature : il conclut
     le propos au lieu d'attendre dans une barre séparée. */
  .about-cta{margin-top:24px;}
  .about-cta-arrow{
    width:14px;height:14px;margin-left:10px;flex:none;
    stroke:currentColor;stroke-width:1.7;fill:none;
    stroke-linecap:round;stroke-linejoin:round;
    transition:transform .3s var(--ease);
  }
  @media (prefers-reduced-motion:reduce){
    .glow-btn,.glow-btn::after,.about-cta-arrow{transition:none;}
    .glow-btn:active{transform:none;}
  }
  @media (max-width:600px){
    .glow-btn{padding:0.8em 1.5em;font-size:12px;}
    /* Le reflet au sol double la hauteur perçue du bouton : sur mobile
       il touchait la section suivante. */
    .glow-btn::after{filter:blur(1em);opacity:0.4;}
  }

  @media (max-width:900px){
    .about-panel{--ab-pad:32px;}
    .about-body{grid-template-columns:1fr;gap:34px;padding:34px var(--ab-pad) 30px;}
    .about-lede{max-width:none;}
  }
  @media (max-width:600px){
    .about-panel{--ab-pad:22px;}
    .about-hud .ab-hud-right{display:none;}
  }

  /* ---------- AVIS ----------
     Direction « moniteur de contrôle » : chaque témoignage est une
     fenêtre de lecteur — HUD mono en haut, repères de coin, lueur
     rasante sur le bord gauche, attribution en pied sous un filet. */
  .avis-grid{
    /* — jetons de la section — */
    --av-accent:77,166,255;      /* accent bleu (RGB brut) */
    --av-radius:var(--radius-lg);
    --av-pad:30px;
    --av-gap:22px;               /* aligné sur le reste du site */
    --av-star:#ffc63d;           /* étoiles */
    --av-dur:260ms;              /* hover : 200–300 ms */
    --av-glow-dur:520ms;         /* fondu de la lueur au survol */
    --av-ease:cubic-bezier(0.16, 1, 0.3, 1);

    /* 4 témoignages : 2×2 plutôt que 3+1, qui laissait une carte
       orpheline en seconde rangée */
    display:grid;grid-template-columns:repeat(2,1fr);
    gap:var(--av-gap);
    align-items:stretch;         /* hauteur uniforme */
  }
  .avis-card{
    position:relative;
    height:100%;
    margin:0;                    /* <figure> */
    padding:var(--av-pad);
    display:flex;flex-direction:column;
    border-radius:var(--av-radius);
    /* fond distinct de la section, pas du même noir */
    background:
      radial-gradient(120% 90% at 0% 0%, rgba(var(--av-accent),0.07), transparent 60%),
      var(--panel);
    border:1px solid var(--glass-border);
    box-shadow:inset 0 1px 0 rgba(200,225,255,0.05),
               0 14px 30px -26px rgba(0,0,0,0.9);
    overflow:hidden;
    /* opacity : reprise du reveal au scroll (la règle globale des
       cartes ne s'applique plus ici).
       box-shadow plus lent que le reste : la lueur monte en fondu
       au lieu de s'allumer d'un coup. */
    transition:opacity .6s var(--ease),
               transform var(--av-dur) var(--av-ease),
               border-color var(--av-dur) var(--av-ease),
               box-shadow var(--av-glow-dur) var(--av-ease);
  }
  /* lueur rasante sur le seul bord gauche — rappel du thème caméra */
  .avis-card::before{
    content:'';position:absolute;left:0;top:0;bottom:0;width:2px;
    background:linear-gradient(180deg,
      transparent 0%,
      rgba(var(--av-accent),0.85) 22%,
      rgba(var(--av-accent),0.85) 78%,
      transparent 100%);
    opacity:0.55;
    transition:opacity var(--av-glow-dur) var(--av-ease);
  }
  /* guillemet ouvrant : élément graphique en filigrane, hors du flux
     du texte (il était en exposant devant la première ligne) */
  .avis-card::after{
    content:'“';
    position:absolute;top:52px;right:18px;
    font-family:'Big Shoulders Display',sans-serif;
    font-size:120px;line-height:0.7;
    color:rgba(var(--av-accent),0.10);
    pointer-events:none;user-select:none;
  }

  /* barre HUD : identifiant mono à gauche, étoiles à droite */
  .avis-hud{
    display:flex;align-items:center;justify-content:space-between;gap:12px;
    padding-bottom:14px;margin-bottom:20px;
    border-bottom:1px solid var(--steel-line);
  }
  .avis-id{
    font-family:'IBM Plex Mono',monospace;font-size:11.5px;
    letter-spacing:0.14em;color:var(--steel-mid);
  }
  /* Étoiles : chacune est un élément à part, sinon aucun décalage
     possible entre elles. L'espacement passe de letter-spacing à un
     gap flex — letter-spacing ajoute aussi une chasse APRÈS la dernière
     étoile, qui décalait le bloc vers la gauche. */
  .stars{
    display:inline-flex;gap:3px;
    color:var(--av-star);font-size:15px;letter-spacing:0;
  }
  .stars i{
    font-style:normal;display:block;
    transform-origin:50% 65%;   /* pivot bas : l'étoile se soulève,
                                   elle ne gonfle pas sur place */
    text-shadow:0 0 12px rgba(255,198,61,0.45);
    /* Sortie sans délai (toutes ensemble) : on ne fait attendre
       personne pour un retour au repos. Le décalage n'existe qu'à
       l'entrée, où il porte la lecture de gauche à droite. */
    transition:transform .22s var(--ease), text-shadow .22s var(--ease);
  }
  @media (prefers-reduced-motion:reduce){
    .stars i{transition:none !important;transition-delay:0ms !important;}
  }

  .avis-card .quote{
    margin:0;
    font-family:'Inter',sans-serif;text-transform:none;
    font-size:15.5px;line-height:1.7;color:var(--text-hi);
    position:relative;z-index:1;
  }

  /* pied ancré en bas quelle que soit la longueur de la citation */
  .avis-foot{
    margin-top:auto;padding-top:20px;
    border-top:1px solid var(--steel-line);
    display:flex;align-items:center;gap:12px;
  }
  /* monogramme carré : slot logo, remplaçable par une <img> */
  .avis-mono{
    flex:0 0 auto;width:38px;height:38px;
    display:grid;place-items:center;border-radius:9px;
    background:rgba(var(--av-accent),0.10);
    border:1px solid rgba(var(--av-accent),0.28);
    font-family:'IBM Plex Mono',monospace;font-size:12.5px;
    letter-spacing:0.04em;color:var(--tag-blue);
    overflow:hidden;
  }
  /* variante logo : l'image remplit le carré, le fond bleu translucide
     ne doit plus transparaître derrière */
  .avis-mono:has(img){background:#000;border-color:var(--glass-border-strong);}
  .avis-mono img{width:100%;height:100%;object-fit:cover;border-radius:inherit;}
  /* logos à silhouette détourée (fond transparent) : on les contient
     et on garde un fond sombre plutôt que de rogner le dessin */
  .avis-mono-contain{background:#0a0f16;}
  .avis-mono-contain img{object-fit:contain;padding:6px;}
  .avis-ident{display:flex;flex-direction:column;gap:2px;min-width:0;}
  .avis-foot .client{
    font-family:'Big Shoulders Display',sans-serif;font-size:17px;
    font-weight:700;letter-spacing:0.03em;text-transform:uppercase;
    color:var(--text-hi);line-height:1.1;
  }
  /* rôle/secteur : --text-mid (#a6b3c4 sur #0c1119 ≈ 8.6:1, AA large) */
  .avis-role{
    font-family:'IBM Plex Mono',monospace;font-size:11.5px;
    letter-spacing:0.06em;color:var(--text-mid);
  }

  /* Mobile : carrousel à accroche horizontale (3 cartes, une par vue),
     avec débord visible pour signaler qu'il y a une suite. */
  @media (max-width:800px){
    .avis-grid{
      display:flex;
      grid-template-columns:none;
      overflow-x:auto;
      scroll-snap-type:x mandatory;
      /* débordement en pleine largeur : on annule le padding du .wrap
         (32px) puis on le rétablit en padding interne, pour que les
         cartes puissent glisser jusqu'au bord de l'écran */
      scroll-padding-left:32px;
      padding-bottom:14px;
      margin-inline:-32px;
      padding-inline:32px;
      -webkit-overflow-scrolling:touch;
      scrollbar-width:thin;
    }
    .avis-card{
      flex:0 0 84%;max-width:420px;
      scroll-snap-align:start;
    }
    .avis-card::after{font-size:96px;top:46px;}
  }

  /* ---------- TARIFS ---------- */
  .price-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:22px;align-items:stretch;}
  @media (max-width:800px){
    .price-grid{grid-template-columns:1fr;}
    .price-card.featured{order:-1;}
  }
  .price-card{
    /* Surélévation permanente de la carte, en variable : la carte
       "Recommandé" est décalée vers le haut en permanence. En la
       codant en dur dans un transform, l'animation d'entrée l'écrasait
       (une seule propriété transform par élément). En variable, l'entrée
       compose avec elle au lieu de la remplacer. */
    --pc-lift:0px;
    position:relative;padding:34px 30px;display:flex;flex-direction:column;gap:14px;
    background:var(--panel);backdrop-filter:none;-webkit-backdrop-filter:none;
    box-shadow:0 20px 45px -22px rgba(77,166,255,0);
    transform:translateY(var(--pc-lift));
    transition:transform .45s var(--ease-in-out), border-color .45s var(--ease), box-shadow .45s var(--ease-in-out);
  }
  /* Entrée séquencée (voir sequenceIn côté JS). Spécificité 0,2,0 pour
     passer devant la règle de survol `.price-card{transition:… .2s}`
     définie plus bas, qui sinon écourterait la montée à 200 ms. */
  .price-card.reveal{
    opacity:0;
    transform:translateY(calc(var(--pc-lift) + 26px));
    transition:opacity .7s var(--ease), transform .7s var(--ease);
  }
  .price-card.reveal.is-visible{
    opacity:1;
    transform:translateY(var(--pc-lift));
  }
  /* ---- Carte "Présentation" : fond aurore + bordure lumineuse
     tournante (d'après le motif Uiverse de MuhammadHasann,
     transposé sur la palette bleue du site). ---- */
  .price-card.featured{
    --pc-glow:#4da6ff;           /* accent principal */
    --pc-glow-2:#8fcaff;         /* halo clair */
    --pc-ink:#04121f;            /* texte sur aplat bleu */
    --pc-spin:8s;                /* tour complet du faisceau */

    position:relative;isolation:isolate;
    border:1px solid transparent;
    border-radius:var(--radius-lg);
    background:
      /* aurore bleue : trois foyers colorés en bas, creusés par deux
         puits sombres en haut pour que le titre et le montant restent
         lisibles. Ellipses larges = transitions longues, pas de bandes. */
      radial-gradient(120% 80% at 50% -10%, rgba(12,17,25,0.96) 0%, transparent 70%),
      radial-gradient(90% 60% at 88% 22%, rgba(12,17,25,0.9) 0%, transparent 75%),
      radial-gradient(95% 85% at -10% 88%, rgba(19,96,176,0.85) 0%, transparent 72%),
      radial-gradient(110% 90% at 45% 118%, rgba(95,216,255,0.55) 0%, transparent 68%),
      radial-gradient(120% 100% at 108% 104%, rgba(77,166,255,0.95) 0%, transparent 70%),
      linear-gradient(200deg, #0b1017 0%, #0e1a2b 46%, #12263f 100%),
      #0c1119;
    box-shadow:inset 0 -16px 30px -4px rgba(143,202,255,0.22),
               inset 0 1px 0 rgba(200,230,255,0.18),
               0 24px 60px -20px rgba(77,166,255,0.6);
    --pc-lift:-10px;
    overflow:visible;
  }
  /* le fond opaque de la carte, posé par-dessus la bordure lumineuse :
     seul le liseré d'1px déborde et reste visible */
  .price-card.featured::after{
    content:'';position:absolute;inset:1px;z-index:1;
    border-radius:inherit;pointer-events:none;
    background:
      radial-gradient(120% 80% at 50% -10%, rgba(12,17,25,0.96) 0%, transparent 70%),
      radial-gradient(90% 60% at 88% 22%, rgba(12,17,25,0.9) 0%, transparent 75%),
      radial-gradient(95% 85% at -10% 88%, rgba(19,96,176,0.85) 0%, transparent 72%),
      radial-gradient(110% 90% at 45% 118%, rgba(95,216,255,0.55) 0%, transparent 68%),
      radial-gradient(120% 100% at 108% 104%, rgba(77,166,255,0.95) 0%, transparent 70%),
      linear-gradient(200deg, #0b1017 0%, #0e1a2b 46%, #12263f 100%),
      #0c1119;
  }
  /* :not(.card__border) — la piste lumineuse doit rester sous le fond.
     :not(.price-badge) — le badge garde son position:absolute (sinon
     il repasse dans le flux et s'étire sur toute la largeur). */
  .price-card.featured > *:not(.card__border):not(.price-badge){position:relative;z-index:2;}
  .price-card.featured .price-badge{z-index:3;}
  /* piste de la bordure : dégradé de base + faisceau qui tourne */
  .card__border{
    position:absolute;inset:-1px;z-index:0;
    border-radius:inherit;overflow:hidden;pointer-events:none;
    background:linear-gradient(0deg, rgba(200,230,255,0.55) -50%, rgba(90,110,135,0.35) 100%);
  }
  .card__border::before{
    content:'';position:absolute;
    top:50%;left:50%;width:200%;aspect-ratio:1;
    transform-origin:center;
    background:conic-gradient(from 0deg,
      transparent 0deg,
      var(--pc-glow) 60deg,
      var(--pc-glow-2) 90deg,
      var(--pc-glow) 120deg,
      transparent 190deg,
      transparent 360deg);
    animation:pc-rotate var(--pc-spin) linear infinite;
  }
  @keyframes pc-rotate{
    from{transform:translate(-50%,-50%) rotate(0deg);}
    to{transform:translate(-50%,-50%) rotate(360deg);}
  }
  /* le faisceau ne tourne que quand la carte est à l'écran */
  .price-card.featured:not(.is-visible) .card__border::before{animation-play-state:paused;}

  /* CTA de la carte : même bouton que partout (forme, taille, voile,
     shader), mais repeint en bleu de charte au lieu du noir. */
  .price-card.featured .price-cta.btn-primary{
    background:linear-gradient(180deg, #5fb2ff 0%, var(--tag-blue) 55%, #1f74cc 100%);
    color:#04121f;
    text-shadow:none;
    box-shadow:
      0 0 0 1px rgba(8,34,60,0.5),
      0 20px 12px -4px rgba(9,32,58,0.2),
      0 9px 9px -3px rgba(9,32,58,0.22),
      0 2px 5px 0 rgba(9,32,58,0.24),
      inset 0 1px 0 rgba(255,255,255,0.45);
  }
  .price-card.featured .price-cta.btn-primary .btn-label{color:#04121f;}
  /* le voile ::after du bouton est un noir 35 % : il éteindrait le
     bleu, on le passe en version claire */
  .price-card.featured .price-cta.btn-primary::after{
    background:linear-gradient(135deg, rgba(255,255,255,0.32), rgba(255,255,255,0.05) 55%, rgba(255,255,255,0.20));
    border-color:rgba(255,255,255,0.32);
    backdrop-filter:none;-webkit-backdrop-filter:none;
  }
  /* le shader animé est calibré pour un fond noir : neutralisé ici */
  .price-card.featured .price-cta.btn-primary .shader-mount{display:none;}

  /* puces : pastille bleue à coche, comme le motif d'origine */
  /* Carte mise en avant : même coche, seule la couleur change. La
     pastille pleine d'avant faisait un troisième niveau de traitement
     dans une liste qui n'en demande pas. */
  .price-card.featured .price-features li{color:var(--text-hi);}
  .price-card.featured .price-features li::before{background-color:var(--pc-glow);}
  @media (max-width:800px){ .price-card.featured{--pc-lift:0px;} }
  /* Badge : posé à l'intérieur de la carte, sur la ligne du libellé
     "Présentation" — à cheval sur le bord il coupait la bordure
     lumineuse animée. En verre bleu, pour ne pas faire doublon avec
     le CTA qui est désormais un aplat bleu plein. */
  .price-badge{
    position:absolute;top:30px;right:30px;z-index:3;
    display:inline-flex;align-items:center;gap:6px;
    padding:3px 9px 3px 8px;border-radius:99px;
    background:rgba(77,166,255,0.12);
    border:1px solid rgba(143,202,255,0.45);
    backdrop-filter:blur(8px) saturate(140%);
    -webkit-backdrop-filter:blur(8px) saturate(140%);
    box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),
               0 6px 18px -10px rgba(77,166,255,0.9);
    color:#cfe6ff;font-weight:600;
    font-size:9px;text-transform:uppercase;letter-spacing:0.09em;
    line-height:1.3;
    font-family:'IBM Plex Mono',monospace;
    white-space:nowrap;
  }
  /* pastille lumineuse en tête du badge */
  .price-badge::before{
    content:'';width:5px;height:5px;border-radius:50%;flex:0 0 auto;
    background:var(--pc-glow-2, #8fcaff);
    box-shadow:0 0 8px 1px rgba(143,202,255,0.9);
  }
  .price-card .tag2{font-size:11px;color:var(--tag-blue);text-transform:uppercase;letter-spacing:0.09em;font-family:'IBM Plex Mono',monospace;}
  .price-card .amount{font-family:'Big Shoulders Display',sans-serif;font-size:32px;font-weight:700;}
  .price-card .amount span{font-size:13px;color:var(--text-mid);font-weight:400;font-family:'IBM Plex Mono',monospace;text-transform:none;}
  .price-card .desc{color:var(--text-mid);font-size:14px;line-height:1.6;font-family:'Inter',sans-serif;text-transform:none;flex-grow:1;}
  /* list-style:none — sinon la puce native du <ul> s'ajoute au point
     bleu du ::before et on voit deux points par ligne */
  .price-features{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:9px;flex-grow:1;font-size:13.5px;color:var(--text-mid);font-family:'Inter',sans-serif;}
  .price-features li{padding-left:22px;position:relative;line-height:1.4;}
  /* Coche en masque plutôt qu'en caractère '✓' : le glyphe change de
     dessin et de chasse d'une police à l'autre, et il ne se colore pas
     indépendamment du texte. Le masque garde un tracé identique partout
     et prend sa couleur de background-color, donc des tokens. */
  .price-features li::before{
    content:'';position:absolute;left:0;top:2px;
    width:13px;height:13px;
    background-color:var(--tag-blue);
    -webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3 8.5l3.2 3.2L13 5' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat center / contain;
            mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3 8.5l3.2 3.2L13 5' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat center / contain;
  }
  .price-cta{margin-top:8px;align-self:stretch;text-align:center;}
  /* Le bouton primaire est un dégradé noir : sur la carte "Présentation"
     (fond #101a26 bleuté) il se noyait dans la carte. On le repeint en
     accent de charte — même traitement que le badge, texte sombre. */

  .price-guarantee{color:var(--text-mid);font-size:13px;line-height:1.6;margin-top:22px;max-width:78ch;}
  /* le mot sur les délais respire davantage : il clôt la section */
  .price-delay{margin-top:30px;padding-left:14px;border-left:2px solid var(--glass-border);}

  /* Options : liste tarifaire à points de conduite plutôt que des
     cartes — 5 items en grille laissaient une ligne orpheline et des
     hauteurs inégales. Deux colonnes qui se replient en une. */
  .addons-title{
    display:block;margin-top:34px;margin-bottom:14px;
    font-family:'IBM Plex Mono',monospace;font-size:11.5px;
    letter-spacing:0.08em;color:var(--tag-blue);
  }
  .addons-title::before{content:'[ ';color:var(--steel-mid);}
  .addons-title::after{content:' ]';color:var(--steel-mid);}
  /* 3 colonnes fixes : 5 options = 3 + 2, la seconde rangée centrée
     (les deux cartes prennent les colonnes 1-2 puis 2-3 via une
     grille à 6 sous-colonnes). Hauteurs égalisées par la grille. */
  /* ---- Options : liste tarifaire, plus des cartes ----
     Le format carte posait deux problèmes que la liste supprime d'un
     coup : cinq éléments dans une grille de 6 colonnes obligeaient à
     recentrer la seconde rangée à la main (nth-child 4 et 5), et le
     verre dépoli sur des boîtes de 112px faisait cinq blocs lourds
     pour cinq lignes de texte. Ce ne sont pas des produits, c'est un
     tarif : une ligne par option, le prix aligné à droite, des filets
     à la place des boîtes. Le regard descend une colonne de prix au
     lieu de scanner cinq rectangles. */
  .price-addons{
    display:flex;flex-direction:column;
    border-top:1px solid var(--glass-border);
  }
  .addon{
    position:relative;
    display:flex;align-items:center;gap:18px;
    padding:15px 14px;
    border-bottom:1px solid var(--glass-border);
    transition:background .3s var(--ease), padding .3s var(--ease);
  }
  /* Voile de survol, tiré depuis la gauche : il remplace l'ancien filet
     d'accent, qui n'a plus de sens sans boîte à border. */
  .addon::before{
    content:'';position:absolute;inset:0;
    background:linear-gradient(90deg,
      rgba(var(--tag-blue-rgb),0.10), transparent 65%);
    opacity:0;pointer-events:none;
    transition:opacity .3s var(--ease);
  }
  .addon > *{position:relative;z-index:1;}
  .addon-head{display:flex;align-items:center;gap:14px;flex:1;min-width:0;}
  .addon-ico{
    flex:none;
    width:32px;height:32px;
    display:inline-flex;align-items:center;justify-content:center;
    border-radius:var(--radius-sm);
    color:var(--tag-blue);
    background:rgba(var(--tag-blue-rgb),0.10);
    border:1px solid rgba(var(--tag-blue-rgb),0.20);
    transition:background .4s var(--ease), border-color .4s var(--ease),
               color .4s var(--ease);
  }
  .addon-ico svg{
    width:16px;height:16px;display:block;
    fill:none;stroke:currentColor;stroke-width:1.4;
    stroke-linecap:round;stroke-linejoin:round;
  }
  /* ---- Logo After Effects, recoloré sur la palette du site ----
     SVG inline et non <img src="ae.svg"> : c'est ce qui permet de
     styler les tracés depuis le CSS. Une image externe est une boîte
     noire, sa couleur ne peut pas suivre les tokens.
     Le violet Adobe (#9999FF sur #00005B) jurait à côté du bleu
     d'accent : deux bleus voisins mais non accordés, l'œil lit une
     erreur. Ici la forme du "Ae" est conservée — c'est elle qui
     identifie le logiciel — et seules les valeurs changent. */
  .ae-badge{
    display:inline-flex;flex:none;
    width:1.15em;height:1.15em;
    vertical-align:-0.18em;margin-right:0.45em;
  }
  .ae-badge svg{width:100%;height:100%;display:block;}
  .ae-plate{fill:rgba(var(--tag-blue-rgb),0.14);}
  .ae-mark{fill:#8fcaff;}
  /* Dans la liste d'options la pastille garde son cadre : la plaque du
     logo y est translucide, elle se pose donc dans le cadre existant
     au lieu de le doubler. */
  .addon-ico-ae svg{width:100%;height:100%;}
  .addon-ico-ae .ae-plate{fill:none;}     /* le cadre fait déjà la plaque */
  .formation-module h3 .ae-badge-sm{width:1em;height:1em;vertical-align:-0.12em;}

  .addon-name{color:var(--text-hi);font-size:14.5px;font-weight:500;line-height:1.4;}
  /* Prix calé à droite. En chasse fixe (IBM Plex Mono) : les montants
     s'alignent verticalement d'une ligne à l'autre, ce qui est tout
     l'intérêt de passer en liste. */
  .addon-price{
    margin-left:auto;flex:none;
    color:var(--tag-blue);font-size:14px;letter-spacing:0.02em;
    font-family:'IBM Plex Mono',monospace;white-space:nowrap;
    text-align:right;
    transition:color .3s var(--ease);
  }

  @media (max-width:560px){
    /* Trop étroit pour une ligne : le prix repasse sous le libellé,
       toujours aligné sur le texte et non sur l'icône. */
    .addon{flex-wrap:wrap;gap:6px 14px;padding:14px 10px;}
    .addon-head{flex:1 1 100%;}
    .addon-price{margin-left:46px;}
  }

  /* ---------- FORMATION ---------- */
  #formation{isolation:isolate;}
  .formation-bg{
    position:absolute;inset:-160px -120px 0;z-index:-1;pointer-events:none;
    background-image:radial-gradient(560px 380px at 75% 22%, rgba(77,166,255,0.07), transparent 70%);
  }

  .formation-head{max-width:560px;margin-bottom:56px;position:relative;}
  .formation-head p{color:var(--text-mid);font-size:15px;line-height:1.65;font-family:'Inter',sans-serif;text-transform:none;}
  .formation-title{margin-bottom:14px;}
  .formation-title-main{display:block;font-size:clamp(38px,6vw,64px);font-weight:800;line-height:1;}
  .formation-title-sub{
    display:block;margin-top:10px;font-size:clamp(14px,1.6vw,17px);font-weight:500;color:var(--text-mid);
    text-transform:none;font-family:'IBM Plex Mono',monospace;letter-spacing:0.05em;
  }

  .formation-block{margin-top:64px;}
  .formation-block-label{display:block;margin-bottom:24px;font-size:11px;color:var(--tag-blue);text-transform:uppercase;letter-spacing:0.09em;font-family:'IBM Plex Mono',monospace;}

  /* Modules ("Ce que vous pouvez apprendre") */
  .formation-modules{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;}
  @media (max-width:900px){ .formation-modules{grid-template-columns:repeat(2,1fr);} }
  @media (max-width:560px){ .formation-modules{grid-template-columns:1fr;} }
  .formation-module{
    grid-column:span 1;padding:26px 24px;display:flex;flex-direction:column;gap:10px;
    background:var(--panel);backdrop-filter:none;-webkit-backdrop-filter:none;
    transition:transform .4s var(--ease-in-out), border-color .4s var(--ease), background .4s var(--ease);
  }
  .formation-modules .formation-module:first-child{grid-column:span 2;}
  @media (max-width:900px){ .formation-modules .formation-module:first-child{grid-column:span 2;} }
  @media (max-width:560px){ .formation-modules .formation-module:first-child{grid-column:span 1;} }
  .formation-module .module-top{display:flex;align-items:baseline;justify-content:space-between;gap:12px;}
  .formation-module .module-num{font-family:'Big Shoulders Display',sans-serif;font-size:26px;font-weight:700;color:var(--text-low);transition:color .4s var(--ease);}
  .formation-module .module-cat{font-size:11.5px;color:var(--text-low);text-transform:uppercase;letter-spacing:0.09em;font-family:'IBM Plex Mono',monospace;}
  .formation-module h3{font-size:16.5px;font-weight:700;text-transform:none;font-family:'Inter',sans-serif;letter-spacing:0;color:var(--text-hi);}
  .formation-module p{font-size:13px;color:var(--text-mid);line-height:1.6;font-family:'Inter',sans-serif;}
  @media (hover:hover) and (pointer:fine){
    .formation-module:hover{border-color:var(--tag-blue);background:#101a26;transform:translateY(-4px);}
    .formation-module:hover .module-num{color:var(--tag-blue);}
  }

  /* Profils ("Pour qui ?") */
  .formation-profiles{display:grid;grid-template-columns:repeat(2,1fr);}
  @media (max-width:700px){ .formation-profiles{grid-template-columns:1fr;} }
  .formation-profile{
    display:flex;gap:20px;padding:24px 22px;border-top:1px solid var(--steel-line);border-right:1px solid var(--steel-line);
    transition:background .4s var(--ease), padding-left .4s var(--ease-in-out);
  }
  .formation-profiles .formation-profile:nth-child(2n){border-right:none;}
  .formation-profiles .formation-profile:nth-child(3),.formation-profiles .formation-profile:nth-child(4){border-bottom:1px solid var(--steel-line);}
  @media (max-width:700px){
    .formation-profile{border-right:none !important;}
    .formation-profiles .formation-profile:nth-child(3),.formation-profiles .formation-profile:nth-child(4){border-bottom:1px solid var(--steel-line);}
    .formation-profiles .formation-profile:last-child{border-bottom:none;}
  }
  .formation-profile .profile-num{font-family:'IBM Plex Mono',monospace;font-size:13px;color:var(--tag-blue);flex-shrink:0;padding-top:2px;}
  .formation-profile h3{font-size:15px;font-weight:700;text-transform:uppercase;letter-spacing:0.03em;margin-bottom:6px;font-family:'Big Shoulders Display',sans-serif;}
  .formation-profile p{font-size:13.5px;color:var(--text-mid);line-height:1.55;font-family:'Inter',sans-serif;}
  @media (hover:hover) and (pointer:fine){
    .formation-profile:hover{background:var(--glass-fill);padding-left:30px;}
  }

  /* Accompagnement (timeline) */
  .formation-timeline{display:grid;grid-template-columns:repeat(5,1fr);gap:0;position:relative;}
  @media (max-width:900px){ .formation-timeline{grid-template-columns:1fr;gap:22px;} }
  .timeline-step{
    position:relative;padding:0 18px 0 0;border-left:1px solid var(--steel-line);padding-left:18px;
  }
  .formation-timeline .timeline-step:first-child{border-left:none;padding-left:0;}
  @media (max-width:900px){
    .formation-timeline .timeline-step{border-left:none;padding-left:20px;border-top:1px solid var(--steel-line);padding-top:18px;}
    .formation-timeline .timeline-step:first-child{border-top:none;padding-top:0;}
  }
  .timeline-step .step-num{font-family:'Big Shoulders Display',sans-serif;font-size:20px;font-weight:700;color:var(--tag-blue);}
  .timeline-step .step-label{
    display:block;margin-top:8px;margin-bottom:8px;font-size:12px;font-weight:700;
    text-transform:uppercase;letter-spacing:0.08em;font-family:'IBM Plex Mono',monospace;color:var(--text-hi);
  }
  .timeline-step p{font-size:13px;color:var(--text-mid);line-height:1.55;font-family:'Inter',sans-serif;}

  /* CTA sur mesure */
  .formation-cta-panel{
    margin-top:64px;padding:44px 48px;display:flex;justify-content:space-between;align-items:center;gap:32px;flex-wrap:wrap;
  }
  .formation-cta-panel .formation-block-label{margin-bottom:12px;}
  .formation-cta-panel p{font-size:14.5px;color:var(--text-mid);line-height:1.6;max-width:400px;font-family:'Inter',sans-serif;}
  .formation-cta-right{display:flex;align-items:center;gap:28px;flex-wrap:wrap;}
  .formation-price{text-align:right;}
  .formation-price .amount{font-family:'Big Shoulders Display',sans-serif;font-size:22px;font-weight:700;color:var(--text-hi);}
  .formation-price span{display:block;font-size:11.5px;color:var(--text-low);text-transform:uppercase;letter-spacing:0.08em;font-family:'IBM Plex Mono',monospace;margin-top:4px;}
  @media (max-width:700px){ .formation-cta-panel{padding:32px 28px;} .formation-cta-right{width:100%;justify-content:space-between;} }

  /* ---------- CONTACT ---------- */
  .contact-panel{
    padding:64px 56px;text-align:center;display:flex;flex-direction:column;align-items:center;gap:26px;
  }
  .contact-panel h2{font-size:clamp(30px,5vw,52px);font-weight:700;max-width:640px;}
  .contact-panel p{color:var(--text-mid);max-width:460px;line-height:1.6;font-family:'Inter',sans-serif;text-transform:none;}
  .contact-links{display:flex;flex-wrap:wrap;gap:14px;justify-content:center;align-items:center;margin-top:8px;max-width:100%;}
  @media (max-width:520px){
    .contact-links .btn{flex:1 0 100%;padding-left:14px;padding-right:14px;font-size:12.5px;}
  }

  /* ---------- SOCIAL BUTTONS ---------- */
  .social-btn{
    position:relative;display:inline-flex;align-items:center;justify-content:center;
    width:50px;height:50px;flex-shrink:0;
    border-radius:var(--radius-md);
    background:var(--panel);
    border:1px solid var(--glass-border);
    overflow:hidden;
    box-shadow:0 10px 24px -18px rgba(0,0,0,0.7);
    transition:transform .25s var(--ease), border-color .3s var(--ease), background .3s var(--ease), box-shadow .3s var(--ease);
  }
  .social-btn::before{
    content:'';position:absolute;inset:0;border-radius:inherit;opacity:0;pointer-events:none;
    background:radial-gradient(circle at 50% 42%, var(--social-glow, var(--tag-blue)) 0%, transparent 70%);
    filter:blur(9px);
    transition:opacity .35s var(--ease);
  }
  .social-icon-mask{
    position:absolute;inset:0;margin:auto;width:20px;height:20px;
    background:var(--text-mid);
    transform:scale(0.9709);
    -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
    -webkit-mask-position:center;mask-position:center;
    -webkit-mask-size:contain;mask-size:contain;
    transition:opacity .35s var(--ease);
  }
  .social-icon-color{
    position:absolute;inset:0;margin:auto;width:20px;height:20px;opacity:0;
    object-fit:contain;
    transform:scale(0.9709);
    transition:opacity .35s var(--ease);
  }
  .social-btn.is-instagram{--social-glow:#e1306c;}
  .social-btn.is-instagram .social-icon-mask{-webkit-mask-image:url('upload/instagram.svg');mask-image:url('upload/instagram.svg');}
  .social-btn.is-tiktok{--social-glow:#25f4ee;}
  .social-btn.is-tiktok .social-icon-mask{-webkit-mask-image:url('upload/tiktok.svg');mask-image:url('upload/tiktok.svg');}

  .social-btn:hover, .social-btn:focus-visible{
    transform:translateY(-2px) scale(1.03);
    border-color:var(--glass-border-strong);
    background:#101a26;
  }
  .social-btn:hover::before, .social-btn:focus-visible::before{opacity:0.4;}
  .social-btn:hover .social-icon-mask, .social-btn:focus-visible .social-icon-mask{opacity:0;}
  .social-btn:hover .social-icon-color, .social-btn:focus-visible .social-icon-color{opacity:1;}
  .social-btn:focus-visible{outline:2px solid var(--ice);outline-offset:3px;}

  footer{padding:32px 0 46px;}
  .foot-row{
    display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:16px;
    color:var(--text-low);font-size:12.5px;padding-top:24px;border-top:1px solid var(--steel-line);
    font-family:'IBM Plex Mono',monospace;
  }
  .foot-row .domain{display:inline-flex;flex-direction:row;align-items:center;color:var(--tag-blue);font-family:'IBM Plex Mono',monospace;font-size:12px;}

  /* ---------- HOVER (souris fine uniquement — évite le sticky-hover tactile) ---------- */
  @media (hover:hover) and (pointer:fine){
    .navlinks a:hover{color:var(--text-hi);}
    .navlinks a:hover::after{transform:scaleX(1);}
    .mobile-menu a:hover{color:var(--text-hi);}
    .btn-ghost:hover{border-color:var(--glass-border-strong);}
    .btn:hover{transform:translateY(-2px);}
    .btn:active{transform:translateY(0);}
    .btn-primary:hover .btn-arrow{transform:translateY(0);width:13px;opacity:1;margin-right:7px;}
    /* Survol : bloom au maximum, scale < 1.02.
       Écrit en variables, pas en filter/transform : le JS pose les mêmes
       variables en style inline (qui gagne), donc quand la boucle tourne
       c'est elle qui pilote — avec inertie. Cette règle est le repli
       quand le JS ne tourne pas. */
    .hero h1 .premium-word:hover{
      --pw-int:1;
      --pw-scale:1.015;
      /* Sweep chrome : plus vif et plus rapide qu'au repos, et surtout
         en boucle serrée — tant que le curseur reste, le métal continue
         de renvoyer la lumière. */
      --pw-sweep-a:0.92;
      animation:pw-sweep-hover 3.2s linear infinite;
    }
    /* Mise au point sur la carte survolée : les autres reculent, floutées
       et rétrécies. La règle porte sur .work-list:hover, pas sur chaque
       carte — c'est le conteneur qui sait qu'UNE de ses cartes est visée,
       et :not(:hover) désigne alors toutes les autres.
       Pas de scale d'agrandissement sur la carte survolée : attachTilt
       agrandit déjà son .media de 1,32, les deux se multiplieraient. */
    .work-list:hover > .work-card:not(:hover){
      filter:blur(10px);
      transform:scale(0.9);
    }
    .work-card:hover .frame{border-color:var(--glass-border-strong);}
    .work-card:hover .info .name,
    .work-card:hover .info .tag{text-shadow:0 10px 18px rgba(0,0,0,0.7);}
    .about-item:hover{transform:translateX(3px);}
    .about-item:hover .n{color:var(--tag-blue);}
    .ac-logo:hover{filter:none;opacity:1;border-color:rgba(143,202,255,0.5);transform:translateY(-2px);}
    .avis-card:hover{
      transform:translateY(-4px);
      border-color:rgba(var(--av-accent),0.45);
      box-shadow:inset 0 1px 0 rgba(200,225,255,0.08),
                 0 22px 44px -26px rgba(var(--av-accent),0.6);
    }
    .avis-card:hover::before{opacity:1;}
    /* Étoiles au survol : cascade de gauche à droite.
       Primaire  = l'étoile se soulève et grossit (scale, la propriété
                   de l'emphase) ;
       secondaire= la lueur s'intensifie en même temps ;
       le léger dépassement (1.56 sur la courbe) donne le rebond d'un
       objet léger — 22 % d'amplitude, pas plus : au-delà ça devient
       un gadget sur un bloc de témoignage.
       45 ms × 5 = 180 ms de cascade, bien sous le budget de 500 ms. */
    .avis-card:hover .stars i{
      transform:translateY(-3px) scale(1.22);
      text-shadow:0 0 16px rgba(255,198,61,0.85);
      transition:transform .26s cubic-bezier(.34,1.56,.64,1),
                 text-shadow .26s var(--ease);
    }
    .avis-card:hover .stars i:nth-child(1){transition-delay:0ms;}
    .avis-card:hover .stars i:nth-child(2){transition-delay:45ms;}
    .avis-card:hover .stars i:nth-child(3){transition-delay:90ms;}
    .avis-card:hover .stars i:nth-child(4){transition-delay:135ms;}
    .avis-card:hover .stars i:nth-child(5){transition-delay:180ms;}
    /* Le survol s'ajoute à la surélévation de base au lieu de la
       remplacer : sinon la carte "Recommandé" RETOMBERAIT de 10px avant
       de monter, puisque son -14px absolu vaut -4px de mouvement réel. */
    .price-card:hover{border-color:var(--tag-blue);box-shadow:0 20px 45px -22px rgba(77,166,255,0.4);transform:translateY(calc(var(--pc-lift) - 6px));}
    /* Les deux ombres `inset` sont reprises à l'identique : une liste de
       box-shadow ne s'interpole que si les ombres se correspondent une à
       une, `inset` compris. En n'écrivant que l'ombre externe, la liste
       passait de 3 à 1 et la transition devenait discrète — la lueur
       sautait. Les reprendre règle le fondu ET conserve le modelé
       interne de la carte, qui disparaissait au survol. */
    .price-card.featured:hover{
      box-shadow:inset 0 -16px 30px -4px rgba(143,202,255,0.22),
                 inset 0 1px 0 rgba(200,230,255,0.18),
                 0 26px 60px -20px rgba(77,166,255,0.65);
      transform:translateY(calc(var(--pc-lift) - 6px));
    }
    .price-card.featured .price-cta.btn-primary:hover{
      background:linear-gradient(180deg, #8ccdff 0%, #5fb2ff 55%, #2d86e0 100%);
      box-shadow:
        0 0 0 1px rgba(8,34,60,0.55),
        0 12px 6px -2px rgba(9,32,58,0.12),
        0 8px 5px -2px rgba(9,32,58,0.16),
        0 4px 4px 0 rgba(9,32,58,0.18),
        inset 0 1px 0 rgba(255,255,255,0.55);
    }
    /* La ligne se décale légèrement vers la droite au survol, comme une
       entrée que l'on tire hors de la liste. Un translateY aurait fait
       vibrer les filets voisins. */
    .addon:hover{padding-left:22px;}
    .addon:hover::before{opacity:1;}
    .addon:hover .addon-price{color:#8fcaff;}
    .addon:hover .addon-ico{
      color:#8fcaff;
      background:rgba(var(--tag-blue-rgb),0.18);
      border-color:rgba(var(--tag-blue-rgb),0.38);
    }
    /* Le logo AE est en fill, pas en currentColor : il ne suivrait pas
       la règle ci-dessus. On l'éclaircit explicitement. */
    .addon:hover .addon-ico-ae .ae-mark{fill:#bfe0ff;}
    /* .avis-card exclue : elle a sa propre transition (avec box-shadow,
       sinon la lueur de survol apparaissait d'un coup) */
    /* filter ajouté pour la mise au point : sans lui le flou des cartes
       voisines apparaîtrait et disparaîtrait d'un coup. Durée alignée sur
       les 400ms de l'effet d'origine, plus lente que le transform pour que
       le recul se lise avant le flou. */
    .work-card{transition:opacity .6s var(--ease), transform .2s var(--ease),
               border-color .3s var(--ease), filter .4s var(--ease);}

    /* .price-card séparée de .work-card pour la même raison que
       .avis-card. Cette règle arrive APRÈS celle de .price-card (l.1523)
       et, à spécificité égale, l'écrase : omettre box-shadow ici privait
       la lueur de toute transition, elle apparaissait et disparaissait
       d'un coup. La lueur de .work-card, elle, est portée par .media qui
       a sa propre transition — d'où la séparation plutôt qu'un ajout.
       Contour et lueur partagent durée et courbe : le fondu est
       identique à l'aller et au retour. */
    .price-card{
      transition:opacity .6s var(--ease),
                 transform .2s var(--ease),
                 border-color .45s var(--ease),
                 box-shadow .45s var(--ease);
    }
  }

  /* ============================================================
     BANDEAU CLIENTS — preuve placée juste sous le hero.
     Extrait du pied d'"À propos" : un dirigeant cherche la preuve
     avant la présentation. Bandeau bas, sans boîte : il ponctue
     le hero, il ne doit pas se lire comme une section à part.
     ============================================================ */
  .clients-strip{
    display:flex;align-items:center;gap:28px;flex-wrap:wrap;
    padding:22px 0 4px;
    border-top:1px solid var(--steel-line);
    border-bottom:1px solid var(--steel-line);
    margin-bottom:0;
  }
  .cs-label{
    font-family:'IBM Plex Mono',monospace;font-size:11.5px;
    letter-spacing:0.14em;color:var(--text-low);
    text-transform:uppercase;flex:none;
  }
  .clients-strip .about-clients{margin:0;}
  @media (max-width:700px){
    .clients-strip{gap:14px;padding:18px 0;}
  }

  /* ============================================================
     DÉROULÉ D'UN PROJET
     ============================================================ */
  /* Le délai est l'information la plus attendue après le prix : il est
     sorti de la liste et posé en tête, en gros, pour être lu sans
     effort de lecture. */
  .process-lead{
    display:flex;align-items:baseline;gap:18px;flex-wrap:wrap;
    padding:22px 24px;margin-bottom:34px;
    border-radius:var(--radius-md);
    background:
      radial-gradient(120% 100% at 0% 0%, rgba(var(--tag-blue-rgb),0.10), transparent 62%),
      var(--panel);
    border:1px solid var(--glass-border);
  }
  .pl-value{
    font-family:'Big Shoulders Display',sans-serif;
    font-size:34px;font-weight:700;line-height:1;
    color:var(--tag-blue);
    text-shadow:0 0 26px rgba(var(--tag-blue-rgb),0.35);
  }
  /* Le chiffre est isolé du mot "jours" : seul lui est animé.
     display:inline-block + largeur minimale pour que le mot ne se
     décale pas pendant le comptage — le chiffre passe de 1 à 1 caractère
     ici, mais la règle protège d'un futur "14" ou "21". */
  .pl-count{
    display:inline-block;min-width:1ch;text-align:right;
    font-weight:inherit;
    font-variant-numeric:tabular-nums;
  }
  /* Pulsation unique à l'arrivée : la lueur enfle puis retombe. Elle
     signale la fin du comptage sans ajouter de mouvement au chiffre,
     déjà en mouvement pendant une seconde. */
  .pl-count.is-landed{animation:pl-land .5s var(--ease);}
  @keyframes pl-land{
    0%{text-shadow:0 0 26px rgba(var(--tag-blue-rgb),0.35);transform:scale(1);}
    40%{text-shadow:0 0 34px rgba(var(--tag-blue-rgb),0.85);transform:scale(1.12);}
    100%{text-shadow:0 0 26px rgba(var(--tag-blue-rgb),0.35);transform:scale(1);}
  }
  @media (prefers-reduced-motion:reduce){
    .pl-count.is-landed{animation:none;}
  }
  .pl-label{
    font-family:'Inter',sans-serif;text-transform:none;
    font-size:14px;color:var(--text-mid);line-height:1.5;max-width:42ch;
  }

  /* Trois colonnes : les six étapes tiennent en deux rangées franches.
     Une seule colonne aurait donné une liste de six lignes très haute,
     que personne ne lit jusqu'au bout. */
  .process-steps{
    display:grid;grid-template-columns:repeat(3,1fr);gap:1px;
    background:var(--steel-line);
    border:1px solid var(--steel-line);
    border-radius:var(--radius-md);
    overflow:hidden;
  }
  /* Les filets de séparation sont le fond de la grille qui transparaît
     dans le gap de 1px : pas de bordure à gérer par cellule, donc pas
     de doublon sur les bords ni de nth-child à corriger. */
  .step{
    position:relative;
    display:flex;align-items:flex-start;gap:14px;
    padding:24px 22px;
    background:var(--panel);
    transition:background .3s var(--ease);
  }
  .step-num{
    font-family:'IBM Plex Mono',monospace;font-size:12px;
    letter-spacing:0.1em;color:var(--tag-blue);
    flex:none;padding-top:3px;
    transition:color .3s var(--ease);
  }
  .step-d h3{
    font-family:'Inter',sans-serif;text-transform:none;letter-spacing:0;
    font-size:15px;font-weight:600;color:var(--text-hi);
    margin-bottom:7px;
  }
  .step-d p{
    font-family:'Inter',sans-serif;text-transform:none;
    font-size:13.5px;line-height:1.6;color:var(--text-mid);
  }
  @media (hover:hover){
    .step:hover{background:#101a26;}
    .step:hover .step-num{color:#8fcaff;}
  }
  @media (max-width:900px){
    .process-steps{grid-template-columns:repeat(2,1fr);}
  }
  @media (max-width:560px){
    .process-steps{grid-template-columns:1fr;}
    .pl-value{font-size:28px;}
  }

  /* ================================================================
     PAGE LÉGALE (mentions-legales.html)
     Prose longue : la largeur de lecture prime sur la grille du site.
     ================================================================ */
  .page-legal #legal{padding:56px 0 24px;}
  .legal-updated{color:var(--text-low);font-size:12px;margin-bottom:28px;}

  .legal-block{
    padding:26px 28px;border-radius:var(--radius-lg);margin-bottom:18px;
    max-width:780px;
  }
  .legal-block h3{
    font-family:'Big Shoulders Display',sans-serif;
    font-size:21px;font-weight:700;color:var(--text-hi);
    margin-bottom:14px;letter-spacing:0.01em;
  }
  .legal-block p{
    font-family:'Inter',sans-serif;font-size:14.5px;line-height:1.72;
    color:var(--text-mid);margin-bottom:11px;
  }
  .legal-block p:last-child{margin-bottom:0;}
  .legal-block strong{color:var(--text-hi);font-weight:600;}
  .legal-block a{color:var(--tag-blue);text-decoration:underline;text-underline-offset:2px;}

  .legal-list{
    list-style:none;margin:0 0 11px;padding:0;
    font-family:'Inter',sans-serif;font-size:14.5px;line-height:1.72;color:var(--text-mid);
  }
  .legal-list li{position:relative;padding-left:18px;margin-bottom:6px;}
  .legal-list li::before{
    content:'';position:absolute;left:2px;top:0.65em;
    width:5px;height:5px;border-radius:50%;background:var(--tag-blue);opacity:0.55;
  }

  /* Paires libellé / valeur des blocs d'identification */
  .legal-dl{
    display:grid;grid-template-columns:minmax(140px,190px) 1fr;
    gap:9px 20px;margin:0;
  }
  .legal-dl dt{
    font-family:'IBM Plex Mono',monospace;font-size:11px;
    text-transform:uppercase;letter-spacing:0.07em;
    color:var(--text-low);padding-top:2px;
  }
  .legal-dl dd{
    margin:0;font-family:'Inter',sans-serif;font-size:14.5px;
    line-height:1.6;color:var(--text-mid);
  }
  @media (max-width:600px){
    .legal-dl{grid-template-columns:1fr;gap:2px 0;}
    .legal-dl dd{margin-bottom:12px;}
    .legal-block{padding:22px 20px;}
  }

  /* Remarque de travail : visible, mais en retrait du texte contractuel */
  .legal-note{
    border-left:2px solid var(--glass-border-strong);
    padding-left:14px;font-size:13px !important;color:var(--text-low) !important;
    margin-top:14px;
  }

  /* Champ obligatoire non renseigné. Volontairement criard : ce fichier
     ne doit pas pouvoir partir en production avec un seul de ces blocs
     encore en place. */
  .todo{
    display:inline-block;
    font-family:'IBM Plex Mono',monospace;font-size:12.5px;
    color:#ffd5d5;background:rgba(255,59,59,0.13);
    border:1px dashed rgba(255,59,59,0.55);border-radius:var(--radius-sm);
    padding:1px 7px;
  }

  .legal-cgv-head{margin-top:56px;}
  .legal-disclaimer{border-color:rgba(255,59,59,0.3);}

  .foot-legal a{color:var(--text-low);text-decoration:none;transition:color .25s var(--ease);}
  .foot-legal a:hover{color:var(--tag-blue);}


  /* ================================================================
     PLUIE DE LUMIÈRE — le quadrillage s'allume au passage
     ----------------------------------------------------------------
     Aucun trait visible : rien n'est peint en dehors des lignes du
     quadrillage. Ce sont les lignes elles-mêmes qui s'éclairent au
     passage d'une nappe lumineuse qui descend.

     Même principe que .bg-pattern::before (le halo sous le curseur),
     mais piloté par une nappe qui tombe au lieu de suivre la souris.

     Montage, de l'extérieur vers l'intérieur :
       .rain       estompe radiale de la page + découpe du cadre
       .rain-grid  masque à la trame du quadrillage : SEULS les pixels
                   de ligne peuvent être peints
       span        la nappe de lumière, qui descend en translate3d

     La lumière est donc portée par les spans (translation composée par
     le GPU, zéro repeint) et découpée par le masque du parent. Placer
     la trame sur les spans eux-mêmes ne marcherait pas : elle
     descendrait avec eux et se désaligner ait du quadrillage fixe.

     La géométrie doit rester identique à .bg-pattern (32px, origine en
     haut à gauche du viewport), sinon les lignes allumées se décalent
     d'avec les lignes éteintes.
     ================================================================ */
  .rain{
    position:fixed;inset:0;z-index:0;pointer-events:none;overflow:hidden;
    /* le quadrillage de base est lui aussi estompé sur les bords :
       sans ça, on allumerait des lignes là où il n'y en a plus */
    -webkit-mask-image:radial-gradient(ellipse at center, #000, transparent);
    mask-image:radial-gradient(ellipse at center, #000, transparent);
  }
  .rain-grid{
    position:absolute;inset:0;overflow:hidden;
    /* Deux couches de masque = union par défaut (mask-composite:add),
       donc la trame complète. Mêmes 32px que .bg-pattern. */
    -webkit-mask-image:
      linear-gradient(to right, #000 1px, transparent 1px),
      linear-gradient(to bottom, #000 1px, transparent 1px);
    mask-image:
      linear-gradient(to right, #000 1px, transparent 1px),
      linear-gradient(to bottom, #000 1px, transparent 1px);
    -webkit-mask-size:32px 32px;
    mask-size:32px 32px;
  }
  .rain-grid span{
    position:absolute;top:0;height:var(--h);
    background:radial-gradient(ellipse 52% 52% at 50% 50%,
      rgba(var(--tag-blue-rgb),var(--i)) 0%,
      rgba(var(--tag-blue-rgb),calc(var(--i) * 0.78)) 34%,
      rgba(var(--tag-blue-rgb),calc(var(--i) * 0.34)) 58%,
      transparent 78%);
    animation:light-fall var(--dur) linear infinite;
    will-change:transform;
  }
  /* Quatorze nappes : la densité fait la pluie. Les durées sont
     mutuellement non multiples (5,3 / 6,1 / 6,9 …) — avec autant de
     sources, des durées harmoniques les regrouperaient périodiquement
     en une seule vague au lieu d'une averse continue. */
  .rain-grid span:nth-child(1){ left:-8%; width:20%; --h:24vh; --i:0.72; --dur:5.3s; animation-delay:-1s; }
  .rain-grid span:nth-child(2){ left:4%; width:14%; --h:18vh; --i:0.8; --dur:6.1s; animation-delay:-4s; }
  .rain-grid span:nth-child(3){ left:12%; width:24%; --h:28vh; --i:0.58; --dur:6.9s; animation-delay:-9s; }
  .rain-grid span:nth-child(4){ left:21%; width:16%; --h:15vh; --i:0.76; --dur:7.7s; animation-delay:-2s; }
  .rain-grid span:nth-child(5){ left:29%; width:22%; --h:26vh; --i:0.62; --dur:8.3s; animation-delay:-12s; }
  .rain-grid span:nth-child(6){ left:37%; width:13%; --h:20vh; --i:0.84; --dur:9.1s; animation-delay:-6s; }
  .rain-grid span:nth-child(7){ left:44%; width:25%; --h:30vh; --i:0.55; --dur:9.7s; animation-delay:-15s; }
  .rain-grid span:nth-child(8){ left:52%; width:17%; --h:17vh; --i:0.78; --dur:10.3s; animation-delay:-3s; }
  .rain-grid span:nth-child(9){ left:59%; width:21%; --h:23vh; --i:0.64; --dur:11.1s; animation-delay:-8s; }
  .rain-grid span:nth-child(10){ left:66%; width:14%; --h:27vh; --i:0.82; --dur:11.9s; animation-delay:-17s; }
  .rain-grid span:nth-child(11){ left:73%; width:23%; --h:16vh; --i:0.6; --dur:12.7s; animation-delay:-5s; }
  .rain-grid span:nth-child(12){ left:80%; width:15%; --h:25vh; --i:0.75; --dur:13.3s; animation-delay:-10s; }
  .rain-grid span:nth-child(13){ left:87%; width:19%; --h:21vh; --i:0.68; --dur:14.1s; animation-delay:-13s; }
  .rain-grid span:nth-child(14){ left:93%; width:12%; --h:29vh; --i:0.86; --dur:15.1s; animation-delay:-7s; }
  @keyframes light-fall{
    from{transform:translate3d(0,calc(-1 * var(--h)),0);}
    to  {transform:translate3d(0,100vh,0);}
  }
  /* La descente EST l'effet : à l'arrêt il ne resterait que des zones
     du quadrillage plus claires que d'autres, sans raison apparente. */
  @media (prefers-reduced-motion:reduce){ .rain{display:none;} }
  /* Sur mobile, .bg-pattern::before est déjà désactivé (pas de curseur) :
     on garde la lumière, c'est la seule vie du fond qui reste. */

  /* Échange d'icônes des commandes son : une seule des deux est montée à
     la fois, l'état est porté par aria-pressed et le CSS le reflète. */
  .snd-btn .ico-sound-on{display:none;}
  .snd-btn[aria-pressed="true"] .ico-sound-off{display:none;}
  .snd-btn[aria-pressed="true"] .ico-sound-on{display:block;}

  /* ================================================================
     FORMULAIRE DE QUALIFICATION (#contact)
     Quatre champs, pas un de plus. Les fourchettes de budget sont
     affichées en clair : elles qualifient le prospect ET normalisent le
     tarif haut, qui paraît légitime dès lors qu'il figure dans une liste.
     ================================================================ */
  .lead-form{
    display:flex;flex-direction:column;gap:20px;
    max-width:460px;margin:30px auto 8px;text-align:left;
  }
  .lf-row{border:0;padding:0;margin:0;min-width:0;}
  .lf-label{
    display:block;margin-bottom:9px;padding:0;
    font-family:'IBM Plex Mono',monospace;font-size:11.5px;
    text-transform:uppercase;letter-spacing:0.12em;color:var(--text-low);
  }

  /* ---- Liste déroulante ---- */
  .lf-select{position:relative;}
  .lf-select select{
    appearance:none;-webkit-appearance:none;
    width:100%;padding:12px 38px 12px 14px;
    font-family:'Inter',sans-serif;font-size:14.5px;color:var(--text-hi);
    background:var(--glass-fill);border:1px solid var(--glass-border);
    border-radius:var(--radius-md);cursor:pointer;
    transition:border-color .3s var(--ease), background .3s var(--ease);
  }
  /* Le placeholder ne doit pas se lire comme une réponse déjà donnée. */
  .lf-select select:invalid{color:var(--text-low);}
  .lf-select select option{background:var(--panel);color:var(--text-hi);}
  .lf-chevron{
    position:absolute;right:14px;top:50%;transform:translateY(-50%);
    width:14px;height:14px;pointer-events:none;
    fill:none;stroke:var(--steel-mid);stroke-width:1.6;
    stroke-linecap:round;stroke-linejoin:round;
  }

  /* ---- Choix segmentés (durée, budget) ---- */
  /* nowrap : les trois paliers doivent rester sur UNE ligne. Un retour à
     la ligne casserait la lecture comparative — c'est en les voyant côte
     à côte que « 700 € et + » se lit comme une option parmi d'autres. */
  .lf-choices{display:flex;gap:8px;flex-wrap:nowrap;}
  /* flex-basis:auto et non 0 : la base de calcul est la largeur du texte,
     donc chaque pastille part de ce qu'il lui faut puis se partage
     l'espace restant. Avec une base à 0 les trois recevaient la même
     largeur quelle que soit la longueur du libellé, et les plus longs
     étaient rognés. */
  .lf-chip{flex:1 1 auto;cursor:pointer;}
  /* L'input reste focusable au clavier : masqué visuellement seulement,
     jamais display:none, qui le sortirait de l'ordre de tabulation. */
  .lf-chip input{position:absolute;opacity:0;width:0;height:0;}
  .lf-chip span{
    display:block;padding:11px 8px;text-align:center;
    white-space:nowrap;
    font-family:'IBM Plex Mono',monospace;font-size:12.5px;
    color:var(--text-mid);
    background:var(--glass-fill);border:1px solid var(--glass-border);
    border-radius:var(--radius-md);
    transition:color .3s var(--ease), background .3s var(--ease),
               border-color .3s var(--ease);
  }
  .lf-chip input:checked + span{
    color:var(--tag-blue);
    background:rgba(var(--tag-blue-rgb),0.12);
    border-color:rgba(var(--tag-blue-rgb),0.45);
  }
  .lf-chip input:focus-visible + span{
    outline:2px solid var(--tag-blue);outline-offset:2px;
  }

  /* ---- Email ---- */
  .lf-input{
    width:100%;padding:12px 14px;
    font-family:'Inter',sans-serif;font-size:14.5px;color:var(--text-hi);
    background:var(--glass-fill);border:1px solid var(--glass-border);
    border-radius:var(--radius-md);
    transition:border-color .3s var(--ease), background .3s var(--ease);
  }
  .lf-input::placeholder{color:var(--text-low);}
  .lf-select select:focus,.lf-input:focus{
    outline:none;border-color:rgba(var(--tag-blue-rgb),0.5);
    background:var(--glass-fill-strong);
  }
  /* Erreur signalée seulement après une tentative d'envoi : :invalid seul
     colorerait en rouge des champs que le visiteur n'a pas encore atteints. */
  .lead-form.is-checked :invalid{border-color:rgba(255,59,59,0.55);}

  .lf-submit{width:100%;margin-top:4px;}
  .lf-status{
    min-height:18px;margin:0;text-align:center;
    font-family:'IBM Plex Mono',monospace;font-size:12px;color:var(--text-low);
  }
  .lf-status.is-error{color:#ff8a8a;}
  /* Succès : le seul vert du site, et c'est voulu — il ne sert qu'ici.
     Un envoi confirmé en bleu d'accent se confondrait avec le reste de
     l'interface, alors que c'est le seul moment où l'état compte.
     #6ee7a8 sur le panneau sombre tient largement le 4,5:1. */
  .lf-status.is-ok{
    display:flex;align-items:center;justify-content:center;gap:7px;
    color:#6ee7a8;
  }
  .lf-status-ico{
    width:14px;height:14px;flex:none;
    fill:none;stroke:currentColor;stroke-width:1.5;
    stroke-linecap:round;stroke-linejoin:round;
    /* la coche se trace : l'envoi a un instant de bascule, il se voit */
    animation:lf-ok-pop .42s var(--ease) both;
  }
  @keyframes lf-ok-pop{
    from{transform:scale(0.4);opacity:0;}
    60%{transform:scale(1.12);opacity:1;}
    to{transform:scale(1);opacity:1;}
  }
  @media (prefers-reduced-motion:reduce){
    .lf-status-ico{animation:none;}
  }

  .lf-call{
    display:inline-flex;align-items:center;gap:8px;
    font-family:'Inter',sans-serif;font-size:13.5px;color:var(--text-mid);
    text-decoration:none;transition:color .3s var(--ease);
  }
  .lf-call svg{width:15px;height:15px;fill:none;stroke:currentColor;
    stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;}
  .lf-call:hover{color:var(--tag-blue);}

  .contact-alt{
    margin:26px 0 14px;
    font-family:'IBM Plex Mono',monospace;font-size:11.5px;
    text-transform:uppercase;letter-spacing:0.12em;color:var(--text-low);
  }
  /* Sous 560px on resserre au lieu d'empiler : c'est la marge latérale du
     panneau qui libère la place, pas la mise sur plusieurs lignes. */
  @media (max-width:560px){
    .contact-panel{padding:44px 18px;}
    .lf-choices{gap:6px;}
    .lf-chip span{padding:11px 6px;}
  }

  /* ---- Réservation d'appel ---- */
  .book-call{
    display:flex;flex-direction:column;align-items:center;gap:12px;
    margin-top:18px;
  }
  .book-sep{
    font-family:'IBM Plex Mono',monospace;font-size:11.5px;
    text-transform:uppercase;letter-spacing:0.12em;color:var(--text-low);
  }
  .book-btn{
    display:inline-flex;align-items:center;gap:9px;
    padding:11px 20px;border-radius:var(--radius-md);
    font-family:'Inter',sans-serif;font-size:14px;font-weight:500;
    color:var(--text-hi);text-decoration:none;
    background:var(--glass-fill);border:1px solid var(--glass-border);
    transition:color .3s var(--ease), background .3s var(--ease),
               border-color .3s var(--ease);
  }
  .book-btn svg{width:15px;height:15px;flex:none;
    fill:none;stroke:currentColor;stroke-width:1.5;
    stroke-linecap:round;stroke-linejoin:round;}
  @media (hover:hover){
    .book-btn:hover{
      color:var(--tag-blue);
      background:rgba(var(--tag-blue-rgb),0.10);
      border-color:rgba(var(--tag-blue-rgb),0.30);
    }
  }
  /* Le widget Calendly se charge au clic : sans retour visuel, le délai
     réseau passerait pour un bouton cassé. */
  .book-btn.is-loading{opacity:0.6;pointer-events:none;}
  .book-btn.is-loading svg{animation:book-spin 0.9s linear infinite;}
  @keyframes book-spin{to{transform:rotate(360deg);}}

  /* ================================================================
     FORMULAIRE — interactions
     ----------------------------------------------------------------
     user-select:none sur les commandes uniquement. Le champ e-mail et
     les textes de statut restent sélectionnables : empêcher un visiteur
     de relire ou copier ce qu'il vient de saisir serait une régression,
     pas une finition.
     ================================================================ */
  .lead-form .lf-label,
  .lead-form .lf-chip,
  .lead-form .lf-submit,
  .lf-combo-btn,
  .lf-combo-list,
  .book-btn,
  .contact-alt{
    -webkit-user-select:none;user-select:none;
  }

  /* ---- Pastilles durée / budget ---- */
  @media (hover:hover){
    .lf-chip:hover span{
      color:var(--text-hi);
      background:var(--glass-fill-strong);
      border-color:var(--glass-border-strong);
      transform:translateY(-2px);
    }
    .lf-chip input:checked + span:hover{color:var(--tag-blue);}
  }
  .lf-chip span{transition:color .3s var(--ease), background .3s var(--ease),
                border-color .3s var(--ease), transform .18s var(--ease);}
  /* Retour au clic : l'enfoncement doit être plus rapide que le survol,
     sinon le geste paraît mou. */
  .lf-chip:active span{transform:translateY(0) scale(0.96);transition-duration:.08s;}
  /* Confirmation du choix : une brève dilatation au moment où la pastille
     devient active. Se rejoue à chaque nouveau choix. */
  .lf-chip input:checked + span{animation:lf-pick .34s var(--ease);}
  @keyframes lf-pick{
    0%{transform:scale(0.94);}
    55%{transform:scale(1.04);}
    100%{transform:scale(1);}
  }

  /* ---- Menu type de projet ---- */
  .lf-select.is-enhanced > select{
    position:absolute;width:1px;height:1px;overflow:hidden;
    clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;
    /* PAS display:none : un champ ainsi masqué sort de la validation
       HTML, et le `required` du select cesserait d'être vérifié. */
  }
  .lf-select.is-enhanced > .lf-chevron{display:none;}

  .lf-combo-btn{
    display:flex;align-items:center;gap:10px;width:100%;
    padding:12px 14px;cursor:pointer;text-align:left;
    font-family:'Inter',sans-serif;font-size:14.5px;color:var(--text-hi);
    background:var(--glass-fill);border:1px solid var(--glass-border);
    border-radius:var(--radius-md);
    transition:background .3s var(--ease), border-color .3s var(--ease),
               transform .18s var(--ease);
  }
  .lf-combo-btn .lf-combo-value{flex:1 1 auto;min-width:0;}
  .lf-combo-btn .lf-combo-value.is-placeholder{color:var(--text-low);}
  .lf-combo-ico{display:flex;flex:none;}
  .lf-combo-ico:empty{display:none;}
  .lf-combo-btn .lf-chevron{
    position:static;transform:none;flex:none;
    transition:transform .3s var(--ease), stroke .3s var(--ease);
  }
  .lf-select.is-open .lf-combo-btn{
    border-color:rgba(var(--tag-blue-rgb),0.5);
    background:var(--glass-fill-strong);
  }
  .lf-select.is-open .lf-chevron{transform:rotate(180deg);stroke:var(--tag-blue);}
  @media (hover:hover){
    .lf-combo-btn:hover{background:var(--glass-fill-strong);
      border-color:var(--glass-border-strong);}
  }
  .lf-combo-btn:active{transform:scale(0.99);transition-duration:.08s;}
  .lf-combo-btn:focus-visible{outline:2px solid var(--tag-blue);outline-offset:2px;}
  /* Accusé de réception du choix, sur le bouton refermé. */
  .lf-combo-btn.just-picked{animation:lf-pick .34s var(--ease);}

  .lf-opt-ico{
    width:16px;height:16px;flex:none;
    fill:none;stroke:currentColor;stroke-width:1.4;
    stroke-linecap:round;stroke-linejoin:round;
    color:var(--steel-mid);
  }
  .lf-combo-btn.has-value .lf-opt-ico{color:var(--tag-blue);}

  /* ---- Panneau déroulant ---- */
  .lf-select{position:relative;}
  .lf-combo-list{
    position:absolute;left:0;right:0;top:calc(100% + 8px);z-index:20;
    margin:0;padding:6px;list-style:none;
    max-height:270px;overflow-y:auto;
    background:rgba(10,17,26,0.96);
    border:1px solid var(--glass-border-strong);
    border-radius:var(--radius-md);
    box-shadow:0 22px 44px -18px rgba(0,0,0,0.85);
    -webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);
    opacity:0;transform:translateY(-6px) scale(0.98);transform-origin:top center;
    transition:opacity .18s var(--ease), transform .18s var(--ease);
  }
  .lf-select.is-open .lf-combo-list{opacity:1;transform:translateY(0) scale(1);}
  .lf-combo-list:focus{outline:none;}
  .lf-opt{
    display:flex;align-items:center;gap:10px;
    padding:10px 11px;border-radius:var(--radius-sm);cursor:pointer;
    font-family:'Inter',sans-serif;font-size:14px;color:var(--text-mid);
    transition:color .18s var(--ease), background .18s var(--ease);
  }
  /* .is-active plutôt que :hover : la même mise en évidence doit servir au
     survol ET aux flèches du clavier, sinon la navigation clavier n'a
     aucun repère visuel. */
  .lf-opt.is-active{color:var(--text-hi);background:rgba(var(--tag-blue-rgb),0.12);}
  .lf-opt.is-active .lf-opt-ico{color:var(--tag-blue);}
  .lf-opt[aria-selected="true"]{color:var(--tag-blue);}
  .lf-opt:active{transform:scale(0.985);}

  /* ---- Bouton d'envoi et réservation ---- */
  .lf-submit,.book-btn{transition:transform .18s var(--ease),
    color .3s var(--ease), background .3s var(--ease), border-color .3s var(--ease);}
  .lf-submit:active,.book-btn:active{transform:scale(0.98);transition-duration:.08s;}
  @media (hover:hover){
    .book-btn:hover{transform:translateY(-2px);}
  }

  /* ================================================================
     FAQ
     ================================================================ */
  /* Pas de panneau autour de la liste : ce sont les cartes de questions
     qui portent la matière. La section garde sa nappe d'ambiance. */
  .faq-list{display:flex;flex-direction:column;gap:10px;max-width:820px;}
  .faq-item{
    border:1px solid var(--glass-border);border-radius:var(--radius-md);
    background:var(--glass-fill);overflow:hidden;
    transition:border-color .35s var(--ease), background .35s var(--ease);
  }
  @media (hover:hover){
    .faq-item:not(.is-open):hover{
      background:var(--glass-fill-strong);
      border-color:var(--glass-border-strong);
    }
  }
  .faq-item.is-open{border-color:rgba(var(--tag-blue-rgb),0.3);background:var(--glass-fill-strong);}
  .faq-item h3{margin:0;font-size:inherit;letter-spacing:normal;text-transform:none;}

  .faq-q{
    display:flex;align-items:center;justify-content:space-between;gap:18px;
    width:100%;padding:20px 22px;cursor:pointer;text-align:left;
    background:none;border:0;
    font-family:'Big Shoulders Display',sans-serif;
    font-size:19px;font-weight:700;color:var(--text-hi);
    -webkit-user-select:none;user-select:none;
    transition:color .3s var(--ease);
  }
  .faq-q:focus-visible{outline:2px solid var(--tag-blue);outline-offset:-2px;border-radius:var(--radius-md);}
  @media (hover:hover){ .faq-q:hover{color:var(--tag-blue);} }
  .faq-item.is-open .faq-q{color:var(--tag-blue);}

  /* Signe +/− en deux traits : la barre verticale pivote et disparaît,
     ce qui évite d'échanger deux icônes et donne une transition continue. */
  .faq-sign{position:relative;width:14px;height:14px;flex:none;}
  .faq-sign::before,.faq-sign::after{
    content:'';position:absolute;left:0;top:50%;
    width:14px;height:1.5px;border-radius:1px;background:currentColor;
    transition:transform .35s var(--ease-in-out), opacity .35s var(--ease);
  }
  .faq-sign::after{transform:rotate(90deg);}
  .faq-item.is-open .faq-sign::after{transform:rotate(0deg);opacity:0;}

  /* grid-template-rows 0fr → 1fr : anime jusqu'à la hauteur réelle du
     contenu, sans max-height arbitraire à maintenir. L'enfant doit être
     en overflow:hidden, sinon il déborde pendant la fermeture. */
  .faq-a{
    display:grid;grid-template-rows:1fr;
    transition:grid-template-rows .38s var(--ease-in-out);
  }
  .faq-a > div{overflow:hidden;}
  .faq-item:not(.is-open) .faq-a{grid-template-rows:0fr;}
  .faq-a p{
    margin:0 22px 14px;font-family:'Inter',sans-serif;
    font-size:14.5px;line-height:1.7;color:var(--text-mid);
  }
  .faq-a p:first-child{padding-top:2px;}
  .faq-a p:last-child{margin-bottom:20px;}
  .faq-a strong{color:var(--text-hi);font-weight:600;}
  .faq-a a{color:var(--tag-blue);text-decoration:underline;text-underline-offset:2px;}

  @media (max-width:560px){
    .faq-q{padding:17px 14px;font-size:17px;gap:12px;}
    .faq-a p{margin-left:14px;margin-right:14px;}
  }

  /* ================================================================
     MENTIONS DE RÉASSURANCE SOUS LES CTA
     Trois freins levés en une ligne : le coût de la demande,
     l'incertitude de l'attente, la peur de l'engagement.
     ================================================================ */
  .cta-note{
    margin:14px 0 0;
    font-family:'IBM Plex Mono',monospace;font-size:11.5px;
    letter-spacing:0.06em;color:var(--text-low);
    text-transform:none;
    /* pas de text-align : la mention suit l'alignement de son bloc —
       à gauche dans le hero, centrée dans les tarifs et le contact. */
  }
  /* Séparateurs décoratifs : aria-hidden côté markup pour que les
     lecteurs d'écran énoncent trois phrases et non des points médians. */
  .cta-note span{
    display:inline-block;margin:0 9px;
    color:var(--steel-mid);
  }
  /* Sous le bouton d'envoi, la mention précède la ligne de statut :
     on resserre pour qu'elles ne se lisent pas comme deux messages. */
  .lead-form .cta-note{margin-top:12px;margin-bottom:2px;}
  .price-grid + .cta-note{margin-top:26px;text-align:center;}

  @media (max-width:420px){
    .cta-note span{margin:0 6px;}
  }

  /* ================================================================
     SHOWREEL DU HERO
     ----------------------------------------------------------------
     z-index:-1, comme .viewport::before. Étant un enfant réel, la vidéo
     est peinte APRÈS le pseudo-élément, donc par-dessus sa lueur ; et
     le texte du hero, non positionné, passe au-dessus des deux.
     Le backdrop-filter du ::before n'est pas affecté : il échantillonne
     ce qui se trouve DERRIÈRE .viewport, pas son contenu.
     ================================================================ */
  .vp-reel{
    position:absolute;inset:0;z-index:-1;
    width:100%;height:100%;object-fit:cover;
    border-radius:inherit;pointer-events:none;
    /* Le showreel est une preuve, pas le sujet : à pleine opacité il
       entrerait en concurrence avec le titre, qui est ce qui doit être
       lu en premier. */
    opacity:0.42;
  }
  /* Voile de lisibilité. Sans lui, un plan clair du montage (la séquence
     Pinterest est presque blanche) ferait disparaître le texte. */
  .vp-veil{
    position:absolute;inset:0;z-index:-1;
    border-radius:inherit;pointer-events:none;
    background:
      linear-gradient(180deg,
        rgba(5,7,10,0.90) 0%,
        rgba(5,7,10,0.74) 42%,
        rgba(5,7,10,0.88) 100%),
      radial-gradient(120% 90% at 20% 40%, rgba(5,7,10,0.55), transparent 70%);
  }
  /* Écran étroit : le texte occupe toute la hauteur, le fond doit
     s'effacer davantage. */
  @media (max-width:720px){
    .vp-reel{opacity:0.3;}
  }
  @media (prefers-reduced-motion:reduce){
    .vp-reel{opacity:0.26;}
  }


  /* ---- Barre d'action mobile --------------------------------------
     Fixée en bas, hors du flux : le CTA reste à portée de pouce quel que
     soit l'endroit de la page. Absente au-dessus de 720 px, où la nav
     sticky joue déjà ce rôle. */
  .mbar{
    position:fixed;left:0;right:0;bottom:0;z-index:60;
    display:none;
    flex-direction:column;align-items:center;gap:8px;
    padding:12px 16px calc(12px + env(safe-area-inset-bottom));
    background:linear-gradient(180deg, rgba(5,7,10,0) 0%, rgba(5,7,10,0.92) 38%, rgba(5,7,10,0.98) 100%);
    border-top:1px solid var(--glass-border);
    backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
    opacity:0;transform:translateY(100%);
    transition:opacity .32s var(--ease), transform .42s var(--ease);
    user-select:none;-webkit-user-select:none;
  }
  .mbar.is-on{opacity:1;transform:translateY(0);}
  .mbar-note{
    margin:0;font-family:'IBM Plex Mono',monospace;font-size:11.5px;
    letter-spacing:0.06em;text-transform:uppercase;color:var(--text-low);
  }
  .mbar-note span{margin:0 7px;color:var(--tag-blue);}
  .mbar-cta{width:100%;justify-content:center;text-align:center;}
  .mbar-cta:active{transform:scale(0.97);}

  @media (max-width:720px){
    .mbar{display:flex;}
    /* la barre couvre le bas du document : sans marge, le pied de page
       resterait sous elle */
    footer{padding-bottom:96px;}
  }
  @media (prefers-reduced-motion:reduce){
    .mbar{transition:opacity .2s linear;transform:none;}
  }

  /* ---- Moyens de paiement (footer) --------------------------------
     Rangée sobre au-dessus de la ligne de copyright : elle rassure sur le
     règlement sans peser visuellement. Icônes tracées au trait, à la même
     grammaire que le reste des pictos du site (stroke, pas de fill). */
  .pay-row{
    list-style:none;margin:0 0 18px;padding:0 0 16px;
    display:flex;flex-wrap:wrap;justify-content:center;
    gap:10px 22px;
    border-bottom:1px solid var(--glass-border);
    user-select:none;-webkit-user-select:none;
  }
  .pay{display:inline-flex;align-items:center;gap:8px;}
  .pay-ico{display:block;width:24px;height:16px;flex:none;}
  .pay-ico svg{
    width:100%;height:100%;display:block;
    fill:none;stroke:var(--steel-mid);stroke-width:1.3;
    stroke-linecap:round;stroke-linejoin:round;
    transition:stroke .3s var(--ease);
  }
  .pay-name{
    font-family:'IBM Plex Mono',monospace;font-size:11.5px;
    letter-spacing:0.05em;text-transform:uppercase;color:var(--text-low);
    transition:color .3s var(--ease);
  }
  .pay:hover .pay-ico svg{stroke:#8fcaff;}
  .pay:hover .pay-name{color:var(--text-mid);}
  @media (max-width:720px){
    .pay-row{gap:10px 16px;}
    .pay-name{font-size:11.5px;letter-spacing:0.03em;}
  }

  /* ---- Livrables (fin de la Méthode) -------------------------------
     Les six étapes racontent le travail ; cette ligne montre l'objet
     remis. Les trois derniers cadres sont tracés AU RATIO EXACT dans un
     viewBox commun de 22x14 : c'est le dessin qui dit le format, le texte
     ne fait que le confirmer. Changer un ratio ici veut dire redessiner
     le rect, pas seulement l'étiquette. */
  .deliver{
    display:flex;flex-wrap:wrap;align-items:center;gap:12px 20px;
    margin-top:30px;padding-top:20px;
    border-top:1px solid var(--glass-border);
    user-select:none;-webkit-user-select:none;
  }
  .deliver-label{
    font-family:'IBM Plex Mono',monospace;font-size:11.5px;
    letter-spacing:0.14em;text-transform:uppercase;color:var(--steel-mid);
  }
  .deliver-list{
    list-style:none;margin:0;padding:0;
    display:flex;flex-wrap:wrap;gap:10px 12px;
  }
  .dl-item{
    display:inline-flex;align-items:center;gap:8px;
    padding:7px 12px;border-radius:var(--radius-sm);
    border:1px solid var(--glass-border);background:var(--glass-fill);
    font-family:'IBM Plex Mono',monospace;font-size:11.5px;
    letter-spacing:0.05em;color:var(--text-mid);
    transition:border-color .3s var(--ease), color .3s var(--ease);
  }
  .dl-ico{display:block;width:22px;height:14px;flex:none;}
  .dl-ico svg{
    width:100%;height:100%;display:block;
    fill:none;stroke:var(--steel-mid);stroke-width:1.2;
    stroke-linecap:round;stroke-linejoin:round;
    transition:stroke .3s var(--ease);
  }
  @media (hover:hover){
    .dl-item:hover{border-color:rgba(var(--tag-blue-rgb),0.4);color:var(--text-hi);}
    .dl-item:hover .dl-ico svg{stroke:#8fcaff;}
  }

  /* ---- Icônes des trois promesses ---------------------------------
     Document / horloge / bouclier : chaque mention porte le picto de ce
     qu'elle promet. Ils remplacent les points médians — l'icône sépare
     visuellement aussi bien qu'un séparateur, en disant quelque chose. */
  .cn-item{display:inline-flex;align-items:center;gap:6px;margin-right:16px;}
  .cn-item:last-child{margin-right:0;}
  .cn-ico{display:block;width:13px;height:13px;flex:none;}
  .cn-ico svg{
    width:100%;height:100%;display:block;
    fill:none;stroke:var(--steel-mid);stroke-width:1.35;
    stroke-linecap:round;stroke-linejoin:round;
  }
  @media (max-width:420px){
    .cn-item{margin-right:12px;}
  }

  /* ---- Délai rappelé sur chaque carte tarif ------------------------
     Le prix et le délai se décident ensemble : les séparer obligeait à
     redescendre au paragraphe sous la grille pour savoir quand on est
     livré. Posé juste au-dessus du bouton, au moment de la décision. */
  .pc-delay{
    display:flex;align-items:center;gap:7px;
    margin:0 0 14px;
    font-family:'IBM Plex Mono',monospace;font-size:11.5px;
    letter-spacing:0.05em;text-transform:uppercase;color:var(--text-low);
  }
  .pd-ico{display:block;width:13px;height:13px;flex:none;}
  .pd-ico svg{
    width:100%;height:100%;display:block;
    fill:none;stroke:var(--steel-mid);stroke-width:1.35;
    stroke-linecap:round;stroke-linejoin:round;
    transition:stroke .3s var(--ease);
  }
  @media (hover:hover){ .price-card:hover .pd-ico svg{stroke:#8fcaff;} }

  /* ---- Avion du bouton d'envoi -------------------------------------
     Il décolle au survol et part à l'envoi : l'action a une direction,
     le bouton la montre au lieu de l'écrire. */
  .lf-plane{
    display:inline-block;width:14px;height:14px;margin-left:9px;
    vertical-align:-0.15em;
    transition:transform .35s var(--ease);
  }
  .lf-plane svg{
    width:100%;height:100%;display:block;
    fill:none;stroke:currentColor;stroke-width:1.3;
    stroke-linecap:round;stroke-linejoin:round;
  }
  @media (hover:hover){
    .lf-submit:hover .lf-plane{transform:translate(3px,-3px);}
  }
  .lf-submit.is-sending .lf-plane{
    transform:translate(26px,-26px);opacity:0;
    transition:transform .5s var(--ease-in-out), opacity .5s var(--ease-in-out);
  }
  @media (prefers-reduced-motion:reduce){
    .lf-plane,.lf-submit.is-sending .lf-plane{transition:none;transform:none;opacity:1;}
  }

  /* ---- Filet de progression des étapes -----------------------------
     ADAPTATION : la recommandation parlait d'un filet vertical courant
     le long des six étapes. Ici le déroulé est une grille 3x2, pas une
     colonne — un trait continu n'aurait aucun tracé à suivre. Chaque
     étape porte donc son propre filet, qui se remplit quand elle entre
     en scène ; la cascade de sequenceIn (140 ms) fait le reste, l'oeil
     lit une progression 01 -> 06.
     Sur mobile la grille passe à une colonne : les six filets se
     retrouvent alignés et forment le trait vertical d'origine. */
  .step::before{
    content:'';position:absolute;left:0;top:0;bottom:0;width:2px;
    background:linear-gradient(180deg, var(--tag-blue), rgba(var(--tag-blue-rgb),0.15));
    transform:scaleY(0);transform-origin:top center;
    transition:transform .7s var(--ease-in-out);
    pointer-events:none;
  }
  .step.is-visible::before{transform:scaleY(1);}
  @media (prefers-reduced-motion:reduce){
    .step::before{transition:none;}
  }

  /* ---- Barre de lecture de la vignette -----------------------------
     Posée au bas de la carte survolée : elle dit où en est le clip et
     combien il reste. Alimentée par l'événement timeupdate (~4 Hz), donc
     lissée par une transition linéaire — sans elle, la barre avancerait
     par à-coups visibles. */
  .media-prog{
    position:absolute;left:0;right:0;bottom:0;height:2px;z-index:3;
    background:rgba(255,255,255,0.10);
    opacity:0;transition:opacity .3s var(--ease);
    pointer-events:none;
  }
  /* Aucune transition : la position est recalculée à chaque frame par
     mediaProgress. Une transition ajouterait un retard constant — c'est
     ce qui décalait la barre du temps réel de la vidéo. */
  .media-prog i{
    display:block;height:100%;width:100%;
    transform:scaleX(0);transform-origin:left center;
    background:var(--tag-blue);
    box-shadow:0 0 8px rgba(var(--tag-blue-rgb),0.6);
  }
  @media (hover:hover){ .work-card:hover .media-prog{opacity:1;} }
  /* Au tactile il n'y a pas de survol : la barre reste visible, en
     retrait, sur les vignettes qui jouent. */
  @media (hover:none){ .media-prog{opacity:0.55;} }

  /* Piège à robots du formulaire : hors de l'écran et hors du parcours
     clavier, mais présent dans le DOM — c'est justement ce qu'un script
     de spam remplit. clip-path plutôt que display:none, que certains
     robots savent détecter. */
  .lf-botcheck{
    position:absolute;width:1px;height:1px;
    clip-path:inset(50%);overflow:hidden;
    white-space:nowrap;
  }

  /* ---- Signature de l'auteur --------------------------------------
     Le rouge est la seule entorse à la palette du site, et elle est
     assumée : un coeur bleu ne se lit pas comme un coeur. Il est
     cantonné à 13 px dans le pied de page, loin de tout ce qui porte
     l'accent de marque. */
  .made-by{
    margin:16px 0 0;text-align:center;
    font-family:'IBM Plex Mono',monospace;font-size:11.5px;
    letter-spacing:0.05em;color:var(--text-low);
    user-select:none;-webkit-user-select:none;
  }
  .made-by strong{color:var(--text-mid);font-weight:500;}
  .mb-heart{
    display:inline-block;width:13px;height:13px;
    margin:0 5px;vertical-align:-0.15em;
    color:#ff4d5e;
    /* La lueur est portée par drop-shadow et non box-shadow : elle suit
       le tracé du coeur au lieu d'éclairer un carré autour. */
    filter:drop-shadow(0 0 5px rgba(255,77,94,0.75));
    animation:mb-beat 1.6s var(--ease-in-out) infinite;
  }
  .mb-heart svg{width:100%;height:100%;display:block;fill:currentColor;}
  /* Deux battements rapprochés puis une pause — le rythme d'un vrai
     pouls. Un scale sinusoïdal régulier fait respirer, pas battre. */
  @keyframes mb-beat{
    0%,  100%{transform:scale(1);}
    14%      {transform:scale(1.28);}
    28%      {transform:scale(1);}
    42%      {transform:scale(1.18);}
    56%      {transform:scale(1);}
  }
  /* Le mot que le coeur remplace, pour les lecteurs d'écran : sans lui
     la phrase se lit « Made by Scyzoc with for Zensu Visuals ». */
  .mb-sr{
    position:absolute;width:1px;height:1px;
    clip-path:inset(50%);overflow:hidden;white-space:nowrap;
  }
  @media (prefers-reduced-motion:reduce){
    .mb-heart{animation:none;}
  }
