/* =========================================================================
 * eki-erp — feuille de style applicative
 *
 * Architecture (cf. ADR refactor CSS 2026-05-28) :
 *   tokens.css           — design tokens --eki-* (couleurs, espacements)
 *   tokens/breakpoints   — 3 breakpoints canoniques (560 / 880 / 1080)
 *   reset.css, base.css  — reset + typo + container
 *   components/          — primitives partagées préfixées .eki-*
 *                          (.eki-card, .eki-btn, .eki-dialog, .eki-photo,
 *                          .expandable-list, .htmx-feedback, form bases)
 *   layouts/public/      — modules page par page (home, shop, contact…)
 *
 * Cette feuille est l'entrée du SITE PUBLIC. Les modules admin sont dans
 * app.admin.css, qui reprend celle-ci puis y ajoute layouts/admin/ : un
 * visiteur ne télécharge plus les 49 Ko de styles d'écrans qu'il ne verra
 * jamais, et l'admin n'a aucune règle en double.
 * Toute règle utilisée des DEUX côtés vit dans components/ — pas dans
 * layouts/admin/, d'où la famille .btn a dû être rapatriée.
 *
 * Règles de contribution (cf. CLAUDE.md §CSS) :
 *   1. Toujours un token --eki-* avant un hex en dur (sauf cas vraiment
 *      isolé — ex. badge de statut avec couleur ad hoc).
 *   2. Une nouvelle "card" compose .eki-card en plus de sa classe métier.
 *      Idem .eki-btn, .eki-dialog, .eki-photo.
 *   3. Les @media n'utilisent QUE 560 / 880 / 1080 (cf. tokens/breakpoints).
 *   4. Pas de classe orpheline : si on retire un usage, marquer @deprecated
 *      pendant 1-2 semaines avant suppression définitive.
 *   5. Une règle qui n'a aucun usage HTML est un bug — corriger ou supprimer.
 *
 * Audit/historique : split en 3 étapes (commits 418a6e9, 1f2c263, db45096),
 * finalisation étapes 4-8.
 * ========================================================================= */


/* css/fonts.css */
/* =========================================================================
 * fonts.css — Archivo (display) + Inter (corps), self-hostées.
 *
 * Elles étaient chargées depuis fonts.googleapis.com : une feuille de style
 * TIERCE et BLOQUANTE avant le premier rendu, sur une connexion à ouvrir
 * (DNS + TLS) en plus de la nôtre — et une dépendance externe de plus sur le
 * chemin critique, contraire au principe self-hosted du projet.
 *
 * Seuls les sous-ensembles `latin` et `latin-ext` sont repris : le CSS de
 * Google en propose aussi vietnamien, cyrillique et grec, que le site
 * n'affiche jamais.
 *
 * `font-display: swap` conservé : le texte s'affiche immédiatement dans la
 * police de repli puis bascule, plutôt que de rester invisible.
 *
 * Licence : Archivo et Inter sont sous SIL Open Font License 1.1, qui autorise
 * explicitement l'hébergement et la redistribution. Cf. wwwroot/fonts/LICENSE.
 * ========================================================================= */

@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/fonts/archivo-500-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/fonts/archivo-500-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/fonts/archivo-600-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/fonts/archivo-600-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/fonts/archivo-700-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/fonts/archivo-700-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url('/fonts/archivo-800-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url('/fonts/archivo-800-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/inter-400-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/inter-400-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/fonts/inter-500-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/fonts/inter-500-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/fonts/inter-600-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/fonts/inter-600-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}


/* css/tokens.css */
/*
 * tokens.css — Design tokens EKI®
 * Source de vérité couleurs/typo/espacements partagée entre :
 *   - site web (ici)
 *   - PDF QuestPDF (via EkiBranding côté C#)
 *   - emails transactionnels
 *   - plaquette commerciale + catalogue tarifaire
 *
 * Couleur de marque : rouge vermillon RAL 2002 (#CB2821),
 * identique à la finition thermolaquée des tables EKI® physiques.
 *
 * Dark mode : par défaut on respecte `prefers-color-scheme` via la fonction CSS
 * `light-dark()` (Chromium 123+, Firefox 121+, Safari 17.5+). Le sélecteur du pied
 * de page (Auto / Clair / Sombre) force light ou dark via `<html data-theme="…">`
 * (cf. wwwroot/js/theme-toggle.js). Sans attribut data-theme (état "auto"), le
 * comportement système est préservé.
 * Cf. docs/design-guidelines.md §6 (rouge dark validé : oklch(62% 0.19 26)).
 */

