:root {
  --color-primary: #0f5f5c;
  --color-primary-strong: #0a4644;
  --color-primary-soft: #dff3ef;
  --color-accent: #f2a65a;
  --color-background: #f7f4ed;
  --color-surface: #ffffff;
  --color-surface-muted: #f1eee6;
  --color-text: #18312f;
  --color-text-muted: #667370;
  --color-border: #ddd7cb;
  --color-focus: #1a7f78;
  --font-base: "Poppins", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-heading: "Jost", "Poppins", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 2.5rem;
  --space-8: 3rem;
  --space-9: 4rem;
  --space-10: 5rem;
  --radius-md: 0.875rem;
  --radius-lg: 1.25rem;
  --radius-xl: 1.75rem;
  --radius-pill: 999px;
  --shadow-sm: 0 4px 14px rgba(24, 49, 47, 0.08);
  --shadow-md: 0 14px 36px rgba(24, 49, 47, 0.14);
  --container: 72rem;
  --header-height: 60px;
}

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

html {
  min-width: 320px;
  overflow-x: hidden;
  text-size-adjust: 100%;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  min-width: 320px;
  overflow-x: hidden;
  background: var(--color-background);
  color: var(--color-text);
  font-family: var(--font-base);
  font-size: 1rem;
  line-height: 1.6;
}

img, svg { max-width: 100%; height: auto; }
button, input, select, textarea { font: inherit; }
button { cursor: pointer; }
a { color: inherit; }

:focus-visible { outline: 3px solid var(--color-focus); outline-offset: 3px; }

.skip-link {
  position: fixed;
  top: var(--space-2);
  left: var(--space-2);
  z-index: 999;
  transform: translateY(-150%);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-pill);
  background: var(--color-primary);
  color: #ffffff;
  font-weight: 700;
}

.skip-link:focus { transform: translateY(0); }
.visually-hidden { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }

.container {
  width: min(100%, var(--container));
  margin-inline: auto;
  padding-inline: var(--space-5);
}

.container.narrow { width: min(100%, 48rem); }
.section, .page-hero { padding-block: var(--space-8); }
.section-soft { background: var(--color-surface-muted); }

.eyebrow {
  margin: 0 0 var(--space-2);
  color: var(--color-primary);
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

h1, h2, h3, p { margin-top: 0; }
/* Phase 1 (2026-07-22) -- harmonisation typographique : Jost etait deja charge via Google
   Fonts sur index.html/carte.html/nos-biens.html mais jamais cable a un selecteur -> police
   invisible en pratique (body et titres retombaient tous sur --font-base/Poppins). h1/h2/h3
   utilisent maintenant --font-heading (Jost, fallback Poppins) sur tout le site : comme
   style.css est partage par toutes les pages, cette regle s'applique partout automatiquement,
   y compris sur les pages qui viennent de recevoir le <link> Jost (about, mentions-legales,
   guides). Sur une page qui n'aurait pas (encore) le <link> Jost, le fallback Poppins evite
   toute rupture visuelle : jamais de police systeme brute. */
h1, h2, h3 { font-family: var(--font-heading); font-weight: 600; }
h1 {
  margin-bottom: var(--space-4);
  max-width: 12ch;
  font-size: clamp(2.25rem, 12vw, 4.5rem);
  line-height: 1.05;
  letter-spacing: -0.055em;
}
h2 {
  margin-bottom: var(--space-4);
  max-width: 14ch;
  font-size: clamp(2rem, 8vw, 3rem);
  line-height: 1.12;
  letter-spacing: -0.04em;
}
h3 { margin-bottom: var(--space-2); font-size: 1.125rem; line-height: 1.25; }
.lead { max-width: 34rem; color: var(--color-text-muted); font-size: clamp(1.05rem, 4vw, 1.35rem); line-height: 1.5; }
.section-header { display: grid; gap: var(--space-2); margin-bottom: var(--space-6); }
.actions { display: flex; flex-direction: column; gap: var(--space-3); margin-top: var(--space-5); }

.button {
  display: inline-flex;
  min-height: 48px;
  align-items: center;
  justify-content: center;
  padding: 0.85rem 1.1rem;
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  font-weight: 700;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  box-shadow: var(--shadow-sm);
  /* Phase 1 (2026-07-22) : micro-interaction "premium" minimale, cf. direction artistique --
     transition douce uniquement, pas d'effet gadget. Neutralisee globalement par la regle
     prefers-reduced-motion deja presente en fin de fichier (transition-duration: 0.01ms). */
  transition: transform 0.18s ease, box-shadow 0.18s ease, background 0.18s ease;
}
.button-primary { background: var(--color-primary); color: #ffffff; }
.button-secondary { background: var(--color-primary-soft); color: var(--color-primary-strong); }
.button:hover { transform: translateY(-1px); box-shadow: var(--shadow-md); }
.button:active { transform: translateY(0); box-shadow: var(--shadow-sm); }

.card {
  padding: var(--space-5);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  background: var(--color-surface);
  box-shadow: var(--shadow-sm);
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.card p { margin-bottom: 0; color: var(--color-text-muted); }
.card img { display: block; width: 100%; aspect-ratio: 4 / 3; object-fit: cover; border-radius: var(--radius-lg); margin-bottom: var(--space-4); }
.card:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); }
a.card:hover, a.card:focus-visible { text-decoration: none; }

/* ==========================================================================
   BADGE "CHOIX DE MIGUEL(TM)" -- Phase 1 (2026-07-22)
   Base du composant partage demande par le client : un seul langage visuel pour signifier
   "Miguel a choisi / Miguel explique", reutilise en Phase 2/3 sur le pin principal de la carte,
   la liste .choix-miguel et la future carte de recommandation enrichie. L'orange (--color-accent)
   reste ICI la seule utilisation decorative autorisee de cette couleur (regle validee : jamais
   sur un bouton secondaire, un titre ou une simple separation graphique). */
.miguel-choice-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.3rem 0.7rem;
  border: 1px solid rgba(242, 166, 90, 0.4);
  border-radius: var(--radius-pill);
  background: rgba(242, 166, 90, 0.15);
  color: #9a5a18;
  font-family: var(--font-base);
  font-size: 0.75rem;
  font-weight: 600;
  line-height: 1.2;
  white-space: nowrap;
  transition: transform 0.18s ease, box-shadow 0.18s ease;
}
.miguel-choice-badge__icon { flex-shrink: 0; width: 0.9em; height: 0.9em; }
/* Halo respirant reutilise depuis le pin principal de carte.css (meme nom d'animation, meme
   intention : signaler doucement "ceci est un choix actif de Miguel", jamais un clignotement
   agressif). Applique uniquement quand le badge est associe a l'element actif d'une liste. */
.miguel-choice-badge--live { animation: dht-halo-respire-badge 2.6s ease-in-out infinite; }
@keyframes dht-halo-respire-badge {
  0%, 100% { box-shadow: 0 0 0 0 rgba(242, 166, 90, 0.16); }
  50% { box-shadow: 0 0 0 4px rgba(242, 166, 90, 0.16); }
}
@media (prefers-reduced-motion: reduce) {
  .miguel-choice-badge--live { animation: none; box-shadow: 0 0 0 2px rgba(242, 166, 90, 0.16); }
}

/* ==========================================================================
   PATTERN EDITORIAL -- Phase 1 (2026-07-22)
   Preparation demandee pour la Phase 1 : classes de base uniquement (pas encore appliquees a la
   refonte complete des articles Guides, cf. perimetre Phase 1 valide). Objectif : que chaque
   page qui raconte un lieu s'appuie sur le meme squelette (photo dominante -> meta -> contenu)
   au lieu de developper son propre style au cas par cas. */
.editorial-cover {
  display: block;
  overflow: hidden;
  margin: 0 0 var(--space-6);
  border-radius: var(--radius-md);
}
.editorial-cover img { display: block; width: 100%; height: 45vh; object-fit: cover; }
.editorial-card {
  padding: var(--space-5);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
  box-shadow: var(--shadow-sm);
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.editorial-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); }
/* Phase 1 bis D (2026-07-22) : blog/index.html utilise .editorial-card comme <a> (toute la carte
   cliquable), pas comme <div>. Reset minimal pour que le lien ne casse pas la mise en page. */
