/* =========================================================================
   Vauban Vitrine — Composants partagés
   Blocs réutilisés sur plusieurs pages, chargés sur toutes les pages vitrine.
   Sommaire :
     1. Carte de hero (.vauban-hero-card)
     2. Bandeau d'appel à l'action (.vauban-offer-cta)
   ========================================================================= */

/* ---------- 1. Carte de hero ----------
   Le bloc qui chevauche l'image d'en-tête de chaque page. Apparence unique ;
   chaque page ne gère plus que son positionnement (largeur, décalage, padding). */
.vauban-hero-card {
  background: var(--vb-hero-card-bg);
  border: 1px solid var(--vb-hero-card-border);
  border-radius: var(--vb-hero-card-radius);
  box-shadow: var(--vb-hero-card-shadow);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}

/* ---------- Sous-titres en pilule indigo douce (style /tarifs/) ----------
   Une seule règle transforme tous les eyebrows des 5 pages en badge arrondi.
   La couleur du texte vient de --vb-eyebrow (indigo) posée par chaque page. */
.vauban-hero__eyebrow,
.vauban-section-head__eyebrow,
.vauban-home-hero__eyebrow,
.vauban-benefits__eyebrow,
.vauban-contact-commitments__eyebrow,
.vauban-engagements__eyebrow,
.vauban-testimonials__eyebrow,
.about-story__eyebrow,
.contact-hero__eyebrow,
.vauban-contact-actions__eyebrow,
.vauban-offer-hero__label,
.service-zigzag__eyebrow,
.owner-cta-mobile__eyebrow,
.vauban-faq-hero__label,
.vauban-offer-cta__eyebrow {
  display: inline-flex;
  align-items: center;
  padding: 6px 13px;
  border-radius: 999px;
  background: var(--vb-accent-soft);
  border: 1px solid rgba(79, 70, 229, 0.18);
}

/* ---------- Micro-interactions UX (mutualisées sur toutes les pages) ----------
   Survol des cartes (légère élévation) + zoom doux des images de contenu. */
.vauban-benefits__card,
.vauban-engagements__card,
.about-story__highlight,
.vauban-testimonials__card {
  transition: transform var(--vb-transition) var(--vb-ease), box-shadow var(--vb-transition) var(--vb-ease);
}

.vauban-benefits__card:hover,
.vauban-engagements__card:hover,
.about-story__highlight:hover,
.vauban-testimonials__card:hover {
  transform: translateY(-4px);
  box-shadow: var(--vb-card-shadow-hover);
}

.about-story__portrait img,
.about-extra__team-media img {
  transition: transform 0.6s var(--vb-ease);
}

.about-story__portrait:hover img,
.about-extra__team-media:hover img {
  transform: scale(1.04);
}

@media (prefers-reduced-motion: reduce) {
  .vauban-benefits__card,
  .vauban-engagements__card,
  .about-story__highlight,
  .vauban-testimonials__card,
  .vauban-hero__stat,
  .about-story__portrait img,
  .about-extra__team-media img {
    transition: none;
    transform: none;
  }
}

/* ---------- 2. Bandeau d'appel à l'action ---------- */
@keyframes vbn-float {
  0%, 100% { transform: translateY(0); }
  50%       { transform: translateY(-7px); }
}

.vauban-offer-cta {
  width: 100%;
  padding: 24px 8px;
  background: var(--vb-bg);
  font-family: var(--vb-font-sans);
}

.vauban-offer-cta__inner {
  position: relative;
  width: min(100%, 1240px);
  margin: 0 auto;
  min-height: 360px;
  padding: 28px;
  border-radius: var(--vb-card-radius);
  overflow: hidden;
  background-image: url("https://www.conciergerie-vauban.fr/wp-content/uploads/2025/09/conciergerie-Croix.jpeg");
  background-size: cover;
  background-position: center center;
  background-repeat: no-repeat;
  display: flex;
  align-items: center;
  justify-content: center;
}

.vauban-offer-cta__overlay {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(36, 30, 25, 0.18) 0%, rgba(36, 30, 25, 0.32) 100%);
}

.vauban-offer-cta__panel {
  position: relative;
  z-index: 2;
  width: min(100%, 760px);
  padding: clamp(26px, 3vw, 34px);
  text-align: center;
  border: 1px solid rgba(36, 30, 55, 0.08);
  border-radius: var(--vb-card-radius);
  background: linear-gradient(155deg, rgba(252, 250, 255, 0.95) 0%, rgba(237, 233, 248, 0.90) 100%);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  box-shadow: 0 18px 48px rgba(33, 26, 48, 0.14);
}

.vauban-offer-cta__eyebrow {
  margin: 0 0 10px;
  font-family: var(--vb-font-sans);
  font-size: 0.7rem;
  line-height: 1;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--vb-eyebrow);
}

.vauban-offer-cta__panel h2 {
  margin: 0 0 18px;
  font-family: var(--vb-font-serif);
  font-size: clamp(2rem, 1.35rem + 1.25vw, 3rem);
  line-height: 1.08;
  color: var(--vb-heading);
  font-weight: 700;
}

.vauban-offer-cta__panel h2 span {
  color: var(--vb-primary);
}

.vauban-offer-cta__panel p {
  margin: 0 0 16px;
  font-size: 1rem;
  line-height: 1.8;
  color: #4f5568;
}

.vauban-offer-cta__panel p:last-of-type {
  margin-bottom: 24px;
}

.vauban-offer-cta__button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 50px;
  padding: 14px 24px;
  border-radius: 999px;
  background: var(--vb-primary-gradient);
  color: #ffffff;
  text-decoration: none;
  font-size: 0.95rem;
  line-height: 1.4;
  font-weight: 700;
  box-shadow: 0 12px 28px rgba(91, 33, 182, 0.24);
  animation: vbn-float 3.2s ease-in-out infinite;
  transition: background var(--vb-transition) var(--vb-ease), color var(--vb-transition) var(--vb-ease), box-shadow var(--vb-transition) var(--vb-ease);
}

