/* ============================================================================
   VOLTYR LABS — LA FRISE « EN ACTION » (#demo)

   🔴 CE FICHIER N'EST PLUS UN MIROIR DE LA MAQUETTE. La frise est du CONTENU
   de site : son markup vit dans `app/verticales.ts`, qui n'existe que dans ce
   dépôt. `scripts/sync-vnext.mjs` ne le recopie donc plus depuis
   `voltyr-factory` (entrée retirée du manifeste le 12/08/2026, avec son motif).
   Éditer ici est SÛR ; ça ne l'était pas avant.

   🔴 CE QUI A CHANGÉ LE 12/08/2026, ET POURQUOI ON NE LE REFAIT PAS.

   AVANT : le bloc était ÉPINGLÉ (pin GSAP) pendant 1800 px de scroll, portait
   `min-height:100svh` + `justify-content:center`, et ne révélait qu'UNE
   légende à la fois en fondu croisé.

   Deux défauts, tous deux mesurés, tous deux rejetés par Julien :

   1. LE TROU. Le bloc réservait une hauteur d'écran ENTIÈRE pour un contenu
      qui n'en remplissait que les deux tiers → 278 px de vide sur une fenêtre
      de 900 px, 428 px sur une fenêtre de 1200 px (sonde du 12/08). Le vide
      GRANDISSAIT avec la hauteur de fenêtre : c'est la signature d'une hauteur
      réservée, pas d'une marge.
      ⚠️ AU MOMENT DE RÉÉCRIRE `min-height:100svh`, `height:100vh`, un
      `justify-content:center` sur un bloc plus haut que son contenu, ou de
      remettre un pin ici → `node scripts/sonde-vide.mjs` le REFUSE (exit 2).
      Le correctif n'a jamais été d'ajouter du contenu pour boucher : c'est que
      le bloc cesse de réserver une hauteur qu'il ne remplit pas.

   2. LES SIX TEMPS CACHÉS. Une légende visible à la fois = cinq sixièmes de
      l'explication masqués à tout instant, derrière 1800 px de scroll. Les six
      cartes sont désormais TOUTES lisibles, ensemble.

   ⚠️ L'ANIMATION D'ENTRÉE EST ADDITIVE, JAMAIS BLOQUANTE. Aucun texte n'est
   posé à `opacity:0` dans la feuille de base : c'est le pilote qui ajoute
   `.chain-entree` avant d'animer, et seulement s'il peut animer. Script tombé,
   GSAP absent, `prefers-reduced-motion` : la page reste entière et lisible.

   ⚠️ ORDRE DES RÈGLES : toute règle de base est déclarée AVANT les `@media`
   qui la reprennent. Une règle posée dans un `@media` avant sa règle de base
   perd la cascade — et le build reste vert (piège déjà payé).
   ============================================================================ */

.chain-scroll{position:relative;margin-top:10px;}

/* Le bloc : hauteur NATURELLE. Il ne réserve rien.
   La lueur diffuse derrière le circuit est la « matière » du hero rapportée
   ici : le juge vision lisait la section comme une grille utilitaire posée
   après la poésie visuelle du hero — « un sentiment de baisse de gamme ».
   Elle est décorative et ne coûte aucune hauteur (position absolue). */
.chain-corps{position:relative;display:flex;flex-direction:column;gap:30px;padding:6px 0 0;}
.chain-corps::before{
  content:"";position:absolute;left:50%;top:-40px;width:min(1100px,96%);height:420px;
  transform:translateX(-50%);pointer-events:none;z-index:0;
  background:radial-gradient(60% 50% at 50% 40%,rgba(31,143,255,.13),transparent 72%);
  filter:blur(6px);
}
.chain-corps > *{position:relative;z-index:1;}

/* --- la tête : la promesse en une phrase, lisible en trois secondes --- */
.chain-head{text-align:center;max-width:780px;margin:0 auto;}
.chain-head h3{
  font-family:var(--font-display);font-weight:700;font-size:clamp(23px,3.1vw,35px);
  letter-spacing:-.02em;line-height:1.16;
}
.chain-sous{margin-top:13px;color:var(--text-muted);font-size:15.5px;line-height:1.6;}
.chain-sous b{color:var(--text);font-weight:600;}

