/* LE STYLE DE TOUTE LA BOUTIQUE — accueil et pages produit.
   Sorti de boutique.html pour n'exister qu'une fois : 45 pages
   produit le partagent, et le navigateur ne le telecharge qu'une
   seule fois pour toute la visite. */
*{box-sizing:border-box;margin:0;padding:0;-webkit-tap-highlight-color:transparent}

:root{
  /* ── LA MATIÈRE ──
     La « laine » est la composante RGB de ce qui se posait en blanc
     translucide sur la nuit ; « blanc » son opaque. La surcouche
     ROTATIVE (presse.css) les retourne vers l'encre, puis les
     re-retourne vers le papier dans les îlots restés sombres. Sans
     surcouche : les valeurs d'origine, rien ne change d'un pixel. */
  --laine:255,255,255;
  --blanc:#fff;
  /* ── LE SOCLE ── */
  --nuit:#120D0A; --nuit2:#1C1512; --creme:#FCF6EC;
  --encre:var(--blanc); --encre2:rgba(var(--laine),.70);
  /* ── L'ACCENT ── */
  --or:#F0A830; --or-clair:#FFE0A3; --or-fonce:#A96F14;
  /* ── ÉCHELLE DE BLANCS ── */
  --b5:rgba(var(--laine),.05); --b10:rgba(var(--laine),.10);
  --b20:rgba(var(--laine),.20); --b30:rgba(var(--laine),.30);
  --b50:rgba(var(--laine),.50);
  /* ── COURBES ── */
  --e-ciao:cubic-bezier(0,.702,.202,1);
  --e-sortie:cubic-bezier(.22,1,.36,1);
  --e-doux:cubic-bezier(.4,0,.2,1);
  --e-inout:cubic-bezier(.455,.03,.515,.955);
  --e-ressort:cubic-bezier(.34,1.56,.64,1);
  /* ── DURÉES ── */
  --t-micro:120ms; --t-survol:220ms; --t-transit:420ms;
  --t-entree:640ms; --t-long:900ms;
  /* ── POLICES ──
     POURQUOI LA PILE DE TITRE A CHANGÉ. Elle était
     Impact/Haettenschweiler : une grotesque ultra-condensée dessinée
     pour crier sur une affiche. Le propriétaire l'a désignée sans la
     nommer — « la police d'écriture trop basic fit », c'est-à-dire
     salle de sport : large, criarde, sans chaleur. On passe à une
     humane à empattements, ronde et calligraphique, servie AUSSI aux
     textes de lecture : c'est elle qui porte la chaleur de la maison.

     ZÉRO FICHIER, ZÉRO CDN, ZÉRO GOOGLE FONTS. La boutique part par
     FTP et doit s'afficher hors ligne, du premier coup, sans requête
     vers un tiers. Ces polices sont donc livrées AVEC les systèmes, et
     l'ordre n'est pas décoratif : chaque système prend la première
     qu'il possède, et la suite ne le concerne pas.

       · Apple — macOS et iOS ...... Iowan Old Style (livrée)
       · Windows — XP jusqu'à 11 ... Palatino Linotype (livrée)
       · Linux, BSD ................ URW Palladio L (le Palatino libre)
       · Android, ChromeOS ......... Noto Serif
       · dernier recours ........... ui-serif, puis la serif du navigateur

     C'est la même famille de dessin partout : la Palatino d'Hermann
     Zapf et ses cousines, calligraphiques, à axe humaniste — jamais
     une géométrique froide, jamais une condensée d'affiche.

     MESURÉ, PAS SUPPOSÉ — ET LE RELEVÉ A ÉTÉ REFAIT LE 10/08.
     `document.fonts.check()` NE SERT À RIEN pour ça : interrogé sur les
     treize polices de ce fichier, il a répondu « oui » aux treize, y
     compris à celles que Windows n'a jamais eues. La seule preuve est
     la LARGEUR : on mesure la même chaîne en « X, serif », en
     « X, sans-serif » et en « X, monospace » ; si les trois largeurs
     retombent sur celles des trois génériques, X est absente.

     Relevé de la machine de vérification (Windows 11), à 100 px, sur
     la chaîne « S'INCLINER Hamburgefonstiv 0123456789 » — la chaîne
     fait partie du relevé, sans elle aucun de ces nombres ne se
     refait :
       présentes .. Georgia 1940,97 · Palatino Linotype 1903,58 ·
                    Cambria 1842 · Constantia 1816,13 ·
                    Sitka Display 1699,34
       absentes ... Iowan Old Style · Palatino · Book Antiqua ·
                    URW Palladio L · P052 · TeX Gyre Pagella ·
                    Noto Serif — toutes à 1788,28, c'est-à-dire à la
                    largeur exacte de la serif générique, donc jamais
                    servies.
     Et les mots géants ont été mesurés DANS la page, pas dans une
     capture. Les cinq, à 51,2 px de corps : HUILES 192,19 px · PRIÈRE
     182,20 · ENFANTS 243,39 · LIVRES 180,94 · ZAMZAM 247,88. Palatino
     Linotype donne exactement ces cinq largeurs-là ; Impact en
     donnerait 141,48 · 141,23 · 175,73 · 139,44 · 171,19. C'est donc
     Palatino Linotype qui peint, cinq fois sur cinq.

     LES CLONES LINUX SONT NOMMÉS DEUX FOIS. « URW Palladio L » est
     l'ancien nom du Palatino libre ; les distributions récentes livrent
     le même dessin sous « P052 » (paquet urw-base35) et « TeX Gyre
     Pagella ». Le nom seul ne suffisait donc pas : une machine Linux à
     jour tombait sur Noto Serif, voire sur la serif du navigateur.

     GEORGIA ET CONSTANTIA SONT ÉCARTÉES DE LA TÊTE DE PILE, alors
     qu'elles sont présentes sur Windows et parfaitement chaleureuses :
     leurs chiffres sont elzéviriens (de hauteurs inégales). « 01 02 03
     04 05 » y danse, et un prix — 12,90 € — s'y lit mal. Les chiffres
     alignés ne sont pas négociables sur une boutique. Elles restent en
     secours lointain, où elles ne peindront jamais. */
  --f-titre:'Iowan Old Style','Palatino Linotype',Palatino,'Book Antiqua',
            'URW Palladio L','P052','TeX Gyre Pagella',
            'Sitka Display',Georgia,'Noto Serif',ui-serif,serif;
  --f-corps:system-ui,-apple-system,'Segoe UI',Roboto,sans-serif;
  --f-mono:ui-monospace,'SF Mono','Cascadia Mono',Consolas,monospace;
  /* ── LE BLEU DE LA BOUTIQUE ──
     L'arc doré est la marque de l'application. Le même arc en bleu dit
     au client qui connaît l'app qu'il est passé côté boutique : même
     maison, autre versant. C'est la demande, mot pour mot. */
  --bleu:#5C93F0; --bleu-clair:#9CC6FF; --bleu-fonce:#274B8E;
  /* ── UNIVERS PAR DÉFAUT ── */
  --u1:#6E2A0C; --u2:#F0A830; --u3:#FFE0A3; --u2f:#A96F14;
}
/* Les couleurs d'univers s'animent : @property les rend interpolables,
   donc la bascule est un fondu de 900 ms au lieu d'un saut. Sans le
   support, le changement est instantané — rien ne casse. */
