/* ==========================================================================
   LUMEA — Landing page
   Toutes les valeurs proviennent de tokens.css. Aucune valeur esthétique en dur.
   Fond de page UNI (--surface-page) sur toute la hauteur : aucune section
   colorée, aucun filet séparateur. La profondeur vient des halos jaunes.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. BASE
   -------------------------------------------------------------------------- */
html { overflow-x: clip; }
body {
  position: relative;      /* référence des halos de fond */
  background: var(--surface-page);
  overflow-x: clip;        /* `clip` et non `hidden` : ne casse pas position:sticky */
}
/* `hidden` doit gagner sur nos display:flex/grid/block. Sans ce garde-fou,
   une règle d'auteur banale rend visible un élément masqué en JS. */
[hidden] { display: none !important; }

.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }
h1, h2, h3, h4, p, ul, ol, figure { margin: 0; }
ul, ol { padding: 0; list-style: none; }
a { text-decoration: none; }
button { font: inherit; color: inherit; }

.wrap {
  width: 100%;
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.sec { position: relative; padding-block: var(--section-y); }
.sec--about { padding-block: var(--section-y-lg) var(--space-8); }
/* Resserrage des raccords entre sections. Sélecteurs d'ID : ils passent
   devant `.sec--cta` qui redéclare son padding.
   `max()` pose un plancher : --section-y descend à 64px sur mobile, une
   soustraction sèche y écraserait complètement les raccords. */
/* Rythme resserré à partir de « Système complet » : le haut de page respire,
   la moitié basse enchaîne. Une seule variable pilote les quatre raccords,
   avec un plancher — --section-y descend à 64px sur mobile. */
#systeme, #videos, #avis, #faq, #demo {
  --raccord: max(var(--space-10), calc(var(--section-y) - 54px));
}
#systeme { padding-top: calc(var(--raccord) + 18px); padding-bottom: var(--raccord); }
#videos  { padding-block: var(--raccord); }
#avis    { padding-block: var(--raccord); }
#demo    { padding-top: var(--raccord); padding-bottom: var(--raccord); }

#faq     { padding-block: var(--raccord); }
.sec--cta   { padding-block: var(--section-y) var(--section-y); }

.ico { width: 1em; height: 1em; flex: none; }

.skip {
  position: fixed; top: var(--space-3); left: var(--space-3);
  z-index: var(--z-toast);
  transform: translateY(-200%);
  background: var(--surface-inverted); color: var(--text-on-dark);
  padding: var(--space-3) var(--space-5);
  border-radius: var(--radius-pill);
  font-size: var(--fs-body-sm); font-weight: var(--fw-semibold);
  transition: transform var(--dur-base) var(--ease-standard);
}
.skip:focus-visible { transform: translateY(0); }

/* --------------------------------------------------------------------------
   2. DÉCOR — halos jaunes de part et d'autre, fond uni
   -------------------------------------------------------------------------- */
.page-glow {
  position: absolute; inset: 0;
  z-index: var(--z-base);
  pointer-events: none;
  overflow: hidden;
}
.glow {
  position: absolute;
  display: block;
  border-radius: 50%;
  background: var(--halo-light);
  filter: blur(6px);
}
.glow--1 { top: -22vh;   left: -34vw;  width: 64vw; height: 64vw; opacity: .60; }
.glow--2 { top: -16vh;   right: -36vw; width: 68vw; height: 68vw; opacity: .52; }
.glow--3 { top: 78vh;    left: -40vw;  width: 60vw; height: 60vw; opacity: .42; }
.glow--4 { top: 160vh;   right: -38vw; width: 62vw; height: 62vw; opacity: .40; }
.glow--5 { top: 262vh;   left: -38vw;  width: 58vw; height: 58vw; opacity: .34; }
.glow--6 { bottom: -22vh; right: -32vw; width: 66vw; height: 66vw; opacity: .46; }

/* Lueur de pied de page : une nappe qui monte du bas et s'éteint vers le
   haut. Elle vit dans la couche décorative (z-index 0), donc DERRIÈRE le
   contenu — elle éclaire le raccord avec la section supérieure au lieu de
   la voiler. Aucune arête : la fusion se fait par le dégradé lui-même. */
.glow--foot {
  left: 50%; bottom: 0;
  width: 160vw; height: 66vh;
  transform: translateX(-50%);
  border-radius: 50% 50% 0 0 / 100% 100% 0 0;
  opacity: .75;
  background:
    radial-gradient(58% 100% at 50% 100%,
      rgba(255, 233, 105, .26) 0%,
      rgba(255, 233, 105, .09) 46%,
      rgba(255, 233, 105, 0) 80%),
    linear-gradient(180deg,
      rgba(255, 243, 180, 0) 0%,
      rgba(255, 243, 180, .04) 62%,
      rgba(255, 243, 180, .11) 100%);
  filter: blur(10px);
}

main, .hdr, .ftr, .mbar { position: relative; z-index: 1; }

/* --------------------------------------------------------------------------
   3. BOUTONS
   -------------------------------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--space-2);
  border: 0; border-radius: var(--radius-pill);
  font-weight: var(--fw-semibold); letter-spacing: -0.01em;
  text-align: center; white-space: nowrap; cursor: pointer;
  transition: transform var(--dur-fast) var(--ease-standard),
              box-shadow var(--dur-fast) var(--ease-standard),
              background-color var(--dur-fast) var(--ease-standard),
              color var(--dur-fast) var(--ease-standard);
}
.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translateY(0) scale(.99); }
.btn[disabled] { opacity: .4; pointer-events: none; box-shadow: none; }

.btn--sm { height: 40px; padding-inline: var(--space-5); font-size: var(--fs-caption); }
.btn--md { height: 48px; padding-inline: var(--space-6); font-size: var(--fs-body-sm); }
.btn--lg { height: 56px; padding-inline: var(--space-8); font-size: var(--fs-body); gap: var(--space-3); }
.btn--xl { height: 64px; padding-inline: var(--space-10); font-size: var(--fs-body-lg); gap: var(--space-3); }
.btn--sm .ico { font-size: 16px; }
.btn--md .ico { font-size: 18px; }
.btn--lg .ico { font-size: 20px; }
.btn--xl .ico { font-size: 22px; }

.btn--accent { background: var(--surface-accent); color: var(--text-on-accent); box-shadow: var(--shadow-accent); }
.btn--accent:hover { background: var(--yellow-300); box-shadow: var(--shadow-lg), var(--shadow-accent); }

.btn--primary { background: var(--yellow-800); color: var(--text-on-dark); }
.btn--primary:hover { background: var(--yellow-700); box-shadow: var(--shadow-md); }

.btn--inverted { background: var(--surface-inverted); color: var(--text-on-dark); }
.btn--inverted:hover { background: var(--ink-700); box-shadow: var(--shadow-md); }

.btn--secondary { background: var(--surface-muted); color: var(--text-primary); }
.btn--secondary:hover { background: var(--ink-100); }

.btn--outline { background: transparent; color: var(--text-primary); box-shadow: inset 0 0 0 1.5px var(--border-strong); }
.btn--outline:hover { background: var(--surface-inverted); color: var(--text-on-dark); box-shadow: inset 0 0 0 1.5px var(--border-strong); }

.btn--ghost { background: transparent; color: var(--ink-600); }
.btn--ghost:hover { background: var(--surface-muted); color: var(--text-primary); }

/* Réseaux sociaux : fond plein encre au repos, jaune au survol.
   Encre sur jaune et jamais l'inverse — le blanc sur #FFE969 tombe à 1,4:1. */
.btn-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; border-radius: 50%;
  background: var(--surface-inverted);
  color: var(--text-on-dark); font-size: 18px;
  transition: background-color var(--dur-fast) var(--ease-standard),
              color var(--dur-fast) var(--ease-standard),
              box-shadow var(--dur-fast) var(--ease-standard),
              transform var(--dur-fast) var(--ease-standard);
}
.btn-icon:hover {
  background: var(--surface-accent);
  color: var(--text-on-accent);
  box-shadow: var(--shadow-accent);
  transform: translateY(-2px);
}

.nav-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 52px; height: 52px; border-radius: 50%;
  background: transparent; border: 0; cursor: pointer;
  box-shadow: inset 0 0 0 1.5px var(--border-soft);
  font-size: 20px;
  transition: background-color var(--dur-fast) var(--ease-standard),
              color var(--dur-fast) var(--ease-standard),
              transform var(--dur-fast) var(--ease-standard),
              opacity var(--dur-fast) var(--ease-standard);
}
.nav-btn:hover { background: var(--surface-inverted); color: var(--text-on-dark); transform: translateY(-2px); }
.nav-btn[disabled] { opacity: .3; pointer-events: none; }

/* Badges de store */
.stores { display: flex; flex-wrap: wrap; gap: var(--space-3); }
.store {
  display: inline-flex; align-items: center; gap: var(--space-3);
  height: 56px; padding-inline: var(--space-6);
  border-radius: var(--radius-pill);
  background: var(--surface-inverted); color: var(--text-on-dark);
  transition: transform var(--dur-fast) var(--ease-standard),
              box-shadow var(--dur-fast) var(--ease-standard);
}
.store:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); }
.store__ico { width: 24px; height: 24px; }
.store span { display: flex; flex-direction: column; line-height: 1.15; }
.store small { font-size: var(--fs-micro); color: var(--text-on-dark-muted); }
.store strong { font-size: var(--fs-body-sm); font-weight: var(--fw-bold); }

