/* ==========================================================================
   LUUBO · SerenTag — Sections & composants de l'entonnoir
   ========================================================================== */

/* ======================= 1. HERO =======================================
   Plein cadre. Le texte tient dans une colonne bornée, calée à gauche ; le
   visuel produit sort du cadre à droite et touche le bord de l'écran. C'est
   ce débord qui donne l'échelle — pas une marge supplémentaire.

   Le héros ne contient QUE : un titre, une phrase, un bouton, le compte à
   rebours. Toute rangée de pastilles ou de réassurances ajoutée ici ramène
   l'encombrement « gabarit » : ces éléments vivent dans .why et .ratingbar.
   ====================================================================== */
.hero { position: relative; background: var(--ground); overflow: hidden; }
.hero__grid {
  display: grid; align-items: center;
  grid-template-columns: minmax(0, 42rem) minmax(0, 1fr);
  gap: clamp(1.5rem, 1rem + 2vw, 3rem);
  min-height: clamp(30rem, 74vh, 48rem);
  /* Pas de marge basse : les animaux touchent le bandeau d'avis. */
  padding-block: clamp(2.5rem, 1.5rem + 3vw, 4rem) 0;
  /* Marge gauche = gouttière, sauf sur très grand écran où le bloc de texte
     se recentre. Aucun padding à droite : la colonne visuelle file au bord. */
  padding-left: max(var(--gutter), calc((100vw - var(--max-wide)) / 2 + var(--gutter)));
}
.hero__copy { position: relative; z-index: 2; }
.hero h1 { margin-bottom: 1.1rem; max-width: 15ch; }
.hero h1 em { font-style: normal; color: var(--blue); }
.hero__lead { margin-bottom: 1.8rem; font-size: var(--t-lead); color: var(--ink-soft); max-width: 38ch; }
.hero__cta { display: flex; flex-wrap: wrap; gap: .8rem; align-items: center; }
.hero__cta .btn { white-space: nowrap; }
/* Le CTA principal garde son libellé et son prix sur une ligne ; s'il manque
   de place, c'est le bouton secondaire qui passe dessous. */
.hero__cta .btn--primary { flex: 0 1 auto; }
@media (max-width: 520px) { .hero__cta .btn { flex: 1 1 100%; } }
.hero .cutoff { margin-top: 1.2rem; }

/* Colonne visuelle : visuel DÉTOURÉ (alpha) ancré en bas à droite, plus
   large que sa colonne pour empiéter vers le centre comme sur la maquette.
   Le ::before fond le bord gauche du chien dans le blanc pour que le titre
   reste lisible ; le texte passe au-dessus (z-index). */
/* overflow: hidden est indispensable : l'image dépasse sa colonne à gauche ;
   sans rognage, la partie qui déborde échappe au fondu et laisse une arête
   verticale nette sur le flanc du chien. Rognée, l'arête tombe sous le
   début du fondu — blanc à cet endroit — et disparaît. */
.hero__stage { position: relative; align-self: stretch; min-height: clamp(22rem, 60vh, 40rem); overflow: hidden; }
.hero__stage::before {
  content: ""; position: absolute; inset: 0 auto 0 -1px; width: 42%; z-index: 1;
  background: linear-gradient(90deg, var(--ground) 0%, rgba(255, 255, 255, 0) 100%);
}
.hero__bg {
  position: absolute; bottom: 0; right: 0; z-index: 0;
  width: min(118%, 62rem); max-width: none; height: auto; max-height: 100%;
  object-fit: contain; object-position: right bottom; display: block;
}
/* Trois réassurances sous le bouton */
.hero__trust {
  list-style: none; margin: 1.6rem 0 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: .9rem 1.8rem;
}
.hero__trust li { display: flex; align-items: center; gap: .55rem; font-size: var(--t-xs); color: var(--ink-soft); line-height: 1.25; }
.hero__trust li b { color: var(--ink); font-weight: 700; }
.hero__trust .ico { width: 26px; height: 26px; color: var(--blue); }
.hero .btn .ico { margin-left: .2rem; }

@media (max-width: 940px) {
  .hero__grid {
    grid-template-columns: 1fr; min-height: 0; gap: 2rem;
    padding-left: var(--gutter); padding-right: var(--gutter);
  }
  /* Le visuel passe sous l'accroche et reprend toute la largeur de l'écran :
     sur mobile c'est le titre qui doit occuper le premier écran. */
  /* Mobile : le texte d'abord, les animaux dessous, pleine largeur,
     posés sur le bandeau d'avis. Plus de fondu : rien ne passe dessus. */
  .hero__stage { margin-inline: calc(var(--gutter) * -1); min-height: clamp(15rem, 68vw, 24rem); }
  .hero__stage::before { display: none; }
  .hero__bg { width: 100%; right: 0; }
  .hero h1 { max-width: none; }
}

/* ======================= 2. VISUEL PRODUIT (SerenTag) ================== */
/* Le produit n'est JAMAIS dessiné en CSS ou SVG : on affiche toujours le
   visuel officiel assets/img/serentag.png. Si le fichier manque, ui.js pose
   .is-missing et un repère neutre remplace l'icône d'image cassée. */
.product-shot {
  position: relative; flex: none;
  display: grid; place-items: center;
  width: 64px; aspect-ratio: 1;
  container-type: inline-size;
}
.product-shot img { width: 100%; height: 100%; object-fit: contain; display: block; }
.product-shot--xs    { width: 40px; }
.product-shot--sm    { width: 52px; }
.product-shot--thumb { width: 58px; }
.product-shot--md    { width: 84px; }
.product-shot--lg    { width: 62%; max-width: 220px; }
.product-shot.is-missing img { visibility: hidden; }
.product-shot.is-missing::after {
  content: "SerenTag";
  position: absolute; inset: 0;
  display: grid; place-items: center; text-align: center;
  border: 1.5px dashed var(--line-strong); border-radius: 22%;
  background: var(--surface-muted); color: var(--ink-faint);
  font-size: clamp(7px, 16cqw, 14px); font-weight: 700; letter-spacing: .02em;
}

/* Ondes NFC */
.waves { display: block; color: var(--blue-bright); }
.waves path { animation: wave 2.4s var(--ease) infinite; opacity: 0; }
.waves path:nth-child(1) { animation-delay: 0s; }
.waves path:nth-child(2) { animation-delay: .28s; }
.waves path:nth-child(3) { animation-delay: .56s; }
@keyframes wave {
  0%   { opacity: 0; transform: translateX(-3px); }
  35%  { opacity: 1; }
  100% { opacity: 0; transform: translateX(3px); }
}

