/* ================= ACCUEIL =================
   Styles propres à la page d'accueil, chargés par elle seule (front matter
   `stylesPage`). L'en-tête et le pied viennent de theme.css : ce sont des
   composants partagés. Correspondance WordPress : un wp_enqueue_style
   conditionnel sur le template de l'accueil.
   ⚠️ Ce fichier redéfinit --gris et --ligne (l'accueil a ses propres
   valeurs, #5C6169 / #E8E1D6) : il doit être chargé APRÈS theme.css. */
:root{
  --noir:#26262A; --bleu:#3D6F8E; --ciel:#D8EEFF; --terra:#B5673E;
  --creme:#FBF7EE; --blanc:#fff; --fond:#fff; /* camel unique : même camel partout (retour client) */
  /* --fond : surface de page, blanche depuis le 20/08 — voir theme.css. */
  /* --terra-txt est parti avec le formulaire (17/08) : il n'avait plus d'usage. */
  --gris:#5C6169; --ligne:#E8E1D6;
  
  
}

/* Gouttière latérale de l'accueil. Une variable, pour que le réglage se
   fasse en un seul endroit — .w porte la trame, la légende des photos
   pleine largeur s'aligne dessus.
   17/08 : divisée par deux (était clamp(24px,5vw,88px)) — essai Raphaël. */
:root{--out:cubic-bezier(.16,1,.3,1)} /* --trame et --gut sont dans theme.css : ils valent pour tout le site */
*,*::before,*::after{box-sizing:border-box}
body{margin:0;background:var(--fond);color:var(--noir);font-family:var(--sans);
  font-size:16px;line-height:1.6;-webkit-font-smoothing:antialiased;overflow-x:hidden}
img{max-width:100%;height:auto;display:block}
a{color:inherit;text-decoration:none}
h1,h2,h3{font-family:var(--serif);font-weight:600;margin:0;line-height:.98;
  letter-spacing:-.022em;text-wrap:balance;font-variation-settings:'SOFT' 0,'WONK' 0}
p{margin:0}
:focus-visible{outline:2px solid var(--bleu);outline-offset:4px}

/* ---- trame ---- */
/* Sur un écran large, la marge visible ne vient pas du padding mais du
   centrage de cette trame : à 1920, 230px de centrage contre 44 de padding.
   Réduire la gouttière seule ne se voyait donc pas. 1460 → 1740 divise la
   marge par deux à 1920, puis +25 % à la demande : 274 → 134 → 168px. */
/* Même trame que les pages internes, même formule : deux techniques pour
   une même intention divergeraient de la largeur d'une barre de défilement. */
.w{padding:0 var(--pad)}
.rule{height:1px;background:var(--ligne);border:0;margin:0}
/* .lbl → .over, défini une seule fois dans theme.css */
.mut{color:var(--gris)}
.num{font-variant-numeric:tabular-nums;font-feature-settings:'tnum'}


/* ---- en-tête aligné sur la trame ----
   L'en-tête est un composant partagé : il se cale sur le bord de l'écran
   (clamp(20px,4.5vw,72px)), ce qui l'alignait sur le contenu des pages
   internes mais plus sur celui de l'accueil depuis que sa trame a bougé.
   Il reprend donc ici la trame de .w — même max-width, même gouttière —
   pour que le logo tombe sur la même verticale que les titres.
   Surcharge locale : sur les 19 autres pages, l'alignement actuel est juste. */
/* L'en-tête est aligné sur la trame dans theme.css, pour tout le site. */

/* ---- ouverture ---- */
/* Aucun rognage ici. `.open` porte aussi `.w`, qui borne le contenu à la trame :
   un overflow-x posé dessus coupe les nuages décoratifs au bord de la colonne de
   texte et non au bord de l'écran, laissant une bande de crème vide sur les
   grands écrans. Le défilement horizontal est déjà impossible — `body`
   est en overflow-x:hidden, valeur propagée au viewport.
   ⚠️ scrollWidth reste supérieur à clientWidth dans ce cas : ce n'est pas la
   preuve d'un défilement. Vérifier window.scrollX après un scrollTo. */
/* `svh` = plus petite hauteur possible (barre Safari déployée) : au premier
   rendu iOS, le viewport réellement visible peut dépasser cette estimation
   et laisser passer un bout de la section suivante en bas d'écran. `dvh`
   (dynamique) suit la hauteur réelle — le hero peut très légèrement changer
   de taille pendant un scroll qui replie la barre, préférable au trou. */
.open{min-height:100svh;min-height:100dvh;display:grid;grid-template-rows:1fr auto;padding-top:132px;position:relative}
/* Vidéo de fond du hero (18/09) : pleine section, sous le contenu (z-index).
   Carrousel produits retiré, texte en blanc (retour 18/09) — lavis assombri
   (et non plus crème) pour garder le blanc lisible sur la vidéo.
   `prefers-reduced-motion` coupe la lecture — le poster reste affiché, immobile. */
.hero-bg{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:0}
.open::before{content:"";position:absolute;inset:0;z-index:0;
  background:var(--noir);opacity:.42}
/* Le lavis uniforme (.42) ne suffit pas sous le header : la vidéo a des
   scènes claires (fenêtres, plafond blanc) où le blanc du menu se noie
   (retour 18/09). Un scrim propre à la bande du header, plus sombre,
   au-dessus du lavis général — `.site-head` est fixed et hors de `.open`,
   donc ceci ne fait qu'assombrir ce qu'il y a derrière lui. */
.open::after{content:"";position:absolute;inset:0 0 auto 0;z-index:0;height:190px;
  background:linear-gradient(rgba(0,0,0,.55),transparent)}
.open .mid,.open .foot{position:relative;z-index:1}
/* Nav blanche tant qu'on est sur la vidéo (retour 18/09) : `.site-head.on`
   est déjà posé par nav.js au premier pixel de scroll (theme.css), avant
   même de quitter le hero — repris ici plutôt que recalculé sur la hauteur
   du hero, qui varie avec le viewport. Le logo est un PNG noir : inversé en
   blanc par filtre plutôt que doubler l'asset. Le bouton `.go` garde son
   fond plein — devenu transparent sur la vidéo (retour 18/09), contour
   blanc, repasse plein dès `.on` comme le reste de la nav.
   `text-shadow`/`drop-shadow` en filet de sécurité supplémentaire : le scrim
   fixe le cas général, l'ombre porte absorbe les pics de luminosité que le
   scrim ne couvre pas parfaitement (bords, transitions de plan).
   `nav>a` et non `nav a` : `.drop` (le menu déroulant) vit aussi dans `nav`
   et garde un fond clair plein quel que soit l'état du header — le blanc
   s'y appliquait aussi et rendait ses liens illisibles (blanc sur blanc). */
body.a-hero .site-head:not(.on):not(.is-ouvert) nav>a,
body.a-hero .site-head:not(.on):not(.is-ouvert) .has-drop>a{
  color:var(--blanc);text-shadow:0 1px 4px rgba(0,0,0,.5)}
body.a-hero .site-head:not(.on):not(.is-ouvert) .go{
  background:transparent;border-color:rgba(255,255,255,.7);color:var(--blanc)}
body.a-hero .site-head:not(.on):not(.is-ouvert) .logo img{
  filter:brightness(0) invert(1) drop-shadow(0 1px 4px rgba(0,0,0,.5))}
body.a-hero .site-head:not(.on):not(.is-ouvert) .burger{
  color:var(--blanc);text-shadow:0 1px 4px rgba(0,0,0,.5)}
