/* =========================================================================
   LA BEAUTÉ CACHÉE — CHARTE GRAPHIQUE GLOBALE
   ========================================================================= */

/* =====================================================================
   1. VARIABLES & BASE
   ===================================================================== */
:root {
  /* --- Couleurs officielles --- */
  --couleur-primaire: #9C0537;      /* Bordeaux / framboise — enseigne, boutons, icônes */
  --couleur-secondaire: #F0C3C8;    /* Rosé plus soutenu — footer, fonds d'accent, cartes de tarifs */
  --couleur-enseigne: #7A1C30;       /* Bordeaux profond — bandeau enseigne (titre, sous-titre, baseline) */
  --couleur-banniere-fond: #9C0538; /* Fond bordeaux exact de la bannière d'en-tête */

  /* Alias utilisés dans le reste de la feuille de style */
  --couleur-marque: var(--couleur-primaire);
  --couleur-marque-clair: #B8375A;
  --couleur-poudre: var(--couleur-secondaire);
  --couleur-dore: #C9A66B;          /* Doré discret — accents décoratifs (paquet cadeau) */

  --couleur-fond: #faf7f5;
  --couleur-carte: #ffffff;
  --couleur-texte: #2e2a2a;
  --couleur-texte-doux: #6f6666;
  --couleur-bordure: #eadfe2;
  --couleur-teinte: var(--couleur-poudre);

  --ombre-douce: 0 8px 24px rgba(156, 5, 55, 0.08);
  --ombre-hover: 0 16px 32px rgba(156, 5, 55, 0.15);
  --rayon-carte: 18px;
  --rayon-pilule: 999px;

  /* --- Polices officielles --- */
  --police-titres: 'Sacramento', cursive;         /* Enseigne « La Beauté Cachée » exclusivement */
  --police-corps: 'Montserrat', sans-serif;        /* Texte courant */
  --police-soins: 'Playfair Display', serif;       /* Noms de soins, titres de sous-sections, mentions d'offres (italique) */
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: var(--police-corps);
  background: var(--couleur-fond);
  color: var(--couleur-texte);
  line-height: 1.6;
  /* Empêche la barre de défilement horizontale que provoqueraient les
     fonds "plein bord" du header/menu/footer (technique du box-shadow
     100vmax), sans avoir besoin de clip-path (qui rognerait aussi les
     sous-menus déroulants). */
  overflow-x: hidden;
}

a { color: inherit; }

/* =====================================================================
   2. HEADER — bandeau enseigne (logo + baseline + contact rapide) sur une
      seule ligne, inspiré de l'ancienne bannière du site, + menu responsive
   ===================================================================== */
/* Dégradé vertical du bordeaux profond (--couleur-enseigne) vers le bordeaux
   clair (--couleur-marque-clair) — valeurs de repli, reprises par
   LBC.appliquerParametresGlobaux() depuis Parametres_des_contenus.csv
   (page=global, sections couleur_header_debut / couleur_header_fin, si
   renseignées). S'étend sur tout le header (bandeau enseigne + menu), le
   menu récupère ensuite son propre fond blanc ci-dessous pour ne pas
   hériter du dégradé. */
/* position+z-index nécessaires : depuis que .menu-principal a son propre
   z-index (pour son fond "plein bord", cf. plus bas), il forme son propre
   contexte d'empilement — son sous-menu déroulant (z-index:200) ne se
   compare donc plus qu'à l'intérieur de ce contexte, pas au reste de la
   page. Sans ceci, le header entier (menu compris) redevient un simple
   élément "au fil du texte" et se fait recouvrir par tout ce qui suit dans
   le HTML (ex. le carrousel d'accueil), qui vient après lui dans l'ordre du
   DOM. Valeur (150) volontairement au-dessus de .barre-onglets (100,
   prestations.html) : sinon la barre d'onglets catégories, sticky, passe
   par-dessus le sous-menu déroulant "Prestations" et cache son dernier
   lien (Épilations) — le z-index:200 du sous-menu ne le protège pas, car
   il ne se compare qu'à l'intérieur du contexte d'empilement créé ici.
   Reste sous la modale (z-index:1000). */
.site-header {
  position: relative;
  z-index: 150;
  background: linear-gradient(to bottom, var(--couleur-enseigne) 0%, var(--couleur-marque-clair) 100%);
}

/* --- Bandeau enseigne : grille à 3 zones (enseigne gauche / baseline
   centre / contact rapide droite), alignées et centrées verticalement sur
   une seule ligne. La colonne centrale ("auto") reste toujours centrée sur
   la largeur totale car encadrée par deux colonnes "1fr" symétriques,
   quelles que soient les largeurs du bloc enseigne et du bloc contact. --- */
.header-principal {
  max-width: 1200px;
  margin: 0 auto;
  padding: 14px 20px;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  column-gap: 20px;
  position: relative;
  /* z-index nécessaire : le menu juste en dessous (.menu-principal) déborde
     largement au-dessus de sa propre boîte à cause de son fond "plein bord"
     en box-shadow (spread 100vmax, qui s'étend dans toutes les directions,
     pas seulement horizontalement) — sans ce z-index, ce débord blanc
     recouvrirait le bandeau enseigne au lieu de s'arrêter dessous. */
  z-index: 1;
  /* Le dégradé bordeaux vient du parent .site-header (transparent ici) :
     comme .site-header n'est pas limité en largeur, il s'étend déjà d'un
     bord à l'autre de l'écran, sans avoir besoin de la technique du
     "bleed" en box-shadow (incompatible avec un dégradé). */
}

.logo-lien {
  grid-column: 1;
  justify-self: start;
  display: flex;
  align-items: center;
  gap: 12px;
  text-decoration: none;
}

.logo-image {
  /* Hauteur choisie pour retrouver la même proportion logo / nom d'enseigne
     que sur la carte cadeau (68px de logo pour un nom affiché à 2.1rem/33.6px,
     ratio ~2.02) : 32px de logo-texte ici × 2.02 ≈ 65px. */
  height: 65px;
  width: auto;
  flex: none;
}

.enseigne-texte {
  display: flex;
  flex-direction: column;
  align-items: center;
  line-height: 1.15;
}

.logo-texte {
  display: inline-block;
  position: relative;
  line-height: 1;
  font-family: var(--police-titres);
  font-size: 32px;
  font-weight: 400;
  color: #ffffff;
  letter-spacing: normal;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
}

/* Filet sous "La Beauté Cachée", en pseudo-élément plutôt qu'en
   border-bottom : Sacramento (police script) réserve, dans sa propre boîte
   de ligne, une hauteur "descendante" bien plus grande que ce que les
   lettres dessinent réellement (mesuré : ~11px d'espace fantôme sous
   l'encre visible du texte, contre 1px de descente réelle) — un
   border-bottom classique s'accroche donc au bas de cette boîte gonflée et
   semble "flotter" loin du texte, pas centré avec "Institut de Beauté" en
   dessous. Un ::after positionné en absolu ignore cette boîte et se cale
   à une distance fixe (mesurée à l'œil) sous l'encre réelle des lettres. */
.logo-texte::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 2px;
  height: 1.5px;
  background: #ffffff;
}

.logo-sous-titre {
  margin-top: 4px;
  font-family: var(--police-corps);
  font-size: 13px;
  font-weight: 700;
  color: #ffffff;
  letter-spacing: 2px;
  text-transform: none;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
}

.baseline {
  grid-column: 2;
  margin: 0;
  text-align: center;
  font-family: var(--police-corps);
  font-size: 22px;
  font-weight: 700;
  color: #ffffff;
  letter-spacing: 1px;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
}

.baseline .baseline-signature {
  display: block;
  margin-top: 4px;
  font-family: var(--police-titres);
  font-style: normal;
  font-weight: 400;
  font-size: 28px;
  letter-spacing: normal;
  color: #ffffff;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
}

/* --- Contact rapide (ex-bandeau supérieur), replié dans l'enseigne --- */
.header-contact-rapide {
  grid-column: 3;
  justify-self: end;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 4px;
}

