/* ==========================================================================
   SECTIONS
   --------------------------------------------------------------------------
   Un bloc par section, dans l'ordre de la page. Toutes les valeurs sont
   relevees dans la reference — voir CARTE_DES_SECTIONS.md pour la source de
   chacune.
   ========================================================================== */

/* --------------------------------------------------------------------------
   BANDEAU + EN-TETE
   --------------------------------------------------------------------------
   Les deux vivent dans un meme bloc `position: fixed`, comme dans la
   reference : c'est le parent qui est fixe, pas l'en-tete lui-meme.
   -------------------------------------------------------------------------- */

.oya-entete-fixe {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 10;
  animation: oya-descend 1.5s var(--e-ressort-net) both;
}

.oya-bandeau {
  background: var(--c-marque-vif);
  color: var(--c-blanc);
  padding-block: 11px;
  font-size: var(--t-14);
  font-weight: var(--g-400);
}

/* Trois offres dans un groupe, 20 px entre elles ; 40 px entre deux groupes,
   porte par l'ecart de la piste. Chaque offre est suivie de sa puce, a 40 px. */
/* 20 px entre les trois offres d'un groupe, 40 entre deux groupes :
   les deux valeurs de la reference. */
.oya-bandeau .oya-marquee { --ecart: 20px; --ecart-copies: 40px; }

.oya-bandeau__groupe {
  display: flex;
  align-items: center;
  gap: 20px;
  white-space: nowrap;
}

.oya-bandeau__offre {
  display: flex;
  align-items: center;
  gap: 40px;
}

/* 17 px de haut pour un corps de 14 : interlignage 1,2. */
.oya-bandeau__texte { line-height: 1.2; }

/* La reference emploie un vrai caractere, en graisse 500 et interlignage 1,1 :
   6 x 15 px. Un pseudo-element rond de 4 px, comme ici auparavant, ne fait ni
   la meme largeur ni la meme hauteur. */
.oya-bandeau__puce {
  font-weight: var(--g-500);
  line-height: 1.1;
}

.oya-nav {
  /* Toute la largeur : c'est `.oya-nav__interieur` qui est plafonne. */
  padding: 15px 60px;
  display: flex;
  align-items: center;
  gap: 10px;
  backdrop-filter: blur(5px);
  -webkit-backdrop-filter: blur(5px);
}

@media (max-width: 679.98px) {
  .oya-nav { padding: 15px 25px; }
}

/* La barre blanchit des que la page a bouge d'un pixel.

   A SAVOIR : la page de reference ne fait PAS cela. Le composant de
   navigation embarque bien la bascule « Transparent -> White » — la variante
   existe, avec ce fond degrade, cette ombre et cette bordure — mais elle est
   pilotee par une propriete `navChange` que la page ne renseigne jamais. La
   plage de correspondance reste vide et la variante ne se declenche pas.

   Les valeurs ci-dessous sont donc celles du DESIGN, relevees dans la
   variante inutilisee ; le declenchement, lui, est un ajout demande pour OYA.
   C'est une difference volontaire avec la reference, pas une reproduction. */
.oya-nav {
  --bordure: var(--c-blanc-00);
  border-bottom: 1px solid var(--bordure);
  transition:
    background   0.4s var(--e-ressort-net),
    box-shadow   0.4s var(--e-ressort-net),
    border-color 0.4s var(--e-ressort-net);
}

.oya-nav[data-defile] {
  background: linear-gradient(180deg, var(--c-blanc) 0%, var(--c-blanc-80) 100%);
  --bordure: var(--c-blanc);
  box-shadow: 0 2px 3px var(--c-encre-05);
}

.oya-nav__interieur {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  width: 100%;
  max-width: var(--l-page);
  margin-inline: auto;
}

/* Logo et liens forment un seul groupe, separes de 40 px. */
.oya-nav__debut {
  display: flex;
  align-items: center;
  gap: 40px;
}

.oya-nav__logo {
  display: block;
  flex: none;
}

/* La reference emploie une image, pas du texte : la graisse et le
   chasse du logotype ne sont pas ceux d'une police disponible.
   87 x 25 px dans la reference. */
.oya-nav__logo img { height: 25px; width: auto; }

.oya-nav__liens {
  display: flex;
  align-items: center;
  gap: 24px;
  font-size: var(--t-14);
  font-weight: var(--g-500);
  /* 15,4 px pour un corps de 14 — interligne 1,1, comme tout le Switzer
     14/500 de la reference. Il etait a 1,28, soit 17,92 px. */
  line-height: var(--i-serre);
  color: var(--c-encre-70);
}

.oya-nav__liens > span { display: block; }
.oya-nav__liens a { color: inherit; transition: opacity 150ms var(--e-survol); }
.oya-nav__liens a:hover { opacity: 0.6; }

/* Le selecteur de langue et le bouton, dans cet ordre. `gap` est celui de
   `.oya-nav__interieur` : 10 px. */
.oya-nav__fin {
  flex: none;
  display: flex;
  align-items: center;
  gap: 16px;
}

/* SELECTEUR DE LANGUE.

   Il est GENERE par `scripts/poser-langues.py`, jamais saisi : les cinq pages
   d'une langue doivent porter un en-tete identique au caractere pres, et
   `check-repo.sh` §6 le verifie.

   La langue courante est un `<span>`, les autres des `<a>` : on ne met pas de
   lien vers la page ou l'on est, et c'est ce qui donne l'etat courant sans une
   ligne de JavaScript. Les libelles sont des codes de deux lettres, identiques
   dans toutes les langues -- rien a traduire, donc rien a mal traduire. Le nom
   complet de la langue, dans sa propre langue, vit dans l'`aria-label`.

   IL RESTE VISIBLE SOUS 680 px, contrairement aux quatre liens de navigation.
   Quelqu'un qui arrive sur la mauvaise langue doit pouvoir en changer, et c'est
   sur telephone que ca arrive le plus. */
.oya-langues {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: var(--t-14);
  font-weight: var(--g-500);
  line-height: var(--i-serre);
  letter-spacing: 0.02em;
}

.oya-langues a {
  color: var(--c-encre-40);
  transition: color 150ms var(--e-survol);
}

.oya-langues a:hover { color: var(--c-encre-70); }

.oya-langues__courante { color: var(--c-encre); }

/* Un filet fin entre deux codes, pose par le pseudo-element du suivant : il
   n'y a donc pas de filet en trop apres le dernier. */
.oya-langues > * + *::before {
  content: "";
  display: inline-block;
  width: 1px;
  height: 10px;
  margin-right: 8px;
  vertical-align: -1px;
  background: var(--c-encre-15);
}

/* La navigation disparait sous 680 px — variante « (M) Transparent » de la
   reference : les quatre liens sont retires, sans remplacement. Le selecteur,
   lui, reste. */
@media (max-width: 679.98px) {
  .oya-nav__liens { display: none; }
  .oya-nav__fin { gap: 12px; }
}

/* SOUS 400 px, LA BARRE NE TIENT PLUS SANS RESSERRER.

   Mesure a 320 px, la plus petite largeur qu'on rencontre encore (iPhone SE) :
   logo 53 + selecteur 53 + ecart 12 + bouton 170 = 288, plus 25 px de
   rembourrage de chaque cote = 338. Il manque 18 px, et comme la barre est en
   `space-between`, le manque ne deborde pas : il fait se CHEVAUCHER le logo et
   le selecteur.

   C'est aussi pour ca qu'aucune sonde de debordement ne l'avait vu : une barre
   en `position: fixed` ne cree pas de defilement horizontal. Elle se contente
   de se superposer a elle-meme.

   On reprend 18 px sur le rembourrage et 10 sur les ecarts. */
@media (max-width: 400px) {
  .oya-nav { padding-inline: 16px; }
  .oya-nav__fin { gap: 8px; }
  .oya-langues { gap: 6px; }
  .oya-langues > * + *::before { margin-right: 6px; }
}

/* --------------------------------------------------------------------------
   HERO
   --------------------------------------------------------------------------
   Fond en degrade vertical, releve tel quel. Le bloc central mesure
   1100 x 1100 px et porte le pot ; les sept gommes flottent autour, en
   position absolue.
   -------------------------------------------------------------------------- */

.oya-hero {
  position: relative;
  min-height: 900px;
  padding: 170px 40px 40px;
  overflow: clip;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  background: linear-gradient(0deg, var(--c-fond-pale-haut) -3%, var(--c-blanc) 81.5896%, var(--c-fond-pale-haut) 105%);
}

@media (max-width: 1199.98px) {
  .oya-hero { padding: 170px 40px 40px; }
}

@media (max-width: 679.98px) {
  .oya-hero { min-height: 800px; padding: 160px 25px 60px; }
}

.oya-hero__titre {
  position: relative;
  z-index: 2;
  font-family: var(--f-titre);
  font-size: var(--t-65);
  font-weight: var(--g-700);
  line-height: var(--i-serre);
  letter-spacing: var(--a-grand);
  /* 656 px dans la reference : les deux lignes « Your Supplement » et
     « Shelf, Simplified ». */
  max-width: 656px;
  animation: oya-monte 1.5s var(--e-ressort) 0.2s both;
}

.oya-hero__titre > span { display: inline-block; }

@media (max-width: 809.98px) {
  .oya-hero__titre { font-size: var(--t-40); }
}

.oya-hero__plomb {
  position: relative;
  z-index: 2;
  margin-top: 18px;
  /* 455 x 64 dans la reference : deux lignes de 32. */
  max-width: 455px;
  font-size: var(--t-20);
  line-height: var(--i-ample);
  color: var(--c-encre);
  animation: oya-monte 1.5s var(--e-ressort) 0.2s both;
}

.oya-hero__action {
  position: relative;
  z-index: 2;
  margin-top: 30px;
  animation: oya-monte 1.5s var(--e-ressort) 0.3s both;
}

/* Le decor : pot central et gommes -------------------------------------- */

.oya-hero__decor {
  position: absolute;
  top: 90%;
  left: 50%;
  width: 1100px;
  height: 1100px;
  pointer-events: none;
  /* Le centrage est DANS les keyframes, pas sur l'element : une animation
     qui anime `transform` remplace la propriete entiere. Pose ici, le
     translate(-50%,-50%) serait efface des la premiere image, et le decor
     tomberait 550 px trop bas. Constate a la capture du 2026-09-09. */
  animation: oya-decor-entree 2s var(--e-ressort) 0.4s both;
}

@keyframes oya-decor-entree {
  from { opacity: 0.001; transform: translate(-50%, -50%) translateY(50px); }
  to   { opacity: 1;     transform: translate(-50%, -50%) translateY(0); }
}

/* ==========================================================================
   LE DECOR DE LA V5 — la gourde OYA, son bouchon, et sept sticks
   --------------------------------------------------------------------------
   PREMIER ECHANGE DE VISUELS DE MARQUE. Le pot et les sept gommes du gabarit
   OneThing laissent la place a la gourde OYA et aux quatre formules.

   D'OU VIENNENT CES NOMBRES

   Ils ne sont pas dessines a l'oeil. Ils sont mesures sur la maquette de
   reference (capture du 2026-09-14, 993 x 418) et convertis dans le repere du
   decor. La chaine de mesure, pour qu'on puisse la refaire :

   1. La maquette EST notre V1, avec les visuels echanges. Preuve : son bouton
      noir tombe en x 449..535 ; notre V1 rendue a 1965 px le place en
      x 890..1057. Le rapport est constant, 0,5054 -- la capture est donc une
      reduction a 50,5 % d'une page de 1965 px. La capture commence a 87,6 px
      du haut de la page, deduit de la meme facon.

   2. Chaque stick a ete isole dans la capture par sa couleur (creme sur fond
      bleu pale), ce qui donne sa boite ENGLOBANTE. Une boite englobante n'est
      pas l'element : pour un rectangle w x h tourne de t, elle vaut
      (w.cos t + h.sin t) x (w.sin t + h.cos t). Deux equations, deux
      inconnues : on en tire la taille reelle ET la rotation. L'ecart residuel
      est inferieur a 2 % sur les sept.

   3. Le sens de rotation, lui, ne se calcule pas -- la boite englobante est
      la meme a gauche et a droite. Il a ete lu sur chaque stick agrandi.

   Les `left` des emplacements 5 et 7 ne sont pas ceux du premier calcul : ils
   ont ete repris apres l'echange BEAUTY <-> IMMUNITY. A hauteur egale les deux
   sachets n'ont pas la meme largeur (0,362 contre 0,320), et un `left` inchange
   aurait deplace le CENTRE de 4 px. C'est le centre qui est mesure, donc c'est
   lui qu'on garde.

   POURQUOI DES POURCENTAGES ET NON DES PIXELS

   Le decor est un carre dont le cote change : 1100 px en bureau, et sous
   680 px il vaut 100vw + 426. Des positions en pixels y seraient fausses
   partout sauf en bureau -- c'est exactement ce que le gabarit devait
   rattraper avec une deuxieme serie de valeurs pour le telephone. En
   pourcentages du cote, la composition se transporte telle quelle.
   Le decor etant carre, `height: 31%` et `left: 5%` parlent de la meme unite.

   CE QUI EST GARDE DU GABARIT

   Les vitesses de parallaxe (`data-parallaxe`), les entrees au ressort et le
   flottement. Ce sont eux qui donnent sa profondeur a la scene ; les refaire
   n'aurait rien apporte. Les sticks reutilisent donc les keyframes des
   gommes, `oya-gummy-entree` et `oya-flotte-gummy`.
   ========================================================================== */

/* LA GOURDE EST UNE SEULE IMAGE, ET C'EST LE PLAN DE REFERENCE.

   La premiere version de la V5 posait deux elements -- corps et bouchon --
   places a la main d'apres la maquette. Le visuel fourni le 2026-09-14 les
   reunit deja, detoure, dans un carre de 1100 x 1100 : exactement le gabarit
   du decor. Deux elements et leurs six mesures disparaissent donc au profit
   d'une image qui remplit son cadre. Moins de nombres a defendre.

   Elle ne porte PAS `data-parallaxe`. Ce n'est pas un oubli : elle est le plan
   sur lequel tout le reste se situe. Une vitesse de 100 ne ferait rien de plus
   (le coefficient vaut alors zero), mais la laisser absente dit mieux qu'elle
   est la reference et non un element de plus a regler. */
.oya-hero__gourde {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  z-index: 14;
  /* LA GOURDE DESCEND DE 4 %, SINON SON BOUCHON PASSE DERRIERE LE BOUTON.

     Le decor est ancre a `top: 90%` du heros : sa position depend donc de la
     hauteur de la fenetre, et le sommet du bouchon remonte quand elle
     diminue. Mesure du 2026-09-15, ecart entre le bas du bouton et le sommet
     du bouchon -- negatif veut dire qu'ils se chevauchent :

       fenetre 1440 x 1000    -8 px
       fenetre 1904 x 1000   -19 px

     4 % du cote du decor, soit 44 px en bureau, ramene l'ecart a +36 et +25.
     La valeur est en POURCENTAGE et non en pixels pour que le decalage suive
     le decor quand il retrecit, au telephone comme ailleurs.

     C'est `translate` et non `transform` : l'entree `oya-monte-50` occupe deja
     `transform`, et le navigateur compose les deux. Meme raison que pour la
     parallaxe des sticks. */
  translate: 0 4%;
  /* Releve, entrees `w7ue3b` et `bhp2dn` : y +50 px, opacite 0.001, ressort a
     rebond 0,2, 2 s, delai 0,4 s. */
  animation: oya-monte-50 2s var(--e-ressort) 0.4s both;
}