a.editorial-card { display: block; color: inherit; text-decoration: none; }
a.editorial-card:hover h3 { color: var(--color-primary); }
.editorial-card img { display: block; width: 100%; aspect-ratio: 4 / 3; object-fit: cover; border-radius: var(--radius-md); margin-bottom: var(--space-3); }
.editorial-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin: 0 0 var(--space-2);
  color: var(--color-text-muted);
  font-size: 0.85rem;
}
@media (prefers-reduced-motion: reduce) {
  .card:hover, .editorial-card:hover, .button:hover { transform: none; }
}

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  border-bottom: 1px solid rgba(221, 215, 203, 0.72);
  background: rgba(247, 244, 237, 0.9);
  backdrop-filter: blur(16px);
}
.site-header__inner { display: flex; min-height: var(--header-height); align-items: center; justify-content: space-between; gap: var(--space-4); width: min(100%, var(--container)); margin-inline: auto; padding-inline: var(--space-4); }
.site-brand { display: inline-flex; align-items: center; gap: var(--space-2); font-weight: 800; text-decoration: none; white-space: nowrap; flex-shrink: 0; }
.site-brand img { width: 48px; height: auto; }
.site-nav__toggle { display: inline-flex; align-items: center; justify-content: center; min-height: 44px; min-width: 44px; padding: 0; border: 1px solid var(--color-border); border-radius: var(--radius-pill); background: var(--color-surface); color: var(--color-text); font-weight: 700; }
.site-nav__toggle svg { width: 20px; height: 20px; }
.site-nav__list { position: fixed; top: calc(var(--header-height) + var(--space-2)); right: var(--space-4); left: var(--space-4); display: none; margin: 0; padding: var(--space-3); border: 1px solid var(--color-border); border-radius: var(--radius-xl); background: var(--color-surface); box-shadow: var(--shadow-md); list-style: none; }
.site-nav__list[data-open] { display: grid; gap: var(--space-1); }
.site-nav__list a { display: block; padding: var(--space-3) var(--space-4); border-radius: var(--radius-pill); font-weight: 700; text-decoration: none; }
.site-nav__list a[aria-current="page"] { background: var(--color-primary-soft); color: var(--color-primary-strong); }
.site-header__right { display: flex; align-items: center; gap: var(--space-3); }
.site-header__map-cta { display: inline-flex; align-items: center; gap: var(--space-2); flex-shrink: 0; min-height: 44px; padding: 0 var(--space-4); border: 1.5px solid var(--color-primary); border-radius: var(--radius-pill); background: var(--color-primary-soft); color: var(--color-primary-strong); font-weight: 700; font-size: 0.9rem; text-decoration: none; white-space: nowrap; transition: background-color 160ms ease, transform 160ms ease; }
.site-header__map-cta:hover, .site-header__map-cta:focus-visible { background: var(--color-primary); color: #ffffff; }
.site-header__map-cta svg { width: 18px; height: 18px; flex-shrink: 0; }
.site-header__map-cta-full { display: none; }
.site-header__map-cta[aria-current="page"] { background: var(--color-primary); color: #ffffff; }

/* correctif P1-2 (audit responsive) : le h1 global (max-width: 12ch) convient aux titres courts
   (ex. "Investir local, aux Açores"), mais forçait les titres-phrases plus longs du hero
   (index.html, about.html) à s'enrouler dans une colonne étroite disproportionnée par rapport
   à l'espace réellement disponible sur tablette/desktop, sans jamais rien casser (pas de
   débordement), mais avec un déséquilibre visuel net sur grand écran. */
.home-hero h1, .page-hero h1 { max-width: none; }
.home-hero { padding-block: var(--space-6) var(--space-8); }
.home-hero .container { display: grid; gap: var(--space-6); }
.home-hero__media { margin: 0; }
.home-hero__media img { display: block; width: 100%; border-radius: var(--radius-xl); object-fit: cover; box-shadow: var(--shadow-md); }
.proof-grid { display: grid; gap: var(--space-4); }
.site-footer { padding-block: var(--space-6); background: var(--color-text); color: #ffffff; }
.site-footer__inner { display: grid; gap: var(--space-4); width: min(100%, var(--container)); margin-inline: auto; padding-inline: var(--space-4); }
.site-footer a { color: inherit; }
.site-footer nav { display: flex; flex-wrap: wrap; gap: var(--space-3); }
.site-footer__social { align-items: center; }
.site-footer__social-link { display: inline-flex; align-items: center; justify-content: center; color: rgba(255, 255, 255, 0.72); transition: color 0.2s ease, transform 0.2s ease; }
.site-footer__social-link:hover, .site-footer__social-link:focus-visible { color: #ffffff; transform: translateY(-1px); }
.legal h2 { font-size: 1.35rem; letter-spacing: -0.02em; }
.confirmation { min-height: 60vh; display: grid; align-items: center; }

@media (min-width: 480px) {
  .container, .site-header__inner, .site-footer__inner { padding-inline: var(--space-5); }
  .actions { flex-direction: row; flex-wrap: wrap; }
}
@media (min-width: 768px) {
  .section, .page-hero { padding-block: var(--space-10); }
  .proof-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .home-hero .container { grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.05fr); align-items: center; }
  .site-header__map-cta-full { display: inline; }
}
@media (min-width: 1024px) {
  .site-nav__toggle { display: none; }
  .site-nav__list { position: static; display: flex; gap: var(--space-2); padding: 0; border: 0; border-radius: 0; background: transparent; box-shadow: none; }
}
@media (min-width: 1440px) { :root { --container: 80rem; } }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { scroll-behavior: auto; transition-duration: 0.01ms; animation-duration: 0.01ms; }
}

/* ============================================================
   PHASE 3 — Contenus : page "Notre histoire" (about.html)
   Restauration du texte et de l'esprit éditorial de V1 dans le design V2.
   ============================================================ */
.about-article { display: grid; gap: var(--space-5); }
.about-article p { margin: 0; }
.about-photo { margin: 0; }
.about-photo img { display: block; width: 100%; aspect-ratio: 16 / 10; object-fit: cover; border-radius: var(--radius-xl); box-shadow: var(--shadow-md); }
.about-cta { text-align: center; margin: var(--space-2) 0; }
.about-signoff { font-size: 1.3rem; font-weight: 700; color: var(--color-primary); text-align: center; margin-top: var(--space-4); }

.miguel-callout { display: grid; gap: var(--space-3); background: linear-gradient(180deg, #ffffff, var(--color-primary-soft)); border-color: var(--color-primary-soft); }
.miguel-callout__title { margin: 0; font-size: 1.1rem; font-weight: 800; color: var(--color-text); display: flex; align-items: center; gap: var(--space-2); }
/* Phase 1 bis D (2026-07-22) : remplace l'emoji 🧭 par l'icône du registre DHTIcons partagé
   (navigation.exploration), résolue via resoudreIconesDHT() -- voir DHTIcons.js. Couleur teal :
   ce callout explique comment Miguel raisonne, ce n'est pas le badge "Choix de Miguel(TM)". */
.miguel-callout__icon { width: 1.2em; height: 1.2em; flex-shrink: 0; color: var(--color-primary); }
/* Phase 1 bis D (2026-07-22) : classe explicite pour le paragraphe d'explication du callout --
   valeurs identiques à l'héritage .card p déjà en place, donc aucun changement visuel, juste un
   sélecteur propre réutilisable sur les deux articles qui ont ce bloc. */
.miguel-callout__text { color: var(--color-text-muted); margin-bottom: var(--space-3); }
.miguel-callout__cta { margin-bottom: 0; }
.miguel-callout__cta { margin: 0; }
/* correctif restauration V1 (nos-biens.html) : badge de statut d'un projet immobilier, construit
   à partir des tokens de couleur du design system existant, pas un style isolé. */
.status-badge { display: inline-block; padding: var(--space-1) var(--space-4); border-radius: var(--radius-pill); font-size: 0.85rem; font-weight: 700; letter-spacing: 0.01em; }
.status-badge--progress { background: #fdf0e2; color: #9a5b18; border: 1px solid var(--color-accent); }
.status-badge--rented { background: var(--color-primary-soft); color: var(--color-primary-strong); border: 1px solid var(--color-primary); }
.trademark { font-size: 0.55em; vertical-align: super; margin-left: 1px; }

/* ============================================================
   PHASE 2 — Refonte éditoriale du blog : template d'article unifié
   (remplace l'ancien gabarit "article-body" isolé, aligné sur les
   composants existants .about-article / .about-photo / .card)
   ============================================================ */
.article-hero {
  position: relative;
  margin: 0;
  min-height: 260px;
  display: flex;
  align-items: flex-end;
  background-color: var(--color-text);
  background-size: cover;
  background-position: center;
}
.article-hero::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(24, 49, 47, 0) 35%, rgba(24, 49, 47, 0.82) 100%);
}
.article-hero__inner {
  position: relative;
  z-index: 1;
  width: min(100%, var(--container));
  margin-inline: auto;
  padding: var(--space-6) var(--space-4);
  color: #ffffff;
}
/* Phase 1 bis D (2026-07-22) : cet eyebrow est un simple libelle de categorie ("Meteo", "Bons
   plans"), sans rapport avec une decision de Miguel(TM) -- l'orange etant reserve exclusivement
   au langage "Choix / preuve de Miguel(TM)" (regle Phase 1), on bascule sur un blanc casse
   coherent avec le reste du texte blanc de la hero, plutot que l'accent de marque. */
.article-hero .eyebrow { color: rgba(255, 255, 255, 0.82); }
.article-hero h1 { margin: 0; max-width: none; color: #ffffff; }

.article-lead {
  font-size: clamp(1.05rem, 3.2vw, 1.25rem);
  font-weight: 600;
  color: var(--color-text);
}
.about-article figcaption {
  margin-top: var(--space-2);
  font-size: 0.85rem;
  color: var(--color-text-muted);
  text-align: center;
}
.about-article ul { padding-left: 1.2em; }
.about-article li { margin-bottom: var(--space-2); }

@media (min-width: 768px) {
  .article-hero { min-height: 380px; }
}

/* ============================================================
   HOMEPAGE — Refonte éditoriale premium en 7 actes (2026-07-21)
   Remplace home-hero / proof-grid / section "how" par une narration au
   scroll (émotion → révélation → preuve → méthode → guides → biens → CTA).
   N'affecte aucune autre page (about.html, nos-biens.html, blog/*) :
   celles-ci continuent d'utiliser .page-hero / .about-article / .card.
   Ne dépend ni de carte.js ni de carte.css : contenu 100% statique,
   la démo Miguel™ est une simulation marketing indépendante du moteur réel.
   ============================================================ */

/* ACTE 1 — Hero cinéma */
.acte-hero { position: relative; min-height: 92vh; min-height: 92svh; display: flex; align-items: flex-end; overflow: hidden; color: #ffffff; }
.acte-hero__media { position: absolute; inset: 0; z-index: 0; overflow: hidden; }
.acte-hero__frame { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; opacity: 0; transition: opacity 700ms ease; }
.acte-hero__frame--base, .acte-hero__frame.is-visible { opacity: 1; }
.acte-hero__frame--base, .acte-hero__frame--kenburns { animation: acteHeroZoom 26s ease-in-out infinite alternate; }
.acte-hero__credit { position: absolute; z-index: 1; right: var(--space-3); bottom: var(--space-2); margin: 0; padding: 2px 8px; font-size: 0.68rem; line-height: 1.3; color: rgba(255, 255, 255, 0.72); background: rgba(10, 20, 19, 0.28); border-radius: 999px; backdrop-filter: blur(4px); pointer-events: none; }
.acte-hero::before { content: ""; position: absolute; inset: 0; z-index: 1; background: rgba(10, 20, 19, 0.22); }
.acte-hero::after { content: ""; position: absolute; inset: 0; z-index: 1; background: linear-gradient(180deg, rgba(10, 20, 19, 0) 55%, var(--color-background) 100%); }
.acte-hero__content { position: relative; z-index: 2; width: min(100%, var(--container)); margin-inline: auto; padding: var(--space-8) var(--space-4) var(--space-10); }
.acte-hero__content h1 { max-width: none; color: #ffffff; text-shadow: 0 2px 24px rgba(0, 0, 0, 0.25); }
.heading-line { display: block; }
.acte-hero__subtitle { max-width: 30ch; margin: 0; font-size: clamp(1rem, 3vw, 1.25rem); color: rgba(255, 255, 255, 0.88); }
.acte-hero__scroll { position: absolute; z-index: 2; left: 50%; bottom: var(--space-5); transform: translateX(-50%); display: flex; flex-direction: column; align-items: center; gap: var(--space-2); color: rgba(255, 255, 255, 0.85); text-decoration: none; font-size: 0.75rem; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase; }
.acte-hero__scroll-line { width: 1px; height: 28px; background: rgba(255, 255, 255, 0.6); animation: acteHeroScroll 1.8s ease-in-out infinite; }

/* Carte Miguel™ flottante (Phase H1-B.1) : preuve visuelle immédiate, jamais une capture d'écran de
   l'application. Superposition légère façon carnet de voyage premium (Polarsteps), profondeur via
   halo + ombre portée diffuse, léger flottement continu désactivé si prefers-reduced-motion. */
.acte-hero__card { position: absolute; z-index: 3; right: var(--space-6); bottom: 18%; width: min(280px, 78vw); padding: var(--space-5) var(--space-5) var(--space-4); border-radius: 18px; background: rgba(255, 255, 255, 0.86); backdrop-filter: blur(14px) saturate(140%); -webkit-backdrop-filter: blur(14px) saturate(140%); box-shadow: 0 24px 60px -18px rgba(10, 20, 19, 0.45), 0 2px 8px rgba(10, 20, 19, 0.12); color: var(--color-text); animation: acteHeroCardFloat 7s ease-in-out infinite; }
.acte-hero__card::before { content: ""; position: absolute; inset: -22% -22% auto auto; top: -18%; right: -18%; width: 60%; height: 60%; background: radial-gradient(circle, rgba(255, 255, 255, 0.5), transparent 70%); z-index: -1; filter: blur(2px); pointer-events: none; }
.acte-hero__card-brand { margin: 0 0 var(--space-1); font-family: var(--font-heading); font-weight: 700; font-size: 0.95rem; letter-spacing: 0.01em; color: var(--color-text); }
.acte-hero__card-context { margin: 0 0 var(--space-3); font-size: 0.7rem; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--color-text-muted); }
.acte-hero__card-spot { margin: 0; font-size: 1.05rem; font-weight: 700; line-height: 1.25; color: var(--color-text); }
.acte-hero__card-quote { margin: var(--space-1) 0 var(--space-3); font-size: 0.85rem; font-style: italic; line-height: 1.4; color: var(--color-text-muted); }
.acte-hero__card-meta { display: flex; gap: var(--space-4); font-size: 0.85rem; font-weight: 600; color: var(--color-text); }
.acte-hero__card-meta span { display: inline-flex; align-items: center; gap: 6px; }
.acte-hero__card-icon { width: 16px; height: 16px; flex: 0 0 auto; color: var(--color-primary); }
/* Chantier « Hero vivant -- chargement honnête de la carte Miguel™ » (2026-07-26, périmètre
   strictement limité à `.acte-hero__card` ; le volet "narration variable" du fond hero, prévu au
   même contrat, a été retiré et n'a jamais été livré) : pendant le calcul réel de Miguel™
   (`--loading`), aucune valeur
   (lieu, température, durée) n'est affichée -- seule une légère pulsation signale une analyse en
   cours. En cas d'échec/timeout confirmé (`--fallback`), l'état se stabilise sans pulsation ni
   valeur inventée. Les deux états masquent `.acte-hero__card-meta` : aucun chiffre tant que la
   vraie donnée n'est pas disponible. */
.acte-hero__card--loading .acte-hero__card-meta,
.acte-hero__card--fallback .acte-hero__card-meta { display: none; }
.acte-hero__card--loading .acte-hero__card-context,
.acte-hero__card--loading .acte-hero__card-spot,
.acte-hero__card--loading .acte-hero__card-quote { animation: acteHeroCardPulse 1.6s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) {
  .acte-hero__card--loading .acte-hero__card-context,
  .acte-hero__card--loading .acte-hero__card-spot,
  .acte-hero__card--loading .acte-hero__card-quote { animation: none; opacity: 0.7; }
}
@media (max-width: 860px) {
  .acte-hero__card { right: var(--space-4); bottom: auto; top: var(--space-6); width: min(240px, 62vw); padding: var(--space-4); }
}
@media (max-width: 560px) {
  .acte-hero { flex-direction: column; align-items: stretch; justify-content: flex-end; min-height: 70vh; min-height: 70svh; }
  .acte-hero__content { padding-top: var(--space-6); padding-bottom: var(--space-5); }
  .acte-hero__card { position: static; margin: var(--space-4) var(--space-4) var(--space-2); width: auto; animation: none; }
  .acte-revelation { padding-block: var(--space-8) var(--space-8); }
}
@media (prefers-reduced-motion: no-preference) {
  @keyframes acteHeroZoom { from { transform: scale(1); } to { transform: scale(1.07); } }
  @keyframes acteHeroScroll { 0%, 100% { opacity: 0.3; transform: translateY(0); } 50% { opacity: 1; transform: translateY(6px); } }
  @keyframes acteHeroCardFloat { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-10px); } }
  @keyframes acteHeroCardPulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.55; } }
}
@media (prefers-reduced-motion: reduce) {
  .acte-hero__frame, .acte-hero__scroll-line, .acte-hero__card { animation: none; transition: none; }
}

/* ACTE 2 BIS — Comprendre : respiration éditoriale, 3 cartes volontairement non identiques */
.acte-comprendre { padding-block: var(--space-10); background: var(--color-surface); }
.acte-comprendre__intro { text-align: left; margin-bottom: var(--space-8); margin-inline: auto; }
.acte-comprendre__intro h2 { margin: 0 0 var(--space-3); max-width: none; font-size: clamp(1.4rem, 3.4vw, 1.85rem); font-weight: 600; }
.acte-comprendre__lead { max-width: 46ch; margin: 0; color: var(--color-text-muted); font-size: clamp(1rem, 2.4vw, 1.1rem); line-height: 1.55; }
.acte-comprendre__grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-6); max-width: var(--container); margin-inline: auto; }
.acte-comprendre__card { position: relative; overflow: hidden; padding: var(--space-8) var(--space-5); border-radius: var(--radius-xl); text-align: center; background: var(--color-surface); box-shadow: var(--shadow-md); }
.acte-comprendre__card::before { content: ""; position: absolute; inset: 0; z-index: 0; opacity: 0.07; pointer-events: none; }
.acte-comprendre__card--ciel::before { background: radial-gradient(circle at 70% 20%, var(--color-accent), transparent 60%); }
.acte-comprendre__card--lieux::before { background: radial-gradient(circle at 30% 80%, var(--color-primary), transparent 60%); }
.acte-comprendre__card--envies::before { background: radial-gradient(circle at 50% 50%, var(--color-primary-strong), transparent 65%); }
.acte-comprendre__icon { position: relative; z-index: 1; display: block; width: 32px; height: 32px; margin: 0 auto var(--space-4); color: var(--color-primary); }
.acte-comprendre__card h3 { position: relative; z-index: 1; margin: 0 0 var(--space-2); font-size: 1.05rem; }
.acte-comprendre__card p { position: relative; z-index: 1; margin: 0 auto; max-width: 26ch; color: var(--color-text-muted); font-size: 0.95rem; line-height: 1.55; }
@media (max-width: 780px) {
  .acte-comprendre__grid { grid-template-columns: 1fr; gap: var(--space-5); }
}