/* --------------------------------------------------------------------------
   4. CHIPS · AVATARS
   -------------------------------------------------------------------------- */
.chip {
  display: inline-flex; align-items: center; gap: var(--space-2);
  height: 34px; padding-inline: var(--space-4);
  border-radius: var(--radius-pill);
  font-size: var(--fs-caption); font-weight: var(--fw-semibold);
  letter-spacing: -0.01em;
}
.chip--outline { background: var(--surface-raised); color: var(--text-primary); box-shadow: inset 0 0 0 1px var(--border-hairline), var(--shadow-xs); }
.chip--soft    { background: var(--surface-muted); color: var(--text-primary); }
.chip--accent  { background: var(--surface-accent); color: var(--text-on-accent); }
.chip .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--green-500); }

.av {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; border-radius: 50%;
  font-size: var(--fs-caption); font-weight: var(--fw-bold);
  color: var(--text-primary); flex: none;
}
.av--y { background: var(--yellow-200); }
.av--c { background: var(--cream-200); }

/* --------------------------------------------------------------------------
   5. HEADER
   -------------------------------------------------------------------------- */
.hdr {
  position: sticky; top: 0;
  z-index: var(--z-header);
  height: var(--header-h);
  display: flex; align-items: center;
  transition: background-color var(--dur-base) var(--ease-standard),
              box-shadow var(--dur-base) var(--ease-standard),
              backdrop-filter var(--dur-base) var(--ease-standard);
}
.hdr.is-stuck {
  background: rgba(253, 251, 240, .85);
  -webkit-backdrop-filter: var(--backdrop-blur);
  backdrop-filter: var(--backdrop-blur);
  box-shadow: 0 1px 0 var(--border-hairline), var(--shadow-sm);
}
/* Grille 1fr / auto / 1fr : la navigation est centrée sur le header, pas
   sur l'espace laissé libre entre logo et boutons. Avec `space-between`
   elle se décalait dès que la largeur du logo ou des CTA changeait. */
.hdr__in {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: var(--space-6);
}
.hdr__nav { justify-self: center; }
.hdr__act { justify-self: end; }

.logo { display: inline-flex; align-items: center; gap: var(--space-2); color: var(--text-primary); }
/* mot-symbole du header — hauteur 28px imposée par le §13.1, largeur libre.
   `max-width: none` annule la règle globale `img { max-width: 100% }` de
   tokens.css : dans une colonne de grille étroite, elle comprimait la
   largeur alors que la hauteur restait fixe, donc déformait le logo. */
.logo__img { height: 28px; width: auto; max-width: none; }
/* monogramme du footer — l'image porte déjà son aplat jaune.
   `alt=""` sur l'image : c'est le mot à côté qui porte le nom, sans quoi
   un lecteur d'écran annoncerait « Lumea » deux fois. */
.logo__badge { width: 56px; height: 56px; border-radius: var(--radius-md); }
.logo__word {
  font-size: var(--fs-h3); font-weight: var(--fw-extra);
  letter-spacing: var(--ls-heading);
  color: var(--text-primary);
}

.hdr__nav { display: flex; align-items: center; gap: var(--space-8); }
.hdr__nav a {
  position: relative;
  font-size: var(--fs-body-sm); font-weight: var(--fw-medium);
  color: var(--ink-600);
  transition: color var(--dur-fast) var(--ease-standard);
}
.hdr__nav a::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -6px; height: 2px;
  background: var(--yellow-500); border-radius: var(--radius-pill);
  transform: scaleX(0); transform-origin: left;
  transition: transform var(--dur-base) var(--ease-standard);
}
.hdr__nav a:hover,
.hdr__nav a[aria-current="page"] { color: var(--text-primary); }
.hdr__nav a:hover::after,
.hdr__nav a[aria-current="page"]::after { transform: scaleX(1); }

.hdr__act {
  display: flex; align-items: center;
  gap: calc(var(--space-2) + 10px);     /* 18px */
}
/* hauteur 36px (+3px de padding vertical de chaque côté),
   dont 4px de rembourrage haut pour redescendre le libellé */
.hdr__act .btn { height: 36px; padding-top: 4px; }
/* « Demander une démo » : padding vertical de 15px. `height: auto` est
   indispensable — avec box-sizing: border-box, une hauteur fixe absorberait
   le rembourrage au lieu de s'y ajouter. */
.hdr__act .btn--accent { height: auto; padding-block: 15px; }

.burger {
  display: none;
  width: 44px; height: 44px; border: 0; background: transparent; cursor: pointer;
  flex-direction: column; align-items: center; justify-content: center; gap: 6px;
}
.burger span {
  display: block; width: 20px; height: 2px; border-radius: 2px;
  background: var(--text-primary);
  transition: transform var(--dur-base) var(--ease-standard),
              opacity var(--dur-base) var(--ease-standard);
}
.burger[aria-expanded="true"] span:first-child { transform: translateY(4px) rotate(45deg); }
.burger[aria-expanded="true"] span:last-child  { transform: translateY(-4px) rotate(-45deg); }

/* Le panneau couvre TOUT l'écran, à partir de 0 — il démarrait sous le
   header et laissait voir une bande de page.
   Son z-index passe SOUS celui du header : sans ça, il recouvrait le burger
   et le menu devenait impossible à refermer. Le header restant transparent
   tant qu'on n'a pas défilé, le fond crème du panneau se voit au travers. */
.menu {
  position: fixed; inset: 0;
  z-index: calc(var(--z-header) - 1);
  background: var(--surface-page);
  overflow-y: auto;
  overscroll-behavior: contain;
  opacity: 0; transform: translateY(-8px);
  transition: opacity var(--dur-base) var(--ease-standard),
              transform var(--dur-base) var(--ease-standard);
}
.menu.is-open { opacity: 1; transform: none; }
.menu__in {
  display: flex; flex-direction: column; gap: var(--space-2);
  /* la hauteur du header est réservée en haut pour que le premier lien ne
     passe pas derrière le logo */
  padding: calc(var(--header-h) + var(--space-6)) var(--gutter) var(--space-10);
}
.menu__in a {
  font-size: 14px; font-weight: var(--fw-bold);
  letter-spacing: var(--ls-snug);
  padding-block: var(--space-2);
}
.menu__cta {
  align-self: flex-start;          /* ne prend plus toute la largeur */
  margin-top: var(--space-6);
  height: 44px;
  padding-inline: var(--space-6);
  font-size: 12px;
}

/* --------------------------------------------------------------------------
   6. HERO
   -------------------------------------------------------------------------- */
.hero { position: relative; padding-block: var(--space-12) var(--space-8); }
/* z-index explicite : sans lui, .hero__stage (positionné) se peint après
   .hero__head (bloc en flux) et son halo — qui déborde vers le haut —
   passe par-dessus le titre, le chapô et les boutons. */
.hero__head {
  position: relative; z-index: 2;
  text-align: center; max-width: 1060px; margin-inline: auto;
}
.hero__chip { margin-bottom: var(--space-6); }

.hero__title {
  /* Calibré pour tenir sur 2 lignes : la 1re ligne du H1 fait 38 signes,
     elle ne passe pas au-delà de ~56px dans une zone de 1060px. */
  /* −3px sur toute la plage fluide : 30→56 devient 27→53 */
  font-size: clamp(1.6875rem, 0.9125rem + 3.4vw, 3.3125rem);
  font-weight: var(--fw-extra);
  line-height: 1.12;   /* entre --lh-tight (1.04) et --lh-heading (1.16) */
  letter-spacing: var(--ls-display);
  /* pas de `text-wrap: balance` : il rééquilibre les lignes en coupant plus
     tôt que nécessaire, alors que les <br> du titre fixent déjà les
     coupures. C'est lui qui ajoutait une 3e ligne. */
  text-wrap: pretty;
}
.mark {
  position: relative; font-style: normal; white-space: nowrap;
  z-index: 0;
}
.mark::before {
  content: ""; position: absolute; z-index: -1;
  left: -.12em; right: -.12em; bottom: .02em; height: .42em;
  background: var(--surface-accent);
  border-radius: var(--radius-pill);
}

.hero__lead {
  margin: var(--space-8) auto 0;   /* titre → chapô : 20 → 32px */
  max-width: var(--measure-lead);
  font-size: var(--fs-lead);
  color: var(--text-secondary);
  line-height: var(--lh-snug);
}

.hero__cta {
  margin-top: var(--space-12);     /* chapô → boutons : 32 → 48px */
  display: flex; flex-wrap: wrap; gap: 25px; justify-content: center;
}
/* padding vertical : −7px, +3px, +2px de chaque côté → 64px → 60px */
.hero__cta .btn { height: 60px; }

/* --- Scène du hero --- */
.hero__stage {
  position: relative; z-index: 1;
  margin-top: calc(var(--space-10) + 35px);   /* 40 + 35 = 75px sous les CTA */
  min-height: 420px;
  display: flex; align-items: flex-end; justify-content: center;
}

.hero__halo {
  position: absolute; inset: auto auto 0 50%;
  transform: translateX(-50%);
  width: min(760px, 118%); aspect-ratio: 1;
  background: var(--halo-light);
  border-radius: 50%;
  pointer-events: none;
}

/* --- Chorégraphie de la scène ------------------------------------------
   Tout est en transition (et non en @keyframes) pour être rejouable :
   .hero__stage reçoit .is-in à chaque entrée dans le viewport et la perd
   dès qu'elle en sort complètement. Voir §16.
   ----------------------------------------------------------------------- */
