/*
 * LE SITE PUBLIC eqnx.vc — LE DÉFILEMENT DE L'ACCUEIL (07/11/2026 ; Alex : « des défilements un peu plus classe façon
 * Apple » ; « une démo sur le docker » ; prototype #680, puis « choisis pour moi et déploie » : tout gardé, choix de
 * Claude sur délégation d'Alex, decisions.md §9.2 n°287 ; claude-docs/modules/site-public.md §11).
 *
 * Chargée sur l'accueil (EN et FR) seulement — base.html.twig pose html[data-defilement] ; les pages légales et la 404
 * gardent les apparitions de site.js. Consigne permanente d'Alex pour le site (26/10/2026) : « évolution sobre, pas trop
 * changer » — ni texte, ni image, ni structure, ni classe .eq-* touchés ; les animations d'avant gardées (l'intro, le
 * titre du hero, les Lottie, la couronne) ; l'orange #E8632B en touche seulement (l'élément courant d'une scène).
 *
 * Ce qu'elle fait (et site-defilement.js, son pendant) :
 *   1. les APPARITIONS au défilement — fondu, montée de 20 px (16 au téléphone), léger flou qui se dissipe (ordinateur
 *      seulement) — CADENCÉES PAR LE DÉFILEMENT : `animation-timeline: view()` (CSS scroll-driven animations : Chrome,
 *      Edge, Safari 26) ; elles se rejouent à l'envers quand on remonte. Repli : site-defilement.js pose html.s-ap-io et un
 *      IntersectionObserver ajoute .s-ap-vu (une transition, une fois). Les colonnes d'une même rangée se décalent un peu ;
 *   2. les TITRES de section gagnent en netteté et en échelle à l'entrée (0,965 → 1, flou → net), et leur filet se trace
 *      de gauche à droite ;
 *   3. le HERO se retire au défilement : le titre recule (échelle 0,94, fondu), la couronne s'ouvre un peu (1,08) ;
 *   4. LES SCÈNES COLLANTES — les secteurs (quatre), puis la thèse (trois principes) : chaque bloc reste fixe sous la
 *      barre, un pas de 25 svh par élément, et ses éléments s'allument l'un après l'autre (le courant marqué d'orange,
 *      un filet de progression sur le filet du haut) ; les secteurs s'effacent quand la thèse monte. Ordinateur et tablette
 *      seulement (≥ 641 × 720, et les deux blocs tiennent dans l'écran) ; au téléphone, les apparitions ordinaires.
 *      Posées par site-defilement.js (html.s-ap-scene, data-etape, --s-scene-p) : sans script, rien n'est collant ;
 *   5. l'ÉNONCÉ d'About en deux temps, et la suite (« Why EQNX? ») qui ne part que quand il recule (§5).
 * Jamais de détournement du défilement (aucun scroll-jacking : la molette et le doigt font ce qu'ils font), aucune
 * bibliothèque ; les animations ne touchent que transform et opacity (plus le flou, à l'ordinateur seulement) ;
 * prefers-reduced-motion : rien de tout cela (toutes les règles sont sous `prefers-reduced-motion: no-preference`).
 * Pas de !important ; aucune classe .eq-* redéfinie.
 */

/* ── 1. Les jetons du défilement ───────────────────────────────────────────────────────────────────────────────────── */
html[data-defilement]{
  --s-ap-courbe:cubic-bezier(.2,.7,.2,1);
  --s-ap-montee:20px;
  --s-ap-flou:6px;
  --s-ap-flou-titre:10px;
}