:root {
  /* Permet à light-dark() de fonctionner ET annonce au navigateur que la page
     supporte les deux modes (cookies, scrollbars natives, etc. s'adaptent). */
  color-scheme: light dark;

  /* === Couleurs marque (immuables, identiques light et dark) === */
  --eki-red: #CB2821;                                     /* RAL 2002, identité visuelle physique */
  --eki-red-dark: #9F1D1A;
  --eki-red-light: #E94B3F;

  /* === Grays primitifs (rarement utilisés directement — préférer les sémantiques) === */
  --eki-black: #1a1a1a;
  --eki-gray-900: light-dark(#2a2a2a, #e2e2e2);
  --eki-gray-700: light-dark(#555555, #9b9ba0);
  --eki-gray-500: light-dark(#888888, #6e6e74);
  --eki-gray-300: light-dark(#cccccc, #3a3a3e);
  --eki-gray-200: light-dark(#e2e2e2, #28282b);
  --eki-gray-100: light-dark(#f5f5f5, #161618);
  --eki-white: #ffffff;

  /* === Surfaces sémantiques (s'adaptent au mode) === */
  --eki-bg:         light-dark(#ffffff, #0d0d0e);
  --eki-bg-alt:     light-dark(#f5f5f5, #161618);
  --eki-bg-elev:    light-dark(#ffffff, #1c1c1f);          /* cards, dialog, popover */
  --eki-text:       light-dark(#1a1a1a, #f0f0f1);
  --eki-text-muted: light-dark(#555555, #9b9ba0);
  --eki-border:     light-dark(#cccccc, #28282b);

  /* === Surface "inversée" : zones marketing volontairement contrastées (topbar,
     trust bar). Couleurs FIXES, ne suivent pas le thème. Permettent de garder un
     bandeau sombre identifiable même en dark mode. === */
  --eki-inverse-bg:        #1a1a1a;
  --eki-inverse-bg-elev:   #242427;
  --eki-inverse-fg:        rgba(255, 255, 255, 0.92);
  --eki-inverse-fg-muted:  rgba(255, 255, 255, 0.65);
  --eki-inverse-border:    rgba(255, 255, 255, 0.12);

  /* === Accents UI dérivés (s'adaptent au mode) ===
     En OKLCH (perceptuellement uniforme), on monte la luminosité L de 54% → 62%
     en dark pour éviter la vibration sur fond sombre. Hue 26° reste constant. */
  --eki-accent:        light-dark(#CB2821, oklch(62% 0.19 26));
  --eki-accent-strong: light-dark(#9F1D1A, oklch(68% 0.17 26));

  /* === Status (montés en luminosité pour dark) === */
  --eki-success: light-dark(#2e7d32, #4caf50);
  --eki-warning: light-dark(#ed6c02, #ffa726);
  --eki-error:   light-dark(#c62828, #ef5350);
  --eki-info:    light-dark(#0277bd, #29b6f6);

  /* === Typographie === */
  --eki-font-display: "Archivo", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --eki-font-body: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --eki-font-mono: ui-monospace, SFMono-Regular, "Cascadia Code", Consolas, monospace;

  /* Échelle modulaire 1.25 (Major Third) */
  --eki-fs-xs: 0.75rem;
  --eki-fs-sm: 0.875rem;
  --eki-fs-base: 1rem;
  --eki-fs-lg: 1.125rem;
  --eki-fs-xl: 1.5rem;
  --eki-fs-2xl: 2rem;
  --eki-fs-3xl: 3rem;
  --eki-fs-4xl: 4.5rem;

  --eki-lh-tight: 1.1;
  --eki-lh-normal: 1.5;
  --eki-lh-loose: 1.75;

  /* === Espacements (échelle 4px, alignée Tailwind) === */
  --eki-space-1:  0.25rem; /*  4px */
  --eki-space-2:  0.5rem;  /*  8px */
  --eki-space-3:  0.75rem; /* 12px */
  --eki-space-4:  1rem;    /* 16px */
  --eki-space-5:  1.25rem; /* 20px */
  --eki-space-6:  1.5rem;  /* 24px */
  --eki-space-7:  1.75rem; /* 28px */
  --eki-space-8:  2rem;    /* 32px */
  --eki-space-9:  2.25rem; /* 36px */
  --eki-space-10: 2.5rem;  /* 40px */
  --eki-space-12: 3rem;    /* 48px */
  --eki-space-16: 4rem;    /* 64px */
  --eki-space-24: 6rem;    /* 96px */

  /* === Bordures et coins === */
  --eki-radius-sm: 4px;
  --eki-radius-md: 8px;
  --eki-radius-lg: 16px;

  /* === Ombres === */
  --eki-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
  --eki-shadow-md: 0 4px 12px rgba(0, 0, 0, 0.1);
  --eki-shadow-lg: 0 10px 30px rgba(0, 0, 0, 0.15);

  /* === Transitions === */
  --eki-transition-fast: 100ms ease;
  --eki-transition: 200ms ease;
  --eki-transition-slow: 400ms ease;

  /* === Layout === */
  --eki-container-max: 1280px;
  --eki-content-max: 720px;
  /* Hauteur du bandeau collant AU REPOS (barre de contact 3rem + navigation ~4rem). Il se compacte
     au défilement, donc tout élément qui se cale dessus — sommaire fixé, marge d'ancre — doit
     prendre cette valeur haute : le reste du temps il gagne de l'air, alors qu'une valeur basse le
     ferait passer sous la barre tant qu'elle n'est pas réduite. */
  --eki-header-height: 7rem;
  /* Hauteur du même bandeau une fois COMPACTÉ (la barre de contact se replie au défilement).
     C'est la valeur à utiliser pour ce qui ne s'affiche qu'après avoir défilé. */
  --eki-header-height-compact: 4rem;
}

/* === Override du mode via le sélecteur du pied de page (cf. theme-toggle.js) ===
   Sans data-theme : color-scheme:"light dark" actif → light-dark() suit
   prefers-color-scheme. Avec data-theme : on force un mode. */
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"]  { color-scheme: dark;  }


/* css/tokens/breakpoints.css */
/* =========================================================================
 * tokens/breakpoints.css — 3 breakpoints canoniques
 *
 * On ramène les ~6 valeurs ad hoc historiques (540 / 560 / 720 / 860 / 880 /
 * 980) à un jeu cohérent de 3 seuils qui couvrent l'essentiel des usages
 * responsive du site :
 *
 *   --bp-sm: 560px   téléphone large (au-delà : on commence à pouvoir
 *                    afficher 2 colonnes dans une zone étroite)
 *   --bp-md: 880px   tablette / petit laptop (passage 1-col -> 2-col
 *                    pour la majorité des layouts marketing/admin)
 *   --bp-lg: 1080px  desktop (au-delà : tous les labels nav + grilles
 *                    4-col confortables)
 *
 * Important : ces tokens sont *documentaires*. Les `@media (max-width: ...)`
 * n'acceptent pas (encore) de var() de manière universelle, on les laisse
 * donc en littéral pixel dans les feuilles. La règle de contribution est :
 *
 *   "Tout `@media` n'utilise QUE 560 / 880 / 1080 — sinon on perd la
 *    cohérence du système et on accumule la dette."
 *
 * Cf. ADR refactor CSS 2026-05-28 (étape 4).
 * ========================================================================= */

:root {
  --bp-sm: 560px;
  --bp-md: 880px;
  --bp-lg: 1080px;
}


/* css/reset.css */
/*
 * reset.css — Reset moderne, inspiré de modern-normalize + Josh Comeau's reset.
 * Choix : box-sizing border-box, marges 0 par défaut, héritage typo cohérent.
 */

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

* {
  margin: 0;
}

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  tab-size: 4;
}

body {
  line-height: var(--eki-lh-normal);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

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

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

p, h1, h2, h3, h4, h5, h6 {
  overflow-wrap: break-word;
}

#root, #__next {
  isolation: isolate;
}

button {
  cursor: pointer;
  background: none;
  border: none;
}

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

table {
  border-collapse: collapse;
  border-spacing: 0;
}

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


/* css/base.css */
/*
 * base.css — Typographie et structure communes.
 */

html {
  font-size: 16px;
}

body {
  font-family: var(--eki-font-body);
  font-size: var(--eki-fs-base);
  color: var(--eki-text);
  background-color: var(--eki-bg);
  min-height: 100vh;
}

h1, h2, h3, h4, h5, h6 {
  font-family: var(--eki-font-display);
  font-weight: 700;
  line-height: var(--eki-lh-tight);
  color: var(--eki-text);
}

h1 { font-size: var(--eki-fs-4xl); }
h2 { font-size: var(--eki-fs-3xl); }
h3 { font-size: var(--eki-fs-2xl); }
h4 { font-size: var(--eki-fs-xl); }
h5 { font-size: var(--eki-fs-lg); }
h6 { font-size: var(--eki-fs-base); }

p {
  margin-block-end: var(--eki-space-4);
}

a {
  color: var(--eki-accent);
  transition: color var(--eki-transition);
}

a:hover {
  color: var(--eki-red-dark);
}

code, pre, kbd, samp {
  font-family: var(--eki-font-mono);
  font-size: 0.95em;
}

code {
  background-color: var(--eki-gray-100);
  padding: 0 var(--eki-space-1);
  border-radius: var(--eki-radius-sm);
}

strong {
  font-weight: 600;
}

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

.content {
  max-width: var(--eki-content-max);
  margin-inline: auto;
}

/* Visually hidden — accessibilité pour les libellés screen-reader */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Le sélecteur de thème vit dans le pied de page (cf. layouts/public/footer.css). */


/* css/components/card.css */
/* =========================================================================
 * card.css — primitive .eki-card
 *
 * À utiliser comme classe de base sur le markup, et composer avec des
 * modificateurs ou des classes scope-locales si besoin :
 *   <div class="eki-card eki-card--primary contact-card">
 *
 * Étape 2 du refactor CSS (cf. ADR-style commit 418a6e9).
 * ========================================================================= */

.eki-card {
  background: var(--eki-bg);
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-md);
  padding: var(--eki-space-6);
  display: flex;
  flex-direction: column;
  gap: var(--eki-space-3);
}

.eki-card--muted {
  background: var(--eki-bg-alt);
}

.eki-card--primary {
  border-color: var(--eki-accent);
}

.eki-card > * { margin: 0; }


/* css/components/button.css */
/* =========================================================================
 * button.css — primitive .eki-btn
 *
 * À utiliser comme classe de base sur le markup, et composer avec des
 * modificateurs ou des classes scope-locales si besoin :
 *   <button class="eki-btn eki-btn--primary deal-submit">
 *
 * Étape 2 du refactor CSS (cf. ADR-style commit 418a6e9).
 * ========================================================================= */

.eki-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--eki-space-2);
  padding: var(--eki-space-3) var(--eki-space-5);
  font: inherit;
  font-weight: 500;
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-sm);
  background: var(--eki-bg);
  color: var(--eki-text);
  text-decoration: none;
  cursor: pointer;
  transition: var(--eki-transition-fast);
}

.eki-btn:hover {
  border-color: var(--eki-accent);
  color: var(--eki-accent);
}

.eki-btn:focus-visible {
  outline: 2px solid var(--eki-accent);
  outline-offset: 2px;
}

.eki-btn--primary {
  background: var(--eki-accent);
  border-color: var(--eki-accent);
  color: var(--eki-white, #ffffff);
}
.eki-btn--primary:hover {
  background: var(--eki-red-dark);
  border-color: var(--eki-red-dark);
  color: var(--eki-white, #ffffff);
}

.eki-btn--danger {
  background: transparent;
  border-color: #b91c1c;
  color: #b91c1c;
}
.eki-btn--danger:hover {
  background: #b91c1c;
  color: #ffffff;
}

.eki-btn--ghost {
  background: transparent;
  border-color: transparent;
  color: var(--eki-text);
}
.eki-btn--ghost:hover {
  color: var(--eki-accent);
  background: transparent;
  border-color: transparent;
}

.eki-btn--sm {
  padding: var(--eki-space-2) var(--eki-space-3);
  font-size: var(--eki-fs-sm);
}


/* =========================================================================
 * Famille .btn / .btn-primary / .btn-danger / .btn-link / .btn-small
 *
 * Rapatriée de layouts/admin/ le 2026-07-31. Elle y était définie alors que
 * VINGT-DEUX pages publiques s'en servent (bouton d'ajout au panier, connexion,
 * tous les CTA de formulaire) : la feuille admin ne pouvait donc pas être
 * retirée du bundle public sans dépouiller la vitrine. Ces règles sont
 * partagées, leur place est ici.
 *
 * Coexiste avec la primitive .eki-btn ci-dessus, qui est la cible du refactor ;
 * la famille .btn est l'existant, encore majoritaire dans le markup.
 * ========================================================================= */

/* === Boutons ===
   Box partagée entre .btn (secondary) et .btn-primary (primary).
   `border: 1px solid transparent` est posée d'office pour réserver l'épaisseur —
   sans ça, .btn et .btn-primary auraient 2px d'écart de hauteur. Les variants
   ajustent juste background/border-color.
   Convention : toujours poser une classe explicite (.btn / .btn-primary / .btn-danger
   / .btn-link / .btn-icon / .btn-small) sur chaque <button>. Pas de style par défaut
   sur button[type="submit"] (supprimé 2026-05-27 — anti-pattern). */

.btn,
.btn-primary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: var(--eki-space-3) var(--eki-space-6);
  border: 1px solid transparent;
  border-radius: var(--eki-radius-sm);
  font-size: var(--eki-fs-base);
  font-weight: 500;
  line-height: 1.4;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--eki-transition-fast), color var(--eki-transition-fast), border-color var(--eki-transition-fast);
}

.btn {
  background: var(--eki-bg-alt);
  color: var(--eki-text);
  border-color: var(--eki-border);
}

.btn:hover {
  background: var(--eki-border);
}

.btn-primary {
  background: var(--eki-accent);
  color: var(--eki-white);
}

.btn-primary:hover {
  background: var(--eki-red-dark);
}

.btn-danger {
  display: inline-block;
  padding: var(--eki-space-3) var(--eki-space-6);
  background: transparent;
  color: var(--eki-error);
  border: 1px solid var(--eki-error);
  border-radius: var(--eki-radius-sm);
  font-size: var(--eki-fs-base);
  font-weight: 500;
  cursor: pointer;
  transition: var(--eki-transition);
  margin-left: auto;
}

.btn-danger:hover {
  background: var(--eki-error);
  color: var(--eki-white);
}

.btn-link {
  display: inline-block;
  padding: var(--eki-space-2) var(--eki-space-3);
  background: transparent;
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-sm);
  color: var(--eki-text);
  font-size: var(--eki-fs-sm);
  text-decoration: none;
  cursor: pointer;
  transition: var(--eki-transition-fast);
}

.btn-link:hover {
  border-color: var(--eki-accent);
  color: var(--eki-accent);
}
/* Bouton compact pour les sous-formulaires denses (valeurs d'un axe de variation). */
.btn-small {
  padding: var(--eki-space-1) var(--eki-space-3);
  font-size: var(--eki-fs-sm);
  line-height: 1.2;
}


/* css/components/dialog.css */
/* =========================================================================
 * dialog.css — primitive .eki-dialog
 *
 * À utiliser comme classe de base sur le markup, et composer avec des
 * modificateurs ou des classes scope-locales si besoin :
 *   <dialog class="eki-dialog deal-public-dialog">
 *
 * Étape 2 du refactor CSS (cf. ADR-style commit 418a6e9).
 * ========================================================================= */

.eki-dialog {
  margin: auto;
  border: none;
  border-radius: var(--eki-radius-md);
  padding: var(--eki-space-6);
  max-width: 540px;
  width: calc(100% - 2 * var(--eki-space-4));
  background: var(--eki-bg);
  color: var(--eki-text);
  box-shadow: 0 24px 64px rgba(0, 0, 0, 0.25);
}

.eki-dialog::backdrop {
  background: rgba(0, 0, 0, 0.55);
}

.eki-dialog__title {
  margin: 0 0 var(--eki-space-3);
  font-size: var(--eki-fs-xl);
  border: none;
  padding: 0;
}

.eki-dialog__intro {
  margin: 0 0 var(--eki-space-3);
  color: var(--eki-text-muted);
  font-size: var(--eki-fs-sm);
}

.eki-dialog__actions {
  display: flex;
  gap: var(--eki-space-3);
  justify-content: flex-end;
  flex-wrap: wrap;
  margin-top: var(--eki-space-4);
}


/* css/components/photo-widget.css */
/* =========================================================================
 * photo-widget.css — primitive .eki-photo
 *
 * Widget photo unifié : remplace les 3 widgets dupliqués
 *   - .photo-section / .photo-preview / .photo-section-actions     (products)
 *   - .manufacturing-photo-widget / -title / -content / -thumb /
 *     -placeholder / -actions                                      (manufacturing)
 *   - .manufacturing-list-thumb (mode --xs inline)                  (manufacturing)
 *
 * Structure BEM :
 *   <section class="eki-photo eki-photo--section eki-photo--md">
 *     <h4 class="eki-photo__title">Photo</h4>
 *     <img class="eki-photo__thumb" src="…" />
 *     <div class="eki-photo__placeholder">📷</div>
 *     <div class="eki-photo__actions">…</div>
 *   </section>
 *
 * Modificateurs :
 *   --xs        thumbnail 28×28 inline (pour les listes composants/ressources)
 *   --sm        thumbnail 96×96
 *   --md        thumbnail 160×160 (défaut)
 *   --lg        thumbnail 256×256
 *   --section   layout vertical avec titre, séparé par border-top dashed
 *   --inline    rend l'ensemble inline-block (à combiner avec --xs)
 *
 * Étape 3 du refactor CSS (cf. commits 418a6e9, 1f2c263).
 * ========================================================================= */

.eki-photo {
  display: flex;
  flex-direction: row;
  gap: var(--eki-space-4);
  align-items: flex-start;
  flex-wrap: wrap;
}

.eki-photo__thumb,
.eki-photo__placeholder {
  width: 160px;
  height: 160px;
  display: block;
  object-fit: cover;
  border-radius: var(--eki-radius-sm);
  border: 1px solid var(--eki-border);
}

.eki-photo__placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 2.5rem;
  background: var(--eki-bg-alt);
  border-style: dashed;
  color: var(--eki-text-muted);
}

.eki-photo__actions {
  display: flex;
  flex-direction: column;
  gap: var(--eki-space-2);
  align-items: flex-start;
}

.eki-photo__actions form { margin: 0; }
.eki-photo__actions .form-help {
  font-size: var(--eki-fs-xs);
  color: var(--eki-text-muted);
}

.eki-photo__title {
  font-size: var(--eki-fs-sm);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--eki-text-muted);
  margin: 0 0 var(--eki-space-3);
}

/* Modificateur taille --xs : thumbnail inline 28×28, utilisable en début de
   ligne dans des listes (composants d'une étape, ressources, etc.). */
.eki-photo--xs .eki-photo__thumb,
.eki-photo--xs .eki-photo__placeholder,
.eki-photo--xs.eki-photo__thumb,
.eki-photo--xs.eki-photo__placeholder {
  width: 28px;
  height: 28px;
  font-size: var(--eki-fs-sm);
  display: inline-block;
  vertical-align: middle;
  margin-right: var(--eki-space-2);
}

.eki-photo--xs.eki-photo__placeholder {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.eki-photo--inline {
  display: inline-block;
  gap: 0;
}

.eki-photo--sm .eki-photo__thumb,
.eki-photo--sm .eki-photo__placeholder {
  width: 96px;
  height: 96px;
  font-size: var(--eki-fs-xl);
}

.eki-photo--md .eki-photo__thumb,
.eki-photo--md .eki-photo__placeholder {
  width: 160px;
  height: 160px;
}

.eki-photo--lg .eki-photo__thumb,
.eki-photo--lg .eki-photo__placeholder {
  width: 256px;
  height: 256px;
}

/* Modificateur layout --section : titre au-dessus, content en colonne. Ancien
   pattern .manufacturing-photo-widget / .photo-section. Utile dans les zones
   détail expandable d'une ligne admin. */
.eki-photo--section {
  flex-direction: column;
  margin-top: var(--eki-space-4);
  padding-top: var(--eki-space-4);
  border-top: 1px dashed var(--eki-border);
}

/* Variante --section-solid : séparateur plein (ancien .photo-section sur
   products, qui utilisait `1px solid` au lieu de dashed). */
.eki-photo--section-solid {
  flex-direction: column;
  margin-top: var(--eki-space-6);
  padding-top: var(--eki-space-4);
  border-top: 1px solid var(--eki-border);
}

/* Dans une section, on veut le titre puis le contenu (thumb + actions) en
   ligne. On enveloppe optionnellement le couple thumb/actions dans un
   .eki-photo__row pour préserver le layout horizontal sous le titre. */
.eki-photo--section .eki-photo__row {
  display: flex;
  flex-direction: row;
  gap: var(--eki-space-4);
  align-items: flex-start;
  flex-wrap: wrap;
}


/* css/components/expandable-list.css */
/* =========================================================================
 * expandable-list.css — Composants génériques : SortableHeader + liste expandable inline-edit.
 *
 * Promu depuis layouts/admin/ vers components/ (refactor CSS étape 6,
 * 2026-05-28) car utilisable au-delà de l'admin (cf. /compte/adresses).
 * ======================================================================== */

/* === Composant générique : liste avec édition expandable === */
/* Utilisable sur toutes les listes admin via <table class="expandable-list">.
   Le JS associé est /js/admin-expandable-list.js (délégation sur la table).
   Convention HTML cf. en-tête de ce JS. */

.expandable-list .expandable-tbody {
  border-bottom: 1px solid var(--eki-border);
}

.expandable-summary {
  cursor: pointer;
  transition: background var(--eki-transition-fast);
}

.expandable-summary:hover {
  background: var(--eki-bg-alt);
}

.expandable-summary > td {
  padding: var(--eki-space-3) var(--eki-space-4);
  border-bottom: none;
}

.row-chevron {
  display: inline-block;
  font-size: var(--eki-fs-base);
  color: var(--eki-text-muted);
  transition: transform 300ms ease;
}

.expandable-tbody.expanded .row-chevron {
  transform: rotate(180deg);
  color: var(--eki-accent);
}

.text-muted {
  color: var(--eki-text-muted);
  font-size: var(--eki-fs-sm);
}

/* Détail row : caché par défaut via max-height: 0 sur l'inner.
   Quand .expandable-tbody.expanded, l'inner s'ouvre via transition.
   La cellule n'a aucun padding/border pour que l'animation ne révèle rien. */

.expandable-detail-row > .expandable-detail-cell {
  padding: 0;
  border-bottom: none;
  background: var(--eki-bg-alt);
}

.expandable-detail-inner {
  max-height: 0;
  overflow: hidden;
  opacity: 0;
  transition: max-height 350ms ease, padding 350ms ease, opacity 250ms ease;
  padding: 0 var(--eki-space-6);
}

.expandable-tbody.expanded .expandable-detail-inner {
  /* État déplié non borné (max-height: none, overflow visible) : le contenu
     n'est JAMAIS clippé, quelle que soit sa hauteur — étape à plusieurs
     variantes chargées (M8/M10/M12…), ou tbody re-rendu déjà déplié après un
     swap htmx. Un plafond fixe (ancien 2000px) rouvrait toujours la falaise de
     clipping puisque overflow:hidden masquait le dépassement sans scrollbar.
     Le slide vertical (incompatible avec une hauteur non bornée) est remplacé
     par un simple fondu à l'ouverture. */
  max-height: none;
  overflow: visible;
  opacity: 1;
  padding: var(--eki-space-6);
}

.expandable-edit-form .form-row {
  margin-bottom: var(--eki-space-4);
}

.row-error {
  padding: var(--eki-space-3) var(--eki-space-4);
  margin-bottom: var(--eki-space-4);
  background: light-dark(#fee, #4a1a1a);
  border: 1px solid var(--eki-accent);
  border-radius: var(--eki-radius-sm);
  color: light-dark(#7a1a1a, #ffb3b3);
  font-size: var(--eki-fs-sm);
}

/* Bandeau neutre en tête de fiche dépliée (ex. société archivée). */
.row-archived-banner {
  padding: var(--eki-space-3) var(--eki-space-4);
  margin-bottom: var(--eki-space-4);
  background: var(--eki-bg-alt);
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-sm);
  color: var(--eki-text-muted);
  font-size: var(--eki-fs-sm);
  font-weight: 500;
}

/* Bandeau de succès en tête de fiche dépliée (ex. invitation envoyée). */
.row-notice {
  padding: var(--eki-space-3) var(--eki-space-4);
  margin-bottom: var(--eki-space-4);
  background: light-dark(#e8f5ec, #16331f);
  border: 1px solid light-dark(#9ad3ab, #2f6b41);
  border-radius: var(--eki-radius-sm);
  color: light-dark(#1c6b35, #9ad3ab);
  font-size: var(--eki-fs-sm);
  font-weight: 500;
}

.detail-metadata {
  font-family: var(--eki-font-mono);
  font-size: var(--eki-fs-sm);
  resize: vertical;
}

.expandable-edit-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--eki-space-4);
  margin-top: var(--eki-space-6);
  padding-top: var(--eki-space-4);
  border-top: 1px solid var(--eki-border);
  flex-wrap: wrap;
}



/* css/components/htmx-feedback.css */
/* =========================================================================
 * htmx-feedback.css — Feedback async htmx : .htmx-request + badge .save-confirm + animation rise.
 *
 * Promu depuis layouts/admin/ vers components/ (refactor CSS étape 6,
 * 2026-05-28) car potentiellement réutilisable sur formulaires publics
 * (avis clients, demande de rappel…).
 * ======================================================================== */

/* === Feedback async htmx ===
   Pattern recommandé NN/G + a11y + htmx 2024-2026 (cf. décision 2026-05-22) :
   - Pendant la requête : opacity baissée + cursor:wait sur le SEUL bouton qui
     a déclenché (cible le submitter via data-hx-submitter marqué par save-confirm.js,
     ou les buttons avec hx-post direct via la classe htmx-request).
     Pas de spinner — éviterait le mouvement de layout sur actions rapides, et
     le ✓ Enregistré qui apparaît après succès joue le rôle de "fin d'activité".
   - Après succès : SaveConfirmFilter ajoute HX-Trigger: saved → save-confirm.js
     écoute htmx:afterRequest et insère un span "✓ Enregistré" role="status"
     à côté du bouton, avec animation d'apparition + fade-out après 1.5s.

   Coût futur zéro : tout nouveau handler partial-retour est couvert. */

/* Buttons avec hx-post direct (Move Up/Down, ✕ Remove, etc.) : htmx leur
   ajoute automatiquement la class htmx-request pendant la requête. Pour les
   form submits le marquage est manuel et complexe → on s'en passe, le ✓
   Enregistré qui apparaît après succès joue le rôle de feedback fin. */
button.htmx-request {
  opacity: 0.6;
  pointer-events: none;
  cursor: wait;
}

/* Style "fumée qui monte" : le badge apparaît juste au-dessus du bouton cliqué
   (coords fixed calculées en JS au moment de l'insertion), monte de ~3rem et
   s'efface. Position fixed + z-index élevé pour passer au-dessus de tout. */
.save-confirm {
  position: fixed;
  z-index: 9999;
  padding: var(--eki-space-1) var(--eki-space-3);
  background: var(--eki-bg-elev);
  color: var(--eki-success);
  font-size: var(--eki-fs-sm);
  font-weight: 600;
  border: 1px solid var(--eki-success);
  border-radius: var(--eki-radius-sm);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  pointer-events: none;
  white-space: nowrap;
  /* Le translate(-50%, ...) centre le badge horizontalement sur les coords
     left/top que le JS pose au centre-haut du bouton déclencheur. */
  animation: eki-save-confirm-rise 1800ms ease-out forwards;
}

@keyframes eki-save-confirm-rise {
  0%   { opacity: 0; transform: translate(-50%, 0); }
  15%  { opacity: 1; transform: translate(-50%, -0.5rem); }
  100% { opacity: 0; transform: translate(-50%, -3rem); }
}


/* css/components/form.css */
/* =========================================================================
 * form.css — Primitives formulaire génériques.
 *
 * Promu depuis layouts/admin/forms.css vers components/ (refactor CSS
 * étape 6, 2026-05-28). On extrait les patterns réutilisables (form-row,
 * form-inline, form-fieldset, validation Razor) du scope admin.
 *
 * Les règles vraiment admin-only (.admin-form max-width, .candidate-*
 * recherche BOM htmx) restent dans layouts/admin/forms.css.
 * ======================================================================== */

/* === Une ligne de formulaire (label + input/textarea en colonne) === */

.form-row {
  display: flex;
  flex-direction: column;
  gap: var(--eki-space-2);
  margin-bottom: var(--eki-space-6);
}

.form-row label {
  font-weight: 500;
  font-size: var(--eki-fs-sm);
  color: var(--eki-text);
}

.form-row label code {
  font-family: var(--eki-font-mono);
  font-size: 0.85em;
  background: var(--eki-bg-alt);
  padding: 0.05em 0.3em;
  border-radius: var(--eki-radius-sm);
}

.form-row .required {
  color: var(--eki-accent);
}

.form-row input[type="text"],
.form-row input[type="number"],
.form-row input:not([type]),
.form-row select,
.form-row textarea {
  width: 100%;
  padding: var(--eki-space-3);
  font-size: var(--eki-fs-base);
  font-family: inherit;
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-sm);
  background: var(--eki-bg);
}

.form-row textarea {
  resize: vertical;
  min-height: 80px;
}

.form-row input:focus,
.form-row select:focus,
.form-row textarea:focus {
  outline: 2px solid var(--eki-accent);
  outline-offset: 1px;
  border-color: var(--eki-accent);
}

/* === Groupe horizontal de form-row sans sémantique fieldset === */
/* Pas de legend, pas de bordure logique. Utile pour aligner sur une ligne
   deux ou trois champs liés (ex. Nom + Coût horaire) sans payer la
   sémantique d'un fieldset. */
.form-inline {
  display: flex;
  flex-wrap: wrap;
  gap: var(--eki-space-3) var(--eki-space-6);
  align-items: flex-end;
  margin: var(--eki-space-5) 0;
}

.form-inline > .form-row {
  margin: 0;
  flex: 0 0 auto;
}

.form-inline > .form-row--grow {
  flex: 1 1 12rem;
}

/* === Groupement logique de champs (dimensions, etc.) === */
/* Style sobre — pas de border lourde, juste un legend en sm + un petit
   padding-top. Layout flex pour disposer les form-rows en ligne (ex.
   dimensions/poids : 4 inputs courts côte à côte au lieu de 4 lignes
   pleine largeur). Le legend en width:100% force un retour ligne, les
   form-rows wrap au besoin. */
.form-fieldset {
  border: none;
  padding: 0;
  margin: var(--eki-space-6) 0 0 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--eki-space-3) var(--eki-space-6);
  align-items: flex-end;
}

.form-fieldset > legend {
  font-size: var(--eki-fs-sm);
  font-weight: 500;
  color: var(--eki-text-muted, inherit);
  padding: 0 0 var(--eki-space-2) 0;
  width: 100%;
}

.form-fieldset .form-row {
  margin: 0;
  /* flex-basis 8ch = minimum lisible pour un input numérique, grow = se partage
     la largeur dispo équitablement avec les autres rows du fieldset (ex. 4 inputs
     dimensions/poids s'étalent au lieu de rester collés à gauche). */
  flex: 1 1 8ch;
}

.form-fieldset input[type="number"] {
  width: 100%;
}

/* === Barre d'actions de formulaire === */

.form-actions {
  display: flex;
  align-items: center;
  gap: var(--eki-space-4);
  margin-top: var(--eki-space-8);
  padding-top: var(--eki-space-4);
  border-top: 1px solid var(--eki-border);
}

/* === Validation et erreurs (Razor + ASP.NET) === */

.admin-error,
.field-validation-error,
.validation-summary-errors {
  color: var(--eki-error);
  font-size: var(--eki-fs-sm);
  margin-top: var(--eki-space-1);
}

.validation-summary-errors ul {
  margin: 0;
  padding-left: var(--eki-space-4);
}

.input-validation-error {
  border-color: var(--eki-error) !important;
}


/* css/components/address-autocomplete.css */
/* === Autocomplétion d'adresse (Géoplateforme/BAN) ===
 * Dropdown de suggestions rendu sous un <input data-ban-autocomplete>, inséré
 * dans son <label> parent (rendu positionné en relatif). Cf. address-autocomplete.js. */

.public-form label:has(> input[data-ban-autocomplete]),
.form-row:has(> input[data-ban-autocomplete]) {
  position: relative;
}

.eki-autocomplete {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 30;
  margin: var(--eki-space-1) 0 0;
  padding: var(--eki-space-1);
  list-style: none;
  background: var(--eki-bg-elev);
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-md);
  box-shadow: var(--eki-shadow-md);
  max-height: 16rem;
  overflow-y: auto;
}

.eki-autocomplete-item {
  padding: var(--eki-space-2) var(--eki-space-3);
  font-size: var(--eki-fs-sm);
  color: var(--eki-text);
  border-radius: var(--eki-radius-sm);
  cursor: pointer;
}

.eki-autocomplete-item.is-active,
.eki-autocomplete-item:hover {
  background: var(--eki-bg-alt);
}


/* css/components/help.css */
/* =========================================================================
 * help.css — aide admin : déclencheur « ? », drawer contextuel, hub /admin/help.
 * Le contenu d'un sujet (.help-topic) est partagé entre le hub et le drawer.
 * ========================================================================= */

/* --- Déclencheur « ? » --- */
.help-trigger {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.5rem;
  height: 1.5rem;
  padding: 0;
  border: 1px solid var(--eki-border);
  border-radius: 50%;
  background: var(--eki-bg-alt);
  color: var(--eki-text-muted);
  font-size: var(--eki-fs-sm);
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
  vertical-align: middle;
}
.help-trigger:hover,
.help-trigger:focus-visible {
  border-color: var(--eki-accent);
  color: var(--eki-accent);
}
.help-trigger--inline {
  cursor: default; /* purement illustratif dans le lead du hub */
}

/* --- Drawer (slide-over droit, compose la primitive .eki-dialog) --- */
.help-drawer {
  /* neutralise le centrage de .eki-dialog : panneau ancré à droite, flottant
     (petit espace sur les 4 côtés) pour des coins arrondis visibles partout.
     Positionnement fixed explicite, indépendant du mode modal/non-modal. */
  position: fixed;
  inset: var(--eki-space-4) var(--eki-space-4) var(--eki-space-4) auto;
  margin: 0;
  max-width: 480px;
  width: min(480px, calc(100% - 2 * var(--eki-space-4)));
  height: auto;
  max-height: calc(100dvh - 2 * var(--eki-space-4));
  border-radius: var(--eki-radius-lg);
  padding: 0;
  overflow: hidden; /* clippe le contenu (chrome + scroll) aux coins arrondis */
}
/* display UNIQUEMENT à l'état ouvert : sinon une règle auteur écrase le
   `dialog:not([open]) { display:none }` du navigateur et le panneau reste affiché. */
.help-drawer[open] {
  display: flex;
  flex-direction: column;
}
.help-drawer__chrome {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: space-between;
  padding: var(--eki-space-4) var(--eki-space-6);
  border-bottom: 1px solid var(--eki-border);
  background: var(--eki-bg);
}
.help-drawer__eyebrow {
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-size: var(--eki-fs-sm);
  font-weight: 700;
  color: var(--eki-accent);
}
.help-drawer__close {
  padding: 0 var(--eki-space-2);
  border: none;
  background: none;
  font-size: var(--eki-fs-xl);
  line-height: 1;
  color: var(--eki-text-muted);
  cursor: pointer;
}
.help-drawer__close:hover {
  color: var(--eki-text);
}
.help-drawer__body {
  flex: 1 1 auto;
  min-height: 0;
  padding: var(--eki-space-6);
  overflow-y: auto;
}

/* --- Contenu d'un sujet (partagé hub + drawer) --- */
.help-topic {
  margin-bottom: var(--eki-space-8);
}
.help-topic:last-child {
  margin-bottom: 0;
}
.help-topic__title {
  margin: 0 0 var(--eki-space-4);
  font-size: var(--eki-fs-lg);
  color: var(--eki-text);
}
.help-topic__block {
  margin-bottom: var(--eki-space-5);
}
.help-topic__block:last-child {
  margin-bottom: 0;
}
.help-topic__block h4 {
  margin: 0 0 var(--eki-space-2);
  font-size: var(--eki-fs-sm);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--eki-accent);
}
.help-topic dl {
  margin: 0;
  font-size: var(--eki-fs-sm);
  line-height: 1.5;
}
/* Mise en garde : une règle qu'on ne peut pas rattraper après coup (code GS1 diffusé, document
   émis). Détachée du texte courant pour qu'elle ne se lise pas comme une précision de plus. */
.help-topic__note {
  margin: var(--eki-space-3) 0 0;
  padding: var(--eki-space-3);
  border-left: 3px solid var(--eki-accent);
  background: var(--eki-bg-alt);
  font-size: var(--eki-fs-sm);
  line-height: 1.5;
  color: var(--eki-text-muted);
}
.help-topic dt {
  margin-top: var(--eki-space-3);
  font-weight: 600;
  color: var(--eki-text);
}
.help-topic dt:first-of-type {
  margin-top: 0;
}
.help-topic dd {
  margin: var(--eki-space-1) 0 0;
  color: var(--eki-text-muted);
}
.help-topic ol {
  margin: 0;
  padding-left: var(--eki-space-5);
  font-size: var(--eki-fs-sm);
  line-height: 1.6;
  color: var(--eki-text-muted);
}
.help-topic ol li {
  margin-bottom: var(--eki-space-2);
}
.help-topic ol li strong,
.help-topic dd strong {
  color: var(--eki-text);
}

/* --- Hub /admin/help --- */
.help-hub__lead {
  max-width: 70ch;
  margin-bottom: var(--eki-space-6);
  color: var(--eki-text-muted);
}
.help-hub__toc {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--eki-space-5);
  padding: var(--eki-space-5);
  margin-bottom: var(--eki-space-8);
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-md);
  background: var(--eki-bg-alt);
}
.help-hub__toc-group strong {
  display: block;
  margin-bottom: var(--eki-space-2);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-size: var(--eki-fs-sm);
  color: var(--eki-accent);
}
.help-hub__toc-group ul {
  margin: 0;
  padding-left: var(--eki-space-4);
  font-size: var(--eki-fs-sm);
}
.help-hub__domain {
  margin-bottom: var(--eki-space-10);
}
.help-hub__domain-title {
  margin-bottom: var(--eki-space-5);
  padding-bottom: var(--eki-space-2);
  font-size: var(--eki-fs-xl);
  border-bottom: 1px solid var(--eki-border);
}


/* css/components/bulk-save.css */
/* bulk-save.css — bouton flottant « Tout enregistrer » (cf. admin-bulk-save.js).
   Visible uniquement quand des formulaires [data-bulk-save] ont des modifs non
   enregistrées. Positionné en bas à droite, hors du flux. */

.bulk-save-fab {
    position: fixed;
    right: 1.5rem;
    bottom: 1.5rem;
    z-index: 1000;
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.75rem 1.25rem;
    font: inherit;
    font-weight: 600;
    color: #fff;
    background: var(--eki-red, #CB2821);
    border: none;
    border-radius: 999px;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25);
    cursor: pointer;
    transition: transform 0.12s ease, box-shadow 0.12s ease, opacity 0.12s ease;
}

/* L'attribut [hidden] doit l'emporter sur le display:inline-flex ci-dessus. */
.bulk-save-fab[hidden] {
    display: none;
}

.bulk-save-fab:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
}

.bulk-save-fab:focus-visible {
    outline: 2px solid #fff;
    outline-offset: 2px;
}

.bulk-save-fab:disabled {
    opacity: 0.7;
    cursor: default;
    transform: none;
}

@media (max-width: 640px) {
    .bulk-save-fab {
        right: 1rem;
        bottom: 1rem;
        padding: 0.6rem 1rem;
    }
}


/* css/layouts/public/_index.css */
/* =========================================================================
 * _index.css — Agrégateur des sous-fichiers du layout public.
 * L'ordre des @import respecte la cascade originale de layouts/public.css.
 * ======================================================================== */


/* css/layouts/public/_header.css */
/* =========================================================================
 * _header.css — Topbar + nav primaire + dropdown + mega-menu + actions + hamburger + drawer mobile.
 * Issu du split de layouts/public.css (refactor CSS étape 1, 2026-05-28).
 * ======================================================================== */

/* =====================================================================
 * Header refondu (3 niveaux : topbar + main + drawer mobile).
 * Inspiré best practices Baymard / NN/g 2024-2026, pattern Manutan /
 * Festool / Würth adapté à un fabricant français direct.
 * ===================================================================== */

.site-header {
  position: sticky;
  inset-block-start: 0;
  z-index: 50;
  background-color: var(--eki-bg);
  border-block-end: 1px solid var(--eki-border);
  transition: box-shadow 200ms;
}

.site-header.is-scrolled {
  box-shadow: 0 1px 6px rgba(0,0,0,.06);
}

/* ----- Top thin bar (signaux de réassurance) ----- */

.site-topbar {
  background-color: var(--eki-inverse-bg);
  color: var(--eki-inverse-fg);
  font-size: var(--eki-fs-xs);
  transition: max-height 200ms, padding 200ms;
  max-height: 3rem;
  overflow: hidden;
}

.site-header.is-scrolled .site-topbar {
  max-height: 0;
}

.site-topbar-inner {
  max-width: var(--eki-container-max);
  margin-inline: auto;
  padding: var(--eki-space-2) var(--eki-space-4);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--eki-space-4) var(--eki-space-6);
}

.site-topbar-item {
  display: inline-flex;
  align-items: center;
  gap: var(--eki-space-2);
  color: inherit;
  text-decoration: none;
}

.site-topbar-item .ico {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
}

.site-topbar-item:hover {
  color: var(--eki-red-light);
}

@media (max-width: 880px) {
  .site-topbar-tagline { display: none; }
}

/* ----- Main row (logo / nav / actions) ----- */

.site-header-main {
  background: var(--eki-bg);
}

.site-header-inner {
  max-width: var(--eki-container-max);
  margin-inline: auto;
  padding: var(--eki-space-3) var(--eki-space-4);
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: var(--eki-space-6);
  transition: padding 200ms;
}

.site-header.is-scrolled .site-header-inner {
  padding-block: var(--eki-space-2);
}

.site-brand {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
}

.site-brand-logo {
  height: 2.25rem;
  width: auto;
  display: block;
  transition: height 200ms;
}

.site-header.is-scrolled .site-brand-logo {
  height: 1.75rem;
}

/* ----- Nav primaire desktop ----- */

.site-nav {
  justify-self: center;
}

.site-nav-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  align-items: center;
  gap: var(--eki-space-1);
}

.site-nav-item {
  position: relative;
}

.site-nav-link {
  display: inline-flex;
  align-items: center;
  gap: var(--eki-space-1);
  padding: var(--eki-space-3) var(--eki-space-4);
  font-size: var(--eki-fs-md);
  font-weight: 500;
  color: var(--eki-text);
  text-decoration: none;
  border-radius: var(--eki-radius-sm);
}

.site-nav-link:hover,
.site-nav-link[aria-expanded="true"] {
  color: var(--eki-red);
}

.site-nav-caret {
  width: 10px;
  height: 10px;
  transition: transform 150ms;
}

.site-nav-item:hover .site-nav-caret,
.site-nav-link[aria-expanded="true"] .site-nav-caret {
  transform: rotate(180deg);
}

/* ----- Dropdown simple (Entreprise) ----- */

.site-nav-dropdown {
  list-style: none;
  margin: 0;
  padding: var(--eki-space-2) 0;
  position: absolute;
  inset-block-start: 100%;
  inset-inline-start: 0;
  min-width: 14rem;
  background: var(--eki-bg);
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-sm);
  box-shadow: 0 8px 24px rgba(0,0,0,.08);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-4px);
  transition: opacity 150ms, transform 150ms, visibility 150ms;
}

.site-nav-item.has-dropdown:hover .site-nav-dropdown,
.site-nav-item.has-dropdown:focus-within .site-nav-dropdown {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

.site-nav-dropdown a {
  display: block;
  padding: var(--eki-space-2) var(--eki-space-4);
  font-size: var(--eki-fs-sm);
  color: var(--eki-text);
  text-decoration: none;
}

.site-nav-dropdown a:hover {
  background: var(--eki-bg-alt);
  color: var(--eki-red);
}

/* ----- Mega-menu (Boutique) ----- */

/* Le panneau est ancré sur l'item « Boutique » — c'est ce qui rend le trajet de souris
   vertical : on descend du déclencheur dans la liste des catégories, puis on va à droite.
   Il faut donc le BORNER, pas le déplacer.

   Il était large de 56rem sans borne utile : entre 881px — largeur à laquelle la nav desktop
   réapparaît — et ~1350px, son bord droit sortait du viewport. Et comme il est masqué en
   `visibility: hidden` et non `display: none`, il reste dans la zone de défilement : la page
   portait une barre de défilement horizontale MÊME MENU FERMÉ (mesuré : viewport 869,
   scrollWidth 1026).

   La borne suit la place réellement disponible à droite du déclencheur. La nav étant centrée
   dans un conteneur plafonné, cette place croît d'un demi-pixel par pixel de viewport —
   mesuré : 838px à 1219, 913px à 1369, 1013px à 1569, 1188px à 1919, soit `50vw + 228px`.
   Sous ~1000px la grille se resserre et la place tombe 40px sous cette droite ; d'où la
   constante ramenée à 180px, qui laisse en plus de quoi absorber la gouttière de barre de
   défilement que `vw` compte à tort. Le panneau atteint sa pleine largeur dès ~1420px et se
   resserre en continu en dessous — sans point de rupture supplémentaire, la feuille n'en
   admettant que trois (cf. tokens/breakpoints).

   `90vw` retiré au passage : il valait 796px pour un viewport utile de 869px. */
.megamenu {
  position: absolute;
  inset-block-start: 100%;
  inset-inline-start: 0;
  inset-inline-end: auto;
  width: 56rem;
  max-width: calc(50vw + 180px);
  background: var(--eki-bg);
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-md);
  box-shadow: 0 12px 32px rgba(0,0,0,.10);
  overflow: hidden;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-4px);
  transition: opacity 150ms, transform 150ms, visibility 150ms;
}

.site-nav-item.has-megamenu:hover .megamenu,
.site-nav-item.has-megamenu:focus-within .megamenu {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

.megamenu-grid {
  display: grid;
  grid-template-columns: 15rem minmax(0, 1fr) 16rem;
  min-height: 13rem;
}

/* Colonne 1 — catégories de premier rang, en liste verticale. */
.megamenu-roots {
  list-style: none;
  margin: 0;
  padding: var(--eki-space-3);
  border-inline-end: 1px solid var(--eki-border);
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.megamenu-root {
  display: flex;
  align-items: center;
  border-radius: var(--eki-radius-sm);
}

.megamenu-root-link {
  flex: 1 1 auto;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--eki-space-2);
  padding: var(--eki-space-2) var(--eki-space-3);
  font-size: var(--eki-fs-sm);
  font-weight: 600;
  color: var(--eki-text);
  text-decoration: none;
}

.megamenu-root-caret {
  padding-inline-end: var(--eki-space-3);
  font-size: var(--eki-fs-md);
  line-height: 1;
  color: var(--eki-text-muted);
}

.megamenu-root.is-active {
  background: var(--eki-bg-alt);
}

.megamenu-root.is-active .megamenu-root-link,
.megamenu-root.is-active .megamenu-root-caret {
  color: var(--eki-red);
}

/* Colonne 2 — sous-catégories de la racine active (une seule visible à la fois). */
.megamenu-panels {
  padding: var(--eki-space-4) var(--eki-space-5);
}

.megamenu-panel {
  list-style: none;
  margin: 0;
  padding: 0;
  display: none;
  flex-direction: column;
  gap: var(--eki-space-1);
}

.megamenu-panel.is-active {
  display: flex;
}

/* Une entrée est un bloc de deux lignes : libellé (+ compteur aligné à droite),
   puis description courte. La mise en ligne vit sur .megamenu-item-head, pas sur
   le lien lui-même — sinon la description viendrait se ranger à côté du compteur. */
.megamenu-panel a {
  display: block;
  padding: var(--eki-space-2) 0;
  font-size: var(--eki-fs-sm);
  color: var(--eki-text-muted);
  text-decoration: none;
}

.megamenu-item-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--eki-space-3);
}