.hero__phone {
  position: relative;
  width: min(560px, 80vw);
  height: auto;
  filter: drop-shadow(0 40px 80px rgba(18, 18, 18, .18));
  opacity: 0; transform: translateY(20px) scale(.985);
  transition: opacity var(--dur-reveal) var(--ease-standard),
              transform var(--dur-reveal) var(--ease-standard);
  transition-delay: 80ms;
}
.hero__stage.is-in .hero__phone { opacity: 1; transform: none; }

.hero__lines {
  position: absolute; top: 0; left: calc(var(--gutter) * -1);
  width: calc(100% + var(--gutter) * 2); height: 100%;
  pointer-events: none;
}
.hero__lines .ln {
  fill: none;
  stroke: var(--border-soft);
  stroke-width: 1;
  stroke-dasharray: 4 7;
  stroke-dashoffset: 240;
  opacity: 0;
  transition: opacity var(--dur-slow) var(--ease-standard),
              stroke-dashoffset 900ms var(--ease-standard);
  transition-delay: 220ms;
}
.hero__stage.is-in .hero__lines .ln { opacity: 1; stroke-dashoffset: 0; }

.brk {
  position: absolute; width: 26px; height: 26px;
  border: 1.5px solid var(--border-soft);
  opacity: 0; transform: scale(.72);
  transition: opacity var(--dur-slow) var(--ease-standard),
              transform var(--dur-slow) var(--ease-standard);
  transition-delay: 480ms;
}
.hero__stage.is-in .brk { opacity: 1; transform: none; }
.brk--tl { top: 0; left: 0;  border-right: 0; border-bottom: 0; border-top-left-radius: var(--radius-xs); transform-origin: top left; }
.brk--tr { top: 0; right: 0; border-left: 0;  border-bottom: 0; border-top-right-radius: var(--radius-xs); transform-origin: top right; }
.brk--bl { bottom: 0; left: 0;  border-right: 0; border-top: 0; border-bottom-left-radius: var(--radius-xs); transform-origin: bottom left; }
.brk--br { bottom: 0; right: 0; border-left: 0;  border-top: 0; border-bottom-right-radius: var(--radius-xs); transform-origin: bottom right; }

/* --- Cartes de notification -------------------------------------------
   Quatre cartes serrées autour du mockup. Elles apparaissent une à une :
   même transition, délais échelonnés de 170ms. Comme tout part de
   .hero__stage.is-in, la séquence se rejoue à chaque passage au scroll.
   ----------------------------------------------------------------------- */
.float {
  position: absolute;
  width: 320px; max-width: 88%;
  display: flex; align-items: flex-start; gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  background: var(--surface-raised);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg), inset 0 0 0 1px var(--border-hairline);
  opacity: 0;
  /* entrée volontairement plus lente que le --dur-reveal général (620ms) :
     les quatre cartes se posent l'une après l'autre, sans précipitation. */
  transition: opacity 900ms var(--ease-standard),
              transform 900ms var(--ease-standard);
}
.hero__stage.is-in .float { opacity: 1; transform: none; }

/* elles entrent depuis leur propre côté */
.float--n1, .float--n2 { transform: translate(-16px, 14px); }
.float--n3, .float--n4 { transform: translate(16px, 14px); }

/* les cartes de gauche sont décalées vers l'intérieur : dans l'image, le
   téléphone est à gauche et la main déborde à droite — sans ce décalage
   l'écart au mockup serait deux fois plus grand à gauche qu'à droite. */
/* n1 « Nouvelle note » en haut, n2 « Bulletin » en bas. L'ordre d'entrée
   ne bouge pas : la carte signature reste la première à se poser. */
.float--n1 { left: 6%;  top: 6%;     transition-delay: 300ms; }
.float--n2 { left: 5%;  bottom: 10%; transition-delay: 540ms; }
.float--n3 { right: 0;  bottom: 16%; transition-delay: 780ms; }
.float--n4 { right: 1%; top: 2%;     transition-delay: 1020ms; }

/* Flottement continu, une fois les cartes posées.
   Il anime `translate`, propriété distincte de `transform` : il se compose
   avec la transition d'entrée au lieu de l'écraser.
   Durées volontairement inégales et délais négatifs — les quatre cartes
   démarrent déjà déphasées et ne se resynchronisent jamais, ce qui évite
   l'effet mécanique d'un mouvement à l'unisson. */
/* Une carte visible ~1,9s sur les 8s du cycle, avec fondu de part et d'autre. */
/* Entrée et sortie portées à 5% du cycle, soit 0,8s chacune : à 2% (0,32s)
   le glissement passait presque inaperçu, la carte semblait apparaître sur
   place. Les courbes sont posées par palier — décélération à l'entrée,
   accélération à la sortie. */
@keyframes notif-defile {
  0%   { opacity: 0; transform: translateX(64px);
         animation-timing-function: cubic-bezier(.2, .8, .2, 1); }
  5%   { opacity: 1; transform: none; }
  20%  { opacity: 1; transform: none;
         animation-timing-function: cubic-bezier(.4, 0, 1, 1); }
  25%  { opacity: 0; transform: translateX(-64px); }
  100% { opacity: 0; transform: translateX(64px); }
}

@keyframes float-soft {
  0%, 100% { translate: 0 0; }
  50%      { translate: 0 -7px; }
}
.float { animation: float-soft 6s var(--ease-standard) infinite; }
.float--n1 { animation-duration: 6.4s; animation-delay: -0.6s; }
.float--n2 { animation-duration: 7.2s; animation-delay: -2.4s; }
.float--n3 { animation-duration: 6.8s; animation-delay: -4.1s; }
.float--n4 { animation-duration: 7.6s; animation-delay: -5.3s; }

.notif__dot {
  display: grid; place-items: center;
  width: 40px; height: 40px; border-radius: var(--radius-md);
  background: var(--surface-accent); color: var(--text-on-accent);
  font-size: 18px; flex: none;
}
.notif__dot--soft { background: var(--surface-accent-soft); color: var(--yellow-800); }
.notif__body { flex: 1; min-width: 0; }
.notif__t { font-size: var(--fs-body-sm); font-weight: var(--fw-bold); line-height: 1.3; }
.notif__s {
  margin-top: 2px;
  font-size: var(--fs-caption); color: var(--text-secondary); line-height: 1.4;
}
.notif__s strong { color: var(--text-primary); font-variant-numeric: tabular-nums; }
.notif__time { font-size: var(--fs-micro); color: var(--text-tertiary); flex: none; }

/* --------------------------------------------------------------------------
   7. À PROPOS
   -------------------------------------------------------------------------- */
.about {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
  gap: var(--grid-gap) var(--space-16);
  align-items: start;
}
.about__text {
  font-size: calc(var(--fs-body-sm) + 2px);   /* 15 → 17px */
  color: var(--text-secondary);
  line-height: var(--lh-loose);
  max-width: 42ch;
  padding-top: var(--space-3);
}
.about__right { display: flex; align-items: flex-start; gap: var(--space-6); }
.about__badge {
  display: grid; place-items: center; flex: none;
  width: 48px; height: 48px; border-radius: 50%;
  background: var(--surface-inverted); color: var(--text-on-dark);
  font-size: 20px;
  margin-top: .35em;
  animation: nudge 2.6s var(--ease-standard) infinite;
}
@keyframes nudge {
  0%, 70%, 100% { translate: 0 0; }
  80%           { translate: 0 5px; }
}
.about__title {
  font-size: var(--fs-h1);
  font-weight: var(--fw-bold);
  line-height: var(--lh-heading);
  letter-spacing: var(--ls-heading);
  text-wrap: balance;
}

/* --------------------------------------------------------------------------
   8. TÊTES DE SECTION
   -------------------------------------------------------------------------- */
.sec__head {
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
  gap: var(--grid-gap) var(--space-16);
  align-items: end;
  margin-bottom: var(--space-16);
}
.sec__head--center {
  grid-template-columns: 1fr;
  justify-items: center; text-align: center;
  gap: var(--stack-heading);
}
.sec__title {
  font-size: var(--fs-h2);
  font-weight: var(--fw-bold);
  line-height: var(--lh-heading);
  letter-spacing: var(--ls-heading);
  text-wrap: balance;
}
.sec__intro {
  font-size: calc(var(--fs-body-sm) + 2px);   /* 15 → 17px */
  color: var(--text-secondary);
  line-height: var(--lh-loose);
  max-width: 46ch;
}

/* --------------------------------------------------------------------------
   9. FONCTIONNALITÉS
   -------------------------------------------------------------------------- */
.feats {
  display: grid;
  position: relative;
  /* colonne centrale resserrée : le nouveau mockup fait un ratio 0,51,
     il gagne en hauteur ce qu'il perd en largeur.
     L'écart de 64px ouvre le couloir dans lequel courent les connecteurs. */
  /* minmax(0, …) et non minmax(230px, …) : un plancher en pixels rompt le
     rapport de colonnes sur les écrans étroits, et les connecteurs — tracés
     en coordonnées normalisées — cesseraient de tomber sur les bords. */
  grid-template-columns: minmax(0, 1fr) minmax(0, .85fr) minmax(0, 1fr);
  gap: var(--space-16);
  align-items: center;
}

/* Connecteurs pointillés en Z, carte → mockup.
   `vector-effect: non-scaling-stroke` est indispensable : sans lui, l'étirement
   non uniforme de la viewBox déformerait l'épaisseur et le pas des pointillés. */
