/* ========================================================================
   MyLithoBox — Refonte
   Mode "allumé / éteint" en métaphore du lithophane.
   ======================================================================== */

:root {
  /* ══ L'ÉCHELLE ══ Constantes, jamais redéfinies. Les sept premières sont
     relevées au pixel sur la carte de visite ; les cinq suivantes sont le
     versant clair, hérité du site en production (mylithobox.fr). */
  --noir:    #0d0d0d;   /* le fond de la carte : noir neutre */
  --nuit:    #241d16;   /* surface relevée */
  --brun:    #7c5d3c;   /* le brun du sol, au loin */
  --or-deep: #a57548;   /* l'or à mi-distance du cube */
  --or:      #f9bc6e;   /* la lumière au pied du cube */
  --creme:   #f0e2cd;
  --blanc:   #f8f7eb;   /* le blanc des faces allumées */

  /* Le versant NUIT. Le noir de la carte (#0d0d0d) est juste sur un carton
     imprimé de 8 cm ; sur un écran plein il devenait un trou. Ces valeurs
     gardent la chaleur de l'or en remontant la clarté : L* 3,6 → 12,4. */
  --brun-nuit:    #2a1e15;   /* le fond */
  --brun-carte:   #37281c;   /* ce qui se pose dessus */
  --brun-fort:    #3d2b1d;   /* les blocs à contraste inversé */
  --brun-creux:   #1a120d;   /* ce qui doit s'enfoncer */

  --parchemin:      #f5ede2;
  --parchemin-haut: #faf6ee;
  --parchemin-bas:  #e8dac4;
  --encre:          #241a11;
  --encre-douce:    #5d4630;

  /* ══ ALLUMÉ ══ L'état d'arrivée : il fait jour, la pièce est éclairée.
     Chaque rôle ci-dessous a son pendant dans le bloc [data-lights="off"] plus
     bas ; TOUT ce qui porte une couleur doit passer par l'un d'eux, sinon
     il reste figé quand on éteint. */
  --bg:        var(--parchemin);
  --bg-soft:   var(--parchemin-haut);
  --fg:        var(--encre);        /* 14,7:1 */
  --fg-soft:   var(--encre-douce);  /*  7,6:1 */
  --fg-label:  var(--brun);         /*  5,2:1 — tient même en 10 px */
  --hairline:  rgba(36, 26, 17, .14);

  /* L'accent doit rester chaleureux SANS descendre sous le seuil : l'or de
     la carte (#f9bc6e) tombe à 1,45:1 sur le parchemin. On le brûle donc
     jusqu'à 4,95:1, et il redevient l'or franc une fois la lumière éteinte. */
  --accent:      #8a5c31;
  --accent-on:   var(--parchemin-haut);
  --accent-deep: #6b4a2d;
  --accent-glow: var(--or);
  /* Sommet du dégradé des titres. Distinct de --accent-glow : celui-ci peint
     des lueurs derrière les choses, celui-là est de l'ENCRE et doit rester
     lisible sur le fond. */
  --glow-text: var(--or-deep);

  /* L'appel à l'action : sombre sur clair le jour, lumineux sur noir la nuit.
     Dans les deux cas c'est lui qui porte le plus fort contraste de la page. */
  --cta-bg: var(--encre);
  --cta-fg: var(--parchemin-haut);

  /* Surface à contraste inversé (section sombre, badge, modale). */
  --surface-fort:      var(--encre);
  --sur-surface-fort:  var(--parchemin-haut);
  --sur-surface-doux:  #c9b394;

  /* Le plateau sur lequel repose la box (visuel produit, viewer 3D). */
  --plateau-1: var(--parchemin-haut);
  --plateau-2: var(--parchemin);
  --plateau-3: var(--parchemin-bas);

  --ink: var(--encre);
  --wordmark-ink: linear-gradient(96deg,
    #3d2a17 0%, #6b4a2d 38%, #8a5c31 72%, #a57548 100%);

  /* La barre du haut est à contraste INVERSÉ : elle se pose sur la page au
     lieu de s'y fondre. D'où sa propre paire de rôles — le wordmark compris,
     car son dégradé doit s'inverser avec elle sous peine de disparaître. */
  --bar-bg: var(--encre);
  --bar-fg: var(--parchemin-haut);
  --bar-accent: var(--or);
  --bar-wordmark: linear-gradient(96deg,
    #f8f7eb 0%, #f0e2cd 34%, #f9bc6e 70%, #d99a4e 100%);

  /* Les CARTES posées sur le fond (étapes, emplacements photo, options).
     Mesuré : elles ne creusaient que ΔL* 2 avec la page — un liseré les
     tenait seul. Sur fond clair l'écart plafonne (le blanc est la limite),
     c'est donc la bordure et l'ombre qui portent le détachement ; sur fond
     sombre, la surface peut faire le travail elle-même. */
  --carte-bg:   #ffffff;
  --carte-bord: #e0d2bc;
  --carte-ombre: 0 2px 10px -4px rgba(36, 26, 17, .18);

  /* Le cube ÉTEINT. Sa valeur ne peut pas être fixe : elle doit rester plus
     sombre que le fond dans les deux thèmes, or le fond de nuit est passé du
     noir au brun — le cube s'y est confondu. */
  --cube-off: #2a2018;

  /* Niveau de lumière global 0..1 : pilote les halos et les lueurs. */
  --lit: 1;

  /* Typo */
  /* Les polices de la CARTE DE VISITE, relevées dans le PDF : DM Serif Text
     pour le nom, DM Sans pour le reste. La charte HTML proposait Bodoni Moda
     et Instrument Sans, mais l'objet imprimé fait foi — c'est lui que le
     client a en main. */
  --font-display: "DM Serif Text", "DM Serif Display", Georgia, serif;
  --font-body: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  /* Les libellés en capitales : mêmes lettres que le corps, tenues à
     distance par le letter-spacing. JetBrains Mono n'était ni dans la
     charte ni sur la carte. */
  --font-label: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-mono: var(--font-label);

  /* Métriques */
  --radius-sm: 8px;
  --radius: 16px;
  --radius-lg: 28px;
  --container: 1280px;
  --gutter: clamp(20px, 4vw, 56px);
}

/* La bascule doit se voir : la page fond d'un état à l'autre plutôt que de
   sauter. On l'annule pour qui demande moins d'animation. */
html, body {
  transition: background-color .55s ease, color .55s ease;
}
@media (prefers-reduced-motion: reduce) {
  html, body { transition: none; }
}

/* ══ ÉTEINT ══ On coupe la lumière : la pièce devient noire et l'objet reste
   la seule source. Mêmes rôles que :root, valeurs inversées.

   data-lights est posé sur <html> — le crochet existait déjà pour le panneau
   de réglages, le bouton du héros s'y branche plutôt que d'en ouvrir un
   second. Toute couleur qui ne passe pas par un de ces rôles reste figée à
   la bascule. */
:root[data-lights="off"] {
  --bg:        var(--brun-nuit);
  --bg-soft:   var(--brun-carte);
  --fg:        var(--creme);
  --fg-soft:   #d9c9b0;
  --fg-label:  var(--or);
  --hairline:  rgba(240, 226, 205, .16);

  --accent:      var(--or);
  --accent-on:   var(--nuit);
  --accent-deep: var(--or-deep);
  --accent-glow: #ffd9a3;
  --glow-text: #ffd9a3;

  --cta-bg: var(--or);
  --cta-fg: var(--nuit);

  --surface-fort:      var(--brun-fort);
  --sur-surface-fort:  var(--blanc);
  --sur-surface-doux:  #c0ae94;

  --plateau-1: #241a12;
  --plateau-2: #1f160f;
  --plateau-3: var(--brun-creux);

  --ink: var(--brun-creux);
  --wordmark-ink: linear-gradient(96deg,
    #f8f7eb 0%, #f0e2cd 34%, #f9bc6e 70%, #d99a4e 100%);

  /* La barre s'inverse elle aussi : claire sur la page noire. */
  --bar-bg: var(--creme);
  --bar-fg: var(--brun-creux);
  --cube-off: var(--brun-creux);
  --carte-bg:   #443422;   /* ΔL* 10,6 : la surface se détache seule */
  --carte-bord: color-mix(in oklab, var(--or) 22%, transparent);
  --carte-ombre: 0 2px 12px -6px rgba(0, 0, 0, .5);
  --bar-accent: var(--or-deep);
  --bar-wordmark: linear-gradient(96deg,
    #3d2a17 0%, #6b4a2d 38%, #8a5c31 72%, #a57548 100%);

  /* Les halos et reflets s'éteignent avec la pièce. */
  --lit: 0.15;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
  transition: background-color 900ms cubic-bezier(.4,0,.2,1), color 900ms cubic-bezier(.4,0,.2,1);
}

img { max-width: 100%; display: block; }

a { color: inherit; text-decoration: none; }

button {
  font: inherit;
  color: inherit;
  background: transparent;
  border: 0;
  cursor: pointer;
  padding: 0;
}

/* ===== Typographie ===== */
h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 400;
  letter-spacing: -0.02em;
  margin: 0;
  text-wrap: balance;
}
.display {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: clamp(48px, 8.2vw, 120px);
  line-height: 0.96;
  letter-spacing: -0.035em;
}
.h-eyebrow {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--fg-soft);
  font-weight: 500;
}
.italic-glow {
  font-style: italic;
  padding: 0 0.06em;
  background: linear-gradient(120deg,
    color-mix(in oklab, var(--accent) 60%, var(--fg) 40%) 0%,
    var(--glow-text) 50%,
    color-mix(in oklab, var(--accent) 60%, var(--fg) 40%) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
:root[data-lights="off"] .italic-glow {
  text-shadow: 0 0 28px color-mix(in oklab, var(--accent-glow) 60%, transparent);
}

/* ── Signature « MyLithoBox » ────────────────────────────────────────────
   Le nom de la marque reprend le lettrage du logo plutôt que le style de
   titre courant : Fraunces en graisse haute (le nom était rendu en 300,
   trop fin pour porter la marque) et le dégradé doré du logo, qui va du
   blond clair au brun profond.

   `font-optical-sizing: auto` fait travailler l'axe optique de Fraunces :
   à 22 px dans la barre de navigation les déliés restent lisibles, à 120 px
   dans le héros ils s'affinent et le contraste plein/délié s'ouvre, comme
   sur le logo. C'est pourquoi une seule classe suffit à toutes les tailles.

   Le dégradé est une variable : en mode « éteint » il doit rester clair,
   sinon la fin du mot disparaît dans le fond sombre. */
.wordmark {
  font-family: var(--font-display);
  /* DM Serif Text n'existe qu'en 400 : demander 700 ferait synthétiser un
     faux gras par le navigateur, épais et sale. Et `font-optical-sizing` ne
     s'applique qu'aux fontes variables — sans objet ici. */
  font-weight: 400;
  letter-spacing: -0.02em;
  background-image: var(--wordmark-ink);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;

  /* `background-clip: text` ne peint le dégradé QUE dans la boîte de
     l'élément. Avec l'interligne serrée de `.display` (0.96), le jambage du
     « y » tombait sous cette boîte : il était coupé net à l'horizontale.
     On agrandit donc la zone peinte, et on annule l'effet sur la mise en
     page par des marges négatives — sans effet sur un élément en ligne
     (fiche produit), elles ne comptent que là où le mot devient élément
     flex (en-tête, héros, pied de page). */
  padding: 0.1em 0 0.26em;
  margin: -0.1em 0 -0.26em;
}
:root[data-lights="off"] .wordmark {
  filter: drop-shadow(0 0 26px color-mix(in oklab, var(--accent-glow) 45%, transparent));
}

/* ===== Layout helpers ===== */
.container {
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 var(--gutter);
}
.section { padding: clamp(72px, 12vh, 140px) 0; position: relative; }
.section--tight { padding: clamp(48px, 8vh, 96px) 0; }

/* ===== Nav ===== */
.nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 50;
  padding: 18px var(--gutter);
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 24px;
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  background: color-mix(in oklab, var(--bar-bg) 90%, transparent);
  border-bottom: 1px solid color-mix(in oklab, var(--bar-fg) 16%, transparent);
  transition: background-color 600ms, border-color 600ms, color 600ms;

  /* Tout ce qui vit DANS la barre bascule avec elle : redéfinir les rôles ici
     évite d'avoir à traiter chaque enfant (liens, icônes, panier, burger) un
     par un — et n'en oublie aucun. */
  color: var(--bar-fg);
  --fg: var(--bar-fg);
  --fg-soft: color-mix(in oklab, var(--bar-fg) 78%, transparent);
  --fg-label: var(--bar-accent);
  --accent: var(--bar-accent);
  --accent-glow: var(--bar-accent);
  --hairline: color-mix(in oklab, var(--bar-fg) 22%, transparent);
  --wordmark-ink: var(--bar-wordmark);
}
.nav__brand {
  /* 16 px et non 10 : au pic de son grésillement le logo grossit d'un tiers
     et venait frôler le nom à un demi-pixel près. L'écart au repos ne se
     remarque pas, le frôlement si. */
  display: flex; align-items: center; gap: 16px;
  font-family: var(--font-display); font-size: 22px; letter-spacing: -0.02em;
}
/* Le logo est un bouton : il en a la cible et les états, pas l'apparence. */
.nav__lamp {
  appearance: none; border: 0; background: none; padding: 4px; margin: -4px;
  cursor: pointer; line-height: 0; border-radius: 10px;
  /* La perspective est portée par le bouton pour que la rotation du logo se
     lise comme un volume qui pivote, et non comme un aplati qui s'écrase. */
  perspective: 420px;
}
.nav__lamp:focus-visible {
  outline: 2px solid var(--bar-accent);
  outline-offset: 3px;
}
.nav__brand img {
  width: 32px; height: 32px;
  filter: drop-shadow(0 4px 12px color-mix(in oklab, var(--accent) 40%, transparent));
  transform-style: preserve-3d;
  transition: filter 500ms ease;
}
/* Le grésillement, en DEUX salves séparées d'un souffle : « vrrr … vrrr ».
   Le logo grossit d'un tiers et le reste pendant les deux salves, tremble de
   6.5° d'un côté à l'autre, et passe au noir TROIS fois — deux dans la
   première salve, une dans la seconde.

   Une oscillation toutes les 0.85 % du cycle, soit ~94 ms : c'est la cadence qui
   sépare un tremblement d'un balancement. L'amplitude retombe en fin de
   chaque salve, comme un moteur qui s'arrête.

   Cycle de 11 s : l'accroc dure ~2.0 s, le reste est immobile. */
@keyframes lampe-gresille {
  0%, 78.0% { transform: scale(1) translate(0, 0) rotate(0deg);
              filter: brightness(1) drop-shadow(0 4px 12px color-mix(in oklab, var(--accent) 40%, transparent)); }
  78.42% { transform: scale(1.054) translate(1.6px, -0.9px) rotate(6.5deg);
              filter: brightness(1) drop-shadow(0 6px 24px color-mix(in oklab, var(--accent-glow) 80%, transparent)); }
  79.27% { transform: scale(1.163) translate(-1.6px, 0.9px) rotate(-6.5deg);
              filter: brightness(1) drop-shadow(0 6px 24px color-mix(in oklab, var(--accent-glow) 80%, transparent)); }
  80.12% { transform: scale(1.272) translate(1.6px, -0.9px) rotate(6.5deg);
              filter: brightness(0) drop-shadow(0 0 0 transparent); }
  80.97% { transform: scale(1.32) translate(-1.6px, 0.9px) rotate(-6.5deg);
              filter: brightness(1) drop-shadow(0 6px 24px color-mix(in oklab, var(--accent-glow) 80%, transparent)); }
  81.82% { transform: scale(1.32) translate(1.6px, -0.9px) rotate(6.5deg);
              filter: brightness(0) drop-shadow(0 0 0 transparent); }
  82.67% { transform: scale(1.32) translate(-0.72px, 0.41px) rotate(-2.9deg);
              filter: brightness(1) drop-shadow(0 6px 24px color-mix(in oklab, var(--accent-glow) 80%, transparent)); }
  83.52% { transform: scale(1.32) translate(0.72px, -0.41px) rotate(2.9deg);
              filter: brightness(1) drop-shadow(0 6px 24px color-mix(in oklab, var(--accent-glow) 80%, transparent)); }
  84.0%, 86.6% { transform: scale(1.32) translate(0, 0) rotate(0deg);
              filter: brightness(1) drop-shadow(0 6px 24px color-mix(in oklab, var(--accent-glow) 80%, transparent)); }
  87.02% { transform: scale(1.32) translate(-1.6px, -0.9px) rotate(-6.5deg);
              filter: brightness(1) drop-shadow(0 6px 24px color-mix(in oklab, var(--accent-glow) 80%, transparent)); }
  87.87% { transform: scale(1.32) translate(1.6px, 0.9px) rotate(6.5deg);
              filter: brightness(1) drop-shadow(0 6px 24px color-mix(in oklab, var(--accent-glow) 80%, transparent)); }
  88.72% { transform: scale(1.32) translate(-1.6px, -0.9px) rotate(-6.5deg);
              filter: brightness(0) drop-shadow(0 0 0 transparent); }
  89.57% { transform: scale(1.32) translate(1.6px, 0.9px) rotate(6.5deg);
              filter: brightness(1) drop-shadow(0 6px 24px color-mix(in oklab, var(--accent-glow) 80%, transparent)); }
  90.42% { transform: scale(1.32) translate(-1.6px, -0.9px) rotate(-6.5deg);
              filter: brightness(1) drop-shadow(0 6px 24px color-mix(in oklab, var(--accent-glow) 80%, transparent)); }
  91.27% { transform: scale(1.32) translate(0.72px, 0.41px) rotate(2.9deg);
              filter: brightness(1) drop-shadow(0 6px 24px color-mix(in oklab, var(--accent-glow) 80%, transparent)); }
  92.0% { transform: scale(1.32) translate(0, 0) rotate(0deg);
              filter: brightness(1) drop-shadow(0 6px 24px color-mix(in oklab, var(--accent-glow) 80%, transparent)); }
  96.5%, 100% { transform: scale(1) translate(0, 0) rotate(0deg);
              filter: brightness(1) drop-shadow(0 4px 12px color-mix(in oklab, var(--accent) 40%, transparent)); }
}
.nav__lamp.is-lit img {
  transform-origin: 50% 50%;
  animation: lampe-gresille 11s linear infinite;
}

/* Éteint, le logo garde EXACTEMENT le même grésillement — mêmes temps, même
   agrandissement, mêmes deux salves — mais ses couleurs sont inversées : il
   reste sombre au repos, et ce sont les trois accrocs qui le rallument
   brièvement. Un contact qui cherche à revenir, au lieu d'un qui lâche. */
@keyframes lampe-gresille-nuit {
  0%, 78.0% { transform: scale(1) translate(0, 0) rotate(0deg);
              filter: brightness(.07) sepia(.5) saturate(2.5) drop-shadow(0 0 0 transparent); }
  78.42% { transform: scale(1.054) translate(1.6px, -0.9px) rotate(6.5deg);
              filter: brightness(.07) sepia(.5) saturate(2.5) drop-shadow(0 0 0 transparent); }
  79.27% { transform: scale(1.163) translate(-1.6px, 0.9px) rotate(-6.5deg);
              filter: brightness(.07) sepia(.5) saturate(2.5) drop-shadow(0 0 0 transparent); }
  80.12% { transform: scale(1.272) translate(1.6px, -0.9px) rotate(6.5deg);
              filter: brightness(1) sepia(0) saturate(1) drop-shadow(0 4px 12px color-mix(in oklab, var(--accent) 35%, transparent)); }
  80.97% { transform: scale(1.32) translate(-1.6px, 0.9px) rotate(-6.5deg);
              filter: brightness(.07) sepia(.5) saturate(2.5) drop-shadow(0 0 0 transparent); }
  81.82% { transform: scale(1.32) translate(1.6px, -0.9px) rotate(6.5deg);
              filter: brightness(1) sepia(0) saturate(1) drop-shadow(0 4px 12px color-mix(in oklab, var(--accent) 35%, transparent)); }
  82.67% { transform: scale(1.32) translate(-0.72px, 0.41px) rotate(-2.9deg);
              filter: brightness(.07) sepia(.5) saturate(2.5) drop-shadow(0 0 0 transparent); }
  83.52% { transform: scale(1.32) translate(0.72px, -0.41px) rotate(2.9deg);
              filter: brightness(.07) sepia(.5) saturate(2.5) drop-shadow(0 0 0 transparent); }
  84.0%, 86.6% { transform: scale(1.32) translate(0, 0) rotate(0deg);
              filter: brightness(.07) sepia(.5) saturate(2.5) drop-shadow(0 0 0 transparent); }
  87.02% { transform: scale(1.32) translate(-1.6px, -0.9px) rotate(-6.5deg);
              filter: brightness(.07) sepia(.5) saturate(2.5) drop-shadow(0 0 0 transparent); }
  87.87% { transform: scale(1.32) translate(1.6px, 0.9px) rotate(6.5deg);
              filter: brightness(.07) sepia(.5) saturate(2.5) drop-shadow(0 0 0 transparent); }
  88.72% { transform: scale(1.32) translate(-1.6px, -0.9px) rotate(-6.5deg);
              filter: brightness(1) sepia(0) saturate(1) drop-shadow(0 4px 12px color-mix(in oklab, var(--accent) 35%, transparent)); }
  89.57% { transform: scale(1.32) translate(1.6px, 0.9px) rotate(6.5deg);
              filter: brightness(.07) sepia(.5) saturate(2.5) drop-shadow(0 0 0 transparent); }
  90.42% { transform: scale(1.32) translate(-1.6px, -0.9px) rotate(-6.5deg);
              filter: brightness(.07) sepia(.5) saturate(2.5) drop-shadow(0 0 0 transparent); }
  91.27% { transform: scale(1.32) translate(0.72px, 0.41px) rotate(2.9deg);
              filter: brightness(.07) sepia(.5) saturate(2.5) drop-shadow(0 0 0 transparent); }
  92.0% { transform: scale(1.32) translate(0, 0) rotate(0deg);
              filter: brightness(.07) sepia(.5) saturate(2.5) drop-shadow(0 0 0 transparent); }
  96.5%, 100% { transform: scale(1) translate(0, 0) rotate(0deg);
              filter: brightness(.07) sepia(.5) saturate(2.5) drop-shadow(0 0 0 transparent); }
}
.nav__lamp:not(.is-lit) img {
  transform-origin: 50% 50%;
  animation: lampe-gresille-nuit 11s linear infinite;
}
/* Au survol il s'éclaircit à peine — assez pour dire « cliquable », pas assez
   pour laisser croire que la lumière est revenue. */
.nav__lamp:not(.is-lit):hover img { filter: brightness(.16) sepia(.4) saturate(2); }

/* Ceinture de sécurité : les images-clés portent désormais toutes la même
   liste de fonctions de filtre, si bien qu'aucun moteur n'a plus à « sauter »
   d'un filtre à l'autre — c'est ce saut qui pouvait laisser le logo figé sur
   une image noire. Cette règle garantit l'état de repos même si l'animation
   ne démarre pas du tout. */
.nav__lamp.is-lit img {
  filter: brightness(1) drop-shadow(0 4px 12px color-mix(in oklab, var(--accent) 40%, transparent));
}
.nav__lamp:not(.is-lit) img {
  filter: brightness(.07) sepia(.5) saturate(2.5) drop-shadow(0 0 0 transparent);
}

@media (prefers-reduced-motion: reduce) {
  .nav__lamp img { animation: none; transform: none; }
}
.nav__links {
  display: flex; gap: 36px; justify-content: center;
  font-size: 14px; letter-spacing: 0.04em;
}
.nav__links a { position: relative; padding: 6px 2px; transition: color .2s; }
.nav__links a::after {
  content: ""; position: absolute; left: 0; right: 100%; bottom: 0;
  height: 1px; background: var(--accent);
  transition: right .35s cubic-bezier(.4,0,.2,1);
}
.nav__links a:hover { color: var(--accent); }
.nav__links a:hover::after { right: 0; }
.nav__cta {
  display: flex; align-items: center; gap: 12px; justify-content: flex-end;
}
.icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; border-radius: 99px;
  border: 1px solid var(--hairline);
  transition: all .25s;
  position: relative;
}
.icon-btn:hover { border-color: var(--accent); color: var(--accent); }
.icon-btn .badge {
  position: absolute; top: -4px; right: -4px;
  min-width: 18px; height: 18px; padding: 0 5px;
  background: var(--accent); color: var(--accent-on);
  border-radius: 99px; font-size: 10px; font-weight: 600;
  display: inline-flex; align-items: center; justify-content: center;
}

/* ===== Boutons ===== */
.btn {
  display: inline-flex; align-items: center; gap: 12px;
  padding: 14px 26px;
  border-radius: 99px;
  font-size: 14px; letter-spacing: 0.03em; font-weight: 500;
  transition: transform .3s cubic-bezier(.4,0,.2,1), box-shadow .3s, background .3s, color .3s;
  position: relative;
  overflow: hidden;
  white-space: nowrap;
}
.btn--primary {
  /* Le fond était var(--ink) — la couleur EXACTE du fond de page. Le bouton
     ne se détachait que par son halo, ce qui le rendait presque invisible
     dans le héros. Sur la carte, ce qui attire l'œil est la lumière du cube :
     l'appel à l'action devient donc cette lumière. */
  background: var(--accent);
  color: var(--accent-on);
  box-shadow:
    0 1px 0 rgba(255,255,255,0.06) inset,
    0 8px 24px -8px color-mix(in oklab, var(--accent) calc(var(--lit) * 60%), transparent),
    0 0 0 0 var(--accent);
}
.btn--primary:hover {
  transform: translateY(-2px);
  /* La teinte fonce au survol : l'encre suit. */
  background: var(--accent-deep);
  color: var(--cta-fg);
  box-shadow:
    0 1px 0 rgba(255,255,255,0.06) inset,
    0 14px 30px -8px color-mix(in oklab, var(--accent) 70%, transparent),
    0 0 32px -4px color-mix(in oklab, var(--accent-glow) 80%, transparent);
}
/* État désactivé. L'ancien traitement (opacity .55 en style inline) délavait
   le fond ET le texte ensemble : sur un bouton devenu clair, l'encre tombait
   à 3,2:1. On atténue donc le fond seul, et l'encre repasse au clair. */
.btn:disabled, .btn[disabled] {
  background: color-mix(in oklab, var(--cta-bg) 76%, var(--bg));
  color: var(--cta-fg);
  box-shadow: none;
  cursor: not-allowed;
}
.btn:disabled:hover, .btn[disabled]:hover {
  transform: none;
  background: color-mix(in oklab, var(--cta-bg) 76%, var(--bg));
  color: var(--cta-fg);
}

.btn--primary .arrow { transition: transform .3s; }
.btn--primary:hover .arrow { transform: translateX(4px); }

.btn--ghost {
  border: 1px solid var(--hairline);
  color: var(--fg);
}
.btn--ghost:hover { border-color: var(--accent); color: var(--accent); }

.btn--accent {
  /* L'accent est désormais une lumière, pas un brun : du blanc dessus
     tomberait à 1,7:1. Le texte passe en brun profond — 11,5:1. */
  background: var(--cta-bg);
  color: var(--cta-fg);
}
/* Au survol la teinte fonce, donc le texte doit repasser au clair. */
.btn--accent:hover {
  background: var(--accent-deep);
  color: var(--cta-fg);
  transform: translateY(-2px);
}

/* ===== Hero ===== */
.hero {
  position: relative;
  min-height: 100vh;
  padding: 140px var(--gutter) 80px;
  display: grid;
  /* Une seule colonne depuis que la scène a été retirée : garder deux pistes
     laisserait la moitié droite vide. Le texte est borné pour ne pas s'étirer
     sur toute la largeur — au-delà de ~62 caractères la lecture décroche. */
  grid-template-columns: minmax(0, 68ch);
  align-items: center;
  justify-content: start;
  overflow: hidden;
}
@media (max-width: 960px) {
  .hero { grid-template-columns: 1fr; padding-top: 120px; gap: 48px; }
}

.hero__bg {
  position: absolute; inset: 0;
  pointer-events: none;
  background:
    radial-gradient(ellipse 60% 50% at 75% 50%,
      color-mix(in oklab, var(--accent-glow) calc(var(--lit) * 35%), transparent) 0%,
      transparent 60%),
    radial-gradient(ellipse 40% 30% at 25% 80%,
      color-mix(in oklab, var(--accent) calc(var(--lit) * 18%), transparent) 0%,
      transparent 70%);
  transition: background 900ms;
}
.hero__noise {
  position: absolute; inset: 0;
  pointer-events: none;
  opacity: 0.035;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='240' height='240'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
}

.hero__copy { position: relative; z-index: 2; }
/* La ligne d'accroche est passée SOUS « Illuminez vos souvenirs » : elle
   ferme le bloc de titre au lieu de l'annoncer, d'où le retard dans la
   cascade d'apparition (marque .15s → sous-titre .4s → accroche .55s). */
.hero__eyebrow {
  display: inline-flex; align-items: center; gap: 12px;
  margin: 0 0 30px;
  opacity: 0;
  animation: heroIn 1s .55s cubic-bezier(.2,.7,.2,1) forwards;
}
.hero__eyebrow .dot {
  width: 8px; height: 8px; border-radius: 99px;
  background: var(--accent);
  box-shadow: 0 0 0 0 color-mix(in oklab, var(--accent) 60%, transparent);
  animation: pulse 2.4s ease-out infinite;
}
@keyframes pulse {
  0%   { box-shadow: 0 0 0 0 color-mix(in oklab, var(--accent) 60%, transparent); }
  70%  { box-shadow: 0 0 0 14px color-mix(in oklab, var(--accent) 0%, transparent); }
  100% { box-shadow: 0 0 0 0 color-mix(in oklab, var(--accent) 0%, transparent); }
}

/* Marque, sous-titre et accroche forment un seul bloc de titre : les écarts
   restent serrés, et c'est l'accroche qui pose la respiration avant le
   paragraphe. */
.hero h1 { margin-bottom: 10px; }
.hero h1 .word {
  display: inline-block;
  opacity: 0;
  transform: translateY(28px);
  animation: heroIn .9s cubic-bezier(.2,.7,.2,1) forwards;
}
@keyframes heroIn { to { opacity: 1; transform: none; } }

.hero__lead {
  max-width: 52ch;
  font-size: clamp(16px, 1.4vw, 19px);
  color: var(--fg-soft);
  margin-bottom: 40px;
  opacity: 0;
  animation: heroIn 1s .7s cubic-bezier(.2,.7,.2,1) forwards;
}
.hero__ctas {
  display: flex; gap: 16px; flex-wrap: wrap;
  opacity: 0;
  animation: heroIn 1s .85s cubic-bezier(.2,.7,.2,1) forwards;
}

/* Hero stage — la scène du cube */
@keyframes float {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-12px); }
}