.topbar-lien {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: #ffffff;
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.3px;
  text-decoration: none;
  text-underline-offset: 2px;
  white-space: nowrap;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
}

.topbar-lien:hover,
.topbar-lien:focus-visible { opacity: 0.85; text-decoration: underline; }

.topbar-lien .icone-mini { width: 14px; height: 14px; flex: none; }

/* Avis Google : texte au-dessus, étoiles centrées dessous */
.topbar-avis {
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
}

.topbar-etoiles { color: #ffd66b; letter-spacing: 1px; font-size: 0.75rem; text-shadow: 0 1px 3px rgba(0, 0, 0, 0.35); }

/* Nombre d'avis (ex. « 307 avis Google »), affiché seul au-dessus de la note et des étoiles. */
.topbar-avis-nombre { font-size: 0.72rem; font-weight: 600; color: #ffffff; opacity: 0.9; }

/* Note moyenne (ex. « 4,9 »), sur la même ligne que les étoiles, juste avant elles. */
.topbar-avis-ligne { display: inline-flex; align-items: center; gap: 4px; }
.topbar-avis-note { font-size: 0.75rem; font-weight: 600; color: #ffffff; }

/* --- Bouton burger (mobile) --- */
.menu-toggle {
  display: none;
  position: absolute;
  top: 16px;
  right: 20px;
  width: 40px;
  height: 40px;
  border: none;
  background: none;
  cursor: pointer;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
}

.menu-toggle span {
  display: block;
  width: 26px;
  height: 2px;
  background: #ffffff;
  transition: transform 0.25s ease, opacity 0.25s ease;
}

.menu-toggle.actif span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.menu-toggle.actif span:nth-child(2) { opacity: 0; }
.menu-toggle.actif span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* --- Menu principal --- */
.menu-principal {
  max-width: 1200px;
  margin: 6px auto 0;
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 6px;
  padding: 0 20px 10px;
  position: relative;
  z-index: 0;
  background: var(--couleur-carte);
}

/* Étend le fond blanc du menu (bordure basse comprise) jusqu'aux bords de
   l'écran, en ne débordant QUE horizontalement (top:0 / bottom:0 borne la
   hauteur exactement à celle du menu) — contrairement à un box-shadow à
   spread 100vmax, qui déborde dans toutes les directions et finit par
   "fuiter" par transparence derrière le bandeau enseigne du dessus. Un
   ::before (pas de vrais enfants) évite aussi tout risque de rogner le
   sous-menu déroulant. La bordure basse est ici (plutôt que sur
   .menu-principal directement) pour qu'elle aussi s'étende d'un bord à
   l'autre, sans quoi elle s'arrêtait net à 1200px avec un liseré bordeaux
   du bandeau visible juste au-dessus dans la zone de débord. */
.menu-principal::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 100vw;
  margin-left: -50vw;
  background: var(--couleur-carte);
  border-bottom: 1px solid var(--couleur-bordure);
  z-index: -1;
}

.menu-lien {
  display: inline-block;
  padding: 6px 16px;
  border-radius: var(--rayon-pilule);
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.3px;
  color: var(--couleur-texte);
  text-decoration: none;
  transition: background 0.2s ease, color 0.2s ease;
}

.menu-lien:hover {
  background: var(--couleur-poudre);
  color: var(--couleur-marque);
}

/* --- Sous-menus déroulants (« Prestations », « Plus ») --- */
.menu-item--dropdown { position: relative; }

.menu-lien-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: none;
  background: none;
  font-family: var(--police-corps);
  /* Un <button> ne reprend pas la hauteur de ligne du body comme le fait un
     <a> (les navigateurs lui appliquent leur propre line-height par défaut) :
     sans ce line-height:inherit, "Prestations"/"Plus" se retrouvaient un peu
     plus bas en hauteur totale, donc visuellement décalés vers le haut par
     rapport aux liens simples du menu. */
  line-height: inherit;
  cursor: pointer;
}

.chevron-menu {
  width: 9px;
  height: 6px;
  transition: transform 0.2s ease;
}

.menu-item--dropdown.ouvert .chevron-menu { transform: rotate(180deg); }

.sous-menu {
  position: absolute;
  top: calc(100% + 10px);
  left: 50%;
  transform: translateX(-50%);
  min-width: 220px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 10px;
  background: #fff;
  border: 1px solid var(--couleur-bordure);
  border-radius: 14px;
  box-shadow: var(--ombre-hover);
  opacity: 0;
  visibility: hidden;
  transform: translateX(-50%) translateY(-6px);
  transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s ease;
  z-index: 200;
}

.menu-item--dropdown.ouvert .sous-menu {
  opacity: 1;
  visibility: visible;
  transform: translateX(-50%) translateY(0);
}

.sous-menu-lien {
  display: block;
  padding: 10px 14px;
  border-radius: 10px;
  font-size: 0.82rem;
  font-weight: 500;
  color: var(--couleur-texte);
  text-decoration: none;
  white-space: nowrap;
  transition: background 0.2s ease, color 0.2s ease;
}

.sous-menu-lien:hover {
  background: var(--couleur-poudre);
  color: var(--couleur-marque);
}

@media (max-width: 860px) {
  .menu-toggle { display: flex; }

  /* La ligne unique (enseigne / baseline / contact rapide) n'a de sens
     qu'avec assez de largeur : en dessous de 860px, on repasse en colonne
     centrée et le contact rapide (déjà présent dans le menu « Plus » et
     dans le pied de page) est masqué pour garder un bandeau compact. */
  .header-principal {
    /* minmax(0, 1fr), pas juste "1fr" : "Nous contacter" (colonne 1) est
       plus large que le bloc avis (colonne 3), et un simple 1fr laisse le
       contenu le plus large pousser sa propre colonne au-delà de sa part
       équitable — les 2 colonnes latérales devenaient alors inégales, ce
       qui décalait aussi le centrage du logo/baseline (ligne au-dessus, en
       areas fusionnées sur les 3 colonnes) puisque les tracks de colonnes
       sont partagés entre toutes les lignes de la grille. minmax(0, 1fr)
       force les 2 colonnes à rester strictement égales ; un texte plus
       long que sa part déborde légèrement dans l'espace de gap voisin
       (blanc, sans collision avec le bouton burger) plutôt que d'élargir
       sa colonne. */
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
    grid-template-areas:
      "logo     logo   logo"
      "baseline baseline baseline"
      "contact  toggle  avis";
    row-gap: 6px;
    padding: 16px 20px 14px;
    justify-items: center;
  }

  /* Le logo sort du flux (position absolute) pour ne plus peser dans le
     centrage : sans ça, justify-self:center centre le duo logo+texte, donc
     "La Beauté Cachée / Institut de Beauté" se retrouvait décalé vers la
     droite (le logo à sa gauche déséquilibrait le calcul). En absolute, il
     ne reste plus que .enseigne-texte comme contenu de .logo-lien, qui se
     centre alors seul sur la largeur de l'écran ; le logo est repositionné
     juste à sa gauche (12px d'écart, comme le gap desktop) et suit donc le
     texte plutôt que l'inverse. */
  .logo-lien { grid-area: logo; justify-self: center; position: relative; }
  .logo-image { position: absolute; top: 50%; right: calc(100% + 12px); transform: translateY(-50%); }
  .enseigne-texte { align-items: center; }
  .baseline { grid-area: baseline; }

  /* Le conteneur d'origine (desktop) empile "Nous contacter" et l'avis
     Google en colonne, dans un seul bloc à droite. En display:contents il
     disparaît du rendu (plus de boîte, plus de flex-column) et ses 2 liens
     enfants deviennent directement placables dans la grille du header :
     "Nous contacter" à gauche du bouton burger, l'avis Google à droite —
     aucune modification du HTML nécessaire, identique sur les 10 pages. */
  .header-contact-rapide { display: contents; }
  .topbar-lien:not(.topbar-avis) { grid-area: contact; justify-self: start; }
  .topbar-avis { grid-area: avis; justify-self: end; }

  /* Bouton burger replacé dans le flux (sous la baseline, entre les 2 liens
     ci-dessus) plutôt qu'en position absolute top-right : sinon le padding
     droit réservé pour lui désaxait le centrage du logo/baseline vers la
     gauche (le bloc de texte se centrait sur la largeur restante, pas sur
     la largeur réelle de l'écran). Ainsi le padding redevient symétrique et
     le centrage est correct pour toutes les largeurs mobiles. */
  .menu-toggle {
    grid-area: toggle;
    position: static;
  }

  .menu-principal {
    display: none;
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    border-bottom: none;
    padding: 10px 20px 20px;
  }

  .menu-principal.ouvert { display: flex; }

  .menu-lien { text-align: center; padding: 12px 16px; }

  .menu-lien-toggle { width: 100%; justify-content: center; }

  /* Sous-menus : accordéon empilé dans le flux du menu mobile */
  .sous-menu {
    position: static;
    top: auto;
    left: auto;
    transform: none;
    min-width: 0;
    margin-top: 2px;
    box-shadow: none;
    background: var(--couleur-fond);
    display: none;
  }

  .menu-item--dropdown.ouvert .sous-menu {
    display: flex;
    opacity: 1;
    visibility: visible;
    transform: none;
  }

  .sous-menu-lien { text-align: center; }
}

/* =====================================================================
   3. NAVIGATION À 2 NIVEAUX (onglets catégories / sous-catégories)
   ===================================================================== */
.barre-onglets {
  position: sticky;
  top: 0;
  z-index: 100;
  background: rgba(250, 247, 245, 0.94);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-bottom: 1px solid #f1e5e8;
}

.barre-onglets .onglets {
  max-width: 1200px;
  margin: 0 auto;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
  padding: 14px 24px;
}

/* Niveau 2 : masqué automatiquement si la catégorie n'a pas de sous-catégories */
.barre-onglets .onglets-niveau2 {
  padding-top: 0;
  padding-bottom: 14px;
  gap: 8px;
}

.barre-onglets .onglets-niveau2:empty { display: none; }

.onglet {
  font-family: var(--police-corps);
  font-size: 0.82rem;
  font-weight: 600;
  letter-spacing: 0.4px;
  padding: 10px 22px;
  border-radius: var(--rayon-pilule);
  border: 1px solid var(--couleur-bordure);
  background: #fff;
  color: var(--couleur-texte-doux);
  cursor: pointer;
  transition: background 0.25s ease, color 0.25s ease,
              border-color 0.25s ease, transform 0.2s ease;
}

.onglet:hover {
  border-color: var(--couleur-marque-clair);
  color: var(--couleur-marque);
  transform: translateY(-1px);
}

.onglet:focus-visible {
  outline: 2px solid var(--couleur-marque);
  outline-offset: 2px;
}

.onglet[aria-selected="true"] {
  background: var(--couleur-marque);
  border-color: var(--couleur-marque);
  color: #fff;
  box-shadow: 0 6px 16px rgba(156, 5, 55, 0.22);
}

/* Onglets de niveau 2 : plus discrets que le niveau 1 */
.onglets-niveau2 .onglet {
  font-size: 0.74rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.8px;
  padding: 7px 16px;
  background: transparent;
  border-color: transparent;
}

.onglets-niveau2 .onglet:hover {
  background: #fff;
  border-color: var(--couleur-bordure);
}

.onglets-niveau2 .onglet[aria-selected="true"] {
  background: var(--couleur-teinte);
  border-color: var(--couleur-marque);
  color: var(--couleur-marque);
  box-shadow: none;
}

/* =====================================================================
   4. SECTIONS & GRILLE
   ===================================================================== */
main {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 24px 80px;
}

.groupe { margin-bottom: 40px; }

/* Bandeau titre + chapô des pages éditoriales (Contact, Épilations, Le
   Hammam, L'Institut, À Découvrir, Nos Prestations…) : réglage unique de
   l'espace sous le titre de page et sous son chapô d'introduction, repris
   automatiquement partout — inutile de dupliquer ces deux règles dans le
   <style> de chaque page. */
.page-contenu h1.titre-script {
  text-align: center;
  margin: 0 0 8px;
  font-family: var(--police-titres);
  font-style: normal;
  font-weight: 400;
  font-size: 40px;
  color: #9A0033;
}
.page-chapo { text-align: center; color: var(--couleur-texte-doux); font-size: 1rem; margin: 0 0 24px; }

.groupe .eyebrow {
  text-align: center;
  text-transform: uppercase;
  letter-spacing: 3px;
  font-size: 0.75rem;
  color: var(--couleur-texte-doux);
  margin-bottom: 4px;
}

/* Titre de sous-section réutilisable sur toutes les pages (catalogue, pages
   éditoriales, « bientôt disponible »…) : nom des soins, titres de
   sous-sections, mentions d'offres — jamais l'enseigne « La Beauté Cachée ». */
.titre-script {
  font-family: var(--police-soins);
  font-style: italic;
  font-weight: 500;
  color: var(--couleur-marque);
}

.groupe .titre-script {
  text-align: center;
  font-size: 2.6rem;
  margin: 0 0 24px;
}

.grille-cartes {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 20px;
  align-items: start;
}

/* Apparition douce au changement d'onglet */
@keyframes fondu-montant {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}

.panneau-anime { animation: fondu-montant 0.35s ease both; }

@media (prefers-reduced-motion: reduce) {
  .panneau-anime,
  .modal-box { animation: none; }
  .carte,
  .carte-image img { transition: none; }
}

/* =====================================================================
   5. CARTE DE SOIN
   ===================================================================== */
.carte {
  background: var(--couleur-carte);
  border: 1px solid #d3d3d3;
  border-radius: var(--rayon-carte);
  overflow: hidden;
  box-shadow: var(--ombre-douce);
  transition: transform 0.35s ease, box-shadow 0.35s ease;
  display: flex;
  flex-direction: column;
}

.carte:hover {
  transform: translateY(-6px);
  box-shadow: var(--ombre-hover);
}

/* Le bloc image n'est créé que si la colonne image1 est renseignée */
.carte-image {
  width: 100%;
  height: 220px;
  overflow: hidden;
  background: #eee2e2;
}

.carte-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 0.6s ease;
}

