/* =====================================================================
   TY 3D PRINT — feuille de style unique
   Mobile-first · CSS Grid + Flexbox · thème sombre, accents fluo
   Un seul fichier : pas d'étape de build, une seule requête HTTP.
   Sections : 1 jetons · 2 socle · 3 mise en page · 4 composants
              · 5 pages · 6 utilitaires · 7 impression
   ===================================================================== */

/* ------------------------------------------------------------------ */
/* 1. JETONS                                                           */
/* ------------------------------------------------------------------ */
:root{
  /* Indique au navigateur que la page est sombre : sans cela les
     contrôles natifs (cases à cocher décochées, boutons radio, champ
     de fichier, ascenseurs, liste déroulante des select) sont dessinés
     en clair et tranchent violemment sur le fond. */
  color-scheme: dark;

  /* Surfaces */
  --bg:        #0B0D12;
  --bg-2:      #10131A;
  --panel:     #161A23;
  --panel-2:   #1C212C;
  --line:      #262C3B;
  --line-soft: #1D2230;

  /* Texte */
  --txt:       #E8ECF4;
  --txt-2:     #AEB7C6;
  --muted:     #7C8698;

  /* Accents */
  --cyan:      #22E3F5;
  --cyan-dim:  #0FA9BC;
  --orange:    #FF8A2B;
  --orange-dim:#C4610F;
  --ok:        #2FD07A;
  --warn:      #FFC53D;
  --ko:        #FF5A5A;

  /* Typographie */
  --font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;

  --fs-xs: .75rem;  --fs-sm: .8125rem; --fs-base: .9375rem;
  --fs-md: 1.0625rem; --fs-lg: 1.25rem; --fs-xl: 1.5rem;
  --fs-2xl: clamp(1.75rem, 1.2rem + 2.2vw, 2.75rem);
  --fs-3xl: clamp(2.1rem, 1.3rem + 3.4vw, 3.6rem);

  /* Espacements (échelle de 4) */
  --s-1: .25rem; --s-2: .5rem;  --s-3: .75rem; --s-4: 1rem;
  --s-5: 1.5rem; --s-6: 2rem;   --s-7: 3rem;   --s-8: 4rem; --s-9: 6rem;

  --radius:    10px;
  --radius-sm: 6px;
  --radius-lg: 16px;
  --maxw:      1200px;
  --header-h:  64px;

  --shadow:    0 12px 32px -12px rgba(0,0,0,.7);
  --shadow-lg: 0 24px 60px -20px rgba(0,0,0,.85);
  --ring:      0 0 0 2px var(--bg), 0 0 0 4px var(--cyan);

  --ease: cubic-bezier(.22,.61,.36,1);
}

/* ------------------------------------------------------------------ */
/* 2. SOCLE                                                            */
/* ------------------------------------------------------------------ */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
body{
  margin:0;background:var(--bg);color:var(--txt);
  font:var(--fs-base)/1.65 var(--font);
  -webkit-font-smoothing:antialiased;
  overflow-wrap:break-word;
}
h1,h2,h3,h4{margin:0 0 var(--s-3);line-height:1.2;font-weight:700;letter-spacing:-.015em}
h1{font-size:var(--fs-2xl)}
h2{font-size:var(--fs-xl)}
h3{font-size:var(--fs-md)}
p{margin:0 0 var(--s-4)}
a{color:var(--cyan);text-decoration:none}
a:hover{text-decoration:underline}
img,svg,video{max-width:100%;height:auto;display:block}
/* La règle ci-dessus l'emporte sur le [hidden]{display:none} du
   navigateur : sans ce rappel, le sprite d'icônes <svg hidden> reste
   dans le flux et occupe une cellule de la grille du back-office. */
[hidden]{display:none!important}
ul,ol{margin:0 0 var(--s-4);padding-left:1.25rem}
hr{border:0;border-top:1px solid var(--line);margin:var(--s-6) 0}
small{font-size:var(--fs-sm)}
code,kbd{font-family:var(--mono);font-size:.9em}

:focus-visible{outline:none;box-shadow:var(--ring);border-radius:var(--radius-sm)}

::selection{background:var(--cyan);color:#04121a}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms!important;transition-duration:.001ms!important;scroll-behavior:auto!important}
}

.skip-link{
  position:absolute;left:var(--s-4);top:-100px;z-index:100;
  background:var(--cyan);color:#04121a;padding:var(--s-3) var(--s-4);
  border-radius:var(--radius-sm);font-weight:700;
}
.skip-link:focus{top:var(--s-3)}

.visually-hidden{
  position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0;
}

/* ------------------------------------------------------------------ */
/* 3. MISE EN PAGE                                                     */
/* ------------------------------------------------------------------ */
.wrap{width:100%;max-width:var(--maxw);margin-inline:auto;padding-inline:var(--s-4)}
@media (min-width:768px){.wrap{padding-inline:var(--s-5)}}

main{min-height:60vh;padding-block:var(--s-6) var(--s-9)}

/* --- En-tête ------------------------------------------------------- */
.header{
  position:sticky;top:0;z-index:40;
  background:rgba(11,13,18,.86);
  backdrop-filter:blur(12px);
  border-bottom:1px solid var(--line);
}
.header__inner{
  display:flex;align-items:center;gap:var(--s-4);
  min-height:var(--header-h);
}
.brand{
  display:inline-flex;align-items:baseline;gap:.35ch;
  font-weight:800;font-size:var(--fs-md);letter-spacing:.02em;
  color:var(--txt);text-decoration:none;white-space:nowrap;
}
.brand:hover{text-decoration:none}
.brand b{color:var(--cyan);font-weight:800}
.brand span{color:var(--muted);font-weight:600;font-size:var(--fs-xs);letter-spacing:.18em;text-transform:uppercase}

.nav{display:none}
@media (min-width:960px){
  .nav{display:flex;gap:var(--s-5);flex:1;align-items:center}
}
.nav a{
  color:var(--txt-2);font-size:var(--fs-sm);font-weight:500;
  padding-block:var(--s-2);position:relative;text-decoration:none;
}
.nav a::after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:2px;
  background:var(--cyan);transform:scaleX(0);transform-origin:left;
  transition:transform .18s var(--ease);
}
.nav a:hover,.nav a[aria-current]{color:var(--txt)}
.nav a:hover::after,.nav a[aria-current]::after{transform:scaleX(1)}

.header__actions{display:flex;align-items:center;gap:var(--s-2);margin-left:auto}

.icon-btn{
  display:inline-flex;align-items:center;justify-content:center;gap:var(--s-2);
  min-width:40px;height:40px;padding-inline:var(--s-3);
  background:transparent;border:1px solid var(--line);border-radius:var(--radius-sm);
  color:var(--txt-2);cursor:pointer;font:600 var(--fs-sm)/1 var(--font);
  transition:border-color .15s var(--ease),color .15s var(--ease);
}
.icon-btn:hover{border-color:var(--cyan-dim);color:var(--txt)}
.icon-btn svg{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:1.8}

.cart-btn{position:relative}
.cart-count{
  position:absolute;top:-6px;right:-6px;min-width:19px;height:19px;padding:0 5px;
  display:none;align-items:center;justify-content:center;
  background:var(--orange);color:#1a0d00;border-radius:999px;
  font:800 var(--fs-xs)/1 var(--font);
}
.cart-count.is-visible{display:inline-flex}

/* Menu mobile */
.burger{display:inline-flex}
@media (min-width:960px){.burger{display:none}}
.mobile-nav{
  display:none;border-top:1px solid var(--line);background:var(--bg-2);
  padding:var(--s-3) 0;
}
.mobile-nav.is-open{display:block}
.mobile-nav a{display:block;padding:var(--s-3) var(--s-4);color:var(--txt-2);font-weight:500}
.mobile-nav a:hover{background:var(--panel);color:var(--txt);text-decoration:none}

