/* ============================================================================
   VSN STRAPS — STYLE PRINCIPAL
   ----------------------------------------------------------------------------
   SOMMAIRE
   01 Base & reset          07 Best sellers (slider)   13 Quick view (modale)
   02 Boutons               08 Rotation                14 Tiroir panier
   03 Accès privé           09 Lifestyle / stories     15 Toast
   04 Header                10 Newsletter / formulaires 16 Checkout & pages
   05 Menu mobile           11 Collection               17 Footer
   06 Hero (carrousel)      12 Fiche produit            18 Responsive
   ============================================================================ */

/* ======================= 01. BASE & RESET ================================ */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
/* 04.09.2026 : `overflow-x: hidden` remplace par `clip`. Les deux coupent le
   debordement horizontal de la meme facon, mais `hidden` force le navigateur a
   faire de l'element une BOITE DE DEFILEMENT (overflow-y bascule en auto), et
   un element collant se cale alors sur cette boite-la, qui ne defile pas. C'est
   la seconde cause qui empechait la galerie de la fiche de suivre la lecture.
   `clip` coupe sans creer de boite de defilement, donc `position: sticky`
   fonctionne a nouveau partout dans la page. */
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; overflow-x: clip; }
body {
  font-family: var(--font-ui);
  font-size: var(--text-base);
  line-height: 1.65;
  color: var(--color-black);
  background: var(--color-warm-white);
  -webkit-font-smoothing: antialiased;
  /* 04.09.2026 : `clip` et non `hidden`, pour la meme raison que sur `html`
     plus haut. `hidden` aurait fait du body une boite de defilement et aurait
     re-casse `position: sticky` a lui seul, malgre la correction du html. Le
     garde-fou contre le debordement horizontal est identique. */
  overflow-x: clip;
}
img { max-width: 100%; display: block; height: auto; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
input, select, textarea { font: inherit; color: inherit; }
ul { list-style: none; }

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

/* Le rythme vertical VARIE d'une section à l'autre : un padding unique du haut
   en bas de la page est ce qui fait « page générée ». */
.section { padding-block: clamp(3.5rem, 6.4vw, 6.5rem); }
.section--tight { padding-block: clamp(2.4rem, 4vw, 4rem); }
.section--tall  { padding-block: clamp(5rem, 9vw, 9rem); }

/* Environnements de section : la page traverse des pièces différentes au lieu
   d'être repeinte de la même couleur partout. */
.section--ivory { background: var(--color-ivory); }
.section--paper { background: var(--color-warm-white); }
.section--ink   { background: var(--color-black); color: var(--color-ivory); }
/* Troisième niveau de fond : ni le blanc des respirations, ni l'encre des
   ruptures. Il sert aux sections « utiles » (compatibilité, offre) qui
   doivent se détacher sans crier. */
.section--deep  { background: var(--color-ivory-deep); }
.section--wine  { background: var(--color-black); color: var(--color-ivory); }
.section--ink .section-sub,
.section--wine .section-sub { color: rgba(243,239,230,0.72); }

/* Label discret : il situe, il n'annonce pas. Casse naturelle, pas de
   capitales espacées décoratives au-dessus de chaque titre. */
.label {
  font-size: var(--text-sm); font-weight: 600;
  color: var(--color-muted);
  display: flex; align-items: center; gap: 0.6rem;
}
.label::before {
  content: ""; width: 22px; height: 1px; background: currentColor; opacity: 0.5; flex: none;
}
.label--light { color: rgba(243,239,230,0.7); }

.section-head { max-width: 640px; margin-bottom: var(--space-4); }
.section-title {
  font-family: var(--font-display); font-weight: 700;
  font-size: var(--text-xl); line-height: 1.08;
  letter-spacing: var(--tracking-tight);
  margin-top: var(--space-1); text-wrap: balance;
}
.section-sub { color: var(--color-muted); margin-top: 0.8rem; max-width: 54ch; }

/* Filet Riviera : double ligne signature de la maison */

/* Bandeau « bracelet uniquement » */
.band-only-note {
  display: inline-flex; align-items: center; gap: 0.55rem;
  font-size: var(--text-sm); color: var(--color-muted);
}
.band-only-note::before {
  content: ""; width: 5px; height: 5px; border-radius: 50%;
  background: var(--color-navy); flex: none;
}

/* Reassurance d'achat sous le bouton (brief v1.2, bloc 02). Compacte par
   construction : c'est une liste de faits, pas une nouvelle section. Le point
   reprend celui de .band-only-note pour rester dans la meme famille. */
.product-badge { margin: 0.6rem 0 0; }

.trust-strip {
  list-style: none; margin: var(--space-3) 0 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: 0.35rem 1.4rem;
}
.trust-strip li {
  display: inline-flex; align-items: center; gap: 0.55rem;
  font-size: var(--text-sm); color: var(--color-muted);
}
.trust-strip li::before {
  content: ""; width: 5px; height: 5px; border-radius: 50%;
  background: var(--color-navy); flex: none;
}
/* Sous 430 px la ligne passe en colonne : trois faits cote a cote se coupent
   en plein milieu d'un mot sur un iPhone SE. */
@media (max-width: 430px) {
  .trust-strip { flex-direction: column; gap: 0.3rem; }
}


:focus-visible { outline: 2px solid var(--color-navy); outline-offset: 3px; border-radius: 1px; }
.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 300;
  background: var(--color-black); color: var(--color-warm-white);
  padding: 0.6rem 1rem; font-size: var(--text-sm);
}
.skip-link:focus { left: 8px; top: 8px; }
.visually-hidden {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap;
}

/* ======================= 02. BOUTONS ===================================== */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.6rem;
  padding: 1.02rem 2.2rem; border-radius: 4px;
  font-size: var(--text-sm); font-weight: 600; letter-spacing: 0.09em; text-transform: uppercase;
  transition: background-color var(--dur-fast) var(--ease-ui),
              color var(--dur-fast) var(--ease-ui),
              border-color var(--dur-fast) var(--ease-ui),
              transform var(--dur-fast) var(--ease-ui),
              opacity var(--dur-fast) var(--ease-ui);
  position: relative; overflow: hidden;
}
.btn:active { transform: translateY(1px) scale(0.995); }
.btn[disabled] { opacity: 0.45; cursor: not-allowed; }

/* Noir plein — remplissage inversé au survol + overlay animé */
.btn--solid { background: var(--color-black); color: var(--color-warm-white); border: 1px solid var(--color-black); box-shadow: 0 1px 2px rgba(17,16,14,0.12); }
.btn--solid::before {
  content: ""; position: absolute; inset: 0; z-index: 0;
  background: var(--color-charcoal); transform: translateY(100%);
  transition: transform var(--dur-fast) var(--ease-luxury);
}
.btn--solid { isolation: isolate; }
.btn--solid > * { position: relative; z-index: 1; }
.btn--solid:hover::before { transform: translateY(0); }
.btn--solid:hover { background: var(--color-charcoal); box-shadow: 0 8px 22px -8px rgba(17,16,14,0.5); transform: translateY(-1px); }
/* Clair bordé */
.btn--outline { background: transparent; color: var(--color-black); border: 1px solid var(--color-black); }
.btn--outline:hover { background: var(--color-black); color: var(--color-warm-white); box-shadow: 0 8px 22px -10px rgba(17,16,14,0.45); transform: translateY(-1px); }
/* Texte avec flèche */
.btn--text {
  padding: 0.2rem 0; border-radius: 0; text-transform: none; letter-spacing: 0.02em;
  font-weight: 600; border-bottom: 1px solid var(--color-black);
}
.btn--text .arrow { transition: transform var(--dur-fast) var(--ease-ui); }
.btn--text:hover .arrow { transform: translateX(4px); }
/* Circulaire (flèches de carrousel, fermeture) */
.btn--icon {
  width: 46px; height: 46px; padding: 0; border-radius: 50%;
  border: 1px solid var(--color-border); background: rgba(251,250,247,0.7);
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  display: inline-flex; align-items: center; justify-content: center; font-size: 1.05rem;
  transition: background-color var(--dur-fast) var(--ease-ui),
              color var(--dur-fast) var(--ease-ui),
              border-color var(--dur-fast) var(--ease-ui),
              transform var(--dur-fast) var(--ease-luxury);
}
.btn--icon:hover { background: var(--color-black); color: var(--color-warm-white); border-color: var(--color-black); box-shadow: 0 10px 24px -10px rgba(17,16,14,0.5); }
.btn--icon:active { transform: scale(0.94); }
.btn--icon:hover { border-color: var(--color-black); }
.btn--icon:disabled { opacity: 0.3; }

/* États loading / success (ajout panier) */
.btn.is-loading { pointer-events: none; opacity: 0.75; }
.btn.is-loading::after {
  content: ""; width: 14px; height: 14px; border-radius: 50%;
  border: 2px solid currentColor; border-top-color: transparent;
  animation: vsn-spin 700ms linear infinite; margin-left: 0.3rem;
}
@keyframes vsn-spin { to { transform: rotate(360deg); } }
.btn.is-success { background: var(--color-ok); border-color: var(--color-ok); color: #fff; }

/* ======================= 03. ACCÈS PRIVÉ ================================= */
/* Protection front-end de DÉMONSTRATION : le mot de passe est lisible dans
   config.js. Non sécurisé pour un site public — voir README §7. */
/* `hidden` seul ne suffit PAS ici : l'attribut ne pose son display:none que via
   la feuille du navigateur, la moins prioritaire de toutes. La règle `.gate`
   ci-dessous la bat, donc le rideau était PEINT au premier affichage et ne
   disparaissait qu'à l'exécution de initGate(). D'où le flash d'écran de mot de
   passe sur un site qui n'en a plus (constaté en production le 20.08.2026).
   Toute règle `display:` sur un élément porteur de `hidden` demande ce garde. */
.gate[hidden] { display: none; }
.gate {
  position: fixed; inset: 0; z-index: 200;
  display: flex; align-items: center; justify-content: center;
  background:
    radial-gradient(1200px 600px at 80% -10%, var(--color-sand-soft), transparent 60%),
    var(--color-ivory);
  padding: var(--gutter);
}
.gate-card {
  width: min(430px, 100%); background: var(--color-warm-white);
  border: 1px solid var(--color-border); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card); padding: clamp(2rem, 5vw, 3rem);
  text-align: center; animation: vsn-fade-up var(--dur-med) var(--ease-luxury);
}
.gate-monogram {
  font-family: var(--font-display); font-weight: 700; font-size: 1.35rem; letter-spacing: 0.24em;
  padding-left: 0.3em; /* compense le tracking */
  border: 1px solid var(--color-black); border-radius: 50%;
  width: 74px; height: 74px; display: inline-flex; align-items: center; justify-content: center;
  margin-bottom: var(--space-2);
}
.gate h1 { font-family: var(--font-ui); font-weight: 700; font-size: var(--text-lg); letter-spacing: -0.01em; }
.gate p  { color: var(--color-muted); font-size: var(--text-sm); margin-top: 0.5rem; }
.gate form { margin-top: var(--space-3); display: grid; gap: 0.8rem; }
.gate input {
  width: 100%; padding: 0.9rem 1rem; text-align: center; letter-spacing: 0.2em;
  border: 1px solid var(--color-border); border-radius: var(--radius);
  background: var(--color-warm-white);
  transition: border-color var(--dur-fast) var(--ease-ui);
}
.gate input:focus { border-color: var(--color-navy); outline: none; }
.gate-err { color: var(--color-err); font-size: var(--text-sm); min-height: 1.2em; }
.gate-note { font-size: var(--text-xs); color: var(--color-muted); margin-top: var(--space-2); }

/* ======================= 04. HEADER ====================================== */
.announce {
  background: var(--color-black); color: var(--color-ivory);
  font-size: var(--text-xs); letter-spacing: 0.1em; text-transform: uppercase;
  position: relative; height: 36px; overflow: hidden;   /* hauteur FIXE : aucun saut */
}
.tick-item {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  padding-inline: var(--gutter); text-align: center;
  opacity: 0; transform: translateY(9px);
  transition: opacity 480ms var(--ease-luxury), transform 480ms var(--ease-luxury);
  pointer-events: none;
}
.tick-item.is-active { opacity: 1; transform: none; }
.tick-item.is-leaving { opacity: 0; transform: translateY(-9px); }
/* Le barème tient en une phrase, et cette phrase est plus longue en anglais,
   en espagnol et en italien qu'en français. Mesurée à 320 px, elle dépassait
   la largeur utile de 27 px en anglais : le bandeau étant en `overflow:hidden`
   avec un texte centré, elle se serait coupée aux deux bouts sans rien signaler.
   On resserre donc la lettre et le corps sur les tout petits écrans, plutôt que
   de raccourcir un message qui doit rester lisible d'un coup d'oeil. */
@media (max-width: 360px) {
  .announce { font-size: 0.7rem; letter-spacing: 0.05em; }
}
.site-header {
  position: sticky; top: 0; z-index: 90;
  background: transparent; border-bottom: 1px solid transparent;
  transition: background-color 380ms var(--ease-ui),
              border-color 380ms var(--ease-ui),
              backdrop-filter 380ms var(--ease-ui);
}
.site-header.is-scrolled {
  background: rgba(251, 250, 247, 0.85);
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  border-bottom-color: var(--color-border-soft);
}
.header-inner {
  display: grid; grid-template-columns: minmax(0,1fr) auto minmax(0,1fr); align-items: center;
  gap: var(--space-3);
  height: var(--header-h); transition: height 380ms var(--ease-ui);
  max-width: 100%; margin-inline: 0;                 /* pleine largeur : logo près du bord */
  padding-inline: clamp(1rem, 2.6vw, 2rem);
}
.is-scrolled .header-inner { height: var(--header-h-scrolled); }
.header-left { display: flex; align-items: center; gap: 1rem; justify-self: start; }

.logo { display: flex; flex-direction: column; line-height: 1;
  /* Le bloc est centre par la grille : son contenu doit l'etre aussi, sinon le
     wordmark et sa ligne de sous-titre se decalent l'un par rapport a l'autre. */
  align-items: center; text-align: center; }
.logo-word {
  font-weight: 800; letter-spacing: 0.34em; font-size: 1.02rem; white-space: nowrap;
}
.logo-word span { font-weight: 300; }
.logo-sub {
  font-size: 0.54rem; letter-spacing: 0.4em; text-transform: uppercase;
  color: var(--color-muted); margin-top: 0.32rem; white-space: nowrap;
}

.main-nav { display: flex; gap: 1.9rem; justify-self: center; }
.main-nav a {
  font-size: var(--text-sm); font-weight: 600; letter-spacing: 0.05em;
  position: relative; padding-block: 0.4rem; color: var(--color-charcoal);
}
.main-nav a::after {
  content: ""; position: absolute; left: 0; right: 100%; bottom: 0; height: 1px;
  background: var(--color-black); transition: right var(--dur-fast) var(--ease-luxury);
}
.main-nav a:hover::after, .main-nav a.active::after { right: 0; }
.main-nav a.active { color: var(--color-black); }

.header-tools { display: flex; align-items: center; gap: 0.9rem; justify-self: end; }
.tool-select {
  border: 1px solid var(--color-border-soft); border-radius: 20px;
  background: transparent; font-size: var(--text-xs); font-weight: 700;
  letter-spacing: 0.08em; cursor: pointer; padding: 0.4rem 0.7rem;
  transition: border-color var(--dur-fast) var(--ease-ui), background-color var(--dur-fast) var(--ease-ui);
}
.tool-select:hover { border-color: var(--color-border); background: var(--color-warm-white); }
.cart-btn { position: relative; display: inline-flex; padding: 0.4rem; }
/* La loupe remplace le burger en desktop : elle ouvre le panneau qui porte la
   recherche, sans dupliquer une navigation déjà visible. */
.search-btn { display: inline-flex; padding: 0.4rem; color: inherit; }
.search-btn svg { width: 20px; height: 20px; }
.search-btn:hover { color: var(--color-scarlet); }
@media (max-width: 860px) { .search-btn { display: none; } }
.cart-btn svg { width: 21px; height: 21px; }
.cart-count {
  position: absolute; top: -2px; right: -5px;
  min-width: 17px; height: 17px; border-radius: 10px; padding-inline: 4px;
  background: var(--color-navy); color: #fff;
  font-size: 0.62rem; font-weight: 700; line-height: 17px; text-align: center;
}
/* Le burger ne sert plus à rien en desktop, où la navigation complète est
   déjà affichée : deux portes vers le même endroit. Il n'apparaît qu'à partir
   du moment où la navigation passe en menu (1024px). */
.burger { display: none; width: 42px; height: 42px; position: relative; flex: none; margin-right: 0.4rem; }
@media (max-width: 860px) { .burger { display: block; } }   /* pile quand .main-nav disparaît */
.burger span {
  position: absolute; left: 10px; right: 10px; height: 1.5px; background: var(--color-black);
  transition: transform var(--dur-fast) var(--ease-ui), opacity var(--dur-fast) var(--ease-ui);
}
.burger span:nth-child(1) { top: 15px; } .burger span:nth-child(2) { top: 21px; } .burger span:nth-child(3) { top: 27px; }
.burger.open span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.burger.open span:nth-child(2) { opacity: 0; }
.burger.open span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

/* ======================= 05. MENU MOBILE ================================= */
.mobile-menu {
  position: fixed; top: 0; left: 0; bottom: 0; z-index: 125;
  width: min(430px, 94vw);
  background:
    radial-gradient(600px 300px at 0% 0%, var(--color-sand-soft), transparent 60%),
    var(--color-warm-white);
  box-shadow: 24px 0 60px -24px rgba(17,16,14,0.28);
  border-top-right-radius: 16px; border-bottom-right-radius: 16px;
  display: flex; flex-direction: column; gap: 0.15rem;
  padding: 1.6rem var(--space-3) var(--space-3);
  overflow-y: auto;
  transform: translateX(-106%); visibility: hidden;
  transition: transform 500ms var(--ease-luxury), visibility 0s 500ms;
}
.mobile-menu.open { transform: none; visibility: visible; transition-delay: 0s; }
.menu-brand {
  display: flex; flex-direction: column; line-height: 1; margin-bottom: 1rem;
}
.menu-brand .logo-word { font-weight: 800; letter-spacing: 0.32em; font-size: 1rem; }
.menu-brand .logo-word span { font-weight: 300; }
.menu-brand small {
  font-size: 0.54rem; letter-spacing: 0.4em; text-transform: uppercase;
  color: var(--color-muted); margin-top: 0.35rem;
}
.menu-group {
  font-size: var(--text-xs); font-weight: 700; letter-spacing: var(--tracking-caps);
  text-transform: uppercase; color: var(--color-muted);
  margin-top: var(--space-3); padding-bottom: 0.5rem;
}
.mobile-link {
  font-size: var(--text-md); font-weight: 600;
  padding: 0.7rem 0.2rem; border-bottom: 1px solid var(--color-border-soft);
  display: flex; align-items: center; justify-content: space-between;
  transition: padding-left var(--dur-fast) var(--ease-luxury), color var(--dur-fast) var(--ease-ui), background-color var(--dur-fast) var(--ease-ui);
}
.mobile-link::after {
  content: "→"; opacity: 0; transform: translateX(-6px);
  transition: opacity var(--dur-fast) var(--ease-ui), transform var(--dur-fast) var(--ease-luxury);
  color: var(--color-navy);
}
.mobile-link:hover { padding-left: 0.6rem; color: var(--color-navy); }
.mobile-link:hover::after { opacity: 1; transform: none; }

/* Recherche de modèles */
.menu-search { position: relative; margin-top: 0.4rem; }
.menu-search input {
  width: 100%; padding: 0.85rem 1rem 0.85rem 2.4rem;
  border: 1px solid var(--color-border); border-radius: 24px;
  background: var(--color-ivory) url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="%2380786d" stroke-width="2"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/></svg>') 0.85rem center / 16px no-repeat;
  transition: border-color var(--dur-fast) var(--ease-ui), background-color var(--dur-fast) var(--ease-ui);
}
.menu-search input:focus { border-color: var(--color-navy); background-color: var(--color-warm-white); outline: none; }
.menu-search-results { display: grid; gap: 0.15rem; margin-top: 0.5rem; }
.menu-search-results a {
  display: flex; align-items: center; gap: 0.8rem;
  padding: 0.45rem 0.5rem; border-radius: var(--radius);
  animation: vsn-fade-up 260ms var(--ease-luxury);
  transition: background-color var(--dur-fast) var(--ease-ui);
}
.menu-search-results a:hover { background: var(--color-ivory); }
.menu-search-results img { width: 40px; height: 40px; border-radius: 6px; object-fit: contain; padding: 4px; background: var(--color-plate); flex: none; }
.menu-search-results span { display: grid; font-size: var(--text-sm); font-weight: 600; line-height: 1.3; }
.menu-search-results small { color: var(--color-muted); font-weight: 400; }
.search-empty { font-size: var(--text-sm); color: var(--color-muted); padding: 0.5rem; }
.mobile-menu .band-only-note { margin-top: var(--space-3); }

/* ======================= 06. HERO (CARROUSEL ÉDITORIAL) ==================
   Slides EMPILÉES : une seule visible à la fois — jamais de duplication.
   Composition asymétrique, fond d'accent par slide, titre révélé par masque,
   image entrant avec une rotation < 2°, grand numéro éditorial. */
/* Le hero passe sur fond encre : c'est le langage du produit éclairé, celui
   des vitrines de montres. Le bracelet devient la seule source de lumière de
   l'écran, et la page démarre sur une image, pas sur un document. */