.megamenu-item-title {
  color: var(--eki-text);
  font-weight: 500;
}

.megamenu-item-desc {
  display: block;
  margin-block-start: 2px;
  font-size: var(--eki-fs-xs);
  color: var(--eki-text-muted);
  line-height: 1.4;
}

.megamenu-panel a:hover .megamenu-item-title {
  color: var(--eki-red);
}

.megamenu-count {
  font-size: var(--eki-fs-xs);
  color: var(--eki-text-muted);
  font-weight: 400;
  margin-inline-start: var(--eki-space-2);
}


/* Colonne 3 — encart dynamique reprenant la racine active. */
.megamenu-promo {
  background: var(--eki-bg-alt);
  border-inline-start: 1px solid var(--eki-border);
  padding: var(--eki-space-5);
  display: flex;
  flex-direction: column;
}

.megamenu-promo-title {
  margin: 0 0 var(--eki-space-2);
  font-family: var(--eki-font-display);
  font-size: var(--eki-fs-md);
  color: var(--eki-text);
}

.megamenu-promo-text {
  flex: 1 1 auto;
  margin: 0 0 var(--eki-space-3);
  font-size: var(--eki-fs-sm);
  color: var(--eki-text-muted);
  line-height: 1.5;
}

.megamenu-promo-cta {
  display: inline-block;
  margin-block-end: var(--eki-space-2);
  font-size: var(--eki-fs-sm);
  font-weight: 600;
  color: var(--eki-red);
  text-decoration: none;
}

.megamenu-promo-cta:hover {
  text-decoration: underline;
}

.megamenu-promo-all {
  font-size: var(--eki-fs-xs);
  color: var(--eki-text-muted);
  text-decoration: underline;
}

.megamenu-promo-all:hover {
  color: var(--eki-red);
}

/* ----- Cluster droite (actions) ----- */

.site-header-actions {
  display: flex;
  align-items: center;
  gap: var(--eki-space-1);
}

.site-header-action {
  display: inline-flex;
  align-items: center;
  gap: var(--eki-space-2);
  padding: var(--eki-space-2) var(--eki-space-3);
  font-size: var(--eki-fs-sm);
  font-weight: 500;
  color: var(--eki-text);
  text-decoration: none;
  border-radius: var(--eki-radius-sm);
}

.site-header-action:hover {
  background: var(--eki-bg-alt);
  color: var(--eki-red);
}

.site-header-action .ico {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
}

.site-header-action-admin {
  color: var(--eki-red);
}

@media (max-width: 1080px) {
  .site-header-action-label { display: none; }
}

/* ----- Bouton hamburger (mobile uniquement) ----- */

.site-nav-toggle {
  display: none;
  width: 2.5rem;
  height: 2.5rem;
  background: transparent;
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-sm);
  cursor: pointer;
  padding: 0;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 4px;
}

.site-nav-toggle-bar {
  display: block;
  width: 18px;
  height: 2px;
  background: var(--eki-text);
  border-radius: 1px;
  transition: transform 200ms, opacity 200ms;
}

.site-nav-toggle[aria-expanded="true"] .site-nav-toggle-bar:nth-child(1) {
  transform: translateY(6px) rotate(45deg);
}

.site-nav-toggle[aria-expanded="true"] .site-nav-toggle-bar:nth-child(2) {
  opacity: 0;
}

.site-nav-toggle[aria-expanded="true"] .site-nav-toggle-bar:nth-child(3) {
  transform: translateY(-6px) rotate(-45deg);
}

/* ----- Breakpoint mobile ----- */

@media (max-width: 880px) {
  .site-header-inner {
    grid-template-columns: auto 1fr auto;
    gap: var(--eki-space-3);
  }
  .site-nav-toggle { display: flex; order: 1; }
  .site-brand { order: 2; justify-self: center; }
  .site-header-actions { order: 3; }
  .site-nav { display: none; }
}

/* ----- Drawer mobile slide-in ----- */

.site-drawer {
  position: fixed;
  inset-block-start: 0;
  inset-inline-start: 0;
  width: min(85vw, 22rem);
  height: 100dvh;
  background: var(--eki-bg);
  z-index: 100;
  transform: translateX(-100%);
  transition: transform 250ms ease-out;
  display: flex;
  flex-direction: column;
  box-shadow: 4px 0 24px rgba(0,0,0,.12);
}

.site-drawer.is-open {
  transform: translateX(0);
}

.site-drawer-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,.4);
  z-index: 90;
  cursor: pointer;
}

.site-drawer-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--eki-space-4);
  border-block-end: 1px solid var(--eki-border);
}

.site-drawer-title {
  font-family: var(--eki-font-display);
  font-size: var(--eki-fs-md);
  color: var(--eki-text);
}

.site-drawer-close {
  width: 2rem;
  height: 2rem;
  background: transparent;
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-sm);
  cursor: pointer;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--eki-text);
}

.site-drawer-close svg {
  width: 18px;
  height: 18px;
}

.site-drawer-nav {
  flex: 1;
  overflow-y: auto;
  padding: var(--eki-space-4);
}

.site-drawer-nav ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

.site-drawer-link {
  display: block;
  padding: var(--eki-space-3);
  font-size: var(--eki-fs-md);
  color: var(--eki-text);
  text-decoration: none;
  border-block-end: 1px solid var(--eki-bg-alt);
}

.site-drawer-link:hover,
.site-drawer-link:focus {
  background: var(--eki-bg-alt);
  color: var(--eki-red);
}

.site-drawer-link-strong {
  font-weight: 600;
  font-size: var(--eki-fs-lg);
}

.site-drawer-group {
  margin-block-start: var(--eki-space-4);
  padding-block-start: var(--eki-space-2);
  border-block-start: 1px solid var(--eki-border);
}

.site-drawer-group-title {
  display: block;
  padding: var(--eki-space-2) var(--eki-space-3);
  font-size: var(--eki-fs-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--eki-text-muted);
}

.site-drawer-group ul .site-drawer-link {
  padding-inline-start: var(--eki-space-5);
  font-size: var(--eki-fs-sm);
}

/* Accordéon catégories : racine (lien + chevron) sur une ligne, sous-catégories repliables. */
.site-drawer-cat-row {
  display: flex;
  align-items: stretch;
}

.site-drawer-group .site-drawer-cat-row .site-drawer-link {
  flex: 1 1 auto;
  padding-inline-start: var(--eki-space-3);
  font-size: var(--eki-fs-md);
}

.site-drawer-cat-toggle {
  flex: 0 0 auto;
  width: 3rem;
  background: transparent;
  border: 0;
  border-block-end: 1px solid var(--eki-bg-alt);
  color: var(--eki-text-muted);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.site-drawer-cat-toggle svg {
  width: 16px;
  height: 16px;
  transition: transform 200ms;
}

.site-drawer-cat-toggle[aria-expanded="true"] svg {
  transform: rotate(180deg);
}

.site-drawer-cat-toggle[aria-expanded="true"] {
  color: var(--eki-red);
}

.site-drawer-group .site-drawer-subcats .site-drawer-link {
  padding-inline-start: var(--eki-space-6);
  color: var(--eki-text-muted);
}

/* La section Catégories se lit comme un panneau teinté distinct des liens de nav
   simples (même fond que le pied de drawer), avec sa propre marge haut/bas. */
.site-drawer-group--categories {
  margin-block: var(--eki-space-3);
  padding: var(--eki-space-1) var(--eki-space-2) var(--eki-space-2);
  background: var(--eki-bg-alt);
  border-radius: var(--eki-radius-md);
  border-block-start: 0;
}

/* Sur le fond teinté, les filets bg-alt deviennent invisibles : on les retire. */
.site-drawer-group--categories .site-drawer-link,
.site-drawer-group--categories .site-drawer-cat-toggle {
  border-block-end: 0;
}

/* Drawer = tactile, pas de survol : le retour au doigt se joue à l'appui (:active),
   avec un fond qui contraste sur le panneau teinté. (Le focus clavier hérite du rouge
   de .site-drawer-link.) */
.site-drawer-group--categories .site-drawer-link:active,
.site-drawer-group--categories .site-drawer-cat-toggle:active {
  background: var(--eki-bg);
}

.site-drawer-foot {
  padding: var(--eki-space-4);
  border-block-start: 1px solid var(--eki-border);
  background: var(--eki-bg-alt);
  display: flex;
  flex-direction: column;
  gap: var(--eki-space-2);
}

.site-drawer-cta {
  margin-block-start: var(--eki-space-2);
  padding: var(--eki-space-3);
  background: var(--eki-red);
  color: #ffffff;
  font-weight: 600;
  text-align: center;
  text-decoration: none;
  border-radius: var(--eki-radius-sm);
}

.site-drawer-cta:hover {
  background: var(--eki-red-dark);
}

/* Second CTA du tiroir : en secondaire pour ne pas mettre deux boutons pleins
   côte à côte. On reste sur la charte plutôt que sur le vert Meta — l'icône et
   le libellé portent déjà la reconnaissance du canal. */
.site-drawer-cta-whatsapp {
  background: transparent;
  color: var(--eki-red);
  border: 1px solid var(--eki-red);
}

.site-drawer-cta-whatsapp:hover {
  background: var(--eki-red);
  color: #ffffff;
}

body.no-scroll {
  overflow: hidden;
}


/* css/layouts/public/footer.css */
/* =========================================================================
 * footer.css — Pied de page public global (cf. _Layout.cshtml).
 *
 * Surface claire sur tokens sémantiques (--eki-bg-alt / --eki-text*) : suit
 * le thème (clair en light, sombre en dark) plutôt qu'un sombre fixe. Filet
 * supérieur pour détacher du contenu. Grille marque + 3 colonnes de liens
 * qui s'effondre aux breakpoints canoniques 880 / 560.
 * ======================================================================== */

.site-footer {
  margin-block-start: var(--eki-space-24);
  border-block-start: 1px solid var(--eki-border);
  background-color: var(--eki-bg-alt);
  color: var(--eki-text-muted);
  font-size: var(--eki-fs-sm);
}

.site-footer-inner {
  max-width: var(--eki-container-max);
  margin-inline: auto;
  padding: var(--eki-space-12) var(--eki-space-4) var(--eki-space-6);
}

/* ---------- Zone haute : marque + colonnes ---------- */

.site-footer-top {
  display: grid;
  grid-template-columns: 1.6fr repeat(3, 1fr);
  gap: var(--eki-space-8);
}

.site-footer-brand {
  max-width: 34ch;
}

.site-footer-logo {
  height: 32px;
  width: auto;
  margin-block-end: var(--eki-space-4);
}

.site-footer-tagline {
  margin: 0 0 var(--eki-space-4);
  line-height: var(--eki-lh-normal);
}

.site-footer-contact {
  display: flex;
  flex-direction: column;
  gap: var(--eki-space-1);
  margin: 0;
}

.site-footer-contact a {
  color: var(--eki-text);
  font-weight: 500;
  text-decoration: none;
}

.site-footer-contact a:hover {
  color: var(--eki-red);
}

.site-footer-whatsapp {
  display: inline-flex;
  align-items: center;
  gap: var(--eki-space-2);
  align-self: flex-start;
}

.site-footer-whatsapp svg {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}

/* Libellé de colonne — élément non-titre (cf. _Layout) : on évite d'injecter
   des <h2> répétés sur tout le site dans le plan de titres (propreté SEO). */
.site-footer-title {
  margin: 0 0 var(--eki-space-3);
  font-family: var(--eki-font-display);
  font-size: var(--eki-fs-sm);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--eki-text);
}

.site-footer-col ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--eki-space-2);
}

.site-footer-col a {
  color: var(--eki-text-muted);
  text-decoration: none;
}

.site-footer-col a:hover {
  color: var(--eki-text);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* ---------- Zone basse : mentions légales + version ---------- */

.site-footer-bottom {
  margin-block-start: var(--eki-space-8);
  padding-block-start: var(--eki-space-6);
  border-block-start: 1px solid var(--eki-border);
}

/* Préférence d'affichage. Elle était en bouton flottant fixé en bas à droite : il
   recouvrait le « Haut de page » du guide, et un réglage consulté une fois n'a pas
   à occuper un coin de l'écran en permanence. Le pied de page est l'emplacement
   attendu pour ce type de préférence — c'est aussi là qu'atterrira le choix de
   langue (cf. ADR-039), d'où le bloc `prefs` plutôt qu'une classe dédiée au thème. */
.site-footer-prefs {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--eki-space-3);
  margin-block-end: var(--eki-space-4);
  font-size: var(--eki-fs-xs);
  color: var(--eki-gray-500);
}

.theme-switch {
  display: inline-flex;
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-md);
  overflow: hidden;
}

.theme-switch button {
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--eki-text-muted);
  font: inherit;
  padding: 0 var(--eki-space-3);
  min-height: 36px;
  cursor: pointer;
  transition: background var(--eki-transition-fast),
              color var(--eki-transition-fast);
}

.theme-switch button + button {
  border-inline-start: 1px solid var(--eki-border);
}

.theme-switch button:hover {
  background: var(--eki-bg-alt);
  color: var(--eki-text);
}

.theme-switch button[aria-pressed="true"] {
  background: var(--eki-bg-alt);
  color: var(--eki-text);
  font-weight: 600;
}

.theme-switch button:focus-visible {
  outline: 2px solid var(--eki-accent);
  outline-offset: -2px;
}

.site-footer-admin {
  margin: 0 0 var(--eki-space-3);
  color: var(--eki-text);
}

.site-footer-admin a {
  color: var(--eki-accent);
}

.site-footer-legal {
  margin: 0 0 var(--eki-space-3);
  font-size: var(--eki-fs-xs);
  line-height: var(--eki-lh-normal);
  color: var(--eki-gray-500);
}

.site-footer-meta {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--eki-space-2);
  margin: 0;
  font-size: var(--eki-fs-xs);
  color: var(--eki-gray-500);
}

.site-footer-version {
  font-family: var(--eki-font-mono);
}

.site-footer-version code {
  background: var(--eki-gray-200);
  color: var(--eki-text-muted);
  padding: 0 var(--eki-space-1);
  border-radius: var(--eki-radius-sm);
}

/* Tablette : 3 colonnes de liens, marque en pleine largeur au-dessus. */
@media (max-width: 880px) {
  .site-footer-top {
    grid-template-columns: repeat(3, 1fr);
  }

  .site-footer-brand {
    grid-column: 1 / -1;
    max-width: none;
  }
}

/* Mobile : tout en pile. */
@media (max-width: 560px) {
  .site-footer-top {
    grid-template-columns: 1fr;
    gap: var(--eki-space-6);
  }

  .site-footer-meta {
    flex-direction: column;
  }
}


/* css/layouts/public/deal-public.css */
/* =========================================================================
 * deal-public.css — Landing publique devis /deals/{token} + dialog accept/refus + footer base.
 * Issu du split de layouts/public.css (refactor CSS étape 1, 2026-05-28).
 * ======================================================================== */

/* === Landing publique devis (/deals/{token}) ===
   Vue client par token : récap devis + actions Accept/Refuse + lien PDF. */

.deal-public-public {
  max-width: 880px;
  margin: var(--eki-space-8) auto var(--eki-space-12);
  padding: 0 var(--eki-space-4);
}
.deal-public-public-header h1 {
  font-size: var(--eki-fs-3xl);
  margin-block-end: var(--eki-space-2);
}
.deal-public-public-header h1 strong {
  color: var(--eki-accent);
}
.deal-public-meta {
  color: var(--eki-text-muted);
  font-size: var(--eki-fs-sm);
}
.deal-public-customer-ref {
  margin-block-start: var(--eki-space-2);
  padding: var(--eki-space-2) var(--eki-space-3);
  background: var(--eki-bg-alt);
  border-radius: var(--eki-radius-sm);
  font-size: var(--eki-fs-sm);
}

.deal-public-section {
  margin-block-start: var(--eki-space-8);
}
.deal-public-section h2 {
  font-size: var(--eki-fs-xl);
  margin-block-end: var(--eki-space-3);
  border-bottom: 2px solid var(--eki-accent);
  padding-block-end: var(--eki-space-1);
}

.deal-public-addresses {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--eki-space-4);
}
@media (max-width: 880px) {
  .deal-public-addresses { grid-template-columns: 1fr; }
}
.deal-public-address-box {
  padding: var(--eki-space-3);
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-sm);
  background: var(--eki-bg-elev);
}
.deal-public-address-box h2 {
  font-size: var(--eki-fs-base);
  margin-block-end: var(--eki-space-2);
  border: none;
  padding: 0;
}

.deal-public-lines {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--eki-fs-sm);
}
.deal-public-lines th,
.deal-public-lines td {
  padding: var(--eki-space-2) var(--eki-space-3);
  border-bottom: 1px solid var(--eki-border);
  text-align: left;
}
.deal-public-lines thead th {
  background: var(--eki-accent);
  color: var(--eki-white);
  font-weight: 600;
}
.deal-public-lines .num { text-align: right; white-space: nowrap; }
.deal-public-lines tfoot td {
  font-weight: 500;
}
.deal-public-lines tfoot tr.deal-public-total td {
  border-top: 2px solid var(--eki-accent);
  font-size: var(--eki-fs-base);
}
.deal-public-lines tfoot tr.deal-public-total td strong {
  color: var(--eki-accent);
}
.deal-public-tax-mention {
  padding-block: var(--eki-space-3) !important;
  font-size: var(--eki-fs-sm);
  color: var(--eki-text-muted);
  font-weight: normal;
  background: var(--eki-bg-alt);
}

.deal-public-note p {
  background: var(--eki-bg-alt);
  padding: var(--eki-space-3);
  border-radius: var(--eki-radius-sm);
  /* Préserve les retours à la ligne saisis dans la textarea note ; wrap normal sinon.
     Sans ça, HTML collapse tous les \n en espaces simples. */
  white-space: pre-wrap;
}

