/* ════════════════════════════════════════════════════════════════
   L'ACCUEIL DE LA BOUTIQUE — LE STYLE QUI N'EXISTE QUE LÀ.

   Chargé APRÈS boutique/socle.css, qui reste la base commune aux 45
   fiches produit. Rien n'est copié d'ici vers là : ce fichier ne fait
   que reprendre la main sur ce qui appartient à la page d'accueil.

   TROIS REPROCHES, TROIS RÉPONSES :

   « ça ressemble pas à un site awwward » — le socle peignait UN seul
   univers à la fois, celui du corps de page. Un rayon vert redevenait
   doré dès qu'on remontait, et la boutique n'avait qu'une couleur.
   Ici chaque rayon porte ses quatre variables : la couleur devient
   une propriété du rayon, pas de l'endroit où l'on se trouve. Cinq
   blocs saturés pleine largeur se succèdent, chacun avec son mot
   géant en filigrane.

   « pas l'air d'une supérette bancale » — une grille de vignettes
   toutes pareilles est une supérette. Un rayon qui s'annonce par son
   numéro, sa couleur, son mot géant et sa phrase est un univers.

   « faut vraiment que le visiteur ait envie de tout acheter » — la
   photo occupe un carré plein, le prix est gros, et l'ajout est un
   bouton à part, épais, de la couleur du rayon. Plus rien n'est
   caché derrière un « voir plus » : les 45 produits sont peints.

   CE QUI RESTE VRAI, PARCE QUE C'EST LA MARQUE : le prix montré est
   celui qui sera débité, la date de livraison est écrite avant le
   paiement, aucun compte à rebours, aucun stock inventé, aucun prix
   barré, aucun avis fabriqué, aucun être animé dessiné.

   LES PIÈGES DÉJÀ PAYÉS, RESPECTÉS ICI :
   · tout :hover vit dans @media (hover:hover) and (pointer:fine) — le
     navigateur de vérification pilote une souris même en mode mobile ;
   · 100svh et jamais 100vh — la barre d'adresse ment ;
   · tout ce qui dépasse en largeur est enfermé dans un conteneur qui
     coupe : sans ça, la page se décale de trois pixels sur téléphone
     et plus rien ne se recentre.
   ════════════════════════════════════════════════════════════════ */

/* ══════════ 0. CHAQUE UNIVERS PORTE SA COULEUR, TOUT SEUL ══════════
   socle.css n'attache ces quatre variables qu'à <body>. Un élément qui
   les porte lui-même gagne toujours, quelle que soit la spécificité :
   pour une variable héritée, c'est l'ancêtre le plus proche qui
   décide. Une seule ligne par rayon suffit donc à rendre la section,
   sa tuile et sa vignette autonomes. */
