/* ==========================================================================
   V&P Philadelphia — le hero scrubbe et les sections de l'accueil.
   Charge par toutes les pages : les pages internes n'ont pas de .hero,
   donc rien de ce bloc ne s'applique chez elles.
   ========================================================================== */

.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* ==========================================================================
   1. Le hero epingle
   18 secondes de video chainee demandent environ 1000vh de course,
   sinon chaque legende defile trop vite quel que soit le reglage des bandes.
   ========================================================================== */

/* Le rideau : le dernier ecran de course du hero ne fait plus avancer le film.
   La scene reste epinglee, et la section suivante remonte par-dessus. Une
   seule valeur pour les deux, sinon la course et le recouvrement se decalent.
   Le script lit la marge negative reellement calculee, il ne la recopie pas. */
/* 100svh, et ce n'est PAS un reglage libre : c'est une contrainte.
   La scene se decolle quand son bas atteint le bas du hero, soit apres
   hauteur_hero - 100svh de defilement. La section suivante atteint le haut de
   l'ecran apres hauteur_hero - rideau. Les deux ne coincident que si le
   rideau vaut exactement une hauteur d'ecran.
   Essai du 06/09 a 170svh, pour ralentir la montee de la section : la scene
   restait collee 630px APRES que la section suivante ait couvert l'ecran, et
   la video du hero reapparaissait derriere la section produits. Le rideau ne
   commande pas la vitesse de montee, qui vaut toujours un ecran de
   defilement : il ne fait qu'allonger le collage. */
:root{--curtain:100svh}

/* padding:0 obligatoire : la regle generique section{padding-block:...} de
   base.css s appliquait aussi a ce <section>, et ses 140px de marge haute
   decalaient la scene collante vers le bas, laissant le fond visible au-dessus. */
/* 500vh et non 1000vh. La course reelle vaut hauteur moins un ecran moins le
   rideau, soit 4 ecrans au lieu de 9. Sur un telephone c'etait 15 a 19 coups
   de pouce pour atteindre le sac, remonte par une vraie testeuse. Les 20
   premiers pour cent du film etant desormais joues tout seuls a l'arrivee,
   ces 4 ecrans ne portent plus que les 80 pour cent restants. */
/* UNE HAUTEUR D ECRAN, la ou il y en avait 615vh. Changement du 07/09 apres
   un test utilisateur : le
   film ne se joue plus au scroll, il se joue tout seul en 5 secondes des
   que l age est confirme (voir INTRO_MS dans app.js). Les 615vh existaient
   pour porter les 80 % du film qui restaient au doigt : ils n ont plus rien
   a porter, et les garder aurait laisse six ecrans de defilement mort par
   dessus un film deja fini.
   Verdict des testeurs, remonte par Lucas : le defilement du debut n etait
   pas une bonne experience. C etait la definition meme du piege a scroll,
   six ecrans avant que la section suivante commence seulement a monter.
   A une hauteur d ecran plus le rideau, la section "qui on est" commence a
   monter des le premier pixel de defilement : plus aucun temps mort. */
.hero{position:relative;height:calc(100svh + var(--curtain));padding:0}
.hero-stage{
  position:sticky;top:0;height:100svh;overflow:hidden;
  background:#05050A;
}

.hero-poster{
  position:absolute;inset:0;
  /* L affiche est declaree ICI et pas seulement en JavaScript : le navigateur
     la telecharge des l analyse de la feuille de style, en parallele du reste.
     Chargee par JS seulement, elle attendait l execution du script, et le fond
     noir de la scene restait visible le temps d un aller-retour complet.
     Le bloc mobile plus bas remplace cette valeur, donc un telephone ne
     telecharge jamais cette image-ci. */
  background-image:url("../img/hero-poster.jpg");
  background-size:cover;background-position:50% 45%;
  transition:opacity .8s var(--ease-slow);
}
#hero-video{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;object-position:50% 45%;
  opacity:0;transition:opacity .8s var(--ease-slow);
  will-change:transform;transform:translateZ(0);
}
/* La video ne prend la place de l affiche qu au PREMIER SCROLL, pas des que
   le fichier est pret. Raison : l affiche vient de l image d origine, nette,
   alors que la premiere image de la video a subi l interpolation puis une
   compression a crf 25 et parait molle. A l arret le visiteur voit donc une
   image nette ; des qu il scrolle la video prend le relais, et son leger
   ramollissement devient invisible parce que tout bouge. */
.hero-stage.video-ready.scrolled #hero-video{opacity:1}
.hero-stage.video-ready.scrolled .hero-poster{opacity:0}

/* L'anneau de chargement : honnete, et il disparait quoi qu'il arrive. */
.ring{position:absolute;right:calc(var(--gutter));bottom:var(--gutter);width:34px;height:34px;color:var(--accent);opacity:.7;transform:rotate(-90deg)}
.ring circle{transition:stroke-dashoffset .2s linear}

/* Le voile global : aucune image de la video n'est jamais brute derriere la page. */
.scrim{
  position:absolute;inset:0;pointer-events:none;
  background:radial-gradient(ellipse 120% 90% at 50% 45%,rgba(8,8,18,0) 35%,rgba(8,8,18,.62) 100%);
}

/* ==========================================================================
   2. Les bandes de legende
   Elles vivent dans le tiers inferieur gauche, sur le parc sombre,
   sauf la derniere qui se centre sous l'objet tendu.
   ========================================================================== */

.bands{position:absolute;inset:0;pointer-events:none}
.band{
  position:absolute;left:var(--gutter);bottom:clamp(90px,14vh,170px);
  width:min(46ch,52vw);
  opacity:0;visibility:hidden;
  text-shadow:var(--tshadow);
  pointer-events:none;
}
.band .btn{text-shadow:none}


/* ==========================================================================
   3. Les entrees de texte, une par bande, chacune en echo de l'image.
   Transform et opacity uniquement, pilotees par --k, entierement reversibles.
   ========================================================================== */

.w{display:inline-block;white-space:pre}
.c{display:inline-block}
/* Le mot qui vivait dans un <em> avant le decoupage (ex. "Zero") garde son
   accent violet. Le decoupage remplace la vraie balise par ce marqueur. */
.w--em{color:var(--accent)}

/* Les quatre entrees de texte des bandes narratives ont ete retirees avec
   elles. .w, .c et .w--em restent : le titre du bloc d'arrivee passe par le
   meme decoupage. */

/* ==========================================================================
   4. Le bandeau de statut dans le hero, et le V signature
   ========================================================================== */
/* ==========================================================================
   Le bloc d arrivee
   Tout apparait ici et nulle part avant : panneau de mission, titre, sous-titre,
   bouton et garanties. Le voile assombrit la moitie gauche pour que l ensemble
   ressorte sur la rue, sans toucher au sac ni au bras a droite.
   ========================================================================== */

.settle-veil{
  position:absolute;inset:0;pointer-events:none;z-index:1;
  opacity:var(--settle,0);
  /* Le voile s eteint avant le sac : plus loin il mangeait le logo V&P, qui
     est le sujet du plan. Le texte qui deborde au-dela garde son ombre portee. */
  background:linear-gradient(90deg,
    rgba(4,4,9,.90) 0%,
    rgba(4,4,9,.80) 26%,
    rgba(4,4,9,.50) 40%,
    rgba(4,4,9,.16) 54%,
    rgba(4,4,9,0) 68%);
}

.band--settle{
  left:var(--gutter);
  bottom:auto;
  top:50%;
  transform:translateY(-50%);
  width:min(58ch,52vw);
  text-align:left;
  z-index:2;
}
/* Le voile fait deja tout le travail d assombrissement : le halo local des
   bandes de descente ferait une tache sombre visible par-dessus. */
.band--settle::before{content:none}

/* --- Le panneau de mission ------------------------------------------------ */
.hud{
  display:inline-block;
  border:1px solid rgba(168,85,247,.42);
  border-radius:10px;
  background:rgba(10,8,20,.42);
  backdrop-filter:blur(8px);
  padding:.75rem 1.1rem .8rem;
  margin-bottom:clamp(1.4rem,3vh,2.2rem);
  font-family:var(--font-mono);
  font-variant-numeric:tabular-nums;
  color:var(--text-primary);
}

/* ==========================================================================
   Les deux places du bandeau, decidees par le script
   .hud--hero  : pose en bas a gauche de la scene, a partir de 1200px
   .hud--fixed : filet pleine largeur colle sous la nav, en dessous
   La mise en ligne interieure est la meme dans les deux cas : une seule
   hauteur de texte, etiquette avant la valeur.
   ========================================================================== */

.hud--hero,
.hud--fixed{margin:0}

.hud--hero .hud__row,
.hud--fixed .hud__row{display:flex;align-items:center;gap:0}

.hud--hero .hud__cell,
.hud--fixed .hud__cell{
  flex-direction:row;align-items:center;gap:.45rem;
  justify-content:flex-start;
  padding-right:.65rem;margin-right:.65rem;
  border-right:1px solid rgba(168,85,247,.22);
}
.hud--hero .hud__cell:last-child,
.hud--fixed .hud__cell:last-child{margin-right:0;padding-right:0;border-right:none}

/* Le libelle de la cellule lieu etait masque quand il disait seulement
   LOCATION, redite du texte a cote. Il dit maintenant PICKUP POINT, qui
   porte le sens de la ligne : il reste visible. */
.hud--hero .hud__cell--loc .hud__lab,
.hud--fixed .hud__cell--loc .hud__lab{display:block}

.hud--hero .hud__lab,
.hud--fixed .hud__lab{order:-1;margin-top:0;font-size:.52rem;letter-spacing:.12em}

.hud--hero .hud__val,
.hud--fixed .hud__val{font-size:.62rem;letter-spacing:.03em}

/* En bas a gauche de la scene, a partir de 1200px.
   Il est pose DANS la scene collante, qui est rognee : la section suivante
   la recouvre en montant et emporte donc le bandeau avec elle, sans un seul
   calcul de scroll. C'est le comportement demande, disparaitre en passant a
   la section du dessous.
   Il se serre sur son contenu au lieu de s'etirer : dans la nav il devait
   remplir l'espace entre le logo et les liens, ici il n'a plus rien a
   remplir. */
.hud--hero{
  position:absolute;z-index:3;
  left:var(--gutter);
  bottom:clamp(20px,3.6vh,38px);
  width:max-content;max-width:calc(100% - var(--gutter) * 2);
  padding:.62rem 1rem;
  border-radius:10px;
  border-color:rgba(168,85,247,.30);
  background:rgba(8,8,15,.55);
  -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);
  text-shadow:none;
}
.hud--hero .hud__val{font-size:.66rem}

/* Sous la nav : un filet traversant. pointer-events:none, sinon cette bande
   avalerait les appuis sur le contenu qui defile dessous. */
.hud--fixed{
  position:fixed;top:var(--nav-h);left:0;right:0;
  z-index:90;
  display:block;
  padding:.65rem var(--gutter);
  border-radius:0;border-left:none;border-right:none;
  border-top:1px solid rgba(168,85,247,.38);
  border-bottom:1px solid rgba(168,85,247,.38);
  background:rgba(6,5,12,.82);
  backdrop-filter:blur(8px);
  pointer-events:none;
}

/* --- Le rappel de lieu en bas de cadre ------------------------------------- */
.hero-place{
  position:absolute;left:var(--gutter);bottom:clamp(20px,3.6vh,38px);
  z-index:2;pointer-events:none;margin:0;
  opacity:var(--settle,0);
  display:flex;align-items:center;gap:.55rem;
  font-family:var(--font-mono);font-size:.62rem;
  letter-spacing:.14em;text-transform:uppercase;
  color:var(--text-secondary);
  text-shadow:var(--tshadow-sm);
}
.hero-place svg{width:15px;height:15px;flex:none;color:var(--accent)}
@media (max-width:720px){.hero-place{display:none}}
/* nowrap obligatoire sur les deux : chaque lettre est un inline-block pour
   le decodage, donc sans ca le navigateur coupe au milieu d une valeur et
   affiche 00:00: puis 00 a la ligne. */
.hud__val,.hud__lab{white-space:nowrap}

/* Le point de service, en violet a la demande de Lucas plutot qu'au vert
   fonctionnel du reste du site. Il garde quand meme son sens : il ne bat
   que quand quelqu'un est en haut, et s'eteint en gris a la fermeture.
   inline-block obligatoire sur le point : il porte aussi la classe
   .hud__val, dont le display:block plus bas gagnait la cascade et le
   remettait en flux inline, ou sa largeur etait ignoree. Il disparaissait. */