@media (prefers-reduced-motion:no-preference){

  /* les images clés : l'ordinateur a le flou ; le téléphone, transform et opacity seulement (60 im/s) */
  @keyframes s-ap-entree{
    from{opacity:0;transform:translate3d(0,var(--s-ap-montee),0);filter:blur(var(--s-ap-flou))}
    to{opacity:1;transform:none;filter:none}
  }
  @keyframes s-ap-entree-tel{
    from{opacity:0;transform:translate3d(0,var(--s-ap-montee),0)}
    to{opacity:1;transform:none}
  }
  @keyframes s-ap-titre{
    from{opacity:0;transform:translate3d(0,var(--s-ap-montee),0) scale(.965);filter:blur(var(--s-ap-flou-titre))}
    to{opacity:1;transform:none;filter:none}
  }
  @keyframes s-ap-titre-tel{
    from{opacity:0;transform:translate3d(0,var(--s-ap-montee),0) scale(.965)}
    to{opacity:1;transform:none}
  }
  @keyframes s-ap-filet{from{transform:scaleX(0)}to{transform:none}}
  @keyframes s-ap-hero-sortie{to{opacity:0;transform:translate3d(0,-5vh,0) scale(.94)}}
  @keyframes s-ap-anneau{to{scale:1.08;opacity:.45}}

  /* le décalage d'une colonne dans sa rangée (la position de départ et d'arrivée glisse de --s-ap-d ; le repli : un retard) */
  html[data-defilement] [data-site-apparait]{--s-ap-d:0px;--s-ap-retard:0s}
  @media (min-width:901px){
    html[data-defilement] :is(.s-vert,.s-tm)>li:nth-child(4n+2),
    html[data-defilement] .s-th>li:nth-child(3n+2),
    html[data-defilement] .s-pf-l>li:nth-child(2n){--s-ap-d:48px;--s-ap-retard:.07s}
    html[data-defilement] :is(.s-vert,.s-tm)>li:nth-child(4n+3),
    html[data-defilement] .s-th>li:nth-child(3n){--s-ap-d:96px;--s-ap-retard:.14s}
    html[data-defilement] :is(.s-vert,.s-tm)>li:nth-child(4n){--s-ap-d:144px;--s-ap-retard:.21s}
  }
  @media (min-width:641px) and (max-width:900px){
    html[data-defilement] .s-vert>li:nth-child(2n),
    html[data-defilement] .s-tm>li:nth-child(3n+2){--s-ap-d:48px;--s-ap-retard:.07s}
    html[data-defilement] .s-tm>li:nth-child(3n){--s-ap-d:96px;--s-ap-retard:.14s}
  }
  @media (max-width:640px){
    html[data-defilement] .s-tm>li:nth-child(2n){--s-ap-d:40px;--s-ap-retard:.07s}
    html[data-defilement]{--s-ap-montee:16px}
  }

  /* les titres de section : le filet se trace (un trait à part, ::after, à la place de la bordure — même place, même couleur) */
  html[data-defilement] .s-label{position:relative;border-bottom-color:transparent;transform-origin:0 100%}
  html[data-defilement] .s-label::after{content:"";position:absolute;left:0;right:0;bottom:-1px;height:1px;background:var(--eq-filet);transform-origin:0 50%}
  html[data-defilement] .s-statement{transform-origin:0 50%}
  html[data-defilement] .s-cta-t{transform-origin:50% 50%}

  /* ── 2. Cadencé par le défilement (CSS scroll-driven animations) ─────────────────────────────────────────────────── */
  @supports (animation-timeline:view()){
    /* l'élément apparaît pendant que son haut monte du bas de l'écran aux ~70 % de sa hauteur (cover 0 → 25 %) ;
       `animation` d'abord, `animation-timeline` ensuite (le raccourci la remet à auto) */
    html[data-defilement] [data-site-apparait]{
      animation:s-ap-entree linear both;
      animation-timeline:view();
      animation-range:cover var(--s-ap-d) cover calc(25% + var(--s-ap-d));
    }
    html[data-defilement] :is(.s-statement,.s-cta-t),
    html[data-defilement] .s-label{
      animation:s-ap-titre linear both;
      animation-timeline:view();
      animation-range:cover 0% cover 30%;
    }
    html[data-defilement] .s-label::after{
      animation:s-ap-filet linear both;
      animation-timeline:view();
      animation-range:cover 4% cover 34%;
    }
    /* le hero se retire : sa propre ligne de temps (il fait la hauteur de l'écran : exit 0 % = le haut de la page) */
    html[data-defilement] .s-hero{view-timeline:--s-hero block}
    html[data-defilement] .s-h1{
      transform-origin:50% 60%;
      animation:s-ap-hero-sortie linear both;
      animation-timeline:--s-hero;
      animation-range:exit 0% exit 75%;
    }
    html[data-defilement] .s-ring{
      animation:s-ring 14s var(--eq-courbe) infinite alternate,s-ap-anneau linear both;
      animation-timeline:auto,--s-hero;
      animation-range:normal,exit 0% exit 100%;
    }
    @media (max-width:640px){
      html[data-defilement] [data-site-apparait]{animation-name:s-ap-entree-tel}
      html[data-defilement] :is(.s-statement,.s-cta-t),
      html[data-defilement] .s-label{animation-name:s-ap-titre-tel}
    }
  }

  /* ── 3. Le repli (Firefox, un Safari plus ancien) : un IntersectionObserver, une transition, une fois ──────────── */
  html.s-ap-io[data-defilement] :is([data-site-apparait],.s-label){
    opacity:0;transform:translate3d(0,var(--s-ap-montee),0);filter:blur(var(--s-ap-flou));
    transition:opacity .9s var(--s-ap-courbe) var(--s-ap-retard,0s),transform 1.1s var(--s-ap-courbe) var(--s-ap-retard,0s),filter .9s var(--s-ap-courbe) var(--s-ap-retard,0s)}
  html.s-ap-io[data-defilement] :is(.s-statement,.s-cta-t,.s-label){transform:translate3d(0,var(--s-ap-montee),0) scale(.965);filter:blur(var(--s-ap-flou-titre))}
  html.s-ap-io[data-defilement] .s-label::after{transform:scaleX(0);transition:transform 1.2s var(--s-ap-courbe) .15s}
  html.s-ap-io[data-defilement] :is([data-site-apparait],.s-label).s-ap-vu{opacity:1;transform:none;filter:none}
  html.s-ap-io[data-defilement] .s-label.s-ap-vu::after{transform:none}
  @media (max-width:640px){
    html.s-ap-io[data-defilement] :is([data-site-apparait],.s-label,.s-statement,.s-cta-t){filter:none}
  }

  /* ── 4. Les scènes collantes : LES SECTEURS, PUIS LA THÈSE (≥ 641 × 720 ; html.s-ap-scene, posé par
     site-defilement.js quand les deux blocs tiennent dans l'écran — sinon aucune, les apparitions ordinaires) ───────────
     Alex, 07/11/2026 : la thèse, puis « les secteurs, on pourrait avoir le même fonctionnement que la thèse ». Même
     rythme pour les deux : un pas de --s-scene-pas (25 svh) par élément — 4 pas pour les secteurs, 3 pour la thèse.
     · Les deux blocs gardent leur hauteur et collent CENTRÉS dans l'écran sous la barre (leur `top`, et la marge de la
       thèse, posés par le script ; ces valeurs-ci ne sont que le repli avant sa première mesure).
     · Les secteurs restent fixes pendant 4 pas (la marge de la thèse au-dessus d'elle : jamais vide à l'écran, les
       secteurs la couvrent), puis la thèse MONTE et les secteurs s'effacent devant elle (--s-scene-sortie, la relève) ;
       elle colle à son tour 3 pas (un ::after
       en fin de section : du contenu — un élément collant ne descend jamais dans le padding de son conteneur) ; les deux
       glissent avec la section quand elle finit.
     · Le script dit, pour chaque bloc, l'étape (data-etape, de 1 au nombre d'éléments) et la progression (--s-scene-p,
       0 → 1) : les éléments s'allument l'un après l'autre (l'élément à venir à 16 %), le courant marqué d'orange — le
       numéro d'un principe, le point d'un secteur (celui que le survol allume déjà) — ; un filet de progression court sur
       le filet du haut. */
  html[data-defilement]{--s-scene-pas:25svh}
  html.s-ap-scene[data-defilement] .s-about::after{content:"";display:block;height:calc(var(--s-scene-pas) * 3)}
  html.s-ap-scene[data-defilement] :is(.s-bloc--vert,.s-bloc--these){position:sticky;top:var(--eq-barre-h)}
  html.s-ap-scene[data-defilement] .s-bloc--vert{z-index:1}
  /* la relève : la thèse monte, les secteurs s'effacent en remontant de 80 px (40 au prototype : un instant presque vide
     à 1440 — porté à 80 sur le choix du 07/11/2026) — le script fait aller --s-scene-sortie de 0
     à 1 juste avant que le contenu de la thèse (centré dans son bloc) ne rejoigne le leur : jamais un écran vide, jamais
     deux contenus superposés ; ils reviennent quand on remonte */
  html.s-ap-scene[data-defilement] .s-bloc--vert>*{opacity:calc(1 - var(--s-scene-sortie,0));transform:translate3d(0,calc(var(--s-scene-sortie,0) * -80px),0)}
  html.s-ap-scene[data-defilement] .s-bloc--these{z-index:2;margin-top:calc(var(--s-scene-pas) * 4 + 30svh)}
  html.s-ap-scene[data-defilement] :is(.s-bloc--vert .s-vert,.s-bloc--these .s-th){position:relative}
  html.s-ap-scene[data-defilement] :is(.s-bloc--vert .s-vert,.s-bloc--these .s-th)::before{content:"";position:absolute;left:0;right:0;top:-1px;height:1px;
    background:var(--eq-texte);transform-origin:0 50%;transform:scaleX(var(--s-scene-p,0))}
  /* les éléments : plus d'apparition propre (la scène les mène), allumés jusqu'à l'étape, éteints après */
  html.s-ap-scene[data-defilement] :is(.s-bloc--vert .s-vert,.s-bloc--these .s-th)>li{animation:none;opacity:1;transform:none;filter:none;
    transition:opacity .7s var(--s-ap-courbe),transform .9s var(--s-ap-courbe)}
  html.s-ap-scene[data-defilement] :is(.s-bloc--vert,.s-bloc--these)[data-etape="1"] :is(.s-vert,.s-th)>li:nth-child(n+2),
  html.s-ap-scene[data-defilement] :is(.s-bloc--vert,.s-bloc--these)[data-etape="2"] :is(.s-vert,.s-th)>li:nth-child(n+3),
  html.s-ap-scene[data-defilement] :is(.s-bloc--vert,.s-bloc--these)[data-etape="3"] :is(.s-vert,.s-th)>li:nth-child(n+4){opacity:.16;transform:translate3d(0,14px,0)}
  html.s-ap-scene[data-defilement] .s-bloc--these[data-etape="1"] .s-th>li:nth-child(1) .s-n,
  html.s-ap-scene[data-defilement] .s-bloc--these[data-etape="2"] .s-th>li:nth-child(2) .s-n,
  html.s-ap-scene[data-defilement] .s-bloc--these[data-etape="3"] .s-th>li:nth-child(3) .s-n{color:var(--eq-accent-texte)}
  html.s-ap-scene[data-defilement] .s-bloc--vert[data-etape="1"] .s-vert>li:nth-child(1) .s-v-n b,
  html.s-ap-scene[data-defilement] .s-bloc--vert[data-etape="2"] .s-vert>li:nth-child(2) .s-v-n b,
  html.s-ap-scene[data-defilement] .s-bloc--vert[data-etape="3"] .s-vert>li:nth-child(3) .s-v-n b,
  html.s-ap-scene[data-defilement] .s-bloc--vert[data-etape="4"] .s-vert>li:nth-child(4) .s-v-n b{background:var(--eq-orange)}
}

