/* =====================================================================
   Motion. Tout ce qui bouge est ici, la mise en page reste dans styles.css.
   Transposé du travail d'Ikovaline sur papier clair : entrée en vagues,
   lumière du hero, curseur bloc, manifeste au scroll, apparitions, fil tracé.
   Les états cachés ne s'appliquent que si JS tourne (html.js) : sans script,
   tout est visible.
   ===================================================================== */

:root{
  --expo:cubic-bezier(.16,1,.3,1);       /* sortie franche, tout ce qui entre */
  --trace:cubic-bezier(.65,0,.35,1);     /* tracé du fil */
}

/* ---------- Entrée de page : quatre vagues, CSS pur, ~0,55 s ----------
   Rien n'attend le JS. fill-mode backwards tient l'état de départ pendant le
   délai puis rend la main : both figerait la valeur de fin et l'emporterait
   sur tout style posé ensuite (survol du bouton, transform inline). */

/* 1re vague : les mots du titre, 0,32 s chacun, décalés de 0,03 s */
.hero-h1 .w{animation:monte .32s var(--expo) backwards}
.hero-h1 .w:nth-child(1){animation-delay:0s}
.hero-h1 .w:nth-child(2){animation-delay:.03s}
.hero-h1 .w:nth-child(3){animation-delay:.06s}
.hero-h1 .w:nth-child(5){animation-delay:.12s}
.hero-h1 .w:nth-child(6){animation-delay:.15s}
@keyframes monte{
  from{opacity:0;filter:blur(14px);transform:translateY(130%) scale(.85)}
  to{opacity:1;filter:blur(0);transform:translateY(0) scale(1)}
}

/* 2e vague : eyebrow, lede, portrait, 0,28 s à partir de 0,22 s */
.entree-item{animation:item .28s var(--expo) backwards;animation-delay:var(--t,.22s)}
.t2{--t:.28s}
.t3{--t:.34s}
@keyframes item{
  from{opacity:0;filter:blur(10px);transform:translateY(44px) scale(.96)}
  to{opacity:1;filter:blur(0);transform:translateY(0) scale(1)}
}

/* 3e vague : la barre de navigation, fondu net à partir de 0,26 s */
.nav-bar{animation:fondu-net .34s var(--expo) backwards;animation-delay:.26s}
@keyframes fondu-net{from{opacity:0;filter:blur(8px)}to{opacity:1;filter:blur(0)}}

/* 4e vague : le bloc sous le hero (la bande de chiffres) monte, grandit, se dénette */
.entree-bloc{animation:bloc .85s var(--expo) backwards;animation-delay:.55s}
@keyframes bloc{
  from{opacity:0;filter:blur(16px);transform:translateY(64px) scale(.94)}
  to{opacity:1;filter:blur(0);transform:translateY(0) scale(1)}
}

/* ---------- Lumière du hero ----------
   Un faisceau cyan entre par la gauche après le titre, puis balaie très
   lentement (34 s). Cinq rais inclinés à 45 degrés dérivent chacun à leur
   rythme, un sixième passe en éclair. Une copie du faisceau est posée
   PAR-DESSUS le texte en mode screen : là où un rai traverse les lettres,
   l'encre s'éclaircit et se teinte, le rayon semble passer au travers. */
.lumiere{position:absolute;inset:0;z-index:0;pointer-events:none;overflow:hidden;
  animation:fondu .9s ease-out both;animation-delay:.45s}
@keyframes fondu{from{opacity:0}to{opacity:1}}
.lumiere::before{content:"";position:absolute;inset:0;
  background:radial-gradient(70% 160% at 0% 0%,rgba(59,91,253,.42) 0%,rgba(59,91,253,.1) 45%,transparent 100%)}
.lumiere::after{content:"";position:absolute;inset:0;opacity:.09;mix-blend-mode:soft-light;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='140'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/></filter><rect width='140' height='140' filter='url(%23n)'/></svg>");
  background-size:140px 140px}