@property --u1{syntax:'<color>';inherits:true;initial-value:#6E2A0C}
@property --u2{syntax:'<color>';inherits:true;initial-value:#F0A830}
@property --u3{syntax:'<color>';inherits:true;initial-value:#FFE0A3}
@property --angle{syntax:'<angle>';inherits:false;initial-value:0deg}

/* --u2f : l'ombre pleine sous le bouton d'achat. Elle doit être la
   couleur du rayon assombrie — sinon un bouton vert garde une ombre
   dorée, et ça se voit immédiatement. */
body[data-univers="huiles"] { --u1:#6E2A0C; --u2:#F0A830; --u3:#FFE0A3; --u2f:#A96F14 }
body[data-univers="priere"] { --u1:#07352A; --u2:#12A177; --u3:#BFE9D6; --u2f:#0A6B4E }
body[data-univers="enfants"]{ --u1:#4A1C6B; --u2:#FF6B4A; --u3:#FFD4C4; --u2f:#B03C22 }
body[data-univers="livres"] { --u1:#121F4E; --u2:#5C93F0; --u3:#CBDCFF; --u2f:#2F5EA8 }

html{scroll-behavior:smooth}
body{
  font-family:var(--f-corps);font-size:16px;line-height:1.65;
  background:var(--nuit);color:var(--encre);
  overflow-x:hidden;-webkit-text-size-adjust:100%;
  transition:--u1 var(--t-long) var(--e-inout),
             --u2 var(--t-long) var(--e-inout),
             --u3 var(--t-long) var(--e-inout);
}
a{color:inherit}
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}
img{max-width:100%;display:block}
.coquille{max-width:1320px;margin:0 auto;padding-left:clamp(18px,5vw,56px);padding-right:clamp(18px,5vw,56px)}

/* ══ TYPOGRAPHIE ══
   « METTRE UNE BONNE POLICE MAIS ESPACÉE ». La police seule ne suffit
   pas : l'ancienne mise en page SERRAIT les lettres (-.035 em),
   ÉCRASAIT les interlignes (.78) et PENCHAIT les blocs de six degrés.
   Serrer, écraser, pencher : c'est le vocabulaire exact de l'affiche
   sportive, et il aurait survécu au changement de police. On fait donc
   l'inverse, partout :
     · interlettrage POSITIF sur les capitales — une capitale à
       empattements a besoin d'air, sinon les empattements se touchent
       et le mot redevient un bloc ;
     · interlignes qui respirent — .78 devient .95 et plus ;
     · plus une seule inclinaison : `transform:skewX(-6deg)` a disparu
       de tous les titres. Une police penchée à la main est une police
       déformée, et l'œil le voit même s'il ne sait pas le nommer.
   Les tailles baissent en même temps, parce qu'une humane est plus
   large qu'une condensée à corps égal. Mesuré à 100 px et à graisse
   NORMALE des deux côtés — c'est celle de ces titres : « ZAMZAM »
   fait 328,33 px en Impact contre 478,13 en Palatino Linotype (+ 46 %)
   et « ENFANTS » 336,23 contre 468,36 (+ 39 %).
   LE CHIFFRE DE 593 px QUI FIGURAIT ICI COMPARAIT DEUX CHOSES QUI NE
   SE COMPARENT PAS : c'est la largeur de Palatino Linotype en GRAS
   (593,03 px pour « S'INCLINER »), mise en face d'un Impact maigre.
   Aucun de ces titres n'est gras, et le mot « S'INCLINER » lui-même
   ne figure plus dans la page. Sans cette baisse de corps, les mots
   géants sortaient de l'écran. */
.geant{font-family:var(--f-titre);font-size:clamp(2.9rem,11vw,9.5rem);line-height:.95;
  letter-spacing:.012em;text-transform:uppercase;
  white-space:nowrap;user-select:none}
.titre-rayon{font-family:var(--f-titre);font-size:clamp(2.1rem,5.4vw,4.4rem);line-height:1.06;
  letter-spacing:-.004em}
.titre-2{font-family:var(--f-titre);font-size:clamp(1.7rem,3.4vw,2.6rem);line-height:1.16}
.sur{font-family:var(--f-mono);font-size:.72rem;letter-spacing:.2em;text-transform:uppercase;
  color:var(--encre2)}
/* Le texte de lecture passe lui aussi à l'humane : c'est là que la
   chaleur se joue vraiment, pas dans les titres qu'on ne lit pas. */
.mot{font-family:var(--f-titre);font-size:clamp(1rem,1.25vw,1.14rem);line-height:1.78;
  letter-spacing:.006em;color:var(--encre2);max-width:60ch}

/* ══ LES BOUTONS ══ */
.btn{
  position:relative;isolation:isolate;overflow:hidden;
  display:inline-flex;align-items:center;justify-content:center;gap:.7rem;
  min-height:60px;padding:1.1rem 2.1rem;border:0;border-radius:50vw;
  /* Les boutons restent à la linéale : une humane à empattements dans
     une pastille de 60 px se lit moins vite, et un bouton se lit avant
     de se regarder. Ce qui part, c'est la CAPITALE — « PRÉCOMMANDER »
     en gras 800 crie exactement comme le titre qu'on vient de calmer.
     Le texte est déjà écrit « Précommander » dans le HTML et dans
     accueil.js : retirer text-transform suffit, aucun libellé à
     retoucher. */
  font-family:var(--f-corps);font-size:1rem;font-weight:700;line-height:1;
  letter-spacing:.015em;text-decoration:none;cursor:pointer;
}
.btn:focus-visible{outline:3px solid var(--or-clair);outline-offset:4px}

/* ① l'achat — ombre PLEINE, écrasée au clic : l'épaisseur d'une touche */
.btn--achat{
  background:var(--u2);color:var(--nuit);
  box-shadow:0 8px 0 -1px var(--u2f),0 22px 40px -18px rgba(0,0,0,.85);
  transition:transform var(--t-survol) var(--e-sortie),box-shadow var(--t-survol) var(--e-doux);
}
.btn--achat::before{
  content:'';position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(105deg,transparent 38%,rgba(var(--laine),.78) 50%,transparent 62%);
  transform:translateX(-130%);
}
.btn--achat:focus-visible::before{animation:balaye 700ms var(--e-sortie) forwards}
@media (hover:hover) and (pointer:fine){
  .btn--achat:hover::before{animation:balaye 700ms var(--e-sortie) forwards}
  .btn--achat:hover{transform:translateY(-3px);
    box-shadow:0 11px 0 -1px var(--u2f),0 30px 50px -18px rgba(0,0,0,.9)}
}
@keyframes balaye{to{transform:translateX(130%)}}
.btn--achat:active{transform:translateY(6px);
  box-shadow:0 2px 0 -1px var(--u2f),0 10px 20px -14px rgba(0,0,0,.9);
  transition-duration:var(--t-micro)}
.btn--achat[disabled]{opacity:.45;cursor:default;box-shadow:0 4px 0 -1px var(--u2f)}
.btn .prix{background:var(--nuit);color:var(--u2);padding:6px 12px;border-radius:999px;
  font-size:.86rem;font-variant-numeric:tabular-nums;letter-spacing:0}

/* ② le creux — remplissage qui monte */
.btn--creux{
  background:transparent;color:var(--encre);
  box-shadow:inset 0 0 0 1.5px var(--b30);
  transition:color var(--t-transit) var(--e-doux),box-shadow var(--t-transit) var(--e-doux);
}
.btn--creux::before{
  content:'';position:absolute;inset:0;z-index:-1;border-radius:inherit;
  background:var(--creme);transform:translateY(101%);
  transition:transform var(--t-transit) var(--e-ciao);
}
@media (hover:hover) and (pointer:fine){
  .btn--creux:hover{color:var(--nuit);box-shadow:inset 0 0 0 1.5px transparent}
  .btn--creux:hover::before{transform:translateY(0)}
}
.btn--creux:focus-visible{color:var(--nuit)}
.btn--creux:focus-visible::before{transform:translateY(0)}
.btn--creux:active{transform:scale(.985);transition-duration:var(--t-micro)}

/* ③ la flèche */
.btn--fleche{
  width:60px;height:60px;min-height:0;padding:0;
  background:transparent;color:var(--encre);
  box-shadow:inset 0 0 0 1.5px var(--b20);
  transition:box-shadow var(--t-survol) var(--e-doux),background-color var(--t-survol),
             transform var(--t-survol) var(--e-sortie);
  font-size:1.4rem;
}
@media (hover:hover) and (pointer:fine){
  .btn--fleche:hover{box-shadow:inset 0 0 0 1.5px var(--b50),0 0 28px -6px var(--u3);
    background:var(--b5);transform:scale(1.05)}
}
.btn--fleche:active{transform:scale(.94);transition-duration:var(--t-micro)}

/* ④ le rayon — la couleur envahit avant le clic */
.btn--rayon{
  --uc:var(--or);
  justify-content:space-between;gap:1rem;width:100%;
  min-height:78px;padding:1.2rem 1.5rem;border-radius:20px;
  background:var(--nuit2);color:var(--encre);
  box-shadow:inset 0 0 0 1px var(--b10);
  transition:transform var(--t-transit) var(--e-sortie),
             box-shadow var(--t-transit) var(--e-doux),color var(--t-transit) var(--e-doux);
}
.btn--rayon .num{font-family:var(--f-mono);font-size:.72rem;letter-spacing:.14em;
  color:var(--uc);transition:color var(--t-transit)}
.btn--rayon .nom{font-family:var(--f-titre);font-size:clamp(1.2rem,2.1vw,1.8rem);
  letter-spacing:-.004em;flex:1;text-align:left;margin-left:.9rem}
.btn--rayon .cpt{font-family:var(--f-mono);font-size:.74rem;color:var(--b50);
  transition:color var(--t-transit);white-space:nowrap}
.btn--rayon::before{
  content:'';position:absolute;inset:0;z-index:-1;border-radius:inherit;
  background:var(--uc);transform:translateY(101%);
  transition:transform 520ms var(--e-ciao);
}
@media (hover:hover) and (pointer:fine){
  .btn--rayon:hover{transform:translateY(-4px);color:var(--nuit);
    box-shadow:inset 0 0 0 1px transparent,0 26px 46px -24px var(--uc)}
  .btn--rayon:hover::before{transform:translateY(0)}
  .btn--rayon:hover .num,.btn--rayon:hover .cpt{color:var(--nuit)}
}
.btn--rayon:focus-visible{color:var(--nuit)}
.btn--rayon:focus-visible::before{transform:translateY(0)}
.btn--rayon:active{transform:translateY(-1px) scale(.995);transition-duration:var(--t-micro)}

/* ⑤ le panier — bordure conique qui tourne
   `margin-inline-start:auto` LE COLLE À DROITE, ET CE N'EST PAS UN
   RÉGLAGE D'ESTHÈTE. Sous 940 px, #sommaire passe en display:none
   (plus bas dans ce fichier) : la barre ne contient plus que deux
   éléments et rien pour occuper le vide entre eux. Mesuré sur un
   écran de 375 px : le logo tenait de 19 à 91 px, le panier de 101 à
   223 px, et les 152 px restants — le tiers droit de l'écran —
   étaient vides, le panier échoué au milieu. Le `auto` mange tout
   l'espace libre quoi qu'il arrive au voisin ; sur écran large, où
   #sommaire prend déjà le reste, il ne reste rien à manger et la
   ligne ne bouge pas d'un pixel. */
#btnPanier{
  position:relative;display:inline-flex;align-items:center;gap:.6rem;
  margin-inline-start:auto;
  min-height:52px;padding:0 1.1rem 0 1.4rem;
  border:2px solid transparent;border-radius:50vw;
  font-weight:700;font-size:.88rem;letter-spacing:.03em;
  color:var(--or-clair);white-space:nowrap;
  background-image:linear-gradient(var(--nuit2),var(--nuit2)),
    conic-gradient(from var(--angle),var(--or) 0%,var(--or-clair) 18%,#7A5A12 42%,var(--or-clair) 66%,var(--or) 100%);
  background-origin:border-box;background-clip:padding-box,border-box;
  animation:tourne 4s linear infinite;
  transition:transform var(--t-survol) var(--e-sortie);
}
@keyframes tourne{to{--angle:360deg}}
#btnPanier::after{
  content:'';position:absolute;inset:-3px;border-radius:inherit;z-index:-1;
  background:conic-gradient(from var(--angle),var(--or),var(--or-clair),#7A5A12,var(--or));
  filter:blur(13px);opacity:0;transition:opacity var(--t-transit) var(--e-doux);
}
@media (hover:hover) and (pointer:fine){
  #btnPanier:hover{transform:translateY(-2px)}
  #btnPanier:hover::after{opacity:.75}
}
#btnPanier:active{transform:translateY(0) scale(.97);transition-duration:var(--t-micro)}
#btnPanier:focus-visible{outline:3px solid var(--or-clair);outline-offset:3px}
/* Firefox ancien ignore @property : l'angle resterait à 0° et le bouton
   paraîtrait cassé. Une classe posée en JS le remplace par un dégradé fixe. */
html.sans-property #btnPanier{animation:none;
  background-image:linear-gradient(var(--nuit2),var(--nuit2)),
                   linear-gradient(120deg,var(--or),var(--or-clair),var(--or))}
#pnCompte{min-width:24px;height:24px;border-radius:999px;display:grid;place-items:center;
  padding:0 6px;background:var(--or);color:var(--nuit);
  font-size:.76rem;font-weight:900;font-variant-numeric:tabular-nums}
#pnCompte.saute{animation:sursaut 420ms var(--e-ressort)}
/* ⚠ 20/08 — LE PANIER VIDE AFFICHAIT « 0 » POUR TOUJOURS, ET LE CODE
   AVAIT RAISON : `majCompteurSeul()` (socle.js) écrit bien
   `c.hidden = n === 0`. Mesuré dans la page, panier vide :
     c.hidden === true   ET   getComputedStyle(c).display === 'grid'.
   La règle du navigateur est `[hidden]{display:none}` — un sélecteur
   d'attribut, poids 0-1-0. `#pnCompte{display:grid}` pèse 1-0-0 et
   l'écrase. Le JavaScript cachait, le CSS rallumait : une pastille
   vermillon de 24 x 24 px collée en permanence dans un bouton qui
   prend déjà le tiers de la barre sur téléphone.
   Une seule ligne rend au `hidden` son sens, sans toucher au script. */
#pnCompte[hidden]{display:none}

/* ══ 20/08 — LE PANIER SE FAIT PETIT SOUS 620 px ══
   « sur les petits écrans le panier est relou ». Mesuré à 375 px sur
   l'accueil : #btnPanier occupait 128 x 52 px, de x = 228 à x = 356 —
   34 % de la largeur de l'écran pour un panier vide, bordure conique
   en rotation perpétuelle comprise. La barre entière ne fait que
   375 px et doit y loger le menu, la marque et lui.

   CE QU'ON GARDE : le bouton, sa cible tactile de 44 px, son nom pour
   les lecteurs d'écran (il est porté par `aria-label`, pas par le
   texte — l'effacer à l'œil ne coûte donc rien à la voix), et la
   pastille du compte DÈS QU'IL Y A QUELQUE CHOSE DEDANS.
   CE QU'ON RETIRE : le mot écrit, le dégradé conique qui tourne sans
   fin (batterie, et du mouvement pour rien), et le halo au survol —
   un téléphone ne survole pas. Le panonceau devient un pictogramme de
   panier, dessiné en trait : ni personnage, ni être animé.
   Mesure après : 48 x 44 px, soit 13 % de la largeur au lieu de 34. */
.pn-ico{display:none;width:21px;height:21px;flex:0 0 auto}
@media(max-width:620px){
  #btnPanier{gap:.35rem;min-height:44px;padding:0 12px;
    border-width:1px;animation:none;
    background-image:linear-gradient(var(--nuit2),var(--nuit2)),
      linear-gradient(120deg,var(--or),var(--or-clair),var(--or))}
  #btnPanier::after{content:none}
  .pn-ico{display:block}
  .pn-mot{position:absolute;width:1px;height:1px;overflow:hidden;
    clip-path:inset(50%);white-space:nowrap}
  #pnCompte{min-width:20px;height:20px;font-size:.7rem;padding:0 5px}
}
@keyframes sursaut{0%{transform:scale(1)}40%{transform:scale(1.38)}100%{transform:scale(1)}}

/* ⑥ l'interrupteur d'animations — le juge de paix entre les deux publics */
.btn--calme{
  min-height:48px;padding:.8rem 1.3rem;border-radius:12px;
  background:transparent;color:var(--encre2);
  box-shadow:inset 0 0 0 1.5px var(--b20);
  font-size:.82rem;font-weight:700;letter-spacing:.03em;text-transform:none;
  transition:color var(--t-survol),box-shadow var(--t-survol),background-color var(--t-survol);
}
.btn--calme[aria-pressed="true"]{background:var(--creme);color:var(--nuit);box-shadow:none}
@media (hover:hover) and (pointer:fine){
  .btn--calme:hover{color:var(--encre);box-shadow:inset 0 0 0 1.5px var(--b50)}
}

/* ══ PROGRESSION DE LECTURE ══ */
#progres{position:fixed;top:0;left:0;height:2px;width:0;z-index:100;
  background:var(--u2);box-shadow:0 0 12px var(--u2)}

/* ══ BANDEAU LÉGAL — ne bouge jamais ══
   DEUX ORTHOGRAPHES, ET C'ÉTAIT VISIBLE. boutique/index.html écrit
   `id="délai"` avec l'accent — et c'est bien ce nom-là que socle.js
   (ligne 459) et accueil.js (ligne 46) vont chercher, donc on n'y
   touche pas. Cette feuille, elle, ne connaissait que `#delai` sans
   accent, le nom que portent les pages de boutique/p/. Résultat mesuré
   sur l'accueil : fond transparent au lieu de --nuit2, texte en 16 px
   de linéale au lieu de 11,2 px de mono, aucun interlettrage — la
   première ligne de la page, celle qui porte l'engagement de prix,
   était la seule à ne pas être composée. On accepte les deux noms
   plutôt que d'en renommer un dans un fichier que je ne tiens pas. */
#delai,#délai{background:var(--nuit2);text-align:center;font-family:var(--f-mono);
  font-size:.7rem;letter-spacing:.06em;padding:10px 16px;color:var(--encre2);
  border-bottom:1px solid var(--b10)}

/* ══ EN-TÊTE ══
   `body > header` ET RIEN D'AUTRE (17/08). La règle visait `header`
   tout court : elle attrapait donc les en-têtes des SECTIONS écrites
   par les modules (les trois vitrines, le mode d'emploi des 399
   fiches, la bulle d'aide). Ces titres de section devenaient collants,
   avec un z-index de 70 et un flou d'arrière-plan — ils voyageaient
   par-dessus les produits en défilant, et floutaient ce qu'il y avait
   dessous. C'est le rectangle flou vu sur la capture du 17/08.
   Le vrai en-tête est le SEUL enfant direct de <body> : la règle le
   dit maintenant, et la porte est fermée pour les modules à venir. */
body > header{position:sticky;top:0;z-index:70;
  background:linear-gradient(rgba(18,13,10,.94),rgba(18,13,10,.74) 70%,transparent);
  backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px)}
body > header .dedans{max-width:1320px;margin:0 auto;display:flex;align-items:center;
  gap:clamp(10px,2vw,24px);padding:14px clamp(18px,5vw,56px)}
/* ══ LA MARQUE, EN HAUT À GAUCHE ══
   « au lieu de MUSLIMOS tout en majuscules — comme ça ça fait très
   sportif — faut que ça soit chaleureux. Je propose que tu mettes
   notre logo arc mais en bleu, pour que les clients qui utilisent
   l'app voient qu'on est passé en mode business. »

   Donc : le mot en capitales penchées disparaît, l'ARC prend sa place.
   Le tracé est celui du logo, au caractère près — il est copié de
   js/global/arches.js, qui l'extrude en volume sur le site public, et
   des pages qui le portent déjà en clair. Deux rayons, deux centres :
   c'est l'arc brisé. Redessiné à la main, il aurait divergé.

   L'arc est BLEU ici et doré dans l'application : même forme, autre
   versant de la maison. Le nom reste écrit à côté, mais en bas de
   casse et à l'humane — un logo sans nom lisible ne se retient pas, et
   Google non plus ne le lit pas.

   C'est un <button> et non un <a> : il n'emmène nulle part tout seul,
   il ouvre le panneau qui pose la question. Un lien qui ouvre une
   boîte de dialogue ment au clavier et au lecteur d'écran. */
#marque{
  display:inline-flex;align-items:center;gap:.62rem;flex:0 0 auto;
  min-height:48px;padding:5px 12px 5px 5px;border-radius:15px;
  background:transparent;color:inherit;text-decoration:none;white-space:nowrap;
  box-shadow:inset 0 0 0 1px transparent;
  transition:background-color var(--t-survol) var(--e-doux),
             box-shadow var(--t-survol) var(--e-doux),
             transform var(--t-survol) var(--e-sortie);
}
/* L'écrin de l'arc : un carré de nuit bleutée, pas un aplat. La
   lumière vient d'en haut à gauche, comme partout ailleurs sur la
   page — sans quoi le logo a l'air collé sur la barre. */
.marque__arc{
  position:relative;display:grid;place-items:center;flex:0 0 auto;
  width:38px;height:38px;border-radius:12px;
  /* ⚠ CE CADRE ETAIT BLEU. Il enchassait l'arche doree de la maison
     dans un ecrin bleu nuit : le logo ne se reconnaissait plus.
     On reprend les tons de `icon-512.png` — une lueur doree en haut a
     gauche, sur la nuit de la boutique (--nuit2 puis --nuit). */
  background:radial-gradient(120% 120% at 28% 0%,
    rgba(240,168,48,.30) 0%,rgba(28,21,18,.94) 62%,rgba(18,13,10,.97) 100%);
  box-shadow:inset 0 0 0 1px rgba(255,224,163,.34),
             0 10px 22px -14px var(--or);
}
.marque__arc svg{width:25px;height:25px;display:block}
.marque__mot{display:flex;flex-direction:column;gap:3px;line-height:1;text-align:left}
.marque__mot b{font-family:var(--f-titre);font-weight:600;font-size:1.14rem;
  letter-spacing:.04em;color:var(--encre)}
.marque__mot i{font-family:var(--f-mono);font-style:normal;font-size:.55rem;
  letter-spacing:.24em;text-transform:uppercase;color:var(--or-clair)}
/* Le chevron dit qu'il va s'ouvrir quelque chose. Sans lui, un logo
   qui n'est pas un lien laisse le visiteur sans indice. */
.marque__chev{flex:0 0 auto;width:13px;height:13px;margin-left:.1rem;
  color:var(--b50);transition:transform var(--t-transit) var(--e-sortie),color var(--t-survol)}
.marque__chev svg{width:100%;height:100%;display:block}
#marque[aria-expanded="true"] .marque__chev{transform:rotate(180deg);color:var(--or-clair)}
#marque[aria-expanded="true"]{background:rgba(92,147,240,.13);
  box-shadow:inset 0 0 0 1px rgba(150,195,255,.30)}
#marque:focus-visible{outline:3px solid var(--bleu-clair);outline-offset:3px}
@media (hover:hover) and (pointer:fine){
  #marque:hover{background:rgba(92,147,240,.13);
    box-shadow:inset 0 0 0 1px rgba(150,195,255,.26)}
  #marque:hover .marque__chev{color:var(--bleu-clair)}
}
#marque:active{transform:scale(.985);transition-duration:var(--t-micro)}
/* Sous 420 px, la barre doit tenir : l'arc et le panier survivent, le
   nom écrit s'efface. L'arc reste lisible seul — c'est un logo.

   IL S'EFFACE DE L'ŒIL, PAS DE LA VOIX. `display:none` sortait le nom
   de l'arbre d'accessibilité — et comme l'arc ET le chevron sont tous
   deux aria-hidden, il ne restait plus rien à nommer : mesuré à 375 px
   dans l'arbre d'accessibilité de la page, le bouton s'annonçait
   « button », sans un mot, juste à côté d'un « Ouvrir le panier »
   correctement nommé. On le sort donc du flux et on le découpe à un
   pixel au lieu de l'éteindre : la mise en page ne bouge pas — les
   deux seuls éléments qui restent en boîte flexible sont l'arc et le
   chevron, exactement comme avant — et le nom continue d'être lu. */
@media(max-width:420px){
  #marque{gap:.4rem;padding-right:8px}
  .marque__mot{position:absolute;width:1px;height:1px;overflow:hidden;
    clip-path:inset(50%);white-space:nowrap}
}