.feats__links {
  position: absolute; inset: 0; z-index: 0;
  width: 100%; height: 100%;
  pointer-events: none;
  overflow: visible;
}
.feats__links path {
  fill: none;
  /* le gris hairline disparaissait sur le crème : on passe au jaune 600,
     lisible sur --surface-page tout en restant un filet. */
  stroke: var(--yellow-600);
  stroke-width: 1.5;
  stroke-dasharray: 5 5;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
  opacity: 0;
  stroke-dashoffset: 180;
  transition: opacity var(--dur-slow) var(--ease-standard),
              stroke-dashoffset 1s var(--ease-standard);
  transition-delay: 320ms;
}
.feats.is-in .feats__links path { opacity: 1; stroke-dashoffset: 0; }
.feats__col { display: flex; flex-direction: column; gap: var(--space-10); }
.feats__col--l .fcard:first-child { margin-left: var(--space-10); }
.feats__col--r .fcard:last-child  { margin-right: var(--space-10); }

.fcard {
  position: relative; z-index: 1;
  background: var(--surface-raised);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
  padding-left: calc(var(--space-5) + 3px);
  box-shadow: inset 0 0 0 1px var(--border-hairline), var(--shadow-sm);
  transition: transform var(--dur-base) var(--ease-standard),
              box-shadow var(--dur-base) var(--ease-standard);
}
.fcard:hover {
  transform: translateY(-3px);
  box-shadow: inset 0 0 0 1px var(--border-hairline), var(--shadow-md);
}
/* Pastille d'amorce du connecteur, sur le bord intérieur de la carte.
   En CSS et non en <circle> : sous l'étirement non uniforme de la viewBox,
   un cercle SVG deviendrait une ellipse. */
.fcard::after {
  content: "";
  position: absolute; top: 50%;
  width: 9px; height: 9px; margin-top: -4.5px;
  border-radius: 50%;
  background: var(--surface-accent);
  box-shadow: 0 0 0 3px var(--surface-page), inset 0 0 0 1.5px var(--yellow-600);
}
.feats__col--l .fcard::after { right: -4.5px; }
.feats__col--r .fcard::after { left: -4.5px; }

.fcard__n {
  position: absolute; top: var(--space-5); right: var(--space-5);
  font-size: var(--fs-caption); font-weight: var(--fw-bold);
  color: var(--text-tertiary);
  font-variant-numeric: tabular-nums;
}
.fcard__ico {
  display: grid; place-items: center;
  width: 40px; height: 40px; border-radius: var(--radius-sm);
  background: var(--surface-accent-soft); color: var(--yellow-800);
  font-size: 20px;
  margin-bottom: var(--space-4);
  transition: background-color var(--dur-base) var(--ease-standard);
}
.fcard:hover .fcard__ico { background: var(--surface-accent); }
.fcard__t {
  font-size: calc(var(--fs-h4) - 4px); font-weight: var(--fw-bold);
  line-height: var(--lh-heading); letter-spacing: var(--ls-snug);
  margin-bottom: var(--space-2);
  padding-right: var(--space-8);
}
.fcard__p { font-size: var(--fs-body-sm); color: var(--text-secondary); line-height: var(--lh-body); }

/* même règle : le halo du téléphone déborde de 10 % de chaque côté et
   mordait sur les cartes de la colonne de gauche uniquement. */
.feats__mid { position: relative; z-index: 0; display: grid; place-items: center; }
.feats__halo {
  position: absolute; inset: auto auto 8% 50%;
  transform: translateX(-50%);
  width: 190%; aspect-ratio: 1;
  background: var(--halo-light);
  border-radius: 50%;
  pointer-events: none;
}
.feats__phone {
  position: relative;
  width: 100%; height: auto;
  filter: drop-shadow(0 30px 60px rgba(18, 18, 18, .16));
}

.feats__foot {
  margin-top: var(--space-16);
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: var(--space-6);
  text-align: center;
}
.feats__foot p {
  font-size: var(--fs-body-lg); font-weight: var(--fw-medium);
  color: var(--text-secondary); max-width: 44ch;
}

/* --------------------------------------------------------------------------
   10. LECTEUR VIDÉO
   -------------------------------------------------------------------------- */
/* Liste à gauche (30 %), lecteur à droite (70 %).
   minmax(0, …) sur les deux colonnes : sans cela une piste `auto` se
   dimensionne sur son max-content et déborde du conteneur. */
.player {
  display: grid;
  grid-template-columns: minmax(0, 28fr) minmax(0, 72fr);
  gap: var(--space-10);
  align-items: stretch;
}

.player__stage {
  position: relative;
  grid-column: 2; grid-row: 1;
  /* `start` et non `stretch` : avec 4 cartes la colonne de gauche devient
     plus haute que le lecteur, et sans ça le lecteur s'étirerait en perdant
     son 16/9. La colonne, elle, continue de s'étirer quand elle est plus courte. */
  align-self: start;
  aspect-ratio: 16 / 9;
  border-radius: var(--radius-2xl);
  overflow: hidden;
  background: var(--surface-muted);
  box-shadow: inset 0 0 0 1px var(--border-hairline), var(--shadow-lg);
}
/* Empilement du lecteur, du fond vers l'avant :
   1 <video> · 2 iframe YouTube · 3 affiche.
   À z-index égal c'est l'ordre du DOM qui tranche, et le <video> (fond
   encre opaque) vient après l'iframe : sans ces valeurs explicites il
   masque complètement la vidéo YouTube. */
.player__poster {
  position: absolute; inset: 0; z-index: 3;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--space-6);
  text-align: center;
  padding: var(--gutter);
  background: var(--cream-100);
  transition: opacity var(--dur-slow) var(--ease-standard),
              visibility var(--dur-slow) var(--ease-standard);
}
.player__meta {
  position: relative; z-index: 2;
  display: flex; flex-direction: column; align-items: center; gap: var(--space-2);
}
.player.is-playing .player__poster { opacity: 0; visibility: hidden; }
.player__halo {
  position: absolute; inset: -20% auto auto 50%;
  transform: translateX(-50%);
  width: 90%; aspect-ratio: 1;
  background: var(--halo-light);
  border-radius: 50%;
  pointer-events: none;
}
/* Affiche de la vidéo. Avec image : voile encre pour garder un contraste
   AA sur le texte quelle que soit la photo, et halo masqué (inutile). */
/* Affichage piloté par la classe, pas par l'attribut `hidden` : la règle
   globale `img { display: block }` de tokens.css est une règle d'auteur,
   elle bat le `display:none` que le navigateur applique à `hidden`. Sans
   ça, la miniature YouTube resterait visible derrière une vidéo MP4. */
.player__img {
  display: none;
  position: absolute; inset: 0; z-index: 0;
  width: 100%; height: 100%; object-fit: cover;
}
.player__poster.has-img .player__img { display: block; }
.player__poster.has-img { background: var(--ink-900); }
.player__poster.has-img::after {
  content: ""; position: absolute; inset: 0; z-index: 1;
  background: linear-gradient(180deg,
              rgba(18, 18, 18, .12) 0%,
              rgba(18, 18, 18, .28) 48%,
              rgba(18, 18, 18, .88) 100%);
}
.player__poster.has-img .player__halo { display: none; }
/* le texte descend en bas, sur la partie dense du dégradé : contraste
   garanti quelle que soit la photo, et l'image reste lisible au-dessus. */
.player__poster.has-img .player__meta {
  position: absolute; z-index: 2;
  left: var(--space-8); right: var(--space-8); bottom: var(--space-8);
  align-items: flex-start; text-align: left;
}
.player__poster.has-img .player__label { color: var(--text-on-dark); }
.player__poster.has-img .player__note  { color: var(--text-on-dark-muted); }

.player__embed { position: absolute; inset: 0; z-index: 2; }
.player__embed iframe { display: block; width: 100%; height: 100%; border: 0; }

.player__label {
  position: relative; z-index: 2;
  font-size: var(--fs-h3); font-weight: var(--fw-bold);
  letter-spacing: var(--ls-heading);
  text-wrap: balance;
}
.player__play {
  position: relative; z-index: 2;
  display: grid; place-items: center;
  width: 84px; height: 84px; border-radius: 50%; border: 0;
  background: var(--surface-accent); color: var(--text-on-accent);
  font-size: 34px; cursor: pointer;
  box-shadow: var(--shadow-accent);
  transition: transform var(--dur-base) var(--ease-standard),
              box-shadow var(--dur-base) var(--ease-standard);
}
.player__play:hover { transform: scale(1.06); box-shadow: var(--shadow-lg), var(--shadow-accent); }
.player__play::after {
  content: ""; position: absolute; inset: -10px;
  border-radius: 50%; border: 1.5px solid var(--yellow-500);
  opacity: .5;
}
.player__note { position: relative; z-index: 2; font-size: var(--fs-body-sm); color: var(--text-secondary); }
.player__video {
  position: absolute; inset: 0; z-index: 1;
  width: 100%; height: 100%; object-fit: cover;
  background: var(--ink-900);
  opacity: 0;
  transition: opacity var(--dur-slow) var(--ease-standard);
}
.player.is-playing .player__video { opacity: 1; }
/* source YouTube : le <video> n'a rien à afficher, on le sort du rendu */
.player.is-yt .player__video { display: none; }

/* --- Liste des autres vidéos ------------------------------------------- */
.player__side {
  grid-column: 1; grid-row: 1;
  display: flex; flex-direction: column;
  /* liste calée en haut du lecteur, bouton calé en bas : le bouton descend
     au lieu de rester collé sous la 3e carte. */
  justify-content: space-between;
  gap: var(--space-5);
  min-width: 0;
}
.vlist {
  display: grid;
  grid-auto-rows: max-content;   /* blocs à la hauteur de leur contenu */
  gap: var(--space-4);
  min-width: 0;
}
.vlist > li { min-width: 0; }

