/* Polices AUTO-HÉBERGÉES (check-up 08.2026) : plus d'appel à Google Fonts —
   ni fuite d'IP vers un tiers, ni premier rendu suspendu à fonts.googleapis.com.
   Les @font-face vivent dans fonts/polices.css (même origine, cache long). */
@import url('./fonts/polices.css');

:root {
  --bg: #141210;
  --ink: #141210;
  --paper: #f3ecdd;
  --surface: #1e1a15;
  --surface-soft: #191510;
  --surface-muted: #26221b;
  --text: #f2ece0;
  --text-soft: #b7ac97;
  --text-faint: #9c9182; /* éclairci (audit a11y 2026-07-08) : contraste AA sur --bg */
  --line: rgba(233, 216, 160, 0.14);
  --line-strong: rgba(233, 216, 160, 0.30);
  --accent: #e8d8a0;
  --accent-strong: #c9a227;
  --accent-deep: #e8d8a0;
  --gold: #c9a227;
  --gold-soft: #e8d8a0;
  --success: #7fae83;
  --danger: #d08a84;
  --shadow: 0 24px 60px rgba(0, 0, 0, 0.45);
  --radius-lg: 28px;
  --radius-md: 18px;
  --radius-sm: 12px;
  --container: 1200px;
}

* { box-sizing: border-box; }
/* ── [hidden] CONTRE display : le filet, une bonne fois ──────────────────────
   La feuille du navigateur ne pose que `[hidden] { display: none }` (0,1,0) :
   n'importe quelle règle d'auteur qui fixe `display` la bat. Le dépôt s'est
   fait mordre trois fois — `.bande { display:flex }` publiait un bandeau vide
   de 353 px sur le site de Maison Corvel, `.wiz-panel` a dû être rattrapé à la
   main, `.profile-modal` aussi. `index.html`, qui ne charge pas cette feuille,
   porte déjà exactement cette ligne depuis août ; elle manquait ici.
   Mesuré avant correctif sur les pages qui chargent style.css : 105 sélecteurs
   dont l'attribut `hidden` était sans effet, dont sept réellement basculés par
   le JS (`.account-login`, `.account-choice`, `.account-create`, `.wiz-signed`,
   `.svc-filter`, `.quick-actions`, `.wl-open`).
   Les règles `[hidden]` nommées qui suivent dans le fichier restent : elles
   documentent le piège à l'endroit exact où le `display:` le tend. */
[hidden] { display: none !important; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body, 'Jost'), sans-serif;
}
img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
button, input, textarea, select { font: inherit; }
/* Police des BOUTONS / NAV / chrome UI (3e emplacement --font-ui) — appliquée à
   TOUTES les pages publiques (accueil, réservation, boutique, contact, espace client).
   Repli var(--font-ui, var(--font-body, 'Jost')) = strictement rétrocompatible : sans
   police UI choisie, boutons et nav gardent la police de corps actuelle. Sélecteurs de
   classe (spécificité > `button`) → gagnent sur le reset `font: inherit` ci-dessus. */
.main-nav a,
.reserve-btn,
.btn-light, .btn-ghost, .btn-accent, .btn-soft, .btn-outline,
button {
  font-family: var(--font-ui, var(--font-body, 'Jost')), sans-serif;
}

.container {
  width: min(var(--container), calc(100% - 40px));
  margin: 0 auto;
}

.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: rgba(255,255,255,0.94);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid rgba(0,0,0,0.05);
}

.header-inner {
  min-height: 92px;
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 28px;
  align-items: center;
}

.brand {
  font-family: var(--font-heading, 'Cormorant Garamond'), serif;
  font-size: 1.9rem;
  font-weight: 600;
  line-height: 0.95;
  letter-spacing: 0.02em;
}
/* Logo du salon (rempli par tenant-theme.js quand branding.logoUrl existe). */
.brand-logo {
  height: 40px;
  width: auto;
  max-width: 120px;
  object-fit: contain;
  vertical-align: middle;
  margin-right: 10px;
  border-radius: 8px;
}
.brand small {
  display: block;
  margin-top: 6px;
  font-family: var(--font-body, 'Jost'), sans-serif;
  font-size: 0.58rem;
  font-weight: 500;
  letter-spacing: 0.32em;
  text-transform: uppercase;
}

.main-nav {
  display: flex;
  justify-content: center;
  gap: 30px;
  flex-wrap: wrap;
}
.main-nav a {
  font-size: 0.82rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  position: relative;
}
.main-nav a::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -7px;
  width: 100%;
  height: 1px;
  background: var(--text);
  transform: scaleX(0);
  transform-origin: center;
  transition: transform 180ms ease;
}
.main-nav a:hover::after,
.main-nav a.active::after {
  transform: scaleX(1);
}
/* Navigation clavier : le soulignement animé ne suffit pas comme indicateur
   de focus — on ajoute un contour explicite (a11y, polish 2026-07-08). */
.main-nav a:focus-visible {
  outline: 2px solid var(--accent-strong);
  outline-offset: 4px;
  border-radius: 2px;
}
.main-nav a:focus-visible::after { transform: scaleX(1); }

.header-actions {
  display: flex;
  align-items: center;
  gap: 13px;
}
/* Les quatre commandes de l'en-tête (jour/nuit · Réserver · panier · compte)
   partagent UNE hauteur : 40 px. Elles faisaient 36, 42, 32 et 32. */
.site-header .theme-toggle { width: 40px; height: 40px; }
.site-header #cart-launcher,
.site-header .acct-btn { padding: 8px; }

.reserve-btn {
  min-height: 40px;
  padding: 0 21px;
  border: 1px solid var(--text);
  border-radius: 999px;
  background: transparent;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 0.78rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  transition: background-color 180ms ease, color 180ms ease, border-color 180ms ease;
}
.reserve-btn:hover {
  background: var(--text);
  color: var(--on-accent, white);
}

.icon-links {
  display: flex;
  align-items: center;
  gap: 14px;
}
.icon-links a {
  font-size: 1rem;
}

.hero {
  position: relative;
  min-height: 78vh;
  display: flex;
  align-items: center;
  overflow: hidden;
}
/* La photo de couverture (migration 084) est stylée dans `index.html`, la SEULE
   page qui porte un `.hero-media` — et cette page ne charge pas ce fichier.
   L'ancienne règle `.hero-media` vivait ici : elle pointait en dur vers une
   photo de barbier hébergée chez Unsplash et n'était référencée par aucune
   page. Du décor mort, retiré plutôt que déplacé. */
.hero-panel {
  position: relative;
  z-index: 1;
  max-width: 760px;
  color: white;
  padding: 80px 0 100px;
}
.eyebrow {
  display: inline-block;
  margin-bottom: 18px;
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.34em;
  text-transform: uppercase;
}
.hero-title {
  margin: 0;
  font-size: clamp(3.1rem, 8vw, 5.9rem);
  line-height: 0.95;
  letter-spacing: -0.06em;
  font-weight: 800;
}
.hero-text {
  max-width: 650px;
  margin-top: 24px;
  font-size: 1rem;
  line-height: 1.9;
  color: rgba(255,255,255,0.9);
}
.hero-actions {
  margin-top: 32px;
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
}

.btn-light,
.btn-ghost,
.btn-accent,
.btn-soft,
.btn-outline {
  min-height: 52px;
  padding: 0 24px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  border-radius: var(--radius-sm);
  font-size: 0.9rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  cursor: pointer;
  transition: transform 160ms ease, box-shadow 160ms ease,
    background-color 160ms ease, color 160ms ease, opacity 160ms ease;
}
.btn-light:hover,
.btn-ghost:hover,
.btn-soft:hover,
.btn-outline:hover { transform: translateY(-2px); }
.btn-accent:hover {
  transform: translateY(-1px);
  filter: brightness(1.06);
}
.btn-light:active,
.btn-ghost:active,
.btn-accent:active,
.btn-soft:active,
.btn-outline:active { transform: translateY(0); }
.btn-light:disabled,
.btn-ghost:disabled,
.btn-accent:disabled,
.btn-soft:disabled,
.btn-outline:disabled,
button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  transform: none !important;
  box-shadow: none !important;
}

.btn-light {
  background: white;
  color: var(--text);
  border: 1px solid white;
}
.btn-ghost {
  background: transparent;
  color: white;
  border: 1px solid rgba(255,255,255,0.92);
}
.btn-accent {
  background: #de9467;
  color: var(--on-accent, white);
  border: none;
}
.btn-soft {
  background: #f4ede5;
  color: var(--text);
  border: none;
}
.btn-outline {
  background: transparent;
  color: var(--text);
  border: 1px solid var(--line-strong);
}

.section {
  padding: 96px 0;
}
.section-soft {
  background: #fcfbf9;
}
.section-title {
  margin: 0 0 16px;
  font-family: var(--font-heading, 'Cormorant Garamond'), serif;
  font-size: clamp(2.3rem, 4vw, 3.4rem);
  font-weight: 500;
  letter-spacing: -0.02em;
  text-align: center;
}
.section-intro {
  max-width: 820px;
  margin: 0 auto 48px;
  text-align: center;
  line-height: 1.9;
  color: var(--text-soft);
}

.two-col {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 46px;
  align-items: center;
}

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
}

.copy-card {
  padding: 40px;
}
.copy-card h2 {
  margin: 0 0 16px;
  font-family: var(--font-heading, 'Cormorant Garamond'), serif;
  font-size: 2.7rem;
  font-weight: 500;
}
.copy-card p {
  margin: 0 0 16px;
  line-height: 1.85;
  color: var(--text-soft);
}