.open .mid{display:flex}
.open .dire{display:flex;flex-direction:column;justify-content:center}
.open h1{font-size:clamp(38px,7vw,98px);font-weight:700;letter-spacing:-.035em;color:var(--terra)}
.open h1 span{display:block}
.open h1 .t{padding-left:.09em}
.open .say{max-width:46ch;margin-top:clamp(28px,4vw,52px);font-size:clamp(16px,1.35vw,20px);
  line-height:1.5;color:var(--blanc)}
/* ---- le bandeau d'infos défile (25/08) ---- */
/* Il reprend les ressorts du marquee des logos — piste dupliquée, fondu aux
   deux bords, pause au survol, immobile en « mouvement réduit » — mais garde
   son filet et sa ligne de base. Il ne peut pas réutiliser `.piste`/`.defile` :
   `.piste` porte l'échelle et les masques des logos (même piège que `vt-`
   plus haut), d'où le préfixe `fo-`.
   ⚠️ `overflow:hidden` ici, jamais sur `.open` : le hero doit pouvoir laisser
   respirer ce qui dépasse, et un conteneur de défilement tuerait tout sticky. */
.open .foot{--fo-gap:clamp(26px,3vw,58px);
  padding:24px 0 30px;border-top:1px solid var(--ligne);font-size:13px;
  overflow:hidden;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 4%,#000 96%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 4%,#000 96%,transparent)}
/* Le pas d'une boucle sans couture : la piste porte QUATRE passages des trois
   lignes, séparés par 4n−1 gouttières. Un quart du contenu s'arrête donc un
   quart de gouttière trop tôt — d'où `-25% - gap/4`. (`glisse`, chez les
   logos, dit `-50% - gap/2` : c'est la même formule pour deux passages.) La
   variable est reprise dans le pas pour que le réglage du `gap` suffise. */
.open .fo-piste{display:flex;align-items:baseline;width:max-content;
  gap:var(--fo-gap);animation:glisse-info 46s linear infinite;will-change:transform}
.open .fo-item{display:inline-flex;align-items:baseline;gap:8px;white-space:nowrap}
/* Le filet camel qui sépare deux lignes : la signature du site, plutôt qu'un
   point médian ou une barre. Il vit dans la gouttière, à mi-chemin — d'où la
   marge égale au `gap` de part et d'autre. */
.open .fo-item::after{content:"";width:5px;height:5px;border-radius:999px;flex:none;
  margin-left:var(--fo-gap);background:var(--terra);
  transform:translateY(-.32em)}
.open .foot{border-top-color:rgba(255,255,255,.35)}
.open .foot b{font-family:var(--sans);font-size:18px;font-weight:400;color:var(--blanc)}
@keyframes glisse-info{from{transform:translate3d(0,0,0)}
  to{transform:translate3d(calc(-25% - var(--fo-gap) / 4),0,0)}}
@media(hover:hover) and (pointer:fine){
  .open .foot:hover .fo-piste{animation-play-state:paused}}
/* Immobile : la piste reprend sa largeur normale et le bandeau redevient une
   bande qu'on fait glisser au doigt, sans fondu qui masquerait du texte. */
@media(prefers-reduced-motion:reduce){
  .open .foot{-webkit-mask-image:none;mask-image:none;overflow-x:auto}
  .open .fo-piste{animation:none}}
/* ---- vitrine du hero : toutes les solutions dans une carte ---- */
/* Rayon aligné le 02/09 sur celui des cartes-photo du site (16px), plutôt que
   sur la pastille de l'en-tête (12px) — un seul rayon partout (retour client).
   Fond bleu ciel clair (repris de la maquette client, #D8EDFF) au lieu du
   bleu profond de charte : la carte reste une surface distincte au milieu
   d'une page claire, et les packshots détourés s'y détachent toujours. La
   légende passe donc en foncé (--noir) — le crème qui allait sur fond sombre
   ne se verrait plus ici. */
.vitrine{position:relative;background:#D8EDFF;border-radius:16px;
  overflow:hidden;aspect-ratio:5/4}
/* ⚠️ Préfixe `vt-` obligatoire : `.piste` appartient déjà au marquee des logos
   (`.piste{width:max-content;animation:defile 62s}` plus bas). Nommée `.piste`,
   la piste de la vitrine héritait de sa largeur max-content ET de son
   animation — les vues débordaient de la carte. `.vue` et `.pas` sont préfixées
   pour la même raison, avant qu'elles ne collisionnent à leur tour.
   La piste porte le déplacement ; chaque vue occupe exactement la carte.
   `flex:0 0 100%` et non une largeur en pixels : la carte est fluide. */
/* ⚠️ `position:absolute;inset:0` et non `height:100%` : la hauteur de la carte
   vient d'`aspect-ratio`, et un pourcentage ne se résout pas à travers cette
   chaîne (carte à ratio → piste flex → vue étirée). L'image retombait sur sa
   hauteur intrinsèque et débordait de 78px, rognée par l'overflow — on voyait
   un nuage géant au lieu d'un packshot. Une boîte posée par `inset` est
   définie, donc les 100% en dessous se résolvent. */
.vitrine .vt-piste{position:absolute;inset:0;display:flex;
  transition:transform 720ms var(--out);will-change:transform}
.vitrine .vt-vue{flex:0 0 100%;height:100%;margin:0;position:relative;
  display:grid;place-items:center;padding:clamp(9px,1.1vw,18px)}
/* `contain` et non `cover` : ce sont des packshots, on ne rogne pas un produit.
   Les cinq n'ont pas le même format (900x897 pour Le Nuage, 1000x691 pour les
   versions connectée et Sunshine) — `contain` absorbe l'écart sans les étirer. */
/* ⚠️ `min-height:0` : un item de grille a `min-height:auto`, donc il refuse de
   descendre sous la hauteur intrinsèque de son contenu. Les packshots quasi
   carrés (900x897, 900x924, 760x741) restaient plantés à 550-566px dans une
   boîte de 420 et débordaient sous la carte. Les deux versions connectée et
   Sunshine (1000x691) « passaient » seulement parce qu'elles sont plus plates
   que la carte — le défaut ne se voyait donc que sur trois vues sur cinq. */
.vitrine .vt-vue img{width:100%;height:100%;min-width:0;min-height:0;object-fit:contain;
  transform:scale(1.26);
  filter:drop-shadow(0 22px 34px rgba(38,38,42,.32))}
/* Même échelle que `.over`, en --noir : sur le fond bleu ciel clair, c'est
   le foncé qui tient le contraste AA (le crème d'origine visait le bleu
   profond, remplacé le 02/09 par le bleu clair de la maquette client). */
.vitrine figcaption{position:absolute;top:clamp(18px,2.2vw,30px);left:clamp(18px,2.2vw,30px);
  font-size:10.5px;font-weight:600;letter-spacing:.34em;text-transform:uppercase;
  color:var(--noir);z-index:1}
/* Pastilles de position. Elles ne sont pas dans la maquette, mais un carrousel
   qui tourne tout seul sans repère ne dit pas qu'il y a cinq produits — et sans
   commande, il n'est pas atteignable au clavier.
   ⚠️ Aucune règle `button` nue ne vit dans ce fichier : la pastille porte
   elle-même son `border`, son `background` et son curseur. */
.vitrine .vt-pas{position:absolute;left:clamp(18px,2.2vw,30px);bottom:clamp(18px,2.2vw,30px);
  display:flex;gap:8px;z-index:1}
.vitrine .vt-pas button{width:7px;height:7px;padding:0;border:0;border-radius:999px;
  background:var(--creme);opacity:.45;cursor:pointer;
  transition:opacity 220ms ease-out}
.vitrine .vt-pas button[aria-current="true"]{opacity:1}
.vitrine .vt-pas button:focus-visible{outline:2px solid var(--creme);outline-offset:3px}
@media(hover:hover) and (pointer:fine){.vitrine .vt-pas button:hover{opacity:.7}}
@media(prefers-reduced-motion:reduce){.vitrine .vt-piste{transition:none}}
/* Sous 900px la carte passe sous le discours : deux colonnes de 350px ne
   servent ni le titre ni le packshot. */
@media(max-width:900px){
  .open .mid{grid-template-columns:1fr;gap:clamp(26px,5vw,44px)}
  .vitrine{aspect-ratio:4/3}
}

/* ---- pleine largeur ---- */
.slab{position:relative;margin:0;overflow:hidden}
.slab img{width:100%;height:clamp(616px,109vh,1204px);object-fit:cover;object-position:center 30%} /* Ozenspa : hauteur augmentée + recadrage +haut/−bas (retour client) ; +40 % le 15/09 */
/* Légende en blanc, en bas à droite de la photo, dans une carte verre
   dépoli. Allégée le 08/09 en matière plus liquide : fond moins opaque,
   blur plus ample et reflets internes, sans affadir le texte. */
.slab figcaption{position:absolute;right:var(--pad);bottom:clamp(108px,13vw,196px);
  color:#fff;text-shadow:0 1px 20px rgba(0,0,0,.35);max-width:min(60ch,72%);display:block;text-align:right;
  background:linear-gradient(135deg,rgba(255,255,255,.045),rgba(255,255,255,.012) 42%,rgba(38,38,42,.025));
  backdrop-filter:blur(26px) saturate(175%);-webkit-backdrop-filter:blur(26px) saturate(175%);
  border:1px solid rgba(255,255,255,.24);border-radius:16px;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.34),inset 0 -28px 56px rgba(38,38,42,.08),0 30px 80px rgba(38,38,42,.24);
  padding:clamp(20px,2.6vw,32px) clamp(22px,3vw,36px)}