.hud__dot{
  display:inline-block;
  width:7px;height:7px;border-radius:50%;flex:none;position:relative;
  background:var(--accent);
}
.hud__dot::after{
  content:"";position:absolute;inset:-4px;border-radius:50%;
  background:var(--accent);opacity:0;
  animation:pulse 2.4s var(--ease-slow) infinite;
}
/* Ferme : le point ne bat plus et passe au gris. Il reste volontairement
   visible, sinon le bandeau donne l'impression d'etre casse plutot que
   de dire honnetement que personne n'est en haut. */
body.is-closed .hud__dot{background:#8B8B96}
body.is-closed .hud__dot::after{animation:none}

.hud__row{display:flex;align-items:stretch;gap:clamp(.9rem,1.6vw,1.5rem)}
.hud__cell{display:flex;flex-direction:column;justify-content:flex-end;padding-right:clamp(.9rem,1.6vw,1.5rem);border-right:1px solid rgba(168,85,247,.20)}
.hud__cell:last-child{padding-right:0;border-right:none}
.hud__val{display:block;font-size:clamp(.82rem,1.15vw,1.08rem);font-weight:500;line-height:1.25;letter-spacing:.04em}
/* Apres .hud__val, sinon son display:block ecrase ce flex a specificite egale. */
.hud__loc{display:flex;align-items:center;gap:.5rem}
.hud__val--accent{color:var(--accent)}
.hud__lab{display:block;font-size:.56rem;letter-spacing:.2em;color:var(--text-faint);margin-top:.4rem}

/* --- Le lien vers la carte -----------------------------------------------
   Le souligne est une demande explicite : il faut comprendre au premier coup
   d oeil que l adresse se clique. Il est pose sur le SEGMENT et non sur le
   lien, sinon il passe aussi sous le point de service, qui est une pastille.
   pointer-events:auto est OBLIGATOIRE : .hud--fixed porte pointer-events:none
   pour ne pas avaler les appuis sur le contenu qui defile dessous, et sans
   cette ligne le lien serait mort au doigt sur telephone. */
.hud__map{color:inherit;text-decoration:none;pointer-events:auto}
/* Le souligne est pose sur les i, pas sur le segment qui les contient :
   chaque caractere du decodage est un inline-block (il porte sa propre
   opacite), et une boite inline-block ne recoit pas la decoration de son
   ancetre. Souligne sur le segment, il ne se dessinait tout simplement pas.
   Les i se touchent (white-space:pre, aucun blanc entre eux), donc les
   traits se raccordent en une ligne continue. */
.hud__map .hud__seg i{
  text-decoration:underline;
  text-decoration-color:rgba(168,85,247,.85);
  text-decoration-thickness:1px;
  text-underline-offset:3px;
}
.hud__map .hud__seg{transition:color var(--dur) var(--ease)}
.hud__map:hover .hud__seg{color:var(--accent)}
.hud__map:hover .hud__seg i{text-decoration-color:var(--accent)}
.hud__map:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-radius:4px}

/* Chaque caractere porte son index. Une seule ecriture de --n sur le panneau
   revele toute la ligne : aucune boucle DOM par lettre a chaque image. */
.hud i{
  font-style:normal;display:inline-block;white-space:pre;
  opacity:clamp(0,calc((var(--n,0) - var(--i,0)) * 4),1);
}

/* --- Le titre ------------------------------------------------------------- */
.settle__title{
  font-family:var(--font-display);font-weight:800;
  font-size:clamp(2.3rem,4.6vw,4.1rem);
  line-height:1.02;letter-spacing:-.03em;text-transform:uppercase;
  margin:0 0 1.1rem;
}
/* Une phrase par ligne, toujours : le titre ne depend plus de la largeur
   disponible pour tomber au bon endroit. */
.settle__title > span{display:block}
.settle__title em{font-style:normal;color:var(--accent)}

.settle__sub{
  font-size:clamp(.95rem,1.15vw,1.08rem);
  color:var(--text-secondary);line-height:1.65;
  margin:0 0 clamp(1.5rem,3vh,2.2rem);max-width:46ch;
}
.settle__hl{color:var(--accent)}

/* --- L appel a l action ---------------------------------------------------- */
/* En contour et deja en surbrillance, partout : jamais l'aplat plein. Sur
   telephone il n'y a pas de survol, donc l'etat brillant doit etre l'etat
   normal, et l'ordinateur suit la meme regle pour que le bouton soit le meme
   objet sur les deux. */
.settle__cta{
  display:inline-flex;align-items:center;gap:.85rem;
  pointer-events:auto;
  background:rgba(168,85,247,.22);
  color:#fff;
  border:1px solid var(--accent);
  font-family:var(--font-mono);font-weight:500;
  font-size:clamp(.82rem,1vw,.95rem);letter-spacing:.14em;text-transform:uppercase;
  padding:1.05rem 1.5rem;border-radius:12px;
  text-shadow:none;
  box-shadow:0 0 0 1px rgba(168,85,247,.45),0 0 26px rgba(168,85,247,.5);
  transition:background var(--dur) var(--ease),box-shadow var(--dur) var(--ease),border-color var(--dur) var(--ease);
}
/* :active en plus de :hover, sinon rien ne se passe au doigt : un telephone
   n'a pas de survol, seulement l'appui. */
.settle__cta:hover,
.settle__cta:focus-visible,
.settle__cta:active{
  background:rgba(168,85,247,.36);
  border-color:var(--accent-hover);
  box-shadow:0 0 0 1px var(--accent),0 0 34px rgba(168,85,247,.7);
}
.settle__cta-ico{width:19px;height:19px;flex:none}
.settle__cta-arrow{width:20px;height:20px;flex:none;margin-left:auto;transition:transform var(--dur) var(--ease)}
.settle__cta:hover .settle__cta-arrow{transform:translateX(4px)}

/* --- Les garanties --------------------------------------------------------- */
.settle__trust{
  list-style:none;margin:clamp(1.3rem,2.6vh,1.9rem) 0 0;padding:0;
  display:flex;flex-wrap:wrap;gap:clamp(.9rem,2vw,1.7rem);
  font-family:var(--font-mono);font-size:.66rem;letter-spacing:.16em;
  text-transform:uppercase;color:var(--text-secondary);
}
.settle__trust li{display:flex;align-items:center;gap:.55rem}
.settle__badge{
  width:22px;height:22px;flex:none;border-radius:6px;
  display:inline-flex;align-items:center;justify-content:center;
  border:1px solid rgba(168,85,247,.34);background:rgba(168,85,247,.10);
  color:var(--accent);
}
.settle__badge svg{width:13px;height:13px}

/* --- Les entrees du bloc, echelonnees sur sa propre progression -------------
   Panneau, puis titre mot a mot, puis sous-titre, puis bouton, puis garanties.
   Transform et opacite uniquement. Le bouton et les garanties n ont que de
   l opacite : une transform ici entrerait en conflit avec celle du survol. */
.band--settle .hud{
  --kh:clamp(0,var(--k,0)*3.4,1);
  opacity:var(--kh);
  transform:translateY(calc((1 - var(--kh)) * 12px));
}
.band--settle .settle__title .w{
  --kc:clamp(0,(var(--k,0) - var(--th,0)*.5 - .24)*3.4,1);
  opacity:var(--kc);
  transform:translateY(calc((1 - var(--kc)) * 22px));
}
.band--settle .settle__sub{--ks:clamp(0,(var(--k,0) - .56)*4,1);opacity:var(--ks)}
.band--settle .settle__cta{--kb:clamp(0,(var(--k,0) - .68)*4.5,1);opacity:var(--kb)}
.band--settle .settle__trust{--kt:clamp(0,(var(--k,0) - .80)*5,1);opacity:var(--kt)}

/* --- L invite a poursuivre -------------------------------------------------- */
/* Deux chevrons, sans le mot : le geste de glisser vers le bas se lit tout
   seul. En violet comme le reste des reperes, celui du haut plus efface que
   celui du bas pour donner le sens de la descente. */
.scrollcue{
  position:absolute;left:50%;bottom:clamp(18px,3.4vh,34px);
  transform:translateX(-50%);
  z-index:2;pointer-events:none;
  opacity:var(--settle,0);
  display:flex;flex-direction:column;align-items:center;gap:.2rem;
  color:var(--accent);
}
.scrollcue svg{width:19px;height:10px}
.scrollcue svg:first-child{opacity:.45}

/* Le V signature s efface quand le bloc final arrive : il tomberait sur le bras. */
.hero-v{opacity:calc(1 - var(--settle,0))}

@media (max-width:1100px){
  .band--settle{width:min(52ch,72vw)}
  .hud__row{flex-wrap:wrap;gap:.7rem 1.1rem}
  .hud__cell{border-right:none;padding-right:0}
  /* Le filet passe sur deux lignes des que l adresse du point de retrait est
     la : le separateur vertical de la cellule lieu se retrouvait alors seul
     au bout de la premiere ligne, comme un trait orphelin. Il faut nommer
     .hud--fixed ici, sinon la regle .hud--fixed .hud__cell plus haut gagne
     la cascade et le trait revient. */
  .hud--fixed .hud__cell,
  .hud--hero .hud__cell{border-right:none;padding-right:0;margin-right:0}
}
@media (max-height:680px){
  .settle__trust{display:none}
  .hud{margin-bottom:1rem}
}

/* ==========================================================================
   La composition en deux zones sur grand ecran (maquette du 02/09)
   L'image ne prend plus toute la largeur : elle est calee a droite, et la
   colonne de gauche est du noir plein ou le texte se pose. Le raccord entre
   les deux est un degrade, jamais une arete.
   Pourquoi retrecir l'element video plutot que de deplacer l'image dedans :
   sur un ecran 16/9 le film est deja au format du cadre, donc object-position
   n'a presque aucun jeu et ne decale rien. Reduire la largeur du cadre, elle,
   recadre vraiment et fait sortir le sac vers la droite.
   Le seuil est a 1000px : en dessous, la colonne de noir mangerait l'image.
   ========================================================================== */
@media (min-width:1000px){
  /* Le recadrage est PILOTE PAR --settle, pas permanent : pendant toute la
     descente le film occupe l'ecran entier, exactement comme avant. Ce n'est
     qu'a l'arrivee, quand le plan se pose sur le sac, que le cadre glisse
     vers la droite pour liberer la colonne de gauche.
     Transform seule, jamais width : c'est la regle du hero, et animer une
     largeur relancerait une mise en page a chaque image.
     22% de translation avec un zoom de 1,2 amenent le sac autour de 70% de
     la largeur, mesure sur les images du film. Le zoom sert a couvrir : sans
     lui, la translation laisserait un vide a gauche plus large que le noir. */
  #hero-video,.hero-poster{
    transform:translate3d(calc(var(--settle,0) * 22%),0,0)
              scale(calc(1 + var(--settle,0) * .2));
  }

  /* Le voile d'arrivee devient la colonne noire. Son opacite suit deja
     --settle, donc il n'existe pas pendant la descente et se pose avec le
     texte. Il s'arrete toujours avant le sac, comme decide au depart. */
  .settle-veil{
    background:linear-gradient(90deg,
      #05050A 0%,
      #05050A 22%,
      rgba(5,5,10,.88) 32%,
      rgba(5,5,10,.50) 44%,
      rgba(5,5,10,0) 60%);
  }

  /* Le texte tient dans la colonne assombrie au lieu de deborder sur l'image.
     --cta-w est la mesure commune du bouton et du filet : la jauge se remplit
     donc exactement jusqu'au bout du bouton, sans valeur recopiee a deux
     endroits qui pourraient diverger. */
  /* Largeur en pixels et en vw, pas en ch : l'unite ch se calcule sur la
     police du corps de texte, alors que c'est le titre a 66px qui commande
     ici. Une valeur en ch parait large et coupait "PREMIUM VAPES." en deux. */
  .band--settle{
    width:min(680px,48vw);
    --cta-w:min(390px,34vw);
  }

  /* Le filet violet entre le titre et la ligne de promesse. Il sert aussi de
     jauge : voir la regle de survol juste apres. Les marges sont larges,
     c'est ce qui aere la colonne. */
  .settle__title{margin-bottom:0}
  .settle__title::after{
    content:"";display:block;
    width:var(--cta-w);height:2px;background:var(--accent);
    margin:2.1rem 0 1.9rem;
    transform:scaleX(.16);transform-origin:0 50%;
    transition:transform .6s var(--ease-slow);
  }
  /* Au survol du bouton, le filet se remplit sur toute sa longueur. :has
     permet de remonter du bouton vers le titre, qui le precede dans le
     balisage : aucun script n'est necessaire. */
  .band--settle:has(.settle__cta:hover) .settle__title::after,
  .band--settle:has(.settle__cta:focus-visible) .settle__title::after{
    transform:scaleX(1);
  }

  /* La promesse en une ligne, en monospace comme les etiquettes du site,
     et en blanc : en gris elle passait derriere le reste. */
  .settle__sub{
    color:var(--text-primary);
    font-family:var(--font-mono);
    font-size:clamp(.74rem,.92vw,.9rem);
    letter-spacing:.14em;text-transform:uppercase;
    line-height:1.5;
    margin:0 0 3.6rem;
  }

  /* Plus bas et plus long : la marge au-dessus vient de la ligne precedente,
     la longueur de la mesure commune avec le filet. */
  .settle__cta{
    min-width:var(--cta-w);
    justify-content:flex-start;
    padding:1.15rem 1.6rem;
  }
}