.vauban-offer-cta__button:hover,
.vauban-offer-cta__button:focus,
.vauban-offer-cta__button:active,
.vauban-offer-cta__button:visited {
  background: var(--vb-primary-gradient-hover);
  color: #ffffff !important;
  animation-play-state: paused;
  transform: translateY(-3px);
  box-shadow: 0 16px 32px rgba(76, 29, 149, 0.28);
  text-decoration: none;
}

.vauban-offer-cta__button:focus-visible {
  outline: 3px solid rgba(255, 255, 255, 0.9);
  outline-offset: 3px;
}

@media (max-width: 991px) {
  .vauban-offer-cta {
    padding: 14px 8px;
  }

  .vauban-offer-cta__inner {
    min-height: 240px;
    padding: 18px;
    border-radius: var(--vb-card-radius);
    align-items: flex-end;
  }

  .vauban-offer-cta__panel {
    width: min(100%, 860px);
    padding: 20px 18px 16px;
    border-radius: 18px;
  }

  .vauban-offer-cta__panel p {
    font-size: 0.95rem;
    line-height: 1.72;
  }

  .vauban-offer-cta__button {
    width: 100%;
    max-width: 420px;
  }
}

@media (max-width: 640px) {
  .vauban-offer-cta {
    padding: 10px 6px;
  }

  .vauban-offer-cta__inner {
    min-height: 180px;
    padding: 10px;
    border-radius: 16px;
    background-position: center center;
  }

  .vauban-offer-cta__panel {
    width: 100%;
    padding: 14px 12px 12px;
    border-radius: 14px;
  }

  .vauban-offer-cta__eyebrow {
    font-size: 0.64rem;
    margin-bottom: 6px;
  }

  .vauban-offer-cta__panel h2 {
    margin-bottom: 10px;
    font-size: 1.35rem;
    line-height: 1.15;
  }

  .vauban-offer-cta__panel p {
    margin-bottom: 8px;
    font-size: 0.88rem;
    line-height: 1.55;
  }

  .vauban-offer-cta__panel p:last-of-type {
    margin-bottom: 12px;
  }

  .vauban-offer-cta__button {
    width: 100%;
    min-height: 42px;
    padding: 10px 14px;
    font-size: 0.88rem;
    line-height: 1.35;
  }
}

@media (prefers-reduced-motion: reduce) {
  .vauban-offer-cta__button {
    animation: none;
    transition: none;
    transform: none;
  }
}

/* =========================================================================
   3. Hero hybride (refonte UX 2026) — partagé par les 5 pages
   Titre éditorial à gauche + photo cadrée à droite, sur fond clair avec un
   halo dégradé discret. Remplace l'ancien hero « image pleine largeur + carte
   qui chevauche » : plus épuré, plus moderne, moins « gros bloc ».
   ========================================================================= */
.vauban-hero {
  position: relative;
  width: 100%;
  font-family: var(--vb-font-sans);
  color: var(--vb-text);
  overflow: hidden;
}

.vauban-hero::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--vb-glow);
  pointer-events: none;
}

/* Quand Astra active le header transparent sur une page (classe posée par Astra
   sur <body>), le header flotte au-dessus du contenu : compenser sa hauteur pour
   que le texte du hero n'apparaisse pas sous le header. */
body.ast-transparent-header .vauban-hero {
  padding-top: var(--vb-header-h, 90px);
}

/* Pages à route virtuelle (hub « zones desservies », pages-villes, guides) :
   rendues via get_header()/get_footer() avec le template « page builder » d'Astra
   (aucun conteneur de contenu) et SANS la classe ast-transparent-header → le header
   fixe (HFB) recouvre le hero à TOUTES les tailles. On compense donc la hauteur du
   header (--vb-header-h, mesurée dynamiquement par vitrine-animations.js ; repli
   100 px) en desktop ET en mobile. */
.vauban-vitrine--ville .vauban-hero,
.vauban-vitrine--guides .vauban-hero {
  padding-top: var(--vb-header-h, 100px);
}

/* Dégagement sous le header Astra (position: fixed) en DESKTOP uniquement.
   accueil, faq, contact et qui-sommes-nous dépendaient auparavant du padding
   parasite d'Astra (.ast-article-single + réglage par page de .site-content),
   désormais neutralisé à la source (vitrine-base.css) : sans dégagement explicite,
   leur hero passait sous le header fixe. On porte ce dégagement via le token unique
   --vb-header-h, par-dessus l'air esthétique propre à chaque hero (.__inner).
   IMPORTANT — desktop seulement (>= 922 px) : en mobile/tablette le header du site
   est .vbm-header, STICKY et dans le flux (pas le header fixe Astra), donc le contenu
   se place naturellement dessous — y ajouter ce dégagement créerait une bande vide.
   offre et simulateur ne sont pas listés : ils réservent déjà la hauteur du header
   dans leur __inner (cf. bloc ci-dessous / simulateur.css). */
@media (min-width: 922px) {
  .vauban-vitrine--accueil .vauban-hero,
  .vauban-vitrine--faq .vauban-hero,
  .vauban-vitrine--contact .vauban-hero,
  .vauban-vitrine--qui-sommes-nous .vauban-hero {
    padding-top: var(--vb-header-h, 90px);
  }
}

.vauban-hero__inner {
  position: relative;
  z-index: 1;
  width: min(100%, var(--vb-maxw));
  margin: 0 auto;
  padding: clamp(8px, 1.3vw, 24px) 20px clamp(40px, 4.5vw, 64px);
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(28px, 4vw, 64px);
  align-items: center;
}