.deal-public-status {
  margin-block: var(--eki-space-4);
  padding: var(--eki-space-3) var(--eki-space-4);
  border-radius: var(--eki-radius-sm);
  font-weight: 500;
}
.deal-public-status-accepted { background: #d1fae5; color: #065f46; }
.deal-public-status-refused  { background: #fee2e2; color: #991b1b; }
.deal-public-status-cancelled { background: var(--eki-bg-alt); color: var(--eki-text-muted); }
.deal-public-status-expired   { background: #fef3c7; color: #92400e; }

.deal-public-error {
  margin-block: var(--eki-space-3);
  padding: var(--eki-space-3);
  background: #fee2e2;
  color: #991b1b;
  border-radius: var(--eki-radius-sm);
}

.deal-public-actions-section {
  display: flex;
  flex-wrap: wrap;
  gap: var(--eki-space-3);
  align-items: center;
  margin-block-start: var(--eki-space-8);
  padding-block: var(--eki-space-4);
  border-top: 1px solid var(--eki-border);
}
.deal-public-action-form { display: inline; }
.deal-public-btn {
  display: inline-block;
  padding: var(--eki-space-3) var(--eki-space-5);
  font-size: var(--eki-fs-base);
  font-weight: 500;
  border-radius: var(--eki-radius-sm);
  border: 1px solid transparent;
  cursor: pointer;
  text-decoration: none;
  line-height: 1.4;
}
/* La couleur du texte est répétée sur :hover/:focus : sinon la règle globale
   a:hover { color: var(--eki-red-dark) } (base.css, spécificité a:hover > .classe) reprend
   la main et, sur le bouton primaire, fond ET texte deviennent red-dark → texte invisible. */
.deal-public-btn-primary { background: var(--eki-accent); color: var(--eki-white); }
.deal-public-btn-primary:hover,
.deal-public-btn-primary:focus { background: var(--eki-red-dark); color: var(--eki-white); }
.deal-public-btn-refuse { background: transparent; color: var(--eki-text); border-color: var(--eki-border); }
.deal-public-btn-refuse:hover,
.deal-public-btn-refuse:focus { background: var(--eki-bg-alt); color: var(--eki-text); }
.deal-public-btn-secondary { background: var(--eki-bg-alt); color: var(--eki-text); border-color: var(--eki-border); }
.deal-public-btn-secondary:hover,
.deal-public-btn-secondary:focus { background: var(--eki-border); color: var(--eki-text); }

/* Modale acceptation / refus (HTML5 <dialog>) — au clic des boutons primaires
   de la section actions. Le markup compose .eki-dialog + .deal-public-dialog
   pour le shell, .eki-dialog__title + .eki-dialog__intro + .eki-dialog__actions
   pour la structure interne. Seule la textarea garde son styling local. */

/* Composé avec .eki-dialog (étape 2). Plus rien à ajouter ici — gardé vide
   pour rétro-compat si un sélecteur scope-local devient nécessaire (ex.
   variante par taille de devis ou par status). */
/* .deal-public-dialog { } */

/* Composé avec .eki-dialog__title / __intro / __actions — règles factorisées.
   Gardés comme classes "marqueur" pour aria-labelledby et hooks JS éventuels. */
/* .deal-public-dialog-title, .deal-public-dialog-intro { } */

/* La primitive .eki-dialog__actions ajoute margin-top: --space-4. La textarea
   au-dessus ayant déjà margin-block-end: --space-4, on neutralise ici pour
   garder le rendu d'origine (1× --space-4 et pas 2×). */
.deal-public-dialog-actions { margin-top: 0; }

/* Textarea custom : style spécifique au champ commentaire client (bg-elev,
   min-height plus généreux, marge basse pour séparer des actions). N'est pas
   couvert par .eki-dialog. */
.deal-public-dialog-textarea {
  width: 100%;
  font: inherit;
  padding: var(--eki-space-2) var(--eki-space-3);
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-sm);
  background: var(--eki-bg-elev);
  color: var(--eki-text);
  resize: vertical;
  min-height: 100px;
  margin-block-end: var(--eki-space-4);
  box-sizing: border-box;
}
.deal-public-dialog-textarea:focus {
  outline: 2px solid var(--eki-accent);
  outline-offset: 2px;
}

.deal-public-confirmation {
  max-width: 640px;
  margin: var(--eki-space-16) auto;
  padding: 0 var(--eki-space-4);
  text-align: center;
}
.deal-public-confirmation h1 {
  font-size: var(--eki-fs-4xl);
  color: var(--eki-accent);
}
.deal-public-confirmation .lead {
  font-size: var(--eki-fs-lg);
  margin-block: var(--eki-space-4);
}
.deal-public-confirmation-refused h1 { color: var(--eki-text); }
/* Variante « accepté » : le titre accentué de .deal-public-confirmation convient déjà — classe
   gardée comme marqueur sémantique (pendant de -refused, hooks JS/tests). Même convention que
   .deal-public-dialog ci-dessus : commentée pour qu'elle ne passe pas pour un oubli. */
/* .deal-public-confirmation-accepted { } */

/* Confirmation d'acceptation avec paiement immédiat : le « Payer maintenant » est l'action
   principale, le reste (revoir devis, PDF, virement) passe en secondaire discret. */
.deal-public-confirmation-due {
  font-size: var(--eki-fs-lg);
  margin-block: var(--eki-space-4) var(--eki-space-6);
}
.deal-public-confirmation-due strong { color: var(--eki-accent); }
.deal-public-btn-lg {
  font-size: var(--eki-fs-lg);
  padding: var(--eki-space-4) var(--eki-space-8);
}
.deal-public-confirmation-secondary {
  margin-block-start: var(--eki-space-6);
  font-size: var(--eki-fs-sm);
}
.deal-public-confirmation-contact {
  margin-block-start: var(--eki-space-4);
  font-size: var(--eki-fs-sm);
  color: var(--eki-text-muted);
}

/* Sous-total catalogue (devis avec tarif préférentiel) — étiqueté, plus barré. */
.deal-public-catalog td { color: var(--eki-text-muted); }
/* Double prix par ligne : catalogue discret au-dessus de « votre prix ». */
.deal-line-catalog,
.deal-line-net { display: block; }
.deal-line-catalog { font-size: var(--eki-fs-xs); color: var(--eki-text-muted); }

/* Bloc d'appel au paiement de la landing devis : une fois le devis accepté, « Payer » est l'action
   principale de la page — détaché du corps du devis pour ne pas se perdre sous le tableau de lignes. */
.deal-public-pay-section {
  background: var(--eki-bg-alt);
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-md);
  padding: var(--eki-space-6);
  text-align: center;
}
/* Rappel du solde à suivre (ou du reste dû après un acompte) : information secondaire, à ne jamais
   confondre avec le montant appelé. Rendu tantôt en <span> (landing), tantôt en <p> (retour de
   paiement) → display: block dans les deux cas. */
.deal-public-pay-rest {
  display: block;
  margin-block-start: var(--eki-space-1);
  font-size: var(--eki-fs-sm);
  color: var(--eki-text-muted);
}

/* === Page de paiement embarqué (/deals/{token}/pay) ===
   Carte centrée autour du formulaire KR.js (thème neon). Le formulaire lui-même
   est stylé par la librairie SG ; on encadre juste son contexte (montant, note, retour). */
.deal-public-pay {
  max-width: 520px;
  margin: var(--eki-space-12) auto;
  padding: 0 var(--eki-space-4);
}
.deal-public-pay-card {
  background: var(--eki-bg-elev);
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-lg);
  box-shadow: var(--eki-shadow-md);
  padding: var(--eki-space-8) var(--eki-space-6);
}
/* Le smart form KR.js (thème neon) rend ses champs dans un bloc de largeur fixe aligné à
   gauche. On centre ce bloc dans la carte : align-items:center recadre l'enfant fixe quelle
   que soit sa classe interne KR (robuste aux styles inline de la lib), margin auto couvre le
   cas où la largeur fixe est portée par .kr-smart-form lui-même. */
.deal-public-pay .kr-smart-form {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-inline: auto;
}
.deal-public-pay-header {
  text-align: center;
  margin-block-end: var(--eki-space-6);
}
.deal-public-pay-header h1 {
  font-size: var(--eki-fs-2xl);
  margin: 0;
}
.deal-public-pay-ref {
  margin-block-start: var(--eki-space-1);
  color: var(--eki-text-muted);
  font-size: var(--eki-fs-sm);
}
.deal-public-pay-amount {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--eki-space-1);
  margin-block-end: var(--eki-space-6);
  padding: var(--eki-space-5);
  background: var(--eki-bg-alt);
  border-radius: var(--eki-radius-md);
}
.deal-public-pay-amount-label {
  font-size: var(--eki-fs-sm);
  color: var(--eki-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.deal-public-pay-amount-value {
  font-size: var(--eki-fs-3xl);
  font-weight: 700;
  line-height: 1.1;
  color: var(--eki-accent);
}
.deal-public-pay-amount-tax {
  font-size: var(--eki-fs-xs);
  color: var(--eki-text-muted);
}
.deal-public-pay-loading {
  padding: var(--eki-space-6) 0;
  font-size: var(--eki-fs-sm);
  color: var(--eki-text-muted);
  text-align: center;
}
.deal-public-pay-note {
  margin-block-start: var(--eki-space-5);
  font-size: var(--eki-fs-sm);
  line-height: 1.5;
  color: var(--eki-text-muted);
  text-align: center;
}
.deal-public-pay-contact {
  margin-block-start: var(--eki-space-3);
  font-size: var(--eki-fs-sm);
  color: var(--eki-text-muted);
  text-align: center;
}
.deal-public-pay-back {
  display: block;
  margin-block-start: var(--eki-space-4);
  font-size: var(--eki-fs-sm);
  color: var(--eki-text-muted);
  text-align: center;
}
.deal-public-pay-back:hover { color: var(--eki-accent); }


/* css/layouts/public/home.css */
/* =========================================================================
 * home.css — Home v2 (hero + USP + trust + featured + custom + FAQ) + content-page éditorial générique.
 * Issu du split de layouts/public.css (refactor CSS étape 1, 2026-05-28).
 * ======================================================================== */


/* =====================================================================
 * Site public refondu — home, pages éditoriales (about / philosophy /
 * guide / contact), SEO-optimized layouts.
 * ===================================================================== */

/* ---------- Home : hero ---------- */

.home-hero h1 {
  font-family: var(--eki-font-display);
  font-size: clamp(2rem, 5vw, var(--eki-fs-4xl));
  margin-block: 0 var(--eki-space-4);
  color: var(--eki-text);
}

.home-hero-accent {
  color: var(--eki-red);
}

.home-hero-tagline {
  max-width: 42rem;
  margin-inline: auto;
  margin-block: 0 var(--eki-space-8);
  font-size: var(--eki-fs-lg);
  color: var(--eki-text-muted);
  line-height: 1.55;
}

.home-hero-cta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--eki-space-3);
  justify-content: center;
}

/* ---------- Boutons home / pages éditoriales ---------- */

.home-btn {
  display: inline-block;
  padding: var(--eki-space-3) var(--eki-space-5);
  border: 1px solid transparent;
  border-radius: var(--eki-radius-sm);
  font-size: var(--eki-fs-md);
  font-weight: 500;
  text-decoration: none;
  text-align: center;
  font-family: inherit;
  cursor: pointer;
  transition: background-color 120ms, border-color 120ms;
}

.home-btn-primary {
  background-color: var(--eki-red);
  color: #ffffff;
  border-color: var(--eki-red);
}

.home-btn-primary:hover {
  background-color: var(--eki-red-dark);
  border-color: var(--eki-red-dark);
  /* Surcharge la règle globale a:hover { color: var(--eki-red-dark) } de base.css :
     sans ça le texte du bouton devient rouge foncé sur fond rouge foncé = invisible. */
  color: #ffffff;
}

.home-btn-secondary {
  background-color: var(--eki-bg);
  color: var(--eki-text);
  border-color: var(--eki-border);
}

.home-btn-secondary:hover {
  background-color: var(--eki-gray-100);
}

.home-btn-link {
  background: transparent;
  color: var(--eki-red);
  border-color: transparent;
  text-decoration: underline;
  text-underline-offset: 4px;
}

.home-btn-link:hover {
  color: var(--eki-red-dark);
}

/* ---------- Home : USP / range / trust / custom ---------- */

.home-usp,
.home-range,
.home-trust,
.home-custom {
  max-width: var(--eki-container-max);
  margin-inline: auto;
  padding: var(--eki-space-12) var(--eki-space-4);
}

.home-usp {
  background-color: var(--eki-gray-100);
  max-width: none;
}

.home-usp-grid {
  max-width: var(--eki-container-max);
  margin-inline: auto;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: var(--eki-space-6);
}

/* @deprecated 2026-05-28 — aucun usage HTML détecté (classe orpheline héritée
   de la v1 home). Si on en ré-introduit une, composer avec .eki-card et ne
   garder ici que le `color: var(--eki-red)` du h3. À supprimer après vérif. */

.home-range h2,
.home-trust h2,
.home-custom h2 {
  font-family: var(--eki-font-display);
  font-size: var(--eki-fs-2xl);
  margin-block: 0 var(--eki-space-4);
  color: var(--eki-text);
}

.home-range-intro {
  color: var(--eki-text-muted);
  margin-block: 0 var(--eki-space-6);
  font-size: var(--eki-fs-md);
}

.home-range-list {
  list-style: none;
  padding: 0;
  margin: 0 0 var(--eki-space-6);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: var(--eki-space-2) var(--eki-space-6);
  font-size: var(--eki-fs-md);
}

.home-range-list li {
  padding: var(--eki-space-2) 0;
  border-block-end: 1px dashed var(--eki-border);
}

.home-range-list strong {
  color: var(--eki-red);
}

.home-range-cta a {
  color: var(--eki-red);
  text-decoration: none;
  font-weight: 500;
}

.home-range-cta a:hover {
  text-decoration: underline;
}

.home-trust {
  text-align: center;
  background-color: var(--eki-gray-100);
  max-width: none;
}

.home-trust-list {
  font-size: var(--eki-fs-lg);
  color: var(--eki-text-muted);
  letter-spacing: 0.02em;
  margin: 0;
}

.home-custom {
  text-align: center;
}

.home-custom p {
  max-width: 40rem;
  margin-inline: auto;
  margin-block-end: var(--eki-space-6);
  font-size: var(--eki-fs-md);
  color: var(--eki-text);
  line-height: 1.55;
}

/* ---------- Pages éditoriales (about / philosophy / guide / contact) ---------- */

.content-page {
  max-width: var(--eki-container-max);
  margin-inline: auto;
  padding: var(--eki-space-12) var(--eki-space-4);
}

/* Pour les pages éditoriales très textuelles (Guide, About long form), un modificateur
   `--narrow` borne la largeur de ligne pour préserver la lisibilité (~75 caractères).
   À appliquer ponctuellement si une page paraît trop étalée. */
.content-page--narrow {
  max-width: 56rem;
}

.content-page-header {
  margin-block-end: var(--eki-space-12);
  padding-block-end: var(--eki-space-6);
  border-block-end: 1px solid var(--eki-border);
}

.content-page-header h1 {
  font-family: var(--eki-font-display);
  font-size: clamp(2.5rem, 6vw, 4.5rem);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.05;
  margin-block: 0 var(--eki-space-5);
  color: var(--eki-text);
}

.content-page-lead {
  font-size: var(--eki-fs-lg);
  line-height: 1.55;
  color: var(--eki-text-muted);
  margin: 0;
  max-width: 48rem;
}

.content-section {
  margin-block-end: var(--eki-space-10);
}

.content-section h2 {
  font-family: var(--eki-font-display);
  font-size: var(--eki-fs-2xl);
  margin-block: 0 var(--eki-space-4);
  color: var(--eki-text);
  scroll-margin-block-start: var(--eki-space-8);
}

.content-section h3 {
  font-size: var(--eki-fs-lg);
  margin-block: var(--eki-space-5) var(--eki-space-2);
  color: var(--eki-text);
}

.content-section p {
  margin-block: 0 var(--eki-space-4);
  line-height: 1.65;
  color: var(--eki-text);
  font-size: var(--eki-fs-md);
}

/* Liens de prose éditoriale uniquement : on exclut les liens porteurs d'une
   classe (boutons .home-btn, .contact-card-link…) dont la couleur est gérée
   par leur propre règle. Sans le :not([class]), le rouge éditorial (0,1,1)
   écrase le texte blanc d'un bouton primaire (0,1,0) = texte invisible sur
   fond rouge tant qu'on ne le survole pas. */
.content-section a:not([class]) {
  color: var(--eki-red);
}

.content-list {
  margin-block: 0 var(--eki-space-4);
  padding-inline-start: var(--eki-space-6);
  line-height: 1.7;
}

.content-list li {
  margin-block-end: var(--eki-space-2);
  color: var(--eki-text);
}

.content-quote {
  margin: var(--eki-space-6) 0;
  padding: var(--eki-space-4) var(--eki-space-6);
  border-inline-start: 4px solid var(--eki-red);
  background: var(--eki-bg-alt);
  font-style: italic;
  font-size: var(--eki-fs-lg);
  color: var(--eki-text);
}

.content-cta {
  margin-block-start: var(--eki-space-10);
  padding-block-start: var(--eki-space-6);
  border-block-start: 1px solid var(--eki-border);
}

.content-cta p {
  display: flex;
  flex-wrap: wrap;
  gap: var(--eki-space-3);
  margin: 0;
}

/* ---------- Guide : sommaire ---------- */

.content-toc {
  background: var(--eki-bg-alt);
  border-radius: var(--eki-radius-md);
  padding: var(--eki-space-5);
  margin-block-end: var(--eki-space-10);
}

.content-toc h2 {
  font-size: var(--eki-fs-sm);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--eki-text-muted);
  margin-block: 0 var(--eki-space-3);
  font-family: inherit;
}

.content-toc ul {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--eki-space-2);
}

.content-toc a {
  display: inline-block;
  padding: var(--eki-space-1) 0;
  color: var(--eki-text);
  text-decoration: none;
  font-size: var(--eki-fs-sm);
}

.content-toc a::before {
  content: "→ ";
  color: var(--eki-red);
}

.content-toc a:hover {
  color: var(--eki-red);
}

/* =====================================================================
 * Home refondue v2 — pattern e-commerce industriel premium 2024-2026,
 * inspiré Siegmund USA / Demmeler. Sections empilées, hero plein-cadre
 * statique (LCP-friendly), trust bar, featured grid, storytelling,
 * sur-mesure contrasté, FAQ SEO.
 * ===================================================================== */

.home {
  /* Conteneur global home — sections gèrent leur padding individuellement. */
}

/* ---------- Hero v2 ---------- */

.home-hero-v2 {
  background:
    radial-gradient(ellipse at 80% 30%, rgba(203,40,33,.08), transparent 60%),
    linear-gradient(180deg, var(--eki-bg) 0%, var(--eki-bg-alt) 100%);
  border-block-end: 1px solid var(--eki-border);
}

.home-hero-v2-inner {
  max-width: var(--eki-container-max);
  margin-inline: auto;
  padding: var(--eki-space-16) var(--eki-space-4);
  display: grid;
  grid-template-columns: 1.2fr 1fr;
  align-items: center;
  gap: var(--eki-space-12);
}

@media (max-width: 880px) {
  .home-hero-v2-inner {
    grid-template-columns: 1fr;
    padding: var(--eki-space-12) var(--eki-space-4);
    gap: var(--eki-space-8);
  }
}

.home-hero-v2-eyebrow {
  display: inline-block;
  margin: 0 0 var(--eki-space-3);
  padding: var(--eki-space-1) var(--eki-space-3);
  background: rgba(203,40,33,.08);
  color: var(--eki-red);
  font-size: var(--eki-fs-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  border-radius: var(--eki-radius-sm);
}

.home-hero-v2-title {
  font-family: var(--eki-font-display);
  font-size: clamp(2.25rem, 5.5vw, 4rem);
  line-height: 1.05;
  letter-spacing: -0.02em;
  margin: 0 0 var(--eki-space-5);
  color: var(--eki-text);
}

.home-hero-v2-accent {
  color: var(--eki-red);
  display: inline-block;
}

.home-hero-v2-lead {
  font-size: var(--eki-fs-lg);
  line-height: 1.55;
  color: var(--eki-text-muted);
  margin: 0 0 var(--eki-space-6);
  max-width: 32rem;
}

.home-hero-v2-cta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--eki-space-3);
  margin-block-end: var(--eki-space-6);
}

.home-hero-v2-points {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--eki-space-2) var(--eki-space-6);
  font-size: var(--eki-fs-sm);
  color: var(--eki-text);
}

.home-hero-v2-points li {
  display: inline-flex;
  align-items: center;
  gap: var(--eki-space-2);
}

.home-hero-v2-points svg {
  width: 18px;
  height: 18px;
  color: var(--eki-red);
}

/* Visual hero : si une vraie photo est déposée dans wwwroot/img/hero/atelier-table.jpg
   elle prend la place. Sinon, le placeholder "matrice BFS" (motif SVG de cercles
   imitant la perforation des plateaux) reste affiché, avec un badge "Système BFS". */
.home-hero-v2-visual {
  position: relative;
  aspect-ratio: 4 / 5;
  max-width: 30rem;
  margin-inline: auto;
  border-radius: var(--eki-radius-lg);
  overflow: hidden;
  background:
    linear-gradient(135deg, var(--eki-bg-alt) 0%, var(--eki-gray-100) 100%);
  box-shadow: 0 24px 60px rgba(0,0,0,.10);
}

.home-hero-v2-photo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 2;
}

.home-hero-v2-pattern {
  position: absolute;
  inset: 0;
  z-index: 1;
  color: var(--eki-red);
  opacity: .55;
}

.home-hero-v2-pattern svg {
  width: 100%;
  height: 100%;
  display: block;
}

/* Badge "Système BFS" — affiché par-dessus le placeholder (z-index 3). Quand une
   vraie photo est en place, il reste visible en bas-droite comme un signal de
   valeur ajoutée. */
.home-hero-v2-badge {
  position: absolute;
  z-index: 3;
  inset-block-end: var(--eki-space-5);
  inset-inline-end: var(--eki-space-5);
  background: var(--eki-inverse-bg);
  color: var(--eki-inverse-fg);
  padding: var(--eki-space-3) var(--eki-space-4);
  border-radius: var(--eki-radius-md);
  box-shadow: 0 8px 24px rgba(0,0,0,.20);
  text-align: start;
}

.home-hero-v2-badge-title {
  display: block;
  font-family: var(--eki-font-display);
  font-size: var(--eki-fs-md);
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--eki-red-light);
}

.home-hero-v2-badge-sub {
  display: block;
  font-size: var(--eki-fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--eki-inverse-fg-muted);
  margin-block-start: 2px;
}

/* Lorsque la photo n'a pas pu charger (404), JS ajoute .is-placeholder.
   On affiche un overlay textuel discret pour signaler le placeholder en dev. */
.home-hero-v2-visual.is-placeholder::after {
  content: "Placeholder · photo atelier à venir";
  position: absolute;
  z-index: 3;
  inset-block-start: var(--eki-space-3);
  inset-inline-start: var(--eki-space-3);
  background: rgba(255,255,255,.85);
  color: var(--eki-text-muted);
  padding: var(--eki-space-1) var(--eki-space-2);
  border-radius: var(--eki-radius-sm);
  font-size: var(--eki-fs-xs);
  font-style: italic;
}

@media (max-width: 880px) {
  .home-hero-v2-visual { display: none; }
}

/* ---------- Variante hero plein cadre (photo atelier en fond) ----------
   Activée par .home-hero-v2--photo sur la <section>. La photo couvre tout le
   bloc, un voile sombre (dégradé côté texte + voile global) garantit la
   lisibilité du texte passé en clair. Le panneau visuel portrait est masqué. */
