/* SANSIL 3D — site.css (retouche 154, 6 septembre 2026) : tokens + base + components + themes + catalogue + ux-plus,
   concaténés dans l'ordre des pages. Une seule requête bloquante au lieu de six. Les fichiers d'origine restent servis. */
/* ===== tokens.css ===== */
/* ==========================================================================
   SANSIL 3D — tokens.css
   Design system : couleurs, typographie, espacements, motion, élévations.
   Source unique de vérité. Aucune valeur codée en dur ailleurs.
   ========================================================================== */

/* --- Polices auto-hébergées (RGPD : aucun appel à Google Fonts) ----------- */

@font-face {
  font-family: "Space Grotesk";
  src: url("../fonts/SpaceGrotesk.woff2") format("woff2-variations");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Inter";
  src: url("../fonts/Inter.woff2") format("woff2-variations");
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Fira Code";
  src: url("../fonts/FiraCode.woff2") format("woff2-variations");
  font-weight: 400 500;
  font-style: normal;
  font-display: swap;
}

:root {
  /* --- Couleurs corporate (charte) -------------------------------------- */
  --c-bg: #0a0e1a;          /* fond principal */
  --c-cyan: #00e5ff;        /* accent énergie */
  --c-violet: #7b2fff;      /* accent premium */
  --c-text: #f0f4ff;        /* texte principal */
  --c-muted: #a0aec0;       /* texte secondaire */
  --c-success: #00d97e;     /* validé / en stock */
  --c-danger: #ff4444;      /* erreur / rupture */

  /* --- Surfaces dérivées ------------------------------------------------ */
  --c-surface: #101728;         /* carte, panneau */
  --c-surface-2: #16203a;       /* carte survolée / champ actif */
  --c-border: #1f2b47;          /* trait de séparation */
  --c-border-strong: #2c3c63;   /* bordure de champ */
  --c-overlay: rgba(10, 14, 26, 0.88);
  --c-placeholder: #66748f;      /* texte indicatif des champs */
  --c-violet-clair: #b48cff;     /* violet lisible sur fond sombre */
  --c-warn: #ffb020;             /* avertissement, distinct de l'alerte */
  --c-viewer-bg: #131c33;        /* fond du halo de l'aperçu 3D */
  --shadow-rgb: 0, 0, 0;

  /* Teintes transparentes (badges, halos, focus) */
  --c-cyan-08: rgba(0, 229, 255, 0.08);
  --c-cyan-16: rgba(0, 229, 255, 0.16);
  --c-cyan-40: rgba(0, 229, 255, 0.4);
  --c-violet-08: rgba(123, 47, 255, 0.08);
  --c-violet-16: rgba(123, 47, 255, 0.16);
  --c-success-12: rgba(0, 217, 126, 0.12);
  --c-danger-12: rgba(255, 68, 68, 0.12);

  /* Texte sur fond clair/accentué (contraste AA garanti) */
  --c-on-accent: #05070f;

  /* --- Dégradés & signature « lignes de couche » ------------------------- */
  --grad-accent: linear-gradient(135deg, var(--c-cyan) 0%, var(--c-violet) 100%);
  --grad-fade: linear-gradient(180deg, transparent, var(--c-bg));
  /* Striation FDM : rappel des strates d'impression, utilisé en séparateur */
  --layer-lines: repeating-linear-gradient(
    180deg,
    var(--c-cyan-08) 0px,
    var(--c-cyan-08) 1px,
    transparent 1px,
    transparent 6px
  );

  /* --- Typographie ------------------------------------------------------- */
  --f-display: "Space Grotesk", "Segoe UI", system-ui, -apple-system, sans-serif;
  --f-body: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --f-mono: "Fira Code", ui-monospace, "SF Mono", Consolas, monospace;

  /* Échelle fluide 320px → 2560px (clamp, pas de media query) */
  --t-h1: clamp(2.25rem, 1.4rem + 4.2vw, 4.5rem);
  --t-h2: clamp(1.75rem, 1.25rem + 2.4vw, 3rem);
  --t-h3: clamp(1.3rem, 1.1rem + 1vw, 1.875rem);
  --t-h4: clamp(1.1rem, 1rem + 0.5vw, 1.375rem);
  --t-lead: clamp(1.0625rem, 1rem + 0.4vw, 1.25rem);
  --t-body: 1rem;
  --t-sm: 0.9375rem;
  --t-xs: 0.8125rem;
  --t-eyebrow: 0.75rem;

  --lh-tight: 1.08;
  --lh-title: 1.18;
  --lh-body: 1.65;

  --ls-tight: -0.02em;
  --ls-eyebrow: 0.14em;

  --w-regular: 400;
  --w-medium: 500;
  --w-semibold: 600;
  --w-bold: 700;

  /* --- Espacements (base 4px) -------------------------------------------- */
  --s-1: 0.25rem;
  --s-2: 0.5rem;
  --s-3: 0.75rem;
  --s-4: 1rem;
  --s-5: 1.5rem;
  --s-6: 2rem;
  --s-7: 3rem;
  --s-8: 4rem;
  --s-9: 6rem;
  --s-10: 8rem;
  /* Rythme vertical des sections, fluide */
  --s-section: clamp(3.5rem, 2rem + 7vw, 7.5rem);

  /* --- Mise en page ------------------------------------------------------ */
  --w-container: 1240px;
  --w-wide: 1560px;
  --w-prose: 68ch;
  --gutter: clamp(1rem, 0.5rem + 2.5vw, 2.5rem);
  --header-h: 68px;

  /* --- Rayons ------------------------------------------------------------ */
  --r-xs: 4px;
  --r-sm: 8px;
  --r-md: 12px;
  --r-lg: 18px;
  --r-xl: 28px;
  --r-pill: 999px;

  /* --- Élévations -------------------------------------------------------- */
  --e-1: 0 1px 2px rgba(var(--shadow-rgb), 0.4);
  --e-2: 0 8px 24px rgba(var(--shadow-rgb), 0.45);
  --e-3: 0 20px 50px rgba(var(--shadow-rgb), 0.55);
  --glow-cyan: 0 0 0 1px var(--c-cyan-40), 0 8px 32px rgba(0, 229, 255, 0.18);

  /* --- Motion ------------------------------------------------------------ */
  --dur: 0.3s;
  --dur-fast: 0.15s;
  --dur-slow: 0.6s;
  --ease: cubic-bezier(0.16, 0.84, 0.44, 1); /* ease-out fluide */
  --hover-lift: brightness(1.05);            /* +5 % de luminosité au survol */

  /* --- Couches ----------------------------------------------------------- */
  --z-base: 1;
  --z-sticky: 100;
  --z-header: 200;
  --z-drawer: 300;
  --z-modal: 400;
  --z-toast: 500;
}

/* Accessibilité : respect de la préférence système d'animation réduite */
@media (prefers-reduced-motion: reduce) {
  :root {
    --dur: 0.01ms;
    --dur-fast: 0.01ms;
    --dur-slow: 0.01ms;
  }
}

/* ===== base.css ===== */
/* ==========================================================================
   SANSIL 3D — base.css
   Reset, typographie, mise en page, accessibilité, utilitaires.
   Mobile-first : les media queries ne font qu'élargir.
   ========================================================================== */

*,
*::before,
*::after { box-sizing: border-box; }

* { margin: 0; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + var(--s-4));
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

body {
  min-height: 100svh;
  background: var(--c-bg);
  color: var(--c-text);
  font-family: var(--f-body);
  font-size: var(--t-body);
  font-weight: var(--w-regular);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

body.is-locked { overflow: hidden; }

img, svg, video, canvas {
  display: block;
  max-width: 100%;
  height: auto;
}

input, button, textarea, select {
  font: inherit;
  color: inherit;
}

/* --- Titres --------------------------------------------------------------- */

h1, h2, h3, h4 {
  font-family: var(--f-display);
  font-weight: var(--w-bold);
  line-height: var(--lh-title);
  letter-spacing: var(--ls-tight);
  text-wrap: balance;
}

h1 { font-size: var(--t-h1); line-height: var(--lh-tight); }
h2 { font-size: var(--t-h2); }
h3 { font-size: var(--t-h3); }
h4 { font-size: var(--t-h4); font-weight: var(--w-semibold); }

p { text-wrap: pretty; }
p + p { margin-top: var(--s-4); }

.lead {
  font-size: var(--t-lead);
  color: var(--c-muted);
  max-width: var(--w-prose);
}

.muted { color: var(--c-muted); }
.mono { font-family: var(--f-mono); font-size: 0.94em; }

/* Surtitre : sert à situer la section, pas à décorer */
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  font-family: var(--f-mono);
  font-size: var(--t-eyebrow);
  font-weight: var(--w-medium);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--c-cyan);
}

.eyebrow::before {
  content: "";
  width: 24px;
  height: 1px;
  background: currentColor;
}

/* Texte en dégradé — réservé à un seul mot-clé par page */
.accent-text {
  background: var(--grad-accent);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* --- Liens ---------------------------------------------------------------- */

a {
  color: var(--c-cyan);
  text-decoration-color: var(--c-cyan-40);
  text-underline-offset: 3px;
  transition: color var(--dur) var(--ease),
              text-decoration-color var(--dur) var(--ease);
}

a:hover { filter: var(--hover-lift); text-decoration-color: currentColor; }

/* --- Listes --------------------------------------------------------------- */

ul.clean, ol.clean { list-style: none; padding: 0; }

ul.checks {
  list-style: none;
  padding: 0;
  display: grid;
  gap: var(--s-3);
}

ul.checks li {
  position: relative;
  padding-left: var(--s-6);
  color: var(--c-muted);
}

ul.checks li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.55em;
  width: 10px;
  height: 10px;
  border-radius: 2px;
  background: var(--c-cyan);
}

/* --- Accessibilité -------------------------------------------------------- */

:focus-visible {
  outline: 2px solid var(--c-cyan);
  outline-offset: 3px;
  border-radius: var(--r-xs);
}

.skip-link {
  position: absolute;
  left: var(--s-4);
  top: var(--s-4);
  z-index: var(--z-toast);
  transform: translateY(-200%);
  padding: var(--s-3) var(--s-5);
  background: var(--c-cyan);
  color: var(--c-on-accent);
  font-weight: var(--w-semibold);
  border-radius: var(--r-sm);
  text-decoration: none;
  transition: transform var(--dur) var(--ease);
}

.skip-link:focus-visible { transform: translateY(0); }

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* --- Mise en page --------------------------------------------------------- */

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

.container--wide { max-width: var(--w-wide); }
.container--prose { max-width: var(--w-prose); }

.section { padding-block: var(--s-section); }
.section--tight { padding-block: calc(var(--s-section) * 0.6); }

/* Fond alterné pour séparer visuellement deux sections successives */
.section--panel {
  background: var(--c-surface);
  border-block: 1px solid var(--c-border);
}

.section__head {
  display: grid;
  gap: var(--s-4);
  margin-bottom: var(--s-7);
  max-width: var(--w-prose);
}

/* Grille fluide : min 260px par colonne, sans media query */
.grid {
  display: grid;
  gap: var(--s-5);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
}

.grid--2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 380px), 1fr)); }
.grid--wide { gap: var(--s-6); }

.stack { display: grid; gap: var(--s-4); }
.stack--lg { gap: var(--s-6); }

.cluster {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3);
  align-items: center;
}

/* Case à cocher suivie de son libellé : le texte reste À CÔTÉ de la case.

   Sans ces deux lignes, un libellé long passe entièrement sous la case. La
   raison est dans le « flex-wrap: wrap » ci-dessus : le <span> garde sa
   largeur naturelle, dépasse, et la boîte le renvoie à la ligne d'un bloc.
   Les cases courtes — « J'accepte les CGV » — tenaient, les longues non, ce
   qui donnait un formulaire à moitié aligné.

   flex: 1 1 0 lui fait prendre la place restante au lieu de réclamer la
   sienne ; min-width: 0 l'autorise à se couper en fin de ligne plutôt qu'à
   pousser. Le libellé s'aligne alors sur le haut de la case. */
label.cluster > input[type="checkbox"],
label.cluster > input[type="radio"] {
  flex: none;
}

label.cluster > input[type="checkbox"] ~ *,
label.cluster > input[type="radio"] ~ * {
  flex: 1 1 0;
  min-width: 0;
}

/* Séparateur signature : strates d'impression FDM */
.layer-rule {
  height: 18px;
  background: var(--layer-lines);
  border: 0;
  opacity: 0.9;
  mask-image: linear-gradient(90deg, transparent, rgb(var(--shadow-rgb)) 15%, rgb(var(--shadow-rgb)) 85%, transparent);
}

/* --- Révélation au défilement (JS ajoute .is-visible) --------------------- */

.js .reveal {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity var(--dur-slow) var(--ease),
              transform var(--dur-slow) var(--ease);
}

.reveal.is-visible { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; }
}

/* --- Utilitaires ---------------------------------------------------------- */

.text-center { text-align: center; }
.mx-auto { margin-inline: auto; }
.mt-4 { margin-top: var(--s-4); }
.mt-6 { margin-top: var(--s-6); }
.mt-7 { margin-top: var(--s-7); }
.full-bleed { width: 100%; }
.hide { display: none !important; }