.faisceau{position:absolute;top:0;bottom:0;left:0;width:100%;pointer-events:none;
  transform-origin:0 50%;will-change:transform;
  animation:faisceau-entree 1.1s var(--expo) .45s both,faisceau-balaye 34s ease-in-out 1.55s infinite}
@media(min-width:768px){.faisceau{width:80%}}
@media(min-width:1280px){.faisceau{width:70%}}
@keyframes faisceau-entree{from{transform:translateX(-16%) scaleX(.9)}to{transform:translateX(-4%) scaleX(1)}}
@keyframes faisceau-balaye{
  0%{transform:translateX(-4%) scaleX(1)}
  28%{transform:translateX(3%) scaleX(1.14)}
  52%{transform:translateX(9%) scaleX(.92)}
  76%{transform:translateX(-1%) scaleX(1.08)}
  100%{transform:translateX(-4%) scaleX(1)}
}
.faisceau.sur-texte{z-index:3;mix-blend-mode:screen;opacity:.55}
.rai{position:absolute;top:-20%;bottom:-20%;left:var(--x);width:var(--w);opacity:.34;
  filter:blur(18px);transform:skewX(45deg);will-change:transform;
  background:linear-gradient(180deg,rgba(59,91,253,.9) 0%,rgba(59,91,253,.66) 28%,rgba(59,91,253,.38) 52%,rgba(59,91,253,.12) 78%,transparent 100%);
  animation:rai-derive var(--d) ease-in-out infinite}
.rai:nth-child(1){--x:4%;--w:14%;--d:23s}
.rai:nth-child(2){--x:19%;--w:5%;--d:31s;animation-delay:-9s}
.rai:nth-child(3){--x:26%;--w:16%;--d:27s;animation-delay:-4s}
.rai:nth-child(4){--x:44%;--w:6%;--d:35s;animation-delay:-15s}
.rai:nth-child(5){--x:52%;--w:13%;--d:29s;animation-delay:-21s}
@keyframes rai-derive{
  0%{transform:skewX(45deg) translateX(-3%)}
  50%{transform:skewX(45deg) translateX(7%)}
  100%{transform:skewX(45deg) translateX(-3%)}
}
.rai-passage{position:absolute;top:-20%;bottom:-20%;right:0;width:55%;opacity:0;filter:blur(22px);
  background:linear-gradient(180deg,rgba(214,221,255,.5) 0%,rgba(214,221,255,.18) 45%,transparent 100%);
  animation:rai-passage 14s ease-in-out 3s infinite}
@keyframes rai-passage{
  0%,58%{opacity:0;transform:skewX(45deg) translateX(-6%)}
  72%,84%{opacity:.5;transform:skewX(45deg) translateX(2%)}
  100%{opacity:0;transform:skewX(45deg) translateX(8%)}
}
/* Hero hors écran : on fige les rais, inutile de peindre ce qu'on ne voit pas */
html.hero-hors-ecran .rai,
html.hero-hors-ecran .rai-passage,
html.hero-hors-ecran .faisceau{animation-play-state:paused!important}

/* ---------- Curseur bloc ----------
   Creux, à peine plus foncé que le papier. Il clignote au repos et reste plein
   pendant la frappe (data-typing posé par typewriter.js). */
.hero-period::after,.caret::after{content:"";display:inline-block;box-sizing:border-box;
  width:.48em;height:.76em;margin-left:.08em;background:var(--paper-2);
  border:1px solid rgba(242,244,248,.28);border-radius:2px;vertical-align:baseline;
  animation:caret-blink 1.1s ease-in-out infinite}
.caret::after{width:.5em;margin-left:.12em}
#hero-key[data-typing] + .hero-period::after{animation:none}
@keyframes caret-blink{0%,45%,100%{opacity:1}55%,90%{opacity:0}}