.home-hero-v2--photo {
  position: relative;
  background: var(--eki-inverse-bg); /* fond sombre pendant le chargement de la photo */
  border-block-end: none;
}

/* Le <picture> porte le positionnement, l'<img> le cadrage : le conteneur est nécessaire pour
   proposer AVIF puis WebP avant le repli JPEG, et laissé en flux il ouvrirait une ligne de texte
   vide sous le hero. */
.home-hero-v2-bg {
  position: absolute;
  inset: 0;
}

.home-hero-v2-bg img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 42%;
}

.home-hero-v2--photo::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(90deg, rgba(8,9,11,.88) 0%, rgba(8,9,11,.62) 42%, rgba(8,9,11,.18) 100%),
    linear-gradient(180deg, rgba(8,9,11,.25) 0%, rgba(8,9,11,.45) 100%);
}

.home-hero-v2--photo .home-hero-v2-inner {
  position: relative; /* au-dessus de la photo et du voile */
  z-index: 1;
  grid-template-columns: 1fr;
  min-height: min(76vh, 660px);
  align-items: center;
}

.home-hero-v2--photo .home-hero-v2-visual { display: none; }

.home-hero-v2--photo .home-hero-v2-text { max-width: 38rem; }

.home-hero-v2--photo .home-hero-v2-title,
.home-hero-v2--photo .home-hero-v2-points li { color: #ffffff; }

.home-hero-v2--photo .home-hero-v2-lead { color: rgba(255,255,255,.86); }

.home-hero-v2--photo .home-hero-v2-accent { color: var(--eki-red-light); }

.home-hero-v2--photo .home-hero-v2-eyebrow {
  background: rgba(203,40,33,.92);
  color: #ffffff;
}

/* Le 2ᵉ CTA (.home-btn-secondary, clair par défaut) repassé en bouton clair
   translucide pour rester lisible sur la photo sombre. */
.home-hero-v2--photo .home-btn-secondary {
  background: rgba(255,255,255,.12);
  color: #ffffff;
  border-color: rgba(255,255,255,.5);
}
.home-hero-v2--photo .home-btn-secondary:hover {
  background: rgba(255,255,255,.2);
}

/* ---------- Trust bar ---------- */

.home-trust-bar {
  background: var(--eki-inverse-bg);
  color: var(--eki-inverse-fg);
}

.home-trust-bar-list {
  max-width: var(--eki-container-max);
  margin-inline: auto;
  padding: var(--eki-space-6) var(--eki-space-4);
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--eki-space-6);
  list-style: none;
}

@media (max-width: 1080px) {
  .home-trust-bar-list { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
  .home-trust-bar-list { grid-template-columns: 1fr; }
}

.home-trust-bar-item {
  display: flex;
  align-items: center;
  gap: var(--eki-space-4);
}

.home-trust-ico {
  width: 40px;
  height: 40px;
  color: var(--eki-red);
  flex-shrink: 0;
}

.home-trust-bar-item strong {
  display: block;
  color: var(--eki-inverse-fg);
  font-size: var(--eki-fs-md);
  font-weight: 600;
  line-height: 1.2;
}

.home-trust-bar-item span {
  display: block;
  font-size: var(--eki-fs-xs);
  color: var(--eki-inverse-fg-muted);
  margin-block-start: 2px;
}

/* ---------- Featured products ---------- */

.home-featured {
  max-width: var(--eki-container-max);
  margin-inline: auto;
  padding: var(--eki-space-16) var(--eki-space-4);
}

.home-featured-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--eki-space-3);
  margin-block-end: var(--eki-space-8);
  padding-block-end: var(--eki-space-4);
  border-block-end: 1px solid var(--eki-border);
}

.home-featured-head h2 {
  font-family: var(--eki-font-display);
  font-size: clamp(1.75rem, 3vw, var(--eki-fs-3xl));
  margin: 0;
  color: var(--eki-text);
}

.home-featured-all {
  color: var(--eki-red);
  font-weight: 600;
  text-decoration: none;
}

.home-featured-all:hover {
  text-decoration: underline;
}

.home-featured-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: var(--eki-space-6);
}

.home-featured-card {
  background: var(--eki-bg);
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-md);
  overflow: hidden;
  transition: border-color 150ms, transform 150ms, box-shadow 200ms;
}

.home-featured-card:hover {
  border-color: var(--eki-red);
  transform: translateY(-2px);
  box-shadow: 0 8px 24px rgba(0,0,0,.08);
}

.home-featured-link {
  display: block;
  text-decoration: none;
  color: inherit;
}

.home-featured-media {
  position: relative;
  aspect-ratio: 4 / 3;
  background: var(--eki-bg-alt);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.home-featured-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.home-featured-placeholder {
  position: absolute;
  inset: 0;
  background: url("/img/logo-eki.svg") no-repeat center / 50%;
  opacity: .3;
  filter: grayscale(.6);
  pointer-events: none;
}

.home-featured-body {
  padding: var(--eki-space-4);
}

.home-featured-name {
  font-size: var(--eki-fs-md);
  font-weight: 600;
  margin: 0 0 var(--eki-space-2);
  color: var(--eki-text);
}

.home-featured-price {
  margin: 0;
  font-size: var(--eki-fs-sm);
  color: var(--eki-text-muted);
}

.home-featured-price strong {
  color: var(--eki-red);
  font-size: var(--eki-fs-md);
  font-weight: 700;
  margin-inline: 2px;
}

.home-featured-vat {
  font-size: var(--eki-fs-xs);
  color: var(--eki-text-muted);
}

/* Double affichage tarif remisé en home : « Prix catalogue » / « Votre prix » empilés. */
.home-featured-price-catalog,
.home-featured-price-net {
  display: block;
}

/* ---------- Why EKI ---------- */

.home-why {
  background: var(--eki-bg-alt);
  border-block: 1px solid var(--eki-border);
}

.home-why-inner {
  max-width: var(--eki-container-max);
  margin-inline: auto;
  padding: var(--eki-space-16) var(--eki-space-4);
  display: grid;
  grid-template-columns: 1.4fr 1fr;
  gap: var(--eki-space-10);
  align-items: center;
}

@media (max-width: 880px) {
  .home-why-inner {
    grid-template-columns: 1fr;
    padding-block: var(--eki-space-12);
  }
}

.home-why-eyebrow {
  margin: 0 0 var(--eki-space-3);
  font-size: var(--eki-fs-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--eki-red);
}

.home-why-text h2 {
  font-family: var(--eki-font-display);
  font-size: clamp(1.75rem, 3.5vw, var(--eki-fs-3xl));
  line-height: 1.15;
  letter-spacing: -0.01em;
  margin: 0 0 var(--eki-space-5);
  color: var(--eki-text);
}

.home-why-text p {
  font-size: var(--eki-fs-md);
  line-height: 1.65;
  color: var(--eki-text);
  margin: 0 0 var(--eki-space-4);
}

.home-why-link {
  display: inline-block;
  margin-block-start: var(--eki-space-2);
  color: var(--eki-red);
  font-weight: 600;
  text-decoration: none;
}

.home-why-link:hover {
  text-decoration: underline;
}

.home-why-stats {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--eki-space-4);
}

.home-why-stats li {
  background: var(--eki-bg);
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-md);
  padding: var(--eki-space-5);
}

.home-why-stats strong {
  display: block;
  font-family: var(--eki-font-display);
  font-size: clamp(1.5rem, 2.5vw, 2.25rem);
  color: var(--eki-red);
  line-height: 1;
  margin-block-end: var(--eki-space-2);
}

.home-why-stats span {
  display: block;
  font-size: var(--eki-fs-sm);
  color: var(--eki-text-muted);
  line-height: 1.4;
}

/* ---------- Sur-mesure contrasté ---------- */

.home-custom-v2 {
  background:
    linear-gradient(135deg, var(--eki-red) 0%, var(--eki-red-dark) 100%);
  color: #ffffff;
  position: relative;
  overflow: hidden;
}

.home-custom-v2::before {
  content: "";
  position: absolute;
  inset-block-start: -20%;
  inset-inline-end: -10%;
  width: 45%;
  aspect-ratio: 1;
  background: radial-gradient(circle, rgba(255,255,255,.08) 0%, transparent 70%);
  pointer-events: none;
}

.home-custom-v2-inner {
  position: relative;
  max-width: 56rem;
  margin-inline: auto;
  padding: var(--eki-space-16) var(--eki-space-4);
  text-align: center;
}

.home-custom-v2-eyebrow {
  margin: 0 0 var(--eki-space-3);
  font-size: var(--eki-fs-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: rgba(255,255,255,.75);
}

.home-custom-v2-title {
  font-family: var(--eki-font-display);
  font-size: clamp(1.875rem, 4vw, 3rem);
  line-height: 1.1;
  letter-spacing: -0.01em;
  margin: 0 0 var(--eki-space-5);
}

.home-custom-v2-lead {
  font-size: var(--eki-fs-lg);
  line-height: 1.55;
  color: rgba(255,255,255,.88);
  margin: 0 auto var(--eki-space-6);
  max-width: 40rem;
}

.home-custom-v2-points {
  list-style: none;
  margin: 0 auto var(--eki-space-8);
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--eki-space-4) var(--eki-space-8);
  font-size: var(--eki-fs-sm);
}

.home-custom-v2-points li {
  display: inline-flex;
  align-items: center;
  gap: var(--eki-space-2);
}

.home-custom-v2-points svg {
  width: 18px;
  height: 18px;
}

.home-custom-v2-cta {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--eki-space-3);
}

/* Variantes de boutons spécifiques au bloc sur-mesure (fond rouge) */
.home-btn-primary-light {
  background: #ffffff;
  color: var(--eki-red);
  border-color: #ffffff;
}

.home-btn-primary-light:hover {
  background: var(--eki-bg-alt);
  border-color: var(--eki-bg-alt);
}

.home-btn-ghost {
  background: transparent;
  color: #ffffff;
  border-color: rgba(255,255,255,.4);
}

.home-btn-ghost:hover {
  background: rgba(255,255,255,.1);
  border-color: #ffffff;
}

.home-btn-lg {
  padding: var(--eki-space-3) var(--eki-space-6);
  font-size: var(--eki-fs-md);
}

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

.home-faq {
  max-width: 48rem;
  margin-inline: auto;
  padding: var(--eki-space-16) var(--eki-space-4);
}

.home-faq h2 {
  font-family: var(--eki-font-display);
  font-size: clamp(1.75rem, 3vw, var(--eki-fs-3xl));
  text-align: center;
  margin: 0 0 var(--eki-space-8);
  color: var(--eki-text);
}

.home-faq-list {
  display: flex;
  flex-direction: column;
  gap: var(--eki-space-2);
}

.home-faq-item {
  background: var(--eki-bg);
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-md);
  overflow: hidden;
  transition: border-color 150ms;
}

.home-faq-item[open] {
  border-color: var(--eki-red);
}

.home-faq-item summary {
  list-style: none;
  cursor: pointer;
  padding: var(--eki-space-4) var(--eki-space-5);
  font-weight: 600;
  font-size: var(--eki-fs-md);
  color: var(--eki-text);
  position: relative;
  padding-inline-end: var(--eki-space-10);
}

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

.home-faq-item summary::after {
  content: "+";
  position: absolute;
  inset-inline-end: var(--eki-space-5);
  inset-block-start: 50%;
  transform: translateY(-50%);
  color: var(--eki-red);
  font-weight: 400;
  font-size: 1.5rem;
  line-height: 1;
  transition: transform 200ms;
}

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

.home-faq-item summary:hover {
  background: var(--eki-bg-alt);
}

.home-faq-item p {
  margin: 0;
  padding: 0 var(--eki-space-5) var(--eki-space-5);
  color: var(--eki-text-muted);
  line-height: 1.6;
}

.home-faq-item a {
  color: var(--eki-red);
}

/* CTA primaire sous le lead d'une content-page (utilisé sur /contact pour pousser /rendez-vous). */
.content-page-cta {
  margin-block-start: var(--eki-space-5);
  margin-block-end: 0;
}


/* css/layouts/public/shop.css */
/* =========================================================================
 * shop.css — Catalogue : home hero, liste, fiche produit, catégories, sidebar filtres, slider.
 * Issu du split de layouts/public.css (refactor CSS étape 1, 2026-05-28).
 * ======================================================================== */


/* === Home hero === */
.home-hero {
  max-width: var(--eki-content-max);
  margin-inline: auto;
  padding-inline: var(--eki-space-4);
  padding-block: var(--eki-space-24);
  text-align: center;
}

.home-title {
  color: var(--eki-red);
  margin-block-end: var(--eki-space-4);
}

.home-title .home-r {
  font-size: 0.4em;
  vertical-align: super;
  font-weight: 600;
}

.home-subtitle {
  font-size: var(--eki-fs-lg);
  color: var(--eki-text-muted);
  margin-block-end: var(--eki-space-8);
}

.home-status {
  display: inline-block;
  text-align: start;
  background-color: var(--eki-gray-100);
  border-radius: var(--eki-radius-md);
  padding: var(--eki-space-6) var(--eki-space-8);
}

.home-status p {
  margin-block-end: var(--eki-space-2);
}

.home-status p:last-child {
  margin-block-end: 0;
}

/* === Boutique : liste catalogue === */
.shop-content {
  max-width: var(--eki-container-max);
  margin-inline: auto;
  padding: var(--eki-space-8) var(--eki-space-4);
}

.shop-header {
  margin-block-end: var(--eki-space-8);
}

.shop-header h1 {
  font-family: var(--eki-font-display);
  font-size: var(--eki-fs-3xl);
  margin: 0 0 var(--eki-space-2);
}

.shop-intro {
  font-size: var(--eki-fs-lg);
  color: var(--eki-text-muted);
  margin: 0;
}

.shop-empty {
  text-align: center;
  padding: var(--eki-space-12);
  color: var(--eki-text-muted);
  font-style: italic;
}

.shop-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: var(--eki-space-6);
}

.shop-card {
  background: var(--eki-bg);
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-md);
  overflow: hidden;
  transition: var(--eki-transition);
}

.shop-card:hover {
  border-color: var(--eki-red);
  box-shadow: var(--eki-shadow-md);
}

.shop-card-link {
  display: block;
  text-decoration: none;
  color: inherit;
}

.shop-card-photo {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  background: var(--eki-gray-100);
}

.shop-card-placeholder,
.shop-product-placeholder {
  position: relative;
  color: transparent;
}

.shop-card-placeholder::before,
.shop-product-placeholder::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: url("/img/logo-eki.svg");
  background-repeat: no-repeat;
  background-position: center;
  background-size: 42% auto;
  opacity: 0.18;
  filter: grayscale(0.7);
  pointer-events: none;
}

.shop-card-placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  aspect-ratio: 1 / 1;
  background: var(--eki-gray-100);
  font-family: var(--eki-font-display);
  font-size: var(--eki-fs-3xl);
}

.shop-card-title {
  font-size: var(--eki-fs-base);
  font-weight: 600;
  margin: var(--eki-space-3) var(--eki-space-4) var(--eki-space-1);
}

.shop-card-price {
  margin: 0 var(--eki-space-4) var(--eki-space-4);
  font-size: var(--eki-fs-sm);
  color: var(--eki-text-muted);
}

.shop-card-price strong {
  color: var(--eki-text);
  font-size: var(--eki-fs-base);
}

/* Double affichage tarif remisé : catalogue discret, « Votre prix » mis en avant. */
.shop-card-price-catalog,
.shop-card-price-net {
  display: block;
}

.shop-card-price-net strong {
  color: var(--eki-red);
}

/* === Boutique : fiche produit === */
.shop-show {
  max-width: var(--eki-container-max);
  margin-inline: auto;
  padding: var(--eki-space-6) var(--eki-space-4);
}

.shop-breadcrumb {
  margin-block-end: var(--eki-space-4);
  font-size: var(--eki-fs-sm);
}

.shop-breadcrumb a {
  color: var(--eki-text-muted);
  text-decoration: none;
}

.shop-breadcrumb a:hover {
  color: var(--eki-red);
}

.shop-product {
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
  gap: var(--eki-space-8);
}

@media (max-width: 880px) {
  .shop-product { grid-template-columns: 1fr; }
}

.shop-product-media img {
  width: 100%;
  border-radius: var(--eki-radius-md);
  border: 1px solid var(--eki-border);
  background: var(--eki-gray-100);
}

.shop-product-placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 1 / 1;
  background: var(--eki-gray-100);
  border-radius: var(--eki-radius-md);
  font-family: var(--eki-font-display);
  font-size: var(--eki-fs-4xl, 3rem);
}

.shop-product-thumbs {
  list-style: none;
  margin: var(--eki-space-3) 0 0;
  padding: 0;
  display: flex;
  gap: var(--eki-space-2);
}

.shop-product-thumbs img {
  width: 80px;
  height: 80px;
  object-fit: cover;
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-sm);
}

.shop-product-info h1 {
  font-family: var(--eki-font-display);
  font-size: var(--eki-fs-2xl);
  margin: 0 0 var(--eki-space-4);
}

.shop-product-description {
  font-size: var(--eki-fs-base);
  line-height: 1.6;
  color: var(--eki-text);
  margin-block-end: var(--eki-space-6);
  white-space: pre-wrap; /* Markdown rendu Phase 2+ (cf. ADR-019) — pour l'instant pre-wrap */
}

.shop-variant-selector {
  display: flex;
  flex-direction: column;
  gap: var(--eki-space-3);
  margin-block-end: var(--eki-space-6);
  padding: var(--eki-space-4);
  background: var(--eki-gray-100);
  border-radius: var(--eki-radius-sm);
}

.shop-product-price {
  margin: var(--eki-space-4) 0;
  font-size: var(--eki-fs-xl);
}

.shop-product-price strong {
  color: var(--eki-red);
  font-weight: 700;
}

/* Double affichage tarif remisé sur la fiche : « Prix catalogue » discret au-dessus. */
.shop-product-price-catalog,
.shop-product-price-net {
  display: block;
}

.shop-product-price-catalog {
  font-size: var(--eki-fs-sm);
  color: var(--eki-text-muted);
}

.shop-product-note {
  background: var(--eki-bg-alt);
  border-left: 3px solid var(--eki-red);
  padding: var(--eki-space-3) var(--eki-space-4);
  margin-block-end: var(--eki-space-4);
  font-size: var(--eki-fs-sm);
  color: var(--eki-text);
}

/* === Bandeau menu catégories (sous le header logo) === */
.shop-category-bar {
  background: var(--eki-bg-alt);
  border-block-start: 1px solid var(--eki-border);
}

.shop-category-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--eki-space-1);
  max-width: var(--eki-container-max);
  margin-inline: auto;
  padding-inline: var(--eki-space-4);
}

.shop-category-item {
  position: relative;
}

.shop-category-item > a {
  display: inline-block;
  padding: var(--eki-space-3) var(--eki-space-4);
  font-size: var(--eki-fs-sm);
  font-weight: 500;
  color: var(--eki-text);
  text-decoration: none;
  border-block-end: 2px solid transparent;
}

.shop-category-item > a:hover {
  color: var(--eki-red);
  border-block-end-color: var(--eki-red);
}

.shop-category-count {
  margin-inline-start: var(--eki-space-1);
  color: var(--eki-text-muted);
  font-weight: 400;
  font-size: var(--eki-fs-xs);
}

.shop-category-submenu {
  list-style: none;
  margin: 0;
  padding: var(--eki-space-2) 0;
  position: absolute;
  inset-block-start: 100%;
  inset-inline-start: 0;
  min-width: 12rem;
  background: var(--eki-bg);
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-sm);
  box-shadow: var(--eki-shadow-md);
  z-index: 10;
  display: none;
}

.shop-category-item:hover > .shop-category-submenu,
.shop-category-item:focus-within > .shop-category-submenu {
  display: block;
}

.shop-category-submenu a {
  display: block;
  padding: var(--eki-space-2) var(--eki-space-4);
  font-size: var(--eki-fs-sm);
  color: var(--eki-text);
  text-decoration: none;
}

.shop-category-submenu a:hover {
  background: var(--eki-bg-alt);
  color: var(--eki-red);
}

/* === Page catégorie : header + sous-cats === */
.shop-category-header {
  margin-block-end: var(--eki-space-6);
}

.shop-category-header h1 {
  font-family: var(--eki-font-display);
  font-size: var(--eki-fs-3xl);
  margin: 0 0 var(--eki-space-2);
}

.shop-subcats {
  margin-block-end: var(--eki-space-6);
  padding: var(--eki-space-4);
  background: var(--eki-bg-alt);
  border-radius: var(--eki-radius-sm);
}

.shop-subcats-title {
  font-size: var(--eki-fs-sm);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--eki-text-muted);
  margin: 0 0 var(--eki-space-3);
}

.shop-subcats-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--eki-space-2);
}

.shop-subcats-list a {
  display: inline-block;
  padding: var(--eki-space-2) var(--eki-space-3);
  background: var(--eki-bg);
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-sm);
  color: var(--eki-text);
  text-decoration: none;
  font-size: var(--eki-fs-sm);
}

.shop-subcats-list a:hover {
  border-color: var(--eki-red);
  color: var(--eki-red);
}

/* === Layout : sidebar filtres + résultats === */
.shop-layout {
  display: grid;
  grid-template-columns: minmax(0, 240px) minmax(0, 1fr);
  gap: var(--eki-space-6);
}

@media (max-width: 880px) {
  .shop-layout { grid-template-columns: 1fr; }
}

/* === Sidebar filtres === */
.shop-filters {
  background: var(--eki-bg);
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-sm);
  padding: var(--eki-space-4);
  align-self: start;
}

.shop-filters-title {
  font-size: var(--eki-fs-sm);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--eki-text-muted);
  margin: 0 0 var(--eki-space-3);
}

.shop-filters-empty {
  font-size: var(--eki-fs-sm);
  color: var(--eki-text-muted);
  font-style: italic;
}

.shop-filter-group {
  border: none;
  padding: 0;
  margin: 0 0 var(--eki-space-4);
}

.shop-filter-group legend {
  font-weight: 600;
  font-size: var(--eki-fs-sm);
  margin-block-end: var(--eki-space-2);
}

.shop-filter-option {
  display: flex;
  align-items: center;
  gap: var(--eki-space-2);
  font-size: var(--eki-fs-sm);
  padding: var(--eki-space-1) 0;
  cursor: pointer;
}

.shop-filter-option input[type="checkbox"] {
  width: auto;
}

.shop-filters-actions {
  display: flex;
  align-items: center;
  gap: var(--eki-space-3);
  margin-block-start: var(--eki-space-4);
  padding-block-start: var(--eki-space-3);
  border-block-start: 1px solid var(--eki-border);
}

.shop-filters-reset {
  font-size: var(--eki-fs-sm);
  color: var(--eki-text-muted);
  text-decoration: none;
}

.shop-filters-reset:hover {
  color: var(--eki-red);
}

/* === Zone résultats === */
.shop-results-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--eki-space-3);
  margin-block-end: var(--eki-space-4);
  padding-block-end: var(--eki-space-3);
  border-block-end: 1px solid var(--eki-border);
}

.shop-results-count {
  font-size: var(--eki-fs-sm);
  color: var(--eki-text-muted);
}

.shop-sort-form {
  display: flex;
  align-items: center;
  gap: var(--eki-space-2);
  font-size: var(--eki-fs-sm);
}

.shop-sort-form select {
  padding: var(--eki-space-1) var(--eki-space-3);
  font-size: var(--eki-fs-sm);
}

/* Filtres dynamiques (htmx) : la grille se grise le temps de la requête. */
.shop-results-grid {
  transition: opacity 120ms ease;
}