.vlist__more { align-self: flex-start; }
.vlist__more .ico {
  transition: transform var(--dur-base) var(--ease-standard);
}
.vlist__more:hover .ico { transform: translateX(3px); }

.vitem {
  width: 100%;
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center; gap: var(--space-4);
  text-align: left; cursor: pointer; border: 0;
  padding: var(--space-4) var(--space-5);
  border-radius: var(--radius-lg);
  background: var(--surface-raised);
  box-shadow: inset 0 0 0 1px var(--border-hairline);
  transition: transform var(--dur-base) var(--ease-standard),
              box-shadow var(--dur-base) var(--ease-standard),
              background-color var(--dur-base) var(--ease-standard);
}

/* pastille d'icône : jaune clair au repos, jaune plein sur le bloc actif */
.vitem__ico {
  display: grid; place-items: center;
  width: 40px; height: 40px; border-radius: var(--radius-sm);
  background: var(--surface-accent-soft); color: var(--yellow-800);
  font-size: 22px;
  transition: background-color var(--dur-base) var(--ease-standard),
              transform var(--dur-base) var(--ease-standard);
}

/* chevron de lecture, révélé sur le bloc actif */
.vitem__go {
  display: grid; place-items: center;
  width: 32px; height: 32px; border-radius: 50%;
  background: var(--surface-accent); color: var(--text-on-accent);
  font-size: 14px;
  opacity: 0; transform: translateX(-6px);
  transition: opacity var(--dur-base) var(--ease-standard),
              transform var(--dur-base) var(--ease-standard);
}

/* --- Vidéo en cours : même apparence que le survol, filet jaune 1px --- */
.is-current .vitem {
  transform: translateY(-3px);
  background: var(--yellow-50);
  box-shadow: inset 0 0 0 1px var(--surface-accent), var(--shadow-md);
}
.is-current .vitem__ico { background: var(--surface-accent); transform: scale(1.06); }
.is-current .vitem__go  { opacity: 1; transform: none; }

/* --- Survol / focus : identique, filet jaune 1px lui aussi --- */
.vitem:hover,
.vitem:focus-visible {
  transform: translateY(-3px);
  background: var(--yellow-50);
  box-shadow: inset 0 0 0 1px var(--surface-accent), var(--shadow-md);
}
/* au clavier on ajoute l'anneau de focus : #FFE969 sur blanc ne contraste
   qu'à 1,4:1, il ne peut pas servir seul d'indicateur de focus (§16.2). */
.vitem:focus-visible {
  box-shadow: inset 0 0 0 1px var(--surface-accent), var(--shadow-md), var(--focus-ring);
}
.vitem:hover .vitem__ico,
.vitem:focus-visible .vitem__ico { background: var(--surface-accent); transform: scale(1.06); }
.vitem:hover .vitem__go,
.vitem:focus-visible .vitem__go { opacity: 1; transform: none; }

.vitem__txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.vitem__txt strong {
  font-size: var(--fs-body-sm); font-weight: var(--fw-semibold);
  line-height: 1.3; letter-spacing: var(--ls-snug);
}
.vitem__txt small { font-size: var(--fs-micro); color: var(--text-secondary); }

/* --------------------------------------------------------------------------
   11. AVIS
   -------------------------------------------------------------------------- */
.avis {
  display: grid;
  grid-template-columns: minmax(0, .78fr) minmax(0, 1.6fr);
  gap: var(--space-16);
  align-items: start;
}
/* titre + flèches centrés verticalement en face des cartes */
.avis__head { align-self: center; display: flex; flex-direction: column; gap: var(--space-10); }
.avis__nav { display: flex; gap: var(--space-3); }

/* --- Bande d'avis en défilement continu ---------------------------------
   Un rail animé en translation linéaire, dupliqué en JS pour boucler sans
   raccord. Fondu aux deux bords par masque : les cartes entrent et sortent
   au lieu d'être coupées net. */
.avis__track {
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 7%, #000 93%, transparent 100%);
          mask-image: linear-gradient(90deg, transparent 0, #000 7%, #000 93%, transparent 100%);
}
.avis__rail {
  display: flex;
  width: max-content;
  animation: avis-roule var(--avis-duree, 72s) linear infinite;
}
.avis__track:hover .avis__rail,
.avis__track:focus-within .avis__rail { animation-play-state: paused; }
.avis__track.is-reverse .avis__rail { animation-direction: reverse; }

/* pas de `gap` : chaque carte porte sa propre marge, ainsi la moitié du rail
   tombe exactement sur la 9e carte et la boucle est invisible. */
@keyframes avis-roule {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

.tcard {
  flex: none;
  width: 340px;
  margin-right: var(--space-5);
  background: var(--surface-raised);
  border-radius: var(--radius-xl);
  padding: var(--space-8);
  box-shadow: inset 0 0 0 1px var(--border-hairline), var(--shadow-sm);
  display: flex; flex-direction: column; gap: var(--space-5);
  transition: transform var(--dur-base) var(--ease-standard),
              box-shadow var(--dur-base) var(--ease-standard);
}
.tcard:hover { transform: translateY(-3px); box-shadow: inset 0 0 0 1px var(--border-hairline), var(--shadow-md); }
.tcard__who { display: flex; align-items: center; gap: var(--space-3); }
.tcard__who > span:last-child { display: flex; flex-direction: column; }
.tcard__stars {
  display: flex; gap: 3px;
  color: var(--yellow-500); font-size: 17px;
  margin-top: calc(var(--space-3) * -1);
}
.tcard__who strong { font-size: var(--fs-body-sm); font-weight: var(--fw-semibold); }
.tcard__who small { font-size: var(--fs-micro); color: var(--text-secondary); }
.tcard p { font-size: var(--fs-body-sm); color: var(--text-secondary); line-height: var(--lh-body); }

/* --------------------------------------------------------------------------
   12. FAQ
   -------------------------------------------------------------------------- */
.faq {
  display: grid;
  grid-template-columns: minmax(0, .8fr) minmax(0, 1.5fr);
  gap: var(--space-16);
  align-items: start;
}
.faq__head {
  display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-5);
  position: sticky; top: calc(var(--header-h) + var(--space-8));
}
.faq__aside { font-size: var(--fs-body-sm); color: var(--text-secondary); line-height: var(--lh-body); max-width: 34ch; }
.faq__list { display: flex; flex-direction: column; gap: var(--space-3); }

.qa {
  background: var(--surface-muted);
  border-radius: var(--radius-lg);
  overflow: hidden;
  transition: background-color var(--dur-base) var(--ease-standard),
              box-shadow var(--dur-base) var(--ease-standard);
}
.qa[open] {
  background: var(--surface-raised);
  box-shadow: inset 0 0 0 1px var(--border-hairline), var(--shadow-sm);
}
.qa summary {
  list-style: none; cursor: pointer;
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-5);
  padding: var(--space-5) var(--space-6);
  font-size: var(--fs-body-lg); font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-snug);
  min-height: 44px;
}
.qa summary::-webkit-details-marker { display: none; }
.qa summary i {
  display: grid; place-items: center; flex: none;
  width: 32px; height: 32px; border-radius: 50%;
  background: var(--surface-raised); color: var(--text-primary);
  font-size: 16px;
  box-shadow: inset 0 0 0 1px var(--border-hairline);
  transition: transform var(--dur-base) var(--ease-standard),
              background-color var(--dur-base) var(--ease-standard),
              color var(--dur-base) var(--ease-standard);
}
.qa[open] summary i {
  transform: rotate(135deg);
  background: var(--surface-accent); color: var(--text-on-accent);
  box-shadow: none;
}
.qa__c {
  padding: 0 var(--space-6) var(--space-6);
  font-size: var(--fs-body); color: var(--text-secondary); line-height: var(--lh-body);
  max-width: var(--measure-body);
}

/* --------------------------------------------------------------------------
   13. CTA FINAL
   -------------------------------------------------------------------------- */
.cta {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr);
  gap: var(--space-10);
  align-items: center;
  background: var(--surface-raised);
  border-radius: var(--radius-3xl);
  padding: var(--space-12) var(--space-16);
  box-shadow: inset 0 0 0 1px var(--border-hairline), var(--shadow-lg);
  overflow: hidden;
}
.cta__halo {
  position: absolute; inset: -30% -20% auto auto;
  width: 620px; aspect-ratio: 1;
  background: var(--halo-light);
  border-radius: 50%;
  pointer-events: none;
}
.cta__l { position: relative; display: flex; flex-direction: column; align-items: flex-start; gap: calc(var(--space-5) + 3px); }
.cta__t {
  font-size: var(--fs-h2); font-weight: var(--fw-extra);
  line-height: var(--lh-heading); letter-spacing: var(--ls-heading);
}
.cta__p { font-size: var(--fs-lead); color: var(--text-secondary); max-width: var(--measure-lead); line-height: var(--lh-snug); }
/* les deux actions tiennent sur une ligne : `nowrap` + libellés courts.
   C'est le principal gain de hauteur sur la carte. */
.cta__btns { display: flex; flex-wrap: nowrap; gap: var(--space-3); margin-top: var(--space-1); }
.cta__mail {
  display: flex; align-items: center; gap: var(--space-2);
  font-size: var(--fs-body-sm); color: var(--text-secondary);
}
.cta__mail .ico { font-size: 18px; color: var(--yellow-700); }
.cta__mail a { text-decoration: underline; text-underline-offset: 3px; color: var(--text-primary); }
.cta__mail a:hover { color: var(--text-brand); }