@media (min-width: 48rem) {
  .md-hide { display: none !important; }
}

@media (max-width: 47.99rem) {
  .sm-hide { display: none !important; }
}

@media (min-width: 48rem) {
  .sm-only { display: none !important; }
}

/* --- Attribut hidden (v147, 6 septembre 2026) -----------------------------
   Les classes de mise en page (.stack, .recap__rows, .nuancier…) posent un
   display: grid ou flex qui l'emporte sur le « hidden » du navigateur : les
   filtres de la FAQ marquaient bien les blocs cachés, sans rien cacher.
   Une règle, et « hidden » veut dire caché, partout. */
[hidden] { display: none !important; }

/* --- Finitions (retouche 153, 6 septembre 2026) ---------------------------
   Design : les sections sont visibles au repos (la révélation ne joue plus
   que sur une légère translation, jamais sur l'opacité), puces de la liste
   « Par métier » retirées, H1 plus court sur téléphone.
   Accessibilité : étiquettes monospace à 13 px minimum, animations coupées
   quand le système demande un mouvement réduit, bulle Assistant masquée tant
   que le bandeau cookies est ouvert (elle recouvrait « Refuser »). */
.js .reveal { opacity: 1; }
ul.cluster { list-style: none; padding-left: 0; margin: 0; }
:root { --t-eyebrow: 0.8125rem; }
.eyebrow, .specbar dt, .hint, .crumbs, .card__foot .muted { font-size: max(13px, var(--t-xs)); }
@media (max-width: 600px) {
  .hero h1 { font-size: clamp(1.5rem, 7.4vw, 2rem); }
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .reveal, [data-parallax] { transform: none !important; }
}
body:has(.consent) .as-bouton { display: none; }

/* ===== components.css ===== */
/* ==========================================================================
   SANSIL 3D — components.css
   Briques réutilisables par toutes les pages.
   ========================================================================== */

/* --- En-tête -------------------------------------------------------------- */

.header {
  position: sticky;
  top: 0;
  z-index: var(--z-header);
  height: var(--header-h);
  display: flex;
  align-items: center;
  background: var(--c-overlay);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid transparent;
  transition: border-color var(--dur) var(--ease),
              background var(--dur) var(--ease);
}

.header.is-scrolled { border-bottom-color: var(--c-border); }

/* La barre porte huit liens, le téléphone, le sélecteur de langue et l'appel
   à l'action : 1 319 px nécessaires contre 1 240 dans le conteneur standard.
   On lui donne la largeur étendue, déjà définie pour les grilles denses. Le
   contenu des pages, lui, garde sa largeur de lecture. */
.header .container { max-width: var(--w-wide); }

.header__inner {
  display: flex;
  align-items: center;
  gap: var(--s-5);
  width: 100%;
}

.logo {
  display: inline-flex;
  align-items: center;
  gap: var(--s-3);
  font-family: var(--f-display);
  font-weight: var(--w-bold);
  font-size: 1.0625rem;
  letter-spacing: var(--ls-tight);
  color: var(--c-text);
  text-decoration: none;
}

/* « SANSIL 3D » frôlait « Professionnels » au survol. On décale le logo
   d'un cran vers la gauche (-12 px) et on rend cet espace au menu (+12 px) :
   l'écart double, et la largeur totale de la barre ne bouge pas d'un pixel.
   (L'ancien duo `margin-right: 24px` puis `margin-right: auto` s'annulait :
   la dernière déclaration gagne, et `auto` vaut 0 dans une barre pleine.) */
.header .logo { margin-left: calc(-1 * var(--s-3)); margin-right: var(--s-3); }

.logo img { width: 32px; height: 32px; object-fit: contain; }

/* Pied de page : le verrouillage complet, marque et baseline comprises */
.logo--complet {
  display: block;
  max-width: 190px;
  margin-bottom: var(--s-2);
}

.logo--complet img { width: 100%; height: auto; }
.logo:hover { filter: var(--hover-lift); }

.nav { display: flex; align-items: center; gap: var(--s-3); }

.nav__link {
  /* 44 px de haut : la cible tactile minimale recommandée. En dessous, on
     clique à côté, surtout sur les libellés courts comme « FAQ ». */
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: var(--s-2) var(--s-3);
  border-radius: var(--r-sm);
  color: var(--c-muted);
  font-size: var(--t-sm);
  font-weight: var(--w-medium);
  text-decoration: none;
  transition: color var(--dur) var(--ease), background var(--dur) var(--ease);
}

.nav__link:hover,
.nav__link:focus-visible { color: var(--c-text); background: var(--c-cyan-08); }

.nav__link[aria-current="page"] { color: var(--c-text); }

.nav__link[aria-current="page"]::after {
  content: "";
  display: block;
  height: 2px;
  margin-top: 4px;
  border-radius: var(--r-pill);
  background: var(--grad-accent);
}

/* Bouton hamburger */
.nav-toggle {
  display: inline-flex;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 42px;
  height: 42px;
  padding: 0 9px;
  background: transparent;
  border: 1px solid var(--c-border-strong);
  border-radius: var(--r-sm);
  cursor: pointer;
}

.nav-toggle span {
  display: block;
  height: 2px;
  background: var(--c-text);
  border-radius: var(--r-pill);
  transition: transform var(--dur) var(--ease), opacity var(--dur-fast) var(--ease);
}

.nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* Tiroir mobile */
.drawer {
  position: fixed;
  inset: var(--header-h) 0 0 0;
  z-index: var(--z-drawer);
  display: grid;
  align-content: start;
  gap: var(--s-2);
  padding: var(--s-6) var(--gutter) var(--s-8);
  background: var(--c-bg);
  border-top: 1px solid var(--c-border);
  transform: translateY(-8px);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--dur) var(--ease),
              transform var(--dur) var(--ease),
              visibility var(--dur);
}

.drawer.is-open { opacity: 1; transform: none; visibility: visible; }

.drawer a {
  padding: var(--s-4) var(--s-2);
  border-bottom: 1px solid var(--c-border);
  font-family: var(--f-display);
  font-size: var(--t-h4);
  color: var(--c-text);
  text-decoration: none;
}

/* --- Sélecteur de langue -------------------------------------------------- */
/* Quatre libellés alignés mangeaient ~230 px de barre : à l'étroit, la
   navigation compressait ses voisins et le numéro de téléphone se cassait en
   colonne. Un seul bouton déroulant rend cette largeur, et `nowrap` interdit
   désormais à un lien de se couper en plusieurs lignes. */

.nav > * { flex: 0 0 auto; }
.nav__link { white-space: nowrap; }

.langsw { position: relative; }

.langsw > summary {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-2) var(--s-3);
  border: 1px solid var(--c-border-strong);
  border-radius: var(--r-sm);
  color: var(--c-muted);
  font-size: var(--t-sm);
  font-weight: var(--w-medium);
  white-space: nowrap;
  cursor: pointer;
  list-style: none;
  transition: color var(--dur) var(--ease),
              background var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}

/* Safari affiche encore son triangle sans cette règle */
.langsw > summary::-webkit-details-marker { display: none; }

.langsw > summary:hover,
.langsw > summary:focus-visible {
  color: var(--c-text);
  background: var(--c-cyan-08);
  border-color: var(--c-cyan-40);
}

.langsw__globe { width: 16px; height: 16px; flex: none; }
.langsw__code { font-family: var(--f-mono); letter-spacing: 0.04em; }

.langsw__caret {
  width: 10px;
  height: 10px;
  flex: none;
  transition: transform var(--dur-fast) var(--ease);
}

.langsw[open] > summary .langsw__caret { transform: rotate(180deg); }

.langsw__menu {
  position: absolute;
  top: calc(100% + var(--s-2));
  right: 0;
  z-index: var(--z-drawer);
  display: grid;
  gap: 2px;
  min-width: 200px;
  padding: var(--s-2);
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--r-md);
  box-shadow: var(--e-2);
}

.langsw__item {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-2) var(--s-3);
  border-radius: var(--r-sm);
  color: var(--c-muted);
  font-size: var(--t-sm);
  text-decoration: none;
  white-space: nowrap;
  transition: color var(--dur-fast) var(--ease),
              background var(--dur-fast) var(--ease);
}

.langsw__item:hover,
.langsw__item:focus-visible { color: var(--c-text); background: var(--c-surface-2); }
.langsw__item[aria-current="true"] { color: var(--c-text); }

.langsw__abbr {
  min-width: 2.2em;
  font-family: var(--f-mono);
  font-size: var(--t-xs);
  color: var(--c-cyan);
}

/* Langues dans le tiroir mobile : pastilles, pas une pile de lignes pleines */
.drawer__langs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  padding: var(--s-4) var(--s-2) 0;
}

.drawer__langs a {
  padding: var(--s-2) var(--s-4);
  border: 1px solid var(--c-border-strong);
  border-radius: var(--r-pill);
  font-family: var(--f-body);
  font-size: var(--t-sm);
  color: var(--c-muted);
}

.drawer__langs a[aria-current="true"] {
  color: var(--c-on-accent);
  background: var(--c-cyan);
  border-color: var(--c-cyan);
}

/* Le seuil est calé sur la largeur réellement occupée par la barre complète.
   En dessous, le menu déroulant prend le relais : mieux vaut un tiroir qu'une
   navigation qui déborde. */
/* La barre complète — huit liens, téléphone, langues, appel à l'action —
   demande environ 1 330 px. En dessous elle débordait : on garde le menu
   burger jusqu'à ce qu'elle tienne réellement. */
@media (min-width: 90rem) {
  .nav-toggle, .drawer { display: none; }
}

@media (max-width: 89.99rem) {
  .nav { display: none; }
}

/* --- Boutons -------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  padding: var(--s-3) var(--s-5);
  min-height: 44px; /* cible tactile */
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  font-family: var(--f-body);
  font-size: var(--t-sm);
  font-weight: var(--w-semibold);
  line-height: 1;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: filter var(--dur) var(--ease),
              transform var(--dur) var(--ease),
              background var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}

.btn:hover { filter: var(--hover-lift); transform: translateY(-1px); }
.btn:active { transform: translateY(0); }
.btn:disabled, .btn[aria-disabled="true"] {
  opacity: 0.5; cursor: not-allowed; transform: none; filter: none;
}

.btn--primary {
  background: var(--c-cyan);
  color: var(--c-on-accent);
  box-shadow: 0 6px 22px rgba(0, 229, 255, 0.22);
}

.btn--accent {
  background: var(--grad-accent);
  color: var(--c-on-accent);
}

.btn--ghost {
  background: transparent;
  color: var(--c-text);
  border-color: var(--c-border-strong);
}

.btn--ghost:hover { background: var(--c-cyan-08); border-color: var(--c-cyan-40); }

.btn--quiet { background: transparent; color: var(--c-muted); padding-inline: var(--s-3); }
.btn--lg { padding: var(--s-4) var(--s-6); font-size: var(--t-body); min-height: 52px; }
.btn--block { width: 100%; }

/* --- Badges & puces ------------------------------------------------------- */

.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  padding: 5px var(--s-3);
  border-radius: var(--r-pill);
  background: var(--c-cyan-08);
  border: 1px solid var(--c-cyan-16);
  color: var(--c-cyan);
  font-family: var(--f-mono);
  font-size: var(--t-xs);
  letter-spacing: 0.02em;
}

.badge--success { background: var(--c-success-12); border-color: transparent; color: var(--c-success); }
.badge--danger { background: var(--c-danger-12); border-color: transparent; color: var(--c-danger); }
.badge--violet { background: var(--c-violet-08); border-color: var(--c-violet-16); color: var(--c-violet-clair); }

.dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; }

/* --- Cartes --------------------------------------------------------------- */

.card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  padding: var(--s-5);
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--r-lg);
  transition: border-color var(--dur) var(--ease),
              background var(--dur) var(--ease),
              transform var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease);
}

.card--link {
  /* Toute la carte est cliquable : le curseur doit le dire partout, y
     compris sur l'image et dans les marges intérieures. */
  cursor: pointer;
}

.card--link::before {
  /* Zone de survol stable, prolongée de 3 px sous la carte — exactement le
     déplacement appliqué au survol. Sans elle, survoler le bord bas fait
     osciller la carte indéfiniment : elle monte, sort de sous le curseur,
     perd le survol, redescend, le retrouve. */
  content: "";
  position: absolute;
  inset: 0 0 -3px 0;
  z-index: 0;
}

.card--link:hover,
.card--link:focus-within {
  background: var(--c-surface-2);
  border-color: var(--c-cyan-40);
  transform: translateY(-3px);
  box-shadow: var(--e-2);
}

@media (prefers-reduced-motion: reduce) {
  .card--link:hover,
  .card--link:focus-within { transform: none; }
}

/* Le lien couvre toute la carte sans dupliquer le libellé pour les lecteurs d'écran */
.card__link::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  z-index: 2;
}

.card__icon {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: var(--r-md);
  background: var(--c-cyan-08);
  color: var(--c-cyan);
}

.card__title { font-size: var(--t-h4); }
.card__text { color: var(--c-muted); font-size: var(--t-sm); }
.card__foot { margin-top: auto; padding-top: var(--s-3); }

/* Carte produit */
.product__media {
  aspect-ratio: 4 / 3;
  border-radius: var(--r-md);
  background: var(--c-bg) var(--layer-lines);
  overflow: hidden;
}