/* ---------- Apparitions au scroll ----------
   Deux mécaniques : .reveal par élément (fondu flouté qui monte), et
   [data-apparition] par conteneur, qui passe à "vue" une seule fois à 22 % de
   visibilité et déclenche ses enfants en cascade. */
html.js .reveal{opacity:0;filter:blur(8px);transform:translateY(24px);
  transition:opacity .6s var(--expo),filter .6s var(--expo),transform .6s var(--expo)}
html.js .reveal.in{opacity:1;filter:blur(0);transform:none}

/* Libellé de section : la ligne monte depuis un masque */
.mask{display:inline-block;overflow:hidden;padding-bottom:4px;margin-bottom:-4px;vertical-align:bottom}
.mask-in{display:inline-block}
html.js [data-apparition="non"] .mask-in{transform:translateY(114%)}
html.js [data-apparition="vue"] .mask-in{animation:ligne .7s var(--expo) backwards}
@keyframes ligne{from{transform:translateY(114%)}to{transform:translateY(0)}}

/* Cartes produits : chacune arrive à son tour, le logo monte ensuite */
html.js [data-apparition="non"] .card{opacity:0}
html.js [data-apparition="vue"] .card{animation:item .55s var(--expo) backwards;animation-delay:calc(.08s * var(--i,0))}
html.js [data-apparition="non"] .visuel{opacity:0;transform:translateY(18px)}
html.js [data-apparition="vue"] .visuel{animation:visuel .85s var(--expo) backwards;animation-delay:calc(.08s * var(--i,0) + .25s)}
@keyframes visuel{from{opacity:0;transform:translateY(18px)}to{opacity:1;transform:translateY(0)}}

/* ---------- Manifeste : les mots s'allument au fil du scroll ----------
   La section fait 200vh, le texte reste épinglé un écran. manifeste.js pose
   .on sur les mots déjà lus et .caret sur le dernier. */
.mw{display:inline-block;opacity:.42;transition:opacity .25s ease-out}
.mw.on{opacity:1}
html:not(.js) .mw{opacity:1}

/* ---------- Barre de navigation : toujours visible, seule sa couleur change ---------- */
.nav-bar{transition:transform .3s cubic-bezier(.23,.65,.74,1.09),opacity .3s cubic-bezier(.23,.65,.74,1.09)}

/* ---------- Boutons et cartes : grossissement avec rebond, la flèche avance ----------
   Courbe de rebond reprise telle quelle d'Ikovaline : le bouton dépasse sa
   taille finale puis revient. Autorisée explicitement, elle sort de la règle
   maison « pas de bounce ». Pour l'enlever : remettre var(--expo) et 1.04. */
.btn-primary{transition:transform .25s cubic-bezier(.34,1.56,.64,1),background .18s ease}
.btn-primary:hover{transform:scale(1.1)}
.btn-primary:active{transform:scale(.97)}
.btn-primary .ic svg{transition:transform .3s ease}
.btn-primary:hover .ic svg{transform:translateX(2px)}
.card{transition:background .2s ease,transform .3s var(--expo),box-shadow .3s var(--expo)}
.card:hover{transform:translateY(-4px);box-shadow:0 18px 40px -22px rgba(0,0,0,.8)}

/* ---------- Mouvement réduit : tout est posé, rien ne bouge ---------- */
@media (prefers-reduced-motion:reduce){
  .hero-h1 .w,.entree-item,.nav-bar,.entree-bloc,.lumiere,.faisceau,.rai,.rai-passage,
  .hero-period::after,.caret::after,
  html.js [data-apparition="vue"] .mask-in,
  html.js [data-apparition="vue"] .card,
  html.js [data-apparition="vue"] .visuel{animation:none!important}
  .lumiere{opacity:1}
  .faisceau{transform:translateX(-4%)}
  .rai-passage{opacity:.5;transform:skewX(45deg) translateX(2%)}
  html.js .reveal{opacity:1;filter:none;transform:none;transition:none}
  html.js [data-apparition="non"] .mask-in,
  html.js [data-apparition="non"] .card,
  html.js [data-apparition="non"] .visuel{opacity:1;transform:none}
  .mw{opacity:1;transition:none}
  .manifeste{height:auto}
  .manifeste-sticky{position:static;min-height:0}
  .nav-bar,.btn-primary,.card{transition:none}
  .btn-primary:hover,.card:hover{transform:none}
}