.hero {
  position: relative; overflow: hidden; outline: none;
  background:
    radial-gradient(900px 620px at 66% 44%, rgba(214,183,107,0.14) 0%, transparent 62%),
    radial-gradient(1200px 800px at 62% 40%, rgba(72,86,120,0.22) 0%, transparent 66%),
    linear-gradient(168deg, #191713 0%, var(--color-black) 46%, #0b0b09 100%);
  color: var(--color-ivory);
  --mx: 0px; --my: 0px; --sy: 0px; --syt: 0px;
}
/* Halo de projecteur derrière la pièce : il respire lentement. */
.hero::before {
  content: ""; position: absolute; z-index: 0; pointer-events: none;
  right: 4%; top: 46%; width: min(760px, 58vw); aspect-ratio: 1;
  transform: translateY(-50%);
  background: radial-gradient(closest-side, rgba(255,247,230,0.20), rgba(255,247,230,0.05) 46%, transparent 72%);
  filter: blur(18px);
  animation: vsn-breathe 9s ease-in-out infinite;
}
@keyframes vsn-breathe {
  0%,100% { opacity: 0.75; transform: translateY(-50%) scale(1); }
  50%     { opacity: 1;    transform: translateY(-50%) scale(1.06); }
}
.hero .hero-kicker { color: rgba(243,239,230,0.72); }
.hero .hero-title { color: var(--color-ivory); }
.hero .hero-spec  { color: rgba(243,239,230,0.9); }
.hero .hero-sub   { color: rgba(243,239,230,0.66); }
.hero .hero-price-label { color: rgba(243,239,230,0.6); }
.hero .hero-price .now  { color: var(--color-ivory); }
.hero .hero-price .was  { color: rgba(243,239,230,0.45); }
.hero .band-only-note   { color: rgba(243,239,230,0.55); }
.hero .band-only-note::before { background: var(--color-sand); }
.hero .btn--solid {
  background: var(--color-ivory); color: var(--color-black); border-color: var(--color-ivory);
}
.hero .btn--solid:hover { background: #fff; color: var(--color-black); }
.hero .btn--outline { color: var(--color-ivory); border-color: rgba(243,239,230,0.42); }
.hero .btn--outline:hover { background: var(--color-ivory); color: var(--color-black); border-color: var(--color-ivory); }
.hero .hero-pag-cur, .hero .hero-pag-total { color: rgba(243,239,230,0.55); }
.hero .hero-progress { background: rgba(243,239,230,0.2); }
.hero .hero-progress-fill { background: var(--color-sand); }
.hero .btn--icon { color: var(--color-ivory); border-color: rgba(243,239,230,0.32); }
.hero .btn--icon:hover { background: var(--color-ivory); color: var(--color-black); border-color: var(--color-ivory); }
.hero-stage {
  position: relative;
  min-height: clamp(520px, 82vh, 760px);
  min-height: clamp(520px, calc(100svh - 118px), 760px);  /* svh : stable sur mobile */
}
.hero-slide {
  position: absolute; inset: 0;
  transition: opacity 620ms var(--ease-luxury), visibility 0s linear 620ms;
  display: grid; grid-template-columns: 1.02fr 1fr; align-items: center;
  gap: var(--space-4);
  max-width: var(--container); margin-inline: auto;
  padding: calc(var(--header-h) + 1.2rem) var(--gutter) calc(var(--space-4) + 2.6rem);
  opacity: 0; visibility: hidden; pointer-events: none;
}
.hero-slide.is-active {
  opacity: 1; visibility: visible; pointer-events: auto;
  transition: opacity 620ms var(--ease-luxury), visibility 0s linear 0s;
  z-index: 2;
}
/* Fond d'accent propre à chaque slide, qui déborde de la grille à droite */
.hero-slide::before {
  content: ""; position: absolute; z-index: -1;
  top: 12%; right: -12%; width: 58%; height: 76%;   /* géométrie FIXE pour toutes les slides */
  background: radial-gradient(closest-side, var(--accent), transparent 74%);
}

/* Entrée / sortie premium (texte vertical, image glissée + rotation légère) */
.hero-slide .hero-copy > * {
  opacity: 0; transform: translateY(26px);
  transition: opacity 700ms var(--ease-luxury), transform 700ms var(--ease-luxury);
}
.hero-slide.is-active .hero-copy > * { opacity: 1; transform: none; }
.hero-slide.is-active .hero-copy > *:nth-child(1) { transition-delay: 60ms; }
.hero-slide.is-active .hero-copy > *:nth-child(2) { transition-delay: 140ms; }
.hero-slide.is-active .hero-copy > *:nth-child(3) { transition-delay: 260ms; }
.hero-slide.is-active .hero-copy > *:nth-child(4) { transition-delay: 340ms; }
.hero-slide.is-active .hero-copy > *:nth-child(5) { transition-delay: 420ms; }
.hero-slide.is-active .hero-copy > *:nth-child(6) { transition-delay: 500ms; }
.hero-slide.is-leaving .hero-copy > *, .hero-slide.is-leaving-back .hero-copy > * {
  opacity: 0; transform: translateY(-16px); transition-duration: 420ms; transition-delay: 0ms;
}

.hero-copy { max-width: 560px; position: relative; z-index: 2; transform: translateY(var(--syt)); }
.hero-title {
  font-family: var(--font-display); font-weight: 700;
  font-size: var(--text-hero); line-height: 0.94;
  letter-spacing: var(--tracking-tight);
  margin-top: var(--space-2); text-transform: none;
}
/* Reveal du titre ligne par ligne, par masque */
.hline { display: block; overflow: hidden; }
.hline-in {
  display: inline-block; transform: translateY(110%);
  transition: transform 800ms var(--ease-luxury);
  transition-delay: calc(140ms + var(--l) * 110ms);
}
.hero-slide.is-active .hline-in { transform: none; }
.hero-slide.is-leaving .hline-in, .hero-slide.is-leaving-back .hline-in {
  transform: translateY(-110%); transition-duration: 420ms; transition-delay: 0ms;
}

.hero-sub { color: var(--color-muted); max-width: 40ch; margin-top: var(--space-2); }
.hero-price { display: flex; align-items: baseline; gap: 1rem; margin-top: var(--space-3); }
.hero-price .now { font-size: var(--text-lg); font-weight: 800; letter-spacing: -0.01em; }
.hero-price .was { color: var(--color-muted); text-decoration: line-through; font-size: var(--text-sm); opacity: 0.85; }

.hero-ctas { display: flex; flex-wrap: wrap; gap: 1.1rem; margin-top: var(--space-3); }
.hero .band-only-note { margin-top: var(--space-2); }

/* Visuel : zone NORMALISÉE, strictement identique sur chaque slide.
   Plaque à ratio fixe 1:1, même fond (--color-plate), mêmes dimensions,
   même ancrage, même ombre : aucune image ne paraît plus grande ou plus
   petite qu'une autre, aucun saut entre les slides. */
.hero-visual {
  position: relative; z-index: 1; display: grid; place-items: center; cursor: grab;
  --gx: 50%; --gy: 32%;                 /* position du reflet, pilotée par JS */
}
.hero-visual:active { cursor: grabbing; }
/* Halo doux diffus derrière la plaque (respiration très légère) */
.hero-visual::after {
  content: ""; position: absolute; width: 80%; aspect-ratio: 1; z-index: -1;
  background: radial-gradient(closest-side, rgba(255,255,255,0.85), transparent 72%);
  filter: blur(10px);
  transform: translate(calc(var(--mx) * 0.35), calc(var(--my) * 0.35));
}
.hero-slide.is-active .hero-visual::after { animation: vsn-halo 7s ease-in-out infinite; }

/* Le cadre du hero EST la scène 3D : plus d'overflow:hidden (il aplatit
   preserve-3d), le fond passe sur la plaque et l'image devient le sujet qui
   avance vers le visiteur. Le zoom-au-survol est remplacé par l'inclinaison,
   qui dit la même chose (l'objet réagit) en donnant du volume. */
.hero-figure {
  width: min(468px, 90%); aspect-ratio: 1 / 1;
  display: grid; place-items: center;
  transform: translate(var(--mx), calc(var(--my) + var(--sy)));
  will-change: transform;
}
/* Plus de plaque blanche : sur fond sombre, la pièce est en apesanteur, tenue
   par sa seule lumière. C'est ce qui la fait exister au lieu de la poser. */
.hero-figure .stage-plate { display: none; }
.hero-figure .stage-gloss { display: none; }
.hero-figure img {
  width: 100%; height: 100%;
  object-fit: contain; object-position: center;
  filter:
    drop-shadow(0 30px 50px rgba(0,0,0,0.55))
    drop-shadow(0 0 60px rgba(255,240,210,0.16));
}
/* LÉVITATION + ROTATION PERMANENTES. Le mouvement ne dépend plus du survol :
   il tourne tout seul, on le voit dès l'arrivée sur la page. C'est la
   correction du reproche « on la remarque à peine ». */
.hero-figure .stage-subject {
  animation: vsn-levitate 11s ease-in-out infinite;
  transform-origin: 50% 50%;
}
@keyframes vsn-levitate {
  0%   { transform: translate3d(0, 0, 60px)     rotateY(-17deg) rotateX(6deg)  rotateZ(-2deg); }
  25%  { transform: translate3d(0, -20px, 90px) rotateY(0deg)   rotateX(2deg)  rotateZ(0deg); }
  50%  { transform: translate3d(0, -8px, 60px)  rotateY(17deg)  rotateX(-4deg) rotateZ(2deg); }
  75%  { transform: translate3d(0, -24px, 90px) rotateY(0deg)   rotateX(2deg)  rotateZ(0deg); }
  100% { transform: translate3d(0, 0, 60px)     rotateY(-17deg) rotateX(6deg)  rotateZ(-2deg); }
}
/* L'ombre au sol suit la lévitation : elle rétrécit quand la pièce monte. */
.hero-figure .stage-shadow {
  bottom: -4%; width: 62%; height: 9%;
  background: radial-gradient(ellipse at center, rgba(0,0,0,0.6), transparent 70%);
  animation: vsn-levitate-shadow 11s ease-in-out infinite;
}
@keyframes vsn-levitate-shadow {
  0%,100% { transform: translate3d(-50%, 0, -60px) scale(1);      opacity: 0.75; }
  25%     { transform: translate3d(-50%, 0, -60px) scale(0.84);   opacity: 0.5; }
  50%     { transform: translate3d(-50%, 0, -60px) scale(0.94);   opacity: 0.65; }
  75%     { transform: translate3d(-50%, 0, -60px) scale(0.8);    opacity: 0.45; }
}
/* Au survol, l'inclinaison du curseur prend le relais de l'animation. */
.hero-visual.is-live .stage-subject,
.hero-visual.is-live .stage-shadow { animation-play-state: paused; }

@media (prefers-reduced-motion: reduce) {
  .hero-figure .stage-subject, .hero-figure .stage-shadow { animation: none; }
}
@media (prefers-reduced-motion: reduce) {
  .hero-slide.is-active .hero-visual::after { animation: none; }
}
@keyframes vsn-halo {
  0%,100% { opacity: 0.7; }
  50%     { opacity: 1; }
}
.hero-slide .hero-visual {
  opacity: 0; transform: translateX(48px) scale(0.985);
  transition: opacity 800ms var(--ease-luxury), transform 900ms var(--ease-luxury);
  transition-delay: 180ms;
}
.hero-slide.is-active .hero-visual { opacity: 1; transform: none; }
.hero-slide.is-leaving .hero-visual { opacity: 0; transform: translateX(-36px) scale(0.985); transition-delay: 0ms; transition-duration: 480ms; }
.hero-slide.is-leaving-back .hero-visual { opacity: 0; transform: translateX(36px) scale(0.985); transition-delay: 0ms; transition-duration: 480ms; }

/* Grand numéro éditorial en fond */

/* UI du carrousel : pagination numérotée + barre de progression + flèches */
.hero-ui {
  position: absolute; left: 0; right: 0; bottom: clamp(1rem, 3.4vh, 2.2rem); z-index: 3;
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  max-width: var(--container); margin-inline: auto; padding-inline: var(--gutter);
  pointer-events: none;
}
.hero-ui > * { pointer-events: auto; }
.hero-pag { display: flex; align-items: center; gap: 1rem; font-size: var(--text-xs); font-weight: 700; letter-spacing: 0.16em; font-variant-numeric: tabular-nums; }
.hero-pag-cur { color: var(--color-navy); }
.hero-pag-total { color: var(--color-muted); }
.hero-progress { width: clamp(96px, 15vw, 200px); height: 2px; background: var(--color-border); overflow: hidden; display: inline-block; border-radius: 2px; }
.hero-progress-fill { display: block; height: 100%; width: 0; background: var(--color-navy); border-radius: 2px; }
.hero-arrows { display: flex; gap: 0.6rem; }

/* ======================= 07. BEST SELLERS (SLIDER) ======================= */
.slider-head { display: flex; align-items: flex-end; justify-content: space-between; gap: var(--space-2); }
.slider {
  display: flex; gap: clamp(1rem, 2.4vw, 1.8rem);
  overflow-x: auto;
  scroll-behavior: smooth;
  padding-block: var(--space-3) var(--space-2);
  scrollbar-width: none; cursor: grab;
  -webkit-overflow-scrolling: touch;
}
.slider.dragging { scroll-behavior: auto; }
.slider::-webkit-scrollbar { display: none; }
.slider.dragging { cursor: grabbing; scroll-snap-type: none; }
.slider > * { flex: 0 0 clamp(268px, 28.5%, 360px); }   /* ≈ 3,2 cartes, défilement libre */

/* ======================= CARTES PRODUITS ================================= */
.card {
  background: var(--color-warm-white); border: 1px solid var(--color-border-soft);
  border-radius: var(--radius-lg); overflow: hidden; position: relative;
  box-shadow: var(--shadow-card);
  transition: border-color var(--dur-fast) var(--ease-ui), transform var(--dur-fast) var(--ease-luxury);
  display: flex; flex-direction: column;
}
.card:hover { border-color: var(--color-border); transform: translateY(-5px); box-shadow: 0 1px 2px rgba(17,16,14,0.04), 0 22px 48px -18px rgba(17,16,14,0.22); }
.card-media { position: relative; background: var(--color-ivory); overflow: hidden; }
.card-media { background: var(--color-plate); }
.card-media img {
  aspect-ratio: 1; object-fit: contain; object-position: center; width: 100%;
  padding: 8%;                              /* respiration autour du bracelet */
  transition: transform 750ms var(--ease-luxury);
}
.card:hover .card-media img { transform: scale(1.045); }
.card-badges { position: absolute; top: 0.8rem; left: 0.8rem; display: grid; gap: 0.35rem; }
.badge {
  font-size: 0.6rem; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase;
  background: var(--color-warm-white); border: 1px solid var(--color-border);
  padding: 0.28rem 0.55rem; border-radius: 2px; width: max-content;
}
.badge--navy { background: var(--color-navy); color: #fff; border-color: var(--color-navy); }
.badge--new { background: var(--color-black); color: var(--color-sand); border-color: var(--color-black); }

.card-hover {
  position: absolute; left: 0.8rem; right: 0.8rem; bottom: 0.8rem;
  display: grid; grid-template-columns: 1fr 1fr; gap: 0.5rem;
  opacity: 0; transform: translateY(8px);
  transition: opacity var(--dur-fast) var(--ease-ui), transform var(--dur-fast) var(--ease-luxury);
}
.card:hover .card-hover, .card:focus-within .card-hover { opacity: 1; transform: none; }
.card-hover .btn { padding: 0.62rem 0.5rem; font-size: 0.66rem; background: rgba(251,250,247,0.92); border: 1px solid var(--color-border); color: var(--color-black); text-transform: uppercase; letter-spacing: 0.08em; -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); }
.card-hover .btn:hover { background: var(--color-black); color: #fff; border-color: var(--color-black); }

.card-body { padding: 1.1rem 1.2rem 1.3rem; display: grid; gap: 0.42rem; }
.card-name { font-size: var(--text-base); font-weight: 700; letter-spacing: 0.01em; }
.card-meta { display: flex; align-items: center; gap: 0.5rem; font-size: var(--text-xs); color: var(--color-muted); }
.swatch { width: 11px; height: 11px; border-radius: 50%; border: 1px solid var(--color-border); flex: none; }
.card-compat { font-size: var(--text-xs); color: var(--color-muted); }
.card-price { display: flex; align-items: baseline; gap: 0.55rem; margin-top: 0.25rem; }
.card-price .now { font-weight: 700; }
.card-price .was { font-size: var(--text-sm); color: var(--color-muted); text-decoration: line-through; }

/* Sur écran tactile, les actions restent visibles */
@media (hover: none) {
  .card-hover { opacity: 1; transform: none; position: static; margin: 0 1.2rem 1rem; }
}

/* ======================= 08. ROTATION (liée au panier) =================== */
.rotation { position: relative; }

/* Casse naturelle : une phrase de conditions se lit, elle ne se crie pas. */
.rot-fifth {
  font-size: var(--text-sm); color: var(--color-charcoal);
  font-weight: 600; margin-top: var(--space-3);
}
.rot-note { font-size: var(--text-sm); color: var(--color-muted); max-width: 62ch; margin-top: var(--space-3); }

/* ======================= 09. LIFESTYLE / STORIES ========================= */
.life-grid { display: grid; grid-template-columns: 1.3fr 1fr 1fr; gap: 1rem; margin-top: var(--space-4); }
.life-item {
  position: relative; border-radius: var(--radius-lg); overflow: hidden;
  background: var(--color-sand-soft); aspect-ratio: 4 / 5;
}
.life-item img { width: 100%; height: 100%; object-fit: cover; transition: transform 900ms var(--ease-luxury); }
.life-item:hover img { transform: scale(1.04); }
.life-ph {
  /* Placeholder élégant, clairement identifiable, facile à remplacer :
     mettez une <img> à la place du <div class="life-ph"> */
  position: absolute; inset: 0; display: grid; place-items: center;
  color: var(--color-muted); font-size: var(--text-xs);
  letter-spacing: var(--tracking-caps); text-transform: uppercase; text-align: center; padding: 1rem;
  background:
    linear-gradient(120deg, transparent 46%, rgba(255,255,255,0.5) 50%, transparent 54%) 0 0 / 200% 100%,
    repeating-linear-gradient(-45deg, transparent 0 14px, rgba(17,16,14,0.03) 14px 15px);
  animation: vsn-shimmer 3.4s linear infinite;
}

.stories { border: 1px dashed var(--color-border); border-radius: var(--radius-lg); padding: var(--space-3); }

/* ======================= 10. NEWSLETTER / FORMULAIRES ==================== */
.field { display: grid; gap: 0.4rem; }
.field label { font-size: var(--text-xs); font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--color-charcoal); }
.field input, .field select, .field textarea {
  padding: 0.85rem 1rem; border: 1px solid var(--color-border);
  border-radius: var(--radius); background: var(--color-warm-white);
  transition: border-color var(--dur-fast) var(--ease-ui);
}
.field input:focus, .field select:focus, .field textarea:focus { border-color: var(--color-navy); outline: none; }
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem 1.2rem; }
.form-grid .full { grid-column: 1 / -1; }
.form-msg { font-size: var(--text-sm); min-height: 1.4em; margin-top: 0.8rem; }
.form-msg.ok { color: var(--color-ok); } .form-msg.err { color: var(--color-err); }

.newsletter { text-align: center; }
.newsletter form {
  display: flex; gap: 0.7rem; max-width: 460px; margin: var(--space-3) auto 0;
}
.newsletter input {
  flex: 1; padding: 0.9rem 1.1rem; border: 1px solid var(--color-border);
  border-radius: var(--radius); background: var(--color-warm-white);
}

/* ======================= 11. COLLECTION ================================== */
.filters { display: flex; flex-wrap: wrap; gap: 0.6rem; margin-block: var(--space-3); }
.filter-btn {
  padding: 0.55rem 1.15rem; border: 1px solid var(--color-border); border-radius: 20px;
  font-size: var(--text-sm); font-weight: 600;
  transition: background-color var(--dur-fast) var(--ease-ui), color var(--dur-fast) var(--ease-ui), border-color var(--dur-fast) var(--ease-ui);
}
.filter-btn:hover { border-color: var(--color-black); }
.filter-btn.active { background: var(--color-black); border-color: var(--color-black); color: var(--color-warm-white); }
.grid-products { display: grid; grid-template-columns: repeat(auto-fill, minmax(258px, 1fr)); gap: clamp(1rem, 2.4vw, 1.8rem); }

/* ======================= 12. FICHE PRODUIT =============================== */
.product-layout { display: grid; grid-template-columns: 1.1fr 1fr; gap: var(--space-5); align-items: start; }

/* 04.09.2026 — LA GALERIE SUIT LA LECTURE.
   Sortir la description de la colonne d'achat (voir app.js) raccourcit la
   colonne de droite, mais il reste un decalage : la galerie est un carre, la
   colonne d'achat fait facilement le double. Sans rien de plus, le bas de
   l'image reste une zone morte.
   `sticky` demande deux choses, et c'est la seconde qu'on oublie : la colonne
   qui porte l'element collant doit avoir la hauteur de la LIGNE de grille.
   Or `.product-layout` est en `align-items: start`, donc chaque colonne se
   contente de son contenu et il n'y a aucune course a suivre. D'ou le
   `align-self: stretch` sur la seule colonne de gauche. */
@media (min-width: 861px) {
  .product-layout > div:first-child { align-self: stretch; }
  .product-layout .gallery {
    position: sticky;
    top: calc(var(--header-h-scrolled) + 1.6rem);
  }
}

/* Le bas de fiche, en pleine largeur sous les deux colonnes. La mesure de
   lecture compte plus que le remplissage : on ne laisse pas une ligne de texte
   filer sur 1400 px, d'ou les deux colonnes en grand ecran. */
.product-bas {
  display: grid; grid-template-columns: 1fr; gap: var(--space-4);
  margin-top: var(--space-5);
}
@media (min-width: 861px) {
  .product-bas {
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
    gap: var(--space-5); align-items: start;
  }
}
/* La galerie est une scène 3D : plus d'overflow:hidden (il aplatit
   preserve-3d), et le zoom-au-survol laisse place à l'inclinaison. */
.gallery-main { position: relative; }
.gallery-main .stage3d-inner { aspect-ratio: 1; display: grid; place-items: center; }
.gallery-main .stage-plate {
  background:
    radial-gradient(120% 96% at 50% 6%,
      var(--plateau-haut) 0%, var(--plateau-fond) 58%, var(--plateau-bord) 100%);
  border-radius: var(--radius-lg);
  /* Le liseré intérieur clair est ce qui empêche le beige de paraître sale :
     il rejoue le bord d'un cyclorama éclairé. */
  box-shadow:
    0 1px 0 rgba(255,255,255,0.55) inset,
    0 0 0 1px rgba(120,104,78,0.09) inset,
    0 30px 60px -28px rgba(17,17,15,0.28);
}
.gallery-main .stage-gloss { border-radius: var(--radius-lg); }
.gallery-main img {
  width: 84%; height: 84%; object-fit: contain; object-position: center;
  filter: drop-shadow(0 22px 34px rgba(17,17,15,0.17));
  transition: opacity var(--dur-fast) var(--ease-ui);
}
.gallery-main.swapping img { opacity: 0; }
.gallery-thumbs { display: flex; gap: 0.7rem; margin-top: 0.8rem; overflow-x: auto; }
.gallery-thumbs button {
  flex: 0 0 76px; border: 1px solid var(--color-border-soft); border-radius: var(--radius);
  overflow: hidden; background: var(--color-ivory); padding: 0;
  transition: border-color var(--dur-fast) var(--ease-ui);
}
.gallery-thumbs button.active, .gallery-thumbs button:hover { border-color: var(--color-black); }
.gallery-thumbs img { aspect-ratio: 1; object-fit: contain; padding: 10%; background: var(--color-plate); }

.pinfo h1 { font-family: var(--font-ui); font-weight: 700; font-size: var(--text-xl); line-height: 1.12; letter-spacing: -0.015em; }
.pinfo .meta { display: flex; align-items: center; gap: 0.6rem; color: var(--color-muted); font-size: var(--text-sm); margin-top: 0.7rem; }
.pinfo .price-line { display: flex; align-items: baseline; gap: 0.8rem; margin-top: var(--space-2); }
.pinfo .price-line .now { font-size: var(--text-lg); font-weight: 800; }
.pinfo .price-line .was { color: var(--color-muted); text-decoration: line-through; }
/* 04.09.2026 : ces quatre regles etaient accrochees a `.pinfo`. En sortant la
   lecture de la colonne d'achat, les paragraphes ont perdu leur interligne et
   les points leur tiret : ils sont tombes en texte nu. Le contexte
   `.product-texte` est donc ajoute partout. A retenir : deplacer un bloc dans
   le HTML casse silencieusement toute regle CSS qui nommait son ancien parent. */
.pinfo .desc, .product-texte .desc { margin-top: var(--space-2); max-width: 62ch; }
.pinfo .advantages, .product-texte .advantages { margin-top: var(--space-3); display: grid; gap: 0.45rem; font-size: var(--text-sm); color: var(--color-charcoal); }
.pinfo .advantages li, .product-texte .advantages li { display: flex; gap: 0.6rem; align-items: baseline; }
.pinfo .advantages li::before, .product-texte .advantages li::before { content: "—"; color: var(--color-navy); }


/* Zone de clic large (44px) autour d'une pastille visuelle de 30px */
/* Anneau de sélection sur la pastille active (fixe, pas de déplacement) */
/* Info-bulle avec le nom de la couleur au survol */

.buy-box { margin-top: var(--space-3); display: grid; gap: 1.3rem; }
.qty-stepper {
  display: inline-flex; align-items: center; border: 1px solid var(--color-border); border-radius: var(--radius);
}
.qty-stepper button { width: 42px; height: 46px; font-size: 1.1rem; }
.qty-stepper input { width: 48px; text-align: center; border: 0; background: transparent; height: 46px; }
.buy-row { display: flex; gap: 1.1rem; flex-wrap: wrap; align-items: stretch; }
.buy-row .btn--solid { flex: 1; min-width: 220px; }

.accordions { margin-top: var(--space-4); border-top: 1px solid var(--color-border-soft); }
.acc-item { border-bottom: 1px solid var(--color-border-soft); }
.acc-btn {
  width: 100%; display: flex; justify-content: space-between; align-items: center;
  padding: 1.05rem 0.2rem; font-weight: 700; font-size: var(--text-sm);
  letter-spacing: 0.06em; text-transform: uppercase;
}
.acc-btn .chev { transition: transform var(--dur-fast) var(--ease-luxury); }
.acc-btn[aria-expanded="true"] .chev { transform: rotate(45deg); }
.acc-panel { overflow: hidden; max-height: 0; transition: max-height var(--dur-med) var(--ease-luxury); }
.acc-panel-inner { padding: 0 0.2rem 1.2rem; color: var(--color-muted); font-size: var(--text-sm); }

/* Barre d'ajout sticky sur mobile */
.sticky-buy {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
  background: rgba(251,250,247,0.92); -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px);
  border-top: 1px solid var(--color-border-soft);
  padding: 0.7rem var(--gutter) calc(0.7rem + env(safe-area-inset-bottom));
  display: none; align-items: center; gap: 0.9rem;
  transform: translateY(110%); transition: transform var(--dur-med) var(--ease-luxury);
}
.sticky-buy.visible { transform: none; }
.sticky-buy .sb-price { font-weight: 800; }
.sticky-buy .btn { flex: 1; }

/* ======================= 13. QUICK VIEW (MODALE) ========================= */
.modal-veil {
  position: fixed; inset: 0; z-index: 110; background: rgba(17,16,14,0.44);
  opacity: 0; visibility: hidden;
  transition: opacity 560ms cubic-bezier(0.16,1,0.3,1), visibility 0s 560ms, backdrop-filter 560ms ease;
  -webkit-backdrop-filter: blur(0); backdrop-filter: blur(0);
}
.modal-veil.open {
  opacity: 1; visibility: visible; transition-delay: 0s;
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
}
.qv {
  position: fixed; z-index: 120; inset: 0; display: grid; place-items: center;
  padding: var(--gutter); pointer-events: none;
}
.qv-card {
  pointer-events: auto; width: min(880px, 100%); max-height: 90vh; overflow: auto;
  background: var(--color-warm-white); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-float);
  display: grid; grid-template-columns: 1fr 1fr;
  opacity: 0; transform: translateY(22px) scale(0.985);
  transition: opacity 320ms var(--ease-luxury), transform 420ms var(--ease-luxury);
}
.qv.open .qv-card { opacity: 1; transform: none; }
.qv-media { background: var(--color-ivory); }
.qv-media img { width: 100%; aspect-ratio: 1; object-fit: contain; padding: 8%; background: var(--color-plate); }
.qv-body { padding: clamp(1.4rem, 3vw, 2.2rem); position: relative; display: grid; gap: 0.9rem; align-content: start; }
.qv-close { position: absolute; top: 0.9rem; right: 0.9rem; }
.qv-body h2 { font-family: var(--font-ui); font-weight: 700; font-size: var(--text-lg); line-height: 1.2; letter-spacing: -0.01em; padding-right: 2.4rem; }

/* ======================= 14. TIROIR PANIER =============================== */
.drawer {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 120;
  width: min(440px, 96vw); background: var(--color-warm-white);
  box-shadow: -30px 0 80px -30px rgba(17,16,14,0.05);
  border-top-left-radius: 18px; border-bottom-left-radius: 18px;
  transform: translateX(105%);
  transition: transform 640ms cubic-bezier(0.16, 1, 0.3, 1), box-shadow 640ms ease;
  display: flex; flex-direction: column; will-change: transform;
}
.drawer.open { transform: none; box-shadow: -30px 0 80px -30px rgba(17,16,14,0.32); }
/* Le contenu du panier entre en douceur, légèrement décalé après le panneau */
.drawer-items, .drawer-foot { opacity: 0; transition: opacity 420ms ease 220ms; }
.drawer.open .drawer-items, .drawer.open .drawer-foot { opacity: 1; }
.drawer-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 1.4rem var(--space-3) 1rem;
}
.drawer-head h2 { font-family: var(--font-ui); font-weight: 700; font-size: var(--text-md); letter-spacing: -0.01em; }
.drawer-ship { padding: 0.4rem var(--space-3) 0.2rem; }
.ship-bar { height: 3px; background: var(--color-border-soft); border-radius: 2px; overflow: hidden; }
.ship-fill { height: 100%; background: var(--color-navy); width: 0; transition: width var(--dur-med) var(--ease-luxury); }
.ship-msg { font-size: var(--text-xs); color: var(--color-muted); margin-top: 0.45rem; }
.ship-msg.ok { color: var(--color-ok); font-weight: 700; }

.drawer-items { flex: 1; overflow-y: auto; padding: 0.8rem var(--space-3); display: grid; gap: 0; align-content: start; }
.cart-line { padding-block: 1.2rem; border-bottom: 1px solid var(--color-border-soft); }
.cart-line:last-child { border-bottom: 0; }
.cart-line { display: grid; grid-template-columns: 74px 1fr auto; gap: 0.9rem; align-items: start;
  opacity: 0; transform: translateY(10px); animation: vsn-fade-up 460ms var(--ease-luxury) forwards;
  animation-delay: calc(var(--i, 0) * 60ms); }
.cart-line-media { position: relative; width: 74px; }
.cart-line-media img { width: 74px; border-radius: var(--radius); background: var(--color-plate); object-fit: contain; padding: 6%; }
.line-disc {
  position: absolute; top: -6px; left: -6px;
  background: var(--color-navy); color: #fff;
  font-size: 0.6rem; font-weight: 800; letter-spacing: 0.02em;
  padding: 0.15rem 0.4rem; border-radius: 20px; box-shadow: 0 2px 6px rgba(17,16,14,0.2);
}
.line-disc.is-free { background: var(--color-ok); }
.cart-line .n { font-weight: 700; font-size: var(--text-sm); line-height: 1.3; }
.cart-line .m { font-size: var(--text-xs); color: var(--color-muted); margin-top: 0.2rem; }
.cart-line .qty-stepper { margin-top: 0.5rem; transform: scale(0.86); transform-origin: left; }
.cart-line .p { font-weight: 700; font-size: var(--text-sm); text-align: right; }
.cart-line .pw { font-weight: 400; color: var(--color-muted); text-decoration: line-through; font-size: var(--text-xs); }
.cart-line .rm { font-size: var(--text-xs); color: var(--color-muted); text-decoration: underline; margin-top: 0.4rem; }
.cart-line .rm:hover { color: var(--color-err); }
.cart-empty { text-align: center; color: var(--color-muted); padding-block: var(--space-4); display: grid; gap: 1rem; justify-items: center; }

.drawer-foot { border-top: 1px solid var(--color-border-soft); padding: 1.1rem var(--space-3) 1.4rem; display: grid; gap: 0.5rem; }
.tot-row { display: flex; justify-content: space-between; font-size: var(--text-sm); }
.tot-row.discount { color: var(--color-ok); align-items: center; }
.disc-chip {
  display: inline-block; margin-left: 0.35rem; vertical-align: middle;
  background: var(--color-black); color: var(--color-ivory);
  font-size: 0.56rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
  padding: 0.15rem 0.45rem; border-radius: 20px;
}
.free-pill {
  background: var(--color-ok); color: #fff; font-weight: 700; font-size: var(--text-xs);
  padding: 0.12rem 0.5rem; border-radius: 20px;
}
.saved-line {
  font-size: var(--text-xs); color: var(--color-ok); font-weight: 700;
  text-align: right; margin-top: 0.1rem;
}
.tot-row.total { font-weight: 800; font-size: var(--text-md); border-top: 1px solid var(--color-border-soft); padding-top: 0.6rem; margin-top: 0.3rem; }
.drawer-foot .btn { margin-top: 0.7rem; }
.drawer-foot .band-only-note { font-size: var(--text-xs); }

/* ======================= 15. TOAST ======================================= */
.toast {
  position: fixed; z-index: 140; left: 50%; bottom: 2rem; transform: translateX(-50%);
  background: var(--color-black); color: var(--color-ivory);
  padding: 0.8rem 1.4rem; border-radius: 3px; font-size: var(--text-sm); font-weight: 600;
  display: none; align-items: center; gap: 0.6rem; box-shadow: var(--shadow-float);
}
.toast.show { display: inline-flex; animation: vsn-toast var(--toast-ms, 2600ms) var(--ease-ui) forwards; }
.toast .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--color-ok); }

/* ======================= 16. CHECKOUT & PAGES ============================ */
.page-head { padding-top: clamp(2.5rem, 5vw, 4rem); }
.page-title { font-family: var(--font-ui); font-weight: 700; font-size: var(--text-xl); line-height: 1.12; letter-spacing: -0.015em; }
.page-sub { color: var(--color-muted); margin-top: 0.7rem; max-width: 60ch; }
.prose { max-width: 68ch; display: grid; gap: 1rem; }
.prose h2 { font-weight: 700; font-size: var(--text-md); letter-spacing: -0.01em; margin-top: var(--space-2); }
.prose li { display: flex; gap: 0.6rem; }
.prose li::before { content: "—"; color: var(--color-navy); flex: none; }
.notice {
  border: 1px solid var(--color-border); border-left: 3px solid var(--color-navy);
  background: var(--color-ivory); padding: 1rem 1.2rem; border-radius: var(--radius);
  font-size: var(--text-sm); color: var(--color-charcoal); max-width: 68ch;
}

.pay-methods { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0.7rem; }
.pay-method {
  border: 1px solid var(--color-border); border-radius: 8px; padding: 1rem 0.9rem;
  text-align: center; font-weight: 700; font-size: var(--text-sm); position: relative;
  transition: border-color var(--dur-fast) var(--ease-ui), background-color var(--dur-fast) var(--ease-ui), transform var(--dur-fast) var(--ease-luxury), box-shadow var(--dur-fast) var(--ease-ui);
}
.pay-method:hover { border-color: var(--color-charcoal); transform: translateY(-2px); }
.pay-method.active {
  border-color: var(--color-black); background: var(--color-ivory);
  box-shadow: 0 6px 18px -8px rgba(17,16,14,0.3);
}
.pay-method.active::after {
  content: "✓"; position: absolute; top: 6px; right: 8px;
  font-size: 0.7rem; color: var(--color-ok); font-weight: 800;
}
.checkout-layout { display: grid; grid-template-columns: 1.2fr 0.9fr; gap: var(--space-5); align-items: start; }
.summary-card {
  background: var(--color-ivory); border: 1px solid var(--color-border-soft);
  border-radius: var(--radius-lg); padding: var(--space-3);
  position: sticky; top: calc(var(--header-h) + 1rem); display: grid; gap: 0.55rem;
  box-shadow: var(--shadow-card);
}
.summary-card .tot-row.total { border-top: 1px solid var(--color-border); padding-top: 0.7rem; margin-top: 0.4rem; }