/* ==========================================================================
   Mise en page mobile du bloc d'arrivee, sur la maquette validee par Lucas
   le 02/09. Ce n'est pas la version desktop retrecie : c'est une autre
   composition. Le bandeau devient un filet pleine largeur colle sous la nav,
   tout le discours se pose en bas de l'ecran, le bouton passe en contour et
   les garanties s'alignent en trois colonnes separees par des filets.
   Le desktop, valide tel quel, n'est pas touche : tout est sous 720px.
   ========================================================================== */
@media (max-width:720px) and (prefers-reduced-motion:no-preference){

  /* Le bloc occupe toute la scene. pointer-events reste a none (herite de
     .band), donc il n'intercepte jamais le geste de scroll qui pilote la video. */
  /* Le bas reserve la place de l'invite SCROLL : sans cette marge, les
     garanties et la fleche se chevauchent, verifie en capture. */
  .band--settle{
    left:0;right:0;top:0;bottom:0;width:auto;transform:none;
    display:flex;flex-direction:column;
    padding:calc(var(--nav-h) + .4rem) var(--gutter) clamp(86px,13vh,120px);
  }

  /* Le bandeau n'a plus de regles ici : sa presentation vient des classes
     .hud--hero / .hud--fixed posees par le script, valables a toute largeur. */
  .hud__dot{width:7px;height:7px}

  /* La ligne de promesse est reservee au grand ecran : sur telephone le hero
     tient volontairement en un titre et un bouton. */
  .settle__sub{display:none}

  /* --- le voile : vertical, il laisse le sac respirer au milieu --- */
  .settle-veil{
    background:linear-gradient(180deg,
      rgba(4,4,9,.92) 0%,
      rgba(4,4,9,.55) 13%,
      rgba(4,4,9,0) 34%,
      rgba(4,4,9,.55) 62%,
      rgba(4,4,9,.93) 100%);
  }

  /* --- les legendes de la descente --------------------------------------
     Remontees au-dessus du V, qui vit maintenant dans le tiers bas, et
     elargies : dans l'ancienne colonne de 52vw le gros corps du titre se
     coupait en quatre ou cinq lignes sur un telephone. */
  .band:not(.band--settle){
    left:var(--gutter);right:var(--gutter);width:auto;
    bottom:30vh;
  }
  .band__line{font-size:clamp(1.75rem,7.4vw,2.4rem)}

  /* --- l'ordre est inverse sur telephone -------------------------------
     Le bouton passe AVANT le titre et remonte sur le sac, juste sous le
     lockup V&P imprime dessus : le geste devient "je clique sur le sac".
     La marge haute est en svh pour que le bouton tombe au meme endroit du
     cadre quelle que soit la taille du telephone, le hero faisant 100svh.
     Tout est centre, le bouton etant desormais l'ancre de la composition. */
  /* Seules la taille et la place changent ici : l'aspect (contour, halo,
     etats) vient de la regle de base, commune aux deux plateformes. */
  .settle__cta{
    order:1;
    /* Descendu au milieu du sac plutot que juste sous son logo : le hero
       respire davantage, le bandeau etant desormais fixe en haut. */
    margin:46svh auto 0;
    width:auto;justify-content:center;
    padding:.7rem 1.1rem;font-size:.68rem;gap:.6rem;
  }
  .settle__cta-ico{width:16px;height:16px}
  .settle__cta-arrow{width:17px;height:17px;margin-left:0}

  /* margin-top:auto absorbe tout l'espace libre et pousse le titre tout en
     bas de la scene, juste au-dessus des deux fleches. */
  .settle__title{
    order:2;
    font-size:clamp(1.7rem,7.4vw,2.4rem);
    margin:auto 0 0;text-align:center;
  }
  /* Le filet violet, centre sous le titre. */
  .settle__title::after{
    content:"";display:block;width:58px;height:2px;
    background:var(--accent);margin:1rem auto 0;
  }
}

/* L'element signature : le V se remplit au fil de la descente et sert de
   barre de progression. Pose au centre bas, ou il reste lisible sur
   n'importe quel plan du film, plutot qu'a droite ou il traversait des
   facades et des fenetres. Reste un simple V qui se trace : pas de forme
   ajoutee qui viendrait se confondre avec le vrai logo du sac a l'arrivee. */
.hero-v{
  position:absolute;left:50%;bottom:clamp(64px,11vh,120px);transform:translateX(-50%);
  width:clamp(88px,8.5vw,136px);z-index:2;pointer-events:none;
}
.hero-v svg{width:100%;height:auto;overflow:visible}
.hero-v .trace{
  fill:none;stroke:var(--accent);stroke-width:6;stroke-linecap:square;stroke-linejoin:miter;
  stroke-dasharray:var(--len,340);
  stroke-dashoffset:calc(var(--len,340) * (1 - var(--hp,0)));
  opacity:.92;
  filter:drop-shadow(0 2px 14px rgba(168,85,247,.4));
}
/* Le V vit aussi sur telephone : c'est le seul repere de progression pendant
   la descente, et il s'efface tout seul quand le bloc d'arrivee prend sa
   place (opacite pilotee par --settle plus haut). Pose plus bas que sur
   ordinateur pour rester dans le tiers bas de l'ecran. */
@media (max-width:900px){
  .hero-v{bottom:13vh;width:clamp(74px,21vw,104px)}
}
/* Un ecran court en paysage n'a la place de rien : le V y disparait. */
@media (max-height:560px){.hero-v,.hero__status{display:none}}

/* ==========================================================================
   5. Le hero statique : une mise en page dessinee, pas un repli d'excuse.
   Essai du 01/09 : la video tourne maintenant aussi sur telephone, donc ce
   bloc ne se declenche plus que pour le mouvement reduit, un vrai besoin
   d'accessibilite. Les quatre portes tactiles/etroites d'origine ont ete
   retirees d'ici (CSS n'a pas de commentaire de ligne pour les garder en
   place proprement) mais restent en commentaire dans le GATES de app.js :
   pour revenir en arriere, les deux fichiers doivent toujours s'accorder.
   ========================================================================== */

@media (prefers-reduced-motion:reduce){
  .hero{height:auto}
  /* Plus de course, donc plus de rideau : sans ca la marge negative
     remonterait la section par-dessus le contenu du hero statique. */
  .who{margin-top:0;box-shadow:none}
  .hero-stage{position:relative;height:auto;min-height:88svh;display:flex;align-items:flex-end}
  .hero-poster{background-image:url('../img/hero-still.jpg')}
  #hero-video,.ring,.hero-v{display:none}
  .bands{position:relative;inset:auto;width:100%;padding:0 var(--gutter) clamp(48px,9vh,90px)}
  /* Les bandes de descente n ont pas de sens sans scroll : seul le bloc
     d arrivee est montre, entierement ouvert. Il n y a plus de balisage
     statique duplique, c est le meme bloc que sur les ecrans qui scrubbent. */
  .band{display:none}
  .band--settle{
    display:block;position:relative;left:auto;top:auto;bottom:auto;transform:none;
    opacity:1;visibility:visible;width:100%;
  }
  .band--settle .hud,
  .band--settle .settle__title .w,
  .band--settle .settle__sub,
  .band--settle .settle__cta,
  .band--settle .settle__trust{opacity:1;transform:none}
  .settle-veil{opacity:.72;background:linear-gradient(0deg,rgba(4,4,9,.94) 0%,rgba(4,4,9,.72) 46%,rgba(4,4,9,.15) 100%)}
  .scrollcue{display:none}
}

/* ==========================================================================
   6. Les sections de l'accueil
   Deux sections voisines ne partagent jamais la meme ossature.
   ========================================================================== */

/* ==========================================================================
   QUI ON EST : l'ecran scinde
   Carte sombre a gauche, panneau clair a droite. C'est le seul endroit clair
   du site, et c'est voulu : apres un hero entierement noir, ce contraste est
   ce qui fait respirer la page et donne son poids au discours de confiance.
   Les couleurs claires sont declarees ici, en local, et jamais dans les
   jetons globaux : rien d'autre sur le site ne doit s'eclaircir par erreur.
   ========================================================================== */
.who{
  --paper:#F2EFE9;
  --ink:#111116;
  --ink-soft:#3A3A44;
  --ink-line:rgba(17,17,22,.14);
  padding:0;                       /* la regle generique section{padding-block} ne s'applique pas ici */
  display:grid;
  /* minmax(0,1fr) et non 1fr : un simple 1fr ne descend jamais sous la largeur
     minimale de son contenu, et le panneau de droite, plus dense, volait alors
     une centaine de pixels a la carte. Les deux moities etaient inegales. */
  grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  align-items:stretch;
  min-height:100svh;               /* la section prend tout l'ecran */
  background:var(--paper);         /* evite tout liseré sombre au raccord */

  /* Le rideau. La marge negative fait demarrer la section un ecran avant la
     fin du hero : pendant ce dernier ecran de scroll, la scene reste epinglee
     derriere et c'est la section qui monte par-dessus. Au moment precis ou le
     hero se termine, elle couvre exactement l'ecran, donc aucun saut.
     position:relative et z-index : sans eux elle passerait DERRIERE la scene
     collante au lieu de la recouvrir. */
  position:relative;
  z-index:2;
  margin-top:calc(var(--curtain) * -1);
  box-shadow:0 -26px 60px rgba(0,0,0,.55);
}

.who__media{
  position:relative;overflow:hidden;
  background-image:url("../img/carte-center-city.jpg");
  background-size:cover;
  /* 50% et non 58% : la couche animee par-dessus est un SVG, dont le
     recadrage "slice" ne sait se caler qu'au centre. Les deux doivent
     partager exactement le meme cadrage, sinon les points quittent les
     traits des que la largeur du cadre change. */
  background-position:50% 50%;
  background-color:#05050A;
  min-height:340px;
}

/* --- Les points qui circulent sur les avenues ------------------------------
   Ils partent du point de Center City vers l'exterieur : ce qui sort, ce sont
   les commandes. Trajets releves sur l'image a la grille, en coordonnees de
   son propre viewBox, donc ils suivent de vrais traits violets. */
.who__pulse{position:absolute;inset:0;width:100%;height:100%;pointer-events:none}
.who__spark{
  fill:#fff;
  filter:drop-shadow(0 0 5px rgba(168,85,247,.95)) drop-shadow(0 0 13px rgba(126,34,206,.8));
}
@keyframes spark{
  0%{offset-distance:0%;opacity:0}
  10%{opacity:1}
  82%{opacity:1}
  100%{offset-distance:100%;opacity:0}
}
/* Les quatre trajets ne sont pas dessines a l'oeil : le point central a ete
   localise par recherche du pixel le plus lumineux (815,415), puis la
   luminosite a ete sondee le long de rayons pour trouver les avenues, et
   chaque segment retenu est le plus long passage continument eclaire de son
   avenue. Une estimation a vue placait le centre 40px trop a droite et les
   points tombaient a cote des traits. */
.who__spark--a{offset-path:path("M835,375 L957,137");animation:spark 6.5s linear infinite}
.who__spark--b{offset-path:path("M800,372 L738,191");animation:spark 8.2s linear infinite 1.4s}
.who__spark--c{offset-path:path("M826,459 L869,633");animation:spark 9s linear infinite 3.1s}
.who__spark--d{offset-path:path("M773,430 L623,485");animation:spark 7.4s linear infinite 4.6s}

@media (prefers-reduced-motion:reduce){
  .who__pulse{display:none}
}

.who__panel{
  background:var(--paper);
  color:var(--ink);
  display:flex;align-items:center;
}
.who__inner{
  width:100%;
  padding:clamp(42px,5.4vw,78px) clamp(24px,3.4vw,52px);
}

.who__kicker{
  display:flex;align-items:center;gap:.6rem;
  font-family:var(--font-mono);font-size:.74rem;font-weight:500;
  letter-spacing:.2em;text-transform:uppercase;
  color:var(--accent);
  margin-bottom:clamp(26px,3.8vw,46px);
}
.who__dot{width:6px;height:6px;border-radius:50%;background:var(--accent);flex:none}