/* =====================================================================
   Deuxieme vague : bandeau, collage, mot geant, menu plein ecran.
   ===================================================================== */

/* ---------- Bandeau technique : defilement continu ----------
   La piste contient le groupe en double. Elle glisse d'exactement la
   largeur d'un groupe, puis repart : la boucle est invisible. */
.bandeau-piste{animation:defile 34s linear infinite}
@keyframes defile{from{transform:translateX(0)}to{transform:translateX(-50%)}}
.bandeau:hover .bandeau-piste{animation-play-state:paused}

/* ---------- Mot geant : la taille vient de zoom.js, pas d'une keyframe ----------
   Rien a poser ici : le CSS donne la taille de lecture, zoom.js la fait
   grossir. Surtout pas de transform:scale, cela rasteriserait le texte une
   fois pour toutes et le mot arriverait flou (voir le commentaire de zoom.js). */
.zoom-legende{animation:fondu .6s ease-out both;animation-delay:.2s}

/* ---------- Menu plein ecran ----------
   Le panneau se decoupe du haut vers le bas, puis les lignes montent depuis
   leur masque, de la derniere a la premiere. */
.menu{clip-path:inset(0 0 100% 0);
  transition:clip-path .7s var(--expo),visibility 0s linear .7s}
.menu.is-ouvert{clip-path:inset(0 0 0 0);visibility:visible;transition:clip-path .7s var(--expo),visibility 0s}
.menu-lien-masque{display:block;overflow:hidden;padding-bottom:6px;margin-bottom:-6px}
.menu-lien{transform:translateY(-114%);transition:transform .75s cubic-bezier(.87,0,.13,1)}
.menu.is-ouvert .menu-lien{transform:translateY(0)}
/* cascade inverse : la derniere ligne demarre en premier */
.menu.is-ouvert .menu-liens li:nth-last-child(1) .menu-lien{transition-delay:.15s}
.menu.is-ouvert .menu-liens li:nth-last-child(2) .menu-lien{transition-delay:.21s}
.menu.is-ouvert .menu-liens li:nth-last-child(3) .menu-lien{transition-delay:.27s}
.menu.is-ouvert .menu-liens li:nth-last-child(4) .menu-lien{transition-delay:.33s}
.menu-pied,.menu-fermer{opacity:0;transition:opacity .4s ease}
.menu.is-ouvert .menu-pied{opacity:1;transition-delay:.45s}
.menu.is-ouvert .menu-fermer{opacity:1;transition-delay:.3s}

/* ---------- Mouvement reduit ---------- */
@media (prefers-reduced-motion:reduce){
  .bandeau-piste{animation:none}
  .zoom-legende{animation:none}
  /* la section du mot geant se replie sur un ecran, sans course de scroll */
  .zoom{height:auto}
  .zoom-sticky{position:static;height:auto;padding:96px 0}
  .menu,.menu-lien,.menu-pied,.menu-fermer{transition:none}
  .menu.is-ouvert .menu-lien{transform:none}
}

/* ---------- Lignes « signal » : la lueur monte et descend, en decale ----------
   backwards : pendant le delai, chaque ligne tient l'etat de depart (eteinte)
   au lieu d'afficher son opacite de repos puis de sauter a 0. */
@keyframes signal{0%,100%{opacity:.15}45%,55%{opacity:.8}}
.signal line{animation:signal 2.6s ease-in-out infinite backwards;animation-delay:calc(var(--i) * .16s)}
@media (prefers-reduced-motion:reduce){
  .signal line{animation:none}
}