/* ======================= 3. TÉLÉPHONE (maquette live) ================== */
.phone {
  position: relative; width: 100%;
  background: var(--night);
  border-radius: clamp(22px, 9%, 40px);
  padding: 8px;
  box-shadow: var(--sh-phone), inset 0 0 0 1.5px #3A3F47;
}
.phone__screen {
  position: relative; overflow: hidden;
  border-radius: clamp(16px, 7%, 32px);
  background: var(--ground);
  aspect-ratio: 9 / 19.2;
  display: flex; flex-direction: column;
  container-type: inline-size;
}
.phone__notch {
  position: absolute; top: 3.2%; left: 50%; transform: translateX(-50%);
  width: 30%; height: 4.2%; border-radius: var(--r-pill); background: var(--night); z-index: 3;
}
.statusbar {
  display: flex; align-items: center; justify-content: space-between;
  padding: 4.2cqw 5cqw 1cqw;
  font-size: 3.3cqw; font-weight: 650; color: var(--ink);
}
.statusbar__icons { display: flex; gap: 1.2cqw; align-items: center; opacity: .9; }
.statusbar__icons svg { width: 3.8cqw; height: auto; }
.phone--dark .phone__screen { background: #05070A; }
.phone--dark .statusbar { color: #fff; }

/* Profil animal (réplique du visuel de référence) */
.pp { flex: 1; padding: 2.5cqw 4cqw 4cqw; display: flex; flex-direction: column; gap: 3cqw; }
.pp__head { display: flex; align-items: center; gap: 2.4cqw; font-size: 4.4cqw; font-weight: 700; letter-spacing: -.02em; }
.pp__paw {
  width: 9cqw; height: 9cqw; border-radius: 50%; flex: none;
  background: var(--blue-tint); color: var(--blue-bright); display: grid; place-items: center;
}
.pp__paw svg { width: 5.4cqw; height: auto; }
.pp__card {
  background: var(--surface); border-radius: 4.5cqw; padding: 4.5cqw 4cqw;
  box-shadow: var(--sh-1); display: grid; gap: 3cqw; justify-items: center;
}
.pp__avatar {
  width: 27cqw; aspect-ratio: 1; border-radius: 50%;
  background: var(--blue-tint); border: .8cqw solid #fff;
  box-shadow: 0 0 0 .4cqw var(--blue-line);
  display: grid; place-items: center; overflow: hidden;
  color: var(--blue); font-size: 2.4cqw; font-weight: 700; text-align: center; line-height: 1.2;
}
.pp__avatar img { width: 100%; height: 100%; object-fit: cover; }
.pp__name {
  display: flex; align-items: center; gap: 1.8cqw;
  font-size: 7cqw; font-weight: 800; letter-spacing: -.03em; line-height: 1;
}
.pp__name svg { width: 4.6cqw; height: auto; color: var(--blue-bright); }
.pp__rows { margin: 0; width: 100%; display: grid; grid-template-columns: auto 1fr; gap: 1.6cqw 4cqw; font-size: 3.5cqw; }
.pp__rows dt { color: var(--ink-soft); }
.pp__rows dd { margin: 0; font-weight: 600; }
.pp__traits { width: 100%; font-size: 3.4cqw; line-height: 1.35; }
.pp__traits b { display: block; color: var(--ink-soft); font-weight: 500; }
.pp__contacts {
  width: 100%; background: var(--blue-tint); border-radius: 3.4cqw;
  padding: 3.2cqw 3cqw; display: grid; gap: 2.2cqw;
}
.pp__contacts h4 { font-size: 3.7cqw; color: #122A8C; letter-spacing: -.01em; }
.pp__contact {
  display: flex; align-items: center; gap: 2.6cqw;
  background: #fff; border-radius: 2.6cqw; padding: 2.4cqw 3cqw;
  font-size: 3.4cqw; box-shadow: 0 1px 2px rgba(20,20,15,.05);
}
.pp__contact-ico {
  width: 8cqw; height: 8cqw; border-radius: 50%; flex: none;
  background: var(--blue-bright); color: #fff; display: grid; place-items: center;
}
.pp__contact-ico svg { width: 4cqw; height: auto; }
.pp__contact b { display: block; font-weight: 650; }
.pp__contact span { color: var(--ink-soft); font-size: 3.2cqw; }
.pp__foot { text-align: center; font-size: 3.2cqw; color: var(--ink-soft); line-height: 1.4; margin-top: auto; }

/* Écran "NFC détecté" */
.nfcscan { flex: 1; display: grid; place-content: center; justify-items: center; gap: 4cqw; padding: 6cqw; text-align: center; }
.nfcscan__ring {
  width: 26cqw; aspect-ratio: 1; border-radius: 50%;
  border: 1.2cqw solid var(--blue-bright); color: var(--blue-bright);
  display: grid; place-items: center;
  box-shadow: 0 0 0 2cqw rgba(27,63,224,.12);
}
.nfcscan__ring svg { width: 13cqw; height: auto; }
.nfcscan h4 { color: #fff; font-size: 6cqw; letter-spacing: -.02em; }
.nfcscan__card {
  width: 100%; border-radius: 4cqw; padding: 4cqw 3cqw;
  background: rgba(255,255,255,.06); border: 1px solid rgba(255,255,255,.12);
  display: grid; gap: 2.6cqw; justify-items: center;
}
.nfcscan__flow { display: flex; align-items: center; gap: 2.6cqw; color: #fff; }
.nfcscan__flow svg { width: 7cqw; height: auto; opacity: .9; }
.nfcscan__card p { font-size: 3cqw; color: var(--on-night-soft); }

/* ======================= 4. ÉLÉMENTS PARTAGÉS ==========================
   Rescapés des sections supprimées lors du passage en mise en page plein
   cadre : ils servent encore ailleurs, ne les retirez pas sans vérifier.
   ====================================================================== */
/* Étoiles de notation : réutilisées par le bandeau d'avis (.ratingbar) et
   par les cartes d'avis. Couleur d'accent de la marque — plus d'ambre
   depuis le passage à l'identité LUUBO ; le bandeau les repasse en --night
   puisqu'elles y sont posées sur l'accent lui-même. */
.stars { display: inline-flex; gap: 2px; color: var(--accent-strong); }
.stars svg { width: 15px; height: 15px; }

/* Composition « médaille + ondes + téléphone » : seul rescapé de l'ancienne
   section « 3 étapes », réutilisé par le calque 2 du bloc collant
   (.follow__layer[data-layer="2"]). */
.step__scan { display: flex; align-items: center; gap: .55rem; width: 100%; justify-content: center; }
.step__scan .waves { width: 26px; flex: none; }

/* ======================= 8. COMPARATIF ================================= */
/* position: relative est indispensable : les libellés .sr-only (position absolue)
   des cellules se caleraient sinon sur la page entière, échapperaient au rognage
   du défilement et élargiraient le viewport mobile (tiroir et barre d'achat
   décalés hors écran). */
.cmp-scroll { position: relative; overflow-x: auto; -webkit-overflow-scrolling: touch; border-radius: var(--r-lg); border: 1px solid var(--line); background: var(--surface); box-shadow: var(--sh-1); }
.cmp { width: 100%; min-width: 660px; border-collapse: collapse; font-size: var(--t-sm); }
.cmp th, .cmp td { padding: .95rem 1rem; text-align: center; border-bottom: 1px solid var(--line); }
.cmp thead th { font-size: var(--t-xs); letter-spacing: .06em; text-transform: uppercase; color: var(--ink-faint); font-weight: 700; vertical-align: bottom; }
.cmp tbody th { text-align: left; font-weight: 600; color: var(--ink); min-width: 15rem; }
/* Notre colonne est peinte en couleur d'accent, comme sur la référence :
   c'est le seul endroit du tableau qui attire l'œil. */
.cmp .is-us { background: var(--accent-soft); }
.cmp thead .is-us { background: var(--accent); color: var(--night); font-size: var(--t-body); text-transform: none; letter-spacing: -.01em; }
.cmp tbody tr:last-child th, .cmp tbody tr:last-child td { border-bottom: 0; }
.cmp .yes { color: var(--blue); }
.cmp .no { color: var(--ink-faint); }
.cmp svg { display: inline-block; vertical-align: -4px; }
.cmp__price { font-weight: 800; letter-spacing: -.02em; }

/* Comparatif sur mobile : au lieu d'un tableau de 5 colonnes à faire défiler
   (les concurrents restaient hors écran), on compare SerenTag à UN concurrent
   choisi dans .cmp-switch. Sans support de :has(), le tableau défilant reste. */
.cmp-switch { display: none; min-width: 0; margin: 0 0 1rem; padding: 0; border: 0; }
.cmp-switch__label {
  display: block; width: 100%; padding: 0; margin-bottom: .55rem;
  font-size: var(--t-xs); font-weight: 600; color: var(--ink-faint); text-align: center;
}
.cmp-switch__row {
  display: flex; gap: .3rem; padding: .3rem;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-pill);
  box-shadow: var(--sh-1);
}
.cmp-switch__opt { position: relative; flex: 1 1 0; min-width: 0; }
.cmp-switch__opt input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
.cmp-switch__opt span {
  display: grid; place-items: center; height: 100%; min-height: 44px;
  padding: .45rem .35rem; border-radius: var(--r-pill);
  font-size: var(--t-xs); font-weight: 650; line-height: 1.15; text-align: center; color: var(--ink-soft);
  transition: background var(--fast) var(--ease), color var(--fast) var(--ease);
}
.cmp-switch__opt input:checked + span { background: var(--ink); color: #fff; }
.cmp-switch__opt input:focus-visible + span { outline: 2.5px solid var(--focus); outline-offset: 2px; }

@media (max-width: 760px) {
  @supports selector(:has(*)) {
    .cmp-switch { display: block; }
    .cmp { min-width: 0; table-layout: fixed; }
    .cmp th, .cmp td { padding: .85rem .55rem; }
    .cmp tbody th { min-width: 0; font-size: var(--t-xs); line-height: 1.35; }
    .cmp :is(th, td):first-child { width: 44%; }
    .cmp tbody td { font-size: var(--t-xs); line-height: 1.35; }
    .cmp thead th { font-size: 11px; letter-spacing: .03em; }
    .cmp thead .is-us { font-size: var(--t-sm); }
    .cmp :is(th, td):nth-child(n+3) { display: none; }
    .cmp-block:has(input[value="3"]:checked) .cmp :is(th, td):nth-child(3),
    .cmp-block:has(input[value="4"]:checked) .cmp :is(th, td):nth-child(4),
    .cmp-block:has(input[value="5"]:checked) .cmp :is(th, td):nth-child(5) { display: table-cell; }
  }
}

/* ======================= 9. OFFRES (packs) =============================
   Rangées larges et sélectionnables, et non trois cartes côte à côte.
   Raison technique : catalog.js cherche TOUS les éléments d'un pack à
   l'intérieur de son article (`$(card, "[data-swatches]")`, et les
   gestionnaires remontent par `closest("[data-offer]")`). Le détail
   — couleurs, abonnement, bouton — doit donc rester DANS l'article ; une
   rangée pleine largeur lui donne la place, trois colonnes étroites non.

   Le pack mis en avant porte data-selected="true" DIRECTEMENT DANS LE HTML :
   sans JS, un pack reste choisi et son bouton d'achat reste accessible.
   ====================================================================== */
.packs { display: grid; gap: .6rem; }
.offer {
  position: relative; display: grid; gap: .85rem;
  background: var(--surface); border: 1.5px solid var(--line); border-radius: var(--r-lg);
  padding: .3rem 1.1rem 1.1rem;
  transition: border-color var(--fast) var(--ease), background var(--fast) var(--ease);
}
.offer:hover { border-color: var(--line-strong); }
.offer[data-selected="true"] { border-color: var(--blue); background: var(--blue-tint); }

/* Tête cliquable : un vrai <button>, donc accessible au clavier. */
.offer__head {
  display: grid; grid-template-columns: auto 1fr auto; gap: .9rem; align-items: center;
  width: 100%; padding: .95rem 0 0; margin: 0;
  background: none; border: 0; text-align: left; cursor: pointer; color: inherit;
}
.offer__radio {
  width: 21px; height: 21px; border-radius: 50%; flex: none;
  border: 2px solid var(--line-strong); display: grid; place-items: center;
  transition: border-color var(--fast) var(--ease);
}
.offer__radio::after {
  content: ""; width: 11px; height: 11px; border-radius: 50%; background: var(--blue);
  transform: scale(0); transition: transform var(--fast) var(--ease);
}
.offer[data-selected="true"] .offer__radio { border-color: var(--blue); }
.offer[data-selected="true"] .offer__radio::after { transform: scale(1); }
.offer__name { font-size: var(--t-label); font-weight: 800; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-faint); }
.offer__qty { font-size: 1.12rem; font-weight: 750; letter-spacing: -.022em; line-height: 1.15; }
.offer__money { display: grid; justify-items: end; gap: .1rem; }
.offer__price { display: flex; align-items: baseline; gap: .45rem; flex-wrap: wrap; justify-content: flex-end; }
.offer__price b { font-size: 1.5rem; font-weight: 800; letter-spacing: -.03em; line-height: 1; }
.offer__price s { color: var(--ink-faint); font-size: var(--t-xs); }
.offer__unit { font-size: var(--t-xs); color: var(--ink-faint); text-align: right; }
.offer__save { justify-self: start; }
/* Pastille « Le plus choisi » posée sur le bord supérieur de la rangée. */
.offer__ribbon {
  position: absolute; top: 0; right: 1.1rem; transform: translateY(-50%);
  background: var(--accent); color: var(--night); border-radius: var(--r-pill);
  padding: .26rem .75rem; font-size: 11px; font-weight: 800;
  letter-spacing: .1em; text-transform: uppercase; white-space: nowrap;
}
/* Détail : ouvert uniquement sur le pack choisi. */
.offer__detail { display: none; gap: .85rem; }
.offer[data-selected="true"] .offer__detail { display: grid; }
.offer__perks { list-style: none; margin: 0; padding: 0; display: grid; gap: .5rem; font-size: var(--t-sm); }
.offer__perks li { display: grid; grid-template-columns: auto 1fr; gap: .55rem; align-items: start; color: var(--ink-soft); }
.offer__perks svg { color: var(--blue); margin-top: .25rem; }
.offer__perks b { color: var(--ink); font-weight: 650; }
.swatches { display: grid; gap: .45rem; }
.swatches__label { font-size: var(--t-xs); color: var(--ink-faint); font-weight: 600; }
.swatches__row { display: flex; gap: .4rem; flex-wrap: wrap; }
.swatch { position: relative; }
.swatch input { position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.swatch span {
  display: inline-flex; align-items: center; gap: .35rem;
  padding: .36rem .6rem; border-radius: var(--r-pill);
  border: 1.5px solid var(--line); background: var(--surface-muted);
  font-size: var(--t-xs); font-weight: 600; cursor: pointer;
  transition: border-color var(--fast) var(--ease), background var(--fast) var(--ease);
}
.swatch i { width: 12px; height: 12px; border-radius: 50%; border: 1px solid rgba(0,0,0,.14); }
/* Packs multi-médailles : une rangée de couleurs par médaille */
.swatches__row--medals { display: grid; gap: .7rem; }
.medal { display: grid; gap: .3rem; }
.medal__label { font-size: var(--t-xs); font-weight: 700; color: var(--ink); }
.medal__row { display: flex; gap: .4rem; flex-wrap: wrap; }
/* Pastille-photo : vignette de la variante Shopify, nom dessous. */
.swatch--img span { flex-direction: column; gap: .3rem; padding: .3rem .3rem .4rem; border-radius: var(--r-sm); min-width: 64px; }
.swatch--img img { width: 56px; height: 56px; object-fit: cover; border-radius: var(--r-xs); display: block; }
.swatch--img small { font-size: 11px; font-weight: 650; line-height: 1.1; text-align: center; }
.swatch--img input:checked + span { border-color: var(--blue); background: var(--blue-tint); }
.swatch input:checked + span { border-color: var(--ink); background: var(--surface); }
.swatch input:focus-visible + span { outline: 2.5px solid var(--focus); outline-offset: 2px; }
.swatch input:disabled { cursor: not-allowed; }
.swatch input:disabled + span { opacity: .45; text-decoration: line-through; cursor: not-allowed; }
.offer__fine { font-size: var(--t-xs); color: var(--ink-faint); text-align: center; }

/* --- Bloc abonnement (visible seulement si Shopify expose des plans) ----- */
.sub {
  display: grid; gap: .55rem; justify-items: start;
  padding: .85rem .9rem; border-radius: var(--r);
  background: var(--blue-tint); border: 1px solid var(--blue-line);
}
.sub__freq { display: grid; gap: .3rem; width: 100%; font-size: var(--t-xs); font-weight: 650; color: var(--ink-soft); }
.sub__freq select {
  width: 100%; padding: .55rem .7rem; border-radius: var(--r-sm);
  border: 1.5px solid var(--blue-line); background: var(--surface);
  font-size: var(--t-sm); font-weight: 600; color: var(--ink);
}
.sub__note { font-size: var(--t-xs); color: var(--ink-soft); line-height: 1.4; }
.sub[data-mode="onetime"] { background: var(--surface-muted); border-color: var(--line); }

/* États pilotés par catalog.js : chargement → prêt | épuisé | erreur */
.offer[aria-busy="true"] [data-price] {
  display: inline-block; min-width: 7rem; height: 2.1rem; border-radius: var(--r-xs);
  background: linear-gradient(90deg, var(--ground-deep) 25%, var(--surface-muted) 50%, var(--ground-deep) 75%);
  background-size: 200% 100%; animation: shimmer 1.2s linear infinite;
}
@keyframes shimmer { to { background-position: -200% 0; } }
.offer[data-state="error"] [data-price] { font-size: 1.15rem; color: var(--ink-faint); }
.offer[data-state="soldout"] .offer__price b { color: var(--ink-faint); }
.offer__stock { font-size: var(--t-xs); font-weight: 700; color: var(--danger); text-align: center; }
.offers-status {
  max-width: 40rem; margin: 0 auto 1.6rem; padding: .9rem 1.2rem;
  border-radius: var(--r); background: var(--blue-tint); border: 1px solid var(--blue-line);
  color: var(--blue); font-size: var(--t-sm); font-weight: 600; text-align: center;
}
/* ======================= 9 bis. BLOC D'ACHAT ===========================
   Galerie collante à gauche, colonne d'achat à droite : le visuel produit
   reste à l'écran pendant qu'on choisit son pack. Sur mobile la galerie
   redevient statique — un visuel collant qui mange la moitié de l'écran
   pendant qu'on choisit un pack gêne au lieu d'aider.
   ====================================================================== */
.buy__grid {
  display: grid; grid-template-columns: minmax(0, 1.02fr) minmax(0, .98fr);
  gap: clamp(2rem, 1rem + 4vw, 4.5rem); align-items: start;
}
.buy__gallery {
  position: sticky; top: calc(var(--nav-h) + 1.4rem);
  display: grid; grid-template-columns: 5.2rem minmax(0, 1fr); gap: .7rem;
}
.buy__thumbs { display: grid; gap: .55rem; align-content: start; }
.buy__thumb {
  aspect-ratio: 1; border: 1.5px solid var(--line); border-radius: var(--r-sm);
  background: var(--surface); display: grid; place-items: center; overflow: hidden; padding: 0; cursor: pointer;
}
.buy__thumb img, .buy__main img { width: 100%; height: 100%; object-fit: cover; display: block; }
.buy__thumb.is-active { border-color: var(--blue); }
.buy__main {
  aspect-ratio: 1; border-radius: var(--r-lg); background: var(--surface);
  display: grid; place-items: center; overflow: hidden;
}
.buy__col { display: grid; gap: 1.05rem; align-content: start; }
.buy__title { font-size: clamp(1.9rem, 1.2rem + 2.2vw, 3rem); }
.buy__claim { font-weight: 700; }
.buy__desc { color: var(--ink-soft); font-size: var(--t-sm); }
.buy__rows { display: grid; }
.buy__row { border-top: 1px solid var(--line); }
.buy__row:last-of-type { border-bottom: 1px solid var(--line); }
.buy__row summary {
  display: flex; align-items: center; gap: .7rem; padding: .95rem 0;
  cursor: pointer; list-style: none; font-weight: 650; font-size: var(--t-sm);
}
.buy__row summary::-webkit-details-marker { display: none; }
.buy__row summary svg { color: var(--blue); }
.buy__row summary::after {
  content: ""; margin-left: auto; width: 9px; height: 9px;
  border-right: 2px solid var(--ink-soft); border-bottom: 2px solid var(--ink-soft);
  transform: rotate(45deg) translateY(-2px); transition: transform var(--mid) var(--ease);
}
.buy__row[open] summary::after { transform: rotate(225deg) translateY(-2px); }
.buy__row-body { padding-bottom: 1rem; font-size: var(--t-sm); color: var(--ink-soft); }
.buy__helper { font-size: var(--t-sm); }

/* --- Carrousel d'avis (une carte, flèches) : cartes clonées depuis #avis --- */
.rcar { position: relative; display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: .5rem; align-items: center; }
.rcar__track {
  display: flex; overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none;
  scroll-behavior: smooth; -webkit-overflow-scrolling: touch;
}
.rcar__track::-webkit-scrollbar { display: none; }
.rcar__track .review { flex: 0 0 100%; scroll-snap-align: start; padding: 1rem 1.1rem; box-shadow: none; }
.rcar__track .review blockquote { font-size: var(--t-sm); }
.rcar__btn {
  width: 36px; height: 36px; border-radius: 50%; display: grid; place-items: center;
  background: var(--surface); border: 1.5px solid var(--line); cursor: pointer; color: var(--ink);
}
.rcar__btn:hover { border-color: var(--ink); }
.rcar__btn:first-of-type svg { transform: rotate(180deg); }
.rcar__count { grid-column: 2; justify-self: center; font-size: var(--t-label); color: var(--ink-faint); letter-spacing: .08em; }
@media (prefers-reduced-motion: reduce) { .rcar__track { scroll-behavior: auto; } }

/* --- « Plus que N en stock » : réel uniquement (catalog.js) --- */

/* --- Moyens de paiement sous le bouton : logos SVG du sprite (#pay-*) ---
   Un nom de PAYMENT_METHODS sans symbole retombe sur une puce texte. */
.pay-methods { display: flex; flex-wrap: wrap; gap: .45rem; justify-content: center; }
.pay-methods__logo { width: 46px; height: 29px; display: block; }
.pay-methods__chip {
  padding: .22rem .55rem; border-radius: var(--r-xs); border: 1px solid var(--line);
  font-size: 11px; font-weight: 700; letter-spacing: .04em; color: var(--ink-soft); background: var(--surface);
}

/* --- Communauté : avatars sous le bouton, « Rejoignez … » sous les avis --- */
.avatars { display: flex; align-items: center; gap: .6rem; justify-content: center; margin-top: .2rem; font-size: var(--t-xs); color: var(--ink-soft); }
.avatars__stack { display: flex; }
.avatars__item {
  width: 30px; height: 30px; border-radius: 50%; overflow: hidden; flex: none;
  border: 2px solid var(--surface); margin-left: -8px; background: var(--accent);
  display: grid; place-items: center; font-weight: 800; font-size: 11px; color: var(--night);
}
.avatars__item:first-child { margin-left: 0; }
.avatars__item img { width: 100%; height: 100%; object-fit: cover; }
.avatars b { color: var(--ink); }
.loved {
  display: flex; align-items: center; justify-content: center; gap: .45rem;
  margin-top: .2rem; padding: .55rem .9rem; border-radius: var(--r-pill);
  background: var(--accent-soft); color: var(--night); font-size: var(--t-sm); font-weight: 650;
}
.loved svg { color: var(--blue); }

/* --- Bandeau de livraison (dates réelles J+min → J+max, ui.js) --- */
.delivery { margin-top: .4rem; display: grid; gap: .35rem; }
.delivery__row {
  display: flex; align-items: center; gap: .6rem; flex-wrap: wrap;
  padding: .8rem .95rem; background: var(--ground-deep); border-radius: var(--r-sm);
  font-size: var(--t-sm);
}
.delivery__row b { font-weight: 700; }
.delivery__row--muted { background: var(--surface-muted); }
.delivery__dot { width: 9px; height: 9px; border-radius: 50%; background: var(--blue); flex: none; }
.delivery__dot--soft { background: var(--accent-strong); }
.delivery__right { margin-left: auto; color: var(--ink-soft); font-size: var(--t-xs); font-weight: 600; white-space: nowrap; }

/* --- Vidéos clients sous le bloc d'achat --- */
/* Vit dans .buy__col : largeur des offres sur PC, pleine largeur sur mobile. */
.ugc { margin-top: .6rem; }
.ugc__title { font-family: var(--font-display); font-size: var(--t-h3); margin-bottom: .7rem; }
.ugc__grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .8rem; }
.ugc__item { aspect-ratio: 9 / 16; border-radius: var(--r); overflow: hidden; position: relative; }
.ugc__video { width: 100%; height: 100%; object-fit: cover; display: block; }
.ugc__play {
  position: absolute; inset: 0; margin: auto; width: 56px; height: 56px; border-radius: 50%;
  border: 0; background: rgba(11, 18, 64, .7); color: #fff; display: grid; place-items: center; cursor: pointer;
}
.ugc__item.is-playing .ugc__play { opacity: 0; }
@media (max-width: 760px) { .ugc__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .5rem; } }

@media (max-width: 960px) {
  /* minmax(0, 1fr) et NON 1fr : `1fr` vaut minmax(auto, 1fr), la colonne
     prend alors la largeur minimale de son contenu le plus large (prix en
     nowrap, rangée de logos…) et déborde de l'écran — coupé net par le
     overflow-x: clip du body. Mesuré : 447 px de colonne pour 390 d'écran. */
  .buy__grid { grid-template-columns: minmax(0, 1fr); }
  .buy__col, .buy__gallery, .offer, .rcar, .packs { min-width: 0; }
  /* Six couleurs sur une seule ligne par médaille (353 px utiles). */
  .medal__row { gap: .25rem; }
  .swatch--img span { min-width: 0; padding: .15rem .15rem .25rem; gap: .15rem; }
  .swatch--img img { width: 34px; height: 34px; }
  .swatch--img small { font-size: 9.5px; letter-spacing: -.01em; }
  .buy__gallery { position: static; grid-template-columns: minmax(0, 1fr); }
  .buy__thumbs { grid-auto-flow: column; grid-auto-columns: 4.2rem; justify-content: start; overflow-x: auto; position: relative; scrollbar-width: none; }
}

/* Bump de commande */
.bump {
  margin-top: 1.6rem;
  border: 2px dashed var(--blue-line); border-radius: var(--r-lg);
  background: var(--blue-tint); padding: 1.2rem 1.4rem;
  display: grid; grid-template-columns: auto 1fr auto; gap: 1rem; align-items: center;
}
.bump input { width: 22px; height: 22px; accent-color: var(--blue); cursor: pointer; }
.bump__label { font-weight: 700; font-size: var(--t-sm); cursor: pointer; }
.bump__label span { display: block; font-weight: 500; color: var(--ink-soft); font-size: var(--t-xs); margin-top: .2rem; }
.bump__price { font-weight: 800; white-space: nowrap; color: var(--blue); }
@media (max-width: 620px) { .bump { grid-template-columns: auto 1fr; } .bump__price { grid-column: 2; } }

.pay-trust {
  margin-top: 1.6rem; display: flex; flex-wrap: wrap; gap: .5rem 1.4rem;
  justify-content: center; font-size: var(--t-xs); color: var(--ink-faint);
}
.pay-trust span { display: inline-flex; align-items: center; gap: .4rem; }
.pay-trust svg { color: var(--blue); }

/* ======================= 10. AVIS ====================================== */
.reviews-grid { display: grid; gap: 1.2rem; grid-template-columns: repeat(3, minmax(0, 1fr)); }
.review {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg);
  padding: 1.5rem; display: grid; gap: .9rem; align-content: start; box-shadow: var(--sh-1);
}
.review blockquote { margin: 0; font-size: var(--t-sm); line-height: 1.6; color: var(--ink); }
.review__who { display: flex; align-items: center; gap: .7rem; font-size: var(--t-xs); }
.review__ava {
  width: 38px; height: 38px; border-radius: 50%; flex: none;
  background: var(--blue-tint); color: var(--blue); display: grid; place-items: center;
  font-weight: 800; font-size: var(--t-sm);
}
.review__who b { display: block; font-size: var(--t-sm); }
.review__who span { color: var(--ink-faint); }
.rating-head { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; margin-top: .6rem; }
.rating-head b { font-size: 1.6rem; font-weight: 800; letter-spacing: -.03em; }
/* Avis posés sur le fond nuit : la carte devient un simple voile clair. */
.section--night .review { background: rgba(255, 255, 255, .06); border-color: rgba(255, 255, 255, .14); box-shadow: none; }
.section--night .review blockquote { color: var(--on-night); }
.section--night .review__who span { color: var(--on-night-soft); }
.section--night .review__ava { background: var(--accent); color: var(--night); }
@media (max-width: 900px) { .reviews-grid { grid-template-columns: 1fr; } }

/* ======================= 11. GARANTIE ================================== */
.guarantee {
  display: grid; grid-template-columns: auto 1fr; gap: clamp(1.2rem, .5rem + 2vw, 2.4rem);
  align-items: center;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-xl);
  padding: clamp(1.6rem, 1rem + 2vw, 2.6rem); box-shadow: var(--sh-2);
}
.guarantee__seal {
  width: clamp(88px, 12vw, 118px); aspect-ratio: 1; border-radius: 50%;
  background: var(--blue-tint); border: 2px solid var(--blue-line);
  display: grid; place-items: center; justify-items: center; gap: 0; text-align: center;
  color: var(--blue); font-weight: 800; line-height: 1;
}
.guarantee__seal b { font-size: clamp(1.5rem, 2.4vw, 2rem); letter-spacing: -.04em; }
.guarantee__seal small { font-size: var(--t-label); letter-spacing: .1em; text-transform: uppercase; }
.guarantee__cols { display: grid; gap: 1rem 1.6rem; grid-template-columns: repeat(2, minmax(0, 1fr)); margin-top: 1.1rem; }
.guarantee__cols li { display: grid; grid-template-columns: auto 1fr; gap: .6rem; font-size: var(--t-sm); color: var(--ink-soft); }
.guarantee__cols { list-style: none; padding: 0; }
.guarantee__cols svg { color: var(--blue); margin-top: .2rem; }
@media (max-width: 700px) {
  .guarantee { grid-template-columns: 1fr; text-align: left; }
  .guarantee__cols { grid-template-columns: 1fr; }
}

/* ======================= 12. FAQ ======================================= */
.faq-list { display: grid; gap: .7rem; }
.faq-item {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r);
  overflow: hidden; transition: border-color var(--fast) var(--ease);
}
.faq-item[open] { border-color: var(--line-strong); box-shadow: var(--sh-1); }
.faq-item summary {
  display: flex; align-items: center; gap: 1rem;
  padding: 1.15rem 1.3rem; cursor: pointer; list-style: none;
  font-weight: 650; font-size: var(--t-body); letter-spacing: -.01em;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after {
  content: ""; flex: none; margin-left: auto;
  width: 11px; height: 11px; border-right: 2px solid var(--ink-soft); border-bottom: 2px solid var(--ink-soft);
  transform: rotate(45deg) translateY(-2px); transition: transform var(--mid) var(--ease);
}
.faq-item[open] summary::after { transform: rotate(225deg) translateY(-2px); }
.faq-item__body { padding: 0 1.3rem 1.3rem; font-size: var(--t-sm); color: var(--ink-soft); max-width: 68ch; }
.faq-item__body p + p { margin-top: .7rem; }
.faq-aside { margin-top: 1.6rem; text-align: center; font-size: var(--t-sm); color: var(--ink-soft); }

/* ======================= 13. CTA FINAL ================================= */
.final { position: relative; overflow: hidden; }
.final::before {
  content: ""; position: absolute; inset: auto -10% -60% 40%;
  height: 120%; background: radial-gradient(circle at 50% 50%, rgba(27,63,224,.22), transparent 60%);
}
.final__inner { position: relative; z-index: 1; display: grid; gap: 2rem; justify-items: center; text-align: center; }
.final h2 { max-width: 26ch; }
.final .lead { max-width: 48ch; }
.final__cta { display: flex; flex-wrap: wrap; gap: .8rem; justify-content: center; }
.final__pills { display: flex; flex-wrap: wrap; gap: .5rem; justify-content: center; }

/* ======================= 14. BANDEAU D'AVIS ============================
   Fine bande d'accent entre le héros et la première section sombre : elle
   coupe la page et porte la note. Chiffres TODO tant qu'ils ne sont pas réels.
   ====================================================================== */
.ratingbar { background: var(--accent); color: var(--night); }
.ratingbar__inner {
  display: flex; flex-wrap: wrap; justify-content: center; align-items: center;
  gap: .3rem .8rem; padding-block: .8rem;
  font-size: var(--t-sm); font-weight: 650;
}
.ratingbar .stars { color: var(--night); }
.ratingbar__sep { opacity: .45; }

/* ======================= 15. POURQUOI LUUBO ===========================
   Trois arguments, trois pictos, sur fond nuit. Pas de carte : le fond de
   section suffit à isoler le bloc.
   ====================================================================== */
.why { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(1.8rem, 1rem + 3vw, 4.5rem); }
.why__item { display: grid; justify-items: center; text-align: center; gap: .9rem; }
.why__ico { width: 58px; height: 58px; color: var(--accent); stroke-width: 1.5; }
.why__item h3 { font-size: 1.05rem; max-width: 20ch; color: var(--on-night); }
.why__item p { font-size: var(--t-sm); color: var(--on-night-soft); max-width: 26ch; }
@media (max-width: 760px) { .why { grid-template-columns: 1fr; gap: 2.4rem; } }

/* ======================= 16. VU DANS (presse) ==========================
   TODO : n'affichez un logo QUE si la retombée presse existe réellement.
   Tant qu'il n'y en a pas, ces emplacements restent des repères de mise en
   page — publier un faux logo média est une pratique trompeuse.
   ====================================================================== */
/* Filet de séparation OBLIGATOIRE en bas : la presse est suivie du bloc
   d'achat, tous deux sur fond blanc transparent. Sans ce trait, les deux
   sections forment une seule étendue blanche (mesuré : bas de la presse et
   haut de l'achat au même pixel, bordure 0). Un trait et non un fond : le
   bloc collant qui précède est déjà en --ground-deep, un fond coloré ferait
   fusionner la presse avec lui de l'autre côté. Pas d'ombre portée : elles
   sont proscrites par la mise en page plein cadre. */
.press { overflow: hidden; border-bottom: 1px solid var(--line); }
.press__title { text-align: center; font-family: var(--font-display); font-size: var(--t-h3); margin-bottom: 1.5rem; }
.press__mask { overflow: hidden; }
/* Défilement sans couture — DEUX conditions, toutes deux indispensables :

   1) La piste contient un nombre ENTIER de groupes identiques et l'animation
      translate d'exactement UN groupe (3 groupes → -33.3333 %). Avec
      seulement 2 groupes la piste est trop courte : arrivé à mi-course, la
      fenêtre déborde de la fin de la piste et on voit du VIDE après le
      dernier logo. Ne pas descendre sous 3 groupes.

   2) L'écart n'est PAS un `gap` de la piste. Avec un gap uniforme, N logos
      donnent N-1 écarts : un pourcentage de la piste ne tombe alors jamais
      sur une frontière de groupe (il manque un demi-écart) et la boucle
      dérive. L'écart est donc porté par le GROUPE — gap interne plus un
      padding-right de même valeur, ce qui rend chaque groupe strictement
      identique et répétable. */
.press__track { display: flex; width: max-content; align-items: center; animation: press-scroll 42s linear infinite; }
.press__group {
  display: flex; align-items: center;
  gap: clamp(2rem, 1rem + 3vw, 4.5rem);
  padding-right: clamp(2rem, 1rem + 3vw, 4.5rem);
}
/* Logos de presse : PNG OPAQUES fournis sur un fond très légèrement grisé.
   - `mix-blend-mode: multiply` fait disparaître ce fond sur notre blanc pur ;
     sans lui, chaque logo s'affiche comme un rectangle gris.
   - Le passage en gris est volontaire : un bandeau « Vu dans » doit rester
     neutre, sinon les couleurs des titres (bordeaux, vert citron…)
     concurrencent le bleu de la marque. Couleur rendue au survol.
   - Hauteur fixe, largeur libre : les fichiers n'ont pas le même rapport
     (240×120 et 360×120) ; imposer une largeur commune les déformerait. */
.press__logo {
  height: 42px; width: auto; flex: none;
  mix-blend-mode: multiply;
  /* Opacité à 1 : à .62 les titres déjà clairs (Bête de Cœur en rose, Maison
     Ravel en gris pâle) devenaient illisibles, tandis que les titres noirs
     passaient très bien. Le gris vient du `grayscale`, pas d'un voile.
     NE PAS assombrir avec `brightness()` : le filtre s'applique AVANT le
     `mix-blend-mode`, donc assombrir le fond quasi blanc des PNG ferait
     réapparaître les rectangles gris que `multiply` fait disparaître. */
  filter: grayscale(1) contrast(1.25);
  opacity: 1;
  transition: opacity var(--fast) var(--ease), filter var(--fast) var(--ease);
}
.press__logo:hover { opacity: 1; filter: none; }
@media (prefers-reduced-motion: reduce) { .press__logo { transition: none; } }
/* -33.3333 % = exactement un groupe sur les trois que contient la piste.
   Si vous changez le nombre de groupes, changez CETTE valeur en conséquence
   (100 / nombre de groupes), sinon la boucle saute à chaque tour. */
@keyframes press-scroll { to { transform: translateX(-33.3333%); } }

/* ======================= 17. LE PRODUIT VOUS SUIT =====================
   Mécanique demandée : « que l'utilisateur ne sorte jamais du visuel
   produit, qu'il le suive de façon fluide ».

   Le visuel est en `position: sticky` : il reste à l'écran pendant que les
   panneaux de texte défilent à côté. Zéro librairie — sticky pour l'ancrage,
   IntersectionObserver (ui.js) uniquement pour savoir quel panneau est actif.

   Règle : les panneaux ne sont estompés QUE sous html.js. Si le JS échoue,
   ils restent tous lisibles (même piège que .reveal).
   ====================================================================== */
.follow { position: relative; background: var(--ground-deep); }
/* align-items doit rester `stretch` : avec `start`, la cellule de grille ne
   fait que la hauteur de son contenu et l'élément collant n'a aucune course
   — il ne colle pas du tout. La cellule sert de rail, l'enfant colle. */
.follow__grid {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, .88fr);
  gap: clamp(2rem, 1rem + 4vw, 5rem); align-items: stretch;
}
.follow__media { display: block; }
.follow__shot {
  position: sticky; top: calc(var(--nav-h) + clamp(.8rem, 2vh, 2rem));
  width: min(100%, 30rem); height: min(72vh, 40rem);
  margin-inline: auto; display: grid; place-items: center;
}
/* Rotation douce pilotée par le défilement (--follow-p, 0 → 1, posé par ui.js) */
.follow__object {
  width: 100%; height: 100%; display: grid; place-items: center;
  transform: rotate(calc(var(--follow-p, 0) * 18deg)) scale(calc(1 + var(--follow-p, 0) * .05));
  transition: transform 140ms linear;
}
.follow__img { width: min(100%, 26rem); height: auto; max-height: 100%; object-fit: contain; display: block; }
/* Image verticale (profil 9:16) : calée sur la hauteur du rail. */
.follow__img--tall { width: auto; height: 100%; max-width: 100%; }
.follow__medal { width: 96px; height: auto; flex: none; }
/* Écran « NFC détecté » (image client, sans transparence) : calé sur la
   hauteur du rail ; .step__scan doit donc prendre toute cette hauteur. */