.cta__stores { margin-top: var(--space-2); display: flex; flex-direction: column; gap: var(--space-3); }
.cta__stores-txt { font-size: var(--fs-body-sm); color: var(--text-secondary); max-width: 40ch; }

/* L'image affleure les bords droit et bas de la carte : on annule le
   rembourrage du conteneur par des marges négatives. `overflow: hidden`
   sur .cta se charge du rognage sur l'angle arrondi. */
.cta__r {
  position: relative;
  align-self: stretch;
  display: flex; align-items: flex-end; justify-content: flex-end;
  margin-right: calc(var(--space-16) * -1);
  margin-bottom: calc(var(--space-12) * -1);
}
.cta__phone {
  width: min(460px, 100%); height: auto; display: block;
  filter: drop-shadow(0 30px 60px rgba(18, 18, 18, .16));
}

/* --------------------------------------------------------------------------
   14. FOOTER
   -------------------------------------------------------------------------- */
/* raccord resserré avec la carte CTA qui la précède */
.ftr { padding-block: var(--space-12) var(--space-10); }
.ftr__top {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  gap: var(--space-10) var(--space-16);
  align-items: center;
}
.ftr__brand { display: flex; flex-direction: column; gap: var(--space-3); }
.ftr__base { font-size: var(--fs-body-sm); color: var(--text-secondary); max-width: 34ch; }
.ftr__contact {
  margin-top: var(--space-4);
  display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-3);
  font-size: var(--fs-body-sm); font-weight: var(--fw-medium);
}
.ftr__contact a {
  display: inline-flex; align-items: center; gap: var(--space-3);
  transition: color var(--dur-fast) var(--ease-standard);
}
.ftr__contact a:hover { color: var(--text-brand); }
/* pastille à dégradé jaune — dégradé d'une seule teinte, la charte
   n'interdit que les dégradés multicolores (§2, interdit n°2). */
.ftr__ico {
  display: grid; place-items: center; flex: none;
  width: 38px; height: 38px; border-radius: var(--radius-md);
  background: linear-gradient(135deg, var(--yellow-200) 0%, var(--yellow-400) 100%);
  color: var(--yellow-800); font-size: 18px;
  box-shadow: var(--shadow-xs);
  transition: transform var(--dur-base) var(--ease-standard),
              box-shadow var(--dur-base) var(--ease-standard);
}
.ftr__contact a:hover .ftr__ico { transform: translateY(-2px); box-shadow: var(--shadow-accent); }
.ftr__nav { display: flex; flex-wrap: wrap; gap: var(--space-3) var(--space-8); }
.ftr__nav a {
  font-size: var(--fs-body-sm); font-weight: var(--fw-medium); color: var(--ink-600);
  transition: color var(--dur-fast) var(--ease-standard);
}
.ftr__nav a:hover { color: var(--text-primary); }
.ftr__social { display: flex; gap: var(--space-2); }

.ftr__bot {
  margin-top: var(--space-12);
  padding-top: var(--space-6);
  border-top: 1px solid var(--border-hairline);
  display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--space-3);
  font-size: var(--fs-caption); color: var(--text-secondary);
}
.ftr__legal { display: flex; gap: var(--space-6); }
.ftr__legal a { transition: color var(--dur-fast) var(--ease-standard); }
.ftr__legal a:hover { color: var(--text-primary); }

/* --------------------------------------------------------------------------
   15. BARRE MOBILE
   -------------------------------------------------------------------------- */
.mbar {
  position: fixed; inset: auto 0 0;
  z-index: var(--z-sticky);
  display: none; gap: var(--space-3);
  padding: var(--space-3) var(--gutter);
  padding-bottom: calc(var(--space-3) + env(safe-area-inset-bottom));
  background: rgba(253, 251, 240, .94);
  -webkit-backdrop-filter: var(--backdrop-blur);
  backdrop-filter: var(--backdrop-blur);
  box-shadow: 0 -1px 0 var(--border-hairline);
  transform: translateY(110%);
  transition: transform var(--dur-base) var(--ease-standard);
}
.mbar.is-on { transform: none; }
.mbar .btn { flex: 1; }
/* WhatsApp en fond noir plutôt qu'en olive : les deux boutons de la barre
   se distinguent alors franchement, jaune contre encre. */
.mbar .btn--primary { background: var(--surface-inverted); color: var(--text-on-dark); }
.mbar .btn--primary:hover { background: var(--ink-700); }

/* --------------------------------------------------------------------------
   16. RÉVÉLATION AU SCROLL — rejouable

   Les animations ne sont PAS jouées une seule fois au chargement : chaque
   élément reprend son état de départ dès qu'il sort complètement du champ,
   et se rejoue à chaque nouvelle entrée. D'où des transitions (réversibles)
   plutôt que des @keyframes en `animation-fill-mode: both`.

   Deux observateurs pour éviter le clignotement (hystérésis) :
   · entrée  — déclenchée à 12 % de la hauteur du viewport
   · sortie  — déclenchée seulement 12 % au-delà du bord, donc hors champ
   -------------------------------------------------------------------------- */
.reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity var(--dur-reveal) var(--ease-standard),
              transform var(--dur-reveal) var(--ease-standard);
  transition-delay: var(--d, 0ms);
}
.reveal[data-side="l"] { transform: translate(-22px, 8px); }   /* entre par la gauche */
.reveal[data-side="r"] { transform: translate(22px, 8px); }    /* entre par la droite */
.reveal[data-side="s"] { transform: translateY(24px) scale(.985); }  /* carte CTA */
.reveal.is-in { opacity: 1; transform: none; }

/* --------------------------------------------------------------------------
   17. RESPONSIVE
   -------------------------------------------------------------------------- */
@media (max-width: 1279px) {
  /* le conteneur se resserre : mockup et cartes rétrécissent ensemble
     pour que le recouvrement reste de l'ordre de 20 à 40px */
  .hero__phone { width: min(470px, 78vw); }
  .float { width: 280px; padding: var(--space-3) var(--space-4); }

  /* on garde le MÊME rapport de colonnes qu'au-dessus de 1280px : les
     connecteurs sont tracés en coordonnées normalisées, changer le rapport
     les décalerait. Seul l'écart se resserre. */
  .feats { gap: var(--space-12); }
  .feats__col--l .fcard:first-child,
  .feats__col--r .fcard:last-child { margin-inline: 0; }
  .cta { padding: var(--space-12); }
}