/* ACTE 6 BIS — Confiance : les repères confirment une histoire, ils ne la remplacent pas */
.acte-confiance { padding-block: var(--space-10); background: var(--color-surface); }
.acte-confiance__inner { text-align: center; display: grid; gap: var(--space-5); }
.acte-confiance__lead { max-width: 44ch; margin: 0 auto; font-size: clamp(1.15rem, 3vw, 1.4rem); font-weight: 600; line-height: 1.4; color: var(--color-text); }
.acte-confiance__reperes { margin: var(--space-2) 0 0; padding: 0; list-style: none; display: flex; flex-direction: column; align-items: center; gap: var(--space-3); }
.acte-confiance__reperes li { font-size: 0.85rem; font-weight: 700; letter-spacing: 0.03em; text-transform: uppercase; color: var(--color-text-muted); }
/* Correctif alignement (2026-07-24, signale par Antoine) : le separateur "." en ::after avec
   margin-left fixe n'avait de sens que lorsque plusieurs reperes partageaient une meme ligne --
   des que chacun s'empile seul sur sa ligne (mobile etroit), ce point pendait avec un vide a
   droite du texte centre, cassant la symetrie. Par defaut (mobile) : liste empilee, sans point.
   Le point ne reapparait qu'a partir de 600px, quand les reperes partagent reellement une ligne. */