/* ══ LE PANNEAU DE LA MAISON ══
   « et quand quelqu'un clique ça ouvre un petit truc stylé avec
   accueil de la boutique ou app. » Deux portes, pas une de plus.

   C'EST UN <dialog>, ET C'EST LE FOND DE L'AFFAIRE. Une div qu'on
   montre et qu'on cache oblige à réécrire à la main quatre choses que
   le navigateur sait déjà faire, et qu'on rate presque toujours : la
   fermeture par Échap, le piège à tabulation (sans lui, la touche Tab
   sort du panneau et va cocher des liens invisibles derrière), le
   `inert` sur le reste de la page pour les lecteurs d'écran, et le
   voile. `::backdrop` est ce voile — il est peint par le navigateur,
   au-dessus de TOUT, sans avoir à inventer un z-index de plus.
   On ne se sert donc PAS de #voile ici : lui appartient au panier, et
   deux choses qui se partagent un même voile finissent par se le
   reprendre au mauvais moment.

   LES DEUX PORTES PORTENT CHACUNE LA COULEUR DE SA MAISON : l'arc est
   bleu du côté boutique, doré du côté application. C'est la demande
   même du propriétaire, poussée d'un cran — la couleur dit où l'on va
   avant que le mot soit lu.

   ⚠ 18/08 — LE PANNEAU ÉTAIT NOIR SUR NOIR, ET LA CAUSE EST LA MÊME
   QUE POUR LES BOUTONS PLEINS DU JOURNAL. Le fond de `.pm` est écrit
   EN DUR (dégradé #1A2236 → #12172A → #0E1222) : c'est un îlot qui ne
   change JAMAIS de peau. Ses encres, elles, étaient prises dans les
   variables — `var(--encre)`, `var(--encre2)`, `var(--laine)`. Or la
   surcouche ROTATIVE (presse.css, chargée en dernier sur les 409 pages
   de la boutique) retourne ces variables vers l'encre noire :
   --encre passe de #fff à #141210, --laine de 255,255,255 à 20,18,16.
   MESURÉ AU CALCUL, encre #141210 sur le fond #12172A du panneau :
     · titre « Où souhaitez-vous aller ? » ......... 1,05:1
     · phrase « Une seule maison, deux versants » .. 1,04:1
     · « Accueil de la boutique » / « L'application » 1,05:1
     · la croix de fermeture ....................... 1,04:1
   Le minimum lisible est 4,5:1 ; 1,05:1, c'est du noir sur du noir.
   Seule la sur-ligne « MuslimOs » survivait, parce qu'elle est la
   seule à porter une couleur littérale (--bleu-clair, que la
   surcouche ne retourne pas).
   Les encres sont donc ÉCRITES ICI, en clair. Après : 15,7:1 pour le
   titre et les deux portes, 9,1:1 pour les phrases secondaires.
   Même raison pour --pc/--pc2 : ils lisaient --or et --or-clair, que
   ROTATIVE remplace par le vermillon #E8380D — la porte de
   l'application perdait son doré et l'écrin de son arc virait au
   rouge derrière un arc resté doré (le tracé SVG, lui, est en dur
   dans le HTML). */
#porteMaison{
  /* margin:auto centre un dialogue modal dans les deux sens ; sans lui
     il se colle en haut de l'écran. padding:0 pour que le clic sur le
     voile ne touche jamais une bande morte du dialogue. */
  margin:auto;padding:0;border:0;overflow:visible;
  width:min(430px,calc(100vw - 28px));max-width:none;
  background:transparent;color:#EDF1FA;
  opacity:0;transform:translateY(14px) scale(.985);
  transition:opacity 240ms var(--e-doux),
             transform 320ms var(--e-sortie),
             overlay 320ms allow-discrete,
             display 320ms allow-discrete;
}
#porteMaison[open]{opacity:1;transform:none}
/* @starting-style donne au navigateur l'état AVANT l'ouverture ; sans
   lui, un élément qui vient de passer de display:none à display:block
   n'a pas d'état de départ et n'anime rien. Là où il n'existe pas, le
   panneau apparaît d'un coup — il reste utilisable, c'est tout. */
@starting-style{ #porteMaison[open]{opacity:0;transform:translateY(14px) scale(.985)} }
#porteMaison::backdrop{
  background:rgba(6,11,24,.74);
  backdrop-filter:blur(7px);-webkit-backdrop-filter:blur(7px);
  opacity:0;transition:opacity 260ms var(--e-doux),overlay 260ms allow-discrete,
                       display 260ms allow-discrete;
}
#porteMaison[open]::backdrop{opacity:1}
@starting-style{ #porteMaison[open]::backdrop{opacity:0} }

.pm{
  position:relative;padding:26px 22px 22px;border-radius:26px;
  background:
    radial-gradient(120% 90% at 18% -10%,rgba(92,147,240,.22) 0%,transparent 58%),
    linear-gradient(180deg,#1A2236 0%,#12172A 62%,#0E1222 100%);
  box-shadow:inset 0 0 0 1px rgba(150,195,255,.20),
             0 42px 80px -36px rgba(0,0,0,.95);
}
/* 44 px, et pas 40 : c'est la plus petite cible qu'un pouce touche à
   coup sûr. Mesurée à 40 px sur un écran de 375 px, la croix était la
   seule commande du panneau sous ce seuil — les deux portes font 70 et
   80 px de haut. */
.pm__fermer{
  position:absolute;top:11px;right:11px;width:44px;height:44px;border-radius:999px;
  display:grid;place-items:center;font-size:1rem;line-height:1;
  /* en dur : voir l'en-tête du panneau — 1,04:1 avant, 11,9:1 après */
  color:rgba(237,241,250,.80);background:rgba(237,241,250,.07);
  box-shadow:inset 0 0 0 1px rgba(237,241,250,.14);
  transition:color var(--t-survol) var(--e-doux),background-color var(--t-survol) var(--e-doux);
}
.pm__fermer:focus-visible{outline:3px solid var(--bleu-clair);outline-offset:3px}
@media (hover:hover) and (pointer:fine){
  .pm__fermer:hover{color:#EDF1FA;background:rgba(237,241,250,.13)}
}
/* « ESPACÉE » : la sur-ligne est le seul endroit du panneau où l'on
   pousse l'interlettrage à .24em. Sur trois mots courts, l'air se lit
   comme du calme ; sur une phrase, il se lirait comme une panne. */
.pm__sur{font-family:var(--f-mono);font-size:.6rem;letter-spacing:.24em;
  text-transform:uppercase;color:var(--bleu-clair);margin-bottom:7px}
.pm__titre{font-family:var(--f-titre);font-weight:600;
  font-size:1.42rem;line-height:1.25;letter-spacing:.004em;
  margin:0 52px 4px 0}   /* 44 de croix + 8 d'air : le titre ne passe jamais dessous */
.pm__mot{font-family:var(--f-titre);font-size:.86rem;line-height:1.6;
  color:rgba(237,241,250,.74);margin-bottom:16px;max-width:34ch}
.pm__choix{display:flex;flex-direction:column;gap:10px}

.pm__porte{
  /* ⚠ REGLE GENERALE DE CE FICHIER : tout ce qui doit RESTER dore
     malgre la peau ROTATIVE se code EN DUR.
     presse.css est chargee en dernier et reecrit --or ET
     --or-clair en #E8380D. Mesure le 20/08 dans le navigateur.
     var(--or*) n'est pas une couleur ici : c'est un emplacement
     que la rotative peut reprendre.
     --pc/--pc2 EN DUR : ROTATIVE remplace --or par le vermillon, et la
     porte « L'application » virait au rouge autour d'un arc doré.
     ⚠ 20/08 — ILS ETAIENT BLEUS (#5C93F0/#9CC6FF) : l'ecrin de la porte
     « boutique » cerclait de bleu une arche devenue doree. Les deux
     portes portent desormais l'or de la maison. La distinction entre
     les deux versants ne se fait plus par la COULEUR DU LOGO — un
     logo, une maison — mais par le texte de chaque porte. */
  --pc:#5C93F0;--pc2:#9CC6FF;
  display:flex;align-items:center;gap:13px;
  padding:13px 14px;border-radius:18px;text-decoration:none;color:inherit;
  background:rgba(237,241,250,.05);
  box-shadow:inset 0 0 0 1px rgba(237,241,250,.13);
  transition:background-color var(--t-survol) var(--e-doux),
             box-shadow var(--t-survol) var(--e-doux),
             transform var(--t-survol) var(--e-sortie);
}
.pm__porte--app{--pc:#F0A830;--pc2:#FFE0A3}
.pm__arc{
  flex:0 0 auto;display:grid;place-items:center;width:44px;height:44px;border-radius:14px;
  background:radial-gradient(120% 120% at 28% 0%,
    color-mix(in oklab,var(--pc) 34%,transparent) 0%,rgba(10,16,32,.92) 66%);
  box-shadow:inset 0 0 0 1px color-mix(in oklab,var(--pc2) 40%,transparent);
}
.pm__arc svg{width:26px;height:26px;display:block}
.pm__mots{display:flex;flex-direction:column;gap:3px;flex:1;min-width:0}
.pm__mots b{font-family:var(--f-titre);font-weight:600;font-size:1.02rem;
  letter-spacing:.01em;line-height:1.2;color:#F4F7FF}
.pm__mots i{font-style:normal;font-size:.72rem;line-height:1.35;color:rgba(237,241,250,.74)}
.pm__fleche{flex:0 0 auto;width:17px;height:17px;color:var(--pc2);opacity:.62;
  transition:transform var(--t-survol) var(--e-sortie),opacity var(--t-survol)}
.pm__porte:focus-visible{outline:3px solid var(--pc2);outline-offset:3px}
@media (hover:hover) and (pointer:fine){
  .pm__porte:hover{background:color-mix(in oklab,var(--pc) 16%,transparent);
    box-shadow:inset 0 0 0 1px color-mix(in oklab,var(--pc2) 38%,transparent);
    transform:translateY(-2px)}
  .pm__porte:hover .pm__fleche{transform:translateX(4px);opacity:1}
}
.pm__porte:active{transform:translateY(1px);transition-duration:var(--t-micro)}

/* On calme, on n'éteint pas : le panneau reste, il arrête de glisser. */
@media (prefers-reduced-motion:reduce) and (min-width:999999px) /* desarme 17/08 : data-calme est le seul interrupteur */{
  #porteMaison,#porteMaison::backdrop,.pm__porte,.pm__fleche{transition:none!important}
  #porteMaison{transform:none!important}
}
html[data-calme="1"] #porteMaison,
html[data-calme="1"] #porteMaison::backdrop{transition:none!important}

/* ══ LA BARRE DES CATÉGORIES, EN HAUT DE L'ACCUEIL ══
   ⚠ 20/08 — « les catégories en haut faut pouvoir rester appuyer et
   defiler gauche droite ». Le glissement à la souris existait déjà
   (socle.js, bloc GLISSER LA BANDE, `#sommaire` est dans BANDES) :
   ce n'est pas lui qui manquait. C'EST LE CENTRAGE QUI TUAIT UN SENS
   SUR DEUX, et c'est mesuré dans la page :

     largeur 1280 px — la barre mesure 723 px, son contenu 797 :
       elle déborde de 74. `justify-content:center` centre ce contenu,
       donc il dépasse de 37 px de CHAQUE côté. Or `scrollLeft` ne
       descend jamais sous 0 : les 73 px de gauche — le rayon 01,
       « Huiles » — sont hors d'atteinte. Relevé au
       getBoundingClientRect à scrollLeft = 0 : la barre commence à
       x = 333, le premier lien à x = 260. Il est coupé, et AUCUN
       geste vers la droite ne le ramène.
     largeur 1600 px — même défaut, 46 px coupés. Ce n'est donc pas
       « un problème de petit écran » : la barre était tronquée
       jusque sur les grands.

   `safe center` dit au navigateur : centre TANT QUE ça rentre, et
   aligne au début dès que ça déborde. Les deux déclarations sont
   écrites l'une après l'autre — un navigateur qui ignore le mot-clé
   `safe` jette la seconde ligne et garde exactement le rendu
   d'avant, jamais rien de pire. */
#sommaire{display:flex;gap:4px;flex:1;justify-content:center;
  justify-content:safe center;overflow-x:auto;scrollbar-width:none}
#sommaire::-webkit-scrollbar{display:none}
#sommaire a{font-family:var(--f-mono);font-size:.7rem;letter-spacing:.1em;text-transform:uppercase;
  text-decoration:none;white-space:nowrap;padding:9px 12px;border-radius:999px;
  color:var(--encre2);transition:color .2s,background-color .2s}
#sommaire a b{color:var(--or);margin-right:6px}
#sommaire a[data-actif]{color:var(--nuit);background:var(--u2)}
#sommaire a[data-actif] b{color:var(--nuit)}
@media (hover:hover) and (pointer:fine){#sommaire a:hover{color:var(--encre);background:var(--b10)}}

/* ══ BANDEAUX de retour ══ */
.bandeau{padding:14px 16px;font-size:.9rem;font-weight:800;text-align:center}
.bandeau.ok{background:#12A177;color:#052F22}
.bandeau.non{background:var(--nuit2);color:var(--encre2)}

/* ══════════ LE HÉROS ══════════ */
#hero{position:relative;min-height:100svh;display:grid;place-items:center;
  overflow:clip;isolation:isolate;background:var(--u1);
  padding:clamp(60px,9svh,100px) 5vw clamp(30px,6svh,60px);
  transition:background-color var(--t-long) var(--e-inout)}
.hero__fond{position:absolute;inset:0;z-index:0;
  background:radial-gradient(72% 55% at 50% 34%,
    color-mix(in oklab,var(--u2) 34%,var(--u1)) 0%,var(--u1) 58%,
    color-mix(in oklab,var(--nuit) 55%,var(--u1)) 118%)}
/* le gobo : des ombres qui dérivent — c'est ce qui empêche le fond d'être mort */
.hero__gobo{position:absolute;inset:-12%;z-index:1;mix-blend-mode:multiply;
  opacity:.20;filter:contrast(1.5);pointer-events:none}
.hero__gobo i{position:absolute;display:block;border-radius:50%;
  background:radial-gradient(50% 50% at 50% 50%,#000 0%,transparent 70%);
  filter:blur(60px);will-change:transform}
.hero__gobo i:nth-child(1){width:58%;height:52%;left:-8%;top:-6%;
  animation:derive-a 37s var(--e-inout) infinite alternate}
.hero__gobo i:nth-child(2){width:46%;height:64%;right:-6%;top:18%;
  animation:derive-b 29s var(--e-inout) infinite alternate}
.hero__gobo i:nth-child(3){width:70%;height:38%;left:12%;bottom:-14%;
  animation:derive-c 43s var(--e-inout) infinite alternate}
@keyframes derive-a{to{transform:translate3d(14%,9%,0) scale(1.18)}}
@keyframes derive-b{to{transform:translate3d(-11%,-13%,0) scale(.86)}}
@keyframes derive-c{to{transform:translate3d(9%,-7%,0) scale(1.10)}}
.hero__geant{position:absolute;z-index:2;top:20%;right:-2%;left:auto;translate:0;
  color:color-mix(in oklab,var(--u3) 30%,transparent);pointer-events:none;
  transition:color var(--t-long) var(--e-inout)}
.hero__dedans{position:relative;z-index:5;display:grid;grid-template-columns:1fr 1fr;
  gap:clamp(20px,4vw,60px);align-items:center;width:100%;max-width:1240px}
.hero__scene{position:relative;display:grid;place-items:center}
.hero__halo{position:absolute;z-index:-1;width:84%;aspect-ratio:1;
  background:radial-gradient(50% 50% at 50% 48%,
    color-mix(in oklab,var(--u3) 58%,transparent) 0%,
    color-mix(in oklab,var(--u2) 22%,transparent) 40%,transparent 70%);
  filter:blur(44px);opacity:.62}
.hero__packshot{display:block;height:clamp(240px,52svh,540px);width:auto;
  border-radius:24px;object-fit:cover;
  filter:drop-shadow(0 30px 34px rgba(0,0,0,.42)) drop-shadow(0 3px 3px rgba(0,0,0,.24));
  animation:flotte 6.4s cubic-bezier(.45,0,.55,1) infinite alternate;will-change:transform;
  transition:opacity .45s var(--e-doux)}
.hero__ombre{position:absolute;z-index:-2;bottom:-4%;left:50%;width:46%;height:6%;
  translate:-50% 0;
  background:radial-gradient(50% 50% at 50% 50%,rgba(0,0,0,.62) 0%,rgba(0,0,0,.30) 44%,transparent 74%);
  filter:blur(9px) contrast(1.5);mix-blend-mode:multiply;pointer-events:none;
  animation:respire 6.4s cubic-bezier(.45,0,.55,1) infinite alternate}
/* amplitude FAIBLE : 2,4 % et 1,1°. Au-delà, ça fait jouet. */
@keyframes flotte{from{transform:translate3d(0,0,0) rotate(0)}
                  to{transform:translate3d(0,-2.4%,0) rotate(-1.1deg)}}
/* l'ombre respire EN CONTRE-PHASE : c'est ce détail qui fait croire à la lumière */
@keyframes respire{from{transform:translateX(-50%) scale(1,1);opacity:.30}
                   to{transform:translateX(-50%) scale(.86,.80);opacity:.16}}
.hero__texte{display:flex;flex-direction:column;gap:14px;align-items:flex-start}
.hero__texte h1{font-family:var(--f-titre);font-size:clamp(2rem,4.2vw,3.3rem);
  line-height:1.08;letter-spacing:-.004em}
.hero__actions{display:flex;gap:12px;flex-wrap:wrap;margin-top:8px}
.hero__flechesV{display:flex;gap:10px;margin-top:10px;align-items:center}
.hero__pts{display:flex;gap:6px;margin-left:8px}
.hero__pts i{width:8px;height:8px;border-radius:999px;background:var(--b30);
  transition:background-color .3s,width .3s}
.hero__pts i[data-on]{background:var(--u2);width:22px}
.hero__grain{position:absolute;inset:0;z-index:9;pointer-events:none;opacity:.09;
  mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='140'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/></filter><rect width='140' height='140' filter='url(%23n)' opacity='.6'/></svg>");
  background-size:180px 180px}

/* ══ BANDEAU DÉFILANT ══ */
#defile{background:var(--u2);color:var(--nuit);overflow:hidden;position:relative;
  padding:13px 0;transition:background-color var(--t-long) var(--e-inout)}
#defile .piste{display:flex;gap:2.2rem;width:max-content;
  animation:glisse 26s linear infinite;font-family:var(--f-titre);
  /* Les cinq phrases sont écrites en bas de casse dans accueil.js. En
     capitales elles hurlaient ; à l'humane, espacées, elles se lisent
     comme la devanture qu'elles sont. */
  font-size:clamp(.95rem,1.6vw,1.3rem);letter-spacing:.04em}
#defile:hover .piste{animation-play-state:paused}
@keyframes glisse{to{transform:translateX(-50%)}}

/* ══ MANIFESTE ══ */
#manifeste{padding-top:clamp(56px,10vh,120px);padding-bottom:clamp(40px,7vh,80px)}
#manifeste h2{margin-bottom:26px}
#refus{display:flex;gap:10px;flex-wrap:wrap;margin-bottom:24px}
#refus span{font-family:var(--f-mono);font-size:.76rem;padding:10px 16px;border-radius:999px;
  background:var(--nuit2);color:var(--encre2);box-shadow:inset 0 0 0 1px var(--b10)}
#refus b{color:#FF6B4A;margin-right:7px}

/* ══ PORTES ══ */
#portes{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(290px,1fr));
  padding-bottom:clamp(40px,7vh,80px)}

/* ══ GAGES ══ */
#gages{border-top:1px solid var(--b10);border-bottom:1px solid var(--b10);
  padding:22px 0;display:flex;gap:clamp(16px,4vw,52px);flex-wrap:wrap;justify-content:center}