@media (max-width: 1023px) {
  /* `display: contents` fait remonter les enfants de .hdr__act comme
     items de la grille : logo | bouton | burger, donc un vrai centrage
     du bouton sur le header et non sur l'espace restant. */
  .hdr__in { grid-template-columns: 1fr auto 1fr; gap: var(--space-3); }
  .hdr__act { display: contents; }
  .hdr__act .btn--accent { justify-self: center; padding-inline: 18px; }
  .burger { justify-self: end; }
  .logo__img { height: 26px; }
  .hdr__nav { display: none; }
  .burger { display: flex; }
  .hide-md { display: none; }

  /* Sous 1024px il n'y a plus la place de part et d'autre du mockup :
     les quatre cartes se superposent au même endroit et défilent, une
     toutes les 2 secondes. Le cycle complet fait donc 8s, chaque carte
     étant décalée d'un quart.
     `top: auto` est obligatoire : sinon le `top` du desktop cohabiterait
     avec ce `bottom` et étirerait la carte sur toute la hauteur. */
  .hero__stage { min-height: 0; }
  .float {
    left: 50%; right: auto; top: auto; bottom: -2%;
    margin-left: -150px; width: 300px; max-width: none;
    /* cartes plus basses : rembourrage et gouttière resserrés */
    padding: var(--space-3) var(--space-4);
    gap: var(--space-3);
    align-items: center;
    transform: none;
    transition: none;              /* l'animation pilote seule opacity/transform */
    animation-name: float-soft, notif-defile;
    animation-duration: 6.4s, 16s;   /* 4 cartes × 4s */
    animation-timing-function: ease-in-out, linear;
    animation-iteration-count: infinite, infinite;
    /* `backwards` est indispensable : sans lui, pendant son délai (4, 8 ou
       12s) la carte affiche son style normal — donc l'opacité 1 héritée de
       `.hero__stage.is-in .float`. Les trois cartes en attente restaient
       visibles, empilées, et le glissement devenait imperceptible. */
    animation-fill-mode: none, backwards;
  }
  .float .notif__dot { width: 32px; height: 32px; font-size: 15px; border-radius: var(--radius-sm); }
  .float .notif__t { font-size: var(--fs-caption); }
  .float .notif__s { margin-top: 1px; font-size: var(--fs-micro); line-height: 1.3; }
  .float .notif__time { font-size: 10px; }

  .float--n1 { animation-delay: -0.6s,  0s; }
  .float--n2 { animation-delay: -2.4s,  4s; }
  .float--n3 { animation-delay: -4.1s,  8s; }
  .float--n4 { animation-delay: -5.3s, 12s; }

  .about { grid-template-columns: 1fr; gap: var(--space-8); }
  .about__right { order: -1; }

  .sec__head { grid-template-columns: 1fr; gap: var(--space-6); align-items: start; margin-bottom: var(--space-12); }

  /* sous 1024px le mockup passe au-dessus : les connecteurs latéraux
     n'ont plus rien à relier. */
  .feats { grid-template-columns: 1fr 1fr; gap: var(--space-5); }
  .feats__links, .fcard::after { display: none; }
  .feats__mid { grid-column: 1 / -1; order: -1; max-width: 250px; margin-inline: auto; }

  /* le lecteur repasse pleine largeur, les 3 blocs se rangent dessous */
  .player { grid-template-columns: 1fr; gap: var(--space-6); }
  .player__stage { grid-column: 1; grid-row: 1; }
  .player__side { grid-column: 1; grid-row: 2; }
  .vlist { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .vitem { padding: var(--space-4); gap: var(--space-3); }
  .vitem__go { display: none; }   /* pas de survol au doigt, et la place manque */

  .avis { grid-template-columns: 1fr; gap: var(--space-8); }
  .avis__head { align-self: start; flex-direction: row; align-items: center; justify-content: space-between; }

  .faq { grid-template-columns: 1fr; gap: var(--space-10); }
  .faq__head { position: static; }

  /* empilé : l'image passe SOUS le texte, marges négatives annulées.
     Sans `order`, elle suit l'ordre du DOM et se retrouve en bas. */
  .cta { grid-template-columns: 1fr; }
  .cta__r {
    align-self: auto;
    justify-content: center; margin-right: 0; margin-bottom: 0;
  }
  .cta__phone { width: min(320px, 72%); }

  .ftr__top { grid-template-columns: 1fr; align-items: start; gap: var(--space-8); }
}

@media (max-width: 430px) {
  /* À cette largeur, logo (113px) + bouton centré + burger dépassent la
     place disponible. Plutôt que de rétrécir le logo jusqu'à l'illisible,
     on repasse en deux colonnes : logo à gauche, actions à droite. */
  .hdr__in { grid-template-columns: 1fr auto; }
  .hdr__act { display: flex; align-items: center; gap: var(--space-2); }
  .hdr__act .btn--accent { justify-self: auto; padding-inline: 14px; font-size: var(--fs-micro); }
  .burger { justify-self: auto; }
}

@media (max-width: 767px) {
  /* barre d'action basse retirée : deux boutons fixes en permanence,
     c'était trop lourd sur un petit écran. */
  .mbar { display: none; }

  /* +6px de marge latérale partout sur mobile. Les trois conteneurs qui
     calent le contenu sur les bords utilisent --gutter : on les décale
     ensemble pour qu'ils restent alignés entre eux. */
  .wrap,
  .mbar,
  .menu__in { padding-inline: calc(var(--gutter) + 6px); }

  /* titres de section resserrés sur mobile */
  .about__title              { font-size: calc(var(--fs-h1) - 5px); }
  #fonctionnalites .sec__title { font-size: calc(var(--fs-h2) - 5px); }
  #systeme .sec__title,
  #videos .sec__title,
  #avis .sec__title          { font-size: calc(var(--fs-h2) - 3px); }

  .hero { padding-top: var(--space-8); }
  /* boutons resserrés ET de largeur égale : c'est le conteneur qui est
     borné, les boutons s'y étirent — sinon chacun prend la largeur de son
     libellé et les deux ne s'alignent pas. */
  .hero__cta {
    flex-direction: column; align-items: stretch;
    max-width: 300px; margin-inline: auto;
  }
  .hero__cta .btn {
    width: 100%; min-width: 0;
    height: 56px; padding-inline: var(--space-6);
    font-size: var(--fs-body);
  }
  /* mockup agrandi : 78 → 96vw */
  .hero__phone { width: min(470px, 96vw); }
  .hero__lines, .brk { display: none; }
  .hero__stage { margin-top: var(--space-12); }
  /* centrage par margin-left et non par translateX : `transform` reste
     entièrement disponible pour l'animation d'entrée. */
  .float--n1 {
    left: 50%; margin-left: -150px; bottom: -4%;
    width: 300px; max-width: none;
    transform: translateY(14px);
  }

  /* `display: contents` dissout les deux colonnes : les quatre cartes
     deviennent items de la grille, donc un seul `gap` régit tous les
     écarts. Il rétablit aussi l'ordre de lecture — empilées telles quelles,
     les colonnes donnaient 01, 03, 02, 04. */
  .feats { grid-template-columns: 1fr; gap: var(--space-5); }
  .feats__col { display: contents; }
  .feats__mid { order: 0; }
  .feats__col--l .fcard:nth-of-type(1) { order: 1; margin-left: 0; }
  .feats__col--r .fcard:nth-of-type(1) { order: 2; }
  .feats__col--l .fcard:nth-of-type(2) { order: 3; }
  .feats__col--r .fcard:nth-of-type(2) { order: 4; margin-right: 0; }
  .feats__foot { flex-direction: column; order: 5; }
  .feats__foot .btn { width: 100%; }

  .player__poster { gap: var(--space-4); }
  .player__poster.has-img .player__meta {
    left: var(--space-5); right: var(--space-5); bottom: var(--space-5);
  }
  /* l'affiche ne fait que ~196px de haut : on réserve la place du titre
     pour que le bouton de lecture, centré, ne vienne pas le toucher. */
  .player__poster.has-img { padding-bottom: calc(var(--space-5) + 3.4em); }
  .player__label { font-size: var(--fs-h4); }
  .player__play { width: 52px; height: 52px; font-size: 21px; }
  .player__note { font-size: var(--fs-caption); }

  /* les 3 blocs s'empilent : à 390px, une rangée de 3 serait illisible */
  .vlist { grid-template-columns: 1fr; gap: var(--space-3); }

  /* Largeur de piste FIXE (et non minmax) : sinon les pistes se compriment
     dans le conteneur au lieu de déborder et de défiler. */
  .tcard { width: 82vw; padding: var(--space-6); }

  .qa summary { font-size: var(--fs-body); padding: var(--space-4) var(--space-5); }
  .qa__c { padding: 0 var(--space-5) var(--space-5); font-size: var(--fs-body-sm); }

  .cta { padding: var(--space-8) var(--space-5); border-radius: var(--radius-2xl); }
  .cta__t { font-size: calc(var(--fs-h2) - 3px); }
  /* l'image affleure le bas de la carte : on annule le rembourrage bas */
  .cta__r { align-self: end; margin-bottom: calc(var(--space-8) * -1); }
  .cta__l { width: 100%; }
  .cta__phone { width: min(340px, 82%); }
  .cta__btns {
    flex-direction: column; align-items: stretch; width: 100%;
    gap: var(--space-5);
  }
  .cta__btns .btn { width: 100%; height: 56px; font-size: var(--fs-body); }
  /* Les badges étaient dimensionnés par leur contenu : .cta__stores, dans
     un parent en `align-items: flex-start`, se réduisait à la largeur du
     texte. On lui rend toute la largeur pour que `flex: 1` puisse enfin
     répartir la ligne entre les deux. */
  /* Les deux badges sur une seule ligne. La ligne utile fait 268px : tout
     l'intérieur est calibré pour que « Google Play », le plus long, tienne
     sans être coupé. */
  .cta__stores { width: 100%; }
  .stores { width: 100%; flex-wrap: nowrap; gap: var(--space-2); }
  .store {
    flex: 1 1 0; min-width: 0; justify-content: center;
    height: 52px; padding-inline: var(--space-2); gap: var(--space-2);
  }
  .store__ico { width: 20px; height: 20px; }
  .store small { font-size: 9px; }
  .store strong { font-size: var(--fs-micro); }
  .store span { min-width: 0; }

  .ftr__bot { flex-direction: column; }
}

/* --------------------------------------------------------------------------
   18. MOUVEMENT RÉDUIT
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .avis__rail { animation: none !important; width: auto; }
  .avis__track { overflow-x: auto; }
  .float, .about__badge, .hero__phone, .hero__lines .ln, .brk, .reveal, .feats__links path {
    animation: none !important;
    transition: none !important;
    opacity: 1 !important;
    transform: none !important;
    stroke-dashoffset: 0 !important;
  }
  /* sans animation, les quatre cartes se superposeraient au même endroit */
  @media (max-width: 1023px) {
    .float--n2, .float--n3, .float--n4 { display: none; }
  }
}

/* ==========================================================================
   PAGE CONTACT
   ========================================================================== */
.ct-intro { padding-block: var(--space-16) var(--space-10); text-align: center; }
.ct-intro__t {
  margin-top: var(--space-6);
  font-size: calc(var(--fs-display) - 10px);
  font-weight: var(--fw-extra);
  line-height: var(--lh-tight); letter-spacing: var(--ls-display);
  text-wrap: balance;
}
.ct-intro__p {
  margin: var(--space-6) auto 0;
  max-width: 56ch;
  font-size: var(--fs-lead); color: var(--text-secondary); line-height: var(--lh-snug);
}

.ct-sec { padding-top: var(--space-4); }
.ct {
  display: grid;
  grid-template-columns: minmax(0, 1.8fr) minmax(0, 1fr);
  gap: var(--space-16);
  align-items: start;
}

/* --- Panneau du formulaire --- */
.ct__form {
  background: var(--surface-raised);
  border-radius: var(--radius-2xl);
  padding: var(--space-10);
  box-shadow: inset 0 0 0 1px var(--border-hairline), var(--shadow-md);
}
.ct__t {
  font-size: var(--fs-h3); font-weight: var(--fw-bold);
  letter-spacing: var(--ls-heading);
  margin-bottom: var(--space-6);
}

/* Sélecteur de profil — deux radios natives habillées en segments.
   On garde les <input> pour l'accessibilité clavier et le focus. */