[data-univers="huiles"] { --u1:#6E2A0C; --u2:#F0A830; --u3:#FFE0A3; --u2f:#A96F14 }
[data-univers="priere"] { --u1:#07352A; --u2:#12A177; --u3:#BFE9D6; --u2f:#0A6B4E }
[data-univers="enfants"]{ --u1:#4A1C6B; --u2:#FF6B4A; --u3:#FFD4C4; --u2f:#B03C22 }
[data-univers="livres"] { --u1:#121F4E; --u2:#5C93F0; --u3:#CBDCFF; --u2f:#2F5EA8 }
[data-univers="parfums"] { --u1:#7A1E52; --u2:#E05C9A; --u3:#F8DFEC; --u2f:#7A1E52 }
[data-univers="soins"] { --u1:#3E6212; --u2:#7FB03A; --u3:#E9F0DA; --u2f:#3E6212 }
[data-univers="alimentaire"] { --u1:#6B1D1D; --u2:#D64545; --u3:#F6DCD2; --u2f:#6B1D1D }
[data-univers="vetements"] { --u1:#4E4638; --u2:#9A8866; --u3:#EDE6D8; --u2f:#4E4638 }
/* Le rayon 10, ouvert le 18/08 — il manquait ici comme il manquait dans
   presse.css et dans socle.css. Mêmes valeurs que presse.css, au
   caractère près : deux fichiers qui déclarent la même chose avec deux
   valeurs différentes finissent toujours par diverger, et c'est presse
   qui l'emporte (chargé en dernier). Raison du choix et contrastes
   mesurés : voir le commentaire de presse.css. */
[data-univers="femme"] { --u1:#3B4A57; --u2:#7E9AAE; --u3:#DDE6EC; --u2f:#3B4A57 }

/* ══════════ 1. LA BANNIÈRE ══════════
   Le socle empilait ses blocs dans une grille centrée. La bannière a
   maintenant trois étages à tenir dans un écran : le produit, les cinq
   vedettes, et le bouton Découvrir. Une colonne flexible les répartit
   sans qu'aucun ne dépasse. */
#hero{
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:clamp(8px,1.1svh,30px);
  /* PAS 100svh. Trois barres occupent le haut de la page — la ligne
     légale, l'en-tête et le ruban — et elles font 185 px sur
     téléphone. Une bannière d'un écran plein commençait donc 185 px
     trop bas, et son bouton Découvrir tombait sous le pli quel que
     soit l'appareil. accueil.js mesure ces trois barres et écrit leur
     hauteur dans --chrome ; le repli de 120 px sert le temps que le
     script arrive. */
  min-height:calc(100svh - var(--chrome,120px));
  padding:clamp(12px,1.8svh,54px) clamp(16px,5vw,56px) clamp(10px,1.2svh,44px);
  overflow:clip;
  /* Le fondu de 900 ms appartenait au corps de page : la bannière
     changeait donc de couleur d'un coup pendant que le reste fondait. */
  transition:background-color var(--t-long) var(--e-inout),
             --u1 var(--t-long) var(--e-inout),
             --u2 var(--t-long) var(--e-inout),
             --u3 var(--t-long) var(--e-inout);
}
/* 2,6vh valait 21,1 px sur un 812 et 2,6 VH — pas svh — c'est-à-dire la
   hauteur SANS la barre d'adresse, donc toujours la plus grande des
   deux. Le fichier entier compte en svh ; cette ligne était la seule à
   compter en vh. 1,9svh vaut 15,4 px sur un 812 et 12,7 px sur un 667 :
   5,7 px repris sur le grand téléphone, 8,4 sur le petit, au seul
   endroit de la bannière où l'espace ne porte aucune information. */
#hero .hero__dedans{
  display:grid;grid-template-columns:1fr;gap:clamp(12px,1.9svh,26px);
  width:100%;max-width:1240px;align-items:center;
}
/* Sur téléphone la photo passe devant : on achète un objet, pas un
   paragraphe. */
#hero .hero__scene{order:-1}
/* LE PLANCHER DE 130 px NE SERVAIT QU'AUX TÉLÉPHONES COURTS, ET IL LES
   PUNISSAIT. 18svh vaut 146,2 px sur un 812 (le plancher ne joue pas)
   mais 120 px sur un 667 : le plancher de 130 rendait donc 10 px à
   l'image PRÉCISÉMENT sur l'appareil qui n'en avait pas. Le plancher
   descend à 104 px — il ne se déclenche plus qu'en dessous de 578 px de
   haut, c'est-à-dire jamais sur un téléphone en portrait. */
#hero .hero__packshot{height:clamp(104px,18svh,220px);border-radius:20px}
#hero .hero__texte{gap:8px}
#hero .hero__texte h1{font-size:clamp(1.9rem,8vw,2.7rem)}
/* Deux lignes d'accroche, pas trois : la troisième coûtait la place
   exacte du bouton Découvrir. Le texte entier reste sur la fiche. */
/* ⚠ 18/08 — L'ACCROCHE PASSE SOUS LE PRIX, SUR TÉLÉPHONE SEULEMENT.
   Elle valait 42,2 px de texte plus 8 px d'écart, et elle était posée
   ENTRE le titre et le bouton d'achat : le prix commençait donc 50,2 px
   plus bas qu'il n'avait besoin. Mesuré sur un 375×812 avec 165 px de
   barres en haut de page, le bas du bouton « Précommander » tombait à
   779 px sur 812 — dernier élément du premier écran, et sous le pli dès
   qu'une barre grandit d'un cheveu. Sur un 375×667 (iPhone SE), il
   tombait à 739 px sur 667 : SOUS LE PLI, franchement.
   L'ordre devient celui d'une fiche produit : le nom, le prix et le
   bouton, puis la phrase qui explique. `order` ne touche QUE l'ordre
   visuel — le lecteur d'écran et la tabulation gardent l'ordre du HTML,
   où l'accroche reste sous le titre. Sur écran (941 px et plus) la
   place ne manque pas : l'ordre d'origine revient. */
#hero .hero__texte .mot{order:1;font-size:.88rem;line-height:1.5;max-width:46ch;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
/* Les deux boutons sur UNE ligne : empilés, ils coûtaient 58 px de
   hauteur, exactement ce qui manquait pour que Découvrir tienne dans
   le premier écran. `flex:1 1 0` + `min-width:0` — sans le min-width,
   la pastille de prix refuse de rétrécir et la ligne se casse quand
   même. */
#hero .hero__actions{width:100%;gap:8px;margin-top:3px;flex-wrap:nowrap}
#hero .hero__actions>*{flex:1 1 0;min-width:0}
#hero .btn{min-height:50px;padding:.9rem .7rem;font-size:.75rem;gap:.45rem;letter-spacing:.03em}
#hero .btn .prix{padding:5px 8px;font-size:.76rem}
/* ⚠ 18/08 — LE BOUTON D'ACHAT ÉTAIT COUPÉ AUX DEUX BOUTS, ET C'EST
   COMPTÉ. `.btn` porte `overflow:hidden` (socle.css) et centre son
   contenu : quand le contenu est plus large que la boîte, il n'est pas
   réduit, il est ROGNÉ — moitié à gauche, moitié à droite.
   Largeur disponible sur un 375 : 375 − 2×18,75 de gouttière = 337,5 ;
   moins 9 px d'écart, deux boutons à parts égales = 164,25 px chacun.
   Ce qu'il fallait y faire tenir, à 12 px de corps :
     « Précommander » 83 px + écart 8 + pastille « 24,90 € » 69
     + 2×14,4 de rembourrage = 188,8 px → 24,5 px rognés ;
     « Choisir la version » 124 + 8 + « dès 12,90 € » 98 + 28,8
     = 258,8 px → 94,5 px rognés, soit 37 % du bouton.
   Et la vedette n° 1 est justement un article à versions : c'est CE
   cas-là qui s'affichait à l'arrivée.
   Deux corrections, aucune sur la hauteur :
   · « Voir la fiche » cesse de réclamer la moitié de la ligne — il prend
     la largeur de ses mots (≈ 112 px) et rend le reste à l'achat, qui
     passe de 164,25 à 217,1 px ;
   · le rembourrage latéral passe de 14,4 à 11,2 px.
   Le pire cas retombe à 188,8 − 6,4 = 182,4 px dans 217,1 : 34,7 px
   d'air. Le libellé « Choisir la version » devient « Choisir » dans
   accueil.js — le même mot que les 45 cartes du bas de page. */
#hero #heroVoir{flex:0 0 auto}
#hero #heroAchat{flex:1 1 auto}

@media(min-width:941px){
  #hero .hero__dedans{grid-template-columns:1.02fr .98fr;gap:clamp(24px,4vw,60px)}
  #hero .hero__scene{order:0}
  #hero .hero__packshot{height:clamp(220px,38svh,420px)}
  #hero .hero__texte{gap:14px}
  #hero .hero__texte h1{font-size:clamp(2.4rem,4.4vw,3.6rem)}
  /* Sur écran la place ne manque plus : l'accroche entière revient, et
     elle reprend sa place entre le titre et les boutons. */
  #hero .hero__texte .mot{order:0;display:block;font-size:1rem;line-height:1.6}
  #hero .hero__actions{flex-wrap:wrap;gap:12px}
  #hero .hero__actions>*{flex:0 0 auto}
  /* Les deux boutons reprennent leur largeur naturelle : sur 941 px et
     plus, la ligne n'a jamais manqué de place. */
  #hero #heroVoir,#hero #heroAchat{flex:0 0 auto}
  #hero .btn{min-height:60px;padding:1.1rem 2.1rem;font-size:1rem;gap:.7rem;letter-spacing:.05em}
  #hero .btn .prix{padding:6px 12px;font-size:.86rem}
}

/* ══════════ 2. LES CINQ PRODUITS MIS EN AVANT ══════════
   C'est la demande exacte : quatre ou cinq produits en avant dans la
   bannière. Ils ne défilent pas tout seuls — un carrousel qui tourne
   sans qu'on le lui demande fait rater celui qu'on regardait. On les
   voit tous les cinq, on touche celui qu'on veut. Chacun porte la
   couleur de SON rayon : cinq couleurs annoncées d'un coup. */
.vedettes{
  display:grid;grid-auto-flow:column;grid-auto-columns:minmax(108px,1fr);
  gap:9px;width:100%;max-width:1240px;
  padding:2px;
  overflow-x:auto;
  scroll-snap-type:x proximity;scrollbar-width:none;
  /* TOUCH-ACTION : LA MEME VALEUR QUE CELLE QUE POSE LE SCRIPT.
     socle.js écrit `manipulation` EN LIGNE sur cette bande, ce qui bat
     toutes les feuilles, cache compris — c'est lui qui fait foi. La
     valeur est répétée ici pour que la feuille ne dise pas le contraire
     du code.
     ⚠ 19/08 — ELLE DISAIT `pan-y pinch-zoom`, c'est-à-dire « depuis cet
     élément, QUE du vertical » : interdiction faite au navigateur de
     défiler la bande au doigt, et c'est socle.js qui écrivait
     `scrollLeft` à chaque mouvement. Le raisonnement d'origine était
     bon sur un point — le balayage natif dépendait d'une feuille gardée
     en cache — mais le remède était la déclaration EN LIGNE, pas la
     confiscation du geste : une ligne en ligne peut aussi bien RENDRE
     l'axe horizontal que le retirer.
     `manipulation` = les deux axes au navigateur (donc l'élan et le
     rebond du système, sur le compositeur, jamais bloqués par une photo
     qui se décode), le zoom à deux doigts conservé — ce que
     `pinch-zoom` protégeait — et le délai de 300 ms du double-tape en
     moins. Le glissement de socle.js reste, pour la souris seule. */
  touch-action:manipulation;
  /* Le balayage horizontal ne doit pas remonter a la page ni declencher
     le « retour » du navigateur quand on arrive au bout de la bande. */
  overscroll-behavior-x:contain;
  /* Une souris maintenue sur une vignette ne doit pas partir en
     glisser-deposer d image : le navigateur volerait le geste et la
     bande resterait plantee. socle.css fait deja ca pour les autres
     bandes ; celle-ci n y etait pas. */
  user-select:none}
.vedettes img{-webkit-user-drag:none;user-drag:none}
.vedettes::-webkit-scrollbar{display:none}
.vedette{
  position:relative;display:flex;flex-direction:column;gap:4px;
  padding:6px 6px 8px;border-radius:15px;text-align:left;
  background:rgba(0,0,0,.24);
  box-shadow:inset 0 0 0 1px var(--b10);
  scroll-snap-align:center;
  transition:transform var(--t-survol) var(--e-sortie),
             box-shadow var(--t-survol) var(--e-doux),
             background-color var(--t-survol) var(--e-doux);
}
/* Vignette moins haute que large sur téléphone : le carré coûtait
   25 px par vedette, et c'est la bande entière qui poussait le bouton
   Découvrir sous le pli. Sur écran, le carré revient. */
.vedette__img{display:block;aspect-ratio:5/4;border-radius:10px;overflow:hidden;background:var(--blanc)}
.vedette__img img{width:100%;height:100%;object-fit:cover}
.vedette__nom{
  font-size:.63rem;line-height:1.22;font-weight:700;color:var(--encre2);
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
}
.vedette__prix{font-family:var(--f-mono);font-size:.67rem;font-weight:700;color:var(--u3)}
@media(min-width:620px){
  /* Bridée à 780 px : étalées sur toute la largeur, les cinq vignettes
     faisaient 223 px de large et 245 px de haut — la bande devenait
     plus imposante que le produit qu'elle sert à choisir. */
  .vedettes{gap:10px;max-width:780px}
  .vedette{padding:8px 8px 11px;gap:7px}
  .vedette__img{aspect-ratio:1;border-radius:11px}
  .vedette__nom{font-size:.68rem;line-height:1.28}
  .vedette__prix{font-size:.7rem}
}
.vedette[aria-pressed="true"]{
  background:rgba(0,0,0,.44);transform:translateY(-3px);
  box-shadow:inset 0 0 0 2px var(--u2),0 16px 30px -16px #000;
}
.vedette[aria-pressed="true"] .vedette__nom{color:var(--encre)}
.vedette:focus-visible{outline:3px solid var(--or-clair);outline-offset:3px}
@media (hover:hover) and (pointer:fine){
  .vedette:hover{transform:translateY(-3px);background:rgba(0,0,0,.38)}
  .vedette:hover .vedette__nom{color:var(--encre)}
}

/* ══════════ 3. DÉCOUVRIR ══════════
   Le bouton demandé, en bas de la bannière. Crème plein, ombre pleine :
   l'épaisseur d'une touche qu'on enfonce. La flèche fait un signe
   toutes les deux secondes et demie — assez pour dire « ça continue en
   dessous », trop rare pour agacer. */
.decouvrir{
  display:inline-flex;align-items:center;gap:.75rem;
  min-height:56px;padding:1rem clamp(1.6rem,6vw,2.4rem);border-radius:50vw;
  background:var(--creme);color:var(--nuit);text-decoration:none;
  font-weight:900;font-size:.84rem;letter-spacing:.09em;text-transform:uppercase;
  box-shadow:0 7px 0 -1px rgba(0,0,0,.42),0 26px 44px -20px rgba(0,0,0,.9);
  transition:transform var(--t-survol) var(--e-sortie),box-shadow var(--t-survol) var(--e-doux);
}
.decouvrir svg{width:16px;height:16px;flex:0 0 auto;
  animation:decouvrir-signe 2.6s var(--e-inout) infinite}
@keyframes decouvrir-signe{0%,74%,100%{transform:translateY(0)}86%{transform:translateY(4px)}}
.decouvrir:focus-visible{outline:3px solid var(--or-clair);outline-offset:4px}
@media (hover:hover) and (pointer:fine){
  .decouvrir:hover{transform:translateY(-3px);
    box-shadow:0 10px 0 -1px rgba(0,0,0,.42),0 34px 54px -20px rgba(0,0,0,.95)}
}
.decouvrir:active{transform:translateY(5px);
  box-shadow:0 2px 0 -1px rgba(0,0,0,.42),0 12px 22px -16px rgba(0,0,0,.9);
  transition-duration:var(--t-micro)}

/* ⚠ 18/08 — « LE BOUTON DÉCOUVRIR SUR LA BANNIÈRE EST INVISIBLE ».
   Il l'était, et le calcul le dit à la décimale.

   Le bouton se remplit de `var(--creme)`. Sur la peau d'origine, crème
   voulait dire #FCF6EC : une pastille claire sur l'univers sombre du
   rayon, elle se voyait de l'autre bout de la page. La surcouche
   ROTATIVE (presse.css) RETOURNE ce jeton — « ce qui se posait en
   crème sur la nuit se pose désormais en encre sur papier », donc
   --creme vaut #141210. Sauf que la bannière, elle, est restée l'îlot
   d'encre pleine du journal : elle garde le fond --u1 de son rayon.
   On peignait donc du #141210 sur du #9C3F00, du #16307A, du #6B1D1D…
   c'est-à-dire de l'encre presque noire sur de l'encre foncée.
   Le mot « DÉCOUVRIR », lui, avait été rattrapé (presse.css lui donne
   le papier) : il restait donc trois lettres claires flottant sur le
   fond, sans bouton autour, et l'ombre pleine — rgba(0,0,0,.42) — était
   invisible elle aussi. Un bouton dont on ne voit ni le bord, ni le
   fond, ni le relief n'est plus un bouton.

   CONTRASTE DU REMPLISSAGE CONTRE LE FOND DE BANNIÈRE, AVANT,
   les neuf univers, encre #141210 contre --u1 de presse.css :
     huiles #9C3F00 ....... 2,78:1     zamzam #04516B ....... 2,13:1
     prière #0E5A42 ....... 2,28:1     parfums #7A1E52 ...... 1,90:1
     enfants #55208F ...... 1,77:1     soins #3E6212 ........ 2,63:1
     livres #16307A ....... 1,55:1     épicerie #6B1D1D ..... 1,62:1
     habits #4E4638 ....... 2,01:1
   Neuf univers sur neuf sous 3:1, le pire à 1,55:1.

   APRÈS, remplissage papier #F2ECE0 contre les mêmes neuf fonds :
     huiles 5,71:1 · prière 6,97:1 · enfants 8,97:1 · livres 10,27:1 ·
     zamzam 7,45:1 · parfums 8,36:1 · soins 6,03:1 · épicerie 9,82:1 ·
     habits 7,91:1.  Le pire monte de 1,55 à 5,71:1.
   Et le libellé, encre #141210 sur papier #F2ECE0 : 15,9:1.

   POURQUOI EN DUR, ET PAS DANS UNE VARIABLE. C'est la leçon déjà payée
   sur les deux flèches de la même bannière, qui étaient devenues
   « blanc sur blanc » pour exactement la même raison : dans un îlot qui
   ne change pas de peau, la couleur ne se met jamais en variable. Le
   bouton porte donc la MÊME paire que les flèches — papier plein, encre
   pour le mot, filet d'encre autour — ce qui a l'avantage second de les
   faire enfin appartenir à la même famille.

   `#hero a.decouvrir` : trois crans de spécificité (1,1,1) contre le
   `#hero .decouvrir` de presse.css (1,1,0), qui est chargée après. */
/* ══ 18/08 — LE BOUTON ET LES VEDETTES PASSAIENT SOUS LE FOND ══
   Mesuré dans le navigateur : `elementFromPoint` au centre du bouton
   « Découvrir » renvoyait `.hero__fond`, pas le bouton. Autrement dit
   il était là, visible, et **le clic ne l'atteignait pas**.

   LA CAUSE, ET ELLE VAUT POUR TOUT LE PROJET : `.hero__fond` est en
   `position:absolute; z-index:0` et il couvre tout le héros ; le bouton
   et la bande des vedettes étaient en `position:static` **sans aucune
   couche**. Or un élément non positionné est peint AVANT tout élément
   positionné, même à z-index 0 — il passe dessous. `.hero__dedans`, lui,
   porte `position:relative; z-index:5` : c'est pour ça que le titre,
   seul, restait cliquable.

   ⚠ Le défaut touchait aussi `.vedettes` — les TROIS PRODUITS MIS EN
   AVANT n'étaient pas cliquables. Il ne se voyait pas parce que le
   bouton était de toute façon sous le pli : un défaut en cachait un
   autre.

   `z-index:6` pour le bouton (au-dessus du contenu à 5), `5` pour les
   vedettes. Tous deux restent sous le grain (9) et les volets (7), qui
   sont en `pointer-events:none` et ne captent donc rien. */
#hero .decouvrir,
#hero .vedettes{ position:relative; }
#hero .decouvrir{ z-index:6; }
#hero .vedettes { z-index:5; }

/* ══ LA BANNIÈRE SE TIRE — CE QUI DOIT NE PAS PARTIR AVEC LE GESTE ══
   19/08. `accueil.js` écoute le pointeur sur TOUT `#hero` ; il reste
   deux choses que le navigateur fait par-dessus lui et qui volent le
   geste. La règle du 19/08 au matin ne portait que sur `.vedettes img`
   — la photo du héros, elle, n'y était pas, et c'est mesuré : sur elle,
   le journal montrait pointerdown → pointermove → dragstart →
   pointercancel, geste mort.
   ⚠ On NE met PAS `user-select:none` sur toute la bannière : le titre
   et le prix doivent rester copiables. La sélection ne se coupe QUE
   pendant le geste, quand `accueil.js` a posé `.hero--tire`. */
#hero img{ -webkit-user-drag:none; user-drag:none; }
/* Le curseur dit que ça se tire — sans lui, personne n'essaie. */
#hero{ cursor:grab; }
#hero a,#hero button,#hero .vedette{ cursor:pointer; }
#hero.hero--tire,
#hero.hero--tire a,#hero.hero--tire button,#hero.hero--tire .vedette{ cursor:grabbing; }
#hero.hero--tire{ user-select:none; -webkit-user-select:none; }

/* Le héros empile ses étages avec un `gap` proportionnel. Sur téléphone,
   le bandeau du journal en prend 226 à lui seul — le bouton finissait
   8 px sous le bord. On resserre le gap là, et seulement là : 8 px
   suffisaient, on en rend une vingtaine. */
@media (max-width:640px){
  #hero{ gap:4px; }
}

#hero a.decouvrir{
  background:#F2ECE0;color:#141210;
  box-shadow:inset 0 0 0 2px #141210,
             0 7px 0 -1px rgba(20,18,16,.85),
             0 26px 44px -20px rgba(0,0,0,.75);
}
#hero a.decouvrir svg{color:#141210}
@media (hover:hover) and (pointer:fine){
  #hero a.decouvrir:hover{transform:translateY(-3px);
    box-shadow:inset 0 0 0 2px #141210,
               0 10px 0 -1px rgba(20,18,16,.85),
               0 34px 54px -20px rgba(0,0,0,.85)}
}
#hero a.decouvrir:active{transform:translateY(5px);
  box-shadow:inset 0 0 0 2px #141210,
             0 2px 0 -1px rgba(20,18,16,.85),
             0 12px 22px -16px rgba(0,0,0,.8);
  transition-duration:var(--t-micro)}
#hero a.decouvrir:focus-visible{outline:3px solid #F2ECE0;outline-offset:4px}

/* ⚠ 18/08 — « VOIR LA FICHE » AVAIT LA MÊME MALADIE, UN CRAN PLUS BAS.
   Le bouton d'à côté est un `.btn--creux` : pas de fond, juste un filet
   et un mot. Trois mesures, les trois fautives.

   ① LE FILET. socle.css l'écrit `inset 0 0 0 1.5px var(--b30)`. Dans le
   héros, presse.css retourne --b30 vers rgba(242,236,224,.30) : un
   trentième de papier posé sur l'encre pleine du rayon. Contraste du
   filet contre le fond, les neuf univers de presse.css :
     huiles 1,76:1 · prière 1,95:1 · enfants 2,07:1 · livres 2,23:1 ·
     zamzam 1,99:1 · parfums 2,00:1 · soins 1,88:1 · épicerie 2,14:1 ·
     habits 2,12:1 — plus le repli sans univers (#6E2A0C) à 2,11:1.
   Dix sur dix sous le 3:1 que demande WCAG 1.4.11 pour le contour d'une
   commande. presse.css croyait l'avoir rattrapé avec
   `border-color:var(--papier)` — mais ce bord-là est une OMBRE INTERNE,
   pas une bordure : la déclaration ne peignait rien du tout.

   ② LE SURVOL ET LE FOCUS CLAVIER. `.btn--creux::before` monte un
   remplissage `var(--creme)` et le mot passe à `var(--nuit)`. Sous la
   rotative --creme vaut #141210 et --nuit vaut #120D0A : encre sur
   encre, contraste 1,03:1. Le libellé DISPARAISSAIT à la tabulation —
   exactement la panne du bouton Découvrir, sur le bouton d'à côté.

   ③ APRÈS, tout en dur, comme les flèches et comme Découvrir : filet
   papier #F2ECE0 sur le fond du rayon, donc 5,71:1 au pire (huiles) et
   10,27:1 au mieux (livres) ; mot papier au repos, 5,71:1 au pire ;
   et une fois rempli, encre #141210 sur papier #F2ECE0, 15,9:1.
   `#hero a.btn--creux` = (1,1,1), au-dessus du `#hero .btn--creux`
   (1,1,0) de presse.css, qui est chargée après. */
#hero a.btn--creux{
  color:#F2ECE0;
  box-shadow:inset 0 0 0 1.7px #F2ECE0;
}
#hero a.btn--creux::before{background:#F2ECE0}
#hero a.btn--creux:focus-visible{color:#141210}
@media (hover:hover) and (pointer:fine){
  #hero a.btn--creux:hover{color:#141210;box-shadow:inset 0 0 0 1.7px #F2ECE0}
}

/* ══════════ 4. LES CINQ UNIVERS ══════════
   Là où le visiteur atterrit en appuyant sur Découvrir. Deux colonnes
   sur téléphone, cinq de front sur écran : une carte du magasin, pas
   une liste de liens. */
/* Longhands, et pas `padding:` : #univers porte AUSSI la classe
   .coquille, dont les marges latérales sont la gouttière de toute la
   page. Un raccourci les remettait à zéro et le texte touchait le bord
   de l'écran sur téléphone. */
#univers{padding-top:clamp(46px,8vh,100px);padding-bottom:clamp(28px,5vh,56px);
  scroll-margin-top:84px}
#univers .sur{display:block;margin-bottom:10px}
#univers h2{margin-bottom:clamp(20px,3vh,32px)}
#portes{grid-template-columns:repeat(2,1fr);gap:10px;padding-bottom:0}
/* Cinq tuiles sur deux colonnes : la dernière prend toute la ligne
   plutôt que de laisser un trou. */
#portes a:last-child{grid-column:1/-1}
@media(min-width:760px){
  #portes{grid-template-columns:repeat(5,1fr);gap:14px}
  #portes a:last-child{grid-column:auto}
}
#portes .btn--rayon{
  --uc:var(--u2);
  flex-direction:column;align-items:flex-start;justify-content:flex-end;gap:.3rem;
  min-height:clamp(124px,21vw,172px);padding:15px 14px;border-radius:20px;
  background:linear-gradient(158deg,
    color-mix(in oklab,var(--uc) 30%,var(--nuit2)) 0%,var(--nuit2) 66%);
}
/* Le chiffre fantôme : il donne l'échelle et la couleur d'un coup, et
   il est écrit dans l'attribut — donc jamais lu deux fois par un
   lecteur d'écran, qui a déjà le numéro dans le texte de la tuile. */
/* LA DERNIÈRE INCLINAISON DE LA PAGE EST PARTIE D'ICI. socle.css
   annonce « plus une seule inclinaison : skewX(-6deg) a disparu de tous
   les titres » — ce chiffre fantôme était le survivant, et c'est
   justement lui qu'on voit le plus, en 112 px derrière chaque tuile.
   Une condensée d'affiche supporte d'être penchée à la main ; une
   humane à empattements non : l'axe de sa plume est déjà oblique, on le
   tord une deuxième fois et les pleins et les déliés ne tombent plus au
   bon endroit. Le -.04 em de chasse part avec, pour la même raison — il
   avait été réglé sur des chiffres d'Impact, qui sont étroits ; sur des
   chiffres de Palatino, qui sont larges et alignés, il colle le 0 au 1. */
#portes .btn--rayon::after{
  content:attr(data-num);position:absolute;right:-.02em;bottom:-.30em;z-index:-2;
  font-family:var(--f-titre);font-size:clamp(3.8rem,11.5vw,6.2rem);line-height:1;
  letter-spacing:0;pointer-events:none;
  color:color-mix(in oklab,var(--uc) 36%,transparent);
}
#portes .btn--rayon .num{color:var(--uc)}
#portes .btn--rayon .nom{
  flex:0 0 auto;margin-left:0;text-align:left;
  font-size:clamp(1.08rem,3.6vw,1.5rem);line-height:.94;
}
#portes .btn--rayon .cpt{color:var(--encre2);font-size:.68rem}
@media (hover:hover) and (pointer:fine){
  #portes .btn--rayon:hover .num{color:var(--nuit)}
  #portes .btn--rayon:hover::after{color:rgba(0,0,0,.16)}
}

