@charset "utf-8";

/* =========================================================================
   POLICES, HÉBERGÉES SUR LE SITE
   Poppins 400 et 700, sous licence SIL Open Font License 1.1, sous-ensemble
   latin et latin étendu, en woff2. Aucune requête vers un tiers : le site ne
   contacte que son propre serveur, ce qui vaut aussi pour la vie privée des
   visiteurs. font-display: swap affiche le texte avec la pile système le
   temps du chargement, plutôt que de le masquer.
   ========================================================================= */
@font-face{
  font-family:"Poppins";
  src:url("fonts/poppins-400.woff2") format("woff2");
  font-weight:400;
  font-style:normal;
  font-display:swap;
}
@font-face{
  font-family:"Poppins";
  src:url("fonts/poppins-700.woff2") format("woff2");
  font-weight:700;
  font-style:normal;
  font-display:swap;
}

/* ==========================================================================
   AZUR DIGITAL SOLUTIONS, « Ads. »
   Feuille de style unique, partagée par index.html et bureaux.html
   --------------------------------------------------------------------------
   Sommaire
   01 Tokens
   02 Reset & base
   03 Cadre & sections
   04 Typographie
   05 Logo « Ads. »
   06 Navigation
   07 Boutons
   08 Éléments graphiques (disque, trame de points, barre de progression)
   09 Typographie fantôme
   10 Filets d'annotation
   11 Grilles & cartes
   12 Plan SVG
   13 Galerie
   14 Pied de page
   15 Accessibilité & responsive
   ========================================================================== */


/* 01 · TOKENS ============================================================= */

:root{
  /* Palette de marque */
  --ink:    #0D1117;
  --orange: #FF6A00;
  --paper:  #F4F4F2;
  --grey:   #D9D9D9;

  /* Orange assombri : SEULE variante autorisée pour du TEXTE sur fond clair.
     #FF6A00 sur #F4F4F2 ne fait que 2,6:1, insuffisant (AA = 4,5:1).
     #BF4E00 sur #F4F4F2 = 4,4:1, conforme. */
  --orange-deep: #BF4E00;

  /* Texte sur fond sombre */
  --on-dark:      #F4F4F2;               /* 17:1  */
  --on-dark-soft: rgba(244,244,242,.68); /* ~7:1  */
  --on-dark-faint:rgba(244,244,242,.42);
  --line-dark:    rgba(244,244,242,.14);
  --line-dark-2:  rgba(244,244,242,.20);

  /* Texte sur fond clair */
  --on-light:      #0D1117;
  --on-light-soft: #4A5058;              /* ~8:1  */
  --line-light:    #D9D9D9;

  /* Contextuel : redéfini par .sec--dark / .sec--paper */
  --fg:        var(--on-light);
  --fg-soft:   var(--on-light-soft);
  --rule:      var(--line-light);
  --accent-tx: var(--orange-deep);
  --focus:     #0D1117;
  /* Bouton d'action principal : APLAT OPAQUE, jamais du verre, jamais orange.
     Sur fond clair il est sombre ; sur fond sombre il est clair (motif Apple). */
  --btn-solid-bg: var(--ink);
  --btn-solid-fg: var(--paper);
  --btn-solid-hv: #1B2230;

  /* Surface opaque légèrement surélevée : c'est le matériau du CONTENU
     (cartes, plaques). Différenciée par l'élévation et un filet fin,
     jamais par de la transparence. */
  --surface-bg:     #FFFFFF;
  --surface-bg-2:   #F0F0EC;
  --surface-brd:    rgba(13,17,23,.09);
  --surface-shadow: 0 1px 2px rgba(13,17,23,.05), 0 16px 34px -24px rgba(13,17,23,.30);

  /* Verre, valeurs pour CONTEXTE CLAIR (plus dense que sur sombre).
     Le verre ne s'applique qu'à ce qui flotte au-dessus du contenu :
     barre de nav, pilules, pastilles, libellés d'annotation, cartes de
     prix, conteneur du plan. Les sections, elles, restent opaques. */
  --glass-bg:     rgba(255,255,255,.09);
  /* la surface qui porte les schémas : à peine détachée de la section */
  --art-bg:       rgba(13,17,23,.030);
  --art-brd:      rgba(13,17,23,.085);
  --glass-brd:    rgba(13,17,23,.10);
  --glass-hi:     rgba(255,255,255,.78);   /* reflet spéculaire, arête haute */
  --glass-shadow: 0 22px 48px -26px rgba(13,17,23,.32);
  --glass-solid:  rgba(255,255,255,.80);   /* repli sans backdrop-filter    */
  --glass-radius: clamp(16px, 2vw, 22px);
  --glass-blur:   blur(14px) saturate(135%);

  /* Mesures */
  --gap:      clamp(1rem, 3vw, 1.75rem);
  --pad-x:    clamp(1.25rem, 5vw, 4.5rem);
  --pad-y:    clamp(4.5rem, 11vw, 10rem);
  --measure:  62ch;
  --radius-frame: clamp(20px, 3vw, 34px);
  --radius-card:  clamp(14px, 1.6vw, 20px);

  --font: "Poppins", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
          "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif;
}


/* 02 · RESET & BASE ======================================================= */

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

html{
  -webkit-text-size-adjust:100%;
  scroll-behavior:smooth;
}