.carte:hover .carte-image img { transform: scale(1.06); }

.carte-corps {
  padding: 20px 16px 22px;
  display: flex;
  flex-direction: column;
  flex: 1;
}

/* --- Nouvelle disposition (v2, essai) : en-tête centré, photo réduite +
   liste de tarifs côte à côte, texte repliable, boutons en bas. Repli
   facile : `git checkout -- style.css prestations.html` restaure la
   disposition précédente (image pleine largeur en haut, menu déroulant,
   bouton « Détails » ouvrant une modale). --- */
/* Bandeau en dégradé rosé (même teinte que le reste du site) derrière le
   titre + sous-titre, pour qu'ils ressortent au premier coup d'œil dans la
   grille de cartes — déborde jusqu'aux bords de la carte (marges négatives
   annulant le padding de .carte-corps), les coins arrondis sont hérités du
   overflow:hidden de .carte. */
.carte-entete {
  text-align: center;
  margin: -20px -16px 8px;
  padding: 18px 16px 10px;
  background: linear-gradient(180deg, var(--couleur-poudre) 0%, #ffffff 100%);
}

.carte-corps h3 {
  margin: 0 0 4px;
  font-family: var(--police-soins);
  font-style: italic;
  font-size: 1.35rem;
  font-weight: 600;
  color: var(--couleur-marque);
}

.carte-corps .sous-titre {
  margin: 0;
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--couleur-marque-clair);
  white-space: pre-line;
}

/* Photo (réduite) + liste des tarifs, côte à côte et de même largeur —
   s'il n'y a pas de photo, la liste occupe seule toute la largeur. */
.carte-media {
  display: grid;
  grid-template-columns: 3fr 2fr;
  gap: 12px;
  align-items: start;
  margin-bottom: 14px;
}
.carte-media:not(.avec-image) { grid-template-columns: 1fr; }