.faq-item { border-bottom: 1px solid var(--color-border-soft); }

/* ======================= 17. FOOTER ====================================== */
.site-footer { background: var(--color-black); color: var(--color-sand-soft); margin-top: clamp(3rem, 6vw, 5rem); }
/* Cette marge respire quand la page se termine sur une section claire. Quand
   elle se termine sur une section d'encre, comme la newsletter de l'accueil,
   elle ouvre au contraire une bande ivoire de 80 px entre deux noirs : on ne
   la lit pas comme un blanc voulu, on la lit comme un trou. On la retire alors,
   et l'encre file d'un bloc jusqu'au bas de la page.
   Un navigateur qui ignorerait `:has()` garde simplement la marge : il perd le
   raccord, il ne casse rien. */
#view:has(> .section--ink:last-child) + .site-footer { margin-top: 0; }
.footer-inner { padding-block: clamp(2.75rem, 5vw, 4rem) var(--space-3); display: grid; grid-template-columns: 1.4fr 1fr 1fr 1fr; gap: var(--space-4); }
.footer-brand .logo-word { color: var(--color-warm-white); }
.footer-brand p { color: rgba(236,229,216,0.65); font-size: var(--text-sm); margin-top: 1rem; max-width: 30ch; }
.footer-col h3 { font-size: var(--text-xs); letter-spacing: var(--tracking-caps); text-transform: uppercase; color: rgba(236,229,216,0.5); margin-bottom: 1rem; font-weight: 700; }
.footer-col a { display: block; padding-block: 0.3rem; font-size: var(--text-sm); color: rgba(236,229,216,0.85); transition: color var(--dur-fast) var(--ease-ui); }
.footer-col a:hover { color: #fff; }
.footer-bottom {
  border-top: 1px solid rgba(236,229,216,0.14); padding-block: 1.3rem;
  font-size: var(--text-xs); color: rgba(236,229,216,0.55); display: grid; gap: 0.4rem;
}

/* ======================= 18. RESPONSIVE ================================== */
@media (max-width: 1024px) {
  .hero-slide {
    grid-template-columns: 1fr; gap: var(--space-2);
    padding: calc(var(--header-h) + var(--space-2)) var(--gutter) calc(var(--space-5) + 2.4rem);
  }
  .hero-visual { order: 2; margin-block: 0.6rem; }         /* label → titre → image → prix → CTA */
  .hero-copy { display: contents; }
  .hero-kicker { order: 0; } .hero-title { order: 1; }
  .hero-spec { order: 3; } .hero-sub { order: 4; }
  .hero-price { order: 5; } .hero-ctas { order: 6; }
  .hero .band-only-note { order: 7; }
  /* Les commandes du carrousel remontaient SUR la note « bracelet seul »
     (mesure : 5 px de chevauchement a 390 px). .hero-ui garde un `bottom`
     herite du temps ou elle etait en position:absolute, mais la regle de la
     section 30 la repasse en position:relative. Or sur un element relatif,
     `bottom` decale vers le haut SANS liberer de place : les deux blocs se
     superposent. On neutralise le decalage et on remet un vrai ecart. */
  .hero-ui { bottom: auto; margin-top: var(--space-3); }
  .hero-figure { width: min(340px, 88%); margin-inline: auto; }   /* même taille sur toutes les slides */
  .hero-slide::before { top: 18%; right: -30%; width: 90%; height: 52%; }

  .ed-grid { grid-template-columns: 1fr 1fr; }
  .ed-big { grid-row: auto; grid-column: 1 / 3; aspect-ratio: 16 / 10; }
  .ed-copy { grid-column: 1 / 3; }
  .story-grid { grid-template-columns: 1fr; }

  .product-layout, .checkout-layout,   .footer-inner { grid-template-columns: 1fr 1fr; }

  .life-grid { grid-template-columns: 1fr 1fr; }
  .summary-card { position: static; }
}
@media (max-width: 860px) {
  .product-layout, .checkout-layout { grid-template-columns: 1fr; }
  /* 04.09.2026 — LOGO RECENTRE. La marque tombait 54 px a gauche du centre de
     l'ecran sur un iPhone de 390 px. La cause n'etait pas le centrage mais la
     STRUCTURE : le logo vit dans `.header-left`, donc dans la meme boite que le
     burger, collee au bord gauche. La colonne du milieu, elle, porte
     `.main-nav`, qui est justement masquee sur mobile : le centre etait vide.
     `display: contents` dissout la boite de gauche sans toucher au HTML, qui
     est duplique dans theme.liquid et qu'il faudrait sinon changer deux fois.
     Le burger, le logo et le panier deviennent alors les trois items directs
     de la grille, et tombent chacun dans leur colonne. */
  .header-inner { grid-template-columns: minmax(0,1fr) auto minmax(0,1fr); }
  .header-left { display: contents; }
  .burger { justify-self: start; }
  .header-inner > .logo, .header-left > .logo { justify-self: center; }
  .header-tools { justify-self: end; }
  .main-nav { display: none; }
  .header-left { gap: 0.6rem; }
  /* langue & devise vont dans le menu ; on garde le panier visible à droite */
  .header-tools .tool-select { display: none; }
  .mobile-menu .tool-select { display: inline-block; }
  .mobile-tools { display: flex; gap: 0.8rem; margin-top: var(--space-3); }
}
@media (max-width: 560px) {
  .logo-sub { display: none; }                 /* garde le wordmark seul, plus net */
  .logo-word { font-size: 0.94rem; letter-spacing: 0.28em; }
  .header-inner { padding-inline: 1rem; }
}
@media (max-width: 640px) {
  .section { padding-block: var(--space-5); }
  .form-grid { grid-template-columns: 1fr; }

  .life-grid { grid-template-columns: 1fr; }
  .pay-methods { grid-template-columns: 1fr 1fr; }
  .slider > * { flex: 0 0 88%; }                         /* ~1,12 carte visible */
  .ed-grid { grid-template-columns: 1fr; }
  .ed-big, .ed-copy { grid-column: auto; }
  .ed-small.b { transform: none; }
  .manifesto-intro { font-size: 1.5rem; }

  .qv-card { grid-template-columns: 1fr; }
  .qv-media img { aspect-ratio: 4 / 3; }
  .hero-ctas .btn { flex: 1; }
  .sticky-buy { display: flex; }
  /* 04.09.2026 — BUG SIGNALE PAR BENJAMIN (capture du 03.09, 19h05). La barre
     d'achat est en `position: fixed` mais rien ne reservait sa hauteur : elle
     recouvrait la fin de la fiche, donc les lignes CARE et SHIPPING passaient
     dessous et devenaient illisibles. La hauteur reelle est mesuree en JS et
     posee dans --sticky-h ; la valeur ici n'est qu'un filet de securite si le
     script ne tourne pas. */
  .page-head:has(.product-layout) {
    padding-bottom: calc(var(--sticky-h, 5.5rem) + 1rem);
  }
  .newsletter form { flex-direction: column; }
  .footer-inner { grid-template-columns: 1fr; gap: var(--space-3); }
  .hero-figure { width: min(292px, 86%); }
}

/* ======================= 20. MANIFESTE =================================== */
.manifesto { padding-block: clamp(3.25rem, 6.5vw, 6rem); }
.manifesto-intro {
  font-family: var(--font-display); font-weight: 600;
  font-size: clamp(1.55rem, 3.1vw, 2.5rem); line-height: 1.18;
  letter-spacing: var(--tracking-tight); max-width: 26ch;
}
/* Sur fond encre, le manifeste tient en deux colonnes : l'aveu à gauche, les
   trois faits à droite, alignés en colonne comme une fiche technique. */
.manifesto .container {
  display: grid; grid-template-columns: 1.15fr 0.85fr;
  gap: clamp(1.6rem, 5vw, 5rem); align-items: end;
}
.manifesto-intro { color: var(--color-ivory); }
.manifesto-lines {
  display: grid; gap: 0; border-top: 1px solid rgba(243,239,230,0.22);
}
.manifesto-line {
  font-size: var(--text-sm); font-weight: 600; letter-spacing: 0;
  color: rgba(243,239,230,0.88);
  padding-block: 0.85rem; border-bottom: 1px solid rgba(243,239,230,0.22);
}
@media (max-width: 820px) {
  .manifesto .container { grid-template-columns: 1fr; align-items: start; }
  .manifesto-lines { margin-top: var(--space-3); }
}

/* ======================= 21. COLLECTION ÉDITORIALE ======================= */
.ed-grid {
  position: relative;
  display: grid; grid-template-columns: 1.25fr 0.9fr 0.9fr;
  grid-template-rows: auto auto; gap: clamp(1rem, 2.4vw, 1.8rem);
}
.ed-grid figure { border-radius: var(--radius-lg); overflow: hidden; background: var(--color-warm-white); margin: 0; }
.ed-grid figure { background: var(--color-plate); }
.ed-grid figure img { width: 100%; height: 100%; object-fit: contain; padding: 9%; transition: transform 850ms var(--ease-luxury); }
.ed-grid figure:hover img { transform: scale(1.045); }
.ed-big { grid-row: 1 / 3; aspect-ratio: 1; }
.ed-copy { grid-column: 2 / 4; align-self: center; padding-inline: clamp(0rem, 2vw, 1.5rem); }
.ed-small { aspect-ratio: 1; }
.ed-small.b { transform: translateY(clamp(0px, 2.5vw, 26px)); }   /* léger décalage éditorial */

/* ======================= 22. LIFESTYLE IMMERSIF ========================== */

.life-ph-tag {
  position: absolute; right: var(--gutter); bottom: 1rem;
  font-size: var(--text-xs); letter-spacing: var(--tracking-caps); text-transform: uppercase;
  color: rgba(251,250,247,0.4);
}
.btn--light { border-color: rgba(251,250,247,0.75); color: var(--color-warm-white); }
.btn--light:hover { background: var(--color-warm-white); color: var(--color-black); border-color: var(--color-warm-white); }

/* ======================= 24. MATIÈRE & HOTSPOTS ========================== */
.mat-stage {
  position: relative; max-width: 720px; margin-inline: auto;
  border-radius: var(--radius-lg); overflow: visible; background: var(--color-ivory);
}
.mat-stage > img { border-radius: var(--radius-lg); }
.hotspot { position: absolute; transform: translate(-50%, -50%); z-index: 2; padding: 10px; }
.hotspot-dot {
  display: block; width: 14px; height: 14px; border-radius: 50%;
  background: var(--color-warm-white); border: 1px solid var(--color-black);
  position: relative; transition: transform var(--dur-fast) var(--ease-luxury);
}
.hotspot-dot::after {
  content: ""; position: absolute; inset: 4px; border-radius: 50%; background: var(--color-black);
  transition: background var(--dur-fast) var(--ease-ui);
}
.hotspot:hover .hotspot-dot, .hotspot[aria-expanded="true"] .hotspot-dot { transform: scale(1.25); }
.hotspot[aria-expanded="true"] .hotspot-dot::after { background: var(--color-navy); }
.hotspot-tip {
  position: absolute; left: 50%; bottom: calc(100% + 10px); transform: translateX(-50%) translateY(6px);
  width: max-content; max-width: 230px; text-align: left;
  background: var(--color-black); color: var(--color-ivory);
  font-size: var(--text-xs); line-height: 1.5; padding: 0.7rem 0.9rem; border-radius: 3px;
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity var(--dur-fast) var(--ease-ui), transform var(--dur-fast) var(--ease-luxury);
}
.hotspot-tip strong { display: block; letter-spacing: 0.08em; text-transform: uppercase; margin-bottom: 0.2rem; }
.hotspot:hover .hotspot-tip, .hotspot:focus-visible .hotspot-tip, .hotspot[aria-expanded="true"] .hotspot-tip {
  opacity: 1; visibility: visible; transform: translateX(-50%) translateY(0);
}

/* ======================= 25. STORYTELLING ================================ */
.story-grid { display: grid; grid-template-columns: 1fr 1px 1fr; gap: var(--space-4); align-items: center; }

.story .section-title, .editorial .section-title { font-family: var(--font-ui); }

.story-media { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
.story-media .life-item { aspect-ratio: 1; background: var(--color-plate); }
.story-media .life-item img { object-fit: contain; padding: 10%; }
.story-media .life-item:last-child { transform: translateY(clamp(0px, 2.5vw, 26px)); }
.story-copy .btn--text { margin-top: var(--space-2); }

/* ======================= 26. CURSEUR PERSONNALISÉ ======================== */
/* Petit point discret qui SUIT le curseur natif sans le remplacer. */
.cursor {
  position: fixed; left: 0; top: 0; z-index: 300; pointer-events: none;
  transform: translate(-100px, -100px);
}
.cursor span {
  position: absolute; left: 14px; top: 14px;
  display: grid; place-items: center;
  min-width: 8px; height: 8px; border-radius: 999px;
  background: var(--color-black); color: var(--color-ivory);
  font-size: 0.6rem; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase;
  transition: min-width 200ms var(--ease-luxury), height 200ms var(--ease-luxury), padding 200ms var(--ease-ui);
  white-space: nowrap; overflow: hidden;
}
.cursor.has-label span { min-width: 52px; height: 26px; padding-inline: 0.7rem; }
@media (hover: none), (pointer: coarse) { .cursor { display: none; } }

/* ======================= 27. AVIS (DÉMO) & WHOOP ========================= */

.whoop-strip { background: var(--color-ivory); border-block: 1px solid var(--color-border-soft); }
.whoop-inner { padding-block: 1.6rem; display: grid; gap: 0.4rem; }
.whoop-inner > p:first-child { font-size: var(--text-sm); color: var(--color-charcoal); }
.whoop-inner .btn--text { margin-left: 0.4rem; font-size: var(--text-sm); }

/* ======================= 29. BANDE DE STATEMENTS ========================= */

@keyframes vsn-band { to { transform: translateX(-50%); } }

/* ======================= 30. PAGE DE SUCCÈS (CHECKOUT) =================== */
.order-success {
  position: relative; overflow: hidden;
  min-height: 74vh; display: grid; place-items: center;
  padding: var(--space-5) var(--gutter);
  background: radial-gradient(900px 500px at 50% -10%, var(--color-sand-soft), transparent 62%), var(--color-warm-white);
}
.success-card {
  position: relative; z-index: 2; text-align: center; max-width: 520px;
  display: grid; gap: 1rem; justify-items: center;
  animation: vsn-rise 700ms var(--ease-luxury);
}
.success-card .btn { margin-top: 0.8rem; }
@keyframes vsn-rise { from { opacity: 0; transform: translateY(22px); } to { opacity: 1; transform: none; } }

/* Coche qui se trace */
.success-check svg { width: 92px; height: 92px; }
.success-check circle {
  stroke: var(--color-ok); stroke-width: 2.5;
  stroke-dasharray: 151; stroke-dashoffset: 151;
  animation: vsn-draw 620ms var(--ease-luxury) 120ms forwards;
}
.success-check path {
  stroke: var(--color-ok); stroke-width: 3.5; stroke-linecap: round; stroke-linejoin: round;
  stroke-dasharray: 40; stroke-dashoffset: 40;
  animation: vsn-draw 420ms var(--ease-luxury) 620ms forwards;
}
@keyframes vsn-draw { to { stroke-dashoffset: 0; } }

/* Confettis discrets, dans les tons de la maison */
.confetti { position: absolute; inset: 0; pointer-events: none; z-index: 1; }
.confetti i {
  position: absolute; top: -12px; left: var(--x);
  width: 7px; height: 11px; border-radius: 1px;
  background: hsl(calc(var(--d) * 1deg + 20), 45%, 62%);
  opacity: 0; transform: rotate(0deg);
  animation: vsn-confetti 2.6s var(--ease-ui) var(--delay) forwards;
}
.confetti i:nth-child(3n)   { background: var(--color-navy); }
.confetti i:nth-child(3n+1) { background: var(--color-sand); }
.confetti i:nth-child(4n)   { width: 6px; height: 6px; border-radius: 50%; }
@keyframes vsn-confetti {
  0%   { opacity: 0; transform: translateY(0) rotate(0deg); }
  12%  { opacity: 1; }
  100% { opacity: 0; transform: translateY(78vh) rotate(540deg); }
}
@media (prefers-reduced-motion: reduce) {
  .confetti { display: none; }
  .success-check circle, .success-check path { animation: none; stroke-dashoffset: 0; }
  .success-card { animation: none; }
}

/* ======================= 31. LOGOS DE PAIEMENT ========================== */
.pay-method { display: flex; flex-direction: column; align-items: center; gap: 0.5rem; }
.pay-ico { display: inline-flex; height: 22px; }
.pay-ico svg { height: 22px; width: auto; color: var(--color-charcoal); }
.pay-method.active .pay-ico svg { color: var(--color-black); }
/* Sélecteurs du formulaire (pays/ville) alignés avec les inputs */
.field select { appearance: none; -webkit-appearance: none;
  background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 8" fill="none" stroke="%2380786d" stroke-width="1.5"><path d="M1 1l5 5 5-5"/></svg>');
  background-repeat: no-repeat; background-position: right 1rem center; background-size: 11px;
  padding-right: 2.4rem; cursor: pointer;
}

/* ======================= 32. BARRE DE DÉFILEMENT SLIDER ================= */
.slider-scroll {
  position: relative; height: 4px; margin: 0.6rem auto 0;
  max-width: 260px; background: var(--color-border-soft);
  border-radius: 20px; cursor: pointer; touch-action: none;
}
.slider-thumb {
  position: absolute; top: 50%; left: 0; height: 4px; width: 30%;
  transform: translateY(-50%); background: var(--color-navy);
  border-radius: 20px; cursor: grab;
  transition: background-color var(--dur-fast) var(--ease-ui), height 160ms var(--ease-luxury);
}
.slider-scroll:hover .slider-thumb { height: 6px; }
.slider-scroll.dragging .slider-thumb { cursor: grabbing; background: var(--color-black); height: 6px; }
/* zone de préhension plus large que le trait visible */
.slider-thumb::after { content: ""; position: absolute; inset: -9px 0; }
.slider-scroll:focus-visible { outline: 2px solid var(--color-navy); outline-offset: 3px; }

/* ======================= 33. BOUTON RETOUR =============================== */
.back-btn {
  display: inline-flex; align-items: center; gap: 0.5rem;
  margin-bottom: 1.4rem; padding: 0.5rem 0.9rem 0.5rem 0.7rem;
  border: 1px solid var(--color-border); border-radius: 30px;
  background: transparent; color: var(--color-charcoal);
  font-size: var(--text-xs); font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase;
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-ui),
              border-color var(--dur-fast) var(--ease-ui),
              color var(--dur-fast) var(--ease-ui);
}
.back-btn:hover { background: var(--color-black); border-color: var(--color-black); color: var(--color-warm-white); }
.back-btn .back-arrow {
  display: inline-block; font-size: 1rem; line-height: 1;
  transition: transform var(--dur-fast) var(--ease-luxury);
}
.back-btn:hover .back-arrow { transform: translateX(-4px); }
.back-btn:focus-visible { outline: 2px solid var(--color-navy); outline-offset: 3px; }

/* ======================= 21. HERO — LIGNE TECHNIQUE ======================= */
/* Le hero annonce la PHRASE portée par la pièce, puis les trois faits qui
   décident l'achat : coloris, largeur, compatibilité. */
.hero-kicker {
  font-size: var(--text-sm); font-weight: 600; color: var(--color-muted);
  display: flex; align-items: center; gap: 0.6rem;
}
/* Le badge se pose DANS la ligne du kicker : elle est deja en flex avec son
   filet, donc aucune hauteur ajoutee au-dessus du titre. */
.hero-best {
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.08em;
  text-transform: uppercase;
  /* Aucune couleur propre : le hero est sombre et le kicker y est deja clair.
     Poser une encre foncee ici rendait le badge illisible sur le fond. */
  border: 1px solid currentColor; border-radius: 2px;
  padding: 0.18em 0.5em;
}
.hero-kicker::before {
  content: ""; width: 22px; height: 1px; background: currentColor; opacity: 0.5;
}
.hero-spec {
  margin-top: var(--space-2); font-size: var(--text-sm); font-weight: 600;
  color: var(--color-charcoal); font-variant-numeric: tabular-nums;
}
.hero-price-label { font-size: var(--text-sm); color: var(--color-muted); }

/* ======================= 22. MUR DE STATEMENTS =========================== */
/* La marque vend des phrases : elles sont listées comme un index, en très
   grand, et débordent volontairement de la colonne centrale. */
.wall {
  background: var(--color-ivory-deep);
  padding-block: clamp(3.5rem, 7vw, 7rem);
  overflow: hidden;
}
.wall-intro {
  font-size: var(--text-md); color: var(--color-charcoal);
  max-width: 40ch; margin-bottom: clamp(1.6rem, 3vw, 2.8rem);
}
.wall-list { list-style: none; border-top: 1px solid var(--color-border); }
.wall-row { border-bottom: 1px solid var(--color-border); }
.wall-row a {
  display: flex; align-items: baseline; gap: clamp(0.8rem, 2vw, 2rem);
  padding: clamp(0.5rem, 1.4vw, 1rem) var(--gutter);
  max-width: var(--container); margin-inline: auto;
  position: relative; text-decoration: none; color: inherit;
}
.wall-text {
  font-family: var(--font-display); font-weight: 700;
  font-size: var(--text-wall); line-height: 1.02;
  letter-spacing: var(--tracking-tight);
  transition: color var(--dur-fast) var(--ease-ui), opacity var(--dur-fast) var(--ease-ui);
}
.wall-meta {
  font-size: var(--text-xs); color: var(--color-muted);
  white-space: nowrap; margin-left: auto; font-variant-numeric: tabular-nums;
}
/* La pièce n'apparaît qu'au survol, et seulement là où le survol existe. */
.wall-peek {
  position: absolute; right: clamp(5rem, 12vw, 11rem); top: 50%;
  width: clamp(70px, 8vw, 116px); aspect-ratio: 1; pointer-events: none;
  opacity: 0; transform: translateY(-50%) scale(0.9) rotate(-4deg);
  transition: opacity var(--dur-fast) var(--ease-luxury), transform var(--dur-fast) var(--ease-luxury);
}
.wall-peek img { width: 100%; height: 100%; object-fit: contain; }
@media (hover: hover) and (pointer: fine) {
  .wall-list:hover .wall-text { opacity: 0.34; }
  .wall-row:hover .wall-text { opacity: 1; color: var(--color-navy); }
  .wall-row:hover .wall-peek { opacity: 1; transform: translateY(-50%) scale(1) rotate(0deg); }
}
.wall-row a:focus-visible { outline: 2px solid var(--color-navy); outline-offset: -4px; }
.wall-cta { margin-top: clamp(1.4rem, 3vw, 2.4rem); }

/* ======================= 23. COMPATIBILITÉ =============================== */
/* La première question d'un acheteur de bracelet : est-ce que ça va sur MON
   tracker ? Elle occupe une section entière, sur fond bordeaux du catalogue. */
.fitcheck .fit-head { max-width: 46ch; }
.fitcheck .section-title { color: var(--color-black); }
.fit-options {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: 1px; background: rgba(243,239,230,0.22);
  border: 1px solid rgba(243,239,230,0.22);
  margin-top: clamp(1.8rem, 3.5vw, 3rem);
}
.fit-option {
  background: var(--color-black); color: var(--color-ivory);
  padding: clamp(1.3rem, 2.6vw, 2.2rem);
  display: grid; gap: 0.35rem; align-content: start;
  text-decoration: none;
  transition: background var(--dur-fast) var(--ease-ui);
}
.fit-option:hover, .fit-option:focus-visible { background: #1d1c18; outline: none; }
.fit-name {
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(1.25rem, 2.2vw, 1.7rem); letter-spacing: var(--tracking-tight);
}
.fit-count { font-size: var(--text-sm); color: rgba(243,239,230,0.72); font-variant-numeric: tabular-nums; }
.fit-go {
  font-size: var(--text-sm); font-weight: 600; margin-top: 0.7rem;
  opacity: 0; transform: translateX(-6px);
  transition: opacity var(--dur-fast) var(--ease-ui), transform var(--dur-fast) var(--ease-ui);
}
.fit-option:hover .fit-go, .fit-option:focus-visible .fit-go { opacity: 1; transform: none; color: var(--color-gold); }
.fit-none { margin-top: var(--space-3); font-size: var(--text-sm); color: rgba(243,239,230,0.72); }

/* ======================= 24. BON DE COMMANDE (ROTATION) ================== */
/* Une remise par rang n'est pas une grille de quatre cartes : c'est un bon de
   commande. Une ligne par bracelet, pointillés, prix à droite, total en bas. */
.rot-grid {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: clamp(2rem, 5vw, 5rem); align-items: start;
}
.rot-fifth { margin-top: var(--space-3); font-size: var(--text-sm); font-weight: 600; }
.rot-note { margin-top: var(--space-2); font-size: var(--text-xs); color: var(--color-muted); max-width: 52ch; }

.ticket {
  background: var(--color-warm-white);
  border: 1px solid var(--color-border);
  padding: clamp(1.3rem, 2.6vw, 2rem);
  position: relative; font-variant-numeric: tabular-nums;
  box-shadow: var(--shadow-card);
}
.ticket-head {
  display: flex; justify-content: space-between; align-items: baseline;
  padding-bottom: 0.9rem; border-bottom: 1px solid var(--color-black);
}
.ticket-brand { font-weight: 700; letter-spacing: 0.16em; font-size: var(--text-sm); }
.ticket-ref { font-size: var(--text-xs); color: var(--color-muted); }
.ticket-lines { list-style: none; }
.ticket-line {
  display: flex; align-items: center; gap: 0.6rem;
  padding-block: clamp(0.6rem, 1.4vw, 0.85rem);
  border-bottom: 1px dotted var(--color-border);
  font-size: var(--text-sm);
}
.tl-slot {
  width: 30px; height: 30px; flex: none;
  border: 1px dashed var(--color-border); border-radius: 50%;
  display: grid; place-items: center; overflow: hidden;
}
.ticket-line.is-filled .tl-slot { border-style: solid; border-color: var(--color-navy); }
.tl-slot img { width: 100%; height: 100%; object-fit: cover; animation: vsn-fade 400ms var(--ease-ui); }
.tl-name { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ticket-line.is-filled .tl-name { color: var(--color-navy); }
/* Les pointillés tiennent la ligne : c'est ce qui fait lire « addition ». */
.tl-dots {
  flex: 1 1 auto; min-width: 1rem; height: 1px;
  background-image: radial-gradient(circle, var(--color-muted) 1px, transparent 1px);
  background-size: 5px 1px; background-repeat: repeat-x; opacity: 0.55;
  transform: translateY(4px);
}
.tl-rate { font-size: var(--text-xs); color: var(--color-navy); font-weight: 700; white-space: nowrap; }
.tl-price { font-weight: 700; white-space: nowrap; min-width: 4.5ch; text-align: right; }
.ticket-total {
  display: flex; align-items: center; gap: 0.6rem;
  padding-top: 1rem; margin-top: 0.3rem;
  border-top: 1px solid var(--color-black);
  font-family: var(--font-display); font-weight: 700;
}
.tt-dots { flex: 1 1 auto; }
.tt-value { font-size: 1.35rem; letter-spacing: var(--tracking-tight); }
.ticket-msg {
  margin-top: 0.8rem; font-size: var(--text-sm);
  font-weight: 600; color: var(--color-navy); min-height: 1.4em;
}
/* Bord déchiré du bas, comme un ticket détaché de sa souche. */
.ticket-tear {
  position: absolute; left: 0; right: 0; bottom: -9px; height: 9px;
  background: radial-gradient(circle at 5px -2px, transparent 0 6px, var(--color-warm-white) 6px);
  background-size: 14px 9px; background-repeat: repeat-x;
  filter: drop-shadow(0 1px 0 var(--color-border));
}

@media (max-width: 900px) {
  .fit-options { grid-template-columns: 1fr; }
  .rot-grid { grid-template-columns: 1fr; }
  .wall-row a { gap: 0.7rem; }
  .wall-peek { display: none; }
}

/* ======================= 25. RESPONSIVE (FIN DE CASCADE) ================== */
/* Le bloc responsive n° 18 est placé AVANT les styles des sections 20 à 24 :
   à spécificité égale, ce sont ces derniers qui gagnent, et les adaptations
   mobiles de la collection éditoriale et du récit ne
   s'appliquaient jamais. Elles sont rejouées ici, en fin de cascade.
   (Défaut présent avant la refonte, corrigé au passage.) */
@media (max-width: 1024px) {
  .ed-grid { grid-template-columns: 1fr 1fr; }
  .ed-big { grid-row: auto; grid-column: 1 / 3; aspect-ratio: 16 / 10; }
  .ed-copy { grid-column: 1 / 3; }
  .story-grid { grid-template-columns: 1fr; }
}
@media (max-width: 640px) {
  .ed-grid { grid-template-columns: 1fr; }
  .ed-big, .ed-copy { grid-column: auto; }
  .ed-small.b { transform: none; }
  /* Le ticket reste lisible : on resserre plutôt que de laisser tronquer. */
  .ticket { padding: 1.1rem 0.95rem; }
  .ticket-line { gap: 0.45rem; font-size: 0.82rem; }
  .tl-slot { width: 26px; height: 26px; }
}

/* ======================= 26. PROFONDEUR 3D =============================== */
/* De la vraie 3D, en transformations CSS : la scène a une perspective, le
   sujet s'incline vers le curseur, son ombre part dans l'autre sens et un
   reflet balaie la surface. Aucune librairie : le site reste sans dépendance
   et s'ouvre encore par double-clic sur index.html.
   Règle : le VOLUME est permanent (il donne la matière), le MOUVEMENT n'existe
   qu'à la souris et disparaît en reduced-motion. */
.stage3d { perspective: 1100px; perspective-origin: 50% 45%; }
.stage3d-inner {
  position: relative;
  transform-style: preserve-3d;
  transition: transform 620ms var(--ease-luxury);
  will-change: transform;
}
.stage3d.is-live .stage3d-inner { transition: transform 120ms linear; }

/* La plaque reste en fond, le produit avance vers le visiteur : c'est cet
   écart qui crée la profondeur, pas l'inclinaison. */
.stage-plate {
  position: absolute; inset: 0;
  background: var(--color-plate);
  border-radius: var(--radius-lg);
  transform: translateZ(-40px) scale(1.02);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.6);
}
.stage-subject { position: relative; transform: translateZ(52px); transform-style: preserve-3d; }
/* Ombre portée réelle : elle vit sur son propre plan, sous le sujet. */
.stage-shadow {
  position: absolute; left: 50%; bottom: 7%;
  width: 56%; height: 11%;
  transform: translate3d(-50%, 0, -30px);
  background: radial-gradient(ellipse at center, rgba(17,17,15,0.32), transparent 68%);
  filter: blur(13px);
  transition: transform 620ms var(--ease-luxury), opacity 620ms var(--ease-luxury);
  pointer-events: none;
}
.stage3d.is-live .stage-shadow { transition: transform 120ms linear; }
/* Reflet : une bande de lumière qui traverse quand l'objet bouge. */
.stage-gloss {
  position: absolute; inset: 0; border-radius: var(--radius-lg);
  transform: translateZ(60px);
  background: linear-gradient(105deg, transparent 38%, rgba(255,255,255,0.55) 50%, transparent 62%);
  opacity: 0; mix-blend-mode: soft-light; pointer-events: none;
  transition: opacity 400ms var(--ease-ui);
}
.stage3d.is-live .stage-gloss { opacity: 1; }

/* Sans souris (tactile) et en reduced-motion : on garde le volume, on retire
   le suivi du curseur. */
@media (hover: none), (pointer: coarse) {
  .stage3d-inner { transform: none !important; }
  .stage-gloss { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .stage3d-inner, .stage-shadow { transition: none; transform: none !important; }
  .stage-gloss { display: none; }
  .stage-plate, .stage-subject { transform: none; }
}

/* ======================= 27. COLLECTION PAR STATEMENT ==================== */
/* La phrase devient le titre de sa propre page, à l'échelle du hero. */
.story-statement {
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(2.4rem, 6.4vw, 5.4rem); line-height: 0.95;
  letter-spacing: var(--tracking-tight); margin-top: var(--space-1);
  max-width: 16ch;
}
.sb-grid {
  display: grid; grid-template-columns: 1.05fr 0.95fr;
  gap: clamp(1.8rem, 4.5vw, 4.5rem); align-items: center;
}
.sb-stage { width: 100%; }
.sb-stage .stage3d-inner {
  aspect-ratio: 1; display: grid; place-items: center;
}
.sb-stage .stage-plate {
  background: radial-gradient(130% 110% at 50% 0%, #ffffff 0%, var(--color-plate) 70%);
  border: 1px solid rgba(255,255,255,0.85); border-radius: 20px;
  box-shadow: 0 1px 0 rgba(255,255,255,0.9) inset, 0 34px 66px -26px rgba(17,17,15,0.28);
}
.sb-stage .stage-gloss { border-radius: 20px; }
.sb-stage img {
  width: 80%; height: 80%; object-fit: contain;
  filter: drop-shadow(0 24px 36px rgba(17,17,15,0.17));
}

/* Le nuancier : une bande par coloris, la matière en aplat à gauche. */
.swatches { list-style: none; margin-top: var(--space-2); border-top: 1px solid var(--color-border); }
.swatch-row {
  width: 100%; display: flex; align-items: center; gap: 1rem;
  padding: 0.85rem 0.6rem; background: none; border: 0;
  border-bottom: 1px solid var(--color-border);
  cursor: pointer; text-align: left; font: inherit; color: inherit;
  transition: background var(--dur-fast) var(--ease-ui), padding-left var(--dur-fast) var(--ease-ui);
}
.swatch-row:hover { background: var(--color-warm-white); padding-left: 1.1rem; }
.swatch-row.is-on { background: var(--color-warm-white); padding-left: 1.1rem; }
.swatch-row.is-on .sw-name { color: var(--color-navy); }
.sw-chip {
  width: 42px; height: 42px; flex: none; border-radius: 3px;
  background: var(--c); border: 1px solid rgba(17,17,15,0.16);
  box-shadow: inset 0 1px 2px rgba(255,255,255,0.35);
  transition: transform var(--dur-fast) var(--ease-luxury);
}
.swatch-row.is-on .sw-chip { transform: scale(1.08); box-shadow: 0 0 0 2px var(--color-black); }
.sw-text { display: grid; gap: 0.15rem; }
.sw-name { font-weight: 700; font-size: var(--text-base); }
.sw-fit { font-size: var(--text-xs); color: var(--color-muted); }
.sw-new {
  margin-left: auto; font-size: 0.6rem; font-weight: 700; letter-spacing: 0.1em;
  background: var(--color-black); color: var(--color-ivory); padding: 0.25rem 0.5rem;
}
.sb-buy { display: flex; align-items: center; gap: 1.2rem; margin-top: var(--space-3); flex-wrap: wrap; }
.sb-price { display: flex; align-items: baseline; gap: 0.6rem; }
.sb-price .now { font-family: var(--font-display); font-weight: 700; font-size: 1.5rem; }
.sb-price .was { color: var(--color-muted); text-decoration: line-through; font-size: var(--text-sm); }
.sb-fits { margin-top: var(--space-2); font-size: var(--text-sm); color: var(--color-muted); }

/* Passer d'une phrase à l'autre sans repasser par la grille. */
.story-jump { list-style: none; display: flex; flex-wrap: wrap; gap: 0.5rem 1.6rem; margin-top: var(--space-2); }
.story-jump a {
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(1rem, 1.9vw, 1.45rem); letter-spacing: var(--tracking-tight);
  text-decoration: none; color: var(--color-muted);
  transition: color var(--dur-fast) var(--ease-ui);
}
.story-jump a:hover { color: var(--color-black); }

@media (max-width: 860px) {
  .sb-grid { grid-template-columns: 1fr; }
}

/* ======================= 28. VITRINE EN ANNEAU (3D) ====================== */
/* Les pièces sont posées sur un cercle réel : chacune tourne de son angle
   puis part vers l'extérieur. On tourne le cercle entier. Un bracelet est un
   anneau — la collection se présente comme elle se porte. */
.ring-scene {
  position: relative;
  background: var(--color-ivory-deep);
  padding-block: clamp(2rem, 4.5vw, 4rem) clamp(1.4rem, 3vw, 2.4rem);
  overflow: hidden; cursor: grab; touch-action: pan-y;
  --radius: 460px;
  --card: 300px;
}
.ring-scene:active { cursor: grabbing; }
.ring-scene:focus-visible { outline: 2px solid var(--color-navy); outline-offset: -4px; }
.ring-stage {
  position: relative; height: clamp(240px, 32vw, 380px);
  perspective: 1500px; perspective-origin: 50% 46%;
}
.ring-track {
  position: absolute; inset: 0;
  transform-style: preserve-3d;
  transform: translateZ(calc(var(--radius) * -1)) rotateY(var(--rot, 0deg));
}
.ring-item {
  position: absolute; top: 50%; left: 50%;
  width: var(--card); height: var(--card);
  margin: calc(var(--card) / -2) 0 0 calc(var(--card) / -2);
  transform: rotateY(calc(var(--i) * var(--step))) translateZ(var(--radius));
  display: grid; place-items: center;
  transition: opacity 400ms var(--ease-ui), filter 400ms var(--ease-ui);
  opacity: 0.34; filter: saturate(0.6);
  /* Les pièces de l'autre côté du cercle nous montrent leur dos : on les
     masque, sinon on voit au travers de l'anneau (et les PNG dont le fond
     n'est pas encore détouré apparaissent en plaques claires). */
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}
.ring-item img {
  width: 100%; height: 100%; object-fit: contain;
  filter: drop-shadow(0 22px 30px rgba(17,17,15,0.22));
  pointer-events: none;
}
/* La pièce de face reprend sa couleur et sa netteté : c'est elle qu'on lit. */
.ring-item.is-front { opacity: 1; filter: none; }
.ring-item.is-front img { filter: drop-shadow(0 30px 42px rgba(17,17,15,0.3)); }
/* Sol : une ombre unique sous l'anneau, qui ancre la scène. */
.ring-floor {
  position: absolute; left: 50%; bottom: 4%;
  width: min(560px, 70%); height: 34px; transform: translateX(-50%);
  background: radial-gradient(ellipse at center, rgba(17,17,15,0.22), transparent 70%);
  filter: blur(12px);
}
.ring-readout {
  position: relative; text-align: center;
  max-width: var(--container); margin-inline: auto; padding-inline: var(--gutter);
}
.ring-name {
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(1.4rem, 3.4vw, 2.6rem); letter-spacing: var(--tracking-tight);
  line-height: 1.05;
}
.ring-hint { font-size: var(--text-xs); color: var(--color-muted); margin-top: 0.5rem; }

@media (max-width: 900px) { .ring-scene { --radius: 300px; --card: 200px; } }
@media (max-width: 560px) { .ring-scene { --radius: 210px; --card: 150px; } }

/* Sans mouvement : l'anneau devient une simple rangée lisible. */
@media (prefers-reduced-motion: reduce) {
  .ring-stage { perspective: none; height: auto; }
  .ring-track { position: static; transform: none; display: flex; gap: 1rem; overflow-x: auto; padding-bottom: 1rem; }
  .ring-item {
    position: static; margin: 0; transform: none; opacity: 1; filter: none;
    flex: 0 0 clamp(130px, 34vw, 190px); height: auto; aspect-ratio: 1;
  }
  .ring-floor { display: none; }
  .ring-hint { display: none; }
}

/* ======================= 29. FICHE PRODUIT — EN-TÊTE ===================== */
/* La fiche s'ouvre comme le hero : la phrase d'abord, à l'échelle, puis les
   faits sur une seule ligne. Le nom du coloris ne vole plus la vedette. */
.product-head { margin-bottom: var(--space-4); }
.product-head .label a { color: inherit; text-decoration: none; }
.product-head .label a:hover { color: var(--color-navy); text-decoration: underline; text-underline-offset: 3px; }
.product-statement {
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(2.2rem, 5.6vw, 4.6rem); line-height: 0.95;
  letter-spacing: var(--tracking-tight); margin-top: var(--space-1);
  max-width: 18ch;
}
.product-spec {
  display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap;
  margin-top: var(--space-2);
  font-size: var(--text-sm); font-weight: 600; color: var(--color-charcoal);
}

/* ======================= 30. PIÈCES EN APESANTEUR ======================== */
/* Des bracelets dérivent au fond du hero, à des profondeurs différentes, et
   tournent lentement sur eux-mêmes. Ils ne sont pas décoratifs : ce sont les
   vraies pièces du catalogue, floutées par la distance. */
.hero-drift {
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  perspective: 1400px; overflow: hidden;
}
.hero-drift .drift {
  position: absolute;
  width: clamp(120px, 15vw, 230px); aspect-ratio: 1;
  object-fit: contain;
  opacity: 0.2;
  filter: blur(1.5px) drop-shadow(0 20px 40px rgba(0,0,0,0.5));
  transform-style: preserve-3d;
  will-change: transform;
}
.hero-drift .d1 { left: 6%;  top: 16%; animation: vsn-drift-a 34s ease-in-out infinite; }
.hero-drift .d2 { left: 30%; bottom: 8%; animation: vsn-drift-b 41s ease-in-out infinite; opacity: 0.14; }
.hero-drift .d3 { right: 30%; top: 8%;  animation: vsn-drift-c 47s ease-in-out infinite; opacity: 0.12; }
.hero-drift .d4 { right: 6%;  bottom: 12%; animation: vsn-drift-a 39s ease-in-out infinite reverse; opacity: 0.16; }

@keyframes vsn-drift-a {
  0%   { transform: translate3d(0,0,-160px)      rotateY(0deg)   rotateZ(-6deg); }
  33%  { transform: translate3d(46px,-56px,-40px) rotateY(140deg) rotateZ(4deg); }
  66%  { transform: translate3d(-30px,-24px,-200px) rotateY(250deg) rotateZ(-3deg); }
  100% { transform: translate3d(0,0,-160px)      rotateY(360deg) rotateZ(-6deg); }
}
@keyframes vsn-drift-b {
  0%   { transform: translate3d(0,0,-220px)       rotateY(20deg)  rotateZ(5deg); }
  50%  { transform: translate3d(-58px,-70px,-90px) rotateY(200deg) rotateZ(-6deg); }
  100% { transform: translate3d(0,0,-220px)       rotateY(380deg) rotateZ(5deg); }
}
@keyframes vsn-drift-c {
  0%   { transform: translate3d(0,0,-260px)      rotateY(-10deg) rotateZ(-8deg); }
  50%  { transform: translate3d(40px,62px,-120px) rotateY(170deg) rotateZ(6deg); }
  100% { transform: translate3d(0,0,-260px)      rotateY(350deg) rotateZ(-8deg); }
}
/* Le contenu du hero passe devant les pièces en dérive. */
.hero-stage, .hero-ui { position: relative; z-index: 2; }

@media (max-width: 860px) { .hero-drift .d2, .hero-drift .d3 { display: none; } }
@media (prefers-reduced-motion: reduce) { .hero-drift { display: none; } }

/* ======================= 31. RAYONS PAR PHRASE =========================== */
/* Une phrase est un rayon, pas une carte produit : sa pièce en 3D, ses
   coloris en pastilles, et l'état réel du stock. */
.chapter-list {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: clamp(1.2rem, 2.6vw, 2.2rem);
}
.chapter { display: grid; gap: 0.9rem; }
.chapter-visual {
  display: block; position: relative;
  background: linear-gradient(165deg, var(--color-plate), var(--color-ivory-deep));
  border-radius: var(--radius-lg); aspect-ratio: 4 / 3;
  overflow: visible; perspective: 900px;
}
.chapter-visual .stage3d-inner { display: grid; place-items: center; height: 100%; }
.chapter-visual img {
  width: 74%; height: 74%; object-fit: contain;
  filter: drop-shadow(0 18px 26px rgba(17,17,15,0.24));
  /* Chaque rayon respire à son propre rythme : la grille ne se fige jamais. */
  animation: vsn-hover-piece 7s ease-in-out infinite;
}
.chapter:nth-child(3n+2) .chapter-visual img { animation-duration: 8.5s; animation-delay: -2s; }
.chapter:nth-child(3n+3) .chapter-visual img { animation-duration: 9.5s; animation-delay: -4s; }
@keyframes vsn-hover-piece {
  0%,100% { transform: translateY(0) rotateY(-9deg)  rotateX(3deg); }
  50%     { transform: translateY(-11px) rotateY(9deg) rotateX(-2deg); }
}
.chapter-visual .stage-shadow {
  bottom: 6%; width: 52%; height: 8%;
  background: radial-gradient(ellipse at center, rgba(17,17,15,0.3), transparent 70%);
}
.chapter-name {
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(1.1rem, 1.8vw, 1.4rem); line-height: 1.06;
  letter-spacing: var(--tracking-tight);
}
.chapter-name a { text-decoration: none; color: inherit; }
.chapter-name a:hover { color: var(--color-navy); }
.chapter-meta { font-size: var(--text-xs); color: var(--color-muted); margin-top: 0.2rem; }
.chapter-dots { list-style: none; display: flex; gap: 0.4rem; margin-top: 0.55rem; }
.chapter-dots a {
  display: block; width: 20px; height: 20px; border-radius: 3px;
  background: var(--c); border: 1px solid rgba(17,17,15,0.2);
  transition: transform var(--dur-fast) var(--ease-luxury);
}
.chapter-dots a:hover { transform: scale(1.18); }
.chapter-dots a.is-out { opacity: 0.32; position: relative; }
.chapter-dots a.is-out::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(45deg, transparent 44%, var(--color-err) 46%, var(--color-err) 54%, transparent 56%);
}

/* ======================= 32. ÉTAT DU STOCK ============================== */
.chapter-stock, .card-stock, .sw-stock {
  font-size: var(--text-xs); color: var(--color-muted);
  font-variant-numeric: tabular-nums;
}
.chapter-stock { margin-top: 0.5rem; }
.card-stock { margin-top: 0.3rem; }
.sw-stock { display: block; margin-top: 0.1rem; }
/* Les deux états qui décident un achat sortent du gris. */
.chapter-stock.is-low, .card-stock.is-low, .sw-stock.is-low {
  color: var(--color-navy); font-weight: 700;
}
.chapter-stock.is-out, .card-stock.is-out, .sw-stock.is-out {
  color: var(--color-err); font-weight: 700;
}
.swatch-row:has(.sw-stock.is-out) .sw-chip { opacity: 0.4; }

/* ======================= 33. RYTHME SOMBRE / CLAIR ====================== */
/* Les blocs se touchent FRANCHEMENT : pas de dégradé de raccord entre deux
   sections. Un fondu entre un ivoire et une encre produit une bande grise qui
   n'appartient à personne — c'est plus sale qu'une arête nette. */

/* Le mur de statements devient le grand moment sombre de la page : les onze
   phrases en clair sur encre, séparées par des filets d'or très fins. */
.wall--ink { background: var(--color-black); color: var(--color-ivory); }
.wall--ink .wall-intro { color: rgba(243,239,230,0.78); }
.wall--ink .wall-list { border-top-color: rgba(214,183,107,0.28); }
.wall--ink .wall-row { border-bottom-color: rgba(214,183,107,0.18); }
.wall--ink .wall-meta { color: rgba(243,239,230,0.45); }
.wall--ink .wall-cta { color: var(--color-ivory); }
@media (hover: hover) and (pointer: fine) {
  .wall--ink .wall-list:hover .wall-text { opacity: 0.26; }
  .wall--ink .wall-row:hover .wall-text { opacity: 1; color: var(--color-gold); }
}

/* Sur fond sombre, l'accent est TOUJOURS l'or ; sur fond clair, le bleu nuit.
   Les deux ne se croisent jamais, c'est ce qui tient la page ensemble. */
.section--ink .label, .section--wine .label { color: rgba(243,239,230,0.62); }
.section--ink .btn--text, .wall--ink .btn--text { color: var(--color-ivory); }
.section--ink .btn--text:hover, .wall--ink .btn--text:hover { color: var(--color-gold); }
.section--ink .section-title { color: var(--color-ivory); }

/* Newsletter de clôture : elle reprend la lumière du hero. */
.newsletter.section--ink { text-align: center; }
.newsletter.section--ink .section-sub { color: rgba(243,239,230,0.66); }
.newsletter.section--ink input {
  background: rgba(243,239,230,0.06); border-color: rgba(243,239,230,0.28);
  color: var(--color-ivory);
}
.newsletter.section--ink input::placeholder { color: rgba(243,239,230,0.45); }
.newsletter.section--ink .btn--solid {
  background: var(--color-ivory); color: var(--color-black); border-color: var(--color-ivory);
}
.newsletter.section--ink .form-msg { color: rgba(243,239,230,0.8); }

/* Le manifeste repasse en clair : on annule l'habillage sombre hérité. */
.manifesto.section--paper .manifesto-intro { color: var(--color-black); }
.manifesto.section--paper .manifesto-lines { border-top-color: var(--color-border); }
.manifesto.section--paper .manifesto-line {
  color: var(--color-charcoal); border-bottom-color: var(--color-border);
}

/* La compatibilité repasse en clair : encre sur ivoire, accent bleu nuit. */
.fitcheck .fit-none { color: var(--color-muted); }

/* ======================= 34. PARALLAXE AU SCROLL ========================= */
/* --para est écrit par le JS ; le CSS ne fait que l'appliquer. Un élément qui
   se déplace moins vite que la page paraît plus loin : c'est ce décalage qui
   crée la profondeur, pas un effet ajouté par-dessus. */
[data-para] {
  transform: translate3d(0, var(--para, 0px), 0);
  will-change: transform;
}
/* La collection éditoriale et le récit gardent leurs propres transitions
   d'image : la parallaxe agit sur le conteneur, jamais sur l'image elle-même. */
.ed-grid figure[data-para], .life-item[data-para], .mat-stage[data-para] {
  transition: none;
}
@media (prefers-reduced-motion: reduce) {
  [data-para] { transform: none !important; }
}

/* ======================= 35. VITRINE PRODUIT ============================= */
/* La galerie de la fiche passe en vitrine sombre : le produit y est éclairé
   comme dans le hero. Réservé aux visuels réellement détourés — un PNG à fond
   blanc y dessinerait un rectangle (d'où .gallery-main--dark, posé par le JS
   selon le champ opaqueBg du catalogue). */
.gallery-main--dark .stage-plate {
  background:
    radial-gradient(70% 60% at 50% 42%, rgba(214,183,107,0.16), transparent 70%),
    linear-gradient(165deg, #1b1a16 0%, var(--color-black) 60%, #0c0c0a 100%);
  border-radius: var(--radius-lg);
  box-shadow: 0 30px 60px -28px rgba(0,0,0,0.55);
}
.gallery-main--dark img {
  filter:
    drop-shadow(0 26px 40px rgba(0,0,0,0.5))
    drop-shadow(0 0 44px rgba(255,240,210,0.13));
  /* La pièce respire dans sa vitrine, comme dans le hero. */
  animation: vsn-levitate-soft 12s ease-in-out infinite;
}
@keyframes vsn-levitate-soft {
  0%,100% { transform: translate3d(0,0,40px) rotateY(-8deg) rotateX(3deg); }
  50%     { transform: translate3d(0,-12px,60px) rotateY(8deg) rotateX(-2deg); }
}
.gallery-main--dark .stage-shadow {
  background: radial-gradient(ellipse at center, rgba(0,0,0,0.55), transparent 70%);
}
.gallery-main.is-live img { animation-play-state: paused; }
@media (prefers-reduced-motion: reduce) {
  .gallery-main--dark img { animation: none; }
}

/* ======================= 36. TRANSITION ENTRE PAGES ====================== */
/* Un voile encre balaie l'écran au changement de page : la navigation devient
   un mouvement continu au lieu d'un remplacement brutal du contenu. */
.page-veil {
  position: fixed; inset: 0; z-index: 200; pointer-events: none;
  background: var(--color-black);
  transform: scaleY(0); transform-origin: 50% 100%;
}
.page-veil.is-in {
  transform: scaleY(1); transform-origin: 50% 100%;
  transition: transform 340ms cubic-bezier(0.7, 0, 0.84, 0);
}
.page-veil.is-out {
  transform: scaleY(0); transform-origin: 50% 0%;
  transition: transform 420ms cubic-bezier(0.16, 1, 0.3, 1);
}
/* 04.09.2026 — `both` remplace par `backwards`, et ce n'est pas cosmetique.
   `fill-mode: both` fait RETENIR l'etat final par l'element une fois
   l'animation finie. Or cette animation touche `transform` : tant qu'elle est
   retenue, `#view` compte comme transforme, meme si la valeur d'arrivee est
   `none`. Un ancetre transforme devient le bloc de reference de tous ses
   descendants, ce qui neutralise `position: sticky` a l'interieur, en silence
   et sans la moindre erreur. C'est ce qui empechait la galerie de la fiche de
   suivre la lecture. `backwards` pose l'etat de depart AVANT le demarrage et
   ne retient plus rien apres : l'animation d'entree est identique a l'oeil, et
   le collage redevient possible. Meme famille de piege que la regle maison
   « backwards, jamais forwards ». */
#view { animation: vsn-page-in 520ms var(--ease-luxury) backwards; }
@keyframes vsn-page-in {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .page-veil { display: none; }
  #view { animation: none; }
}

/* ======================= 37. SECTIONS UTILES ============================= */
/* « Vous portez lequel ? » et « Composez votre rotation » étaient deux pavés
   blancs sans relief. Elles se détachent maintenant par leur fond soutenu et
   par une composition propre, pas par une couleur criarde de plus. */

/* Compatibilité : les trois modèles deviennent trois blocs francs, séparés par
   un filet d'encre, avec un chiffre lisible de loin. */
.fitcheck.section--deep .fit-options {
  background: var(--color-black);
  border: 1px solid var(--color-black);
  gap: 1px;
}
.fitcheck.section--deep .fit-option {
  background: var(--color-warm-white); color: var(--color-black);
  padding: clamp(1.5rem, 3vw, 2.4rem);
  position: relative; overflow: hidden;
}
/* L'encre monte du bas au survol : le bloc bascule, il ne se contente pas de
   changer de teinte. */
.fitcheck.section--deep .fit-option::before {
  content: ""; position: absolute; inset: 0; background: var(--color-black);
  transform: translateY(100%); transition: transform 420ms var(--ease-luxury);
}
.fitcheck.section--deep .fit-option > * { position: relative; z-index: 1; }
.fitcheck.section--deep .fit-option:hover::before,
.fitcheck.section--deep .fit-option:focus-visible::before { transform: none; }
.fitcheck.section--deep .fit-option:hover,
.fitcheck.section--deep .fit-option:focus-visible { color: var(--color-ivory); outline: none; }
.fitcheck.section--deep .fit-option:hover .fit-count { color: rgba(243,239,230,0.68); }
.fitcheck.section--deep .fit-option:hover .fit-go { color: var(--color-gold); }
.fitcheck.section--deep .fit-name {
  font-size: clamp(1.4rem, 2.6vw, 2rem);
}
.fitcheck.section--deep .fit-count {
  font-size: var(--text-base); color: var(--color-muted);
  transition: color 420ms var(--ease-luxury);
}

/* Offre : le bon de commande est déjà une forme forte, il lui manquait un
   fond qui le fasse exister. On le décolle et on l'appuie. */
.rotation.section--deep .ticket {
  background: var(--color-warm-white);
  border-color: var(--color-black);
  box-shadow: 0 26px 54px -30px rgba(17,17,15,0.45);
}
.rotation.section--deep .ticket-tear {
  background: radial-gradient(circle at 5px -2px, transparent 0 6px, var(--color-warm-white) 6px);
  background-size: 14px 9px; background-repeat: repeat-x;
}

/* Le plateau porte désormais la hauteur de la slide la plus haute : sur les
   slides plus courtes, la mention légale se retrouvait sous les contrôles du
   carrousel. On réserve leur bande. */
.hero-slide { padding-bottom: clamp(5.5rem, 12vh, 7rem); }
@media (max-width: 1024px) {
  .hero-slide { padding-bottom: clamp(6.5rem, 15vh, 8.5rem); }
}
/* Le bleu nuit est un accent de fond CLAIR : sur l'encre du hero, la
   pagination reprend la lumière dorée. */
.hero .hero-pag-cur { color: var(--color-gold); }
.hero .hero-pag-total { color: rgba(243,239,230,0.45); }

/* ===========================================================================
   26. DÉPOUILLEMENT, SIGNATURE, ÉPUISÉ                        (mise à jour 1.1.0)
   ---------------------------------------------------------------------------
   Trois surfaces nées du §1 et du §7 : voter pour la prochaine collection,
   laisser son adresse, signaler un coloris épuisé.

   Parti pris : aucune de ces trois surfaces n'a le droit de ressembler à un
   composant d'application. Pas de carte arrondie, pas de barre de progression,
   pas de bouton pilule coloré. On reprend le vocabulaire déjà posé par le bon
   de commande de la rotation : filets, pointillés, chiffres alignés à droite.
   =========================================================================== */

/* --- Le dépouillement ---------------------------------------------------- */
/* ===========================================================================
   LE SCRUTIN
   Troisieme dessin. Les deux premiers echouaient pour la meme raison : ils
   traitaient un vote comme une liste. On ne choisit pas une phrase dans un
   tableau, on la choisit en la VOYANT.

   D'ou la scene : la piece candidate en grand sur son plateau, sa phrase au
   corps d'affiche, son decompte, le geste. A cote, les dix phrases numerotees
   comme sur un bulletin. On parcourt du regard, on tape, la piece change.

   Le fond quitte l'encre pour le sable. Le noir ecrasait des visuels qui sont
   clairs ; deux d'entre eux gardent un fond gris opaque et n'existent que
   posees sur un plateau, ce que le sable permet et l'encre interdisait ; et
   la page comptait deja quatre plages sombres. Sur clair, l'accent redevient
   le bleu nuit, comme partout ailleurs sur ivoire.
   =========================================================================== */
.ballot {
  background:
    radial-gradient(120% 80% at 12% 0%, rgba(255,255,255,0.55) 0%, transparent 58%),
    var(--color-sand-soft);
}
.ballot-head { margin-bottom: var(--space-5); max-width: 56ch; }

.ballot-grid {
  display: grid; grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr);
  gap: clamp(2rem, 5vw, 5rem); align-items: start;
}

/* --- La scene ------------------------------------------------------------- */
.ballot-stage { position: sticky; top: calc(var(--h-header, 72px) + var(--space-3)); }

.bs-plate {
  position: relative; aspect-ratio: 1; display: grid; place-items: center;
  background: radial-gradient(130% 110% at 50% 0%, #ffffff 0%, var(--color-plate) 72%);
  border: 1px solid rgba(255,255,255,0.9); border-radius: 22px;
  box-shadow: 0 1px 0 rgba(255,255,255,0.9) inset,
              0 38px 74px -30px rgba(17,17,15,0.30);
  overflow: hidden;
}
/* Une lueur tres douce derriere la piece : sans elle, un bracelet sombre se
   colle au plateau et perd son relief. */
.bs-glow {
  position: absolute; inset: 16% 12%; border-radius: 50%;
  background: radial-gradient(circle, rgba(20,35,63,0.09) 0%, transparent 68%);
}
.bs-img {
  position: relative; width: 82%; height: 82%; object-fit: contain;
  filter: drop-shadow(0 26px 40px rgba(17,17,15,0.20));
  transition: opacity 220ms var(--ease-ui), transform 420ms var(--ease-luxury);
}
.bs-img.is-swapping { opacity: 0; transform: scale(0.965); }

.bs-copy { margin-top: var(--space-3); }
.bs-label {
  font-size: var(--text-xs); letter-spacing: var(--tracking-caps);
  text-transform: uppercase; color: var(--color-muted); margin-bottom: 0.5rem;
}
.bs-title {
  font-family: var(--font-display);
  font-size: clamp(1.9rem, 4.6vw, 3rem); font-weight: 700;
  letter-spacing: var(--tracking-tight); line-height: 1.02;
  color: var(--color-black); text-wrap: balance;
}
.bs-tally { margin-top: 0.9rem; color: var(--color-muted); font-size: var(--text-sm); }
.bs-tally strong {
  font-family: var(--font-display); font-size: 1.45rem; font-weight: 700;
  color: var(--color-navy); font-variant-numeric: tabular-nums;
  margin-right: 0.15rem;
}
.bs-share::before { content: "·"; margin: 0 0.45rem; color: var(--color-border); }

.bs-acts { display: flex; flex-wrap: wrap; gap: 0.7rem; margin-top: var(--space-3); }
.ballot .btn--solid[disabled] { opacity: 1; background: var(--color-navy); border-color: var(--color-navy); cursor: default; }

/* Pendant l'appel reseau : la scene s'assourdit, on sait que ca part. */
.ballot.is-casting .bs-plate { opacity: 0.72; }
.ballot.is-casting .bs-plate { transition: opacity var(--dur-fast) var(--ease-ui); }

/* --- Le bulletin ---------------------------------------------------------- */
.ballot-list {
  list-style: none; margin: 0; padding: 0;
  border-top: 1px solid var(--color-border);
  counter-reset: bulletin;
}
.ballot-row { border-bottom: 1px solid var(--color-border); }

.ballot-hit {
  display: grid; width: 100%;
  grid-template-columns: 2.4rem minmax(0, 1fr) auto auto;
  align-items: baseline; gap: 0 var(--space-2);
  padding: 0.95rem 0.6rem 0.85rem 0;
  font: inherit; text-align: left; background: none; border: 0;
  color: inherit; cursor: pointer;
  transition: padding-left var(--dur-fast) var(--ease-ui),
              background var(--dur-fast) var(--ease-ui);
}
.ballot-no {
  font-size: var(--text-xs); color: var(--color-muted);
  font-variant-numeric: tabular-nums; letter-spacing: 0.08em;
}
.ballot-text {
  font-family: var(--font-display);
  font-size: clamp(1.05rem, 1.9vw, 1.4rem); font-weight: 600;
  letter-spacing: var(--tracking-tight); line-height: 1.15;
  color: var(--color-charcoal);
  transition: color var(--dur-fast) var(--ease-ui);
}
.ballot-num {
  font-size: var(--text-sm); color: var(--color-muted);
  font-variant-numeric: tabular-nums;
}
.ballot-num[hidden] { display: none; }
.ballot-mark { width: 1rem; color: var(--color-navy); font-size: var(--text-sm); }

/* Le filet de part, en bleu nuit : sur fond clair, l'or n'a rien a y faire. */
.ballot-bar { display: block; height: 2px; background: rgba(20,35,63,0.10); }
.ballot-bar[hidden] { display: none; }
.ballot-bar i {
  display: block; height: 100%; background: var(--color-navy);
  transform: scaleX(var(--part, 0)); transform-origin: left;
  transition: transform 620ms var(--ease-luxury);
}

.ballot-row.is-on .ballot-hit { background: rgba(255,255,255,0.62); padding-left: 0.7rem; }
.ballot-row.is-on .ballot-text { color: var(--color-navy); }
.ballot-row.is-on .ballot-no { color: var(--color-navy); }
.ballot-row.is-leading .ballot-no::after {
  content: "▲"; display: block; font-size: 0.5rem; color: var(--color-navy);
}
.ballot-row.is-voted .ballot-text { color: var(--color-muted); }

@media (hover: hover) and (pointer: fine) {
  .ballot-hit:hover { background: rgba(255,255,255,0.62); padding-left: 0.7rem; }
  .ballot-hit:hover .ballot-text { color: var(--color-navy); }
}

@media (max-width: 899px) {
  /* Sur telephone, la scene passe au-dessus et cesse de coller : une image
     collante mangerait la moitie d'un ecran de 667 px de haut. */
  .ballot-grid { grid-template-columns: minmax(0, 1fr); gap: var(--space-4); }
  .ballot-stage { position: static; }
  .bs-plate { aspect-ratio: 4 / 3; }
  .bs-img { width: 74%; height: 88%; }
  .bs-acts .btn { flex: 1 1 auto; text-align: center; justify-content: center; }
  .ballot-hit { grid-template-columns: 2rem minmax(0, 1fr) auto auto; min-height: 52px; }
}

/* Le scrutin a un seul candidat, sur la page d'une collection a venir : pas
   de liste, la phrase est deja le titre de la page. */
.ballot--seule .ballot-list { display: none; }
.ballot--seule .bs-copy { margin-top: 0; max-width: 52ch; }
.ballot--seule .bs-title { font-size: clamp(1.5rem, 3.4vw, 2.1rem); }

@media (prefers-reduced-motion: reduce) {
  .bs-img, .ballot-bar i { transition: none; }
}

.ballot-signup { padding: 0 0 1.1rem; max-width: 46ch; }
.ballot-signup[hidden] { display: none; }

/* --- La ligne de signature ------------------------------------------------
   Un filet pointillé sur lequel on écrit son adresse. Le champ n'a ni cadre
   ni fond : c'est la ligne qui fait le formulaire. */
.signature { display: block; margin-top: var(--space-2); }
.signature-label {
  display: block; font-size: var(--text-xs);
  letter-spacing: var(--tracking-caps); text-transform: uppercase;
  color: var(--color-muted); margin-bottom: 0.55rem;
}
.signature-line {
  display: flex; align-items: baseline; gap: 0.6rem;
  border-bottom: 1px dashed var(--color-black);
  padding-bottom: 0.45rem;
}
.signature-line input {
  flex: 1; min-width: 0;
  border: 0; background: none; padding: 0.35rem 0;
  /* 16 px minimum : en dessous, iOS zoome tout seul à la mise au point. */
  font-family: inherit; font-size: 1rem; color: var(--color-black);
}
.signature-line input::placeholder { color: rgba(109,106,100,0.7); }
.signature-line input:focus { outline: none; }
.signature-line:focus-within { border-bottom-color: var(--color-navy); border-bottom-style: solid; }
.signature-go {
  flex: none; background: none; border: 0; cursor: pointer;
  font-size: 1.15rem; line-height: 1; color: var(--color-black);
  min-width: 44px; min-height: 44px;
}
.signature-msg { display: block; margin-top: 0.5rem; font-size: var(--text-sm); color: var(--color-ok); }
.signature.is-busy { opacity: 0.55; pointer-events: none; }
.signature.is-done .signature-line { border-bottom-style: solid; border-bottom-color: var(--color-ok); }
.signature.is-done .signature-go { display: none; }

/* Variante posée sur un fond clair soutenu : le pointillé se renforce. */
.signature--light .signature-line { border-bottom-color: rgba(17,17,15,0.45); }

/* --- Coloris épuisé (§7) --------------------------------------------------
   La pastille se barre en diagonale. C'est lisible sans couleur, donc
   lisible aussi pour qui ne distingue pas les teintes. */
.swatch--out, .variant-swatches button.is-out .sw-dot { position: relative; }
.swatch--out::after,

.buy-soon {
  font-size: var(--text-sm); letter-spacing: var(--tracking-caps);
  text-transform: uppercase; color: var(--color-muted);
  padding-bottom: 0.9rem; border-bottom: 1px solid var(--color-border);
}

/* Compatibilité devenue un fait, plus un choix : on l'affiche comme une
   donnée de la fiche, pas comme une liste déroulante d'un seul élément. */
.fit-fixed-value {
  font-size: var(--text-md); font-weight: 500; color: var(--color-black);
  margin-top: 0.25rem;
}
.acc-notice {
  display: block; margin-top: 0.8rem; padding-top: 0.8rem;
  border-top: 1px solid var(--color-border-soft);
  font-size: var(--text-sm); color: var(--color-muted);
}
.story-soon { margin-top: var(--space-3); max-width: 46ch; }

/* --- Mobile ---------------------------------------------------------------
   La ligne de dépouillement passe en deux étages : la phrase et sa vignette
   en haut, le décompte et les actions en dessous. Les quatre colonnes de
   bureau ne tiennent pas sous 720 px sans écraser le statement, qui est
   justement ce qu'on vient lire. */


/* ===========================================================================
   27. PASSE MOBILE-FIRST                                        (09.08.2026)
   ---------------------------------------------------------------------------
   Le trafic vient de TikTok. Donc du téléphone, en 4G, souvent d'une main,
   souvent en marchant. Trois manques constatés à l'audit :

     · 58 règles de survol, 2 protégées. Sur un écran tactile, un `:hover`
       se déclenche au doigt et RESTE COLLÉ après le tap. Une carte reste
       soulevée, un bouton reste foncé : l'interface a l'air cassée.
     · 4 états pressés sur tout le site. Rien ne répond sous le doigt, et
       l'attente de la page suivante ressemble à un bug.
     · Des cibles à 32 et 34 px, sous le minimum de 44.

   Rien ici ne change le dessin. On répare ce qui se sent, pas ce qui se voit.
   =========================================================================== */

/* --- 1. Le survol redevient une affaire de souris -------------------------
   On ne réécrit pas les 58 règles : on annule le DÉPLACEMENT là où il colle,
   uniquement sur les appareils sans vrai survol. Les changements de couleur
   restent, eux ne gênent pas. */
@media (hover: none) {
  .btn--solid:hover,
  .btn--outline:hover,
  .card:hover,
  .pay-method:hover,
  .mobile-link:hover { transform: none; padding-left: 0; }
  .card:hover .card-media img,
  .life-item:hover img,
  .ed-grid figure:hover img { transform: none; }
  .btn--text:hover .arrow,
  .back-btn:hover .back-arrow { transform: none; }
  /* La carte au survol dévoilait deux boutons : au doigt, ils apparaissaient
     sous le pouce au moment du tap et volaient le clic. */
  .card:hover .card-hover { opacity: 0; }
}

/* --- 2. Tout ce qui se presse doit répondre -------------------------------
   Le retour d'appui est la seule chose qui distingue une interface qui écoute
   d'une interface qui rame. Il coûte deux lignes. */
.btn,
.btn--solid,
.btn--outline,
.btn--icon,
.filter-btn,
.signature-go,
.qty-stepper button,
.swatch-row,
.acc-btn,
.hotspot,
.card-hover .btn,
.wp-tile,
.pair-add { transition: transform var(--dur-press) var(--ease-out); }

.btn:active,
.btn--solid:active,
.btn--outline:active,
.btn--icon:active,
.filter-btn:active,
.signature-go:active,
.qty-stepper button:active,
.acc-btn:active { transform: scale(var(--press)); }

/* Les pastilles de couleur sont petites : un scale de 0.97 ne se verrait pas.
   On enfonce plus franchement, la cible étant déjà généreuse. */
.swatch-row:active { transform: scale(0.92); }

/* La carte entière est cliquable : elle s'enfonce, mais moins qu'un bouton,
   parce qu'elle est plus grande et qu'un même ratio y paraîtrait excessif. */
.card:active { transform: scale(0.988); transition: transform var(--dur-press) var(--ease-out); }

/* --- 3. Cibles tactiles -----------------------------------------------------
   44 px est le minimum d'Apple. On agrandit la ZONE SENSIBLE, jamais le
   dessin : un bouton qui grossit casse la composition, un ::after ne se voit
   pas. */
@media (max-width: 900px) {
  .cart-btn::after, .burger::after {
    content: ""; position: absolute; inset: -6px;
  }
  /* 16 px minimum sur les champs et les listes : en dessous, iOS zoome tout
     seul à la mise au point et le visiteur se retrouve à 150 % sans comprendre. */
  .tool-select, select, input, textarea {
    font-size: max(16px, 1rem);
    min-height: 44px;
  }
}

/* --- 4. Le focus au clavier, visible partout ------------------------------
   Un contour de focus retiré est le premier réflexe esthétique et la première
   faute d'accessibilité. On le rend net, et on ne l'affiche qu'au clavier. */
:where(a, button, select, input, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--color-navy);
  outline-offset: 3px;
  border-radius: 2px;
}
.section--ink :focus-visible,
.section--wine :focus-visible,
.wall--ink :focus-visible,
.ballot :focus-visible { outline-color: var(--color-navy); }

/* --- 5. Mouvement réduit ---------------------------------------------------
   « Réduire les animations » ne veut pas dire « aucune animation ». On garde
   les fondus, qui aident à comprendre, on supprime les déplacements, qui
   donnent le mal des transports. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    scroll-behavior: auto !important;
  }
  [data-reveal] { opacity: 1 !important; transform: none !important; }
  .btn:active, .card:active, .variant-swatches button:active { transform: none; }
  /* On conserve volontairement les transitions d'opacité et de couleur. */
  * { transition-property: opacity, color, background-color, border-color, outline-color; }
}

/* --- 6. Rythme des visuels sur mobile -------------------------------------
   `auto-fill minmax(258px, 1fr)` donne UNE colonne sous 540 px : six coloris
   identiques empilés en six grandes vignettes, soit six écrans de défilement
   avant d'atteindre le bas. C'est long, et surtout c'est plat : rien ne dit
   par où commencer.

   On casse la régularité. La première pièce prend toute la largeur, c'est
   l'entrée en matière de quelqu'un qui vient de quitter une vidéo. Les
   suivantes passent à deux colonnes : on compare des coloris, et comparer
   demande de voir côte à côte, pas l'un après l'autre. */
@media (max-width: 640px) {
  .grid-products {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.85rem 0.7rem;
  }
  .grid-products > .card:first-child { grid-column: 1 / -1; }

  /* En pleine largeur, le visuel respire : on lui donne un format plus large
     que haut, comme une image d'ouverture, au lieu du carré des vignettes. */
  .grid-products > .card:first-child .card-media { aspect-ratio: 4 / 3; }
  .grid-products > .card:first-child .card-name { font-size: 1.22rem; }

  /* Deux par ligne : les métadonnées secondaires sortent, il n'y a pas la
     place et elles ne servent pas à choisir une couleur. Le nom, la pastille
     et le prix suffisent. */
  .grid-products > .card:not(:first-child) .card-compat { display: none; }
  .grid-products > .card:not(:first-child) .card-name { font-size: 0.94rem; line-height: 1.25; }
  .grid-products > .card:not(:first-child) .card-meta { font-size: 0.78rem; }
}

/* --- 7. Le parcours d'achat sur petit écran -------------------------------
   L'ordre commercial est desormais celui de la SOURCE, sur toutes les
   largeurs : prix, coloris, achat, deuxieme coloris, puis la description.
   Ce bloc n'a plus qu'a caler la marge du prix et la barre collante.
   (Les regles `order` d'aout, ecrites pour `.variant-row`, sont tombees avec
   ce sélecteur : elles renvoyaient les nouveaux blocs en tete de colonne.) */
@media (max-width: 720px) {
  .pinfo { display: flex; flex-direction: column; }
  .pinfo .price-line { margin-bottom: 0.4rem; }

  /* La barre d'achat collante doit dégager le bas de l'écran des iPhone,
     sinon le bouton se retrouve sous la barre de gestes. */
  .sticky-buy { padding-bottom: calc(0.7rem + env(safe-area-inset-bottom)); }
}

/* --- 8. Les deux dernières cibles trop courtes ----------------------------
   Relevé après coup : le bouton retour tombait à 38 px et les boutons de
   carte à 39. Deux pixels sous la limite se voient à l'usage, pas à l'œil. */
@media (max-width: 900px) {
  .back-btn { min-height: 44px; padding-block: 0.55rem; }
  .card-hover .btn, .btn { min-height: 44px; }
  /* Les liens de pied de page, alignés en colonne serrée, se touchaient. */
  .site-footer a { display: inline-block; padding-block: 0.4rem; }
}

/* --- 9. Aligner les cartes et refermer la grille ---------------------------
   Relevé sur capture à 375 px : dans une ligne de deux, un nom qui passe sur
   deux lignes décale le prix de sa voisine. L'œil compare des prix, il faut
   qu'ils soient sur la même ligne. On étire la carte et on pousse le bloc
   prix vers le bas.

   Et avec six coloris, la sixième se retrouvait seule sur sa ligne, en demi
   largeur, laissant un trou. Elle passe pleine largeur : la grille s'ouvre et
   se referme sur une pièce en grand, ce qui fait une composition au lieu
   d'un reste. */
@media (max-width: 640px) {
  .grid-products > .card { display: flex; flex-direction: column; }
  .grid-products > .card .card-body { display: flex; flex-direction: column; flex: 1; }
  .grid-products > .card .card-price { margin-top: auto; padding-top: 0.5rem; }

  .grid-products > .card:last-child:nth-child(even) { grid-column: 1 / -1; }
  .grid-products > .card:last-child:nth-child(even) .card-media { aspect-ratio: 4 / 3; }
  .grid-products > .card:last-child:nth-child(even) .card-name { font-size: 1.22rem; }
  .grid-products > .card:last-child:nth-child(even) .card-compat { display: block; }
}

/* ---------------------------------------------------------------------------
   27.10 CE QUE LE POUCE RATE ENCORE                              (10.08.2026)
   Le premier passage a corrigé les boutons d'achat, pas le reste. Un audit à
   375 px a listé ce qui restait sous 44 px de haut : les pastilles de la
   figure matériaux (34 px), les titres du dépouillement (19 px), les liens de
   pied de page (35 px), le logo (15 px). Sur un écran tenu d'une main, ça se
   traduit par des taps ratés, pas par une gêne esthétique.

   Deux méthodes, choisies selon le voisinage :
   - min-height quand l'élément a de la place autour de lui (pied de page,
     en-tête). La colonne s'allonge un peu, le doigt gagne beaucoup.
   - un ::after invisible quand agrandir déplacerait le dessin (les pastilles
     sont posées au pixel près sur la photo du bracelet). La zone de touche
     grandit, le point reste où il est.
   --------------------------------------------------------------------------- */

/* Les pastilles de la figure matériaux : le point garde ses 34 px, la zone
   sensible passe à 44. Elles sont assez espacées pour que rien ne se chevauche. */
/* Surtout ne pas redéclarer `position` ici : la pastille est en `absolute`,
   posée au pourcentage sur la photo. La repasser en `relative` la renverrait
   dans le flux et déplacerait les trois points. `absolute` sert déjà de
   repère au ::after. */
.hotspot::after {
  content: ""; position: absolute; inset: 50% auto auto 50%;
  width: 44px; height: 44px; transform: translate(-50%, -50%);
  border-radius: 50%;
}

/* Le titre d'une ligne de vote mène à la page histoire. 19 px de haut, c'est
   la moitié d'un doigt, et le bouton « Drop this » est juste dessous : un tap
   approximatif votait au lieu d'ouvrir. */

/* Pied de page : huit liens empilés à 35 px. On les met à 44 en gardant leur
   graisse et leur taille, donc sans toucher au dessin. */
.footer-col a {
  display: flex; align-items: center; min-height: 44px;
}

/* Le logo est le retour à l'accueil le plus utilisé du site, et le plus fin. */
.logo { display: inline-flex; align-items: center; min-height: 44px; }

/* Deux liens s'arrêtaient à 42 px, à deux pixels du minimum. */
.skip-link, .wall-row > a { min-height: 44px; }
.wall-row > a { display: flex; align-items: center; }

/* Le titre d'une carte double le lien de l'image, déjà large. On l'épaissit
   sans décaler la carte : la marge négative rend l'espace que la marge
   intérieure vient de prendre. */
.card-name a {
  display: block;
  padding-block: 0.66rem; margin-block: -0.66rem;
}

/* ===========================================================================
   38. LA FICHE DU DROP                                          (10.08.2026)
   Quatre faits sous l'anneau : combien de coloris, à quel prix, pour quel
   appareil, sous quel délai. Sur écran large ils tiennent une ligne, séparés
   par des filets verticaux. Sous 720 px la ligne casse en carré de quatre :
   deux colonnes, deux rangs, ce qui reste lisible sans réduire le corps.

   Aucune couleur, aucun fond : sur une page où le produit porte déjà tout le
   coloris, un encadré teinté aurait sonné promotionnel. La seule variation
   est le prix barré, qui est justement l'information à faire remarquer.
   =========================================================================== */
.drop-facts {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  margin: var(--space-3) 0 0; padding: 0;
  border-top: 1px solid var(--color-border);
  border-bottom: 1px solid var(--color-border);
}
.drop-fact {
  padding: 1rem 1.3rem;
  border-left: 1px solid var(--color-border);
}
.drop-fact:first-child { border-left: 0; padding-left: 0; }

.drop-fact dt {
  font-size: var(--text-xs); letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--color-muted); margin-bottom: 0.4rem;
}
.drop-fact dd {
  margin: 0; font-size: 1.02rem; line-height: 1.3; color: var(--color-black);
}
/* Le prix barré garde le gris et le trait des cartes : même signe partout. */
.drop-fact dd s { color: var(--color-muted); margin-left: 0.4rem; font-weight: 400; }

@media (max-width: 720px) {
  .drop-facts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* En carré, ce n'est plus la première cellule qui n'a pas de filet à gauche
     mais la première de chaque rang ; et il faut un filet horizontal entre
     les deux rangs, que la ligne unique n'avait pas besoin de porter. */
  .drop-fact { padding: 0.9rem 1rem; }
  .drop-fact:nth-child(odd) { border-left: 0; padding-left: 0; }
  .drop-fact:nth-child(n+3) { border-top: 1px solid var(--color-border); }
}

/* ---------------------------------------------------------------------------
   39.1 SIX PIÈCES, DEUX RANGS PLEINS                             (10.08.2026)
   `auto-fill` remplit la largeur : à 1440 px il tenait quatre colonnes, donc
   quatre pièces au premier rang et deux au second, avec deux cases vides à
   côté. Une grille qui se termine en trou n'est pas une composition, c'est un
   reste. Le drop compte six coloris : trois colonnes les rangent en deux
   rangs pleins, et chaque bracelet gagne au passage de la taille.

   La règle vaut pour la page collection, pas pour les autres grilles : elle
   est écrite sur `.page-head`, seul endroit où le nombre est connu. */
@media (min-width: 900px) {
  .page-head .grid-products { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* ---------------------------------------------------------------------------
   40. CE QUI N'EST PAS EN VENTE NE PORTE PAS DE PRIX      (10.08.2026)
   Une collection a venir affichait 48 CHF barre 68, puis « voir la piece »,
   puis une fiche qui disait « prochainement ». Trois ecrans pour apprendre
   qu'on ne peut pas acheter. Le prix disparait, le bouton disparait, et la
   page d'histoire devient terminale : elle porte le nuancier, le vote et
   l'inscription, et ne renvoie plus vers une impasse.
   --------------------------------------------------------------------------- */
.sb-soon {
  font-family: var(--font-display); font-weight: 700; font-size: 1.35rem;
  letter-spacing: var(--tracking-tight); color: var(--color-navy);
}
.sw-stock.is-soon { color: var(--color-muted); font-style: italic; }

/* Le bulletin seul, sur la page d'une collection a venir. Pas de titre : la
   phrase est deja le titre de la page, la repeter serait bavard. La ligne
   n'a donc qu'a se poser, avec de l'air au-dessus et en dessous. */


/* ===========================================================================
   41. UNE COLLECTION À VENIR                                    (10.08.2026)
   La page ne vend rien, elle fait attendre. Elle etait batie comme une fiche
   produit amputee : titre, puis une bande de vote, puis enfin le visuel, avec
   un panneau lateral presque vide et un seul coloris montre sur deux.

   Elle suit desormais l'ordre d'une affiche. La phrase et la piece ensemble,
   tous les coloris en grand, le vote apres, les autres candidates en
   vignettes. On ne demande plus de voter avant d'avoir vu.
   =========================================================================== */
.story-soon-head { padding-bottom: var(--space-3); }
.ssh-grid {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 0.92fr);
  gap: clamp(2rem, 5vw, 4.5rem); align-items: center;
  margin-top: var(--space-3);
}
.ssh-title {
  font-family: var(--font-display);
  font-size: clamp(2.6rem, 7vw, 5.2rem); font-weight: 700;
  letter-spacing: var(--tracking-tight); line-height: 0.98;
  text-wrap: balance; margin-bottom: var(--space-2);
}
.ssh-desc { color: var(--color-muted); font-size: 1.06rem; max-width: 42ch; }

.ssh-meta {
  display: flex; align-items: center; gap: 0.8rem; flex-wrap: wrap;
  margin-top: var(--space-2);
  font-size: var(--text-xs); letter-spacing: var(--tracking-caps);
  text-transform: uppercase; color: var(--color-muted);
}
/* Le seul aplat de la page : il dit tout de suite qu'on ne peut pas acheter,
   sans qu'on ait a chercher le bouton absent. */
.ssh-tag {
  padding: 0.35rem 0.7rem; border-radius: 2px;
  background: var(--color-navy); color: var(--color-ivory);
  letter-spacing: var(--tracking-caps);
}

.ssh-piece {
  position: relative; aspect-ratio: 1; display: grid; place-items: center;
  margin: 0;
}
.ssh-img {
  position: relative; width: 100%; height: 100%; object-fit: contain;
  filter: drop-shadow(0 34px 52px rgba(17,17,15,0.22));
}

/* --- Les coloris en grand -------------------------------------------------
   Une pastille de 42 px ne montre pas une matiere tissee. Sur une page dont
   c'est le seul contenu, chaque coloris a droit a sa planche. */
.ways-grid {
  list-style: none; margin: var(--space-3) 0 0; padding: 0;
  /* Borne haute obligatoire : sans elle, une collection a deux coloris etale
     deux planches de 570 px et l'echelle du site part en fumee. */
  display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 400px));
  justify-content: start; gap: clamp(1rem, 2.6vw, 2rem);
}
.way-plate {
  aspect-ratio: 1; display: grid; place-items: center; overflow: hidden;
  background: radial-gradient(130% 110% at 50% 0%, #ffffff 0%, var(--color-plate) 74%);
  border: 1px solid rgba(255,255,255,0.9); border-radius: 18px;
  box-shadow: 0 1px 0 rgba(255,255,255,0.9) inset,
              0 28px 56px -26px rgba(17,17,15,0.24);
}
.way-img {
  width: 84%; height: 84%; object-fit: contain;
  filter: drop-shadow(0 18px 28px rgba(17,17,15,0.16));
  transition: transform 520ms var(--ease-luxury);
}
.way-name {
  display: flex; align-items: center; gap: 0.55rem; margin-top: 0.9rem;
  font-size: var(--text-sm); color: var(--color-charcoal);
}
@media (hover: hover) and (pointer: fine) {
  .way:hover .way-img { transform: scale(1.06) translateY(-6px); }
}

/* --- Les autres candidates ------------------------------------------------
   Une liste de mots ne donne envie d'ouvrir aucune d'elles. Une bande de
   vignettes, si. Elle defile au doigt sous 900 px. */
.others-rail {
  list-style: none; margin: var(--space-3) 0 0;
  /* Le fer a gauche doit tomber sur celui du texte. `--gutter` seul ne suffit
     pas : au-dela de `--container`, la colonne est centree, il faut ajouter la
     marge que le centrage a creee. `scroll-padding` evite que l'accrochage
     colle la premiere vignette au bord. */
  padding-inline: max(var(--gutter), (100vw - var(--container)) / 2 + var(--gutter));
  scroll-padding-inline: max(var(--gutter), (100vw - var(--container)) / 2 + var(--gutter));
  display: grid; grid-auto-flow: column; grid-auto-columns: 170px;
  gap: var(--space-2); overflow-x: auto; scroll-snap-type: x proximity;
  scrollbar-width: none;
}
.others-rail::-webkit-scrollbar { display: none; }
.others-rail li { scroll-snap-align: start; }
.others-rail a { display: block; text-decoration: none; color: inherit; }
.others-plate {
  display: grid; place-items: center; aspect-ratio: 1; overflow: hidden;
  background: var(--color-plate); border-radius: 12px;
  border: 1px solid var(--color-border-soft);
}
.others-plate img {
  width: 82%; height: 82%; object-fit: contain;
  transition: transform 480ms var(--ease-luxury);
}
.others-name {
  display: block; margin-top: 0.6rem; font-weight: 600; line-height: 1.2;
  font-size: 0.94rem;
}
.others-state {
  display: block; margin-top: 0.2rem;
  font-size: var(--text-xs); letter-spacing: var(--tracking-caps);
  text-transform: uppercase; color: var(--color-muted);
}
@media (hover: hover) and (pointer: fine) {
  .others-rail a:hover .others-plate img { transform: scale(1.07); }
  .others-rail a:hover .others-name { color: var(--color-navy); }
}

/* Le vote de la page a venir : il vient APRES les coloris, et il porte le
   rappel de la promesse, que la page de scrutin porte deja ailleurs. */
/* Le bandeau de vote : question a gauche, geste a droite. Aligne a gauche sur
   toute la largeur, il laissait la moitie de l'ecran vide en 1440. Le texte
   est regroupe dans son propre bloc : pose directement sur la grille, chaque
   paragraphe devenait une rangee etiree et le rythme vertical se cassait. */
@media (min-width: 900px) {
  .ballot--seule .bs-copy {
    display: flex; align-items: flex-end; justify-content: space-between;
    gap: var(--space-5); max-width: none;
  }
  .ballot--seule .bs-text { max-width: 56ch; }
  .ballot--seule .bs-acts { margin-top: 0; flex: none; }
}

.ballot--seule .bs-sub {
  color: var(--color-muted); max-width: 54ch; margin-top: 0.7rem;
  font-size: var(--text-sm);
}

@media (max-width: 900px) {
  .ssh-grid { grid-template-columns: minmax(0, 1fr); gap: var(--space-3); }
  /* Sur telephone la piece passe AVANT le texte : on la voit en arrivant,
     et la phrase se lit juste apres, comme une legende d'affiche. */
  .ssh-piece { order: -1; aspect-ratio: 4 / 3; }
  .ssh-img { width: 88%; height: 100%; }
}

/* ===========================================================================
   42. CHOISIR ET CUMULER LES COLORIS                            (10.08.2026)
   Deux manques sur la fiche produit, tous deux commerciaux.

   1. Changer de coloris se faisait sur six pastilles de 12 px. Sur un ecran
      tactile on ne sait meme pas que ca se touche, et rien ne dit ce qu'on
      va obtenir. C'est pourtant LE geste d'une collection qui n'est qu'une
      phrase declinee en six couleurs.

   2. Le bareme du §6 ne rapporte qu'a partir de deux bracelets, et le port
      n'est offert qu'a 70 CHF, soit deux pieces. Ajouter une seconde couleur
      demandait de revenir a la collection, rouvrir une fiche, recommencer.
      Autant dire que personne ne le faisait.
   =========================================================================== */

/* --- Le selecteur : la piece, son nom, son stock -------------------------- */
.ways-pick { margin-top: var(--space-4); }
.wp-current { color: var(--color-navy); font-weight: 600; text-transform: none; letter-spacing: 0; }

.wp-list {
  list-style: none; margin: var(--space-2) 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(92px, 1fr));
  gap: 0.6rem;
}
.wp-tile {
  display: grid; width: 100%; gap: 0.35rem; padding: 0.45rem 0.4rem 0.6rem;
  font: inherit; text-align: center; color: inherit; cursor: pointer;
  background: none; border: 1px solid transparent; border-radius: 10px;
  transition: border-color var(--dur-fast) var(--ease-ui),
              background var(--dur-fast) var(--ease-ui);
}
.wp-plate {
  display: grid; place-items: center; aspect-ratio: 1; border-radius: 8px;
  background: var(--color-plate); border: 1px solid var(--color-border-soft);
  overflow: hidden;
}
.wp-plate img {
  width: 88%; height: 88%; object-fit: contain;
  transition: transform 420ms var(--ease-luxury);
}
.wp-name { font-size: 0.82rem; font-weight: 600; line-height: 1.15; }
.wp-stock { font-size: 0.7rem; color: var(--color-muted); line-height: 1.1; }