.slab .who{font-family:var(--serif);font-size:clamp(20px,2.4vw,32px);font-weight:600;display:block}
.slab .what{display:block;margin-top:6px;font-size:13.5px;opacity:.9}
/* « Le problème » posé directement sur la photo (02/09) : mêmes textes que
   l'ancien bloc #probleme-sec sur fond camel, mais réduits — l'onde et les
   deux paragraphes tiennent sur l'image sans l'écraser, à la place du
   .who/.what par défaut de .slab. */
.slab figcaption .cocktail p{font-family:var(--serif);font-size:clamp(19px,2.1vw,30px);
  line-height:1.24;letter-spacing:-.015em;margin:0;text-align:justify}
.slab figcaption .cocktail .mut{text-align:justify}

/* ---- section ---- */
.sec{padding-block:clamp(96px,12vw,190px)} /* padding vertical seul : laisse .w gérer l'horizontal même sur <section class="sec w"> (fix largeur) */
.sec.tight{padding-block:clamp(72px,8vw,124px)}
.sec h2{font-family:var(--serif);font-weight:700}
.hd{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.05fr);gap:clamp(24px,5vw,80px);
  align-items:end;padding-bottom:clamp(42px,5vw,76px)}
.hd h2{font-size:clamp(34px,5.4vw,76px)}
.hd .say{font-size:clamp(16px,1.3vw,19.5px);color:#3F444B;max-width:48ch}
@media(max-width:900px){.hd{grid-template-columns:1fr}}

/* ---- manifeste ---- */
.mani{display:grid;grid-template-columns:minmax(0,.34fr) minmax(0,1fr);gap:clamp(24px,5vw,90px)}
.mani p{font-family:var(--serif);font-size:clamp(23px,2.9vw,42px);line-height:1.24;
  letter-spacing:-.015em;text-wrap:pretty}
.mani p+p{margin-top:.7em}
.mani em{font-style:normal;color:var(--terra)}
@media(max-width:900px){.mani{grid-template-columns:1fr}}

/* ---- planches produit ---- */
.plate{display:grid;grid-template-columns:minmax(0,1.25fr) minmax(0,.75fr);
  gap:clamp(20px,4vw,64px);align-items:center;padding:clamp(56px,6vw,98px) 0;
  border-top:1px solid var(--terra)}
.plate:last-of-type{border-bottom:1px solid var(--terra)}
@keyframes pulse-dot{0%{box-shadow:0 0 0 0 rgba(181,103,62,.45)}70%,100%{box-shadow:0 0 0 9px rgba(181,103,62,0)}}
.plate.flip>.pic{order:2}
.plate .pic{padding:clamp(16px,2.6vw,44px);perspective:1300px;
  display:grid;place-items:center;position:relative}
.plate .pic::after{content:"";position:absolute;left:14%;right:14%;bottom:8%;height:26px;
  border-radius:50%;background:radial-gradient(closest-side,rgba(38,38,42,.20),transparent 72%);
  transform:translateX(var(--decal,0px)) scaleX(var(--ombre,1));
  transition:transform 620ms var(--out);z-index:-1}
.plate .pic img{transform:rotateX(0deg) rotateY(0deg);
  transform-style:preserve-3d;
  filter:drop-shadow(0 26px 30px rgba(38,38,42,.16));
  transition:transform 620ms var(--out),filter 620ms var(--out)}
/* pendant le suivi la planche doit coller au curseur ; c'est le retour, une fois
   la souris partie, qui a le droit de s'installer sur 620ms */
.plate .pic.suit img,.plate .pic.suit::after{transition-duration:220ms}
@media(hover:hover) and (pointer:fine){
  .plate .pic:hover img{filter:drop-shadow(0 34px 44px rgba(38,38,42,.22))}
}
@media(prefers-reduced-motion:reduce){
  .plate .pic img{transform:none;transition:none}}
.plate h3{font-size:clamp(28px,3.4vw,48px);margin-bottom:14px}
.plate .say{color:#3F444B;max-width:44ch;font-size:15.5px;text-align:justify;-webkit-hyphens:auto;hyphens:auto}
.refs .hd .say{text-align:justify;margin-left:auto} /* justifiée + bord droit aligné au filet de séparation (retour client) */
/* L'intro des témoignages flottait au milieu de sa colonne : son bord droit
   s'arrêtait 470px avant celui de la trame, quand #objets et #protocole
   viennent buter dessus. Même geste, sans la justification (l'intro est
   courte, justifiée elle ouvrirait des rivières). */
#temoignages .hd .say{margin-left:auto}
.temps p{text-align:justify;margin-left:auto} /* textes des étapes justifiés + bord droit aligné (retour client) */
/* fiches produit : photos dans un cadre de hauteur fixe → fiches de même hauteur (retour client) */
.plate .pic img{width:100%;height:clamp(300px,30vw,440px);object-fit:contain}
@media(min-width:901px){.plate{min-height:clamp(430px,32vw,480px)}}
@media(max-width:900px){.plate{grid-template-columns:1fr}.plate.flip>.pic{order:0}}

/* ---- #objets : carrousel produits, fond camel, texte crème, défilement
   automatique, 4 cartes visibles (test 02/09) ---- */
.obj-dark{background:var(--camel);color:var(--creme)}
/* Retour Justine 16/09 : section perçue trop basse par rapport au bloc du
   dessus — on resserre juste son padding haut, pas le bas (cartes) ni les
   autres .sec.tight. */
#objets{padding-top:clamp(48px,5vw,84px)}
.obj-dark .over{color:var(--creme)}
.obj-hd-r{display:flex;flex-direction:column;gap:22px;align-items:flex-start}
/* En-têtes empilés (08/09) : sur-titre, titre Fraunces bold, texte dessous.
   On garde l'alternance directionnelle de la landing : gauche pour
   #objets/#protocole, droite pour #pourquoi/#lieux. */
#objets .hd,.proto-hd{display:block;max-width:min(980px,100%);
  margin-left:0;margin-right:auto;text-align:left}
#objets .hd h2,.proto-hd h2{text-align:left}
#objets .hd .say,.proto-hd .say{text-align:left;
  margin:clamp(22px,2.6vw,34px) 0 0;max-width:68ch}