.product__media img { width: 100%; height: 100%; object-fit: cover; }

.price {
  font-family: var(--f-display);
  font-size: var(--t-h4);
  font-weight: var(--w-bold);
}

.price small { font-family: var(--f-body); font-size: var(--t-xs); color: var(--c-muted); font-weight: var(--w-regular); }

/* --- Tableau de specs ----------------------------------------------------- */

.specs { width: 100%; border-collapse: collapse; font-size: var(--t-sm); }
.specs th, .specs td { padding: var(--s-3) var(--s-2); text-align: left; border-bottom: 1px solid var(--c-border); }
.specs th { color: var(--c-muted); font-weight: var(--w-medium); }
.specs td { font-family: var(--f-mono); }

/* --- Formulaires ---------------------------------------------------------- */

.field { display: grid; gap: var(--s-2); }

.label { font-size: var(--t-sm); font-weight: var(--w-medium); }
.label span { color: var(--c-muted); font-weight: var(--w-regular); }

.input, .select, .textarea {
  width: 100%;
  padding: var(--s-3) var(--s-4);
  min-height: 46px;
  background: var(--c-bg);
  border: 1px solid var(--c-border-strong);
  border-radius: var(--r-sm);
  color: var(--c-text);
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}

.input::placeholder, .textarea::placeholder { color: var(--c-placeholder); }
.input:hover, .select:hover, .textarea:hover { border-color: var(--c-cyan-40); }
.input:focus, .select:focus, .textarea:focus {
  outline: none;
  border-color: var(--c-cyan);
  background: var(--c-surface);
  box-shadow: 0 0 0 3px var(--c-cyan-16);
}

.textarea { min-height: 130px; resize: vertical; }
.hint { font-size: var(--t-xs); color: var(--c-muted); }
.error { font-size: var(--t-xs); color: var(--c-danger); }
.input[aria-invalid="true"] { border-color: var(--c-danger); }

/* Zone de dépôt de fichier (devis / slicer) */
.dropzone {
  display: grid;
  place-items: center;
  gap: var(--s-3);
  padding: var(--s-8) var(--s-5);
  text-align: center;
  background: var(--c-surface);
  border: 1.5px dashed var(--c-border-strong);
  border-radius: var(--r-lg);
  cursor: pointer;
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}

.dropzone:hover, .dropzone.is-dragover {
  border-color: var(--c-cyan);
  background: var(--c-cyan-08);
}

/* --- Chargement ----------------------------------------------------------- */

.spinner {
  width: 22px;
  height: 22px;
  border: 2px solid var(--c-border-strong);
  border-top-color: var(--c-cyan);
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
}

@keyframes spin { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
  .spinner { animation-duration: 1.5s; }
}

/* --- Fil d'ariane --------------------------------------------------------- */

.crumbs { display: flex; flex-wrap: wrap; gap: var(--s-2); font-size: var(--t-xs); color: var(--c-muted); }
.crumbs a { color: var(--c-muted); text-decoration: none; }
.crumbs a:hover { color: var(--c-cyan); }

/* --- Pied de page --------------------------------------------------------- */

.footer {
  padding-block: var(--s-8) var(--s-6);
  background: var(--c-surface);
  border-top: 1px solid var(--c-border);
  font-size: var(--t-sm);
}

.footer__grid {
  display: grid;
  gap: var(--s-6);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr));
}

.footer__titre {
  font-family: var(--f-mono);
  font-size: var(--t-eyebrow);
  font-weight: var(--w-medium);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--c-muted);
  margin-bottom: var(--s-4);
}

.footer ul { list-style: none; padding: 0; display: grid; gap: var(--s-3); }
.footer a { color: var(--c-muted); text-decoration: none; }
.footer a:hover { color: var(--c-cyan); }

.footer__bottom {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-4);
  justify-content: space-between;
  align-items: center;
  margin-top: var(--s-7);
  padding-top: var(--s-5);
  border-top: 1px solid var(--c-border);
  color: var(--c-muted);
  font-size: var(--t-xs);
}

/* --- CTA flottant (mobile) ------------------------------------------------ */

.cta-flottant {
  position: fixed;
  right: var(--s-4);
  bottom: var(--s-4);
  z-index: var(--z-sticky);
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  min-height: 48px;
  padding: var(--s-3) var(--s-5);
  background: var(--grad-accent);
  color: var(--c-on-accent);
  font-size: var(--t-sm);
  font-weight: var(--w-semibold);
  text-decoration: none;
  border-radius: var(--r-pill);
  box-shadow: var(--e-3);
  transform: translateY(120%);
  transition: transform var(--dur) var(--ease), filter var(--dur) var(--ease);
}

.cta-flottant.is-visible { transform: translateY(0); }
.cta-flottant:hover { filter: var(--hover-lift); }

/* Ne s'affiche que sur petit écran : sur desktop, l'en-tête suffit */
@media (min-width: 48rem) {
  .cta-flottant { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .cta-flottant { transition: none; }
}

/* ==========================================================================
   Figures illustratives
   Utilisées sur les pages éditoriales : accueil, atelier, matières, hubs.
   La légende porte la mention « vue d'illustration » : les visuels ne sont
   pas des photographies de commandes réelles, et le dire évite toute
   ambiguïté commerciale.
   ========================================================================== */

.figure {
  margin: 2.5rem 0;
}

.figure img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--r-lg);
  border: 1px solid var(--c-border);
}

.figure figcaption {
  margin-top: .7rem;
  font-size: .85rem;
  line-height: 1.5;
  color: var(--c-muted);
}

/* ==========================================================================
   Bandeau de consentement
   Ancré en bas, sans voile d'arrière-plan : la lecture n'est jamais bloquée,
   ce qui évite le schéma trompeur du mur de cookies. Les deux actions
   partagent la même rangée et la même taille — refuser doit coûter le même
   effort qu'accepter.
   ========================================================================== */

.consent {
  position: fixed;
  inset: auto 0 0 0;
  z-index: var(--z-modal);
  padding: var(--s-4);
  display: flex;
  justify-content: center;
  pointer-events: none;
}

.consent__boite {
  pointer-events: auto;
  width: min(46rem, 100%);
  padding: var(--s-5);
  background: var(--c-surface);
  border: 1px solid var(--c-border-strong);
  border-radius: var(--r-lg);
  box-shadow: var(--e-3);
}

.consent__titre {
  margin: 0 0 .4rem;
  font-weight: var(--w-semibold);
}

.consent__texte {
  margin: 0;
  font-size: var(--t-sm);
  color: var(--c-muted);
  line-height: 1.55;
}

.consent__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  margin-top: var(--s-4);
}

.consent__actions .btn {
  flex: 1 1 8rem;
  justify-content: center;
}

@media (max-width: 480px) {
  .consent { padding: var(--s-2); }
  .consent__actions .btn { flex-basis: 100%; }
}

/* --- Sélecteur de charte : même habillage que les langues, mais 20 entrées
       au lieu de 5. Sans plafond de hauteur, le menu sort de l'écran et les
       derniers thèmes deviennent inatteignables.                          */
[data-themesw] .langsw__menu {
  max-height: min(60vh, 420px);
  overflow-y: auto;
  overscroll-behavior: contain;   /* le défilement ne se propage pas à la page */
}

[data-themesw] .langsw__item {
  width: 100%;
  background: none;
  border: 0;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

/* Le numéro d'ordre tient sur deux chiffres : on fige la largeur pour que
   les libellés restent alignés de 1 à 20. */
[data-themesw] .langsw__abbr {
  min-width: 2ch;
  text-align: right;
}

/* --- Sélecteur de thème dans le pied de page ------------------------------
   Placé en bas, le tiroir doit s'ouvrir vers le HAUT : vers le bas il
   sortirait de la fenêtre et les derniers thèmes seraient inatteignables.  */
[data-themesw] .langsw__menu {
  top: auto;
  bottom: calc(100% + var(--s-2));
}

/* --- Tableaux de la page prix ---------------------------------------------
   Un tableau de six lignes déborde en dessous de 480 px : on le rend
   défilant plutôt que de le laisser pousser la page en largeur.          */
.tableau {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  margin-top: var(--s-5);
  border: 1px solid var(--c-border);
  border-radius: var(--r-md);
}

.tableau table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--t-sm);
}

.tableau th,
.tableau td {
  padding: var(--s-3) var(--s-4);
  text-align: left;
  white-space: nowrap;
}

.tableau thead th {
  background: var(--c-surface-2);
  color: var(--c-text);
  font-weight: var(--w-medium);
}

.tableau tbody tr + tr { border-top: 1px solid var(--c-border); }

/* Les colonnes chiffrées se lisent mieux alignées à droite et en chasse fixe. */
.tableau td:not(:first-child) {
  font-family: var(--f-mono);
  text-align: right;
  color: var(--c-muted);
}

.tableau td strong { color: var(--c-text); }

/* --- Page avis -------------------------------------------------------------
   Les avis viennent de la fiche Google et sont repris mot pour mot. Aucune
   note moyenne n'est balisée en données structurées : Google n'accorde plus
   d'étoiles à une entreprise qui balise ses propres avis.                  */
.avis__resume {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-4) var(--s-5);
  padding: var(--s-5);
  background: var(--c-cyan-08);
  border: 1px solid var(--c-cyan-40);
  border-radius: var(--r-md);
}

.avis__note {
  margin: 0;
  font-family: var(--f-display);
  font-size: var(--t-h2);
  font-weight: var(--w-bold);
  color: var(--c-cyan);
  line-height: 1;
}

.avis__note span {
  font-size: var(--t-body);
  color: var(--c-muted);
}

.avis__compte {
  margin: 0;
  margin-right: auto;
  color: var(--c-muted);
}

.avis__grille {
  display: grid;
  gap: var(--s-4);
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
}

.avis {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  margin: 0;
  padding: var(--s-5);
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--r-md);
}

.avis__etoiles {
  color: var(--c-cyan);
  letter-spacing: 0.12em;
  font-size: var(--t-sm);
}

.avis__texte {
  margin: 0;
  flex: 1;
  color: var(--c-text);
  font-size: var(--t-sm);
  line-height: 1.6;
}

.avis__auteur {
  color: var(--c-text);
  font-size: var(--t-sm);
  font-weight: var(--w-medium);
}

.avis__date {
  color: var(--c-muted);
  font-weight: var(--w-regular, 400);
}

/* Le lien de vérification passe à la ligne : accolé au nom, il se lit comme
   une partie du nom de l'auteur. */
.avis__lien {
  display: block;
  margin-top: var(--s-2);
  font-size: var(--t-xs);
  font-weight: var(--w-regular, 400);
  color: var(--c-muted);
}

/* Champ fichier : le bouton natif affiche son texte dans la langue du
   navigateur, pas dans celle de la page. On masque l'input et on pose un
   bouton dont le libellé suit la page. */
.fichier-choix {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  flex-wrap: wrap;
}

.fichier-choix .muted { font-size: var(--t-sm); }

/* --- Fil d'étapes du formulaire MakerWorld -------------------------------- */
/* La classe .steps-tabs n'avait aucune règle : le navigateur appliquait la
   numérotation de liste et le style système des boutons, gris clair, sur
   lequel la couleur de texte du thème sombre devenait illisible. */

.steps-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  list-style: none;
  margin: 0 0 var(--s-6);
  padding: 0;
  counter-reset: etape;
}

.steps-tabs > li { flex: 1 1 12rem; counter-increment: etape; }

.steps-tabs button {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  width: 100%;
  min-height: 48px;
  padding: var(--s-3) var(--s-4);
  border: 1px solid var(--c-border);
  border-radius: var(--r-sm);
  background: var(--c-surface);
  color: var(--c-muted);
  font-family: var(--f-body);
  font-size: var(--t-sm);
  font-weight: 500;
  text-align: left;
  cursor: pointer;
  transition: color .15s, border-color .15s, background .15s;
}

.steps-tabs button::before {
  content: counter(etape);
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  border-radius: var(--r-pill);
  border: 1px solid var(--c-border-strong);
  background: var(--c-bg);
  color: var(--c-muted);
  font-family: var(--f-mono);
  font-size: var(--t-xs);
  line-height: 1;
}

.steps-tabs button:hover {
  color: var(--c-text);
  border-color: var(--c-border-strong);
  background: var(--c-surface-2);
}

.steps-tabs button.is-active {
  color: var(--c-text);
  border-color: var(--c-cyan-40);
  background: var(--c-cyan-08);
}

.steps-tabs button.is-active::before {
  background: var(--c-cyan);
  border-color: var(--c-cyan);
  color: var(--c-on-accent);
  font-weight: 700;
}

.steps-tabs button.is-done::before {
  content: "\2713";
  background: var(--c-success-12);
  border-color: var(--c-success);
  color: var(--c-success);
}

.steps-tabs button:focus-visible {
  outline: 2px solid var(--c-cyan);
  outline-offset: 2px;
}

.step-panel { display: none; }
.step-panel.is-active { display: block; }

@media (max-width: 640px) {
  .steps-tabs > li { flex: 1 1 100%; }
}

/* --- Classes employées dans les pages mais jamais définies ----------------- */
/* Relevé sur les 1 448 pages : ces sélecteurs étaient appelés dans le HTML
   sans aucune règle correspondante, les éléments tombaient donc sur les
   défauts du navigateur. */