.shop-results-grid.htmx-request {
  opacity: 0.5;
  pointer-events: none;
}

/* === Slider double-thumb pour filtres dimensions/poids === */
.range-slider .range-slider-unit {
  font-weight: 400;
  color: var(--eki-text-muted);
  font-size: var(--eki-fs-xs);
}

.range-slider-track {
  position: relative;
  height: 18px;
  margin: var(--eki-space-3) 0 var(--eki-space-2);
}

.range-slider-track::before {
  content: "";
  position: absolute;
  inset-block-start: 50%;
  inset-inline: 0;
  height: 4px;
  background: var(--eki-border);
  border-radius: 2px;
  transform: translateY(-50%);
}

.range-slider-range {
  position: absolute;
  inset-block-start: 50%;
  height: 4px;
  background: var(--eki-red);
  border-radius: 2px;
  transform: translateY(-50%);
  pointer-events: none;
}

.range-slider-thumb {
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: 0;
  width: 100%;
  height: 18px;
  background: transparent;
  appearance: none;
  -webkit-appearance: none;
  margin: 0;
  pointer-events: none;
}

.range-slider-thumb::-webkit-slider-thumb {
  appearance: none;
  -webkit-appearance: none;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--eki-bg);
  border: 2px solid var(--eki-red);
  cursor: pointer;
  pointer-events: auto;
}

.range-slider-thumb::-moz-range-thumb {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--eki-bg);
  border: 2px solid var(--eki-red);
  cursor: pointer;
  pointer-events: auto;
}

.range-slider-thumb::-webkit-slider-runnable-track { background: transparent; height: 18px; }
.range-slider-thumb::-moz-range-track { background: transparent; height: 18px; }

.range-slider-inputs {
  display: flex;
  align-items: center;
  gap: var(--eki-space-2);
  font-size: var(--eki-fs-sm);
}

.range-slider-inputs input[type="number"] {
  /* flex partagé + min-width:0 : les deux champs se répartissent la largeur du parent au lieu
     d'une largeur fixe (6rem) qui débordait / décalait le bloc en layout large. */
  flex: 1 1 0;
  min-width: 0;
  padding: var(--eki-space-1) var(--eki-space-2);
  font-size: var(--eki-fs-sm);
  text-align: end;
  /* Mêmes codes que les inputs thémés (form.css) — ces champs ne sont pas dans un .form-row,
     ils n'héritaient donc d'aucun style et tombaient sur le rendu par défaut du navigateur. */
  color: var(--eki-text);
  background: var(--eki-bg);
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-sm);
  appearance: textfield;
  -moz-appearance: textfield;
}

.range-slider-inputs input[type="number"]:focus {
  outline: none;
  border-color: var(--eki-red);
}

/* Masque les flèches haut/bas du spinner number (Chrome/Safari). */
.range-slider-inputs input[type="number"]::-webkit-inner-spin-button,
.range-slider-inputs input[type="number"]::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

.range-slider-sep {
  color: var(--eki-text-muted);
}

/* ---------- Vue 3D (fiche /shop/{slug}) ---------- */

/* La section est rendue `hidden` et révélée par le script si un modèle existe pour le GTIN. */
.shop-product-3d {
  margin-block-start: var(--eki-space-12);
  padding-block-start: var(--eki-space-6);
  border-block-start: 1px solid var(--eki-border);
}

.shop-product-3d h2 {
  margin-block-end: var(--eki-space-4);
}

/* Hauteur fixée avant tout rendu : un canvas WebGL n'a pas de dimension intrinsèque, et une
   scène chargée dans un conteneur de hauteur nulle sort en 1 px de haut sans erreur. */
/* Calée sur la largeur du contenu, comme le reste de la fiche. Elle a d'abord été posée en pleine
   largeur de fenêtre — une table de 2,8 m se regarde de loin dans une colonne étroite — mais un
   bloc qui déborde de la colonne casse la lecture de la page et attire l'œil plus que le modèle
   lui-même. La distance de recul se règle mieux par le cadrage de la caméra que par la largeur du
   cadre.
   Hauteur explicite plutôt qu'un `aspect-ratio` : sur une colonne large, 16/10 donnerait encore un
   bloc trop haut. */
.shop-product-3d-stage {
  position: relative;
  block-size: min(70vh, 620px);
  min-block-size: 360px;
  border-radius: var(--eki-radius-md);
  /* La scène est rendue sur fond transparent : c'est cette surface qu'on voit derrière elle, et
     elle doit suivre le thème (un cadre blanc dans une page sombre se voit de loin). */
  background: var(--eki-bg-alt);
  overflow: hidden;
}

.shop-product-3d-stage canvas {
  inline-size: 100%;
  block-size: 100%;
  display: block;
  /* pan-y : un doigt qui glisse verticalement fait défiler la PAGE, pas tourner le modèle. Capter
     le geste vertical piégerait le visiteur mobile — il ne pourrait plus quitter la vue, le bloc
     occupant l'essentiel de son écran. L'horizontal et le pincement restent au viewer. C'est le
     réglage que <model-viewer> recommande pour un viewer intégré dans une page défilante. */
  touch-action: pan-y;
  outline: none;
}

/* Rappel « Ctrl + molette » : apparaît quand le visiteur utilise la molette sans Ctrl (la page
   défile alors normalement) et s'efface seul. Même parti pris que Google Maps. */
.shop-product-3d-scrollhint {
  position: absolute;
  inset-block-end: var(--eki-space-4);
  inset-inline: 0;
  margin: 0;
  text-align: center;
  color: var(--eki-text);
  font-size: 0.95rem;
  pointer-events: none;
  opacity: 0;
  transition: opacity 160ms ease-out;
}

.shop-product-3d-scrollhint > span {
  display: inline-block;
  padding: var(--eki-space-2) var(--eki-space-4);
  border-radius: var(--eki-radius-sm);
  background: color-mix(in srgb, var(--eki-bg) 82%, transparent);
}

.shop-product-3d-scrollhint.is-visible {
  opacity: 1;
}

.shop-product-3d-status {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  margin: 0;
  color: var(--eki-text-muted);
  font-size: 0.9rem;
  pointer-events: none;
}

/* `display: grid` ci-dessus l'emporte sur le `display: none` que la feuille du navigateur
   applique à [hidden] : sans cette règle, l'indicateur reste affiché PAR-DESSUS le modèle une
   fois celui-ci chargé, alors que le script l'a bien masqué (mesuré). Vaut pour tout élément
   masquable auquel on donne un display explicite. */
.shop-product-3d-status[hidden] {
  display: none;
}

/* Commandes des parties mobiles. Le conteneur est vide côté serveur et rempli par le script à
   partir des animations du modèle : sans partie mobile, il n'occupe aucune place. */
.shop-product-3d-controls {
  display: flex;
  flex-wrap: wrap;
  gap: var(--eki-space-2);
  margin-block-start: var(--eki-space-3);
}

.shop-product-3d-controls:empty {
  display: none;
}

.shop-product-3d-control {
  padding: var(--eki-space-2) var(--eki-space-4);
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-sm);
  background: var(--eki-bg-elev);
  color: var(--eki-text);
  font-size: var(--eki-fs-sm);
  cursor: pointer;
}

.shop-product-3d-control:hover:not(:disabled) {
  border-color: var(--eki-red);
}

/* Enfoncé = partie ouverte. L'état est porté par aria-pressed, pas par une classe : le lecteur
   d'écran et le style disent alors la même chose. */
.shop-product-3d-control[aria-pressed="true"] {
  border-color: var(--eki-red);
  background: color-mix(in srgb, var(--eki-red) 16%, var(--eki-bg-elev));
}

.shop-product-3d-control:disabled {
  opacity: 0.55;
  cursor: default;
}

.shop-product-3d-hint {
  margin-block-start: var(--eki-space-2);
  color: var(--eki-text-muted);
  font-size: 0.85rem;
}

/* ---------- Section avis clients (fiche /shop/{slug}) ---------- */

.shop-reviews {
  margin-block-start: var(--eki-space-12);
  padding-block-start: var(--eki-space-6);
  border-block-start: 1px solid var(--eki-border);
}

.shop-reviews-header {
  display: flex;
  align-items: baseline;
  gap: var(--eki-space-4);
  flex-wrap: wrap;
  margin-block-end: var(--eki-space-4);
}

.shop-reviews-header h2 {
  margin: 0;
}

.shop-reviews-summary {
  margin: 0;
  display: inline-flex;
  align-items: baseline;
  gap: var(--eki-space-2);
  font-size: var(--eki-fs-md);
}

.shop-reviews-summary-empty {
  color: var(--eki-text-muted);
  font-style: italic;
}

.shop-reviews-summary-count {
  color: var(--eki-text-muted);
  font-size: var(--eki-fs-sm);
}

.shop-reviews-stars {
  color: var(--eki-red);
  letter-spacing: 0.05em;
  font-size: var(--eki-fs-lg);
}

.shop-reviews-flash {
  margin-block-end: var(--eki-space-4);
  padding: var(--eki-space-3) var(--eki-space-4);
  border-radius: var(--eki-radius-sm);
  border-inline-start: 4px solid var(--eki-border);
  background: var(--eki-bg-alt);
  font-size: var(--eki-fs-sm);
}

.shop-reviews-flash-ok {
  border-inline-start-color: #10b981;
}

.shop-reviews-flash-error {
  border-inline-start-color: var(--eki-accent);
}

/* Formulaire client */
.shop-reviews-form {
  display: flex;
  flex-direction: column;
  gap: var(--eki-space-3);
  padding: var(--eki-space-5);
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-md);
  background: var(--eki-bg-alt);
  margin-block-end: var(--eki-space-6);
}

.shop-reviews-form h3 {
  margin: 0;
}

.shop-reviews-form-status {
  margin: 0;
  padding: var(--eki-space-2) var(--eki-space-3);
  border-radius: var(--eki-radius-sm);
  background: var(--eki-bg);
  font-size: var(--eki-fs-sm);
  color: var(--eki-text-muted);
}

.shop-reviews-form-status-warn {
  background: #fef3c7;
  color: #92400e;
}

/* Notation 5 étoiles cliquables (technique CSS :checked + ~ pour highlight les
   étoiles à gauche de la sélection ; markup volontairement inversé en HTML
   pour que ~ aille de droite à gauche). */
.shop-reviews-rating {
  display: flex;
  flex-direction: row-reverse;
  justify-content: flex-end;
  gap: var(--eki-space-1);
  align-items: center;
}

.shop-reviews-rating .form-help {
  margin-inline-end: var(--eki-space-3);
  font-size: var(--eki-fs-sm);
}

.shop-reviews-rating input[type="radio"] {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
}

.shop-reviews-rating label {
  font-size: var(--eki-fs-2xl);
  color: var(--eki-border);
  cursor: pointer;
  transition: color 0.1s;
  user-select: none;
  line-height: 1;
}

.shop-reviews-rating input[type="radio"]:checked ~ label,
.shop-reviews-rating label:hover,
.shop-reviews-rating label:hover ~ label {
  color: var(--eki-red);
}

.shop-reviews-rating input[type="radio"]:focus-visible + label {
  outline: 2px solid var(--eki-accent);
  outline-offset: 2px;
}

/* Photos déjà uploadées du user (édition) */
.shop-reviews-form-photos {
  margin-block-end: var(--eki-space-4);
}

.shop-reviews-form-photos ul {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  gap: var(--eki-space-3);
  flex-wrap: wrap;
}

.shop-reviews-form-photos li {
  display: flex;
  flex-direction: column;
  gap: var(--eki-space-1);
  align-items: center;
}

.shop-reviews-form-photos img {
  width: 96px;
  height: 96px;
  object-fit: cover;
  border-radius: var(--eki-radius-sm);
  border: 1px solid var(--eki-border);
}

.shop-reviews-photo-delete-form,
.shop-reviews-delete-form {
  margin: 0;
}

.shop-reviews-cta {
  margin-block-end: var(--eki-space-5);
  padding: var(--eki-space-3) var(--eki-space-4);
  border-radius: var(--eki-radius-sm);
  background: var(--eki-bg-alt);
  font-size: var(--eki-fs-sm);
}

.shop-reviews-cta a {
  color: var(--eki-red);
  font-weight: 500;
}

.shop-reviews-cta-muted {
  color: var(--eki-text-muted);
  font-style: italic;
}

/* Liste des avis publiés */
.shop-reviews-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--eki-space-5);
}

.shop-reviews-item {
  padding: var(--eki-space-5);
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-md);
}

.shop-reviews-item-head {
  display: flex;
  align-items: baseline;
  gap: var(--eki-space-3);
  flex-wrap: wrap;
  margin-block-end: var(--eki-space-2);
}

.shop-reviews-item-title {
  font-size: var(--eki-fs-md);
}

.shop-reviews-item-meta {
  color: var(--eki-text-muted);
  font-size: var(--eki-fs-sm);
}

.shop-reviews-item-body {
  margin: 0;
  white-space: pre-wrap;
  line-height: 1.5;
}

.shop-reviews-item-photos {
  list-style: none;
  padding: 0;
  margin-block-start: var(--eki-space-3);
  display: flex;
  gap: var(--eki-space-2);
  flex-wrap: wrap;
}

.shop-reviews-item-photos img {
  width: 120px;
  height: 120px;
  object-fit: cover;
  border-radius: var(--eki-radius-sm);
  border: 1px solid var(--eki-border);
}

.shop-reviews-admin-response {
  margin-block-start: var(--eki-space-3);
  padding: var(--eki-space-3) var(--eki-space-4);
  background: var(--eki-bg-alt);
  border-inline-start: 3px solid var(--eki-accent);
  border-radius: var(--eki-radius-sm);
}

.shop-reviews-admin-response strong {
  display: block;
  margin-block-end: var(--eki-space-1);
  color: var(--eki-accent);
}

.shop-reviews-admin-response p {
  margin: 0 0 var(--eki-space-1);
  white-space: pre-wrap;
}

.shop-reviews-admin-response small {
  color: var(--eki-text-muted);
}

.shop-reviews-pagination {
  display: flex;
  gap: var(--eki-space-2);
  justify-content: center;
  margin-block-start: var(--eki-space-5);
}

.shop-reviews-page {
  display: inline-block;
  min-width: 32px;
  padding: var(--eki-space-1) var(--eki-space-2);
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-sm);
  text-align: center;
  color: var(--eki-text);
  text-decoration: none;
}

.shop-reviews-page-current {
  background: var(--eki-accent);
  color: var(--eki-white, #ffffff);
  border-color: var(--eki-accent);
}

/* === Contenu éditorial de catégorie === */
/* Texte long saisi en HTML depuis l'admin, affiché sous la grille. Les styles sont posés ici et
   non dans le contenu : l'admin écrit du texte et des liens, pas de la mise en forme — sinon
   chaque catégorie finirait avec sa propre typographie. */
.shop-category-editorial {
  margin-block-start: var(--eki-space-12);
  padding-block-start: var(--eki-space-6);
  border-block-start: 1px solid var(--eki-border);
  max-inline-size: 70ch; /* longueur de ligne lisible, comme un article */
  line-height: 1.65;
  color: var(--eki-text-muted);
}
.shop-category-editorial h2,
.shop-category-editorial h3 {
  margin-block: var(--eki-space-6) var(--eki-space-2);
  color: var(--eki-text);
  font-family: var(--eki-font-display);
}
.shop-category-editorial h2 { font-size: var(--eki-fs-xl); }
.shop-category-editorial h3 { font-size: var(--eki-fs-lg); }
.shop-category-editorial h2:first-child,
.shop-category-editorial h3:first-child { margin-block-start: 0; }
.shop-category-editorial p,
.shop-category-editorial ul,
.shop-category-editorial ol {
  margin-block: 0 var(--eki-space-4);
}
.shop-category-editorial ul,
.shop-category-editorial ol {
  padding-inline-start: var(--eki-space-6);
}
.shop-category-editorial li { margin-block-end: var(--eki-space-2); }
.shop-category-editorial a {
  color: var(--eki-accent);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.shop-category-editorial table {
  inline-size: 100%;
  border-collapse: collapse;
  margin-block-end: var(--eki-space-4);
}
.shop-category-editorial th,
.shop-category-editorial td {
  padding: var(--eki-space-2);
  border-block-end: 1px solid var(--eki-border);
  text-align: start;
}


/* css/layouts/public/account.css */
/* =========================================================================
 * account.css — Pages /compte/* : formulaires, alerts, cards adresses.
 * Issu du split de layouts/public.css (refactor CSS étape 1, 2026-05-28).
 * ======================================================================== */


/* =====================================================================
 * Pages /compte/* (espace client) + formulaires publics génériques.
 * ===================================================================== */

.public-main {
  max-width: var(--eki-container-max);
  margin-inline: auto;
  padding: var(--eki-space-8) var(--eki-space-4);
}

.public-main-narrow {
  max-width: 36rem;
  margin-inline: auto;
  padding: var(--eki-space-8) var(--eki-space-4);
}

.public-main h1,
.public-main-narrow h1 {
  font-size: var(--eki-fs-2xl);
  margin-block: 0 var(--eki-space-2);
  color: var(--eki-text);
}

.public-main h2,
.public-main-narrow h2 {
  font-size: var(--eki-fs-lg);
  margin-block: var(--eki-space-6) var(--eki-space-3);
  color: var(--eki-text);
}

.public-lead {
  color: var(--eki-text-muted);
  margin-block: 0 var(--eki-space-6);
  font-size: var(--eki-fs-md);
}

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

.public-form {
  display: flex;
  flex-direction: column;
  gap: var(--eki-space-4);
  margin-block: var(--eki-space-4);
}

.public-form label {
  display: flex;
  flex-direction: column;
  gap: var(--eki-space-1);
  font-size: var(--eki-fs-sm);
  color: var(--eki-text);
}

.public-form label > span:first-child {
  font-weight: 500;
}

.public-form input[type="text"],
.public-form input[type="email"],
.public-form input[type="password"],
.public-form input[type="tel"],
.public-form input[type="number"],
.public-form select,
.public-form textarea {
  padding: var(--eki-space-2) var(--eki-space-3);
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-sm);
  background-color: var(--eki-bg);
  color: var(--eki-text);
  font-size: var(--eki-fs-md);
  font-family: inherit;
}

.public-form input:focus,
.public-form select:focus,
.public-form textarea:focus {
  outline: 2px solid var(--eki-red);
  outline-offset: 0;
  border-color: var(--eki-red);
}

/* Champ mot de passe avec bouton afficher / masquer (password-toggle.js). */
.password-field {
  display: flex;
  gap: var(--eki-space-2);
  align-items: stretch;
}

.password-field input {
  flex: 1 1 auto;
  min-width: 0;
}

.password-toggle {
  flex: 0 0 auto;
  padding: var(--eki-space-2) var(--eki-space-3);
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-sm);
  background-color: transparent;
  color: var(--eki-text);
  font-size: var(--eki-fs-sm);
  font-family: inherit;
  cursor: pointer;
}

.password-toggle:hover {
  border-color: var(--eki-red);
}

.public-form-checkbox {
  flex-direction: row !important;
  align-items: center;
  gap: var(--eki-space-2) !important;
}

.public-form-checkbox input[type="checkbox"] {
  margin: 0;
  width: 1rem;
  height: 1rem;
  accent-color: var(--eki-red);
}

.public-form-error {
  color: var(--eki-red);
  font-size: var(--eki-fs-sm);
  margin-block-start: var(--eki-space-1);
}

.public-form-footnote {
  margin-block-start: var(--eki-space-6);
  font-size: var(--eki-fs-sm);
  color: var(--eki-text-muted);
}

.public-form-legal {
  margin-block-start: var(--eki-space-3);
  font-size: var(--eki-fs-xs);
  color: var(--eki-text-muted);
}

/* Indication au-dessus d'un groupe de champs (ex. « renseignez au moins l'un des deux »). */
.public-form-hint {
  margin-block: 0 var(--eki-space-2);
  font-size: var(--eki-fs-sm);
  color: var(--eki-text-muted);
}

.public-form-legal a {
  color: var(--eki-red);
  text-decoration: underline;
}

.public-form-actions-row {
  flex-direction: row;
  flex-wrap: wrap;
  gap: var(--eki-space-2);
}

.public-form-margin-top {
  margin-block-start: var(--eki-space-6);
}

.public-form-footnote a {
  color: var(--eki-red);
  text-decoration: underline;
}

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

.public-btn-primary,
.public-btn-secondary {
  display: inline-block;
  padding: var(--eki-space-2) var(--eki-space-5);
  border: 1px solid transparent;
  border-radius: var(--eki-radius-sm);
  font-size: var(--eki-fs-md);
  font-weight: 500;
  cursor: pointer;
  text-decoration: none;
  text-align: center;
  font-family: inherit;
  transition: background-color 120ms;
}

.public-btn-primary {
  background-color: var(--eki-red);
  color: #ffffff;
  border-color: var(--eki-red);
}

.public-btn-primary:hover {
  background-color: var(--eki-red-dark);
  border-color: var(--eki-red-dark);
}

.public-btn-secondary {
  background-color: var(--eki-bg);
  color: var(--eki-text);
  border-color: var(--eki-border);
}

.public-btn-secondary:hover {
  background-color: var(--eki-gray-100);
}

/* ---------- Alerts ---------- */

.public-alert {
  padding: var(--eki-space-3) var(--eki-space-4);
  border-radius: var(--eki-radius-sm);
  margin-block: var(--eki-space-3);
  font-size: var(--eki-fs-sm);
  border-inline-start: 3px solid transparent;
}

.public-alert-error {
  background-color: #fdecea;
  border-inline-start-color: var(--eki-red);
  color: #7a1f1c;
}

.public-alert-success {
  background-color: #ecfdf5;
  border-inline-start-color: #10b981;
  color: #065f46;
}

.public-alert-info {
  background-color: #eff6ff;
  border-inline-start-color: #3b82f6;
  color: #1e3a8a;
}

/* ---------- Card / Definition list / Badge ---------- */

/* Composé avec .eki-card (étape 2). Reste : padding spécifique (--space-5 au lieu
   du --space-6 de .eki-card) + margin verticale entre cards. */
.public-card {
  padding: var(--eki-space-5);
  margin-block: var(--eki-space-4);
}

.public-card h2 {
  margin-block-start: 0;
}

.public-dl {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: var(--eki-space-2) var(--eki-space-4);
  margin: 0;
  font-size: var(--eki-fs-sm);
}

.public-dl dt {
  color: var(--eki-text-muted);
  font-weight: 500;
}

.public-dl dd {
  margin: 0;
  color: var(--eki-text);
}

.public-badge {
  display: inline-block;
  padding: var(--eki-space-1) var(--eki-space-2);
  font-size: var(--eki-fs-xs);
  font-weight: 500;
  border-radius: var(--eki-radius-sm);
  background-color: #fef3c7;
  color: #92400e;
  margin-inline-start: var(--eki-space-2);
}

/* ---------- Tableau de bord compte (/account) ---------- */

.account-actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--eki-space-3);
  margin-block: var(--eki-space-6);
}

@media (max-width: 560px) {
  .account-actions {
    grid-template-columns: 1fr;
  }
}

.account-action {
  display: flex;
  flex-direction: column;
  gap: var(--eki-space-1);
  padding: var(--eki-space-4);
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-md);
  background: var(--eki-bg);
  text-decoration: none;
  color: var(--eki-text);
  transition: border-color 120ms, background-color 120ms, transform 120ms;
}

.account-action:hover {
  border-color: var(--eki-red);
  background: var(--eki-bg-elev);
  transform: translateY(-2px);
}

/* Carte « à venir » (ex. Mes factures, Phase 2) : présente mais non cliquable, atténuée. */
.account-action-disabled {
  opacity: 0.55;
  cursor: default;
  border-style: dashed;
}