#objets .hd h2,#objets .hd .say{color:var(--creme)}
#objets .hd .say{opacity:.85}
#objets .hd{padding-bottom:clamp(24px,3vw,40px)} /* retour Justine 16/09 : rapproché des cartes */
#pourquoi .hd.rev,#lieux .hd.rev{display:block;max-width:min(980px,100%);
  margin-left:auto;margin-right:0;text-align:right}
#pourquoi .hd.rev h2,#lieux .hd.rev h2{text-align:right}
#pourquoi .hd.rev .say,#lieux .hd.rev .say{text-align:right;
  margin:clamp(22px,2.6vw,34px) 0 0 auto;max-width:68ch}
/* Piste en scroll-snap natif : l'auto-défilement ne fait que scroller la
   largeur d'une carte + gap, pas de calc JS des positions (cf. accueil.js).
   --gap répété en JS via getComputedStyle. */
.obj-track{--gap:clamp(18px,2.4vw,28px);display:flex;gap:var(--gap);overflow-x:auto;
  scroll-snap-type:x mandatory;padding:8px 0 22px;margin-top:calc(clamp(40px,5vw,64px) - 8px);margin-bottom:-16px;
  scrollbar-width:none}
.obj-track::-webkit-scrollbar{display:none}
/* Barre de progression du carrousel (retour Justine 16/09) : reflète la
   position de scroll du track, pilotée en JS (scrollLeft/scrollWidth),
   pas de dépendance au nombre de cartes. */
.obj-progress{height:3px;background:rgba(251,247,238,.25);border-radius:2px;
  margin-top:18px;overflow:hidden}
.obj-progress span{display:block;height:100%;width:25%;background:var(--creme);
  border-radius:2px;transition:width .25s ease}
/* 4 cartes de front sur desktop, 2 en tablette, 1 (quasi) sur mobile —
   flex-basis en calc() sur la largeur du track plutôt qu'en vw : la
   largeur réelle dépend du padding de page (--pad), pas du viewport. */
.obj-card{--obj-motion:900ms cubic-bezier(.37,0,.63,1);
  flex:0 0 calc((100% - 3*var(--gap))/4);scroll-snap-align:start;
  background:var(--blanc);border-radius:16px;overflow:hidden;
  display:flex;flex-direction:column;color:var(--noir);
  transition:transform var(--obj-motion),box-shadow var(--obj-motion)}
.obj-media{aspect-ratio:4/3;background:radial-gradient(62% 62% at 50% 45%, var(--halo) 0%, var(--blanc) 82%);
  display:flex;align-items:center;justify-content:center;padding:clamp(6px,.8vw,12px);overflow:hidden}
/* Le flottement continue pendant le zoom : aucune pause abrupte au survol.
   Zoom, élévation et ombre suivent la même courbe douce et réversible. */
@keyframes obj-flotte{0%,100%{transform:translateY(0)}50%{transform:translateY(-4px)}}
.obj-media img{width:99%;height:99%;object-fit:contain;scale:1.45;
  animation:obj-flotte 8s ease-in-out infinite;transition:scale var(--obj-motion)}
@media(hover:hover) and (pointer:fine){.obj-card:hover{transform:translateY(-8px);box-shadow:0 26px 48px -24px rgba(38,38,42,.4)}
  .obj-card:hover .obj-media img{scale:1.53}}
.obj-card:nth-child(2n) .obj-media img{animation-delay:-2.8s}
@media(prefers-reduced-motion:reduce){.obj-media img{animation:none;transition:none}
  .obj-card,.obj-card:hover{transform:none;transition:none}
  .obj-card:hover .obj-media img{scale:1.45}}
.obj-body{padding:clamp(16px,1.8vw,22px) clamp(18px,2vw,22px) clamp(20px,2.2vw,26px)}
.obj-tag{font-size:10.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--camel);margin:0}
.obj-body h3{font-size:clamp(17px,1.3vw,19px);margin:9px 0 7px}
.obj-body h3 a{color:inherit;text-decoration:none}
.obj-desc{font-size:12.5px;color:var(--gris);margin:0 0 14px;max-width:30ch}
.obj-link{font-size:12.5px;font-weight:600;color:var(--bleu)}
@media(max-width:1100px){.obj-card{flex-basis:calc((100% - var(--gap))/2)}}
@media(max-width:640px){.obj-card{flex-basis:100%}}

/* ---- bandeau logos, dans la carte de #lieux, sous le texte + la carte
   France (retour client 03/09) ---- `grid-column:1/-1` : troisième enfant
   de la grille à 2 colonnes de `.real-map-card`, il prend toute la largeur
   plutôt que la moitié qui lui reviendrait par défaut. `.piste .m` reste en
   `background` masqué (technique inchangée) — seule la couleur passe de
   `--terra` à `--blanc`, pour porter sur le bleu `--ciel` de la carte. */
.real-map-card .marques-band{grid-column:1/-1;min-width:0;margin-top:clamp(8px,1.2vw,16px)}
.marques-band .piste .m{background:var(--bleu)}


/* ---- protocole ---- */
/* Passé à 5 étapes le 03/09 (retour client), une carte par étape avec une
   illustration en fond ; numéro + titre posés dessus, en transparence — le
   texte descriptif se dévoile au survol, à la place. Sans souris (pas de
   `hover:hover`), tout reste visible en permanence : le texte suit le titre
   dans le flux, rien n'est jamais cliqué à l'aveugle. */
.proto-grid{display:grid;grid-template-columns:repeat(5,1fr);gap:clamp(14px,1.6vw,22px)}
.proto-c{position:relative;background:var(--creme);border:1px solid var(--ligne);border-radius:16px;
  overflow:hidden;aspect-ratio:3/4;padding:clamp(20px,2vw,26px);
  display:flex;flex-direction:column;justify-content:center;text-align:center}
.proto-ic{position:absolute;inset:12%;margin:auto;width:76%;height:76%;
  fill:none;stroke:var(--terra);stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round;
  opacity:.16;pointer-events:none}
.proto-n{position:relative;font-family:var(--serif);font-size:clamp(26px,2.6vw,36px);
  color:var(--terra);line-height:1;font-variant-numeric:tabular-nums;margin-bottom:10px}