.carte-media .carte-image {
  width: 100%;
  height: 108px;
  border-radius: 12px;
  overflow: hidden;
  background: #eee2e2;
}
.carte-media .carte-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 0.6s ease;
}
.carte:hover .carte-media .carte-image img { transform: scale(1.06); }

.carte-media .tarif-zone { margin-top: 0; padding-top: 0; border-top: none; }

.description {
  font-size: 0.9rem;
  color: var(--couleur-texte);
  margin-bottom: 12px;
}

.description p { margin: 0 0 12px; }
.description p:last-child { margin-bottom: 0; }

/* Lignes commençant par « - » dans un descriptif : puces rondes plutôt que
   le tiret brut (cf. rendreParagrapheEnHtml dans prestations.html). Mêmes
   marges que les paragraphes environnants pour un espacement homogène. */
.liste-puces { margin: 0 0 12px; padding-left: 1.15em; }
.liste-puces:last-child { margin-bottom: 0; }
.liste-puces li { margin: 0; line-height: 1.3; }

/* Description repliée sur quelques lignes (fondu en bas), avec une flèche
   pour la développer entièrement. La classe .sans-repli (posée en JS par
   ajusterRepliDescriptions, une fois la carte réellement mesurable dans le
   DOM) retire fondu + hauteur maximale sur les descriptions assez courtes
   pour tenir entièrement — sans quoi un « Lire la suite » qui ne
   développerait rien de plus apparaîtrait systématiquement. */
.description-repliable .description {
  max-height: 7.6em;
  overflow: hidden;
  position: relative;
  transition: max-height 0.35s ease;
}
.description-repliable .description p { margin: 0 0 10px; }
.description-repliable .description p:last-child { margin-bottom: 0; }
.description-repliable .description .liste-puces { margin: 0 0 10px; }
.description-repliable .description .liste-puces:last-child { margin-bottom: 0; }
.description-repliable.est-ouvert .description { max-height: 800px; }

.description-repliable .description::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1.6em;
  background: linear-gradient(to bottom, rgba(255, 255, 255, 0) 0%, var(--couleur-carte) 88%);
  transition: opacity 0.2s ease;
}
.description-repliable.est-ouvert .description::after { opacity: 0; }

.description-repliable.sans-repli .description {
  max-height: none;
  overflow: visible;
}
.description-repliable.sans-repli .description::after { display: none; }

/* Ligne de pied partagée : bouton « Lire la suite » à gauche, details à
   droite sur la même ligne (justify-content + margin-left:auto sur
   .details-note ci-dessous — celui-ci reste poussé à droite même quand le
   bouton est absent, ex. description assez courte pour ne pas être repliée,
   ou prestation sans description). Repasse à la ligne sur les cartes
   étroites plutôt que de laisser déborder un details trop long. */
.description-pied {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 4px 14px;
  margin-top: 6px;
}

.description-repliable-toggle {
  display: flex;
  align-items: center;
  gap: 5px;
  background: none;
  border: none;
  padding: 0;
  font-family: var(--police-corps);
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--couleur-marque);
  cursor: pointer;
}
.description-repliable-toggle svg { width: 9px; height: 6px; transition: transform 0.25s ease; }
.description-repliable-toggle.est-ouvert svg { transform: rotate(180deg); }

/* Details (souvent des précisions sur les tarifs) : toujours visible, jamais
   repliée, alignée à droite sur la ligne du bouton « Lire la suite »
   (cf. .description-pied ci-dessus) plutôt qu'en colonne à part sous les
   tarifs, pour ne pas faire varier la hauteur de la zone photo/tarifs d'une
   carte à l'autre et décaler le début de la description (cf. discussion
   2026-08-21). */
.details-note {
  margin-left: auto;
  text-align: right;
  font-size: 0.82rem;
  font-style: italic;
  color: var(--couleur-texte-doux);
}
.details-note p { margin: 0; }
.details-note p + p { margin-top: 2px; }

.couleur-marque {
  color: var(--couleur-marque);
  font-weight: 500;
}

/* =====================================================================
   6. DURÉES / TARIFS
   ===================================================================== */
.tarif-zone {
  padding-top: 14px;
  border-top: 1px solid #f0e8e8;
}

/* Sélection de la durée : menu déroulant « durée — prix » sur toute la ligne
   (repli conservé — non utilisé par la disposition v2, cf. .tarif-liste
   ci-dessous, mais réutilisable si on revient à l'ancienne disposition). */
.tarif-selection { display: block; }

/* Liste de tarifs cliquables (disposition v2) : chaque ligne "durée — prix"
   est sélectionnable, la sélection active étant mise en couleur — remplace
   le menu déroulant lorsqu'il y a plusieurs tarifs. */
.tarif-liste {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 6px;
}
.tarif-choix {
  display: flex;
  align-items: baseline;
  justify-content: flex-end;
  gap: 6px;
  max-width: 100%;
  background: none;
  border: none;
  padding: 3px 4px;
  cursor: pointer;
  font-family: var(--police-corps);
  text-align: right;
}
/* La durée peut se réduire et passer sur 2 lignes si besoin (ex. "Dos et
   jambes 1h"), mais le prix ("90 €") garde toujours sa largeur et ne se
   coupe jamais entre le nombre et le symbole. */
.tarif-choix-duree { font-size: 0.78rem; line-height: 1.25; color: var(--couleur-texte-doux); flex: 1 1 auto; min-width: 0; }
.tarif-choix-prix { font-size: 0.94rem; font-weight: 700; color: var(--couleur-texte-doux); white-space: nowrap; flex: 0 0 auto; }
/* Le tiret séparateur devant le prix a été retiré (cf. discussion
   2026-08-21) : une fois le prix sélectionné mis en badge plein
   (.tarif-choix.est-selectionne .tarif-choix-prix ci-dessous), le tiret se
   serait retrouvé à l'intérieur de la pilule — et supprimer le tiret
   partout plutôt que de le sortir du badge dans un seul contexte reste
   plus simple et cohérent entre les deux présentations. */
/* Sans photo, la liste de tarifs est seule sur toute la largeur de la
   carte : centrée plutôt qu'alignée à droite (l'alignement à droite n'a de
   sens que collé contre une photo à gauche). */
.carte-media:not(.avec-image) .tarif-liste { align-items: center; }
.carte-media:not(.avec-image) .tarif-choix { justify-content: center; text-align: center; }
.carte-media:not(.avec-image) .tarif-choix-duree { flex: 0 0 auto; }
.carte-media:not(.avec-image) .tarif-ligne-unique { justify-content: center; }

.tarif-choix.est-selectionne .tarif-choix-duree { color: var(--couleur-marque-clair); }
/* Prix sélectionné : fond plein + texte blanc (inversion vidéo), pas
   seulement un changement de couleur de texte — reste distinguable en
   niveaux de gris/N&B (daltonisme y compris), où le bordeaux et le gris de
   repos ont une luminosité trop proche pour se voir. */