.follow__layer[data-layer="2"] .step__scan { height: 100%; }
.follow__phone-img { height: 100%; width: auto; max-width: 62%; object-fit: contain; border-radius: var(--r); display: block; }
@media (max-width: 900px) { .follow__medal { width: 64px; } }
/* Calques (médaille → scan → profil) : un seul visible, selon l'étape active */
.follow__layer {
  /* grid-template-rows: 100 % rend la hauteur de rangée DÉFINIE : sans
     cela, un enfant en height: 100 % (image verticale du calque 3) ne peut
     pas se résoudre et déborde du rail. */
  position: absolute; inset: 0; display: grid; grid-template-rows: 100%; place-items: center;
  opacity: 0; transform: translateY(14px) scale(.97); pointer-events: none;
  transition: opacity var(--slow) var(--ease), transform var(--slow) var(--ease);
}
.follow__layer .phone { width: min(62%, 15rem); }
.follow[data-step="1"] .follow__layer[data-layer="1"],
.follow[data-step="2"] .follow__layer[data-layer="2"],
.follow[data-step="3"] .follow__layer[data-layer="3"] { opacity: 1; transform: none; }
/* Sans JS, aucun data-step n'est posé : on montre le premier calque. */
.follow:not([data-step]) .follow__layer[data-layer="1"] { opacity: 1; transform: none; }