.ct__seg { border: 0; padding: 0; margin: 0 0 var(--space-8); }
.ct__seg legend {
  padding: 0; margin-bottom: var(--space-3);
  font-size: var(--fs-label); font-weight: var(--fw-bold);
  letter-spacing: var(--ls-label); text-transform: uppercase;
  color: var(--text-secondary);
}
.seg { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.seg input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.seg label {
  display: inline-flex; align-items: center; gap: var(--space-2);
  padding: var(--space-3) var(--space-5);
  border-radius: var(--radius-pill);
  font-size: var(--fs-body-sm); font-weight: var(--fw-semibold);
  cursor: pointer;
  background: var(--surface-muted); color: var(--ink-600);
  transition: background-color var(--dur-fast) var(--ease-standard),
              color var(--dur-fast) var(--ease-standard),
              box-shadow var(--dur-fast) var(--ease-standard);
}
.seg label .ico { font-size: 17px; }
.seg label:hover { color: var(--text-primary); }
.seg input:checked + label {
  background: var(--surface-accent); color: var(--text-on-accent);
  box-shadow: var(--shadow-accent);
}
.seg input:focus-visible + label { box-shadow: var(--focus-ring); }

/* --- Champs --- */
.fgrid {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: var(--space-5); margin-bottom: var(--space-5);
}
/* quand l'un des deux champs est masqué par le profil, l'autre reprend
   toute la largeur au lieu de rester sur une demi-colonne. */
.fgrid:has(> .field[hidden]) { grid-template-columns: 1fr; }
.field { display: flex; flex-direction: column; gap: var(--space-2); margin-bottom: var(--space-5); }
.fgrid .field { margin-bottom: 0; }
.field label {
  font-size: var(--fs-body-sm); font-weight: var(--fw-semibold);
  display: flex; align-items: baseline; gap: var(--space-2);
}
.field .hint { font-size: var(--fs-micro); font-weight: var(--fw-regular); color: var(--text-secondary); }
.input {
  width: 100%;
  min-height: 48px;
  padding: var(--space-3) var(--space-5);
  border: 0; border-radius: var(--radius-pill);
  background: var(--surface-page);
  box-shadow: inset 0 0 0 1px var(--border-soft);
  font-family: inherit; font-size: var(--fs-body-sm); color: var(--text-primary);
  transition: box-shadow var(--dur-fast) var(--ease-standard),
              background-color var(--dur-fast) var(--ease-standard);
}
textarea.input { min-height: 108px; resize: vertical; line-height: var(--lh-body); border-radius: var(--radius-lg); }
.input::placeholder { color: var(--text-tertiary); }
.input:hover { box-shadow: inset 0 0 0 1px var(--border-strong); }
.input:focus { outline: none; background: var(--surface-raised); box-shadow: inset 0 0 0 2px var(--yellow-800); }
.input[aria-invalid="true"] { box-shadow: inset 0 0 0 2px var(--red-500); background: var(--red-50); }

.ct__erreur {
  margin-bottom: var(--space-4);
  font-size: var(--fs-body-sm); font-weight: var(--fw-medium); color: var(--text-danger);
}
.ct__envoi { width: 100%; margin-top: var(--space-2); }
.ct__legal {
  margin-top: var(--space-4);
  font-size: var(--fs-micro); color: var(--text-secondary); line-height: var(--lh-snug);
}

/* Confirmation — même vocabulaire que le bouton (§15 : « Demande envoyée ») */
.ct__ok {
  display: flex; gap: var(--space-4); align-items: flex-start;
  margin-top: var(--space-6);
  padding: var(--space-5);
  border-radius: var(--radius-lg);
  background: var(--green-50);
}
.ct__ok-ico {
  display: grid; place-items: center; flex: none;
  width: 36px; height: 36px; border-radius: 50%;
  background: var(--green-500); color: var(--cream-0); font-size: 18px;
}
.ct__ok-t { font-size: var(--fs-body); font-weight: var(--fw-bold); color: var(--green-500); }
.ct__ok-s { margin-top: 2px; font-size: var(--fs-body-sm); color: var(--text-secondary); line-height: var(--lh-snug); }

/* --- Colonne des coordonnées --- */
.ct__side { display: flex; flex-direction: column; gap: var(--space-5); position: sticky; top: calc(var(--header-h) + var(--space-6)); }
.ct__card {
  background: var(--surface-raised);
  border-radius: var(--radius-xl);
  padding: var(--space-8);
  box-shadow: inset 0 0 0 1px var(--border-hairline), var(--shadow-sm);
}
.ct__card--soft { background: var(--surface-muted); box-shadow: none; }
.ct__card-t {
  font-size: var(--fs-h4); font-weight: var(--fw-bold);
  letter-spacing: var(--ls-snug); margin-bottom: var(--space-5);
}
.ct__card-p { font-size: var(--fs-body-sm); color: var(--text-secondary); line-height: var(--lh-body); margin-bottom: var(--space-4); }
.ct__list { display: flex; flex-direction: column; gap: var(--space-5); }
.ct__list li { display: flex; align-items: center; gap: var(--space-4); }
.ct__list li > span:last-child { display: flex; flex-direction: column; min-width: 0; }
.ct__list strong { font-size: var(--fs-micro); font-weight: var(--fw-bold); color: var(--text-secondary); text-transform: uppercase; letter-spacing: var(--ls-label); }
.ct__list a, .ct__plain { font-size: var(--fs-body-sm); font-weight: var(--fw-medium); }
.ct__list a { transition: color var(--dur-fast) var(--ease-standard); }
.ct__list a:hover { color: var(--text-brand); }
.ct__ways { display: flex; flex-direction: column; gap: var(--space-3); font-size: var(--fs-body-sm); color: var(--text-secondary); line-height: var(--lh-snug); }
.ct__ways li { display: flex; align-items: flex-start; gap: var(--space-3); }
.ct__ways .ico { font-size: 18px; color: var(--yellow-700); margin-top: 2px; }

@media (max-width: 1023px) {
  .ct { grid-template-columns: 1fr; gap: var(--space-8); }
  .ct__side { position: static; }
}
@media (max-width: 767px) {
  .ct__form { padding: var(--space-6); }
  .fgrid { grid-template-columns: 1fr; }
  .fgrid .field + .field { margin-top: var(--space-5); }
  .ct__card { padding: var(--space-6); }
}

/* Piège à robots : hors écran mais lisible par un automate, qui remplira
   le champ. `display:none` ne conviendrait pas — beaucoup de robots
   ignorent les champs masqués. */
.hp {
  position: absolute;
  left: -9999px;
  width: 1px; height: 1px;
  overflow: hidden;
}

/* Indicateur d'envoi (§7.3) */
.btn__spin {
  width: 18px; height: 18px; flex: none;
  border-radius: 50%;
  border: 2px solid currentColor;
  border-top-color: transparent;
  animation: tourne .7s linear infinite;
}
@keyframes tourne { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .btn__spin { animation-duration: 1.6s; }
}

/* ==========================================================================
   SECTION « SYSTÈME COMPLET » — deux blocs alternés
   ========================================================================== */
.duo { display: flex; flex-direction: column; gap: var(--section-y); }

.duo__row {
  display: grid;
  gap: var(--space-16);
  align-items: center;
}
/* ratios distincts : le MacBook est en paysage, le téléphone en portrait —
   une grille unique donnerait un visuel écrasé d'un côté, géant de l'autre. */
.duo__row--mac { grid-template-columns: minmax(0, .78fr) minmax(0, 1.5fr); }
.duo__row--tel { grid-template-columns: minmax(0, .6fr) minmax(0, 1fr); }

.duo__txt { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-4); }
.duo__t {
  font-size: var(--fs-h3); font-weight: var(--fw-bold);
  line-height: var(--lh-heading); letter-spacing: var(--ls-heading);
  text-wrap: pretty;
}
.duo__p {
  font-size: var(--fs-lead); color: var(--text-secondary);
  line-height: var(--lh-snug); max-width: 44ch;
}
.duo__list {
  display: flex; flex-direction: column; gap: var(--space-3);
  margin-top: var(--space-2);
  font-size: var(--fs-body-sm); color: var(--text-primary); line-height: var(--lh-snug);
}
.duo__list li { display: flex; align-items: flex-start; gap: var(--space-3); }
.duo__list .ico {
  font-size: 18px; color: var(--yellow-800);
  margin-top: 2px;
  background: var(--surface-accent-soft);
  border-radius: 50%;
  padding: 3px; box-sizing: content-box;
}

.duo__vis { position: relative; display: grid; place-items: center; }
.duo__halo {
  position: absolute; inset: auto auto 50% 50%;
  translate: -50% 50%;
  width: 105%; aspect-ratio: 1;
  background: var(--halo-light);
  border-radius: 50%;
  pointer-events: none;
}
.duo__mac, .duo__phone {
  position: relative;
  width: 100%; height: auto;
  filter: drop-shadow(0 26px 54px rgba(18, 18, 18, .16));
}
.duo__phone { width: min(300px, 100%); }

@media (max-width: 1023px) {
  .duo { gap: var(--space-16); }
  .duo__row, .duo__row--mac, .duo__row--tel {
    grid-template-columns: 1fr;
    gap: var(--space-8);
  }
  /* le visuel passe au-dessus du texte dans les deux blocs, pour garder
     le même rythme une fois la grille dépliée. */
  .duo__vis { order: -1; }
  .duo__phone { width: min(260px, 70%); }
}