/* Les sept sticks. Chacun porte SA formule. La maquette en montrait deux
   IMMUNITY, deux ENERGY, deux BEAUTY et un FOCUS -- sept emplacements, quatre
   formules, ce qui n'est pas une erreur de lecture. Les deux sticks du bas a
   droite ont depuis ete echanges a la demande : le net y porte BEAUTY, le
   flou IMMUNITY. La repartition, elle, ne change pas.

   Seule la HAUTEUR est posee : la largeur suit le rapport propre de chaque
   sachet, qui n'est pas le meme d'une formule a l'autre (0,320 pour IMMUNITY,
   0,377 pour ENERGY). Poser les deux aurait deforme les visuels. */
.oya-stick {
  position: absolute;
  width: auto;
  /* Pas de `z-index` commun : chaque stick porte le sien, et c'est son rang de
     profondeur. Un `z-index` partage laissait l'ordre du balisage decider des
     recouvrements -- c'est ainsi qu'un stick flou se retrouvait devant un
     stick net. */
  will-change: transform;
  animation:
    oya-gummy-entree 2s var(--e-ressort) 0.5s both,
    oya-flotte-gummy 6s linear 2.5s infinite alternate;
}

/* --------------------------------------------------------------------------
   LA PROFONDEUR : UNE SEULE ECHELLE, ET TOUT EN DECOULE
   --------------------------------------------------------------------------
   PLUS C'EST FLOU, PLUS C'EST LOIN. C'est la regle, et le flou en est le
   temoin : c'est lui que l'oeil lit en premier, avant la taille.

   La premiere V5 reprenait les vitesses de parallaxe du gabarit OneThing sans
   les questionner. Elles etaient a l'envers : le plus gros et le plus net --
   donc le plus proche -- avancait a 90, le plus petit et le plus flou a 180.
   Un objet lointain doublait un objet proche. Et comme les sept sticks
   partageaient un meme `z-index`, c'est l'ordre du balisage qui decidait des
   recouvrements : ENERGY, net, passait derriere BEAUTY, flou.

   Un seul rang, du plus proche au plus lointain, ordonne par la taille ; le
   flou, le `z-index` et la vitesse le suivent tous les trois :

     rang  stick  formule    hauteur   flou     z    vitesse
       1     1    IMMUNITY    30,9 %   net      18     180
       2     2    FOCUS       20,0 %   net      17     160
       3     3    ENERGY      19,2 %   net      16     150
       4     5    BEAUTY      16,7 %   net      15     130
       -          LA GOURDE                     14     100  <- plan de reference
       5     4    ENERGY      15,5 %   1,5 px   13      92
       6     6    BEAUTY      13,9 %   2,5 px   12      85
       7     7    IMMUNITY     9,6 %   3,5 px   11      78

   LA GOURDE EST LE PLAN DE REFERENCE, a 100 : elle suit la page. Les quatre
   sticks nets sont devant elle et vont plus vite ; les trois flous sont
   derriere et trainent. La lecture est donc la meme au repos et en mouvement,
   ce qui n'etait pas le cas avant.

   DEUX ECARTS ASSUMES AVEC LA MAQUETTE. Elle donne 3 px de flou au stick 6 et
   2 px au stick 7, alors que le 7 est le plus petit -- le flou n'y croit donc
   pas tout a fait avec l'eloignement. Il est rendu monotone ici. Et ses
   vitesses, reprises du gabarit, sont remplacees par celles du tableau.
   Positions, tailles et rotations, elles, ne bougent pas d'un pixel.
   -------------------------------------------------------------------------- */

/* CES SEPT REGLES SONT CADREES AU HEROS, ET C'EST INDISPENSABLE.

   La classe `.oya-stick-N` sert dans DEUX decors : ici et dans « Introduce ».
   Ecrites sans cadre, ces regles fuyaient dans l'autre bloc. Le symptome etait
   spectaculaire : `.oya-stick-6` y recoit `right: 83px` d'Introduce et
   recevait `left: 26.21%` d'ici. Un element absolu qui a gauche ET droite avec
   une largeur intrinseque est sur-contraint -- le navigateur ignore alors
   `right`, et le stick se retrouvait 658 px trop a gauche. Constate le
   2026-09-14 en comparant les centres de mise en page avec ceux de la V4.

   Le cadre `.oya-hero__decor` referme la fuite dans les deux sens : ni ce bloc
   ni celui d'Introduce ne peuvent plus s'atteindre.

                                gauche      haut      hauteur     rotation      z      flou */
.oya-hero__decor .oya-stick-1 { left:  4.69%; top:  5.91%; height: 30.91%; --rot:  27deg; z-index: 18; }
.oya-hero__decor .oya-stick-2 { left: 71.84%; top: 16.18%; height: 20.00%; --rot: -30deg; z-index: 17; }
.oya-hero__decor .oya-stick-3 { left: 19.47%; top: 33.86%; height: 19.18%; --rot: -42deg; z-index: 16; }
.oya-hero__decor .oya-stick-5 { left: 67.24%; top: 40.09%; height: 16.73%; --rot:  33deg; z-index: 15; }
.oya-hero__decor .oya-stick-4 { left: 87.09%; top:  4.55%; height: 15.45%; --rot:  -3deg; z-index: 13; filter: blur(1.5px); }
.oya-hero__decor .oya-stick-6 { left: 26.21%; top: 16.32%; height: 13.91%; --rot:  -2deg; z-index: 12; filter: blur(2.5px); }
.oya-hero__decor .oya-stick-7 { left: 86.09%; top: 43.73%; height:  9.64%; --rot:  -8deg; z-index: 11; filter: blur(3.5px); }

/* `.oya-hero__pot` a disparu avec la V5 : le pot du gabarit n'est plus dans le
   balisage, la gourde et le bouchon l'ont remplace. La regle est retiree plutot
   que gardee « au cas ou » -- une regle morte se recopie a la version suivante
   et finit par se faire respecter.

   `.oya-gummy` a disparu avec elle. La classe n'existe plus nulle part dans
   le balisage de la V5 : le heros ET la section « Introduce » posent
   desormais des sticks. Seules SES DEUX ANIMATIONS survivent,
   `oya-gummy-entree` et `oya-flotte-gummy`, parce que les sticks s'en
   servent -- leur nom garde la trace de leur origine plutot que de la
   maquiller. */

@keyframes oya-gummy-entree {
  from { opacity: 0.001; transform: var(--centre, ) translateY(-80px) rotate(var(--rot)); }
  to   { opacity: 1;     transform: var(--centre, ) translateY(0)     rotate(var(--rot)); }
}

@keyframes oya-flotte-gummy {
  from { transform: var(--centre, ) translateY(0)    rotate(var(--rot)); }
  to   { transform: var(--centre, ) translateY(50px) rotate(var(--rot)); }
}

/* La parallaxe passe par `translate`, PAS par `transform`.

   Les deux proprietes sont distinctes et le navigateur les compose — `translate`
   s'applique avant `transform`. Le flottement peut donc garder `transform` sans
   que la parallaxe l'ecrase, et sans conteneur supplementaire.

   Ecrire la parallaxe dans `transform` aurait efface le centrage et la rotation
   a la premiere image : c'est exactement la faute qui avait fait tomber le
   decor du hero 550 px trop bas. */
.oya-hero__decor .oya-stick {
  translate: 0 var(--parallaxe-y, 0px);
}

/* Sous 680 px, seul le CADRE du decor change : les sticks sont poses en
   pourcentages de son cote et suivent d'eux-memes. Le gabarit avait ici une
   seconde serie de positions en pixels pour ses gommes -- elle disparait avec
   elles, et c'est exactement ce que les pourcentages devaient rendre inutile. */
@media (max-width: 679.98px) {
  /* LE HEROS MOBILE EST UNE AUTRE COMPOSITION, PAS LE BUREAU RETRECI.
     Releve sur `02_propre/mobile.html` a 500 px, le 2026-09-12. La reference
     y pose un calque « Mobile » de 926 x 926 dont le haut est a 154 px du haut
     du heros, centre, et y range cinq gommes en pixels ABSOLUS dans ce calque.
     Avant ce bloc, le decor gardait ses 1100 px de bureau et ses gommes de
     bureau : le pot debordait de 19 %, les gommes de 26 %, et la 7 etait
     entierement hors ecran. Le bureau, lui, ne change pas : ce bloc n'existe
     qu'en dessous de 680 px. */
  .oya-hero__decor {
    /* La regle EXACTE de la page vivante (`.framer-w7ue3b-container`, en
       dessous de 680 px) :

         bottom: -280px; left: -213px; right: -213px;
         top: unset; width: unset; transform: unset; aspect-ratio: 1

       Le calque n'a donc pas de largeur fixe : il deborde de 213 px de
       chaque cote, soit 100vw + 426 px, et son BAS est a 280 px sous le
       heros. A 500 px de large cela donne 926 x 926 avec le haut a 154 px --
       ce que mesurait la version precedente, qui avait fige ces 926 px. A
       390 px, la vraie largeur d'un telephone, cela donne 816 x 816 avec le
       haut a 264 px : le pot est plus petit et plus bas, et les gommes
       reviennent dans le cadre. C'est la difference que l'oeil voyait. */
    top: auto;
    bottom: -280px;
    left: -213px;
    right: -213px;
    width: auto;
    height: auto;
    aspect-ratio: 1;
    /* Le centrage par translate(-50%, -50%) n'a plus lieu d'etre : left et
       right suffisent. L'entree garde sa duree et son ressort, seule la
       trajectoire change -- monter de 50 px, comme le pot lui-meme. */
    animation-name: oya-monte-50;
  }

  /* Les textes du heros a la taille de la reference : 36/39.6 pour le titre,
     16/22.4 pour le chapo. Les notres etaient a 40/44 et 20/32 -- d'ou un
     chapo sur trois lignes au lieu de deux et un bouton 27 px trop bas. */
  .oya-hero__titre { font-size: 36px; }
  .oya-hero__plomb { font-size: 16px; line-height: var(--i-moyen); }
}

/* --------------------------------------------------------------------------
   BENEFITS
   --------------------------------------------------------------------------
   Titre et bouton sur une ligne, puis un marquee horizontal de cinq cartes.
   Ce n'est pas un carrousel a boutons : il defile en continu, et il ne
   s'arrete ni au survol ni hors ecran — verifie dans le code de la reference.
   -------------------------------------------------------------------------- */

.oya-benefits {
  /* La reference rogne cette section. Sans cela un decor en position absolue
     — le collage de la Timeline et sa pastille, le pot du hero — pousse le
     document au-dela de la fenetre, et une bande blanche apparait a droite sur
     telephone. Mesure du 2026-09-10 : document a 525 px pour une fenetre de
     500, la Timeline seule en cause. */
  overflow: clip;
  display: flex;
  flex-direction: column;
  gap: 60px;
  padding: 80px 60px 60px;
  scroll-margin-top: 60px;
}

@media (max-width: 1199.98px) {
  .oya-benefits { padding: 60px 40px; }
}

@media (max-width: 679.98px) {
  .oya-benefits { gap: 40px; padding: 40px 25px; }
}

/* Le titre pousse le bouton a droite ; les deux s'alignent sur leur base. */
.oya-benefits__tete {
  width: 100%;
  max-width: var(--l-page);
  margin-inline: auto;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px;
}

@media (max-width: 679.98px) {
  .oya-benefits__tete {
    flex-direction: column;
    align-items: flex-start;
    gap: 20px;
  }
}

/* Le H2 de section : Manrope 600, et non la police de titre. C'est le choix
   de la reference, releve dans son preset. */
.oya-titre-section {
  flex: 1 0 0;
  max-width: 498px;
  font-family: var(--f-titre);
  font-size: var(--t-40);
  font-weight: var(--g-600);
  line-height: var(--i-titre);
  letter-spacing: var(--a-titre);
  text-wrap: balance;
}

@media (max-width: 1199.98px) { .oya-titre-section { font-size: var(--t-36); } }
@media (max-width: 679.98px)  { .oya-titre-section { font-size: var(--t-28); flex: none; width: 100%; } }

/* Le marquee de cartes ---------------------------------------------------- */

/* Le marquee sort du rembourrage de la section pour aller d'un bord a
   l'autre : les cartes se coupent aux deux extremites, comme dans la
   reference. Les marges negatives annulent exactement le padding lateral,
   quel que soit le palier. */
.oya-benefits__piste-cadre {
  width: auto;
  margin-inline: -60px;
  border-radius: var(--r-10);
  /* La reference affiche le curseur de prehension : le marquee s'attrape. */
  cursor: grab;
}

@media (max-width: 1199.98px) { .oya-benefits__piste-cadre { margin-inline: -40px; } }
@media (max-width: 679.98px)  { .oya-benefits__piste-cadre { margin-inline: -25px; } }

.oya-benefits__piste-cadre:active { cursor: grabbing; }

/* Ce marquee-ci deborde volontairement de la gouttiere : les cartes se
   coupent aux deux bords, comme dans la reference. */
.oya-benefits .oya-marquee {
  -webkit-mask: none;
          mask: none;
}

.oya-benefits .oya-marquee { --ecart: 24px; }

.oya-benefit {
  flex: none;
  width: 220px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 16px;
  user-select: none;
}

.oya-benefit__media {
  width: 100%;
  /* La reference declare `height:250px` ET `aspect-ratio:.8`. C'est le
     ratio qui l'emporte : 220 / 0.8 = 275, et le media mesure bien 275 de
     haut a l'ecran. Reprendre la hauteur donnait une carte 25 px trop
     courte. Mesure du 2026-09-09. */
  aspect-ratio: 0.8;
  border-radius: var(--r-15);
  overflow: hidden;
  background: var(--c-gris-050);
}

.oya-benefit__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.oya-benefit__texte {
  display: flex;
  flex-direction: column;
  gap: 5px;
  width: 100%;
}

.oya-benefit__titre {
  font-family: var(--f-texte);
  font-size: var(--t-16);
  font-weight: var(--g-500);
  line-height: var(--i-titre);
  letter-spacing: 0;
}

.oya-benefit__soustitre {
  font-family: var(--f-texte);
  font-size: var(--t-16);
  font-weight: var(--g-400);
  line-height: var(--i-texte);
  color: var(--c-encre-70);
}

/* --------------------------------------------------------------------------
   TIMELINE
   --------------------------------------------------------------------------
   Deux colonnes : titre et collage d'images a gauche, les trois etapes a
   droite le long d'un filet de progression. Bascule en une colonne sous 680.
   -------------------------------------------------------------------------- */