.proto-c h3{position:relative;font-size:clamp(16px,1.3vw,18.5px);margin:0}
.proto-c p{position:relative;color:#3F444B;font-size:13.5px;line-height:1.5;margin:10px 0 0}
@media(max-width:1100px){.proto-grid{grid-template-columns:repeat(3,1fr)}}
@media(max-width:640px){.proto-grid{grid-template-columns:1fr 1fr}}
@media(max-width:420px){.proto-grid{grid-template-columns:1fr}}

/* L'interaction « survol dévoile le texte » n'existe qu'avec un pointeur
   précis : au clavier/tactile, `p` reste dans le flux normal (règles
   ci-dessus). Ici seulement, elle sort du flux, cachée derrière le
   numéro/titre jusqu'au survol ou au focus (tabindex sur `.proto-c`). */
@media(hover:hover) and (pointer:fine){
  .proto-c p{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
    padding:clamp(20px,2vw,26px);margin:0;background:var(--creme);opacity:0;
    transition:opacity 260ms var(--out)}
  .proto-n,.proto-c h3{transition:opacity 220ms var(--out)}
  .proto-ic{transition:opacity 260ms var(--out)}
  .proto-c:hover .proto-ic,.proto-c:focus-visible .proto-ic{opacity:.06}
  .proto-c:hover .proto-n,.proto-c:hover h3,
  .proto-c:focus-visible .proto-n,.proto-c:focus-visible h3{opacity:0}
  .proto-c:hover p,.proto-c:focus-visible p{opacity:1}
}
@media(prefers-reduced-motion:reduce){
  .proto-c p,.proto-n,.proto-c h3,.proto-ic{transition:none}}

/* ---- en-tête .hd.rev / .hd-lead ---- */
/* Variante d'en-tête : titre en colonne de droite. Le motif vient d'un
   retour client sur #usages (déménagée sur /besoins le 03/09, avec sa
   propre CSS — besoins.css, où .hd-lead groupe encore sur-titre+intro).
   #pourquoi et #lieux l'adoptent à leur tour (demande Raphaël, 17/08 et
   03/09) : .hd-lead y groupe sur-titre+titre à droite, l'intro passe seule
   en 1re colonne — cf. index.njk. */
.hd.rev{align-items:start}
.hd.rev h2{text-align:right}
.hd.rev .hd-lead .say{margin-top:clamp(18px,1.8vw,28px)} /* espace sur-titre → intro maîtrisé (besoins.css) */
/* #pourquoi/#lieux : le sur-titre doit suivre l'alignement du titre qu'il
   surmonte (à droite ici), sinon les deux lignes du même bloc partent
   chacune d'un bord différent — cf. .hd-lead > .over ci-dessous, groupe
   sur-titre+titre à droite (pas de .say dedans, à la différence de
   besoins.css). */
#pourquoi .hd-lead>.over,#lieux .hd.rev>div>.over{text-align:right}

/* ---- preuve : témoignages en rangée + carte pleine largeur (03/09) ----
   Restructuré sur le modèle envoyé par le client : plus de grille à 2
   colonnes, les témoignages redeviennent 3 cartes côte à côte (comme sur
   /realisations) et la carte de France passe en pleine largeur en dessous,
   dans sa propre carte bleue plutôt qu'à même le fond de page. */
.real-tm{margin-top:clamp(32px,3.6vw,56px)}
/* En-tête resserré côté #lieux uniquement : le padding par défaut de .hd
   (partagé avec les autres sections de l'accueil) laissait trop d'air avant
   les témoignages une fois le carrousel de vignettes retiré (retour client). */
#lieux .hd{padding-bottom:clamp(24px,3vw,40px)}
/* Inversé (retour client 03/09) : l'intro passe en 1re colonne à gauche
   (alignement par défaut, comme #protocole), sur-titre+titre en 2e à
   droite — .hd.rev gère déjà le text-align:right du h2. */
/* Cartes témoignages : le filet vertical entre colonnes (thème global,
   .tm+.tm{border-left}, une seule bande continue) devient 3 cartes
   séparées par un espace — chacune avec son propre encart, guillemet,
   fond, rayon commun au site. */
.real-tm .tm-grid{gap:clamp(20px,2.4vw,28px)}
.real-tm .tm{background:var(--blanc);border:1px solid var(--ligne);border-radius:16px;
  padding:clamp(26px,2.4vw,34px)}
.real-tm .tm::before{position:static;display:block;font-size:40px;opacity:.5}
.real-tm .tm blockquote{margin-top:14px}
/* Avatar : un fond de couleur par carte plutôt que le cercle pointillé
   « photo à fournir » — bleu / camel / noir, en écho aux trois teintes de
   la charte (pas d'initiales : aucun nom de personne dans ces 3 exemples). */
.real-tm .tm .ph-av{border:0;background:var(--bleu)}
.real-tm .tm:nth-child(2) .ph-av{background:var(--camel)}
.real-tm .tm:nth-child(3) .ph-av{background:var(--noir)}

/* ---- carte de France : pleine largeur, palette bleue (03/09) ---- */
.real-map-card{display:grid;grid-template-columns:minmax(0,.85fr) minmax(0,1.15fr);
  gap:clamp(32px,5vw,72px);align-items:center;margin-top:clamp(28px,3.2vw,40px);
  background:var(--ciel);border-radius:16px;overflow:hidden;
  padding:clamp(32px,4vw,56px)}
.real-map-txt .over{color:var(--bleu)}
.real-map-txt h2{margin-top:14px;font-size:clamp(28px,3.4vw,44px)}
.real-map-txt .say{margin-top:clamp(16px,2vw,24px);max-width:42ch;color:#2C4A5E}
/* `border-radius:6px` : celui de `.btn` (theme.css), le bouton plein du
   site — ce bouton-ci a sa propre couleur (bleu carte) mais pas sa propre
   forme, sans quoi le site aurait deux vocabulaires de bouton (retour
   client 09/09 : « respecte le border-radius »). */
.real-map-cta{display:inline-flex;align-items:center;gap:8px;margin-top:clamp(24px,2.8vw,34px);
  background:var(--bleu);color:var(--creme);font-size:13px;font-weight:600;
  padding:14px 26px;border-radius:6px;text-decoration:none;
  transition:background 180ms ease-out}
@media(hover:hover) and (pointer:fine){.real-map-cta:hover{background:var(--camel)}}
.real-map-svg{position:relative}
.real-map-svg svg{width:100%;height:auto;display:block}
.real-map-svg .fr-land{fill:rgba(61,111,142,.14);stroke:var(--bleu);stroke-width:.3;stroke-linejoin:round;stroke-linecap:round}

.real-map-markers{position:absolute;inset:0}
/* Un nuage par projet plutôt qu'un aplat par ville (retour client 09/09) :
   plus petit qu'avant (6% → 3.2%, avec un plancher px pour rester cliquable
   sur mobile) puisqu'ils sont maintenant plusieurs à se regrouper autour
   d'une même ville (Bordeaux, Nantes). Devenu `<a>` — tous les nuages
   pointent désormais vers la fiche réelle de leur projet sur /realisations,
   d'où `text-decoration:none` et `color:inherit` qui manquaient au bouton. */
.map-marker{position:absolute;transform:translate(-50%,-50%);
  width:clamp(16px,4.2%,28px);aspect-ratio:24/16;
  border:0;padding:0;margin:0;background:none;text-decoration:none;color:inherit;
  cursor:pointer;-webkit-tap-highlight-color:transparent}
.map-marker-icon{display:block;width:100%;height:100%;fill:var(--bleu);
  transition:transform 180ms ease-out,fill 180ms ease-out}
.map-marker:hover .map-marker-icon,.map-marker:focus-visible .map-marker-icon{fill:var(--terra);transform:scale(1.15)}
.map-marker:hover,.map-marker:focus-visible{z-index:5}

.map-dot{position:absolute;transform:translate(-50%,-50%);width:9px;height:9px;
  border-radius:50%;background:var(--bleu);pointer-events:none}

.map-tip{position:absolute;bottom:calc(100% + 10px);left:50%;transform:translate(-50%,4px) scale(.96);
  min-width:150px;padding:12px 16px;border-radius:14px;background:var(--noir);color:var(--blanc);
  font-family:var(--sans);font-size:13px;line-height:1.4;white-space:nowrap;text-align:left;
  opacity:0;pointer-events:none;transition:opacity 160ms ease-out,transform 160ms ease-out}
.map-tip::after{content:"";position:absolute;top:100%;left:50%;transform:translateX(-50%);
  border:6px solid transparent;border-top-color:var(--noir)}
.map-tip b{display:block;font-size:14px;font-weight:700;margin-bottom:2px;color:var(--blanc)}
.map-marker:hover .map-tip,.map-marker:focus-visible .map-tip{opacity:1;transform:translate(-50%,0) scale(1)}
@media(max-width:820px){
  /* `1fr` seul ne suffit pas à contraindre la piste : la largeur minimale
     implicite d'un enfant de grille est `auto` (= son contenu), pas 0. Le
     texte non cassé y forçait une piste de ~3000px et un débordement
     horizontal de toute la page. `min-width:0` sur les deux enfants remet
     la piste à la largeur du conteneur. */
  .real-map-card{grid-template-columns:1fr}
  .real-map-txt,.real-map-svg{min-width:0}
  .real-map-svg{order:-1;max-width:340px;margin:0 auto}
}

/* ---- contact ----
   Tout est parti dans `theme.css` le 17/08 — le formulaire ET sa grille : la
   section sert aussi /etude-acoustique, et une DA ne se duplique pas. `.ct` a
   fusionné dans `.contact`, qui portait les mêmes deux colonnes en plus étroit. */



/* ---- le seul moment orchestré : l'ouverture ---- */
.open h1 span,.open .say,.open .foot{opacity:0;transform:translateY(18px);
  transition:opacity 620ms var(--out),transform 620ms var(--out)}
.ready .open h1 span,.ready .open .say,.ready .open .foot{opacity:1;transform:none}
.ready .open h1 span:nth-child(2){transition-delay:90ms}
.ready .open .say{transition-delay:210ms}
.ready .open .foot{transition-delay:300ms}

/* ---- second moment : la photo se pose ---- */
.slab img{transform:scale(1.06);transition:transform 1100ms var(--out)}
.slab.in img{transform:none}

@media(prefers-reduced-motion:reduce){
  .open h1 span,.open .say,.open .foot{opacity:1;transform:none;transition:none}
  .slab img{transform:none;transition:none}
}


/* ---- références ---- */
.defile{display:grid;gap:clamp(26px,3.4vw,48px);overflow:hidden;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent)}
.piste{display:flex;align-items:center;gap:clamp(38px,5vw,86px);width:max-content;
  animation:glisse 64s linear infinite;will-change:transform}
.piste.retour{animation-duration:78s;animation-direction:reverse}
.piste .m{height:clamp(19px,2vw,27px);flex:none;display:block;
  background:var(--terra);
  -webkit-mask-image:var(--u);mask-image:var(--u);
  -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
  -webkit-mask-position:center;mask-position:center;
  -webkit-mask-size:contain;mask-size:contain;
  opacity:.7;transition:opacity 220ms ease-out}
@media(hover:hover) and (pointer:fine){
  .defile:hover .piste{animation-play-state:paused}
  .piste .m:hover{opacity:1}
}
@keyframes glisse{from{transform:translate3d(0,0,0)}
  to{transform:translate3d(calc(-50% - clamp(19px,2.5vw,43px)),0,0)}}
@media(prefers-reduced-motion:reduce){
  .defile{-webkit-mask-image:none;mask-image:none;overflow-x:auto}
  .piste{animation:none}}

/* ---- simulateur ---- */
.sim{display:grid;grid-template-columns:minmax(0,.82fr) minmax(0,1.18fr);
  gap:clamp(26px,4vw,64px);align-items:start}
.sim .panel{display:grid;gap:26px}
.ctl label{display:block;font-size:10.5px;font-weight:600;letter-spacing:.24em;
  text-transform:uppercase;color:var(--gris);margin-bottom:10px}
.ctl select{width:100%;font-family:var(--sans);font-size:16px;color:var(--noir);
  background:transparent;border:0;border-bottom:1px solid var(--noir);padding:9px 0;border-radius:0}
.cnt{display:flex;align-items:baseline;justify-content:space-between;gap:16px;margin-bottom:6px}
.cnt b{font-family:var(--serif);font-size:clamp(38px,4.6vw,64px);line-height:1;
  font-variant-numeric:tabular-nums}
.cnt span{font-size:13px;color:var(--gris)}
input[type=range]{-webkit-appearance:none;appearance:none;width:100%;height:22px;
  background:transparent;cursor:pointer;display:block}
input[type=range]::-webkit-slider-runnable-track{height:2px;background:var(--noir)}
input[type=range]::-moz-range-track{height:2px;background:var(--noir)}
input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;width:20px;height:20px;
  border-radius:50%;background:var(--terra);margin-top:-9px;
  transition:transform 120ms ease-out,box-shadow 160ms ease-out}