.tarif-choix.est-selectionne .tarif-choix-prix {
  color: #fff;
  background: var(--couleur-marque);
  padding: 2px 9px;
  border-radius: var(--rayon-pilule);
}
.tarif-choix:hover .tarif-choix-prix { color: var(--couleur-marque-clair); }
.tarif-choix.est-selectionne:hover .tarif-choix-prix { color: #fff; }

.tarif-ligne.tarif-ligne-unique { justify-content: flex-end; }

.select-duree {
  display: block;
  width: 100%;
  padding: 9px 32px 9px 12px;
  border: 1.5px solid #c2c2c2;
  border-radius: 12px;
  background-color: #fff;
  /* Chevron dessiné en SVG (couleur marque) : évite la flèche native,
     inégale d'un OS à l'autre et impossible à colorer en CSS. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' fill='none' stroke='%239C0537' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 11px 8px;
  font-family: var(--police-corps);
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--couleur-marque);
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  transition: border-color 0.2s ease, border-width 0.2s ease;
}

/* Liste déroulée : rendue par l'OS, seules la couleur et le fond sont pilotables */
.select-duree option {
  color: var(--couleur-marque);
  background-color: #fff;
}

.select-duree:hover { border-color: var(--couleur-marque-clair); border-width: 2px; }

.select-duree:focus-visible {
  outline: 2px solid var(--couleur-marque);
  outline-offset: 1px;
}

/* Tarif unique : simple ligne non interactive. gap aligné sur celui de
   .tarif-choix (liste à puces, cas le plus courant, 6px) pour que la durée
   et le prix restent aussi resserrés d'une présentation à l'autre. */
.tarif-ligne {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 6px;
  padding: 4px 2px;
}

.tarif-duree {
  font-size: 0.88rem;
  color: var(--couleur-texte-doux);
}

.prix-affiche {
  font-weight: 700;
  color: var(--couleur-marque);
  font-size: 1.05rem;
  white-space: nowrap;
}

/* Mention type « *avec 20 min de massage du dos » (durée sans prix associé) */
.tarif-note {
  margin: 8px 0 0;
  font-size: 0.76rem;
  font-style: italic;
  color: var(--couleur-texte-doux);
}

/* Affiché lorsque aucun couple durée/prix n'est renseigné */
.tarif-absent {
  margin: 0;
  padding: 10px 14px;
  border: 1px dashed var(--couleur-bordure);
  border-radius: 12px;
  font-size: 0.82rem;
  color: var(--couleur-texte-doux);
  text-align: center;
}

/* =====================================================================
   7. ACTIONS DE CARTE
   ===================================================================== */
.actions-carte {
  margin-top: auto;
  padding-top: 14px;
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.btn-reserver {
  position: relative;
  overflow: hidden;
  flex: 1 1 auto;
  background: var(--couleur-marque);
  color: #fff;
  border: none;
  padding: 9px 18px;
  border-radius: var(--rayon-pilule);
  font-family: var(--police-corps);
  font-size: 15px;
  font-weight: bold;
  letter-spacing: 0.5px;
  cursor: pointer;
  transition: background 0.25s ease, transform 0.2s ease;
  box-shadow: 0 3px 10px rgba(156, 5, 55, 0.2);
}

.btn-reserver:hover {
  background: var(--couleur-marque-clair);
  transform: translateY(-1px);
}

/* Changement de prix sur le bouton « Acheter » (déclenché en JS via
   .anime-prix, cf. majTexteAchat dans prestations.html, quand le visiteur
   choisit un autre tarif) : un bandeau opaque (::before) balaye le bouton
   de gauche à droite, recouvrant l'ancien prix puis le « reconstruisant »
   — le texte est en fait échangé en JS pile à mi-parcours, à l'instant où
   le bandeau le recouvre entièrement, donnant l'impression d'un effacement
   suivi d'une réécriture plutôt qu'un changement net. Le reflet lumineux
   (::after, effet d'origine) reste en prime, par-dessus, à la même
   vitesse. Les deux animations doivent rester synchronisées avec
   DUREE_ANIMATION_ACHAT_MS dans prestations.html. */
.btn-reserver::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--couleur-marque);
  transform: translateX(-100%);
  pointer-events: none;
}

.btn-reserver.anime-prix::before {
  animation: effacementPrixBouton 0.55s ease-out;
}

@keyframes effacementPrixBouton {
  0%   { transform: translateX(-100%); }
  50%  { transform: translateX(0%); }
  100% { transform: translateX(100%); }
}

.btn-reserver::after {
  content: "";
  position: absolute;
  top: 0;
  left: -75%;
  width: 45%;
  height: 100%;
  background: linear-gradient(115deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.6) 50%, rgba(255, 255, 255, 0) 100%);
  transform: skewX(-20deg);
  pointer-events: none;
}

.btn-reserver.anime-prix::after {
  animation: balayagePrixBouton 0.55s ease-out;
}

@keyframes balayagePrixBouton {
  from { left: -75%; }
  to { left: 130%; }
}

.btn-offrir-cadeau {
  flex: 0 0 auto;
  background: var(--couleur-poudre);
  border: 1px solid transparent;
  color: var(--couleur-marque);
  padding: 9px 18px;
  border-radius: var(--rayon-pilule);
  font-family: var(--police-corps);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.3px;
  cursor: pointer;
  transition: background 0.25s ease, border-color 0.25s ease;
}

.btn-offrir-cadeau:hover {
  background: #fff;
  border-color: var(--couleur-marque);
}

/* Réduits au minimum sur les cartes de prestations spécifiquement (ces
   classes sont aussi utilisées ailleurs sur le site, où la taille normale
   reste voulue — cf. .btn-reserver / .btn-offrir-cadeau ci-dessus). */
.actions-carte .btn-reserver,
.actions-carte .btn-offrir-cadeau {
  padding: 6px 12px;
  font-size: 0.72rem;
}

.btn-details {
  align-self: center;
  flex: 0 0 auto;
  background: transparent;
  border: 1px solid var(--couleur-marque);
  color: #7A1C30;
  padding: 9px 20px;
  border-radius: var(--rayon-pilule);
  font-family: var(--police-corps);
  font-size: 12px;
  font-weight: bold;
  letter-spacing: 1px;
  text-transform: none;
  cursor: pointer;
  transition: background 0.25s ease, color 0.25s ease;
}

.btn-details:hover {
  background: var(--couleur-marque);
  color: #fff;
}

/* Variante réduite : bouton « Détails » affiché juste sous le sous-titre
   de la carte, au-dessus du prix (au lieu du bouton pleine taille du bas). */
.btn-details-petit {
  align-self: flex-start;
  margin: 2px 0 10px;
  padding: 4px 14px;
  font-size: 0.68rem;
}

/* =====================================================================
   8. MODALE DE RÉSERVATION / PAIEMENT
   ===================================================================== */
.modal-reservation { max-width: 480px; }

.recap-prestation {
  background: var(--couleur-teinte);
  border-radius: 14px;
  padding: 12px 18px;
  margin-bottom: 16px;
}

.recap-titre {
  margin: 0 0 4px;
  font-weight: 600;
  font-size: 1rem;
  color: var(--couleur-texte);
}

.recap-tarif {
  margin: 0;
  display: flex;
  align-items: baseline;
  gap: 6px;
  font-size: 0.9rem;
}

.recap-separateur {
  color: var(--couleur-marque);
  font-weight: 700;
  font-size: 1.05rem;
}

.paiement-label {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--couleur-texte);
  margin: 0 0 10px;
}

.coordonnees-client { margin-bottom: 16px; }

.champs-grille {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 12px;
}