body{
  margin:0;
  font-family:var(--font);
  font-weight:400;
  font-size:clamp(1rem, .96rem + .18vw, 1.0625rem);
  line-height:1.62;
  color:var(--on-light);
  background:var(--paper);
  /* Dégradé directionnel doux, presque monochrome, derrière le cadre */
  background-image:
    linear-gradient(135deg, #FFFFFF 0%, #EFEFEC 42%, #DEDEDA 100%);
  background-attachment:fixed;
  overflow-x:hidden;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
}

img{ max-width:100%; height:auto; display:block; }
svg{ display:block; }

a{ color:inherit; }

::selection{ background:var(--orange); color:#fff; }


/* 02b · MATIÈRES ==========================================================

   Deux matériaux, et la règle qui décide lequel s'applique :

   .glass  , pour ce qui FLOTTE au-dessus du contenu qui défile. C'est-à-dire
              la barre de navigation, et les étiquettes posées par-dessus le
              dégradé du hero. RIEN D'AUTRE. Pas de bouton d'action, pas de
              carte, pas de pastille posée sur un fond plein : un contrôle
              translucide sans couleur propre ne fonctionne pas.

   .surface, pour le CONTENU. Une carte posée sur une section pleine est une
              surface opaque légèrement surélevée, différenciée par une ombre
              douce et un filet fin.

   Rayons concentriques : un élément imbriqué prend le rayon de son parent
   moins la marge intérieure. Les conteneurs ont un grand rayon
   (--radius-card), les contrôles sont des capsules (999px). */

/* Surface opaque, le matériau par défaut du contenu. */
.surface{
  background:var(--surface-bg);
  border:1px solid var(--surface-brd);
  border-radius:var(--radius-card);
  box-shadow:var(--surface-shadow);
}

.glass{
  position:relative;
  background:var(--glass-bg);
  border:1px solid var(--glass-brd);
  border-radius:var(--glass-radius);
  box-shadow:
    inset 0 1px 0 var(--glass-hi),
    inset 0 -1px 0 rgba(255,255,255,.06),
    var(--glass-shadow);
  -webkit-backdrop-filter:var(--glass-blur);
          backdrop-filter:var(--glass-blur);
}
/* Grain très fin : c'est ce qui empêche la matière de paraître plastique. */
.glass::before{
  content:"";
  position:absolute;
  inset:0;
  border-radius:inherit;
  pointer-events:none;
  background-image:radial-gradient(currentColor .5px, transparent .5px);
  background-size:4px 4px;
  /* Le grain reste, mais il ne doit plus que se deviner. */
  opacity:.028;
  mix-blend-mode:overlay;
}

/* Repli : fond opaque équivalent, ni transparence ni bouillie. */
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .glass{ background:var(--glass-solid); }
}


/* Même logique côté matière : sur petit écran le flou large et le grain
   coûtent cher pour un gain visuel faible sur un écran de cette taille. */
@media (max-width:1099px){
  :root{ --glass-blur:blur(9px) saturate(125%); }
  .glass::before{ display:none; }
}


/* 03 · CADRE & SECTIONS =================================================== */

/* Conteneur principal : encadré, très grand rayon, en retrait des bords. */
.frame{
  margin:clamp(8px, 1.6vw, 22px);
  border-radius:var(--radius-frame);
  /* overflow:clip découpe les angles SANS créer de conteneur de défilement :
     c'est ce qui permet à la barre de navigation de rester réellement
     collante. overflow:hidden, lui, casse position:sticky. La première
     déclaration sert de repli pour les moteurs qui ignorent « clip ». */
  overflow:hidden;
  overflow:clip;
  background:var(--ink);
  border:1px solid rgba(13,17,23,.10);
  box-shadow:
    0 1px 2px rgba(13,17,23,.06),
    0 24px 60px -28px rgba(13,17,23,.35);
  isolation:isolate;
}

/* Couche de fond vivante : collée en haut sur toute la hauteur du cadre,
   avec une marge négative pour ne rien occuper dans le flux. Le canvas
   qu'elle porte peint des nappes lentes par-dessus l'encre du cadre ;
   les sections sombres, semi-transparentes, les laissent transparaître.
   C'est ce mouvement que le flou de la barre de navigation vient déformer. */
.bg-layer{
  position:sticky;
  top:0;
  height:100vh;
  margin-bottom:-100vh;
  z-index:0;
  pointer-events:none;
}
.bg-layer canvas{ display:block; width:100%; height:100%; }
/* Voile sombre sous la barre de navigation : au repos elle est presque
   transparente, il faut donc garantir que ce qu'elle laisse voir reste
   sombre quel que soit l'état du fond animé. Mesuré : sans lui, les liens
   de la barre tombaient à 3,65:1 dans le pire cas du canvas. */
.bg-layer::after{
  content:"";
  position:absolute;
  inset:0 0 auto 0;
  height:190px;
  background:linear-gradient(to bottom, rgba(13,17,23,.72), rgba(13,17,23,0));
  pointer-events:none;
}

/* Le contenu passe au-dessus de la couche de fond. */
.frame > main,
.frame > footer{ position:relative; z-index:1; }

.sec{
  position:relative;
  padding:var(--pad-y) var(--pad-x);
}

.sec--dark{
  --fg:        var(--on-dark);
  --fg-soft:   var(--on-dark-soft);
  --rule:      var(--line-dark);
  --accent-tx: var(--orange);
  --focus:     var(--orange);
  --plan-bg:   #10161E;

  --btn-solid-bg: var(--paper);
  --btn-solid-fg: var(--ink);
  --btn-solid-hv: #FFFFFF;

  --surface-bg:     #161D27;
  --surface-bg-2:   #1D2531;
  --surface-brd:    rgba(244,244,242,.10);
  --surface-shadow: 0 1px 2px rgba(0,0,0,.30), 0 20px 44px -26px rgba(0,0,0,.62);

  /* Verre en contexte sombre : moins dense, reflet plus retenu. */
  --glass-bg:     rgba(244,244,242,.06);
  --art-bg:       rgba(244,244,242,.035);
  --art-brd:      rgba(244,244,242,.10);
  --glass-brd:    rgba(244,244,242,.14);
  --glass-hi:     rgba(255,255,255,.52);
  --glass-shadow: 0 26px 58px -26px rgba(0,0,0,.66);
  --glass-solid:  rgba(31,38,48,.94);

  color:var(--on-dark);
  /* Semi-transparente : le fond animé passe à travers. */
  background-color:rgba(13,17,23,.70);
  /* Trois nappes très étalées, deux froides, une chaude quasi
     imperceptible, plus la trame de points de la charte. Elles donnent au
     flou du verre quelque chose à déformer. */
  /* Aucune couche opaque ici : le dégradé directionnel de la charte est
     désormais porté par le canvas, en mouvement, derrière la section. Ne
     restent que la trame de points et deux nappes de renfort, translucides. */
  background-image:
    radial-gradient(rgba(244,244,242,.055) .9px, transparent .9px),
    radial-gradient(120% 85% at 14% -8%,  rgba(104,140,200,.13) 0%, rgba(104,140,200,0) 62%),
    radial-gradient(115% 95% at 62% 112%, rgba(126,156,205,.09) 0%, rgba(126,156,205,0) 60%);
  background-size:26px 26px, auto, auto;
  background-position:0 0, center, center;
  background-repeat:repeat, no-repeat, no-repeat;
}

.sec--paper{
  --fg:        var(--on-light);
  --fg-soft:   var(--on-light-soft);
  --rule:      var(--line-light);
  --accent-tx: var(--orange-deep);
  --focus:     #0D1117;
  --plan-bg:   #F4F4F2;
  color:var(--on-light);
  /* Les respirations claires restent calmes et opaques : le mouvement est
     réservé aux sections sombres, où le verre de la barre le déforme. */
  background-color:var(--paper);
  /* Même principe, nettement plus sourd : on doit sentir une profondeur,
     pas voir un décor. */
  background-image:
    radial-gradient(rgba(13,17,23,.028) .9px, transparent .9px),
    radial-gradient(105% 75% at 16% -6%, rgba(104,140,200,.10) 0%, rgba(104,140,200,0) 62%),
    radial-gradient(80% 60% at 90% 14%,  rgba(255,138,74,.038) 0%, rgba(255,138,74,0) 64%),
    linear-gradient(170deg, #FBFBF9 0%, #F4F4F2 60%, #EBEBE7 100%);
  background-size:26px 26px, auto, auto, auto;
  background-position:0 0, center, center, center;
  background-repeat:repeat, no-repeat, no-repeat, no-repeat;
}

.sec--tight{ padding-block:clamp(2.5rem, 5vw, 4rem); }

/* La barre étant réellement collante, les ancres doivent s'arrêter sous elle. */
[id]{ scroll-margin-top:calc(var(--navh, 88px) + 1rem); }

.wrap{
  max-width:1080px;
  margin-inline:auto;
  position:relative;
  z-index:1;
}
.wrap--narrow{ max-width:760px; }


hr.rule{
  border:0;
  border-top:1px solid var(--rule);
  margin:clamp(2.5rem,6vw,4.5rem) 0;
}


/* 04 · TYPOGRAPHIE ======================================================== */

h1,h2,h3,h4{
  font-weight:700;
  line-height:1.06;
  letter-spacing:-.025em;
  margin:0 0 .5em;
  text-wrap:balance;
}

.h-display{ font-size:clamp(2.35rem, 1.2rem + 5.2vw, 5rem); }
.h-1{ font-size:clamp(2rem, 1.15rem + 3.6vw, 3.6rem); }
.h-2{ font-size:clamp(1.5rem, 1.1rem + 1.8vw, 2.35rem); line-height:1.14; }
.h-3{ font-size:clamp(1.125rem, 1rem + .6vw, 1.375rem); line-height:1.25; }

p{ margin:0 0 1.1em; }
p:last-child{ margin-bottom:0; }

.lead{
  font-size:clamp(1.05rem, .98rem + .5vw, 1.3rem);
  line-height:1.55;
  color:var(--fg-soft);
  max-width:var(--measure);
}

.muted{ color:var(--fg-soft); }
.small{ font-size:.875rem; line-height:1.55; }

/* Accent orange, usage volontairement rare. */
.accent{ color:var(--accent-tx); }

/* Sur-titre de section */
.eyebrow{
  display:block;
  font-size:.72rem;
  font-weight:700;
  letter-spacing:.16em;
  text-transform:uppercase;
  color:var(--fg-soft);
  margin:0 0 1.25rem;
}

.center{ text-align:center; }
.center .lead{ margin-inline:auto; }



/* 05 · LOGO « Ads. » ====================================================== */

.logo{
  display:inline-flex;
  align-items:baseline;
  gap:.04em;
  font-weight:700;
  letter-spacing:-.045em;
  line-height:1;
  text-decoration:none;
  color:var(--fg);
  font-size:1.5rem;
}
.logo-dot{
  width:.24em;
  height:.24em;
  border-radius:50%;
  background:var(--orange);
  flex:none;
  transform:translateY(-.015em);
}

.baseline{
  font-size:.8rem;
  line-height:1.35;
  color:var(--fg-soft);
  letter-spacing:.005em;
  margin:.45rem 0 0;
}


/* 06 · NAVIGATION ========================================================= */

/* La barre flotte au-dessus du contenu qui défile : c'est le seul grand
   élément en verre. À plat contre le haut du cadre, donc sans rayon.

   Scroll edge effect : au repos elle est quasi invisible ; dès que du
   contenu passe dessous elle gagne en opacité, en flou et en séparation
   basse. La classe .is-scrolled est posée par quelques lignes de JS. */
/* C'est le <header> qui est collant, pas la barre elle-même : un élément
   sticky ne peut pas sortir des limites de son parent, et un <header> à la
   hauteur de la barre l'y enfermerait. Le header, lui, est enfant direct
   de .frame et couvre donc toute la page. */
.frame > header{
  position:sticky;
  top:0;
  z-index:20;
}
.nav{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:1rem;
  padding:.85rem var(--pad-x);
  color:var(--on-dark);
  border:0;
  border-bottom:1px solid transparent;
  border-radius:0;
  box-shadow:none;
  background:rgba(13,17,23,.20);
  -webkit-backdrop-filter:blur(0px) saturate(100%);
          backdrop-filter:blur(0px) saturate(100%);
  transition:background-color .28s ease, border-color .28s ease,
             box-shadow .28s ease, backdrop-filter .28s ease,
             -webkit-backdrop-filter .28s ease;
}
.nav.is-scrolled{
  background:var(--glass-bg-nav, rgba(13,17,23,.62));
  border-bottom-color:var(--glass-brd);
  box-shadow:inset 0 1px 0 var(--glass-hi), 0 10px 26px -20px rgba(0,0,0,.75);
  -webkit-backdrop-filter:var(--glass-blur);
          backdrop-filter:var(--glass-blur);
}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .nav{ background:rgba(13,17,23,.86); }
  .nav.is-scrolled{ background:rgba(13,17,23,.97); }
}
/* La barre est toujours sur fond sombre : elle bascule sur les jetons « sur sombre ». */
.nav{
  --fg:      var(--on-dark);
  --fg-soft: var(--on-dark-soft);
  --rule:    var(--line-dark-2);
  --focus:   var(--orange);
  /* jetons verre « sombre », la barre étant toujours sur fond ink */
  --glass-bg:     rgba(244,244,242,.05);
  --glass-brd:    rgba(244,244,242,.13);
  --glass-hi:     rgba(255,255,255,.30);
  --glass-shadow: 0 18px 40px -26px rgba(0,0,0,.6);
  --glass-solid:  rgba(31,38,48,.94);
  /* La barre est toujours sombre alors qu'elle survole des sections claires
     ET sombres. Il lui faut donc assez de densité pour rester lisible
     au-dessus de --paper : mesuré, .62 tombait à 3,4:1, .80 tient 5,7:1. */
  --glass-bg-nav: rgba(13,17,23,.80);
}

.nav-links{
  display:flex;
  align-items:center;
  gap:clamp(1rem, 3vw, 2.25rem);
  list-style:none;
  margin:0;
  padding:0;
}
.nav-links a{
  text-decoration:none;
  font-size:.9rem;
  color:var(--on-dark-soft);
  padding:.35rem .1rem;
  border-radius:4px;
  transition:color .2s ease;
}
.nav-links a:hover,
.nav-links a[aria-current="page"]{ color:var(--on-dark); }

/* Le CTA existe deux fois dans le balisage : une fois dans la liste (il ne
   sert que dans le panneau mobile) et une fois à côté, en clair sur grand
   écran. Chaque contexte n'en montre qu'un. */
.nav .nav-cta{ display:none; }

/* Bouton de menu : invisible tant qu'il n'y a pas de JS pour l'animer, et
   invisible au-dessus de 900px. Trois barres dessinées en CSS, cible
   tactile de 44px comme le demande le critère 2.5.8. */
.nav-toggle{
  display:none;
  width:44px;
  height:44px;
  flex:none;
  align-items:center;
  justify-content:center;
  padding:0;
  margin-right:-.35rem;
  background:none;
  border:0;
  border-radius:10px;
  color:var(--on-dark);
  cursor:pointer;
  -webkit-tap-highlight-color:transparent;
}
.nav-toggle:focus-visible{ outline:2px solid var(--focus); outline-offset:2px; }
.nav-toggle-bars,
.nav-toggle-bars::before,
.nav-toggle-bars::after{
  display:block;
  width:20px;
  height:1.5px;
  background:currentColor;
  border-radius:2px;
  transition:transform .24s ease, opacity .16s ease;
}
.nav-toggle-bars{ position:relative; }
.nav-toggle-bars::before,
.nav-toggle-bars::after{
  content:"";
  position:absolute;
  left:0;
}
.nav-toggle-bars::before{ top:-6px; }
.nav-toggle-bars::after{  top:6px; }
/* Ouvert : les deux barres extrêmes se croisent, celle du milieu disparaît. */
.nav-toggle[aria-expanded="true"] .nav-toggle-bars{ background:transparent; }
.nav-toggle[aria-expanded="true"] .nav-toggle-bars::before{ transform:translateY(6px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle-bars::after{  transform:translateY(-6px) rotate(-45deg); }

/* Sous 900px : la barre tient sur UNE rangée compacte.
   Mesuré sur iPhone 13 (390x844) : 56px de barre, soit 6,6% de la hauteur
   d'écran, contre 45% quand les liens et le bouton se répartissaient sur
   deux rangées. Les liens partent dans un panneau posé sous la barre. */
@media (max-width:899px){
  .nav{
    position:relative;
    padding:.4rem var(--pad-x);
    gap:.75rem;
  }
  .logo{ font-size:1.3rem; }
  .nav .nav-desk-cta{ display:none; }
  .nav .nav-cta{ display:block; }

  /* Sans JavaScript, aucun bouton ne peut ouvrir quoi que ce soit : les
     liens restent alors dans le flux, sur une seconde rangée. La page ne
     perd rien, elle est seulement un peu plus haute. */
  .nav{ flex-wrap:wrap; row-gap:.35rem; }
  .nav-links{ order:3; width:100%; justify-content:flex-start; gap:1rem; }
  .nav-links a{ font-size:.8rem; white-space:nowrap; }
  .nav .nav-cta{ margin-left:auto; }
  .nav .nav-cta a{ padding:.28rem .8rem; font-size:.76rem; white-space:nowrap; }

  /* Avec JavaScript : une seule rangée, et un panneau en superposition. */
  html.js .nav{ flex-wrap:nowrap; row-gap:0; }
  html.js .nav-toggle{ display:inline-flex; }
  html.js .nav-links{
    position:absolute;
    top:100%;
    left:0;
    right:0;
    order:0;
    width:auto;
    display:none;
    flex-direction:column;
    align-items:stretch;
    gap:0;
    padding:.2rem var(--pad-x) 1rem;
    background:rgba(13,17,23,.94);
    border-bottom:1px solid var(--glass-brd);
    box-shadow:0 22px 40px -26px rgba(0,0,0,.85);
    -webkit-backdrop-filter:var(--glass-blur);
            backdrop-filter:var(--glass-blur);
  }
  @supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
    html.js .nav-links{ background:rgba(13,17,23,.985); }
  }
  html.js .nav.is-open .nav-links{ display:flex; }
  html.js .nav-links li + li{ border-top:1px solid var(--line-dark); }
  html.js .nav-links a{
    display:flex;
    align-items:center;
    min-height:48px;
    font-size:1rem;
    color:var(--on-dark);
    padding:.35rem 0;
    border-radius:6px;
  }
  html.js .nav-cta{
    margin:.75rem 0 0;
    border-top:0;
  }
  html.js .nav-cta a{
    justify-content:center;
    min-height:48px;
    font-size:.95rem;
  }
}


/* 07 · BOUTONS ============================================================ */

/* Les contrôles sont des capsules. Par défaut : bouton SECONDAIRE, contour
   fin sur fond transparent. */
.btn{
  display:inline-flex;
  align-items:center;
  gap:.6rem;
  padding:.72rem 1.35rem;
  border:1px solid var(--rule);
  border-radius:999px;
  font-family:inherit;
  font-size:.9rem;
  font-weight:700;
  letter-spacing:.005em;
  text-decoration:none;
  color:var(--fg);
  background:transparent;
  cursor:pointer;
  transition:border-color .2s ease, background-color .2s ease,
             color .2s ease, transform .2s ease;
}
.btn:hover{ border-color:var(--fg); }
.btn:active{ transform:translateY(1px); }

.btn--sm{ padding:.5rem 1rem; font-size:.82rem; }

/* Bouton PRINCIPAL, aplat opaque. Sur fond sombre il est clair, sur fond
   clair il est sombre. Jamais translucide, jamais orange en aplat. */
.btn--primary{
  background:var(--btn-solid-bg);
  border-color:var(--btn-solid-bg);
  color:var(--btn-solid-fg);
}
.btn--primary:hover{
  background:var(--btn-solid-hv);
  border-color:var(--btn-solid-hv);
  color:var(--btn-solid-fg);
}

/* Bouton secondaire EN VERRE, réservé à ceux réellement posés sur le
   dégradé du hero, où il y a une matière à laisser voir. */
.btn--glass{ border-color:var(--glass-brd); }

.btn-arrow{ flex:none; }

.btn-row{
  display:flex;
  flex-wrap:wrap;
  gap:.75rem 1rem;
  align-items:center;
}


/* 08 · ÉLÉMENTS GRAPHIQUES ================================================ */

/* Disque orange */
.disc{
  width:.5rem; height:.5rem;
  border-radius:50%;
  background:var(--orange);
  display:inline-block;
  flex:none;
}
/* Seule survivance de l'orange sur les pastilles : 4 px. */
.disc--sm{ width:4px; height:4px; }


/* Barre de progression sombre → orange */
.progress{
  height:5px;
  border-radius:999px;
  background:linear-gradient(90deg, var(--ink) 0%, #33241B 46%, var(--orange) 100%);
  max-width:340px;
}
/* La barre de charte reste sombre -> orange, mais très atténuée :
   l'orange plein est désormais réservé au point du logo, au titre du
   hero, à l'arête du CTA et au point du plan. */
.sec--dark .progress{
  background:linear-gradient(90deg, rgba(244,244,242,.14) 0%, rgba(255,106,0,.20) 58%, rgba(255,106,0,.50) 100%);
}

/* Icônes en trait fin */
.ico{
  width:34px; height:34px;
  stroke:currentColor;
  stroke-width:1.25;
  fill:none;
  stroke-linecap:round;
  stroke-linejoin:round;
  flex:none;
}
.ico--sm{ width:24px; height:24px; stroke-width:1.35; }


/* 09 · TYPOGRAPHIE FANTÔME ================================================ */

.ghost-holder{
  position:absolute;
  inset:0;
  overflow:hidden;
  pointer-events:none;
  user-select:none;
  display:grid;
  place-items:center;
}
.ghost{
  font-weight:700;
  letter-spacing:-.05em;
  line-height:.82;
  white-space:nowrap;
  font-size:clamp(7rem, 24vw, 22rem);
  color:rgba(244,244,242,.045);           /* repli */
  transform:translateY(-2%);
}
/* Variante ancrée en bas : le fantôme devient une couche graphique distincte,
   posée sous le bloc de texte et débordant du bord inférieur de la section.
   Il ne doit jamais passer derrière un texte lisible. */
.ghost-holder--bottom{ place-items:end center; }
.ghost--wide{
  font-size:clamp(4.25rem, 18vw, 13rem);
  transform:translateY(32%);
}
@supports (-webkit-text-stroke:1px #000){
  .ghost{
    color:transparent;
    -webkit-text-stroke:1px rgba(244,244,242,.11);
  }
}
.sec--paper .ghost{ color:rgba(13,17,23,.035); }
@supports (-webkit-text-stroke:1px #000){
  .sec--paper .ghost{ color:transparent; -webkit-text-stroke:1px rgba(13,17,23,.10); }
}


/* 10 · FILETS D'ANNOTATION ================================================
   Motif signature : un petit label, un trait de 1px très discret qui part
   vers un détail. Décoratif : toujours doublé par du texte réel ailleurs. */

.annot{
  position:absolute;
  display:flex;
  align-items:center;
  gap:0;
  pointer-events:none;
  z-index:2;
}
/* Le libellé flotte au-dessus du fond : c'est du verre, en pilule. */
.annot-label{
  font-size:.75rem;
  line-height:1.25;
  letter-spacing:.01em;
  color:var(--fg-soft);
  white-space:nowrap;
  padding:.34rem .72rem;
  border-radius:999px;
}
.annot-rule{
  display:block;
  height:1px;
  background:currentColor;
  opacity:.22;
  flex:none;
}
.annot-dot{
  width:5px; height:5px;
  border-radius:50%;
  border:1px solid currentColor;
  opacity:.35;
  flex:none;
}
.annot--r .annot-label{ order:3; margin-left:.7rem; }
.annot--r .annot-rule{ order:2; width:clamp(48px,7vw,110px); }
.annot--r .annot-dot{ order:1; }
.annot--l .annot-label{ margin-right:.7rem; }
.annot--l .annot-rule{ width:clamp(48px,7vw,110px); }

/* Les filets flottants ne s'affichent qu'à partir de 1360px. Mesuré : en
   dessous, le cadre est trop étroit pour qu'une étiquette tienne à côté du
   texte à la hauteur du paragraphe d'introduction, et son filet coupait les
   lignes. À 1200 et 1280 il restait des chevauchements, à 1366 il n'y en a
   plus aucun. Le seuil existait déjà pour cette raison, il était simplement
   placé trop bas. */
.annot--float{ display:none; }
@media (min-width:1360px){
  .annot--float{ display:flex; }
}


/* 11 · GRILLES & CARTES =================================================== */

.grid{
  display:grid;
  gap:var(--gap);
  grid-template-columns:1fr;
}
@media (min-width:600px){
  .grid--2{ grid-template-columns:repeat(2,minmax(0,1fr)); }
}
@media (min-width:900px){
}



.card-ico{ color:var(--fg); opacity:.85; margin-bottom:1.1rem; }

/* Item simple sans bordure (valeurs) */
.item{ padding-top:1.25rem; border-top:1px solid var(--rule); }
.item h3{ font-size:1.0625rem; margin-bottom:.3rem; }
.item p{ color:var(--fg-soft); font-size:.92rem; margin:0; }

/* Carte espace (page bureaux) */
/* Les cartes de prix sont du contenu posé sur une section pleine : surface
   opaque, légèrement surélevée. */
.space{
  display:flex;
  flex-direction:column;
  gap:1.1rem;
  padding:clamp(1.5rem,3vw,2.25rem);
}

.space-tag{
  display:inline-flex;
  align-items:center;
  gap:.5rem;
  font-size:.72rem;
  font-weight:700;
  letter-spacing:.16em;
  text-transform:uppercase;
  color:var(--fg-soft);
}
.space-meta{
  font-size:.95rem;
  color:var(--fg-soft);
  margin:0;
}
.price-block{
  margin-top:auto;
  padding-top:1.1rem;
  border-top:1px solid var(--rule);
}
.price{
  display:flex;
  flex-wrap:wrap;
  align-items:baseline;
  gap:.25rem .55rem;
  margin:0;
}
.price-amount{
  font-size:clamp(1.85rem,1.2rem + 2vw, 2.6rem);
  font-weight:700;
  letter-spacing:-.03em;
  line-height:1;
}
.price-unit{ font-size:.95rem; color:var(--fg-soft); }

/* « tout compris » reste attaché au prix : c'est l'argument central.
   La pastille est en verre ; il n'en reste qu'un point orange de 4 px. */
.price-all{ margin:.8rem 0 0; }
.chip{
  display:inline-flex;
  align-items:center;
  gap:.5rem;
  padding:.42rem .85rem;
  border-radius:999px;            /* capsule : c'est un contrôle, pas un bloc */
  border:1px solid var(--surface-brd);
  background:var(--surface-bg-2);
  font-size:.82rem;
  font-weight:700;
  letter-spacing:.02em;
  color:var(--fg);
}

.list{
  list-style:none;
  margin:0;
  padding:0;
  display:grid;
  gap:.55rem;
}
.list li{
  position:relative;
  padding-left:1.35rem;
  font-size:.94rem;
  color:var(--fg-soft);
}
.list li::before{
  content:"";
  position:absolute;
  left:0; top:.62em;
  width:6px; height:1px;
  background:currentColor;
  opacity:.55;
}
.list--strong li{ color:var(--fg); }

/* Bandeau de chiffres clés */
.figures{
  display:grid;
  gap:clamp(1.5rem,4vw,3rem);
  grid-template-columns:1fr;
}
@media (min-width:640px){ .figures{ grid-template-columns:repeat(3,minmax(0,1fr)); } }
.figure-n{
  font-size:clamp(2rem,1.4rem + 2.4vw,3rem);
  font-weight:700;
  letter-spacing:-.03em;
  line-height:1;
  margin:0 0 .4rem;
}
.figure-l{ font-size:.86rem; color:var(--fg-soft); margin:0; }

/* Grille « ce qui est inclus » */
.incl{
  display:grid;
  gap:clamp(1.1rem,2.4vw,1.75rem);
  grid-template-columns:repeat(2,minmax(0,1fr));
  list-style:none;
  margin:0;
  padding:0;
}
@media (min-width:640px){ .incl{ grid-template-columns:repeat(3,minmax(0,1fr)); } }
@media (min-width:960px){ .incl{ grid-template-columns:repeat(4,minmax(0,1fr)); } }
.incl li{
  display:flex;
  flex-direction:column;
  gap:.7rem;
  padding-top:1rem;
  border-top:1px solid var(--rule);
  font-size:.88rem;
  line-height:1.4;
}
.incl .ico{ opacity:.8; }


/* 11b · COMPOSANTS DE LA PAGE D'ACCUEIL ET DES PAGES LÉGALES ============== */

/* Sous-ligne du h1 : porte la localisation sans casser le titre en deux. */
.h1-sub{
  display:block;
  margin-top:1.1rem;
  font-size:clamp(1rem,.9rem + .5vw,1.25rem);
  font-weight:400;
  letter-spacing:0;
  line-height:1.4;
  color:var(--fg-soft);
}



/* FAQ : questions et réponses en clair dans le document, pas repliées ,
   elles doivent être lisibles et indexables. */
.faq{ display:grid; gap:var(--gap); }
.faq-item{ padding:clamp(1.35rem,2.4vw,1.9rem); }
.faq-item h3{ font-size:1.05rem; margin:0 0 .5rem; }
.faq-item p{ color:var(--fg-soft); font-size:.95rem; margin:0; }

/* Réseaux sociaux dans le pied de page. */
.foot-social{
  display:inline-flex;
  align-items:center;
  gap:.5rem;
  text-decoration:none;
  color:var(--fg-soft);
}
.foot-social:hover{ color:var(--fg); }
.foot-social svg{ width:16px; height:16px; flex:none; }

/* Pages légales : une seule colonne de lecture, du texte long. */
.prose{ max-width:70ch; }
.prose h2{
  font-size:clamp(1.2rem,1.05rem + .6vw,1.6rem);
  margin:clamp(2.5rem,5vw,3.5rem) 0 .7rem;
}
.prose h2:first-child{ margin-top:0; }
.prose h3{ font-size:1.02rem; margin:1.8rem 0 .45rem; }
.prose p, .prose li{ color:var(--fg-soft); font-size:.97rem; }
.prose ul{ margin:0 0 1.1em; padding-left:1.15rem; }
.prose li{ margin-bottom:.4rem; }
.prose a{ color:var(--fg); text-underline-offset:3px; }

/* Encart d'avertissement des pages légales. */


/* 11c · SCÈNES, SECTION ÉPINGLÉE, OBJET DU HERO ==========================*/

/* --- L'objet du hero -------------------------------------------------- */
.hero-object{
  position:absolute;
  inset:0;
  z-index:0;
  pointer-events:none;
}
.hero-object canvas{
  display:block; width:100%; height:100%;
  /* Pas de mask-image ici : l'atténuation de la colonne de lecture est
     calculée dans le canvas, par particule. Un masque CSS sur une surface
     de cette taille coûtait 16 images par seconde. */
}
.hero-copy{ position:relative; z-index:2; }

/* Sur écran étroit la colonne de lecture occupe presque toute la largeur :
   le masque doit alors protéger bien plus large, et l'objet s'atténue.
   Mesuré : sans cela le sous-titre tombait à 3,42:1 quand une traînée
   passait derrière lui. */
/* Sous 1100 px la composition bascule à la verticale : le flux descend.
   Une bande est dégagée sous la barre de navigation pour que la dispersion,
   le seuil et le début de la condensation soient réellement dans la
   première image ; plus bas, l'objet passe derrière le texte, atténué. */
@media (max-width:1099px){
  .sec--hero{ padding-top:clamp(11rem, 30vw, 15rem) !important; }
}

/* --- Scènes pleine largeur, alternées --------------------------------- */
.scene{
  display:grid;
  gap:clamp(2.5rem,6vw,5.5rem);
  align-items:center;
  padding-block:clamp(4rem,9vw,7.5rem);
  border-top:1px solid var(--rule);
}
.scene:first-of-type{ border-top:0; padding-top:clamp(1.5rem,4vw,3rem); }
@media (min-width:900px){
  /* Le visuel occupe TOUJOURS la colonne large, y compris quand la scène est
     retournée : sans cela les schémas retournés seraient cadrés plus serré
     que les autres et la famille se verrait de travers. */
  .scene{ grid-template-columns:minmax(0,5fr) minmax(0,6fr); }
  .scene--flip{ grid-template-columns:minmax(0,6fr) minmax(0,5fr); }
  .scene--flip .scene-text{ order:2; }
  .scene--flip .scene-art{ order:1; }
}
.scene-text h3{
  font-size:clamp(1.4rem,1.1rem + 1.2vw,2.05rem);
  margin:.9rem 0 .7rem;
}
.scene-text p{ color:var(--fg-soft); max-width:46ch; margin:0; }
.scene-index{
  font-size:.72rem;
  font-weight:700;
  letter-spacing:.18em;
  text-transform:uppercase;
  color:var(--fg-soft);
}
/* La hauteur de la scène est celle du plus grand des deux blocs. Le visuel
   ne l'impose plus : il est plafonné et se centre dans la place disponible,
   ce qui supprime le vide sous les paragraphes courts. */
/* Le schéma est posé sur une surface légère et délimitée : sans elle il
   flotte, et des traits fins sur du papier ne se lisent pas comme un objet.
   Le fond se distingue à peine de la section, le filet est fin, et le rayon
   est celui des cartes du reste de la page. La boîte a le même rapport pour
   les quatre : c'est là que passe l'harmonie d'échelle. */
.scene-art{
  position:relative;
  width:100%;
  aspect-ratio:560 / 330;
  max-height:none;
  display:flex;
  align-items:center;
  justify-content:center;
  padding:clamp(.9rem, 2vw, 1.6rem);
  background:var(--art-bg);
  border:1px solid var(--art-brd);
  border-radius:var(--radius-card);
}
/* La couche de flux : posée par-dessus le schéma, hors du flux de mise en
   page, et transparente à la souris comme au toucher. Elle n'existe que si le
   JS l'ajoute, et jamais sous prefers-reduced-motion. */
.scene-art .flow-canvas{
  position:absolute;
  inset:0;
  width:100%;
  height:100%;
  pointer-events:none;
}
/* Le dessin remplit la surface. Les quatre n'ont pas le même rapport interne,
   preserveAspectRatio les centre donc sans jamais les déformer, et la surface
   commune leur donne la même échelle apparente. */
.scene-art svg{
  width:100%;
  height:100%;
  overflow:visible;
}

/* Le tracé des scènes : armé en JS seulement, donc visible sans JS. */
/* SYSTÈME DE DESSIN DES QUATRE SCHÉMAS
   Les sujets restent figuratifs et reconnaissables, c'est le système qui les
   met en famille : deux graisses de trait et pas une de plus, tout calé sur
   une grille de 8 unités, un seul rayon d'angle de 8, au plus trois éléments
   intérieurs par objet, aucun aplat ni volume, et le même mouvement de
   gauche à droite jusqu'à un unique point orange minuscule. */

/* Graisse 1 : les contours. Un cran au dessus du niveau d'avant
   l'allègement : sur une surface, un trait trop clair se perd. */
.scene-art .s-line{
  fill:none;
  stroke:currentColor;
  stroke-width:1.25;
  stroke-linejoin:round;
  stroke-linecap:round;
  opacity:.62;
}
/* Graisse 2 : les détails secondaires. */
.scene-art .s-line--soft{
  stroke-width:1;
  opacity:.36;
}
/* Les aplats des schémas : très légers, ils ne servent qu'à donner un corps
   aux volumes de l'entonnoir et aux blocs d'interface. */
.scene-art .s-fill{ fill:currentColor; stroke:none; opacity:.085; }
.scene-art .s-block{ fill:currentColor; stroke:none; opacity:.10; }
.scene-art .s-dot{ fill:currentColor; opacity:.50; }
.scene-art .s-hot{ fill:var(--orange); }

/* Le tracé des scènes suit le défilement : c'est l'utilisateur qui dessine
   le visuel en descendant, et le tracé se défait s'il remonte. La plage est
   « entry 36 % » à « cover 64 % » : mesuré, le sujet est en train de se
   terminer quand la scène atteint le centre de la fenêtre, et complet bien
   avant qu'elle ne sorte du champ. */

/* Le tracé des scènes est piloté par UNE seule progression, calculée en JS et
   posée dans --p, --pi et --ph. On n'utilise pas ici les chronologies de vue
   du CSS : chacune se cale sur la boîte de SON élément, si bien qu'un grand
   cadre de page se termine après un petit filet intérieur et que l'ordre de
   construction s'inverse. Une progression unique par scène garantit l'ordre :
   la silhouette, puis les éléments intérieurs, puis le point d'aboutissement. */
@media (prefers-reduced-motion:no-preference){
  html.js-scrub .scene-art .s-line,
  html.js-scrub .scene-art .s-line--soft{
    stroke-dasharray:1000;
    /* en px : sans unité, la valeur reste un calc() non résolu que les
       lectures de style ne savent pas interpréter */
    stroke-dashoffset:calc(1000px * (1 - var(--p, 0)));
  }
  /* --pi retarde les éléments intérieurs, --ph le point d'aboutissement. */
  html.js-scrub .scene-art .s-line--soft{
    stroke-dashoffset:calc(1000px * (1 - var(--pi, 0)));
  }
  html.js-scrub .scene-art .s-fill { opacity:calc(var(--pi, 0) * .085); }
  html.js-scrub .scene-art .s-block{ opacity:calc(var(--pi, 0) * .10); }
  html.js-scrub .scene-art .s-dot  { opacity:calc(var(--ph, 0) * .50); }
  html.js-scrub .scene-art .s-hot  { opacity:var(--ph, 0); }
}

/* Les rails ne sont que de la géométrie : ils portent le flux, ils ne se
   voient jamais. Ils sont échantillonnés une fois par le JS, qui en tire les
   trajectoires suivies sur la couche canvas. */
.scene-art .rails{ pointer-events:none; }
.scene-art .rail{ fill:none; stroke:none; }
/* Le battement de réception. Son opacité est pilotée par l'attribut SVG :
   une déclaration CSS d'opacity l'écraserait.
   Sur le point d'aboutissement c'est la pastille qui enfle ; sur un bloc
   d'action c'est son contour qui s'allume, jamais un aplat. */
.scene-art .pulse{ fill:currentColor; }
.scene-art .pulse--hot{ fill:var(--orange); }
.scene-art .pulse--goal{ fill:none; stroke:var(--orange); stroke-width:1.4; }

/* --- Méthode : section épinglée --------------------------------------- */
.pinned{ display:grid; gap:clamp(2rem,5vw,4rem); }
@media (min-width:900px){
  .pinned{ grid-template-columns:minmax(0,4fr) minmax(0,6fr); align-items:start; }
  /* Un élément collant décroche dès que le bas de son conteneur remonte
     au dessus de (top + sa propre hauteur). La colonne est donc tenue
     courte : sans cela l'indicateur sortait du champ aux trois quarts du
     parcours des quatre étapes. */
  .pinned-head{ position:sticky; top:4rem; }
  .pinned-head .lead{ font-size:1rem; line-height:1.5; }
}
.pinned-steps{ list-style:none; margin:0; padding:0; display:grid; gap:clamp(1rem,2.5vw,1.5rem); }

.pstep{
  padding:clamp(1.5rem,2.6vw,2.15rem);
  transition:opacity .45s ease, transform .45s cubic-bezier(.22,.7,.28,1);
}
/* Ces cartes flottent au-dessus du fond animé : c'est du verre, pas une
   surface opaque. L'étape active est un peu plus dense que les autres. */
.pstep{ --glass-bg:rgba(244,244,242,.05); }
.pstep.is-active{ --glass-bg:rgba(244,244,242,.09); }
.step-meter{ --glass-bg:rgba(244,244,242,.06); padding:1.1rem 1.25rem; }
@media (min-width:900px) and (prefers-reduced-motion:no-preference){
  .pstep{ opacity:.42; }
  .pstep.is-active{ opacity:1; }
}
.pstep h3{ font-size:clamp(1.1rem,1rem + .4vw,1.3rem); margin:0 0 .55rem; }
.pstep p{ color:var(--fg-soft); font-size:.95rem; margin:0; }
.pstep-n{
  display:block;
  font-size:.8rem; font-weight:700; letter-spacing:.18em;
  color:var(--fg-soft); margin-bottom:.9rem;
}

/* L'indicateur d'étape qui reste en place */
.step-meter{ margin-top:2rem; }
.step-meter-top{
  display:flex; align-items:baseline; gap:.6rem;
  font-weight:700; letter-spacing:.1em; font-size:.8rem;
}
.step-meter-num{ font-size:clamp(2.2rem,1.6rem + 2vw,3.2rem); letter-spacing:-.03em; line-height:1; }
.step-meter-label{ color:var(--fg-soft); font-size:.86rem; letter-spacing:.02em; font-weight:400; }
.step-bar{
  margin-top:1.1rem;
  height:2px;
  background:var(--rule);
  border-radius:999px;
  overflow:hidden;
}
.step-bar::after{
  content:"";
  display:block;
  height:100%;
  width:var(--p,25%);
  background:linear-gradient(90deg, rgba(244,244,242,.35), rgba(255,106,0,.55));
  transition:width .5s cubic-bezier(.22,.7,.28,1);
}


/* Sur mobile la colonne défile avec les cartes : l'indicateur devient une
   barre compacte collée sous la barre de navigation, visible pendant tout le
   parcours des quatre étapes puis relâchée avec la section. display:contents
   sur l'en tête sort l'indicateur de sa boîte, dont la hauteur limiterait
   sinon la zone de collage. */
@media (max-width:899px){
  .pinned{ gap:0; }
  .pinned-head{ display:contents; }
  .pinned-head .lead{ margin-bottom:1.25rem; }
  .step-meter{
    position:sticky;
    top:var(--navh, 58px);
    z-index:15;
    margin:0 0 1.5rem;
    padding:.5rem .85rem;
    display:flex;
    align-items:center;
    gap:.85rem;
  }
  .step-meter-top{ margin:0; display:flex; align-items:baseline; gap:.45rem; flex:none; }
  .step-meter-num{ font-size:1.45rem; }
  .step-meter-label{ font-size:.78rem; }
  .step-bar{ flex:1; margin-top:0; }
  .pinned-steps{ margin-top:0; }
}


/* 12 · PLAN SVG =========================================================== */

/* Le plan est du contenu : plaque opaque, pas du verre. */
.plan-scroll{
  overflow-x:auto;
  overflow-y:hidden;
  -webkit-overflow-scrolling:touch;
  padding:clamp(1rem,2.4vw,1.6rem);
  scrollbar-width:thin;
}
.plan{
  width:100%;
  min-width:900px;              /* garantit des labels lisibles ; scroll interne */
  height:auto;
  color:var(--fg);
}
@media (min-width:1100px){
  .plan{ min-width:0; }
  .plan-scroll{ max-width:960px; margin-inline:auto; overflow:visible; }
}

.plan .wall{
  fill:none;
  stroke:currentColor;
  stroke-width:1.4;
  stroke-linejoin:round;
  stroke-linecap:square;
  opacity:.75;
}
.plan .wall--inner{ stroke-width:1.2; opacity:.6; }
/* Les surfaces commercialisées se distinguent par un liseré posé en retrait
   des murs, jamais par un aplat : le système de dessin de la page n'en
   comporte aucun. Même rayon d'angle que les cartes. */
.plan .zone{ fill:none; stroke:currentColor; stroke-width:1; opacity:.34; stroke-dasharray:none; }
.plan .door{ fill:none; stroke:currentColor; stroke-width:1; opacity:.45; }
/* Gaine technique : le carré barré en croix du plan de repérage. */
.plan .duct{ fill:none; stroke:currentColor; stroke-width:1; opacity:.5; }

/* Le filet d'annotation, version SVG : 1px, ~20% d'opacité. */
.plan .lead{ fill:none; stroke:currentColor; stroke-width:1; opacity:.28; }
.plan .lead-dot{ fill:currentColor; opacity:.45; }
.plan .lead-dot--hi{ fill:var(--orange); opacity:1; }

.plan text{ font-family:var(--font); fill:currentColor; }
.plan .t-label{ font-size:15px; font-weight:700; letter-spacing:-.01em; }
.plan .t-sub{ font-size:13px; opacity:.62; }
.plan .t-room{ font-size:13px; font-weight:700; letter-spacing:.08em; opacity:.9; }
.plan .t-room-sub{ font-size:12px; opacity:.6; }
.plan .t-micro{ font-size:10.5px; letter-spacing:.14em; opacity:.64; }
/* Libellés inscrits dans les parties communes, un seul traitement pour les trois. */
.plan .t-common{ font-size:10px; letter-spacing:.06em; opacity:.64; }


.plan-note{
  font-size:.78rem;
  color:var(--fg-soft);
  margin:1rem 0 0;
}
.plan-hint{
  font-size:.78rem;
  color:var(--fg-soft);
  margin:0 0 1rem;
}
@media (min-width:1100px){ .plan-hint{ display:none; } }

/* Lecture textuelle du plan, utile en mobile et pour les lecteurs d'écran. */
.plan-key{
  list-style:none;
  margin:1.75rem 0 0;
  padding:0;
  display:grid;
  gap:.65rem;
}
@media (min-width:700px){ .plan-key{ grid-template-columns:repeat(2,minmax(0,1fr)); column-gap:2.5rem; } }
.plan-key li{
  display:flex;
  gap:.7rem;
  align-items:baseline;
  font-size:.88rem;
  color:var(--fg-soft);
  padding-top:.65rem;
  border-top:1px solid var(--rule);
}
.plan-key b{ color:var(--fg); font-weight:700; flex:none; }


/* --- Le plan se dessine (page bureaux) ----------------------------------
   Séquencé : murs, pièces, porte, filets, étiquettes, point orange. Une
   seule fois. Les classes sont posées en JS, donc sans JS le plan est
   complet et immobile. */
@media (prefers-reduced-motion:no-preference){
  .plan.is-armed .wall,
  .plan.is-armed .door,
  .plan.is-armed .duct{ stroke-dasharray:2600; stroke-dashoffset:2600; }
  .plan.is-armed .zone{ opacity:0; }
  .plan.is-armed text{ opacity:0; }
  .plan.is-armed .lead{ stroke-dasharray:700; stroke-dashoffset:700; }
  .plan.is-armed .lead-dot{ opacity:0; transform:scale(0); }
  .plan.is-armed .door-leaf{ transform:rotate(-88deg); }

  .plan.is-drawn .wall{
    stroke-dashoffset:0;
    transition:stroke-dashoffset 1.6s cubic-bezier(.3,.7,.25,1);
  }
  .plan.is-drawn .duct{
    stroke-dashoffset:0;
    transition:stroke-dashoffset .9s ease 1.1s;
  }
  .plan.is-drawn .zone{
    opacity:.34;
    transition:opacity .7s ease;
  }
  .plan.is-drawn .zone--a{ transition-delay:.75s; }
  .plan.is-drawn .zone--b{ transition-delay:.95s; }
  .plan.is-drawn .zone--c{ transition-delay:1.15s; }

  /* la porte s'ouvre : c'est l'argument de la page */
  .plan.is-drawn .door-leaf{
    transform:none;
    transition:transform 1s cubic-bezier(.34,.8,.3,1) 1.5s;
  }
  .plan.is-drawn .door{
    stroke-dashoffset:0;
    transition:stroke-dashoffset 1s ease 1.4s;
  }
  .plan.is-drawn text{ opacity:1; transition:opacity .6s ease 1.15s; }
  .plan.is-drawn .t-label,
  .plan.is-drawn .t-sub{ transition-delay:2.5s; }
  .plan.is-drawn .lead{
    stroke-dashoffset:0;
    transition:stroke-dashoffset 1.1s cubic-bezier(.3,.7,.25,1) 2.1s;
  }
  .plan.is-drawn .lead-dot{
    opacity:.45; transform:scale(1);
    transition:opacity .45s ease 2.9s, transform .45s cubic-bezier(.2,1.5,.4,1) 2.9s;
  }
  .plan.is-drawn .lead-dot--hi{ opacity:1; transition-delay:3.15s; }
}
/* le gond de la porte, en coordonnées du viewBox */
.plan .door-leaf{ transform-box:view-box; transform-origin:613px 131px; }


/* 13 · GALERIE ============================================================ */

.gallery{
  display:grid;
  gap:var(--gap);
  grid-template-columns:1fr;
  margin:0;
  padding:0;
}
@media (min-width:560px){ .gallery{ grid-template-columns:repeat(2,minmax(0,1fr)); } }
@media (min-width:960px){ .gallery{ grid-template-columns:repeat(3,minmax(0,1fr)); } }

.shot{ margin:0; }
.shot img{
  width:100%;
  aspect-ratio:3 / 2;
  object-fit:cover;
  border-radius:calc(var(--radius-card) - 4px);
  background:#E7E7E4;
  border:1px solid var(--rule);
}
.shot figcaption{
  font-size:.78rem;
  color:var(--fg-soft);
  margin-top:.6rem;
  letter-spacing:.02em;
}


/* 14 · PIED DE PAGE ======================================================= */

.foot{
  display:grid;
  gap:2rem;
  align-items:start;
}
@media (min-width:760px){
  .foot{ grid-template-columns:1.2fr 1fr 1fr; gap:3rem; }
}
.foot h2{ font-size:.72rem; letter-spacing:.16em; text-transform:uppercase; color:var(--fg-soft); font-weight:700; margin:0 0 .9rem; }
.foot-list{ list-style:none; margin:0; padding:0; display:grid; gap:.5rem; font-size:.9rem; color:var(--fg-soft); }
.foot-list a{ color:var(--fg-soft); text-decoration:none; border-bottom:1px solid transparent; }
.foot-list a:hover{ color:var(--fg); border-bottom-color:var(--rule); }

.foot-legal{ display:inline-flex; flex-wrap:wrap; gap:.4rem 1.4rem; }
.foot-legal a{ color:inherit; text-decoration:none; border-bottom:1px solid transparent; }
.foot-legal a:hover{ color:var(--fg); border-bottom-color:var(--rule); }

.foot-bottom{
  margin-top:clamp(2.5rem,6vw,4rem);
  padding-top:1.25rem;
  border-top:1px solid var(--rule);
  display:flex;
  flex-wrap:wrap;
  gap:.5rem 1.5rem;
  justify-content:space-between;
  font-size:.78rem;
  color:var(--fg-soft);
}

/* Placeholder à remplacer par le client */
.ph{
  font-weight:700;
  color:var(--fg);
  border-bottom:1px dashed var(--rule);
  padding-bottom:1px;
  white-space:nowrap;
}


/* 14b · MOUVEMENT =========================================================

   Trois règles tenues partout dans ce fichier :
   1. l'état AU REPOS est l'état visible. Rien n'est parqué à opacity:0 en
      attendant un observateur : sans JS, la page est entière ;
   2. le pilotage par le défilement passe par animation-timeline: view()
      quand le moteur le supporte, sinon par une classe posée en JS ;
   3. prefers-reduced-motion neutralise tout, sans exception. */

@keyframes rise{
  from{ opacity:0; transform:translateY(20px); }
  to  { opacity:1; transform:none; }
}

/* Chemin CSS pur : l'apparition suit le défilement, sans JavaScript. */
@supports (animation-timeline:view()){
  @media (prefers-reduced-motion:no-preference){
    .reveal{
      animation:rise linear both;
      animation-timeline:view();
      animation-range:entry 4% cover 20%;
    }
  }
}

/* Repli : la classe n'est posée qu'en JS, donc sans JS rien n'est masqué. */
html.js-reveal .reveal{
  opacity:0;
  transform:translateY(20px);
  transition:opacity .5s cubic-bezier(.22,.7,.28,1),
             transform .5s cubic-bezier(.22,.7,.28,1);
}
html.js-reveal .reveal.is-in{ opacity:1; transform:none; }

/* Décalages courts pour que les éléments d'une même rangée ne partent pas
   tous ensemble. */
html.js-reveal .reveal--d1{ transition-delay:.07s; }
html.js-reveal .reveal--d2{ transition-delay:.14s; }
html.js-reveal .reveal--d3{ transition-delay:.21s; }

/* --- Icônes : elles se tracent, puis répondent au survol -------------- */
@media (prefers-reduced-motion:no-preference){
  @supports (animation-timeline:view()){
    .ico [pathLength],
    .ico path, .ico circle, .ico rect{
      animation:trace 1.1s cubic-bezier(.3,.7,.2,1) both;
      animation-timeline:view();
      animation-range:entry 0% cover 18%;
    }
  }
}
@keyframes trace{
  from{ stroke-dasharray:100; stroke-dashoffset:100; }
  to  { stroke-dasharray:100; stroke-dashoffset:0; }
}
.card-ico .ico,
.domain-ico .ico{ transition:transform .35s cubic-bezier(.22,.7,.28,1); }
.surface:hover .card-ico .ico,
.surface:hover .domain-ico .ico{ transform:translateY(-2px) scale(1.05); }

/* --- Reflet spéculaire qui suit le curseur ---------------------------- */
.btn, .surface{ position:relative; }
.btn::after, .surface::after{
  content:"";
  position:absolute;
  inset:0;
  border-radius:inherit;
  pointer-events:none;
  background:radial-gradient(180px circle at var(--mx,50%) var(--my,-40%),
             var(--sheen, rgba(255,255,255,.13)), transparent 62%);
  opacity:0;
  transition:opacity .3s ease;
}
.btn:hover::after,
.surface:hover::after{ opacity:1; }
.sec--paper .surface{ --sheen:rgba(13,17,23,.055); }
.btn--primary{ --sheen:rgba(13,17,23,.07); }
.sec--paper .btn--primary{ --sheen:rgba(255,255,255,.16); }
@media (hover:none){
  .btn::after, .surface::after{ display:none; }
}


/* 15 · ACCESSIBILITÉ & RESPONSIVE ========================================= */

a:focus-visible,
button:focus-visible,
.btn:focus-visible,
[tabindex]:focus-visible{
  outline:2px solid var(--focus);
  outline-offset:3px;
  border-radius:6px;
}

.skip{
  position:absolute;
  left:-9999px;
  top:0;
  z-index:100;
  background:var(--paper);
  color:var(--ink);
  padding:.7rem 1.1rem;
  border-radius:0 0 8px 0;
  font-size:.9rem;
  font-weight:700;
  text-decoration:none;
}
.skip:focus{ left:0; }

.visually-hidden{
  position:absolute;
  width:1px; height:1px;
  margin:-1px; padding:0;
  overflow:hidden;
  clip:rect(0 0 0 0);
  clip-path:inset(50%);
  white-space:nowrap;
  border:0;
}

@media (prefers-reduced-motion:reduce){
  html{ scroll-behavior:auto; }
  *,*::before,*::after{
    animation-duration:.01ms !important;
    animation-iteration-count:1 !important;
    animation-delay:0s !important;
    transition-duration:.01ms !important;
    scroll-behavior:auto !important;
  }
  /* Tout ce qui n'apparaît qu'à l'animation devient visible d'emblée. */
  .reveal,
  html.js-reveal .reveal{ opacity:1 !important; transform:none !important; }
  .ico path, .ico circle, .ico rect{ stroke-dashoffset:0 !important; }
  .btn::after, .surface::after{ display:none; }
}

@media print{
  body{ background:#fff; }
  .frame{ margin:0; border:0; box-shadow:none; border-radius:0; }
  .sec--dark{ background:#fff !important; color:#000 !important; --fg:#000; --fg-soft:#333; --rule:#bbb; }
  .nav, .ghost-holder, .annot{ display:none !important; }
  .plan{ min-width:0; }
}