/* ══════════ 5. LES RAYONS, EN UNIVERS ══════════ */
.rayon{
  padding:clamp(52px,9vh,116px) 0;
  overflow:clip;                 /* le mot géant dépasse : il est coupé ici */
  scroll-margin-top:76px;
  border-top:1px solid rgba(var(--laine),.08);
}
/* LE MOT GÉANT. Il est déjà écrit dans RAYONS (socle.js) et ne servait
   qu'à la bannière. Relevé DANS la page le 10/08, c'est le nom de la
   FAMILLE : HUILES, PRIÈRE, ENFANTS, LIVRES, ZAMZAM — socle.js a
   remplacé les anciens mots (NIGELLE, S'INCLINER…) parce qu'ils
   nommaient un produit au lieu du rayon. La liste vit là-bas ; ce
   commentaire ne fait que constater ce que la page peint. Posé en
   filigrane derrière le titre, le mot donne au rayon son identité
   avant même qu'on ait lu une ligne. */
/* LA TAILLE A BAISSÉ AVEC LE CHANGEMENT DE POLICE, ET C'EST MESURÉ.
   À 100 px et à graisse normale des deux côtés, « ZAMZAM » fait
   328,33 px en Impact contre 478,13 en Palatino Linotype (+ 46 %), et
   « ENFANTS » 336,23 contre 468,36 (+ 39 %) : la même consigne de 21vw
   donnait un mot bien plus large, qui sortait des deux côtés au lieu
   de border le titre. 13vw remet le mot à la largeur qu'il avait.
   L'inclinaison de six degrés part avec le reste : une humane penchée
   à la main est une humane déformée. */