/* Tags flottants autour du cube */
@keyframes tagIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

.hero__stats {
  position: absolute; left: var(--gutter); bottom: 36px; z-index: 2;
  display: flex; gap: 40px;
  opacity: 0;
  animation: heroIn 1s 1.1s cubic-bezier(.2,.7,.2,1) forwards;
}
.hero__stats .stat .num {
  font-family: var(--font-display); font-size: 36px; line-height: 1;
  letter-spacing: -0.03em;
}
.hero__stats .stat .lbl {
  font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--fg-label);
  margin-top: 6px;
}
@media (max-width: 760px) {
  .hero__stats { position: static; margin-top: 32px; }
}

/* ===== Reveal au scroll ===== */
.reveal { opacity: 0; transform: translateY(28px); transition: opacity .9s cubic-bezier(.2,.7,.2,1), transform .9s cubic-bezier(.2,.7,.2,1); }
.reveal.is-in { opacity: 1; transform: none; }
.reveal--right { transform: translateX(32px); }
.reveal--right.is-in { transform: none; }

/* ===== Concept section : lithophane éteint→allumé ===== */
.concept {
  display: grid;
  grid-template-columns: 1.05fr 1fr;
  gap: clamp(40px, 6vw, 96px);
  align-items: center;
}
@media (max-width: 900px) { .concept { grid-template-columns: 1fr; } }