/* Marges utilitaires : 615 emplois cumulés, aucune définition. */
.mt-1 { margin-top: var(--s-1); }
.mt-2 { margin-top: var(--s-2); }
.mt-3 { margin-top: var(--s-3); }
.mt-4 { margin-top: var(--s-4); }
.mt-5 { margin-top: var(--s-5); }
.mt-6 { margin-top: var(--s-6); }
.mt-7 { margin-top: var(--s-7); }
.mt-8 { margin-top: var(--s-8); }

/* Grille à trois colonnes, dans la continuité de .grid--2 */
.grid--3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr)); }

/* Conteneur du visuel produit, présent sur les 1 099 fiches */
.fiche__media {
  margin-bottom: var(--s-6);
  border-radius: var(--r-md);
  overflow: hidden;
  background: var(--c-surface);
  border: 1px solid var(--c-border);
}

.fiche__media img { display: block; width: 100%; height: auto; }

/* Champ de formulaire : contact, devis et MakerWorld, en cinq langues */
.champ { display: grid; gap: var(--s-2); margin-bottom: var(--s-5); }

.champ > label,
.champ > .label {
  font-size: var(--t-sm);
  font-weight: 600;
  color: var(--c-text);
}

.champ .hint { margin: 0; font-size: var(--t-xs); color: var(--c-muted); }

/* Les champs saisis directement (sans classe .input, comme l'adresse du
   modèle MakerWorld) gardaient le fond BLANC par défaut du navigateur avec
   le texte clair du thème : blanc sur blanc, saisie invisible. On leur
   applique l'habillage du design system — liste explicite pour ne pas
   toucher aux cases, boutons radio ni dépôts de fichier. */
.champ input[type="text"], .champ input[type="url"], .champ input[type="email"],
.champ input[type="tel"], .champ input[type="number"], .champ input[type="search"],
.champ select, .champ textarea {
  width: 100%;
  padding: var(--s-3) var(--s-4);
  min-height: 46px;
  background: var(--c-bg);
  border: 1px solid var(--c-border-strong);
  border-radius: var(--r-sm);
  color: var(--c-text);
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}

.champ input::placeholder, .champ textarea::placeholder { color: var(--c-placeholder); }

.champ input[type="text"]:focus, .champ input[type="url"]:focus,
.champ input[type="email"]:focus, .champ input[type="tel"]:focus,
.champ input[type="number"]:focus, .champ input[type="search"]:focus,
.champ select:focus, .champ textarea:focus {
  outline: none;
  border-color: var(--c-cyan);
  background: var(--c-surface);
  box-shadow: 0 0 0 3px var(--c-cyan-16);
}

/* Enveloppe du formulaire de devis et son récapitulatif */
.devis-form { display: block; }

.estimation {
  display: grid;
  gap: var(--s-3);
  margin: 0;
  padding: var(--s-5);
  border: 1px solid var(--c-border);
  border-radius: var(--r-md);
  background: var(--c-surface);
}

.estimation > div {
  display: flex;
  justify-content: space-between;
  gap: var(--s-4);
  padding-bottom: var(--s-3);
  border-bottom: 1px solid var(--c-border);
}

.estimation > div:last-child { padding-bottom: 0; border-bottom: 0; }
.estimation dt { color: var(--c-muted); font-size: var(--t-sm); }
.estimation dd { margin: 0; color: var(--c-text); font-weight: 600; text-align: right; }

/* Coche des pages de confirmation */
.coche {
  display: grid;
  place-items: center;
  width: 64px;
  height: 64px;
  margin: 0 auto var(--s-5);
  border-radius: var(--r-pill);
  background: var(--c-success-12);
  border: 1px solid var(--c-success);
  color: var(--c-success);
  font-size: 2rem;
  line-height: 1;
}

/* Tableau des matières : défilement horizontal sur petit écran */
.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.table-wrap > table { min-width: 640px; }

/* Prix mis en avant dans un bloc d'offre */
.offre__cle {
  font-family: var(--f-display);
  font-size: var(--t-h3);
  font-weight: 700;
  color: var(--c-cyan);
  margin: var(--s-2) 0;
}

/* Ligne de matière résistante aux UV, dans le tableau comparatif */
.mat.is-uv td:first-child::after {
  content: "UV";
  display: inline-block;
  margin-left: var(--s-2);
  padding: 2px 6px;
  border-radius: var(--r-pill);
  background: var(--c-warn);
  color: var(--c-on-accent);
  font-family: var(--f-mono);
  font-size: 0.6875rem;
  font-weight: 700;
  vertical-align: middle;
}

/* Enveloppe du bloc de devis : le sélecteur .devis n'existait que sous la
   forme .devis-form, la classe seule n'avait donc aucune règle. */
.devis {
  padding: var(--s-6);
  border: 1px solid var(--c-border);
  border-radius: var(--r-md);
  background: var(--c-surface);
}

@media (max-width: 640px) {
  .devis { padding: var(--s-5) var(--s-4); }
}

/* ==========================================================================
   Couche « futur » (v74) — effets de défilement et micro-interactions.
   Principes : uniquement transform/opacity (aucun recalcul de mise en page),
   jetons du design system (les 20 thèmes suivent), extinction totale via
   « prefers-reduced-motion », et rien n'est masqué sans JavaScript — le
   contenu reste intégralement visible et indexable.
   ========================================================================== */

/* --- Barre de progression de lecture -------------------------------------- */
body::before {
  content: "";
  position: fixed;
  top: 0; left: 0;
  width: 100%; height: 3px;
  background: var(--grad-accent);
  transform: scaleX(var(--defilement, 0));
  transform-origin: 0 50%;
  z-index: calc(var(--z-toast) + 1);
  pointer-events: none;
}

@supports (animation-timeline: scroll()) {
  body::before {
    animation: lecture-avance linear both;
    animation-timeline: scroll(root);
  }
  @keyframes lecture-avance { from { transform: scaleX(0); } to { transform: scaleX(1); } }
}

/* --- En-tête : verre dépoli renforcé au défilement ------------------------- */
@supports (background: color-mix(in srgb, red 50%, transparent)) {
  .header.is-scrolled {
    background: color-mix(in srgb, var(--c-bg) 70%, transparent);
    -webkit-backdrop-filter: blur(16px) saturate(1.5);
    backdrop-filter: blur(16px) saturate(1.5);
    box-shadow: 0 10px 30px -18px rgba(var(--shadow-rgb), 0.55);
  }
}

/* --- Accueil : aurore vivante + grille technique --------------------------- */
.hero::before {
  /* Seconde nappe lumineuse, animée — le halo existant garde son parallaxe. */
  content: "";
  position: absolute; inset: -20% -10%; z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(38% 46% at 72% 68%, var(--c-violet-16), transparent 70%),
    radial-gradient(30% 42% at 12% 78%, var(--c-cyan-16), transparent 70%);
  filter: blur(12px);
  opacity: 0.8;
}

.hero::after {
  /* Grille de plan technique, fondue vers les bords. */
  content: "";
  position: absolute; inset: 0; z-index: 0;
  pointer-events: none;
  background:
    linear-gradient(var(--c-cyan-08) 1px, transparent 1px),
    linear-gradient(90deg, var(--c-cyan-08) 1px, transparent 1px);
  background-size: 46px 46px;
  -webkit-mask-image: radial-gradient(70% 85% at 32% 28%, #000, transparent 78%);
  mask-image: radial-gradient(70% 85% at 32% 28%, #000, transparent 78%);
}

@media (prefers-reduced-motion: no-preference) {
  .hero::before { animation: aurore-vie 16s var(--ease) infinite alternate; }
  .hero::after { animation: grille-derive 30s linear infinite; }

  @keyframes aurore-vie {
    from { transform: translate3d(0, 0, 0) scale(1); opacity: 0.65; }
    to   { transform: translate3d(-2.5%, 2%, 0) scale(1.08); opacity: 1; }
  }
  @keyframes grille-derive { to { background-position: 46px 46px, 46px 46px; } }

  /* --- Accueil : entrée cinétique ---------------------------------------- */
  .hero .eyebrow, .hero h1 span, .hero .lead,
  .hero .hero__cta, .hero .specbar > div {
    opacity: 0;
    transform: translateY(20px);
    animation: entree-hero 0.8s var(--ease) forwards;
  }
  .hero .eyebrow { animation-delay: 0.05s; }
  .hero h1 span:nth-child(1) { animation-delay: 0.15s; }
  .hero h1 span:nth-child(2) { animation-delay: 0.3s; }
  .hero .lead { animation-delay: 0.45s; }
  .hero .hero__cta { animation-delay: 0.58s; }
  .hero .specbar > div:nth-child(1) { animation-delay: 0.7s; }
  .hero .specbar > div:nth-child(2) { animation-delay: 0.78s; }
  .hero .specbar > div:nth-child(3) { animation-delay: 0.86s; }
  .hero .specbar > div:nth-child(4) { animation-delay: 0.94s; }

  @keyframes entree-hero { to { opacity: 1; transform: none; } }

  /* Le dégradé du titre balaie une fois de droite à gauche. Attention :
     cette règle est plus spécifique que « .hero h1 span » — elle doit donc
     porter AUSSI l'animation d'entrée, sinon elle l'écrase et la ligne
     resterait à opacité 0. Les deux se cumulent, propriétés disjointes. */
  .hero h1 .accent-text {
    background-size: 220% auto;
    animation:
      entree-hero 0.8s var(--ease) 0.3s forwards,
      titre-balaye 2.4s var(--ease) 0.5s backwards;
  }
  @keyframes titre-balaye {
    from { background-position: 120% 0; }
    to   { background-position: 0% 0; }
  }
}

/* --- Bandeau des matières (construit par main.js sur l'accueil) ------------ */
.bande-tech {
  overflow: hidden;
  padding-block: var(--s-4);
  border-block: 1px solid var(--c-border);
  font-family: var(--f-mono);
  font-size: 0.9rem;
  letter-spacing: 0.08em;
  color: var(--c-muted);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 14%, #000 86%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 14%, #000 86%, transparent);
}

/* Espacement porté par le groupe (et non la piste) : la boucle à -50 %
   retombe ainsi exactement sur la couture, sans à-coup. */
.bande-tech__piste { display: flex; width: max-content; }

.bande-tech__groupe {
  display: flex; align-items: center;
  gap: var(--s-7); padding-right: var(--s-7);
  white-space: nowrap;
}

.bande-tech__sep { color: var(--c-cyan); font-size: 0.7em; }

@media (prefers-reduced-motion: no-preference) {
  .bande-tech__piste { animation: bande-defile 34s linear infinite; }
  .bande-tech:hover .bande-tech__piste { animation-play-state: paused; }
  @keyframes bande-defile { to { transform: translateX(-50%); } }
}

/* --- Révélations : images qui se posent en douceur ------------------------- */
.figure.reveal { overflow: hidden; }
.figure.reveal img {
  transform: scale(1.06);
  transition: transform 1.2s var(--ease);
}
.figure.reveal.is-visible img { transform: none; }

/* --- Cartes et portes : reflet balayé au survol ----------------------------- */
@media (hover: hover) and (pointer: fine) {
  .porte { position: relative; }

  .card--link::after, .porte::after {
    content: "";
    position: absolute; inset: 0; z-index: 1;
    border-radius: inherit;
    pointer-events: none;
    background: linear-gradient(105deg,
      transparent 42%,
      rgba(255, 255, 255, 0.06) 50%,
      transparent 58%);
    background: linear-gradient(105deg,
      transparent 42%,
      color-mix(in srgb, var(--c-text) 9%, transparent) 50%,
      transparent 58%);
    background-size: 260% 100%;
    background-position: 125% 0;
    background-repeat: no-repeat;
    opacity: 0;
  }

  .card--link:hover::after, .porte:hover::after {
    opacity: 1;
    background-position: -25% 0;
    transition: background-position 0.9s var(--ease), opacity 0.15s linear;
  }

  /* Inclinaison 3D pilotée par main.js : suivi souple du pointeur au
     survol, retour détendu quand il s'en va. */
  .est-inclinable { transition: transform 0.5s var(--ease); }
  .est-inclinable:hover { transition: transform 0.18s var(--ease); }
}

/* --- Filets de sécurité ----------------------------------------------------- */
@media print {
  .reveal { opacity: 1 !important; transform: none !important; }
  body::before, .bande-tech, .hero::before, .hero::after { display: none !important; }
}

/* --- Étapes : la ligne se dessine, le compteur s'allume --------------------- */
.step { position: relative; }
.step::after {
  content: "";
  position: absolute; top: -2px; left: 0;
  width: 100%; height: 2px;
  background: var(--grad-accent);
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform 1s var(--ease) 0.15s;
}
.step.is-visible::after { transform: scaleX(1); }

/* --- Séparateurs « lignes de couche » : faisceau lumineux ------------------- */
hr.layer-rule { position: relative; overflow: hidden; }

@media (prefers-reduced-motion: no-preference) {
  hr.layer-rule::after {
    content: "";
    position: absolute; inset: 0 auto 0 0;
    width: 20%;
    background: linear-gradient(90deg, transparent, var(--c-cyan-16), transparent);
    animation: faisceau-course 7s linear infinite;
  }
  @keyframes faisceau-course {
    from { transform: translateX(-100%); }
    to   { transform: translateX(600%); }
  }
}

/* --- Appels à l'action : halo d'énergie au survol --------------------------- */
@supports (background: color-mix(in srgb, red 50%, transparent)) {
  .btn--primary:hover, .btn--primary:focus-visible,
  .btn--accent:hover, .btn--accent:focus-visible {
    box-shadow:
      0 0 0 1px color-mix(in srgb, var(--c-cyan) 45%, transparent),
      0 6px 28px color-mix(in srgb, var(--c-cyan) 32%, transparent);
  }
}

/* --- Couche « futur » : signatures lumineuses ------------------------------- */

/* (Le halo global qui suivait le curseur a été retiré à la demande de Flo
   le 31/07/2026 — seuls restent les effets localisés sur les cartes.) */

/* Cartes-projecteur : un point de lumière suit le curseur sur la carte. */
@media (hover: hover) and (pointer: fine) {
  .est-inclinable:hover {
    background-image: radial-gradient(240px circle at var(--mx, 50%) var(--my, 50%),
      var(--c-cyan-08), transparent 68%);
  }
}

/* Images : parallaxe douce dans leur cadre, pilotée par le défilement
   (navigateurs compatibles ; les autres gardent le dézoom à l'arrivée). */
.figure.reveal { border-radius: var(--r-lg); }

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .figure.reveal img {
      transform: none;
      transition: none;
      animation: figure-plane linear both;
      animation-timeline: view();
      animation-range: cover 0% cover 100%;
    }
    @keyframes figure-plane {
      from { transform: scale(1.14) translateY(4.5%); }
      to   { transform: scale(1.14) translateY(-4.5%); }
    }
  }
}