/* Deux colonnes : le discours a gauche, les preuves a droite, separees par un
   filet. Elles s'empilent des que la place manque. */
.who__cols{
  display:grid;gap:clamp(26px,3.4vw,48px);
  grid-template-columns:1fr;
}
/* La colonne du discours prend un peu plus que celle des preuves : le titre
   est en gros corps et se coupait en trois lignes a parts egales. Mesure :
   "PHILLY'S TRUSTED" demande 291px, la colonne en offre 320. */
@media (min-width:1180px){
  .who__cols{grid-template-columns:1.15fr .85fr}
  .who__facts{border-left:1px solid var(--ink-line);padding-left:clamp(22px,2.2vw,38px)}
}

.who__title{
  font-family:var(--font-display);font-weight:800;
  font-size:clamp(1.7rem,2.45vw,2.3rem);
  line-height:1.05;letter-spacing:-.025em;text-transform:uppercase;
  text-wrap:balance;
  color:var(--ink);margin:0;
}
.who__title em{font-style:normal;color:var(--accent);display:block}
/* Le petit filet sous le titre, comme dans le hero. */
.who__title::after{
  content:"";display:block;width:40px;height:2px;
  background:var(--ink);opacity:.55;margin:1.6rem 0 1.7rem;
}
.who__lede{
  color:var(--ink-soft);
  font-size:clamp(1rem,1.15vw,1.14rem);
  line-height:1.72;margin:0;max-width:44ch;
}

/* Les quatre preuves : icone en contour, titre, deux lignes. */
.who__facts{list-style:none;margin:0;padding:0;display:grid;gap:clamp(24px,2.8vw,36px)}
.who__facts li{display:grid;grid-template-columns:auto 1fr;gap:clamp(14px,1.4vw,20px);align-items:start}
.who__ico{color:var(--accent);flex:none;display:block}
.who__ico svg{width:36px;height:36px;display:block}
.who__facts h3{
  font-family:var(--font-body);font-weight:600;
  font-size:1.02rem;letter-spacing:.01em;text-transform:uppercase;
  color:var(--ink);margin:0 0 .35rem;
}
.who__facts p{color:var(--ink-soft);font-size:.96rem;line-height:1.58;margin:0;max-width:30ch}

/* La ligne du bas, posee sur un filet qui traverse le panneau. */
.who__foot{
  margin:clamp(30px,4vw,54px) 0 0;
  padding-top:clamp(18px,2.2vw,28px);
  border-top:1px solid var(--ink-line);
  font-family:var(--font-mono);font-size:.76rem;
  letter-spacing:.14em;text-transform:uppercase;
  color:var(--ink);text-align:center;
}
.who__foot span{color:var(--accent)}
/* L adresse du point de retrait. Elle vit sur le panneau CLAIR, donc elle
   prend l encre du panneau et non le violet, qui y perd trop de contraste.
   Souligne permanent : c est un lien, il doit se voir comme tel. */
.who__map{
  color:var(--ink);
  text-decoration:underline;
  text-decoration-color:rgba(168,85,247,.6);
  text-decoration-thickness:1px;
  text-underline-offset:3px;
  transition:color var(--dur) var(--ease), text-decoration-color var(--dur) var(--ease);
}
.who__map:hover{color:var(--accent);text-decoration-color:var(--accent)}
.who__map:focus-visible{outline:2px solid var(--accent);outline-offset:3px}

/* Sous 900px l'ecran ne se scinde plus : la carte passe au-dessus du texte,
   sinon chaque colonne devient trop etroite pour son contenu. */
@media (max-width:900px){
  .who{grid-template-columns:1fr;min-height:0}
  /* La carte disparait des que la section passe en colonne. Empilee, elle
     devient le premier ecran qui monte en rideau et repousse le texte d'un
     ecran entier : le visiteur voit une image avant de savoir ou il est.
     C'est le panneau creme qui doit monter en premier. Demande de Lucas,
     telephone et petite tablette uniquement, l'ecran scinde reste intact
     au-dessus de 900px. */
  .who__media{display:none}
  /* Consequence directe du retrait de la carte : le panneau devient le premier
     ecran de la section, donc son sommet tombe pile sous la barre de navigation
     et sous le filet du bandeau, tous deux fixes. Mesure a 390px : navigation
     0..76, bandeau 76..112, alors que le sur-titre demarrait a 41. On degage
     donc le haut du panneau au-dela de 112, marge de respiration comprise.
     C'est la carte qui absorbait ce recouvrement jusqu'ici. */
  .who__inner{padding-top:140px}
}

/* ==========================================================================
   LES PRODUITS : le presentoir defilant
   Le defilement est un vrai scroll horizontal avec accroche. Ce n'est pas un
   detail : le doigt, le pave tactile et le clavier fonctionnent sans une
   ligne de code, et les fleches ne font que le piloter. Un carrousel pilote
   uniquement en JavaScript aurait fallu tout reecrire pour le tactile.
   Le script n'ecrit que deux nombres par carte, --d (distance au centre) et
   --s (le meme, signe). Toute la mise en scene est faite ici, en transform
   et en opacite, donc reversible et sans recalcul de mise en page.
   ========================================================================== */
.shelf{overflow:hidden}
.shelf__head{
  display:grid;gap:clamp(18px,2.6vw,40px);
  align-items:end;
  grid-template-columns:1fr;
  margin-bottom:clamp(32px,4.6vw,64px);
}
@media (min-width:900px){
  .shelf__head{grid-template-columns:1.3fr .7fr}
}
.shelf__kicker{
  display:flex;align-items:center;gap:.6rem;
  font-family:var(--font-mono);font-size:.74rem;font-weight:500;
  letter-spacing:.2em;text-transform:uppercase;color:var(--accent);
  margin-bottom:1.1rem;
}
.shelf__dot{width:6px;height:6px;border-radius:50%;background:var(--accent);flex:none}
.shelf__title{
  font-family:var(--font-display);font-weight:800;
  font-size:clamp(1.9rem,3.6vw,3.4rem);
  line-height:1.04;letter-spacing:-.03em;text-transform:uppercase;margin:0;
}
.shelf__title em{font-style:normal;color:var(--accent)}
.shelf__lede{
  color:var(--text-secondary);margin:0;
  font-size:clamp(.98rem,1.1vw,1.1rem);line-height:1.65;max-width:38ch;
}

/* --- la scene et les fleches --- */
/* PAS de display:flex ici, et c'est deliberé.
   La piste etait un ELEMENT FLEXIBLE portant a la fois overflow-x:auto et un
   remplissage en POURCENTAGE, calc(50% - var(--card-w)/2). Cette combinaison
   est le cas ou Safari se trompe : la taille de base de l'element flexible se
   calcule en incluant un remplissage dont le pourcentage n'est pas encore
   resolu, et la piste ressortait a environ 170px au lieu de 390. La carte,
   large de 250px, debordait alors des DEUX cotes, ce qui coupait a la fois
   "BEST SELLER" a gauche et le ".00" du prix a droite, symptome releve au
   pixel sur la capture de Lucas.
   Ce conteneur flexible ne servait a rien : les fleches sont en position
   absolue et n'ont jamais eu besoin de lui, et align-items:center n'agissait
   que sur un axe vertical sans effet. En bloc, la piste prend simplement
   toute la largeur et le pourcentage se resout contre une valeur certaine. */
.shelf__stage{position:relative}
.shelf__nav{
  position:absolute;top:50%;transform:translateY(-50%);z-index:5;
  width:46px;height:46px;flex:none;
  display:flex;align-items:center;justify-content:center;
  background:rgba(10,8,20,.5);backdrop-filter:blur(8px);
  border:1px solid rgba(168,85,247,.42);border-radius:12px;
  color:var(--text-primary);cursor:pointer;
  transition:background var(--dur) var(--ease),border-color var(--dur) var(--ease),opacity var(--dur) var(--ease);
}
.shelf__nav svg{width:20px;height:20px}
.shelf__nav:hover{background:rgba(168,85,247,.24);border-color:var(--accent)}
.shelf__nav[disabled]{opacity:.25;pointer-events:none}
/* Une piste qui n'a qu'UNE carte cache ses fleches, le script pose l'attribut.
   Sans cette regle le display:flex ci-dessus battrait l'attribut hidden. */
.shelf__nav[hidden]{display:none}
.shelf__nav--prev{left:clamp(8px,2vw,34px)}
.shelf__nav--next{right:clamp(8px,2vw,34px)}

/* --- la piste --- */
/* Le remplissage lateral vaut la moitie de la piste moins la moitie d'une
   carte : c'est ce qui permet a la PREMIERE et a la DERNIERE carte de venir
   se centrer. Sans lui, elles restent collees au bord. */
/* Cartes plus larges et ecart plus genereux : on en voit trois plutot que
   cinq, ce qui laisse respirer sans perdre l'annonce des suivantes. */
.shelf__track{
  --card-w:clamp(240px,26vw,382px);
  /* Le rapport EXACT des photos produit (941x1672). La carte prend la forme
     de l'image, donc rien n'est recadre. A refaire si les photos changent. */
  --card-ar:941/1672;
  list-style:none;margin:0;
  /* Largeur explicite : la piste n'est plus dimensionnee par un parent
     flexible, elle remplit son bloc. border-box est global, le remplissage
     reste donc a l'interieur des 100%. */
  width:100%;
  display:flex;align-items:center;
  /* Ecart calcule pour que trois cartes remplissent l'ecran : au-dela, il ne
     reste des suivantes qu'un liseré, juste de quoi annoncer qu'elles sont
     la sans en faire une quatrieme et une cinquieme. */
  gap:clamp(18px,5.6vw,88px);
  overflow-x:auto;overflow-y:hidden;
  scroll-snap-type:x mandatory;
  padding:clamp(26px,3.4vw,52px) calc(50% - var(--card-w)/2);
  scrollbar-width:none;-ms-overflow-style:none;
  overscroll-behavior-x:contain;
}
.shelf__track::-webkit-scrollbar{display:none}
.shelf__track:focus-visible{outline:2px solid var(--accent);outline-offset:-4px;border-radius:16px}

.shelf__card{
  flex:0 0 var(--card-w);
  scroll-snap-align:center;
  /* --d : distance au centre, 0 pour la carte centree. --s : la meme, signee.
     Le rapprochement lateral cree le chevauchement du modele. */
  /* Le rapprochement lateral est devenu un ECARTEMENT : les voisines
     s'eloignent au lieu de se chevaucher, ce qui aere la rangee. */
  transform:
    translateX(calc(var(--s,0) * 10px))
    scale(calc(1 - .13 * var(--d,0)));
  /* Attenuation mesuree pour que la deuxieme carte reste lisible : plus fort,
     les voisines devenaient de simples taches sombres et on ne voyait plus
     "les cartes qui arrivent". */
  opacity:calc(1 - .26 * var(--d,0));
  filter:brightness(calc(1 - .1 * var(--d,0)));
  /* Transition longue et sur la courbe lente du site : c'est elle qui donne
     le moelleux au changement de produit. */
  transition:transform .8s var(--ease-slow),opacity .8s var(--ease-slow),filter .8s var(--ease-slow);
}
/* La carte EST la photo : l'image occupe le cadre entier, bord a bord, et le
   texte se pose par-dessus dans le bas. C'est ce qui distingue une vraie
   carte produit d'une vignette posee sur un panneau.
   Le rapport de la carte vaut EXACTEMENT celui des photos (941/1672), donc
   `cover` n'a rien a couper : le cadrage decide dans le fichier est celui
   qu'on voit. Changer ce rapport sans refaire les photos les recadrerait. */