.oya-timeline {
  /* La reference rogne cette section. Sans cela un decor en position absolue
     — le collage de la Timeline et sa pastille, le pot du hero — pousse le
     document au-dela de la fenetre, et une bande blanche apparait a droite sur
     telephone. Mesure du 2026-09-10 : document a 525 px pour une fenetre de
     500, la Timeline seule en cause. */
  overflow: clip;
  display: flex;
  justify-content: center;
  padding: 80px 60px 100px;
  scroll-margin-top: 60px;
}

@media (max-width: 679.98px) {
  .oya-timeline { padding: 40px 25px; }
}

.oya-timeline__grille {
  display: flex;
  gap: 80px;
  width: 100%;
  max-width: var(--l-page);
}

@media (max-width: 1199.98px) {
  .oya-timeline__grille { flex-direction: column; gap: 60px; }
}

@media (max-width: 679.98px) {
  .oya-timeline__grille { flex-direction: column; gap: 40px; }
}

/* Colonne de gauche : titre puis collage --------------------------------- */

.oya-timeline__gauche {
  flex: 1 0 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 100px;
}

/* Le titre de la Timeline occupe toute sa colonne — 560 px — la ou celui de
   Benefits est bride a 498. La limite appartient donc a chaque section, pas
   au style de titre. */
.oya-timeline__gauche .oya-titre-section { max-width: none; }

@media (max-width: 1199.98px) { .oya-timeline__gauche { gap: 80px; flex: none; width: 100%; } }
@media (max-width: 679.98px)  { .oya-timeline__gauche { gap: 40px; } }

/* Le collage : deux photos qui se chevauchent, plus la pastille. La hauteur
   minimale reserve la place, car les deux photos sont en absolu. */
.oya-timeline__collage {
  position: relative;
  width: 100%;
  max-width: 500px;
  min-height: 366px;
}

.oya-timeline__photo-1 {
  position: absolute;
  top: 0;
  left: 0;
  width: 300px;
  height: 300px;
  /* Pas de `overflow:hidden` ici : la pastille deborde volontairement du
     coin superieur droit. C'est l'image elle-meme qui porte le rognage. */
}

.oya-timeline__photo-2 {
  position: absolute;
  bottom: 0;
  right: 0;
  width: 241px;
  height: 241px;
  border-radius: 20px;
  overflow: hidden;
  z-index: 1;
}

/* `> img` et non ` img` : la pastille vit DANS la premiere photo, et son logo
   se faisait etirer a 81 px par cette regle. Un selecteur de descendance
   attrape ce qu'on n'avait pas prevu d'y mettre. */
.oya-timeline__photo-1 > img,
.oya-timeline__photo-2 > img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: inherit;
}

.oya-timeline__photo-1 > img { border-radius: var(--r-15); }

@media (max-width: 679.98px) {
  .oya-timeline__photo-1 { width: 270px; height: 270px; }
  .oya-timeline__photo-2 { width: 210px; height: 210px; }
}

/* La pastille circulaire : fond bleu, logo au centre, rotation continue.
   La reference dessine son texte sur un canvas a 20 degres par seconde ;
   on reprend la vitesse — 360 / 20 = 18 s le tour. */
.oya-pastille {
  position: absolute;
  top: -40px;
  right: -50px;
  /* 112 px dans la reference, pas 110. */
  width: 112px;
  height: 112px;
  border-radius: 50%;
  background: var(--c-marque-vif);
  display: grid;
  place-items: center;
  z-index: 2;
  /* Le conteneur porte un leger devers fixe dans la reference. */
  rotate: -1deg;
}

/* L'anneau de texte occupe toute la pastille et tourne : 360 degres en 18 s,
   soit les 20 degres par seconde de la reference.

   Une version avait redessine ce texte en SVG, en croyant que l'image du
   centre etait un logo. C'etait l'anneau lui-meme : la page affichait donc
   DEUX anneaux, l'un par-dessus l'autre. Le nom `__logo` avait suffi a
   m'egarer — c'est pourquoi il s'appelle maintenant `__anneau`. */
/* L'anneau et la marque occupent la MEME cellule de grille : la marque se
   pose au centre de l'anneau sans position absolue. */
.oya-pastille__anneau,
.oya-pastille__marque { grid-area: 1 / 1; }

.oya-pastille__anneau {
  width: 100%;
  height: 100%;
  object-fit: contain;
  animation: oya-tourne-pastille 18s linear infinite;
}

/* La marque centrale. 50 px sur 112 dans la reference, soit 44,64 % --
   exprimee en proportion, elle suit la pastille de 80 px du telephone sans
   seconde regle.

   Elle ne tourne pas : dans la reference l'anneau est un `<canvas>` qui porte
   seul la rotation, et la marque est un `<img>` pose par-dessus. */
.oya-pastille__marque {
  width: 44.64%;
  height: 44.64%;
  object-fit: contain;
  z-index: 1;
}

@keyframes oya-tourne-pastille { to { rotate: 360deg; } }

@media (max-width: 679.98px) {
  .oya-pastille { top: -30px; right: -39px; width: 80px; height: 80px; }
}


/* Colonne de droite : le filet et les trois etapes ----------------------- */

.oya-timeline__droite {
  flex: 1 0 0;
  min-width: 0;
  /* La colonne ne s'etire PAS sur la hauteur de la section : elle mesure sa
     propre hauteur — 527 px — et se centre en face du titre et du collage.
     Etiree, elle faisait 562 et la premiere etape partait 18 px trop haut. */
  align-self: center;
  display: flex;
  gap: 40px;
  padding-top: 15px;
}

@media (max-width: 1199.98px) { .oya-timeline__droite { flex: none; width: 100%; } }

.oya-timeline__piste {
  align-self: stretch;
  flex: none;
  width: 5px;
  /* Le rail ne va pas d'un bord a l'autre : 8 px en haut, 3 en bas, releves
     dans la reference (cadre de 512, rail de 501). */
  margin-block: 8px 3px;
  border-radius: var(--r-pilule);
  background: var(--c-marque-pose);
  overflow: hidden;
  position: relative;
}

/* La jauge descend le long du rail au fil du defilement.

   La reference lui donne `speed:0, offset:1, adjustPosition:true` sur le
   calque « Fill » — autrement dit `y` suit exactement `scrollY`.

   Ici c'est `animation-timeline: view()` qui fait le travail, sans une ligne
   de JavaScript, la ou le navigateur le reconnait. Ailleurs, le script pose
   `--progression`, de -100 % a 100 %.

   Une version precedente lisait deja `--progression`... que personne
   n'ecrivait. La jauge restait donc collee en haut, immobile. Une variable
   sans auteur est un reglage qui n'existe pas. Constate le 2026-09-10. */
.oya-timeline__remplissage {
  position: absolute;
  inset: 0 0 auto 0;
  height: 40vh;
  border-radius: var(--r-pilule);
  background: var(--c-marque-jauge);
  /* Le decalage est pose par le script, en pixels : il cloue le BAS du bloc a
     40vh du haut de la fenetre. La valeur de repli garde le bloc hors du rail
     tant que le script n'a pas tourne. */
  translate: 0 -100%;
}

/* Pas d'`animation-timeline` ici, et c'est un choix.

   La version precedente s'appuyait dessus. Deux ennuis. D'abord elle etait
   posee sur la jauge, qui mesurait SA propre visibilite — un bloc de 40vh en
   position absolue — et non celle du rail. Ensuite et surtout : une animation
   liee au defilement ne se met a jour qu'a l'image, et le navigateur du banc
   d'essai gele les images apres le chargement. Impossible d'en verifier une
   seule ligne.

   Un ecouteur de defilement, lui, se declenche a la demande : il suffit
   d'envoyer un evenement pour voir la valeur changer. On echange une elegance
   contre une chose qu'on peut prouver. Voir `animations.js`. */

.oya-timeline__etapes {
  flex: 1 0 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  /* Les etapes mesurent 500 px dans une colonne de 515 : elles sont CENTREES,
     pas collees a gauche. Sans cela elles commencaient 8 px trop tot. */
  align-items: center;
  gap: 40px;
}

.oya-etape {
  width: 100%;
  max-width: 500px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
}

/* La premiere etape respire un peu plus. */
.oya-etape:first-child { gap: 16px; }

@media (max-width: 679.98px) {
  .oya-etape:not(:last-child) { padding-bottom: 40px; }
}

.oya-etape__pastille {
  background: var(--c-marque-pose);
  color: var(--c-marque-jauge);
  border-radius: var(--r-pilule);
  padding: 10px 15px;
  font-family: var(--f-texte);
  font-size: var(--t-14);
  font-weight: var(--g-500);
}

/* Le libelle dans son propre element : la pastille porte le rembourrage,
   le texte sa boite. Structure de la reference — 49 x 15. */
.oya-etape__pastille > span { display: block; line-height: 1.1; }

@media (max-width: 679.98px) {
  .oya-etape__pastille { padding: 8px 12px; }
}

.oya-etape__titre {
  align-self: stretch;
  font-family: var(--f-titre);
  font-size: var(--t-25, 25px);
  font-weight: var(--g-600);
  line-height: var(--i-titre);
  letter-spacing: var(--a-titre);
}

.oya-etape__texte {
  /* Encre pleine : c'est la valeur de la reference. Le gris a 70 % est
     reserve aux sous-titres de cartes. */
  font-family: var(--f-texte);
  font-size: var(--t-16);
  font-weight: var(--g-400);
  line-height: var(--i-texte);
  color: var(--c-encre);
}

/* --------------------------------------------------------------------------
   FEATURED
   --------------------------------------------------------------------------
   Bandeau de logos de presse defilant, avec la pastille produit posee
   par-dessus. Le masque du bandeau evide son CENTRE : c'est ce trou qui
   laisse voir la pastille. Sans lui, les logos passeraient dessous.
   -------------------------------------------------------------------------- */

.oya-featured {
  display: flex;
  flex-direction: column;
  align-items: center;
  /* La reference empile titre, logos et carte dans UNE seule colonne a
     ecart constant de 100. L'ecart de 90 pose ici remontait la carte de
     10 px, et ces 10 px se propageaient jusqu'au pied de page. */
  gap: 100px;
  padding: 60px 60px 100px 59px;
  background: linear-gradient(var(--c-coquille) 68%, var(--c-blanc) 100%);
  scroll-margin-top: 60px;
}

@media (max-width: 1199.98px) { .oya-featured { padding: 60px 40px; } }
@media (max-width: 679.98px)  { .oya-featured { padding: 40px 25px; } }

.oya-featured__haut {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 100px;
  width: 100%;
}

.oya-featured__haut .oya-titre-section {
  width: 100%;
  max-width: 498px;
  text-align: center;
  flex: none;
}

/* Le bandeau et la pastille partagent la meme boite. */
.oya-featured__logos {
  position: relative;
  display: flex;
  justify-content: center;
  width: 100%;
}

/* ECART VOLONTAIRE AU MODELE — demande le 2026-09-10.
   
   La reference arrete le bandeau aux marges de section et creuse un trou de
   41 % a 58 % pour degager la pastille :
   
     mask: linear-gradient(270deg, #000 0%, #0000 41% 58%, #000 100%)
   
   Ce comportement a ete verifie quatre fois comme conforme -- geometrie,
   masque, tailles de logos, position de la pastille, tous identiques a la
   reference a 500, 810 et 1440 px. Ce n'est donc PAS une correction : c'est un
   choix de design assume, qui s'ecarte du modele.
   
   Le bandeau va desormais d'un bord a l'autre de la fenetre, et les logos
   defilent sans interruption. Il ne reste qu'un fondu de 4 % a chaque
   extremite, pour que la coupe ne soit pas brutale. La pastille passe
   par-dessus. */
.oya-featured__logos {
  /* Deborder les marges de la section sans les connaitre : `50% - 50vw` place
     le bord gauche d'un bloc de 100vw sur le bord de la fenetre, quel que soit
     le rembourrage du parent. */
  width: 100vw;
  margin-inline: calc(50% - 50vw);
}