/* Titres de section : le souligné dégradé se dessine à l'arrivée. */
.section__head h2::after {
  content: "";
  display: block;
  width: 64px; height: 3px;
  margin-top: var(--s-3);
  border-radius: var(--r-pill);
  background: var(--grad-accent);
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform 0.9s var(--ease) 0.2s;
}

.section__head.is-visible h2::after,
.section__head:not(.reveal) h2::after { transform: scaleX(1); }

/* Pied de page : faisceau d'énergie sur la ligne de crête. */
.footer { position: relative; }

@media (prefers-reduced-motion: no-preference) {
  .footer::before {
    content: "";
    position: absolute;
    top: -1px; left: 0; right: 0;
    height: 2px;
    background: linear-gradient(90deg,
      transparent, var(--c-cyan) 40%, var(--c-violet) 60%, transparent);
    background-size: 30% 100%;
    background-repeat: no-repeat;
    background-position: -40% 0;
    animation: faisceau-pied 8s linear infinite;
    opacity: 0.75;
    pointer-events: none;
  }
  @keyframes faisceau-pied {
    from { background-position: -40% 0; }
    to   { background-position: 140% 0; }
  }
}

@media print {
  .footer::before { display: none !important; }
}

/* ==========================================================================
   Couche « premium » (v76) — corrections d'audit + matière haut de gamme.
   ========================================================================== */

/* En-tête compact : le menu s'aligne à droite, la loupe passe en icône seule.
   Avec le seuil du burger remonté à 90rem, la barre tient réellement partout. */
.header .nav { margin-left: auto; gap: var(--s-2); }
.header .rg-bouton span, .header .rg-bouton kbd { display: none; }

/* Tiroir mobile défilable : le CTA devis restait hors d'atteinte en paysage. */
.drawer { overflow-y: auto; overscroll-behavior: contain; }

/* L'assistant ne recouvre plus le CTA flottant mobile. */
@media (max-width: 900px) { .as-bouton { bottom: 88px !important; } }

/* Grain cinématographique : tue l'aspect « plastique plat » des dégradés. */
html::before {
  content: "";
  position: fixed; inset: 0;
  z-index: calc(var(--z-toast) + 2);
  pointer-events: none;
  opacity: 0.05;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='b'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.68' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23b)' opacity='0.5'/%3E%3C/svg%3E");
}