input[type=range]::-moz-range-thumb{width:20px;height:20px;border:0;border-radius:50%;
  background:var(--terra)}
@media(hover:hover) and (pointer:fine){
  input[type=range]:hover::-webkit-slider-thumb{transform:scale(1.12)}
}
input[type=range]:active::-webkit-slider-thumb{transform:scale(.95)}
input[type=range]:focus-visible::-webkit-slider-thumb{box-shadow:0 0 0 4px rgba(61,111,142,.32)}

.read{border-top:1px solid var(--noir)}
.read div{display:grid;grid-template-columns:1fr auto;gap:16px;align-items:baseline;
  padding:14px 0;border-bottom:1px solid var(--ligne)}
.read .k{font-size:13.5px;color:var(--gris)}
.read .v{font-family:var(--serif);font-weight:600;font-size:clamp(21px,2.2vw,30px);
  font-variant-numeric:tabular-nums;line-height:1}
.read .v.hit{color:var(--bleu)}
.verdict{font-family:var(--serif);font-size:clamp(19px,1.9vw,25px);line-height:1.2;
  padding-top:8px}
.verdict.hit{color:var(--bleu)}

.stage{border:1px solid var(--noir)}
.stage canvas{display:block;width:100%;height:clamp(300px,44vh,440px)}
.stage .legend{display:flex;flex-wrap:wrap;gap:8px 22px;padding:12px 18px;
  border-top:1px solid var(--ligne);font-size:12px;color:var(--gris)}
.stage .legend i{font-style:normal;display:inline-flex;align-items:center;gap:7px}
.stage .legend i::before{content:"";width:9px;height:9px;border-radius:50%;background:currentColor}
.stage .legend .r{color:var(--terra)}
.stage .legend .c{color:var(--bleu)}
.hyp{font-size:12.5px;color:var(--gris);border-left:1px solid var(--terra);
  padding-left:14px;margin-top:20px;max-width:64ch}