.wp-tile.is-on {
  border-color: var(--color-navy); background: var(--color-warm-white);
}
.wp-tile.is-on .wp-name { color: var(--color-navy); }
/* Un coloris epuise reste cliquable : sa fiche porte l'inscription au retour
   en stock (§7). On le grise, on ne le retire pas. */
.wp-tile.is-out .wp-plate img { opacity: 0.42; }
.wp-tile.is-out .wp-name { text-decoration: line-through; color: var(--color-muted); }

@media (hover: hover) and (pointer: fine) {
  .wp-tile:hover { border-color: var(--color-border); background: var(--color-warm-white); }
  .wp-tile:hover .wp-plate img { transform: scale(1.07); }
}
.wp-tile:active { transform: scale(var(--press)); }

/* --- Prendre un deuxieme coloris ------------------------------------------
   Encadre, mais sans couleur d'alerte : c'est une proposition, pas une
   promotion criarde. Le filet bleu nuit a gauche suffit a le detacher. */
.pair-up {
  margin-top: var(--space-4); padding: var(--space-3);
  background: var(--color-warm-white);
  border-left: 2px solid var(--color-navy); border-radius: 0 8px 8px 0;
}
.pair-title {
  font-family: var(--font-display); font-weight: 700; font-size: 1.12rem;
  letter-spacing: var(--tracking-tight); color: var(--color-black);
}
.pair-mix { margin-top: 0.3rem; font-size: var(--text-sm); color: var(--color-muted); }