.concept__copy h2 {
  font-size: clamp(36px, 5vw, 72px);
  line-height: 1.02;
  margin-bottom: 24px;
}
.concept__copy p {
  color: var(--fg-soft);
  font-size: 17px;
  max-width: 48ch;
}

.lithoCard {
  position: relative;
  aspect-ratio: 5 / 4;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: #0c0805;
  cursor: pointer;
  user-select: none;
  box-shadow:
    0 30px 80px -30px rgba(0,0,0,.5),
    0 1px 0 rgba(255,255,255,.04) inset;
}
.lithoCard__img {
  position: absolute; inset: 0;
  background-size: cover; background-position: center;
  transition: filter 1.2s cubic-bezier(.4,0,.2,1), opacity 1.2s;
}
.lithoCard__off { opacity: 1; }
.lithoCard__on  { opacity: 0; }
.lithoCard.is-on .lithoCard__off { opacity: 0; }
.lithoCard.is-on .lithoCard__on  { opacity: 1; }
.lithoCard.is-on { box-shadow:
  0 30px 80px -30px rgba(0,0,0,.5),
  0 0 100px -10px color-mix(in oklab, var(--accent-glow) 60%, transparent),
  0 1px 0 rgba(255,255,255,.04) inset;
}
.lithoCard__toggle {
  position: absolute; right: 18px; bottom: 18px;
  display: inline-flex; align-items: center; gap: 10px;
  padding: 10px 16px; border-radius: 99px;
  background: rgba(255,255,255,.92); color: var(--encre);
  font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.16em; text-transform: uppercase;
  border: 0;
  z-index: 2;
}
.lithoCard__toggle .led {
  width: 8px; height: 8px; border-radius: 99px; background: #999;
  transition: background .4s, box-shadow .4s;
}
.lithoCard.is-on .lithoCard__toggle .led {
  background: var(--accent-glow);
  box-shadow: 0 0 12px var(--accent-glow);
}
.lithoCard__hint {
  position: absolute; left: 18px; bottom: 18px;
  font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.2em; text-transform: uppercase;
  color: rgba(255,255,255,.55);
  z-index: 2;
}