#gages span{font-family:var(--f-mono);font-size:.74rem;letter-spacing:.05em;color:var(--encre2);
  display:flex;gap:9px;align-items:center}
#gages svg{width:15px;height:15px;flex:0 0 auto;color:var(--or)}
#gages a{color:var(--or-clair);font-weight:700}

/* ══ LES RAYONS ══ */
.rayon{position:relative;padding:clamp(56px,10vh,120px) 0;isolation:isolate;
  background:var(--u1);transition:background-color var(--t-long) var(--e-inout)}
.rayon::before{content:'';position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:radial-gradient(60% 50% at 18% 0%,
    color-mix(in oklab,var(--u2) 22%,transparent) 0%,transparent 65%)}
.rayon-tete{display:flex;align-items:flex-end;gap:20px;flex-wrap:wrap;margin-bottom:12px}
.rayon-num{font-family:var(--f-mono);font-size:.8rem;letter-spacing:.16em;color:var(--u3);
  padding-bottom:.5rem}
.rayon-cpt{font-family:var(--f-mono);font-size:.76rem;color:var(--encre2);padding-bottom:.6rem}
.rayon-mot{margin-bottom:30px;color:color-mix(in oklab,var(--u3) 88%,white)}
.grille{display:grid;gap:clamp(12px,1.6vw,20px);
  grid-template-columns:repeat(auto-fill,minmax(160px,1fr))}
@media(min-width:760px){.grille{grid-template-columns:repeat(auto-fill,minmax(220px,1fr))}}
.produit{
  background:var(--creme);color:var(--nuit);border-radius:18px;overflow:hidden;
  cursor:pointer;text-align:left;display:flex;flex-direction:column;position:relative;
  box-shadow:0 14px 34px -20px rgba(0,0,0,.7);
  opacity:0;transform:translateY(18px);
  transition:opacity .55s var(--e-sortie),transform .55s var(--e-sortie),box-shadow .25s;
}
.produit.visible{opacity:1;transform:none}
@media (hover:hover) and (pointer:fine){
  .produit:hover{transform:translateY(-6px);box-shadow:0 30px 56px -26px rgba(0,0,0,.85)}
  .produit:hover .cadre img{transform:scale(1.06)}
}
.produit .cadre{aspect-ratio:1/1.02;background:var(--blanc);overflow:hidden;position:relative}
.produit .cadre img{width:100%;height:100%;object-fit:cover;transition:transform .6s var(--e-sortie)}
.badge{position:absolute;top:10px;left:10px;z-index:2;padding:5px 11px;border-radius:999px;
  font-family:var(--f-mono);font-size:.62rem;letter-spacing:.08em;text-transform:uppercase}
.badge.mort{background:rgba(18,13,10,.86);color:var(--creme)}
.badge.choix{background:var(--u2);color:var(--nuit);font-weight:700}
.produit .infos{padding:13px 14px 15px;display:flex;flex-direction:column;gap:7px;flex:1}
.produit h3{font-size:.87rem;line-height:1.3;font-weight:700;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.produit .bas{margin-top:auto;display:flex;align-items:baseline;gap:8px}
.prix{font-weight:900;font-size:1.02rem;font-variant-numeric:tabular-nums}
.produit .var{font-family:var(--f-mono);font-size:.66rem;color:#8A6A50}
.voir-plus{margin:26px auto 0;display:flex}

/* ══ FAÇON DE VENDRE ══ */
#facon{background:var(--nuit);padding:clamp(56px,10vh,110px) 0}
#facon ol{list-style:none;display:grid;gap:14px;margin-top:30px;
  grid-template-columns:repeat(auto-fit,minmax(250px,1fr))}
#facon li{background:var(--nuit2);border-radius:18px;padding:26px;line-height:1.65;
  font-size:.93rem;color:var(--encre2);box-shadow:inset 0 0 0 1px var(--b10)}
#facon li b{display:block;font-family:var(--f-titre);font-size:2.6rem;color:var(--or);
  margin-bottom:10px;line-height:1}

/* ══ LA MAISON — la respiration claire, rien ne bouge ══ */
#maison{background:var(--creme);color:var(--nuit);padding:clamp(56px,10vh,110px) 0}
#maison .deux{display:grid;grid-template-columns:1.1fr .9fr;gap:clamp(24px,4vw,60px);
  align-items:center}
#maison h2{color:var(--nuit);margin-bottom:16px}
#maison p{line-height:1.75;color:#5A4634;font-size:.97rem;max-width:56ch}
#maison p b{color:var(--nuit)}
#maison .carte{background:var(--blanc);border-radius:20px;padding:28px;
  box-shadow:0 20px 44px -26px rgba(0,0,0,.4)}
#maison .carte h3{font-family:var(--f-titre);font-size:1.5rem;letter-spacing:-.004em;
  margin-bottom:10px}
#maison .carte a{font-weight:800;color:#A96F14}

/* ══ PIED ══ */
footer{background:var(--nuit);padding:34px 0 46px;border-top:1px solid var(--b10)}
footer .lignes{display:flex;gap:20px;flex-wrap:wrap;justify-content:space-between;
  align-items:center;font-family:var(--f-mono);font-size:.74rem;color:var(--encre2)}
footer nav{display:flex;gap:18px;flex-wrap:wrap}
footer a{text-decoration:none}
footer a:hover{color:var(--or-clair)}
footer details{margin-top:18px;max-width:70ch;color:var(--encre2);font-size:.84rem}
footer summary{font-weight:800;cursor:pointer;padding:9px 0;color:var(--encre)}
footer details p{padding:2px 0 10px;line-height:1.7}

/* ══ FICHE PRODUIT ══ */
#voile{position:fixed;inset:0;background:rgba(10,6,4,.7);z-index:80;
  opacity:0;pointer-events:none;transition:opacity .3s ease;backdrop-filter:blur(3px)}
#voile.on{opacity:1;pointer-events:auto}
#fiche{position:fixed;z-index:90;background:var(--nuit2);color:var(--encre);
  inset:auto 0 0 0;max-height:94svh;border-radius:26px 26px 0 0;
  transform:translateY(103%);transition:transform 520ms var(--e-ciao);
  display:flex;flex-direction:column;overflow:hidden}
#fiche.on{transform:none}
@media(min-width:940px){
  #fiche{inset:0 0 0 auto;width:min(960px,95vw);max-height:none;
    border-radius:26px 0 0 26px;transform:translateX(103%)}
  #fiche .corps{display:grid;grid-template-columns:1fr 1.05fr}
}
#fiche .corps{overflow-y:auto;flex:1;overscroll-behavior:contain}
#fFermer{position:absolute;top:14px;right:14px;z-index:6;width:46px;height:46px;
  border-radius:999px;background:var(--b10);color:var(--encre);font-size:1.1rem;font-weight:900;
  backdrop-filter:blur(8px)}
.f-photos{background:var(--u1);padding:26px;display:flex;flex-direction:column;gap:12px;
  transition:background-color var(--t-long) var(--e-inout)}
#fImage{width:100%;aspect-ratio:1;object-fit:contain;border-radius:16px;cursor:zoom-in;
  filter:drop-shadow(0 20px 30px rgba(0,0,0,.4))}
.f-mini{display:flex;gap:8px;flex-wrap:wrap}
.f-mini img{width:56px;height:56px;object-fit:cover;border-radius:10px;cursor:pointer;
  border:2px solid transparent;opacity:.6;transition:opacity .2s,border-color .2s}
.f-mini img[data-on]{border-color:var(--u2);opacity:1}
.f-infos{padding:28px clamp(18px,3vw,36px) 180px}
#fTitre{margin:10px 0 8px}
#fAccroche{color:var(--u3);font-size:1.02rem;line-height:1.55;margin-bottom:18px}
.f-prixLigne{display:flex;align-items:baseline;gap:14px;flex-wrap:wrap}
#fPrix{font-family:var(--f-titre);font-size:2.4rem;letter-spacing:-.02em;color:var(--u2)}
.f-port{font-family:var(--f-mono);font-size:.72rem;color:var(--encre2)}
#fDate{margin:14px 0 18px;padding:13px 16px;border-radius:14px;font-size:.86rem;font-weight:700;
  background:var(--b5);color:var(--u3);box-shadow:inset 0 0 0 1px var(--b10)}
#fVarZone{margin-bottom:18px}
#fVarZone label{font-family:var(--f-mono);font-size:.7rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--encre2)}
#fVar{width:100%;margin-top:8px;padding:14px;border-radius:12px;font:inherit;font-size:1rem;
  border:1.5px solid var(--b20);background:var(--nuit);color:var(--encre);min-height:52px}
#fDesc{font-size:.92rem;line-height:1.75;color:var(--encre2);margin-bottom:20px}
.f-salam{border-radius:16px;padding:18px;margin-bottom:20px;background:var(--b5);
  box-shadow:inset 0 0 0 1px var(--b10)}
.f-salam h4{font-family:var(--f-mono);font-size:.68rem;letter-spacing:.14em;text-transform:uppercase;
  color:var(--or);margin-bottom:12px}
.f-salam ol{list-style:none;display:grid;gap:9px;font-size:.86rem;line-height:1.55;
  color:var(--encre2)}
.f-salam b{color:var(--or)}
#fEnsemble h4{font-family:var(--f-mono);font-size:.68rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--encre2);margin-bottom:12px}
.duo{display:flex;gap:10px}
.duo .mini{flex:1;display:flex;gap:10px;align-items:center;text-align:left;
  background:var(--b5);border-radius:14px;padding:10px;cursor:pointer;
  box-shadow:inset 0 0 0 1px var(--b10);transition:transform .16s var(--e-sortie)}
@media (hover:hover) and (pointer:fine){.duo .mini:hover{transform:translateY(-2px)}}
/* 17/08 : flex:none — l'image est un enfant flex, le texte la
   comprimait (mesurée 26×50 au lieu de 50×50). Et contain, pas cover :
   une découpe haute passée en cover ne montrait qu'une tranche. */
.duo .mini img{flex:none;width:50px;height:50px;object-fit:contain;border-radius:9px;background:var(--blanc)}
.duo .mini b{font-size:.75rem;line-height:1.25;display:block}
.duo .mini i{font-style:normal;font-size:.78rem;font-weight:900;color:var(--u2)}
.f-achat{position:absolute;bottom:0;left:0;right:0;z-index:5;
  padding:16px clamp(18px,3vw,36px) 20px;
  background:linear-gradient(to top,var(--nuit2) 74%,transparent)}
.f-achat .btn{width:100%}
#fAjouter{margin-top:9px;min-height:52px;font-size:.88rem}
.f-sous{font-family:var(--f-mono);font-size:.68rem;color:var(--encre2);text-align:center;
  margin-top:10px}

/* ══ ZOOM ══ */
#zoom{position:fixed;inset:0;z-index:120;background:rgba(10,6,4,.95);
  display:none;align-items:center;justify-content:center;cursor:zoom-out}
#zoom.on{display:flex}
#zoom img{max-width:94vw;max-height:92svh;object-fit:contain;border-radius:10px}

/* ══ PANIER ══ */
#panier{position:fixed;z-index:90;inset:0 0 0 auto;width:min(450px,96vw);
  background:var(--nuit2);color:var(--encre);display:flex;flex-direction:column;
  transform:translateX(103%);transition:transform 520ms var(--e-ciao)}
#panier.on{transform:none}
#panier .tete{display:flex;align-items:center;gap:10px;padding:22px 22px 12px}
#panier .tete h2{flex:1;font-family:var(--f-titre);font-size:1.5rem;letter-spacing:-.004em}
#pFermer{width:44px;height:44px;border-radius:999px;background:var(--b10);font-weight:900}
#pBarreZone{padding:0 22px 14px}
#pBarreMot{font-family:var(--f-mono);font-size:.72rem;color:var(--u3);margin-bottom:8px}
#pBarre{height:8px;border-radius:999px;background:var(--b10);overflow:hidden}
#pBarre i{display:block;height:100%;width:0;background:var(--u2);border-radius:999px;
  box-shadow:0 0 14px var(--u2);transition:width var(--t-transit) var(--e-sortie)}
#pLignes{flex:1;overflow-y:auto;padding:2px 22px;overscroll-behavior:contain}
.p-ligne{display:grid;grid-template-columns:56px 1fr auto;gap:12px;align-items:center;
  padding:13px 0;border-bottom:1px solid var(--b10)}