/* ── 5. L'énoncé d'About et la suite : un vrai décalage (Alex, 07/11/2026, sur la démo : « il manque un peu de décalage
   entre "We back the companies… — at the moment they are ready to lead" et la suite ») ─────────────────────────────
   · l'énoncé se révèle en deux temps : la première proposition, puis « — at the moment they are ready to lead. » (sa
     ligne en texte 2, .s-statement-fin, du catalogue : rien d'ajouté au gabarit), plus tard dans la ligne de temps ;
   · « Why EQNX? » (la suite) part plus tard, et seulement quand l'énoncé a commencé à reculer (fondu à 45 %, échelle
     0,985, 12 px plus haut — il revient quand on remonte) ;
   · plus d'air entre les deux : la marge de « Why EQNX? » grandit de 40 à 96 px, EN MODE APPLE SEULEMENT (« Avant »
     inchangé ; sous prefers-reduced-motion, rien de ceci).
   Le repli (sans scroll-driven animations) : la seconde ligne 0,32 s après la première, la suite 0,2 s après son entrée. */
@media (prefers-reduced-motion:no-preference){
  @keyframes s-ap-recul{to{opacity:.45;transform:translate3d(0,-12px,0) scale(.985)}}
  html[data-defilement] .s-why{margin-top:calc(clamp(72px,8vw,120px) + clamp(40px,6vw,96px))}
  html[data-defilement] .s-statement-fin{transform-origin:0 50%}
  @supports (animation-timeline:view()){
    /* l'entrée (remplie avant et après), puis le recul (rempli après seulement : il part de l'état d'entrée) */
    html[data-defilement] .s-statement{
      animation:s-ap-titre linear both,s-ap-recul linear forwards;
      animation-timeline:view(),view();
      animation-range:cover 0% cover 22%,cover 50% cover 80%;
    }
    html[data-defilement] .s-statement-fin{
      animation:s-ap-entree linear both;
      animation-timeline:view();
      animation-range:cover 12% cover 34%;
    }
    html[data-defilement] .s-why{animation-range:cover 16% cover 40%}
    @media (max-width:640px){
      html[data-defilement] .s-statement{animation-name:s-ap-titre-tel,s-ap-recul}
      html[data-defilement] .s-statement-fin{animation-name:s-ap-entree-tel}
    }
  }
  html.s-ap-io[data-defilement] .s-statement .s-statement-fin{opacity:0;transform:translate3d(0,var(--s-ap-montee),0);
    transition:opacity .9s var(--s-ap-courbe) .32s,transform 1.1s var(--s-ap-courbe) .32s}
  html.s-ap-io[data-defilement] .s-statement.s-ap-vu .s-statement-fin{opacity:1;transform:none}
  html.s-ap-io[data-defilement] .s-why{--s-ap-retard:.2s}
}