/* ===== Produit configurateur ===== */
.product {
  display: grid;
  grid-template-columns: 1.2fr 1fr;
  gap: clamp(40px, 6vw, 80px);
  align-items: stretch;
}
@media (max-width: 900px) { .product { grid-template-columns: 1fr; } }

.product__visual {
  background: linear-gradient(165deg, var(--plateau-1) 0%, var(--plateau-2) 60%, var(--plateau-3) 100%);
  border-radius: var(--radius-lg);
  position: relative;
  aspect-ratio: 1 / 1;
  overflow: hidden;
  display: grid; place-items: center;
  border: 1px solid var(--hairline);
  /* Empêche l'item de grille de déborder sa piste (sinon aspect-ratio le fait grossir) */
  min-width: 0;
  width: 100%;
  align-self: start; /* sinon stretch vertical → l'aspect-ratio est cassé */
  position: sticky;
  top: 24px;
}
.product__form { min-width: 0; }
.product__visual::before {
  content: ""; position: absolute; inset: 0;
  background: radial-gradient(circle at 50% 40%,
    color-mix(in oklab, var(--accent-glow) calc(var(--lit) * 28%), transparent) 0%,
    transparent 60%);
}
.product__visual img {
  width: 86%; aspect-ratio: 1/1; object-fit: contain;
  position: relative; z-index: 1;
  animation: float 7s ease-in-out infinite;
  filter: drop-shadow(0 24px 36px rgba(43, 24, 16, 0.18));
}
.product__visual .thumbs {
  position: absolute; left: 20px; bottom: 20px;
  display: flex; gap: 10px; z-index: 2;
}
.product__visual .thumb {
  width: 56px; height: 56px; border-radius: 10px;
  background: var(--bg-soft) center / contain no-repeat;
  border: 1px solid var(--hairline);
  cursor: pointer;
  transition: border-color .2s, transform .2s, box-shadow .2s;
}
.product__visual .thumb.is-active { border-color: var(--accent); box-shadow: 0 0 0 2px color-mix(in oklab, var(--accent) 30%, transparent); }
.product__visual .thumb:hover { transform: translateY(-2px); }
.product__visual .badge-price {
  position: absolute; right: 20px; top: 20px;
  background: var(--surface-fort); color: var(--sur-surface-fort);
  padding: 10px 14px; border-radius: 99px;
  font-family: var(--font-display); font-size: 16px;
  letter-spacing: -0.01em;
  z-index: 2;
}
:root[data-lights="off"] .product__visual {
  background: linear-gradient(165deg, var(--plateau-1) 0%, var(--plateau-3) 100%);
  border-color: rgba(255, 200, 140, 0.08);
}
:root[data-lights="off"] .product__visual .thumb { background-color: var(--bg-soft); }

.product__form {
  padding: 8px 0;
  display: flex; flex-direction: column; gap: 22px;
}
.product__title { font-size: clamp(32px, 4vw, 52px); line-height: 1; }
.product__sub {
  font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--fg-label);
}
.product__desc { color: var(--fg-soft); max-width: 48ch; }

.field { display: flex; flex-direction: column; gap: 10px; }
.field__lbl {
  font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--fg-label);
  display: flex; justify-content: space-between;
}
.optionGrid {
  display: grid; gap: 8px;
  grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
}
.opt {
  padding: 12px 14px;
  border-radius: 12px;
  border: 1px solid var(--carte-bord);
  background: var(--carte-bg);
  text-align: center;
  font-size: 13px;
  display: flex; flex-direction: column; gap: 2px;
  transition: all .2s;
  cursor: pointer;
}
.opt:hover { border-color: var(--accent); }
/* Sur l'ancien thème crème, l'option retenue s'assombrissait. Sur fond
   obsidienne, `--ink` est devenu la couleur du fond : le bouton actif
   disparaissait purement et simplement. Le principe de la charte s'applique
   ici littéralement — ce qui est choisi est ce qui est ÉCLAIRÉ. */
.opt.is-active {
  border-color: var(--fg);
  background: var(--fg);
  color: var(--bg);
  box-shadow: 0 0 24px -6px rgba(255, 214, 150, 0.45);
}
:root[data-lights="off"] .opt.is-active {
  background: var(--accent); border-color: var(--accent); color: var(--accent-on);
  box-shadow: none;
}
.opt .opt__sub { font-size: 10px; color: var(--fg-label); letter-spacing: 0.1em; text-transform: uppercase; }
.opt.is-active .opt__sub { color: inherit; }

.product__buy {
  display: flex; gap: 12px; align-items: center; margin-top: 12px;
}
.qty {
  display: inline-flex; align-items: center; gap: 4px;
  border: 1px solid var(--hairline); border-radius: 99px; padding: 4px;
}
.qty button {
  width: 32px; height: 32px; border-radius: 99px;
  display: inline-flex; align-items: center; justify-content: center;
  transition: background .2s;
}
.qty button:hover { background: var(--hairline); }
.qty input {
  width: 28px; text-align: center; background: transparent; border: 0; color: inherit;
  font-family: var(--font-mono); font-size: 14px;
}

/* ===== Steps ===== */
/* ============================================================
   LE PARCOURS — trois étapes reliées par une route pointillée

   Ni cartes ni numéros : une icône par étape, posée sur la route. Le rang
   n'a pas besoin d'être écrit, la route le dit — et une pastille numérotée
   dans une case aurait redit trois fois ce que le trajet montre déjà.
   ============================================================ */
.parcours {
  --icone: clamp(54px, 5vw, 72px);
  /* Hauteur de l'arc, en px : le viewBox fait 130 unités de haut pour cette
     même hauteur, si bien qu'une unité vaut un pixel et que les remontées
     calculées se reportent telles quelles. */
  --arc: 130px;
  /* Décalage vertical du SVG pour que l'ordonnée 110 du viewBox — celle des
     deux étapes basses — tombe pile sur le centre de leur icône. Sans lui la
     courbe flotte au-dessus des icônes au lieu de les traverser. */
  --arc-haut: calc(var(--arc) + var(--icone) / 2 - 110px);
  position: relative;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  align-items: start;
  margin-top: 56px;
  padding-top: var(--arc);
}

/* ---- la courbe ------------------------------------------------------ */
.parcours__arc {
  position: absolute;
  left: 0; right: 0;
  top: var(--arc-haut);
  /* Hauteur EXACTEMENT égale au viewBox : une unité vaut un pixel, donc les
     ordonnées calculées sur la Bézier se reportent sans conversion. */
  height: var(--arc);
  width: 100%;
  overflow: visible;
  pointer-events: none;
}
.parcours__arc-trace {
  stroke: var(--accent);
  stroke-width: 2;
  opacity: .55;
  /* Tirets et épaisseur restent constants malgré l'étirement du viewBox,
     et le décalage animé fait avancer la route. */
  stroke-dasharray: 7 9;
  animation: arc-defile 1.1s linear infinite;
}
@keyframes arc-defile { to { stroke-dashoffset: -16; } }

/* ---- les étapes, posées sur la courbe -------------------------------- */
.parcours__etape {
  text-align: center;
  padding: 0 clamp(2px, 0.6vw, 10px);
  position: relative;
  z-index: 1;
}
/* Remontées lues sur la Bézier aux t réguliers : 0 · 33,75 · 45 · 33,75 · 0.
   Les extrémités restent au niveau bas, le sommet est au centre. */
.parcours__etape--composition,
.parcours__etape--livraison  { margin-top: 0; }
.parcours__etape--commande,
.parcours__etape--packaging  { margin-top: -34px; }
.parcours__etape--conception { margin-top: -45px; }