.follow__panel {
  min-height: min(78vh, 34rem);
  display: grid; align-content: center; gap: .9rem;
  padding-block: clamp(1.5rem, 1rem + 2vw, 3rem);
}
/* Le dernier panneau est volontairement plus court : sinon le rail collant
   continue de défiler une demi-page après la fin du texte et laisse un grand
   vide avant la section suivante. */
.follow__panel:last-of-type { min-height: min(52vh, 24rem); }
.js .follow__panel { opacity: .34; transition: opacity var(--mid) var(--ease); }
.js .follow__panel.is-active { opacity: 1; }
.follow__step { font-size: var(--t-label); font-weight: 800; letter-spacing: .16em; text-transform: uppercase; color: var(--blue); }
.follow__panel h3 { font-size: clamp(1.7rem, 1.1rem + 2vw, 2.7rem); }
.follow__panel p { font-size: var(--t-lead); color: var(--ink-soft); max-width: 40ch; }
.follow__note { font-size: var(--t-sm); color: var(--ink-faint); }

@media (max-width: 900px) {
  /* Sur une seule colonne, les rôles s'INVERSENT. En grille 2 colonnes, le
     rail s'étire sur la hauteur des panneaux et c'est .follow__shot qui
     colle. En une colonne, le rail deviendrait sa propre rangée, haute
     exactement comme le visuel : l'élément collant n'aurait plus aucune
     course (symptôme : rect.top très négatif, le visuel part vers le haut).
     On repasse donc en flux bloc et c'est le RAIL qui colle — son bloc
     conteneur est alors la section entière, qui elle est haute. */
  .follow__grid { display: block; }
  .follow__media {
    position: sticky; top: var(--nav-h); z-index: 2;
    background: var(--ground-deep);
    margin-inline: calc(var(--gutter) * -1); padding: .5rem var(--gutter);
    box-shadow: 0 12px 18px -14px rgba(11, 18, 64, .45);
  }
  .follow__shot {
    position: static; height: 30vh; width: 100%;
    overflow: hidden; background: none; box-shadow: none; padding: 0;
  }
  /* La hauteur de .phone n'est PAS réglable : elle découle de la largeur via
     `.phone__screen { aspect-ratio: 9/19.2 }` + 16 px de bordure. Poser une
     `height` ferait s'effondrer la largeur de l'écran interne. On dimensionne
     donc par la largeur : 7,4 rem ≈ 234 px de haut, qui tient dans les 30 vh
     du rail (253 px sur un écran de 844). Si vous changez l'une des deux
     valeurs, revérifiez que le téléphone n'est pas rogné. */
  .follow__layer .phone { width: min(30%, 7.4rem); }
  .follow__panel, .follow__panel:last-of-type { min-height: 0; padding-block: 2.4rem; }
  .js .follow__panel { opacity: 1; }
}