/* Page « offre » : son hero porte SON dégagement sous le header fixe dans le __inner
   (desktop). NB : cette page utilise le layout Astra par défaut (non-Elementor) ; un
   BOM parasite en tête du template fournissait autrefois ~24px de dégagement « par
   accident » (line-box) — le BOM a été retiré (offre-services.php), donc on porte ici
   la pleine hauteur de dégagement (≈ hauteur du header fixe ~71px + air). En mobile,
   cette valeur est surchargée par la règle harmonisée de vitrine-mobile-nav.css. */
.vauban-vitrine--offre .vauban-hero__inner {
  padding-top: clamp(72px, 7vw, 104px);
}

.vauban-hero__text {
  max-width: 40rem;
}

.vauban-hero__eyebrow,
.vauban-section-head__eyebrow {
  margin: 0 0 16px;
  font-family: var(--vb-font-sans);
  font-size: 0.72rem;
  line-height: 1;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--vb-eyebrow);
}

.vauban-hero__title {
  margin: 0 0 18px;
  font-family: var(--vb-font-serif);
  font-size: clamp(2.1rem, 1.5rem + 2vw, 3.4rem);
  line-height: 1.05;
  letter-spacing: -0.01em;
  color: var(--vb-heading);
  font-weight: 700;
}

.vauban-hero__title span {
  background: var(--vb-primary-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}

.vauban-hero__lead {
  margin: 0;
  max-width: 50ch;
  font-size: 1.05rem;
  line-height: 1.75;
  color: var(--vb-text-soft);
}

.vauban-hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 26px;
}

.vauban-hero__media {
  position: relative;
}

.vauban-vitrine .vauban-hero__media img {
  width: 100%;
  height: clamp(320px, 36vw, 460px);
  object-fit: cover;
  display: block;
  border-radius: var(--vb-radius-media, 22px);
  border: 1px solid var(--vb-line);
  box-shadow: var(--vb-card-shadow);
}

/* =========================================================================
   Hero MARKETING (accueil, offre, qui-sommes-nous, faq, contact) — desktop.
   Exclut le simulateur, qui a son propre hero (.vsp-hero / .vsp-hero__inner).
   Principe : l'image devient dominante (déborde à droite jusqu'au bord du
   viewport) et le texte se SUPERPOSE par-dessus son bord gauche — il n'est
   donc jamais écrasé par un partage de colonnes. Un dégradé derrière le texte
   garantit la lisibilité sur l'image.
   ========================================================================= */