.parcours__icone {
  width: var(--icone);
  height: var(--icone);
  display: grid;
  place-items: center;
  margin: 0 auto 16px;
  color: var(--accent);
  /* Pas de pastille : l'icône se pose à même la page. Le fond reprend la
     couleur EXACTE de celle-ci plutôt que `transparent`, ce qui revient au
     même à l'œil mais interrompt la courbe juste derrière. */
  border-radius: 50%;
  background: var(--bg);
}
.parcours__icone svg { width: 38px; height: 38px; display: block; }
.parcours__etape h3 {
  font-size: clamp(16px, 1.25vw, 20px);
  line-height: 1.15;
  margin: 0;
  text-wrap: balance;
}
/* Les ICÔNES suivent la courbe, les TITRES non : chacun redescend de la
   remontée de son étape, ce qui les remet tous sur une même ligne. Sans
   cela, cinq titres en escalier — l'arc doit se lire dans le trajet, pas
   dans la typographie.

   Le 16px vient de la marge BASSE de l'icône : les deux marges se fondent
   (margin collapsing) et seule la plus grande s'applique. Sans l'ajouter, une
   remontée de 34 px ne décalait le titre que de 18. */
.parcours__etape--commande h3,
.parcours__etape--packaging h3  { margin-top: calc(16px + 34px); }
.parcours__etape--conception h3 { margin-top: calc(16px + 45px); }


/* ---- le camion, sur le dernier quart de la courbe -------------------- */
.parcours__camion {
  position: absolute;
  top: 0; left: 0;
  /* SOUS les icônes, comme la route qu'il emprunte. Au-dessus (z-index: 2), il
     arrivait en fin de course pile sur l'icône Livraison et s'y superposait :
     on voyait deux camions, l'un incliné et fondu. */
  z-index: 0;
  color: var(--accent);
  line-height: 0;
  /* Les points viennent de la Bézier entre t=0,75 et t=1 : x en % de la
     largeur, y en pixels du viewBox, pente en degrés. Interpoler entre cinq
     positions suffit à épouser une courbe aussi douce. */
  animation: camion-arc 3.6s linear infinite;
}
.parcours__camion svg { width: 26px; height: 26px; display: block; }
@keyframes camion-arc {
  0%   { left: 70%;   top: calc(var(--arc-haut) + 76px);
         transform: translate(-50%, -50%) rotate(6.4deg); opacity: 0; }
  14%  { opacity: 1; }
  28%  { left: 75.6%; top: calc(var(--arc-haut) + 83px);
         transform: translate(-50%, -50%) rotate(8.2deg); }
  56%  { left: 81.2%; top: calc(var(--arc-haut) + 92px);
         transform: translate(-50%, -50%) rotate(10deg); }
  84%  { left: 86.8%; top: calc(var(--arc-haut) + 103px);
         transform: translate(-50%, -50%) rotate(11.7deg); opacity: 1; }
  100% { left: 90%;   top: calc(var(--arc-haut) + 110px);
         transform: translate(-50%, -50%) rotate(12.7deg); opacity: 0; }
}

/* ---- une animation par étape, qui dit ce que l'étape fait -------------
   Chaque icône reste immobile la moitié du cycle puis joue son geste : cinq
   animations qui tourneraient en permanence rendraient la section fatigante.
   Les transformations portent sur les SOUS-ÉLÉMENTS (une tête, un rabat, une
   roue), pas sur l'icône entière — c'est ce qui fait la différence entre un
   pictogramme qui tressaute et un objet qui fonctionne.
   ------------------------------------------------------------------------ */
.parcours__icone svg * { transform-box: fill-box; transform-origin: 50% 50%; }

/* Composition : la boîte pivote, et sa face photo s'allume au passage. */
.parcours__etape--composition .parcours__icone svg {
  animation: boite-tourne 6s cubic-bezier(.45, 0, .3, 1) infinite;
  transform-origin: 50% 55%;
}
@keyframes boite-tourne {
  0%, 52%, 100% { transform: perspective(340px) rotateY(0deg); }
  68%           { transform: perspective(340px) rotateY(-30deg); }
  84%           { transform: perspective(340px) rotateY(14deg); }
}
.parcours__etape--composition .box__panneau {
  animation: panneau-sallume 6s ease-in-out infinite;
}
@keyframes panneau-sallume {
  0%, 58%, 100% { fill: transparent; opacity: 1; }
  70%, 78%      { fill: currentColor; opacity: .28; }
}

/* Commande : l'article tombe dans le panier, qui encaisse. */
.parcours__etape--commande .cart__article {
  animation: article-tombe 6s cubic-bezier(.5, 0, .75, 0) infinite;
}
@keyframes article-tombe {
  0%, 46%   { transform: translateY(-6px); opacity: 0; }
  54%       { opacity: 1; }
  64%       { transform: translateY(9px); opacity: 1; }
  70%, 100% { transform: translateY(9px); opacity: 0; }
}
.parcours__etape--commande .parcours__icone svg {
  animation: panier-encaisse 6s cubic-bezier(.3, 1.5, .5, 1) infinite;
}
@keyframes panier-encaisse {
  0%, 62%, 100% { transform: translateY(0) scaleY(1); }
  70%           { transform: translateY(1px) scaleY(.94); }
  80%           { transform: translateY(0) scaleY(1.02); }
}

/* Conception : la tête balaie le portique, la pièce monte couche par couche. */
.parcours__etape--conception .impr__tete {
  animation: tete-balaie 3s ease-in-out infinite;
}
@keyframes tete-balaie {
  0%, 100% { transform: translateX(-5.5px); }
  50%      { transform: translateX(5.5px); }
}
.parcours__etape--conception .impr__piece {
  transform-origin: 50% 100%;
  animation: piece-monte 6s ease-in-out infinite;
}
@keyframes piece-monte {
  0%, 6%    { transform: scaleY(.12); }
  48%, 64%  { transform: scaleY(1); }
  94%, 100% { transform: scaleY(.12); }
}

/* Packaging : les rabats se referment, PUIS le ruban se tire. */
.parcours__etape--packaging .colis__rabat--g {
  transform-origin: 100% 100%;
  animation: rabat-ferme-g 6s cubic-bezier(.4, 0, .2, 1) infinite;
}
.parcours__etape--packaging .colis__rabat--d {
  transform-origin: 0% 100%;
  animation: rabat-ferme-d 6s cubic-bezier(.4, 0, .2, 1) infinite;
}
@keyframes rabat-ferme-g {
  0%, 40%   { transform: skewX(0deg) scaleY(1); }
  56%, 100% { transform: skewX(26deg) scaleY(.42); }
}
@keyframes rabat-ferme-d {
  0%, 40%   { transform: skewX(0deg) scaleY(1); }
  56%, 100% { transform: skewX(-26deg) scaleY(.42); }
}
.parcours__etape--packaging .colis__ruban {
  stroke-dasharray: 16;
  animation: ruban-se-tire 6s ease-out infinite;
}
@keyframes ruban-se-tire {
  0%, 58%   { stroke-dashoffset: 16; }
  74%, 100% { stroke-dashoffset: 0; }
}

/* Livraison : le pays se dessine d'un trait, puis la destination s'y pose.
   Le contour est TRACÉ plutôt qu'affiché : c'est un trajet qui compte, et il
   se termine quelque part. */
.parcours__etape--livraison .fr__contour {
  /* 88 : la longueur réelle du tracé, relevée avec getTotalLength() (87,7),
     arrondie au-dessus. Trop courte, la valeur laisse le contour OUVERT —
     déjà vu deux fois ici. À revérifier à chaque retouche du tracé. */
  stroke-dasharray: 88;
  animation: pays-se-trace 6s ease-in-out infinite;
}
@keyframes pays-se-trace {
  0%, 8%    { stroke-dashoffset: 88; }
  46%, 88%  { stroke-dashoffset: 0; }
  100%      { stroke-dashoffset: 88; }
}
.parcours__etape--livraison .fr__corse {
  stroke-dasharray: 6;
  animation: corse-se-trace 6s ease-in-out infinite;
}
@keyframes corse-se-trace {
  0%, 44%   { stroke-dashoffset: 6; }
  56%, 88%  { stroke-dashoffset: 0; }
  100%      { stroke-dashoffset: 6; }
}
.parcours__etape--livraison .fr__point {
  transform-box: view-box;
  transform-origin: 15.2px 14.8px;
  animation: destination-se-pose 6s cubic-bezier(.3, 1.6, .5, 1) infinite;
}
@keyframes destination-se-pose {
  0%, 56%   { transform: scale(0); opacity: 0; }
  66%       { transform: scale(1.5); opacity: 1; }
  74%, 88%  { transform: scale(1); opacity: 1; }
  100%      { transform: scale(0); opacity: 0; }
}

/* ---- en colonne : l'arc n'a plus de sens, la route redevient droite ---- */
@media (max-width: 900px) {
  .parcours {
    grid-template-columns: 1fr;
    padding-top: 0;
    /* L'écart ENTRE les étapes doit dépasser celui qui sépare une icône de
       son titre, sinon chaque titre paraît appartenir à l'icône du dessous.
       C'est la loi de proximité : ce qui est proche est lu ensemble. */
    gap: 46px;
  }
  /* Les remontées de l'arc et les compensations de titre ne valent qu'en
     ligne. Empilées, elles décollaient chaque titre de son icône de 34 à
     61 px — d'où un empilement illisible. */
  .parcours__etape { margin-top: 0 !important; }
  .parcours__etape h3 { margin-top: 0 !important; }
  .parcours__icone { margin-bottom: 12px; }
  .parcours__arc, .parcours__camion { display: none; }
  /* Un trait vertical entre les étapes, dessiné par l'étape elle-même. */
  .parcours__etape + .parcours__etape::before {
    content: "";
    position: absolute;
    left: 50%; top: -46px;
    width: 2px; height: 46px;
    transform: translateX(-50%);
    background-image: repeating-linear-gradient(
      180deg, var(--accent) 0 7px, transparent 7px 16px);
    background-size: 2px 16px;
    opacity: .55;
    animation: route-verticale 1.1s linear infinite;
  }
  @keyframes route-verticale { to { background-position: 0 16px; } }
}

/* Un parcours qui s'anime en boucle est exactement ce dont on se passe quand
   on demande moins de mouvement : la route reste, elle ne bouge plus. */
@media (prefers-reduced-motion: reduce) {
  .parcours__arc-trace,
  .parcours__camion,
  .parcours__etape + .parcours__etape::before,
  .parcours__icone svg,
  .parcours__icone svg * { animation: none; }
  .parcours__camion { left: 80%; top: calc(var(--arc-haut) + 92px); opacity: 1;
                      transform: translate(-50%, -50%) rotate(10deg); }
  .colis__ruban { stroke-dasharray: none; }
  .impr__piece, .colis__rabat { transform: none; }
  .fr__contour, .fr__corse { stroke-dasharray: none; }
  .fr__point { transform: none; opacity: 1; }
  .cart__article { opacity: 0; }
}