.oya-featured__logos .oya-marquee {
  flex: 1 0 0;
  min-width: 0;
  -webkit-mask: linear-gradient(90deg, #0000 0%, #000 4%, #000 96%, #0000 100%);
          mask: linear-gradient(90deg, #0000 0%, #000 4%, #000 96%, #0000 100%);
  cursor: grab;
}

.oya-featured__logos .oya-marquee:active { cursor: grabbing; }

.oya-featured__logos .oya-marquee { --ecart: 50px; }

.oya-featured__logos .oya-marquee__copie > div { flex: none; }
/* Chaque logo occupe une boite dont la reference fixe LES DEUX dimensions,
   et son dessin s'y loge en `contain`. Avec `height:auto`, la boite prenait
   la proportion du fichier : la rangee mesurait 51 px au lieu de 72, et les
   31 px manquants se propageaient jusqu'au bas de la page.
   Le rapport est note en `aspect-ratio` pour que les largeurs reduites du
   mobile donnent des hauteurs proportionnees sans seconde table de valeurs. */
.oya-featured__logos img { height: auto; object-fit: contain; }

/* Largeurs et proportions relevees une a une. */
.oya-logo-1 { width: 205px; aspect-ratio: 205 / 62; }
.oya-logo-2 { width: 184px; aspect-ratio: 184 / 55; }
.oya-logo-3 { width: 239px; aspect-ratio: 239 / 72; }
.oya-logo-4 { width: 154px; aspect-ratio: 154 / 46; }

@media (max-width: 679.98px) {
  .oya-logo-1 { width: 143px; }
  .oya-logo-2 { width: 128px; }
  .oya-logo-3 { width: 167px; }
  .oya-logo-4 { width: 106px; }
}

/* LA PASTILLE RETROUVE LA GELULE DU GABARIT : 117 x 142.

   Elle avait ete carree le temps d'une tuile carree. Le nouveau visuel est un
   ovale dresse -- 990 x 1202, rapport 0,8236 -- et la gelule du gabarit vaut
   117 / 142 = 0,8239. Trois millemes d'ecart : la boite d'origine l'habille
   exactement, `object-fit: contain` ne rogne rien et ne laisse aucun vide.
   Telephone : 91 x 110, meme rapport. */
.oya-featured__pastille {
  position: absolute;
  width: 117px;
  height: 142px;
  top: calc(50% - 71px);
  left: calc(50.0463% - 58.5px);
  border-radius: 180px;
  z-index: 1;
  pointer-events: none;
}

@media (max-width: 1199.98px) { .oya-featured__pastille { left: calc(50% - 58.5px); } }

@media (max-width: 679.98px) {
  .oya-featured__pastille {
    width: 91px; height: 110px;
    top: calc(50.7937% - 55px);
    left: calc(50% - 45.5px);
  }
}

.oya-featured__pastille img { width: 100%; height: 100%; object-fit: contain; }

/* Carte produit et paragraphe -------------------------------------------- */

.oya-featured__bas {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 32px;
  width: 100%;
}

.oya-carte-produit {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 20px;
  width: 360px;
  padding: 8px 15px 8px 8px;
  border-radius: 18px;
  background: var(--c-gris-050);
}

@media (max-width: 679.98px) { .oya-carte-produit { width: 100%; } }

.oya-carte-produit__cadre {
  flex: none;
  padding: 10px;
  background: var(--c-blanc);
  border-radius: var(--r-15);
}

.oya-carte-produit__image {
  width: 50px;
  height: 50px;
  aspect-ratio: 1;
  object-fit: contain;
  filter: drop-shadow(var(--c-encre-15) 0 5px 3px);
}

.oya-carte-produit__droite {
  flex: 1 0 0;
  min-width: 0;
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 10px;
}

.oya-carte-produit__infos {
  flex: 1 0 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.oya-carte-produit__nom {
  font-family: var(--f-texte);
  font-size: var(--t-16);
  font-weight: var(--g-500);
  line-height: var(--i-titre);
}

.oya-carte-produit__prix {
  font-family: var(--f-texte);
  font-size: var(--t-16);
  font-weight: var(--g-400);
  /* 24 px de haut pour un corps de 16 : releve dans la reference. */
  line-height: var(--i-texte);
  color: var(--c-encre-70);
}

/* La fleche : un carre noir dont le SVG decoupe la forme. */
.oya-carte-produit__cta {
  flex: none;
  display: grid;
  place-items: center;
  padding: 9px 8px 9px 10px;
  background: var(--c-noir);
  border-radius: var(--r-pilule);
}

.oya-carte-produit__fleche {
  /* Carree dans la reference : 12 x 12. Avec 12 x 10 et un masque en
     `contain`, le dessin tombait a 10 px de large. */
  width: 12px;
  height: 12px;
  /* Le dessin pointe vers le BAS dans le fichier ; la reference le tourne
     d'un quart de tour pour qu'il pointe a droite. Sans cette rotation la
     pointe reste dirigee vers le bas. */
  transform: rotate(-90deg);
  background: var(--c-blanc);
  -webkit-mask: url(../assets/icones/chevron.svg) center / auto no-repeat;
          mask: url(../assets/icones/chevron.svg) center / auto no-repeat;
}

.oya-featured__texte {
  width: 100%;
  max-width: 416px;
  text-align: center;
  font-family: var(--f-texte);
  font-size: var(--t-16);
  font-weight: var(--g-400);
  line-height: var(--i-texte);
  color: var(--c-encre-70);
}

/* --------------------------------------------------------------------------
   ALL IN ONE — deux sous-blocs sur le meme fond bleu pale
   -------------------------------------------------------------------------- */

/* 1) Le bloc « supplement » : photo plein cadre, texte par-dessus --------- */

/* V2 : la section entiere porte l'ancre #parcours (La methode, Le Parcours).
   Meme descente que ses voisines. */
.oya-all-in-one { scroll-margin-top: 60px; }

.oya-supplement {
  position: relative;
  min-height: 815px;
  display: flex;
  flex-direction: column;
  /* Le contenu se cale SOUS le rembourrage haut de 80 px, il n'est pas
     centre dans la hauteur. Centre, il tombait 38 px trop bas. */
  justify-content: flex-start;
  gap: 60px;
  padding: 80px 60px 60px;
  background: var(--c-fond-pale);
  overflow: clip;
}

@media (max-width: 1199.98px) { .oya-supplement { padding: 60px 40px; } }
@media (max-width: 679.98px)  { .oya-supplement { padding: 40px 25px; } }

/* La photo occupe tout le bloc, fondue vers le bas. */
/* Le voile porte sur la photo ET sur son grain, comme dans la reference ou
   les deux vivent dans un meme calque « Image (Change) ».

   Il etait pose sur la seule photo. Le grain, lui, gardait un degrade RADIAL
   et restait donc entier jusqu'en bas, la ou la photo s'etait deja eteinte :
   un voile de bruit flottait sur le bleu de la section. Releve du profil
   vertical du 2026-09-10 : rugosite 0,05 dans la reference contre 7,04 chez
   nous a 96 % de la hauteur. */
.oya-supplement__image {
  position: absolute;
  inset: 0;
  -webkit-mask: linear-gradient(#000 61.5797%, #0006 77%, #0000 98%);
          mask: linear-gradient(#000 61.5797%, #0006 77%, #0000 98%);
}

.oya-supplement__photo {
  position: absolute;
  inset: 0;
  z-index: 1;
}

.oya-supplement__photo img { width: 100%; height: 100%; object-fit: cover; }

.oya-supplement__grain {
  position: absolute;
  inset: 0;
  opacity: 0.15;
  z-index: 2;
  pointer-events: none;
  /* Le grain est une TUILE de 128 px repetee, pas une image etiree. Pose en
     <img> couvrant 1440 x 815, le meme fichier etait grossi onze fois : au
     lieu d'un bruit fin, la photo se couvrait de taches bien visibles.
     C'est la faute la plus voyante de la page, et aucune mesure de texte ne
     pouvait la reveler — seule la comparaison des pixels l'a montree.
     Constate le 2026-09-09. */
  background: url(../assets/images/texture-grain.avif) repeat;
  background-size: 128px auto;
}

.oya-supplement__contenu {
  position: relative;
  z-index: 4;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  align-items: center;
  gap: 60px;
  width: 100%;
  min-height: 600px;
  text-align: center;
}

.oya-supplement__contenu .oya-titre-section {
  max-width: 600px;
  flex: none;
  width: 100%;
  color: var(--c-blanc);
}

.oya-supplement__bloc-texte {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 24px;
  width: 100%;
  max-width: 600px;
}

.oya-supplement__texte {
  font-family: var(--f-texte);
  font-size: var(--t-16);
  font-weight: var(--g-400);
  line-height: var(--i-texte);
  color: var(--c-blanc);
}

/* L'annotation flottante : un point, un filet, une etiquette en verre. */
.oya-annotation {
  position: absolute;
  top: 42%;
  left: 71%;
  width: 289px;
  transform: translate(-50%, -50%);
  display: flex;
  align-items: center;
  gap: 10px;
  z-index: 3;
}

@media (max-width: 1199.98px) { .oya-annotation { width: min-content; top: 44%; left: 81%; } }
@media (max-width: 679.98px)  { .oya-annotation { width: 167px; top: 49%; left: 73%; } }

.oya-annotation__trait { flex: 1 0 0; display: flex; align-items: center; }
.oya-annotation__point { width: 7px; height: 7px; border-radius: var(--r-pilule); background: var(--c-blanc); opacity: 0.8; }
.oya-annotation__filet { flex: 1 0 0; height: 1px; background: var(--c-blanc); opacity: 0.5; }

.oya-annotation__etiquette {
  flex: none;
  padding: 12px;
  border-radius: var(--r-15);
  background: var(--c-blanc-15);
  /* Aucun filet : la reference mesure 179 x 62, soit exactement le texte plus
     ses 12 px de rembourrage. Le liseré d'un pixel ajoutait 2 px sur chaque
     dimension et rognait d'autant le trait voisin. */
  backdrop-filter: blur(5px);
  -webkit-backdrop-filter: blur(5px);
  color: var(--c-blanc);
  font-family: var(--f-texte);
  font-size: var(--t-16);
  font-weight: var(--g-500);
  line-height: var(--i-titre);
}

.oya-annotation__etiquette > span { display: block; width: 155px; }

@media (max-width: 679.98px) { .oya-annotation__etiquette > span { width: 104px; } }

/* 2) Le bloc « ingredients » --------------------------------------------- */

.oya-ingredients {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 80px;
  padding: 0 60px 160px;
  background: var(--c-fond-pale);
  scroll-margin-top: 120px;
}

@media (max-width: 1199.98px) { .oya-ingredients { padding: 0 40px 120px; } }
@media (max-width: 679.98px)  { .oya-ingredients { gap: 70px; padding: 0 25px 40px 24px; } }

.oya-ingredients__contenu {
  display: flex;
  flex-direction: column;
  gap: 80px;
  width: 100%;
  max-width: 955px;
}

@media (max-width: 1199.98px) { .oya-ingredients__contenu { gap: 60px; } }

.oya-ingredients__entete {
  display: flex;
  justify-content: space-between;
  gap: 40px;
  width: 100%;
}

@media (max-width: 1199.98px) {
  .oya-ingredients__entete { flex-direction: column; justify-content: flex-start; gap: 20px; }
}

/* 416 x 96 dans la reference : deux lignes. */
.oya-ingredients__entete .oya-titre-section { max-width: 416px; }

.oya-ingredients__chapo {
  /* La reference emploie `flex:1 0 0` avec un plafond de 361 : la boite
     mesure donc exactement 361, et la premiere phrase — 360,5 px en
     Switzer — y tient tout juste. Avec `flex:none`, l'arrondi de la
     largeur intrinseque la faisait passer a la ligne, d'ou une quatrieme
     ligne. Mesure du 2026-09-09. */
  flex: 1 0 0;
  min-width: 0;
  /* Le plafond de 361 px est celui de la reference. Le `min()` l'empeche de
     depasser la place disponible : `align-self: center` dans une colonne fait
     que la boite se dimensionne sur son contenu, et un paragraphe long sortirait
     du cadre sur un ecran plus etroit que 385 px.

     GARDE-FOU NON OBSERVE. Chrome ecrete la fenetre a 500 px CSS : le banc
     d'essai ne descend pas plus bas, et le defaut n'a donc pas ete vu. La
     borne est posee par raisonnement, pas par mesure — c'est dit ici pour que
     personne ne la croie verifiee. */
  max-width: min(361px, 100%);
  /* Sans cela, l'etirement par defaut du conteneur en ligne porte la boite
     a la hauteur du titre — 96 px au lieu de 72 — alors que le texte tient
     bien sur trois lignes. Les lignes etaient identiques, la boite non.
     CENTRE, et non colle en haut : la reference laisse 12 px au-dessus et
     12 en dessous dans un en-tete de 96. */
  align-self: center;
  font-family: var(--f-texte);
  font-size: var(--t-16);
  font-weight: var(--g-400);
  line-height: var(--i-texte);
  color: var(--c-encre-70);
}

/* Colonne | image | colonne. Sous 1200, l'image passe au-dessus des deux
   groupes : c'est `order` qui fait tout le travail, pas un reagencement. */
.oya-ingredients__grille {
  display: flex;
  justify-content: center;
  gap: 40px;
  width: 100%;
  max-width: 955px;
}

/* En colonne, les deux groupes se CENTRENT et l'ecart tombe a 40.

   Releve dans l'export mobile de la reference : les groupes mesurent 270 px
   et commencent a x=115 dans un bloc de 451 — soit (451-270)/2 = 90,5 de
   marge de chaque cote. Ici ils etaient colles a gauche, avec 60 px d'ecart.
   Mesure du 2026-09-10 a 500 px. */
@media (max-width: 1199.98px) {
  .oya-ingredients__grille {
    max-width: none;
    flex-direction: column;
    align-items: center;
    gap: 40px;
  }
}

.oya-ingredients__colonne {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 40px;
  width: 225px;
  max-width: 225px;
}

/* Aucun `order` sur le bureau : l'ordre du document EST l'ordre visuel,
   colonne / image / colonne. Une version precedente posait order:1 et order:2
   sur les deux colonnes en laissant l'image sans order — donc a 0, donc en
   PREMIERE position, a x=243 au lieu de 508. Les colonnes se retrouvaient
   toutes les deux a droite, 465 px trop loin. Le `order` d'adaptation est
   maintenant enferme dans la requete media a laquelle il appartient.
   Constate le 2026-09-09 par la sonde de positions. */

@media (max-width: 1199.98px) {
  .oya-ingredients__colonne { max-width: none; flex-direction: row; width: 100%; }
}

@media (max-width: 679.98px) {
  .oya-ingredients__colonne { flex-direction: column; width: 100%; max-width: 270px; }
}

.oya-ingredients__gomme {
  flex: none;
  /* 425 dans une rangee de 427 : la reference centre l'image sur la hauteur
     des colonnes, d'ou le decalage d'un pixel vers le bas. */
  align-self: center;
  width: 425px;
  height: 425px;
  aspect-ratio: 1;
  z-index: 8;
}

/* C'est ici, et seulement ici, que l'image remonte au-dessus des colonnes. */
@media (max-width: 1199.98px) {
  .oya-ingredients__gomme { order: -1; }
}

/* Sous 680 px la gomme reste DANS le flux, entre les deux groupes — comme la
   reference, et comme sur le bureau. Elle garde donc sa trajectoire au
   defilement : elle part petite a hauteur du titre et grandit jusqu'a sa
   place.

   Une version l'avait sortie du flux pour la coller a droite du titre, et
   avait desactive sa trajectoire en dessous de 680 px. Les deux etaient de
   mauvaises idees : la gomme ne grandissait plus, et le bloc perdait le
   rythme de la reference. */
@media (max-width: 679.98px) {
  .oya-ingredients__gomme { width: 100%; height: auto; }
}

.oya-ingredients__gomme img { width: 100%; height: 100%; object-fit: contain; }

.oya-ingredient {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 16px;
  /* Pas de plafond propre : l'item occupe la largeur de sa colonne — 225 px
     sur le bureau, 270 en colonne. Un plafond de 250 px le bridait a 250 la
     ou la reference lui en donne 270. */
  width: 100%;
}

/* L'icone est un SVG en masque : la couleur vient du CSS, pas du fichier. */
.oya-ingredient__icone {
  width: 22px;
  height: 22px;
  background: var(--c-encre-70);
  -webkit-mask: var(--icone) center / auto no-repeat;
          mask: var(--icone) center / auto no-repeat;
}

.oya-ingredient__texte { display: flex; flex-direction: column; gap: 8px; width: 100%; }

.oya-ingredient__nom {
  font-family: var(--f-texte);
  font-size: var(--t-18);
  font-weight: var(--g-500);
  line-height: var(--i-titre);
  letter-spacing: var(--a-titre);
}

.oya-ingredient__desc {
  font-family: var(--f-texte);
  font-size: var(--t-16);
  font-weight: var(--g-400);
  line-height: var(--i-texte);
  color: var(--c-encre-70);
}

/* --------------------------------------------------------------------------
   FEATURES — trois cartes texte + illustration en verre
   --------------------------------------------------------------------------
   La section la plus dense de la page. Toute son adaptation tient en trois
   mecanismes : la direction du flex, `order` (l'image passe toujours au-dessus
   du texte sous 1200), et les grilles qui passent de deux colonnes a une.
   -------------------------------------------------------------------------- */

.oya-features {
  /* La reference rogne cette section. Sans cela un decor en position absolue
     — le collage de la Timeline et sa pastille, le pot du hero — pousse le
     document au-dela de la fenetre, et une bande blanche apparait a droite sur
     telephone. Mesure du 2026-09-10 : document a 525 px pour une fenetre de
     500, la Timeline seule en cause. */
  overflow: clip;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 60px;
  padding: 100px 60px 60px;
  scroll-margin-top: 60px;
}

@media (max-width: 1199.98px) { .oya-features { padding: 60px 40px; } }
@media (max-width: 679.98px)  { .oya-features { padding: 40px 25px; } }

.oya-features__pile {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 80px;
  width: 100%;
}

.oya-fiche {
  display: flex;
  flex-direction: row;
  justify-content: center;
  gap: 60px;
  width: 100%;
  max-width: 1000px;
}

@media (max-width: 1199.98px) { .oya-fiche { flex-direction: column; gap: 40px; } }
@media (max-width: 679.98px)  { .oya-fiche { flex-direction: column; gap: 24px; } }

/* Colonne de texte : carree sur bureau, elle epouse l'image d'a cote. */
.oya-fiche__texte {
  flex: 1 0 0;
  min-width: 0;
  aspect-ratio: 1;
  height: 470px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: 15px 0;
}

@media (max-width: 1199.98px) {
  .oya-fiche__texte {
    aspect-ratio: auto; height: auto; flex: none; width: 100%;
    order: 1; justify-content: flex-start; gap: 40px; padding: 0;
  }
}

.oya-fiche__entete {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 16px;
  width: 100%;
  padding-bottom: 40px;
}

@media (max-width: 1199.98px) { .oya-fiche__entete { padding-bottom: 0; } }

.oya-fiche__entete .oya-titre-section { max-width: none; flex: none; width: 100%; }

.oya-fiche__chapo {
  font-family: var(--f-texte);
  font-size: var(--t-16);
  font-weight: var(--g-400);
  line-height: var(--i-texte);
  color: var(--c-encre-70);
}

/* L'image : carree, rognee, et porte l'illustration en verre. */
.oya-fiche__image {
  position: relative;
  flex: 1 0 0;
  min-width: 0;
  aspect-ratio: 1;
  height: 470px;
  border-radius: var(--r-15);
  overflow: clip;
}

@media (max-width: 1199.98px) {
  .oya-fiche__image { aspect-ratio: auto; height: 600px; flex: none; width: 100%; order: 0; }
}

@media (max-width: 679.98px) {
  .oya-fiche__image { height: 310px; }
}

.oya-fiche__image > img { width: 100%; height: 100%; object-fit: cover; }

/* Voile sombre au bas de l'image, pour que le verre se detache. */
.oya-fiche__voile {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(var(--c-encre-00) 40%, var(--c-voile-fiche) 100%);
}

/* Liste a coches ---------------------------------------------------------- */

.oya-liste-coches { display: flex; flex-direction: column; gap: 16px; width: 100%; }

.oya-liste-coches li {
  display: flex;
  align-items: center;
  /* 14 px : le libelle mesure alors 434, comme dans la reference. */
  gap: 14px;
  font-family: var(--f-texte);
  font-size: var(--t-18);
  font-weight: var(--g-500);
  line-height: var(--i-titre);
  letter-spacing: var(--a-titre);
}

/* Le libelle occupe la ligne : 434 px dans la reference. */
.oya-liste-coches li > span:last-child { flex: 1 0 0; min-width: 0; }

.oya-coche {
  flex: none;
  /* 20 px dans la reference, pas 22. */
  width: 20px;
  height: 20px;
  background: var(--c-encre);
  -webkit-mask: url(../assets/icones/coche.svg) center / auto no-repeat;
          mask: url(../assets/icones/coche.svg) center / auto no-repeat;
}

/* Grilles a deux colonnes (chiffres, cartes) ------------------------------ */

.oya-grille-2 {
  display: grid;
  grid-template-columns: repeat(2, minmax(50px, 1fr));
  gap: 24px;
  width: 100%;
}

@media (max-width: 679.98px) { .oya-grille-2 { grid-template-columns: 1fr; } }

.oya-donnee { display: flex; flex-direction: column; align-self: start; gap: 8px; }

.oya-donnee__valeur {
  font-family: var(--f-titre);
  font-size: var(--t-30, 30px);
  font-weight: var(--g-600);
  line-height: var(--i-titre);
  letter-spacing: var(--a-titre);
}

.oya-donnee__texte {
  font-family: var(--f-texte);
  font-size: var(--t-16);
  font-weight: var(--g-400);
  line-height: var(--i-texte);
  color: var(--c-encre-70);
}

/* L'illustration en verre ------------------------------------------------- */

.oya-verre {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 355px;
  z-index: 1;
  border-radius: var(--r-15);
  background: linear-gradient(347deg, var(--c-verre-haut) 19%, var(--c-verre-bas) 89%);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  color: var(--c-blanc);
  overflow: hidden;
}

.oya-verre--profil { width: 351px; border-radius: var(--r-12); z-index: 4; }

@media (max-width: 679.98px) {
  .oya-verre {
    width: auto; left: 20px; right: 20px;
    transform: translateY(-50%);
  }
}

.oya-verre__entete {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 15px;
  border-bottom: 1px solid var(--c-blanc-25);
}

.oya-verre__entete > span {
  font-family: var(--f-texte);
  font-size: var(--t-16);
  font-weight: var(--g-400);
  line-height: var(--i-texte);
}

/* Le graphe : trois barres alignees sur leur base. */
.oya-graphe {
  display: flex;
  align-items: flex-end;
  gap: 16px;
  padding: 20px;
}

.oya-graphe__colonne { flex: 1 0 0; min-width: 0; display: flex; flex-direction: column; gap: 10px; }

/* La valeur et le nom forment un sous-bloc ; les 10 px de la colonne separent
   ce bloc de la barre. Les trois au meme niveau donnaient 10 px partout, et
   le nom tombait 10 px trop bas.

   L'ecart interne vaut 4 px sur la colonne mise en avant et 0 sur les deux
   autres. C'est une irregularite de la reference, relevee telle quelle. */
.oya-graphe__texte { display: flex; flex-direction: column; gap: 0; }
.oya-graphe__colonne:not(.oya-graphe__colonne--attenuee) .oya-graphe__texte { gap: 4px; }

.oya-graphe__valeur,
.oya-graphe__nom {
  font-family: var(--f-texte);
  font-size: var(--t-14);
  font-weight: var(--g-500);
  line-height: 1.1;
  text-align: center;
}

/* L'attenuation est une couleur, pas une opacite : la reference pose
   rgba(255,255,255,.8) sur le texte lui-meme. */
.oya-graphe__colonne--attenuee .oya-graphe__valeur,
.oya-graphe__colonne--attenuee .oya-graphe__nom { color: var(--c-blanc-80); }

.oya-graphe__barre { position: relative; width: 100%; border-radius: var(--r-06); }

/* La barre pleine porte un reflet flou en haut. */
.oya-graphe__barre--forte {
  height: 150px;
  background: linear-gradient(180deg, var(--c-blanc) 1.35135%, var(--c-blanc) 23%, var(--c-blanc-60) 100%);
}

@media (max-width: 679.98px) { .oya-graphe__barre--forte { height: 130px; } }

.oya-graphe__barre--forte::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 30px;
  filter: blur(7px);
  background: linear-gradient(var(--c-blanc) 0%, var(--c-blanc-00) 100%);
}

.oya-graphe__barre--moyenne { height: 50px; opacity: 0.5; background: var(--c-blanc); }
.oya-graphe__barre--faible  { height: 25px; opacity: 0.5; background: var(--c-blanc); border-radius: 4px; }

/* Le profil d'ingredients : une barre segmentee puis quatre lignes. */
.oya-profil { display: flex; flex-direction: column; gap: 20px; padding: 15px; }

.oya-profil__barres { display: flex; gap: 6px; width: 100%; }

.oya-profil__segment { height: 40px; border-radius: var(--r-06); }

.oya-profil__segment--1 {
  position: relative;
  width: 65%;
  z-index: 2;
  background: linear-gradient(270deg, var(--c-blanc) 1.35135% 23%, var(--c-blanc-60) 100%);
}

.oya-profil__segment--1::after {
  content: "";
  position: absolute;
  top: 0; bottom: 0; right: 0;
  width: 31px;
  filter: blur(5px);
  background: linear-gradient(270deg, var(--c-blanc) 0%, var(--c-blanc-00) 100%);
}

.oya-profil__segment--vide { flex: 1 0 0; min-width: 0; opacity: 0.2; background: var(--c-blanc); }

.oya-profil__liste { display: flex; flex-direction: column; gap: 7px; width: 100%; }

.oya-profil__ligne {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--f-texte);
  line-height: 1.2;
}

.oya-profil__nom {
  flex: 1 0 0;
  min-width: 0;
  font-size: var(--t-14);
  font-weight: var(--g-400);
  color: var(--c-blanc-80);
}

.oya-profil__dose {
  flex: none;
  font-size: var(--t-12);
  font-weight: var(--g-400);
  line-height: 1.4;
}

.oya-profil__filet { height: 1px; width: 100%; background: var(--c-blanc-15); }

/* La pile d'avis, posee sur l'image de la deuxieme fiche ------------------ */

.oya-avis-pile {
  position: absolute;
  top: 170px;
  left: 137px;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: min-content;
}

@media (max-width: 679.98px) {
  .oya-avis-pile { top: 90px; left: 50%; transform: translateX(-50%); }
}

/* Trois avatars qui se chevauchent. */
.oya-avatars { position: relative; width: 82px; height: 38px; }
.oya-avatars img { position: absolute; border-radius: 50%; object-fit: cover; }
/* Releve sur la reference, dans l'ordre du DOM :

     1   32 px   left: 50px                      top: 3px
     2   32 px   left: 50% + translate(-50%,-50%)  -> 25px, top 3px
     3   38 px   left: -7px                      top: 0

   Le deuxieme etait pose a `left: 50%` SANS le recentrage, d'ou 41 px au lieu
   de 25 : les deux petites pastilles se chevauchaient mal. */
/* Trois places, relevees sur la reference. Les regles `nth-child` servent de
   repli sans JavaScript ; les regles `[data-place]` qui suivent prennent la
   main des que le script tourne. Meme specificite, donc c'est l'ordre qui
   tranche -- les secondes doivent rester en dessous. */
.oya-avatars img:nth-child(1) { left: 50px; top: 3px; width: 32px; height: 32px; }
.oya-avatars img:nth-child(2) { left: 25px; top: 3px; width: 32px; height: 32px; }
.oya-avatars img:nth-child(3) { left: -7px; top: 0;   width: 38px; height: 38px; }

/* ECART VOLONTAIRE AU MODELE — demande le 2026-09-11.

   La reference garde les MEMES trois avatars pour les trois avis : elle n'a
   qu'un seul bloc `Profile Images` et un seul « Variant 1 ». Verifie dans
   l'instantane comme dans la page vivante.

   Ici, la personne mise en avant change avec l'avis : les trois pastilles
   permutent de place, et celle qui passe devant est celle qui parle. */
.oya-avatars img[data-place="0"] { left: 50px; top: 3px; width: 32px; height: 32px; }
.oya-avatars img[data-place="1"] { left: 25px; top: 3px; width: 32px; height: 32px; }
.oya-avatars img[data-place="2"] { left: -7px; top: 0;   width: 38px; height: 38px; }

.oya-avatars img {
  transition: left 450ms var(--e-ressort-net), top 450ms var(--e-ressort-net),
              width 450ms var(--e-ressort-net), height 450ms var(--e-ressort-net);
}

@media (prefers-reduced-motion: reduce) {
  .oya-avatars img { transition: none; }
}

/* Les trois bulles s'alignent en rangee, 10 px entre elles. Elles debordent
   volontairement de leur conteneur — la reference fait de meme.

   ELLES NE SE MONTRENT QU'UNE A LA FOIS. Dans la reference, « Reviews 2 » et
   « Reviews 3 » portent `opacity: 0` : les trois occupent leur place, mais une
   seule est visible, et le composant les fait alterner.

   CADENCE NON RELEVEE. Le releve des animations ne couvre pas ce composant, et
   la page enregistree ne rejoue pas ses variantes. Les 9 secondes ci-dessous
   sont donc un choix, pas une mesure — trois fois trois secondes. C'est le
   seul nombre a changer si la vraie cadence est connue un jour. */
/* UN SEUL emplacement, pas trois cote a cote.
   
   L'instantane de la reference montre les trois bulles alignees a x=357, 563
   et 769 -- 608 px en tout. On les avait donc posees en ligne. C'etait lire
   l'export au premier degre : leur parent commun `v-review-stack` ne fait que
   196 px et deborde en `overflow: visible`, et le visuel qui les contient n'en
   fait que 470. Les deux dernieres sortent donc du cadre, et elles sont a
   `opacity: 0`.

   Le rendu de la reference tranche : UNE bulle, en haut a gauche du visuel,
   les avatars au-dessus. Les trois se succedent au meme endroit.

   La grille superpose sans position absolue : chaque bulle occupe la meme
   cellule, et la pile prend la hauteur de la plus haute. Constate le
   2026-09-10. */
.oya-bulles {
  display: grid;
  width: min-content;
}

.oya-bulles > .oya-bulle { grid-area: 1 / 1; }

/* Le cycle est mene par le script, plus par une animation CSS. Trois raisons,
   toutes constatees le 2026-09-10 :

   - il etait cadence par `var(--e-ressort-net)`, une courbe a ressort. Sur un
     fondu d'opacite, elle hesite longuement pres de zero : la mesure trouvait
     0,11 la ou on attend 0 ou 1 ;
   - il partait au chargement de la page et tournait en boucle. En arrivant
     sur la carte quarante secondes plus tard, on tombait sur une phase
     quelconque, souvent creuse ;
   - trois emplacements cote a cote et un seul rempli : le moindre trou dans
     l'enchainement se lit comme un bloc casse, pas comme une animation.

   Le script fait tourner les trois bulles, seulement quand la carte est a
   l'ecran, et il en garde toujours exactement une de visible. */
.oya-bulles .oya-bulle {
  opacity: 0;
  transition: opacity 500ms ease;
}

/* Sans JavaScript, la premiere reste affichee : trois emplacements vides
   seraient pires qu'une bulle figee. Des que le script prend la main il pose
   `--anime` sur le conteneur, ce qui rend la barre a sa selection.

   Les specificites sont comptees, pas devinees. `:first-child` compte pour une
   classe : sans la double classe de la derniere regle, la premiere bulle
   resterait allumee en meme temps que la bulle courante.

     .oya-bulles--anime .oya-bulle:first-child        -> 0,2,1
     .oya-bulles--anime .oya-bulle.oya-bulle--vue     -> 0,3,0  gagne */
.oya-bulles .oya-bulle:first-child { opacity: 1; }

.oya-bulles--anime .oya-bulle:first-child { opacity: 0; }
.oya-bulles--anime .oya-bulle.oya-bulle--vue { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .oya-bulles .oya-bulle { transition: none; }
}

/* Chacune mesure 196 px. */
.oya-bulle {
  display: flex;
  flex-direction: column;
  gap: 10px;
  flex: none;
  width: 196px;
  padding: 12px 14px;
  border-radius: var(--r-12);
  background: linear-gradient(347deg, var(--c-verre-haut) 19%, var(--c-verre-bas) 90%);
  backdrop-filter: blur(5px);
  -webkit-backdrop-filter: blur(5px);
  color: var(--c-blanc);
}

/* Les cinq etoiles se centrent : 86 px dans une bulle de 168 utiles. */
.oya-bulle__etoiles { display: flex; justify-content: center; gap: 4px; }

.oya-etoile {
  width: 14px;
  height: 14px;
  background: var(--c-accent);
  -webkit-mask: url(../assets/icones/etoile.svg) center / auto no-repeat;
          mask: url(../assets/icones/etoile.svg) center / auto no-repeat;
}

.oya-bulle__texte {
  width: 168px;
  margin: 0;
  font-family: var(--f-texte);
  font-size: var(--t-14);
  font-weight: var(--g-400);
  line-height: 1.2;
}

/* --------------------------------------------------------------------------
   INTRODUCE — titre collant, sept gommes en fond
   -------------------------------------------------------------------------- */

.oya-introduce {
  /* Rogne HORIZONTALEMENT seulement. Les sept gommes debordent volontairement
     en haut et en bas — `top: -27px`, `bottom: -273px` — mais leur bloc de
     1100 px poussait le document a 849 px pour une fenetre de 768, d'ou une
     bande blanche a droite. `overflow-x: clip` est la seule valeur qui
     autorise ce melange : rogner sur un axe, laisser passer sur l'autre. */
  overflow-x: clip;
  position: relative;
  min-height: 800px;
  padding: 140px 60px 0;
  border-radius: 25px 25px 0 0;
  /* Le bloc s'efface vers le bas. */
  -webkit-mask: linear-gradient(#000 0%, #000000f5 73%, #0000 100%);
          mask: linear-gradient(#000 0%, #000000f5 73%, #0000 100%);
}

@media (max-width: 679.98px) {
  /* Le rembourrage lateral RESTE a 60 px ici, contrairement aux autres
     sections. C'est la valeur de la reference. */
  .oya-introduce { min-height: 700px; padding: 100px 60px 0; }
}

/* Le bloc est COLLANT — il reste a 250 px du haut — et remonte de 100 px au
   fil de la traversee de la section. Les deux effets se cumulent : il se
   decolle visuellement vers le haut pendant que la section defile.

   Le collant etait deja la ; la remontee manquait. */
.oya-introduce__titre {
  position: sticky;
  top: 250px;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 16px;
  width: 100%;
  text-align: center;
  translate: 0 var(--introduce-y, 0px);
}

/* La remontee est posee par le script, pour la meme raison que la jauge :
   une animation liee au defilement ne se verifie pas sur ce banc d'essai. */

/* Les deux lignes du titre : ecart NUL entre elles. Les 16 px de la pile
   separent ce groupe du mot « GUMMIES ». */
.oya-introduce__lignes {
  display: flex;
  flex-direction: column;
  gap: 0;
}

/* Chaque mot est un `inline-block` centre par `text-align`, exactement comme
   la reference. Un bloc a marges automatiques centre sa BOITE, interlettrage
   de fin compris.

   Et le texte de la reference porte une espace parasite : « Introducing_ »
   avec une espace finale, « _GUMMIES » avec une espace initiale. Sous
   `white-space: pre-wrap` ces espaces comptent dans la ligne centree, ce qui
   deplace les mots de 5 px a gauche et de 14 px a droite. Ce n'est pas beau,
   c'est le contenu de la reference — on le reproduit tel quel plutot que de
   corriger sa saisie. Releve le 2026-09-10. */
.oya-introduce__titre h2 > span,
.oya-introduce__gummies > span {
  display: inline-block;
}

.oya-introduce__titre h2,
.oya-introduce__gummies {
  white-space: pre-wrap;
}

.oya-introduce__titre h2 {
  font-family: var(--f-titre);
  font-size: var(--t-65);
  font-weight: var(--g-700);
  line-height: var(--i-serre);
  letter-spacing: var(--a-grand);
}

@media (max-width: 809.98px) { .oya-introduce__titre h2 { font-size: var(--t-40); } }

.oya-introduce__gummies {
  font-family: var(--f-titre);
  font-size: var(--t-26);
  font-weight: var(--g-700);
  line-height: 1.1;
  /* Interlettrage tres large, releve tel quel. */
  letter-spacing: 0.94em;
  text-transform: uppercase;
}

/* Les sept sticks, en fond. Memes positions que le gabarit, tailles propres. */
.oya-introduce__decor {
  position: absolute;
  top: -27px;
  bottom: -273px;
  left: calc(50% - 550px);
  width: 1100px;
  z-index: 1;
  pointer-events: none;
}

@media (max-width: 1199.98px) {
  .oya-introduce__decor { width: 930px; left: calc(50% - 465px); }
}

@media (max-width: 679.98px) {
  .oya-introduce__decor {
    aspect-ratio: 1; height: 390px;
    top: 20px; bottom: auto; left: -15px; right: -15px; width: auto;
  }
}

/* --------------------------------------------------------------------------
   LES SEPT STICKS D'INTRODUCE
   --------------------------------------------------------------------------
   Memes emplacements que le gabarit : positions et rotations sont celles des
   gommes, au pixel. Trois choses seulement changent.

   1. LA TAILLE. Une gomme est un carre de largeur W, un stick un rectangle
      trois fois plus haut que large. A largeur egale il paraitrait minuscule,
      a hauteur egale enorme. La regle posee ici est

          hauteur du stick = 1,25 x largeur de la gomme remplacee

      choisie pour garder le RYTHME de la composition -- des objets de poids
      visuel comparable aux memes endroits. Elle est arbitraire dans sa valeur,
      pas dans son principe, et elle s'applique aux sept sans exception, y
      compris au telephone.

   2. LA PROFONDEUR. Meme regle que le heros : plus c'est flou, plus c'est
      loin, et le rang se lit sur la taille. Le gabarit ne posait aucun flou
      ici et laissait l'ordre du balisage decider des recouvrements.

        rang  stick  formule    hauteur   flou      z
          1     2    ENERGY      313 px   net      18
          2     1    IMMUNITY    274 px   net      17
          3     4    FOCUS       225 px   net      16
          4     3    BEAUTY      209 px   net      15
          5     6    ENERGY      188 px   1,5 px   14
          6     5    FOCUS       170 px   2,5 px   13
          7     7    BEAUTY      104 px   3,5 px   12

      `z-index: 0` sur l'emplacement 1 disparait : il venait du heros, ou le
      pot s'intercalait entre les gommes. Ici il n'y a pas de pot, et ce zero
      ne faisait que contredire la taille.

   3. AUCUNE PARALLAXE. Le script ne suit que `.oya-hero__decor
      [data-parallaxe]`, et rien n'est ajoute : ce bloc a deja son propre
      mouvement, le titre collant qui remonte devant lui.

   POURQUOI DES PIXELS ICI, ET DES POURCENTAGES DANS LE HEROS. Le decor du
   heros est un CARRE : un pourcentage y veut dire la meme chose sur les deux
   axes, et la composition se transporte a toutes les tailles. Celui-ci ne
   l'est pas -- il fait 1100 px de large mais sa hauteur depend de la section.
   Un `top` en pourcentage y suivrait la hauteur du texte. Les pixels sont
   donc le bon choix, et les deux blocs different pour une raison, pas par
   inadvertance.
   -------------------------------------------------------------------------- */

/* LES ANCRAGES SONT RECALCULES POUR PRESERVER LE CENTRE, PAS LE COIN.

   C'est le defaut de la premiere version de ce bloc, et il se voyait. Les
   gommes sont ancrees par leur coin haut-gauche : `top: 48px; left: 31px`
   place le COIN d'un carre de 219. Un stick pose aux memes coordonnees fait
   274 px de haut pour 88 de large -- son centre tombe donc 27 px plus bas et
   66 px plus a gauche que celui de la gomme qu'il remplace. Applique aux
   sept, le decor entier partait en biais.

   Chaque ancrage est donc recalcule a partir du CENTRE de la gomme :

       centre = ancrage + largeur de la gomme / 2
       nouvel ancrage = centre - dimension du stick / 2

   Les emplacements 2 et 7 gardent leur `top` en pourcentage : leur
   `translateY(-50%)` les centre deja verticalement, et un centre ne se
   recalcule pas deux fois. */

.oya-introduce__decor .oya-stick-1 { height: 274px; top:  20px; left:  97px;  z-index: 17; --rot:  47deg; }
.oya-introduce__decor .oya-stick-2 { height: 312px; top:  48%;  left: -13px;  z-index: 18; --rot: -40deg; --centre: translateY(-50%); }
.oya-introduce__decor .oya-stick-3 { height: 209px; top: 306px; left: 213px;  z-index: 15; --rot: 285deg; }
.oya-introduce__decor .oya-stick-4 { height: 225px; top: 202px; left: 738px;  right: auto; z-index: 16; --rot: 145deg; }
.oya-introduce__decor .oya-stick-5 { height: 170px; top: auto;  bottom: 457px; right: 326px; z-index: 13; --rot: -32deg; --centre: ; filter: blur(2.5px); }
.oya-introduce__decor .oya-stick-6 { height: 188px; top:  83px; right:  83px; z-index: 14; --rot:  53deg; filter: blur(1.5px); }
.oya-introduce__decor .oya-stick-7 { height: 104px; top:  46%;  right: 108px; z-index: 12; --rot: -59deg; --centre: translateY(-50%); filter: blur(3.5px); }

@media (max-width: 679.98px) {
  /* Meme regle de taille qu'en bureau : 1,25 x la largeur de la gomme
     remplacee. Les tailles restent dans le meme ordre, le rang de profondeur
     ne bouge donc pas. */
  .oya-introduce__decor .oya-stick-1 { height: 104px; top:  30px; left:  39px; }
  .oya-introduce__decor .oya-stick-2 { height: 119px; top: auto;  bottom:   6px; left:  -2px; --centre: ; }
  .oya-introduce__decor .oya-stick-3 { height:  80px; top: auto;  bottom: 104px; left:  84px; }
  .oya-introduce__decor .oya-stick-4 { height:  69px; top: 149px; left: auto;    right:  20px; }
  .oya-introduce__decor .oya-stick-5 { height:  90px; top: auto;  bottom:   6px; right: 102px; }
  .oya-introduce__decor .oya-stick-6 { height:  99px; top:  48px; right:   4px; }
  .oya-introduce__decor .oya-stick-7 { height:  55px; top:  77%;  right:   7px; }
  .oya-introduce__decor .oya-stick { display: block; }
}

/* --------------------------------------------------------------------------
   BUY — image collante a gauche, fiche produit a droite
   -------------------------------------------------------------------------- */

.oya-buy {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 60px;
  padding: 0 60px 60px;
  scroll-margin-top: 120px;
}

@media (max-width: 1199.98px) { .oya-buy { padding: 0 40px 40px; } }
@media (max-width: 679.98px)  { .oya-buy { padding: 0 25px 40px; } }

.oya-buy__grille {
  display: flex;
  align-items: flex-start;
  gap: 60px;
  width: 100%;
  max-width: var(--l-page);
}

@media (max-width: 1199.98px) { .oya-buy__grille { flex-direction: column; align-items: center; } }
@media (max-width: 679.98px)  { .oya-buy__grille { gap: 40px; } }

/* La colonne image reste collee pendant qu'on lit la fiche. */
.oya-buy__visuel {
  position: sticky;
  top: 120px;
  flex: 1 0 0;
  width: 1px;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 20px;
  z-index: 1;
}

@media (max-width: 1199.98px) {
  .oya-buy__visuel { position: relative; top: auto; flex: none; order: 0; width: 100%; }
}

.oya-buy__cadre {
  position: relative;
  /* CARRE : 590 x 590 dans la reference. Une hauteur explicite de 510 px
     etait posee ici EN PLUS du rapport ; entre les deux, c'est la hauteur qui
     l'emporte, et le cadre mesurait 590 x 510. Les 80 px manquants faisaient
     remonter tout le bas de la colonne — le compteur « / 01 » d'abord.
     Meme piege que les logos de Featured. Constate le 2026-09-10. */
  aspect-ratio: 1;
  width: 100%;
  background: var(--c-gris-050);
  border-radius: 25px;
}

/* Les quatre vues sont empilees au meme endroit et se fondent l'une dans
   l'autre. `visibility` en plus de l'opacite : une image restee a opacite
   nulle continue d'etre lue par les lecteurs d'ecran. */
.oya-buy__vue {
  position: absolute;
  inset: 50px;
  width: calc(100% - 100px);
  height: calc(100% - 100px);
  object-fit: contain;
  z-index: 2;
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
  transition: opacity 600ms ease, visibility 0s linear 600ms;
}

.oya-buy__vue--active {
  opacity: 1;
  visibility: visible;
  transition: opacity 600ms ease, visibility 0s;
}

/* DEUX SORTES DE VUES, DEUX FACONS DE REMPLIR LE CADRE.

   Le gabarit n'en connaissait qu'une : quatre pots detoures, tous carres, que
   `object-fit: contain` posait au milieu avec leur marge de 50 px. Nos vues ne
   sont pas de la meme nature :

     - la gourde est un DETOURAGE, en portrait. Elle a besoin de son air autour
       et ne se rogne pas : `contain`, la regle d'origine ;
     - le coffret et le parcours sont des SCENES, en paysage. Posees en
       `contain` dans un carre, elles laissent deux bandes vides d'un quart de
       hauteur chacune et se lisent comme des vignettes perdues. Elles
       remplissent donc le cadre, et le rognage est sans consequence : ce sont
       des photos d'ambiance, pas des fiches techniques.

   La marge de 50 px disparait avec elles, sinon la scene flotterait dans un
   cadre a bords arrondis sans jamais les toucher. */
.oya-buy__vue--scene {
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: inherit;
}

/* Les quatre puces du carrousel. */
.oya-buy__puces { display: flex; align-items: center; gap: 20px; width: 100%; }
.oya-buy__pistes { flex: 1 0 0; min-width: 0; display: flex; gap: 4px; }

/* Une piste claire qui porte un remplissage sombre. La reference ne pose pas
   une pastille noire pleine sur la vue courante : elle fait progresser un
   voile a 25 % de noir a l'interieur de la piste, et c'est son arrivee au
   bout qui declenche le changement d'image. */
.oya-buy__puce {
  flex: 1 0 0;
  min-width: 0;
  height: 6px;
  border-radius: 11px;
  background: var(--c-gris-050);
  cursor: pointer;
  position: relative;
  overflow: clip;
  padding: 0;
  border: 0;
  appearance: none;
  font: inherit;
  color: inherit;
}

.oya-buy__puce:focus-visible { outline: 2px solid var(--c-noir); outline-offset: 4px; }

.oya-buy__puce--active { border-radius: var(--r-pilule); }

/* Valeurs relevees sur la page vivante, pas choisies : la reference ne fait
   pas grandir le remplissage, elle le fait GLISSER depuis la gauche.

     x: -130 -> 0   duree 4 s   ease cubic-bezier(.33,.31,.66,.66)

   130 px, c'est la largeur d'une piste au bureau ; en pourcentage la regle
   tient a toutes les largeurs. Voir RELEVE-ANIMATIONS.md, entree `199ya20`. */
.oya-buy__remplissage {
  position: absolute;
  inset: 0;
  background: var(--c-encre-25);
  transform: translateX(-100%);
}

/* La progression est portee par une animation nommee plutot que par une
   transition : le script la relance en retirant puis remettant la classe, ce
   qui redemarre le compte a zero de facon fiable. */
.oya-buy__puce--active .oya-buy__remplissage {
  animation: oya-remplir var(--duree-vue, 4s) cubic-bezier(0.33, 0.31, 0.66, 0.66) forwards;
}

@keyframes oya-remplir {
  from { transform: translateX(-100%); }
  to   { transform: translateX(0); }
}

/* Survol ou focus dans le carrousel : le remplissage se fige la ou il en est,
   plutot que de repartir de zero. */
.oya-buy__visuel[data-pause] .oya-buy__remplissage { animation-play-state: paused; }

.oya-buy__compteur {
  flex: none;
  font-family: var(--f-texte);
  font-size: var(--t-14);
  font-weight: var(--g-500);
  line-height: 1.1;
  color: var(--c-encre-30);
}

/* La fiche produit -------------------------------------------------------- */

.oya-buy__fiche {
  flex: 1 0 0;
  width: 1px;
  min-width: 0;
  max-width: 550px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 32px;
}

@media (max-width: 1199.98px) {
  .oya-buy__fiche { max-width: none; flex: none; order: 1; width: 100%; }
}

.oya-buy__entete { display: flex; flex-direction: column; gap: 10px; width: 100%; }

.oya-buy__avis { display: flex; align-items: center; gap: 16px; width: 100%; }
.oya-buy__etoiles { display: flex; gap: 4px; }
.oya-buy__etoiles .oya-etoile { width: 16px; height: 16px; }

.oya-buy__avis-texte {
  flex: 1 0 0;
  min-width: 0;
  font-family: var(--f-texte);
  font-size: var(--t-16);
  font-weight: var(--g-400);
  line-height: var(--i-texte);
}

.oya-buy__portions {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  opacity: 0.5;
  font-family: var(--f-texte);
  font-size: var(--t-16);
  font-weight: var(--g-500);
  line-height: 1.2;
}

.oya-buy__portions > span:last-child { flex: 1 0 0; min-width: 0; }

.oya-buy__filet-v { width: 1px; height: 14px; background: var(--c-encre-25); }

.oya-buy__chapo {
  font-family: var(--f-texte);
  font-size: var(--t-16);
  font-weight: var(--g-400);
  line-height: var(--i-texte);
  color: var(--c-encre);
}

/* Le selecteur d'abonnement ---------------------------------------------- */

.oya-abo { display: flex; flex-direction: column; align-items: flex-start; gap: 24px; width: 100%; }

.oya-abo__choix {
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 100%;
  /* Un <fieldset> arrive avec 2 px de marge laterale, 2 px de bordure en
     relief et un rembourrage propres au navigateur. Sans cette remise a zero,
     la boite mesurait 546 px au lieu de 550 et tout son contenu partait 4 px
     trop a droite. Le balisage est un vrai fieldset parce que les options
     sont un vrai groupe de boutons radio ; il faut juste le desarmer. */
  margin: 0;
  border: 0;
  min-inline-size: 0;
  padding: 10px;
  background: var(--c-gris-050);
  border-radius: var(--r-15);
}

/* Un vrai <label> autour d'un vrai radio : clavier et lecteurs d'ecran
   fonctionnent sans une ligne de JavaScript. */
.oya-option {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 16px;
  padding: 15px;
  cursor: pointer;
  background: var(--c-blanc);
  border-radius: var(--r-12);
}

.oya-option input { position: absolute; opacity: 0; pointer-events: none; }

/* Les deux mentions occupent toute la ligne, l'une a gauche et l'autre
   collee a droite. Avec un simple ecart de 10 px, « Shipped every 28 days »
   tombait 189 px trop a gauche. */
.oya-option__mentions {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  width: 100%;
  font-family: var(--f-texte);
  font-size: var(--t-14);
  font-weight: var(--g-400);
  line-height: 1.2;
  color: var(--c-encre-70);
}

@media (max-width: 679.98px) {
  /* Sous 680, les deux mentions s'empilent. Leur position au-dessus du titre
     n'a plus besoin de `order` : c'est l'ordre du document. */
  .oya-option { gap: 15px; }
  .oya-option__mentions { flex-direction: column; align-items: flex-start; }
}

.oya-option__ligne {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  gap: 10px;
}

.oya-option__titre {
  flex: 1 0 0;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--f-texte);
  font-size: var(--t-18);
  font-weight: var(--g-500);
  line-height: 1.2;
  letter-spacing: var(--a-titre);
}

.oya-option__titre > span:last-child { flex: 1 0 0; min-width: 0; }

.oya-option__puce {
  flex: none;
  width: 20px;
  height: 20px;
  padding: 4px;
  border: 1px solid var(--c-encre-50);
  border-radius: var(--r-pilule);
}

/* `~` et non `+` : dans la premiere option, le bloc des mentions se place ENTRE
   l'input et la ligne, pour respecter l'ordre vertical de la reference (mesure
   du 2026-09-09). Avec `+`, la regle ne s'appliquait plus a cette option : elle
   etait bien cochee, mais son point restait vide. Constate le 2026-09-14. */
.oya-option input:checked ~ .oya-option__ligne .oya-option__puce {
  background: var(--c-noir);
  box-shadow: inset 0 0 0 3px var(--c-blanc);
  border-color: var(--c-noir);
}

.oya-option__prix {
  flex: none;
  display: flex;
  align-items: center;
  gap: 10px;
  /* Chiffres a chasse fixe : sans cela, « $48.00 » mesurait 56 px au lieu
     de 54, et la difference se reportait sur le titre voisin. */
  font-variant-numeric: tabular-nums;
  font-family: var(--f-texte);
  font-size: var(--t-18);
  font-weight: var(--g-500);
  line-height: 1.2;
  letter-spacing: var(--a-titre);
}

/* Le prix barre n'est pas le meme style que le prix actif : Manrope 16/600
   en encre a 30 %, la ou l'actif est en Switzer 18/500. */
.oya-option__barre {
  text-decoration: line-through;
  font-family: var(--f-titre);
  font-size: var(--t-16);
  font-weight: var(--g-600);
  /* 16 px pile, pas 19,2 : la reference serre l'interligne a 1 sur ce seul
     element, et -0,02 em comme tout le Manrope. */
  line-height: 1;
  letter-spacing: var(--a-titre);
  color: var(--c-encre-30);
}

/* Le prix de l'achat unique n'est PAS attenue : la reference lui donne
   exactement le style du prix actif — Switzer 18/500 en noir plein. Une
   version precedente l'affichait en graisse 400 a 70 % d'opacite, une
   combinaison qui n'existe nulle part dans la reference. */

/* Bandeau des trois garanties -------------------------------------------- */

.oya-buy__garanties {
  display: flex;
  align-items: stretch;
  width: 100%;
  padding: 12px 0;
  border-top: 1px solid var(--c-encre-08);
  border-bottom: 1px solid var(--c-encre-08);
}

.oya-garantie {
  flex: 1 0 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  font-family: var(--f-texte);
  font-size: var(--t-14);
  font-weight: var(--g-400);
  line-height: 1.2;
}

.oya-garantie__icone {
  width: 18px;
  height: 18px;
  background: var(--c-encre-70);
  -webkit-mask: var(--icone) center / auto no-repeat;
          mask: var(--icone) center / auto no-repeat;
}

.oya-buy__separateur { width: 1px; align-self: stretch; background: var(--c-encre-08); }

/* Les trois accordeons ---------------------------------------------------- */

.oya-buy__details {
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: 100%;
  padding: 10px;
  background: var(--c-gris-050);
  border-radius: var(--r-15);
}

.oya-detail { background: var(--c-blanc); border-radius: var(--r-12); }

.oya-detail__titre {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 15px;
  cursor: pointer;
  list-style: none;
  font-family: var(--f-texte);
  font-size: var(--t-16);
  font-weight: var(--g-400);
  line-height: var(--i-texte);
}

.oya-detail__titre > span:nth-child(2) { flex: 1 0 0; min-width: 0; }

.oya-detail__titre::-webkit-details-marker { display: none; }

.oya-detail__icone {
  flex: none;
  /* 16 px dans la reference, pas 18. */
  width: 16px;
  height: 16px;
  background: var(--c-encre-70);
  -webkit-mask: var(--icone) center / auto no-repeat;
          mask: var(--icone) center / auto no-repeat;
}

.oya-detail__chevron {
  flex: none;
  margin-left: auto;
  /* La boite du chevron mesure 22 px : 12 de dessin plus 5 de rembourrage
     de chaque cote. Sans lui, le libelle gagnait 8 px. */
  box-sizing: content-box;
  padding: 5px;
  width: 12px;
  height: 12px;
  transform: rotate(-90deg);
  transition: transform var(--m-normal, 200ms) ease;
}

/* Le dessin vit dans un element imbrique, comme dans la reference : la boite
   exterieure porte le rembourrage et la rotation, l'interieure le masque.

   Le masque etait pose sur la boite exterieure. Or le rembourrage ne borne
   PAS la zone d'un masque : elle couvre la boite entiere. Le signe « plus »
   s'etirait donc sur 22 px au lieu de 12, et en noir plein au lieu de 50 %
   d'encre — presque deux fois trop gros et deux fois trop noir. Aucune mesure
   de boite ne pouvait le voir : la boite, elle, faisait bien 22 px.
   Constate le 2026-09-10 par capture. */
.oya-detail__chevron > span {
  display: block;
  width: 12px;
  height: 12px;
  background: var(--c-encre-50);
  -webkit-mask: url(../assets/icones/plus.svg) center / auto no-repeat;
          mask: url(../assets/icones/plus.svg) center / auto no-repeat;
}

.oya-detail[open] .oya-detail__chevron { transform: rotate(0deg); }

.oya-detail__corps {
  padding: 0 15px 15px;
  font-family: var(--f-texte);
  /* Switzer 16/400 a 1,5 : le style de texte courant de la reference. Ce
     bloc etait en 14/400 a 1,5, une combinaison qui n'existe nulle part
     dans la reference. Voir la note sur les reponses dans le README. */
  font-size: var(--t-16);
  font-weight: var(--g-400);
  line-height: var(--i-texte);
  color: var(--c-encre-70);
}

/* --------------------------------------------------------------------------
   FAQ — six accordeons, une seule colonne
   -------------------------------------------------------------------------- */

.oya-faq {
  /* La reference rogne cette section. Sans cela un decor en position absolue
     — le collage de la Timeline et sa pastille, le pot du hero — pousse le
     document au-dela de la fenetre, et une bande blanche apparait a droite sur
     telephone. Mesure du 2026-09-10 : document a 525 px pour une fenetre de
     500, la Timeline seule en cause. */
  overflow: clip;
  display: flex;
  justify-content: center;
  padding: 60px 60px 100px;
  scroll-margin-top: 60px;
  z-index: 2;
  border-radius: 0 0 20px 20px;
}

@media (max-width: 1199.98px) { .oya-faq { padding: 60px 40px 80px; } }
@media (max-width: 679.98px)  { .oya-faq { padding: 40px 25px 60px; } }

/* La reference emboite trois conteneurs pour une seule colonne : reste de
   structure Framer, pas une contrainte. Un seul suffit. */
.oya-faq__colonne {
  display: flex;
  flex-direction: column;
  gap: 60px;
  width: 100%;
  max-width: 600px;
}

@media (max-width: 679.98px) { .oya-faq__colonne { gap: 40px; } }

.oya-faq__colonne .oya-titre-section { max-width: none; flex: none; width: 100%; }

.oya-faq__pile {
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: 100%;
  padding: 10px;
  background: var(--c-gris-050);
  border-radius: var(--r-15);
}

.oya-question { background: var(--c-blanc); border-radius: var(--r-12); }

.oya-question__titre {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 20px;
  cursor: pointer;
  list-style: none;
  font-family: var(--f-texte);
  font-size: var(--t-16);
  font-weight: var(--g-500);
  line-height: 1.2;
  word-break: break-word;
}

.oya-question__titre::-webkit-details-marker { display: none; }
.oya-question__titre > span:first-child { flex: 1 0 0; min-width: 0; }

.oya-question__chevron {
  flex: none;
  box-sizing: content-box;
  padding: 2px;
  width: 16px;
  height: 16px;
  /* 70 % d'encre ici, la ou le bloc Buy est a 50 : deux reglages distincts. */
  transform: rotate(-90deg);
  transition: transform var(--m-normal, 200ms) ease;
}

/* Meme structure que `.oya-detail__chevron`, en 16 px a 70 % d'encre. */
.oya-question__chevron > span {
  display: block;
  width: 16px;
  height: 16px;
  background: var(--c-encre-70);
  -webkit-mask: url(../assets/icones/plus.svg) center / auto no-repeat;
          mask: url(../assets/icones/plus.svg) center / auto no-repeat;
}

.oya-question[open] .oya-question__chevron { transform: rotate(0deg); }

.oya-question__corps {
  padding: 0 20px 20px;
  font-family: var(--f-texte);
  /* Switzer 16/400 a 1,5 : le style de texte courant de la reference. Ce
     bloc etait en 14/400 a 1,5, une combinaison qui n'existe nulle part
     dans la reference. Voir la note sur les reponses dans le README. */
  font-size: var(--t-16);
  font-weight: var(--g-400);
  line-height: var(--i-texte);
  color: var(--c-encre-70);
}

/* --------------------------------------------------------------------------
   CTA — photo pleine largeur, titre et deux boutons
   -------------------------------------------------------------------------- */

.oya-cta {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 24px;
  padding: 240px 100px 60px 60px;
  overflow: clip;
}

@media (max-width: 679.98px) {
  .oya-cta { flex-direction: column; padding: 260px 25px 80px; }
}

.oya-cta__photo { position: absolute; inset: 0; }
.oya-cta__photo img { width: 100%; height: 100%; object-fit: cover; }

.oya-cta__voile {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(var(--c-encre-00) 56%, var(--c-voile-cta) 100%);
}

.oya-cta__contenu {
  position: relative;
  z-index: 2;
  flex: 1 0 0;
  width: 1px;
  max-width: var(--l-page);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 40px;
}

@media (max-width: 679.98px) { .oya-cta__contenu { flex: none; width: 100%; } }

.oya-cta__titre {
  font-family: var(--f-titre);
  font-size: var(--t-30);
  font-weight: var(--g-600);
  line-height: var(--i-titre);
  letter-spacing: var(--a-titre);
  color: var(--c-blanc);
  max-width: 433px;
}

.oya-cta__actions { display: flex; gap: 10px; flex-wrap: wrap; }

.oya-bouton--clair { background: var(--c-blanc); color: var(--c-noir); }

/* --------------------------------------------------------------------------
   PIED DE PAGE
   -------------------------------------------------------------------------- */

.oya-pied {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 60px;
  padding: 60px;
  background: var(--c-blanc);
  z-index: 2;
}

@media (max-width: 1199.98px) { .oya-pied { padding: 40px; } }
@media (max-width: 679.98px)  { .oya-pied { padding: 40px 25px; } }

/* Bandeau d'avis en photos. */
.oya-pied__avis { width: 100%; border-radius: var(--r-15); cursor: grab; }
.oya-pied__avis:active { cursor: grabbing; }
/* 20 px entre les cinq cartes d'une copie, 25 entre deux copies : la piste
   de la reference porte des groupes de 1680 px espaces de 25. */
.oya-pied__avis .oya-marquee { --ecart: 20px; --ecart-copies: 25px; }

.oya-avis-carte {
  position: relative;
  flex: none;
  width: 320px;
  height: 320px;
  aspect-ratio: 1;
  border-radius: var(--r-15);
  overflow: hidden;
  user-select: none;
}

@media (max-width: 679.98px) { .oya-avis-carte { width: 260px; height: 260px; } }

.oya-avis-carte img { width: 100%; height: 100%; object-fit: cover; }

.oya-avis-carte__voile {
  position: absolute;
  inset: 0;
  background: linear-gradient(var(--c-encre-00) 40%, var(--c-voile-avis) 100%);
}

.oya-avis-carte__texte {
  position: absolute;
  inset: auto 0 0 0;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 20px;
  color: var(--c-blanc);
}

.oya-avis-carte__citation {
  margin: 0;
  font-family: var(--f-texte);
  font-size: var(--t-16);
  font-weight: var(--g-500);
  line-height: 1.2;
}

/* Navigation de pied. */
.oya-pied__nav {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 80px;
  width: 100%;
  max-width: var(--l-page);
}

@media (max-width: 1199.98px) { .oya-pied__nav { gap: 60px; } }

.oya-pied__haut {
  display: flex;
  align-items: flex-start;
  gap: 24px;
  width: 100%;
}

@media (max-width: 1199.98px) { .oya-pied__haut { flex-direction: column; gap: 60px; } }

.oya-pied__marque {
  flex: 1 0 0;
  width: 1px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 24px;
}

@media (max-width: 1199.98px) { .oya-pied__marque { flex: none; width: 100%; } }

/* LE RAPPORT EST CELUI DU LOGOTYPE OYA, PAS DE CELUI DU GABARIT.

   La regle portait `width: 118px` et `aspect-ratio: 3.47806` -- les mesures
   du mot-symbole OneThing, plus large et plus plat. Le notre fait 2,1357 :
   pose dans une boite de 118, `object-fit: contain` l'aurait ramene a 73 px
   et laisse 45 px de vide qui poussaient la baseline vers la droite sans
   qu'on comprenne pourquoi. La boite suit donc le trace. */
.oya-pied__logo { width: 72px; height: 34px; aspect-ratio: 2.1357; object-fit: contain; }

.oya-pied__baseline {
  width: 252px;
  opacity: 0.8;
  font-family: var(--f-texte);
  font-size: var(--t-14);
  font-weight: var(--g-400);
  line-height: 1.2;
}

.oya-pied__texte {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 16px;
}

.oya-pied__reseaux { display: flex; gap: 15px; }

.oya-pied__reseau {
  display: grid;
  place-items: center;
  padding: 8px;
  background: var(--c-gris-050);
  border-radius: 8px;
}

.oya-pied__reseau span {
  width: 20px;
  height: 20px;
  /* 70 % d'encre, et non du noir a 50 % d'opacite : ce n'est pas la meme
     couleur a l'ecran. */
  background: var(--c-encre-70);
  -webkit-mask: var(--icone) center / auto no-repeat;
          mask: var(--icone) center / auto no-repeat;
}

.oya-pied__produit {
  display: flex;
  align-items: flex-start;
  justify-content: flex-end;
  gap: 32px;
}

@media (max-width: 1199.98px) { .oya-pied__produit { gap: 0; justify-content: space-between; width: 100%; } }
@media (max-width: 679.98px)  { .oya-pied__produit { flex-direction: column; gap: 32px; } }

.oya-pied__produit .oya-carte-produit { width: 313px; }
@media (max-width: 679.98px) { .oya-pied__produit .oya-carte-produit { width: 100%; } }

.oya-confiance {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: flex-end;
  gap: 10px;
  padding-bottom: 5px;
}

@media (max-width: 679.98px) { .oya-confiance { align-items: flex-start; } }

.oya-confiance__titre {
  font-family: var(--f-texte);
  font-size: var(--t-14);
  font-weight: var(--g-500);
  line-height: 1.1;
  color: var(--c-encre-40);
}

/* L'EMPLACEMENT DES BADGES. Aucun balisage ne l'utilise depuis le 2026-09-15 :
   les trois badges du gabarit -- GMP, FDA, « clinically proven » -- ont ete
   retires le jour ou la V6 est devenue le site indexable. Voir
   OYA/04_Site/Badges_en_attente/README.md.

   CES DEUX REGLES RESTENT VOLONTAIREMENT. Elles ne coutent rien, et elles font
   de la remise de vrais badges une affaire de trois lignes de HTML plutot que
   d'une mesure a refaire. Les retirer, c'est perdre le 48 x 48, l'ecart de
   10 px et l'opacite 0,8 releves dans la reference. */
.oya-confiance__badges { display: flex; gap: 10px; opacity: 0.8; }
.oya-confiance__badges img { width: 48px; height: 48px; aspect-ratio: 1; object-fit: contain; }

.oya-pied__liens {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 60px;
  width: 100%;
}

@media (max-width: 1199.98px) {
  .oya-pied__liens { display: grid; grid-template-columns: repeat(4, minmax(50px, 1fr)); }
  .oya-pied__colonne { flex: initial; }
}

@media (max-width: 679.98px) {
  .oya-pied__liens { grid-template-columns: repeat(2, minmax(50px, 1fr)); }
}

.oya-pied__mentions {
  flex: 1 0 0;
  width: 1px;
  align-self: stretch;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 40px;
  font-family: var(--f-texte);
  font-size: var(--t-12);
  font-weight: var(--g-400);
  line-height: var(--i-moyen);
  color: var(--c-encre-40);
}

/* L'avertissement est plus etroit que la ligne de droits : 335 px contre 590. */
.oya-pied__avertissement { max-width: 335px; }

/* La ligne de droits et le credit, 8 px l'un sous l'autre, en bas du bloc. */
.oya-pied__bas { display: flex; flex-direction: column; gap: 8px; }
.oya-pied__credit { color: inherit; }

@media (max-width: 1199.98px) { .oya-pied__mentions { order: 4; grid-column: span 4; flex: none; width: 100%; } }
@media (max-width: 679.98px)  { .oya-pied__mentions { grid-column: span 2; } }

/* 25 px separent le titre du groupe de liens, 15 px separent les liens entre
   eux. Un ecart unique de 16 px etait pose ici : ni l'un ni l'autre. */
.oya-pied__colonne {
  display: flex;
  flex-direction: column;
  gap: 25px;
  /* La colonne mesure son plus long lien — 77 px pour « Introduction » — et
     non une fraction egale de la largeur. */
  flex: none;
}

.oya-pied__colonne-liens {
  display: flex;
  flex-direction: column;
  gap: 15px;
}

/* Chaque lien vit dans un bloc a interligne serre qui contient un <a> EN
   LIGNE, comme la navigation du haut et comme la reference.

   La typographie est portee par le BLOC, pas par le lien : c'est lui qui
   donne sa hauteur a la ligne. Posee sur le seul <a>, elle laissait le bloc
   a l'interligne herite du corps — 24 px au lieu de 15 — et les liens se
   retrouvaient 39 px l'un de l'autre au lieu de 30. */
.oya-pied__colonne-liens > span {
  display: block;
  width: fit-content;
  font-family: var(--f-texte);
  font-size: var(--t-14);
  font-weight: var(--g-500);
  line-height: var(--i-serre);
  color: var(--c-encre-70);
}

/* L'en-tete de colonne est un titre par le sens, mais pas par le style : la
   reference l'ecrit en Switzer 14/500 SANS interlettrage. Le -0,02 em herite
   de la regle des titres retirait 3 px a « Sections » et « Policies ». */
.oya-pied__colonne h3 { width: fit-content; letter-spacing: normal; }

.oya-pied__colonne h3 {
  font-family: var(--f-texte);
  font-size: var(--t-14);
  font-weight: var(--g-500);
  line-height: var(--i-serre);
  /* La reference ne met AUCUN interlettrage sur le Switzer 14 : les 0,015 em
     poses ici elargissaient les quatre en-tetes de colonne. */
  color: var(--c-encre-40);
}

.oya-pied__colonne a {
  color: inherit;
  transition: opacity 150ms var(--e-survol);
}

.oya-pied__colonne a:hover { opacity: 0.6; }

/* --------------------------------------------------------------------------
   LES ICONES
   --------------------------------------------------------------------------
   Chaque icone est un SVG pose en masque : le dessin donne la forme, le CSS
   donne la couleur. Un changement de marque ne touche donc aucun fichier.

   POURQUOI CES QUINZE LIGNES VIVENT ICI ET NON DANS LE HTML

   Elles y etaient, ecrites `style="--icone:url(assets/x.svg)"`. Aucune ne
   s'affichait, et rien ne le signalait : la boite de 22 px gardait sa place,
   si bien qu'aucune mesure de geometrie ne pouvait s'en apercevoir.

   Une `url()` qui traverse une variable personnalisee n'a pas de base commune
   entre les navigateurs. Chrome la resout par rapport a la feuille qui
   l'UTILISE — `assets/x.svg` devenait donc `styles/assets/x.svg`, un 404
   silencieux. Firefox la resout par rapport a la feuille qui la DECLARE, donc
   par rapport au document. Aucun chemin relatif ne peut satisfaire les deux.

   Declaree et utilisee dans la meme feuille, la question ne se pose plus :
   `../assets/` vise juste partout. Constate le 2026-09-10, apres avoir rendu
   `01_original/` et constate que les icones y sont bien la.
   -------------------------------------------------------------------------- */

.oya-icone--vitamine-d3  { --icone: url(../assets/icones/soleil.svg); }  /* Vitamin D3 — un soleil */
.oya-icone--ashwagandha  { --icone: url(../assets/icones/tete.svg); }  /* Ashwagandha — une tete */
.oya-icone--zinc         { --icone: url(../assets/icones/bouclier.svg); }  /* Zinc — un bouclier */
.oya-icone--l-theanine   { --icone: url(../assets/icones/lune.svg); }  /* L-Theanine — une lune. Le commentaire disait « une onde » : le
                                                             fichier dessine bien un croissant. */
.oya-icone--feuille      { --icone: url(../assets/icones/feuille.svg); }  /* une feuille : Elderberry Extract ET « 100% Natural » */
.oya-icone--certifie     { --icone: url(../assets/icones/certificat.svg); }  /* Tested & Certified */
.oya-icone--complexe-b   { --icone: url(../assets/icones/eclair.svg); }  /* B-Complex — un eclair */
.oya-icone--livraison    { --icone: url(../assets/icones/camion.svg); }  /* Free Shipping */
.oya-icone--naturel      { --icone: url(../assets/icones/feuillage.svg); }  /* 100% Natural */
.oya-icone--regime       { --icone: url(../assets/icones/bouteille.svg); }  /* Diet Friendly */
.oya-icone--composition  { --icone: url(../assets/icones/fiole.svg); }  /* What's inside? */
.oya-icone--prise        { --icone: url(../assets/icones/bol.svg); }  /* How to take */
.oya-icone--retours      { --icone: url(../assets/icones/retour.svg); }  /* Shipping & returns */
.oya-icone--x            { --icone: url(../assets/icones/reseau-x.svg); }  /* reseau X */
.oya-icone--linkedin     { --icone: url(../assets/icones/reseau-linkedin.svg); }  /* reseau LinkedIn */
.oya-icone--facebook     { --icone: url(../assets/icones/reseau-facebook.svg); }  /* reseau Facebook */

/* Les cartes « 100% Natural » et « Tested & Certified » portent chacune une
   icone de 22 px, comme les ingredients. Toutes deux manquaient. */
.oya-donnee__icone {
  flex: none;
  width: 22px;
  height: 22px;
  background: var(--c-encre-70);
  -webkit-mask: var(--icone) center / auto no-repeat;
          mask: var(--icone) center / auto no-repeat;
}

/* --------------------------------------------------------------------------
   L'EQUILIBRAGE DES LIGNES
   --------------------------------------------------------------------------
   La reference pose `text-wrap: balance` sur 112 elements, un par un. Elle
   equilibre le texte DES COMPOSANTS — libelles de benefices, etapes de la
   timeline, ingredients, chiffres du graphe, prix, avis — et laisse `auto`
   aux liens, aux boutons, aux questions de la FAQ et a quelques paragraphes
   longs (le chapo du hero, celui des Ingredients, le CTA, les mentions
   legales).

   Sans ces regles, 71 textes se coupaient ailleurs que dans la reference.
   Le cas le plus visible : « Protects cells and accelerates / skin repair. »
   au lieu de « Protects cells and / accelerates skin repair. » — lignes de
   217 et 78 px la ou la reference en fait 128 et 167.

   Aucune sonde de position ne pouvait le voir : la BOITE mesure 225 x 48 des
   deux cotes. Seul le decoupage en lignes differait. Constate le 2026-09-10.

   Une nuance assumee : parmi les trois garanties du bloc Buy, la reference
   n'equilibre que « 100% Natural ». Sur un libelle d'une seule ligne cela ne
   change rien au rendu, et un selecteur positionnel casserait a la premiere
   modification du balisage — on equilibre donc les trois.
   -------------------------------------------------------------------------- */

.oya-benefit__titre,
.oya-benefit__soustitre,
.oya-etape__titre,
.oya-etape__texte,
.oya-ingredient__nom,
.oya-ingredient__desc,
.oya-graphe__nom,
.oya-graphe__valeur,
.oya-donnee__valeur,
.oya-donnee__texte,
.oya-profil__nom,
.oya-profil__dose,
.oya-carte-produit__nom,
.oya-carte-produit__prix,
.oya-avis-carte__citation,
.oya-buy__avis-texte,
.oya-buy__chapo,
.oya-supplement__texte,
.oya-annotation__etiquette > span,
.oya-buy__portions > span,
.oya-garantie > span,
.oya-verre__entete > span,
.oya-option__titre > span,
.oya-option__prix > span,
.oya-liste-coches li > span,
.oya-introduce__titre h2:nth-of-type(2) {
  text-wrap: balance;
}


/* ---------------------------------------------------------------------- */
/* Carrousel du bloc Buy, en mouvement reduit.                             */
/* Il n'avance plus seul -- le script s'en charge -- et les vues s'echangent */
/* sans fondu. Les pistes restent cliquables : c'est le seul moyen d'aller  */
/* voir les autres vues, il ne doit pas disparaitre.                        */

@media (prefers-reduced-motion: reduce) {
  .oya-buy__vue,
  .oya-buy__vue--active { transition: none; }

  .oya-buy__puce--active .oya-buy__remplissage {
    animation: none;
    transform: translateX(0);
  }
}