.shelf__card a{
  display:block;position:relative;overflow:hidden;
  aspect-ratio:var(--card-ar);
  padding:0;
  border:1px solid var(--line-soft);border-radius:18px;
  /* Fond de secours : il ne se voit que le temps que la photo arrive, et
     derriere les photos qui ne rempliraient pas tout. */
  background:
    radial-gradient(ellipse 120% 70% at 50% 18%,color-mix(in srgb,var(--tone) 16%,transparent),transparent 70%),
    linear-gradient(180deg,#14121C 0%,#0B0A11 100%);
  /* La transformation de survol vit sur le lien, pas sur la carte : celle-ci
     porte deja celle du carrousel, et les deux se seraient ecrasees. */
  transition:
    border-color .55s var(--ease-slow),
    transform .55s var(--ease-slow),
    box-shadow .55s var(--ease-slow);
}
/* Au survol la carte se souleve et se detache du fond, avec une lueur a la
   couleur du parfum. Elle ne change pas de bordure seulement : elle sort. */
.shelf__card a:hover,
.shelf__card a:focus-visible{
  transform:translateY(-10px) scale(1.045);
  border-color:color-mix(in srgb,var(--tone) 55%,transparent);
  box-shadow:
    0 26px 60px rgba(0,0,0,.6),
    0 0 40px color-mix(in srgb,var(--tone) 22%,transparent);
}

/* La photo, en pleine carte. Plus de masque en degrade : il servait a fondre
   le rectangle de la photo dans le panneau, et il n'y a plus de panneau.
   min-height:0 et 100%x100% restent obligatoires, sinon la taille intrinseque
   du fichier l'emporte sur l'aspect-ratio du cadre (piege deja paye). */
.shelf__img{
  position:absolute;inset:0;z-index:0;
  width:100%;height:100%;min-height:0;
  object-fit:cover;object-position:50% 50%;
  /* Un rien de zoom au survol : la photo respire avec la carte. */
  transition:transform .8s var(--ease-slow);
}
.shelf__card a:hover .shelf__img{transform:scale(1.04)}

/* La pastille se pose SUR la photo : sans z-index elle passait dessous. */
.shelf__flag{
  position:absolute;top:14px;left:14px;z-index:3;
  font-family:var(--font-mono);font-size:.58rem;letter-spacing:.16em;
  text-transform:uppercase;color:var(--accent);
  border:1px solid rgba(168,85,247,.5);border-radius:20px;
  padding:.34rem .7rem;background:rgba(10,8,20,.62);
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
}

/* Le bloc de texte, pose sur le bas de la photo.
   Le voile est LEGER a dessein : la zone basse des photos est deja tres
   sombre (moyenne mesuree Y=25, pire pixel Y=114), donc du blanc y passe
   4,8:1 sans aucun voile. Un voile lourd aurait efface la reflexion au sol,
   qui fait la moitie de l'interet de ces photos. */
.shelf__meta{
  position:absolute;left:0;right:0;bottom:0;z-index:2;
  display:flex;flex-direction:column;
  padding:clamp(48px,6.5vw,74px) clamp(14px,1.5vw,20px) clamp(14px,1.5vw,20px);
  background:linear-gradient(180deg,
    transparent 0%,
    rgba(8,8,11,.22) 20%,
    rgba(8,8,11,.60) 40%,
    rgba(8,8,11,.85) 64%,
    rgba(8,8,11,.95) 100%);
}
/* Nom a gauche, prix a droite, sur la meme ligne de base : la lecture se
   fait d'un coup d'oeil et le bloc reste bas. */
.shelf__row{
  display:flex;align-items:baseline;justify-content:space-between;gap:.6rem;
}
.shelf__name{
  font-family:var(--font-display);font-weight:700;
  font-size:clamp(.94rem,1.15vw,1.14rem);letter-spacing:-.01em;
  text-transform:uppercase;color:var(--text-primary);
  text-shadow:0 1px 10px rgba(0,0,0,.92);
}
/* min-height : le RAZ n'affiche aucun parfum sur son etui, sa ligne est donc
   vide. Sans hauteur reservee, sa carte remontait et les trois ne
   s'alignaient plus. */
.shelf__flavour{
  font-family:var(--font-mono);font-size:.68rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--tone);margin-top:.34rem;
  min-height:1.1em;
  text-shadow:0 1px 10px rgba(0,0,0,.8);
}
.shelf__price{
  font-family:var(--font-mono);font-size:.92rem;
  color:var(--text-primary);flex:none;
  font-variant-numeric:tabular-nums;
  text-shadow:0 1px 10px rgba(0,0,0,.92);
}
/* Le bouton prend toute la largeur du bloc : sur une photo pleine carte, un
   pave centre flottait sans point d'accroche. */
.shelf__go{
  display:flex;align-items:center;justify-content:center;gap:.5rem;
  margin-top:clamp(12px,1.3vw,18px);
  font-family:var(--font-mono);font-size:.64rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--text-primary);
  border:1px solid rgba(168,85,247,.5);border-radius:24px;
  padding:.62rem 1rem;
  background:rgba(10,8,20,.42);
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
  transition:background var(--dur) var(--ease),border-color var(--dur) var(--ease);
}
.shelf__go svg{width:15px;height:15px;transition:transform var(--dur) var(--ease)}
.shelf__card a:hover .shelf__go{background:rgba(168,85,247,.30);border-color:var(--accent)}
.shelf__card a:hover .shelf__go svg{transform:translateX(3px)}

/* --- la pagination --- */
.shelf__dots{
  display:flex;justify-content:center;gap:.5rem;
  margin-top:clamp(18px,2.4vw,30px);
}
/* Meme raison que les fleches : un point unique annonce une suite qui
   n'existe pas. Le script pose hidden des que la piste n'a qu'une carte. */
.shelf__dots[hidden]{display:none}
.shelf__dots i{
  width:6px;height:6px;border-radius:50%;
  background:var(--line);transition:background var(--dur) var(--ease),width var(--dur) var(--ease);
}
.shelf__dots i.is-on{background:var(--accent);width:20px;border-radius:4px}

/* --- les marques ---
   Le grand ecran met le libelle et les QUATRE marques sur une seule ligne.
   La grille disait repeat(3,1fr) et datait des trois marques du depart :
   la quatrieme, Lost Mary, tombait donc seule sur une deuxieme ligne depuis
   le 08/09/2026. Corrige le 08/09/2026 au soir, a la demande de Lucas.

   Le libelle "View all" a ete retire des pastilles, et c'est MESURE : avec
   lui, meme en 1440px de large, la pastille ne laisse que 174px au nom et
   "GEEK BAR" comme "LOST MARY" passaient sur deux lignes, ce qui rendait
   deux pastilles sur quatre plus hautes que les autres (100px contre 73).
   Quatre fois le meme "View all" etait de toute facon une redite du libelle
   de la rangee ; la fleche reste, elle dit la meme chose sans le poids.

   Sous 960px la grille laisse la place a une bande qui defile lateralement.
   Ce seuil est mesure aussi : sous lui les noms recommencent a passer sur
   deux lignes, et sur un ecran de 390px quatre pastilles alignees
   tomberaient a 85px de large, trop court pour "Lost Mary". Le geste lateral
   est deja la langue du site (le presentoir, le processus, le catalogue), et
   il garde les pastilles a leur taille lisible. */
.shelf__brands{
  display:grid;gap:clamp(12px,1.4vw,20px);
  grid-template-columns:auto repeat(4,minmax(0,1fr));align-items:center;
  margin-top:clamp(38px,5vw,72px);
}
@media (max-width:959.98px){
  .shelf__brands{
    display:flex;align-items:center;flex-wrap:nowrap;
    /* PAS d'accroche (scroll-snap) sur cette bande, et c'est mesure : avec
       elle, le navigateur cale la bande sur la premiere pastille des le
       chargement (scrollLeft a 53px releve en 390px de large) et le libelle
       "Browse by brand" arrivait deja coupe. Quatre pastilles courtes se
       parcourent tres bien au doigt libre. */
    overflow-x:auto;
    /* Obligatoire, pas cosmetique : sans lui un glissement en butee
       declenche le retour arriere du navigateur sur iOS, et le visiteur
       quitte la page en croyant feuilleter. Meme piege que .proc__view. */
    overscroll-behavior-x:contain;
    -webkit-overflow-scrolling:touch;
    scrollbar-width:none;
    /* La bande deborde volontairement dans la gouttiere : la derniere
       pastille coupee par le bord annonce qu'il en reste. */
    margin-inline:calc(var(--gutter) * -1);
    padding-inline:var(--gutter);
  }
  .shelf__brands::-webkit-scrollbar{display:none}
  .shelf__brands-lab{flex:none}
  .shelf__brand{flex:0 0 auto}
}
.shelf__brands-lab{
  font-family:var(--font-mono);font-size:.68rem;letter-spacing:.18em;
  text-transform:uppercase;color:var(--text-faint);padding-right:1rem;
}
.shelf__brand{
  display:flex;align-items:center;justify-content:space-between;gap:1rem;
  padding:clamp(14px,1.5vw,22px) clamp(16px,1.6vw,24px);
  border:1px solid var(--line-soft);border-radius:14px;
  background:var(--panel);
  transition:border-color var(--dur) var(--ease),background var(--dur) var(--ease);
}
/* Le mot est dans le HTML pour les lecteurs d'ecran (une fleche seule ne dit
   rien a la voix), il n'est pas peint a l'ecran. Voir la note plus haut. */
.shelf__brand-go-lab{
  position:absolute;width:1px;height:1px;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap;
}
.shelf__brand{gap:.7rem}
.shelf__brand:hover{border-color:rgba(168,85,247,.45);background:var(--panel-raised)}
.shelf__brand.is-on{border-color:rgba(168,85,247,.5);background:rgba(168,85,247,.08)}
.shelf__brand-name{
  font-family:var(--font-display);font-weight:700;
  font-size:clamp(1rem,1.2vw,1.2rem);letter-spacing:.02em;text-transform:uppercase;
}
.shelf__brand-go{
  display:inline-flex;align-items:center;gap:.5rem;flex:none;
  font-family:var(--font-mono);font-size:.64rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--accent);
}
.shelf__brand-go svg{width:14px;height:14px;transition:transform var(--dur) var(--ease)}
.shelf__brand:hover .shelf__brand-go svg{transform:translateX(3px)}

/* Sur telephone les fleches n'ont pas leur place : le doigt fait deja le
   travail, et elles mangeraient la largeur des cartes. */
@media (max-width:720px){
  .shelf__nav{display:none}

  /* Le liseré des cartes voisines, mesure et corrige.
     Aux valeurs de bureau il ne restait que 34px de voisine visible, a 81%
     d'opacite et assombrie : sur un fond quasi noir, invisible, et le
     presentoir se lisait comme une carte unique sans rien a faire defiler.
     Trois choses le mangeaient, et les trois sont reduites ici : l'ecart de
     22px, le rapprochement lateral de 10px, et surtout le retrecissement de
     13% qui eloigne le bord de la voisine du bord de l'ecran. */
  .shelf__track{
    --card-w:clamp(210px,64vw,300px);
    gap:10px;
    /* 50vw et non 50%, et c'est le coeur du correctif telephone.
       Un pourcentage se resout contre la largeur du parent, qui n'est pas une
       valeur certaine tant que la mise en page n'est pas finie. Sur mobile
       WebKit, Safari comme Chrome, la piste ressortait a environ 160px au
       lieu de 390 : la carte de 250px debordait des deux cotes, coupant
       "BEST SELLER" a gauche et le ".00" du prix a droite.
       vw se resout contre la fenetre, connue des la premiere ligne de CSS,
       sans dependre d'aucun parent. Sur telephone la piste occupe toute la
       largeur, donc 50vw vaut exactement 50%, sans l'incertitude. */
    padding-left:calc(50vw - var(--card-w) / 2);
    padding-right:calc(50vw - var(--card-w) / 2);
  }
  .shelf__card{
    transform:
      translateX(calc(var(--s,0) * 3px))
      scale(calc(1 - .05 * var(--d,0)));
    opacity:calc(1 - .18 * var(--d,0));
    filter:brightness(calc(1 - .06 * var(--d,0)));
  }
}
@media (prefers-reduced-motion:reduce){
  .shelf__card{transition:none}
  .shelf__track{scroll-behavior:auto}
}

/* Les trois preuves : une grille de cartes. */
.proof__grid{display:grid;gap:clamp(14px,1.6vw,22px);grid-template-columns:repeat(auto-fit,minmax(260px,1fr));margin-top:clamp(28px,4vw,48px)}
.proof__num{font-family:var(--font-mono);font-size:.72rem;letter-spacing:.16em;color:var(--accent);display:block;margin-bottom:.9rem}
.proof__card h3{margin-bottom:.6rem}
.proof__card p{color:var(--text-secondary);margin:0;font-size:.96rem}

/* Le fonctionnement : une liste numerotee en colonne, ossature volontairement
   differente de la grille au-dessus. */
.steps{display:grid;gap:0;margin-top:clamp(28px,4vw,48px);border-top:1px solid var(--line-soft)}
.step{display:grid;grid-template-columns:auto 1fr;gap:clamp(16px,3vw,44px);align-items:baseline;padding:clamp(22px,3vw,38px) 0;border-bottom:1px solid var(--line-soft)}
.step__n{font-family:var(--font-mono);font-size:.8rem;color:var(--accent);letter-spacing:.1em}
.step h3{margin-bottom:.45rem}
.step p{color:var(--text-secondary);margin:0;max-width:56ch}