/* ── 6. La passe de revue UX (07/11/2026, Alex : « refais une passe… d'un point de vue UX / design ») ─────────────────
   · LE FOCUS CLAVIER n'est jamais transparent : un lien atteint à la tabulation (portefeuille, LinkedIn, les boutons du
     contact) arrive au BAS de l'écran, là où son apparition n'en est qu'au début (relevé : « Quantix » à 82 % d'opacité
     au téléphone) — l'élément qui contient le focus est montré tel quel, sans fondu ni flou ;
   · LA RESPIRATION autour des scènes : les blocs collants étaient de la hauteur de l'écran, leur contenu centré — ~430 px
     de noir à 1440 entre la fin de la thèse et le portefeuille (158 en « Avant ») ; ils gardent désormais leur hauteur
     et collent centrés (§4, le script), l'écart redevient celui d'« Avant » ;
   · LE HERO se retire en entier : l'indicateur de défilement s'efface avec le titre (il restait seul, net, sous un titre
     déjà parti). */
@media (prefers-reduced-motion:no-preference){
  html[data-defilement] :is([data-site-apparait],.s-label):focus-within{animation:none;opacity:1;transform:none;filter:none}
  @keyframes s-ap-efface{to{opacity:0}}
  @supports (animation-timeline:view()){
    html[data-defilement] .s-hero-foot{animation:s-ap-efface linear both;animation-timeline:--s-hero;animation-range:exit 0% exit 30%}
  }
}