.account-action-disabled:hover {
  border-color: var(--eki-border);
  background: var(--eki-bg);
  transform: none;
}

.account-action-title {
  font-weight: 600;
  font-size: var(--eki-fs-md);
}

.account-action-sub {
  font-size: var(--eki-fs-sm);
  color: var(--eki-text-muted);
}

.account-logout {
  margin-block-start: var(--eki-space-6);
}

/* ---------- Liste d'adresses (/compte/adresses) ---------- */

.address-list {
  list-style: none;
  padding: 0;
  margin: 0 0 var(--eki-space-6);
  display: flex;
  flex-direction: column;
  gap: var(--eki-space-3);
}

/* Carte adresse expandable : summary cliquable, detail caché jusqu'à .expanded. */
.address-card {
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-md);
  background-color: var(--eki-bg);
  overflow: hidden;
  transition: border-color 120ms;
}

.address-card:hover {
  border-color: var(--eki-text-muted);
}

.address-card-summary {
  padding: var(--eki-space-4);
  cursor: pointer;
  display: flex;
  flex-direction: column;
  gap: var(--eki-space-2);
  position: relative;
}

.address-card-summary .row-chevron {
  position: absolute;
  inset-inline-end: var(--eki-space-4);
  top: var(--eki-space-4);
  color: var(--eki-text-muted);
  transition: transform 120ms;
}

.address-card.expanded .row-chevron {
  transform: rotate(180deg);
}

.address-card-detail {
  display: none;
  padding: 0 var(--eki-space-4) var(--eki-space-4);
  border-top: 1px solid var(--eki-border);
}

.address-card.expanded .address-card-detail {
  display: block;
}

.address-card-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--eki-space-2);
  margin-block-start: var(--eki-space-3);
}

.address-card-actions .public-btn-primary,
.address-card-actions .public-btn-secondary {
  font-size: var(--eki-fs-sm);
  padding: var(--eki-space-1) var(--eki-space-3);
}

.address-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--eki-space-2);
  padding-inline-end: var(--eki-space-6); /* place au chevron */
}

.address-head .public-badge {
  margin-inline-start: 0;
}

.address-body {
  font-style: normal;
  font-size: var(--eki-fs-sm);
  color: var(--eki-text-muted);
  line-height: 1.5;
  margin: 0;
}

/* Carte « par défaut » : liseré rouge d'ancrage charte sur le bord interne. */
.address-card--default {
  border-inline-start: 3px solid var(--eki-red);
}

.public-badge--default {
  background-color: #fde8e7;
  color: var(--eki-red-dark);
}

/* Bouton Supprimer poussé à droite de la barre d'actions pour le séparer du reste. */
.address-btn-delete {
  margin-inline-start: auto;
  color: var(--eki-red);
}

/* ---------- Grille de champs adresse (dense, responsive) ---------- */

/* Paires de champs côte à côte sur écran large, empilées sur mobile. La grille est
   un enfant direct de .public-form → hérite du gap vertical entre blocs. */
.addr-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--eki-space-4);
}

/* CP étroit + Ville large. */
.addr-grid--zip {
  grid-template-columns: minmax(0, 9rem) 1fr;
}

.addr-grid > label {
  margin: 0;
}

@media (max-width: 560px) {
  .addr-grid,
  .addr-grid--zip {
    grid-template-columns: 1fr;
  }
}

/* ---------- Formulaire d'ajout repliable ---------- */

/* Card masquée par défaut ; le bouton « + Ajouter » la révèle (ou .is-open posé
   côté serveur quand le client n'a encore aucune adresse). */
.address-add-card {
  display: none;
}

.address-add.is-open .address-add-card {
  display: block;
}

.address-add.is-open .address-add-toggle {
  display: none;
}

/* ---------- Historique devis / factures (/account/devis, /account/factures) ---------- */

.public-table {
  width: 100%;
  border-collapse: collapse;
  margin-block: var(--eki-space-4);
  font-size: var(--eki-fs-sm);
}

.public-table th,
.public-table td {
  padding: var(--eki-space-3) var(--eki-space-3);
  text-align: left;
  border-block-end: 1px solid var(--eki-border);
}

.public-table thead th {
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-size: var(--eki-fs-xs);
  color: var(--eki-text-muted);
  background: var(--eki-bg-alt);
}

.public-table .num { text-align: right; }

.public-table a {
  color: var(--eki-red);
  text-decoration: none;
  font-weight: 500;
}
.public-table a:hover { text-decoration: underline; }

.public-empty {
  padding: var(--eki-space-4);
  background: var(--eki-bg-alt);
  border-radius: var(--eki-radius-sm);
  color: var(--eki-text-muted);
  font-style: italic;
  margin-block: var(--eki-space-4);
}

.public-help {
  color: var(--eki-text-muted);
  font-size: var(--eki-fs-sm);
  margin-block: var(--eki-space-3);
}

/* Badges statut devis (réutilise palette de l'admin pour cohérence visuelle entre
   espaces commercial et client). */
.public-table .deal-status {
  display: inline-block;
  padding: 2px var(--eki-space-2);
  border-radius: var(--eki-radius-sm);
  font-size: var(--eki-fs-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.public-table .deal-status-draft     { background: var(--eki-bg-alt); color: var(--eki-text-muted); }
.public-table .deal-status-sent      { background: #dbeafe; color: #1e40af; }
.public-table .deal-status-viewed    { background: #ddd6fe; color: #5b21b6; }
.public-table .deal-status-accepted  { background: #d1fae5; color: #065f46; }
.public-table .deal-status-refused   { background: #fee2e2; color: #991b1b; }
.public-table .deal-status-expired   { background: #fef3c7; color: #92400e; }
.public-table .deal-status-cancelled { background: #f3f4f6; color: #6b7280; }

/* ---------- Équipe / référent (/account/team — ADR-031 §3) ---------- */

.team-list {
  list-style: none;
  padding: 0;
  margin: 0 0 var(--eki-space-5);
  display: flex;
  flex-direction: column;
  gap: var(--eki-space-2);
}

.team-member {
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-md);
  background-color: var(--eki-bg);
  padding: var(--eki-space-3) var(--eki-space-4);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--eki-space-3);
}

/* Demande en attente : liseré rouge d'ancrage charte (réclame une décision). */
.team-member--pending {
  border-inline-start: 3px solid var(--eki-red);
}

.team-member-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--eki-space-2);
}

.team-member-email {
  font-size: var(--eki-fs-sm);
  color: var(--eki-text-muted);
}

.team-member-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--eki-space-2);
}

.team-member-actions .public-btn-primary,
.team-member-actions .public-btn-secondary {
  font-size: var(--eki-fs-sm);
  padding: var(--eki-space-1) var(--eki-space-3);
}


/* css/layouts/public/cart.css */
/* =========================================================================
 * cart.css — Panier client : ajout depuis la fiche /shop, page /cart, badge header.
 * ======================================================================== */

/* ---------- Ajout au panier (fiche /shop) ---------- */

.shop-add-form {
  display: flex;
  align-items: flex-end;
  gap: var(--eki-space-3);
  flex-wrap: wrap;
  margin-block-start: var(--eki-space-4);
}

.shop-add-qty {
  display: flex;
  flex-direction: column;
  gap: var(--eki-space-1);
  font-size: var(--eki-fs-sm);
  color: var(--eki-text-muted);
}

.shop-add-qty input {
  width: 5rem;
  padding: var(--eki-space-2) var(--eki-space-3);
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-sm);
  background: var(--eki-bg);
  color: var(--eki-text);
}

.shop-add-error {
  color: var(--eki-red);
  font-size: var(--eki-fs-sm);
  margin-block-start: var(--eki-space-2);
}

/* ---------- Compteur panier dans le header ---------- */

.site-header-action-cart {
  position: relative;
}

.cart-badge {
  position: absolute;
  top: -4px;
  inset-inline-end: -6px;
  min-width: 1.1rem;
  height: 1.1rem;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--eki-red);
  color: #fff;
  font-size: 0.7rem;
  font-weight: 700;
  line-height: 1.1rem;
  text-align: center;
}

/* ---------- Page /cart ---------- */

.cart-table .eki-photo__thumb {
  vertical-align: middle;
  margin-inline-end: var(--eki-space-2);
}

.cart-gtin {
  display: block;
  color: var(--eki-text-muted);
  font-size: var(--eki-fs-xs);
}

.cart-qty-input {
  width: 4.5rem;
  padding: var(--eki-space-1) var(--eki-space-2);
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-sm);
  background: var(--eki-bg);
  color: var(--eki-text);
  text-align: center;
}

/* Article : vignette + libellé alignés. */
.cart-article {
  display: flex;
  align-items: center;
  gap: var(--eki-space-3);
}

.cart-article-text a {
  color: var(--eki-text);
  font-weight: 500;
  text-decoration: none;
}
.cart-article-text a:hover { color: var(--eki-red); text-decoration: underline; }

/* Prix catalogue barré (quand le client a un tarif préférentiel). */
.cart-catalog-price {
  color: var(--eki-text-muted);
}

.cart-ship-pending {
  color: var(--eki-text-muted);
  font-style: italic;
}

.cart-foot-catalog td {
  color: var(--eki-text-muted);
}

.cart-foot-total td {
  border-top: 2px solid var(--eki-border);
  font-size: var(--eki-fs-md);
}

/* Ligne « Frais de port HT » du pied : libellé à gauche, sélecteur d'adresse à droite. */
.cart-ship-row {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--eki-space-3);
}

.cart-ship-select {
  padding: var(--eki-space-1) var(--eki-space-2);
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-sm);
  background: var(--eki-bg);
  color: var(--eki-text);
  max-width: 22rem;
  font-size: var(--eki-fs-sm);
}

.cart-actions {
  display: flex;
  gap: var(--eki-space-3);
  flex-wrap: wrap;
  margin-block: var(--eki-space-5);
}


/* css/layouts/public/editorial.css */
/* =========================================================================
 * editorial.css — Pages About (team cards + sections encadrées) + Contact (cards + carte OSM).
 * Issu du split de layouts/public.css (refactor CSS étape 1, 2026-05-28).
 * ======================================================================== */


/* =====================================================================
 * Page About — header narratif + team cards portrait 4:5 + sections texte.
 * Inspiré sites fabricants premium (Festool /Knipex About).
 * ===================================================================== */

.about-page {
  max-width: var(--eki-container-max);
  margin-inline: auto;
  padding: var(--eki-space-12) var(--eki-space-4) var(--eki-space-16);
}

.about-header {
  max-width: 48rem;
  margin: 0 auto var(--eki-space-16);
  text-align: center;
}

.about-eyebrow {
  margin: 0 0 var(--eki-space-3);
  font-size: var(--eki-fs-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--eki-red);
}

.about-title {
  font-family: var(--eki-font-display);
  font-size: clamp(1.875rem, 4vw, 3rem);
  line-height: 1.1;
  letter-spacing: -0.01em;
  margin: 0 0 var(--eki-space-5);
  color: var(--eki-text);
}

.about-lead {
  font-size: var(--eki-fs-lg);
  line-height: 1.6;
  color: var(--eki-text-muted);
  margin: 0;
}

/* ----- Team cards ----- */

.about-team {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--eki-space-8);
  margin-block-end: var(--eki-space-16);
}

@media (max-width: 880px) {
  .about-team { grid-template-columns: 1fr; gap: var(--eki-space-6); }
}

.about-team-card {
  background: var(--eki-bg-elev);
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-lg);
  overflow: hidden;
  transition: border-color 200ms, transform 200ms, box-shadow 200ms;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.06);
}

.about-team-card:hover {
  border-color: var(--eki-red);
  transform: translateY(-4px);
  box-shadow: 0 16px 40px rgba(0, 0, 0, 0.18);
}

.about-team-portrait {
  position: relative;
  width: 100%;
  aspect-ratio: 4 / 5;
  background: var(--eki-bg-alt);
  overflow: hidden;
}

.about-team-portrait img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  position: relative;
  z-index: 2;
}

.about-team-portrait img.is-missing {
  display: none;
}

/* Fallback affiché si l'image n'est pas (encore) déposée :
   initiales géantes en filigrane sur fond dégradé sobre. */
.about-team-portrait-fallback {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  background:
    radial-gradient(ellipse at 30% 30%, rgba(203,40,33,.06), transparent 60%),
    linear-gradient(135deg, var(--eki-bg-alt), var(--eki-gray-100));
}

.about-team-portrait-fallback span {
  font-family: var(--eki-font-display);
  font-size: clamp(4rem, 10vw, 6rem);
  font-weight: 700;
  color: var(--eki-red);
  opacity: .25;
  letter-spacing: 0.05em;
}

.about-team-body {
  padding: var(--eki-space-6);
  background: var(--eki-bg-elev);
  border-block-start: 3px solid transparent;
  transition: border-color 200ms;
}

.about-team-card:hover .about-team-body {
  border-block-start-color: var(--eki-red);
}

.about-team-role {
  margin: 0 0 var(--eki-space-2);
  font-size: var(--eki-fs-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--eki-red);
}

.about-team-name {
  font-family: var(--eki-font-display);
  font-size: var(--eki-fs-2xl);
  letter-spacing: -0.01em;
  margin: 0 0 var(--eki-space-3);
  color: var(--eki-text);
}

.about-team-bio {
  margin: 0;
  font-size: var(--eki-fs-md);
  line-height: 1.65;
  color: var(--eki-text);
}

/* ----- Sections texte About — cards encadrées pour rythme visuel ----- */

.about-section {
  max-width: 56rem;
  margin: 0 auto var(--eki-space-8);
  padding: var(--eki-space-8) var(--eki-space-8);
  background: var(--eki-bg-elev);
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-lg);
  position: relative;
}

@media (max-width: 880px) {
  .about-section {
    padding: var(--eki-space-6) var(--eki-space-5);
  }
}

.about-section h2 {
  font-family: var(--eki-font-display);
  font-size: clamp(1.5rem, 2.5vw, var(--eki-fs-2xl));
  letter-spacing: -0.01em;
  margin: 0 0 var(--eki-space-5);
  padding-block-end: var(--eki-space-3);
  border-block-end: 2px solid var(--eki-red);
  color: var(--eki-text);
  display: inline-block;
}

.about-section p {
  font-size: var(--eki-fs-md);
  line-height: 1.7;
  color: var(--eki-text);
  margin: 0 0 var(--eki-space-4);
}

.about-section p:last-child {
  margin-block-end: 0;
}

.about-section a {
  color: var(--eki-red);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}

/* Liste sans marker natif (invisible en dark) — bullets ✓ rouge custom. */
.about-list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: var(--eki-space-3);
}

.about-list li {
  position: relative;
  padding-inline-start: var(--eki-space-8);
  color: var(--eki-text);
  line-height: 1.65;
}

.about-list li::before {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  inset-block-start: 0.35em;
  width: 18px;
  height: 18px;
  background-color: var(--eki-red);
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M4 12l5 5L20 6' fill='none' stroke='black' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'/></svg>") no-repeat center / contain;
          mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M4 12l5 5L20 6' fill='none' stroke='black' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'/></svg>") no-repeat center / contain;
}

.about-list li strong {
  color: var(--eki-text);
  font-weight: 700;
}

/* CTA bottom : centré sans bordure supérieure (le rythme est déjà donné par les cards). */
.about-cta {
  max-width: 56rem;
  margin: var(--eki-space-12) auto 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--eki-space-3);
}

/* ---------- Contact : 2 colonnes (cards + carte) ---------- */

.contact-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
  gap: var(--eki-space-8);
  align-items: stretch;
}

@media (max-width: 880px) {
  .contact-layout {
    grid-template-columns: 1fr;
    gap: var(--eki-space-6);
  }
}

.contact-cards {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--eki-space-5);
  align-content: stretch;
}

@media (max-width: 560px) {
  .contact-cards {
    grid-template-columns: 1fr;
  }
}

/* Composé avec .eki-card (étape 2). Reste : padding asymétrique légèrement
   réduit en bas, gap plus serré que la primitive (--space-2 au lieu de
   --space-3). Le `> * { margin:0 }` est déjà fait par .eki-card. */
.contact-card {
  padding: var(--eki-space-6) var(--eki-space-6) var(--eki-space-5);
  gap: var(--eki-space-2);
}

/* @deprecated 2026-05-28 — utiliser .eki-card--primary à la place. */
.contact-card-primary { border-color: var(--eki-accent); }

/* @deprecated 2026-05-28 — utiliser .eki-card--muted à la place. */
.contact-card-muted { background: var(--eki-bg-alt); }

.contact-card h2 {
  font-size: var(--eki-fs-sm);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--eki-text-muted);
  margin: 0 0 var(--eki-space-2);
  font-family: inherit;
  line-height: 1.3;
}

.contact-emphasis {
  font-size: var(--eki-fs-lg);
  font-weight: 500;
  margin: 0;
}

.contact-emphasis a {
  color: var(--eki-red);
  text-decoration: none;
}

.contact-emphasis a:hover {
  text-decoration: underline;
}

.contact-note {
  margin: 0;
  font-size: var(--eki-fs-sm);
  color: var(--eki-text-muted);
  font-style: italic;
}

.contact-card-link {
  display: inline-block;
  margin-top: var(--eki-space-3);
  color: var(--eki-red);
  text-decoration: none;
  font-size: var(--eki-fs-sm);
  font-weight: 500;
}

.contact-card-link:hover {
  text-decoration: underline;
}

/* Carte (iframe OSM embed). Grid template-rows pour que l'iframe stretch sur tout
   l'espace disponible de la cellule et que la légende reste auto-fit en bas.
   Le align-items: stretch côté .contact-layout fait que la map prend la hauteur
   du bloc cards à gauche. */
.contact-map {
  display: grid;
  grid-template-rows: 1fr auto;
  gap: var(--eki-space-3);
  min-height: 420px;
}

.contact-map iframe {
  width: 100%;
  height: 100%;
  min-height: 360px;
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-md);
  display: block;
  color-scheme: light;
}

.contact-map-caption {
  margin: 0;
  font-size: var(--eki-fs-sm);
  color: var(--eki-text-muted);
}

.contact-map-caption a {
  color: var(--eki-red);
  text-decoration: none;
}

.contact-map-caption a:hover {
  text-decoration: underline;
}

/* ---------- Page /rendez-vous (embed Bookings) ----------
   L'iframe Bookings n'est pas thématisable (cross-origin), on assume le contraste
   blanc/sombre comme une intention design : carte flottante centrée volontairement
   étroite, ombre forte qui décolle de la page, liseré rouge top pour ancrer la
   charte. */

.rendezvous-page .content-page-header {
  /* Aucun écart sous le titre : le liseret rouge top de l'iframe colle
     directement au bord inférieur de la zone noire du header. */
  margin-block-end: 0;
  padding-block-end: 0;
  border-block-end: none;
}

/* Le .content-page parent ajoute un padding-block — on le neutralise en bas
   pour que l'iframe full-viewport touche aussi le bas de la page sans bande noire. */
.rendezvous-page {
  padding-block-end: 0;
}

/* Canvas full-viewport : adoucit la transition page sombre → iframe blanche
   par un fond légèrement plus clair. Pas de "carte dans une carte" : l'iframe
   est directement intégrée dans le canvas avec ses bords arrondis et le liseré
   rouge top, pas de wrapper visuel intermédiaire. */
/* Wrapper iframe full-viewport : extend au-delà du container parent via la
   technique width: 100vw + margin: calc(50% - 50vw). Liseret rouge top + iframe
   blanche directement collée à la page sombre — pas de fond intermédiaire. */
.rendezvous-embed-wrapper {
  width: 100vw;
  position: relative;
  left: 50%;
  right: 50%;
  margin-inline: -50vw;
  background: #ffffff;
  color-scheme: light;
}

/* Liseré rouge top sur toute la largeur — ancrage charte EKI. */
.rendezvous-embed-wrapper::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 4px;
  background: linear-gradient(90deg, var(--eki-red) 0%, var(--eki-red-dark) 100%);
  z-index: 1;
}

.rendezvous-iframe {
  display: block;
  width: 100%;
  /* On ne peut pas mesurer le contenu (cross-origin Same-Origin Policy +
     Microsoft Bookings ne pousse pas postMessage). On opte donc pour une hauteur
     fixe assez grande pour absorber tout le tunnel Bookings (services + date +
     heure + formulaire complet + footer Microsoft) sans déclencher de scrollbar
     interne. Le scroll naturel de page prend le relais.
     Un peu de blanc en bas est accepté comme trade-off vs double-scrollbar. */
  height: 2400px;
  border: 0;
  background: #ffffff;
}

@media (min-width: 1200px) {
  .rendezvous-iframe {
    /* En 2-col Bookings est plus court mais affiche tout en même temps (services
       + date + heure + form). 1900px couvre le tunnel complet sans scroll. */
    height: 1900px;
  }
}



/* css/layouts/public/distributors.css */
/* === Carte publique des distributeurs (/distributors) === */

.public-map-content {
  max-width: 1100px;
  margin: 0 auto;
  padding: var(--eki-space-6) var(--eki-space-4);
}

.public-map-intro {
  color: var(--eki-text-muted);
  max-width: 60ch;
}

/* Barre de recherche : champ adresse + bouton « Centrer ». Le champ porte
   position:relative pour ancrer le dropdown .eki-autocomplete (top:100%). */
.public-map-search {
  display: flex;
  gap: var(--eki-space-2);
  align-items: stretch;
  margin-top: var(--eki-space-4);
}

.public-map-search__field {
  position: relative;
  flex: 1 1 auto;
}

.public-map-search__field input {
  width: 100%;
  padding: var(--eki-space-3);
  font: inherit;
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-sm);
  background: var(--eki-bg);
  color: var(--eki-text);
}

.public-map-search__field input:focus {
  outline: 2px solid var(--eki-accent);
  outline-offset: 1px;
  border-color: var(--eki-accent);
}

.public-map-search__btn {
  flex: 0 0 auto;
}

.public-map {
  height: 65vh;
  min-height: 420px;
  margin-top: var(--eki-space-4);
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-md);
  /* Contexte d'empilement isolé : les calques Leaflet restent sous le header sticky. */
  position: relative;
  z-index: 0;
}

.public-map-popup-sep {
  margin: 0.6em 0;
  border: 0;
  border-top: 1px solid var(--eki-border);
}

/* Fiche d'une société dans le popup : logo, nom, adresse, liens de contact, itinéraire.
   Les sélecteurs préfixés .leaflet-popup-content battent les styles de liens de
   leaflet.css (.leaflet-container a, chargé après app.css via @section HeadExtra). */
.public-map-card {
  display: flex;
  flex-direction: column;
  gap: 0.3em;
  min-width: 190px;
  padding: 0.15em 0;
}

.public-map-card__logo {
  display: block;
  max-width: 130px;
  max-height: 52px;
  object-fit: contain;
  margin-bottom: 0.3em;
}

.public-map-card__name {
  font-weight: 700;
  font-size: 1.15em;
  line-height: 1.25;
}

.public-map-card__addr {
  color: var(--eki-text-muted);
  line-height: 1.4;
}

.public-map-card__links {
  margin-top: 0.25em;
  line-height: 1.7;
}

.leaflet-popup-content .public-map-card__links a {
  color: #cb2821; /* rouge EKI, raccord avec les marqueurs */
  text-decoration: none;
}

.leaflet-popup-content .public-map-card__links a:hover {
  text-decoration: underline;
}

.leaflet-popup-content .public-map-card__directions {
  margin-top: 0.5em;
  font-weight: 600;
  color: #cb2821;
  text-decoration: none;
}

.leaflet-popup-content .public-map-card__directions:hover {
  text-decoration: underline;
}