/* Le moment interactif : le rayon de quinze minutes. */
.radius{display:grid;grid-template-columns:1fr;gap:clamp(24px,4vw,56px);align-items:center}
@media (min-width:900px){.radius{grid-template-columns:1.05fr .95fr}}
.radius__map{position:relative;aspect-ratio:1;width:100%;max-width:520px;margin-inline:auto}
.radius__map svg{width:100%;height:auto;overflow:visible}
.radius__grid{stroke:var(--line);stroke-width:1;fill:none;opacity:.55}
.radius__park{fill:rgba(52,211,153,.06)}
.radius__ring{fill:var(--accent-muted);stroke:var(--accent);stroke-width:1.5;transition:r .7s var(--ease-slow),opacity .5s var(--ease)}
.radius__origin{fill:var(--accent)}
.radius__zone{fill:transparent;cursor:pointer;transition:fill var(--dur) var(--ease)}
.radius__zone:hover,.radius__zone[aria-pressed="true"]{fill:var(--accent-muted)}
.radius__readout{font-family:var(--font-mono);font-variant-numeric:tabular-nums}
.radius__min{font-family:var(--font-display);font-size:clamp(3rem,7vw,5rem);font-weight:800;line-height:1;letter-spacing:-.03em}

/* La FAQ : des details natifs, animes proprement. */
.faq{margin-top:clamp(24px,3vw,40px);border-top:1px solid var(--line-soft)}
.faq details{border-bottom:1px solid var(--line-soft)}
.faq summary{list-style:none;cursor:pointer;padding:clamp(16px,2vw,24px) 0;font-family:var(--font-display);font-weight:600;font-size:clamp(1rem,1.5vw,1.2rem);display:flex;justify-content:space-between;gap:1rem;align-items:center;transition:color var(--dur) var(--ease)}
.faq summary::-webkit-details-marker{display:none}
.faq summary:hover{color:var(--accent-hover)}
.faq summary::after{content:"+";font-family:var(--font-mono);color:var(--accent);flex:none;transition:transform var(--dur) var(--ease)}
.faq details[open] summary::after{transform:rotate(45deg)}
.faq p{color:var(--text-secondary);margin:0;padding:0 0 clamp(16px,2vw,24px);max-width:66ch}

/* L'appel a l'action final. */
.close{text-align:center}
.close h2{margin-bottom:.8rem}
.close .lede{margin-inline:auto;margin-bottom:1.8rem}
body.is-closed .close__open{display:none}
.close__closed{display:none}
body.is-closed .close__closed{display:block}

/* Le pied de page. */
.foot__grid{display:grid;gap:clamp(24px,4vw,48px);grid-template-columns:repeat(auto-fit,minmax(200px,1fr))}
.foot__grid h4{font-family:var(--font-mono);font-size:.72rem;letter-spacing:.16em;text-transform:uppercase;color:var(--text-faint);margin:0 0 .9rem;font-weight:500}
.foot__grid a{display:block;padding:.18rem 0;transition:color var(--dur) var(--ease)}
.foot__grid a:hover{color:var(--accent-hover)}
.foot__legal{margin-top:clamp(32px,5vw,56px);padding-top:clamp(20px,3vw,32px);border-top:1px solid var(--line-soft);font-size:.82rem;color:var(--text-faint);display:flex;flex-wrap:wrap;gap:.6rem 1.4rem;justify-content:space-between}

/* ==========================================================================
   7. Les pages internes
   Elles n'ont pas de video, elles ne sont pas des pages au rabais.
   Meme palette, memes courbes, meme vocabulaire d'entrees.
   ========================================================================== */

.pagehead{position:relative;overflow:hidden;padding-block:clamp(56px,9vw,110px) clamp(40px,6vw,72px)}
.pagehead__bg{
  position:absolute;inset:-12% 0 0;z-index:-1;
  background-size:cover;background-position:50% 50%;
  opacity:.30;
  will-change:transform;
}
.pagehead::after{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:linear-gradient(180deg,rgba(8,8,11,.55) 0%,rgba(8,8,11,.86) 62%,var(--canvas) 100%);
}
.pagehead h1{max-width:20ch}
.pagehead .lede{margin-top:1.2rem}
.pagehead__status{margin-top:1.6rem}

/* Deux colonnes texte, ossature reservee aux pages internes. */
.split{display:grid;gap:clamp(24px,4vw,64px);align-items:start}
@media (min-width:900px){.split{grid-template-columns:.85fr 1.15fr}}
.split h2{margin-bottom:1rem}

/* Une liste de faits, alignee sur la ligne de base. */
.facts{display:grid;gap:0;border-top:1px solid var(--line-soft)}
.facts div{display:grid;grid-template-columns:minmax(120px,.4fr) 1fr;gap:clamp(12px,2vw,32px);align-items:baseline;padding:clamp(14px,1.8vw,22px) 0;border-bottom:1px solid var(--line-soft)}
.facts dt{font-family:var(--font-mono);font-size:.76rem;letter-spacing:.12em;text-transform:uppercase;color:var(--text-faint);margin:0}
.facts dd{margin:0;color:var(--text-primary)}

/* La grille produits. */
.grid-shop{display:grid;gap:clamp(14px,1.8vw,24px);grid-template-columns:repeat(auto-fill,minmax(240px,1fr));margin-top:clamp(28px,4vw,48px)}
.item{display:flex;flex-direction:column;gap:.5rem}
.item__media{aspect-ratio:4/3;border-radius:12px;overflow:hidden;border:1px solid var(--line-soft);background:var(--panel)}
.item__media img{width:100%;height:100%;object-fit:cover}
.item__row{display:flex;justify-content:space-between;align-items:baseline;gap:1rem}
.item__price{font-family:var(--font-mono);color:var(--text-primary);font-variant-numeric:tabular-nums}
.item__meta{color:var(--text-faint);font-size:.84rem}
.item[data-out] .item__media{opacity:.4}
.item[data-out] .item__price::after{content:" · sold out";color:var(--text-faint)}

/* Le formulaire. */
.form{display:grid;gap:1.1rem;max-width:52ch;margin-top:clamp(24px,3vw,40px)}
.field{display:grid;gap:.4rem}
.field label{font-family:var(--font-mono);font-size:.74rem;letter-spacing:.12em;text-transform:uppercase;color:var(--text-faint)}
.field input,.field textarea{
  font-family:var(--font-body);font-size:1rem;color:var(--text-primary);
  background:var(--panel);border:1px solid var(--line);border-radius:10px;
  padding:.8rem .9rem;transition:border-color var(--dur) var(--ease);
}
.field input:focus,.field textarea:focus{border-color:var(--accent);outline:none}
.form__note{color:var(--text-faint);font-size:.84rem}
.form__ok{display:none;border:1px solid var(--accent);background:var(--accent-muted);border-radius:10px;padding:1rem}
.form.is-sent .form__ok{display:block}
.form.is-sent .field,.form.is-sent .btn{display:none}

/* La page 404. */
.notfound{min-height:70svh;display:flex;align-items:center;text-align:center}

/* ==========================================================================
   LE PROCESSUS : trois cartes qu on fait glisser sur le cote.
   La mecanique d origine venait du chassis de la competence : trois cartes
   empilees, une section epinglee, et quatre ecrans de scroll pour la
   traverser pendant que chaque carte montait du bas en biais. Remplacee a la
   demande de Lucas apres retour de terrain, le geste attendu par les
   visiteurs etant lateral.

   Le schema, qui tient en trois regles :
     .proc__view   piste horizontale, accroche mandatory, un ecran de haut
     .proc__slide  un cran large d exactement 100 pour cent, gouttiere incluse
     .proc__card   le visuel, sans position ni transform pilotes au scroll

   Le fond partage entre la section et ses cartes est CONSERVE. Il vient du
   piege du chassis : 100svh est la hauteur fenetre barres affichees, donc
   quand la barre d adresse s escamote la fenetre grandit. La piste ne couvre
   plus le bas, et sans ce fond partage une bande claire apparait.
   ========================================================================== */
/* Le degagement du haut n est pas de la respiration, c est de la place
   reservee : il vaut la nav fixe PLUS le filet du bandeau, qui vit sous elle
   en dessous de 1200px. L ancien inset de la carte epinglee le portait ; sans
   lui, la carte demarre trop haut et son compteur 01 / 03 passe sous la barre,
   verifie en capture sur un ecran de telephone.
   Les trois valeurs sont accordees pour que la section fasse exactement un
   ecran : dessus plus piste plus dessous vaut 100svh. La section se cale donc
   pile sous la barre quand on arrive dessus, y compris depuis le lien Process
   de la navigation. */
.proc{
  position:relative;background:var(--canvas);
  padding-top:calc(var(--nav-h) + clamp(46px,6vh,66px));
  padding-bottom:clamp(18px,3vh,34px);
}

/* La piste. Le defilement est natif, donc le doigt, le pave tactile, la barre
   d espace et les fleches marchent sans code. overscroll-behavior-x:contain
   est obligatoire, pas cosmetique : sans lui, un glissement qui arrive en
   butee sur la premiere carte declenche le retour arriere du navigateur sur
   iOS, et le visiteur quitte la page en croyant feuilleter. */
.proc__view{
  display:flex;
  overflow-x:auto;
  overflow-y:hidden;
  overscroll-behavior-x:contain;
  scroll-snap-type:x mandatory;
  height:calc(100svh - var(--nav-h) - clamp(46px,6vh,66px) - clamp(18px,3vh,34px));
  scrollbar-width:none;
  -ms-overflow-style:none;
}
.proc__view::-webkit-scrollbar{display:none}
.proc__view:focus-visible{outline:2px solid var(--accent);outline-offset:-4px;border-radius:8px}
/* Le curseur est la seule chose qui annonce le geste a la souris, la piste
   n ayant ni barre de defilement ni fleches. */
@media (hover:hover){
  .proc__view{cursor:grab}
  .proc__view.is-drag{cursor:grabbing;user-select:none}
}

/* Un cran = un ecran. La gouttiere vit sur le CRAN, jamais sur la piste : le
   padding de fin d un conteneur qui defile est ignore par plusieurs
   navigateurs, et la derniere carte se collerait au bord droit.
   L accroche est sur le bord de DEPART, pas au centre : chaque cran faisant
   exactement la largeur visible, il n y a aucun calcul de centrage a rejouer,
   donc aucun des trois pieges deja payes sur le presentoir produits. */
.proc__slide{
  flex:0 0 100%;
  scroll-snap-align:start;
  scroll-snap-stop:always;
  padding:10px var(--gutter);
  box-sizing:border-box;
}