/* ===== LES SIX CARTES — le SEUL système d'accroche de la section ==========
   (le circuit SVG qui les surmontait a été retiré : voir le motif détaillé
   dans app/verticales.ts, il tient en une phrase — un composant coupé en deux
   systèmes de même poids ne se lit pas, il se subit.) */
.chain-caps{
  display:grid;grid-template-columns:repeat(3,1fr);grid-auto-rows:1fr;
  gap:16px;max-width:1060px;margin:2px auto 0;width:100%;
}
/* ⚠️ LA PROFONDEUR EST STRUCTURELLE, PAS DÉCORATIVE. Première version : cartes
   à plat (un fond, un trait). Le juge esthétique (modèle vision, 12/08) les a
   lues « plates, orientées wireframe », en retrait de la finition du hero —
   c'est-à-dire exactement le reproche « bas de gamme » de Julien. Trois couches
   réparent ça, et aucune n'est un effet gratuit : un liseré clair sur l'arête
   haute (la lumière vient d'en haut, comme partout sur la page), une ombre
   portée qui décolle la carte du fond, et un halo bleu très diffus au coin de
   la pastille numérotée, qui rattache la carte au circuit. */
.chain-cap{
  position:relative;display:flex;flex-direction:column;gap:12px;text-align:left;
  border:1px solid var(--line);border-radius:16px;padding:17px 18px 19px;
  background:linear-gradient(165deg,rgba(34,38,50,.62),rgba(13,15,21,.40));
  box-shadow:inset 0 1px 0 rgba(255,255,255,.07),0 12px 32px rgba(0,0,0,.30);
  transition:border-color .35s var(--ease-premium,ease),transform .35s var(--ease-premium,ease),box-shadow .35s var(--ease-premium,ease);
}
.chain-cap::before{
  content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;z-index:0;
  background:radial-gradient(320px 150px at 8% 0%,rgba(31,143,255,.16),transparent 70%);
}
/* ⚠️ SANS CECI LE HALO PASSE DEVANT LE TEXTE. Un pseudo-élément positionné est
   peint AU-DESSUS du contenu non positionné : le halo délavait la pastille
   numérotée et le mot de l'étape — le défaut de lisibilité qu'on venait juste
   de corriger, réintroduit par le remède. Le contenu reprend la main. */
.chain-cap > *{position:relative;z-index:1;}
.chain-cap:hover{border-color:rgba(31,143,255,.38);transform:translateY(-3px);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.09),0 20px 46px rgba(0,0,0,.40);}

/* Le CONNECTEUR entre deux cartes d'une même rangée : c'est ce qui reste du
   circuit, réduit à sa seule fonction utile — dire que ça s'enchaîne. Il vit
   dans la gouttière, ne coûte pas une ligne de hauteur, et ne peut pas voler
   l'œil au titre. Pas de connecteur après la 3e ni la 6e carte : la rangée
   s'arrête là. */
.chain-cap::after{
  content:"";position:absolute;right:-17px;top:50%;width:16px;height:2px;border-radius:2px;
  background:linear-gradient(90deg,rgba(31,143,255,.55),rgba(31,143,255,.12));
  pointer-events:none;
}
.chain-cap:nth-child(3n)::after{display:none;}

/* la tête de carte : le numéro reprend celui du nœud du circuit.
   ⚠️ PAS DE `box-shadow` LUMINEUX SUR CETTE PASTILLE. Première version : halo
   bleu + chiffre blanc sur dégradé bleu clair → le chiffre était NOYÉ, illisible
   à l'œil sur la capture. Le halo éclairait le fond au niveau exact du glyphe.
   Fond sombre + contour bleu + chiffre bleu clair : le chiffre se lit, et la
   pastille reste rattachée au nœud du circuit par la couleur. */