.step {
  position: relative;
  padding: 28px 24px 32px;
  border-radius: var(--radius);
  border: 1px solid var(--hairline);
  background: var(--carte-bg);
  border-color: var(--carte-bord);
  box-shadow: var(--carte-ombre);
  transition: transform .4s, border-color .3s, box-shadow .3s;
}
.step:hover {
  transform: translateY(-6px);
  border-color: var(--accent);
  box-shadow:
    0 20px 40px -20px color-mix(in oklab, var(--accent) 40%, transparent),
    0 0 60px -10px color-mix(in oklab, var(--accent-glow) 30%, transparent);
}
.step__num {
  font-family: var(--font-display);
  font-size: 56px; line-height: 1;
  color: var(--accent);
  letter-spacing: -0.04em;
  margin-bottom: 28px;
  position: relative;
}
.step__num::after {
  content: ""; position: absolute; left: 0; bottom: -10px;
  width: 28px; height: 1px; background: var(--accent);
}
.step h3 { font-size: 22px; margin-bottom: 10px; letter-spacing: -0.01em; }
.step p { font-size: 14px; color: var(--fg-soft); margin: 0; }
.step__icon {
  position: absolute; top: 28px; right: 24px;
  width: 32px; height: 32px;
  opacity: .4;
}

/* ===== Galerie ===== */
.gallery {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 12px;
  margin-top: 48px;
}
.gal-item {
  position: relative;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--surface-fort);
  cursor: pointer;
  isolation: isolate;
}
.gal-item .ph {
  position: absolute; inset: 0;
  background-size: cover; background-position: center;
  background-repeat: no-repeat;
  transition: transform .8s cubic-bezier(.2,.7,.2,1), filter .6s;
}
.gal-item:hover .ph { transform: scale(1.06); filter: brightness(1.1); }
.gal-item .meta {
  position: absolute; left: 16px; bottom: 14px; z-index: 1;
  color: #fff;
  font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.2em; text-transform: uppercase;
  opacity: 0; transform: translateY(8px);
  transition: opacity .3s, transform .3s;
}
.gal-item:hover .meta { opacity: 1; transform: none; }
.gal-item::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(180deg, transparent 50%, rgba(0,0,0,.65) 100%);
  opacity: 0; transition: opacity .3s;
}
.gal-item:hover::after { opacity: 1; }

/* tailles tilées */
.gal-item--lg { grid-column: span 6; aspect-ratio: 6/5; }
.gal-item--md { grid-column: span 4; aspect-ratio: 1/1; }
.gal-item--sm { grid-column: span 3; aspect-ratio: 1/1; }
.gal-item--tall { grid-column: span 3; aspect-ratio: 3/4; }
.gal-item--wide { grid-column: span 6; aspect-ratio: 16/10; }
@media (max-width: 900px) {
  .gal-item, .gal-item--lg, .gal-item--md, .gal-item--sm, .gal-item--tall, .gal-item--wide {
    grid-column: span 6; aspect-ratio: 1/1;
  }
}

/* ===== Témoignages ===== */
.testimonials {
  display: grid; gap: 20px;
  grid-template-columns: repeat(3, 1fr);
  margin-top: 56px;
}
@media (max-width: 900px) { .testimonials { grid-template-columns: 1fr; } }

.tcard {
  padding: 32px;
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  background: var(--bg-soft);
  display: flex; flex-direction: column; gap: 18px;
  transition: transform .4s, border-color .3s;
}
.tcard:hover { transform: translateY(-4px); border-color: var(--accent); }
.tcard__stars { color: var(--accent); letter-spacing: 4px; font-size: 14px; }
.tcard__quote { font-family: var(--font-display); font-size: 19px; line-height: 1.35; }
.tcard__author {
  display: flex; align-items: center; gap: 12px;
  font-size: 13px;
  margin-top: auto;
}
.tcard__avatar {
  width: 40px; height: 40px; border-radius: 99px;
  background: linear-gradient(135deg, var(--accent), var(--accent-deep));
  display: grid; place-items: center;
  color: #fff; font-weight: 600; font-size: 14px;
}
.tcard__author small { color: var(--fg-label); font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.16em; text-transform: uppercase; display: block; margin-top: 2px; }

/* ===== CTA final ===== */

/* ===== Footer ===== */
.footer {
  padding: 80px var(--gutter) 36px;
  border-top: 1px solid var(--hairline);
  display: grid;
  grid-template-columns: 2fr 1fr 1fr 1fr;
  gap: 40px;
  max-width: var(--container);
  margin: 0 auto;
}
@media (max-width: 760px) { .footer { grid-template-columns: 1fr 1fr; } }

.footer h4 {
  font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.22em;
  text-transform: uppercase; color: var(--fg-label);
  margin-bottom: 16px; font-weight: 500;
}
.footer ul { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 10px; font-size: 14px; }
.footer a:hover { color: var(--accent); }

.footer__brand p {
  color: var(--fg-soft); font-size: 14px; max-width: 36ch; margin: 16px 0 24px;
}
.footer__brand .socials { display: flex; gap: 10px; }

/* ---- « à venir » sur les réseaux ------------------------------------- */
.social { position: relative; display: inline-flex; }
.social__bulle {
  position: absolute;
  bottom: calc(100% + 10px);
  left: 50%;
  padding: 6px 12px;
  border-radius: 8px;
  background: var(--surface-fort);
  color: var(--sur-surface-fort);
  font-size: 12px;
  letter-spacing: .02em;
  white-space: nowrap;
  /* Retirée du flux ET du calcul de survol : sans `pointer-events: none`,
     la bulle qui apparaît sous le curseur le vole au bouton et clignote. */
  pointer-events: none;
  opacity: 0;
  transform: translate(-50%, 5px);
  transition: opacity .22s ease, transform .22s ease;
}
/* La flèche, taillée dans un carré pivoté plutôt qu'en bordures : elle prend
   ainsi la couleur de la bulle sans avoir à la redéclarer. */
.social__bulle::after {
  content: "";
  position: absolute;
  top: 100%; left: 50%;
  width: 8px; height: 8px;
  margin: -4px 0 0 -4px;
  background: inherit;
  transform: rotate(45deg);
}
.social:hover .social__bulle,
.social:focus-within .social__bulle,
.social__bulle.is-ouverte {
  opacity: 1;
  transform: translate(-50%, 0);
}
@media (prefers-reduced-motion: reduce) {
  .social__bulle { transition: none; }
}

.footer__bottom {
  max-width: var(--container);
  margin: 32px auto 0;
  padding: 24px var(--gutter) 0;
  border-top: 1px solid var(--hairline);
  display: flex; justify-content: space-between;
  font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.14em;
  color: var(--fg-soft);
}

/* ===== Marquee defile ===== */
.marquee {
  overflow: hidden;
  border-block: 1px solid var(--hairline);
  padding: 22px 0;
  position: relative;
  --speed: 50s;
}
.marquee__track {
  display: flex; gap: 56px; width: max-content;
  animation: scroll var(--speed) linear infinite;
}
@keyframes scroll { to { transform: translateX(-50%); } }
.marquee__item {
  font-family: var(--font-display); font-style: italic;
  font-size: 32px; letter-spacing: -0.02em;
  display: inline-flex; align-items: center; gap: 56px;
  white-space: nowrap;
}
.marquee__item .star {
  width: 24px; height: 24px; color: var(--accent);
}
.marquee__item em {
  font-family: var(--font-mono); font-style: normal;
  font-size: 12px; letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--fg-soft);
}

/* ===== Réduit les animations ===== */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001s !important;
    transition-duration: .001s !important;
  }
}

/* ========================================================================
   PHOTO UPLOADER — port React du plugin WooCommerce
   ======================================================================== */

.pu {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin-top: 4px;
}

.pu__head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--fg-soft);
}
.pu__head-title { display: inline-flex; align-items: center; gap: 8px; }
.pu__icon { color: var(--accent); letter-spacing: -2px; }
.pu__head-count { color: var(--fg); }

/* ---- gallery slots ------------------------------------------------- */
.pu__gallery {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
}
@media (max-width: 600px) {
  .pu__gallery { grid-template-columns: repeat(2, 1fr); }
}

.pu__slot {
  position: relative;
  aspect-ratio: 1 / 1;
  border-radius: var(--radius-sm);
  border: 1.5px dashed var(--carte-bord);
  background:
    linear-gradient(135deg, rgba(214,153,84,.04), rgba(214,153,84,.0)),
    var(--carte-bg);
  color: var(--fg-soft);
  cursor: pointer;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  transition: border-color .25s ease, transform .25s ease, background .25s ease;
  font: inherit;
  padding: 0;
}
.pu__slot:hover {
  border-color: var(--accent);
  color: var(--accent);
  transform: translateY(-1px);
}
.pu__slot.is-filled {
  border-style: solid;
  border-color: rgba(214,153,84,.35);
  background: var(--surface-fort);
  box-shadow:
    inset 0 0 0 1px rgba(255,255,255,.04),
    0 1px 0 rgba(255,255,255,.04),
    0 18px 30px -22px rgba(255,170,90, calc(var(--lit) * .7));
}
.pu__slot.is-filled img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  /* effet « lithophane » : un poil chaud + désaturé pour rappeler le rendu */
  filter:
    sepia(35%)
    saturate(120%)
    brightness(calc(.85 + var(--lit) * .25))
    contrast(105%);
  transition: filter .9s ease;
}
.pu__slot-num {
  font-family: var(--font-display);
  font-size: 38px;
  font-weight: 300;
  line-height: 1;
  /* Chiffre en contour seul. `--hairline` est passé à 16 % d'opacité sur fond
     sombre : le trait devenait invisible. On trace avec le caramel, assez
     présent pour se lire sans concurrencer les vignettes remplies. */
  color: rgba(0,0,0,.0);
  -webkit-text-stroke: 1px rgba(210, 165, 116, .45);
  margin-bottom: 6px;
}
:root[data-lights="off"] .pu__slot-num {
  -webkit-text-stroke-color: rgba(255,200,140,.18);
}
.pu__slot-hint {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: .14em;
  text-transform: uppercase;
}
.pu__slot-remove {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: rgba(0,0,0,.55);
  color: #fff;
  font-size: 18px;
  line-height: 20px;
  text-align: center;
  backdrop-filter: blur(4px);
  opacity: 0;
  transition: opacity .2s ease;
}
.pu__slot.is-filled:hover .pu__slot-remove { opacity: 1; }