/* Grille « plan technique » sur les sections panneau (signature ingénierie). */
.section--panel { position: relative; }
.section--panel::before {
  content: "";
  position: absolute; inset: 0;
  pointer-events: none;
  background:
    linear-gradient(var(--c-cyan-08) 1px, transparent 1px),
    linear-gradient(90deg, var(--c-cyan-08) 1px, transparent 1px);
  background-size: 44px 44px;
  -webkit-mask-image: radial-gradient(75% 90% at 50% 0%, #000, transparent 85%);
  mask-image: radial-gradient(75% 90% at 50% 0%, #000, transparent 85%);
  opacity: 0.5;
}

/* Croix de repérage : la ponctuation graphique du plan coté. */
.eyebrow::after { content: "+"; color: var(--c-cyan); font-weight: 400; }

/* Anneau d'énergie en rotation lente autour du CTA principal du hero. */
@property --angle-sansil {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}

@media (prefers-reduced-motion: no-preference) {
  .hero__cta .btn--primary { position: relative; }
  .hero__cta .btn--primary::before {
    content: "";
    position: absolute; inset: -3px;
    border-radius: calc(var(--r-sm) + 3px);
    padding: 2px;
    background: conic-gradient(from var(--angle-sansil),
      transparent 0turn 0.55turn, var(--c-cyan) 0.75turn,
      var(--c-violet) 0.85turn, transparent 0.95turn 1turn);
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    mask-composite: exclude;
    animation: anneau-energie 5s linear infinite;
    pointer-events: none;
  }
  @keyframes anneau-energie { to { --angle-sansil: 360deg; } }
}

@media print {
  html::before, .section--panel::before { display: none !important; }
}

/* --- Signature A (v78) : l'image du hero s'imprime couche par couche ------- */
/* Les paliers steps() SONT les couches : l'image se dépose du bas vers le
   haut, une fine ligne-buse lumineuse balayant le front d'impression. */
@media (prefers-reduced-motion: no-preference) {
  .figure.reveal { position: relative; }

  .figure.reveal.is-visible img {
    animation: impression-couches 2.6s steps(36, jump-none) both;
  }
  @keyframes impression-couches {
    from { clip-path: inset(100% 0 0 0); }
    to   { clip-path: inset(0 0 0 0); }
  }

  .figure.reveal::after {
    content: "";
    position: absolute; left: 3%; right: 3%; top: 100%;
    height: 2px;
    background: linear-gradient(90deg, transparent, var(--c-cyan), transparent);
    box-shadow: 0 0 14px var(--c-cyan);
    opacity: 0;
    pointer-events: none;
  }
  .figure.reveal.is-visible::after {
    animation: buse-depose 2.6s steps(36, jump-none) both;
  }
  @keyframes buse-depose {
    from { top: 99%; opacity: 1; }
    98%  { opacity: 1; }
    to   { top: 0%; opacity: 0; }
  }
}


/* === Correctifs audit 01/08/2026 === ===================================== */

/* Les cartes-liens ne sont pas des liens de texte : plus de soulignement */
.card a,
.card__title a,
.card--link a,
.porte,
.famille-btn { text-decoration: none; }
.card a:hover,
.card__title a:hover { text-decoration: underline; text-underline-offset: 3px; }

/* Une pastille se dimensionne sur son texte, jamais sur son conteneur */
.badge { width: fit-content; justify-self: start; align-self: start; }

/* Compteurs de familles : contraste réel au lieu d'une opacité */
.famille-btn span { opacity: 1; color: var(--c-muted); }
.famille-btn[aria-pressed="true"] span { color: inherit; }

/* Bordures de champs perceptibles (WCAG 1.4.11) */
input[type="text"], input[type="email"], input[type="tel"], input[type="url"],
input[type="number"], input[type="search"], select, textarea {
  border-color: var(--c-bord-fort, rgba(160,174,192,.55));
}

/* Cible tactile des cases à cocher */
input[type="checkbox"], input[type="radio"] { width: 24px; height: 24px; }

/* En-tête : ne jamais déborder, même avec des libellés longs (DE, ES) */
.header__inner { min-width: 0; flex-wrap: nowrap; }
.nav { min-width: 0; flex-wrap: wrap; row-gap: 2px; }
.nav__link { white-space: nowrap; }
@media (max-width: 1500px) {
  .nav { gap: var(--s-2); }
  .nav__link { padding-left: var(--s-2); padding-right: var(--s-2); font-size: calc(var(--t-sm) - 1px); }
}

/* Éléments flottants : ne plus recouvrir le contenu sur petit écran */
@media (max-width: 640px) {
  .as-bouton { bottom: calc(var(--s-6) + 62px); }
  body { padding-bottom: 84px; }
}

/* Impression : un document lisible et transmissible */

/* === Nuancier des fiches matières ======================================== */
.nuancier-f { margin-top: var(--s-4); }
.nuancier-f__t { margin: 0 0 var(--s-2); font-size: 0.9rem; }
.nuancier-f__t span { font-family: var(--f-mono); font-size: 0.78rem; font-weight: 400; color: var(--c-muted); }
.nuancier-f__g { display: flex; flex-wrap: wrap; gap: 6px; }
.pastille-f {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 9px 3px 4px; border: 1px solid var(--c-border);
  border-radius: 999px; font-size: 0.78rem; line-height: 1.3;
}
.pastille-f i {
  width: 15px; height: 15px; border-radius: 50%;
  background: var(--p, var(--c-muted));
  box-shadow: inset 0 0 0 1px rgb(0 0 0 / 0.25);
  flex: 0 0 15px;
}
.pastille-f--inconnue i {
  background: repeating-linear-gradient(45deg, var(--c-border), var(--c-border) 3px, var(--c-surface) 3px, var(--c-surface) 6px);
}
.conf-mat table { width: 100%; }


/* === Survol des cartes produit — 01/08/2026 ============================== */

/* La zone cliquable doit couvrir exactement la zone de survol de la carte.
   Sans ces 3 px, le lien perdait le survol pendant que la carte montait,
   et le soulignement du titre clignotait. */
.card--link .card__link::after { inset: 0 0 -3px 0; }

/* Une carte entièrement cliquable n'est pas un lien de texte : elle se
   soulève, change de bordure et de fond. Le trait sous le titre n'ajoute
   rien et se déclenchait même en survolant le bas de la carte. */
.card--link .card__title a:hover { text-decoration: none; }
.card--link:hover .card__title, .card--link:focus-within .card__title { color: var(--c-cyan); }

@media print {
  html, body { background: #fff !important; color: #111 !important; }
  header.header, .footer, .as-bouton, .as-panneau, .cta-flottant, .consent,
  .rg-bouton, [data-themesw], .skip-link, video, .bande-tech { display: none !important; }
  main, .container, .card, .fiche, section { background: #fff !important; color: #111 !important;
    box-shadow: none !important; }
  h1, h2, h3, h4, strong, dt { color: #000 !important; }
  a { color: #000 !important; text-decoration: underline; }
  main a[href^="/"]::after { content: " (sansil3d.fr" attr(href) ")"; font-size: .8em; color: #555; }
  details { display: block !important; }
  details > summary { list-style: none; font-weight: 700; }
  details > *:not(summary) { display: block !important; }
  img { max-width: 100% !important; page-break-inside: avoid; }
  .galerie__vignettes { display: none !important; }
  @page { margin: 14mm; }
}

/* ===== themes.css ===== */
/* ==========================================================================
   SANSIL 3D — themes.css
   Dix variantes de charte, chacune ne redéfinissant que des variables de
   tokens.css. Aucune règle de mise en page ici : la structure du site ne
   change pas, seules la couleur et la typographie bougent.

   Usage : <html data-theme="ardoise"> sur /styleguide/themes/ pour comparer.
   Une fois le thème retenu, on recopie ses valeurs dans tokens.css et ce
   fichier disparaît — il ne sert qu'à choisir.

   Les paires texte/fond respectent toutes un contraste d'au moins 4,5:1,
   vérifié par tools/audit_contraste.py.
   ========================================================================== */

/* 1 — Nuit (actuel, pour référence) --------------------------------------- */
[data-theme="nuit"] {
  --c-bg: #0a0e1a; --c-surface: #101728; --c-surface-2: #16203a;
  --c-border: #1f2b47; --c-border-strong: #2c3c63;
  --c-text: #f0f4ff; --c-muted: #a0aec0;
  --c-cyan: #00e5ff; --c-violet: #7b2fff; --c-on-accent: #05070f;
}

/* 2 — Ardoise : gris froid, accent orange atelier ------------------------- */
[data-theme="ardoise"] {
  --c-bg: #14171c; --c-surface: #1c2027; --c-surface-2: #252a33;
  --c-border: #2e343f; --c-border-strong: #414957;
  --c-text: #f2f4f7; --c-muted: #a7b0bd;
  --c-cyan: #ff8a3d; --c-violet: #ffb84d; --c-on-accent: #14171c;
}

/* 3 — Établi : fond clair, encre sombre, accent bleu de travail ----------- */
[data-theme="etabli"] {
  --c-bg: #f5f4f1; --c-surface: #ffffff; --c-surface-2: #ebe9e4;
  --c-border: #dcd8d0; --c-border-strong: #b8b2a7;
  --c-text: #1a1a18; --c-muted: #5c5a54;
  --c-cyan: #1d4ed8; --c-violet: #6d28d9; --c-on-accent: #ffffff;
}

/* 4 — Filament : vert acide sur anthracite ------------------------------- */
[data-theme="filament"] {
  --c-bg: #0d1117; --c-surface: #161b22; --c-surface-2: #21262d;
  --c-border: #2d333b; --c-border-strong: #444c56;
  --c-text: #e6edf3; --c-muted: #9198a1;
  --c-cyan: #3fb950; --c-violet: #a371f7; --c-on-accent: #04140a;
}

/* 5 — Blueprint : plan technique, bleu profond --------------------------- */
[data-theme="blueprint"] {
  --c-bg: #0b1a33; --c-surface: #12244a; --c-surface-2: #1a3160;
  --c-border: #234080; --c-border-strong: #3157a8;
  --c-text: #eaf2ff; --c-muted: #9db4dc;
  --c-cyan: #ffd166; --c-violet: #7ea8ff; --c-on-accent: #0b1a33;
}

/* 6 — Papier : très clair, chaleureux, accent terre cuite ---------------- */
[data-theme="papier"] {
  --c-bg: #fbf9f5; --c-surface: #ffffff; --c-surface-2: #f2ede4;
  --c-border: #e4dccf; --c-border-strong: #c3b7a3;
  --c-text: #221f1a; --c-muted: #635c50;
  --c-cyan: #c2410c; --c-violet: #9a3412; --c-on-accent: #ffffff;
}

/* 7 — Carbone : noir dense, accent rouge ---------------------------------- */
[data-theme="carbone"] {
  --c-bg: #0a0a0b; --c-surface: #141416; --c-surface-2: #1e1e21;
  --c-border: #2a2a2e; --c-border-strong: #3d3d43;
  --c-text: #f4f4f5; --c-muted: #a1a1aa;
  --c-cyan: #ef4444; --c-violet: #f97316; --c-on-accent: #0a0a0b;
}

/* 8 — Menthe : sombre mais froid, accent turquoise doux ------------------ */
[data-theme="menthe"] {
  --c-bg: #0f1c1a; --c-surface: #162724; --c-surface-2: #1f3531;
  --c-border: #2a4741; --c-border-strong: #3c6259;
  --c-text: #edfbf7; --c-muted: #9cc0b8;
  --c-cyan: #2dd4bf; --c-violet: #86efac; --c-on-accent: #04211c;
}

/* 9 — Indigo : violet dominant, accent rose ------------------------------ */
[data-theme="indigo"] {
  --c-bg: #12101f; --c-surface: #1b1830; --c-surface-2: #262040;
  --c-border: #332b57; --c-border-strong: #493d78;
  --c-text: #f2efff; --c-muted: #aca4c9;
  --c-cyan: #f472b6; --c-violet: #a78bfa; --c-on-accent: #12101f;
}

/* 10 — Signal : gris neutre, accent jaune sécurité ----------------------- */
[data-theme="signal"] {
  --c-bg: #1b1b1b; --c-surface: #242424; --c-surface-2: #2e2e2e;
  --c-border: #3a3a3a; --c-border-strong: #525252;
  --c-text: #fafafa; --c-muted: #a3a3a3;
  --c-cyan: #facc15; --c-violet: #fb923c; --c-on-accent: #1b1b1b;
}

/* ==========================================================================
   Deuxième série — thèmes 11 à 20
   Même principe : uniquement des surcharges de variables de tokens.css.
   ========================================================================== */

/* 11 — Sable : beige chaud, accent brique ------------------------------- */
[data-theme="sable"] {
  --c-bg: #f7f3ec; --c-surface: #ffffff; --c-surface-2: #efe7d9;
  --c-border: #e0d5c2; --c-border-strong: #bfae94;
  --c-text: #241f18; --c-muted: #5f564a;
  --c-cyan: #b04a1e; --c-violet: #8a5a2b; --c-on-accent: #ffffff;
}

/* 12 — Fonderie : gris fonte, accent cuivre ------------------------------ */
[data-theme="fonderie"] {
  --c-bg: #1a1917; --c-surface: #242220; --c-surface-2: #2f2c29;
  --c-border: #3b3733; --c-border-strong: #524c46;
  --c-text: #f5f2ee; --c-muted: #a8a099;
  --c-cyan: #d98040; --c-violet: #c9a227; --c-on-accent: #1a1917;
}

/* 13 — Océan : bleu-vert profond, accent corail -------------------------- */
[data-theme="ocean"] {
  --c-bg: #08202b; --c-surface: #0e2f3d; --c-surface-2: #144052;
  --c-border: #1c556b; --c-border-strong: #2a7591;
  --c-text: #e8f6fb; --c-muted: #93b8c7;
  --c-cyan: #ff7a59; --c-violet: #5fd6c4; --c-on-accent: #08202b;
}

/* 14 — Craie : gris très clair, accent noir d'encre ---------------------- */
[data-theme="craie"] {
  --c-bg: #f4f5f6; --c-surface: #ffffff; --c-surface-2: #e9ebed;
  --c-border: #dcdfe3; --c-border-strong: #b4bac1;
  --c-text: #16181a; --c-muted: #565c63;
  --c-cyan: #111315; --c-violet: #4a5057; --c-on-accent: #ffffff;
}

/* 15 — Néon : noir bleuté, accent magenta -------------------------------- */
[data-theme="neon"] {
  --c-bg: #0b0b14; --c-surface: #14141f; --c-surface-2: #1d1d2c;
  --c-border: #292940; --c-border-strong: #3d3d5c;
  --c-text: #f3f2ff; --c-muted: #a09eb8;
  --c-cyan: #ff3fa4; --c-violet: #4de0ff; --c-on-accent: #0b0b14;
}

/* 16 — Forêt : vert sombre, accent ambre --------------------------------- */
[data-theme="foret"] {
  --c-bg: #101a12; --c-surface: #17251a; --c-surface-2: #1f3224;
  --c-border: #2a432f; --c-border-strong: #3c5f43;
  --c-text: #edf7ee; --c-muted: #9bb7a0;
  --c-cyan: #e8a33d; --c-violet: #7ec96f; --c-on-accent: #101a12;
}

/* 17 — Lin : blanc cassé, accent bleu marine ----------------------------- */
[data-theme="lin"] {
  --c-bg: #faf8f4; --c-surface: #ffffff; --c-surface-2: #f0ece4;
  --c-border: #e2dcd1; --c-border-strong: #b9b0a1;
  --c-text: #1c1f26; --c-muted: #575d68;
  --c-cyan: #1e3a8a; --c-violet: #4c5fd7; --c-on-accent: #ffffff;
}

/* 18 — Basalte : gris-bleu sombre, accent vert d'eau --------------------- */
[data-theme="basalte"] {
  --c-bg: #12171c; --c-surface: #1a2027; --c-surface-2: #232b34;
  --c-border: #2f3944; --c-border-strong: #435161;
  --c-text: #eef2f6; --c-muted: #9aa7b4;
  --c-cyan: #4ecdc4; --c-violet: #7aa2f7; --c-on-accent: #12171c;
}

/* 19 — Prune : violet profond, accent or --------------------------------- */
[data-theme="prune"] {
  --c-bg: #1a1020; --c-surface: #24172c; --c-surface-2: #2f1f3a;
  --c-border: #3d2a4a; --c-border-strong: #573c69;
  --c-text: #f6eefa; --c-muted: #b39fc0;
  --c-cyan: #e8b53d; --c-violet: #c98bff; --c-on-accent: #1a1020;
}

/* 20 — Chantier : gris moyen, accent orange haute visibilité ------------- */
[data-theme="chantier"] {
  --c-bg: #22262a; --c-surface: #2b3036; --c-surface-2: #363c43;
  --c-border: #434a53; --c-border-strong: #5c6570;
  --c-text: #f6f7f8; --c-muted: #a6afb9;
  --c-cyan: #ff6b1a; --c-violet: #ffc247; --c-on-accent: #22262a;
}

/* --- Typographies alternatives ------------------------------------------- */
/* Indépendantes de la palette : on peut croiser les deux réglages. */
[data-police="actuel"]  { --f-display: "Space Grotesk", system-ui, sans-serif;
                          --f-body: "Inter", system-ui, sans-serif; }
[data-police="serif"]   { --f-display: Georgia, "Times New Roman", serif;
                          --f-body: "Inter", system-ui, sans-serif; }
[data-police="system"]  { --f-display: system-ui, -apple-system, "Segoe UI", sans-serif;
                          --f-body: system-ui, -apple-system, "Segoe UI", sans-serif; }
[data-police="mono"]    { --f-display: "Fira Code", ui-monospace, monospace;
                          --f-body: "Inter", system-ui, sans-serif; }

/* Les dérivés translucides doivent suivre l'accent, sinon un halo cyan
   subsiste sur un thème orange. color-mix est supporté partout depuis 2023. */
[data-theme] {
  --c-cyan-08: color-mix(in srgb, var(--c-cyan) 8%, transparent);
  --c-cyan-16: color-mix(in srgb, var(--c-cyan) 16%, transparent);
  --c-cyan-40: color-mix(in srgb, var(--c-cyan) 40%, transparent);
  --c-violet-08: color-mix(in srgb, var(--c-violet) 8%, transparent);
  --c-violet-16: color-mix(in srgb, var(--c-violet) 16%, transparent);
  --c-violet-clair: color-mix(in srgb, var(--c-violet) 70%, white);
  --c-overlay: color-mix(in srgb, var(--c-bg) 88%, transparent);
  --c-placeholder: var(--c-muted);
  --c-viewer-bg: var(--c-surface-2);
}

/* ===== catalogue.css ===== */
/* ==========================================================================
   SANSIL 3D — catalogue.css
   Hub, pages de famille et fiches produit.
   ========================================================================== */

/* --- Barre de filtres ----------------------------------------------------- */

.filtres {
  display: grid;
  gap: var(--s-4);
  padding: var(--s-5);
  margin-bottom: var(--s-6);
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--r-lg);
}

.filtres__ligne {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3);
  align-items: end;
}

.filtres__ligne .field { flex: 1 1 220px; }

.familles {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
}

.famille-btn {
  padding: var(--s-2) var(--s-3);
  background: transparent;
  border: 1px solid var(--c-border-strong);
  border-radius: var(--r-pill);
  color: var(--c-muted);
  font-size: var(--t-xs);
  cursor: pointer;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease),
              background var(--dur) var(--ease);
}

.famille-btn:hover { color: var(--c-text); border-color: var(--c-cyan-40); }

.famille-btn[aria-pressed="true"] {
  background: var(--c-cyan-08);
  border-color: var(--c-cyan);
  color: var(--c-cyan);
}

.famille-btn span { font-family: var(--f-mono); color: var(--c-muted); margin-left: 4px; }
.famille-btn[aria-pressed="true"] span { color: inherit; }

.compteur { font-size: var(--t-sm); color: var(--c-muted); margin-bottom: var(--s-5); }
.compteur strong { color: var(--c-text); }

.produit.is-hidden { display: none; }

.vide {
  padding: var(--s-8) var(--s-5);
  text-align: center;
  border: 1px dashed var(--c-border-strong);
  border-radius: var(--r-lg);
  color: var(--c-muted);
}

/* --- Fiche produit -------------------------------------------------------- */

.fiche { display: grid; gap: var(--s-6); align-items: start; }

@media (min-width: 56rem) {
  .fiche { grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr); }
}

.fiche__intro { display: grid; gap: var(--s-4); }
.fiche__intro h1 { font-size: var(--t-h2); }

.fiche__meta {
  display: grid;
  gap: var(--s-3);
  padding: var(--s-4) 0;
  border-block: 1px solid var(--c-border);
}

.fiche__meta > div { display: flex; justify-content: space-between; gap: var(--s-4); font-size: var(--t-sm); }
.fiche__meta dt { color: var(--c-muted); }
.fiche__meta dd { margin: 0; font-family: var(--f-mono); text-align: right; }

.fiche__corps {
  display: grid;
  gap: var(--s-7);
  margin-top: var(--s-8);
  padding-top: var(--s-7);
  border-top: 1px solid var(--c-border);
}

@media (min-width: 62rem) {
  .fiche__corps { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.fiche__corps h2 { font-size: var(--t-h3); }

/* --- FAQ ------------------------------------------------------------------ */

.faq {
  border-bottom: 1px solid var(--c-border);
  padding: var(--s-3) 0;
}

.faq summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
  gap: var(--s-3);
}

.faq summary::-webkit-details-marker { display: none; }

.faq summary::after {
  content: "+";
  margin-left: auto;
  font-family: var(--f-mono);
  color: var(--c-cyan);
  transition: transform var(--dur) var(--ease);
}

.faq[open] summary::after { content: "−"; }

.faq summary h3 { font-size: var(--t-body); font-weight: var(--w-semibold); font-family: var(--f-body); }
.faq p { padding-top: var(--s-3); color: var(--c-muted); font-size: var(--t-sm); }

/* --- Bandeau de réassurance ----------------------------------------------- */

.rassurance {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-4);
  justify-content: space-between;
  align-items: center;
  margin-top: var(--s-8);
  padding: var(--s-5);
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--r-lg);
  font-size: var(--t-sm);
}

.rassurance p { color: var(--c-muted); }
.rassurance strong { color: var(--c-text); }

/* --- Blocs B2B du hub ----------------------------------------------------- */

.paliers { width: 100%; border-collapse: collapse; }
.paliers th, .paliers td { padding: var(--s-3) var(--s-4); border-bottom: 1px solid var(--c-border); text-align: left; }
.paliers td:last-child, .paliers th:last-child { text-align: right; font-family: var(--f-mono); }
.paliers tbody tr:hover { background: var(--c-cyan-08); }

.argus { display: grid; gap: var(--s-5); grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr)); }
.argus dt { font-family: var(--f-mono); font-size: var(--t-xs); text-transform: uppercase; letter-spacing: var(--ls-eyebrow); color: var(--c-cyan); }
.argus dd { margin: var(--s-2) 0 0; color: var(--c-muted); font-size: var(--t-sm); }