.cap-tete{display:flex;align-items:center;gap:11px;}
.cap-num{
  width:34px;height:34px;flex:none;border-radius:50%;display:grid;place-items:center;
  font-family:var(--font-display);font-weight:700;font-size:16px;line-height:1;
  color:#eaf4ff;background:rgba(31,143,255,.16);border:1px solid rgba(31,143,255,.55);
  box-shadow:0 0 18px rgba(31,143,255,.22);
}
.cap-noeud{font-size:12px;letter-spacing:.09em;text-transform:uppercase;color:var(--text-muted);font-weight:600;}
/* ⚠️ L'ÉCART TITRE/TEXTE EST VOULU LARGE. À 17/14 px, le juge vision lisait
   « une masse de texte uniforme » où l'œil se perd. Le rapport est donc franc
   (19/13,5) et le titre passe en blanc pur : on lit les six titres d'abord, le
   détail seulement si on s'arrête.
   🔴 LE CONTRASTE SE FAIT PAR LA TAILLE, JAMAIS EN ÉTEIGNANT LE CORPS DE TEXTE.
   Le passage du corps à `--text-faint` (#5e636d) donnait bien le contraste
   demandé par le juge, mais tombait à ~3,2:1 sur le fond de carte — sous le
   plancher WCAG AA de 4,5:1 pour du texte courant. `--text-muted` tient ~7:1.
   Un juge esthétique ne mesure pas la lisibilité : il ne voit pas ce seuil. */
/* 🔴 CES DEUX RÈGLES SONT SCOPÉES À `.cap-txt`, ET CE N'EST PAS COSMÉTIQUE.
   Écrites `.chain-cap span`, elles frappaient TOUS les `span` de la carte —
   dont `.cap-num` (la pastille numérotée) et `.cap-noeud` (le mot de l'étape).
   `.chain-cap span` pèse 0,1,1 contre 0,1,0 pour `.cap-num` : le sélecteur
   large GAGNAIT, imposait `display:block` (ce qui tuait le `place-items:center`
   de la pastille et sortait le chiffre de son cercle), la couleur sourde et la
   petite taille. Résultat : un chiffre pâle, décentré et à moitié hors du rond
   — un défaut que trois captures et deux passes de juge ont vu sans le nommer,
   parce qu'il ressemblait à un problème de CONTRASTE alors que c'était un
   problème de CASCADE. Ne jamais élargir ces sélecteurs. */