@media(max-width:960px){.sim{grid-template-columns:1fr}}
.m0{--u:url(/assets/img/home/img-01-94e6ab65.webp);aspect-ratio:4.311}.m1{--u:url(/assets/img/home/img-02-ef995ba2.webp);aspect-ratio:4.632}.m2{--u:url(/assets/img/home/img-03-f99f7b33.webp);aspect-ratio:1.437}.m3{--u:url(/assets/img/home/img-04-87fc4087.webp);aspect-ratio:1.446}.m4{--u:url(/assets/img/home/img-05-6ed69baa.webp);aspect-ratio:2.349}.m5{--u:url(/assets/img/home/img-06-8933f2d6.webp);aspect-ratio:3.194}.m6{--u:url(/assets/img/home/img-07-2ed4c214.webp);aspect-ratio:2.824}.m7{--u:url(/assets/img/home/img-08-cd02cc46.webp);aspect-ratio:2.1}.m8{--u:url(/assets/img/home/img-09-88c8afcd.webp);aspect-ratio:0.845}.m9{--u:url(/assets/img/home/img-10-db77c85d.webp);aspect-ratio:2.979}.m10{--u:url(/assets/img/home/img-11-c0f97a6e.webp);aspect-ratio:2.274}.m11{--u:url(/assets/img/home/img-12-b97c25a3.webp);aspect-ratio:2.75}.m12{--u:url(/assets/img/home/img-13-abfec0b5.webp);aspect-ratio:1.788}.m13{--u:url(/assets/img/home/img-14-412e71e3.webp);aspect-ratio:6.442}.m14{--u:url(/assets/img/home/img-15-b4453697.webp);aspect-ratio:3.949}.m15{--u:url(/assets/img/home/img-16-393c8875.webp);aspect-ratio:7.947}.m16{--u:url(/assets/img/home/img-17-8647a73b.webp);aspect-ratio:3.822}.m17{--u:url(/assets/img/home/img-18-90535357.webp);aspect-ratio:3.803}.m18{--u:url(/assets/img/home/img-19-49cfe494.webp);aspect-ratio:1.96}.m19{--u:url(/assets/img/home/img-20-bc1a137d.webp);aspect-ratio:6.108}.m20{--u:url(/assets/img/home/img-21-fede0140.webp);aspect-ratio:10.718}.m21{--u:url(/assets/img/home/img-22-835eee16.webp);aspect-ratio:5.418}.m22{--u:url(/assets/img/home/img-23-1dab20c2.webp);aspect-ratio:1.723}.m23{--u:url(/assets/img/home/img-24-23e68c83.webp);aspect-ratio:3.574}

  /* ===== « Le problème » — texte posé sur la photo .slab, plus de bloc
     camel séparé (fusionnés le 02/09 : id `probleme-sec` porté par la
     <figure>, le fondu vers la section suivante reste sur .to-camel) ===== */
  #probleme-sec{position:relative;overflow:hidden}
  /* Fondu en haut (retour 18/09, remplace le bas) : depuis l'inversion de
     l'ordre des sections, .to-camel suit désormais « Nos solutions »
     (fond camel) au lieu de le précéder — le raccord doit donc se faire
     en haut de la photo, pas en bas. */
  .slab.to-camel{position:relative}
  .slab.to-camel::after{content:"";position:absolute;left:0;right:0;top:-1px;
    height:clamp(260px,46vh,600px);pointer-events:none;z-index:1;
    background:linear-gradient(to top,
      color-mix(in srgb,var(--terra) 0%,transparent) 0%,
      color-mix(in srgb,var(--terra) 2%,transparent) 10%,
      color-mix(in srgb,var(--terra) 8%,transparent) 20%,
      color-mix(in srgb,var(--terra) 18%,transparent) 30%,
      color-mix(in srgb,var(--terra) 32%,transparent) 40%,
      color-mix(in srgb,var(--terra) 50%,transparent) 50%,
      color-mix(in srgb,var(--terra) 68%,transparent) 60%,
      color-mix(in srgb,var(--terra) 82%,transparent) 70%,
      color-mix(in srgb,var(--terra) 92%,transparent) 80%,
      color-mix(in srgb,var(--terra) 98%,transparent) 90%,
      var(--terra) 100%)}
  /* Fondu blanc en bas (retour 19/09) : la section qui suit est blanche, la photo s'y fond
     comme les autres transitions du site. */
  .slab.to-camel::before{content:"";position:absolute;left:0;right:0;bottom:-1px;
    height:clamp(200px,34vh,420px);pointer-events:none;z-index:1;
    background:linear-gradient(to bottom,
      color-mix(in srgb,var(--fond) 0%,transparent) 0%,
      color-mix(in srgb,var(--fond) 8%,transparent) 15%,
      color-mix(in srgb,var(--fond) 22%,transparent) 30%,
      color-mix(in srgb,var(--fond) 42%,transparent) 45%,
      color-mix(in srgb,var(--fond) 64%,transparent) 60%,
      color-mix(in srgb,var(--fond) 82%,transparent) 75%,
      color-mix(in srgb,var(--fond) 94%,transparent) 88%,
      var(--fond) 100%)}
  .slab.to-camel figcaption{z-index:2}
  #probleme-sec .cocktail>p:not(.mut){color:var(--blanc)}   /* énoncé */
  #probleme-sec .mut{color:var(--creme);opacity:.9}
  #probleme-sec .mut em{color:var(--blanc);font-weight:600}


  /* soulignement de la promesse */
  #probleme-sec .snap{position:relative}
  #probleme-sec .snap::after{content:"";position:absolute;left:0;right:100%;bottom:-.14em;height:2px;background:var(--creme)}
  #probleme-sec.in .snap::after{animation:pb-draw 3s var(--out) 1.6s 1 forwards}
  @keyframes pb-draw{0%{right:100%}100%{right:0}}

  /* ---- l'onde sonore, en boucle ---- */
  /* Elle remplace le trait qui fermait la section : celui-ci ne s'animait
     qu'une fois, au scroll, puis restait plat — donc lu comme un filet, pas
     comme un signal. Trois couches de périodes et de vitesses différentes, la
     deuxième à contresens : elles se croisent sans jamais retomber en phase.
     `preserveAspectRatio:none` étire l'onde sur toute la bande (le `meet`
     d'avant n'en remplissait que 41 px sur 70) ; `non-scaling-stroke` empêche
     cet étirement d'épaissir le trait au passage. */
  #probleme-sec .onde{margin-top:22px;max-width:none;height:44px;overflow:hidden;margin-left:auto} /* diminuée, alignée sur la largeur du texte de la carte (02/09) */
  #probleme-sec .onde svg{width:100%;height:100%;display:block}
  #probleme-sec .onde path{fill:none;stroke:var(--creme);stroke-linecap:round;
    vector-effect:non-scaling-stroke}
  /* Le pas vaut exactement une période : c'est ce qui rend la boucle
     invisible. Il est déclaré ici, à côté de la période du tracé. */
  #probleme-sec .onde g{animation:onde-glisse var(--t) linear infinite;will-change:transform}
  #probleme-sec .onde .o1{--t:9s;--p:300px}
  #probleme-sec .onde .o1 path{stroke-width:1.6}
  #probleme-sec .onde .o2{--t:8s;--p:196px;animation-direction:reverse;opacity:.55}
  #probleme-sec .onde .o2 path{stroke-width:1.2}
  #probleme-sec .onde .o3{--t:6.5s;--p:122px;opacity:.32}
  #probleme-sec .onde .o3 path{stroke-width:1}
  @keyframes onde-glisse{from{transform:translateX(0)}
    to{transform:translateX(calc(var(--p) * -1))}}

  @media (prefers-reduced-motion:reduce){
    #probleme-sec .snap::after{animation:none;right:0}
    /* L'onde reste, elle ne bouge plus : la forme porte le sens. */
    #probleme-sec .onde g{animation:none}
  }


  /* Frise horizontale (remplace la timeline verticale le 08/09, retour
     client : le nuage sur le filet n'était pas synchro avec les cartes qui
     apparaissaient — cf. brain). Snap-scroll natif, même motif que
     .obj-track ci-dessus, mais sans auto-défilement : un contenu à lire ne
     doit pas courir. Révélée via data-reveal (reveal.js) — jamais
     d'opacity:0 au repos, un simple décalage vertical, en cascade (--i,
     même geste que .tm-grid en theme.css). Easing expo-out (--pq-ease) :
     démarrage franc, fin très amortie, plus fluide que le cubic-bezier
     « material » du premier essai (retour client 08/09 : pictos + douceur). */
  #pourquoi .pq-track{--gap:clamp(20px,2.4vw,28px);display:flex;gap:var(--gap);
    overflow-x:auto;scroll-snap-type:x mandatory;scrollbar-width:none;
    padding:8px 0 4px;margin-top:clamp(36px,4.6vw,64px);
    --pq-ease:cubic-bezier(.16,1,.3,1)}
  #pourquoi .pq-track::-webkit-scrollbar{display:none}
  /* Barre de progression : même mécanisme que .obj-progress ci-dessus. */
  #pourquoi .pq-progress{height:3px;background:color-mix(in srgb,var(--terra) 25%,transparent);
    border-radius:2px;margin-top:18px;overflow:hidden}
  #pourquoi .pq-progress span{display:block;height:100%;width:25%;background:var(--terra);
    border-radius:2px;transition:width .25s ease}
  #pourquoi .pq-card{--i:0;position:relative;flex:0 0 calc((100% - 3*var(--gap))/4);
    scroll-snap-align:start;background:var(--terra);border-radius:16px;
    padding:clamp(28px,3.2vw,46px);min-height:280px}
  #pourquoi .pq-card:nth-child(2){--i:1}
  #pourquoi .pq-card:nth-child(3){--i:2}
  #pourquoi .pq-card:nth-child(4){--i:3}
  /* Pictogrammes trait fin, même langage que .proto-ic un peu plus bas
     (stroke, pas fill) — mais pleins de contraste ici (blanc sur camel),
     pas en filigrane de fond : ce sont des repères de lecture, pas un motif
     décoratif. En repère haut-droite, plus grands (retour client 08/09). */
  #pourquoi .pq-ic{position:absolute;top:clamp(24px,2.8vw,38px);right:clamp(24px,2.8vw,38px);
    width:clamp(44px,4.4vw,58px);height:clamp(44px,4.4vw,58px);
    fill:none;stroke:var(--blanc);stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
  #pourquoi .pq-card .n{display:block;overflow:hidden;font-family:var(--serif);
    font-weight:700;font-size:clamp(36px,3.8vw,52px);line-height:1.15;color:var(--blanc);
    margin-bottom:24px;font-variant-numeric:tabular-nums}
  #pourquoi .pq-card .n>span{display:block}
  #pourquoi .pq-card h3{font-size:clamp(23px,2.2vw,30px);margin:0 0 16px;
    color:var(--blanc);line-height:1.15}
  #pourquoi .pq-card p{margin:0;color:var(--blanc);font-size:16px;line-height:1.65}
  #pourquoi .pq-track.anim .pq-card{opacity:0;transform:translateY(56px) scale(.92)}
  #pourquoi .pq-track.anim.in .pq-card{opacity:1;transform:none;
    will-change:transform,opacity;
    animation:pq-card-in 1600ms var(--pq-ease) calc(var(--i) * 130ms) both}
  #pourquoi .pq-track.anim.in .pq-card .pq-ic{
    will-change:transform,opacity;
    animation:pq-icon-in 1200ms var(--pq-ease) calc(var(--i) * 130ms) both}
  #pourquoi .pq-track.anim.in .pq-card .n>span{
    will-change:transform,opacity;
    animation:pq-number-in 1100ms var(--pq-ease) calc(120ms + var(--i) * 130ms) both}
  @keyframes pq-card-in{
    from{opacity:0;transform:translateY(56px) scale(.92)}
    to{opacity:1;transform:translateY(0) scale(1)}
  }
  @keyframes pq-icon-in{
    from{opacity:0;transform:translateY(18px) scale(.5)}
    to{opacity:1;transform:translateY(0) scale(1)}
  }
  @keyframes pq-number-in{
    from{opacity:0;transform:translateY(100%)}
    to{opacity:1;transform:translateY(0)}
  }
  @media(prefers-reduced-motion:reduce){
    #pourquoi .pq-track.anim .pq-card,
    #pourquoi .pq-track.anim.in .pq-card .pq-ic,
    #pourquoi .pq-track.anim.in .pq-card .n>span{
      animation:none;opacity:1;transform:none}
  }
  @media(max-width:1100px){#pourquoi .pq-card{flex-basis:calc((100% - var(--gap))/2)}}
  @media(max-width:640px){
    /* Empilement vertical plutôt que scroll-snap horizontal (retour client :
       même comportement que .trio/.pil). */
    #pourquoi .pq-track{flex-direction:column;overflow-x:visible;scroll-snap-type:none}
    #pourquoi .pq-card{flex-basis:auto;width:100%;min-height:0}
  }


  /* Les témoignages composaient en cartes blanches à rayon 16px, la grammaire
     des pages internes (.bcard, .temoin dans theme.css). L'accueil, elle,
     compose en angle net, fond transparent et filet 1px : .plate, .temps, .pq
     et le formulaire n'ont aucun rayon ni fond. Le motif repris ici est celui
     de #pourquoi, la section qui précède immédiatement. */
  /* Les témoignages (.tm-grid/.tm) ont migré dans theme.css : la page
     réalisations les emploie aussi, et une DA ne se duplique pas. */

/* ---- #contact : le formulaire dans une carte à liseré camel (retour
   client 09/09) — un fond plein (bleu, puis blanc) avait été écarté le
   03/09 ; un simple contour n'est pas un fond, il structure sans reprendre
   ce qui avait été retiré. Même `border-radius` que `.real-map-card`. ---- */
.ct-card{padding:clamp(28px,3.2vw,44px);border:1px solid var(--camel);border-radius:16px}

/* ---- pied de page ----
   Descendu dans `theme.css` le 18/08 : il n'y a plus qu'un pied, servi par les
   20 pages. Il ne dépend plus de `.w` ni de `.mut`, qui n'existent qu'ici. */

/* Photo d'étape du protocole : l'image vient de `acloud_protocole()` (style en ligne). */
.proto-c.proto-photo{background-size:cover;background-position:65% center}
.proto-photo::before{content:"";position:absolute;inset:0;background:rgba(0,0,0,.38);z-index:1;pointer-events:none}
.proto-photo .proto-n,.proto-photo h3{color:#fff;z-index:1;text-shadow:0 1px 8px rgba(0,0,0,.4)}
.proto-photo p{z-index:2;background:transparent;color:#fff;text-shadow:0 1px 8px rgba(0,0,0,.6)}