@media (min-width: 600px) {
  .acte-confiance__reperes { flex-direction: row; flex-wrap: wrap; justify-content: center; gap: var(--space-3) var(--space-5); }
  .acte-confiance__reperes li:not(:last-child)::after { content: "·"; margin-left: var(--space-5); color: var(--color-border); }
}
/* Correctif (2026-07-24, demande Antoine) : sur desktop, les 4 reperes doivent tenir sur une
   seule ligne. Le conteneur parent (.container.narrow, 48rem) etait trop etroit pour les 4
   libelles + points -- on fait deborder la liste jusqu'a la largeur du viewport (technique
   "full-bleed") pour lui laisser la place, sans toucher a la largeur du reste du bloc confiance. */
@media (min-width: 860px) {
  .acte-confiance__reperes { flex-wrap: nowrap; width: 100vw; max-width: 100vw; margin-inline: calc(50% - 50vw); padding-inline: var(--space-5); box-sizing: border-box; }
  .acte-confiance__reperes li { white-space: nowrap; }
}

/* ACTE 2 — Révélation */
.acte-revelation { padding-block: var(--space-10); background: var(--color-background); }
.acte-revelation__inner { text-align: center; display: grid; gap: var(--space-6); }
.acte-revelation__question { margin: 0 auto; max-width: 26ch; font-size: clamp(1.5rem, 5vw, 2.25rem); font-weight: 600; line-height: 1.35; letter-spacing: -0.02em; color: var(--color-text); }
/* Correctif (2026-07-24, demande Antoine) : sur mobile, "Meteo . Lumiere . Rythme . Voyage"
   prenait de la hauteur et forcait un scroll supplementaire sans apporter de valeur -- retire
   sous 600px. Reapparait a partir de 600px, ou il tient sur une ligne sans cout de scroll. */
.acte-revelation__signals { display: none; }
@media (min-width: 600px) {
  .acte-revelation__signals { margin: 0; padding: 0; list-style: none; display: flex; flex-wrap: wrap; justify-content: center; gap: var(--space-3) var(--space-5); }
  .acte-revelation__signals li { font-size: 0.85rem; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: var(--color-text-muted); }
  .acte-revelation__signals li:not(:last-child)::after { content: "·"; margin-left: var(--space-5); color: var(--color-border); }
}

/* ACTE 3 — Preuve (démo Miguel™) : carte São Miguel réelle + wizard + moteur de réflexion, boucle continue */
.acte-preuve { padding-block: calc(var(--space-10) + 40px) var(--space-10); background: radial-gradient(60% 60% at 50% 20%, var(--color-primary-soft) 0%, var(--color-background) 70%); }
.acte-preuve__eyebrow-line { margin: 0 0 var(--space-6); text-align: center; font-size: 1.05rem; font-weight: 600; color: var(--color-text-muted); }
/* Mobile (Phase suivante) : l'utilisateur doit voir l'île, Miguel qui analyse, puis le résultat, sans
   traverser une grande zone vide au-dessus de la scène. On resserre l'habillage autour de la scène pour
   que la carte devienne immédiatement la première chose vue, en gardant juste assez de respiration pour
   ne pas paraître compressé. */
@media (max-width: 859px) {
  .acte-preuve { padding-block: var(--space-6); }
  .acte-preuve__eyebrow-line { margin: 0 0 var(--space-3); font-size: 0.95rem; }
}

/* Grille responsive globale (Lot 3, H1-C) : rythme vertical mobile plafonne a 64px entre
   deux sections adjacentes (32px + 32px), marges laterales 24px partout, tailles de titres
   recalees sur l'echelle mobile premium (H1 ~42-46px, H2 ~32-36px). Le desktop (>=768px)
   garde les valeurs plus genereuses existantes. */
@media (max-width: 767px) {
  .acte-comprendre, .acte-confiance, .acte-methode, .acte-final { padding-block: var(--space-6); }
  .acte-guides { padding-block: var(--space-6) var(--space-5); }
  .acte-biens { padding-block: var(--space-5) var(--space-6); }
}
.demo-miguel { margin: 0 auto; max-width: 64rem; }
/* Composition Phase 7 (validée) : une scène unique, pas deux blocs séparés. La carte, le wizard, la
   réflexion et le résultat appartiennent au même conteneur premium (même fond, même ombre, même rayon),
   toujours en séquence verticale (carte -> wizard -> réflexion -> résultat), sur mobile comme sur desktop.
   Aucun overlay : la carte reste visible et dominante, le panneau est une bande intégrée à la même scène,
   jamais une carte flottante indépendante. */
.demo-miguel__stage {
  position: relative; display: flex; flex-direction: column; gap: 0;
  border-radius: var(--radius-xl); overflow: hidden;
  background: radial-gradient(70% 70% at 50% 22%, var(--color-primary-soft) 0%, var(--color-background) 62%);
  box-shadow: 0 20px 60px rgba(15, 49, 47, 0.16);
}
@media (min-width: 860px) {
  .demo-miguel__stage { max-width: 42rem; margin-inline: auto; }
}

/* Carte : silhouette réelle de São Miguel (même géométrie/algorithme que carte.js), pins réels.
   Elle occupe l'essentiel de l'attention visuelle (~60-70% de la scène) et n'a plus son propre
   cadre indépendant : elle est la partie haute de la scène unique. */
.demo-map { position: relative; }
/* Correctif P2 (2026-07-24, audit mobile) : CAUSE REELLE des "deux bandes vides" autour de
   l'archipel -- min-height/max-height forcaient le <svg> a une hauteur superieure a celle que
   son propre aspect-ratio (640/360) produit naturellement a la largeur mobile (ex. ~193px a
   343px de large, contre 300px impose). Comme le contenu utilise preserveAspectRatio="xMidYMid
   meet", cet ecart se traduisait par du letterboxing : une bande vide au-dessus ET une bande vide
   en dessous de l'archipel, de meme teinte de fond (donc peu visible isolement mais nette a l'oeil
   une fois cumulee, cf. retour utilisateur). Correctif : la hauteur suit desormais uniquement
   l'aspect-ratio, sans plancher/plafond artificiel -- aucune image/silhouette/donnee modifiee. */