.rayon__mur{
  position:absolute;z-index:-1;top:clamp(6px,1.6vh,24px);left:50%;
  translate:-50% 0;
  font-family:var(--f-titre);font-size:clamp(3.2rem,13vw,10rem);line-height:.94;
  letter-spacing:.01em;text-transform:uppercase;white-space:nowrap;
  pointer-events:none;user-select:none;
  color:color-mix(in oklab,var(--u3) 14%,transparent);
}
.rayon-tete{gap:14px;margin-bottom:10px;align-items:flex-end}
.rayon-num{
  font-size:.72rem;padding:7px 12px;border-radius:999px;
  background:rgba(0,0,0,.28);color:var(--u3);
  box-shadow:inset 0 0 0 1px var(--b20);
}
.rayon-cpt{
  font-size:.7rem;padding:7px 12px;border-radius:999px;
  background:var(--u2);color:var(--nuit);font-weight:700;letter-spacing:.06em;
}
.rayon-mot{margin-bottom:clamp(22px,3.4vh,36px)}

/* ══════════ 6. LES PRODUITS ══════════
   Grande photo, prix lisible, bouton d'ajout à part. Le lien vers la
   fiche couvre la photo et le titre — les 45 pages doivent rester
   atteignables par un lien, sinon Google ne les voit pas et on ne peut
   pas les partager. Le bouton est son VOISIN, pas son enfant : un
   bouton dans un lien est un document invalide, et le navigateur
   choisit alors lui-même lequel des deux répond au clic. */