@media (min-width: 901px) {
  .vauban-vitrine:not(.vauban-vitrine--simulateur) .vauban-hero__inner {
    grid-template-columns: [text-start] minmax(0, 46rem) [text-end] minmax(0, 1fr) [end];
    gap: 0;
    /* Texte aligné en HAUT (pas centré) : sur les pages au titre court, le texte
       « tombait » au milieu d'une grande rangée (l'image + son margin-top la
       rendent haute) → énorme vide header↔texte. En top-align, le texte colle au
       header sur toutes les pages ; l'image reste décalée plus bas (son margin-top). */
    align-items: start;
    /* Plus d'air entre le bord gauche de l'écran et le texte. */
    width: min(100%, 1800px);
    padding-left: clamp(56px, 5.5vw, 110px);
  }

  .vauban-vitrine:not(.vauban-vitrine--simulateur) .vauban-hero__text {
    grid-row: 1;
    grid-column: text-start / text-end;
    position: relative;
    z-index: 2;
    max-width: 46rem;
  }

  /* Halo derrière le texte : dégradé blanc → transparent (lisibilité) +
     backdrop-filter pour flouter légèrement l'image sous-jacente. Le flou
     s'arrête progressivement vers la droite grâce au dégradé d'opacité. */
  .vauban-vitrine:not(.vauban-vitrine--simulateur) .vauban-hero__text::before {
    content: "";
    position: absolute;
    inset: -26px -140px -34px -56px;
    z-index: -1;
    background: radial-gradient(
      ellipse 68% 80% at 38% 50%,
      var(--vb-bg) 0%,
      var(--vb-bg) 18%,
      rgba(246, 247, 251, 0.52) 48%,
      rgba(246, 247, 251, 0) 76%
    );
    backdrop-filter: blur(7px);
    -webkit-backdrop-filter: blur(7px);
    pointer-events: none;
  }

  /* Image dans la colonne de droite (largeur maîtrisée, moins large qu'avant),
     qui déborde un peu vers la gauche sous le bord droit du texte. Marge de
     protection à droite de l'écran + léger décalage vers le bas. */
  .vauban-vitrine:not(.vauban-vitrine--simulateur) .vauban-hero__media {
    grid-row: 1;
    grid-column: text-end / end;
    margin-left: clamp(-90px, -5.5vw, -50px);
    /* Pas de marge négative en vw à droite (incluait la scrollbar → débordement
       hors écran) : l'image s'arrête au bord du conteneur, toujours dans l'écran. */
    margin-right: 0;
    margin-top: clamp(60px, 8vw, 132px);
    z-index: 1;
  }

  /* Rectangle (cover) ; le bord gauche se fond en CERCLE (mask radial) vers le
     fond → débordement doux et arrondi sous le texte, sans cadre rectangulaire
     ni coupure nette. Pas de bordure ni d'ombre (sinon cadre rectangulaire). */
  .vauban-vitrine:not(.vauban-vitrine--simulateur) .vauban-hero__media img {
    height: clamp(280px, 27vw, 400px);
    object-fit: cover;
    border-radius: var(--vb-radius-media, 22px);
    border: none;
    box-shadow: none;
    -webkit-mask-image: radial-gradient(150% 120% at 78% 50%, #000 52%, rgba(0, 0, 0, 0.4) 72%, transparent 88%);
            mask-image: radial-gradient(150% 120% at 78% 50%, #000 52%, rgba(0, 0, 0, 0.4) 72%, transparent 88%);
  }
}

/* Bande de preuves sous le hero : trois cartes claires (même langage que les
   cartes bénéfices), le KPI chiffré accentué au gradient de marque. */
.vauban-hero__strip {
  position: relative;
  z-index: 1;
  width: min(100%, var(--vb-maxw));
  margin: 0 auto;
  padding: 0 20px clamp(36px, 4.4vw, 60px);
}

.vauban-hero__strip-inner {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(14px, 1.6vw, 20px);
}

.vauban-hero__stat {
  position: relative;
  padding: clamp(22px, 2.2vw, 30px) clamp(22px, 2.2vw, 28px);
  background: var(--vb-card-bg);
  border: 1px solid var(--vb-card-border);
  border-radius: var(--vb-card-radius);
  box-shadow: var(--vb-card-shadow);
  transition: transform var(--vb-transition) var(--vb-ease), box-shadow var(--vb-transition) var(--vb-ease);
}

.vauban-hero__stat:hover {
  transform: translateY(-4px);
  box-shadow: var(--vb-card-shadow-hover);
}

.vauban-hero__stat strong {
  display: block;
  margin-bottom: 8px;
  font-family: var(--vb-font-serif);
  font-size: clamp(1.35rem, 1rem + 0.9vw, 1.7rem);
  line-height: 1.1;
  letter-spacing: -0.01em;
  color: var(--vb-heading);
  font-weight: 700;
}

/* Premier élément = le chiffre clé : accentué au gradient pour servir de hook. */
.vauban-hero__stat:first-child strong {
  background: var(--vb-primary-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}

.vauban-hero__stat span {
  display: block;
  font-size: 0.92rem;
  line-height: 1.6;
  color: var(--vb-text-soft);
}

@media (max-width: 900px) {
  .vauban-hero__inner {
    grid-template-columns: 1fr;
    gap: 26px;
  }

  /* Le header HFB est en position: fixed (~100px en mobile) et flotte au-dessus
     du contenu. Sur les pages internes le hero démarre plus haut que l'accueil
     (moins de marge dans le flux) → eyebrow et titre passaient sous le header.
     On rétablit un dégagement aligné sur l'accueil sur toutes les pages. */
  .vauban-vitrine--offre .vauban-hero__inner,
  .vauban-vitrine--qui-sommes-nous .vauban-hero__inner {
    padding-top: 88px;
  }

  .vauban-vitrine .vauban-hero__media img {
    height: clamp(260px, 56vw, 380px);
  }

  .vauban-hero__strip-inner {
    grid-template-columns: 1fr;
    gap: 14px;
  }
}

/* L'accueil est correct en portrait (≤600px : padding 56px → eyebrow à 113px).
   En 601–900px (paysage / petite tablette) le padding tombe à ~10px → eyebrow
   à ~67px, sous le header fixe (~100px). Plage ciblée précisément pour ne pas
   toucher le portrait ni le desktop. */
@media (min-width: 601px) and (max-width: 900px) {
  .vauban-vitrine--accueil .vauban-hero__inner {
    padding-top: 88px;
  }
}

@media (max-width: 600px) {
  .vauban-hero__inner {
    padding: 56px 20px 40px;
    gap: 32px;
  }

  /* Titre du hero allégé sur petit écran (moins « trop grand »). */
  .vauban-hero__title {
    font-size: clamp(1.75rem, 1.2rem + 2vw, 2.2rem);
    line-height: 1.1;
    margin-bottom: 16px;
  }

  .vauban-hero__strip {
    padding-left: 20px;
    padding-right: 20px;
  }

  .vauban-hero__strip-inner {
    gap: 16px;
  }

  .vauban-hero__lead {
    font-size: 0.98rem;
  }

  .vauban-hero__actions {
    gap: 10px;
    margin-top: 30px;
  }

  .vauban-hero__actions .vauban-btn {
    width: 100%;
  }
}

/* =========================================================================
   4. Boutons partagés (.vauban-btn) — refonte UX 2026
   Un seul système de boutons : plein (dégradé de marque) ou fantôme (contour
   fin). Réutilisable sur toutes les pages.
   ========================================================================= */
.vauban-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding: 13px 24px;
  border-radius: 999px;
  font-family: var(--vb-font-sans);
  font-size: 0.95rem;
  line-height: 1.2;
  font-weight: 700;
  text-decoration: none;
  cursor: pointer;
  border: 1px solid transparent;
  transition: background var(--vb-transition) var(--vb-ease),
              color var(--vb-transition) var(--vb-ease),
              border-color var(--vb-transition) var(--vb-ease),
              transform var(--vb-transition) var(--vb-ease),
              box-shadow var(--vb-transition) var(--vb-ease);
}

.vauban-btn--primary {
  background: var(--vb-primary-gradient);
  color: #ffffff;
  box-shadow: 0 12px 26px rgba(91, 33, 182, 0.20);
}

.vauban-btn--primary:hover,
.vauban-btn--primary:focus,
.vauban-btn--primary:active,
.vauban-btn--primary:visited {
  background: var(--vb-primary-gradient-hover);
  color: #ffffff;
  text-decoration: none;
  transform: translateY(-2px);
  box-shadow: 0 16px 30px rgba(76, 29, 149, 0.26);
}

.vauban-btn--ghost {
  background: #ffffff;
  color: var(--vb-heading);
  border-color: var(--vb-line);
}

.vauban-btn--ghost:hover,
.vauban-btn--ghost:focus {
  background: var(--vb-accent-soft);
  color: var(--vb-primary-strong);
  text-decoration: none;
  border-color: rgba(79, 70, 229, 0.30);
  transform: translateY(-2px);
}

.vauban-btn:focus-visible {
  outline: 3px solid rgba(79, 70, 229, 0.35);
  outline-offset: 3px;
}

/* Spécificité renforcée (0,2,0) : neutralise les surcharges thème / Elementor
   sur les <a> stylisés en bouton — couvre tous les états de lien.
   Le !important couvre les thèmes qui appliquent text-decoration sur a:hover
   avec une spécificité contextuelle supérieure (ex. .entry-content a:hover). */
.vauban-vitrine .vauban-btn,
.vauban-vitrine .vauban-btn:hover,
.vauban-vitrine .vauban-btn:focus,
.vauban-vitrine .vauban-btn:visited,
.vauban-vitrine .vauban-btn:active {
  text-decoration: none !important;
}

/* Liens imbriqués à l'intérieur d'un bouton (.vauban-btn > a) */
.vauban-btn a,
.vauban-btn a:hover,
.vauban-btn a:focus,
.vauban-btn a:visited,
.vauban-btn a:active {
  text-decoration: none !important;
}

/* =========================================================================
   5. En-tête de section partagé (.vauban-section-head)
   Eyebrow pilule + titre serif + chapô. Centré par défaut, variante --left.
   Mutualise la présentation des titres de section sur toutes les pages.
   ========================================================================= */
.vauban-section-head {
  width: min(100%, 760px);
  margin: 0 auto clamp(28px, 3.4vw, 48px);
  text-align: center;
}

.vauban-section-head--left {
  margin-left: 0;
  margin-right: 0;
  text-align: left;
}

.vauban-section-head__title {
  margin: 0 0 12px;
  font-family: var(--vb-font-serif);
  font-size: clamp(1.8rem, 1.3rem + 1.4vw, 2.7rem);
  line-height: 1.12;
  letter-spacing: -0.01em;
  color: var(--vb-heading);
  font-weight: 700;
}

.vauban-section-head__title span {
  color: var(--vb-primary);
}

.vauban-section-head__lead {
  margin: 0 auto;
  max-width: 62ch;
  font-size: 1rem;
  line-height: 1.75;
  color: var(--vb-text-soft);
}

.vauban-section-head--left .vauban-section-head__lead {
  margin-left: 0;
}

/* Mobile : titre de section moins imposant, davantage d'air sous le titre et
   avant le contenu — la page « respire » sans toucher au desktop. */
@media (max-width: 600px) {
  .vauban-section-head {
    margin-bottom: clamp(24px, 6vw, 34px);
  }

  .vauban-section-head__title {
    font-size: clamp(1.55rem, 1.1rem + 1.5vw, 2rem);
    line-height: 1.18;
  }

  .vauban-section-head__lead {
    font-size: 0.96rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  .vauban-btn,
  .vauban-hero__media img {
    transition: none;
    transform: none;
  }
}

/* ---------- Invite au scroll (.vauban-scroll-cue) ----------
   Pilule « Découvrir » + chevron, fixée en bas du viewport, partagée par toutes
   les pages vitrine. Clic = scroll doux de 75 % de la hauteur de l'écran (JS).
   Masquée dès le premier scroll / près du bas (JS). */
.vauban-scroll-cue,
.vauban-scroll-cue:visited,
.vauban-scroll-cue:hover,
.vauban-scroll-cue:focus,
.vauban-scroll-cue:active {
  position: fixed;
  bottom: 8px;
  left: 50%;
  transform: translateX(-50%);
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  padding: 8px 16px 7px;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.25);
  background: rgba(15, 23, 42, 0.62);
  color: #fff;
  cursor: pointer;
  text-decoration: none;
  outline: none;
  z-index: 9999;
}

.vauban-scroll-cue {
  opacity: 1;
  transition: opacity 0.5s ease;
}

/* Assombrissement du bas de l'écran (.vauban-scroll-shade) : voile dégradé
   sombre, pleine largeur, fixé au bord bas. Masqué par défaut ; le JS l'active
   (classe --on) en même temps que l'invite, quand on atteint le bas d'un bloc
   de contenu, pour signaler visuellement qu'il reste à scroller. Décoratif. */
.vauban-scroll-shade {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  height: 140px;
  background: linear-gradient(
    to top,
    rgba(15, 23, 42, 0.30) 0%,
    rgba(15, 23, 42, 0.12) 45%,
    rgba(15, 23, 42, 0) 100%
  );
  z-index: 9990;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.4s ease;
}

.vauban-scroll-shade--on {
  opacity: 1;
}

.vauban-scroll-cue__label {
  font-family: var(--vb-font-sans);
  font-size: 0.58rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  line-height: 1;
}

.vauban-scroll-cue__icon {
  display: block;
  width: 16px;
  height: 16px;
  animation: vauban-scroll-bounce 1.8s ease-in-out infinite;
}

.vauban-scroll-cue--hidden {
  opacity: 0;
  pointer-events: none;
}

@keyframes vauban-scroll-bounce {
  0%, 100% { transform: translateY(0); }
  50%       { transform: translateY(5px); }
}

@media (prefers-reduced-motion: reduce) {
  .vauban-scroll-cue__icon { animation: none; }
}

/* ---------- Interrupteur des sons d'interface (.vauban-sound-toggle) ----------
   Le bouton est rendu côté serveur (partial sound-toggle.php, attribut hidden
   natif) et reste MASQUÉ dans le DOM light : vitrine-feedback.js en clone les
   icônes dans le Shadow DOM du widget accessibilité Elementor (ea11y), où une
   carte « Audio » neuve est restylée et rendue visible. Si ea11y est absent
   (ex. dev local), le bouton reste simplement masqué — le son fonctionne quand
   même via le moteur. Le sélecteur [hidden] neutralise tout reset de thème
   type button{display:...} qui battrait la feuille UA. */
.vauban-sound-toggle,
.vauban-sound-toggle[hidden] {
  display: none !important;
}

/* =========================================================================
   6. Section « Vous gérez votre vie, on gère votre bien » (.vauban-effort)
   Comparaison « vous » (très peu) vs « Vauban » (tout le reste) : matérialise
   visuellement le « presque rien à faire » et désamorce la peur de l'effort.
   Partagée (accueil). Tokens uniquement, aucune couleur en dur.
   ========================================================================= */
.vauban-effort {
  width: 100%;
  padding: var(--vb-section-y) 20px;
}

.vauban-effort__inner {
  width: min(100%, var(--vb-maxw));
  margin: 0 auto;
}

.vauban-effort__grid {
  display: grid;
  grid-template-columns: minmax(0, 0.82fr) minmax(0, 1.18fr);
  gap: var(--vb-section-gap);
  align-items: stretch;
}

.vauban-effort__col {
  padding: clamp(24px, 2.6vw, 34px);
  background: var(--vb-card-bg);
  border: 1px solid var(--vb-card-border);
  border-radius: var(--vb-card-radius);
  box-shadow: var(--vb-card-shadow);
}

.vauban-effort__col--you {
  background: var(--vb-surface-tint);
}

.vauban-effort__role {
  display: inline-flex;
  align-items: center;
  margin: 0 0 18px;
  padding: 6px 13px;
  border-radius: 999px;
  background: var(--vb-accent-soft);
  font-family: var(--vb-font-sans);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--vb-eyebrow);
}

.vauban-effort__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 13px;
}