/* ---- glisser-déposer -------------------------------------------------
   La grande zone de dépôt a été retirée le 12/09/2026 : chaque emplacement
   vide porte déjà « + ajouter » et ouvre le sélecteur, elle faisait doublon.
   Le glisser-déposer est CONSERVÉ, simplement passé SUR la grille — déposer
   une image sur les cases est plus direct que de viser une boîte à côté. */
.pu__gallery.is-over .pu__face.is-tex .pu__face-vue {
  border-color: var(--accent);
  background: color-mix(in oklab, var(--accent) 8%, var(--bg-soft));
}

.pu__legal {
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: .08em;
  color: var(--fg-soft);
  margin: 0;
}
.pu__legal strong { color: var(--fg); font-weight: 500; }

/* ---- crop modal ---------------------------------------------------- */
.pu__modal {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: color-mix(in oklab, var(--surface-fort) 88%, transparent);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  backdrop-filter: blur(6px);
  animation: pu-fade .2s ease;
}
@keyframes pu-fade { from { opacity: 0; } to { opacity: 1; } }

.pu__modal-inner {
  width: min(720px, 100%);
  background: var(--surface-fort);
  border: 1px solid rgba(255,200,140,.12);
  border-radius: var(--radius);
  padding: 22px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  color: var(--sur-surface-fort);
  box-shadow: 0 40px 80px -20px rgba(0,0,0,.6);
}
.pu__modal-frame {
  background: #0d0805;
  border-radius: var(--radius-sm);
  padding: 8px;
  display: flex;
  justify-content: center;
  max-height: 70vh;
  overflow: hidden;
}
/* Cropper.js needs the image to be block & full width before init */
.pu__modal-frame img { max-width: 100%; display: block; }

.pu__modal-meta {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--sur-surface-doux);
  text-align: center;
}
.pu__modal-ctrls {
  display: flex;
  gap: 10px;
  justify-content: flex-end;
}
.pu__btn {
  font: inherit;
  padding: 12px 22px;
  border-radius: 999px;
  border: 1px solid transparent;
  cursor: pointer;
  font-size: 14px;
  font-weight: 500;
  transition: transform .15s ease, background .2s ease;
}
.pu__btn--primary {
  background: var(--accent);
  color: var(--accent-on);
  border-color: var(--accent);
}
.pu__btn--primary:hover { transform: translateY(-1px); }
.pu__btn--ghost {
  background: transparent;
  color: var(--sur-surface-fort);
  border-color: rgba(255,200,140,.18);
}
.pu__btn--ghost:hover { border-color: rgba(255,200,140,.4); }

/* Cropper.js overrides so its UI matches the warm MyLithoBox palette */
.cropper-view-box,
.cropper-face {
  outline-color: var(--accent) !important;
}
.cropper-line,
.cropper-point {
  background-color: var(--accent) !important;
}
.cropper-dashed { border-color: rgba(255,200,140,.4) !important; }

/* ===== Cart success modal ===== */
.cart-modal-overlay {
  position: fixed; inset: 0; z-index: 9999;
  background: rgba(10,8,6,.75);
  backdrop-filter: blur(6px);
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
  animation: fadeIn .25s ease;
}
.cart-modal {
  background: #221509;
  border: 1px solid rgba(255,200,140,.15);
  border-radius: 20px;
  padding: clamp(32px, 5vw, 56px) clamp(28px, 5vw, 56px);
  max-width: 480px; width: 100%;
  text-align: center;
  box-shadow: 0 32px 80px -16px rgba(0,0,0,.7);
  animation: slideUp .3s cubic-bezier(.4,0,.2,1);
}
.cart-modal__icon {
  width: 60px; height: 60px; border-radius: 50%;
  background: rgba(214,153,84,.15);
  border: 1.5px solid var(--accent);
  color: var(--accent);
  font-size: 24px;
  display: flex; align-items: center; justify-content: center;
  margin: 0 auto 20px;
}
.cart-modal__title {
  color: var(--sur-surface-fort);
  font-size: clamp(20px, 3vw, 26px);
  font-weight: 600; margin-bottom: 10px;
}
.cart-modal__sub {
  color: var(--sur-surface-doux);
  font-size: 14px; line-height: 1.6; margin-bottom: 28px;
}
.cart-modal__actions {
  display: flex; flex-direction: column; gap: 12px;
}
.cart-modal__actions .btn { justify-content: center; width: 100%; }
.cart-modal__actions .btn--primary {
  background: var(--accent); color: var(--accent-on);
  box-shadow: 0 8px 24px -8px color-mix(in oklab, var(--accent) 45%, transparent);
}
.cart-modal__actions .btn--primary:hover {
  background: var(--accent-deep); color: var(--cta-fg);
  box-shadow: 0 14px 30px -8px color-mix(in oklab, var(--accent) 60%, transparent);
}
.cart-modal__actions .btn--ghost {
  border-color: rgba(255,200,140,.25); color: var(--sur-surface-fort);
}
.cart-modal__actions .btn--ghost:hover {
  border-color: var(--accent); color: var(--accent);
}
@keyframes fadeIn { from { opacity:0 } to { opacity:1 } }
@keyframes slideUp { from { opacity:0; transform:translateY(24px) } to { opacity:1; transform:none } }

/* ===== Navigation mobile ===== */
.nav__burger {
  display: none;
  flex-direction: column; justify-content: center; gap: 5px;
  padding: 8px;
}
.nav__burger span {
  display: block; width: 18px; height: 1.5px;
  background: currentColor; border-radius: 2px;
  transition: transform .3s cubic-bezier(.4,0,.2,1), opacity .2s;
  transform-origin: center;
}
.nav__burger.is-open span:nth-child(1) { transform: translateY(6.5px) rotate(45deg); }
.nav__burger.is-open span:nth-child(2) { opacity: 0; transform: scaleX(0); }
.nav__burger.is-open span:nth-child(3) { transform: translateY(-6.5px) rotate(-45deg); }

.nav__overlay {
  position: fixed; inset: 0; z-index: 48;
  background: rgba(0,0,0,.4); backdrop-filter: blur(2px);
}
@media (min-width: 1025px) {
  .nav__overlay, .nav__mobile { display: none !important; }
}
.nav__mobile {
  position: fixed; top: 0; left: 0; bottom: 0; z-index: 49;
  width: min(320px, 85vw);
  background: var(--bg);
  border-right: 1px solid var(--hairline);
  padding: 88px var(--gutter) 32px;
  display: flex; flex-direction: column;
  transform: translateX(-100%);
  transition: transform .35s cubic-bezier(.4,0,.2,1);
  pointer-events: none;
}
.nav__mobile.is-open {
  transform: none;
  pointer-events: auto;
}
.nav__mobile a {
  font-family: var(--font-display); font-size: 22px;
  padding: 14px 0;
  border-bottom: 1px solid var(--hairline);
  transition: color .2s;
}
.nav__mobile a:hover { color: var(--accent); }
.nav__mobile-footer {
  margin-top: auto; padding-top: 28px;
}
.nav__mobile-footer .btn { width: 100%; justify-content: center; }

/* Intermédiaire : liens resserrés avant de basculer en hamburger */
@media (max-width: 1280px) {
  .nav { gap: 16px; }
  .nav__links { gap: clamp(12px, 1.8vw, 28px); font-size: 13px; }
}

/* Hamburger au-dessous de 1024px */
@media (max-width: 1024px) {
  .nav {
    grid-template-columns: 1fr auto;
  }
  .nav__links { display: none; }
  .nav__burger { display: flex; }
  .nav__cta-hide-mobile { display: none; }
}

/* ===== Overlay de recherche ===== */
.search-overlay {
  position: fixed; inset: 0; z-index: 9000;
  background: rgba(10,8,6,.82);
  backdrop-filter: blur(8px);
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: 16px;
  padding: 24px;
  animation: fadeIn .2s ease;
}
.search-box {
  display: flex; align-items: center; gap: 12px;
  width: 100%; max-width: 560px;
  background: var(--bg);
  border: 1px solid var(--hairline);
  border-radius: 99px;
  padding: 8px 8px 8px 20px;
}
.search-box svg { flex-shrink: 0; opacity: .5; }
.search-box input {
  flex: 1; background: none; border: none; outline: none;
  font-size: 18px; color: var(--fg);
  font-family: var(--font-body);
}
.search-box input::placeholder { color: var(--fg-soft); }
.search-box .btn { flex-shrink: 0; padding: 10px 20px; font-size: 13px; }
.search-hint {
  font-size: 12px; letter-spacing: 0.08em; text-transform: uppercase;
  color: rgba(255,240,220,.35);
}

/* ===== Viewer 3D (LithoCube3D) ===== */
.litho3d {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  z-index: 1;
  cursor: grab;
  touch-action: none;
}
.litho3d:active { cursor: grabbing; }
.litho3d canvas { display: block; width: 100% !important; height: 100% !important; }

.litho3d-hint {
  position: absolute; bottom: 14px; left: 50%; transform: translateX(-50%);
  z-index: 3;
  font-family: var(--font-mono); font-size: 10px;
  letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--fg-soft);
  background: color-mix(in oklab, var(--bg) 80%, transparent);
  border: 1px solid var(--hairline);
  padding: 6px 12px; border-radius: 99px;
  backdrop-filter: blur(6px);
  white-space: nowrap;
  pointer-events: none;
  opacity: .85;
}

/* La sphère lumineuse reste au-dessus du fond mais sous le canvas */
.product__visual::before { z-index: 0; }
.product__visual .badge-price { z-index: 4; }

/* ===== Configurateur single-column (3D dans le form) ===== */
.product--single {
  display: block !important;
  max-width: 720px;
  margin: 0 auto;
}
.product--single .product__form {
  display: flex; flex-direction: column; gap: 24px;
}

.badge-price--inline {
  display: inline-block;
  position: relative; bottom: auto; right: auto; left: auto; top: auto;
  margin-top: 12px;
  background: var(--surface-fort); color: var(--sur-surface-fort);
  padding: 6px 16px; border-radius: 99px;
  font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.14em;
  text-transform: uppercase;
}