/* ======================= 18. BEST-SELLERS =============================
   Deux grandes vignettes plein cadre sur fond nuit.
   ====================================================================== */
.bests { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(1rem, .5rem + 1.6vw, 2rem); }
.best { display: grid; gap: 1rem; }
/* Portrait : les photos chien/chat fournies sont verticales. */
.best__media { aspect-ratio: 4 / 5; border-radius: var(--r-lg); overflow: hidden; }
.best__media img, .review__ava img { width: 100%; height: 100%; object-fit: cover; display: block; }
.best__body { display: grid; gap: .35rem; }
.best h3 { font-size: 1.25rem; color: var(--on-night); }
.best p { font-size: var(--t-sm); color: var(--on-night-soft); max-width: 40ch; }
.best__price { font-weight: 800; letter-spacing: -.02em; color: var(--on-night); }
.best .btn { justify-self: start; margin-top: .5rem; }
@media (max-width: 760px) { .bests { grid-template-columns: 1fr; } }

/* ======================= 19. NOTRE HISTOIRE ===========================
   Image à gauche, gros titre à droite : la composition asymétrique de la
   référence. Pas de carte, pas d'ombre.
   ====================================================================== */
.story { display: grid; grid-template-columns: minmax(0, .82fr) minmax(0, 1fr); gap: clamp(2rem, 1rem + 4vw, 5rem); align-items: center; }
.story__media { aspect-ratio: 4 / 5; border-radius: 0; }
.story__body { display: grid; gap: 1.1rem; justify-items: start; }
.story__body h2 { max-width: 16ch; }
.story__body .lead { max-width: 44ch; }
@media (max-width: 860px) { .story { grid-template-columns: 1fr; } .story__media { aspect-ratio: 16 / 10; } }

/* ======================= 20. GALERIE DÉFILANTE ========================
   Bande d'ambiance en bas de page : défilement horizontal au doigt, sans
   bouton. Conteneur positionné (voir le piège du comparatif).
   ====================================================================== */
.gallery { position: relative; overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
.gallery::-webkit-scrollbar { display: none; }
.gallery__track { display: flex; gap: clamp(.6rem, .3rem + 1vw, 1.1rem); width: max-content; padding-inline: var(--gutter); }
/* Tuiles en portrait 4:5 : les photos client fournies sont verticales. */
.gallery__item { width: clamp(11rem, 18vw, 16rem); aspect-ratio: 4 / 5; flex: none; border-radius: var(--r); overflow: hidden; }
.gallery__item img { width: 100%; height: 100%; object-fit: cover; display: block; }