/* ---------- Etapes : cartes qui montent, fil qui se trace, points qui s'allument ----------
   Declenche une seule fois quand la grille passe a data-apparition="vue".
   pathLength=1 : le trace va de 0 a la fin quelle que soit la longueur. */
html.js [data-apparition="non"] .etape{opacity:0;transform:translateY(18px)}
html.js [data-apparition="vue"] .etape{animation:visuel .85s var(--expo) backwards;animation-delay:calc(var(--i) * .35s)}
html.js .fil path{stroke-dasharray:1;stroke-dashoffset:1}
html.js .fil circle{opacity:0}
html.js [data-apparition="vue"] .fil path{animation:trace 1.5s var(--trace) forwards}
html.js [data-apparition="vue"] .fil circle{animation:point .4s forwards}
html.js [data-apparition="vue"] .fil-court:nth-of-type(1) path{animation-delay:.3s}
html.js [data-apparition="vue"] .fil circle:first-of-type{animation-delay:.3s}
html.js [data-apparition="vue"] .fil circle:last-of-type{animation-delay:1.6s}
html.js [data-apparition="vue"] .fil-long-case path{animation-delay:.65s}
html.js [data-apparition="vue"] .fil-long-case circle:first-of-type{animation-delay:.65s}
html.js [data-apparition="vue"] .fil-long-case circle:last-of-type{animation-delay:2s}
@keyframes point{to{opacity:1}}
@media (prefers-reduced-motion:reduce){
  html.js [data-apparition] .etape{opacity:1;transform:none;animation:none!important}
  html.js .fil path{stroke-dashoffset:0;animation:none!important}
  html.js .fil circle{opacity:1;animation:none!important}
}

/* ---------- FAQ : la reponse glisse en ouvrant ---------- */
.faq-item[open] .faq-reponse{animation:faq-ouvre .35s var(--expo)}
@keyframes faq-ouvre{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){
  .faq-item[open] .faq-reponse{animation:none}
  .faq-ic{transition:none}
}

/* ---------- Vague du pied de page ----------
   Elle monte depuis le bas quand on arrive au bout de la page. Pilotee par le
   defilement en CSS pur (animation-timeline: view()), sans script : la ou le
   navigateur ne le gere pas, la vague reste simplement posee. Les nappes
   flottent en plus doucement, chacune a son rythme. */
@supports (animation-timeline: view()){
  .vague-bloc{animation:vague-monte linear both;animation-timeline:view();animation-range:entry 0% entry 100%}
}
@keyframes vague-monte{from{transform:translateY(60%);opacity:.25}to{transform:none;opacity:1}}
.vague-bloc i{animation:vague-flotte 13s ease-in-out infinite alternate}
.vague-bloc i:nth-child(2){animation-duration:17s;animation-delay:-5s}
.vague-bloc i:nth-child(3){animation-duration:15s;animation-delay:-9s}
.vague-bloc i:nth-child(4){animation-duration:19s;animation-delay:-3s}
.vague-bloc i:nth-child(5){animation-duration:11s;animation-delay:-7s}
@keyframes vague-flotte{from{transform:translate(-3%,4%) scale(1)}to{transform:translate(3%,-3%) scale(1.06)}}
@media (prefers-reduced-motion:reduce){
  .vague-bloc,.vague-bloc i{animation:none!important}
}

/* ---------- Offres : les cartes montent en cascade ---------- */
html.js [data-apparition="non"] .offre{opacity:0;transform:translateY(18px)}
html.js [data-apparition="vue"] .offre{animation:visuel .85s var(--expo) backwards;animation-delay:calc(var(--i) * .12s)}
@media (prefers-reduced-motion:reduce){
  html.js [data-apparition] .offre{opacity:1;transform:none;animation:none!important}
}

/* la section « suite » entre comme les autres blocs clairs */
.suite .reveal:nth-child(2){transition-delay:.12s}