.champ {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.champ label {
  font-size: 0.72rem;
  color: var(--couleur-texte-doux);
  text-transform: uppercase;
  letter-spacing: 0.4px;
}

.champ input {
  padding: 10px 12px;
  border-radius: 10px;
  border: 1px solid #ddc9cf;
  background: #fff;
  font-family: var(--police-corps);
  font-size: 0.88rem;
  color: var(--couleur-texte);
}

.champ input:focus {
  outline: none;
  border-color: var(--couleur-marque);
}

.paiement-grille {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
  margin-bottom: 6px;
}

.paiement-carte {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 16px 10px;
  border: 2px solid var(--couleur-bordure);
  border-radius: 14px;
  background: #fff;
  cursor: pointer;
  transition: border-color 0.2s ease, background 0.2s ease;
  font-family: var(--police-corps);
  text-align: center;
}

.paiement-carte:hover { border-color: var(--couleur-marque-clair); }

.paiement-carte.actif {
  border-color: var(--couleur-marque);
  background: var(--couleur-teinte);
}

.paiement-carte .icone { width: 34px; height: 34px; }

.paiement-carte span {
  font-size: 0.78rem;
  color: var(--couleur-texte);
  line-height: 1.3;
}

.paiement-carte small {
  color: var(--couleur-texte-doux);
  font-size: 0.68rem;
  font-weight: 400;
}

.paiement-detail {
  display: none;
  margin-top: 18px;
  padding-top: 18px;
  border-top: 1px solid #f0e8e8;
}

.paiement-instruction {
  font-size: 0.88rem;
  color: var(--couleur-texte);
  margin: 0 0 14px;
  line-height: 1.5;
}

.paiement-erreur {
  font-size: 0.82rem;
  color: var(--couleur-marque);
  margin-top: 8px;
}

.btn-confirmer {
  width: 100%;
  background: var(--couleur-marque);
  color: #fff;
  border: none;
  padding: 12px 20px;
  border-radius: var(--rayon-pilule);
  font-family: var(--police-corps);
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.25s ease;
}

.btn-confirmer:hover { background: var(--couleur-marque-clair); }

.btn-sms {
  display: block;
  width: 100%;
  margin-top: 10px;
  background: transparent;
  border: 1px solid var(--couleur-marque);
  color: var(--couleur-marque);
  padding: 11px 20px;
  border-radius: var(--rayon-pilule);
  font-family: var(--police-corps);
  font-size: 0.82rem;
  font-weight: 600;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.25s ease, color 0.25s ease;
}

.btn-sms:hover {
  background: var(--couleur-marque);
  color: #fff;
}

#paypal-button-container { min-height: 45px; }

.reservation-confirmation {
  text-align: center;
  padding: 10px 4px 4px;
}

.confirmation-icone {
  width: 56px;
  height: 56px;
  line-height: 56px;
  margin: 0 auto 16px;
  border-radius: 50%;
  background: var(--couleur-marque);
  color: #fff;
  font-size: 1.6rem;
}

.reservation-confirmation h4 {
  margin: 0 0 10px;
  color: var(--couleur-marque);
  font-size: 1.15rem;
}

.reservation-confirmation p {
  font-size: 0.88rem;
  margin: 0 0 10px;
  color: var(--couleur-texte);
}

.confirmation-recap {
  background: var(--couleur-teinte);
  border-radius: 10px;
  padding: 10px 14px;
}

.btn-fermer-confirmation {
  margin-top: 8px;
  background: transparent;
  border: 1px solid var(--couleur-marque);
  color: var(--couleur-marque);
  padding: 9px 24px;
  border-radius: var(--rayon-pilule);
  font-family: var(--police-corps);
  font-size: 0.8rem;
  cursor: pointer;
  transition: background 0.25s ease, color 0.25s ease;
}

.btn-fermer-confirmation:hover {
  background: var(--couleur-marque);
  color: #fff;
}

/* =====================================================================
   9. MODALE GÉNÉRIQUE (détails)
   ===================================================================== */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(46, 33, 33, 0.55);
  display: none;
  align-items: center;
  justify-content: center;
  padding: 24px;
  z-index: 1000;
}

.modal-overlay.ouvert { display: flex; }

.modal-box {
  background: #fff;
  max-width: 560px;
  width: 100%;
  max-height: 85vh;
  overflow-y: auto;
  border-radius: var(--rayon-carte);
  padding: 28px 32px;
  position: relative;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.25);
  animation: apparition 0.3s ease;
}

@keyframes apparition {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: translateY(0); }
}

.modal-box h3 {
  font-size: 1.3rem;
  color: var(--couleur-marque);
  margin: 0 0 14px;
  padding-right: 30px;
}

.modal-box .modal-contenu p {
  margin: 0 0 12px;
  font-size: 0.92rem;
}

.modal-fermer {
  position: absolute;
  top: 18px;
  right: 20px;
  background: none;
  border: none;
  font-size: 1.4rem;
  line-height: 1;
  color: var(--couleur-texte-doux);
  cursor: pointer;
}

.modal-fermer:hover { color: var(--couleur-marque); }

/* =====================================================================
   10. ÉTATS : CHARGEMENT / ERREUR / VIDE
   ===================================================================== */
.message-etat {
  text-align: center;
  padding: 60px 20px;
  color: var(--couleur-texte-doux);
  font-size: 0.95rem;
}

.message-etat.erreur { color: var(--couleur-marque); }

.message-etat code {
  background: #f0e2e6;
  padding: 2px 8px;
  border-radius: 6px;
  font-size: 0.85em;
}

.message-etat .detail-technique {
  display: block;
  margin-top: 18px;
  font-size: 0.78rem;
  color: var(--couleur-texte-doux);
}

/* Petit indicateur de chargement */
.spinner {
  width: 34px;
  height: 34px;
  margin: 0 auto 18px;
  border: 3px solid #eadfe2;
  border-top-color: var(--couleur-marque);
  border-radius: 50%;
  animation: rotation 0.9s linear infinite;
}

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

/* =====================================================================
   11. FOOTER — fond poudré, 3 colonnes, bande inférieure
   ===================================================================== */