.grille{grid-template-columns:repeat(2,1fr);gap:11px}
@media(min-width:620px){.grille{grid-template-columns:repeat(3,1fr);gap:14px}}
@media(min-width:900px){.grille{grid-template-columns:repeat(4,1fr);gap:18px}}
@media(min-width:1220px){.grille{grid-template-columns:repeat(5,1fr);gap:20px}}

.produit{border-radius:20px;cursor:default;
  box-shadow:0 16px 34px -22px rgba(0,0,0,.85)}
.produit__lien{display:flex;flex-direction:column;flex:1;text-decoration:none;color:inherit}
.produit__lien:focus-visible{outline:3px solid var(--u2);outline-offset:-3px;border-radius:20px}
.produit .cadre{aspect-ratio:1;background:var(--blanc)}
.produit .infos{padding:11px 11px 8px;gap:6px}
.produit h3{font-size:.82rem;line-height:1.32;color:var(--nuit)}
.produit .bas{align-items:baseline;gap:7px;flex-wrap:wrap}
.produit .prix{font-size:1.12rem;color:var(--nuit)}
.produit .var{font-size:.63rem}
@media(min-width:900px){
  .produit .infos{padding:14px 14px 10px}
  .produit h3{font-size:.9rem}
  .produit .prix{font-size:1.22rem}
}