.chain-cap .cap-txt b{display:block;font-family:var(--font-display);font-weight:700;font-size:19px;
  line-height:1.2;letter-spacing:-.015em;margin-bottom:7px;color:#fff;}
.chain-cap .cap-txt span{display:block;color:var(--text-muted);font-size:13.5px;line-height:1.55;}

/* état ÉTEINT des cartes : posé par le pilote seulement */
.chain-entree .chain-cap{opacity:0;transform:translateY(14px);}
.chain-entree .chain-cap.vu{opacity:1;transform:none;
  transition:opacity .55s var(--ease-premium,ease),transform .55s var(--ease-premium,ease);}

/* ===== LES MINI-VISUELS ================================================== */
/* ⚠️ HAUTEUR UNIFORME, ET ELLE EST STRUCTURELLE. Les six mini-visuels n'ont
   pas le même contenu (trois créneaux d'agenda contre une bulle de SMS) : à
   hauteur libre, les titres des six cartes ne s'alignaient plus d'une colonne à
   l'autre, et la grille prenait un air bricolé. Une boîte de hauteur fixe, dont
   le contenu est centré, aligne les titres sans rien étirer. */
.cap-mock{width:100%;min-height:150px;display:flex;flex-direction:column;justify-content:center;
  border-radius:11px;border:1px solid var(--line);
  background:linear-gradient(160deg,rgba(28,30,40,.78),rgba(14,16,22,.58));padding:13px 14px;
  box-shadow:0 10px 26px rgba(0,0,0,.34);position:relative;overflow:hidden;font-size:12.5px;line-height:1.45;}
.cap-mock .mk-row{display:flex;align-items:center;gap:6px;color:var(--text-faint);font-size:10.5px;margin-bottom:7px;}
.cap-mock .mk-dot{width:6px;height:6px;border-radius:50%;background:var(--text-faint);}
.cap-mock .mk-dot.g{background:#46d39a;box-shadow:0 0 7px #46d39a;}

/* CE QUI VIENT DU CLIENT, surligné. C'est l'argument de personnalisation
   RENDU VISIBLE — il remplace la phrase « seule sa fiche change » qui, elle,
   argumentait contre les onglets qu'elle accompagnait. */
.mk-var{font-style:normal;color:#d3e8ff;background:rgba(31,143,255,.17);
  border-bottom:1px dashed rgba(31,143,255,.5);border-radius:3px;padding:0 3px;}

/* appel */
.mk-call .mk-usr{color:var(--text-muted);font-size:11.5px;margin-bottom:7px;}
.mk-call .mk-ai{color:var(--electric-bright);font-size:12px;margin-bottom:9px;}
.mk-call .mk-eq{display:flex;align-items:flex-end;gap:3px;height:20px;}
/* ⚠️ ANIMÉ EN `transform:scaleY`, JAMAIS EN `height` (mesuré le 03/08) : une
   hauteur animée refait la mise en page de la barre ET de sa rangée à chaque
   image, et il y a DIX de ces barres dans la page, animées en permanence.
   L'échelle prend appui sur le bas : le rendu est identique. */
.mk-call .mk-eq i{width:4px;border-radius:3px;height:100%;transform-origin:bottom;transform:scaleY(.40);background:linear-gradient(180deg,var(--electric-bright),var(--electric-deep));animation:mk-eq 1s ease-in-out infinite;}
.mk-call .mk-eq i:nth-child(2n){animation-duration:.8s;}.mk-call .mk-eq i:nth-child(3n){animation-duration:1.3s;}.mk-call .mk-eq i:nth-child(4n){animation-duration:1.1s;}
@keyframes mk-eq{0%,100%{transform:scaleY(.22);}50%{transform:scaleY(.95);}}
/* agenda */
.mk-agenda{display:flex;flex-direction:column;gap:6px;}
.mk-agenda .mk-slot{font-size:11px;color:var(--text-muted);border:1px solid var(--line);border-radius:7px;padding:6px 9px;}
.mk-agenda .mk-slot.on{color:#fff;border-color:rgba(31,143,255,.5);background:rgba(31,143,255,.14);box-shadow:0 0 14px rgba(31,143,255,.16);}
/* bulle téléphone (les deux SMS) */
.mk-phone .mk-bubble{background:linear-gradient(135deg,var(--electric-bright),var(--electric-deep));color:#fff;border-radius:12px 12px 12px 4px;padding:9px 11px;font-size:12px;}
/* Dans la bulle bleue, le surlignage se fait DISCRET : le contour pointillé et
   le fond clair qui marchent sur fond sombre y produisaient un pâté illisible. */
.mk-phone .mk-bubble .mk-var{background:rgba(255,255,255,.20);border-bottom:none;color:#fff;padding:0 4px;}
.mk-phone .mk-bubble.alt{background:rgba(255,255,255,.06);border:1px solid var(--line-strong);color:var(--text);}
.mk-phone .mk-meta{display:block;margin-top:5px;font-size:9.5px;opacity:.9;}

/* ============================================================================
   ADAPTATIONS — toujours APRÈS les règles de base qu'elles reprennent.
   ============================================================================ */

/* tablette : deux colonnes plutôt que trois écrasées.
   ⚠️ Le connecteur suit la GRILLE, pas le markup : à deux colonnes, c'est la
   2e carte de chaque rangée qui finit la ligne, plus la 3e. */
@media(max-width:1080px){
  .chain-caps{grid-template-columns:repeat(2,1fr);}
  .chain-cap:nth-child(3n)::after{display:block;}
  .chain-cap:nth-child(2n)::after{display:none;}
}

/* téléphone : une seule colonne, et le connecteur bascule à la VERTICALE.
   Six étapes serrées côte à côte deviendraient soit minuscules, soit entassées
   — c'est l'objection qui a coûté la version précédente. */
@media(max-width:820px){
  .chain-corps{gap:20px;}
  .chain-sous{font-size:14.5px;}
  .chain-caps{grid-template-columns:1fr;grid-auto-rows:auto;gap:16px;max-width:470px;}
  .chain-cap{padding:15px 16px 16px;}
  .chain-cap::after{
    right:auto;top:auto;left:32px;bottom:-16px;width:2px;height:16px;
    background:linear-gradient(180deg,rgba(31,143,255,.55),rgba(31,143,255,.12));
  }
  .chain-cap:nth-child(3n)::after{display:block;}
  .chain-cap:last-child::after{display:none;}
  .chain-cap:hover{transform:none;}
  .chain-cap b{font-size:17px;}
  /* la hauteur uniforme du mini-visuel ne sert qu'à aligner les colonnes entre
     elles : sur une colonne unique, elle ne fait plus qu'ajouter du vide. */
  .cap-mock{min-height:0;}
}

/* mouvement réduit : rien ne bouge, tout est là */
@media (prefers-reduced-motion: reduce){
  .chain-cap{transition:none !important;}
  .mk-call .mk-eq i{animation:none;transform:scaleY(.55);}
}