/* --- Sélecteur de langue ------------------------------------------- */
.langs{position:relative}
.langs__list{
  position:absolute;right:0;top:calc(100% + 6px);z-index:50;
  min-width:160px;padding:var(--s-2);margin:0;list-style:none;
  background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);
  box-shadow:var(--shadow);display:none;
}
.langs.is-open .langs__list{display:block}
.langs__list a{
  display:flex;align-items:center;justify-content:space-between;gap:var(--s-3);
  padding:var(--s-2) var(--s-3);border-radius:var(--radius-sm);
  color:var(--txt-2);font-size:var(--fs-sm);text-decoration:none;
}
.langs__list a:hover{background:var(--panel-2);color:var(--txt)}
.langs__list a[aria-current]{color:var(--cyan);font-weight:700}
.langs__code{font:700 var(--fs-xs)/1 var(--mono);letter-spacing:.1em;text-transform:uppercase;color:var(--muted)}

/* --- Pied de page -------------------------------------------------- */
.footer{border-top:1px solid var(--line);background:var(--bg-2);padding-block:var(--s-7) var(--s-5)}
.footer__grid{display:grid;gap:var(--s-6);grid-template-columns:1fr}
@media (min-width:640px){.footer__grid{grid-template-columns:repeat(2,1fr)}}
@media (min-width:960px){.footer__grid{grid-template-columns:1.4fr 1fr 1fr 1fr}}
.footer h3{font-size:var(--fs-xs);letter-spacing:.16em;text-transform:uppercase;color:var(--orange);margin-bottom:var(--s-3)}
.footer ul{list-style:none;padding:0;margin:0;display:grid;gap:var(--s-2)}
.footer a{color:var(--txt-2);font-size:var(--fs-sm)}
.footer a:hover{color:var(--txt)}
.footer__legal{
  margin-top:var(--s-6);padding-top:var(--s-4);border-top:1px solid var(--line-soft);
  display:flex;flex-wrap:wrap;gap:var(--s-3) var(--s-5);
  color:var(--muted);font-size:var(--fs-xs);
}

/* ------------------------------------------------------------------ */
/* 4. COMPOSANTS                                                       */
/* ------------------------------------------------------------------ */