/* Le bouton d'ajout : couleur du rayon, ombre pleine écrasée au clic.
   C'est le seul endroit de la carte où l'on peut agir sans changer de
   page — il doit donc se voir de loin et rester touchable au pouce
   (44 px de haut, le minimum tenable). */
.produit__ajout{
  margin:0 11px 11px;min-height:44px;border-radius:12px;
  background:var(--u2);color:var(--nuit);
  font-size:.72rem;font-weight:900;letter-spacing:.07em;text-transform:uppercase;
  box-shadow:0 4px 0 -1px var(--u2f);
  transition:transform var(--t-survol) var(--e-sortie),
             box-shadow var(--t-survol) var(--e-doux),filter var(--t-survol);
}
@media(min-width:900px){.produit__ajout{margin:0 14px 14px;min-height:48px;font-size:.76rem}}
.produit__ajout:focus-visible{outline:3px solid var(--nuit);outline-offset:2px}
@media (hover:hover) and (pointer:fine){
  .produit__ajout:hover{transform:translateY(-2px);box-shadow:0 6px 0 -1px var(--u2f);filter:brightness(1.06)}
}
.produit__ajout:active{transform:translateY(3px);box-shadow:0 1px 0 -1px var(--u2f);
  transition-duration:var(--t-micro)}