.p-ligne img{width:56px;height:56px;object-fit:cover;border-radius:10px;background:var(--blanc)}
.p-ligne h4{font-size:.82rem;line-height:1.3;font-weight:700;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.p-v{font-family:var(--f-mono);font-size:.66rem;color:var(--encre2)}
.p-qte{display:flex;align-items:center;gap:3px;margin-top:7px}
/* 17/08 : la zone sensible du doigt fait 44 px sans grossir le bouton —
   même recette que commande.css (un ::after qui déborde, invisible). */
.p-qte button{width:30px;height:30px;border-radius:9px;background:var(--b10);font-weight:900;
  position:relative}
.p-qte button::after{content:'';position:absolute;inset:-7px}
.p-qte b{min-width:26px;text-align:center;font-size:.88rem}
.p-retirer{font-family:var(--f-mono);font-size:.64rem;color:var(--encre2);margin-top:5px;
  text-decoration:underline;position:relative}
/* 17/08 : le mot fait 17 px de haut, la cible en fait 44. */
.p-retirer::after{content:'';position:absolute;left:-8px;right:-8px;
  top:50%;height:44px;transform:translateY(-50%)}
.p-prix{font-weight:900;font-variant-numeric:tabular-nums;font-size:.9rem}
#pVide{padding:46px 18px;text-align:center;color:var(--encre2);line-height:1.75;font-size:.9rem}
#pIdee{padding:12px 22px 0}
#pIdee h4{font-family:var(--f-mono);font-size:.66rem;letter-spacing:.12em;text-transform:uppercase;
  color:var(--encre2);margin-bottom:9px}
#pBas{padding:16px 22px 22px;border-top:1px solid var(--b10)}
.p-sous{display:flex;justify-content:space-between;font-size:.85rem;color:var(--encre2);
  margin-bottom:6px}
.p-sous b{font-variant-numeric:tabular-nums;color:var(--encre)}
.p-total{display:flex;justify-content:space-between;align-items:baseline;margin:10px 0 6px}
.p-total span{font-family:var(--f-mono);font-size:.76rem;letter-spacing:.1em;text-transform:uppercase}
.p-total b{font-family:var(--f-titre);font-size:1.9rem;color:var(--u2);letter-spacing:-.02em}
.p-note{font-size:.73rem;color:var(--encre2);margin:8px 0 14px;line-height:1.6}

/* ══ CE QUI EST ÉPUISÉ SE VOIT DANS LE PANIER (18/08 soir) ══
   La ligne s'éteint sans disparaître — le client doit reconnaître ce
   qu'il avait choisi pour décider de le retirer. Le titre et le mot
   « Épuisé » gardent leur pleine lisibilité : on n'efface JAMAIS
   l'information qui explique le refus, on efface la photo et le décor.
   L'opacité ne descend donc que sur l'image, jamais sur du texte —
   un texte à .5 sur le fond nuit tombe sous 4,5:1. */
.p-ligne--epuise img{opacity:.42;filter:grayscale(1)}
.p-epuise{grid-column:2;font-family:var(--f-mono);font-size:.64rem;
  letter-spacing:.06em;color:#FF8A6E;font-weight:700;margin:3px 0 2px}
.p-ligne--epuise .p-prix{color:var(--encre2);font-weight:700}
/* Le mot au-dessus du bouton mort. Il NOMME l'article : le message du
   serveur, lui, ne le pouvait pas. */
.p-note--epuise{color:#FF8A6E;font-weight:700}
#pPayer:disabled{opacity:.5;cursor:not-allowed}
#pPayer{width:100%}
#pErreur{font-size:.78rem;color:#FF6B4A;font-weight:700;margin-top:10px;display:none}

/* ══ ANNONCE ══ */
#annonce{position:fixed;left:50%;bottom:22px;transform:translateX(-50%) translateY(90px);
  z-index:110;background:var(--u2);color:var(--nuit);font-size:.86rem;font-weight:800;
  padding:14px 24px;border-radius:999px;opacity:0;transition:all .35s var(--e-sortie);
  pointer-events:none;box-shadow:0 18px 40px -16px rgba(0,0,0,.9)}
#annonce.on{opacity:1;transform:translateX(-50%)}

/* ══ RÉVÉLATIONS ══ */
.revele{opacity:0;transform:translateY(20px);
  transition:opacity var(--t-entree) var(--e-sortie),transform var(--t-entree) var(--e-sortie)}
.revele.visible{opacity:1;transform:none}

/* ══ MOUVEMENT REDUIT : ON CALME, ON N'ETEINT PAS ══
   La version precedente coupait tout, jusqu'au fondu de couleur. Or
   beaucoup d'appareils arrivent avec ce reglage actif (economiseur de
   batterie, mode simplifie) : la boutique y paraissait morte, et
   personne ne va fouiller ses parametres pour reparer un site.

   WCAG 2.3.3 vise les mouvements AMPLES — derives, paralaxes, boucles
   infinies — parce qu'ils donnent des vertiges. Une transition de
   couleur de 200 ms n'a jamais ete concernee. On coupe donc ce qui
   tourne en boucle, et on garde ce qui fait respirer. */
@media (prefers-reduced-motion:reduce) and (min-width:999999px) /* desarme 17/08 : data-calme est le seul interrupteur */{
  /* Les boucles infinies et les grandes derives : elles s'arretent. */
  .fond-a,.fond-b,.fond-c,#btnPanier,.bandeau__ruban{animation:none!important}
  *,*::before,*::after{scroll-behavior:auto!important}
  /* Tout le reste garde une transition courte : couleur, opacite,
     apparition. 200 ms, c'est doux et ca ne declenche rien. */
  *,*::before,*::after{transition-duration:200ms!important}
  /* Les cartes apparaissent quand meme, sans glisser de loin. */
  .produit,.revele{transform:none!important}
}
/* L'interrupteur du site, lui, coupe vraiment tout : c'est un choix
   explicite de l'utilisateur, pas une supposition sur son appareil. */
html[data-calme="1"] *,html[data-calme="1"] *::before,html[data-calme="1"] *::after{
  animation:none!important;transition:none!important;scroll-behavior:auto!important}
html[data-calme="1"] .produit,html[data-calme="1"] .revele{opacity:1!important;transform:none!important}

@media(max-width:940px){
  /* ⚠ 20/08 — LA BARRE DES CATÉGORIES NE S'ÉTEINT PLUS SOUS 940 px.
     Elle était en `display:none` : mesuré à 375 px, l'accueil de la
     boutique n'offrait AUCUNE catégorie en haut — ni à glisser, ni à
     cliquer. C'est une moitié de la remarque « le site s'adapte qu'au
     moyen des écrans » : la navigation par rayon n'existait qu'entre
     941 px et l'infini.

     Elle passe donc EN SECONDE LIGNE, sur toute la largeur : la barre
     du haut garde son rang (menu, marque, panier) et la wrap la
     dépose dessous. Elle se glisse au doigt (`touch-action` posé en
     ligne par socle.js) comme à la souris maintenue (même fichier,
     bloc GLISSER LA BANDE) — et `safe center`, plus haut, garantit
     que le rayon 01 reste atteignable. */
  body > header .dedans{flex-wrap:wrap;row-gap:0;padding-bottom:6px}
  #sommaire{flex:1 0 100%;order:9;justify-content:flex-start;
    margin:2px -8px 0;padding:0 8px 2px;scroll-padding-inline:8px}
  /* ⚠ ON NE TOUCHE PAS A LA TAILLE DU TEXTE. Une version de ce
     bloc rapetissait les liens a .66rem « pour qu ils tiennent » :
     la bande se GLISSE et defile, elle n a jamais eu besoin de ca,
     et le proprietaire a vu le changement tout de suite. Seul
     l espacement se resserre. */
  #sommaire a{padding:8px 10px}
  .hero__dedans{grid-template-columns:1fr;gap:22px}
  .hero__scene{order:-1}
  .hero__packshot{height:clamp(190px,32svh,300px)}
  /* Réduit avec la police : à l'humane, le mot géant de la bannière
     est plus large qu'en condensée — relevé dans la page, il vaut
     « HUILES », qui fait 369,34 px en Palatino Linotype contre 270,31
     en Impact à 100 px, soit + 37 % — et 16vw le poussait hors du
     cadre. */
  .hero__geant{top:12%;right:-4%;font-size:clamp(2.1rem,11vw,4.2rem)}
  #maison .deux{grid-template-columns:1fr}
}

/* ══ LE RUBAN DU BANDEAU ══
   Le bandeau ne servait qu apres un paiement : vide le reste du temps,
   il donnait une barre morte sous la banniere. La piste fait DEUX FOIS
   la liste et glisse de -50 % : au moment ou l animation recommence, le
   second exemplaire occupe exactement la place du premier, et la boucle
   ne se voit pas. On l arrete au survol, pour qui veut lire. */
.bandeau.ruban{padding:0;overflow:hidden;background:var(--nuit2);
  color:var(--encre2);text-align:left}
.bandeau__ruban{display:flex;width:max-content;
  animation:ruban-defile 38s linear infinite}
.bandeau__ruban span,.bandeau__ruban a{display:inline-flex;align-items:center;
  padding:12px 0;margin-inline-end:44px;white-space:nowrap;
  font-size:.86rem;font-weight:700;letter-spacing:.04em}
.bandeau__ruban a{color:inherit;text-decoration:none}
.bandeau__ruban a:hover{text-decoration:underline}
.bandeau.ruban:hover .bandeau__ruban{animation-play-state:paused}


/* ══ LE MUR D AVIS — carrousel qui se glisse au doigt ══
   scroll-snap : chaque carte se cale d elle-meme, au doigt comme a la
   molette. Pas de bibliotheque, pas de bouton a maintenir. */
.avis-mur{padding:clamp(44px,7vh,90px) 0;background:var(--nuit2);overflow:hidden}
.avis-mur__d{width:min(94vw,1280px);margin-inline:auto}
.avis-mur h2{font-size:clamp(1.6rem,4vw,2.8rem);margin:0 0 8px}
.avis-mur__source{margin:0 0 26px;opacity:.7;font-size:.9rem;max-width:58ch}
.avis-mur__grille{display:flex;gap:16px;overflow-x:auto;padding-bottom:16px;
  scroll-snap-type:x mandatory;-webkit-overflow-scrolling:touch;
  scrollbar-width:none}
.avis-mur__grille::-webkit-scrollbar{display:none}
.avis{margin:0;padding:22px;flex:0 0 min(86vw,340px);scroll-snap-align:start;
  display:flex;flex-direction:column;gap:14px;border-radius:16px;
  background:rgba(var(--laine),.05);border:1px solid rgba(var(--laine),.12);
  transition:border-color 220ms ease,transform 220ms ease}
.avis:hover{border-color:rgba(var(--laine),.3);transform:translateY(-3px)}
.avis__produit{display:flex;align-items:center;gap:12px;text-decoration:none;
  min-height:44px;padding-bottom:12px;border-bottom:1px solid rgba(var(--laine),.1)}
.avis__produit img{width:54px;height:68px;object-fit:cover;flex:0 0 auto;
  border-radius:8px}
.avis__produit span{font-size:.82rem;line-height:1.3;opacity:.8}
.avis__produit:hover span{opacity:1;text-decoration:underline}
.avis blockquote{margin:0;font-size:1.02rem;line-height:1.5;flex:1}
.avis blockquote::before{content:"C"}
.avis blockquote::after{content:"D"}
.avis figcaption{font-size:.8rem;opacity:.6}
.avis-mur__glisse{font-size:.78rem;opacity:.5;margin:6px 0 0}

/* ══ LES AVIS DE NOS CLIENTS (fiche produit) ══ */
.pavis{width:min(94vw,1280px);margin:0 auto;padding:clamp(36px,6vh,72px) 0;
  border-top:1px solid rgba(var(--laine),.12)}