/* === Liste synchronisée sur la vue === */
/* Deux colonnes : la liste dit ce que la carte montre, et sert de repli quand la carte ne charge
   pas (tuiles bloquées, JS coupé). C'est le schéma des moteurs de points de vente — carte pour
   situer, liste pour lire et comparer. */
.public-map-layout {
  display: grid;
  grid-template-columns: minmax(280px, 22rem) 1fr;
  gap: var(--eki-space-4);
  margin-top: var(--eki-space-4);
  align-items: start;
}

.public-map-layout .public-map {
  margin-top: 0;
}

.public-map-panel {
  /* La liste défile seule, à la hauteur de la carte : sans ça, dix distributeurs allongent la
     page et désalignent les deux colonnes. */
  max-height: 65vh;
  min-height: 420px;
  overflow-y: auto;
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-md);
  background: var(--eki-bg-elev);
}

.public-map-count {
  position: sticky;
  top: 0;
  margin: 0;
  padding: var(--eki-space-3) var(--eki-space-4);
  background: var(--eki-bg-alt);
  border-bottom: 1px solid var(--eki-border);
  font-size: var(--eki-fs-sm);
  color: var(--eki-text-muted);
}

.public-map-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.public-map-list__item + .public-map-list__item {
  border-top: 1px solid var(--eki-border);
}

.public-map-list__button {
  display: block;
  inline-size: 100%;
  padding: var(--eki-space-3) var(--eki-space-4);
  background: transparent;
  border: 0;
  text-align: start;
  cursor: pointer;
  font: inherit;
  color: inherit;
}

.public-map-list__button:hover,
.public-map-list__button:focus-visible {
  background: var(--eki-bg-alt);
}

/* Le contenu d'une entrée est celui d'un popup : on neutralise ce qui n'a de sens qu'en bulle. */
.public-map-list__button .public-map-card__directions {
  display: none;
}

/* Bascule liste / carte — masquée tant que les deux tiennent côte à côte. */
.public-map-viewtoggle {
  display: none;
  gap: var(--eki-space-2);
  margin-top: var(--eki-space-4);
}

@media (max-width: 900px) {
  .public-map-layout {
    grid-template-columns: 1fr;
  }
  .public-map-viewtoggle {
    display: flex;
  }
  .public-map-viewtoggle button {
    flex: 1;
    padding: var(--eki-space-2) var(--eki-space-3);
    background: var(--eki-bg-elev);
    border: 1px solid var(--eki-border);
    border-radius: var(--eki-radius-sm);
    font: inherit;
    cursor: pointer;
  }
  .public-map-viewtoggle button[aria-pressed="true"] {
    background: var(--eki-red);
    border-color: var(--eki-red);
    color: #fff;
  }
  /* Un seul des deux à la fois : côte à côte, chacun devient trop petit pour servir. */
  .public-map-layout[data-view="map"] .public-map-panel { display: none; }
  .public-map-layout[data-view="list"] .public-map { display: none; }
  .public-map-panel { max-height: none; }
}


/* css/layouts/public/guide.css */
/* =========================================================================
 * guide.css — gabarit des pages « Conseils techniques ».
 *
 * Une page de conseil est longue par nature : on y cherche une réponse précise
 * plus qu'on ne la lit d'un trait. Le gabarit répond à ça — sommaire persistant
 * qui dit où l'on est, largeur de ligne bornée, et des blocs qui donnent des
 * points d'entrée visuels au survol de la page (repères chiffrés, encadrés,
 * tableaux comparatifs).
 * ======================================================================== */

.guide-layout {
  /* Même conteneur que toute page publique : le contenu occupe la largeur normale, sans colonne
     qui le rétrécisse. Le sommaire vit en dehors du flux — dans la marge quand elle existe, en
     panneau ouvrable sinon. */
  max-width: var(--eki-container-max);
  margin-inline: auto;
  padding: var(--eki-space-10) var(--eki-space-4);
}

.guide-header {
  padding-block-end: var(--eki-space-6);
  border-block-end: 1px solid var(--eki-border);
}

.guide-eyebrow {
  margin: 0 0 var(--eki-space-2);
  font-size: var(--eki-fs-sm);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--eki-red);
}

.guide-header h1 {
  font-family: var(--eki-font-display);
  font-size: clamp(2rem, 4.5vw, 3.25rem);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.1;
  margin-block: 0 var(--eki-space-4);
}

.guide-lead {
  margin: 0;
  font-size: var(--eki-fs-lg);
  line-height: 1.55;
  color: var(--eki-text-muted);
  max-inline-size: 44rem;
}

/* Temps de lecture et date : deux informations que le lecteur d'un guide cherche
   avant de s'engager — « est-ce long ? » et « est-ce encore vrai ? ». */
.guide-meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--eki-space-4);
  margin-block-start: var(--eki-space-4);
  font-size: var(--eki-fs-sm);
  color: var(--eki-text-muted);
}

/* ---------- Sommaire ---------- */

/* Tant qu'il n'y a pas de marge à occuper, le sommaire est un bloc replié EN TÊTE DU CONTENU,
   dans le flux. C'est là qu'on cherche un sommaire — il sert à décider où aller avant de lire, pas
   à être rappelé en cours de route. Un panneau flottant en bas d'écran est un raccourci d'action ;
   il masque du contenu en permanence et se découvre beaucoup moins. Replié, il ne coûte qu'une
   ligne. */
.guide-toc {
  margin-block: var(--eki-space-6);
  transition: opacity var(--eki-transition-fast);
}

/* Rangé : dans la marge, le sommaire est fixé et se poserait sur le pied de page une fois la
   page finie. Le script l'efface quand celui-ci le rejoint. `visibility` en plus de l'opacité —
   un bloc transparent reste cliquable et atteignable au clavier. */
.guide-toc--tucked {
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--eki-transition-fast), visibility 0s linear var(--eki-transition-fast);
}

.guide-toc__mobile {
  position: relative;   /* référence du repère de position posé sur le rail */
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-md);
  background: var(--eki-bg-alt);
  padding: var(--eki-space-3) var(--eki-space-4);
}

.guide-toc__mobile > summary {
  cursor: pointer;
  font-weight: 600;
  font-size: var(--eki-fs-sm);
  white-space: nowrap;
}

/* Déplié, il reste borné : sur un écran court, la liste entière repousserait le premier
   paragraphe hors de vue. */
.guide-toc__mobile[open] {
  max-block-size: 60vh;
  overflow-y: auto;
}

/* Une fois le sommaire d'origine sorti de l'écran, il revient en barre collante SOUS LE BANDEAU.
   En haut et non en bas : un sommaire est de la navigation, il a sa place avec celle du site, et le
   bas est déjà occupé par le retour en haut — deux pastilles flottantes y encombreraient la zone de
   lecture. La barre ne masque rien : le contenu défile dessous.
   La classe est posée par le script, jamais au chargement — un sommaire flottant présent d'emblée
   doublerait celui de tête. */
.guide-toc--floating {
  position: fixed;
  /* Le bandeau est forcément compacté à ce moment : la barre n'apparaît qu'après défilement. */
  inset-block-start: var(--eki-header-height-compact);
  inset-inline: 0;
  z-index: 30;
  margin: 0;
  max-inline-size: none;
}

.guide-toc--floating .guide-toc__mobile {
  border-inline: 0;
  border-block-start: 0;
  border-radius: 0;
  background: var(--eki-bg-elev);
  box-shadow: var(--eki-shadow-md);
  /* Aligné sur le contenu de la page, pas collé au bord de l'écran. */
  padding-inline: max(var(--eki-space-4), calc((100vw - var(--eki-container-max)) / 2 + var(--eki-space-4)));
}

/* Replié, la barre ne pèse qu'une ligne : le titre de section n'a plus lieu d'être. */
.guide-toc--floating .guide-toc__mobile:not([open]) .guide-toc__title {
  display: none;
}

.guide-toc--floating .guide-toc__mobile[open] {
  max-block-size: 60vh;
  overflow-y: auto;
}

/* Le sommaire rejoint la marge dès qu'elle peut l'accueillir. Le seuil n'est pas une classe
   d'appareil mais une géométrie : conteneur (1280) + deux fois (largeur du sommaire + gouttière).
   En dessous, il empiéterait sur le texte — ce qui est exactement ce qu'on veut éviter. */
@media (min-width: 1800px) {
  .guide-toc {
    position: fixed;
    z-index: 30;
    margin-block: 0;
    inset-block-start: calc(var(--eki-header-height) + var(--eki-space-6));
    /* Bord gauche du conteneur, moins la largeur du sommaire et sa gouttière. */
    inset-inline-start: calc((100vw - var(--eki-container-max)) / 2 - 15rem);
    inline-size: 14rem;
    max-block-size: calc(100vh - var(--eki-header-height) - var(--eki-space-12));
    overflow-y: auto;
  }

  /* Dans la marge, c'est un élément de page et non un panneau : ni cadre, ni ombre, ni bouton. */
  .guide-toc__mobile,
  .guide-toc__mobile[open] {
    border: 0;
    background: transparent;
    padding: 0;
    max-block-size: none;
    overflow: visible;
  }

  .guide-toc__mobile > summary {
    display: none;
  }
}

.guide-toc__title {
  margin: 0 0 var(--eki-space-3);
  font-size: var(--eki-fs-sm);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--eki-text-muted);
}

.guide-toc__list {
  list-style: none;
  margin: 0;
  padding: 0;
  border-inline-start: 2px solid var(--eki-border);
}

.guide-toc__list a {
  display: block;
  padding: var(--eki-space-2) var(--eki-space-3);
  margin-inline-start: -2px;
  border-inline-start: 2px solid transparent;
  font-size: var(--eki-fs-sm);
  line-height: 1.4;
  color: var(--eki-text-muted);
  text-decoration: none;
}

.guide-toc__list a:hover {
  color: var(--eki-text);
}

/* Section en cours de lecture. Le repère se pose sur le trait, pas sur un fond : à cette taille,
   un aplat de couleur pèse plus que le titre qu'il désigne. */
/* Le nom de la section lue — ou de celle qu'on vient de viser d'un clic. Rien d'autre : pas de
   mise en gras, qui élargit le texte et ferait passer à deux lignes l'entrée qui devient
   courante ; pas de trait non plus, c'est le repère de position qui tient le rail. */
.guide-toc__list a[aria-current="true"] {
  color: var(--eki-red);
}

/* Repère de position sur le rail, à la façon d'un ascenseur : il suit le défilement en continu
   et glisse d'une entrée vers la suivante à mesure qu'on avance dans la section — y compris
   pendant le trajet d'un clic, où le nom, lui, reste sur la cible. Posé et dimensionné par le
   script : sans lui, il n'aurait aucune position à montrer. */
.guide-toc__thumb {
  position: absolute;
  inset-block-start: 0;
  inline-size: 2px;
  border-radius: 1px;
  background: var(--eki-red);
  opacity: 0;
  pointer-events: none;
}

/* ---------- Corps ---------- */

.guide-body {
  /* Pas de borne : le contenu occupe la largeur du conteneur, comme toute page publique. */
}

/* Dégagement au-dessus d'une ancre. Ce qui la recouvre après défilement, c'est le bandeau
   COMPACTÉ plus la barre de sommaire ; la hauteur au repos ne concerne que le haut de page,
   où l'on n'atterrit pas par une ancre. Posé sur les trois cibles possibles : les liens du
   sommaire visent la <section>, celle-ci ne portait aucun dégagement et son titre arrivait
   sous le bandeau. */
.guide-section,
.guide-section h2,
.guide-section h3 {
  scroll-margin-block-start: calc(var(--eki-header-height-compact) + 3rem + var(--eki-space-4));
}

.guide-section {
  margin-block-end: var(--eki-space-12);
}

.guide-section h2 {
  font-family: var(--eki-font-display);
  font-size: var(--eki-fs-2xl);
  margin-block: 0 var(--eki-space-4);
}

.guide-section h3 {
  font-size: var(--eki-fs-lg);
  margin-block: var(--eki-space-6) var(--eki-space-2);
}

.guide-section p,
.guide-section li {
  line-height: 1.7;
}

.guide-section p {
  margin-block: 0 var(--eki-space-4);
}

.guide-section a:not([class]) {
  color: var(--eki-red);
}

.guide-list {
  margin-block: 0 var(--eki-space-4);
  padding-inline-start: var(--eki-space-6);
}

.guide-list li {
  margin-block-end: var(--eki-space-2);
}

/* ---------- Blocs visuels ---------- */

/* Repères chiffrés : les valeurs qu'on vient chercher (épaisseurs, pas, tolérance)
   sortent du texte courant, où elles se perdent. */
.guide-figures {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  gap: var(--eki-space-4);
  margin-block: var(--eki-space-6);
  padding: var(--eki-space-4);
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-md);
  background: var(--eki-bg-alt);
}

.guide-figure__value {
  display: block;
  font-family: var(--eki-font-display);
  font-size: var(--eki-fs-xl);
  font-weight: 700;
  color: var(--eki-red);
  line-height: 1.1;
}

.guide-figure__label {
  display: block;
  margin-block-start: var(--eki-space-1);
  font-size: var(--eki-fs-sm);
  color: var(--eki-text-muted);
  line-height: 1.4;
}

/* Encadré « à retenir » : une réponse courte, pour qui survole sans lire. */
.guide-callout {
  margin-block: var(--eki-space-6);
  padding: var(--eki-space-4) var(--eki-space-5);
  border-inline-start: 4px solid var(--eki-red);
  border-radius: 0 var(--eki-radius-md) var(--eki-radius-md) 0;
  background: var(--eki-bg-alt);
}

.guide-callout__title {
  margin: 0 0 var(--eki-space-2);
  font-size: var(--eki-fs-sm);
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--eki-red);
}

.guide-callout p:last-child {
  margin-block-end: 0;
}

/* Tableau comparatif : la forme la plus lisible d'un choix entre deux options. */
.guide-table-wrap {
  /* Le tableau défile dans son cadre plutôt que d'élargir la page. */
  overflow-x: auto;
  margin-block: var(--eki-space-6);
}

.guide-table {
  inline-size: 100%;
  border-collapse: collapse;
  font-size: var(--eki-fs-sm);
}

.guide-table th,
.guide-table td {
  padding: var(--eki-space-3);
  text-align: start;
  border-block-end: 1px solid var(--eki-border);
  vertical-align: top;
}

.guide-table thead th {
  border-block-end: 2px solid var(--eki-red);
  font-weight: 700;
}

.guide-table tbody th {
  font-weight: 600;
  color: var(--eki-text-muted);
}

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

/* Questions dépliables, mais réponse dans le HTML : un contenu replié reste lu
   par les moteurs, un contenu injecté au clic ne l'est pas toujours. */
.guide-faq__item {
  border-block-end: 1px solid var(--eki-border);
}

.guide-faq__item > summary {
  cursor: pointer;
  padding: var(--eki-space-4) 0;
  font-weight: 600;
  font-size: var(--eki-fs-lg);
}

.guide-faq__item > summary::marker {
  color: var(--eki-red);
}

.guide-faq__item p {
  margin-block: 0 var(--eki-space-4);
  line-height: 1.7;
}

/* ---------- Fin de page ---------- */

.guide-cta {
  margin-block-start: var(--eki-space-10);
  padding-block-start: var(--eki-space-6);
  border-block-start: 1px solid var(--eki-border);
  display: flex;
  flex-wrap: wrap;
  gap: var(--eki-space-3);
}

/* Retour en haut : n'apparaît qu'une fois le lecteur descendu, sinon il occupe
   un coin de l'écran pour rien. Posé par le script (data-visible). */
.guide-totop {
  position: fixed;
  /* Coin opposé au panneau du sommaire, qui occupe le bas à gauche. */
  inset-block-end: var(--eki-space-6);
  inset-inline-end: var(--eki-space-6);
  z-index: 20;
  display: none;
  padding: var(--eki-space-3) var(--eki-space-4);
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-md);
  background: var(--eki-bg-elev);
  color: var(--eki-text);
  text-decoration: none;
  font-size: var(--eki-fs-sm);
  box-shadow: var(--eki-shadow-md);
}

.guide-totop[data-visible="true"] {
  display: block;
}

@media (prefers-reduced-motion: no-preference) {
  html {
    scroll-behavior: smooth;
  }
}


/* css/layouts/public/planner.css */
/* =========================================================================
 * planner.css — Plan d'implantation 2D (page /tools/layout, cf. ADR-038).
 *
 * Tout est scopé sous .planner : l'outil est une application dans une page
 * de site, il ne doit rien imposer au document qui l'accueille.
 * ======================================================================== */

/* ----- Renvoi vers l'outil (partial _PlannerCallout) -----
   Vit ici et pas dans editorial.css : c'est l'appel de l'outil, il se déplace
   avec lui. Composé sur .eki-card comme les autres encarts du site. */
.tool-callout {
  margin-block: var(--eki-space-6);
  padding: var(--eki-space-4) var(--eki-space-5);
  border-inline-start: 3px solid var(--eki-red);
}

.tool-callout-title {
  margin: 0 0 var(--eki-space-2);
  font-weight: 600;
  color: var(--eki-text);
}

.tool-callout-text {
  margin: 0 0 var(--eki-space-3);
  color: var(--eki-text-muted);
}

.tool-callout-link {
  font-weight: 600;
  color: var(--eki-red);
  text-decoration: none;
}

.tool-callout-link:hover {
  text-decoration: underline;
}

/* Le fond de ce conteneur sert aussi d'indicateur de thème au rendu canvas :
   planner.js en lit la luminance pour choisir sa palette (cf. readTheme()). */
.planner {
  display: flex;
  flex-direction: column;
  height: clamp(30rem, 78vh, 50rem);
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-md);
  overflow: hidden;
  background: var(--eki-bg);
}

/* ----- Barre de commandes ----- */

.planner-bar {
  display: flex;
  align-items: flex-end;
  flex-wrap: wrap;
  gap: var(--eki-space-4);
  padding: var(--eki-space-3) var(--eki-space-4);
  border-block-end: 1px solid var(--eki-border);
  background: var(--eki-bg-alt);
}

.planner-field {
  display: flex;
  flex-direction: column;
  gap: 3px;
  font-size: var(--eki-fs-xs);
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--eki-text-muted);
}

.planner-field select,
.planner-field input[type="number"] {
  font: inherit;
  font-size: var(--eki-fs-sm);
  text-transform: none;
  letter-spacing: 0;
  color: var(--eki-text);
  padding: 4px 6px;
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-sm);
  background: var(--eki-bg);
}

.planner-field input[type="number"] { width: 6rem; }

.planner-field-check {
  flex-direction: row;
  align-items: center;
  gap: var(--eki-space-2);
  text-transform: none;
  letter-spacing: 0;
  font-size: var(--eki-fs-sm);
  color: var(--eki-text);
  padding-block-end: 5px;
  cursor: pointer;
}

.planner-field-check input { accent-color: var(--eki-red); }

.planner-actions {
  margin-inline-start: auto;
  display: flex;
  flex-wrap: wrap;
  gap: var(--eki-space-2);
}

/* ----- Espace de travail : palette / plan / récapitulatif ----- */

.planner-workspace {
  flex: 1;
  display: flex;
  min-height: 0;
}

.planner-palette,
.planner-summary {
  flex: 0 0 15.5rem;
  padding: var(--eki-space-3);
  overflow-y: auto;
  background: var(--eki-bg);
}

.planner-palette { border-inline-end: 1px solid var(--eki-border); }
.planner-summary { border-inline-start: 1px solid var(--eki-border); }

.planner-palette h2,
.planner-summary h2 {
  font-size: var(--eki-fs-xs);
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--eki-text-muted);
  margin: 0 0 var(--eki-space-2);
}

.planner-hint {
  margin: 0 0 var(--eki-space-3);
  font-size: var(--eki-fs-sm);
  color: var(--eki-text-muted);
}

.planner-group-title {
  font-size: var(--eki-fs-sm);
  font-weight: 600;
  margin: var(--eki-space-3) 0 var(--eki-space-1);
}

.planner-group-title:first-child { margin-block-start: 0; }

.planner-chip {
  display: flex;
  align-items: center;
  gap: var(--eki-space-2);
  width: 100%;
  padding: 7px 9px;
  margin-block-end: 5px;
  border: 1px solid var(--eki-border);
  border-radius: var(--eki-radius-sm);
  background: var(--eki-bg);
  cursor: grab;
  /* Sans ça, le navigateur intercepte le glissement pour faire défiler la page. */
  touch-action: none;
  text-align: start;
}

.planner-chip:hover { border-color: var(--eki-red); }
.planner-chip:active { cursor: grabbing; }

.planner-swatch {
  flex: 0 0 auto;
  width: 22px;
  height: 14px;
  border-radius: 2px;
  border: 1px solid rgba(0, 0, 0, .25);
}

.planner-chip-label { flex: 1; min-width: 0; }
.planner-chip-name { display: block; font-size: var(--eki-fs-sm); color: var(--eki-text); }
.planner-chip-dims { display: block; font-size: var(--eki-fs-xs); color: var(--eki-text-muted); }

.planner-stage {
  flex: 1;
  position: relative;
  min-width: 0;
}

#planner-canvas {
  display: block;
  width: 100%;
  height: 100%;
  touch-action: none;
}

.planner-legend {
  position: absolute;
  inset-inline-start: var(--eki-space-3);
  inset-block-end: var(--eki-space-2);
  font-size: var(--eki-fs-xs);
  color: var(--eki-text-muted);
  background: rgba(255, 255, 255, .88);
  padding: 4px 8px;
  border-radius: var(--eki-radius-sm);
  pointer-events: none;
}

.planner-legend kbd {
  font: inherit;
  font-size: var(--eki-fs-xs);
  border: 1px solid var(--eki-border);
  border-block-end-width: 2px;
  border-radius: var(--eki-radius-sm);
  padding: 0 3px;
  background: var(--eki-bg);
}

/* ----- Récapitulatif ----- */

.planner-conflict {
  padding: 7px 9px;
  margin-block-end: var(--eki-space-3);
  border-inline-start: 3px solid var(--eki-red);
  background: var(--eki-bg-alt);
  font-size: var(--eki-fs-sm);
}

#planner-summary {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--eki-fs-sm);
}

#planner-summary td {
  padding: 4px 0;
  border-block-end: 1px solid var(--eki-border);
  vertical-align: baseline;
}

#planner-summary td.planner-qty {
  text-align: end;
  width: 2.2rem;
  font-variant-numeric: tabular-nums;
  color: var(--eki-text-muted);
}

#planner-summary td.planner-empty {
  color: var(--eki-text-muted);
  border-block-end: none;
}

.planner-totals {
  margin: var(--eki-space-3) 0 0;
  font-size: var(--eki-fs-sm);
}

.planner-totals div {
  display: flex;
  justify-content: space-between;
  gap: var(--eki-space-2);
  padding: 3px 0;
}

.planner-totals dt { color: var(--eki-text-muted); }
.planner-totals dd { margin: 0; font-variant-numeric: tabular-nums; }

/* ----- Écrans étroits -----
   L'outil demande de la surface : sous 880px, les deux panneaux passent
   au-dessus et en dessous du plan plutôt que de l'étrangler. */
@media (max-width: 880px) {
  .planner { height: auto; }

  .planner-workspace { flex-direction: column; }

  .planner-palette,
  .planner-summary {
    flex: 0 0 auto;
    max-height: 14rem;
    border-inline: none;
  }

  .planner-palette { border-block-end: 1px solid var(--eki-border); }
  .planner-summary { border-block-start: 1px solid var(--eki-border); }

  .planner-stage { height: 60vh; }

  .planner-actions { margin-inline-start: 0; }
}



/*
 * Future enrichissements (au fil des Phases) :
 *   @import url("components/_input.css");
 *   @import url("layouts/atelier.css");
 *   @import url("layouts/distributeur.css");
 */