/* « Choisir » plutôt qu'« Ajouter » quand l'article existe en
   plusieurs versions : choisir la contenance à la place du client,
   c'est lui vendre un flacon qu'il n'a pas demandé. */
.produit__ajout--choix{
  background:transparent;color:var(--nuit);
  box-shadow:inset 0 0 0 1.6px rgba(18,13,10,.28);
}
@media (hover:hover) and (pointer:fine){
  .produit__ajout--choix:hover{background:var(--nuit);color:var(--creme);
    box-shadow:inset 0 0 0 1.6px var(--nuit);filter:none;transform:translateY(-2px)}
}
.produit__ajout[disabled]{
  background:transparent;color:#8A6A50;cursor:default;
  box-shadow:inset 0 0 0 1.5px rgba(18,13,10,.16);
}
.produit__ajout[disabled]:active{transform:none;box-shadow:inset 0 0 0 1.5px rgba(18,13,10,.16)}
/* Une carte épuisée reste lisible mais ne se met plus en avant. */
.produit--mort .cadre img{filter:grayscale(1);opacity:.62}

/* ══════════ 7. LE RESTE DE LA PAGE ══════════
   Le manifeste passe APRÈS les rayons : on annonce ce qu'on refuse à
   quelqu'un qui a déjà vu ce qu'on vend, pas à quelqu'un qui vient
   d'arriver. Il forme un bloc avec « notre façon de vendre ». */
#manifeste{padding-top:clamp(48px,8vh,100px);padding-bottom:clamp(32px,5vh,64px)}
#gages{padding:18px 0}

/* ══════════ 8. GARDE-FOUS ══════════ */
/* Rien ne doit pouvoir pousser la page vers la droite. Les trois
   coupables possibles sont le mot géant du rayon, celui de la
   bannière, et la bande des vedettes : les deux premiers sont coupés
   par leur section, la troisième défile dans son propre cadre. */
#hero,.rayon{max-width:100%}
.vedettes,.grille,#portes{min-width:0}
.produit,.vedette{min-width:0}

/* Le mouvement réduit : on calme, on n'éteint pas. Seules les boucles
   sans fin s'arrêtent — la flèche de Découvrir en est une. */
@media (prefers-reduced-motion:reduce) and (min-width:999999px) /* desarme 17/08 : data-calme est le seul interrupteur */{
  .decouvrir svg{animation:none!important}
}
html[data-calme="1"] .decouvrir svg{animation:none!important}


/* Le lien vers la page complète du rayon — posé par accueil.js sur
   chaque section. Discret mais cliquable au doigt (44 px). */