.demo-map__svg { display: block; width: 100%; aspect-ratio: 640 / 360; }
/* Vue archipel (nouvelle intro) : peinte en dernier dans le SVG, donc au-dessus de la carte détaillée —
   elle la masque complètement au repos. Trois temps : (1) les 9 îles apparaissent en fondu très doux
   ("Miguel connaît tout l'archipel") ; (2) les îles autres que São Miguel s'assombrissent et São Miguel
   reçoit un halo ("Miguel affine son choix") ; (3) le groupe entier grossit et disparaît en fondu, centré
   sur São Miguel, révélant la carte détaillée déjà en place dessous ("zoom immersif"). Aucune transition
   n'est déclarée sur l'état de repos : au redémarrage de la boucle, le groupe revient instantanément à son
   état initial (visible, non zoomé) avant de rejouer la séquence, sans flash ni saut visible côté utilisateur
   puisque ce reset se produit pendant que la scène est déjà masquée par le panneau/la transition de boucle. */
.demo-map__archipel { transform-origin: 507.5px 236.25px; }
.demo-map__archipel-veil { fill: var(--color-background); opacity: 1; }
.demo-map__archipel-island {
  /* Correction (audit visibilité) : le remplissage clair sur fond crème n'offrait presque aucun contraste
     à l'opacité prévue (deux tons pastel très proches) — le contour lui-même est désormais entièrement
     opaque dès l'apparition, et le remplissage est plus soutenu, pour que les 9 îles soient identifiables
     sans ambiguïté dès la phase 0, avant même toute animation. */
  fill: #b9e2da; stroke: var(--color-primary); stroke-width: 1.5; stroke-opacity: 1; stroke-linejoin: round;
  opacity: 0; transition: opacity 0.9s ease, stroke-width 1.6s ease, fill 1.6s ease;
  transition-delay: var(--isl-delay, 0s);
}
.demo-map[data-map-phase-archipel] .demo-map__archipel-island { opacity: 1; }
.demo-map[data-archipel-focus] .demo-map__archipel-island:not(.demo-map__archipel-island--target) {
  opacity: 0.35; transition: opacity 1.8s ease;
}
.demo-map[data-archipel-focus] .demo-map__archipel-island--target {
  opacity: 1; fill: var(--color-primary-soft); stroke-width: 2.2; transition: opacity 1.8s ease, stroke-width 1.8s ease, fill 1.8s ease;
}
.demo-map__archipel-glow { fill: var(--color-accent); opacity: 0; filter: blur(10px); transition: opacity 1.8s ease; pointer-events: none; }
.demo-map[data-archipel-focus] .demo-map__archipel-glow { opacity: 0.2; }
.demo-map__archipel-sparks circle {
  fill: var(--color-accent); opacity: 0; transition: opacity 0.8s ease; transition-delay: var(--isl-delay, 0s); pointer-events: none;
}
.demo-map[data-map-phase-archipel] .demo-map__archipel-sparks circle { opacity: 0.5; }
.demo-map[data-archipel-focus] .demo-map__archipel-sparks circle { opacity: 0.12; transition: opacity 1.8s ease; }
/* Correction cadrage (Phase corrective) : un "scale()" seul grossit autour de son propre point d'origine
   (le centre de São Miguel), qui est excentré à droite dans le viewBox de l'archipel — la moitié de l'île
   sortait donc mécaniquement du cadre pendant le zoom. On ajoute une translation constante (indépendante
   de l'ampleur du zoom) qui ramène le centre de São Miguel vers le centre du viewBox : le résultat est un
   vrai mouvement de caméra qui se déplace ET se rapproche, jamais un agrandissement sur place. L'échelle
   est aussi réduite (6.4 -> 4.6) pour que la taille finale de la silhouette simplifiée se raccorde à la
   taille réelle de la carte détaillée qui apparaît juste après, au lieu d'un saut de taille perceptible. */
.demo-map[data-archipel-zoom] .demo-map__archipel {
  transform: translate(-187.5px, -56.25px) scale(4.6); opacity: 0;
  transition: transform 1.5s cubic-bezier(0.4, 0, 0.2, 1), opacity 1.3s ease 0.35s;
}
@media (prefers-reduced-motion: reduce) {
  .demo-map__archipel-island, .demo-map__archipel-sparks circle, .demo-map__archipel-glow { transition-duration: 0.01s; }
  .demo-map[data-archipel-zoom] .demo-map__archipel { transform: none; transition: opacity 0.4s ease; }
}
/* L'île se révèle par strates ("la base de connaissances se construit") : fond calme -> silhouette -> lacs -> points. */
/* Le contour ne doit plus être le premier élément perçu ("une forme SVG entourée d'un trait") : épaisseur
   et contraste réduits pour qu'il guide la lecture de l'île sans la dominer, tout en gardant l'identité DHT. */
.demo-map__silhouette { fill: var(--color-primary-soft); stroke: var(--color-primary); stroke-width: 1.7; stroke-opacity: 0.82; stroke-linejoin: round; opacity: 0; transition: opacity 1s ease; }
.demo-map[data-map-phase-silhouette] .demo-map__silhouette { opacity: 0.95; }
/* Profondeur territoriale : dégradé volcanique très doux, révélé avec la silhouette (jamais un relief 3D
   ni une texture satellite). Audit Phase 7 : halos resserrés (rayon -35%, opacité -45%) pour que l'œil
   aille au lieu et à son pictogramme, jamais à la tache floue autour. */