.vauban-effort__list li {
  position: relative;
  padding-left: 28px;
  font-size: 0.98rem;
  line-height: 1.6;
  color: var(--vb-text);
}

/* Coche dessinée en CSS pur (pas de hex, pas d'image). */
.vauban-effort__list li::before {
  content: "";
  position: absolute;
  left: 4px;
  top: 4px;
  width: 6px;
  height: 11px;
  border: solid var(--vb-primary);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

.vauban-effort__punch {
  margin: clamp(22px, 2.6vw, 32px) auto 0;
  max-width: 62ch;
  text-align: center;
  font-family: var(--vb-font-serif);
  font-size: clamp(1.1rem, 0.92rem + 0.6vw, 1.4rem);
  line-height: 1.4;
  color: var(--vb-heading);
}

.vauban-effort__punch strong {
  color: var(--vb-primary);
}

/* =========================================================================
   7. Section « Notre technologie » (.vauban-tech)
   Met en avant le moat réel : moteur de tarification maison, espace
   propriétaire, application équipe, portail voyageur. Justifie la valeur (et
   donc la commission). Partagée (accueil + offre). Tokens uniquement.
   ========================================================================= */
.vauban-tech {
  width: 100%;
  padding: var(--vb-section-y) 20px;
}

.vauban-tech__inner {
  width: min(100%, var(--vb-maxw));
  margin: 0 auto;
}

.vauban-tech__grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--vb-section-gap);
}