/* --- Boutons -------------------------------------------------------- */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:var(--s-2);
  padding:.75rem 1.25rem;border:1px solid transparent;border-radius:var(--radius-sm);
  font:700 var(--fs-base)/1.1 var(--font);cursor:pointer;text-decoration:none;
  transition:background .15s var(--ease),border-color .15s var(--ease),transform .1s var(--ease);
}
.btn:hover{text-decoration:none}
.btn:active{transform:translateY(1px)}
.btn[disabled],.btn.is-loading{opacity:.55;pointer-events:none}
.btn--primary{background:var(--cyan);color:#04121a}
.btn--primary:hover{background:#5cebf9}
.btn--accent{background:var(--orange);color:#1a0d00}
.btn--accent:hover{background:#ffa257}
.btn--ghost{background:transparent;border-color:var(--line);color:var(--txt)}
.btn--ghost:hover{border-color:var(--cyan-dim)}
.btn--block{width:100%}
.btn--lg{padding:.95rem 1.6rem;font-size:var(--fs-md)}
.btn svg{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:2}

/* --- Badges --------------------------------------------------------- */
.badge{
  display:inline-flex;align-items:center;gap:var(--s-1);
  padding:.2rem .5rem;border-radius:999px;
  font:700 var(--fs-xs)/1.4 var(--font);letter-spacing:.04em;
}
.badge--new{background:rgba(34,227,245,.14);color:var(--cyan)}
.badge--custom{background:rgba(255,138,43,.14);color:var(--orange)}
.badge--stock{background:rgba(47,208,122,.14);color:var(--ok)}
.badge--order{background:rgba(255,197,61,.14);color:var(--warn)}

/* --- Carte produit --------------------------------------------------- */
.grid-products{display:grid;gap:var(--s-4);grid-template-columns:repeat(auto-fill,minmax(min(100%,240px),1fr))}

.product-card{
  display:flex;flex-direction:column;
  background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);
  overflow:hidden;text-decoration:none;color:inherit;
  transition:border-color .18s var(--ease),transform .18s var(--ease);
}
.product-card:hover{border-color:var(--cyan-dim);transform:translateY(-2px);text-decoration:none}
.product-card__media{position:relative;aspect-ratio:4/3;background:var(--bg-2);overflow:hidden}
.product-card__media img{width:100%;height:100%;object-fit:cover;transition:transform .35s var(--ease)}
.product-card:hover .product-card__media img{transform:scale(1.04)}
.product-card__flags{position:absolute;top:var(--s-3);left:var(--s-3);display:flex;gap:var(--s-2);flex-wrap:wrap}
.product-card__body{padding:var(--s-4);display:flex;flex-direction:column;gap:var(--s-2);flex:1}
.product-card__title{font-size:var(--fs-base);font-weight:600;margin:0;line-height:1.35}
.product-card__desc{color:var(--muted);font-size:var(--fs-sm);margin:0;flex:1}
.product-card__foot{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;
  gap:var(--s-2) var(--s-3);margin-top:var(--s-2)}
.product-card__foot .badge{white-space:nowrap}
.price{color:var(--orange);font-weight:800;font-size:var(--fs-md);white-space:nowrap}
.price small{color:var(--muted);font-weight:500;font-size:var(--fs-xs);display:block;line-height:1.2;white-space:nowrap}

/* --- Carte catégorie ------------------------------------------------- */
.grid-categories{display:grid;gap:var(--s-4);grid-template-columns:repeat(auto-fit,minmax(min(100%,220px),1fr))}
.cat-card{
  position:relative;display:flex;flex-direction:column;justify-content:flex-end;
  min-height:150px;padding:var(--s-5);border-radius:var(--radius);
  background:linear-gradient(155deg,var(--panel) 0%,var(--bg-2) 100%);
  border:1px solid var(--line);color:inherit;text-decoration:none;overflow:hidden;
  transition:border-color .18s var(--ease);
}
.cat-card::before{
  content:"";position:absolute;inset:auto -20% -60% auto;width:200px;height:200px;
  background:radial-gradient(circle,rgba(34,227,245,.16),transparent 70%);
}
.cat-card:hover{border-color:var(--cyan-dim);text-decoration:none}
.cat-card h3{margin:0;font-size:var(--fs-md);position:relative}
.cat-card p{margin:var(--s-1) 0 0;color:var(--muted);font-size:var(--fs-sm);position:relative}

/* --- Fil d'Ariane ---------------------------------------------------- */
.breadcrumb{margin-bottom:var(--s-4);font-size:var(--fs-sm);color:var(--muted)}
.breadcrumb ol{list-style:none;padding:0;margin:0;display:flex;flex-wrap:wrap;gap:var(--s-2)}
.breadcrumb li+li::before{content:"›";margin-right:var(--s-2);color:var(--line)}
.breadcrumb a{color:var(--muted)}
.breadcrumb a:hover{color:var(--txt-2)}

/* --- Sélecteurs d'options -------------------------------------------- */
.option{margin:0 0 var(--s-5);padding:0;border:0}   /* remise à zéro du <fieldset> */
.option__label{
  display:flex;align-items:baseline;justify-content:space-between;gap:var(--s-3);
  margin-bottom:var(--s-3);font-size:var(--fs-sm);color:var(--txt-2);font-weight:600;
}
.option__value{color:var(--txt);font-weight:500}
.option__help{color:var(--muted);font-size:var(--fs-xs);margin:var(--s-2) 0 0}

.swatches{display:flex;flex-wrap:wrap;gap:var(--s-2);margin:0;padding:0;border:0}
.swatch{position:relative}
.swatch input{position:absolute;width:1px;height:1px;opacity:0;margin:0;
  /* 1px et non 0 : le champ reste focalisable au clavier et cliquable par
     les outils de test, tout en restant invisible à l'écran. */}
.swatch__btn{
  display:inline-flex;align-items:center;gap:var(--s-2);
  padding:.55rem .85rem;border:1px solid var(--line);border-radius:var(--radius-sm);
  background:var(--panel);color:var(--txt-2);cursor:pointer;
  font:600 var(--fs-sm)/1.2 var(--font);
  transition:border-color .15s var(--ease),color .15s var(--ease),background .15s var(--ease);
}
.swatch__btn:hover{border-color:var(--cyan-dim);color:var(--txt)}
.swatch input:checked + .swatch__btn{border-color:var(--cyan);color:var(--txt);background:var(--panel-2)}
.swatch input:focus-visible + .swatch__btn{box-shadow:var(--ring)}
.swatch input:disabled + .swatch__btn{opacity:.4;cursor:not-allowed;text-decoration:line-through}
.swatch__dot{
  width:18px;height:18px;border-radius:50%;border:1px solid rgba(255,255,255,.22);
  flex:none;box-shadow:inset 0 0 0 2px rgba(0,0,0,.25);
}
.swatch__delta{color:var(--orange);font-weight:700;font-size:var(--fs-xs)}

/* --- Champ de personnalisation ---------------------------------------- */
.field{display:grid;gap:var(--s-2);margin-bottom:var(--s-5)}
.field label{font-size:var(--fs-sm);color:var(--txt-2);font-weight:600}
/*
 * Tous les champs textuels, par exclusion plutôt que par énumération.
 * La liste explicite (text, email, number) laissait password et search
 * au style natif du navigateur : un rectangle blanc au milieu d'une
 * interface sombre, sur la page de connexion et dans chaque filtre.
 * Une exclusion couvre aussi les types qu'on ajoutera plus tard.
 */
.field input:not([type=checkbox]):not([type=radio]):not([type=file]):not([type=range]):not([type=color]),
.field textarea,
.field select,
.checkout-form select{
  width:100%;padding:.7rem .85rem;background:var(--bg-2);color:var(--txt);
  border:1px solid var(--line);border-radius:var(--radius-sm);
  font:var(--fs-base)/1.4 var(--font);
  -webkit-appearance:none;appearance:none;
}
/* appearance:none supprime aussi la flèche native du select : on la
   redessine, sinon plus rien n'indique que la liste se déroule. */
.field select,.checkout-form select{
  padding-right:2.2rem;background-repeat:no-repeat;
  background-position:right .8rem center;background-size:.7rem;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath fill='none' stroke='%237c8798' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' d='M1 1l5 5 5-5'/%3E%3C/svg%3E");
}
/* Safari arrondit les champs de recherche et y colle une croix grise. */
.field input[type=search]::-webkit-search-decoration,
.field input[type=search]::-webkit-search-cancel-button{-webkit-appearance:none}
.field input::placeholder,.field textarea::placeholder{color:var(--muted);opacity:1}
/* Le remplissage automatique de Chrome repeint le fond en blanc : on le
   neutralise par une ombre interne, seul moyen fiable de le contrer. */
/* Contrôles natifs : l'accent vaut pour toute la page, pas seulement
   pour les cases posées dans un .checkbox (grilles d'options, tableaux). */
input[type=checkbox],input[type=radio]{accent-color:var(--cyan);cursor:pointer}

/* Le champ de fichier n'accepte pas appearance:none ; on habille le
   bouton natif, qui est le seul morceau stylable de façon portable. */
input[type=file]{
  width:100%;max-width:100%;color:var(--txt-2);font:var(--fs-sm)/1.4 var(--font);
  padding:.45rem;background:var(--bg-2);border:1px dashed var(--line);
  border-radius:var(--radius-sm);cursor:pointer;
}
input[type=file]::file-selector-button{
  margin-right:var(--s-3);padding:.4rem .8rem;cursor:pointer;
  background:var(--panel-2);color:var(--txt);
  border:1px solid var(--line);border-radius:var(--radius-sm);
  font:600 var(--fs-sm)/1.2 var(--font);
}
input[type=file]::file-selector-button:hover{border-color:var(--cyan);color:var(--cyan)}

.field input:-webkit-autofill,
.field input:-webkit-autofill:hover,
.field input:-webkit-autofill:focus{
  -webkit-text-fill-color:var(--txt);
  -webkit-box-shadow:0 0 0 1000px var(--bg-2) inset;
  caret-color:var(--txt);
}
.field input:focus,.field textarea:focus{outline:none;border-color:var(--cyan);box-shadow:0 0 0 3px rgba(34,227,245,.14)}
.field__meta{display:flex;justify-content:space-between;gap:var(--s-3);font-size:var(--fs-xs);color:var(--muted)}
.field__counter.is-limit{color:var(--warn)}
.field__error{color:var(--ko);font-size:var(--fs-xs)}

/* --- Quantité ---------------------------------------------------------- */
.qty{display:inline-flex;align-items:stretch;border:1px solid var(--line);border-radius:var(--radius-sm);overflow:hidden}
.qty button{
  width:40px;background:var(--panel);border:0;color:var(--txt-2);cursor:pointer;
  font:700 var(--fs-md)/1 var(--font);
}
.qty button:hover{background:var(--panel-2);color:var(--txt)}
.qty input{
  width:56px;text-align:center;background:var(--bg-2);border:0;
  border-inline:1px solid var(--line);color:var(--txt);font:600 var(--fs-base)/1 var(--font);
  -moz-appearance:textfield;
}
.qty input::-webkit-outer-spin-button,.qty input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}

/* --- Panneau panier ----------------------------------------------------- */
.drawer-backdrop{
  position:fixed;inset:0;z-index:60;background:rgba(4,6,10,.6);
  opacity:0;visibility:hidden;transition:opacity .2s var(--ease),visibility .2s;
}
.drawer-backdrop.is-open{opacity:1;visibility:visible}
.drawer{
  position:fixed;top:0;right:0;bottom:0;z-index:61;width:min(420px,100%);
  display:flex;flex-direction:column;
  background:var(--bg-2);border-left:1px solid var(--line);box-shadow:var(--shadow-lg);
  transform:translateX(100%);transition:transform .26s var(--ease);
}
.drawer.is-open{transform:none}
.drawer__head{
  display:flex;align-items:center;justify-content:space-between;gap:var(--s-3);
  padding:var(--s-4);border-bottom:1px solid var(--line);
}
.drawer__head h2{margin:0;font-size:var(--fs-md)}
.drawer__body{flex:1;overflow-y:auto;padding:var(--s-4);display:grid;gap:var(--s-3);align-content:start}
.drawer__foot{padding:var(--s-4);border-top:1px solid var(--line);display:grid;gap:var(--s-3)}
.drawer__total{display:flex;justify-content:space-between;align-items:baseline;font-weight:700}
.drawer__total .price{font-size:var(--fs-lg)}
.drawer__empty{color:var(--muted);text-align:center;padding:var(--s-7) 0}

.line{display:grid;grid-template-columns:64px 1fr auto;gap:var(--s-3);align-items:start}
.line__img{width:64px;height:48px;object-fit:cover;border-radius:var(--radius-sm);background:var(--panel)}
.line__name{font-size:var(--fs-sm);font-weight:600;margin:0 0 2px}
.line__opts{color:var(--muted);font-size:var(--fs-xs);margin:0}
.line__custom{color:var(--orange);font-size:var(--fs-xs);margin:2px 0 0}
.line__price{font-weight:700;font-size:var(--fs-sm);white-space:nowrap}
.line__remove{background:none;border:0;color:var(--muted);cursor:pointer;font-size:var(--fs-xs);padding:0;text-decoration:underline}
.line__remove:hover{color:var(--ko)}

/* --- Notifications ------------------------------------------------------ */
.toasts{position:fixed;right:var(--s-4);bottom:var(--s-4);z-index:70;display:grid;gap:var(--s-2);
  max-width:min(360px,calc(100vw - 2rem));transition:right .26s var(--ease)}
/* Panneau ouvert : les notifications se décalent à sa gauche au lieu de
   recouvrir les boutons « Commander » et « Continuer mes achats ». */
body.has-drawer .toasts{right:calc(min(420px, 100vw) + var(--s-4))}
@media (max-width:520px){body.has-drawer .toasts{right:var(--s-4);bottom:auto;top:calc(var(--header-h) + var(--s-3))}}
.toast{
  padding:var(--s-3) var(--s-4);border-radius:var(--radius-sm);
  background:var(--panel);border:1px solid var(--line);border-left:3px solid var(--cyan);
  box-shadow:var(--shadow);font-size:var(--fs-sm);
  animation:toast-in .22s var(--ease);
}
.toast--error{border-left-color:var(--ko)}
.toast--success{border-left-color:var(--ok)}
@keyframes toast-in{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}

/* --- Messages ------------------------------------------------------------ */
.flash{
  border:1px solid var(--line);border-left:3px solid var(--cyan);background:var(--panel);
  padding:var(--s-3) var(--s-4);border-radius:var(--radius-sm);margin-bottom:var(--s-4);
}
.flash--error{border-left-color:var(--ko)}
.flash--success{border-left-color:var(--ok)}
.errors{color:var(--ko);font-size:var(--fs-sm);margin:0 0 var(--s-4);padding-left:1.1rem}

/* --- Bandeau cookies ------------------------------------------------------ */
.cookie-banner{
  position:fixed;left:var(--s-4);right:var(--s-4);bottom:var(--s-4);z-index:65;
  max-width:640px;margin-inline:auto;padding:var(--s-4);
  background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);
  box-shadow:var(--shadow-lg);display:none;
}
.cookie-banner.is-open{display:block}
.cookie-banner h2{font-size:var(--fs-md);margin:0 0 var(--s-2)}
.cookie-banner p{font-size:var(--fs-sm);color:var(--txt-2);margin-bottom:var(--s-4)}
/* Les deux boutons ont la MÊME largeur et le même poids : refuser ne doit
   pas être plus discret qu'accepter, c'est le point que la CNIL contrôle. */
.cookie-banner__actions{display:flex;flex-wrap:wrap;gap:var(--s-3);align-items:center}
.cookie-banner__actions .btn{flex:1 1 12rem;justify-content:center;min-height:44px}
.cookie-banner__link{font-size:var(--fs-sm);color:var(--muted);flex:0 0 auto}
.cookie-banner__link:hover{color:var(--cyan)}

/* ------------------------------------------------------------------ */
/* 5. PAGES                                                            */
/* ------------------------------------------------------------------ */

/* --- Héros ---------------------------------------------------------- */
/*
 * Trois plans superposés : les nappes colorées (.hero__aura), la trame
 * technique (.hero__grid), puis le contenu. Les deux décors sont des
 * éléments réels et non des pseudo-éléments : ils s'animent séparément,
 * à des vitesses différentes, ce qui crée la profondeur.
 */
.hero{
  position:relative;overflow:hidden;
  border-bottom:1px solid var(--line);
  background:var(--bg);
  isolation:isolate;
}
.hero__aura{
  position:absolute;inset:-25% -10%;z-index:-2;
  background:
    radial-gradient(38% 46% at 18% 22%,rgba(34,227,245,.20),transparent 68%),
    radial-gradient(34% 42% at 84% 16%,rgba(255,138,43,.16),transparent 66%),
    radial-gradient(46% 40% at 62% 88%,rgba(34,227,245,.10),transparent 70%);
  filter:blur(6px);
  animation:aura 22s var(--ease) infinite alternate;
}
@keyframes aura{
  0%  {transform:translate3d(0,0,0)      scale(1)}
  50% {transform:translate3d(-2.5%,2%,0) scale(1.07)}
  100%{transform:translate3d(2%,-1.5%,0) scale(1.03)}
}
/* La trame descend lentement : la valeur de translation vaut exactement
   une maille, la boucle est donc invisible. */
.hero__grid{
  position:absolute;inset:-60px 0 0;z-index:-1;opacity:.55;
  background-image:linear-gradient(var(--line-soft) 1px,transparent 1px),
                   linear-gradient(90deg,var(--line-soft) 1px,transparent 1px);
  background-size:44px 44px;
  mask-image:linear-gradient(to bottom,#000 0%,rgba(0,0,0,.35) 60%,transparent 92%);
  animation:grid-drift 9s linear infinite;
}
@keyframes grid-drift{from{transform:translateY(0)}to{transform:translateY(44px)}}

/* Un liseré fluo file le long du bord bas : la « ligne d'extrusion ». */
.hero::after{
  content:"";position:absolute;left:0;right:0;bottom:-1px;height:1px;
  background:linear-gradient(90deg,transparent,var(--cyan),var(--orange),transparent);
  background-size:220% 100%;
  animation:seam 7s linear infinite;
}
@keyframes seam{from{background-position:-110% 0}to{background-position:110% 0}}

.hero__inner{
  position:relative;display:grid;gap:var(--s-6);
  padding-block:var(--s-8);
}
@media (min-width:900px){
  .hero__inner{grid-template-columns:1.05fr .95fr;align-items:center;padding-block:var(--s-9)}
}

/* Entrée en cascade du bloc de texte. Chaque enfant part avec un retard
   croissant ; `backwards` maintient l'état initial pendant le délai,
   sans quoi tout apparaît d'un coup avant de replonger. */
.hero__text > *{animation:rise .8s var(--ease) backwards}
.hero__text > :nth-child(1){animation-delay:.05s}
.hero__text > :nth-child(2){animation-delay:.14s}
.hero__text > :nth-child(3){animation-delay:.23s}
.hero__text > :nth-child(4){animation-delay:.32s}
.hero__text > :nth-child(5){animation-delay:.41s}
@keyframes rise{from{opacity:0;transform:translateY(18px)}to{opacity:1;transform:none}}

.hero__eyebrow{
  display:inline-flex;align-items:center;gap:var(--s-2);
  color:var(--cyan);font:700 var(--fs-xs)/1 var(--mono);
  letter-spacing:.16em;text-transform:uppercase;margin-bottom:var(--s-4);
}
.hero__eyebrow::before{
  content:"";width:26px;height:1px;background:var(--cyan);
  box-shadow:0 0 8px var(--cyan);
}
.hero h1{font-size:var(--fs-3xl);margin-bottom:var(--s-4);letter-spacing:-.02em}
/* Le mot mis en avant est un dégradé animé découpé par le texte. Le
   `color` reste défini : si `background-clip:text` n'est pas géré, on
   obtient du cyan plein plutôt qu'un mot invisible. */
.hero h1 em{
  font-style:normal;color:var(--cyan);
  background:linear-gradient(100deg,var(--cyan),#8df3ff 32%,var(--orange) 66%,var(--cyan));
  background-size:260% 100%;
  -webkit-background-clip:text;background-clip:text;
  -webkit-text-fill-color:transparent;
  animation:sheen 9s linear infinite;
}
@supports not ((background-clip:text) or (-webkit-background-clip:text)){
  .hero h1 em{background:none;-webkit-text-fill-color:currentColor}
}
@keyframes sheen{from{background-position:0 0}to{background-position:260% 0}}

.hero p{color:var(--txt-2);font-size:var(--fs-md);max-width:52ch}
.hero__cta{display:flex;flex-wrap:wrap;gap:var(--s-3);margin-top:var(--s-5)}
.hero__stats{
  display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s-4);
  margin-top:var(--s-7);padding-top:var(--s-5);border-top:1px solid var(--line);
}
.hero__stat b{
  display:block;font:800 var(--fs-lg)/1.1 var(--mono);color:var(--txt);
  letter-spacing:-.01em;
}
.hero__stat span{color:var(--muted);font-size:var(--fs-xs);line-height:1.35;display:block;margin-top:var(--s-1)}

/* --- Scène 3D --------------------------------------------------------- */
/*
 * Le conteneur garde son ratio quoi qu'il arrive : le canevas WebGL est
 * en position absolue par-dessus le visuel de repli, donc rien ne bouge
 * quand le moteur démarre (ou renonce). `aspect-ratio` fixe la hauteur
 * avant même que l'image ne soit chargée : pas de saut de mise en page.
 */
.hero__visual{
  position:relative;aspect-ratio:4/3;
  border:1px solid var(--line);border-radius:var(--radius-lg);overflow:hidden;
  background:radial-gradient(120% 90% at 50% 105%,rgba(34,227,245,.10),var(--panel) 62%);
  box-shadow:var(--shadow-lg);
}
.hero__visual::after{ /* reflet de verre en haut à gauche */
  content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(150deg,rgba(255,255,255,.055),transparent 42%);
}
.hero__fallback{width:100%;height:100%;object-fit:cover;display:block}
.hero3d__canvas{position:absolute;inset:0;width:100%;height:100%;display:block}
/* Le moteur a démarré : on efface le repli en fondu plutôt que d'un coup. */
.hero__visual.is-3d .hero__fallback{opacity:0;transition:opacity .5s var(--ease)}

/* --- Sections ------------------------------------------------------- */
.section{padding-block:var(--s-7)}
.section__head{
  display:flex;align-items:flex-end;justify-content:space-between;gap:var(--s-4);
  margin-bottom:var(--s-5);flex-wrap:wrap;
}
.section__head h2{margin:0}
.section__head p{margin:var(--s-1) 0 0;color:var(--muted);font-size:var(--fs-sm)}
.section--alt{background:var(--bg-2);border-block:1px solid var(--line)}

/* --- Étapes de fabrication ------------------------------------------- */
.steps{display:grid;gap:var(--s-4);grid-template-columns:repeat(auto-fit,minmax(min(100%,220px),1fr));counter-reset:step}
.step{
  position:relative;padding:var(--s-5);background:var(--panel);
  border:1px solid var(--line);border-radius:var(--radius);
}
.step::before{
  counter-increment:step;content:counter(step,decimal-leading-zero);
  display:block;font:800 var(--fs-lg)/1 var(--mono);color:var(--orange);margin-bottom:var(--s-3);
}
.step h3{font-size:var(--fs-base);margin-bottom:var(--s-2)}
.step p{margin:0;color:var(--muted);font-size:var(--fs-sm)}

/* --- Réassurance ------------------------------------------------------ */
.trust{display:grid;gap:var(--s-4);grid-template-columns:repeat(auto-fit,minmax(min(100%,200px),1fr))}
.trust > div{display:flex;gap:var(--s-3);align-items:flex-start}
.trust svg{width:22px;height:22px;flex:none;stroke:var(--cyan);fill:none;stroke-width:1.7;margin-top:2px}
.trust b{display:block;font-size:var(--fs-sm)}
.trust span{color:var(--muted);font-size:var(--fs-xs)}

/* --- Fiche produit ----------------------------------------------------- */
.product{display:grid;gap:var(--s-6)}
@media (min-width:900px){.product{grid-template-columns:minmax(0,1.05fr) minmax(0,.95fr);gap:var(--s-7);align-items:start}}

.gallery{display:grid;gap:var(--s-3);position:sticky;top:calc(var(--header-h) + var(--s-4))}
@media (max-width:899px){.gallery{position:static}}
.gallery__main{
  aspect-ratio:4/3;background:var(--panel);border:1px solid var(--line);
  border-radius:var(--radius);overflow:hidden;
}
.gallery__main img{width:100%;height:100%;object-fit:cover}
.gallery__thumbs{display:flex;gap:var(--s-2);flex-wrap:wrap}
.gallery__thumb{
  width:72px;aspect-ratio:4/3;padding:0;border:1px solid var(--line);border-radius:var(--radius-sm);
  overflow:hidden;background:var(--panel);cursor:pointer;
}
.gallery__thumb img{width:100%;height:100%;object-fit:cover}
.gallery__thumb[aria-current="true"]{border-color:var(--cyan)}

.product__head{margin-bottom:var(--s-5)}
.product__flags{display:flex;gap:var(--s-2);flex-wrap:wrap;margin-bottom:var(--s-3)}
.product__price{display:flex;align-items:baseline;gap:var(--s-3);margin:var(--s-4) 0}
.product__price .price{font-size:var(--fs-2xl);line-height:1}
.product__price del{color:var(--muted);font-size:var(--fs-md)}
.product__ht{color:var(--muted);font-size:var(--fs-xs)}
.product__lede{color:var(--txt-2)}

.availability{display:flex;align-items:center;gap:var(--s-2);font-size:var(--fs-sm);margin-bottom:var(--s-5)}
.availability__dot{width:8px;height:8px;border-radius:50%;background:var(--ok);flex:none}
.availability--order .availability__dot{background:var(--warn)}
.availability--out .availability__dot{background:var(--ko)}

.buy{
  padding:var(--s-5);background:var(--panel);border:1px solid var(--line);
  border-radius:var(--radius);margin-bottom:var(--s-5);
}
.buy__row{display:flex;flex-wrap:wrap;gap:var(--s-3);align-items:center}
.buy__row .btn{flex:1;min-width:200px}

.specs{width:100%;border-collapse:collapse;font-size:var(--fs-sm)}
.specs th,.specs td{padding:var(--s-3) 0;border-bottom:1px solid var(--line-soft);text-align:left;vertical-align:top}
.specs th{color:var(--muted);font-weight:500;width:45%}

/* --- Bandeau de débogage (dev) ------------------------------------------ */
.debug{margin-top:var(--s-7);border:1px dashed var(--line);border-radius:var(--radius);background:var(--bg-2)}
.debug summary{cursor:pointer;padding:var(--s-3) var(--s-4);color:var(--orange);font:600 var(--fs-xs)/1 var(--mono);letter-spacing:.12em;text-transform:uppercase}
.debug table{width:100%;border-collapse:collapse;font:var(--fs-sm)/1.5 var(--mono)}
.debug td{padding:var(--s-2) var(--s-4);border-top:1px solid var(--line);vertical-align:top;word-break:break-all}
.debug td:first-child{color:var(--muted);width:230px}

/* ------------------------------------------------------------------ */
/* 6. UTILITAIRES                                                      */
/* ------------------------------------------------------------------ */
.lede{color:var(--txt-2);font-size:var(--fs-md);max-width:62ch}
.muted{color:var(--muted)}
.muted-sm{color:var(--muted);font-size:var(--fs-sm)}
.mono{font-family:var(--mono);font-size:var(--fs-sm)}
.trace{overflow:auto;font-size:var(--fs-xs);color:var(--muted);white-space:pre-wrap}
.card{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);padding:var(--s-5)}
.card--narrow{max-width:420px}
.card--error{border-color:var(--ko)}
.card--error h3{color:var(--ko)}
.stack{display:grid;gap:var(--s-4)}
.center{text-align:center}
form.stack{max-width:420px}
form.stack button{justify-self:start}

/* ------------------------------------------------------------------ */
/* 7. IMPRESSION                                                       */
/* ------------------------------------------------------------------ */
@media print{
  .header,.footer,.drawer,.drawer-backdrop,.cookie-banner,.toasts,.debug,.buy{display:none!important}
  body{background:#fff;color:#000}
  a{color:#000;text-decoration:underline}
}

/* ------------------------------------------------------------------ */
/* 8. PANIER ET TUNNEL DE COMMANDE                                     */
/* ------------------------------------------------------------------ */
.cart-layout,.checkout-layout{display:grid;gap:var(--s-5);align-items:start}
@media (min-width:900px){
  .cart-layout,.checkout-layout{grid-template-columns:minmax(0,1.6fr) minmax(0,.9fr);gap:var(--s-6)}
  .cart-aside,.checkout-aside{position:sticky;top:calc(var(--header-h) + var(--s-4))}
}

.cart-lines{display:grid;gap:var(--s-3)}
.cart-line{
  display:grid;grid-template-columns:96px 1fr;gap:var(--s-4);align-items:start;
  padding:var(--s-4);background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);
}
@media (min-width:640px){.cart-line{grid-template-columns:96px 1fr auto}}
.cart-line__img{width:96px;height:72px;object-fit:cover;border-radius:var(--radius-sm);background:var(--bg-2)}
.cart-line__name{font-size:var(--fs-base);margin:0 0 var(--s-1)}
.cart-line__custom{color:var(--orange);font-size:var(--fs-sm);margin:0}
.cart-line__actions{display:flex;flex-wrap:wrap;gap:var(--s-2);align-items:center;grid-column:1/-1}
@media (min-width:640px){.cart-line__actions{grid-column:auto;justify-content:flex-end}}
.cart-line__price{font-weight:800;color:var(--orange);white-space:nowrap;margin-left:auto}

.inline-field{display:flex;gap:var(--s-2)}
.inline-field input{flex:1;min-width:0}

.totals{margin:var(--s-4) 0;display:grid;gap:var(--s-2)}
.totals > div{display:flex;justify-content:space-between;align-items:baseline;gap:var(--s-3)}
.totals dt{color:var(--muted);font-size:var(--fs-sm);margin:0}
.totals dt .muted-sm{display:block}
.totals dd{margin:0;font-size:var(--fs-sm);white-space:nowrap}
.totals__discount dd{color:var(--ok)}
.totals .free{color:var(--ok);font-weight:700}
.totals__grand{padding-top:var(--s-3);border-top:1px solid var(--line);align-items:baseline}
.totals__grand dt{color:var(--txt);font-weight:700;font-size:var(--fs-md)}
.totals__grand dd{font-size:var(--fs-lg)}

/* --- Fil d'étapes ---------------------------------------------------- */
.steps-nav{
  display:flex;flex-wrap:wrap;gap:var(--s-3);list-style:none;padding:0;
  margin:0 0 var(--s-6);font-size:var(--fs-sm);
}
.steps-nav li{display:flex;align-items:center;gap:var(--s-2);color:var(--muted)}
.steps-nav__num{
  display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;
  border-radius:50%;border:1px solid var(--line);font:700 var(--fs-xs)/1 var(--mono);flex:none;
}
.steps-nav li.is-current{color:var(--txt);font-weight:600}
.steps-nav li.is-current .steps-nav__num{border-color:var(--cyan);color:var(--cyan)}
.steps-nav li.is-done{color:var(--txt-2)}
.steps-nav li.is-done .steps-nav__num{background:var(--ok);border-color:var(--ok);color:#04120a}

/* --- Formulaires du tunnel -------------------------------------------- */
.checkout-form fieldset{
  border:1px solid var(--line);border-radius:var(--radius);
  padding:var(--s-5);margin:0 0 var(--s-5);background:var(--panel);
}
.checkout-form legend{padding:0 var(--s-2);font-weight:700;font-size:var(--fs-sm);color:var(--orange)}
.grid-2{display:grid;gap:var(--s-3)}
@media (min-width:560px){.grid-2{grid-template-columns:1fr 1fr}}
.checkbox{display:flex;gap:var(--s-3);align-items:flex-start;font-size:var(--fs-sm);cursor:pointer}
.checkbox input{margin-top:3px;flex:none;width:18px;height:18px;accent-color:var(--cyan)}
.checkout-actions{display:flex;flex-wrap:wrap;gap:var(--s-3);justify-content:space-between;align-items:center}

/* --- Transporteurs et paiement ----------------------------------------- */
.carriers{display:grid;gap:var(--s-3);margin-bottom:var(--s-5)}
.carrier{
  display:flex;gap:var(--s-3);align-items:flex-start;cursor:pointer;
  padding:var(--s-4);background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);
  transition:border-color .15s var(--ease);
}
.carrier:hover{border-color:var(--cyan-dim)}
.carrier:has(input:checked){border-color:var(--cyan);background:var(--panel-2)}
.carrier:has(input:focus-visible){box-shadow:var(--ring)}
.carrier.is-disabled{opacity:.5;cursor:not-allowed}
.carrier input{margin-top:3px;flex:none;width:18px;height:18px;accent-color:var(--cyan)}
.carrier__body{display:grid;gap:var(--s-1);flex:1}
.carrier__head{display:flex;justify-content:space-between;gap:var(--s-3);align-items:baseline;flex-wrap:wrap}

.mini-lines{list-style:none;padding:0;margin:0 0 var(--s-4);display:grid;gap:var(--s-2)}
.mini-lines li{display:flex;justify-content:space-between;gap:var(--s-3);font-size:var(--fs-sm)}
.mini-lines .muted-sm,.mini-lines .cart-line__custom{display:block}

/* --- Confirmation -------------------------------------------------------- */
.confirmation{max-width:680px;margin-inline:auto;text-align:center}
.confirmation .totals,.confirmation .mini-lines{text-align:left}
.confirmation__icon{
  width:56px;height:56px;margin:0 auto var(--s-4);display:block;
  fill:none;stroke:var(--ok);stroke-width:2.5;
  padding:var(--s-3);border:2px solid var(--ok);border-radius:50%;
}
.confirmation h2{margin-top:var(--s-6)}

/* =====================================================================
   Documents longs (pages légales et CMS)
   Colonne étroite, ancrages compensant l'en-tête collant, sommaire
   repliable sur mobile. La mesure vise ~70 caractères par ligne : au-delà,
   l'œil perd la ligne suivante sur un texte de quinze articles.
   ===================================================================== */
.doc{max-width:74ch;margin-inline:auto;padding-block:var(--s-6)}
.doc__head h1{margin-bottom:var(--s-2)}
.doc__meta{display:flex;flex-wrap:wrap;gap:var(--s-4);color:var(--muted);font-size:var(--fs-sm);margin:0 0 var(--s-4)}
.doc__head .lede{font-size:var(--fs-md);color:var(--txt-2);line-height:1.7;margin:0}
.doc__body{line-height:1.75}
.doc__body > * + *{margin-top:var(--s-4)}
.doc__body h2{
  margin-top:var(--s-7);padding-top:var(--s-4);font-size:var(--fs-lg);
  border-top:1px solid var(--line-soft);scroll-margin-top:calc(var(--header-h) + var(--s-4));
}
.doc__body h3{margin-top:var(--s-5);font-size:var(--fs-md);color:var(--txt)}
.doc__body ul,.doc__body ol{padding-left:1.25rem;display:grid;gap:var(--s-2)}
.doc__body li{line-height:1.7}
.doc__body a{color:var(--cyan);text-decoration:underline;text-underline-offset:2px}
.doc__body table{width:100%;border-collapse:collapse;font-size:var(--fs-sm);display:block;overflow-x:auto}
.doc__body th,.doc__body td{padding:var(--s-3);border:1px solid var(--line);text-align:left;vertical-align:top}
.doc__body th{background:var(--panel-2);font-size:var(--fs-xs);text-transform:uppercase;letter-spacing:.08em;color:var(--muted)}
.doc__body .lede{font-size:var(--fs-md);color:var(--txt-2)}
.doc__foot{margin-top:var(--s-7);padding-top:var(--s-4);border-top:1px solid var(--line)}

/* Encadré d'avertissement : exclusion du droit de rétractation, etc. */
.doc__body .callout{
  padding:var(--s-4);border-left:3px solid var(--orange);
  background:rgba(255,138,43,.08);border-radius:0 var(--radius-sm) var(--radius-sm) 0;
}
/* Formulaire type de rétractation : reproduit tel quel, donc encadré */
.doc__body .form-model{
  padding:var(--s-5);border:1px dashed var(--line);border-radius:var(--radius);background:var(--panel);
}
.doc__body .form-model ul{list-style:none;padding-left:0}

/* Valeur de réglage non renseignée : visible, y compris à l'impression */
.doc__body .todo{
  background:rgba(255,90,90,.16);color:var(--ko);
  padding:0 .35em;border-radius:3px;font-weight:600;white-space:nowrap;
}

/* Sommaire */
.doc__toc{
  margin:var(--s-5) 0 var(--s-6);padding:var(--s-4) var(--s-5);
  background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);
}
.doc__toc h2{margin:0 0 var(--s-3);font-size:var(--fs-xs);text-transform:uppercase;letter-spacing:.12em;color:var(--muted)}
.doc__toc ol{margin:0;padding-left:1.1rem;display:grid;gap:var(--s-2);font-size:var(--fs-sm)}
.doc__toc a{color:var(--txt-2)}
.doc__toc a:hover{color:var(--cyan)}

@media print{
  .doc{max-width:none}
  .doc__toc,.header,.footer,.cookie-banner,.cart-drawer{display:none!important}
  .doc__body h2{break-after:avoid}
  .doc__body .todo{border:1px solid #000}
}

/* ==================================================================== */
/* 8. EFFETS DE SURFACE                                                  */
/*                                                                       */
/* Tout ce qui suit est décoratif : la page reste complète, lisible et   */
/* utilisable si rien de cette section ne s'applique. C'est la règle     */
/* qui a dicté chaque choix ci-dessous — en particulier les révélations, */
/* qui ne masquent quoi que ce soit que si le script a confirmé qu'il    */
/* saura les démasquer.                                                  */
/* ==================================================================== */

/* --- Révélations au défilement ----------------------------------------- */
/*
 * `.js-reveal` est posée sur <html> par app.js, et seulement quand un
 * IntersectionObserver a été créé pour redonner la classe `.is-in`.
 * Sans JavaScript, sans IntersectionObserver ou si le script casse, ce
 * sélecteur ne concorde jamais et le contenu reste visible. Cacher du
 * contenu depuis une feuille de style sans cette garantie est le moyen
 * le plus sûr de livrer une page blanche.
 */
.js-reveal [data-reveal],
.js-reveal [data-reveal-group] > *{
  opacity:0;transform:translateY(22px);
  transition:opacity .6s var(--ease),transform .6s var(--ease);
  transition-delay:var(--reveal-delay,0ms);
  will-change:opacity,transform;
}
.js-reveal [data-reveal].is-in,
.js-reveal [data-reveal-group] > .is-in{opacity:1;transform:none;will-change:auto}

@media (prefers-reduced-motion:reduce){
  .js-reveal [data-reveal],
  .js-reveal [data-reveal-group] > *{opacity:1!important;transform:none!important}
  .hero__aura,.hero__grid,.hero::after,.hero h1 em,.hero__text > *{animation:none!important}
}

/* --- Lueur suivant le curseur ------------------------------------------ */
/*
 * --mx/--my sont écrites par app.js ; leurs valeurs de repli (50 %)
 * placent la lueur au centre, donc une carte non survolée — ou une page
 * sans JavaScript — reste correcte.
 */
[data-glow]{position:relative;isolation:isolate}
[data-glow]::after{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  border-radius:inherit;opacity:0;transition:opacity .3s var(--ease);
  background:radial-gradient(220px circle at var(--mx,50%) var(--my,50%),
             rgba(34,227,245,.16),transparent 72%);
}
@media (hover:hover){
  [data-glow]:hover::after{opacity:1}
}

/* --- Cartes : relief et bord fluo --------------------------------------- */
.product-card,.cat-card,.step{
  transition:border-color .22s var(--ease),transform .22s var(--ease),
             box-shadow .22s var(--ease),background-color .22s var(--ease);
}
@media (hover:hover){
  .product-card:hover,.cat-card:hover{
    transform:translateY(-4px);
    border-color:var(--cyan-dim);
    box-shadow:0 18px 40px -22px rgba(34,227,245,.55),var(--shadow);
  }
  .step:hover{border-color:var(--cyan-dim);background:var(--panel-2)}
}
.product-card__media img{transition:transform .5s var(--ease)}
@media (hover:hover){.product-card:hover .product-card__media img{transform:scale(1.06)}}

/* La carte catégorie gagne un halo qui grandit et une flèche qui sort. */
.cat-card::before{
  transition:transform .5s var(--ease),opacity .3s var(--ease);
  opacity:.85;
}
@media (hover:hover){.cat-card:hover::before{transform:scale(1.5);opacity:1}}
.cat-card h3{display:flex;align-items:center;gap:.5ch}
.cat-card h3::after{
  content:"→";color:var(--cyan);font-weight:400;
  opacity:0;transform:translateX(-6px);
  transition:opacity .22s var(--ease),transform .22s var(--ease);
}
@media (hover:hover){.cat-card:hover h3::after{opacity:1;transform:none}}

/* --- Boutons : reflet balayant et halo ----------------------------------- */
.btn{position:relative;overflow:hidden;isolation:isolate;
  transition:background-color .18s var(--ease),border-color .18s var(--ease),
             box-shadow .18s var(--ease),transform .1s var(--ease)}
.btn::before{
  content:"";position:absolute;inset:0;z-index:-1;
  background:linear-gradient(105deg,transparent 35%,rgba(255,255,255,.42) 50%,transparent 65%);
  transform:translateX(-120%);
}
@media (hover:hover){
  .btn:hover::before{transition:transform .6s var(--ease);transform:translateX(120%)}
  .btn--primary:hover{box-shadow:0 8px 26px -10px rgba(34,227,245,.85)}
  .btn--accent:hover{box-shadow:0 8px 26px -10px rgba(255,138,43,.85)}
  .btn--ghost:hover{border-color:var(--cyan);color:var(--cyan)}
}
@media (prefers-reduced-motion:reduce){.btn::before{display:none}}

/* --- Titres de section ---------------------------------------------------- */
/* Un trait fluo court sous le titre : il ancre la section sans ajouter
   de bloc, et se dessine à l'arrivée du titre dans l'écran. */
.section__head h2{position:relative;padding-bottom:var(--s-3)}
.section__head h2::after{
  content:"";position:absolute;left:0;bottom:0;height:2px;width:46px;border-radius:2px;
  background:linear-gradient(90deg,var(--cyan),var(--orange));
  transform-origin:left;transform:scaleX(0);
  transition:transform .6s .15s var(--ease);
}
.section__head.is-in h2::after,
html:not(.js-reveal) .section__head h2::after{transform:scaleX(1)}

.section{padding-block:var(--s-8)}
/* La variante sombre reçoit une nappe très diffuse : la rupture entre
   deux sections cesse d'être une simple ligne. */
.section--alt{position:relative;background:var(--bg-2);border-block:1px solid var(--line);overflow:hidden}
.section--alt::before{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:radial-gradient(60% 100% at 50% 0%,rgba(34,227,245,.07),transparent 70%);
}
.section--alt > *{position:relative}

/* --- Étapes : le fil qui les relie ----------------------------------------- */
@media (min-width:900px){
  .steps{position:relative}
  .steps::before{
    content:"";position:absolute;left:0;right:0;top:3.15rem;height:1px;
    background:linear-gradient(90deg,transparent,var(--line),var(--line),transparent);
  }
  .steps .step{background:var(--panel)}
}
.step::before{
  text-shadow:0 0 18px rgba(255,138,43,.45);
}

/* --- Réassurance : quatre vignettes plutôt qu'une ligne de texte ------------ */
.trust > div{
  padding:var(--s-4);border:1px solid var(--line);border-radius:var(--radius);
  background:var(--panel);transition:border-color .2s var(--ease)}
@media (hover:hover){.trust > div:hover{border-color:var(--cyan-dim)}}
.trust svg{
  width:26px;height:26px;padding:0;
  filter:drop-shadow(0 0 6px rgba(34,227,245,.5));
}

/* --- En-tête compacte au défilement ----------------------------------------- */
.header{transition:background-color .25s var(--ease),box-shadow .25s var(--ease),border-color .25s var(--ease)}
.header.is-stuck{
  background:rgba(11,13,18,.94);
  border-bottom-color:var(--line);
  box-shadow:0 10px 30px -18px rgba(0,0,0,.9);
}
/* Jauge de progression de lecture, dessinée sur la bordure basse. */
.header::after{
  content:"";position:absolute;left:0;bottom:-1px;height:2px;width:100%;
  transform:scaleX(0);transform-origin:left;
  background:linear-gradient(90deg,var(--cyan),var(--orange));
  animation:read-progress linear;
  animation-timeline:scroll(root block);
}
@supports not (animation-timeline:scroll(root block)){
  .header::after{display:none}
}
@keyframes read-progress{from{transform:scaleX(0)}to{transform:scaleX(1)}}

/* ==================================================================== */
/* 9. PAGE ATELIER                                                       */
/* ==================================================================== */

/* Héros de page intérieure : même décor, moins haut — il annonce, il ne
   vend pas une deuxième fois. */
.hero--page .hero__inner{padding-block:var(--s-7)}
@media (min-width:900px){.hero--page .hero__inner{padding-block:var(--s-8)}}
.hero--page h1{font-size:var(--fs-2xl)}

/* --- Deux colonnes : texte + panneau ---------------------------------- */
.split{display:grid;gap:var(--s-6);align-items:start}
@media (min-width:900px){
  .split{grid-template-columns:minmax(0,1.1fr) minmax(0,.9fr);gap:var(--s-7)}
  /* Le formulaire prend un peu plus de place que le texte qui l'annonce :
     c'est lui l'objet de la section. */
  .split--form{grid-template-columns:minmax(0,.95fr) minmax(0,1.05fr)}
}
.prose p{color:var(--txt-2);margin:0 0 var(--s-4);max-width:62ch;line-height:1.7}
.prose p:last-child{margin-bottom:0}

/* --- Fiche technique --------------------------------------------------- */
.spec-list{
  margin:0;display:grid;gap:0;
  border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;
  background:var(--panel);
}
.spec{
  display:grid;gap:var(--s-1);padding:var(--s-4);
  border-bottom:1px solid var(--line-soft);
  transition:background-color .2s var(--ease);
}
.spec:last-child{border-bottom:0}
.spec:hover{background:var(--panel-2)}
@media (min-width:520px){
  .spec{grid-template-columns:minmax(0,10rem) minmax(0,1fr);gap:var(--s-4);align-items:baseline}
}
.spec dt{
  color:var(--cyan);font:700 var(--fs-xs)/1.4 var(--mono);
  letter-spacing:.08em;text-transform:uppercase;
}
.spec dd{margin:0;color:var(--txt);font-size:var(--fs-sm);line-height:1.5}

/* --- Déroulé numéroté ---------------------------------------------------- */
/* Le trait vertical relie les étapes : la liste se lit comme un parcours
   et non comme quatre affirmations sans lien. */
.flow{list-style:none;margin:var(--s-5) 0;padding:0 0 0 var(--s-6);counter-reset:flow;position:relative}
.flow::before{
  content:"";position:absolute;left:9px;top:.6rem;bottom:.6rem;width:1px;
  background:linear-gradient(var(--cyan),var(--orange));opacity:.35;
}
.flow li{position:relative;margin-bottom:var(--s-4)}
.flow li:last-child{margin-bottom:0}
.flow li::before{
  counter-increment:flow;content:counter(flow);
  position:absolute;left:calc(var(--s-6) * -1);top:0;
  width:19px;height:19px;border-radius:50%;
  display:grid;place-items:center;
  background:var(--bg);border:1px solid var(--cyan);color:var(--cyan);
  font:700 10px/1 var(--mono);
}
.flow b{display:block;font-size:var(--fs-base);margin-bottom:2px}
.flow span{color:var(--muted);font-size:var(--fs-sm);line-height:1.55}

/* --- Formulaire de devis --------------------------------------------------- */
.quote-form{display:grid;gap:var(--s-3)}
.quote-form .field{margin:0}
.quote-form__note{text-align:center;margin:0}

/*
 * Pot de miel.
 *
 * PAS `display:none` ni `hidden` : les robots les plus courants sautent
 * les champs invisibles au sens CSS, et le piège ne prend rien. On le
 * sort du cadre visible sans le retirer du rendu. `aria-hidden` et
 * `tabindex="-1"` (posés dans le gabarit) l'écartent des lecteurs
 * d'écran et de la navigation au clavier.
 */
.hp{
  position:absolute!important;left:-9999px;top:auto;
  width:1px;height:1px;overflow:hidden;
}

/* --- Écologie ---------------------------------------------------------------- */
.eco-grid{display:grid;gap:var(--s-4);grid-template-columns:repeat(auto-fit,minmax(min(100%,230px),1fr))}
.eco-card{
  padding:var(--s-5);border:1px solid var(--line);border-radius:var(--radius);
  background:linear-gradient(160deg,var(--panel),var(--bg-2));
  transition:border-color .22s var(--ease),transform .22s var(--ease);
}
@media (hover:hover){.eco-card:hover{border-color:var(--cyan-dim);transform:translateY(-3px)}}
.eco-card svg{
  width:26px;height:26px;fill:none;stroke:var(--cyan);stroke-width:1.6;
  margin-bottom:var(--s-3);filter:drop-shadow(0 0 7px rgba(34,227,245,.45));
}
.eco-card h3{margin:0 0 var(--s-2);font-size:var(--fs-base)}
.eco-card p{margin:0;color:var(--muted);font-size:var(--fs-sm);line-height:1.6}

/* Le paragraphe qui reconnaît les limites du procédé. Il est mis en
   avant, pas relégué en petit : c'est ce qui rend le reste crédible. */
.honest{
  margin:var(--s-6) 0 0;padding:var(--s-5);
  border-left:3px solid var(--orange);border-radius:0 var(--radius) var(--radius) 0;
  background:rgba(255,138,43,.06);
  color:var(--txt-2);font-size:var(--fs-sm);line-height:1.7;max-width:78ch;
}

/* ==================================================================== */
/* 10. VISIONNEUSE 3D                                                    */
/* ==================================================================== */

/* --- Fiche produit ----------------------------------------------------- */
/*
 * Le conteneur occupe exactement la place de la photo et garde son
 * ratio : basculer de l'une à l'autre ne décale rien sur la page. Le
 * canevas est en position absolue par-dessus, comme pour le héros — son
 * apparition, ou son retrait quand WebGL renonce, ne bouge rien.
 */
.m3d{
  position:relative;aspect-ratio:4/3;width:100%;
  border-radius:var(--radius);overflow:hidden;
  background:radial-gradient(120% 90% at 50% 108%,rgba(34,227,245,.10),var(--panel) 62%);
  cursor:grab;touch-action:none;   /* le glisser fait tourner, il ne fait pas défiler */
}
.m3d.is-grabbing{cursor:grabbing}
.m3d:focus-visible{box-shadow:var(--ring)}
.m3d__canvas{position:absolute;inset:0;width:100%;height:100%;display:block}

/* Trame de plateau, en CSS : elle donne un sol à la pièce sans coûter
   un seul triangle au maillage. */
.m3d::before{
  content:"";position:absolute;inset:0;pointer-events:none;
  background-image:linear-gradient(var(--line-soft) 1px,transparent 1px),
                   linear-gradient(90deg,var(--line-soft) 1px,transparent 1px);
  background-size:38px 38px;opacity:.35;
  mask-image:radial-gradient(70% 70% at 50% 60%,#000,transparent 78%);
}

.m3d__hint{
  position:absolute;left:50%;bottom:var(--s-3);transform:translateX(-50%);
  margin:0;padding:.35rem .8rem;border-radius:999px;
  background:rgba(11,13,18,.72);backdrop-filter:blur(6px);
  color:var(--txt-2);font-size:var(--fs-xs);white-space:nowrap;
  pointer-events:none;opacity:0;transition:opacity .3s var(--ease);
}
/* L'indication n'apparaît qu'une fois le modèle chargé : l'afficher
   au-dessus d'un cadre vide inviterait à faire tourner du néant. */
.m3d.is-3d .m3d__hint{opacity:1}
@media (hover:hover){.m3d.is-3d:hover .m3d__hint,.m3d.is-grabbing .m3d__hint{opacity:0}}

/* Attente du maillage. */
.m3d__spinner{position:absolute;inset:0;margin:0;display:none}
.m3d.is-loading .m3d__spinner{display:block}
.m3d.is-loading .m3d__spinner::after{
  content:"";position:absolute;top:50%;left:50%;width:34px;height:34px;
  margin:-17px 0 0 -17px;border-radius:50%;
  border:2px solid var(--line);border-top-color:var(--cyan);
  animation:m3d-spin .8s linear infinite;
}
@keyframes m3d-spin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){
  .m3d.is-loading .m3d__spinner::after{animation:none;border-top-color:var(--line)}
}

/* WebGL indisponible : le conteneur s'efface et la photo reprend sa
   place. Mieux vaut une fiche sans 3D qu'un rectangle noir. */
.m3d.is-unavailable{display:none}

/* Sauf quand il n'y a pas de photo derrière : s'effacer laisserait alors
   une fiche sans aucun visuel. On garde le cadre et on dit pourquoi il
   est vide — une phrase vaut mieux qu'un trou. */
.m3d__unavailable{
  display:none;position:absolute;inset:0;margin:0;padding:var(--s-6);
  align-items:center;justify-content:center;text-align:center;
  color:var(--txt-2);font-size:var(--fs-sm);line-height:1.6;
}
.m3d--only.is-unavailable{display:block}
.m3d--only.is-unavailable .m3d__unavailable{display:flex}
.m3d--only.is-unavailable .m3d__hint,
.m3d--only.is-unavailable::before{display:none}

/* --- Vignette « Vue 3D » de la galerie ---------------------------------- */
.gallery__thumb--3d{padding:0}
.gallery__thumb3d{
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:2px;width:100%;aspect-ratio:4/3;
  background:linear-gradient(155deg,var(--panel-2),var(--bg-2));
  color:var(--cyan);font:700 var(--fs-xs)/1 var(--mono);letter-spacing:.1em;
}
.gallery__thumb3d svg{width:22px;height:22px;fill:none;stroke:currentColor;stroke-width:1.6}
.gallery__thumb--3d[aria-current="true"] .gallery__thumb3d{background:var(--panel-2)}

/* --- Vignettes du catalogue --------------------------------------------- */
/*
 * Un seul canevas circule entre les cartes (voir model3d.js) : il n'y a
 * donc jamais qu'une seule règle de ce bloc active à la fois.
 */
.product-card__media.is-3d img{opacity:0}
.product-card__media img{transition:opacity .25s var(--ease),transform .5s var(--ease)}
.product-card__media .m3d__canvas{position:absolute;inset:0;width:100%;height:100%}

.badge--3d{
  background:rgba(34,227,245,.15);color:var(--cyan);
  font-family:var(--mono);letter-spacing:.06em;
}