.site-footer {
  /* Dégradé rosé (valeurs de repli — reprises par LBC.appliquerParametresGlobaux()
     depuis Parametres_des_contenus.csv, page=global, sections
     couleur_footer_debut / couleur_footer_fin, si renseignées). */
  background: linear-gradient(180deg, #F4D5D8 0%, #FBF0F1 100%);
  margin-top: 40px;
}

.footer-colonnes {
  max-width: 1200px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 20px;
  padding: 34px 24px 26px;
  text-align: center;
}

.footer-colonne {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}

.footer-colonne-liens { gap: 4px; }
.footer-colonne-liens a { margin-top: 2px; }

.footer-icone {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: var(--couleur-marque);
  color: #fff;
}

.footer-icone svg { width: 17px; height: 17px; }

.footer-colonne h3 {
  margin: 2px 0 0;
  font-size: 0.86rem;
  font-weight: 600;
  color: var(--couleur-texte);
}

.footer-colonne a,
.footer-colonne p {
  margin: 0;
  font-size: 0.8rem;
  color: var(--couleur-texte-doux);
  text-decoration: none;
  line-height: 1.4;
}

.footer-colonne a:hover { color: var(--couleur-marque); }

/* Bandeau distinct du reste du footer : même principe de dégradé que le
   header (--couleur-enseigne / --couleur-marque-clair) mais inversé — clair
   en haut (raccord avec les colonnes du footer), sombre en bas (symétrique
   du haut du header, pour "refermer" la page sur la même teinte). Valeurs de
   repli ci-dessous, reprises par LBC.appliquerParametresGlobaux() à partir
   des mêmes couleurs CSV que le header (couleur_header_debut / _fin). */
.footer-bas {
  background: linear-gradient(to bottom, var(--couleur-marque-clair) 0%, var(--couleur-enseigne) 100%);
  text-align: center;
  padding: 12px 20px;
}

.footer-bas p {
  margin: 0;
  font-size: 0.76rem;
  color: #ffffff;
  letter-spacing: 0.3px;
}

.footer-bas p + p { margin-top: 4px; }

/* Rempli en direct par LBC.appliquerParametresGlobaux() (page=global,
   section=footer_maj, colonne body_text de Parametres_des_contenus.csv) —
   reste vide et invisible tant que ce champ n'est pas renseigné. */
.footer-date-maj {
  color: rgba(255, 255, 255, 0.8);
  font-style: italic;
}

@media (max-width: 860px) {
  .footer-colonnes { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 640px) {
  .footer-colonnes {
    grid-template-columns: 1fr;
    gap: 22px;
    padding: 28px 24px 20px;
  }
}

/* =====================================================================
   12. GABARIT UNIVERSEL — CARTE CADEAU (format carte postale, ~600×380)
   Déclinable pour un soin spécifique (data-type="soin") ou un chèque
   cadeau à montant libre (data-type="montant").
   ===================================================================== */
.carte-cadeau {
  --carte-cadeau-largeur: 680px;
  --carte-cadeau-or: #C6952E;
  width: 100%;
  max-width: var(--carte-cadeau-largeur);
  margin: 0 auto;
  padding: 5px;
  /* Angles droits (pas d'arrondi) et pas d'ombre portée : la carte est
     découpée au massicot après impression (2026-08-26), un contour arrondi
     ou une ombre autour du bord n'aurait pas de sens sur le papier imprimé. */
  background: linear-gradient(135deg, var(--couleur-poudre), #ffffff 55%, var(--couleur-poudre));
}

.carte-cadeau-cadre {
  position: relative;
  display: grid;
  /* La colonne "paquet" n'est plus qu'un nom réservé dans les areas
     ci-dessous : le paquet cadeau (.carte-cadeau-paquet) est en
     position:absolute (cf. sa règle plus bas), donc rien n'occupe
     réellement cette 2e colonne — sa largeur ne sert qu'à empêcher un
     intitulé de soin long de passer sous l'image. 2.8fr 1fr (plutôt que
     1.3fr 1fr) laisse le texte utiliser l'espace resté vide à gauche de
     l'image, tout en gardant ~19px de marge avant celle-ci (vérifié sur
     l'intitulé le plus long rencontré à ce jour). */
  grid-template-columns: 2.8fr 1fr;
  grid-template-areas:
    "entete  paquet"
    "titre   paquet"
    "champs  paquet"
    "message message"
    "pied    pied";
  align-items: center;
  gap: 8px 22px;
  border: 1.5px solid var(--couleur-marque);
  padding: 18px 32px 12px;
  /* Fond ivoire (plus chaud qu'un blanc pur). Le fin liseré or à l'intérieur
     de la bordure est un ::before ci-dessous (vraie bordure, pas un
     box-shadow) — cf. commentaire sur .carte-cadeau-cadre::before. */
  background: #FAF6F0;
}

/* Liseré or à l'intérieur de la bordure bordeaux : code visuel du
   certificat-cadeau haut de gamme, façon dorure à chaud (cf. discussion
   2026-08-21). Anciennement un box-shadow inset double-couche, remplacé par
   une vraie bordure sur un ::before positionné en retrait — box-shadow
   (surtout empilé en plusieurs couches) est mal supporté par html2canvas
   (bibliothèque utilisée pour générer le PDF de la carte cadeau), ce qui
   pouvait décaler ou faire disparaître le liseré à l'export et le faire
   traverser le logo, le sceau ou la ligne du bas au lieu de les encadrer
   proprement. Une bordure réelle est rendue de façon fiable par html2canvas. */
.carte-cadeau-cadre::before {
  content: "";
  position: absolute;
  inset: 5px;
  border: 1px solid var(--carte-cadeau-or);
  pointer-events: none;
}

/* --- Zone haute gauche : logo décalé à gauche, avec un espace net avant
   l'enseigne (plus de centrage sur toute la largeur de la colonne — tout le
   bloc gauche, logo compris, s'aligne maintenant sur la même marge que le
   reste du texte en dessous). --- */
.carte-cadeau-entete {
  grid-area: entete;
  display: flex;
  align-items: center;
  gap: 14px;
  min-height: 60px;
}

.carte-cadeau-logo {
  flex: none;
  height: 68px;
  width: auto;
}

/* Centré sur sa propre largeur (celle de "La Beauté Cachée", le plus large
   des deux) plutôt que par rapport au logo à côté — cf. discussion
   2026-08-21. Pas de ligne dédiée dans Parametres_des_styles.csv : c'est un
   choix d'alignement/mise en page, pas une propriété de police (le CSV ne
   pilote que police/taille/couleur/graisse/style/espacement/majuscules,
   cf. card_header_enseigne / card_header_sub, déjà câblées et inchangées). */
.carte-cadeau-enseigne-bloc {
  text-align: center;
}

.carte-cadeau-enseigne {
  display: inline-block;
  position: relative;
  margin: 0;
  font-family: var(--police-titres);
  font-weight: 400;
  font-size: 30px;
  color: var(--couleur-marque);
  line-height: 1;
}

/* Même logique que .logo-texte::after dans le header (Sacramento réserve
   une "descente" bien plus grande que ce que les lettres dessinent
   réellement) : un ::after positionné en absolu, calé à distance fixe de
   l'encre du texte, plutôt qu'un border-bottom qui s'accrocherait au bas
   de la boîte de ligne gonflée. */
.carte-cadeau-enseigne::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 1px;
  height: 1.5px;
  background: var(--couleur-marque);
}

.carte-cadeau-baseline {
  margin: 3px 0 0;
  font-size: 14px;
  letter-spacing: 0.5px;
  font-style: italic;
  color: var(--couleur-texte-doux);
}

/* --- « Carte Cadeau » + montant / soin offert, sous le logo, alignés à
   gauche comme le reste de la colonne (un intitulé de soin long s'étale
   ainsi sur toute la largeur disponible au lieu d'être écrasé dans une
   étroite colonne de droite). --- */
.carte-cadeau-titre-bloc {
  grid-area: titre;
  text-align: left;
}

/* Sorti du flux de la grille (position absolue dans .carte-cadeau-cadre,
   position:relative) : en haut à droite de la carte, plutôt qu'empilé sous
   le logo avec la valeur (montant / soin) — cf. discussion 2026-08-21. */
.carte-cadeau-eyebrow {
  position: absolute;
  top: 24px;
  right: 34px;
  margin: 0;
  font-size: 16px;
  letter-spacing: 3px;
  text-transform: uppercase;
  color: var(--couleur-texte-doux);
}

.carte-cadeau-objet {
  margin: 0;
  font-family: var(--police-corps);
  font-style: italic;
  font-weight: 600;
  font-size: 20px;
  line-height: 1.3;
  color: var(--couleur-marque);
}

/* Libellé « Soin offert » (mode "soin" uniquement) : reprend le style
   discret de carte-cadeau-champ (Pour / De la part de) plutôt que celui,
   mis en valeur, de carte-cadeau-objet juste en dessous. */
.carte-cadeau-soin-label {
  margin: 0 0 2px;
}

/* --- Zone médiane gauche : champs à personnaliser --- */
.carte-cadeau-champs {
  grid-area: champs;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.carte-cadeau-champ {
  margin: 0;
  display: flex;
  align-items: baseline;
  gap: 6px;
  font-size: 14px;
  color: var(--couleur-texte);
  white-space: nowrap;
}

.carte-cadeau-pointilles {
  display: inline-block;
  flex: 1 1 auto;
  min-width: 90px;
  border-bottom: 1px dotted var(--couleur-bordure);
}

/* "Pour :" / "De la part de :" — vraies saisies (remplacent les pointillés
   décoratifs), même police que le libellé, juste soulignées en pointillé
   pour garder l'esprit "à remplir" de la carte. */
.carte-cadeau-champ-saisie {
  flex: 1 1 auto;
  min-width: 90px;
  border: none;
  border-bottom: 1px dotted var(--couleur-bordure);
  background: transparent;
  padding: 0 0 2px;
  font-family: inherit;
  font-size: inherit;
  color: var(--couleur-texte);
}
.carte-cadeau-champ-saisie::placeholder { color: var(--couleur-texte-doux); }
.carte-cadeau-champ-saisie:focus-visible {
  outline: none;
  border-bottom-style: solid;
  border-bottom-color: var(--couleur-marque);
}

/* --- Message personnalisé (3-4 lignes) que le client peut saisir pour
   accompagner son cadeau. Le libellé réutilise le style de "Pour :" / "De
   la part de :" (carte-cadeau-champ) plutôt qu'une nouvelle clé CSV, les
   deux étant visuellement identiques. Ce champ n'est pour l'instant qu'un
   aperçu sur la carte (comme le code ou la date de validité) : sa valeur
   n'est pas encore transmise à la réservation/au paiement. --- */
.carte-cadeau-message {
  grid-area: message;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.carte-cadeau-message-label { margin: 0; }

.carte-cadeau-message-zone {
  width: 100%;
  /* Hauteur fixe (pas min-height) + overflow masqué : un message de
     plusieurs lignes ne doit jamais agrandir la carte au-delà de sa taille
     imprimée prévue — cf. retour utilisateur 2026-08-26 après un test
     d'impression avec un message très long. Au moins 4 lignes visibles
     (retour du 2026-08-26 : 2 lignes étaient trop court), interligne
     resserré à 1.15 pour limiter la hauteur nécessaire. Valeur mesurée
     empiriquement, pas calculée depuis les métriques théoriques de la
     police (ça avait surestimé la hauteur réelle nécessaire la 1ère fois) —
     ne pas recalculer sans re-tester visuellement. */
  height: 161px;
  overflow: hidden;
  line-height: 1.15;
  padding: 8px 10px;
  border: 1px dashed var(--couleur-bordure);
  border-radius: 10px;
  /* Même ivoire que le fond de la carte (#FAF6F0) plutôt que blanc pur : la
     zone message se fondait dans la carte comme un post-it plaqué dessus. */
  background: #FAF6F0;
  font-family: var(--police-corps);
  font-size: 0.82rem;
  color: var(--couleur-texte);
}

.carte-cadeau-message-zone::placeholder { color: var(--couleur-texte-doux); }

.carte-cadeau-message-zone:focus-visible {
  outline: none;
  border-color: var(--couleur-marque);
}

/* --- Paquet cadeau (images/cadeau2.png) : sorti de la grille, en position
   absolue (comme carte-cadeau-eyebrow, cf. plus haut) plutôt que centré sur
   toute la hauteur entête+titre+champs — placé près du bord droit et centré
   verticalement entre le bas de l'intitulé « Carte Cadeau » et le haut de
   la zone Message (cf. discussion 2026-08-21). Repasse en position normale,
   centrée, dans la disposition mobile empilée sur une colonne (cf. media
   query plus bas) : la position absolue n'a de sens que dans la grille à
   deux colonnes. --- */
.carte-cadeau-paquet {
  /* Pas de grid-area ici (contrairement à la version mobile ci-dessous) :
     pour un item de grille en position:absolute, la zone de grille elle-même
     sert de bloc englobant (donc right/top se recalculeraient par rapport à
     la cellule "paquet", décalée par le padding de .carte-cadeau-cadre) —
     en le retirant de la grille, right/top se calculent directement depuis
     le cadre, comme pour carte-cadeau-eyebrow juste au-dessus. */
  position: absolute;
  top: 76px;
  right: 18px;
}

.carte-cadeau-paquet-image {
  width: 100%;
  max-width: 170px;
  height: auto;
  object-fit: contain;
}

/* --- Zone basse : horaires, code d'authentification, validité, coordonnées --- */
.carte-cadeau-pied {
  grid-area: pied;
  border-top: 1px dashed var(--couleur-bordure);
  padding-top: 6px;
  text-align: center;
}

.carte-cadeau-pied-ligne {
  margin: 0 0 2px;
  font-size: 0.8rem;
  line-height: 1.25;
  color: var(--couleur-texte);
}

.carte-cadeau-pied-ligne strong { color: var(--couleur-marque); font-size: 13px; letter-spacing: 0.5px; }

/* Séparateur discret entre date de validité et code, réunis sur une même
   ligne (2026-08-26, pour gagner une ligne de hauteur). */
.carte-cadeau-pied-separateur { margin: 0 6px; color: var(--couleur-texte-doux); }

.carte-cadeau-code strong {
  color: var(--couleur-marque);
  letter-spacing: 0.5px;
}

.carte-cadeau-contact {
  margin: 2px 0 0;
  font-size: 0.7rem;
  line-height: 1.25;
  color: var(--couleur-texte-doux);
}

/* Petit sceau "LBC" en coin, façon cachet de cire — une signature discrète
   plutôt qu'une décoration qui recouvre la carte (cf. discussion
   2026-08-21). Positionné hors du flux, sur le coin bas-droit du cadre.
   right/bottom élargis de 12/10px à 18/16px (2026-08-26) : le sceau étant
   un cercle, son point le plus bas/droit est plus proche du liseré or
   (inset 5px) que ne le suggère la boîte englobante carrée, et la
   compression JPEG de l'export PDF rapprochait encore visuellement les deux
   traits dorés au point de sembler se toucher sur la carte imprimée. */
.carte-cadeau-sceau {
  position: absolute;
  right: 18px;
  bottom: 16px;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  border: 1px solid var(--carte-cadeau-or);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--police-corps);
  font-size: 0.56rem;
  font-weight: 600;
  letter-spacing: 1px;
  color: var(--carte-cadeau-or);
  pointer-events: none;
}

.grille-cartes-cadeaux {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 40px;
  padding: 20px 0 60px;
}

/* --- Sélecteur de montant épuré (saisie libre + suggestions) --- */
.selecteur-montant {
  max-width: 420px;
  margin: 0 auto 36px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
}

.montant-champ-principal {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}

.montant-champ-principal label {
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--couleur-texte);
}

.montant-saisie {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 20px;
  border: 1.5px solid var(--couleur-marque);
  border-radius: var(--rayon-pilule);
  background: #fff;
}

.montant-saisie input {
  width: 110px;
  border: none;
  outline: none;
  font-family: var(--police-corps);
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--couleur-marque);
  text-align: right;
  background: transparent;
}

.montant-saisie span {
  font-weight: 700;
  font-size: 1.15rem;
  color: var(--couleur-marque);
}

.montant-suggestions {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}

.montant-suggestions label {
  font-size: 0.76rem;
  color: var(--couleur-texte-doux);
}

.select-montant {
  width: 100%;
  max-width: 260px;
  padding: 9px 32px 9px 16px;
  border: 1px solid var(--couleur-bordure);
  border-radius: var(--rayon-pilule);
  background-color: #fff;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' fill='none' stroke='%239C0537' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  background-size: 11px 8px;
  font-family: var(--police-corps);
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--couleur-marque);
  text-align: center;
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
}