.rayon-tout{display:inline-flex;align-items:center;min-height:44px;
  margin-top:.4rem;font:600 .78rem/1 var(--f-corps,system-ui);
  letter-spacing:.08em;text-transform:uppercase;color:var(--u3,#FFE0A3);
  text-decoration:none;border-bottom:1px solid var(--u2,#F0A830)}
@media(hover:hover) and (pointer:fine){
  .rayon-tout:hover{color:var(--u2,#F0A830)}
}


/* ════════════════════════════════════════════════════════════════
   9. LA UNE — LA BANNIÈRE REFAITE LE 19/08 AU SOIR

   « refais la bannière, au final je suis pas trop fan », avec une
   référence : ryeisland.com. Ce qui fait tenir cette page-là, mesuré
   dans le navigateur à 1440 px :
     · UN mot de 317 px (22 vw), interligne 0,80, chasse −0,04em, et
       plus rien d'autre au-dessus de 49 px. Rapport d'échelle entre le
       mot et le titre : 6,5:1.
     · le produit passe DEVANT le mot. La profondeur vient du
       recouvrement, pas d'une ombre ni d'une carte.
     · une bande basse où TOUT le petit texte vit sur la même ligne de
       pied, à gauche et à droite ; le milieu reste vide.
     · une seule encre, un seul papier ; la couleur ne vient que du
       produit.

   CE QU'ON EN GARDE : les quatre points ci-dessus.
   CE QU'ON ÉCARTE : leur papier beige (ici la couleur est une
   propriété du RAYON — charte § 2, neuf univers) ; leur carrousel qui
   tourne tout seul (un carrousel automatique emporte toujours celui
   qu'on regardait) ; leurs deux appels à l'action réduits à un mot
   souligné (on prend une précommande : il faut un vrai bouton avec le
   prix) ; leurs sceaux d'origine dessinés (on n'invente aucun
   symbole — charte § 4).

   CE QUI N'ALLAIT PAS, MESURÉ À 1280×800 AVANT :
     · le mot géant valait 140,8 px à 13 % d'opacité — de la boue, pas
       une architecture, et il traversait le TITRE au lieu du produit.
       Rapport mot/titre : 2,5:1 contre 6,5 chez la référence.
     · la bannière faisait 907 px de haut pour 634 px disponibles
       (100svh − les 166 px de barres) : les trois vedettes ET les deux
       légendes d'angle vivaient entièrement sous le pli.
     · les trois vedettes s'étalaient sur 780 px de large, donc 254 px
       chacune, donc 319 px de haut — la bande de sélection était plus
       imposante que le produit qu'elle sert à choisir.

   TOUT CE QUI SUIT EST SOUS `.hero--une`, une classe posée par
   accueil.js. Ce n'est pas de la coquetterie : presse.css est chargée
   APRÈS ce fichier et tient la bannière à (1,2,0) — `.hero--une` donne
   (1,3,0) et permet de reprendre la main SANS toucher à la surcouche
   ROTATIVE, qui reste seule maîtresse des couleurs.
   ════════════════════════════════════════════════════════════════ */

/* Le corps du mot géant, une seule fois : tout le reste s'y accroche
   en fraction, pour que le calage tienne à n'importe quelle largeur. */
#hero.hero--une{--mot:clamp(2.7rem,17vw,11rem)}
@media(min-width:941px){
  #hero.hero--une{--mot:clamp(9rem,18.5vw,16rem)}
}

/* ══ ① LE MOT DEVIENT L'ARCHITECTURE ══
   140,8 → 236,8 px à 1280 (18,5 vw), 13 → 28 % d'opacité. Il reste
   décoratif (`aria-hidden`, posé par banniere.js) et il reste du
   PAPIER : jamais une teinte d'identité en texte.

   `--mot-y` EST MESURÉ, PAS DEVINÉ. Le `top:20%` d'avant était un
   pourcentage de la bannière — or la hauteur de la bannière dépend du
   masthead du journal, qui va de 177 à 242 px selon la largeur. Le mot
   se calait donc n'importe où, et c'est comme ça qu'il a fini par
   traverser le titre. accueil.js publie maintenant la position réelle
   du bloc de contenu ; le repli de 24 % ne sert qu'au cas où la mesure
   n'aurait pas encore eu lieu. */
#hero.hero--une.hero--vivante .hero__geantpiste{
  top:var(--mot-y,24%);
  font-size:var(--mot);
  line-height:.78;
  letter-spacing:-.045em;
  color:var(--papier,#F2ECE0);
  opacity:.28;
}

/* ══ ② LE PRODUIT PASSE DEVANT LE MOT ══
   La scène se cale en HAUT de sa cellule et le texte en BAS : le mot
   croise alors le tiers haut du produit (plan 5 contre plan 2) et
   n'atteint jamais le titre. C'est le seul geste emprunté à la
   référence qui compte vraiment — la profondeur sans une seule ombre
   de plus. */
@media(min-width:941px){
  #hero.hero--une .hero__dedans{align-items:end}
  #hero.hero--une .hero__scene{align-self:start}
  /* Le produit gagne un cran : 38 → 40 svh, et son plancher passe de
     220 à 240 px. Le recouvrement ne coûte AUCUNE hauteur (la piste
     est en position absolue), donc ce cran est gratuit. */
  #hero.hero--une .hero__packshot{height:clamp(240px,40svh,440px)}
  /* Le titre ne descend jamais dans le mot, même sur une fenêtre
     courte où c'est LUI le plus haut des deux : il se réserve la
     hauteur que le mot peut mordre. Sur une fenêtre normale la scène
     est plus haute, le texte est calé en bas, et ce rembourrage ne se
     voit pas. */
  #hero.hero--une .hero__texte{padding-top:calc(var(--mot) * .34)}
  #hero.hero--une .hero__texte h1{font-size:clamp(2.6rem,4.6vw,3.9rem);line-height:.94}
  /* 46 → 38 caractères : la référence tient sa prose à 38 signes de
     large. Au-delà, l'œil perd la ligne et le bloc cesse d'être un
     sous-titre pour devenir un paragraphe. */
  #hero.hero--une .hero__texte .mot{max-width:38ch;font-size:.95rem;line-height:1.55}
}
#hero.hero--une .hero__texte h1{font-size:clamp(2rem,8.6vw,2.9rem);line-height:.96}

/* ══ ③ LA BANDE DE SÉLECTION REDEVIENT UNE BANDE ══
   Trois vedettes étalées sur 780 px faisaient 254 px de large et
   319 px de haut. Bridées à 168 px de colonne et à un rapport 4/3,
   elles retombent à ~170 px : 148 px rendus à la composition, sans
   retirer une seule vignette.
   ⚠ La largeur change, PAS le contrat de glissement : la bande n'est
   rendue à socle.js qu'au test exact `scrollWidth − clientWidth > 2`,
   qui est lu dans accueil.js et nulle part ailleurs. */
#hero.hero--une .vedettes{justify-content:center}
@media(min-width:620px){
  #hero.hero--une .vedettes{max-width:min(100%,560px);gap:12px;
    grid-auto-columns:minmax(104px,168px)}
  #hero.hero--une .vedette{padding:6px 6px 8px;gap:5px}
  #hero.hero--une .vedette__img{aspect-ratio:4/3;border-radius:10px}
  #hero.hero--une .vedette__nom{font-size:.63rem;line-height:1.24}
  #hero.hero--une .vedette__prix{font-size:.66rem}
}

/* ══ ④ « DÉCOUVRIR » CESSE D'ÊTRE LE TROISIÈME ÉLÉMENT FORT ══
   Il restait un jeton crème de 206 × 56 px avec une ombre pleine de
   7 px, planté au centre : à égalité de poids avec le titre et avec le
   produit. Il rétrécit et son relief s'amincit — il ne change NI de
   remplissage NI de mot, parce que ce remplissage papier est la
   correction de contraste du 18/08 (pire univers : 5,71:1 contre
   1,55:1 avant). On touche à l'échelle, jamais à la lisibilité. */
#hero.hero--une a.decouvrir{
  min-height:46px;padding:.7rem clamp(1.2rem,4.6vw,1.9rem);
  font-size:.72rem;letter-spacing:.11em;
  box-shadow:0 4px 0 -1px rgba(0,0,0,.34),0 16px 26px -16px rgba(0,0,0,.82);
}
#hero.hero--une a.decouvrir svg{width:14px;height:14px}
@media (hover:hover) and (pointer:fine){
  #hero.hero--une a.decouvrir:hover{transform:translateY(-2px);
    box-shadow:0 6px 0 -1px rgba(0,0,0,.34),0 22px 34px -18px rgba(0,0,0,.9)}
}
#hero.hero--une a.decouvrir:active{transform:translateY(3px);
  box-shadow:0 1px 0 -1px rgba(0,0,0,.34),0 8px 16px -14px rgba(0,0,0,.9)}