.values-grid,
.stats-grid,
.cards-grid,
.contact-grid,
.shop-grid {
  display: grid;
  gap: 24px;
}
.values-grid {
  grid-template-columns: repeat(3, 1fr);
}
.value-card {
  background: white;
  border: 1px solid var(--line);
  border-radius: 22px;
  padding: 30px;
}
.value-card h3 {
  margin: 0 0 14px;
  font-size: 1rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.value-card p {
  margin: 0;
  line-height: 1.8;
  color: var(--text-soft);
}

.stats-grid {
  margin-top: 6px;
  grid-template-columns: repeat(4, 1fr);
}
.stat-card {
  text-align: center;
  padding: 32px 18px;
  border-top: 1px solid var(--line);
}
.stat-card strong {
  display: block;
  margin-bottom: 10px;
  font-size: 2.8rem;
  font-weight: 800;
  letter-spacing: -0.05em;
}
.stat-card span {
  font-size: 0.9rem;
  color: var(--text-soft);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.cta-banner h2 {
  margin: 0 0 14px;
  font-size: clamp(2.2rem, 4vw, 3.6rem);
  line-height: 1;
  letter-spacing: -0.04em;
}
.cta-banner p {
  max-width: 730px;
  line-height: 1.8;
  color: rgba(255,255,255,0.9);
  margin: 0 0 26px;
}

.page-hero {
  position: relative;
  min-height: 340px;
  display: flex;
  align-items: center;
  color: white;
  overflow: hidden;
}
.page-hero::before {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to right, rgba(21,16,12,0.34), rgba(21,16,12,0.16)),
    var(--hero-image) center/cover no-repeat;
}
.page-hero .container {
  position: relative;
  z-index: 1;
}
.page-hero h1 {
  margin: 0;
  font-family: var(--font-heading, 'Cormorant Garamond'), serif;
  font-weight: 500;
  font-size: clamp(3rem, 6vw, 5rem);
  line-height: 1;
  letter-spacing: 0.01em;
  /* Un mot plus long que l'écran (« CONFIDENTIALITÉ » en registre Affiche)
     se casse plutôt que d'être rogné par l'overflow du héros — filet de
     dernier recours, la règle du téléphone ci-dessous évite d'y arriver. */
  overflow-wrap: anywhere;
}
/* Au téléphone, le plancher de 48 px ne tenait pas : « CONFIDENTIALITÉ » en
   capitales (registres Affiche et Éditorial) courait à 421 px et le héros
   (overflow: hidden) le COUPAIT — mesuré : 101 px hors cadre à 320, 31 px à
   390, sur la démo elle-même (18 sept. 2026). 7,6 vw = 24 px à 320, 30 px à
   390 : le mot tient, et la sonde `scrollWidth` ne voyait rien, puisque le
   rognage était volontaire. */
@media (max-width: 720px) {
  .page-hero h1 { font-size: clamp(1.8rem, 7.6vw, 3rem); }
}
.page-hero p {
  max-width: 740px;
  margin-top: 16px;
  line-height: 1.85;
  color: rgba(255,255,255,0.9);
}
/* Variante SANS image (les 4 pages légales) : sans --hero-image, le shorthand
   background du ::before est invalide en entier → bandeau transparent, et le
   blanc pensé « texte sur photo sombre » devenait invisible en thème clair
   (audit 27.07.2026, chantier F). Ici, couleurs du THÈME uniquement : les
   replis = valeurs sombres de :root ; le clair et les palettes tenant les
   redéfinissent (applyReadableText garantit le contraste par construction). */
.page-hero.page-hero--plain {
  color: var(--text, #f2ece0);
  border-bottom: 1px solid var(--line, #2a251f);
}
.page-hero.page-hero--plain::before { content: none; }
.page-hero.page-hero--plain p { color: var(--text-soft, #b7ac97); }

.pricing-shell,
.shop-shell,
.contact-shell {
  padding: 86px 0 104px;
}
/* Sous l'ouverture centrée (et son filet), le contenu arrive plus tôt : 55 px,
   pas 86 — la suite de Fibonacci de la boutique (21 · 34 · 55 · 89). */
.shop-shell,
.contact-shell { padding: 55px 0 89px; }

.pricing-layout {
  display: grid;
  grid-template-columns: 340px 1fr;
  gap: 30px;
  align-items: start;
}
.pricing-menu {
  background: white;
  border-radius: 26px;
  border: 1px solid var(--line);
  box-shadow: var(--shadow);
  padding: 20px;
}
.pricing-menu button {
  width: 100%;
  background: transparent;
  border: none;
  border-bottom: 1px solid #efe7dd;
  text-align: left;
  padding: 20px 10px;
  cursor: pointer;
  font-weight: 600;
  color: var(--text-soft, #3f3933);
}
.pricing-menu button:last-child { border-bottom: none; }
.pricing-menu button.active { color: var(--accent-strong); }

.panel-card {
  background: white;
  border-radius: 26px;
  border: 1px solid var(--line);
  box-shadow: var(--shadow);
  padding: 28px;
}

.price-row {
  display: grid;
  grid-template-columns: 1fr auto auto;
  gap: 18px;
  align-items: center;
  padding: 20px 0;
  border-bottom: 1px solid #f1ebe5;
}
.price-row:last-child { border-bottom: none; }

.price-meta h3 {
  margin: 0 0 8px;
  font-size: 1.06rem;
}
.price-meta p {
  margin: 0;
  color: var(--text-soft);
  font-size: 0.94rem;
}
.price-amount {
  font-weight: 800;
  white-space: nowrap;
}

/* Boutique (18 sept. 2026) — les mesures suivent le nombre d'or : la photo est
   un rectangle d'or couché (1 : 1,618, ce qui épouse les photos 3:2 d'un
   produit sans les rogner), les écarts suivent la suite 8 · 13 · 21 · 34, et
   chaque carte est une colonne dont le prix et le bouton se rangent EN BAS —
   une description d'une ligne ou de deux ne décale plus rien d'une carte à
   sa voisine. */
.shop-grid {
  grid-template-columns: repeat(3, 1fr);
  gap: 34px;
}
.product-card {
  background: white;
  border: 1px solid var(--line);
  border-radius: 21px;
  box-shadow: var(--shadow);
  padding: 21px;
  text-align: center;
  display: flex;
  flex-direction: column;
}
.product-image {
  aspect-ratio: 1.618;
  border-radius: 13px;
  overflow: hidden;
  background: #faf7f3;
  margin-bottom: 21px;
  position: relative;
}
.product-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.product-card h3 {
  margin: 0 0 8px;
  /* Le nom du produit dans la police de titre du salon — la fiche, le tiroir
     du panier et la carte des tarifs parlent déjà ainsi (8 oct. 2026). */
  font-family: var(--font-heading, 'Cormorant Garamond'), Georgia, serif;
  font-size: 1.3rem;
  font-weight: 600;
  line-height: 1.2;
}
/* Le lien du nom : une cible d'au moins 44 px au doigt, sans changer le dessin. */
.product-card h3 .product-link { display: inline-block; padding: 10px 0; margin: -10px 0; }
.product-card p {
  margin: 0 0 13px;
  line-height: 1.618;
  color: var(--text-soft);
  /* Deux lignes, ni plus ni moins : la fiche dit le reste. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  min-height: calc(2 * 1.618em);
}
.product-price {
  margin: auto 0 13px;
  font-weight: 800;
}
@media (max-width: 1100px) {
  .shop-grid { grid-template-columns: repeat(2, 1fr); gap: 21px; }
}
@media (max-width: 640px) {
  .shop-grid { grid-template-columns: 1fr; }
}

.contact-grid {
  grid-template-columns: 1fr 1fr;
}
.contact-card {
  background: white;
  border: 1px solid var(--line);
  border-radius: 26px;
  box-shadow: var(--shadow);
  padding: 34px;
}
.contact-card h2 {
  margin: 0 0 14px;
  font-family: var(--font-heading, 'Cormorant Garamond'), serif;
  font-size: 2.5rem;
  font-weight: 500;
}
.contact-lines {
  display: grid;
  gap: 12px;
  margin-top: 18px;
  line-height: 1.85;
  color: var(--text-soft);
}
.form-stack {
  display: grid;
  gap: 16px;
}
.form-stack input,
.form-stack textarea,
.form-stack select {
  width: 100%;
  border: 1px solid #ddd4c8;
  border-radius: 14px;
  padding: 16px 18px;
  background: white;
}
.form-stack textarea {
  min-height: 140px;
  resize: vertical;
}

/* Réseaux sociaux du pied de page (04.08.2026).
   Cibles de 44 px : c'est la taille minimale d'un doigt, et ces liens sont
   surtout cliqués depuis un téléphone. La couleur reste discrète au repos et
   passe à l'accent au survol — un pied de page n'est pas une barre de menu, il
   ne doit pas attirer l'œil avant le contenu. */
.footer-social { display: flex; gap: 4px; margin-top: 12px; flex-wrap: wrap; }
.footer-social a {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; border-radius: 999px;
  color: var(--muted); text-decoration: none;
  transition: color .18s ease, background-color .18s ease;
}
.footer-social a:hover, .footer-social a:focus-visible {
  color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, transparent);
}
.footer-social a:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { .footer-social a { transition: none; } }

.site-footer {
  padding: 40px 0 70px;
  background: #fbfaf8;
  border-top: 1px solid rgba(0,0,0,0.05);
}
.footer-inner {
  display: flex;
  justify-content: space-between;
  /* Centré sur la hauteur du bloc d'identité (nom, adresse, téléphone),
     comme au pied de l'accueil — les liens et le © flottaient en haut. */
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
}
.footer-inner p {
  margin: 0;
  /* Le pied de page est une SURFACE : son encre est calculée sur son propre
     fond (--footer-muted, posé par tenant-theme.js), pas sur celui du body.
     Sans ça, un fond de pied de page sombre + un body clair = gris sur noir. */
  color: var(--footer-muted, var(--text-soft));
}
/* Le nom du salon dans sa police de titre, comme au pied de l'accueil : les
   pages intérieures l'écrivaient en texte courant (8 oct. 2026). */
.footer-inner .fbrand {
  font-family: var(--font-heading, 'Cormorant Garamond'), serif;
  font-size: 1.5rem;
  line-height: 1.2;
  color: var(--footer-ink, var(--text));
}
.footer-id .fbrand { margin-bottom: 6px; }
.footer-id p { font-size: .86rem; line-height: 1.6; }
.footer-id p.fbrand { font-size: 1.5rem; line-height: 1.2; }

.ia-bubble {
  position: fixed;
  right: 22px;
  bottom: 22px;
  z-index: 120;
}
/* Réservation engagée (étape ≥ 2, drapeau posé par booking.js) : la bulle se
   retire. Elle est fixée dans le coin bas-droit — exactement là où se trouvent
   la grille de créneaux puis le bouton « Confirmer » — et son panneau ouvert
   recouvrait le tunnel. Elle reste disponible à l'étape 1 (le moment où l'on
   hésite entre deux prestations) et revient sur l'écran de confirmation.
   Même geste que body.acct-menu-open, déjà en place dans account-nav.js. */
body.tunnel-engage .ia-bubble {
  opacity: 0;
  pointer-events: none;
  visibility: hidden;
  transition: opacity 200ms ease;
}
.ia-trigger {
  border: none;
  background: #1c1815;
  color: var(--on-accent, white);
  /* La MÊME pastille que sur l'accueil (index.html .ia-trigger) : sur les
     pages intérieures elle était en gras 700, plus haute et plus serrée —
     deux boutons « Liah » d'une page à l'autre (8 oct. 2026). */
  padding: 14px 20px;
  border-radius: 999px;
  box-shadow: 0 12px 32px rgba(0,0,0,0.28);
  font-size: .8rem;
  font-weight: 500;
  letter-spacing: .06em;
  cursor: pointer;
}
.ia-panel {
  position: absolute;
  right: 0;
  bottom: 76px;
  width: min(720px, calc(100vw - 32px));
  background: white;
  border-radius: 22px;
  border: 1px solid rgba(0,0,0,0.06);
  box-shadow: 0 24px 70px rgba(0,0,0,0.18);
  display: none;
  overflow: hidden;
  /* Vrai panneau d'outil : quasi la moitié de l'écran, borné à la fenêtre —
     la conversation défile à l'intérieur, la saisie reste visible. */
  height: min(880px, calc(100vh - 96px - var(--banners-h, 0px)));
  max-height: min(90vh, calc(100vh - 96px - var(--banners-h, 0px)));
}
.ia-panel.open { display: flex; flex-direction: column; }
.ia-head {
  position: relative;
  padding: 16px 48px 16px 20px;
  background: #1f1a16;
  color: var(--text, white);
  flex: 0 0 auto;
  border-bottom: 1px solid rgba(255,255,255,0.10);
}
.ia-close {
  position: absolute;
  top: 12px;
  right: 12px;
  width: 30px;
  height: 30px;
  border: none;
  border-radius: 50%;
  background: rgba(255,255,255,0.10);
  color: var(--text, #fff);
  font-size: 1.35rem;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 160ms ease;
}
.ia-close:hover { background: rgba(255,255,255,0.22); }
.ia-head strong {
  display: block;
  margin-bottom: 4px;
  font-size: 1.05rem;
}
.ia-head span {
  font-size: 0.82rem;
  line-height: 1.4;
  opacity: 0.82;
}
/* Identité de Liah : avatar + statut « En ligne » — présentation d'outil. */
.ia-id { display: flex; align-items: center; gap: 12px; }
.ia-avatar {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--accent-strong, #c9a227);
  color: var(--on-accent, #fff);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 1.25rem;
  flex: none;
}
.ia-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #7fc98b;
  margin-right: 6px;
  vertical-align: 1px;
}
.ia-body {
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  flex: 1 1 auto;
  min-height: 0;
}
.quick-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}
.quick-actions button {
  border: 1px solid #e8dfd4;
  background: #faf7f3;
  padding: 10px 14px;
  border-radius: 999px;
  cursor: pointer;
}
.ia-body textarea {
  min-height: 90px;
  border: 1px solid #ddd4c8;
  border-radius: 14px;
  padding: 14px;
  resize: vertical;
}
.notice {
  padding: 14px 16px;
  border-radius: 14px;
  background: #f7f2eb;
  color: var(--text-soft, #6c5a49);
  font-size: 0.93rem;
}

.booking-steps {
  display: grid;
  gap: 26px;
  margin-top: 50px;
}
.step-card {
  background: white;
  border: 1px solid var(--line);
  border-radius: 24px;
  box-shadow: var(--shadow);
  padding: 28px;
}
.step-card h2 {
  margin: 0 0 18px;
  font-size: 1.05rem;
  text-transform: uppercase;
  letter-spacing: 0.09em;
}
.inline-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 16px;
}
.staff-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
}
.time-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
}
.staff-grid button,
.time-grid button {
  min-height: 50px;
  border-radius: 14px;
  border: 1px solid #ddd4c8;
  background: white;
  cursor: pointer;
  font-weight: 600;
}
.staff-grid button.active,
.time-grid button.active {
  background: #1d1b19;
  color: var(--on-accent, white);
  border-color: #1d1b19;
}
.service-summary {
  background: #faf5ef;
  color: var(--text-soft, #6a5a4d);
  border-radius: 16px;
  padding: 18px 20px;
  line-height: 1.8;
}
.hidden { display: none !important; }

@media (max-width: 1100px) {
  .header-inner,
  .pricing-layout,
  .two-col,
  .contact-grid,
  .values-grid,
  .stats-grid,
  .staff-grid,
  .time-grid,
  .inline-grid {
    grid-template-columns: 1fr;
  }
  .header-inner {
    justify-items: center;
    padding: 16px 0;
  }
  .feature-image { min-height: 420px; }
  .price-row { grid-template-columns: 1fr; }
}

/* En-tête à burger : 2 rangées nettes au lieu d'une pile pleine largeur.
   Rangée 1 : flèche + marque | burger. Rangée 2 : langues · panier/compte ·
   Réserver. Bornée à 900 px — LA MÊME borne que le burger (.nav-toggle) :
   entre 721 et 900 px, la règle vivait sous 720 et l'en-tête « logo centré »
   empilait marque, burger et actions sur TROIS rangées (mesuré à 768). */
@media (max-width: 900px) {
  .header-inner {
    grid-template-columns: auto 1fr;
    gap: 8px 13px;
    padding: 10px 0;
    min-height: 0;
  }
  .brand-back-wrap { grid-column: 1; grid-row: 1; min-width: 0; }
  .nav-toggle { grid-column: 2; grid-row: 1; }
  .header-actions {
    grid-column: 1 / -1;
    grid-row: 2;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    padding-bottom: 2px;
  }
  .header-actions .reserve-btn {
    width: auto;
    /* En dernier (order) + poussé à droite : les icônes panier/compte restent
       sur la même rangée au lieu de passer seules à la ligne. */
    order: 99;
    margin-left: auto;
    /* 42 px passait sous le minimum tactile de 2 px : mesuré 113x42 sur
       iPhone 12, c'est le bouton le plus utilisé de tout le site public. */
    min-height: 44px;
    padding: 10px 18px;
    font-size: 0.74rem;
  }
  /* « Logo centré » (body.header-centre, posé par tenant-theme.js) au
     téléphone : sa règle centre les éléments de la grille, donc la rangée
     d'actions se RÉTRÉCISSAIT à son contenu et le « margin-left:auto » de
     Réserver ne poussait plus rien — rangée décalée, vide à droite (mesuré
     sur Maison Corvel, 8 oct. 2026). Elle reprend toute la largeur : les
     pictogrammes à gauche, Réserver à droite. Et l'en-tête se resserre
     (21 → 10 px de marge) : 148 px de haut pour deux rangées, c'était un
     cinquième de l'écran. */
  body.header-centre .site-header .header-inner { padding: 10px 0; row-gap: 8px; }
  body.header-centre .site-header .header-actions { grid-column: 1 / 3; justify-self: stretch; justify-content: flex-start; }
  body.header-centre .site-header .brand-back-wrap,
  body.header-centre .site-header .nav-toggle { align-self: center; }
  /* La flèche Retour est posée en absolu à gauche du nom centré
     (back-button.js : top 17-20 px, calé sur l'ancienne marge de 21 px). Avec
     la marge resserrée, on la recentre sur la rangée du nom (10 px + 46 px de
     rangée → 11 px) : elle descendait à 3 px du bouton jour/nuit. */
  body.header-centre .site-header #colabs-back.cb-inline { top: 11px; }
}

@media (max-width: 720px) {
  .container { width: min(var(--container), calc(100% - 24px)); }
  .hero { min-height: 72vh; }
  .hero-panel { padding: 50px 0 70px; }
  .hero-actions,
  .footer-inner {
    flex-direction: column;
    align-items: stretch;
  }
  .btn-light,
  .btn-ghost,
  .btn-accent,
  .btn-soft,
  .btn-outline {
    width: 100%;
    /* Cible tactile confortable (≥ 48px) : la majorité réserve au téléphone. */
    min-height: 48px;
  }
  .brand { font-size: 1.35rem; }
  .brand small { font-size: 0.5rem; letter-spacing: 0.22em; }
  .brand-logo { height: 30px; }
  .section { padding: 74px 0; }
  .copy-card,
  .contact-card,
  .panel-card,
  .step-card {
    padding: 22px;
  }
}

/* --- Ajouts : réservation branchée & boutique dynamique --- */
#booking-service {
  width: 100%;
  padding: 14px 16px;
  border: 1px solid #ddd4c8;
  border-radius: 14px;
  font-size: 15px;
  background: #fff;
}
.booking-date {
  padding: 12px 16px;
  border: 1px solid #ddd4c8;
  border-radius: 14px;
  font-size: 15px;
  margin-bottom: 16px;
}
.slots-hint {
  color: var(--text-soft, #8a8378);
  font-size: 14px;
  margin: 0;
}
.booking-status { font-size: 14px; }
.booking-status.success { color: #15803d; font-weight: 600; }
.booking-status.error { color: #b91c1c; font-weight: 600; }
.shop-loading {
  color: var(--text-soft, #8a8378);
  grid-column: 1 / -1;
  text-align: center;
  padding: 24px 0;
}

/* --- Polish : accessibilité, feedback, widget IA, menu mobile --- */

/* Accessibilité : focus visible cohérent avec la DA */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--accent-strong);
  outline-offset: 3px;
  border-radius: 6px;
}
:focus:not(:focus-visible) { outline: none; }

/* Accessibilité : contenu réservé aux lecteurs d'écran (labels invisibles) */
.sr-only {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Accessibilité : lien d'évitement « Aller au contenu » (visible au focus clavier) */
.skip-link {
  position: absolute;
  left: 12px;
  top: -60px;
  z-index: 2000;
  background: var(--accent, #e8d8a0);
  color: var(--on-accent, #141210);
  padding: 10px 18px;
  border-radius: 0 0 10px 10px;
  font-weight: 700;
  text-decoration: none;
  transition: top 160ms ease;
}
.skip-link:focus {
  top: 0;
  outline: 2px solid var(--accent-strong);
  outline-offset: 2px;
}

/* Champs de formulaire : transition douce au focus */
input,
select,
textarea {
  transition: border-color 160ms ease, box-shadow 160ms ease;
}
input:focus,
select:focus,
textarea:focus {
  border-color: var(--accent-strong);
  box-shadow: 0 0 0 3px rgba(216, 176, 141, 0.22);
}

/* Cartes : léger soulèvement au survol */
.value-card,
.product-card {
  transition: transform 200ms ease, box-shadow 200ms ease, border-color 200ms ease;
}
.value-card:hover,
.product-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 20px 44px rgba(30, 22, 15, 0.10);
  border-color: var(--line-strong);
}

/* Toasts / notifications — au-dessus de la bulle IA (même coin) pour ne
   jamais masquer son bouton. Position UNIQUE sur tout le site public. */
.toast-stack {
  position: fixed;
  right: 22px;
  bottom: 92px;
  z-index: 2000;
  display: flex;
  flex-direction: column;
  gap: 10px;
  max-width: min(340px, calc(100vw - 32px));
}
/* Tiroir du panier ouvert (shop.js pose body.cart-open) : le toast « ajouté au
   panier » recouvrait le sous-total du tiroir, posé au même coin. Il se range
   à gauche du tiroir (sa largeur : min(440px, 100vw)) ; au téléphone, où le
   tiroir prend l'écran, il monte en haut. Le tiroir et son voile vivent à
   9450-9460 (au-dessus de l'en-tête et des bandeaux) : le toast passe juste
   au-dessus, sinon le voile l'assombrirait. */
body.cart-open .toast-stack { right: calc(min(440px, 100vw) + 22px); z-index: 9470; }
@media (max-width: 640px) {
  body.cart-open .toast-stack { right: 16px; left: 16px; bottom: auto; top: 16px; max-width: none; z-index: 9470; }
}
.toast {
  padding: 14px 18px;
  border-radius: 14px;
  background: #1f1a16;
  color: #fff;
  font-size: 0.92rem;
  box-shadow: 0 16px 40px rgba(0, 0, 0, 0.22);
  opacity: 0;
  transform: translateY(12px);
  transition: opacity 220ms ease, transform 220ms ease;
}
.toast.show { opacity: 1; transform: translateY(0); }
.toast.success { background: #15803d; }
.toast.error { background: #b91c1c; }
.toast.info { background: #1f1a16; }

/* Spinner de chargement */
.spinner {
  display: inline-block;
  width: 18px;
  height: 18px;
  border: 2px solid rgba(0, 0, 0, 0.15);
  border-top-color: var(--accent-strong);
  border-radius: 50%;
  animation: spin 700ms linear infinite;
  vertical-align: middle;
}
.spinner.on-dark { border-color: rgba(255, 255, 255, 0.3); border-top-color: #fff; }
@keyframes spin { to { transform: rotate(360deg); } }
.is-loading { position: relative; opacity: 0.7; pointer-events: none; }
/* Feedback visuel pendant un envoi : les boutons en cours affichent un petit
   spinner intégré (polish 2026-07-08) — évite les doubles clics « au cas où ». */
button.is-loading::after,
.btn-accent.is-loading::after {
  content: "";
  display: inline-block;
  width: 14px;
  height: 14px;
  margin-left: 10px;
  border: 2px solid rgba(255, 255, 255, 0.35);
  border-top-color: currentColor;
  border-radius: 50%;
  vertical-align: -2px;
  animation: spin 700ms linear infinite;
}

/* État vide guidé : au lieu d'une ligne de texte grise, un bloc avec icône,
   explication et action claire (polish 2026-07-08). */
.empty-state {
  text-align: center;
  padding: 36px 20px;
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius-md);
  background: var(--surface-soft);
}
.empty-state .empty-icon { font-size: 1.6rem; margin-bottom: 10px; opacity: 0.8; }
.empty-state h3 {
  margin: 0 0 6px;
  font-size: 1.05rem;
  color: var(--text);
}
.empty-state p { margin: 0 0 16px; color: var(--text-soft); font-size: 0.92rem; }

/* États de chargement soignés : squelettes shimmer (évitent l'écran qui « saute ») */
.skeleton {
  position: relative;
  overflow: hidden;
  background: var(--surface-muted);
  border-radius: var(--radius-md, 10px);
  color: transparent !important;
}
.skeleton::after {
  content: "";
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, rgba(233, 216, 160, 0.10), transparent);
  animation: skeleton-shimmer 1.3s ease-in-out infinite;
}
.skeleton-line { height: 12px; margin: 8px 0; }
.skeleton-line.short { width: 55%; }
.skeleton-block { height: 140px; }
@keyframes skeleton-shimmer {
  100% { transform: translateX(100%); }
}
@media (prefers-reduced-motion: reduce) {
  .skeleton::after { animation: none; }
}

/* Widget IA : fil de conversation */
.ia-messages {
  display: flex;
  flex-direction: column;
  gap: 12px;
  flex: 1 1 auto;
  min-height: 220px;
  overflow-y: auto;
  padding: 14px;
  background: #f7f2ec;
  border-radius: 16px;
  scroll-behavior: smooth;
}
.ia-body .quick-actions,
.ia-body .ia-input-row,
.ia-body .btn-accent { flex: 0 0 auto; }
/* Boutons de réponse rapide proposés par Liah (jours, horaires, oui/non…) :
   ils occupent la barre .quick-actions sous la conversation (classe sugg-mode). */
.quick-actions.sugg-mode button {
  border: 1px solid var(--accent-strong, #c9a227);
  background: #fff;
  color: var(--accent-strong, #8a6d1d);
  font-size: 0.9rem;
  padding: 9px 15px;
  border-radius: 999px;
  cursor: pointer;
  transition: background 140ms ease, color 140ms ease;
}
.quick-actions.sugg-mode button:hover {
  background: var(--accent-strong, #c9a227);
  color: #fff;
}
/* Confirmation : « Oui » plein vert, « Non » neutre discret. */
.quick-actions.sugg-mode button.ia-yes {
  background: #2e7d4f;
  border-color: #2e7d4f;
  color: #fff;
  font-weight: 600;
}
.quick-actions.sugg-mode button.ia-yes:hover { background: #256a42; border-color: #256a42; }
.quick-actions.sugg-mode button.ia-no {
  background: transparent;
  border-color: #cabfae;
  color: var(--text-soft, #6f665b);
}
.quick-actions.sugg-mode button.ia-no:hover { background: #f3eee7; color: #4a4239; }
.quick-actions.sugg-mode .ia-more {
  border-style: dashed;
  border-color: #cabfae;
  color: var(--text-soft, #8a8177);
  background: transparent;
}
.ia-msg {
  max-width: 90%;
  padding: 12px 15px;
  border-radius: 16px;
  font-size: 0.98rem;
  line-height: 1.5;
  white-space: pre-wrap;
  word-wrap: break-word;
  box-shadow: 0 1px 2px rgba(0,0,0,0.05);
}
.ia-msg.user {
  align-self: flex-end;
  background: var(--accent-strong);
  color: var(--on-accent, #fff);
  border-bottom-right-radius: 4px;
}
.ia-msg.bot {
  align-self: flex-start;
  background: #fff;
  color: var(--text, #241f1a);
  border-bottom-left-radius: 4px;
}
.ia-msg.typing { color: var(--text-faint); font-style: italic; box-shadow: none; }
.ia-input-row {
  display: flex;
  gap: 8px;
  align-items: flex-end;
}
.ia-input-row textarea {
  flex: 1;
  min-height: 46px;
  max-height: 120px;
  min-width: 0;
}
.ia-input-row textarea:focus { outline: none; border-color: var(--gold, var(--accent-strong)); box-shadow: 0 0 0 3px color-mix(in srgb, var(--gold, var(--accent-strong)) 22%, transparent); }
.ia-send {
  border: none;
  /* L'or du salon, comme sur la page d'accueil (index.html) : ce bouton
     portait un fond noir codé en dur sous une encre calculée POUR L'OR —
     1,06:1 sur le tunnel et la boutique d'un salon sombre (4 sept. 2026). */
  background: var(--gold, #c9a227);
  color: var(--on-accent, #1a1712);
  padding: 0 18px;
  height: 46px;
  border-radius: 12px;
  font-weight: 700;
  cursor: pointer;
  transition: background 160ms ease, transform 120ms ease;
}
.ia-send:hover { background: var(--gold-soft, var(--gold, #c9a227)); transform: translateY(-1px); }
.ia-send:disabled { opacity: 0.5; cursor: not-allowed; transform: none; }

/* Indicateur « Liah écrit… » : trois points animés. */
.ia-typing { display: inline-flex; gap: 5px; align-items: center; min-height: 20px; }
.ia-typing span {
  width: 7px; height: 7px; border-radius: 50%;
  background: currentColor; opacity: 0.35;
  animation: ia-typing-blink 1.2s infinite ease-in-out;
}
.ia-typing span:nth-child(2) { animation-delay: 0.18s; }
.ia-typing span:nth-child(3) { animation-delay: 0.36s; }
@keyframes ia-typing-blink {
  0%, 70%, 100% { opacity: 0.25; transform: translateY(0); }
  35% { opacity: 0.9; transform: translateY(-2px); }
}

/* Carte de confirmation de rendez-vous (réservation faite par l'IA). */
.ia-booking-card {
  align-self: flex-start;
  max-width: 90%;
  padding: 12px 15px;
  border-radius: 14px;
  border: 1px solid var(--accent-strong, #b8860b);
  background: rgba(201, 162, 39, 0.08);
  font-size: 0.9rem;
  line-height: 1.5;
}
/* La même carte que sur la page d'accueil (index.html), avec les jetons de
   cette feuille : date en grand, faits en lignes, deux actions (4 sept. 2026). */
.ia-booking-card { align-self: stretch; padding: 16px 18px 14px; }
.ia-bc-head { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.ia-bc-check {
  flex: 0 0 auto; width: 26px; height: 26px; border-radius: 50%; display: grid; place-items: center;
  background: var(--gold, #c9a227); color: var(--on-accent, #1a1712); font-size: .85rem; font-weight: 700;
}
.ia-bc-title { font-size: .76rem; letter-spacing: .22em; text-transform: uppercase; color: var(--accent-strong, #b8860b); font-weight: 600; }
.ia-bc-when { padding: 2px 0 12px; border-bottom: 1px solid var(--line); margin-bottom: 10px; }
.ia-bc-day { font-family: var(--font-heading, 'Cormorant Garamond'), serif; font-size: 1.45rem; line-height: 1.15; color: var(--text, #241f1a); }
.ia-bc-hour { font-size: 1.05rem; color: var(--text, #241f1a); font-variant-numeric: tabular-nums; margin-top: 2px; }
.ia-bc-rows { display: flex; flex-direction: column; gap: 5px; }
.ia-bc-row { display: grid; grid-template-columns: 5.2em minmax(0, 1fr); gap: 10px; align-items: baseline; }
.ia-bc-label { font-size: .7rem; letter-spacing: .16em; text-transform: uppercase; color: var(--text-soft); }
.ia-bc-value { color: var(--text, #241f1a); overflow-wrap: anywhere; }
.ia-bc-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
.ia-bc-btn {
  display: inline-flex; align-items: center; padding: 9px 15px; border-radius: 999px;
  background: var(--gold, #c9a227); color: var(--on-accent, #1a1712); font-size: .78rem; letter-spacing: .08em;
  text-transform: uppercase; text-decoration: none; font-family: var(--font-ui, var(--font-body, 'Jost')), sans-serif;
}
.ia-bc-btn:hover { background: var(--gold-soft, var(--gold, #c9a227)); }
.ia-bc-btn.ia-bc-btn-ghost { background: transparent; color: var(--text, #241f1a); border: 1px solid var(--line-strong, var(--line)); }
.ia-bc-btn.ia-bc-btn-ghost:hover { border-color: var(--gold, #c9a227); background: transparent; }
.ia-bc-note { margin-top: 10px; font-size: .78rem; color: var(--text-soft); }

/* Note discrète sous une réponse (mode démo sans clé IA). */
.ia-note {
  align-self: flex-start;
  font-size: 0.72rem;
  opacity: 0.55;
  padding: 0 4px;
}

/* Mobile : le panneau devient une feuille pleine largeur, bornée à l'écran. */
@media (max-width: 520px) {
  .ia-bubble { right: 12px; bottom: 12px; }
  .ia-panel {
    position: fixed;
    left: 12px; right: 12px; bottom: 74px;
    width: auto;
    max-height: min(72vh, calc(100vh - 90px));
  }
}

/* Bouton hamburger (mobile) */
.nav-toggle {
  display: none;
  border: 1px solid var(--line-strong);
  background: #fff;
  width: 46px;
  height: 46px;
  border-radius: 12px;
  cursor: pointer;
  align-items: center;
  justify-content: center;
  padding: 0;
}
.nav-toggle span,
.nav-toggle span::before,
.nav-toggle span::after {
  content: "";
  display: block;
  width: 20px;
  height: 2px;
  background: var(--text);
  position: relative;
  transition: transform 200ms ease, opacity 160ms ease;
}
.nav-toggle span::before { position: absolute; top: -6px; }
.nav-toggle span::after { position: absolute; top: 6px; }
.site-header.nav-open .nav-toggle span { background: transparent; }
.site-header.nav-open .nav-toggle span::before { transform: translateY(6px) rotate(45deg); }
.site-header.nav-open .nav-toggle span::after { transform: translateY(-6px) rotate(-45deg); }

/* Récap de réservation */
.booking-recap {
  border: 1px solid var(--line);
  border-radius: 16px;
  background: #faf7f2;
  padding: 18px 20px;
  margin: 4px 0 18px;
  display: grid;
  gap: 8px;
}
.booking-recap h4 {
  margin: 0 0 4px;
  font-family: var(--font-body, 'Jost'), sans-serif;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.booking-recap .recap-row {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  font-size: 0.95rem;
}
.booking-recap .recap-row span:first-child { color: var(--text-soft); }
.booking-recap .recap-row span:last-child { font-weight: 600; text-align: right; }
.booking-recap .recap-total {
  border-top: 1px solid var(--line);
  margin-top: 4px;
  padding-top: 10px;
}
.booking-recap.is-empty { color: var(--text-faint); font-size: 0.92rem; }

/* Lignes de tableau admin : survol */
.ws-table tbody tr { transition: background 140ms ease; }
.ws-table tbody tr:hover { background: rgba(216, 176, 141, 0.10); }

@media (max-width: 900px) {
  .nav-toggle { display: inline-flex; justify-self: end; }
  .header-inner {
    grid-template-columns: auto 1fr auto;
  }
  .main-nav {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: #fff;
    border-bottom: 1px solid var(--line);
    box-shadow: 0 20px 44px rgba(0, 0, 0, 0.10);
    flex-direction: column;
    /* nowrap + flex-start indispensables : avec le wrap/centrage hérités du
       bureau + max-height 0, les liens débordaient de la fenêtre de clip →
       bande de texte tronqué visible sous l'en-tête (audit mobile 390px). */
    flex-wrap: nowrap;
    justify-content: flex-start;
    align-items: stretch;
    gap: 0;
    /* Fermé : aucune épaisseur visible (padding/ombre seulement à l'ouverture). */
    padding: 0;
    border-bottom: none;
    box-shadow: none;
    max-height: 0;
    overflow: hidden;
    transition: max-height 260ms ease;
  }
  .site-header.nav-open .main-nav {
    max-height: 60vh;
    overflow-y: auto;
    padding: 8px 0;
    border-bottom: 1px solid var(--line);
    box-shadow: 0 20px 44px rgba(0, 0, 0, 0.10);
  }
  .main-nav a {
    padding: 14px 22px;
    text-align: center;
  }
  .main-nav a::after { display: none; }
}

/* ==========================================================================
   Phase 4 — finition DA premium (accents dorés + micro-interactions).
   Bloc additif : n'écrase aucune règle existante, uniquement des raffinements.
   ========================================================================== */

/* Filet doré sous l'eyebrow du hero */
.eyebrow { color: var(--accent); position: relative; padding-bottom: 12px; }
.eyebrow::after {
  content: "";
  position: absolute;
  left: 0; bottom: 0;
  width: 46px; height: 2px;
  background: var(--accent);
}

/* Titres de section : petit trait doré centré, signature du salon — le MÊME
   filet que sur l'accueil (.rule : 46 × 1 px, l'or du salon). Il était un
   dégradé qui s'effaçait aux deux bouts, un autre dessin (8 oct. 2026). */
.section-title { position: relative; padding-bottom: 22px; }
.section-title::after {
  content: "";
  position: absolute;
  left: 50%; bottom: 0;
  width: 46px; height: 1px;
  transform: translateX(-50%);
  background: var(--gold, var(--accent-strong));
}

/* Cartes de valeurs : survol qui soulève et révèle un liseré doré */
.value-card {
  transition: transform 200ms ease, box-shadow 200ms ease, border-color 200ms ease;
}
.value-card:hover {
  transform: translateY(-4px);
  border-color: var(--accent);
  box-shadow: 0 22px 44px rgba(139, 95, 67, 0.12);
}

/* Chiffres clés en chiffre doré + libellé discret */
.stat-card strong { color: var(--accent-deep); }

/* Liste de prix : onglet actif marqué d'une barre dorée, tarif en doré */
.pricing-menu button {
  border-left: 3px solid transparent;
  transition: color 160ms ease, border-color 160ms ease, background 160ms ease;
}
.pricing-menu button:hover { background: #faf6f1; }
.pricing-menu button.active {
  border-left-color: var(--accent-strong);
  background: #faf5ef;
}
.price-amount {
  color: var(--accent-deep);
  font-family: var(--font-heading, 'Cormorant Garamond'), serif;
  font-size: 1.5rem;
  letter-spacing: -0.01em;
}
.price-row { transition: background 160ms ease; }
.price-row:hover { background: #fbf8f4; }

/* Boutique : cartes produit qui réagissent, image qui zoome doucement */
.product-card {
  transition: transform 200ms ease, box-shadow 200ms ease, border-color 200ms ease;
}
.product-card:hover {
  transform: translateY(-4px);
  border-color: var(--accent);
  box-shadow: 0 24px 46px rgba(139, 95, 67, 0.14);
}
.product-image img { transition: transform 400ms ease; }
.product-card:hover .product-image img { transform: scale(1.05); }

/* Bandeau CTA : léger grain doré en surimpression pour la profondeur */
.cta-banner { position: relative; }
.cta-banner::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at 85% 15%, rgba(216, 176, 141, 0.28), transparent 55%);
  pointer-events: none;
}
.cta-banner > * { position: relative; z-index: 1; }

/* Lien de marque : accent doré sur le sous-titre */
.brand small { color: var(--accent-deep); }

/* ==========================================================================
   MAISON CORVEL — peau « luxe sombre & or ».
   Bloc final : re-skinne tous les composants encore codés en clair pour
   aligner les pages secondaires (réservation, boutique, contact, espace
   client…) sur l'identité de la page d'accueil. Placé en dernier → prioritaire.
   ========================================================================== */
/* --------------------------------------------------------------------------
   LISIBILITÉ GARANTIE (chantier 77)
   L'en-tête avait un fond CODÉ EN DUR (rgba(15,13,11,.86)) alors que son texte
   suivait les variables du thème. Dès qu'un salon choisissait un fond clair, on
   obtenait du texte clair sur un header clair → invisible (bug constaté sur
   barbier.localhost).
   Désormais l'en-tête consomme --header-bg / --header-ink / --header-ink-soft,
   que contrast.js CALCULE à partir du fond réellement affiché. Les valeurs de
   repli conservent l'ancien rendu si le JS n'a pas (encore) tourné.
   -------------------------------------------------------------------------- */
.brand { color: var(--header-ink, var(--paper)); }

/* En-tête + navigation */
.site-header {
  background: var(--header-bg, rgba(15, 13, 11, 0.86));
  border-bottom: 1px solid var(--line);
}
.reserve-btn { border-color: var(--accent-strong); color: var(--accent); }
.reserve-btn:hover { background: var(--accent-strong); color: var(--on-accent, var(--ink)); }
.main-nav a { color: var(--header-ink-soft, var(--text-soft)); }
.main-nav a:hover, .main-nav a.active { color: var(--accent); }
.main-nav a::after { background: var(--accent); }

/* Boutons */
.btn-light { background: var(--accent-strong); color: var(--on-accent, var(--ink)); border-color: var(--accent-strong); }
/* Le dégradé était figé en or : un salon en bleu gardait un bouton doré, et le
   texte calculé pour SA couleur devenait faux. Il suit maintenant la marque.
   UN APLAT, plus de dégradé (8 oct. 2026) : le passage --accent → --accent-strong
   peignait un bouton bicolore, différent de celui de l'accueil (.btn-gold,
   aplat de --gold) — deux boutons principaux sur un même site. L'aplat est la
   couleur contre laquelle --on-accent est CALCULÉE : le contraste est exact. */
.btn-accent {
  background: var(--gold, var(--accent-strong));
  color: var(--on-accent, var(--ink));
}
.btn-soft { background: var(--surface-muted); color: var(--text); border: 1px solid var(--line); }
.btn-outline { color: var(--text); border-color: var(--line-strong); }

/* Sections & cartes */
.section-soft { background: var(--surface-soft); }
.card,
.value-card,
.pricing-menu,
.panel-card,
.product-card,
.contact-card,
.step-card { background: var(--surface); border-color: var(--line); }

/* Liste de prix */
.pricing-menu button { color: var(--text-soft); border-bottom-color: var(--line); }
.pricing-menu button:hover { background: rgba(201, 162, 39, 0.08); }
.pricing-menu button.active { color: var(--accent); background: rgba(201, 162, 39, 0.12); }
.price-row { border-bottom-color: var(--line); }
.price-row:hover { background: rgba(255, 255, 255, 0.03); }
.price-amount { color: var(--accent); }

/* Boutique */
.product-image { background: var(--surface-muted); }

/* Formulaires */
/* Champ-piège à robots du formulaire de contact : hors écran, jamais display:none
   (certains robots sautent ce qui est display:none — et c'est précisément eux
   qu'on veut voir le remplir). Même règle que la vitrine. */
.form-stack .hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.form-stack input,
.form-stack textarea,
.form-stack select,
#booking-service,
.booking-date,
.ia-body textarea {
  background: var(--surface-muted);
  border: 1px solid var(--line);
  color: var(--text);
}
.form-stack input::placeholder,
.form-stack textarea::placeholder { color: var(--text-faint); }

/* Listes déroulantes maison (chantier 47) : le menu système du navigateur
   ignorait la DA du salon — bouton + popover 100 % aux couleurs du tenant
   (les variables sont réécrites par tenant-theme.js, donc chaque
   configuration client est suivie automatiquement). */
.uisel-native { display: none !important; }
.uisel-btn {
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  width: 100%;
  background: var(--surface-muted);
  border: 1px solid var(--line);
  border-radius: 12px;
  color: var(--text);
  padding: 12px 14px;
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: border-color 0.15s ease;
}
.uisel-btn:hover:not(:disabled), .uisel-btn:focus-visible { border-color: var(--accent-strong); outline: none; }
.uisel-btn:disabled { opacity: 0.55; cursor: not-allowed; }
.uisel-btn .uisel-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.uisel-btn.is-placeholder .uisel-label { color: var(--text-faint); }
.uisel-caret { flex: none; font-size: 0.7rem; color: var(--accent-strong); }
.uisel-pop {
  position: absolute;
  z-index: 1600;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: 14px;
  box-shadow: var(--shadow);
  overflow: hidden;
}
.uisel-search { padding: 8px; border-bottom: 1px solid var(--line); }
.uisel-search input {
  width: 100%;
  background: var(--surface-muted);
  border: 1px solid var(--line);
  border-radius: 10px;
  color: var(--text);
  padding: 9px 12px;
  font: inherit;
  font-size: 0.88rem;
}
.uisel-list { max-height: 288px; overflow: auto; padding: 6px; display: grid; gap: 2px; }
.uisel-group {
  padding: 8px 10px 4px;
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-soft);
}
.uisel-opt {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  width: 100%;
  border: none;
  border-radius: 10px;
  background: transparent;
  color: var(--text);
  padding: 10px 12px;
  font: inherit;
  font-size: 0.92rem;
  text-align: left;
  cursor: pointer;
}
.uisel-opt:hover:not(:disabled), .uisel-opt.is-active { background: var(--surface-muted); }
.uisel-opt.is-sel { background: var(--accent); color: var(--on-accent, #241a10); font-weight: 700; }
.uisel-opt:disabled { opacity: 0.45; cursor: not-allowed; }
.uisel-opt .uisel-opt-sub { flex: none; font-size: 0.78rem; color: var(--text-soft); }
.uisel-opt.is-sel .uisel-opt-sub { color: inherit; opacity: 0.75; }
.uisel-empty { padding: 14px 12px; font-size: 0.85rem; color: var(--text-soft); text-align: center; }
[data-theme="light"] .uisel-opt.is-sel { color: var(--on-accent, #fff); }

/* Réservation : équipe, créneaux, récap */
.staff-grid button,
.time-grid button {
  background: var(--surface-muted);
  border: 1px solid var(--line);
  color: var(--text);
}
.staff-grid button.active,
.time-grid button.active { background: var(--accent-strong); color: var(--on-accent, var(--ink)); border-color: var(--accent-strong); }
.service-summary { background: var(--surface-muted); color: var(--text-soft); }
.booking-recap { background: var(--surface-muted); }
.slots-hint { color: var(--text-faint); }
.booking-status.success { color: var(--success); }
.booking-status.error { color: var(--danger); }

/* Pied de page */
.site-footer {
  background: var(--surface-soft); border-top: 1px solid var(--line);
  /* Le fond est une SURFACE de la page (--surface-soft) : son encre est donc
     celle de la page, qui bascule avec le thème. tenant-theme.js calcule
     --footer-ink/--footer-muted UNE fois, contre le pied tel qu'il est peint
     à son passage — avant la bascule claire, ce pied est sombre, et son encre
     claire restait posée sur un pied devenu clair : 1,68:1 sur le tunnel et
     la boutique en page claire (4 sept. 2026). */
  --footer-ink: var(--text);
  --footer-muted: var(--text-soft);
}

/* Widget IA (bulle flottante sur les pages publiques) */
.ia-trigger { background: var(--accent-strong); color: var(--on-accent, var(--ink)); }
.ia-panel { background: var(--surface); border: 1px solid var(--line); }
.ia-head { background: var(--surface-muted); border-bottom-color: var(--line); }
.quick-actions button { background: var(--surface-muted); border: 1px solid var(--line); color: var(--text); }
/* Zone de conversation encadrée + bulles contrastées (thème sombre). */
.ia-messages { background: var(--surface-soft); }
.ia-msg { box-shadow: 0 1px 3px rgba(0,0,0,0.25); }
.ia-msg.bot { background: var(--surface-muted); color: var(--text); border: 1px solid var(--line); }
.quick-actions.sugg-mode button { background: transparent; color: var(--accent, #d9b64a); border-color: var(--accent-strong); }
.quick-actions.sugg-mode button:hover { background: var(--accent-strong); color: var(--ink, #1c1815); }
.quick-actions.sugg-mode button.ia-yes { background: #2e7d4f; border-color: #2e7d4f; color: #fff; }
.quick-actions.sugg-mode button.ia-yes:hover { background: #38935e; border-color: #38935e; }
.quick-actions.sugg-mode button.ia-no { background: transparent; border-color: var(--line-strong, #4a443c); color: var(--text-soft); }
.quick-actions.sugg-mode button.ia-no:hover { background: var(--surface-muted); color: var(--text); }
.quick-actions.sugg-mode .ia-more { border-color: var(--line-strong, #4a443c); color: var(--text-soft); }
.notice { background: rgba(201, 162, 39, 0.10); color: var(--text-soft); }

/* Menu mobile déroulant */
.nav-toggle { background: var(--surface); border-color: var(--line-strong); }
@media (max-width: 900px) {
  .main-nav { background: var(--surface); }
  .site-header.nav-open .main-nav { border-bottom: 1px solid var(--line); }
}

/* ============================================================
   Assistant de réservation 3 clics (booking wizard)
   ============================================================ */
/* L'OUVERTURE DES PAGES DE COMMERCE — réservation, boutique, contact — est
   UNE seule règle (8 oct. 2026). La boutique et le contact portaient un aplat
   presque noir codé en dur (#26211c), titre calé à gauche : étranger au salon,
   et en page claire une bande noire entre l'en-tête et le contenu crème. Ici :
   le sol du salon, le titre centré dans SA police, un filet pour finir. Un
   aplat, plus de dégradé surface → fond. */
.booking-hero,
.page-hero.page-hero--centre {
  background: var(--bg);
  padding: 88px 0 40px;
  text-align: center;
  border-bottom: 1px solid var(--line);
}
.page-hero.page-hero--centre { min-height: 0; display: block; color: var(--text); overflow: visible; }
.page-hero.page-hero--centre::before { content: none; }
.page-hero.page-hero--centre h1 {
  font-size: clamp(2.2rem, 4.4vw, 3.2rem);
  color: var(--text);
  margin: 0 0 10px;
  text-wrap: balance;
}
.page-hero.page-hero--centre p {
  color: var(--text-soft);
  margin: 0 auto;
  max-width: 560px;
  line-height: 1.618;
  text-wrap: pretty;
}
.booking-hero h1 {
  /* La police de TITRE du salon, comme .page-hero h1 : sans cette ligne le
     titre du tunnel héritait de la police de corps (Jost chez Maison Corvel)
     et la réservation ne ressemblait plus au site qu'on venait de quitter
     (4 sept. 2026). */
  font-family: var(--font-heading, 'Cormorant Garamond'), serif;
  font-weight: 500;
  font-size: clamp(2.2rem, 4.4vw, 3.2rem);
  color: var(--text);
  margin: 0 0 10px;
}
.booking-hero p { color: var(--text-soft); margin: 0 auto; max-width: 560px; line-height: 1.618; text-wrap: pretty; }

.wiz-shell { padding: 32px 0 80px; }

/* --- Barre de progression --- */
.wiz-steps {
  list-style: none;
  display: flex;
  gap: 6px;
  padding: 0;
  margin: 0 0 24px;
  counter-reset: step;
}
.wiz-step {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 6px 2px;
  position: relative;
  color: var(--text-faint);
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: default;
}
.wiz-step .wiz-dot {
  width: 30px; height: 30px;
  border-radius: 50%;
  display: grid; place-items: center;
  background: var(--surface-muted);
  border: 1px solid var(--line-strong);
  color: var(--text-faint);
  font-weight: 700;
  transition: background-color 180ms ease, border-color 180ms ease, color 180ms ease;
}
.wiz-step::after {
  content: "";
  position: absolute;
  top: 21px; left: 60%; right: -40%;
  height: 2px;
  background: var(--line);
}
.wiz-step:last-child::after { display: none; }
.wiz-step.is-active .wiz-dot {
  background: var(--gold);
  border-color: var(--gold);
  color: var(--on-accent, #1a1712);
  box-shadow: 0 0 0 4px rgba(201,162,39,0.18);
}
.wiz-step.is-active { color: var(--accent); }
.wiz-step.is-done .wiz-dot { background: var(--accent); border-color: var(--accent); color: var(--on-accent, #1a1712); }
.wiz-step.is-done { cursor: pointer; }
.wiz-step.is-done::after { background: var(--accent); }

/* --- Carte principale --- */
.wiz-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  padding: 28px;
  min-height: 320px;
}
/* HAUTEUR RÉSERVÉE — mesuré avant correctif en 1280 px : 673 → 464 → 320 →
   697 px d'une étape à l'autre, avec un défilement animé par-dessus ; la page
   rebondissait à chaque clic. `--wiz-reserve` est posée par booking.js
   (recalculerReserve) : c'est la hauteur du plus grand panneau du parcours.
   Elle ne s'applique qu'aux quatre panneaux d'étape — l'écran de succès et le
   formulaire de demande gardent leur hauteur naturelle, les étirer n'aurait
   servi qu'à créer du vide. */
.wiz-card .wiz-panel[data-panel="1"],
.wiz-card .wiz-panel[data-panel="2"],
.wiz-card .wiz-panel[data-panel="3"],
.wiz-card .wiz-panel[data-panel="4"] { min-height: var(--wiz-reserve, 0px); }
.wiz-panel[hidden] { display: none; }
.wiz-panel { animation: wizFade 260ms ease; }
@keyframes wizFade { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
.wiz-panel-head { margin-bottom: 20px; }
/* Police de TITRE du salon (comme .booking-hero h1) : en registre Affiche,
   ce h2 passait en capitales grasses de la police de CORPS — un autre site
   au milieu du tunnel (4 sept. 2026). */
.wiz-panel-head h2 { margin: 6px 0 4px; color: var(--text); font-family: var(--font-heading, 'Cormorant Garamond'), serif; font-weight: 500; font-size: 1.75rem; }
.wiz-sub { color: var(--text-soft); margin: 0; font-size: 0.95rem; }
.wiz-signed {
  margin: 10px 0 0; font-size: 0.9rem; color: var(--gold, #c9a227);
  display: inline-flex; align-items: center; gap: 6px;
}
/* Voir le bloc « [hidden] contre display » en fin de fichier : sans cette
   ligne, la mention « connecté·e » restait affichée (avec sa coche ✓ orpheline)
   après déconnexion, parce que le display ci-dessus bat l'attribut hidden. */
.wiz-signed[hidden] { display: none; }
.wiz-signed::before { content: '✓'; font-weight: 700; }
.wiz-back {
  background: none; border: none;
  color: var(--accent); cursor: pointer;
  font-size: 0.85rem; padding: 0; margin-bottom: 4px;
}
.wiz-back:hover { text-decoration: underline; }
.wiz-loading, .wiz-empty {
  padding: 40px 16px; text-align: center; color: var(--text-soft);
}
/* Une PHRASE placée dans une grille de cartes (#svc-grid : colonnes de 230 px,
   #staff-cards : 180 px) se retrouve pliée dans la première piste. Même piège
   que « Complet ce jour-là » dans #wiz-slots, réglé là par un conteneur frère ;
   ici l'état vide appartient bien à la grille, il doit juste la traverser. */
.svc-grid > .wiz-loading, .svc-grid > .wiz-empty,
.staff-cards > .wiz-loading, .staff-cards > .wiz-empty { grid-column: 1 / -1; }
.wiz-empty p { margin: 0 0 14px; }
.wiz-empty p:last-child { margin-bottom: 0; }
/* Un état d'erreur sans sortie oblige à recharger la page — donc à tout
   ressaisir. Le bouton rejoue le chargement qui a échoué ; le téléphone du
   salon n'apparaît QUE si la boutique en a renseigné un. */
.wiz-empty-actions {
  display: flex; flex-wrap: wrap; align-items: center;
  justify-content: center; gap: 10px 16px;
}
.btn-retry {
  min-height: 44px; padding: 11px 22px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm, 10px);
  background: var(--surface);
  color: var(--text);
  font-family: inherit; font-size: 0.92rem; font-weight: 600;
  cursor: pointer;
  transition: border-color 150ms ease, color 150ms ease;
}
.btn-retry:hover { border-color: var(--gold); color: var(--accent); }
.btn-retry:disabled { opacity: 0.55; cursor: default; }
.wiz-empty-tel { font-size: 0.9rem; color: var(--text-soft); }
.hint-tel { color: var(--accent); font-weight: 600; white-space: nowrap; }

/* --- Étape 1 : prestations --- */
.svc-filter { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 18px; }
.chip {
  background: var(--surface-muted);
  border: 1px solid var(--line);
  color: var(--text-soft);
  border-radius: 999px;
  padding: 7px 16px;
  font-size: 0.82rem;
  cursor: pointer;
  transition: background-color 150ms ease, border-color 150ms ease, color 150ms ease;
}
.chip.is-active { background: var(--gold); color: var(--on-accent, #1a1712); border-color: var(--gold); font-weight: 600; }
.svc-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 14px; }
.svc-card {
  text-align: left;
  background: var(--surface-muted);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  padding: 18px;
  cursor: pointer;
  display: flex; flex-direction: column; gap: 8px;
  transition: transform 160ms ease, border-color 160ms ease, box-shadow 160ms ease;
}
.svc-card:hover { transform: translateY(-3px); border-color: var(--gold); box-shadow: 0 14px 30px rgba(0,0,0,0.35); }
.svc-cat {
  font-size: 0.68rem; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--gold); font-weight: 700;
}
/* Le NOM d'une prestation et son PRIX dans la police de titre du salon, comme
   sur la carte des tarifs de l'accueil et dans le tiroir du panier (8 oct.
   2026) : la cliente passe de l'un à l'autre, elle doit lire la même carte. */
.svc-name { font-family: var(--font-heading, 'Cormorant Garamond'), Georgia, serif; font-size: 1.28rem; font-weight: 600; line-height: 1.2; color: var(--text); }
.svc-desc { font-size: 0.85rem; color: var(--text-soft); margin: 0; line-height: 1.4; }
.svc-meta { display: flex; justify-content: space-between; align-items: baseline; margin-top: auto; padding-top: 6px; }
.svc-dur { font-size: 0.82rem; color: var(--text-faint); }
.svc-price { font-family: var(--font-heading, 'Cormorant Garamond'), Georgia, serif; font-size: 1.22rem; font-weight: 600; color: var(--accent); white-space: nowrap; }

/* Fiche prestation riche : photo en tête + badge « options ». */
.svc-card.has-photo { padding: 0; overflow: hidden; }
.svc-card .svc-photo {
  display: block; width: 100%; height: 120px;
  background-size: cover; background-position: center;
  border-bottom: 1px solid var(--line);
}
.svc-card .svc-body { display: flex; flex-direction: column; gap: 8px; flex: 1; }
.svc-card.has-photo .svc-body { padding: 14px 18px 16px; }
.svc-addon-badge {
  font-size: 0.7rem; font-weight: 600; letter-spacing: 0.04em;
  color: var(--gold); border: 1px solid var(--gold);
  border-radius: 999px; padding: 2px 8px; white-space: nowrap;
}
.svc-meta { gap: 8px; }

/* ===================================================================
   LOT 4 — LE PANIER DANS LE TUNNEL
   Trois surfaces neuves, et une règle qui les tient : rien de ceci
   n'existe tant que la cliente n'a pas ouvert de panier. Un salon qui ne
   s'en sert pas voit l'étape 1 d'avant, au pixel près — c'est ce que
   mesure le test A/B (tunnel-panier-compat).
   =================================================================== */

/* --- Le « + » de mise au panier ------------------------------------
   Un VRAI bouton, donc la carte n'en est plus un (un bouton dans un
   bouton est démonté par le navigateur) : .svc-card est passée en
   div[role=button], exactement comme .staff-card le fait depuis
   toujours. `button { font: inherit }` est déjà posé en tête de
   fichier : la police est la même des deux côtés. */
.svc-add {
  align-self: flex-start;
  display: inline-flex; align-items: center; gap: 7px;
  margin-top: 10px;
  padding: 9px 14px;
  min-height: 40px;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm, 10px);
  color: var(--text);
  font-size: .84rem; font-weight: 600;
  cursor: pointer;
  transition: border-color 150ms ease, background 150ms ease, color 150ms ease;
}
.svc-add:hover { border-color: var(--gold); color: var(--accent); }
.svc-add .svc-add-mark { font-size: 1rem; line-height: 1; font-weight: 700; }
.svc-add.is-on {
  background: var(--gold); border-color: var(--gold);
  color: var(--on-accent, #1a1712);
}
.svc-card.is-au-panier { border-color: var(--gold); }

/* --- La barre collante et son tiroir --------------------------------
   POSITION FIXE, donc HORS FLUX : elle apparaît sans pousser d'un pixel
   ce qui est déjà à l'écran. En flux, chaque ajout aurait coûté ~76 px
   de décalage — exactement le saut de mise en page que le lot 2 a
   supprimé. Le prix à payer est un `padding-bottom` sur le corps, pour
   que la dernière carte ne finisse pas dessous. */
.panier-dock {
  position: fixed; left: 0; right: 0; bottom: 0;
  z-index: 60;
  display: flex; flex-direction: column;
  background: var(--surface);
  border-top: 1px solid var(--line-strong);
  box-shadow: 0 -10px 30px rgba(0,0,0,0.18);
}
.panier-dock[hidden] { display: none; }
body.panier-actif { padding-bottom: 84px; }

.panier-bar {
  display: flex; align-items: center; gap: 14px;
  max-width: 1200px; width: 100%; margin: 0 auto;
  padding: 12px 20px;
  box-sizing: border-box;
}
.panier-sommaire {
  flex: 1;
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  min-height: 44px;
  background: none; border: none; padding: 0;
  color: var(--text); text-align: left; cursor: pointer;
}
.panier-sommaire:hover .panier-n { color: var(--accent); }
.panier-chevron { color: var(--text-faint); font-size: .9rem; line-height: 1; }
.panier-n { font-weight: 700; font-size: .96rem; }
.panier-pt { color: var(--text-faint); }
.panier-duree { font-size: .94rem; color: var(--text-soft); font-variant-numeric: tabular-nums; }
.panier-prix { font-size: .96rem; font-weight: 700; color: var(--accent); }
.panier-go { min-height: 44px; padding: 11px 26px; white-space: nowrap; }

.panier-detail {
  max-width: 1200px; width: 100%; margin: 0 auto;
  padding: 14px 20px 0;
  box-sizing: border-box;
  max-height: 46vh; overflow-y: auto;
  border-bottom: 1px solid var(--line);
}
.panier-detail[hidden] { display: none; }
.panier-lignes { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.panier-ligne {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap;
  padding: 10px 12px;
  background: var(--surface-muted);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm, 10px);
}
.pl-tete { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 220px; }
.pl-nom { font-weight: 600; color: var(--text); font-size: .95rem; }
/* `--text-soft` et non `--text-faint` : mesuré, le second donnait 4,51:1 en
   thème clair — au-dessus d'AA d'un centième. Ces deux lignes portent la durée
   et le prix, c'est-à-dire l'information qui décide. */
.pl-meta { font-size: .82rem; color: var(--text-soft); font-variant-numeric: tabular-nums; }
.pl-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.pl-qui { display: inline-flex; align-items: center; gap: 7px; font-size: .85rem; color: var(--text-soft); }
.pl-qui select {
  background: var(--surface); border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm, 10px);
  padding: 8px 10px; min-height: 40px;
  color: var(--text); font-family: inherit; font-size: .88rem;
}
.pl-qui select:focus { outline: none; border-color: var(--gold); }
.pl-qui-solo, .pl-qui-load { font-style: italic; }
.pl-changer, .pl-vider {
  background: none; border: none; padding: 8px 4px;
  color: var(--accent); font-family: inherit; font-size: .85rem; cursor: pointer;
  text-decoration: underline; min-height: 40px;
}
.pl-retirer {
  width: 40px; height: 40px; flex: none;
  background: none; border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm, 10px);
  color: var(--text-soft); font-size: .9rem; cursor: pointer;
}
.pl-retirer:hover { border-color: var(--danger, #b4453a); color: var(--danger, #b4453a); }
.panier-pied {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; padding: 8px 0 12px;
}
.panier-total { font-size: .86rem; color: var(--text-soft); font-variant-numeric: tabular-nums; }

/* --- Variantes : la modale qui décline une prestation --------------- */
.variant-row {
  display: flex; align-items: baseline; gap: 12px; width: 100%;
  padding: 13px 14px; margin-bottom: 8px;
  background: var(--surface-muted);
  border: 1px solid var(--line); border-radius: var(--radius-md);
  color: var(--text); text-align: left;
  font-family: inherit; cursor: pointer;
  transition: border-color 150ms ease;
}
.variant-row:hover, .variant-row.is-on { border-color: var(--gold); }
.variant-name { flex: 1; font-weight: 600; }
.variant-meta { font-size: .84rem; color: var(--text-faint); white-space: nowrap; font-variant-numeric: tabular-nums; }
.variant-price { font-weight: 700; color: var(--accent); white-space: nowrap; }

/* --- Vente additionnelle : un refus franc, pas une croix ------------ */
.addons-btns { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.addons-non { min-height: 44px; padding: 11px 20px; }
.addons-foot [data-continue][hidden] { display: none; }

/* --- Drill-down mobile ---------------------------------------------
   Sur téléphone, l'étape 1 de Lumière Coiffure mesurait 1569 px : neuf
   cartes empilées, quatre écrans de défilement pour voir l'offre. Les
   pastilles deviennent des LIGNES pleine largeur à chevron, et le
   catalogue n'ouvre qu'une catégorie à la fois. Sur écran large, ces
   règles ne s'appliquent pas : le chevron et le compteur restent
   masqués, et les pastilles restent des pastilles. */
.chip-chevron, .chip-count { display: none; }
.svc-filter.is-drill { flex-direction: column; gap: 0; align-items: stretch; }
.svc-filter.is-drill .chip {
  display: flex; align-items: center; gap: 10px;
  width: 100%; min-height: 56px;
  padding: 15px 4px;
  background: none; border: none;
  border-bottom: 1px solid var(--line);
  border-radius: 0;
  color: var(--text); font-size: 1rem; font-weight: 600;
  text-align: left;
}
.svc-filter.is-drill .chip.is-active { background: none; color: var(--text); }
.svc-filter.is-drill .chip-count {
  display: inline-block; margin-left: auto;
  color: var(--text-faint); font-size: .84rem; font-weight: 500;
  font-variant-numeric: tabular-nums;
}
.svc-filter.is-drill .chip-chevron {
  display: inline-block; color: var(--text-faint); font-size: 1.3rem; line-height: 1;
}
.svc-filter.is-drill .chip-retour {
  border-bottom: none; color: var(--accent); font-size: .92rem; min-height: 44px;
}
.svc-filter.is-drill .chip-retour .chip-chevron-back { margin-left: 0; }
.svc-filter.is-drill .chip-retour .chip-chevron { margin-left: 0; }

/* Modale « options » (add-ons) — réutilise l'habillage des fiches profil. */
.addons-head h3 { margin: 0 0 6px; }
.addons-sub { font-size: 0.88rem; color: var(--text-soft); margin: 0 0 14px; line-height: 1.45; }
.addon-row {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 14px; margin-bottom: 8px;
  background: var(--surface-muted);
  border: 1px solid var(--line); border-radius: var(--radius-md);
  cursor: pointer; transition: border-color 150ms ease;
}
.addon-row:hover { border-color: var(--gold); }
.addon-row:has(input:checked) { border-color: var(--gold); background: rgba(201, 162, 39, 0.07); }
.addon-row input { accent-color: var(--gold); width: 17px; height: 17px; flex: none; }
.addon-name { flex: 1; font-weight: 600; color: var(--text); }
.addon-meta { font-size: 0.82rem; color: var(--text-faint); white-space: nowrap; }
.addons-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.addons-total { font-size: 0.85rem; color: var(--text-soft); text-align: left; }
.recap-addon span:first-child { color: var(--text-soft); }

/* --- Étape 2 : équipe --- */
.staff-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 14px; }
.staff-card {
  background: var(--surface-muted);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  padding: 22px 16px;
  cursor: pointer;
  display: flex; flex-direction: column; align-items: center; gap: 8px; text-align: center;
  transition: transform 160ms ease, border-color 160ms ease, box-shadow 160ms ease;
}
.staff-card:hover { transform: translateY(-3px); border-color: var(--gold); box-shadow: 0 14px 30px rgba(0,0,0,0.35); }
.staff-avatar {
  width: 56px; height: 56px; border-radius: 50%;
  display: grid; place-items: center;
  font-weight: 700; font-size: 1.2rem; color: var(--on-accent, #1a1712);
}
.staff-avatar-any { background: var(--gold); color: var(--on-accent, #1a1712); }
.staff-avatar[style*="background-image"] { background-size: cover; background-position: center; }
.staff-name { font-weight: 600; color: var(--text); }
.staff-role { font-size: 0.8rem; color: var(--text-soft); }
.staff-rating { font-size: 0.82rem; color: var(--gold); font-weight: 600; }
.staff-rating em { color: var(--text-soft); font-style: normal; font-weight: 400; }
.staff-specs { display: flex; flex-wrap: wrap; gap: 5px; justify-content: center; }
.staff-chip {
  font-size: 0.7rem; color: var(--text-soft);
  background: rgba(201,162,39,0.10); border: 1px solid var(--line);
  border-radius: 999px; padding: 2px 8px;
}
.staff-links { display: flex; flex-direction: column; gap: 6px; margin-top: 4px; width: 100%; }
.staff-choose {
  font-size: 0.82rem; font-weight: 600; color: var(--on-accent, #1a1712);
  background: var(--gold);
  border-radius: 999px; padding: 6px 12px;
}
.staff-profile-link {
  background: none; border: 1px solid var(--line); color: var(--text-soft);
  border-radius: 999px; padding: 5px 12px; font-size: 0.78rem; cursor: pointer;
  transition: border-color 140ms ease, color 140ms ease;
}
.staff-profile-link:hover { border-color: var(--gold); color: var(--text); }

/* Fiche profil (modale) */
.profile-modal { position: fixed; inset: 0; z-index: 1000; display: grid; place-items: center; }
/* L'attribut [hidden] doit l'emporter sur le display:grid ci-dessus, sinon la
   modale reste affichée même fermée (bouton ✕ / backdrop sans effet). */
.profile-modal[hidden] { display: none; }
.profile-backdrop { position: absolute; inset: 0; background: rgba(0,0,0,0.62); backdrop-filter: blur(2px); }
.profile-dialog {
  position: relative; z-index: 1; width: min(680px, 92vw); max-height: 88vh; overflow: auto;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-lg);
  box-shadow: 0 30px 80px rgba(0,0,0,0.55); padding: 26px;
  animation: wizFade 220ms ease;
}
.profile-close {
  position: absolute; top: 14px; right: 14px; width: 34px; height: 34px;
  border-radius: 50%; border: 1px solid var(--line); background: var(--surface-muted);
  color: var(--text-soft); cursor: pointer; font-size: 0.9rem;
}
.profile-close:hover { color: var(--text); border-color: var(--gold); }
.profile-head { display: flex; gap: 18px; align-items: center; margin-bottom: 16px; }
.profile-avatar {
  width: 84px; height: 84px; border-radius: 50%; flex: none;
  display: grid; place-items: center; font-weight: 700; font-size: 1.7rem; color: var(--on-accent, #1a1712);
  background-size: cover; background-position: center;
}
.profile-head h3 { margin: 0 0 2px; font-family: var(--font-heading, 'Cormorant Garamond'), serif; font-size: 1.7rem; color: var(--text); }
.profile-title { font-size: 0.85rem; color: var(--text-soft); }
.profile-rating { margin-top: 6px; font-size: 0.9rem; color: var(--text-soft); display: flex; align-items: center; gap: 6px; }
.profile-rating strong { color: var(--gold); }
.profile-norating { color: var(--text-soft); font-style: italic; }
.stars-row .star { color: var(--line); }
.stars-row .star.is-on { color: var(--gold); }
.profile-specs { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 14px; }
.profile-bio { color: var(--text-soft); line-height: 1.55; margin: 0 0 16px; }
.profile-section { margin-top: 18px; }
.profile-section h4 {
  font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--gold); margin: 0 0 10px;
}
.portfolio-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 10px; }
.portfolio-item { margin: 0; border-radius: var(--radius-md); overflow: hidden; border: 1px solid var(--line); background: var(--surface-muted); }
.portfolio-item img { display: block; width: 100%; height: 130px; object-fit: cover; }
.portfolio-item figcaption { font-size: 0.72rem; color: var(--text-soft); padding: 6px 8px; }
.profile-reviews { display: flex; flex-direction: column; gap: 12px; }
.profile-review { border: 1px solid var(--line); border-radius: var(--radius-md); padding: 12px 14px; background: var(--surface-muted); }
.profile-review p { margin: 6px 0; color: var(--text); line-height: 1.5; }
.review-meta { font-size: 0.76rem; color: var(--text-soft); }
.profile-foot { margin-top: 22px; text-align: center; }
body.modal-open { overflow: hidden; }

/* --- Étape 3 : date + créneaux --- */
.date-strip {
  display: flex; gap: 8px; overflow-x: auto;
  padding-bottom: 10px; margin-bottom: 18px;
  scrollbar-width: thin;
}
.date-pill {
  flex: 0 0 auto;
  min-width: 64px;
  background: var(--surface-muted);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 10px 6px;
  cursor: pointer;
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  color: var(--text-soft);
  transition: background-color 150ms ease, border-color 150ms ease, color 150ms ease;
}
.date-pill:hover { border-color: var(--gold); }
.date-pill.is-active { background: var(--gold); border-color: var(--gold); color: var(--on-accent, #1a1712); }
.dp-wd { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.05em; }
.dp-dm { font-size: 0.92rem; font-weight: 700; }

/* --- Les trois états d'un jour ---------------------------------------------
   TROIS traitements franchement distincts, et JAMAIS la couleur seule : un
   daltonien doit lire le calendrier aussi vite qu'un autre.
     · ouvert  — la pastille d'origine, cliquable ;
     · fermé   — la date est BARRÉE (le salon ne travaille pas) ;
     · complet / terminé — grisé et estompé (le salon travaille, mais il n'y a
       plus rien à prendre).
   Chaque pastille bloquée porte en plus SON MOT (Fermé / Complet / Terminé) et
   le répète dans son aria-label : rien ne dépend du rendu. Elles sont
   réellement `disabled` + aria-disabled — on ne propose jamais un clic qui
   n'aboutira pas. */
.dp-state {
  font-size: 0.62rem; text-transform: uppercase; letter-spacing: 0.06em;
  margin-top: 2px; color: var(--text-soft); font-weight: 700;
}
.dp-state[hidden] { display: none; }
/* Estompé par des COULEURS, jamais par `opacity` : l'opacité aurait aussi
   délavé le mot qui porte le sens (mesuré à 2,12:1 en thème clair, illisible).
   La date recule, le mot reste net — c'est lui qui explique le grisé.
   Les boutons désactivés sont hors du champ de la règle 1.4.3, mais un mot
   qu'on ne lit pas ne remplace pas une couleur qu'on ne distingue pas. */
.date-pill:disabled {
  /* `opacity:1` explicite : la règle globale `button:disabled { opacity:.5 }`
     s'appliquerait sinon et délaverait de nouveau le mot d'état. */
  opacity: 1;
  cursor: not-allowed;
  background: transparent;
  border-style: dashed;
}
.date-pill:disabled .dp-wd,
.date-pill:disabled .dp-dm { color: var(--text-faint); }
.date-pill:disabled:hover { border-color: var(--line); }
/* Barré : la marque distinctive du jour de FERMETURE, sur les deux lignes de
   la date — un simple grisé ne se distinguerait pas d'un jour complet. */
.date-pill.is-ferme .dp-wd,
.date-pill.is-ferme .dp-dm { text-decoration: line-through; }
.time-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); gap: 10px; }
/* Conteneur FRÈRE de la grille : phrases, erreurs, liste d'attente. Rien de
   tout ça ne tient dans une colonne de 84 px, et rien de tout ça n'est un
   créneau. Vide, il ne réserve aucune place (:empty). */
.slots-msg { display: block; }
.slots-msg:empty { display: none; }
.slot-btn {
  background: var(--surface-muted);
  border: 1px solid var(--line-strong);
  color: var(--text);
  border-radius: var(--radius-sm);
  padding: 12px 0;
  font-weight: 600;
  cursor: pointer;
  transition: background-color 150ms ease, border-color 150ms ease, color 150ms ease, transform 150ms ease;
}
.slot-btn:hover { background: var(--gold); border-color: var(--gold); color: var(--on-accent, #1a1712); transform: translateY(-2px); }
.slots-hint { color: var(--text-soft); padding: 20px 4px; margin: 0; }
.slots-hint-warn { color: var(--danger); }

/* --- L'état vide à deux sorties ---------------------------------------------
   C'est l'écran où l'on perd la cliente : il ne doit jamais être un cul-de-sac.
   Une phrase qui dit la vérité (fermé / complet / terminé), la prochaine date
   réellement ouverte, puis deux sorties côte à côte : y aller, ou se faire
   prévenir. La boîte de liste d'attente prend toute la largeur DÈS QU'ELLE
   S'OUVRE (`:has`) — son formulaire à trois champs n'a rien à faire dans une
   rangée de boutons. */
.slots-from { margin: 0 4px 14px; color: var(--text); font-weight: 600; }
.slots-hint + .slots-from { margin-top: -10px; }
.slots-actions {
  display: flex; flex-wrap: wrap; gap: 10px; align-items: center;
  padding: 0 4px;
}
.slots-actions:empty { display: none; }
.slots-jump { padding: 11px 18px; border-radius: 999px; }
.slots-actions .wl-box { margin-top: 0; }
.slots-actions .wl-box:has(.wl-form:not([hidden])) { flex: 1 1 100%; }

/* Prochain dispo */
.next-avail {
  margin-top: 22px; padding: 18px;
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius-md);
  background: var(--surface-soft);
}
.na-title { margin: 0 0 12px; font-weight: 600; color: var(--accent); }
.na-list { display: flex; flex-direction: column; gap: 8px; }
.na-item {
  display: flex; justify-content: space-between; align-items: center; gap: 10px;
  background: var(--surface-muted);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 12px 16px;
  cursor: pointer; text-align: left;
  color: var(--text);
  transition: border-color 150ms ease, transform 150ms ease;
}
.na-item:hover { border-color: var(--gold); transform: translateX(3px); }
.na-when { font-weight: 600; }
/* `margin-left:auto` absorbe l'espace libre AVANT que justify-content ne
   s'applique : avec deux enfants le rendu est identique à celui d'avant, avec
   trois la mention reste collée au nom au lieu de flotter au centre. */
.na-who { color: var(--text-soft); font-size: 0.85rem; margin-left: auto; }
/* « Conseillé par le salon ». Pas de pastille pleine ni de couleur de
   remplissage : le remplissage est l'état :hover de .na-item, s'en servir ici
   ferait lire chaque ligne comme déjà sélectionnée. La marque est un MOT, pas
   une couleur — au lecteur d'écran elle s'entend. */
.na-flag { color: var(--text-soft); font-size: 0.85rem; white-space: nowrap; }
.na-who:not(:empty) + .na-flag::before { content: '·'; margin-right: 6px; }
/* L'intitulé de la SECONDE liste (les moments que la maison propose en
   premier). Il est délibérément SUBORDONNÉ à « Prochaines disponibilités » :
   filet de séparation au-dessus, encre douce, corps plus petit, et surtout
   PAS de seconde couleur d'accent dans la même boîte — deux titres de même
   rang se disputeraient la lecture, alors que l'un est une promesse de
   proximité et l'autre une préférence de la maison. */
.na-sous {
  margin: 16px 0 8px; padding-top: 14px;
  border-top: 1px solid var(--line);
  font-weight: 600; font-size: 0.9rem;
  color: var(--text-soft);
}

/* Liste d'attente (« prévenez-moi si un créneau se libère ») */
.wl-box { margin-top: 14px; }
.wl-open {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 11px 18px; cursor: pointer;
  min-height: 44px;
  border: 1px dashed var(--gold);
  border-radius: 999px;
  /* LE TEXTE EN ENCRE, PAS EN ACCENT. `var(--accent)` est la couleur CHOISIE
     PAR LE SALON : mesurée à 3,91:1 sur le fond du tunnel — sous le seuil AA,
     et invérifiable puisqu'elle change d'un client à l'autre. Depuis le lot 6
     ce bouton est affiché en PERMANENCE (plus seulement sur un jour complet),
     donc il ne peut plus se permettre d'être illisible chez un salon au
     jaune pâle. L'accent reste dans le filet, où il ne porte aucun texte. */
  background: transparent; color: var(--text);
  font-weight: 600; font-size: 0.92rem;
  transition: background-color 150ms ease;
}
.wl-open:hover { background: var(--surface-soft); border-style: solid; }
.wl-form {
  margin-top: 12px; padding: 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--surface-soft);
}
.wl-sub { margin: 0 0 12px; color: var(--text-soft); font-size: 0.88rem; }
.wl-fields { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 12px; margin-bottom: 12px; }
@media (max-width: 720px) { .wl-fields { grid-template-columns: 1fr; } }
/* Une ÉTIQUETTE VISIBLE, comme partout ailleurs dans le tunnel (`.field`).
   Les trois entrées n'avaient qu'un placeholder : il disparaît à la première
   frappe, il ne survit pas à un retour en arrière, et il ne donne aucun nom
   accessible stable (WCAG 1.3.1 / 3.3.2). Le placeholder ne reste que là où
   il apporte autre chose que l'étiquette : le format du téléphone. */
.wl-field { display: flex; flex-direction: column; gap: 6px; }
.wl-field > span { font-size: 0.85rem; color: var(--text-soft); font-weight: 600; }
.wl-fields input {
  background: var(--surface-muted);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  color: var(--text);
  padding: 10px 12px; width: 100%;
  font-family: inherit; font-size: 1rem;   /* 16 px : sous ce seuil, iOS zoome */
}
/* Sans cette règle, le placeholder retombait sur le gris du navigateur
   (#757575 en Chromium) : mesuré 3,45:1 sur le fond du champ en thème clair,
   sous le seuil AA — et hors de la DA du salon. `--text-soft` et non
   `--text-faint` : mesuré chez un salon de la flotte, la seconde tombe à
   3,22:1 une fois recalculée par tenant-theme.js. */
.wl-fields input::placeholder { color: var(--text-soft); opacity: 1; }
.wl-fields input:focus { outline: 2px solid var(--text); border-color: var(--text); }
.wl-submit {
  padding: 10px 18px; min-height: 44px; cursor: pointer; border: none;
  border-radius: var(--radius-sm);
  background: var(--accent-strong); color: var(--on-accent, var(--ink));
  font-weight: 700; letter-spacing: .02em;
  transition: background 150ms ease, opacity 150ms ease;
}
.wl-submit:hover { background: var(--gold-soft); }
.wl-submit[disabled] { opacity: .55; cursor: default; }
.wl-status { min-height: 18px; margin: 8px 0 0; font-size: 0.85rem; color: var(--text-soft); }
.wl-status.error { color: var(--danger); }
.wl-done { margin: 0; color: var(--success); font-weight: 600; }

/* LOT 6 — la liste d'attente est proposée EN PERMANENCE, plus seulement sur un
   jour complet. Elle vit donc dans un dock à elle, sous la grille de créneaux,
   et non dans la rangée d'actions du message « Complet ». */
.wl-dock { margin-top: 6px; }
.wl-dock:empty { display: none; }

/* Le choix de la fenêtre. Les libellés sont dérivés des horaires RÉELS du
   jour : ce bloc n'affiche jamais « Le matin » chez un salon qui ouvre à 14 h,
   parce que le serveur ne le renvoie pas. */
.wl-when { border: 0; padding: 0; margin: 0 0 14px; }
.wl-when legend {
  padding: 0; margin-bottom: 8px;
  font-size: 0.85rem; font-weight: 600; color: var(--text-soft);
}
.wl-wins { display: flex; flex-wrap: wrap; gap: 8px; }
.wl-win {
  display: inline-flex; align-items: baseline; gap: 8px;
  padding: 10px 14px; cursor: pointer;
  min-height: 44px;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: var(--surface-muted);
  color: var(--text);
  transition: border-color 150ms ease, background 150ms ease;
}
/* Le bouton radio reste dans le flux accessible (focus clavier, lecteur
   d'écran) : masqué à l'œil seulement, jamais retiré du DOM ni display:none. */
.wl-win input { position: absolute; opacity: 0; width: 1px; height: 1px; }
/* LE POINT DU BOUTON RADIO, REDESSINÉ. Le vrai `input` est masqué à l'œil :
   l'état coché ne tenait donc qu'à `border-color: var(--accent)` — la couleur
   CHOISIE PAR LE SALON, mesurée à 1,94:1 sur le fond de la pastille chez un
   salon rose (seuil WCAG 1.4.11 pour un indicateur non textuel : 3:1) — et à
   un fond `--surface-soft` qui est EXACTEMENT celui de `.wl-form` : la
   pastille sélectionnée perdait son remplissage et se fondait dans la boîte,
   pendant que ses voisines, elles, gardaient le leur. La sélection se lisait
   à l'envers. Elle est maintenant portée par une forme (le point plein) et
   par `--text`, jamais par la seule teinte de la marque. */
.wl-win-dot {
  flex: 0 0 auto; align-self: center;
  width: 15px; height: 15px; border-radius: 50%;
  border: 1.5px solid var(--line-strong);
  background: var(--surface);
  transition: border-color 150ms ease, background 150ms ease, box-shadow 150ms ease;
}
.wl-win:hover { border-color: var(--gold); }
.wl-win:has(input:checked) {
  border-color: var(--text);
  /* Le filet paraît à 2 px sans décaler la rangée (une bordure épaissie
     recalculerait la largeur de la pastille au clic). */
  box-shadow: inset 0 0 0 1px var(--text);
  background: var(--surface-muted);
}
.wl-win:has(input:checked) .wl-win-dot {
  border-color: var(--text);
  background: var(--text);
  box-shadow: inset 0 0 0 2.5px var(--surface);
}
.wl-win:has(input:focus-visible) { outline: 2px solid var(--text); outline-offset: 2px; }
.wl-win-label { font-weight: 600; font-size: 0.92rem; }
.wl-win-hours { color: var(--text-soft); font-size: 0.8rem; font-variant-numeric: tabular-nums; }
@media (max-width: 520px) {
  .wl-wins { flex-direction: column; }
  /* Le point et son libellé restent SOLIDAIRES à gauche, les horaires filent à
     droite. `space-between` répartissait les TROIS éléments et laissait le
     libellé flotter au milieu de la pastille, détaché de son point. */
  .wl-win { justify-content: flex-start; }
  .wl-win-hours { margin-left: auto; }
}

/* Le bandeau d'une PROPOSITION (`?wl=…`) : la cliente n'est pas venue d'elle-
   même, elle a suivi un message. La page doit d'abord lui dire ce qu'elle a
   sous les yeux. */
.wl-offer {
  margin: 0 0 22px; padding: 14px 18px;
  border: 1px solid var(--accent);
  border-radius: var(--radius-md);
  background: var(--surface-soft);
}
.wl-offer-title { margin: 0; font-weight: 700; color: var(--accent); }
.wl-offer-sub { margin: 4px 0 0; color: var(--text-soft); font-size: 0.88rem; }
.wl-offer.is-lost { border-color: var(--line-strong); }
.wl-offer.is-lost .wl-offer-title { color: var(--text); }
/* « Je ne peux pas venir » : discret (elle est venue pour PRENDRE la place),
   mais présent — sans lui, la seule sortie était de fermer l'onglet. */
.wl-offer-no {
  margin-top: 12px; min-height: 44px; padding: 10px 16px;
  border: 1px solid var(--line-strong); border-radius: 999px;
  background: transparent; color: var(--text-soft);
  font-family: inherit; font-size: 0.85rem; font-weight: 600;
  cursor: pointer;
  transition: color 150ms ease, border-color 150ms ease, background 150ms ease;
}
.wl-offer-no:hover { color: var(--text); border-color: var(--text); background: var(--surface-muted); }
.wl-offer-no[disabled] { opacity: .55; cursor: default; }
.wl-offer-err { margin: 8px 0 0; color: var(--danger); font-size: 0.85rem; }
/* « Ne plus m'avertir » (25.09.2026) : quitter la liste, pas seulement ce
   créneau. Un lien, plus discret que le bouton : ce n'est pas la réponse
   attendue, mais elle doit exister. */
.wl-offer-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 16px; }
.wl-offer-quit {
  margin-top: 12px; min-height: 44px; padding: 10px 4px;
  border: 0; background: transparent; color: var(--text-soft);
  font-family: inherit; font-size: 0.85rem; font-weight: 600;
  text-decoration: underline; text-underline-offset: 3px; cursor: pointer;
}
.wl-offer-quit:hover { color: var(--text); }
.wl-offer-quit[disabled] { opacity: .55; cursor: default; }

/* --- Étape 4 : confirmation --- */
.confirm-layout { display: grid; grid-template-columns: 1.4fr 1fr; gap: 26px; align-items: start; }
.confirm-form { display: flex; flex-direction: column; gap: 14px; }
.field { display: flex; flex-direction: column; gap: 6px; }
.field > span { font-size: 0.85rem; color: var(--text-soft); font-weight: 600; }
.field em { color: var(--text-faint); font-style: normal; font-weight: 400; }
/* LOT B2 (1er octobre 2026) : l'aide sous la remarque — même jeton que l'aide
   « première visite » (.deposit-toggle em), jamais une couleur en dur. */
.field .field-aide { display: block; margin-top: 2px; font-size: 0.86rem; color: var(--text-soft); line-height: 1.45; }
.field input, .field textarea {
  background: var(--surface-muted);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  padding: 13px 15px;
  color: var(--text);
  font-size: 0.98rem;
  font-family: inherit;
}
/* Aucune règle ::placeholder n'existait sur le tunnel : le gris par défaut du
   navigateur tombait à 3,27:1 en thème clair et 4,07:1 en sombre. Même jeton
   que .wl-fields, qui portait déjà le correctif. */
.field input::placeholder,
.field textarea::placeholder { color: var(--text-soft); opacity: 1; }
.field input:focus, .field textarea:focus { outline: none; border-color: var(--gold); }
.deposit-box {
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--surface-muted);
  padding: 16px;
}
.deposit-toggle { display: flex; align-items: flex-start; gap: 12px; cursor: pointer; }
.deposit-toggle input { margin-top: 4px; }
.deposit-toggle strong { color: var(--text); }
.deposit-toggle em { display: block; color: var(--text-soft); font-style: normal; font-size: 0.88rem; margin-top: 2px; }
.pay-methods { display: flex; gap: 20px; margin-top: 12px; color: var(--text-soft); }
.first-visit-box {
  border: 1px solid var(--accent);
  border-radius: var(--radius-md);
  background: color-mix(in srgb, var(--accent) 8%, var(--surface));
  padding: 16px;
}
.first-visit-box .deposit-toggle strong { color: var(--accent); }

/* Connexion express « compte existant » dans le tunnel (2026-07-09).
   Apparaît sous le champ e-mail quand l'adresse a déjà un compte : mot de passe
   + œil « Afficher », pour se connecter sans quitter la réservation. */
.account-login {
  border: 1px solid var(--gold);
  border-radius: var(--radius-md);
  background: color-mix(in srgb, var(--gold) 7%, var(--surface));
  padding: 16px;
  display: grid;
  gap: 12px;
  animation: fadeIn 0.25s ease;
}
/* Sans cette ligne, « Un compte existe déjà avec cet e-mail » restait affiché
   EN MÊME TEMPS que « Créer votre espace » : deux blocs contradictoires sous
   les coordonnées, le JS croyant l'avoir masqué. */
.account-login[hidden] { display: none; }
.account-login-msg { margin: 0; color: var(--text); font-size: 0.92rem; }
.pw-wrap { position: relative; display: flex; align-items: center; }
.pw-wrap input {
  flex: 1;
  width: 100%;
  padding: 12px 84px 12px 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm, 10px);
  background: var(--surface);
  color: var(--text);
  font-size: 1rem;
  font-family: inherit;
}
.pw-wrap input:focus { outline: none; border-color: var(--gold); }
.pw-toggle {
  position: absolute;
  right: 6px;
  border: none;
  background: transparent;
  color: var(--gold);
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
  padding: 6px 10px;
}
.pw-toggle:hover { text-decoration: underline; }
.account-login-actions { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.account-login-btn { padding: 10px 20px; }
.account-login-forgot {
  color: var(--text-soft); font-size: 0.85rem;
  /* 141x16 au doigt : ce lien est posé dans une rangée d'actions, pas au fil
     d'une phrase — l'exception « lien en ligne » de WCAG 2.5.8 ne s'y applique
     pas. On étend la zone touchable sans bouger la ligne de base. */
  display: inline-flex; align-items: center; min-height: 44px;
}
.account-login-status { min-height: 18px; font-size: 0.85rem; color: var(--text-soft); }
.account-login-status.error { color: var(--danger, #c0392b); }

/* --- Zone compte : créer un espace OU continuer en invité --- */
.account-choice {
  border: 1px solid var(--gold);
  border-radius: var(--radius-md);
  background: color-mix(in srgb, var(--gold) 7%, var(--surface));
  padding: 16px;
  display: grid;
  gap: 12px;
  animation: fadeIn 0.25s ease;
}
.account-choice-msg { margin: 0; color: var(--text); font-size: 0.92rem; }
.account-choice-tabs { display: flex; gap: 8px; }
.acc-tab {
  flex: 1;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm, 10px);
  background: var(--surface);
  color: var(--text-soft);
  font-size: 0.9rem;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}
.acc-tab:hover { border-color: var(--gold); }
.acc-tab.is-active {
  border-color: var(--gold);
  color: var(--text);
  background: color-mix(in srgb, var(--gold) 14%, var(--surface));
}
.account-create { display: grid; gap: 10px; }
.acc-consent {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  font-size: 0.85rem;
  color: var(--text-soft);
}
.acc-consent input { width: auto; margin-top: 2px; }
.acc-hint { margin: 0; font-size: 0.82rem; color: var(--text-soft); line-height: 1.4; }
.account-signup-status { min-height: 16px; font-size: 0.85rem; color: var(--text-soft); }
.account-signup-status.error { color: var(--danger, #c0392b); }

.recap-discount span:last-child { color: var(--accent) !important; font-weight: 600; }

/* « Bon à savoir » — la politique du salon, LUE AVANT le clic de confirmation.
   Point de conformité suisse : des frais d'annulation ou un acompte ne sont
   opposables que s'ils ont été annoncés par écrit avant l'engagement. Le bloc
   est donc placé entre le formulaire et le bouton, jamais dans un repli. */
.booking-policy {
  margin: 6px 0 4px;
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-sm);
  background: var(--surface-soft, var(--surface-muted));
}
.policy-title {
  margin: 0 0 8px; font-size: 0.78rem; font-weight: 700;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--accent);
}
.policy-list { margin: 0; padding-left: 18px; color: var(--text-soft); font-size: 0.88rem; line-height: 1.5; }
.policy-list li + li { margin-top: 5px; }

/* LOT 5 — L'ENGAGEMENT D'ARGENT.
   Il vit DANS « Bon à savoir », au-dessus des lignes générales, parce que
   c'est le seul point du bloc qui coûte quelque chose : il doit se lire avant
   l'adresse et le délai d'annulation. Trois étages, du plus fort au plus fin —
   le montant, la phrase qui l'explique, puis la mention qui fait foi. Un filet
   à gauche et un fond légèrement plus dense suffisent à le détacher : ni
   cadre, ni couleur d'alerte. Ce n'est pas une erreur, c'est une condition. */
.policy-engage {
  margin: 0 0 12px;
  padding: 12px 14px;
  border-left: 2px solid var(--accent);
  background: var(--surface-muted);
  border-radius: var(--radius-sm);
}
.pe-head {
  margin: 0 0 4px;
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.3;
  color: var(--text);
}
.pe-plain { margin: 0; color: var(--text-soft); font-size: 0.9rem; line-height: 1.5; }
/* L'échéance est la seule ligne qui annonce une PERTE (le rendez-vous tombe) :
   elle porte donc le seul renfort typographique du bloc. */
.pe-deadline {
  margin: 8px 0 0;
  font-size: 0.88rem;
  font-weight: 600;
  line-height: 1.45;
  color: var(--text);
}
.pe-why { margin: 6px 0 0; font-size: 0.82rem; color: var(--text-soft); line-height: 1.45; }
/* Moyens de paiement : deux libellés côte à côte, sans habillage de « carte ».
   Un choix à deux branches n'a pas besoin d'être mis en scène. */
fieldset.pe-methods { margin: 10px 0 0; padding: 0; border: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; }
fieldset.pe-methods legend { padding: 0; font-size: 0.82rem; color: var(--text-soft); }
p.pe-methods { margin: 10px 0 0; font-size: 0.86rem; color: var(--text-soft); }
.pe-moyen { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; font-size: 0.9rem; color: var(--text); min-height: 44px; }
.pe-moyen input { width: 18px; height: 18px; accent-color: var(--accent-strong); }
/* LA MENTION. C'est l'écrit qui sera cité au débit : reproduit mot pour mot,
   jamais tronqué, jamais replié. Il est plus petit que le résumé — il n'est
   pas ce qu'on lit en premier — mais reste au contraste du texte courant. */
.pe-mention-label {
  margin: 10px 0 4px;
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-soft);
}
.pe-mention {
  margin: 0;
  padding: 0 0 0 10px;
  border-left: 1px solid var(--line-strong);
  font-size: 0.83rem;
  line-height: 1.55;
  color: var(--text-soft);
}

/* L'écran de paiement — même famille que la confirmation, pas un autre monde.
   Tout y est borné à la même mesure de lecture (~620 px) : à pleine largeur de
   carte, la mention faisait 1140 px de long, soit deux fois trop pour être
   lue d'un trait — et c'est le seul texte de l'écran qui engage de l'argent. */
.wiz-pay .policy-engage { max-width: 620px; }
.wiz-pay .pay-zone { margin-top: 16px; display: flex; flex-direction: column; gap: 12px; max-width: 620px; }
.wiz-pay .pay-element:empty { display: none; }
.pay-note { margin: 0; font-size: 0.86rem; color: var(--text-soft); line-height: 1.5; }
.pay-note[hidden] { display: none; }
.wiz-pay .pay-go { width: 100%; }
/* `margin: 0` explicite : un <p> garde sinon ses 14.4 px hérités, et la ligne
   d'état creusait 29 px de vide entre « Payer » et « Je règle plus tard ». */
.pay-status { margin: 0; min-height: 20px; font-size: 0.9rem; color: var(--text-soft); }
.pay-status.ok { color: var(--success); font-weight: 600; }
.pay-status.error { color: var(--danger); font-weight: 600; }
.wiz-pay .pay-later { align-self: flex-start; }

/* Ce qui s'est passé côté argent, sur l'écran de succès. Deux tons seulement :
   réglé (accent calme) et en attente (bord d'alerte) — jamais de rouge, rien
   n'a échoué : il reste quelque chose à faire. */
.success-pay {
  margin: 0 auto 18px;
  max-width: 520px;
  padding: 14px 16px;
  text-align: left;
  border: 1px solid var(--line);
  border-left: 3px solid var(--success);
  border-radius: var(--radius-sm);
  background: var(--surface-muted);
}
.success-pay[data-ton="warn"] { border-left-color: var(--accent-strong); }
.success-pay[hidden] { display: none; }
.sp-head { margin: 0 0 4px; font-size: 1rem; font-weight: 700; color: var(--text); }
.sp-note { margin: 4px 0 0; font-size: 0.88rem; line-height: 1.5; color: var(--text-soft); }
/* « Régler l’acompte maintenant » (lot A, revue I15) : le seul chemin pour payer
   après « Continuer sans acompte » — il vit sous la mention, dans l’encart. */
.sp-payer { margin-top: 12px; }

.wiz-confirm { width: 100%; margin-top: 4px; }
/* Pourquoi le bouton est gris. Un bouton désactivé sans explication est pire
   que le message d'erreur qu'il remplace : celui-ci nomme le champ manquant. */
.wiz-need { margin: 6px 0 0; font-size: 0.85rem; color: var(--text-soft); }
.wiz-need[hidden] { display: none; }
.wiz-status { min-height: 20px; font-size: 0.9rem; color: var(--text-soft); }
/* Messages de statut lisibles au premier coup d'œil (polish 2026-07-08) :
   fond léger + liseré + icône, au lieu d'un simple texte coloré. Le variant
   « vide » retombe à zéro pour ne pas réserver d'espace inutile. */
.wiz-status.error,
.status.error {
  display: inline-block;
  color: var(--danger);
  background: rgba(208, 138, 132, 0.10);
  border-left: 3px solid var(--danger);
  border-radius: 6px;
  padding: 10px 14px;
}
.wiz-status.error::before,
.status.error::before { content: "⚠ "; }
.wiz-status.success,
.status.success {
  display: inline-block;
  color: var(--success);
  background: rgba(127, 174, 131, 0.10);
  border-left: 3px solid var(--success);
  border-radius: 6px;
  padding: 10px 14px;
}
.wiz-status.success::before,
.status.success::before { content: "✓ "; }
.wiz-status:empty,
.status:empty { padding: 0; border: 0; background: none; }
.wiz-status:empty::before,
.status:empty::before { content: none; }

.confirm-recap {
  background: var(--surface-soft);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  padding: 20px;
  position: sticky; top: 20px;
}
.confirm-recap h3 { margin: 0 0 14px; font-size: 1.05rem; color: var(--text); }
.recap-row { display: flex; justify-content: space-between; gap: 12px; padding: 7px 0; border-bottom: 1px solid var(--line); color: var(--text-soft); font-size: 0.92rem; }
.recap-row span:last-child { color: var(--text); text-align: right; font-weight: 500; }
.recap-total { border-bottom: none; margin-top: 6px; padding-top: 12px; }
.recap-total span { font-size: 1.05rem; font-weight: 700; color: var(--accent) !important; }

.booking-pay {
  margin-top: 20px; padding: 18px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-md);
  background: var(--surface-muted);
}
.booking-pay h4 { margin: 0 0 6px; }
.booking-pay p { margin: 0 0 12px; color: var(--text-soft); }

/* --- Écran succès --- */
.wiz-success { text-align: center; padding: 20px; }
.success-mark {
  width: 68px; height: 68px; border-radius: 50%;
  background: var(--success); color: var(--on-accent, #12200f);
  display: grid; place-items: center;
  font-size: 2rem; font-weight: 700;
  margin: 0 auto 16px;
  animation: pop 320ms ease;
}
@keyframes pop { 0% { transform: scale(0); } 70% { transform: scale(1.12); } 100% { transform: scale(1); } }
.wiz-success h2 { color: var(--text); margin: 0 0 18px; }
.success-recap { max-width: 380px; margin: 0 auto 22px; text-align: left; }
.success-actions { display: flex; flex-wrap: wrap; gap: 12px; justify-content: center; }
.success-note { color: var(--text-soft); font-size: 0.88rem; margin: 18px auto 0; max-width: 420px; }

/* Produits conseillés après la réservation (reco post-RDV) */
.success-reco { margin: 26px auto 0; max-width: 520px; border-top: 1px solid var(--line); padding-top: 20px; }
.reco-title { font-family: var(--font-heading, 'Cormorant Garamond', Georgia), serif; font-size: 1.3rem; color: var(--text); margin: 0 0 14px; }
.reco-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 12px; }
.reco-card { display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 12px; border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--surface-muted); text-decoration: none; transition: border-color 0.2s, transform 0.2s; }
.reco-card:hover { border-color: var(--gold); transform: translateY(-2px); }
.reco-thumb { width: 100%; aspect-ratio: 1/1; border-radius: var(--radius-sm); background: var(--surface) center/cover no-repeat; }
.reco-name { font-size: 0.85rem; color: var(--text); text-align: center; line-height: 1.3; }
.reco-price { font-family: var(--font-heading, 'Cormorant Garamond', Georgia), serif; font-size: 1.05rem; color: var(--gold); font-weight: 600; }

.wiz-help { text-align: center; margin-top: 22px; color: var(--text-soft); }
.wiz-help a { color: var(--accent); }

/* --- Responsive mobile --- */
@media (max-width: 760px) {
  .booking-hero { padding: 72px 0 30px; }
  .wiz-card { padding: 18px; border-radius: var(--radius-md); }
  .wiz-step .wiz-label { display: none; }
  .wiz-step::after { top: 14px; }
  .confirm-layout { grid-template-columns: 1fr; }
  .confirm-recap { position: static; order: -1; }
  .svc-grid { grid-template-columns: 1fr; }
  .staff-cards { grid-template-columns: repeat(2, 1fr); }
  .time-grid { grid-template-columns: repeat(auto-fill, minmax(72px, 1fr)); }
}

/* LOT 4 — L'ACTION AVANT LA PHOTO (mobile).
   Sur un téléphone, la photo de 120 px poussait le prix et l'action sous la
   ligne de flottaison : on voyait une carte et demie par écran, et le geste
   principal (« Ajouter ») n'était jamais visible sans faire défiler. On
   inverse l'ordre visuel — catégorie, nom, description, prix, ACTION, PUIS la
   photo — sans toucher au DOM : `column-reverse` suffit, et l'ordre de
   lecture au clavier comme au lecteur d'écran reste celui du document.
   Ne s'applique QU'AUX cartes qui ont une photo ; les autres ne bougent pas. */
@media (max-width: 640px) {
  .svc-card.has-photo { flex-direction: column-reverse; }
  .svc-card.has-photo .svc-photo {
    height: 92px;
    border-bottom: none; border-top: 1px solid var(--line);
  }
  .svc-card.has-photo .svc-body { padding: 14px 16px 14px; }
  /* Cible pleine largeur : 44 px de haut ne suffit pas si la cible fait 96 px
     de large au milieu d'une carte de 343 px. */
  .svc-add { align-self: stretch; justify-content: center; min-height: 44px; }
  /* LA BARRE EN DEUX RANGS SUR TÉLÉPHONE. Mesuré à 375 px avec « 1 prestation
     · 30 min · 35.– CHF » : le résumé se repliait sur trois lignes et écrasait
     « Continuer » contre le bord droit. On empile — résumé au-dessus, action
     pleine largeur en dessous — ce qui est aussi la meilleure cible au pouce. */
  .panier-bar { flex-direction: column; align-items: stretch; padding: 10px 16px 12px; gap: 8px; }
  .panier-sommaire { flex: none; min-height: 32px; justify-content: flex-start; }
  .panier-detail { padding: 12px 16px 0; max-height: 46vh; }
  .panier-go { width: 100%; padding: 12px 18px; }
  body.panier-actif { padding-bottom: 122px; }
  .panier-ligne { align-items: flex-start; }
  .pl-actions { width: 100%; justify-content: space-between; }
  .pl-qui { flex: 1; }
  .pl-qui select { flex: 1; min-width: 0; }
}

/* ---------------------------------------------------------------------------
   Pages légales (mentions, confidentialité, CGV, cookies) + liens de pied
--------------------------------------------------------------------------- */
.legal-shell { padding: 46px 0 72px; }
.legal-content { max-width: 820px; margin: 0 auto; }
/* « Cette page fait foi en français » — traduite à l'exécution (vitrine.note.foi),
   un filet et une taille en retrait : une note, pas une clause. */
.legal-foi { margin: 0 0 21px; padding: 13px 0; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); font-size: .88rem; line-height: 1.618; color: var(--text-soft); }
.legal-foi b { color: var(--text); font-weight: 600; }
/* « Supprimer mon compte » : l'encre de danger du thème (--danger tient AA sur
   la carte dans les deux modes), plus un rouge figé posé en ligne. */
.logout-link--danger { color: var(--danger); }
/* « En confirmant, vous acceptez… » sous chaque bouton d'engagement (tunnel,
   commande, carte cadeau, devis) : lu AVANT de conclure, jamais un pied de page. */
.legal-accept { margin: 13px 0 0; font-size: .8rem; line-height: 1.5; color: var(--text-soft); text-align: center; }
.legal-accept a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.legal-content h2 {
  font-family: var(--font-heading, 'Cormorant Garamond', 'Cormorant'), serif; font-weight: 500;
  font-size: 1.5rem; margin: 34px 0 10px; color: var(--gold-soft, #e8d8a0);
}
.legal-content h2:first-child { margin-top: 0; }
/* Un titre de clause se LIT : le registre typographique du salon
   (body.type-affiche h2, 0,1,2 — capitales grasses jusqu'à 48 px) en faisait
   des affiches au milieu d'un texte juridique (mesuré sur les CGV de Maison
   Corvel, 8 oct. 2026). La police de titre du salon reste, à taille de
   lecture et en casse normale. (html body : 0,1,3, au-dessus du registre.) */
html body .legal-content h2 {
  font-size: clamp(1.3rem, 2vw, 1.55rem); font-weight: 600; line-height: 1.25;
  text-transform: none; letter-spacing: .01em;
}
/* Numérotation des clauses par COMPTEUR : certains articles (boutique,
   fidélité) sont coupés par métier — un numéro écrit à la main aurait laissé
   des trous dans la suite. Un élément masqué ne génère pas de boîte, donc
   n'incrémente pas le compteur : la numérotation se referme seule. */
.legal-content { counter-reset: legal-clause; }
.legal-clause { counter-increment: legal-clause; }
.legal-clause > h2::before { content: counter(legal-clause) ". "; }
.legal-clause:first-of-type > h2 { margin-top: 0; }
.legal-content h3 { font-size: 1.08rem; margin: 20px 0 6px; }
.legal-content p, .legal-content li {
  line-height: 1.75; color: var(--text-soft, #cfc7b8); font-size: .96rem;
}
.legal-content ul { margin: 8px 0 8px 1.1rem; }
.legal-content li { margin: 4px 0; }
.legal-content a { color: var(--gold-soft, #e8d8a0); }
.legal-content .legal-updated { font-size: .84rem; color: var(--muted, #a79f8f); margin-bottom: 22px; }
.legal-content .legal-box {
  border: 1px solid var(--line, rgba(232,216,160,.16)); border-radius: 12px;
  padding: 16px 18px; margin: 16px 0; background: rgba(255,255,255,.02);
}
.legal-content .legal-box strong { color: var(--paper, #f4efe6); }

/* Liens légaux dans le pied de page (toutes pages publiques) */
.footer-legal { display: flex; flex-wrap: wrap; gap: 6px 16px; align-items: center; }
.footer-legal a {
  /* --footer-muted : encre calculée sur le fond DU PIED DE PAGE. --muted, lui,
     est calculé sur le fond du body — d'où le gris foncé sur noir en mode clair. */
  color: var(--footer-muted, var(--muted, #a79f8f)); font-size: .82rem; text-decoration: none;
  transition: color .15s;
}
.footer-legal a:hover { color: var(--gold-soft, #e8d8a0); text-decoration: underline; }

/* ---- Accessibilité : réduire les animations si la personne le demande ------ */
/* prefers-reduced-motion : on neutralise animations, transitions et défilement
   animé pour les personnes sensibles au mouvement (vestibulaire, vertiges…). */
/* ⛔ `transition: none`, PAS `transition-duration: .01ms` (8 oct. 2026). La
   propriété de transition vaut « all » par défaut : avec une durée de 0,01 ms
   posée sur `*`, CHAQUE changement de style devenait une transition — celui du
   fond de la page compris. Pendant l'image où elle court, getComputedStyle
   rend encore l'ANCIENNE couleur, et tenant-theme.js, qui calcule la palette
   du salon contre le fond réellement peint, la calculait contre le fond
   sombre d'avant la bascule : en thème clair, des cartes et un en-tête SOMBRES
   sur une page crème, titre illisible. Mesuré : 15 pages sur 24 chez une
   visiteuse qui a activé « réduire les animations » (réglage courant sur
   iPhone), 6 sur 18 en production. Les ANIMATIONS gardent leur 0,01 ms :
   des scripts attendent leur `animationend`. Aucun n'attend `transitionend`. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition: none !important;
    scroll-behavior: auto !important;
  }
}

/* ==========================================================================
   CHANTIER 41 — MODE CLAIR du site public.
   Le site est sombre/or par défaut (peau « Maison Corvel » ci-dessus, toute
   en variables) : il suffit de redéfinir la palette quand html[data-theme=
   "light"] est posé par theme.js (bouton soleil/lune, choix partagé entre
   les trois étages via localStorage 'colabs_theme').
   Le white-label tenant (tenant-theme.js) garde la priorité : ses styles
   inline sur --bg / --gold gagnent sur ces variables.
   ========================================================================== */
:root[data-theme="light"] {
  --bg: #f6f1e7;
  --ink: #141210;              /* texte posé sur les boutons dorés : reste sombre */
  --paper: #2a251c;            /* nom de marque : encre foncée sur fond clair */
  --surface: #ffffff;
  --surface-soft: #f0e9db;
  --surface-muted: #e9e1d1;
  --text: #26221b;
  --text-soft: #6d6355;
  --text-faint: #6b6153;       /* contraste AA (≥4.5) sur --bg clair et --surface-muted */
  --muted: #6d6355;
  --line: rgba(94, 74, 30, 0.16);
  --line-strong: rgba(94, 74, 30, 0.36);
  --accent: #8f6b14;           /* or foncé : lisible en texte sur fond clair */
  --accent-strong: #c9a227;    /* boutons dorés inchangés (texte --ink sombre) */
  --accent-deep: #8f6b14;
  --gold: #a07d16;
  /* 4,36:1 SUR LE FOND CLAIR — SOUS LE SEUIL, ET C'ÉTAIT LA COULEUR DES
     TITRES DE CLAUSE des pages légales (.legal-content h2), celles que
     lisent les clientes. Corrigé le 3 septembre 2026 en n'abaissant que la
     CLARTÉ : teinte et saturation inchangées, l'or reste le même or.
     #8f6b14 → #8b6813, soit 4,56:1. */
  --gold-soft: #8b6813;
  --success: #2e7d4f;
  --danger: #b3564e;
  --shadow: 0 24px 60px rgba(70, 55, 25, 0.14);
}

/* Retouches ciblées : les rares couleurs codées en dur pensées pour le sombre. */
[data-theme="light"] .site-header {
  background: var(--header-bg, rgba(252, 249, 242, 0.92)); /* le fond calculé du salon, comme l'accueil */
  border-bottom: 1px solid var(--line);
}
[data-theme="light"] .price-row:hover { background: rgba(0, 0, 0, 0.035); }
[data-theme="light"] .legal-content .legal-box { background: rgba(0, 0, 0, 0.025); }
[data-theme="light"] .ia-msg { box-shadow: 0 1px 3px rgba(0, 0, 0, 0.10); }
[data-theme="light"] .pricing-menu button:hover { background: rgba(143, 107, 20, 0.08); }
[data-theme="light"] .pricing-menu button.active { background: rgba(143, 107, 20, 0.12); color: var(--accent); }
[data-theme="light"] .notice { background: rgba(160, 125, 22, 0.10); }
[data-theme="light"] .btn-accent { color: var(--on-accent, #141210); }
[data-theme="light"] .footer-legal a:hover { color: var(--accent); }

/* En clair, l'or (auto-assombri par theme.js) porte du texte clair, pas sombre. */
[data-theme="light"] .skip-link,
[data-theme="light"] .chip.is-active,
[data-theme="light"] .wiz-step.is-active .wiz-dot,
[data-theme="light"] .wiz-step.is-done .wiz-dot { color: var(--on-accent, #fff); }

/* ==========================================================================
   CHANTIER 72 — EN-TÊTE ANIMÉE AU SCROLL (toutes pages, tous thèmes).
   app.js pose .is-shrunk sur .site-header après ~40 px de défilement :
   barre compacte, logo + marque réduits, verre dépoli mat TEINTÉ DU FOND
   du thème courant (var(--bg) suit le tenant, clair comme sombre).
   Placé en FIN de feuille : gagne sur les règles antérieures de même
   spécificité ([data-theme="light"] .site-header, skin Corvel…).
   ========================================================================== */
.site-header {
  transition: background-color 280ms ease, border-color 280ms ease,
    box-shadow 280ms ease;
}
.header-inner { transition: min-height 280ms ease, padding 280ms ease, gap 280ms ease; }
.brand { transition: font-size 280ms ease; }
.brand-logo { transition: height 280ms ease, max-width 280ms ease; }
.brand small {
  max-height: 1.4em;
  transition: opacity 280ms ease, max-height 280ms ease, margin-top 280ms ease;
}

/* Barre compacte OPAQUE (18 sept. 2026) : le verre dépoli à 78 % laissait
   transparaître les photos de la page en silhouettes floues sous la marque et
   la navigation — « des choses qui se chevauchent », mesuré sur la boutique.
   Le fond est celui de l'en-tête au repos (--header-bg, calculé du fond du
   salon par tenant-theme.js, encre vérifiée contre lui). */
.site-header.is-shrunk {
  background: var(--header-bg, var(--bg, #141210));
  border-bottom: 1px solid color-mix(in srgb, var(--text, #f2ece0) 16%, transparent);
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.10);
}
.site-header.is-shrunk .header-inner { min-height: 58px; gap: 21px; }
.site-header.is-shrunk .brand { font-size: 1.35rem; }
.site-header.is-shrunk .brand-logo { height: 40px; max-width: 110px; }
/* Le sous-titre de marque se replie en douceur : la barre reste basse. */
.site-header.is-shrunk .brand small { opacity: 0; max-height: 0; margin-top: 0; overflow: hidden; }
.site-header.is-shrunk .main-nav { gap: 21px; }

/* Variante « centre » (logo centré, nav dessous — injectée par
   tenant-theme.js). Compactée, elle empilait trois rangées à 4 px d'écart :
   le soulignement de la nav touchait le bouton Réserver, qui touchait le bord
   de la barre. Elle se range désormais sur DEUX rangées (marque + actions,
   puis la nav) et, dès qu'il y a la place, sur UNE seule ligne de 58 px. */
@media (min-width: 901px) {
  body.header-centre .site-header.is-shrunk .header-inner {
    grid-template-columns: auto 1fr auto;
    grid-template-areas: "marque . actions" "nav nav nav";
    justify-items: stretch;
    text-align: left;
    padding: 8px 0;
    gap: 8px 34px;
    min-height: 0;
  }
  body.header-centre .site-header.is-shrunk .brand-back-wrap,
  body.header-centre .site-header.is-shrunk .header-inner > .brand { grid-area: marque; }
  body.header-centre .site-header.is-shrunk .brand-back-wrap { display: flex; align-items: center; gap: 13px; }
  body.header-centre .site-header.is-shrunk .main-nav { grid-area: nav; }
  body.header-centre .site-header.is-shrunk .header-actions { grid-area: actions; justify-content: flex-end; }
  /* La flèche Retour rejoint le flux, à gauche de la marque (elle est en
     absolu sur l'en-tête déployée, cf. back-button.js). */
  body.header-centre .site-header.is-shrunk #colabs-back.cb-inline { position: static; }
}
@media (min-width: 1200px) {
  body.header-centre .site-header.is-shrunk .header-inner {
    grid-template-areas: "marque nav actions";
    padding: 0;
    min-height: 58px;
  }
}
@media (max-width: 900px) {
  body.header-centre .site-header.is-shrunk .header-inner { padding: 8px 0; row-gap: 8px; }
}

/* Variante « flottant » (header transparent posé sur le hero, en absolute) :
   au scroll elle devient FIXE avec le même verre dépoli — spécificité (0,3,1)
   pour battre la règle injectée body.header-flottant .site-header (0,2,1). */
body.header-flottant .site-header.is-shrunk {
  position: fixed;
  top: var(--banners-h, 0px);
  left: 0;
  right: 0;
  background: var(--header-bg, var(--bg, #141210));
  border-bottom: 1px solid color-mix(in srgb, var(--text, #f2ece0) 16%, transparent);
}

/* Mobile : le header à 3 rangées (marque / actions / burger) garde SA
   géométrie — on ne compacte que le padding, le burger reste intact. */
@media (max-width: 900px) {
  .site-header.is-shrunk .header-inner { min-height: 0; gap: 4px 12px; padding: 6px 0; }
  .site-header.is-shrunk .brand { font-size: 1.2rem; }
  .site-header.is-shrunk .brand-logo { height: 26px; }
}

/* Accessibilité : pas d'animation si l'utilisateur la refuse (l'état
   compact s'applique toujours, mais instantanément). */
@media (prefers-reduced-motion: reduce) {
  .site-header,
  .header-inner,
  .brand,
  .brand-logo,
  .brand small { transition: none; }
}

/* ===================================================================
   SITE PUBLIC AU DOIGT (2 août 2026). Mesuré sur un iPhone (390 px) avant
   correction : « Réserver » à 38 px de haut, « Réserver → » des prestations
   à 38 px, la bascule de thème à 36 px, les libellés Tarif/Durée à 11,2 px.
   44 px = minimum tactile (Apple HIG, WCAG 2.5.8 « Target Size »).
   16 px sur les champs = seul moyen d'empêcher iOS Safari de zoomer à la
   mise au point ; ce zoom est ce qui fait « sauter » la page pendant la
   saisie du tunnel de réservation.
   =================================================================== */
@media (max-width: 860px) {
  .btn-gold, .btn-outline, .btn-accent, .btn-soft, .reserve-btn, .svc-book,
  .cc-btn, .wiz-back, button[type="submit"] {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
  .theme-toggle, .nav-toggle, .cb-inline, #cart-launcher, .acct-btn { min-width: 44px; min-height: 44px; }
  input, select, textarea { min-height: 44px; font-size: 16px; }
  /* MÊME PIÈGE que `.svc-cat` ci-dessous, et il avait été manqué : une media
     query n'ajoute aucune spécificité, donc `input` (0,0,1) perdait contre
     `.field input` (0,1,1) et les neuf champs du tunnel restaient à 15,68 px —
     sous le seuil qui déclenche le zoom d'iOS Safari, celui-là même que la
     règle au-dessus devait empêcher (mesuré sur iPhone 12). */
  .field input, .field select, .field textarea { font-size: 16px; }
  /* Plancher de lisibilité : ces étiquettes tombaient à 10,2-11,5 px. */
  .svc-meta, .svc-label, .meta, .muted, .success-note { font-size: .8rem; }
  /* Deux actions collées se touchent au doigt : on écarte et on autorise le
     passage à la ligne plutôt que de laisser deux cibles se frôler. */
  .hero-actions, .svc-actions, .wiz-actions { gap: 12px; flex-wrap: wrap; }
}

/* Plancher de lisibilité, sélecteurs relevés sur les pages réelles (les
   mêmes cas que sur l'accueil : catégorie, durée, rôle, baseline de marque). */
@media (max-width: 860px) {
  /* Sélecteurs repris À L'IDENTIQUE de l'origine : une media query n'ajoute
     aucune spécificité, `.svc-cat` seul perdait contre `.svc .svc-cat`. */
  .svc .svc-cat { font-size: .78rem; }
  .svc .price small { font-size: .78rem; }
  .member .role { font-size: .78rem; }
  .member .specs span { font-size: .76rem; }
  .svc-foot .dur, .svc-modal__fact span, .reserve-btn { font-size: .8rem; }
  .brand small { font-size: .64rem; letter-spacing: .14em; }
  .footer-legal { gap: 10px 16px; }
  /* Cibles tactiles restées sous 44 px, mesurées sur iPhone 12 : les liens du
     pied (32-37 px), le lien d'évitement (40 px) et le bouton « Mon espace »
     du header (32×32). En PADDING vertical plutôt qu'en hauteur fixe : le
     rythme du pied de page est conservé, seule la zone touchable grandit. */
  .footer-legal a { padding: 12px 0; display: inline-flex; align-items: center; min-height: 44px; }
  .skip-link { padding: 13px 18px; min-height: 44px; box-sizing: border-box; }
  .acct-btn { min-width: 44px; min-height: 44px; }
}