/* --- Pastilles de couleur (catalogue particuliers) ------------------------ */

.couleurs { display: flex; flex-wrap: wrap; gap: var(--s-2); }

.couleur {
  padding: var(--s-2) var(--s-3);
  border: 1px solid var(--c-border-strong);
  border-radius: var(--r-pill);
  font-size: var(--t-xs);
  color: var(--c-muted);
}

/* --- Galerie de fiche ----------------------------------------------------- */

.galerie { display: grid; gap: var(--s-3); }

.galerie__vignettes {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s-3);
}

.vignette {
  padding: 0;
  border: 1px solid var(--c-border);
  border-radius: var(--r-sm);
  background: var(--c-bg);
  overflow: hidden;
  cursor: pointer;
  transition: border-color var(--dur) var(--ease), transform var(--dur) var(--ease);
}

.vignette:hover, .vignette:focus-visible { border-color: var(--c-cyan); transform: translateY(-2px); }
.vignette[aria-current="true"] { border-color: var(--c-cyan); }
.vignette img { width: 100%; height: auto; aspect-ratio: 4 / 3; object-fit: cover; display: block; }

.product__media img { width: 100%; height: 100%; object-fit: cover; }

/* --- Comparateur de matières ---------------------------------------------- */

.tableau-defilant { overflow-x: auto; -webkit-overflow-scrolling: touch; }

.comparateur {
  width: 100%;
  min-width: 720px;
  border-collapse: collapse;
  font-size: var(--t-sm);
}

.comparateur th, .comparateur td {
  padding: var(--s-4) var(--s-3);
  text-align: left;
  border-bottom: 1px solid var(--c-border);
  vertical-align: middle;
}

.comparateur thead th {
  font-family: var(--f-mono);
  font-size: var(--t-xs);
  text-transform: uppercase;
  letter-spacing: var(--ls-eyebrow);
  color: var(--c-muted);
  border-bottom-color: var(--c-border-strong);
  white-space: nowrap;
}

.comparateur tbody tr:hover { background: var(--c-cyan-08); }
.comparateur tbody th { font-weight: var(--w-semibold); }
.comparateur tbody th a { text-decoration: none; }

.mat__long {
  display: block;
  font-size: var(--t-xs);
  font-weight: var(--w-regular);
  color: var(--c-muted);
  margin-top: 2px;
}

.mat.is-devis th a::after {
  content: "sur devis";
  display: inline-block;
  margin-left: var(--s-2);
  padding: 2px 8px;
  border-radius: var(--r-pill);
  background: var(--c-violet-08);
  color: var(--c-violet-clair);
  font-family: var(--f-mono);
  font-size: 0.6875rem;
  vertical-align: middle;
}

.euro { font-family: var(--f-mono); color: var(--c-cyan); }

.notes { display: inline-flex; gap: 3px; }

.etoile {
  width: 9px;
  height: 9px;
  border-radius: 2px;
  background: var(--c-border-strong);
  display: inline-block;
}

.etoile.is-on { background: var(--c-cyan); }

.criteres { display: grid; gap: var(--s-3); }
.critere { display: flex; justify-content: space-between; align-items: center; gap: var(--s-4); }
.critere dt { color: var(--c-muted); font-size: var(--t-sm); }
.critere dd { margin: 0; }

.checks--non li::before { background: var(--c-danger); }

@media (max-width: 47.99rem) {
  .comparateur { min-width: 640px; }
}

/* --- Performance : rendu différé des cartes du catalogue ------------------- */

/* Les cartes hors écran ne sont mises en page qu'à l'approche du viewport.
   La taille réservée (≈ une carte : visuel 4/3 + titre + texte + prix)
   évite les sauts d'ascenseur pendant le défilement. */
.produit {
  content-visibility: auto;
  contain-intrinsic-size: auto 480px;
}

/* --- Preuve sociale (note Google et extraits d'avis) ----------------------- */

.preuve-sociale {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-5) var(--s-7);
  padding: var(--s-5) var(--s-6);
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--r-lg);
}

.preuve-sociale__note {
  display: grid;
  gap: var(--s-1);
  justify-items: start;
}

.preuve-sociale__etoiles {
  color: var(--c-cyan);
  letter-spacing: 0.12em;
  font-size: var(--t-sm);
}

.preuve-sociale__note strong {
  font-family: var(--f-display);
  font-size: var(--t-h3);
  font-weight: var(--w-bold);
  line-height: 1;
}

.preuve-sociale__note strong span {
  font-size: var(--t-body);
  color: var(--c-muted);
}

.preuve-sociale__source { color: var(--c-muted); font-size: var(--t-xs); }

.preuve-sociale__citation {
  flex: 1 1 260px;
  margin: 0;
  padding-left: var(--s-4);
  border-left: 2px solid var(--c-border-strong);
}

.preuve-sociale__citation blockquote {
  margin: 0;
  color: var(--c-text);
  font-size: var(--t-sm);
  line-height: var(--lh-body);
}

.preuve-sociale__citation figcaption {
  margin-top: var(--s-2);
  color: var(--c-muted);
  font-size: var(--t-xs);
}

.preuve-sociale__lien {
  margin-left: auto;
  color: var(--c-cyan);
  font-size: var(--t-sm);
  text-decoration: none;
  white-space: nowrap;
}

.preuve-sociale__lien:hover,
.preuve-sociale__lien:focus-visible { text-decoration: underline; }

/* --- « Les visuels sont des exemples » ------------------------------------
   En tête de fiche, avant même la galerie. Un filet d'accent à gauche plutôt
   qu'un bandeau d'alerte : ce n'est pas un avertissement, c'est la façon
   dont l'atelier travaille. */
.exemple {
  padding: var(--s-3) var(--s-4);
  border: 1px solid var(--c-cyan-40);
  border-left: 3px solid var(--c-cyan);
  border-radius: var(--r-sm);
  background: var(--c-cyan-08);
  font-size: var(--t-sm);
  line-height: 1.55;
  color: var(--c-muted);
}
.exemple strong { color: var(--c-text); }

/* --- credit des visuels repris sous licence Creative Commons -------------
   La mention est la condition de la licence : discrete, mais toujours la. */
.credit-visuel{margin-top:var(--s-2);font-size:.78rem;line-height:1.4;
  color:var(--c-texte-doux,#8a94a8)}
.credit-visuel a{color:inherit;text-decoration:underline;text-underline-offset:2px}
.credit-visuel a:hover{color:var(--c-cyan,#22d3ee)}
/* Le visuel et son credit ne font qu'un enfant de la grille .fiche. */
.fiche__visuel{min-width:0}
.fiche__visuel .fiche__media{margin-bottom:0}
/* Fiche sans visuel : sans cette regle la colonne image resterait vide. */
.fiche--sans-media{grid-template-columns:minmax(0,1fr)}

/* ===== ux-plus.css ===== */
/* ==========================================================================
   SANSIL 3D — ux-plus.css
   Recherche globale, assistant, portes d'entrée, encart pièce introuvable.
   Tout est construit sur tokens.css : aucune couleur codée en dur.
   ========================================================================== */

/* --- Bouton loupe du header ---------------------------------------------- */

.rg-bouton {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: none;
  border: 1px solid var(--c-border-strong);
  border-radius: 999px;
  color: var(--c-muted);
  font: inherit;
  font-size: 0.88rem;
  padding: 6px 14px;
  cursor: pointer;
  transition: border-color 0.15s ease, color 0.15s ease;
}

.rg-bouton:hover,
.rg-bouton:focus-visible {
  border-color: var(--c-cyan-40);
  color: var(--c-text);
}

.rg-bouton svg { flex: none; }

.rg-bouton kbd {
  font-family: "Fira Code", monospace;
  font-size: 0.68rem;
  color: var(--c-placeholder);
  border: 1px solid var(--c-border);
  border-radius: 4px;
  padding: 1px 5px;
}

@media (max-width: 900px) {
  .rg-bouton span, .rg-bouton kbd { display: none; }
  .rg-bouton { padding: 8px; border: none; }
}

/* --- Overlay de recherche -------------------------------------------------- */

.rg-voile {
  position: fixed;
  inset: 0;
  z-index: 9500;
  background: var(--c-overlay);
  backdrop-filter: blur(4px);
  display: none;
  padding: 9vh 16px 16px;
}

.rg-voile.est-ouvert { display: block; }

.rg-panneau {
  max-width: 660px;
  margin: 0 auto;
  background: var(--c-surface);
  border: 1px solid var(--c-border-strong);
  border-radius: 14px;
  box-shadow: 0 24px 80px rgba(var(--shadow-rgb), 0.55);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  max-height: 78vh;
}

.rg-champ {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 18px;
  border-bottom: 1px solid var(--c-border);
}

.rg-champ svg { color: var(--c-cyan); flex: none; }

.rg-champ input {
  flex: 1;
  background: none;
  border: none;
  outline: none;
  color: var(--c-text);
  font: inherit;
  font-size: 1.05rem;
}

.rg-champ input::placeholder { color: var(--c-placeholder); }

.rg-champ kbd {
  font-family: "Fira Code", monospace;
  font-size: 0.7rem;
  color: var(--c-placeholder);
  border: 1px solid var(--c-border);
  border-radius: 4px;
  padding: 2px 6px;
}

.rg-resultats {
  overflow-y: auto;
  padding: 6px;
  scrollbar-width: thin;
}

.rg-groupe {
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--c-placeholder);
  padding: 12px 14px 4px;
}

.rg-item {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 9px 14px;
  border-radius: 8px;
  border-left: 2px solid transparent;
  color: var(--c-text);
  text-decoration: none;
}

.rg-item strong { font-weight: 600; }

.rg-item small { color: var(--c-muted); font-size: 0.8rem; }

.rg-item .rg-prix {
  margin-left: auto;
  color: var(--c-cyan);
  font-size: 0.8rem;
  white-space: nowrap;
}

.rg-item.est-actif,
.rg-item:hover {
  background: var(--c-surface-2);
  border-left-color: var(--c-cyan);
}

.rg-vide {
  padding: 26px 18px;
  color: var(--c-muted);
  text-align: center;
}

.rg-pied {
  border-top: 1px solid var(--c-border);
  padding: 12px 18px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  background: var(--c-violet-08);
}

.rg-pied a {
  color: var(--c-violet-clair);
  text-decoration: none;
  font-size: 0.9rem;
}

.rg-pied a:hover { text-decoration: underline; }

.rg-pied span {
  color: var(--c-placeholder);
  font-size: 0.75rem;
}

/* --- Assistant ------------------------------------------------------------- */

.as-bouton {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 9000;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 12px 18px;
  border: none;
  border-radius: 999px;
  background: linear-gradient(135deg, var(--c-cyan), var(--c-violet));
  color: var(--c-on-accent, #061018);
  font: inherit;
  font-weight: 700;
  cursor: pointer;
  box-shadow: 0 10px 30px rgba(var(--shadow-rgb), 0.45);
  transition: transform 0.15s ease;
}

.as-bouton:hover { transform: translateY(-2px); }

@media (max-width: 640px) {
  .as-bouton span { display: none; }
  .as-bouton { padding: 14px; }
}

.as-panneau {
  position: fixed;
  right: 20px;
  bottom: 84px;
  z-index: 9400;
  width: min(392px, calc(100vw - 24px));
  max-height: min(600px, calc(100vh - 110px));
  display: none;
  flex-direction: column;
  background: var(--c-surface);
  border: 1px solid var(--c-border-strong);
  border-radius: 16px;
  box-shadow: 0 24px 80px rgba(var(--shadow-rgb), 0.55);
  overflow: hidden;
}

.as-panneau.est-ouvert { display: flex; }

.as-tete {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--c-border);
  background: var(--c-surface-2);
}

.as-tete .as-pastille {
  width: 34px;
  height: 34px;
  flex: none;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--c-cyan), var(--c-violet));
  display: grid;
  place-items: center;
  color: var(--c-on-accent, #061018);
}

.as-tete strong { color: var(--c-text); }

.as-tete small { display: block; color: var(--c-muted); font-size: 0.72rem; }

.as-fermer {
  margin-left: auto;
  background: none;
  border: none;
  color: var(--c-muted);
  font-size: 1.3rem;
  line-height: 1;
  cursor: pointer;
  padding: 4px;
}

.as-fermer:hover { color: var(--c-text); }

.as-fil {
  flex: 1;
  overflow-y: auto;
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  scrollbar-width: thin;
}

.as-msg {
  max-width: 86%;
  padding: 10px 13px;
  border-radius: 12px;
  font-size: 0.92rem;
  line-height: 1.45;
  white-space: pre-line;
}

.as-msg--bot {
  align-self: flex-start;
  background: var(--c-surface-2);
  color: var(--c-text);
  border-bottom-left-radius: 4px;
}

.as-msg--moi {
  align-self: flex-end;
  background: var(--c-cyan-16);
  color: var(--c-text);
  border-bottom-right-radius: 4px;
}

.as-liens {
  display: flex;
  flex-direction: column;
  gap: 6px;
  align-self: flex-start;
  width: 86%;
}

.as-lien {
  display: block;
  padding: 9px 12px;
  border: 1px solid var(--c-border-strong);
  border-left: 3px solid var(--c-cyan);
  border-radius: 8px;
  color: var(--c-text);
  text-decoration: none;
  font-size: 0.88rem;
  background: var(--c-surface-2);
}

.as-lien small { display: block; color: var(--c-muted); font-size: 0.75rem; }

.as-lien:hover { border-color: var(--c-cyan-40); }

.as-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 0 14px 10px;
}

.as-chip {
  background: var(--c-cyan-08);
  border: 1px solid var(--c-border-strong);
  border-radius: 999px;
  color: var(--c-text);
  font: inherit;
  font-size: 0.8rem;
  padding: 6px 12px;
  cursor: pointer;
}

.as-chip:hover { border-color: var(--c-cyan-40); }

.as-saisie {
  display: flex;
  gap: 8px;
  padding: 12px 14px;
  border-top: 1px solid var(--c-border);
}

.as-saisie input {
  flex: 1;
  background: var(--c-bg);
  border: 1px solid var(--c-border-strong);
  border-radius: 999px;
  color: var(--c-text);
  font: inherit;
  font-size: 0.92rem;
  padding: 9px 16px;
  outline: none;
}

.as-saisie input:focus { border-color: var(--c-cyan-40); }

.as-saisie button {
  border: none;
  border-radius: 50%;
  width: 40px;
  height: 40px;
  flex: none;
  background: linear-gradient(135deg, var(--c-cyan), var(--c-violet));
  color: var(--c-on-accent, #061018);
  cursor: pointer;
  display: grid;
  place-items: center;
}

.as-attente { display: inline-flex; gap: 4px; padding: 4px 2px; }

.as-attente i {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--c-muted);
  animation: as-pulse 1s infinite;
}

.as-attente i:nth-child(2) { animation-delay: 0.18s; }
.as-attente i:nth-child(3) { animation-delay: 0.36s; }

@keyframes as-pulse { 0%, 100% { opacity: 0.25; } 50% { opacity: 1; } }

/* --- Portes d'entrée (hub catalogue) --------------------------------------- */

.portes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 14px;
  margin-top: 22px;
}