@media (max-width: 640px) {
  .carte-cadeau-cadre {
    grid-template-columns: 1fr;
    grid-template-areas:
      "entete"
      "titre"
      "paquet"
      "champs"
      "pied";
    padding: 26px 24px 18px;
    text-align: center;
  }
  .carte-cadeau-entete { justify-content: center; min-height: 0; padding-top: 42px; }
  .carte-cadeau-logo { left: 50%; top: 0; transform: translateX(-50%); height: 52px; }
  .carte-cadeau-enseigne { font-size: 1.7rem; }
  .carte-cadeau-eyebrow { top: 20px; right: 24px; }
  .carte-cadeau-champ { justify-content: center; white-space: normal; }
  .carte-cadeau-paquet { grid-area: paquet; position: static; display: flex; justify-content: center; }
  .carte-cadeau-paquet-image { max-width: 130px; }
}

/* =====================================================================
   13. RESPONSIVE GÉNÉRAL
   ===================================================================== */
@media (max-width: 640px) {
  .header-principal { padding: 12px 16px 10px; }
  /* Hauteur ajustée pour que le haut/bas du logo affleure le haut/bas du
     bloc "La Beauté Cachée / Institut de Beauté" à côté (mesuré : 55px
     aligne les deux, contre 50px qui laissait le logo visiblement plus
     court que le texte). */
  .logo-image { height: 55px; }
  .logo-texte { font-size: 24px; }
  .logo-sous-titre { font-size: 10px; letter-spacing: 1.5px; }
  /* !important nécessaire : ces 2 tailles sont normalement pilotées par
     Parametres_des_styles.csv via un style inline (LBC.appliquerStyleElement),
     qui l'emporte toujours sur une règle CSS classique quelle que soit sa
     spécificité — voir la note équivalente sur .btn-reserver dans
     contact.html. Ici on veut délibérément ajuster uniquement l'affichage
     mobile sans toucher à la valeur CSV (identique sur desktop, 22px/28px).
     Texte principal légèrement réduit pour laisser plus de place à la
     signature cursive, remontée à 24px : les deux tiennent sur une ligne
     chacune dès 320px de large (vérifié par mesure de largeur réelle du
     texte, avec marge). */
  .baseline { font-size: 20px !important; }
  .baseline .baseline-signature { font-size: 24px !important; }
  .groupe .titre-script { font-size: 2.2rem; }
  main { padding: 0 16px 60px; }
  .barre-onglets .onglets { padding: 12px 16px; gap: 8px; }
  .onglet { font-size: 0.76rem; padding: 8px 16px; }
}

@media (max-width: 420px) {
  .champs-grille,
  .paiement-grille { grid-template-columns: 1fr; }
}