.pair-list {
  list-style: none; margin: var(--space-2) 0 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: 0.5rem;
}
.pair-add {
  display: flex; align-items: center; gap: 0.55rem;
  padding: 0.4rem 0.75rem 0.4rem 0.4rem; min-height: 52px;
  font: inherit; color: inherit; cursor: pointer;
  background: var(--color-warm-white); border: 1px solid var(--color-border);
  border-radius: 40px;
  transition: border-color var(--dur-fast) var(--ease-ui),
              background var(--dur-fast) var(--ease-ui);
}
.pair-plate {
  display: grid; place-items: center; width: 40px; height: 40px; flex: none;
  border-radius: 50%; background: var(--color-plate); overflow: hidden;
}
.pair-plate img { width: 92%; height: 92%; object-fit: contain; }
.pair-name { font-size: 0.88rem; font-weight: 600; white-space: nowrap; }
.pair-plus {
  font-size: 1.1rem; line-height: 1; color: var(--color-navy);
  font-variant-numeric: tabular-nums;
}
.pair-add.is-added {
  border-color: var(--color-navy); background: var(--color-ivory-deep);
}
.pair-add.is-added .pair-plus { color: var(--color-ok); }
@media (hover: hover) and (pointer: fine) {
  .pair-add:hover { border-color: var(--color-navy); background: #fff; }
}
.pair-add:active { transform: scale(var(--press)); }

@media (max-width: 640px) {
  /* Trois par rang : les six coloris tombent en deux rangs pleins. A quatre,
     le second rang n'en portait que deux et la grille finissait en trou. */
  .wp-list { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0.5rem; }
  .wp-name { font-size: 0.76rem; }
  .wp-stock { font-size: 0.66rem; }
  .pair-add { flex: 1 1 calc(50% - 0.25rem); }
  .pair-name { white-space: normal; }
}

/* ---------------------------------------------------------------------------
   43. LE DROP EN GRILLE SUR L'ACCUEIL                            (10.08.2026)
   L'accueil deroulait les six coloris dans une bande a defilement horizontal.
   Sur un telephone elle n'en montrait que deux : quatre pieces sur six
   attendaient un geste que personne ne fait. Un visiteur venu de TikTok ne
   swipe pas une vitrine, il regarde et il part.

   Meme grille que la page collection, donc meme composition : une grande,
   deux, deux, une grande sur telephone ; trois colonnes au-dessus de 900 px.
   --------------------------------------------------------------------------- */
@media (min-width: 900px) {
  .grid-products--drop { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
.grid-products--drop { margin-top: var(--space-3); }

/* La fiche du drop apparait aussi sur l'accueil : elle y perd son filet du
   haut, la ligne de titre la porte deja. */
#drop .drop-facts { border-top: 0; margin-top: var(--space-2); }

/* ======================= GALERIE DE FICHE ET LOUPE =========================
   Ajoutee le 27.08.2026. La fiche n'avait qu'un visuel ; elle en porte
   plusieurs, avec une loupe a 2x.

   Le rail de vignettes passe SOUS la scene sur telephone et sur ordinateur :
   a gauche il volerait de la largeur a l'image, qui est la seule chose que
   le client vient voir. */
.gallery { display: flex; flex-direction: column; gap: var(--space-1); }

.g-thumbs {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(64px, 1fr));
  gap: 8px; list-style: none; margin: 0; padding: 0;
}
.g-thumb {
  display: block; width: 100%; aspect-ratio: 1; padding: 0; cursor: pointer;
  background: var(--color-plate); border: 1px solid var(--color-border-soft);
  border-radius: 2px; overflow: hidden;
  transition: border-color .18s ease;
}
/* Le voile porte sur l'IMAGE, pas sur le bouton : applique au bouton, il
   delavait aussi le plateau et un plateau charbon virait au gris moyen,
   ce qui annulait le contraste qu'on venait de choisir. */
.g-thumb img {
  width: 100%; height: 100%; object-fit: contain; display: block;
  opacity: .62; transition: opacity .18s ease;
}
.g-thumb:hover img { opacity: .9; }
.g-thumb.is-on img { opacity: 1; }
.g-thumb.is-on { border-color: var(--color-black); }
.g-thumb:focus-visible { outline: 2px solid var(--color-navy); outline-offset: 2px; }
/* Les plans de fiche sont detoures : sur fond clair le bracelet noir se lit,
   mais le Starlight creme disparait. Le plateau des vignettes reste donc
   sombre quand la scene l'est. */
.gallery-main--dark ~ .g-thumbs .g-thumb { background: var(--color-charcoal); }

/* Le bouton loupe : discret, en bas a droite de la scene. */
.g-loupe {
  position: absolute; right: 10px; bottom: 10px; z-index: 3;
  width: 38px; height: 38px; padding: 0; cursor: pointer;
  display: grid; place-items: center; border-radius: 50%;
  background: rgba(250, 249, 246, .88); border: 1px solid var(--color-border);
  backdrop-filter: blur(3px);
  transition: transform .18s ease, background .18s ease;
}
.g-loupe svg {
  width: 18px; height: 18px; fill: none;
  stroke: var(--color-black); stroke-width: 1.7; stroke-linecap: round;
}
.g-loupe:hover { transform: scale(1.06); background: var(--color-warm-white); }
.gallery-main { position: relative; }
#g-main { cursor: zoom-in; }

/* --- Le calque de loupe --- */
body.loupe-ouverte { overflow: hidden; }
.loupe {
  position: fixed; inset: 0; z-index: 200;
  display: grid; place-items: center; padding: clamp(12px, 4vw, 48px);
  background: rgba(17, 17, 15, .93);
  animation: loupe-entre .22s ease both;
}
@keyframes loupe-entre { from { opacity: 0 } to { opacity: 1 } }
.loupe-scene {
  width: min(92vw, 68vh); aspect-ratio: 1; overflow: hidden;
  cursor: zoom-in; touch-action: none;
}
.loupe-scene.est-grossi { cursor: zoom-out; }
.loupe-scene img {
  width: 100%; height: 100%; object-fit: contain; display: block;
  transition: transform .28s cubic-bezier(.22, .61, .36, 1);
  will-change: transform;
}
.loupe-fermer {
  position: absolute; top: 16px; right: 18px; z-index: 2;
  width: 42px; height: 42px; padding: 0; cursor: pointer;
  font-size: 26px; line-height: 1; color: var(--color-ivory);
  background: none; border: 0;
}
.loupe-fermer:hover { color: #fff; }
.loupe-aide {
  position: absolute; left: 0; right: 0; bottom: 20px;
  text-align: center; font-size: var(--text-xs); letter-spacing: .08em;
  text-transform: uppercase; color: rgba(243, 239, 230, .58); margin: 0;
}
@media (prefers-reduced-motion: reduce) {
  .loupe { animation: none; }
  .loupe-scene img { transition: none; }
}

/* Une vraie photo remplit la scene : pas de plateau, pas d'ombre portee, pas
   de reflet. Les 33 px de marge du packshot (`width:84%`) fabriquaient un
   lisere sombre tout autour de la photo, refuse par Benjamin le 29.08. */
.gallery-main.est-photo .stage-plate,
.gallery-main.est-photo .stage-shadow,
.gallery-main.est-photo .stage-gloss { display: none; }
.gallery-main.est-photo .stage3d-inner {
  border-radius: var(--radius-lg); overflow: hidden;
  box-shadow: 0 30px 60px -28px rgba(17, 17, 15, .28);
}
.gallery-main.est-photo img {
  width: 100%; height: 100%; object-fit: cover; filter: none;
}
/* Meme regle en vignette, sinon la photo y flotte dans un cadre vide. */
.g-thumb--photo img { object-fit: cover; }
/* Dans la loupe, une photo occupe toute la scene ; un packshot detoure garde
   son air, sinon il touche les bords du calque. */
.loupe-scene.est-photo img { object-fit: cover; }

/* ======================= FICHE PRODUIT, REFONTE DU SHOOTING (10.10.2026) ===
   La fiche s'ouvre sur les photos. Ordinateur : galerie en deux colonnes,
   collee au bord gauche de l'ecran, et colonne d'achat qui suit le
   defilement. Telephone : ruban a glisser, le plan suivant depasse de 14 %
   pour dire qu'on peut glisser. Puis deux environnements : le sombre (la
   piece dans ses deux mondes, a fond perdu) et le clair (la matiere).
   Toutes les photos sont en 4:5 a l'export (outils/shooting-webp.py), donc
   aucun recadrage CSS n'invente de cadre. */
.pdp-retour { padding-top: clamp(2.5rem, 4vw, 3rem); padding-bottom: var(--space-2); }
.pdp-plans { list-style: none; margin: 0; padding: 0; }
.pdp-plan-btn {
  display: block; width: 100%; padding: 0; border: 0; cursor: zoom-in;
  background: var(--color-ivory-deep);
}
.pdp-plan-btn:focus-visible { outline: 2px solid var(--color-navy); outline-offset: -4px; }
/* width/height (1200x1500) portent deja le 4:5 ; height:auto le laisse agir. */
.pdp-plan img { display: block; width: 100%; height: auto; aspect-ratio: 4 / 5; object-fit: cover; }
/* Les pieces pas encore photographiees : rendus detoures sur le plateau. */
.pdp-galerie--rendu .pdp-plan-btn { background: radial-gradient(120% 90% at 50% 30%, var(--plateau-haut), var(--plateau-fond) 70%, var(--plateau-bord)); }
.pdp-galerie--rendu .pdp-plan img { object-fit: contain; padding: 8%; }
.pdp-achat .product-statement { font-size: clamp(2.2rem, 3.5vw, 3.4rem); }
.pdp-achat .product-head { margin-bottom: var(--space-3); }

@media (min-width: 861px) {
  .pdp-grid {
    display: grid; grid-template-columns: minmax(0, 1.45fr) minmax(330px, 1fr);
    gap: clamp(2rem, 4vw, 4.5rem); align-items: start;
    padding-right: max(var(--gutter), calc((100vw - 1440px) / 2));
  }
  .pdp-plans { display: grid; grid-template-columns: 1fr 1fr; gap: 3px; }
  .pdp-compte { display: none; }
  /* Collante : rien entre elle et la page ne porte de transform ni
     d'overflow (voir la lecon du 04.09 sur la barre d'achat). */
  .pdp-achat { position: sticky; top: calc(var(--header-h-scrolled) + 1.5rem); padding-top: var(--space-1); }
}
@media (max-width: 860px) {
  .pdp-galerie { position: relative; }
  .pdp-plans {
    display: flex; gap: 3px; overflow-x: auto; overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory; scrollbar-width: none;
  }
  .pdp-plans::-webkit-scrollbar { display: none; }
  .pdp-plan { flex: 0 0 86%; scroll-snap-align: start; }
  .pdp-plan:last-child { scroll-snap-align: end; }
  .pdp-compte {
    position: absolute; left: var(--gutter); bottom: 0.85rem; margin: 0;
    padding: 0.28rem 0.55rem; border-radius: var(--radius);
    background: rgba(17, 17, 15, 0.62); color: var(--color-warm-white);
    font-size: var(--text-xs); font-weight: 600; font-variant-numeric: tabular-nums;
    pointer-events: none;
  }
  .pdp-achat { padding: var(--space-3) var(--gutter) 0; }
}

/* Du terrain au comptoir : noir encre, photos a fond perdu, deux tailles et
   deux hauteurs. Une paire symetrique se lirait comme une grille de cartes. */
.pdp-porte {
  margin-top: var(--space-6);
  background: var(--color-black); color: var(--color-warm-white);
  padding: var(--space-5) 0 var(--space-4);
}
.pdp-porte-titre {
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(2.4rem, 6.4vw, 5.6rem); line-height: 0.95;
  letter-spacing: var(--tracking-tight);
  margin: 0 0 var(--space-4); padding-inline: var(--gutter); max-width: 13ch;
}
.pdp-porte-duo { display: grid; grid-template-columns: 1.3fr 1fr; gap: 3px; align-items: end; }
.pdp-porte-fig { margin: 0; }
.pdp-porte-fig:nth-child(2) { margin-bottom: clamp(2.5rem, 10vw, 9rem); }
.pdp-porte-fig img { display: block; width: 100%; height: auto; aspect-ratio: 4 / 5; object-fit: cover; }
.pdp-porte-fig figcaption {
  padding: 0.75rem var(--gutter) 0; font-size: var(--text-sm);
  color: rgba(250, 249, 246, 0.72);
}
.pdp-porte-fig:nth-child(2) figcaption { padding-left: 0.75rem; }

/* La matiere : ivoire soutenu, photo a fond perdu a gauche. */
.pdp-matiere { display: grid; grid-template-columns: 1fr; background: var(--color-ivory-deep); }
.pdp-matiere-img { margin: 0; }
.pdp-matiere-img img { display: block; width: 100%; height: auto; aspect-ratio: 4 / 5; object-fit: cover; }
.pdp-matiere-txt { padding: var(--space-5) var(--gutter); max-width: 36rem; }
.pdp-faits { margin: var(--space-4) 0 0; display: grid; gap: var(--space-3); }
.pdp-faits dt { font-weight: 700; font-size: var(--text-md); }
.pdp-faits dd { margin: 0.35rem 0 0; color: var(--color-muted); max-width: 42ch; }
@media (min-width: 861px) {
  .pdp-matiere { grid-template-columns: minmax(0, 0.9fr) minmax(0, 1fr); align-items: center; }
  .pdp-matiere-img img { aspect-ratio: auto; height: min(88vh, 860px); }
  .pdp-matiere-txt { padding-left: clamp(2rem, 6vw, 6rem); }
}
@media (max-width: 860px) {
  .pdp-matiere-img img { aspect-ratio: 1 / 1; }
}

/* Banniere de la collection : a fond perdu, plafonnee pour qu'un ecran tres
   large ne la transforme pas en mur. */
.col-banniere { margin: 0; }
/* Format fixe, jamais plafonne en hauteur : un plafond recadrait et
   zoomait l'image sur grand ecran, et une image de video ne le supporte pas. */
.col-banniere img { display: block; width: 100%; height: auto; aspect-ratio: 2.6 / 1; object-fit: cover; }
@media (max-width: 700px) { .col-banniere img { aspect-ratio: 4 / 5; } }

/* Cartes des pieces photographiees : la photo remplit la carte (4:5), plus
   de plateau ni de marge, et la photo portee apparait au survol. */
/* Le cadre porte le format (4:5, ou 4:3 pour la premiere carte en pleine
   largeur sur telephone), la photo le remplit : aucun plateau ne reste
   visible autour d'une vraie photo. */
.card--photo .card-media { aspect-ratio: 4 / 5; background: var(--color-ivory-deep); }
.card--photo .card-media a { display: block; position: relative; height: 100%; }
.card--photo .card-media img {
  display: block; width: 100%; height: 100%; aspect-ratio: auto;
  object-fit: cover; object-position: 50% 62%; padding: 0;
}
.card--photo .card-media .card-alt {
  position: absolute; inset: 0; width: 100%; height: 100%;
  opacity: 0; transition: opacity 420ms var(--ease-ui), transform 750ms var(--ease-luxury);
}
@media (hover: hover) { .card--photo:hover .card-media .card-alt { opacity: 1; } }

/* Pastilles de coloris des pieces photographiees : la photo remplit la
   pastille, sans plateau beige ni bordure autour. Le coloris choisi se lit
   au trait sous la photo, pas a un cadre arrondi. */
.wp-tile--photo { padding: 0 0 0.55rem; border: 0; border-radius: 0; background: none; }
.wp-tile--photo .wp-plate {
  aspect-ratio: 4 / 5; border: 0; border-radius: var(--radius);
  background: var(--color-ivory-deep); position: relative;
}
.wp-tile--photo .wp-plate img { width: 100%; height: 100%; object-fit: cover; }
.wp-tile--photo .wp-plate::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 3px;
  background: var(--color-black); transform: scaleX(0); transform-origin: left;
  transition: transform var(--dur-fast) var(--ease-ui);
}
.wp-tile--photo.is-on .wp-plate::after { transform: scaleX(1); }
.wp-tile--photo.is-on { border: 0; background: none; box-shadow: none; }
.wp-tile--photo.is-on .wp-name { color: var(--color-black); }
@media (hover: hover) { .wp-tile--photo:hover { background: none; } }

/* ======================= HERO VIDEO (10.10.2026) ===========================
   Le film du shooting a fond perdu, le texte en bas a gauche sur un voile qui
   ne fonce que la ou il y a du texte. Hauteur : l'ecran moins l'en-tete,
   bornee pour qu'un ecran tres haut ou tres bas reste raisonnable. */
.hero-video {
  position: relative; overflow: hidden; isolation: isolate;
  height: calc(100svh - var(--header-h)); min-height: 520px; max-height: 1080px;
  background: var(--color-black); color: var(--color-warm-white);
}
.hv-media { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: -2; }
.hv-voile {
  position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background:
    linear-gradient(180deg, rgba(17,17,15,0) 40%, rgba(17,17,15,0.66) 100%),
    linear-gradient(90deg, rgba(17,17,15,0.38) 0%, rgba(17,17,15,0) 55%);
}
.hv-texte {
  position: absolute; left: var(--gutter); right: calc(var(--gutter) + 3.5rem);
  bottom: clamp(2rem, 7vh, 4.5rem); max-width: 42rem;
}
.hv-kicker { font-size: var(--text-sm); font-weight: 600; color: rgba(250,249,246,0.8); }
.hv-titre {
  margin: 0.45rem 0 0; font-family: var(--font-display); font-weight: 700;
  font-size: var(--text-hero); line-height: 0.92; letter-spacing: var(--tracking-tight);
  color: var(--color-warm-white);
}
.hv-sous { margin-top: 1rem; max-width: 36ch; font-size: var(--text-md); color: rgba(250,249,246,0.88); }
.hv-ctas { margin-top: 1.6rem; display: flex; align-items: center; gap: 0.6rem 1.3rem; flex-wrap: wrap; }
.hv-ctas .btn--solid, .hv-cta.btn--solid { background: var(--color-warm-white); color: var(--color-black); border-color: var(--color-warm-white); }
.hv-prix { font-size: var(--text-sm); font-weight: 600; color: rgba(250,249,246,0.88); }
.hv-prix .now { color: inherit; }
.hv-pause {
  position: absolute; right: var(--gutter); bottom: clamp(2rem, 7vh, 4.5rem);
  width: 2.6rem; height: 2.6rem; display: grid; place-items: center; cursor: pointer;
  border-radius: 50%; border: 1px solid rgba(250,249,246,0.55);
  background: rgba(17,17,15,0.32); color: var(--color-warm-white);
}
.hv-pause svg { width: 1rem; height: 1rem; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.hv-pause .hv-i-play { display: none; fill: currentColor; stroke: none; }
.hv-pause[aria-pressed="true"] .hv-i-pause { display: none; }
.hv-pause[aria-pressed="true"] .hv-i-play { display: block; }
.hv-pause:focus-visible { outline: 2px solid var(--color-warm-white); outline-offset: 3px; }
@media (max-width: 700px) {
  .hero-video { min-height: 560px; }
  .hv-texte { bottom: 1.6rem; }
  .hv-pause { bottom: auto; top: 1rem; }
}
/* Le titre du hero sort de son masque une fois, au chargement. L'etat de
   base est l'etat final : si l'animation ne joue pas, le titre est la. */
.hero-video .hline-in { transform: none; animation: hv-monte 900ms var(--ease-luxury) both; animation-delay: calc(var(--l, 0) * 110ms + 150ms); }
@keyframes hv-monte { from { transform: translateY(110%); } }
@media (prefers-reduced-motion: reduce) { .hero-video .hline-in { animation: none; } }
/* La hauteur part du vrai haut du hero (bandeau + en-tete), mesure en JS. */
.hero-video { height: calc(100svh - var(--hv-haut, var(--header-h))); }

/* 10.10.2026, sur demande de Benjamin : le texte du hero au centre, epure.
   Le titre, une ligne, un bouton, le prix en petit. Le voile devient un halo
   rond qui ne fonce que derriere le texte, la video reste lumineuse ailleurs. */
.hv-voile { background: radial-gradient(ellipse 62% 55% at 50% 52%, rgba(17,17,15,0.46) 0%, rgba(17,17,15,0.16) 62%, rgba(17,17,15,0.06) 100%); }
.hv-texte {
  top: 0; left: 0; right: 0; bottom: 0; max-width: none;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; padding: 0 var(--gutter);
}
.hv-titre { font-size: clamp(3.1rem, 7vw, 6.4rem); }
.hv-titre .hline { padding-bottom: 0.04em; }
.hv-sous { margin-top: 1.1rem; max-width: 34ch; font-size: var(--text-base); }
.hv-cta { margin-top: 1.8rem; }
.hv-prix { margin-top: 0.75rem; font-size: var(--text-xs); letter-spacing: 0.02em; color: rgba(250,249,246,0.78); }
@media (max-width: 700px) {
  .hv-texte { bottom: 0; }
  .hv-sous { font-size: var(--text-sm); max-width: 28ch; }
}

/* 10.10.2026, retours de Benjamin sur iPhone.
   En-tete : le bloc du logo fait 44 px de haut (cible tactile) et le mot
   restait colle en haut du bloc, au-dessus du burger et du panier. On le
   centre, et sur telephone le mot est un cran plus petit. La marge negative
   rend l'espace que l'interlettrage ajoute apres la derniere lettre : sans
   elle, le mot parait decale vers la gauche. */
.logo { justify-content: center; }
@media (max-width: 560px) {
  .logo-word { font-size: 0.84rem; letter-spacing: 0.26em; margin-right: -0.26em; }
}
/* Le vote en sable qui ferme la collection touche le pied de page : la marge
   ouvrait une bande ivoire entre deux aplats, lue comme un trou. */
#view:has(> .ballot:last-child) + .site-footer { margin-top: 0; }
/* Le bouton du hero en contour : la video reste visible derriere. */
.hv-cta.btn--outline { background: transparent; color: var(--color-warm-white); border-color: rgba(250,249,246,0.9); }
.hv-cta.btn--outline:hover { background: var(--color-warm-white); color: var(--color-black); border-color: var(--color-warm-white); }
/* « The house » sans les deux rendus : le texte seul, sur une colonne lisible. */
.story--seule .story-copy { max-width: 40rem; }
/* Quelques plans du film ont un a deux pixels de bord sombre (recadrage du 4K,
   panneaux du triptyque) : 1 % d'agrandissement les sort du cadre. */
.hv-media { transform: scale(1.012); }

/* Sortie du hero, fondu au noir (choisi le 10.10.2026 contre un « cadre »
   qui se resserre). --p va de 0 (hero entier) a 1 (hero sorti), pose par
   initHeroVideo. Le film recule moins vite que la page, s'assombrit et se fond
   dans l'encre du manifeste ; le texte part a une autre vitesse que l'image,
   ce qui donne la profondeur. Aucune arete entre les deux sections.
   Tout passe par transform et opacity : rien ne recalcule la mise en page. */
.hero-video { --p: 0; }
.hv-cadre {
  position: absolute; inset: 0; z-index: -1; overflow: hidden;
  transform: translate3d(0, calc(var(--p) * 38%), 0) scale(calc(1 + var(--p) * 0.06));
}
.hv-noir { position: absolute; inset: 0; z-index: -1; background: var(--color-black); opacity: calc(var(--p) * 1.3); pointer-events: none; }
.hv-texte { transform: translate3d(0, calc(var(--p) * 16%), 0); opacity: calc(1 - var(--p) * 1.8); }
.hv-pause { opacity: calc(1 - var(--p) * 2.4); }
.hero-video::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 24%; z-index: -1; pointer-events: none;
  background: linear-gradient(180deg, rgba(17,17,15,0) 0%, var(--color-black) 100%);
  opacity: calc(var(--p) * 5);
}

/* « What it is » sur la photo du shooting (10.10.2026). En 4:5, la scene est
   plus etroite que l'ancien carre. Les bulles des points proches d'un bord
   s'ancrent de ce cote : centrees, elles sortaient de l'ecran du telephone. */
.mat-stage--photo { max-width: 560px; background: none; }
.mat-stage--photo > img { width: 100%; height: auto; aspect-ratio: 4 / 5; object-fit: cover; }
.hotspot--g .hotspot-tip { left: 0; transform: translateY(6px); }
.hotspot--d .hotspot-tip { left: auto; right: 0; transform: translateY(6px); }
.hotspot--g:hover .hotspot-tip, .hotspot--g:focus-visible .hotspot-tip, .hotspot--g[aria-expanded="true"] .hotspot-tip,
.hotspot--d:hover .hotspot-tip, .hotspot--d:focus-visible .hotspot-tip, .hotspot--d[aria-expanded="true"] .hotspot-tip { transform: translateY(0); }
/* Le point ouvert passe devant ses voisins : sinon un autre point se pose
   sur le texte de sa bulle. */
.hotspot:hover, .hotspot:focus-visible, .hotspot[aria-expanded="true"] { z-index: 4; }

/* ======================= COMMUNAUTE (10.10.2026) ==========================
   Une fiche de developpement par concept : la phrase en grand, le rendu sur
   son plateau, les specs en lignes, le vote. Le rendu passe d'un cote a
   l'autre d'une fiche a la suivante : quatre fiches identiques en cascade se
   liraient comme un catalogue, pas comme un carnet. */
.com-head { padding-bottom: clamp(2rem, 4vw, 3.25rem); }
.com-head .page-sub { max-width: 54ch; }
.com { background: var(--color-sand-soft); padding-bottom: clamp(2.5rem, 6vw, 5rem); }
.com-list { list-style: none; margin: 0; padding: 0; }
.concept + .concept .concept-in { border-top: 1px solid var(--color-border-soft); }
.concept-in {
  display: grid; align-items: center;
  grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
  grid-template-areas: "rendu tete" "rendu corps";
  column-gap: clamp(2rem, 5vw, 5rem);
  padding-block: clamp(2.75rem, 6vw, 5.5rem);
}
.concept:nth-child(even) .concept-in {
  grid-template-columns: minmax(0, 6fr) minmax(0, 5fr);
  grid-template-areas: "tete rendu" "corps rendu";
}
.concept-tete { grid-area: tete; align-self: end; }
.concept-rendu { grid-area: rendu; margin: 0; }
.concept-corps { grid-area: corps; align-self: start; }
.concept-num { font-size: var(--text-sm); font-weight: 600; color: var(--color-muted); }
.concept-titre {
  margin: 0.55rem 0 0; font-family: var(--font-display); font-weight: 700;
  font-size: clamp(2.3rem, 5vw, 4.3rem); line-height: 0.96; letter-spacing: var(--tracking-tight);
}
.concept-plaque {
  aspect-ratio: 1; background: var(--color-plate); border-radius: var(--radius-lg);
  display: grid; place-items: center; overflow: hidden;
}
.concept-plaque img { width: 86%; height: auto; object-fit: contain; }
.concept-rendu figcaption { margin-top: 0.7rem; font-size: var(--text-xs); color: var(--color-muted); }
.concept-desc { margin-top: 1.1rem; max-width: 42ch; font-size: var(--text-md); color: var(--color-charcoal); }
.concept-specs {
  margin: 1.5rem 0 0; display: grid; grid-template-columns: auto 1fr;
  border-top: 1px solid var(--color-border-soft); max-width: 30rem;
}
.concept-specs dt, .concept-specs dd { margin: 0; padding: 0.6rem 0; border-bottom: 1px solid var(--color-border-soft); font-size: var(--text-sm); }
.concept-specs dt { color: var(--color-muted); padding-right: 1.5rem; }
.concept-actes { margin-top: 1.6rem; display: flex; flex-wrap: wrap; align-items: center; gap: 0.75rem 1.1rem; }
.concept-compte { font-size: var(--text-sm); color: var(--color-muted); }
.concept-compte strong { color: var(--color-black); font-weight: 700; }
.concept-signup { margin-top: 1rem; max-width: 30rem; }
.com-fin .container { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 1.2rem 2rem; }
.com-fin-txt { font-family: var(--font-display); font-weight: 700; font-size: clamp(1.6rem, 3.4vw, 2.6rem); line-height: 1.05; color: var(--color-warm-white); max-width: 22ch; }
.ballot-plus { margin-top: var(--space-2); }
@media (max-width: 760px) {
  .concept-in, .concept:nth-child(even) .concept-in {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "tete" "rendu" "corps";
    row-gap: 1.4rem;
  }
  .concept-actes .btn { flex: 1 1 100%; }
}

/* En-tete, 10.10.2026 : avec le lien Communaute, le logo, six liens et les
   outils ne tiennent plus cote a cote sous 1060 px (ils se chevauchaient deja
   un peu entre 861 et 960). Le burger prend le relais des 1060 px ; seules
   les regles de l'en-tete suivent, la page garde sa mise en page d'ordinateur.
   Jusqu'a 1240 px, le sous-titre du logo s'efface et les liens se resserrent. */
@media (max-width: 1240px) {
  .logo-sub { display: none; }
  .main-nav { gap: 1.3rem; }
}
@media (max-width: 1060px) {
  .burger { display: block; justify-self: start; }
  .search-btn { display: none; }
  .header-left { display: contents; }
  .header-inner > .logo, .header-left > .logo { justify-self: center; }
  .header-tools { justify-self: end; }
  .main-nav { display: none; }
  .header-tools .tool-select { display: none; }
  .mobile-menu .tool-select { display: inline-block; }
  .mobile-tools { display: flex; gap: 0.8rem; margin-top: var(--space-3); }
}

/* ======================= FICHE PRODUIT, REPRISE DU 10.10.2026 (SOIR) ======
   Retours de Benjamin sur iPhone, video « defilement » a l'appui :
   1. les infos etaient trop espacees, et surtout irregulierement (8, 16, 44,
      50, 28, 45, 21, 49 px d'un bloc a l'autre) : on lisait un bug. Un seul
      rythme maintenant : serre dans un groupe, plus large entre les groupes ;
   2. la barre d'achat collante est retiree (dans app.js) ;
   3. les photos, sur le modele de WHOOP : plus grandes, une a la fois sur
      telephone, une mosaique sur ordinateur. */

/* --- Galerie ------------------------------------------------------------- */
.pdp-galerie { position: relative; }
.pdp-zoom {
  position: absolute; top: 0.85rem; right: 0.85rem; z-index: 2;
  width: 2.5rem; height: 2.5rem; display: none; place-items: center;
  border-radius: 50%; border: 0; cursor: pointer;
  background: rgba(250, 249, 246, 0.82); color: var(--color-black);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
}
.pdp-zoom svg { width: 1.15rem; height: 1.15rem; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; }
.pdp-points { display: none; }
.pdp-point {
  width: 22px; height: 26px; padding: 0; border: 0; background: none; cursor: pointer;
  display: grid; place-items: center;
}
.pdp-point::before {
  content: ""; width: 6px; height: 6px; border-radius: 50%;
  background: var(--color-border); transition: background-color 220ms var(--ease-ui), transform 220ms var(--ease-ui);
}
.pdp-point[aria-current="true"]::before { background: var(--color-black); transform: scale(1.3); }

@media (max-width: 860px) {
  /* Une photo a la fois, bord a bord : on feuillette, on ne devine plus la
     suivante qui depasse. Les points disent qu'il y en a d'autres. */
  .pdp-plans { gap: 0; }
  .pdp-plan, .pdp-plan:last-child { flex: 0 0 100%; scroll-snap-align: center; scroll-snap-stop: always; }
  .pdp-compte { display: none; }
  .pdp-zoom { display: grid; }
  .pdp-points { display: flex; justify-content: center; padding-top: 0.6rem; }
  .pdp-retour { padding-top: 0.9rem; padding-bottom: 0.9rem; }
}
@media (min-width: 861px) {
  /* La colonne photo prend plus de place, et la mosaique alterne une grande
     photo et deux cote a cote : six photos se lisent comme une sequence. */
  .pdp-grid { grid-template-columns: minmax(0, 1.7fr) minmax(330px, 1fr); }
  .pdp-plans { gap: 4px; }
  .pdp-plan--large { grid-column: 1 / -1; }
}

/* --- Colonne d'achat : un seul rythme ----------------------------------- */
.pdp-achat .product-head { margin-bottom: 0; }
.pdp-achat .product-statement { margin-top: 0.35rem; }
.pdp-achat .product-spec { margin-top: 0.8rem; }
.pdp-achat .price-line { margin-top: 1rem; margin-bottom: 0; }
.pdp-achat .ways-pick { margin-top: 1.75rem; }
.pdp-achat .buy-box { margin-top: 1.75rem; gap: 1rem; }
/* « Compatibility WHOOP 5.0 » sur une ligne, la consigne juste dessous. */
.pdp-achat .fit-fixed { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.15rem 0.6rem; }
.pdp-achat .fit-fixed-value { margin-top: 0; font-size: var(--text-base); }
.pdp-achat .fit-fixed .form-msg, .pdp-achat .fit-fixed .band-only-note { flex-basis: 100%; }
.pdp-achat .fit-fixed .form-msg { margin-top: 0.2rem; }
.pdp-achat .fit-fixed .form-msg:empty { display: none; }
.pdp-achat .trust-strip { margin-top: 0.25rem; }
.pdp-achat .pair-up { margin-top: 2rem; }
.pdp-porte { margin-top: clamp(3rem, 7vw, 5.5rem); }
@media (max-width: 860px) {
  .pdp-achat { padding-top: 1.4rem; }
  /* Quantite et bouton sur une seule ligne : empiles, ils faisaient 123 px. */
  .pdp-achat .buy-row { flex-wrap: nowrap; gap: 0.75rem; }
  .pdp-achat .buy-row .btn--solid { min-width: 0; }
}
/* La liste livraison / retours en une colonne partout : sur deux colonnes
   inegales, elle cassait le rythme de la colonne d'achat. */
.pdp-achat .trust-strip { flex-direction: column; gap: 0.3rem; }

/* Banniere de la collection, reprise du 10.10.2026 au soir : un bandeau
   etendu (3:1, 4:3 sur telephone) plutot qu'un bloc, et une poussee tres
   lente vers l'avant, comme un plan fixe de cinema qui respire. Seulement
   si le visiteur n'a pas demande moins de mouvement. */
.col-banniere { overflow: hidden; }
.col-banniere img { aspect-ratio: 3 / 1; }
@media (max-width: 700px) { .col-banniere img { aspect-ratio: 4 / 3; } }
@media (prefers-reduced-motion: no-preference) {
  .col-banniere img { animation: banniere-respire 22s ease-in-out infinite alternate; transform-origin: 49% 55%; }
}
@keyframes banniere-respire { from { transform: scale(1); } to { transform: scale(1.06); } }

/* ======================= LE VOTE, DE NUIT (10.10.2026) ======================
   Demande de Benjamin : « Which one should we drop next? » sur fond noir.
   Une salle sombre ou seule la vitrine est eclairee : un faisceau tombe du
   haut sur le plateau, le plateau garde sa lumiere (les rendus ont un fond
   clair, on ne les eteint pas) et flotte au-dessus d'une ombre longue. C'est
   la profondeur qui manquait : un plan eclaire, un fond qui recule. Le texte
   passe en blanc chaud ; l'accent reste le blanc, pas l'or. */
.ballot {
  background:
    radial-gradient(60% 55% at 26% 18%, rgba(250,249,246,0.06) 0%, transparent 70%),
    var(--color-black);
  color: var(--color-warm-white);
}
.ballot .section-title { color: var(--color-warm-white); }
.ballot .section-sub { color: rgba(250,249,246,0.64); }
.ballot .btn--text { color: var(--color-warm-white); }
.ballot .btn--text:hover { color: rgba(250,249,246,0.7); }

/* La vitrine : faisceau en haut, bord bas assombri, ombre portee longue. */
.ballot .bs-plate {
  background:
    radial-gradient(85% 70% at 50% -8%, #ffffff 0%, rgba(255,255,255,0) 62%),
    linear-gradient(180deg, #f4f1ea 0%, #ddd8cd 100%);
  border: 1px solid rgba(255,255,255,0.14);
  box-shadow: 0 0 0 1px rgba(0,0,0,0.4),
              0 50px 90px -30px rgba(0,0,0,0.85),
              0 0 120px -10px rgba(250,249,246,0.10);
}
.ballot .bs-plate::after {
  content: ""; position: absolute; inset: 0; pointer-events: none; border-radius: inherit;
  box-shadow: inset 0 -40px 60px -30px rgba(17,17,15,0.28);
}
.ballot .bs-glow { background: radial-gradient(circle, rgba(17,17,15,0.10) 0%, transparent 68%); }
.ballot .bs-img { filter: drop-shadow(0 30px 34px rgba(17,17,15,0.32)); }

.ballot .bs-label { color: rgba(250,249,246,0.5); }
.ballot .bs-title { color: var(--color-warm-white); }
.ballot .bs-tally { color: rgba(250,249,246,0.6); }
.ballot .bs-tally strong { color: var(--color-warm-white); }
.ballot .bs-share::before { color: rgba(250,249,246,0.3); }
.ballot .btn--solid { background: var(--color-warm-white); color: var(--color-black); border-color: var(--color-warm-white); }
.ballot .btn--solid:hover { background: #fff; border-color: #fff; }
.ballot .btn--solid[disabled] { background: transparent; color: var(--color-warm-white); border-color: rgba(250,249,246,0.4); }
.ballot .btn--outline { color: var(--color-warm-white); border-color: rgba(250,249,246,0.55); }
.ballot .btn--outline:hover { background: var(--color-warm-white); color: var(--color-black); border-color: var(--color-warm-white); }

/* Le bulletin : filets a peine visibles, la ligne choisie s'allume. */
.ballot .ballot-list { border-top-color: rgba(250,249,246,0.12); }
.ballot .ballot-row { border-bottom-color: rgba(250,249,246,0.12); }
.ballot .ballot-no { color: rgba(250,249,246,0.4); }
.ballot .ballot-text { color: rgba(250,249,246,0.62); }
.ballot .ballot-num { color: rgba(250,249,246,0.5); }
.ballot .ballot-mark { color: var(--color-warm-white); }
.ballot .ballot-bar { background: rgba(250,249,246,0.1); }
.ballot .ballot-bar i { background: var(--color-warm-white); }
.ballot .ballot-row.is-on .ballot-hit { background: rgba(250,249,246,0.06); box-shadow: inset 2px 0 0 var(--color-warm-white); }
.ballot .ballot-row.is-on .ballot-text, .ballot .ballot-row.is-on .ballot-no { color: var(--color-warm-white); }
.ballot .ballot-row.is-leading .ballot-no::after { color: var(--color-warm-white); }
.ballot .ballot-row.is-voted .ballot-text { color: rgba(250,249,246,0.4); }
@media (hover: hover) and (pointer: fine) {
  .ballot .ballot-hit:hover { background: rgba(250,249,246,0.06); }
  .ballot .ballot-hit:hover .ballot-text { color: var(--color-warm-white); }
}
/* L'inscription, ecrite sur une ligne claire. */
.ballot .signature-label { color: rgba(250,249,246,0.5); }
.ballot .signature-line { border-bottom-color: rgba(250,249,246,0.55); }
.ballot .signature-line input, .ballot .signature-go { color: var(--color-warm-white); }
.ballot .signature-line input::placeholder { color: rgba(250,249,246,0.42); }
.ballot .signature-line:focus-within { border-bottom-color: var(--color-warm-white); }
/* Quand le vote ferme la page (collection), un filet le separe du pied de
   page, noir lui aussi : sans lui, les deux blocs se confondaient. */
#view:has(> .ballot:last-child) + .site-footer { border-top: 1px solid rgba(250,249,246,0.08); }

/* ======================= VIDEOS D'AMBIANCE (10.10.2026) =================== */
.ambiance { display: block; width: 100%; height: 100%; object-fit: cover; background: var(--color-black); }

/* « The house » : le texte a gauche, la boucle a droite en 4:5. Sur
   telephone, la video passe au-dessus du texte, a fond perdu. */
.story-film { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 0.9fr); gap: clamp(2rem, 6vw, 6rem); align-items: center; }
.story-film .story-copy { order: -1; max-width: 34rem; }
.story-video { margin: 0; aspect-ratio: 4 / 5; overflow: hidden; border-radius: var(--radius-lg); background: var(--color-black);
  box-shadow: 0 40px 80px -40px rgba(17,17,15,0.45); }
@media (max-width: 760px) {
  .story-film { grid-template-columns: minmax(0, 1fr); gap: var(--space-4); }
  .story-film .story-copy { order: 0; }
  .story-video { margin-inline: calc(var(--gutter) * -1); border-radius: 0; box-shadow: none; }
}

/* ======================= COMMUNAUTE DE NUIT (10.10.2026) ==================
   Un plan filme en tete (des mains choisissent un bracelet au grillage), qui
   se fond dans le noir des fiches comme le hero de l'accueil. Les fiches
   sont des vitrines eclairees dans une salle sombre : le plateau garde sa
   lumiere, flotte au-dessus d'une ombre longue et derive un peu au
   defilement. La fin repasse au clair avant le pied de page noir. */
.com-tete { position: relative; background: var(--color-black); color: var(--color-warm-white); overflow: hidden; isolation: isolate; }
.com-film { position: absolute; inset: 0; z-index: -2; }
.com-tete::after {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background:
    linear-gradient(180deg, rgba(17,17,15,0.15) 0%, rgba(17,17,15,0.05) 35%, rgba(17,17,15,0.75) 78%, var(--color-black) 100%),
    linear-gradient(90deg, rgba(17,17,15,0.55) 0%, rgba(17,17,15,0) 60%);
}
.com-tete-txt {
  min-height: min(82svh, 820px); display: flex; flex-direction: column; justify-content: flex-end;
  padding-top: var(--space-4); padding-bottom: clamp(2.5rem, 6vw, 4.5rem);
}
.com-tete-txt .back-btn { align-self: flex-start; margin-bottom: auto; color: var(--color-warm-white); border-color: rgba(250,249,246,0.45); background: rgba(17,17,15,0.25); }
.com-tete-txt .back-btn:hover { background: var(--color-warm-white); color: var(--color-black); border-color: var(--color-warm-white); }
.com-tete .page-title { color: var(--color-warm-white); max-width: 16ch; font-size: clamp(2.6rem, 6vw, 5.4rem); line-height: 0.95; }
.com-tete .page-sub { color: rgba(250,249,246,0.78); max-width: 52ch; margin-top: 1rem; }
@media (max-width: 700px) {
  /* Telephone : le plan en 4:5 en haut, le texte dessous sur le noir. */
  .com-film { position: relative; inset: auto; aspect-ratio: 4 / 5; }
  .com-tete::after { background: linear-gradient(180deg, rgba(17,17,15,0) 40%, rgba(17,17,15,0.4) 52%, var(--color-black) 60%); }
  .com-tete-txt { min-height: 0; margin-top: -32%; padding-top: 0; }
  .com-tete-txt .back-btn { position: absolute; top: 1rem; left: var(--gutter); margin: 0; }
}

.com--nuit {
  background:
    radial-gradient(50% 40% at 30% 0%, rgba(250,249,246,0.05) 0%, transparent 70%),
    var(--color-black);
  color: var(--color-warm-white);
}
.com--nuit .concept + .concept .concept-in { border-top-color: rgba(250,249,246,0.1); }
.com--nuit .concept-num { color: rgba(250,249,246,0.5); }
.com--nuit .concept-titre { color: var(--color-warm-white); }
.com--nuit .concept-desc { color: rgba(250,249,246,0.72); }
.com--nuit .concept-rendu figcaption { color: rgba(250,249,246,0.45); }
.com--nuit .concept-specs { border-top-color: rgba(250,249,246,0.12); }
.com--nuit .concept-specs dt, .com--nuit .concept-specs dd { border-bottom-color: rgba(250,249,246,0.12); }
.com--nuit .concept-specs dt { color: rgba(250,249,246,0.5); }
.com--nuit .concept-specs dd { color: var(--color-warm-white); }
.com--nuit .concept-compte { color: rgba(250,249,246,0.6); }
.com--nuit .concept-compte strong { color: var(--color-warm-white); }
.com--nuit .btn--solid { background: var(--color-warm-white); color: var(--color-black); border-color: var(--color-warm-white); }
.com--nuit .btn--solid[disabled] { background: transparent; color: var(--color-warm-white); border-color: rgba(250,249,246,0.4); opacity: 1; }
.com--nuit .btn--outline { color: var(--color-warm-white); border-color: rgba(250,249,246,0.55); }
.com--nuit .btn--outline:hover { background: var(--color-warm-white); color: var(--color-black); border-color: var(--color-warm-white); }
.com--nuit .signature-label { color: rgba(250,249,246,0.5); }
.com--nuit .signature-line { border-bottom-color: rgba(250,249,246,0.55); }
.com--nuit .signature-line input, .com--nuit .signature-go { color: var(--color-warm-white); }
.com--nuit .signature-line input::placeholder { color: rgba(250,249,246,0.42); }
/* La vitrine, meme lumiere que le vote de l'accueil. */
.com--nuit .concept-plaque {
  background:
    radial-gradient(85% 70% at 50% -8%, #ffffff 0%, rgba(255,255,255,0) 62%),
    linear-gradient(180deg, #f4f1ea 0%, #ddd8cd 100%);
  border: 1px solid rgba(255,255,255,0.14);
  box-shadow: 0 0 0 1px rgba(0,0,0,0.4), 0 60px 100px -36px rgba(0,0,0,0.9), 0 0 140px -20px rgba(250,249,246,0.10);
  will-change: transform;
}
.com--nuit .concept-plaque img { filter: drop-shadow(0 30px 34px rgba(17,17,15,0.3)); }

.com-fin .com-fin-txt { color: var(--color-black); }

/* About : deux images a fond perdu, decalees d'une hauteur, comme deux
   tirages poses l'un apres l'autre plutot qu'une grille. */
.about-duo { display: grid; grid-template-columns: 1.15fr 1fr; gap: 4px; margin-top: clamp(2.5rem, 6vw, 4.5rem); align-items: start; }
.about-fig { margin: 0; position: relative; }
.about-fig:last-child { margin-top: clamp(2rem, 8vw, 7rem); }
.about-fig img { display: block; width: 100%; height: auto; aspect-ratio: 3 / 2; object-fit: cover; }
.about-fig figcaption { padding: 0.6rem var(--gutter) 0; font-size: var(--text-xs); color: var(--color-muted); }
@media (max-width: 760px) {
  .about-duo { grid-template-columns: 1fr; gap: 1.5rem; }
  .about-fig:last-child { margin-top: 0; }
}

/* ======================= REPRISE DU 10.10.2026 (NUIT) =====================
   Retours de Benjamin, captures a l'appui. */

/* --- Cartes : le visuel 4:3 est centre sur le bracelet ------------------- */
.card--photo .card-media img:not(.card-alt) { object-position: 50% 50%; }

/* --- « Deuxieme coloris » : la puce se remplit d'encre -------------------- */
.pair-plate { background: var(--color-ivory-deep); }
.pair-plate img { width: 100%; height: 100%; object-fit: cover; }
.pair-add { position: relative; overflow: hidden; isolation: isolate; }
.pair-add::before {
  content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit;
  background: var(--color-black); transform: scaleX(0); transform-origin: left center;
  transition: transform 520ms var(--ease-luxury);
}
.pair-add.is-added { border-color: var(--color-black); background: var(--color-warm-white); color: var(--color-warm-white); }
.pair-add.is-added::before { transform: scaleX(1); }
.pair-add.is-added .pair-plus { color: var(--color-warm-white); font-size: 0.82rem; font-weight: 700; letter-spacing: 0.02em; }
.pair-add.is-added .pair-plate { box-shadow: 0 0 0 1.5px rgba(250,249,246,0.85); }
.pair-add.is-pulse .pair-plus { animation: pair-compte 420ms var(--ease-luxury); }
@keyframes pair-compte { from { transform: translateY(70%); opacity: 0; } }
@media (hover: hover) and (pointer: fine) {
  .pair-add.is-added:hover { background: var(--color-warm-white); border-color: var(--color-black); }
}
@media (prefers-reduced-motion: reduce) {
  .pair-add::before { transition: none; }
  .pair-add.is-pulse .pair-plus { animation: none; }
}

/* --- « Compose your rotation », de nuit ------------------------------------
   Le beige ne tenait plus a cote du noir du vote et du blanc du drop. La
   section passe a l'encre : le recu reste en papier, pose sur un comptoir
   sombre, une lumiere tombe dessus, il est legerement de biais et porte une
   vraie ombre. Sur l'accueil, les plages alternent desormais : encre, clair,
   encre, clair, encre. */
.rotation--nuit {
  background:
    radial-gradient(42% 70% at 72% 50%, rgba(250,249,246,0.085) 0%, transparent 70%),
    var(--color-black);
  padding-block: clamp(4rem, 9vw, 7.5rem);
}
.rotation--nuit .rot-grid { align-items: center; grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr); }
.rotation--nuit .section-title { color: var(--color-warm-white); font-size: clamp(2.4rem, 5vw, 4.4rem); line-height: 0.96; max-width: 11ch; }
.rotation--nuit .section-sub { color: rgba(250,249,246,0.7); max-width: 34ch; }
.rotation--nuit .rot-fifth {
  margin-top: var(--space-4); padding-top: 1rem; max-width: 40ch;
  border-top: 1px solid rgba(250,249,246,0.16);
  color: var(--color-warm-white); font-weight: 600;
}
.rotation--nuit .rot-note { color: rgba(250,249,246,0.5); max-width: 46ch; }
.rotation--nuit .ticket {
  color: var(--color-black);
  background: linear-gradient(180deg, #fbfaf6 0%, #f3f0e8 100%);
  border: 0;
  transform: rotate(-1.6deg);
  box-shadow:
    0 1px 0 rgba(255,255,255,0.9) inset,
    0 2px 3px rgba(0,0,0,0.35),
    0 40px 70px -24px rgba(0,0,0,0.85),
    0 90px 120px -60px rgba(0,0,0,0.9);
  max-width: 34rem; justify-self: center; width: 100%;
}
.rotation--nuit .ticket-tear {
  background: radial-gradient(circle at 5px -2px, transparent 0 6px, #f3f0e8 6px);
  background-size: 14px 9px; background-repeat: repeat-x; filter: none;
}
.rotation--nuit .ticket-ref { color: var(--color-muted); }
@media (max-width: 900px) {
  .rotation--nuit .rot-grid { grid-template-columns: minmax(0, 1fr); gap: var(--space-5); }
  .rotation--nuit .ticket { transform: rotate(-1deg); }
  .rotation--nuit { background: radial-gradient(80% 45% at 50% 78%, rgba(250,249,246,0.08) 0%, transparent 70%), var(--color-black); }
}
/* Telephone : la video de « The house » part du haut de sa section, collee
   au noir du vote. La marge du haut ouvrait une bande claire entre les deux. */
@media (max-width: 760px) { .story--film { padding-top: 0; } }

/* --- Hero : l'ecriture du bracelet ----------------------------------------
   Gochi Hand, penchee de 9 degres comme le trace imprime sur la sangle. Le
   masque des lignes gagne de la marge : une ecriture penchee deborde a
   droite, et le « y » de story descend sous la ligne. */
.hv-titre--main {
  font-family: "Gochi Hand", var(--font-display); font-weight: 400;
  font-size: clamp(3.6rem, 8.6vw, 8.2rem); line-height: 0.9; letter-spacing: 0;
  transform: skewX(-9deg); text-shadow: 0 2px 24px rgba(17,17,15,0.35);
}
.hv-titre--main .hline { padding: 0 0.12em 0.14em; }
.hv-titre--main .hline + .hline { margin-top: -0.06em; }
@media (max-width: 700px) { .hv-titre--main { font-size: clamp(3.4rem, 17vw, 5rem); } }

/* --- Fin de la Communaute : la sangle a ecrire ----------------------------
   Une sangle noire vierge, tissee (deux trames croisees), sa piece au W a
   droite. On ecrit dessus dans l'ecriture du bracelet. Plus courte sur
   telephone : le titre, la sangle, le bouton, rien d'autre. */
.com-fin { padding-block: clamp(3.5rem, 8vw, 6.5rem); }
.com-fin-in { display: grid; gap: clamp(1.5rem, 3vw, 2.25rem); justify-items: start; }
.com-fin .com-fin-txt { font-size: clamp(2rem, 4.6vw, 3.8rem); line-height: 0.98; max-width: 16ch; margin: 0; }
.sangle-form { display: grid; gap: 1.1rem; width: 100%; max-width: 46rem; justify-items: start; }
.sangle {
  position: relative; display: flex; align-items: center; width: 100%;
  height: clamp(5.2rem, 10vw, 7rem); padding: 0 clamp(5rem, 9vw, 7rem) 0 clamp(1.4rem, 3vw, 2.4rem);
  border-radius: 999px; cursor: text;
  background:
    repeating-linear-gradient(90deg, rgba(255,255,255,0.045) 0 2px, transparent 2px 5px),
    repeating-linear-gradient(0deg, rgba(0,0,0,0.35) 0 2px, transparent 2px 5px),
    linear-gradient(180deg, #2a2926 0%, #121210 55%, #1c1b18 100%);
  box-shadow: 0 1px 0 rgba(255,255,255,0.08) inset, 0 -8px 18px rgba(0,0,0,0.45) inset,
              0 30px 50px -28px rgba(17,17,15,0.6);
  transform: rotate(-1.2deg);
  transition: box-shadow 300ms var(--ease-ui), transform 500ms var(--ease-luxury);
}
.sangle:focus-within { transform: rotate(0deg); box-shadow: 0 1px 0 rgba(255,255,255,0.08) inset, 0 -8px 18px rgba(0,0,0,0.45) inset, 0 36px 60px -26px rgba(17,17,15,0.7); }
.sangle-texte {
  flex: 1; min-width: 0; border: 0; background: none; outline: none;
  font-family: "Gochi Hand", cursive; font-size: clamp(1.7rem, 3.6vw, 2.6rem);
  color: var(--color-warm-white); transform: skewX(-9deg); padding: 0.2rem 0;
}
.sangle-texte::placeholder { color: rgba(250,249,246,0.38); }
.sangle-boucle {
  position: absolute; right: clamp(0.9rem, 2vw, 1.4rem); top: 50%; transform: translateY(-50%);
  width: clamp(3.4rem, 6vw, 4.6rem); height: 72%; border-radius: 14px;
  display: grid; place-items: center;
  background: linear-gradient(180deg, #3a3833 0%, #0e0e0c 100%);
  box-shadow: 0 1px 0 rgba(255,255,255,0.12) inset, 0 4px 10px rgba(0,0,0,0.5);
  color: rgba(250,249,246,0.55); font-weight: 600; font-size: 0.95rem; letter-spacing: 0.04em;
}
@media (max-width: 700px) {
  .com-fin { padding-block: var(--space-5) var(--space-6); }
  .sangle-envoi { width: 100%; justify-content: center; }
}

/* --- Le vote sur ordinateur : la liste a la hauteur du plateau ------------
   Quatre lignes courtes en haut d'une colonne vide se lisaient comme un
   oubli. Les lignes grandissent, s'espacent, et la phrase choisie porte une
   fleche. */
@media (min-width: 900px) {
  .ballot .ballot-hit {
    grid-template-columns: 3.4rem minmax(0, 1fr) auto 1.6rem;
    padding: clamp(1.8rem, 2.6vw, 2.5rem) 1rem clamp(1.8rem, 2.6vw, 2.5rem) 0;
    transition: padding-left 380ms var(--ease-luxury), background var(--dur-fast) var(--ease-ui);
  }
  .ballot .ballot-text { font-size: clamp(1.6rem, 2.5vw, 2.4rem); line-height: 1.05; }
  .ballot .ballot-no { font-size: var(--text-sm); align-self: center; }
  .ballot .ballot-row.is-on .ballot-hit { padding-left: 1.2rem; }
  .ballot .ballot-mark { align-self: center; font-size: 1.1rem; }
  .ballot .ballot-row.is-on:not(.is-voted) .ballot-mark::before { content: "→"; }
}
/* L'ancienne regle `.com-fin .container { display: flex }` l'emportait sur la
   grille, et le champ imposait sa largeur minimale : la sangle debordait a
   droite sur telephone. */
.com-fin .com-fin-in { display: grid; grid-template-columns: minmax(0, 1fr); justify-content: stretch; }
.sangle-form { grid-template-columns: minmax(0, 1fr); }
.sangle-texte { width: 100%; }
@media (max-width: 700px) { .sangle { transform: rotate(-0.8deg); } }
/* Telephone : les deux puces restent cote a cote, meme quand l'une affiche
   son compte (×1) et s'elargit. */
@media (max-width: 640px) {
  .pair-list { flex-wrap: nowrap; }
  .pair-list > li { flex: 1 1 0; min-width: 0; }
  .pair-list .pair-add { width: 100%; padding-right: 0.6rem; }
  .pair-list .pair-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; flex: 1; text-align: left; }
}
/* Le compte se pose en petite pastille sur la vignette : le nom du coloris
   garde toute sa place. */
.pair-add.is-added .pair-plus {
  position: absolute; left: 34px; top: 4px; z-index: 1;
  min-width: 20px; height: 20px; padding: 0 5px; border-radius: 10px;
  display: grid; place-items: center;
  background: var(--color-warm-white); color: var(--color-black);
  font-size: 0.68rem; font-weight: 700; box-shadow: 0 0 0 2px var(--color-black);
}
@media (max-width: 640px) { .pair-list .pair-name { overflow: visible; text-overflow: clip; white-space: normal; line-height: 1.15; } }

/* ======================= HERO DE LA COLLECTION, FACON WHOOP ===============
   10.10.2026 (nuit). Le film reste colle sous l'en-tete ; la page (titre,
   cartes, vote) monte par-dessus comme une feuille, et le film s'assombrit a
   mesure qu'il est recouvert (--p, pose par initHeroCollant). Hauteur :
   l'ecran sous le bandeau et l'en-tete, comme le hero de l'accueil. */
.col-hero {
  --p: 0;
  position: sticky; top: var(--header-h-scrolled, 64px); z-index: 0;
  height: calc(100svh - var(--hv-haut, var(--header-h))); min-height: 460px; max-height: 1000px;
  background: var(--color-black); overflow: hidden;
}
.col-hero-film { position: absolute; inset: 0; }
.col-hero-voile {
  position: absolute; inset: 0; pointer-events: none; background: var(--color-black);
  opacity: calc(0.08 + var(--p) * 0.62);
}
.col-hero-film .ambiance { transform: scale(calc(1 + var(--p) * 0.04)); transform-origin: 50% 40%; }
.col-corps {
  position: relative; z-index: 1; background: var(--color-paper, var(--color-warm-white));
  box-shadow: 0 -30px 60px -20px rgba(17,17,15,0.35);
}
.col-corps > .page-head { padding-top: clamp(2.25rem, 5vw, 3.5rem); }
@media (prefers-reduced-motion: reduce) { .col-hero-film .ambiance { transform: none; } }

/* ======================= REPRISE (10.10.2026, tard) ======================= */
/* --- Titre du hero : le geste du bracelet dans la typographie du site ------
   Par defaut « geste » : « No Risk, » droit, « no story » en minuscules et en
   italique, comme la seconde ligne penchee de la sangle. Variantes : droit
   (les deux lignes droites, « No Story » capitalise), italique (tout penche). */
.hv-titre--main {
  font-family: var(--font-display); font-weight: 700; transform: none;
  font-size: clamp(3.1rem, 7vw, 6.4rem); line-height: 0.95; letter-spacing: var(--tracking-tight);
  text-shadow: 0 2px 30px rgba(17,17,15,0.25);
}
.hv-titre--main .hline { padding: 0 0.06em 0.08em; }
.hv-titre--main .hline + .hline { margin-top: 0; }
.hero-video[data-titre="geste"] .hv-titre--main .hline:nth-child(2) .hline-in { font-style: italic; font-weight: 600; letter-spacing: -0.01em; }
.hero-video[data-titre="droit"] .hv-titre--main .hline:nth-child(2) .hline-in { text-transform: capitalize; }
.hero-video[data-titre="italique"] .hv-titre--main .hline-in { font-style: italic; font-weight: 600; }
@media (max-width: 700px) { .hv-titre--main { font-size: clamp(3rem, 13.5vw, 4.4rem); } }

/* La sangle de la Communaute s'ecrit dans la typographie du site. */
.sangle-texte { font-family: var(--font-display); font-style: italic; font-weight: 500; transform: none; font-size: clamp(1.4rem, 3vw, 2.1rem); letter-spacing: -0.01em; }

/* --- « Compose your rotation » : l'escalier --------------------------------
   Trois vrais bracelets, trois marches : chaque colonne descend d'un cran,
   comme le prix. Le chiffre est le heros de chaque marche ; l'ancien prix,
   barre, juste dessous. En pied, le total et l'economie, puis le bouton. */
.rotation--nuit {
  background: radial-gradient(70% 60% at 60% 30%, rgba(250,249,246,0.055) 0%, transparent 70%), var(--color-black);
  padding-block: clamp(4rem, 9vw, 8rem);
}
.rot-tete { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 0.8fr); gap: 1rem 3rem; align-items: end; }
.rotation--nuit .section-title { color: var(--color-warm-white); font-size: clamp(2.4rem, 5.4vw, 4.8rem); line-height: 0.95; max-width: 12ch; margin: 0; }
.rotation--nuit .section-sub { color: rgba(250,249,246,0.66); max-width: 36ch; margin: 0; }
.rot-marches {
  list-style: none; margin: clamp(2.5rem, 6vw, 4.5rem) 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(0.75rem, 2.4vw, 2rem);
  --marche: clamp(1.25rem, 4vw, 3.75rem);
}
.rot-marche { margin-top: calc(var(--i) * var(--marche)); }
.rot-photo { position: relative; margin: 0; aspect-ratio: 4 / 5; overflow: hidden; border-radius: var(--radius); background: #1e1d1a; }
.rot-photo img { display: block; width: 100%; height: 100%; object-fit: cover; transition: transform 900ms var(--ease-luxury); }
@media (hover: hover) and (pointer: fine) { .rot-marche:hover .rot-photo img { transform: scale(1.035); } }
.rot-sac {
  position: absolute; left: 0.7rem; bottom: 0.7rem; padding: 0.3rem 0.6rem; border-radius: var(--radius);
  background: rgba(250,249,246,0.92); color: var(--color-black); font-size: var(--text-xs); font-weight: 600;
  opacity: 0; transform: translateY(6px); transition: opacity 300ms var(--ease-ui), transform 400ms var(--ease-luxury);
}
.rot-marche.is-filled .rot-sac { opacity: 1; transform: none; }
.rot-rang {
  display: flex; justify-content: space-between; gap: 0.5rem; margin: 1rem 0 0; padding-top: 0.75rem;
  border-top: 1px solid rgba(250,249,246,0.18);
  font-size: var(--text-sm); color: rgba(250,249,246,0.6);
}
.rot-rang span:last-child { color: var(--color-warm-white); font-weight: 600; }
.rot-prix {
  margin: 0.35rem 0 0; font-family: var(--font-display); font-weight: 700;
  font-size: clamp(1.6rem, 4.2vw, 3.6rem); line-height: 1; letter-spacing: var(--tracking-tight);
  color: var(--color-warm-white); font-variant-numeric: tabular-nums;
}
.rot-avant { margin: 0.4rem 0 0; font-size: var(--text-sm); color: rgba(250,249,246,0.42); text-decoration: line-through; }
.rot-pied {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 1.25rem 2rem;
  margin-top: clamp(1rem, 3vw, 2rem); padding-top: clamp(1.5rem, 3vw, 2rem); border-top: 1px solid rgba(250,249,246,0.18);
}
.rot-total { margin: 0; font-family: var(--font-display); font-weight: 600; font-size: clamp(1.15rem, 2vw, 1.5rem); color: var(--color-warm-white); }
.rot-msg { margin: 0.35rem 0 0; font-size: var(--text-sm); color: rgba(250,249,246,0.6); }
.rot-msg:empty { display: none; }
.rotation--nuit .rot-note { margin-top: 1.25rem; max-width: 70ch; font-size: var(--text-xs); color: rgba(250,249,246,0.42); }
@media (max-width: 760px) {
  .rot-tete { grid-template-columns: minmax(0, 1fr); }
  .rot-rang { flex-direction: column; gap: 0.1rem; font-size: 0.72rem; }
  .rot-avant { font-size: 0.72rem; }
  .rot-sac { left: 0.35rem; bottom: 0.35rem; font-size: 0.6rem; padding: 0.2rem 0.4rem; }
  .rot-pied .btn { width: 100%; justify-content: center; }
}
.rot-avant--vide { visibility: hidden; }

/* --- Fiche produit : les informations dans la colonne d'achat --------------
   10.10.2026 : description, atouts et volets remontent pres du prix et du
   bouton, au lieu d'attendre en bas de page apres trois sections. */
.pdp-achat .pdp-desc { margin: 1.1rem 0 0; max-width: 46ch; font-size: var(--text-base); line-height: 1.6; color: var(--color-charcoal); }
.pdp-achat .pdp-atouts { list-style: none; margin: 0.9rem 0 0; padding: 0; display: grid; gap: 0.3rem; font-size: var(--text-sm); color: var(--color-muted); }
.pdp-achat .pdp-atouts li { display: flex; gap: 0.55rem; align-items: baseline; }
.pdp-achat .pdp-atouts li::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: var(--color-black); flex: none; transform: translateY(-2px); }
.pdp-achat .pdp-volets { margin-top: 2rem; }
.pdp-achat .pdp-volets .acc-panel-inner p + p { margin-top: 0.7rem; }
@media (min-width: 861px) {
  .pdp-achat { top: var(--achat-top, calc(var(--header-h-scrolled) + 1.5rem)); }
}

/* --- En-tete de la collection : la photo, facon Communaute, plus compact ---
   Collant (defilement WHOOP) : la page monte par-dessus et le voile fonce. */
.col-tete { position: sticky; top: var(--header-h-scrolled, 64px); z-index: 0; --p: 0; }
.col-tete .com-tete-txt { min-height: min(66svh, 660px); }
.col-tete .page-title { font-size: clamp(2.6rem, 5.6vw, 5rem); }
.col-tete .col-hero-voile { z-index: 2; opacity: calc(var(--p) * 0.7); }
.col-page { padding-top: clamp(1.75rem, 4vw, 2.75rem); }
.col-page .drop-facts, .col-page > :first-child { margin-top: 0; }
@media (max-width: 700px) {
  .col-tete .com-tete-txt { min-height: 0; }
  .col-tete .com-film { aspect-ratio: 5 / 4; }
  .col-tete .com-film img { width: 100%; height: 100%; object-fit: cover; }
  .col-tete .com-tete-txt { margin-top: -18%; }
}

/* --- Bas de la collection : le vote noir touche le pied de page noir ------
   La marge du pied de page ouvrait une bande claire (le vote est maintenant
   dans .col-corps, l'ancienne regle ne le trouvait plus). Entre deux noirs,
   un filet rentre dans la grille, comme une couture : il separe sans casser. */
#view:has(> .col-corps > .ballot:last-child) + .site-footer { margin-top: 0; border-top: 0; }
#view:has(> .col-corps > .ballot:last-child) + .site-footer .footer-inner { position: relative; }
#view:has(> .col-corps > .ballot:last-child) + .site-footer .footer-inner::before {
  content: ""; position: absolute; top: 0; left: var(--gutter); right: var(--gutter); height: 1px;
  background: linear-gradient(90deg, transparent, rgba(250,249,246,0.18) 18%, rgba(250,249,246,0.18) 82%, transparent);
}
.com-film picture, .com-film img { display: block; width: 100%; height: 100%; }
.com-film img { object-fit: cover; object-position: 50% 50%; }

/* ======================= PIED DE PAGE : PLUS JAMAIS DE BANDE ===============
   10.10.2026. La marge au-dessus du pied de page ouvrait une bande claire
   sous chaque section coloree (vote, matiere, encre), et on la retirait page
   par page. Regle unique maintenant : le pied de page n'a plus de marge ; ce
   sont les fins de page sur fond clair (pages de texte, About) qui portent
   leur propre respiration, sur leur propre fond. */
.site-footer { margin-top: 0; }
#view > .page-head:last-child { padding-bottom: clamp(3.5rem, 7vw, 6rem); }
#view > .about-duo:last-child { margin-bottom: 0; padding-bottom: clamp(3rem, 6vw, 5rem); }

/* --- « What it is » sur la fiche : le gris du sol du terrain ---------------
   Ni blanc, ni noir, ni beige : la couleur du beton du padel sur lequel les
   bracelets sont poses dans le shooting (releve #a8b9c3 sur les trois
   photos, eclairci a ~58 % de luminance pour le texte noir). La section se
   lit comme le sol du terrain, entre le noir de « From court to counter »
   et le noir du pied de page. */
.pdp-matiere { background: #becad2; color: var(--color-black); }
.pdp-matiere .section-sub { color: rgba(17,17,15,0.72); }
.pdp-matiere .pdp-faits dt { color: var(--color-black); }
.pdp-matiere .pdp-faits dd { color: rgba(17,17,15,0.72); }

/* « What it is », deux fonds a comparer (10.10.2026). Le gris du terrain est
   retire. Blanc : l'alternance noir, clair, noir avec ses deux voisines.
   Flou : la macro s'etend derriere le texte, floutee et assombrie ; chaque
   coloris donne sa propre teinte a la section. */
.pdp-matiere[data-fond="flou"] { position: relative; isolation: isolate; overflow: hidden; background: var(--color-black); color: var(--color-warm-white); }
.pdp-matiere[data-fond="flou"]::before {
  content: ""; position: absolute; inset: -12%; z-index: -1;
  background: var(--macro) center / cover no-repeat;
  filter: blur(70px) brightness(0.42) saturate(1.15);
}
.pdp-matiere[data-fond="flou"] .section-title, .pdp-matiere[data-fond="flou"] .pdp-faits dt { color: var(--color-warm-white); }
.pdp-matiere[data-fond="flou"] .section-sub, .pdp-matiere[data-fond="flou"] .pdp-faits dd { color: rgba(250,249,246,0.74); }

/* ======================= MENU, REFAIT (10.10.2026) ========================
   Un panneau d'encre, comme les sections sombres du site. En tete le
   wordmark et une vraie croix (avant, rien dans le panneau ne le fermait).
   Puis l'entree boutique avec les trois vrais coloris, quatre liens en
   grand, l'aide en petit, la recherche sur une ligne, langue et devise.
   Plein ecran sur telephone ; 440 px sur ordinateur, ou la loupe l'ouvre. */
.mobile-menu {
  background: radial-gradient(70% 40% at 0% 0%, rgba(250,249,246,0.06), transparent 70%), var(--color-black);
  color: var(--color-warm-white);
  width: min(440px, 100vw); border-radius: 0; box-shadow: 30px 0 80px -30px rgba(0,0,0,0.6);
  padding: 0 var(--gutter) calc(1.5rem + env(safe-area-inset-bottom)); gap: 0;
}
@media (max-width: 700px) { .mobile-menu { width: 100vw; } }
.menu-tete {
  display: flex; align-items: center; justify-content: space-between;
  min-height: var(--header-h-scrolled, 64px); margin-bottom: 1.25rem;
  border-bottom: 1px solid rgba(250,249,246,0.1);
}
.menu-tete .logo-word { font-weight: 800; letter-spacing: 0.3em; font-size: 0.9rem; color: var(--color-warm-white); }
.menu-tete .logo-word span { font-weight: 300; }
.menu-close {
  width: 44px; height: 44px; margin-right: -10px; display: grid; place-items: center;
  background: none; border: 0; color: var(--color-warm-white); cursor: pointer;
}
.menu-close svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; }

/* L'entree boutique : trois vignettes qui se chevauchent, la phrase, le prix. */
.menu-shop {
  display: flex; align-items: center; gap: 1rem; padding: 1rem;
  border-radius: var(--radius-lg); background: rgba(250,249,246,0.06);
  border: 1px solid rgba(250,249,246,0.1); color: var(--color-warm-white);
  transition: background-color 300ms var(--ease-ui), border-color 300ms var(--ease-ui);
}
.menu-shop:hover, .menu-shop:focus-visible { background: rgba(250,249,246,0.1); border-color: rgba(250,249,246,0.22); }
.ms-vignettes { display: flex; flex: none; }
.ms-vignettes img {
  width: 46px; height: 46px; border-radius: 50%; object-fit: cover;
  box-shadow: 0 0 0 2px var(--color-black);
}
.ms-vignettes img + img { margin-left: -14px; }
.ms-texte { display: grid; gap: 0.15rem; min-width: 0; flex: 1; }
.ms-texte strong { font-family: var(--font-display); font-weight: 700; font-size: 1.05rem; line-height: 1.15; }
.ms-texte small { font-size: var(--text-sm); color: rgba(250,249,246,0.6); }
.ms-texte small .now { color: rgba(250,249,246,0.85); font-weight: 600; }
.ms-texte small .was { display: none; }
.ms-fleche { flex: none; font-size: 1.1rem; color: rgba(250,249,246,0.7); transition: transform 300ms var(--ease-luxury); }
.menu-shop:hover .ms-fleche { transform: translateX(4px); }

/* Les quatre liens principaux, en grand. Le lien de la page courante porte un
   point a gauche, comme le filet sous le lien actif sur ordinateur. */
.menu-liens { list-style: none; margin: 1.25rem 0 0; padding: 0; }
.mobile-menu .mobile-link {
  display: flex; align-items: center; gap: 0.75rem;
  padding: 0.6rem 0; border: 0; color: var(--color-warm-white);
  font-family: var(--font-display); font-weight: 700; letter-spacing: var(--tracking-tight);
  font-size: clamp(2rem, 9vw, 2.6rem); line-height: 1.05;
}
.mobile-menu .mobile-link::after { content: none; }
.mobile-menu .mobile-link::before {
  content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--color-warm-white);
  flex: none; margin-left: -1.1rem; opacity: 0; transition: opacity 250ms var(--ease-ui);
}
.mobile-menu .mobile-link.active::before { opacity: 1; }
.mobile-menu .mobile-link.active { padding-left: 1.1rem; }
.mobile-menu .mobile-link:not(.active) { color: rgba(250,249,246,0.82); }
.mobile-menu .mobile-link:hover { color: var(--color-warm-white); padding-left: 0; }
.mobile-menu .mobile-link.active:hover { padding-left: 1.1rem; }

/* L'aide, sur une ligne, en petit. */
.menu-aide {
  display: flex; flex-wrap: wrap; gap: 0.35rem 1.4rem; margin-top: 1.5rem; padding-top: 1.25rem;
  border-top: 1px solid rgba(250,249,246,0.1);
}
.menu-aide a { font-size: var(--text-sm); color: rgba(250,249,246,0.66); min-height: 44px; display: inline-flex; align-items: center; }
.menu-aide a:hover, .menu-aide a.active { color: var(--color-warm-white); }

/* Recherche : une ligne sous laquelle on ecrit. */
.mobile-menu .menu-search { margin-top: 0.75rem; }
.mobile-menu .menu-search input {
  width: 100%; border: 0; border-bottom: 1px solid rgba(250,249,246,0.25); border-radius: 0;
  background: transparent; color: var(--color-warm-white); padding: 0.8rem 0 0.8rem 1.8rem;
  font-size: 1rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23faf9f6' stroke-opacity='.6' stroke-width='1.6'%3E%3Ccircle cx='11' cy='11' r='6.5'/%3E%3Cpath d='m16 16 4.5 4.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: 0 50%; background-size: 18px;
}
.mobile-menu .menu-search input::placeholder { color: rgba(250,249,246,0.45); }
.mobile-menu .menu-search input:focus { border-bottom-color: var(--color-warm-white); background-color: transparent; }
.mobile-menu .menu-search-results a { color: var(--color-warm-white); }
.mobile-menu .menu-search-results a:hover { background: rgba(250,249,246,0.06); }
.mobile-menu .menu-search-results small { color: rgba(250,249,246,0.55); }

/* Langue et devise : deux pastilles, puis la mention en bas. */
.mobile-menu .mobile-tools { display: flex; gap: 0.6rem; margin-top: 1.5rem; }
.mobile-menu .tool-select {
  display: inline-block; color: var(--color-warm-white); background-color: transparent;
  border: 1px solid rgba(250,249,246,0.25); padding: 0.55rem 0.9rem;
}
.mobile-menu .tool-select option { color: var(--color-black); }
.mobile-menu .band-only-note { margin-top: auto; padding-top: 1.5rem; color: rgba(250,249,246,0.45); font-size: var(--text-xs); }
.mobile-menu .band-only-note::before { background: rgba(250,249,246,0.45); }

/* Entree des liens a l'ouverture : un seul geste, decale de 50 ms. */
@media (prefers-reduced-motion: no-preference) {
  .mobile-menu .menu-shop, .mobile-menu .menu-liens li, .mobile-menu .menu-aide {
    opacity: 0; transform: translateY(12px);
    transition: opacity 500ms var(--ease-luxury), transform 600ms var(--ease-luxury);
  }
  .mobile-menu.open .menu-shop, .mobile-menu.open .menu-liens li, .mobile-menu.open .menu-aide { opacity: 1; transform: none; }
  .mobile-menu.open .menu-shop { transition-delay: 120ms; }
  .mobile-menu.open .menu-liens li:nth-child(1) { transition-delay: 170ms; }
  .mobile-menu.open .menu-liens li:nth-child(2) { transition-delay: 220ms; }
  .mobile-menu.open .menu-liens li:nth-child(3) { transition-delay: 270ms; }
  .mobile-menu.open .menu-liens li:nth-child(4) { transition-delay: 320ms; }
  .mobile-menu.open .menu-aide { transition-delay: 370ms; }
}

/* --- Espaces resserres sur telephone (10.10.2026) -------------------------- */
@media (max-width: 700px) {
  /* « The house » : le lien About touchait presque la section WHOOP de 72 px. */
  .story--film { padding-bottom: 2.5rem; }
  /* About : la derniere legende et le pied de page. */
  #view > .about-duo:last-child { padding-bottom: 1.5rem; }
}

/* --- Newsletter : une sangle tissee pour finir la page ----------------------
   Le noir de la newsletter et celui du pied de page faisaient un trou de
   100 px. La section se resserre et se termine par une sangle sur toute la
   largeur, sa piece au W au centre : la separation est l'objet lui-meme,
   comme la sangle a ecrire de la Communaute. */
.newsletter { position: relative; padding-bottom: calc(clamp(2.5rem, 5vw, 3.75rem) + 18px); }
.newsletter .form-msg:empty { min-height: 0; margin: 0; }
.newsletter::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 18px;
  background:
    repeating-linear-gradient(90deg, rgba(255,255,255,0.05) 0 2px, transparent 2px 5px),
    repeating-linear-gradient(0deg, rgba(0,0,0,0.4) 0 2px, transparent 2px 5px),
    linear-gradient(180deg, #2c2b28 0%, #1a1917 60%, #232220 100%);
  box-shadow: 0 1px 0 rgba(255,255,255,0.06) inset, 0 -1px 0 rgba(0,0,0,0.5) inset;
}
.newsletter::before {
  content: "W"; position: absolute; left: 50%; bottom: -6px; z-index: 1; transform: translateX(-50%);
  width: 52px; height: 30px; border-radius: 8px; display: grid; place-items: center;
  background: linear-gradient(180deg, #3d3b36 0%, #0f0f0d 100%);
  box-shadow: 0 1px 0 rgba(255,255,255,0.14) inset, 0 6px 14px rgba(0,0,0,0.6);
  color: rgba(250,249,246,0.55); font-size: 0.8rem; font-weight: 600; letter-spacing: 0.04em;
}
.mobile-menu .mobile-link { justify-content: flex-start; }
/* Six liens en grand depuis le 10.10.2026 (FAQ et Contact remontes) : un
   cran plus petits pour que tout tienne sur un ecran de telephone. */
.mobile-menu .mobile-link { font-size: clamp(1.8rem, 8vw, 2.4rem); padding: 0.45rem 0; }
@media (prefers-reduced-motion: no-preference) {
  .mobile-menu.open .menu-liens li:nth-child(5) { transition-delay: 370ms; }
  .mobile-menu.open .menu-liens li:nth-child(6) { transition-delay: 420ms; }
  .mobile-menu.open .menu-aide { transition-delay: 470ms; }
}

/* Hero de l'accueil jusqu'au bas de l'ecran (10.10.2026). Il etait cale sur
   100svh, la hauteur avec les barres de Safari deployees ; sur iOS 26 la barre
   du bas flotte au-dessus de la page, et la section noire suivante depassait
   en bande sous le hero. 100lvh va jusqu'au bord : la video passe derriere la
   barre translucide. vh d'abord pour les navigateurs sans lvh. */
.hero-video { height: calc(100vh - var(--hv-haut, var(--header-h))); height: calc(100lvh - var(--hv-haut, var(--header-h))); }