/* Wrapper du viewer 3D dans le form */
.litho3d-wrap {
  position: relative;
  aspect-ratio: 1 / 1;
  width: 100%;
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 1px solid var(--carte-bord);
  background: linear-gradient(165deg, var(--plateau-1) 0%, var(--plateau-2) 60%, var(--plateau-3) 100%);
}
.litho3d-wrap::before {
  content: ""; position: absolute; inset: 0; z-index: 0;
  background: radial-gradient(circle at 50% 40%,
    color-mix(in oklab, var(--accent-glow) calc(var(--lit) * 28%), transparent) 0%,
    transparent 60%);
}
.litho3d-wrap .litho3d {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
}
.litho3d-wrap .litho3d-hint {
  position: absolute; bottom: 14px; left: 50%; transform: translateX(-50%);
  z-index: 3;
}

/* Sur écrans plus grands, garder le viewer raisonnable */
@media (min-width: 720px) {
  .litho3d-wrap { max-width: 520px; margin: 0 auto; }
}

/* Hiérarchie héros : MyLithoBox = grand titre, Illuminez = sous-titre */
.hero__brand { display: flex; align-items: center; gap: .3em; flex-wrap: wrap;
  opacity: 0; animation: heroIn .9s .15s cubic-bezier(.2,.7,.2,1) forwards; }
.hero__logo { width: .9em; height: .9em; object-fit: contain;
  filter: drop-shadow(0 6px 18px color-mix(in oklab, var(--accent) 45%, transparent)); }
.hero__subtitle { font-family: var(--font-display); font-style: italic; font-weight: 300;
  font-size: clamp(22px, 3.6vw, 44px); line-height: 1.05; letter-spacing: -.015em;
  /* Était en accent-deep (#8a5520) : un brun qui se noyait dans le fond
     obsidienne. La charte donne au texte secondaire sur fond sombre le
     caramel — c'est un sous-titre de héros, il doit se lire. */
  color: var(--fg-label); margin: 0 0 16px;
  opacity: 0; animation: heroIn 1s .4s cubic-bezier(.2,.7,.2,1) forwards; }

/* ============================================================
   HÉROS — la box qui s'allume
   Ajouté le 09/09/2026. Deux photographies de la MÊME box superposées :
   éteinte, on ne voit que le relief blanc ; allumée, la photo apparaît.
   Le fondu entre les deux EST la démonstration du produit.
   ============================================================ */

/* Le halo n'existe que quand la box est allumée. */

@media (prefers-reduced-motion: reduce) {
}

/* La flaque de lumière au sol : sans elle, le cube flotte dans le vide. */
@media (prefers-reduced-motion: reduce) {
}

/* ---- Le logo du pied de page suit la lumière ----
   Le cube du logo est LUMINEUX : peint en crèmes, il se lit sur la barre du
   haut, qui est sombre. Le pied de page, lui, est sur le fond de la page :
   clair le jour, sombre la nuit. Un seul fichier ne pouvait pas tenir les deux
   — mesuré rgb(237,225,208) sur un fond rgb(245,237,226), soit 1,05:1, donc
   invisible. On pose les deux et on montre celui qui se détache. */
.footer__brand .logo--allume { display: none; }
.footer__brand .logo--eteint { display: block; }
:root[data-lights="off"] .footer__brand .logo--allume { display: block; }
:root[data-lights="off"] .footer__brand .logo--eteint { display: none; }

/* ══ LES QUATRE FACES ══════════════════════════════════════════════════════
   Le client ne choisit plus « combien de photos » : sa boîte a quatre faces,
   il en personnalise autant qu'il veut et les autres reçoivent une texture.
   Cette règle se lit dans un texte, mais elle se COMPREND dans ce bandeau :
   quatre cases, ce que chaque face deviendra. Sans lui, il fallait tenir tout
   l'état de la boîte dans sa tête.                                          */
.field__regle {
  margin: 0 0 12px;
  font-size: 13px;
  line-height: 1.5;
  color: var(--fg-soft);
}
.field__regle strong { color: var(--fg); font-weight: 500; }

.faces {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
  margin-top: 14px;
}
.faces__case {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 8px 4px 10px;
  border: 1px solid var(--carte-bord);
  border-radius: var(--radius-sm);
  background: var(--carte-bg);
  /* La face qui porte une photo du client se détache : c'est SON contenu, il
     doit se repérer sans lire les légendes. */
  transition: border-color .25s, box-shadow .25s;
}
.faces__case.is-photo {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px color-mix(in oklab, var(--accent) 35%, transparent);
}
.faces__num {
  font-family: var(--font-label);
  font-size: 10px;
  letter-spacing: .14em;
  color: var(--fg-label);
}
.faces__vue {
  width: 100%;
  aspect-ratio: 1;
  border-radius: 4px;
  background-size: cover;
  background-position: center;
}
.faces__nom {
  font-size: 11px;
  line-height: 1.25;
  text-align: center;
  color: var(--fg-soft);
}
.faces__case.is-photo .faces__nom { color: var(--accent); }

/* Sous 420 px, quatre colonnes rendent chaque case illisible : deux lignes de
   deux gardent la vignette assez grande pour qu'on reconnaisse sa photo. */
@media (max-width: 420px) {
  .faces { grid-template-columns: repeat(2, 1fr); }
}

/* Le supplément d'une face payante, sur la case elle-même : c'est le seul
   endroit où le client voit le prix AU MOMENT où il regarde la face. */
.faces__supp {
  font-family: var(--font-label);
  font-size: 10px;
  letter-spacing: .06em;
  padding: 1px 6px;
  border-radius: 99px;
  background: color-mix(in oklab, var(--accent) 16%, transparent);
  color: var(--accent);
}

/* ══ UNE CARTE PAR FACE ════════════════════════════════════════════════════
   Une même face vivait à trois endroits : l'emplacement de téléversement, le
   sélecteur de texture plus bas, et le récapitulatif en fin de bloc. Il fallait
   rapprocher trois grilles pour savoir ce qu'on achetait, et « sélectionner »
   se faisait à deux endroits pour un seul résultat.

   Une carte porte désormais TOUT ce qui concerne sa face : ce qu'elle
   deviendra, et les deux seules décisions possibles — y mettre une photo, ou
   choisir sa texture.                                                       */
.pu__face {
  display: flex;
  flex-direction: column;
  gap: 7px;
}
.pu__face-num {
  font-family: var(--font-label);
  font-size: 10px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--fg-label);
}
.pu__face-vue {
  position: relative;
  width: 100%;
  aspect-ratio: 1 / 1;
  padding: 0;
  border-radius: var(--radius-sm);
  overflow: hidden;
  cursor: pointer;
  background-size: cover;
  background-position: center;
  border: 1.5px dashed var(--carte-bord);
  background-color: var(--carte-bg);
  transition: border-color .2s, transform .2s, box-shadow .2s;
}
.pu__face-vue:hover { border-color: var(--accent); transform: translateY(-1px); }
.pu__face-vue:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* La face qui porte une photo du client se ferme : trait plein, pas de
   pointillé. Le pointillé dit « il manque quelque chose ici ». */
.pu__face.is-photo .pu__face-vue {
  border-style: solid;
  border-color: var(--accent);
}
.pu__face.is-photo .pu__face-vue img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.pu__face-x {
  position: absolute;
  top: 6px; right: 6px;
  width: 22px; height: 22px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: 15px;
  line-height: 1;
  background: var(--cta-bg);
  color: var(--cta-fg);
  opacity: 0;
  transition: opacity .2s;
}
.pu__face.is-photo .pu__face-vue:hover .pu__face-x,
.pu__face.is-photo .pu__face-vue:focus-visible .pu__face-x { opacity: 1; }

/* La case vide garde l'allure qu'elle avait avant la fusion : fond crème en
   pointillé, chiffre en contour. Elle ne porte PAS la texture en fond — ce
   sont les trois pastilles en dessous qui montrent la finition, et le chiffre
   reste lisible quelle que soit celle qui est choisie. */
.pu__face-vide {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  background:
    linear-gradient(135deg, rgba(214, 153, 84, .04), rgba(214, 153, 84, 0)),
    var(--carte-bg);
  color: var(--fg-soft);
  transition: color .2s;
}
.pu__face-vue:hover .pu__face-vide { color: var(--accent); }
.pu__face-chiffre {
  font-family: var(--font-display);
  font-size: 38px;
  font-weight: 300;
  line-height: 1;
  /* Chiffre en contour seul. `--hairline` tombe à 16 % d'opacité sur fond
     sombre : le trait y devenait invisible. On trace avec le caramel. */
  color: transparent;
  -webkit-text-stroke: 1px rgba(210, 165, 116, .45);
}
:root[data-lights="off"] .pu__face-chiffre {
  -webkit-text-stroke-color: rgba(255, 200, 140, .18);
}
.pu__face-hint {
  font-family: var(--font-label);
  font-size: 10px;
  letter-spacing: .14em;
  text-transform: uppercase;
}

/* Les trois textures, sous la face qu'elles concernent. */
.pu__tex {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 5px;
}
.pu__tex-p {
  width: 100%;
  aspect-ratio: 1 / 1;
  padding: 0;
  border-radius: 6px;
  cursor: pointer;
  background-size: cover;
  background-position: center;
  /* Bordure de largeur CONSTANTE : l'épaissir à l'état actif décalerait les
     vignettes voisines, à cette taille cela se voit. */
  border: 1.5px solid var(--hairline);
  transition: border-color .15s;
}
.pu__tex-p:hover { border-color: var(--accent); }
.pu__tex-p.is-active { border-color: var(--fg); }
.pu__tex-p:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.pu__face-nom {
  font-size: 11.5px;
  line-height: 1.3;
  color: var(--fg-soft);
}
.pu__face-nom.is-photo { color: var(--accent); }
.pu__face-supp {
  font-family: var(--font-label);
  font-size: 10px;
  color: var(--accent);
}

/* ---- Face dont la TEXTURE est choisie ----
   Elle se ferme comme une face qui porte une photo : trait plein, plus de
   pointillé. Le pointillé dit « il manque quelque chose ici » ; une fois la
   finition décidée, il ne manque plus rien. */
.pu__face-vue.is-tex-choisie {
  border-style: solid;
  border-color: var(--carte-bord);
  background-size: cover;
  background-position: center;
}
/* L'invite n'apparaît qu'au survol : la case montre d'abord la finition
   choisie, et ne propose la photo qu'à qui s'y intéresse. */
.pu__face-survol {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-family: var(--font-label);
  font-size: 10.5px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--parchemin-haut);
  background: color-mix(in oklab, var(--encre) 52%, transparent);
  opacity: 0;
  transition: opacity .2s;
}
.pu__face-vue:hover .pu__face-survol,
.pu__face-vue:focus-visible .pu__face-survol { opacity: 1; }

/* Tant que rien n'est décidé, le nom de la face le dit, sans alarmer. */
.pu__face-nom.is-attente {
  color: var(--fg-label);
  font-style: italic;
}