.pavis h2{font-size:clamp(1.4rem,3.2vw,2.2rem);margin:0 0 18px}
.pavis__moy{font-size:1.05rem;margin:0 0 16px}
.pavis__moy b{font-size:1.5rem}
.pavis__vide{opacity:.6;margin:0 0 18px}
.pavis__un{padding:14px 0;border-bottom:1px solid rgba(var(--laine),.08)}
.pavis__et{color:#E8B341;letter-spacing:2px}
.pavis__un p{margin:6px 0}
.pavis__un cite{font-style:normal;font-size:.82rem;opacity:.6}
.pavis__form{margin-top:22px}
.pavis__form summary{cursor:pointer;min-height:44px;display:flex;align-items:center;
  font-size:.8rem;letter-spacing:.13em;text-transform:uppercase}
.pavis__form form{display:grid;gap:14px;max-width:52ch;margin-top:14px}
.pavis__form label{display:grid;gap:6px;font-size:.86rem;opacity:.85}
.pavis__form textarea,.pavis__form input{font:inherit;padding:12px;
  background:rgba(var(--laine),.06);color:inherit;
  border:1px solid rgba(var(--laine),.18);border-radius:10px}
.etoiles{border:0;padding:0;margin:0;display:flex;gap:4px;align-items:center}
.etoiles legend{font-size:.86rem;opacity:.85;margin-bottom:6px}
.etoiles button{min-width:44px;min-height:44px;background:none;border:0;
  font-size:1.5rem;color:rgba(var(--laine),.28);cursor:pointer;
  transition:color 160ms ease}
.etoiles button[aria-pressed="true"]{color:#E8B341}
.pavis__note,.pavis__merci{font-size:.8rem;opacity:.6;margin:0}
.pavis__merci{opacity:1;color:#12A177}

/* ══════════ LA FICHE PRODUIT ══════════
   Ces classes existaient dans le HTML genere mais nulle part ici : la
   page se chargeait donc sans une seule regle, en HTML nu. */
.progres{position:fixed;top:0;left:0;height:3px;width:0;z-index:90;background:var(--or,#E8B341)}
.tete__d{width:min(94vw,1280px);margin-inline:auto;display:flex;align-items:center;
  gap:16px;min-height:64px}
/* Les 45 fiches produit écrivent « MuslimOs » ici. `var(--titre)`
   n'existe nulle part : la règle retombait sur `inherit`, donc sur la
   linéale, et la capitale forcée redonnait le MUSLIMOS de gymnase que
   le propriétaire refuse. On sert la même humane qu'à l'accueil et on
   rend au mot sa bas de casse — le HTML des fiches n'a pas à bouger. */
.logo{font-family:var(--f-titre);font-weight:600;
  font-size:1.14rem;letter-spacing:.04em;text-decoration:none;margin-inline-end:auto;
  min-height:44px;display:inline-flex;align-items:center}
.retour{min-height:44px;display:inline-flex;align-items:center;font-size:.74rem;
  letter-spacing:.14em;text-transform:uppercase;opacity:.6;text-decoration:none}
.retour:hover{opacity:1}
.panier-btn{min-height:44px;padding:0 16px;border-radius:999px;background:none;
  border:1px solid rgba(var(--laine),.3);color:inherit;font:inherit;font-size:.78rem;
  letter-spacing:.12em;text-transform:uppercase;cursor:pointer}
.fil{width:min(94vw,1280px);margin:18px auto 0;font-size:.8rem;opacity:.55}
.fil a{color:inherit;text-decoration:none}
.fil a:hover{text-decoration:underline}

/* 17/08 : minmax(0,…) OBLIGATOIRE. Une piste en « fr » nue refuse de
   descendre sous le min-content de son contenu : la section mode
   d'emploi (grille de volets) gonflait la piste à 1200 px et poussait
   toute la colonne d'achat HORS ÉCRAN (mesuré : .pachat à x=1285 pour
   un viewport de 1265). Le min-width:0 des enfants ferme la même
   porte au niveau du dessous. */
.pfiche{width:min(94vw,1280px);margin-inline:auto;display:grid;
  grid-template-columns:minmax(0,1.05fr) minmax(0,.95fr);gap:clamp(24px,4vw,56px);
  padding:clamp(20px,4vh,40px) 0 clamp(40px,7vh,80px);align-items:start}
.pfiche>*{min-width:0}
@media(max-width:900px){.pfiche{grid-template-columns:minmax(0,1fr)}}

.vitrine{display:grid;gap:12px}
#pvGrande{width:100%;aspect-ratio:4/5;object-fit:cover;border-radius:18px;
  background:#151013;cursor:zoom-in}
.vitrine__minis{display:flex;gap:10px}
.vitrine__minis button{width:72px;height:90px;padding:0;border-radius:10px;
  overflow:hidden;border:1px solid rgba(var(--laine),.16);background:none;cursor:pointer}
.vitrine__minis button[aria-current="true"]{border-color:var(--or,#E8B341)}
.vitrine__minis img{width:100%;height:100%;object-fit:cover}

.pachat .tt{font-size:.72rem;letter-spacing:.16em;text-transform:uppercase;opacity:.55;margin:0}
.pachat h1{font-size:clamp(1.5rem,3.2vw,2.4rem);line-height:1.06;margin:.3em 0 .5em}
.pprix{font-size:1.9rem;font-weight:800;margin:0 0 6px;font-variant-numeric:tabular-nums}
.pdelai{margin:0 0 20px;font-size:.9rem;opacity:.72;max-width:52ch}

.choix{margin:0 0 20px}
.choix .tt{margin:0 0 8px}
.choix__pastilles{display:flex;flex-wrap:wrap;gap:8px}
.choix__pastilles button{min-height:44px;padding:0 14px;border-radius:999px;
  background:none;color:inherit;font:inherit;font-size:.86rem;cursor:pointer;
  border:1px solid rgba(var(--laine),.24);display:inline-flex;align-items:center;gap:8px}
.choix__pastilles button i{font-style:normal;opacity:.6;font-size:.8rem}
.choix__pastilles button[aria-pressed="true"]{border-color:var(--or,#E8B341);
  background:rgba(232,179,65,.12)}

.pboutons{display:flex;flex-wrap:wrap;gap:12px;margin:0 0 14px}
.pboutons .btn{flex:1 1 200px;min-height:54px}
.pport{margin:0 0 22px;font-size:.86rem;opacity:.75;max-width:54ch}
.pport b{opacity:1}

.bons{list-style:none;margin:0 0 18px;padding:0;display:grid;gap:10px}
.bons li{display:grid;grid-template-columns:18px 1fr;gap:10px;font-size:.92rem;opacity:.85}
.bons svg{width:18px;height:18px;margin-top:3px;stroke:var(--or,#E8B341);fill:none;stroke-width:2.4}
.pachat details{border-top:1px solid rgba(var(--laine),.14);padding:14px 0}
.pachat summary{cursor:pointer;min-height:44px;display:flex;align-items:center;
  font-size:.78rem;letter-spacing:.13em;text-transform:uppercase}
.pachat details ul{margin:8px 0 0;padding-inline-start:20px;opacity:.75;font-size:.92rem}
.psobre{font-size:.84rem;opacity:.55;margin:16px 0 0}

.pvoisins{width:min(94vw,1280px);margin:0 auto;padding:clamp(30px,5vh,60px) 0;
  border-top:1px solid rgba(var(--laine),.12)}
.pvoisins h2{font-size:clamp(1.3rem,3vw,2rem);margin:0 0 20px}
.pvoisins__grille{display:flex;gap:clamp(12px,2vw,22px);
  overflow-x:auto;scroll-snap-type:x proximity;-webkit-overflow-scrolling:touch;
  scrollbar-width:none;padding-bottom:6px}
.pvoisins__grille>*{flex:0 0 clamp(190px,44vw,238px);scroll-snap-align:start}
.pcarte{display:flex;flex-direction:column;gap:8px;text-decoration:none;color:inherit}
.pcarte img{width:100%;aspect-ratio:4/5;object-fit:cover;border-radius:14px;background:#151013;
  transition:transform .5s cubic-bezier(.19,1,.22,1)}
.pcarte:hover img{transform:scale(1.04)}
.pcarte span{font-size:.88rem;line-height:1.3}
.pcarte b{font-size:.9rem;opacity:.7;font-weight:500}
.pcarte button{min-height:44px;border-radius:999px;background:none;color:inherit;
  border:1px solid rgba(var(--laine),.26);font:inherit;font-size:.74rem;
  letter-spacing:.12em;text-transform:uppercase;cursor:pointer}

.barre-achat{position:fixed;inset-inline:0;bottom:0;z-index:60;display:none;
  align-items:center;gap:14px;padding:10px 16px calc(10px + env(safe-area-inset-bottom));
  background:rgba(18,13,10,.94);border-top:1px solid rgba(var(--laine),.14);
  backdrop-filter:blur(12px)}
.barre-achat.on{display:flex}
.barre-achat b{font-size:1.1rem;font-variant-numeric:tabular-nums}
.barre-achat .btn{flex:1;min-height:48px}
@media(min-width:901px){.barre-achat{display:none!important}}

.zoom{position:fixed;inset:0;z-index:100;background:rgba(10,7,6,.94);display:none;
  place-items:center;padding:20px;cursor:zoom-out}
.zoom.on{display:grid}
.zoom img{max-width:100%;max-height:100%;object-fit:contain;border-radius:12px}

.ppied{width:min(94vw,1280px);margin:0 auto;padding:28px 0 40px;font-size:.86rem;
  opacity:.6;border-top:1px solid rgba(var(--laine),.12)}
.ppied a{color:inherit}

/* Le bloc d avis suit la meme largeur que le reste de la fiche, et son
   formulaire est centre : sans ca il se collait au bord gauche. */
.pavis{max-width:none}
.pavis__liste{max-width:62ch}
.pavis__form{max-width:52ch;margin-inline:auto;padding:22px;border-radius:16px;
  background:rgba(var(--laine),.04);border:1px solid rgba(var(--laine),.12)}
.pavis__form summary{justify-content:center}
.pavis__err{margin:0;color:#FF8C6B;font-size:.85rem}

/* ⚠ 20/08 — LE MESSAGE D’ÉCHEC DE L’ACHAT DIRECT.
   « Précommander » ouvre maintenant Stripe sans passer par le
   panier ; si la session ne s’ouvre pas, le client doit LIRE
   pourquoi et garder un chemin. Le message s’écrit sous le bouton.
   ⚠ LA COULEUR EST ÉCRITE EN DUR, comme --pc/--pc2 quelques
     centaines de lignes plus haut : `presse.css` (peau ROTATIVE,
     chargée en dernier) réécrit --or ET --or-clair en vermillon.
     Une erreur qui prendrait la couleur du jour ne se lirait plus.
     #FF8C6B est repris de .pavis__err juste au-dessus : une seule
     teinte d’alerte dans la maison. */
.pachat-err{margin:10px 0 0;color:#FF8C6B;font-size:.85rem;line-height:1.45}
.pachat-err a{color:inherit;text-decoration:underline;text-underline-offset:2px}
.pachat-err a:focus-visible{outline:3px solid #FF8C6B;outline-offset:2px}

/* ══ UN DEPLIANT DOIT SE VOIR ══
   « Le detail » ne ressemblait a rien de cliquable : pas de fleche, pas
   de cadre, la meme couleur que le texte autour. Personne ne devine
   qu on peut appuyer dessus. On lui met un signe + qui devient - une
   fois ouvert, un cadre, et le doigt du curseur. */
.pachat details{border:1px solid rgba(var(--laine),.16);border-radius:12px;
  padding:0 16px;margin:0 0 14px;transition:border-color .2s ease}
.pachat details:hover{border-color:rgba(var(--laine),.34)}
.pachat summary{list-style:none;justify-content:space-between;gap:14px;
  padding:14px 0;font-weight:600}
.pachat summary::-webkit-details-marker{display:none}
.pachat summary::after{content:"+";font-size:1.35rem;line-height:1;
  color:var(--or,#E8B341);transition:transform .25s ease}
.pachat details[open] summary::after{content:"-"}
.pachat details[open]{border-color:rgba(232,179,65,.4)}
.pachat details ul{padding-bottom:14px}

/* Meme chose pour « Donner mon avis » : c est un depliant, ca doit se voir. */
.pavis__form summary{list-style:none;gap:10px;font-weight:600}
.pavis__form summary::-webkit-details-marker{display:none}
.pavis__form summary::after{content:"+";font-size:1.3rem;line-height:1;
  color:var(--or,#E8B341)}
.pavis__form[open] summary::after{content:"-"}

/* ══ EN-TETE DE FICHE : menu a gauche, logo au centre, panier a droite ══ */
.tete{position:sticky;top:0;z-index:50;background:rgba(18,13,10,.96);
  backdrop-filter:blur(10px);border-bottom:1px solid rgba(var(--laine),.12)}
.tete__d{width:min(94vw,1280px);margin-inline:auto;display:grid;
  grid-template-columns:44px 1fr auto;align-items:center;gap:12px;min-height:60px}
.burger{width:44px;height:44px;display:grid;place-content:center;gap:5px;
  background:none;border:0;cursor:pointer;padding:0}
.burger span{display:block;width:20px;height:2px;background:currentColor;
  transition:transform .25s ease,opacity .25s ease}
.burger[aria-expanded="true"] span:nth-child(1){transform:translateY(7px) rotate(45deg)}
.burger[aria-expanded="true"] span:nth-child(2){opacity:0}
.burger[aria-expanded="true"] span:nth-child(3){transform:translateY(-7px) rotate(-45deg)}
.tete .logo{justify-self:center;margin:0;font-size:1.1rem}

.cherche{width:min(94vw,1280px);margin:0 auto;padding:0 0 12px;position:relative}
.cherche input{width:100%;font:inherit;font-size:.92rem;padding:11px 14px;
  border-radius:999px;background:rgba(var(--laine),.07);color:inherit;
  border:1px solid rgba(var(--laine),.16)}
.cherche input::placeholder{color:rgba(var(--laine),.4)}
/* ⚠ 18/08 — DEUX ÎLOTS NOIRS DONT L'ENCRE ÉTAIT EN VARIABLE.
   `.cherche__liste` et `.menu` peignent leur fond EN DUR (#171012) :
   ils ne changent jamais de peau, quelle que soit la surcouche. Leur
   TEXTE, lui, était `color:inherit` — donc `body{color:var(--encre)}`,
   donc #141210 dès que ROTATIVE (presse.css) retourne la table.
   MESURÉ AU CALCUL : #141210 sur #171012 = 1,00:1. Pas « peu
   lisible » : rigoureusement invisible.
   Ce que ça coûtait, page par page : les résultats de la recherche des
   409 pages de la boutique (on tapait « qamis », la liste s'ouvrait
   vide à l'œil, seules les vignettes se voyaient), et TOUT le contenu
   du panneau hamburger — « Accueil de la boutique », les noms
   d'articles et leurs prix. Seuls les intertitres survivaient : ils
   portent var(--or), que ROTATIVE change en vermillon (4,5:1).
   Les encres sont donc écrites en clair ici. Après : 14,9:1 pour les
   noms, 10,3:1 pour les prix. */
.cherche__liste{position:absolute;inset-inline:0;top:100%;z-index:60;max-height:56vh;
  overflow:auto;background:#171012;border:1px solid rgba(242,236,224,.18);
  border-radius:14px;padding:6px;color:#F2ECE0}
.cherche__liste a{display:flex;gap:10px;align-items:center;padding:8px;
  border-radius:10px;text-decoration:none;color:#F2ECE0;min-height:44px}
.cherche__liste a:hover{background:rgba(242,236,224,.10)}
.cherche__liste img{width:38px;height:48px;object-fit:contain;background:#221a1c;border-radius:6px}
.cherche__liste b{font-weight:500;font-size:.88rem;color:#F2ECE0}
.cherche__liste i{font-style:normal;font-size:.82rem;margin-inline-start:auto;
  color:rgba(242,236,224,.70)}

.menu{position:fixed;top:0;inset-inline-start:0;z-index:80;height:100dvh;
  width:min(88vw,340px);background:#171012;overflow-y:auto;color:#F2ECE0;
  border-inline-end:1px solid rgba(242,236,224,.16)}
.menu__d{padding:22px}
.menu__tout{display:flex;align-items:center;min-height:44px;font-weight:600;
  text-decoration:none;color:#F2ECE0;margin-bottom:12px}
.menu h3{font-size:.72rem;letter-spacing:.15em;text-transform:uppercase;
  margin:18px 0 6px}
.menu a.art{display:flex;align-items:center;min-height:44px;text-decoration:none;
  color:#F2ECE0;font-size:.88rem}
.menu a.art:hover{color:#fff}
.menu__voile{position:fixed;inset:0;z-index:70;background:rgba(10,7,6,.6)}

/* ══ LES IMAGES NE SONT PLUS ROGNEES ══
   « cover » remplit le cadre en coupant les bords : sur une boite de jeu,
   la moitie du titre disparaissait. « contain » montre tout. */
#pvGrande{object-fit:contain;background:#171012}
.vitrine__minis img{object-fit:contain;background:#171012}
.pcarte img{object-fit:contain;background:#171012}

/* ══ CE QUI CASSAIT LA PAGE ══
   Sans height:auto, l attribut height="1125" du HTML l emporte sur le
   rapport 4/5 : la photo s affichait a 327x1125 et poussait tout le
   reste. C est ce qui donnait cette page interminable. */
.vitrine img,.pcarte img,.cherche__liste img,.pavis img{height:auto}
#pvGrande{width:100%;height:auto;aspect-ratio:4/5;object-fit:contain;
  background:#171012;border-radius:18px;cursor:zoom-in}

/* L en-tete tenait sur 148 px de haut avec la recherche en dessous.
   On la rentre dans la meme ligne des qu il y a la place, et on la
   garde compacte sur telephone. */
.tete__d{min-height:56px}
.cherche{padding:0 0 10px}
.cherche input{padding:9px 14px;font-size:.88rem}

/* ══ L EN-TETE, PROPREMENT ══
   .lecteur (le libelle reserve aux lecteurs d ecran) manquait ici : le
   mot « Chercher un article » s affichait donc en clair au milieu de la
   barre. Et la recherche, posee en absolu, chevauchait « Panier ».
   Deux lignes simples : reperes en haut, recherche en dessous. */
.lecteur{position:absolute!important;width:1px;height:1px;overflow:hidden;
  clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}
.tete__d{grid-template-columns:44px 1fr 44px;align-items:center;gap:10px;min-height:58px}
.tete .logo{justify-self:center;font-size:1.06rem;letter-spacing:.06em;white-space:nowrap}
#pOuvrir{justify-self:end;padding:0;width:auto;min-width:44px;min-height:44px;
  display:inline-flex;align-items:center;gap:7px;background:none;border:0;
  font-size:.7rem;letter-spacing:.1em;text-transform:uppercase;white-space:nowrap}
#pCompte{min-width:20px;height:20px;padding:0 6px;border-radius:999px;
  background:var(--or,#E8B341);color:#120d0a;font-weight:700;font-size:.72rem;
  display:grid;place-items:center}
.cherche{width:min(94vw,1280px);margin:0 auto;padding:0 0 10px;position:relative}
.cherche input{width:100%}
@media(min-width:760px){
  .tete__d{grid-template-columns:44px 1fr minmax(220px,380px) auto;gap:18px}
  .tete .logo{justify-self:start}
  .cherche{position:static;width:auto;padding:0}
}

/* ══ LA RECHERCHE ══
   Elle est SŒUR de .tete__d, pas dedans : les colonnes de la grille ne
   l ont jamais concernee, et elle prenait toute la largeur. On la borne
   et on la centre — un champ de 1900 px pour chercher « huile » n a
   aucun sens. */
.cherche{width:min(94vw,520px);margin:0 auto;padding:0 0 12px;position:relative}
@media(min-width:760px){
  .cherche{width:min(46vw,440px);margin:-46px auto 10px}
}
@media(max-width:759px){
  .cherche{width:min(94vw,100%);margin-inline:auto}
}

/* ══ LA COLONNE DU MENU ══
   Elle etait une liste de texte : rien a reconnaitre, rien a comparer.
   Vignette a gauche, nom, prix a droite — on retrouve un article d un
   coup d oeil. Les titres de rayon sont ancres en haut au defilement. */
.menu{width:min(88vw,380px);background:#171012}
.menu__d{padding:0 0 24px}
.menu__tout{margin:0;padding:20px 20px 16px;font-size:1rem;
  border-bottom:1px solid rgba(242,236,224,.12)}
/* L'intertitre garde l'accent de la maison — c'est le seul endroit du
   panneau où la couleur du journal a le droit d'entrer. Le repli
   #E8B341 sert si aucune surcouche n'est chargée. */
.menu h3{position:sticky;top:0;z-index:2;margin:0;padding:14px 20px 8px;
  background:#171012;font-size:.68rem;letter-spacing:.16em;
  text-transform:uppercase;color:var(--or,#E8B341);opacity:1}
.menu a.art{display:grid;grid-template-columns:44px 1fr auto;align-items:center;
  gap:12px;padding:8px 20px;min-height:60px;font-size:.86rem;line-height:1.25;
  color:#F2ECE0;border-bottom:1px solid rgba(242,236,224,.07)}
.menu a.art:hover{background:rgba(242,236,224,.07)}
.menu a.art img{width:44px;height:54px;object-fit:contain;background:#221a1c;
  border-radius:7px}
.menu a.art span{min-width:0}
.menu a.art i{font-style:normal;font-size:.82rem;
  color:rgba(242,236,224,.66);
  font-variant-numeric:tabular-nums;white-space:nowrap}

/* Le curseur dit qu on peut tirer. Sans ce signe, personne n essaie. */
.avis-mur__grille,.pvoisins__grille,.onglets{user-select:none}
/* Le curseur ne vient PAS d ici : c est .tirable qui le pose, et le
   script ne l ajoute que si la bande deborde vraiment. Une main
   ouverte sur une bande figee promet un geste qui n existe pas. */
.avis-mur__grille a,.pvoisins__grille a{-webkit-user-drag:none}

/* ══ L ASCENSEUR ══
   Celui du systeme est blanc et large : sur un panneau sombre il coupe
   la colonne en deux. On le rend fin et discret, de la couleur du site.
   Firefox comprend scrollbar-*, les autres passent par ::-webkit-.

   ⚠ 18/08 — CETTE RÈGLE RALLUMAIT CE QU'ON VENAIT D'ÉTEINDRE.
   `.avis-mur__grille` et `.pvoisins__grille` déclarent chacune
   `scrollbar-width:none` dans son propre bloc, plus haut dans ce
   fichier ; cette règle-ci, écrite PLUS BAS et à spécificité égale,
   remettait `thin`. Résultat mesuré à la lecture des deux
   cascades : sous Firefox, l'ascenseur natif REVENAIT sur le mur
   d'avis et sur la bande « Prenez aussi » ; sous Chrome le
   `::-webkit-scrollbar{display:none}` d'en dessous le rattrapait, si
   bien que le défaut ne se voyait que sur un moteur sur deux. Les
   trois bandes horizontales sortent donc de la liste : elles se
   tirent, elles n'ont pas d'ascenseur du tout.

   ET LA COULEUR DU CURSEUR EST ÉCRITE EN CLAIR POUR LES DEUX ÎLOTS
   NOIRS. `rgba(var(--laine),.22)` devient rgba(20,18,16,.22) sous
   ROTATIVE : un curseur d'encre sur le #171012 du panneau, soit
   1,0:1 — une gouttière de 6 px parfaitement vide. .menu et
   .cherche__liste prennent donc du papier ; #pLignes et #panier
   gardent la variable, eux, parce que leur fond suit --nuit2 et passe
   au papier avec la surcouche : là, c'est bien l'encre qui doit se
   voir. */
.menu,.cherche__liste{scrollbar-width:thin;
  scrollbar-color:rgba(242,236,224,.30) transparent}
#pCorps,#pLignes,#panier{scrollbar-width:thin;
  scrollbar-color:rgba(var(--laine),.22) transparent}
.menu::-webkit-scrollbar,#pLignes::-webkit-scrollbar,
.cherche__liste::-webkit-scrollbar,#panier::-webkit-scrollbar{width:6px;height:6px}
.menu::-webkit-scrollbar-track,#pLignes::-webkit-scrollbar-track,
.cherche__liste::-webkit-scrollbar-track,#panier::-webkit-scrollbar-track{background:transparent}
.menu::-webkit-scrollbar-thumb,.cherche__liste::-webkit-scrollbar-thumb{
  background:rgba(242,236,224,.30);border-radius:99px}
.menu::-webkit-scrollbar-thumb:hover,.cherche__liste::-webkit-scrollbar-thumb:hover{
  background:rgba(242,236,224,.46)}
#pLignes::-webkit-scrollbar-thumb,#panier::-webkit-scrollbar-thumb{
  background:rgba(var(--laine),.2);border-radius:99px}
#pLignes::-webkit-scrollbar-thumb:hover,#panier::-webkit-scrollbar-thumb:hover{
  background:rgba(var(--laine),.34)}
/* Les carrousels horizontaux n en ont pas besoin : on les tire. */
.avis-mur__grille::-webkit-scrollbar,.pvoisins__grille::-webkit-scrollbar,
.onglets::-webkit-scrollbar{display:none}

/* Le nom et la vignette du panier mènent à la fiche ; la version se
   change sur place, sans avoir à retirer l'article. */
.p-vue{display:block}
.p-ligne h4 a{color:inherit;text-decoration:none}
.p-ligne h4 a:hover{text-decoration:underline}
.p-var{font:inherit;font-size:.8rem;margin:4px 0;padding:5px 8px;max-width:100%;
  background:rgba(var(--laine),.07);color:inherit;border-radius:8px;
  border:1px solid rgba(var(--laine),.2)}
.p-var option{background:#171012;color:#f2ede4}


/* ══ LES BANDES QUI SE TIRENT ══
   `.tirable` n'est pose par le script QUE si la bande deborde vraiment.
   Sans cette condition, une bande de trois articles sur grand ecran
   affichait la main ouverte alors qu'il n'y avait rien a tirer — le
   curseur promettait un geste impossible. */
.tirable{cursor:grab}
.tirable.tire{cursor:grabbing;scroll-snap-type:none;scroll-behavior:auto}
.tirable.tire *{pointer-events:none}

/* ══ 18/08 — « LA BARRE MOCHE POUR DÉFILER » ══
   L'ascenseur natif d'une bande horizontale est une barre grise épaisse
   posée en travers des vignettes. On l'éteint — mais SEULEMENT ici, et
   ce choix d'emplacement est tout le raisonnement :

   `.tirable` n'est pas une classe qu'on écrit dans le HTML. socle.js ne
   la pose QUE si trois choses sont vraies en même temps : le script a
   tourné, la bande fait partie des rails qu'il gère, et elle déborde
   vraiment (`z.scrollWidth - z.clientWidth > 2`). Autrement dit,
   l'ascenseur ne disparaît qu'au moment précis où le glissement au
   doigt, le glisser-souris, le curseur en main ouverte et — quand le
   parent est un vrai cadre — les deux flèches viennent le remplacer.
   Script mort, bande qui ne déborde pas, navigateur sans pointer
   events : la classe n'arrive jamais et la barre du système reste.
   On n'enlève donc jamais un moyen de défiler sans en avoir posé un
   autre : c'est la même main qui fait les deux.

   DOUBLE CLASSE, ET CE N'EST PAS UNE COQUETTERIE. `.v-col__rail`
   (vitrines.css) déclare `scrollbar-width:thin` chez elle, et
   vitrines.css est chargée APRÈS socle.css : à spécificité égale
   (0,1,0) c'est elle qui l'emportait, et le rail des collections
   gardait sa barre. `.tirable.tirable` vaut 0,2,0 et tranche sans
   avoir à écrire dans un fichier qui n'est pas le mien. */
.tirable.tirable{scrollbar-width:none}
.tirable::-webkit-scrollbar{width:0;height:0;display:none}

/* Le cadre qui porte les fleches. `position:relative` seulement : la
   bande garde sa largeur, les fleches flottent par-dessus. */
.bande-cadre{position:relative}
.bande-fleche{position:absolute;top:calc(50% - 22px);z-index:5;
  width:44px;height:44px;border-radius:999px;border:1px solid var(--b20);
  background:rgba(18,13,10,.86);backdrop-filter:blur(10px);color:var(--blanc);
  display:grid;place-items:center;cursor:pointer;padding:0;
  opacity:0;visibility:hidden;
  transition:opacity var(--t-survol,220ms),transform var(--t-survol,220ms),
             background var(--t-survol,220ms),visibility var(--t-survol,220ms)}
.bande-fleche.la{opacity:1;visibility:visible}
.bande-fleche--g{left:-6px}
.bande-fleche--d{right:-6px}
.bande-fleche svg{width:19px;height:19px;fill:none;stroke:currentColor;
  stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round}
@media(hover:hover) and (pointer:fine){
  .bande-fleche:hover{background:var(--or,#F0A830);color:#120D0A;transform:scale(1.08)}
}
/* Le doigt n'a pas besoin de fleches, et elles mangeraient la bande. */
@media(max-width:860px){ .bande-fleche{display:none} }
:root[data-calme="1"] .tirable{scroll-behavior:auto}


/* ══ L AVEU SOUS LA GALERIE ══
   Seize coloris n ont pas de photo chez le fournisseur. On garde la
   photo generale et on l ecrit ici. Discret mais lisible : ce n est pas
   une alerte, c est une precision — et c est ce qui evite au client de
   croire qu il commande un objet noir alors qu il a choisi beige. */
.vitrine__note{display:flex;gap:9px;align-items:flex-start;margin-top:12px;
  padding:11px 13px;border-radius:12px;background:var(--b5,rgba(var(--laine),.05));
  border:1px solid var(--b10,rgba(var(--laine),.1));
  font:400 .82rem/1.45 var(--f-corps,system-ui);color:var(--encre2,rgba(var(--laine),.7))}
.vitrine__note svg{flex:none;width:16px;height:16px;margin-top:1px;
  fill:none;stroke:var(--or,#F0A830);stroke-width:1.9;stroke-linecap:round}
.vitrine__note b{color:var(--encre,#fff);font-weight:600}


/* ══════════ 18/08 — LE SOMMAIRE EN DEUX TEMPS ══════════
   « je clique sur une catégorie c'est pas clair, il faut que TOUS les
   produits de la catégorie s'affichent, mais aussi un bouton en haut
   où c'est RETOUR AUTRE CATÉGORIE qui remet les autres catégories. »

   CE QU'IL VOYAIT : le panneau hamburger déversait les NEUF rayons et
   leurs articles à la suite, dans une seule colonne. Compté dans le
   catalogue : 399 lignes d'affilée, dont 160 pour les seuls livres.
   Choisir « les vêtements » demandait de descendre à travers huit
   autres rayons ; rien ne se refermait, rien ne ramenait en haut.

   CE QUE ÇA DEVIENT : premier temps, les neuf catégories seules, avec
   leur compte — neuf lignes, un écran. Second temps, UNE catégorie,
   TOUS ses articles, et en tête le bouton de retour. Le regroupement
   est fait par socle.js à partir de ce que le script de la page a déjà
   écrit : rien n'est recopié, aucun compte n'est inventé — ils sont
   comptés sur les lignes réellement présentes.

   Les encres sont écrites en clair, comme partout dans cet îlot : le
   panneau est un aplat #171012 qui ne change jamais de peau. */
/* ⚠ 20/08 — `.menu__cat-b` N EST PLUS UN <button>, C EST UN <a>.
   Le proprietaire : « dans le bouton hamburger faut que quand on
   clique sur un truc sa aille sur tout la categorie ». Un <button>
   ne mene nulle part ; le lien, si — vers la page du rayon entier.
   Le dessin ne change pas d un pixel : les memes declarations valent
   pour les deux balises, `text-decoration:none` en plus (un lien est
   souligne par defaut, un bouton non). */
.menu__cats{display:block}
.menu__cat-b{
  display:grid;grid-template-columns:1fr auto;align-items:center;gap:12px;
  width:100%;min-height:60px;padding:12px 20px;text-align:left;
  background:none;border:0;cursor:pointer;text-decoration:none;
  border-bottom:1px solid rgba(242,236,224,.07);
  color:#F2ECE0;
  transition:background-color var(--t-survol,220ms) var(--e-doux,ease);
}
/* Le rayon ou l on se trouve deja : il reste cliquable (recharger sa
   page n a rien d absurde) mais il se distingue, sinon la colonne ment
   sur l endroit ou l on est. */
.menu__cat-b[aria-current]{background:rgba(242,236,224,.06)}
/* ⚠ PAS DE TEXTE AJOUTE ICI. Une version posait un
   `content:" — vous y êtes"` en chasse fixe apres le nom du rayon.
   Personne ne l avait demande, et ca faisait surgir une autre
   police dans le menu. Le fond ci-dessus suffit : il MONTRE ou on
   est au lieu de l ecrire. */
.menu__cat-b b{
  font-family:var(--f-titre);font-weight:600;font-size:1.02rem;line-height:1.2;
  letter-spacing:.004em;color:#F2ECE0;
}
.menu__cat-b i{
  font-style:normal;font-family:var(--f-mono);font-size:.7rem;letter-spacing:.08em;
  color:rgba(242,236,224,.62);white-space:nowrap;
}
/* La chevronnette dit qu'il y a un dessous. Sans elle, une ligne de
   liste ne se distingue pas d'un titre. */
.menu__cat-b b::after{content:" →";color:var(--or,#E8B341)}
@media (hover:hover) and (pointer:fine){
  .menu__cat-b:hover{background:rgba(242,236,224,.07)}
}
.menu__cat-b:focus-visible{outline:3px solid var(--or,#E8B341);outline-offset:-3px}

/* Le retour est COLLÉ EN HAUT du panneau : après quarante articles,
   il doit être là sans qu'on remonte le chercher. Il se pose au même
   endroit que l'intertitre collant, donc un cran au-dessus de lui. */
.menu__retour{
  position:sticky;top:0;z-index:3;
  display:flex;align-items:center;gap:9px;
  width:100%;min-height:52px;padding:14px 20px;text-align:left;
  background:#171012;border:0;cursor:pointer;
  border-bottom:1px solid rgba(242,236,224,.14);
  font-family:var(--f-mono);font-size:.7rem;font-weight:700;
  letter-spacing:.12em;text-transform:uppercase;color:#F2ECE0;
}
.menu__retour::before{content:"←";font-size:.95rem;line-height:1;color:var(--or,#E8B341)}
@media (hover:hover) and (pointer:fine){
  .menu__retour:hover{background:rgba(242,236,224,.09)}
}
.menu__retour:focus-visible{outline:3px solid var(--or,#E8B341);outline-offset:-3px}
/* L'intertitre du rayon reste collant, mais SOUS le bouton de retour :
   52 px, la hauteur exacte de celui-ci. */
.menu__cat h3{top:52px}


/* ══════════ LE MÊME DEUX-TEMPS, DANS LE SOMMAIRE DE L'ACCUEIL ══════════
   Le panneau plein écran du journal (.p-sommaire, posé par presse.js)
   ne portait que les neuf noms de rayon : chacun était un lien qui
   FAISAIT CHANGER DE PAGE. On garde ce lien — il mène à la page
   complète du rayon, et c'est utile — et on ajoute, sous lui, la
   possibilité de voir la liste sur place. Rien n'est retiré. */
.p-som__ouvre{
  display:flex;align-items:center;gap:8px;
  min-height:44px;padding:0 0 12px;margin:-6px 0 0;
  background:none;border:0;cursor:pointer;text-align:left;
  font-family:var(--f-mono);font-size:.7rem;font-weight:700;
  letter-spacing:.12em;text-transform:uppercase;
  color:rgba(242,236,224,.72);
}
.p-som__ouvre::after{content:"↓";color:var(--vermillon,#E8380D)}
@media (hover:hover) and (pointer:fine){
  .p-som__ouvre:hover{color:#F2ECE0}
}
.p-som__ouvre:focus-visible{outline:2px solid #F2ECE0;outline-offset:3px}
.p-som__pan{display:grid;gap:2px}
.p-som__retour{
  justify-self:start;margin-bottom:clamp(10px,3vh,26px);
  border:2px solid #F2ECE0;background:transparent;color:#F2ECE0;
  padding:.6rem 1.3rem;cursor:pointer;
  display:inline-flex;align-items:center;gap:9px;min-height:44px;
  font-family:var(--f-mono);font-weight:700;font-size:.72rem;
  letter-spacing:.14em;text-transform:uppercase;
}
.p-som__retour::before{content:"←"}
@media (hover:hover) and (pointer:fine){
  .p-som__retour:hover{background:#F2ECE0;color:#141210}
}
.p-som__tt{
  margin:0 0 10px;font-family:var(--f-mono);font-size:.7rem;font-weight:700;
  letter-spacing:.14em;text-transform:uppercase;color:rgba(242,236,224,.6);
}
.p-som__tt a{color:var(--vermillon,#E8380D)}
.p-som__a{
  display:grid;grid-template-columns:44px 1fr auto;align-items:center;gap:14px;
  padding:9px 0;min-height:60px;text-decoration:none;color:#F2ECE0;
  border-top:1px solid rgba(242,236,224,.16);
}
.p-som__a img{width:44px;height:54px;object-fit:contain;background:#221a1c}
.p-som__a span{min-width:0;font-size:.92rem;line-height:1.3}
.p-som__a i{
  font-style:normal;font-family:var(--f-mono);font-size:.74rem;
  color:rgba(242,236,224,.66);font-variant-numeric:tabular-nums;white-space:nowrap;
}
@media (hover:hover) and (pointer:fine){
  .p-som__a:hover{background:rgba(242,236,224,.06)}
}

/* ══════════════════════════════════════════════════════════════════
   18/08 SOIR — LA PHOTO PRODUIT ET LES AVIS SE REGARDENT ENFIN
   Demande du proprietaire, en sept points : loupe au survol, cadre au
   clic avec croix rouge, pincement qui agrandit la PHOTO et pas la
   page, aucun zoom de page ailleurs, avis qui se balaient au doigt et
   s'ouvrent dans un cadre.

   ⓐ PLUS AUCUN ZOOM DE PAGE AU DOIGT, ET CE N'EST PAS QUE LA BALISE.
   Le <meta viewport> (`user-scalable=no,maximum-scale=1`) est ignore
   par Safari depuis iOS 10 : seul `touch-action` y est ecoute. Pose
   sur la RACINE, il vaut pour toute la boutique — 438 pages — sans
   qu'on ait a le repeter page par page.
   `pan-x pan-y`, et surtout PAS `manipulation` : `manipulation` laisse
   passer le pincement du navigateur, c'est justement ce qu'on retire.
   Ce qui reste permis : faire defiler, dans les deux sens. Ce qui
   part : le pincement de page ET le zoom au double-tapotement (toute
   valeur autre que `auto` ou `manipulation` le supprime).
   ⚠ `touch-action` ne s'herite pas — il s'INTERSECTE avec celui des
   ancetres, et cette regle-ci est donc le PLAFOND de toute la boutique.
   ⚠ 19/08 — CE QUE L'INTERSECTION DONNE MAINTENANT, ET C'EST VOULU.
   socle.js pose desormais `manipulation` en ligne sur les bandes qui se
   tirent (`pan-x pan-y pinch-zoom`). Croise avec la ligne ci-dessous,
   il reste `pan-x pan-y` : les DEUX axes rendus au navigateur — donc
   l'elan et le rebond du systeme au doigt, sur le compositeur — et le
   pincement toujours supprime par cette ligne, qui reste la consigne.
   L'ancienne valeur, `pan-y pinch-zoom`, s'intersectait en `pan-y` :
   l'horizontale etait interdite au navigateur et recalculee en
   JavaScript sur le fil principal. C'est ce qui rendait le defilement
   saccade au doigt. Le glissement du script reste, pour la souris. */
html{touch-action:pan-x pan-y}

/* ══ ⓑ LA PHOTO PRODUIT : SON CADRE ══
   produit.js glisse #pvGrande dans ce cadre au chargement. Le cadre
   est la boite qui COUPE : c'est lui qui garantit qu'une photo
   agrandie — a la souris comme au pincement — ne pousse jamais la
   page d'un pixel. Mesure exigee par la maison : scrollWidth doit
   valoir clientWidth en 375 comme en 1280.

   `display:grid` et non un bloc : la photo redevient un element de
   grille, donc le `justify-self:center` que fiche.css lui pose sur
   telephone continue de la centrer, et il n'y a pas d'espace de ligne
   de base sous une image en ligne. */
.pv-cadre{
  position:relative;display:grid;justify-items:center;min-width:0;
  overflow:hidden;border-radius:18px;
  /* La page defile toujours verticalement quand le doigt part de la
     photo ; le pincement, lui, n'appartient plus au navigateur mais a
     produit.js — et le double-tapotement ne zoome plus (point 5). */
  touch-action:pan-y;
}
.pv-cadre>#pvGrande{
  grid-area:1/1;cursor:zoom-in;touch-action:pan-y;
  transform-origin:50% 50%;
  transition:transform 200ms var(--e-sortie);
}
/* Pendant le pincement, produit.js ecrit `transition:none` en ligne :
   une transition ferait courir la photo derriere les doigts. Elle
   revient au relachement — c'est elle qui rend le retour a la taille
   normale doux au lieu de sec. */
:root[data-calme="1"] .pv-cadre>#pvGrande{transition:none}

/* LA LOUPE — SOURIS SEULEMENT. `hover:hover` et `pointer:fine` : un
   doigt ne survole rien, il touche, et une loupe collee au doigt
   cacherait ce qu'elle grossit. */
@media (hover:hover) and (pointer:fine){
  .pv-cadre::after{
    content:"Cliquez pour ouvrir en grand";
    position:absolute;left:0;right:0;bottom:0;z-index:2;
    padding:10px 12px;text-align:center;pointer-events:none;
    font-family:var(--f-mono);font-size:.66rem;letter-spacing:.12em;
    text-transform:uppercase;color:#F2ECE0;
    background:linear-gradient(to top,rgba(10,7,6,.78),transparent);
    opacity:0;transition:opacity var(--t-survol) var(--e-doux);
  }
  .pv-cadre:hover::after{opacity:1}
  :root[data-calme="1"] .pv-cadre::after{transition:none}
}

/* ══ ⓒ LE CADRE PAR-DESSUS LA PAGE ══
   Il existait deja (#zoom, dans les 426 fiches) mais ce n'etait qu'une
   photo posee sur du noir : rien ne disait qu'on pouvait en sortir, et
   rien ne permettait de fermer sans viser le vide.
   Ce qu'on ajoute, et rien de plus : un fond assombri et FLOUTE — on
   voit que la page continue derriere, donc qu'on peut y retourner —,
   une croix rouge sur le bord du cadre, et la phrase qui dit le geste.
   Le pincement, ici aussi, appartient a produit.js. */
/* `flex-direction:column` : le cadre et la phrase de sortie s'empilent
   au centre. Posee en absolu contre le bas de l'ecran, la phrase
   tombait PILE sur la barre d'achat collante (mesure du 18/08 en
   375x812) — deux textes l'un sur l'autre. Empilee, elle appartient
   visiblement au cadre et ne recouvre plus rien. */
#zoom{
  position:fixed;inset:0;z-index:120;display:none;
  flex-direction:column;align-items:center;justify-content:center;gap:14px;
  padding:clamp(14px,4vw,40px);
  background:rgba(8,5,4,.82);
  -webkit-backdrop-filter:blur(7px);backdrop-filter:blur(7px);
  cursor:zoom-out;overflow:hidden;touch-action:none;
}
#zoom.on{display:flex}
.zoom__cadre{
  position:relative;cursor:default;overflow:hidden;
  max-width:min(94vw,760px);max-height:76svh;
  border-radius:20px;background:#171012;
  box-shadow:0 44px 90px -34px #000,0 0 0 1px rgba(242,236,224,.18);
  touch-action:none;
}
#zoom img{
  display:block;width:auto;height:auto;
  max-width:min(94vw,760px);max-height:76svh;object-fit:contain;
  border-radius:20px;touch-action:none;
  transform-origin:50% 50%;transition:transform 200ms var(--e-sortie);
}
:root[data-calme="1"] #zoom img{transition:none}
/* LA CROIX EST ROUGE, ET C'EST DEMANDE. 46 px : plus qu'un doigt.
   ⚠ ELLE EST DEDANS, PAS A CHEVAL SUR LE BORD. Premiere version posee
   a `top:-14px;right:-14px` : le cadre porte `overflow:hidden` (c'est
   lui qui coupe la photo agrandie), il coupait donc aussi la croix —
   mesure faite en 375 px, la moitie droite manquait. Une croix qu'on
   ne voit qu'a moitie n'est plus une porte de sortie. */
.zoom__x{
  position:absolute;top:10px;right:10px;z-index:3;
  width:46px;height:46px;border-radius:999px;border:0;
  background:#D7261E;color:#fff;cursor:pointer;
  display:grid;place-items:center;font-size:1.25rem;line-height:1;
  box-shadow:0 10px 24px -8px rgba(0,0,0,.9),0 0 0 3px rgba(8,5,4,.5);
  transition:transform var(--t-micro) var(--e-sortie),background var(--t-micro);
}
@media (hover:hover) and (pointer:fine){
  .zoom__x:hover{background:#F03127;transform:scale(1.08)}
}
.zoom__x:focus-visible{outline:2px solid #fff;outline-offset:3px}
:root[data-calme="1"] .zoom__x{transition:none}
/* La phrase qui dit le geste vit SUR le fond assombri, sous le cadre :
   c'est elle qui rend le « cliquez en dehors » visible au lieu de le
   laisser deviner. `pointer-events:none` — un clic dessus est un clic
   en dehors, et il doit fermer comme les autres. */
/* ⚠ LA COULEUR EST ECRITE EN DUR, ET C'EST OBLIGATOIRE ICI. `--laine`
   est la matiere claire du socle — mais la peau journal (presse.css)
   la RETOURNE vers l'encre : mesuree sur une fiche, elle vaut
   20,18,16. Cette phrase se serait donc peinte en noir sur le voile
   noir du cadre, invisible, sur les 438 pages qui chargent presse.css.
   Le voile, lui, ne se retourne jamais : il est ecrit en dur au-dessus.
   Une couleur posee sur une surface FIXE se declare en dur ; une
   variable ne se justifie que sur une surface qui change avec elle. */
.zoom__sortie{
  flex:none;margin:0;text-align:center;pointer-events:none;
  font-family:var(--f-mono);font-size:.7rem;letter-spacing:.12em;
  text-transform:uppercase;color:rgba(242,236,224,.78);
}
@media (max-width:520px){
  .zoom__x{width:44px;height:44px}
  .zoom__sortie{font-size:.62rem;letter-spacing:.08em}
}

/* ══ ⓓ UN AVIS S'OUVRE DANS UN CADRE ══
   Le meme cadre pour les deux murs — celui de l'accueil (avis-mur.js)
   et celui d'une fiche (produit.js) — parce que c'est le meme geste.
   Les deux scripts construisent la meme boite ; le style, lui, ne vit
   qu'une fois, ici, dans la seule feuille que les 438 pages chargent. */
.avisb{
  position:fixed;inset:0;z-index:140;display:none;
  flex-direction:column;align-items:center;justify-content:center;gap:14px;
  padding:clamp(14px,4vw,40px);
  background:rgba(8,5,4,.82);
  -webkit-backdrop-filter:blur(7px);backdrop-filter:blur(7px);
  cursor:zoom-out;
}
.avisb.on{display:flex}
/* ⚠ CE N'EST PAS LE CADRE QUI DEFILE, C'EST LE TEXTE. Le cadre porte
   la croix en absolu : s'il defilait, elle partirait vers le haut des
   la premiere ligne lue. Le nom, la date et les etoiles restent donc
   fixes, et seul l'avis lui-meme se deroule sous eux.
   `min-height:0` sur l'enfant qui defile : sans lui, un enfant de flex
   refuse de descendre sous la hauteur de son contenu et la boite
   grandit au lieu de defiler — le meme piege que `min-width:0` a
   l'horizontale, qui a coute deux fois aujourd'hui. */
.avisb__cadre{
  position:relative;cursor:default;
  display:flex;flex-direction:column;
  width:min(560px,94vw);max-height:76svh;overflow:hidden;
  padding:clamp(20px,4vw,30px);
  border-radius:20px;
  /* ⚠ LE CREME EST ECRIT EN DUR, PAS `var(--creme)`. Mesure du 18/08
     sur une fiche : la peau journal (presse.css) pose --creme a
     #141210 — le degrade prenait donc une bande NOIRE en diagonale au
     milieu du papier, sur le texte de l'avis. Le cadre flotte sur un
     voile sombre a lui : sa matiere ne suit aucune peau. */
  background:linear-gradient(163deg,#FFFDF8 0%,#FCF6EC 44%,#F5EDDE 100%);
  color:#241A12;
  box-shadow:0 44px 90px -34px #000,0 0 0 1px rgba(36,26,18,.10);
}
.avisb__n{
  flex:none;margin:0;font-family:var(--f-titre,ui-serif,serif);
  font-size:1.25rem;line-height:1.2;font-weight:600;color:#1E1610;
  overflow-wrap:break-word;padding-right:44px;
}
.avisb__dt{
  display:block;margin-top:6px;
  font-family:var(--f-mono,ui-monospace,monospace);
  font-size:.66rem;letter-spacing:.09em;text-transform:uppercase;
  color:rgba(36,26,18,.72);
}
.avisb__et{flex:none;margin-top:12px;color:#B8791A;font-size:1.05rem;letter-spacing:3px}
.avisb__t{
  flex:1 1 auto;min-height:0;overflow:auto;overscroll-behavior:contain;
  margin:16px 0 0;font-size:1rem;line-height:1.68;color:rgba(36,26,18,.9);
  white-space:pre-line;overflow-wrap:break-word;
}

/* ══ ⓔ LES AVIS D'UNE FICHE SE BALAIENT AU DOIGT ══
   Sur l'accueil c'est deja une bande ; sur une fiche, les avis
   s'empilaient en hauteur. Sur telephone ils passent en rail : un
   geste de gauche a droite, comme demande.
   ⚠ `min-width:0` sur le rail : un conteneur qui defile a
   l'horizontale dans une grille ou un flex pousse la page hors de
   l'ecran sans lui. Ce piege a coute deux fois aujourd'hui. */
.pavis__liste{min-width:0}
@media (max-width:900px){
  .pavis__liste.pavis--rail{
    display:flex;gap:12px;align-items:stretch;flex-wrap:nowrap;
    overflow-x:auto;overflow-y:hidden;
    overscroll-behavior-x:contain;scrollbar-width:none;
    scroll-snap-type:x proximity;
    padding-bottom:6px;max-width:100%;min-width:0;
  }
  .pavis__liste.pavis--rail::-webkit-scrollbar{display:none}
  /* ⚠ AUCUN `flex-wrap:wrap` ICI : dans une boite a `overflow-x:auto`,
     l'enroulement remplace le defilement — les cartes passeraient a la
     ligne au lieu de se balayer. La moyenne, qui n'est pas un avis, est
     donc sortie du rail par produit.js et posee AVANT lui. */
  .pavis--rail .pavis__un{
    flex:0 0 min(280px,78vw);width:min(280px,78vw);
    scroll-snap-align:start;
    display:flex;flex-direction:column;
    padding:14px;border-bottom:0;border-radius:16px;
    background:var(--b5);box-shadow:inset 0 0 0 1px rgba(var(--laine),.10);
  }
  .pavis--rail .pavis__un p{
    display:-webkit-box;-webkit-box-orient:vertical;
    -webkit-line-clamp:5;line-clamp:5;overflow:hidden;
  }
}
/* Un avis se clique — au doigt comme a la souris — et il s'ouvre dans
   le cadre. Le curseur le dit ; la cible fait la carte entiere. */
.pavis__un{cursor:pointer}
.pavis__un:focus-visible{outline:2px solid var(--or,#F0A830);outline-offset:3px}
.pavis__glisse{
  margin:8px 0 0;font-family:var(--f-mono);font-size:.68rem;
  letter-spacing:.1em;text-transform:uppercase;color:rgba(var(--laine),.58);
}