.vauban-tech__card {
  padding: clamp(24px, 2.4vw, 30px);
  background: var(--vb-card-bg);
  border: 1px solid var(--vb-card-border);
  border-radius: var(--vb-card-radius);
  box-shadow: var(--vb-card-shadow);
  transition: transform var(--vb-transition) var(--vb-ease), box-shadow var(--vb-transition) var(--vb-ease);
}

.vauban-tech__card:hover {
  transform: translateY(-4px);
  box-shadow: var(--vb-card-shadow-hover);
}

.vauban-tech__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 46px;
  height: 46px;
  margin-bottom: 16px;
  border-radius: 12px;
  background: var(--vb-surface-tint);
  color: var(--vb-primary);
}

.vauban-tech__icon svg {
  width: 24px;
  height: 24px;
}

.vauban-tech__card h3 {
  margin: 0 0 10px;
  font-family: var(--vb-font-sans);
  font-size: 1.05rem;
  line-height: 1.3;
  color: var(--vb-heading);
  font-weight: 700;
}

.vauban-tech__card p {
  margin: 0;
  font-size: 0.94rem;
  line-height: 1.65;
  color: var(--vb-text-soft);
}

.vauban-tech__note {
  margin: clamp(18px, 2vw, 26px) auto 0;
  max-width: 72ch;
  text-align: center;
  font-size: 0.9rem;
  line-height: 1.6;
  color: var(--vb-text-soft);
}

/* =========================================================================
   8. Bloc objection (.vauban-objection)
   Reformule frontalement une crainte (ex. « 24 %, c'est cher ») et y répond.
   Désamorce l'objection prix juste après l'annonce de la commission (offre).
   ========================================================================= */
.vauban-objection {
  width: 100%;
  padding: 0 20px var(--vb-section-y);
}

.vauban-objection__inner {
  width: min(100%, var(--vb-reading));
  margin: 0 auto;
  padding: clamp(24px, 3vw, 38px);
  border: 1px solid var(--vb-card-border);
  border-left: 3px solid var(--vb-primary);
  border-radius: var(--vb-card-radius);
  background: var(--vb-surface-tint);
}

.vauban-objection__q {
  margin: 0 0 12px;
  font-family: var(--vb-font-serif);
  font-size: clamp(1.2rem, 1rem + 0.7vw, 1.6rem);
  line-height: 1.3;
  color: var(--vb-heading);
}

.vauban-objection__a {
  margin: 0;
  font-size: 1rem;
  line-height: 1.8;
  color: var(--vb-text);
}

.vauban-objection__a strong {
  color: var(--vb-primary-strong);
}

@media (max-width: 980px) {
  .vauban-tech__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 760px) {
  .vauban-effort__grid {
    grid-template-columns: 1fr;
  }
}

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

@media (prefers-reduced-motion: reduce) {
  .vauban-tech__card {
    transition: none;
    transform: none;
  }
}

/* =========================================================================
   9. Page locale par commune (.vauban-local / .vauban-zones)
   Section « marché local » (contexte unique par ville) + maillage interne vers
   les autres communes. Réutilise la liste à coches .vauban-effort__list.
   Tokens uniquement, aucune couleur en dur.
   ========================================================================= */