.porte {
  display: block;
  padding: 18px;
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: 12px;
  text-decoration: none;
  color: var(--c-text);
  transition: border-color 0.15s ease, transform 0.15s ease;
}

.porte:hover {
  border-color: var(--c-cyan-40);
  transform: translateY(-2px);
}

.porte svg {
  color: var(--c-cyan);
  margin-bottom: 10px;
}

.porte strong { display: block; font-size: 1.02rem; }

.porte span {
  display: block;
  margin-top: 4px;
  color: var(--c-muted);
  font-size: 0.84rem;
  line-height: 1.4;
}

.porte--violet svg { color: var(--c-violet-clair); }

.porte--violet:hover { border-color: var(--c-violet-16); }

.portes-metiers {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 14px;
}

.portes-metiers a {
  border: 1px solid var(--c-border-strong);
  border-radius: 999px;
  padding: 7px 14px;
  color: var(--c-muted);
  text-decoration: none;
  font-size: 0.85rem;
}

.portes-metiers a:hover {
  color: var(--c-text);
  border-color: var(--c-cyan-40);
}

/* --- Encart pièce introuvable ---------------------------------------------- */

.ux-introuvable {
  margin: 40px auto 48px;
  max-width: 1120px;
  padding: 0 16px;
}

.ux-introuvable .ux-carte {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 18px;
  padding: 22px 26px;
  border-radius: 14px;
  border: 1px solid var(--c-border-strong);
  background: linear-gradient(120deg, var(--c-violet-08), var(--c-cyan-08));
}

.ux-introuvable svg { color: var(--c-violet-clair); flex: none; }

.ux-introuvable .ux-texte { flex: 1 1 320px; }

.ux-introuvable strong { display: block; font-size: 1.08rem; color: var(--c-text); }

.ux-introuvable p { margin: 4px 0 0; color: var(--c-muted); font-size: 0.92rem; }


/* ==========================================================================
   v77 — vidéo de présentation (accueil, 5 langues).
   ========================================================================== */
.video-presentation { max-width: 860px; margin-inline: auto; }
.video-presentation video {
  width: 100%; height: auto; display: block;
  border-radius: 16px;
  border: 1px solid var(--c-border, #1f2b47);
  background: var(--c-bg, #0a0e1a);
  box-shadow: 0 18px 50px rgba(0, 0, 0, .45);
}

/* Retouche 159 : les boutons de fiche technique (PDF) peuvent passer à la ligne.
   Les libellés les plus longs dépassaient la largeur de l'écran sur téléphone —
   .btn est en « white-space: nowrap », ce qui reste juste partout ailleurs. */
.cluster.tds { gap: var(--s-2); }
.cluster.tds .btn {
  white-space: normal;
  text-align: left;
  justify-content: flex-start;
  line-height: 1.25;
  padding-top: var(--s-2);
  padding-bottom: var(--s-2);
}

/* ==========================================================================
   Lettre d'information (retouche 160)
   Le bloc du pied de page était construit par main.js depuis la 145 avec ses
   classes, mais aucune règle ne les habillait : champ pleine largeur, bouton
   seul en dessous, case à cocher blanche du navigateur, texte en gras sur
   toute la ligne. On en fait un panneau : le texte à gauche, le formulaire à
   droite, une seule colonne sur téléphone. Rien qu'avec les variables de
   thème, pour que les vingt thèmes suivent.
   ========================================================================== */
.newsletter {
  margin-top: var(--s-7);
  padding: var(--s-6);
  display: grid;
  gap: var(--s-5) var(--s-7);
  align-items: start;
  background:
    radial-gradient(120% 140% at 0% 0%, var(--c-cyan-16, rgba(0, 229, 255, .10)), transparent 60%),
    var(--c-bg);
  border: 1px solid var(--c-border);
  border-radius: var(--r-md);
}

@media (min-width: 52rem) {
  .newsletter { grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr); align-items: center; }
}

.newsletter .footer__titre { margin-bottom: var(--s-2); }

.newsletter__p {
  margin: 0;
  color: var(--c-muted);
  font-weight: var(--w-regular);
  font-size: var(--t-sm);
  line-height: 1.55;
  max-width: 46ch;
}

.newsletter__form { display: grid; gap: var(--s-3); min-width: 0; }

.newsletter__ligne { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.newsletter__ligne .input { flex: 1 1 15rem; min-width: 0; }
.newsletter__ligne .btn { flex: 0 0 auto; }

@media (max-width: 30rem) {
  .newsletter__ligne .btn { width: 100%; }
}

/* Case à cocher : celle du navigateur restait un carré blanc sur fond sombre.
   On la redessine avec les couleurs du thème, alignée sur la première ligne
   du texte plutôt que centrée sur le paragraphe. */
.newsletter__consent {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--s-3);
  align-items: start;
  color: var(--c-muted);
  font-size: var(--t-xs);
  line-height: 1.5;
  cursor: pointer;
}

.newsletter__consent input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  width: 18px;
  height: 18px;
  margin: 0;
  flex: none;
  display: grid;
  place-content: center;
  background: var(--c-bg);
  border: 1px solid var(--c-border-strong);
  border-radius: 5px;
  cursor: pointer;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
}

.newsletter__consent input[type="checkbox"]:hover { border-color: var(--c-cyan); }

.newsletter__consent input[type="checkbox"]:checked {
  background: var(--c-cyan);
  border-color: var(--c-cyan);
}

.newsletter__consent input[type="checkbox"]:checked::after {
  content: "";
  width: 10px;
  height: 5px;
  margin-top: -3px;
  border-left: 2px solid var(--c-on-accent);
  border-bottom: 2px solid var(--c-on-accent);
  transform: rotate(-45deg);
}

.newsletter__consent input[type="checkbox"]:focus-visible {
  outline: 2px solid var(--c-cyan);
  outline-offset: 2px;
}

.newsletter__consent a { color: var(--c-muted); text-decoration: underline; text-underline-offset: 2px; }
.newsletter__consent a:hover { color: var(--c-cyan); }

.newsletter__etat { margin: 0; min-height: 1em; }
.newsletter__etat:empty { display: none; }

/* ==========================================================================
   Pied de page (retouche 162)
   Quatre colonnes de liens tous du même poids, un logo de 190 px et, sur
   téléphone, 1 900 px à faire défiler. On resserre : le logo cadré, les
   titres de colonne soulignés d'un trait court, les liens qui avancent au
   survol, les contacts lisibles d'un coup d'œil, deux colonnes au lieu
   d'une sur téléphone, et une barre du bas rangée. Que des variables de
   thème : les vingt thèmes suivent.
   ========================================================================== */
.footer__grid { gap: var(--s-7) var(--s-6); }

/* Bloc de marque : le logo est un visuel, on le cadre au lieu de le laisser
   flotter, et on lui met la taille d'un logo, pas d'une image d'illustration. */
.footer .logo--complet {
  max-width: 148px;
  margin-bottom: var(--s-4);
  border: 1px solid var(--c-border);
  border-radius: var(--r-md);
  overflow: hidden;
  background: var(--c-bg);
}

.footer .logo--complet img { display: block; }

.footer .logo--complet:hover { border-color: var(--c-cyan-40, var(--c-cyan)); }

/* Titre de colonne : un trait court de la couleur d'accent, qui donne un
   repère visuel sans alourdir. */
.footer__titre { position: relative; padding-bottom: var(--s-2); }

.footer__titre::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 22px;
  height: 2px;
  border-radius: 2px;
  background: var(--c-cyan);
  opacity: 0.85;
}

/* Liens : ils avancent d'un cheveu au survol, ce qui suffit à les rendre
   vivants sans les faire sauter. */
.footer ul { gap: var(--s-2); }

.footer ul li a {
  display: inline-block;
  padding-block: 2px;
  transition: color var(--dur) var(--ease), transform var(--dur) var(--ease);
}

.footer ul li a:hover { transform: translateX(3px); }

/* Contact : l'adresse et le téléphone sont ce qu'on vient chercher ici. */
.footer__grid > div:last-child ul li a {
  color: var(--c-text);
  font-weight: var(--w-medium);
}

.footer__grid > div:last-child ul li a:hover { color: var(--c-cyan); }

/* Barre du bas : la mention légale d'un côté, les liens de l'autre, séparés
   par de fins points médians plutôt que par des blancs. */
.footer__bottom { gap: var(--s-3) var(--s-5); }
.footer__bottom p { margin: 0; }

.footer__bottom .cluster { gap: var(--s-2) var(--s-3); align-items: center; }

.footer__bottom .cluster a { position: relative; padding-block: 2px; }

.footer__bottom .cluster a + a::before {
  content: "·";
  position: absolute;
  left: calc(-1 * var(--s-2));
  color: var(--c-border-strong);
}

@media (max-width: 52rem) {
  /* Sur téléphone, quatre colonnes empilées font un mur : les listes passent
     à deux colonnes, la marque garde toute la largeur. */
  .footer__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-6) var(--s-5); }
  .footer__grid > div:first-child,
  .footer__grid > div:last-child { grid-column: 1 / -1; }   /* marque et contact sur toute la largeur */
  .footer__grid > div:last-child ul { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-2) var(--s-5); }
  .footer__grid > div:last-child ul li:nth-child(n+3) { grid-column: 1 / -1; }   /* l'adresse tient sur deux lignes, pas quatre */

  /* Le point médian se retrouverait en tête de ligne quand les liens passent
     à la ligne : on le retire et on laisse l'espace faire la séparation. */
  .footer__bottom .cluster a + a::before { display: none; }
  .footer .logo--complet { max-width: 120px; }
  .footer__bottom { justify-content: flex-start; }
}

/* --- Verre dépoli : un filet de sécurité ---------------------------------
   L'en-tête, la barre de total du devis et le voile de recherche sont
   translucides et comptent sur le flou d'arrière-plan pour rester lisibles.
   Là où ce flou n'existe pas — certains navigateurs Android, Firefox quand
   l'option est coupée — ou quand la personne a demandé moins de
   transparence, le texte de la page se lisait au travers. Dans ces deux cas
   seulement, le fond redevient plein. */
@supports not ((backdrop-filter: blur(2px)) or (-webkit-backdrop-filter: blur(2px))) {
  .header,
  .header.is-scrolled,
  .total-sticky,
  .rg-voile { background: var(--c-bg); }
}

@media (prefers-reduced-transparency: reduce) {
  .header,
  .header.is-scrolled,
  .total-sticky,
  .rg-voile {
    background: var(--c-bg);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}