.proc__card{
  position:relative;height:100%;
  border:1px solid rgba(168,85,247,.30);
  border-radius:clamp(16px,1.6vw,24px);
  background:
    radial-gradient(ellipse 90% 60% at 50% 0%,rgba(168,85,247,.13),transparent 62%),
    linear-gradient(180deg,#15121F 0%,#0B0A11 62%,#08080B 100%);
  box-shadow:0 -18px 60px rgba(0,0,0,.6),0 0 40px rgba(168,85,247,.05);
}

/* L'encoche en V du haut, la signature de la maquette.
   Dessinee en SVG plutot qu'en clip-path : le clip-path aurait interdit les
   coins arrondis, que la maquette porte. Le trace est rempli du fond de page
   et couvre le filet du haut, qui contourne donc le V. Sans Z final, seules
   les deux diagonales sont tracees, jamais la corde du haut. */
.proc__notch{
  position:absolute;top:-1px;left:50%;transform:translateX(-50%);
  width:clamp(72px,9vw,116px);height:clamp(22px,2.7vw,34px);
  z-index:2;pointer-events:none;overflow:visible;
}
.proc__notch path{fill:var(--canvas);stroke:rgba(168,85,247,.30);stroke-width:1.6;vector-effect:non-scaling-stroke}

.proc__in{
  position:relative;z-index:1;height:100%;
  padding:clamp(20px,3.2vh,40px) clamp(18px,3.4vw,54px) clamp(16px,2.4vh,32px);
  display:flex;flex-direction:column;
}

/* --- la ligne du haut --- */
.proc__top{
  display:flex;align-items:flex-start;justify-content:space-between;gap:1rem;
  padding-bottom:clamp(12px,1.8vh,20px);
  border-bottom:1px solid var(--line-soft);
}
.proc__count{
  font-family:var(--font-mono);font-size:clamp(.8rem,1.5vw,1.05rem);
  letter-spacing:.1em;color:var(--text-faint);font-variant-numeric:tabular-nums;
}
.proc__count b{color:var(--accent);font-weight:500;font-size:1.35em}
.proc__creed{
  display:flex;align-items:center;gap:.5em;flex-wrap:wrap;justify-content:flex-end;
  font-family:var(--font-mono);font-size:clamp(.56rem,.86vw,.7rem);
  letter-spacing:.22em;text-transform:uppercase;color:var(--text-faint);
  text-align:right;
}
.proc__creed i{width:3px;height:3px;border-radius:50%;background:currentColor;flex:none}

/* --- le corps --- */
/* justify-content:center : le bloc respire au milieu de la carte quel que
   soit l'ecran, plutot que de se coller sous la ligne du haut. */
/* Cale vers le HAUT, pas centre. Les maquettes de Lucas posent le bloc dans
   le tiers haut et laissent le vide retomber au-dessus du pied : centre, le
   texte flottait au milieu avec deux vides symetriques, ce qui n'est pas le
   meme rythme. */
.proc__body{flex:1;min-height:0;overflow:hidden;display:flex;flex-direction:column;justify-content:flex-start;gap:clamp(.5rem,1.2vh,1rem);padding-top:clamp(1rem,4vh,3rem)}
.proc__say{display:flex;flex-direction:column;gap:clamp(.5rem,1.2vh,1rem);min-width:0}
/* Au-dela de 900px la carte devient large : empilee, elle debordait par le
   bas et le pied venait se poser SUR la derniere ligne, verifie en capture.
   Deux colonnes, comme le chassis : le dire a gauche, les preuves a droite.
   La hauteur est divisee par deux et la moitie droite de la carte, vide
   jusque la, se remplit. */
@media (min-width:900px){
  .proc__body{
    display:grid;
    grid-template-columns:minmax(0,.52fr) minmax(0,.48fr);
    gap:clamp(2rem,4.5vw,6rem);
    align-items:start;
    /* Centre dans la hauteur : cale en haut, le bloc laissait 500px de vide
       sous lui sur une carte de 730px. */
    align-content:center;
    padding-top:0;
  }
  .proc__rows{margin-top:0}
}
.proc__step-lab{
  font-family:var(--font-mono);font-size:clamp(.6rem,.95vw,.78rem);
  letter-spacing:.28em;text-transform:uppercase;color:var(--text-secondary);
}
.proc__title{
  font-family:var(--font-display);font-weight:800;
  font-size:clamp(1.75rem,5.4vw,3.6rem);line-height:.98;letter-spacing:-.03em;
  text-transform:uppercase;color:var(--text-primary);margin:0;
}
.proc__title em{font-style:normal;color:var(--accent)}
.proc__lede{
  font-size:clamp(.9rem,1.35vw,1.15rem);line-height:1.5;
  color:var(--text-secondary);max-width:44ch;margin:0;
}

/* --- les trois preuves --- */
.proc__rows{list-style:none;margin:clamp(.5rem,1.6vh,1.4rem) 0 0;padding:0;display:grid;gap:clamp(.7rem,1.8vh,1.5rem)}
.proc__row{display:grid;grid-template-columns:auto 1fr;gap:clamp(.75rem,1.6vw,1.2rem);align-items:start}
.proc__ico{
  width:clamp(38px,4.4vw,58px);aspect-ratio:1;flex:none;
  display:grid;place-items:center;border-radius:50%;
  border:1px solid rgba(168,85,247,.55);color:var(--text-primary);
  background:rgba(168,85,247,.06);
}
.proc__ico svg{width:52%;height:52%}
.proc__row-txt{display:grid;gap:.18rem;min-width:0}
.proc__row-t{
  font-family:var(--font-display);font-weight:700;
  font-size:clamp(.8rem,1.15vw,1rem);text-transform:uppercase;letter-spacing:.01em;
  color:var(--text-primary);
}
.proc__row-d{font-size:clamp(.78rem,1.05vw,.95rem);line-height:1.45;color:var(--text-secondary)}

/* --- le pied --- */
.proc__foot{
  display:flex;align-items:flex-end;justify-content:space-between;gap:1rem;
  padding-top:clamp(10px,1.6vh,18px);
}
.proc__motto{
  font-family:var(--font-mono);font-size:clamp(.56rem,.84vw,.7rem);
  letter-spacing:.2em;text-transform:uppercase;color:var(--text-faint);line-height:1.7;
}
/* En ligne, pas en colonne. La colonne avait ete choisie quand ces cartes
   montaient en remontant la page : des points horizontaux miment le langage
   du carrousel qu on fait glisser au doigt, ce qui etait faux a ce moment la.
   Le geste est maintenant lateral pour de bon, donc l horizontale redit la
   verite, exactement comme .shelf__dots plus haut dans ce fichier.
   Ce ne sont plus des temoins mais des BOUTONS : la seule facon d avancer a
   la souris sans glisser, sur une page ou rien d autre ne le permet. */
.proc__dots{display:flex;align-items:center;gap:.4rem}
.proc__dots button{
  position:relative;
  width:7px;height:7px;padding:0;border:0;border-radius:50%;
  background:rgba(168,85,247,.28);cursor:pointer;
  transition:background var(--dur) var(--ease),width var(--dur) var(--ease);
}
/* La cible tactile fait 26px, la pastille en fait 7. Sans cette zone etendue
   le point est conforme a la maquette et intouchable au doigt. */
.proc__dots button::after{content:'';position:absolute;inset:-10px}
.proc__dots button.is-on{background:var(--accent);width:20px;border-radius:4px}
.proc__dots button:focus-visible{outline:2px solid var(--accent);outline-offset:3px}

/* Sur telephone la carte doit TENIR dans l'ecran : une carte plus haute que
   la fenetre demanderait un defilement interne, qui entre en conflit avec
   celui de la page. On reduit donc, on ne desactive pas. */
@media (max-width:720px){
  .proc__slide{padding:8px 14px}
  .proc__in{padding:16px 16px 14px}
  .proc__creed{display:none}
  .proc__rows{gap:.7rem}
  .proc__ico{width:34px}
  .proc__motto{font-size:.54rem;letter-spacing:.16em}
}

/* Mouvement reduit : l accroche et le glissement anime sont coupes, mais la
   piste reste une piste. Les cartes restent atteignables au doigt, au clavier
   et par les points, simplement sans trajet anime. */
@media (prefers-reduced-motion:reduce){
  .proc__view{scroll-snap-type:none;scroll-behavior:auto}
}

/* --------------------------------------------------------------------------
   LES CARTES CLAIRES : etapes 01 et 03.
   Demande de Lucas, pour alterner avec l'etape 02 restee sombre. Le creme est
   celui de la section "qui on est", et comme elle, ses jetons sont declares
   EN LOCAL sur la carte, jamais dans les jetons globaux : rien d'autre sur le
   site ne doit s'eclaircir par accident.

   Le violet du texte n'est PAS --accent. Mesure : #A855F7 sur ce creme ne
   donne que 3,4:1, ce qui passe pour un tres gros titre mais echoue sur le
   numero et les petites capitales. --accent-deep monte a 6,1:1 et sert donc
   partout ou le violet porte du texte. L'--accent d'origine reste sur ce qui
   est purement decoratif.
   -------------------------------------------------------------------------- */
.proc__card--clair{
  --paper:#F2EFE9;
  --ink:#111116;
  --ink-soft:#3A3A44;
  --ink-line:rgba(17,17,22,.14);
  --violet-lisible:#7E22CE;
  border-color:rgba(17,17,22,.16);
  background:
    radial-gradient(ellipse 90% 60% at 50% 0%,rgba(126,34,206,.08),transparent 62%),
    linear-gradient(180deg,#F7F4EE 0%,var(--paper) 58%,#EAE6DE 100%);
  box-shadow:0 -18px 60px rgba(0,0,0,.5),0 0 40px rgba(126,34,206,.06);
}
/* L'encoche reste remplie du fond de PAGE : c'est une decoupe, elle montre ce
   qu'il y a derriere la carte, pas la carte elle-meme. Seul le filet suit. */
.proc__card--clair .proc__notch path{stroke:rgba(17,17,22,.16)}

.proc__card--clair .proc__top{border-bottom-color:var(--ink-line)}
.proc__card--clair .proc__count{color:rgba(17,17,22,.42)}
.proc__card--clair .proc__count b{color:var(--violet-lisible)}
.proc__card--clair .proc__creed{color:rgba(17,17,22,.45)}
.proc__card--clair .proc__step-lab{color:var(--ink-soft)}
.proc__card--clair .proc__title{color:var(--ink)}
.proc__card--clair .proc__title em{color:var(--violet-lisible)}
.proc__card--clair .proc__lede{color:var(--ink-soft)}
.proc__card--clair .proc__ico{
  border-color:rgba(126,34,206,.45);
  background:rgba(126,34,206,.07);
  color:var(--ink);
}
.proc__card--clair .proc__row-t{color:var(--ink)}
.proc__card--clair .proc__row-d{color:var(--ink-soft)}
.proc__card--clair .proc__motto{color:rgba(17,17,22,.45)}
.proc__card--clair .proc__dots button{background:rgba(17,17,22,.18)}
.proc__card--clair .proc__dots button.is-on{background:var(--violet-lisible)}

/* --------------------------------------------------------------------------
   LE PANNEAU DE SUIVI DE COMMANDE, en pleine largeur.
   Il occupe la bande vide au-dessus du pied, ou la carte paraissait creuse
   sur grand ecran. Premiere version posee dans la colonne de gauche : elle
   debordait de 44px sous le pied et se faisait rogner par l'overflow du
   corps, mesure au navigateur. Le rendre pleine largeur resout les deux
   problemes d'un coup, il devient une bande horizontale basse au lieu d'un
   bloc haut, et c'est aussi ce que demandait la maquette.

   Ecrit en HTML plutot que genere en image, et ce n'est pas un raccourci :
   le dessin demande est fait presque entierement de texte, or les lois de
   generation l'interdisent parce qu'un modele ecorche systematiquement le
   texte et les controles d'interface. Ici le texte est net a toutes les
   tailles, il coute zero credit, et il fait deux choses qu'une image ne peut
   pas faire : suivre la couleur de la carte, et AVANCER avec l'etape. C'est
   la meme commande suivie de bout en bout, #0248.

   Masque sous 900px : la carte y est deja pleine, et ce rendu-la est valide.
   -------------------------------------------------------------------------- */
.proc__panel{display:none}

@media (min-width:900px){
  .proc__panel{
    --p-line:rgba(255,255,255,.12);
    --p-strong:var(--text-primary);
    --p-mute:var(--text-faint);
    --p-live:var(--accent);

    display:block;position:relative;overflow:hidden;
    margin-top:clamp(1rem,2.4vh,2.2rem);
    /* Sans cette marge, le filet bas du panneau et celui du pied se collent
       et se lisent comme un seul trait epais. */
    margin-bottom:clamp(.7rem,1.4vh,1.2rem);
    border:1px solid var(--p-line);border-radius:14px;
    background:rgba(255,255,255,.022);
    -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
  }
  /* La trame de rues, au niveau du murmure : une matiere de fond, jamais un
     dessin. Deux opacites, parce que ce violet ressort deux fois plus sur le
     creme que sur le noir. */
  .proc__plan{position:absolute;inset:0;width:100%;height:100%;color:var(--p-live);opacity:.09;pointer-events:none}

  /* Trois zones sur une seule ligne : identite, avancement, informations.
     Les filets verticaux les separent, comme sur un vrai tableau de bord. */
  .proc__panel-in{
    position:relative;z-index:1;
    display:grid;grid-template-columns:auto minmax(0,1fr) auto;
    align-items:center;
  }
  .proc__panel-id,.proc__panel-meta{padding:clamp(.9rem,1.5vh,1.3rem) clamp(1.1rem,1.8vw,1.6rem)}
  .proc__stages{padding:clamp(.9rem,1.5vh,1.3rem) clamp(1.4rem,2.6vw,2.6rem)}
  .proc__panel-id{display:grid;gap:.4rem}
  .proc__stages,.proc__panel-meta{border-left:1px solid var(--p-line)}

  .proc__ref,.proc__panel-lab{
    font-family:var(--font-mono);font-size:clamp(.56rem,.72vw,.68rem);
    letter-spacing:.2em;text-transform:uppercase;white-space:nowrap;
  }
  .proc__ref{color:var(--p-strong)}
  .proc__panel-lab{color:var(--p-mute)}

  /* Le trait de progression vit sur la liste, en fond, pas sur les pastilles :
     trace par-dessus, il les aurait barrees. --fill dit ou s'arrete la partie
     vive. Le degrade est cale sur les CENTRES des pastilles extremes, a un
     sixieme et cinq sixiemes, sinon le trait depasse des deux cotes. */
  .proc__stages{
    list-style:none;margin:0;
    display:grid;grid-template-columns:repeat(3,1fr);
    position:relative;
  }
  .proc__stages::before{
    content:"";position:absolute;
    left:calc(clamp(1.4rem,2.6vw,2.6rem) + 16.66%);
    right:calc(clamp(1.4rem,2.6vw,2.6rem) + 16.66%);
    top:calc(clamp(.9rem,1.5vh,1.3rem) + 6px);height:1px;
    background:linear-gradient(90deg,
      var(--p-live) 0,var(--p-live) var(--fill,0%),
      var(--p-line) var(--fill,0%),var(--p-line) 100%);
  }
  .proc__stage{display:grid;justify-items:center;gap:.45rem;position:relative}
  .proc__dot{
    width:13px;height:13px;border-radius:50%;display:grid;place-items:center;
    border:1px solid var(--p-line);background:var(--canvas);
    color:transparent;position:relative;z-index:1;
  }
  .proc__dot svg{width:8px;height:8px}
  .proc__stage.is-done .proc__dot{border-color:var(--p-live);color:var(--p-live)}
  .proc__stage.is-live .proc__dot{border-color:var(--p-live);background:var(--p-live)}
  .proc__stage.is-live .proc__dot::after{
    content:"";position:absolute;inset:-5px;border-radius:50%;
    border:1px solid var(--p-live);opacity:.5;
    animation:proc-pulse 2.4s var(--ease-slow) infinite;
  }
  .proc__stage-lab{
    font-family:var(--font-mono);font-size:clamp(.52rem,.68vw,.64rem);
    letter-spacing:.18em;text-transform:uppercase;color:var(--p-mute);white-space:nowrap;
  }
  .proc__stage.is-live .proc__stage-lab{color:var(--p-live)}
  .proc__stage.is-done .proc__stage-lab{color:var(--p-strong)}

  .proc__panel-meta{display:flex;align-items:flex-start;gap:clamp(1.4rem,2.6vw,2.8rem)}
  .proc__meta-b{display:grid;gap:.28rem}
  .proc__meta-b i{
    font-style:normal;font-family:var(--font-mono);
    font-size:clamp(.52rem,.68vw,.64rem);letter-spacing:.2em;
    text-transform:uppercase;color:var(--p-mute);white-space:nowrap;
  }
  .proc__meta-b b{
    font-family:var(--font-display);font-weight:700;
    font-size:clamp(.85rem,1.1vw,1.02rem);line-height:1.2;
    letter-spacing:-.01em;color:var(--p-strong);white-space:nowrap;
  }
  .proc__meta-b:first-child b{color:var(--p-live)}

  .proc__title{font-size:clamp(1.75rem,4.4vw,3.15rem)}
}

/* Sur carte creme le panneau reste SOMBRE, a la demande de Lucas : en clair
   sur clair il ne se detachait pas. Il ne reprend donc AUCUN jeton d'encre et
   herite tel quel de ceux de la carte sombre, y compris le violet vif, qui
   redevient le bon choix sur un fond noir.
   Deux ajustements le rendent possible :
   le fond doit etre OPAQUE, le voile translucide de la carte sombre laissant
   passer le creme, et le filet exterieur passe en encre, un filet blanc a 12%
   etant invisible sur du creme. Les filets INTERIEURS, eux, restent blancs :
   ils separent des zones a l'interieur du panneau sombre.
   L'ombre portee decolle la plaque de la carte, ce qui la fait lire comme un
   ecran encastre plutot que comme un trou. */
.proc__card--clair .proc__panel{
  background:linear-gradient(180deg,#16131F 0%,#0B0A11 100%);
  border-color:rgba(17,17,22,.20);
  box-shadow:0 12px 34px rgba(17,17,22,.16);
}

@keyframes proc-pulse{
  0%{transform:scale(.9);opacity:.55}
  70%{transform:scale(1.5);opacity:0}
  100%{transform:scale(1.5);opacity:0}
}
@media (prefers-reduced-motion:reduce){
  .proc__stage.is-live .proc__dot::after{animation:none;opacity:.4}
}
/* Garde-fou : sur un ecran court le panneau ne tiendrait pas et se ferait
   rogner. Mieux vaut ne pas l'afficher qu'en montrer un morceau coupe. */
@media (min-width:900px) and (max-height:640px){
  .proc__panel{display:none}
}

/* L'invite du DEPART (.nudge, "Scroll to continue") a ete retiree le 07/09.
   Elle apparaissait quand l'ouverture automatique s'arretait, pour dire qu'il
   fallait faire defiler pour la suite du film. Le film allant desormais au
   bout tout seul, il n'y a plus rien a demander : la garder aurait invite a
   un geste qui ne sert plus a rien.
   A ne pas confondre avec .scrollcue, qui vit toujours : elle depend de
   --settle et n'a jamais servi qu'a l'ARRIVEE, pour inviter a poursuivre
   au-dela du hero. */

/* --------------------------------------------------------------------------
   LA TELEMETRIE DE DESCENTE.
   Elle remplace les quatre phrases qui s'affichaient pendant le scroll. La
   difference tient en une ligne : une phrase s'allume puis s'eteint a un
   instant donne, une valeur tourne en CONTINU. L'ecran est donc vivant tout
   du long, et il n'y a plus rien a lire par-dessus le film.

   Placee en haut a gauche, sous la barre de navigation ET sous le filet du
   bandeau, qui est fixe en dessous de 1200px. Meme formule de degagement que
   les cartes du processus, deja mesuree.

   Elle disparait avec l'arrivee du bloc final : celui-ci porte deja son
   propre bandeau lieu et heure, et deux HUD a l'ecran en meme temps se
   marcheraient dessus.
   -------------------------------------------------------------------------- */
.tele{
  position:absolute;z-index:3;pointer-events:none;
  top:calc(var(--nav-h) + clamp(30px,5vh,54px));
  left:var(--gutter);
  display:flex;flex-direction:column;gap:clamp(.7rem,1.6vh,1.2rem);
  opacity:calc(1 - var(--settle,0));
}
/* Le voile d'angle a ete RETIRE a la demande de Lucas : il se voyait comme un
   fond noir. La lisibilite repose donc entierement sur l'ombre portee, la
   meme technique que la barre de navigation, qui protege le texte sans
   assombrir la page derriere. Reserve honnete : sur les images les plus
   lumineuses du film, la ville traversee en particulier, les libelles
   restent nettement moins lisibles qu'avec le voile. C'est le prix accepte. */
.tele__cell{display:flex;flex-direction:column;gap:.22rem}
.tele__val{
  font-family:var(--font-mono);font-weight:500;
  font-size:clamp(1.05rem,1.9vw,1.5rem);
  letter-spacing:.02em;color:var(--text-primary);
  /* Chiffres tabulaires : sans eux la largeur tremble a chaque changement de
     valeur, et l'altitude change en permanence. */
  font-variant-numeric:tabular-nums;
  text-shadow:0 1px 3px rgba(0,0,0,.95),0 2px 12px rgba(0,0,0,.9),0 0 22px rgba(0,0,0,.75);
  display:flex;align-items:baseline;gap:.3em;
}
.tele__val i{
  font-style:normal;font-size:.52em;letter-spacing:.18em;
  text-transform:uppercase;color:var(--text-secondary);
}
/* Le statut est du texte, pas un nombre : plus petit, pour que l'altitude
   reste la valeur dominante. */
.tele__val--txt{
  font-size:clamp(.76rem,1.15vw,.95rem);letter-spacing:.16em;
  text-transform:uppercase;color:var(--accent-hover);
  text-shadow:0 1px 3px rgba(0,0,0,.95),0 2px 12px rgba(0,0,0,.9),0 0 20px rgba(0,0,0,.75);
}
.tele__lab{
  font-family:var(--font-mono);font-size:clamp(.5rem,.68vw,.6rem);
  letter-spacing:.26em;text-transform:uppercase;color:var(--text-secondary);
  text-shadow:0 1px 3px rgba(0,0,0,.95),0 2px 12px rgba(0,0,0,.9),0 0 20px rgba(0,0,0,.75);
}

/* Sur un ecran court, la telemetrie et le V se disputent la hauteur : le V
   porte la progression, il passe avant. */
@media (max-height:560px){.tele{display:none}}

/* En mouvement reduit le hero est statique, il n'y a pas de descente a
   commenter. */
@media (prefers-reduced-motion:reduce){.tele{display:none}}

/* Le rappel de lieu du bas de cadre ferait doublon avec le bandeau, qui
   affiche deja la meme ville et occupe desormais le meme coin. Il ne reste
   donc que sous 1200px, la ou le bandeau est en haut. */
@media (min-width:1200px){
  .hero-place{display:none}
}

/* --------------------------------------------------------------------------
   LES AVIS : un ruban qui defile de la gauche vers la droite, en continu.

   Ce n'est PAS le presentoir produits. Celui-la est un vrai scroll horizontal
   avec accroche, parce qu'on y choisit un article. Ici on ne choisit rien, on
   lit : le mouvement doit donc etre porte par la page, pas par le doigt.
   D'ou une translation CSS plutot qu'un conteneur defilant.

   La piste contient DEUX fois la meme serie. Le ruban se decale de la moitie
   de sa largeur puis repart a zero, instant ou la copie occupe exactement la
   place de l'original : la boucle est donc invisible. Avec une seule serie,
   le retour au debut se verrait comme un saut.
   -------------------------------------------------------------------------- */
.avis__scene{
  position:relative;
  margin-top:clamp(28px,4vw,48px);
  overflow:hidden;
  /* Les deux bords s'effacent : le ruban entre et sort du cadre au lieu
     d'etre coupe net, ce qui donne la sensation qu'il continue au-dela. */
  -webkit-mask-image:linear-gradient(90deg,transparent 0,#000 7%,#000 93%,transparent 100%);
  mask-image:linear-gradient(90deg,transparent 0,#000 7%,#000 93%,transparent 100%);
}
.avis__ruban{
  list-style:none;margin:0;padding:0;
  display:flex;align-items:stretch;
  gap:clamp(14px,1.6vw,24px);
  width:max-content;
  animation:avis-defile 68s linear infinite;
  will-change:transform;
}
/* Le survol suspend le ruban : sans ca, une phrase qu'on commence a lire
   s'echappe avant la fin. */
.avis__scene:hover .avis__ruban,
.avis__scene:focus-within .avis__ruban{animation-play-state:paused}

@keyframes avis-defile{
  /* De la gauche vers la droite : le ruban part decale d'une demi-longueur
     et revient a zero. Une translation positive ferait sortir la premiere
     carte par la droite en laissant un trou a gauche. */
  from{transform:translate3d(-50%,0,0)}
  to{transform:translate3d(0,0,0)}
}

.avis__carte{
  flex:0 0 clamp(258px,25vw,340px);
  display:flex;flex-direction:column;
  padding:clamp(18px,1.9vw,28px);
  border:1px solid var(--line-soft);border-radius:16px;
  background:linear-gradient(180deg,#121118 0%,#0B0A11 100%);
}
.avis__note{display:flex;gap:.18rem;margin-bottom:clamp(.7rem,1.2vw,1rem)}
.avis__note svg{width:13px;height:13px;fill:var(--accent);flex:none}
.avis__mot{
  margin:0;flex:1;
  font-size:clamp(.9rem,1.05vw,1rem);line-height:1.55;
  color:var(--text-primary);
}
.avis__qui{
  margin:clamp(.9rem,1.4vw,1.2rem) 0 0;
  display:flex;align-items:baseline;gap:.55rem;flex-wrap:wrap;
}
.avis__qui b{
  font-family:var(--font-display);font-weight:700;
  font-size:.86rem;color:var(--text-primary);
}
.avis__qui i{
  font-style:normal;font-family:var(--font-mono);
  font-size:.6rem;letter-spacing:.16em;text-transform:uppercase;
  color:var(--text-faint);
}

/* Mouvement reduit : le ruban s'arrete, mais les avis doivent rester
   ATTEIGNABLES. On rend donc la scene defilable au doigt et au clavier,
   plutot que de figer huit cartes dont six seraient hors du cadre. */
@media (prefers-reduced-motion:reduce){
  .avis__ruban{animation:none;transform:none}
  .avis__scene{overflow-x:auto;scrollbar-width:none}
  .avis__scene::-webkit-scrollbar{display:none}
}

/* L etat d envoi du formulaire d expedition. Il ne dit jamais un succes :
   le succes a son propre bloc (.form__ok). Celui-ci porte les refus et
   l etat non configure. */
.form__etat{
  margin:0;border:1px solid var(--ember);background:var(--ember-muted);
  border-radius:10px;padding:.85rem 1rem;font-size:.9rem;color:var(--text-primary);
}
.form.is-sent .form__etat{display:none}