.vauban-local {
  width: 100%;
  padding: var(--vb-section-y) 20px;
}

.vauban-local__inner {
  width: min(100%, var(--vb-maxw));
  margin: 0 auto;
}

.vauban-local__points {
  width: min(100%, var(--vb-reading));
  margin: clamp(20px, 2.4vw, 30px) 0 0;
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.vauban-local__note {
  margin: clamp(16px, 1.8vw, 22px) 0 0;
  max-width: 72ch;
  font-size: 0.9rem;
  line-height: 1.6;
  color: var(--vb-text-soft);
}

.vauban-zones {
  width: 100%;
  padding: var(--vb-section-y) 20px var(--vb-section-y);
}

.vauban-zones__inner {
  width: min(100%, var(--vb-maxw));
  margin: 0 auto;
}

/* ---------- Bulles « Zones desservies » (.vauban-zones__list) ----------
   Encore utilisées par les pages ville (ville.php) et guides (guides.php) pour
   le maillage interne. La page offre (Lille) et l'accueil utilisent désormais le
   carousel d'images .vauban-zc ci-dessous. */
.vauban-zones__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  justify-content: center;
}

.vauban-zones__list a {
  display: inline-flex;
  align-items: center;
  padding: 9px 16px;
  border-radius: 999px;
  background: var(--vb-card-bg);
  border: 1px solid var(--vb-card-border);
  box-shadow: var(--vb-card-shadow);
  color: var(--vb-heading);
  text-decoration: none;
  font-size: 0.92rem;
  font-weight: 600;
  transition: background var(--vb-transition) var(--vb-ease), color var(--vb-transition) var(--vb-ease), border-color var(--vb-transition) var(--vb-ease), transform var(--vb-transition) var(--vb-ease);
}

.vauban-zones__list a:hover,
.vauban-zones__list a:focus {
  background: var(--vb-accent-soft);
  color: var(--vb-primary-strong);
  border-color: var(--vb-primary);
  transform: translateY(-2px);
}

@media (prefers-reduced-motion: reduce) {
  .vauban-zones__list a {
    transition: none;
    transform: none;
  }
}

/* ---------- Carousel des communes (.vauban-zc) ----------
   Photos réelles libres de droits, défilement responsive (3 / 2 / 1 carte selon
   la largeur), navigation flèches + points, glisser tactile. Comportement :
   assets/js/ville-carousel.js. Namespace distinct du hub (.vauban-zones__card*). */
.vauban-zc {
  position: relative;
  margin-top: clamp(22px, 3vw, 34px);
}

.vauban-zc__viewport {
  overflow: hidden;
  cursor: grab;
  touch-action: pan-y;
  user-select: none;
  border-radius: var(--vb-card-radius);
}

.vauban-zc__viewport.is-dragging {
  cursor: grabbing;
}

.vauban-zc__track {
  display: flex;
  gap: var(--vb-section-gap);
  transition: transform 0.6s cubic-bezier(0.16, 1, 0.3, 1);
  will-change: transform;
}

.vauban-zc__card {
  flex: 0 0 calc((100% - 2 * var(--vb-section-gap)) / 3);
  min-width: calc((100% - 2 * var(--vb-section-gap)) / 3);
  display: flex;
  flex-direction: column;
  background: var(--vb-card-bg);
  border: 1px solid var(--vb-card-border);
  border-radius: var(--vb-card-radius);
  overflow: hidden;
  text-decoration: none;
  box-shadow: var(--vb-card-shadow);
  transition: transform var(--vb-transition) var(--vb-ease),
              box-shadow var(--vb-transition) var(--vb-ease);
}

.vauban-zc__card:hover,
.vauban-zc__card:focus-visible {
  transform: translateY(-4px);
  box-shadow: var(--vb-card-shadow-hover);
}

.vauban-zc__media {
  display: block;
  aspect-ratio: 3 / 2;
  overflow: hidden;
  background: var(--vb-surface-muted);
}

.vauban-zc__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 0.6s var(--vb-ease);
}

.vauban-zc__card:hover .vauban-zc__media img {
  transform: scale(1.05);
}

.vauban-zc__body {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 16px 18px 18px;
}

.vauban-zc__name {
  font-family: var(--vb-font-serif);
  font-size: 1.2rem;
  font-weight: 700;
  line-height: 1.2;
  color: var(--vb-heading);
}

.vauban-zc__caption {
  font-size: 0.85rem;
  line-height: 1.4;
  color: var(--vb-text-soft);
}

.vauban-zc__controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  margin-top: 22px;
}

.vauban-zc__nav {
  width: 36px;
  height: 36px;
  flex: 0 0 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid rgba(15, 23, 42, 0.14);
  border-radius: 999px;
  background: #ffffff;
  box-shadow: 0 1px 3px rgba(15, 23, 42, 0.07);
  cursor: pointer;
  transition: transform var(--vb-transition) var(--vb-ease),
              background var(--vb-transition) var(--vb-ease),
              border-color var(--vb-transition) var(--vb-ease),
              box-shadow var(--vb-transition) var(--vb-ease);
}

.vauban-zc__nav:hover,
.vauban-zc__nav:active,
.vauban-zc__nav.is-active {
  transform: translateY(-1px);
  background: var(--vb-primary-gradient);
  border-color: transparent;
  box-shadow: 0 6px 14px -6px rgba(79, 70, 229, 0.50);
}

.vauban-zc__nav:focus-visible {
  outline: 2px solid var(--vb-primary);
  outline-offset: 2px;
}

.vauban-zc__nav svg {
  width: 15px;
  height: 15px;
  display: block;
  overflow: visible;
}

.vauban-zc__nav svg path {
  stroke: #0f172a;
  transition: stroke var(--vb-transition) var(--vb-ease);
}