.demo-map__volcanic { fill: url(#demo-map-volcanic); opacity: 0; transition: opacity 1.8s ease; pointer-events: none; }
.demo-map[data-map-phase-silhouette] .demo-map__volcanic { opacity: 0.55; }
/* Anneau topographique secondaire (priorité 4) : contour seul, sans remplissage, concentrique au halo
   volcanique — c'est cette fine couche intermédiaire qui suggère un relief, jamais un halo de plus. */
.demo-map__topo { fill: none; stroke: #8a6a4a; stroke-width: 1; stroke-opacity: 0; transition: stroke-opacity 1.8s ease; pointer-events: none; }
.demo-map[data-map-phase-silhouette] .demo-map__topo { stroke-opacity: 0.2; }
/* Lacs : addition artistique volontaire (absente du rendu carte.js réel), désormais dessinés comme de
   vraies petites formes de lac (Sete Cidades double lobe, Fogo, Furnas) plutôt que des ellipses floues,
   avec une couleur eau dédiée distincte du teal des pins/spots, pour rester lisibles comme une vraie
   information géographique sans jamais devenir l'élément dominant. */
.demo-map__lake { fill: #3f8fa0; stroke: #245c68; stroke-width: 1; stroke-opacity: 0.5; opacity: 0; transition: opacity 1.6s ease; pointer-events: none; }
.demo-map[data-map-phase-lakes] .demo-map__lake { opacity: 0.42; }
/* Champ de points mineurs : reprend l'esprit réel de carte.js (couche "tous les spots" = petits cercles
   non labellisés) pour donner une impression de densité/richesse, jamais une carte saturée. */
.demo-map__dot {
  fill: var(--color-surface); stroke: var(--color-primary); stroke-width: 1.2;
  opacity: 0; transition: opacity 0.7s ease, r 0.4s ease, fill 0.4s ease;
  transition-delay: var(--dot-delay, 0s);
  pointer-events: none;
}
.demo-map[data-map-phase-dots] .demo-map__dot { opacity: 0.6; }
.demo-map[data-dots-explore] .demo-map__dot[data-dot-explore] { opacity: 1; r: 4.2; fill: var(--color-primary-soft); transition-delay: 0s; }
/* Spots "fantômes" : jamais visibles au repos (base de données bien plus large que ce qui est affiché en
   permanence), révélés seulement pendant "Miguel réfléchit", puis effacés dès que ce moment se termine —
   c'est cette disparition qui donne la sensation d'exploration/comparaison plutôt qu'un simple ajout de points. */
.demo-map[data-map-phase-dots] .demo-map__dot[data-dot-ghost] { opacity: 0; }
/* Ilhéu de Vila Franca do Campo : seul spot volontairement hors silhouette (vrai îlot en mer). Traitement
   visuel légèrement différent (plus discret, teinte légèrement plus froide) pour qu'il se lise comme un
   repère marin intentionnel et non comme une erreur de placement. */
.demo-map[data-map-phase-dots] .demo-map__dot--offshore { opacity: 0.45; fill: var(--color-primary); }
.demo-map__link { stroke: var(--color-primary); stroke-width: 1.5; stroke-dasharray: 3 4; opacity: 0; transition: opacity 1s ease; }
.demo-map__link[data-link-show] { opacity: 0.55; }
.demo-map__pin { opacity: 0; transform-origin: center; transition: opacity 0.7s ease; }
.demo-map__pin[data-pin-show] { opacity: 1; }
.demo-map__pin[data-pin-fade] { transition: opacity 1.2s ease; opacity: 0.16; }
/* Halo façon DHT réel (carte.css: dht-pin-highlight = lueur drop-shadow pulsante), pas un anneau
   graphique ni un effet radar : une lumière douce, comme une recommandation personnelle.
   Audit Phase 7 : rayon, opacité et contraste réduits pour que le halo reste un accent, jamais
   l'élément qui attire l'œil avant le lieu lui-même. */
.demo-map__pin-halo { fill: var(--color-accent); stroke: none; r: 9; filter: blur(7px); opacity: 0; transition: opacity 0.6s ease; }
/* La propriété "opacity" reste uniquement pilotée par la transition ci-dessus (apparition en fondu) ;
   le keyframe n'anime que le rayon "r", pour ne jamais entrer en conflit avec la transition (une
   animation CSS a toujours priorité sur une transition ciblant la même propriété : les combiner sur
   "opacity" provoquait un léger flash au lieu d'un fondu doux).
   Audit Phase 7 (2e passe) : le halo attirait encore autant l'œil que le lieu lui-même — opacité et
   rayon réduits une nouvelle fois pour rester un simple accent, jamais l'élément dominant. */
.demo-map__pin[data-pin-selected] .demo-map__pin-halo { opacity: 0.14; animation: demoPinHalo 2.6s ease-in-out infinite; }
/* Le lieu doit rester le héros visuel, mais plus discret/intégré qu'un pin GPS classique : cercle
   blanc fin, contour aminci, ombre très douce, pictogramme resserré — "un lieu analysé par Miguel",
   pas "un point GPS classique". Rayon encore réduit (11 -> 9.5) pour se fondre davantage dans la carte. */
.demo-map__pin-dot { r: 9.5; fill: var(--color-surface); stroke: var(--color-primary); stroke-width: 0.75; stroke-opacity: 0.5; filter: drop-shadow(0 2px 4px rgba(15, 49, 47, 0.12)); }
.demo-map__pin-icon { color: var(--color-primary-strong); }
@keyframes demoPinHalo { 0%, 100% { r: 7; } 50% { r: 10; } }
/* Chantier "Option A - projection geographique reelle" (2026-07-26, CONTRAT-projection-geo-reelle.md) :
   quand une decision reelle exploitable est disponible ce jour-la, le script (index.html) pose
   data-map-pins-mode="reelles" sur .demo-map et peuple dynamiquement .demo-map__pins-reelles avec
   les VRAIS pins projetes (1 a N). Dans ce seul cas, les 3 pins fixes historiques et leur lien
   statique sont masques -- sans mode (repli, aucune donnee exploitable), rien ne change : ils
   restent visibles et animes exactement comme avant ce chantier. Les pins/lien "reels" reutilisent
   deja les classes .demo-map__pin / .demo-map__link ci-dessus (memes styles, aucune regle dupliquee). */
.demo-map[data-map-pins-mode="reelles"] .demo-map__pin:not(.demo-map__pin--reelle),
.demo-map[data-map-pins-mode="reelles"] .demo-map__link:not(.demo-map__link--reelle) {
  display: none;
}

/* Panneau : bande intégrée à la même scène que la carte (même famille visuelle), pas une carte flottante
   posée à côté. Un simple dégradé + une ligne de séparation très fine suffisent à distinguer les deux
   zones sans jamais donner l'impression de deux blocs indépendants. Compact par nature : question courte,
   3 choix maximum, le détail complet du résultat reste la seule phase où la bande peut respirer davantage. */
.demo-panel {
  position: relative; padding: var(--space-3) var(--space-4) var(--space-4);
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.7) 0%, var(--color-background) 100%);
  border-top: 1px solid rgba(15, 49, 47, 0.08);
}
/* Dernier ajustement mobile (Phase corrective) : respiration explicite sous le CTA, indépendante du
   calcul de hauteur du sizer, pour garantir que le bouton ne soit jamais à fleur de bord sur petit écran. */
@media (max-width: 430px) {
  .demo-panel { padding-bottom: var(--space-6); }
  .demo-scene__sizer, .demo-state { padding-bottom: var(--space-2); }
}
@media (min-width: 860px) {
  .demo-panel { padding: var(--space-4) var(--space-6) var(--space-5); }
}
/* Sur mobile, la scène de résultat est condensée : on garde l'essentiel (étape en cours + programme), le détail "pourquoi" est réservé au desktop pour ne pas alourdir le panneau et laisser la carte dominer visuellement */
/* Audit composition (Phase corrective) : "Pourquoi cette journée" faisait partie de la hiérarchie
   demandée (heure / lieu / raison) — le masquer sur mobile contredisait cette exigence, et cachait le
   vrai bug de hauteur plutôt que de le résoudre. Restauré, avec la correction ci-dessous. */
/* Correctif P2 (2026-07-24, demande Antoine) : la hauteur du conteneur etait auparavant figee sur
   l'etape la plus longue de la demo (le resultat final) via un sizer invisible, pour eviter tout
   saut de mise en page -- au prix d'un grand espace vide sous les etapes courtes (ex. "Votre envie
   aujourd'hui ?"). dhtHomeMiguelDemoSyncHeight() (voir <script> plus bas) mesure desormais la
   hauteur reelle de chaque etape a chaque activation et anime .demo-scene vers cette valeur --
   .demo-scene__sizer reste en place uniquement comme hauteur de repli avant la premiere execution
   du script (jamais de flash a 0px). overflow:hidden empeche ce sizer (toujours dans le flux,
   visibility:hidden) d'influencer quoi que ce soit une fois la hauteur explicite appliquee. */
.demo-scene { position: relative; isolation: isolate; overflow: hidden; transition: height 420ms cubic-bezier(0.2, 0, 0, 1); }
@media (prefers-reduced-motion: reduce) { .demo-scene { transition: none; } }
.demo-scene__sizer { visibility: hidden; pointer-events: none; }
/* Bug identifié : "overflow: hidden" + "justify-content: center" sur un conteneur en position absolue
   dont la hauteur dépend d'un sizer invisible est fragile — au moindre écart de hauteur, le centrage
   rogne le HAUT (badge "Journée recommandée") et le BAS (CTA) en même temps. On aligne désormais le
   contenu en haut (jamais de rognage du badge) et on laisse le contenu déborder proprement plutôt que
   d'être coupé si un écart de hauteur subsiste malgré le sizer. */
.demo-state {
  position: absolute; inset: 0; z-index: 1; overflow: visible;
  display: flex; flex-direction: column; justify-content: flex-start; gap: var(--space-3);
  opacity: 0; transform: scale(0.98); filter: blur(6px);
  pointer-events: none;
  transition: opacity 0.5s cubic-bezier(0.4, 0, 0.2, 1), transform 0.5s cubic-bezier(0.4, 0, 0.2, 1), filter 0.5s cubic-bezier(0.4, 0, 0.2, 1);
}
.demo-state[data-active] { opacity: 1; transform: scale(1); filter: blur(0); pointer-events: auto; z-index: 2; }
.demo-miguel__phase-label { margin: 0 0 var(--space-3); font-size: 0.9rem; font-weight: 700; color: var(--color-primary-strong); }
.demo-miguel__icon { width: 18px; height: 18px; flex: 0 0 auto; color: var(--color-text-muted); }
.demo-miguel__wizard-grid { position: relative; display: flex; flex-wrap: wrap; gap: var(--space-2); }
/* Cartes adoucies : moins "champ de formulaire", plus "carte de voyage" (bord quasi invisible au repos,
   ombre douce plutôt que contour marqué, coins plus généreux). */
/* La carte est l'unique confirmation visuelle du clic ("Miguel comprend votre choix") : fond teinté,
   contraste renforcé, bordure subtile, légère élévation — tout reste à l'intérieur de la carte,
   rien ne dépasse. Aucun badge ni anneau externe : c'est l'élément lui-même qui change d'état. */
.demo-miguel__wizard-card { position: relative; display: flex; flex-direction: column; align-items: center; gap: 6px; flex: 1 1 6rem; min-width: 0; padding: var(--space-3) var(--space-2); border-radius: var(--radius-xl); border: 1px solid transparent; background: rgba(255, 255, 255, 0.55); box-shadow: 0 2px 10px rgba(15, 49, 47, 0.07); font-size: 0.82rem; font-weight: 600; color: var(--color-text-muted); text-align: center; transition: border-color 0.38s ease, background 0.38s ease, color 0.38s ease, box-shadow 0.38s ease, transform 0.38s ease; }
/* Audit icônes (Phase corrective) : dans le vrai wizard Miguel™, le pictogramme reste toujours dans sa
   couleur de sprite d'origine (#0e39c1) — seul le fond/la bordure de la carte change à la sélection,
   jamais la couleur du dessin lui-même. On fige donc la couleur de l'icône au lieu de la faire hériter
   de l'état de la carte, pour reproduire exactement ce comportement. */
.demo-miguel__wizard-card .demo-miguel__icon { width: 24px; height: 24px; color: #0e39c1; }
.demo-miguel__wizard-card[data-selected] { border-color: var(--color-primary); background: var(--color-primary-soft); color: var(--color-primary-strong); box-shadow: 0 10px 22px rgba(15, 49, 47, 0.16); transform: translateY(-2px); }
/* Curseur mutualisé par grille : il apparaît, glisse depuis une position neutre jusqu'à la carte ciblée
   (--cx/--cy calculés en JS), s'arrête brièvement, puis s'efface — sans anneau ni pulse indépendant.
   Le clic n'est perçu que parce que la carte elle-même change d'état, jamais par un effet séparé. */
.demo-miguel__cursor { position: absolute; top: 0; left: 0; width: 10px; height: 10px; border-radius: 50%; transform: translate(var(--cx, 50%), var(--cy, 50%)) translate(-50%, -50%); background: var(--color-primary); box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.9); opacity: 0; transition: transform 0.65s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.4s ease; pointer-events: none; z-index: 3; }
.demo-miguel__cursor[data-show] { opacity: 0.55; }

/* Moteur de réflexion : 3 étapes qui se cochent à un rythme naturel, jamais simultané */
.demo-miguel__checklist { margin: 0; padding: 0; list-style: none; display: grid; gap: var(--space-3); }
.demo-miguel__check { display: flex; align-items: center; gap: 10px; font-size: 0.92rem; font-weight: 600; color: var(--color-text-muted); opacity: 0; transform: translateY(6px); transition: opacity 0.6s ease, transform 0.6s ease, color 0.4s ease; }
.demo-miguel__check[data-show] { opacity: 1; transform: translateY(0); color: var(--color-text); }
.demo-miguel__check-mark { width: 18px; height: 18px; flex: 0 0 auto; border-radius: 50%; border: 1.5px solid var(--color-border); position: relative; transition: border-color 0.4s ease; }
.demo-miguel__check-mark::after { content: ""; position: absolute; inset: 3px; opacity: 0; transform: scale(0.4); transition: opacity 0.3s ease, transform 0.3s ease; background: var(--color-primary); border-radius: 50%; }
.demo-miguel__check-mark[data-show] { border-color: var(--color-primary); }
.demo-miguel__check-mark[data-show]::after { opacity: 1; transform: scale(1); }

.demo-miguel__badge { display: inline-block; margin: 0 0 var(--space-2); padding: 2px 12px; border-radius: var(--radius-pill); background: var(--color-primary-soft); color: var(--color-primary-strong); font-size: 0.78rem; font-weight: 700; }
/* Panneau "Apple / Aman" (Phase suivante) : on retire le bloc "carte" plein-fond au profit d'une simple
   respiration verticale — la hiérarchie doit venir de la typographie (heure discrète / lieu fort / raison
   en retrait), jamais d'un cadre. Les séparateurs entre étapes deviennent un espace, pas un trait. */
.demo-miguel__plan { display: grid; gap: var(--space-3); padding: 0; }
.demo-miguel__plan-title { margin: 0; font-size: 0.82rem; font-weight: 700; letter-spacing: 0.02em; color: var(--color-text-muted); text-transform: uppercase; }
.demo-miguel__steps { margin: 0; padding: 0; list-style: none; display: grid; gap: var(--space-3); }
.demo-miguel__step { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-2); padding: 0; border-top: none; }
.demo-miguel__step-heure { flex: 0 0 auto; font-size: 0.78rem; font-weight: 600; letter-spacing: 0.02em; color: var(--color-text-muted); }
.demo-miguel__step-body { display: block; flex: 1 1 auto; min-width: 0; }
.demo-miguel__step-body strong { display: block; font-size: 1.05rem; font-weight: 700; color: var(--color-text); }
.demo-miguel__step-body span { display: block; margin-top: 2px; font-size: 0.84rem; color: var(--color-text-muted); }
/* "Pourquoi cette journée" ne doit plus être une seconde carte qui rivalise avec le plan : simple texte
   en retrait, séparé par un filet très discret plutôt qu'un fond plein — il informe sans prendre de place
   émotionnelle à la carte. */
.demo-miguel__pourquoi { padding-top: var(--space-3); border-top: 1px solid rgba(15, 49, 47, 0.08); background: none; border-radius: 0; }
.demo-miguel__pourquoi-title { margin: 0 0 var(--space-1); font-size: 0.78rem; font-weight: 700; letter-spacing: 0.02em; text-transform: uppercase; color: var(--color-text-muted); }
.demo-miguel__pourquoi-text { margin: 0; font-size: 0.86rem; font-style: italic; color: var(--color-text-muted); }
.demo-miguel__cta { display: inline-flex; align-items: center; margin-top: 0; padding: 10px 4px; font-weight: 700; color: var(--color-primary); text-decoration: none; min-height: 44px; }
.demo-miguel__cta:hover { text-decoration: underline; }
[data-reveal] { opacity: 0; transform: translateY(4px); transition: opacity 0.5s ease, transform 0.5s ease; }
[data-reveal][data-show] { opacity: 1; transform: translateY(0); }
@media (prefers-reduced-motion: reduce) {
  .demo-state, .demo-miguel__wizard-card, .demo-miguel__cursor, .demo-map__pin, .demo-map__link, .demo-map__silhouette, .demo-map__volcanic, .demo-map__lake, .demo-map__dot, [data-reveal] { transition: none; }
  .demo-map__silhouette { opacity: 0.95; }
  .demo-map__volcanic { opacity: 0.55; }
  .demo-map__lake { opacity: 0.42; }
  .demo-map__dot { opacity: 0.6; }
  .demo-map__dot[data-dot-ghost] { opacity: 0; }
  .demo-map__pin[data-pin-selected] .demo-map__pin-halo { animation: none; opacity: 0.24; }
}

/* ACTE 4 — Méthode */
.acte-methode { padding-block: var(--space-10); }
.acte-methode .eyebrow, .acte-methode h2 { text-align: left; }
.acte-methode h2 { margin-inline: 0; max-width: 26ch; font-weight: 600; }
.acte-methode__list { margin: var(--space-8) 0 0; padding: 0; list-style: none; display: grid; }
.acte-methode__list li { display: flex; flex-wrap: wrap; gap: var(--space-3); padding: var(--space-4) 0; border-top: 1px solid var(--color-border); }
.acte-methode__list li:last-child { border-bottom: 1px solid var(--color-border); }
.acte-methode__label { flex: 0 0 8rem; font-weight: 700; color: var(--color-primary-strong); }
.acte-methode__text { flex: 1 1 16rem; color: var(--color-text-muted); }

/* ACTE 5 — Comprendre les Açores : mini-hero éditorial, une image dominante + un détail subordonné */
.acte-guides { padding-block: var(--space-10) var(--space-8); }
.acte-guides__hero { margin: 0; overflow: hidden; border-radius: var(--radius-xl); }
.acte-guides__hero img { display: block; width: 100%; height: 45vh; object-fit: cover; }
.acte-guides__text { position: relative; z-index: 1; display: grid; gap: var(--space-3); text-align: left; margin: calc(-1 * var(--space-8)) auto 0; padding: var(--space-6) var(--space-5); border-radius: var(--radius-xl); background: var(--color-surface); box-shadow: var(--shadow-md); }
.acte-guides__lead { color: var(--color-text-muted); max-width: 32ch; margin-inline: 0; }
.acte-guides__link { font-weight: 700; color: var(--color-primary); text-decoration: none; }
.acte-guides__link:hover { text-decoration: underline; }
@media (min-width: 768px) {
  .acte-guides__hero img { height: 65vh; }
  .acte-guides__text { padding-block: var(--space-4) var(--space-6); }
}

/* ACTE 6 — Nos projets aux Açores : mini-hero éditorial, une seule image forte */
.acte-biens { padding-block: var(--space-8) var(--space-10); }
.acte-biens__hero { margin: 0; overflow: hidden; border-radius: var(--radius-xl); }
.acte-biens__hero img { display: block; width: 100%; height: 45vh; object-fit: cover; }
.acte-biens__text { position: relative; z-index: 1; display: grid; gap: var(--space-3); text-align: left; margin: calc(-1 * var(--space-8)) auto 0; padding: var(--space-6) var(--space-5); border-radius: var(--radius-xl); background: var(--color-surface); box-shadow: var(--shadow-md); }
.acte-biens__link { font-weight: 700; color: var(--color-primary); text-decoration: none; }
.acte-biens__link:hover { text-decoration: underline; }
@media (min-width: 768px) {
  .acte-biens__hero img { height: 65vh; }
}

/* ACTE 7 — CTA final */
.acte-final { padding-block: var(--space-10); text-align: center; }
.acte-final__statement { max-width: 28ch; margin: 0 auto var(--space-6); font-size: clamp(1.35rem, 4vw, 1.9rem); font-weight: 600; color: var(--color-text); }
.acte-final__cta { display: inline-flex; }

/* I18N-0.1 (2026-07-28, correctif suite retour Antoine REMY sur capture d'ecran) : le premier
   essai I18N-0.1 avait un bug reel -- le groupe "Langue" duplique dans le menu hamburger
   (.site-nav__lang-group) n'etait masque QUE sous 1024px, mais jamais masque AU-DESSUS : comme
   .site-nav__list devient un flex horizontal visible en permanence a partir de 1024px (regle
   preexistante ligne ~293), le groupe langue s'affichait EN PLUS du declencheur d'en-tete, cote a
   cote avec Accueil/Guides/Nos projets/Notre histoire (exactement ce que montre la capture). Le
   correctif retire cette duplication : un seul et unique composant, sur toutes les pages, a
   toutes les tailles d'ecran -- un declencheur compact "🌐 FR ▾" (memes dimensions que les autres
   boutons du header, cf. .site-header__map-cta, min-height 44px) ouvrant un menu deroulant
   (Francais / English / Portugues). Plus de logique de masquage conditionnel, donc plus de risque
   de ce type de bug. */
.dht-lang-switch { position: relative; display: inline-flex; flex-shrink: 0; }
.dht-lang-switch__trigger { display: inline-flex; align-items: center; gap: var(--space-1); min-height: 44px; padding: 0 var(--space-3); border: 1.5px solid var(--color-border); border-radius: var(--radius-pill); background: transparent; color: var(--color-text-muted); font-family: inherit; font-size: 0.85rem; font-weight: 700; letter-spacing: 0.02em; cursor: pointer; white-space: nowrap; transition: border-color 160ms ease, color 160ms ease; }
.dht-lang-switch__trigger:hover, .dht-lang-switch__trigger:focus-visible { border-color: var(--color-primary); color: var(--color-primary-strong); }
.dht-lang-switch__globe { font-size: 1rem; line-height: 1; }
.dht-lang-switch__chevron { width: 10px; height: 10px; flex-shrink: 0; transition: transform 160ms ease; }
.dht-lang-switch[data-open] .dht-lang-switch__chevron { transform: rotate(180deg); }
.dht-lang-switch__menu { position: absolute; z-index: 60; top: calc(100% + var(--space-2)); right: 0; min-width: 168px; margin: 0; padding: var(--space-1); list-style: none; border: 1px solid var(--color-border); border-radius: var(--radius-lg); background: var(--color-surface); box-shadow: var(--shadow-md, 0 12px 32px rgba(24, 49, 47, 0.16)); }
.dht-lang-switch__menu[hidden] { display: none; }
.dht-lang-switch__item { display: flex; align-items: center; gap: var(--space-2); width: 100%; padding: var(--space-2) var(--space-3); border: 0; border-radius: var(--radius-md); background: transparent; color: var(--color-text); font-family: inherit; font-size: 0.85rem; font-weight: 600; text-align: left; text-decoration: none; cursor: pointer; }
.dht-lang-switch__item:hover, .dht-lang-switch__item:focus-visible { background: var(--color-primary-soft); color: var(--color-primary-strong); }
.dht-lang-switch__item.is-active, .dht-lang-switch__item[aria-current="true"] { color: var(--color-primary-strong); font-weight: 700; background: var(--color-primary-soft); }
.dht-lang-switch__item .dht-lang-switch__flag { font-size: 1rem; line-height: 1; }

/* I18N-0.1 (2026-07-28, 3e correctif, valide par Antoine REMY) : le probleme de fond n'etait pas
   la hauteur du header mais la hierarchie visuelle -- et une regression reelle avait ete
   introduite au 2e correctif (le nom "DHT Azores" disparaissait completement sous 400px pour
   gagner de la place). Regle definitivement abandonnee :
     .site-brand span { display: none; }  -- SUPPRIMEE : la marque ne doit jamais disparaitre.
   A la place : (a) .site-brand passe en white-space:nowrap (regle de base ci-dessus) pour eviter
   l'empilement visuel involontaire "DHT / Azores" sur deux lignes constate en capture d'ecran
   (c'etait un retour a la ligne force par manque de largeur, pas une mise en page voulue) ; (b)
   une reduction PROGRESSIVE et bornee du logo/texte/espacements sur 2 paliers, jamais une
   disparition. Hauteur de header cible validee : ~60px desktop (voir --header-height ci-dessus),
   ~56px mobile/tablette (palier ci-dessous). */
@media (max-width: 1023.98px) {
  :root { --header-height: 56px; }
  .site-header__inner { padding-inline: var(--space-3); gap: var(--space-2); }
  .site-brand img { width: 36px; }
  .site-brand { font-size: 0.95rem; gap: var(--space-1); }
  .site-header__right { gap: var(--space-2); }
  .site-nav__toggle { min-height: 42px; min-width: 42px; }
  .site-header__map-cta { min-height: 42px; padding: 0 var(--space-3); font-size: 0.85rem; }
  .site-header__map-cta svg { width: 16px; height: 16px; }
  .dht-lang-switch__trigger { min-height: 42px; padding: 0 var(--space-2); gap: 4px; font-size: 0.8rem; }
}
/* Palier telephone etroit (iPhone SE 375px et en-dessous) : resserrage supplementaire, mais le nom
   "DHT Azores" reste toujours visible, en une seule ligne (voir white-space:nowrap ci-dessus). */
@media (max-width: 400px) {
  .site-header__inner { padding-inline: var(--space-2); gap: var(--space-1); }
  .site-brand img { width: 28px; }
  .site-brand { font-size: 0.78rem; gap: 6px; }
  .site-header__right { gap: 6px; }
  .site-nav__toggle { min-height: 40px; min-width: 40px; }
  .site-nav__toggle svg { width: 18px; height: 18px; }
  .site-header__map-cta { min-height: 40px; padding: 0 var(--space-2); font-size: 0.78rem; gap: 4px; }
  .dht-lang-switch__trigger { min-height: 40px; padding: 0 6px; gap: 2px; font-size: 0.75rem; }
  .dht-lang-switch__chevron { display: none; }
}

/* Bandeau "traduction a venir" (.dht-lang-banner) SUPPRIME le 2026-07-30 (Lot I18N-FINAL, demande
   Antoine REMY) : le mode data-dht-i18n="none" n'existe plus, toutes les pages sont desormais
   integralement traduites (mode "pages", voir dht-page-i18n.js). Regles CSS retirees avec lui. */

/* Note : .map-header__actions (conteneur du selecteur cote carte.html) est deja stylee dans
   carte.css -- aucune regle dupliquee ici, ce composant .dht-lang-switch s'insere comme un
   flex-item de plus dans ce rang existant. */

/* SO partner card, scoped integration on nos-biens only. */
.partner-card-link{display:flex;flex-direction:column;min-height:100%;color:inherit;text-decoration:none;cursor:pointer;transition:transform .2s ease,box-shadow .2s ease,background .2s ease,border-color .2s ease}.partner-card-link:hover,.partner-card-link:focus-visible{background:var(--color-primary);border-color:var(--color-primary-strong);color:#fff;text-decoration:none;transform:translateY(-3px);box-shadow:var(--shadow-md)}.partner-card-link:hover h3,.partner-card-link:focus-visible h3,.partner-card-link:hover p,.partner-card-link:focus-visible p,.partner-card-link:hover strong,.partner-card-link:focus-visible strong,.partner-card-link:hover .eyebrow,.partner-card-link:focus-visible .eyebrow{color:#fff}.partner-card-link__cta{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3);margin-top:auto;padding-top:var(--space-5);color:var(--color-primary);font-weight:700}.partner-card-link:hover .partner-card-link__cta,.partner-card-link:focus-visible .partner-card-link__cta{color:#fff}

.partner-card-link__logo{display:block!important;width:52px!important;height:52px!important;aspect-ratio:1!important;object-fit:cover!important;margin:0 0 var(--space-4)!important;border-radius:var(--radius-md)!important}.partner-card-link:hover .partner-card-link__logo,.partner-card-link:focus-visible .partner-card-link__logo{opacity:.94}