.vauban-zc__nav:hover svg path,
.vauban-zc__nav:active svg path,
.vauban-zc__nav.is-active svg path {
  stroke: #ffffff;
}

.vauban-zc__dots {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  padding: 8px 14px;
  border-radius: 999px;
  background: var(--vb-surface-tint);
  box-shadow: inset 0 0 0 1px var(--vb-line);
  min-width: 120px;
}

.vauban-zc__dot {
  width: 10px;
  height: 10px;
  padding: 0;
  border: none;
  border-radius: 999px;
  background: rgba(15, 23, 42, 0.28);
  cursor: pointer;
  transition: width 0.25s ease, background-color 0.25s ease, transform 0.2s ease;
}

.vauban-zc__dot:hover {
  background: var(--vb-primary-soft);
  transform: scale(1.18);
}

.vauban-zc__dot:focus-visible {
  outline: 2px solid var(--vb-primary);
  outline-offset: 2px;
}

.vauban-zc__dot.is-active {
  width: 30px;
  background: var(--vb-primary-gradient);
  transform: none;
}

.vauban-zc__credits {
  margin: 16px 0 0;
  text-align: center;
  font-size: 0.78rem;
  line-height: 1.5;
  color: var(--vb-text-soft);
  opacity: 0.85;
}

@media (max-width: 980px) {
  .vauban-zc__card {
    flex-basis: calc((100% - var(--vb-section-gap)) / 2);
    min-width: calc((100% - var(--vb-section-gap)) / 2);
  }
}

@media (max-width: 640px) {
  .vauban-zc__card {
    flex-basis: 100%;
    min-width: 100%;
  }
}

@media (max-width: 600px) {
  .vauban-local__points {
    grid-template-columns: 1fr;
  }
}

@media (prefers-reduced-motion: reduce) {
  .vauban-zc__track,
  .vauban-zc__nav,
  .vauban-zc__dot,
  .vauban-zc__media img {
    transition: none;
    transform: none;
  }
}

/* ---------- Hub « Zones desservies » : cartes-villes (.vauban-zones__cards) ---------- */
.vauban-zones__cards {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--vb-section-gap);
}

.vauban-zones__card {
  display: flex;
  flex-direction: column;
  padding: clamp(22px, 2.4vw, 28px);
  background: var(--vb-card-bg);
  border: 1px solid var(--vb-card-border);
  border-radius: var(--vb-card-radius);
  box-shadow: var(--vb-card-shadow);
  color: var(--vb-text);
  text-decoration: none;
  transition: transform var(--vb-transition) var(--vb-ease), box-shadow var(--vb-transition) var(--vb-ease);
}

.vauban-zones__card:hover,
.vauban-zones__card:focus {
  transform: translateY(-4px);
  box-shadow: var(--vb-card-shadow-hover);
}

.vauban-zones__card h3 {
  margin: 0 0 10px;
  font-family: var(--vb-font-serif);
  font-size: 1.25rem;
  line-height: 1.2;
  color: var(--vb-heading);
  font-weight: 700;
  text-decoration: none;
}

.vauban-zones__card p {
  margin: 0 0 16px;
  font-size: 0.92rem;
  line-height: 1.6;
  color: var(--vb-text-soft);
  text-decoration: none;
}

.vauban-zones__card-cta {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin-top: auto;
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--vb-primary);
}

.vauban-zones__card-cta svg {
  transition: transform var(--vb-transition) var(--vb-ease);
}

.vauban-zones__card:hover .vauban-zones__card-cta svg {
  transform: translateX(3px);
}

@media (max-width: 880px) {
  .vauban-zones__cards {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

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

/* ---------- Barre « Zones desservies » en pied de page (maillage sitewide) ----------
   Injectée par Vauban_Vitrine_Local_Pages sur les pages publiques (visiteurs non
   connectés). Tokens globaux (:root de vitrine-base.css, chargé sur tout le front). */
.vauban-zones-footer {
  width: 100%;
  padding: clamp(18px, 2.2vw, 26px) 20px;
  background: var(--vb-surface-muted);
  border-top: 1px solid var(--vb-line);
  font-family: var(--vb-font-sans);
  text-align: center;
}

.vauban-zones-footer__label {
  display: block;
  margin-bottom: 10px;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--vb-eyebrow);
}

.vauban-zones-footer__list {
  list-style: none;
  margin: 0 auto;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 8px 18px;
  justify-content: center;
  max-width: var(--vb-maxw);
}

.vauban-zones-footer__list a {
  color: var(--vb-text-soft);
  text-decoration: none;
  font-size: 0.9rem;
  transition: color var(--vb-transition) var(--vb-ease);
}

.vauban-zones-footer__list a:hover,
.vauban-zones-footer__list a:focus {
  color: var(--vb-primary-strong);
  text-decoration: underline;
}

@media (prefers-reduced-motion: reduce) {
  .vauban-zones__card,
  .vauban-zones__card-cta svg {
    transition: none;
    transform: none;
  }
}

/* ============================================================
   Transition page → onboarding (voile de navigation).
   Activé par JS (window.VaubanAnim.showPageTransition) avant
   toute redirection vers le formulaire d'onboarding.
   ============================================================ */
.vauban-page-transition {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: var(--vb-bg, #f6f7fb);
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.22s ease;
  pointer-events: none;
}

.vauban-page-transition.is-active {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}

.vauban-page-transition__spinner {
  width: 36px;
  height: 36px;
  border: 3px solid rgba(79, 70, 229, 0.15);
  border-top-color: var(--vb-primary, #4f46e5);
  border-radius: 50%;
  animation: vbn-page-spin 0.7s linear infinite;
}

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

@media (prefers-reduced-motion: reduce) {
  .vauban-page-transition { transition: none; }
  .vauban-page-transition__spinner { animation: none; }
}
