/* ============================================================================
   motion.css — Système de profondeur & chorégraphie « Sillage »
   Namespace .syn-*  ·  partagé par la home (scroller = <body>) ET les sous-pages
   (scroller = racine). Aucune librairie, aucun build. Auto-hébergé sous /assets.

   ── RÈGLE D'OR PORTABILITÉ (deux modèles de scroll) ────────────────────────
   • Timelines ANONYMES uniquement : animation-timeline: view() / scroll(nearest).
   • JAMAIS scroll(root) → la racine ne scrolle pas sur la home (figé à 0 %).
   • JAMAIS de scroll-timeline-name nommé → devrait vivre sur l'élément scrollant,
     qui diffère selon la page. view() résout tout seul le bon scrollport.

   ── DÉGRADATION (enhancement-only) ─────────────────────────────────────────
   • Natif supporté  → reveal piloté par le CSS scroll-driven (marche sans JS).
   • Pas de natif + JS → html.syn-js active le masquage, motion.js pose .is-in.
   • Pas de natif + pas de JS → jamais masqué : contenu STATIQUE et VISIBLE.
   • prefers-reduced-motion → tout mouvement retiré, contenu statique.

   Propriétés compositor uniquement (transform / opacity / clip-path ;
   filter/brightness avec parcimonie). Pas de will-change généralisé.
   ============================================================================ */

:root {
  /* easing : retombe sur la valeur hôte (--ease des sous-pages) sinon défaut */
  --syn-ease:    var(--ease, cubic-bezier(0.22, 1, 0.36, 1));
  --syn-rise:    34px;   /* amplitude de montée des reveals */
  --syn-dur:     0.9s;   /* durée des entrées time-based */
  --syn-stagger: 90ms;   /* décalage entre éléments (--syn-i) */
  --syn-drift:   6%;     /* amplitude parallax (% de la hauteur de l'élément) */
  --syn-pscale:  1.16;   /* sur-échelle : évite les bords vides quand un plan translate
                            dans un conteneur en overflow:hidden (images) */
}

/* ── Keyframes partagés ──────────────────────────────────────────────────── */
@keyframes syn-rise-kf {
  from { opacity: 0; transform: translateY(var(--syn-rise)); }
  to   { opacity: 1; transform: none; }
}
@keyframes syn-wipe-kf {
  from { opacity: 0; clip-path: inset(0 0 100% 0); transform: translateY(var(--syn-rise)); }
  to   { opacity: 1; clip-path: inset(0 0 0 0);   transform: none; }
}
@keyframes syn-title-kf {
  from { opacity: 0; clip-path: inset(0 100% 0 0); transform: translateY(0.14em); }
  to   { opacity: 1; clip-path: inset(0 0 0 0);    transform: none; }
}
@keyframes syn-drift-kf {
  from { transform: translateY(calc(var(--syn-plane, 1) * var(--syn-drift) * -1)) scale(var(--syn-pscale)); }
  to   { transform: translateY(calc(var(--syn-plane, 1) * var(--syn-drift)))      scale(var(--syn-pscale)); }
}
@keyframes syn-settle-kf {
  from { opacity: 0.5; transform: perspective(1200px) rotateX(7deg) translateY(var(--syn-rise)) scale(0.955); }
  to   { opacity: 1;   transform: perspective(1200px) rotateX(0deg) translateY(0)                scale(1);     }
}

@media (prefers-reduced-motion: no-preference) {

  /* ── 1. Reveal au scroll (montée + fondu) — pour le contenu SOUS la ligne de flottaison ── */
  @supports (animation-timeline: view()) {
    .syn-reveal {
      animation: syn-rise-kf both linear;
      animation-timeline: view();
      animation-range: entry 0% entry 58%;
    }
    .syn-reveal--wipe {
      animation: syn-wipe-kf both linear;
      animation-timeline: view();
      animation-range: entry 0% entry 66%;
    }
  }
  /* Fallback JS (Firefox / Safari ≤18) : masqué seulement si le JS a pris la main */
  @supports not (animation-timeline: view()) {
    html.syn-js .syn-reveal,
    html.syn-js .syn-reveal--wipe {
      opacity: 0;
      transform: translateY(var(--syn-rise));
      transition: opacity var(--syn-dur) var(--syn-ease),
                  transform var(--syn-dur) var(--syn-ease),
                  clip-path var(--syn-dur) var(--syn-ease);
      transition-delay: calc(var(--syn-i, 0) * var(--syn-stagger));
    }
    html.syn-js .syn-reveal--wipe { clip-path: inset(0 0 100% 0); }
    html.syn-js .syn-reveal.is-in,
    html.syn-js .syn-reveal--wipe.is-in {
      opacity: 1;
      transform: none;
      clip-path: inset(0 0 0 0);
    }
  }

  /* ── 2. Entrée time-based (pour le contenu AU-DESSUS de la ligne de flottaison :
        héros de page). Universel — pas de scroll-timeline (sinon déjà « révélé »
        au chargement puisque déjà dans le viewport). ── */
  .syn-rise-in {
    animation: syn-rise-kf var(--syn-dur) var(--syn-ease) both;
    animation-delay: calc(var(--syn-i, 0) * var(--syn-stagger));
  }
  .syn-title-wipe {
    animation: syn-title-kf calc(var(--syn-dur) + 0.2s) var(--syn-ease) both;
    animation-delay: calc(var(--syn-i, 0) * var(--syn-stagger));
  }

  /* ── 3. Parallax multi-plans — profondeur (enhancement natif, sinon statique) ── */
  @supports (animation-timeline: view()) {
    .syn-parallax {
      animation: syn-drift-kf both linear;
      animation-timeline: view();
      animation-range: cover 0% cover 100%;
      will-change: transform;
    }
  }

  /* ── 4. Empilement sticky (« des choses qui montent sur les autres ») ────────
        Le socle (position:sticky) est UNIVERSEL — marche même sans natif ni JS.
        Chaque panneau se fige en haut du scrollport ; le suivant monte par-dessus.
        Fond opaque requis pour couvrir le panneau précédent. ── */
  .syn-deck { display: block; }
  .syn-deck-panel {
    position: sticky;
    top: 0;
    min-height: 100vh;
    min-height: 100svh;
    background-color: var(--bg, #F1ECE1);
  }

  /* ── 5. Dépose scrubée : l'élément entre légèrement incliné puis se pose ────── */
  @supports (animation-timeline: view()) {
    .syn-scrub {
      animation: syn-settle-kf both linear;
      animation-timeline: view();
      animation-range: entry 6% contain 32%;
    }
  }

}

/* ── 6. Scène en perspective (groupes d'images en couches) ───────────────────
      Statique (marche partout). ATTENTION Safari : un ancêtre avec
      perspective/transform devient le bloc conteneur et casse le position:sticky
      des descendants → ne JAMAIS mettre .syn-scene en ancêtre d'un .syn-deck. */
.syn-scene {
  perspective: 1200px;
  transform-style: preserve-3d;
}
.syn-scene [data-z] {
  transform: translateZ(calc(var(--syn-z, 0) * 1px));
}

/* ════════════════════════════════════════════════════════════════════════════
   7. Sous-pages — reveals automatiques (scopé html.syn-auto)
   Aucune classe .syn-* à poser sur le markup : on cible les composants standard
   de base.css. Le marqueur .syn-auto n'existe que sur les sous-pages, donc la
   home (qui charge aussi ce fichier) n'est jamais touchée.
   ════════════════════════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: no-preference) {

  /* Héros de page (au-dessus de la ligne de flottaison) → entrées time-based,
     vues au chargement. Le h1 Beverly Hills se dévoile en volet. */
  .syn-auto .page-hero h1 {
    animation: syn-title-kf calc(var(--syn-dur) + 0.25s) var(--syn-ease) both;
    animation-delay: 120ms;
  }
  .syn-auto .page-hero-eyebrow {
    animation: syn-rise-kf var(--syn-dur) var(--syn-ease) both;
  }
  .syn-auto .page-hero-lede {
    animation: syn-rise-kf var(--syn-dur) var(--syn-ease) both;
    animation-delay: 280ms;
  }

  /* Contenu sous la ligne de flottaison : reveal au scroll, au grain du BLOC
     (pas de la section entière → pas de mouvement imbriqué). Les titres, cartes,
     sous-titres de prose, specs et bannières montent quand ils entrent. */
  @supports (animation-timeline: view()) {
    .syn-auto .section-eyebrow,
    .syn-auto .section-title,
    .syn-auto .prose > h2,
    .syn-auto .prose > h3,
    .syn-auto .grid-cards > .card,
    .syn-auto .specs,
    .syn-auto .invitation-banner {
      animation: syn-rise-kf both linear;
      animation-timeline: view();
      animation-range: entry 0% entry 50%;
    }
    /* léger décalage des cartes d'une même grille (stagger sans toucher le markup) */
    .syn-auto .grid-cards > .card:nth-child(2)   { animation-range-start: entry 8%; }
    .syn-auto .grid-cards > .card:nth-child(3)   { animation-range-start: entry 15%; }
    .syn-auto .grid-cards > .card:nth-child(n+4) { animation-range-start: entry 22%; }
  }
  /* Fallback JS (Firefox / Safari ≤18) : masqué seulement si le JS a pris la main */
  @supports not (animation-timeline: view()) {
    html.syn-js.syn-auto .section-eyebrow,
    html.syn-js.syn-auto .section-title,
    html.syn-js.syn-auto .prose > h2,
    html.syn-js.syn-auto .prose > h3,
    html.syn-js.syn-auto .grid-cards > .card,
    html.syn-js.syn-auto .specs,
    html.syn-js.syn-auto .invitation-banner {
      opacity: 0;
      transform: translateY(var(--syn-rise));
      transition: opacity var(--syn-dur) var(--syn-ease),
                  transform var(--syn-dur) var(--syn-ease);
    }
    html.syn-js.syn-auto .section-eyebrow.is-in,
    html.syn-js.syn-auto .section-title.is-in,
    html.syn-js.syn-auto .prose > h2.is-in,
    html.syn-js.syn-auto .prose > h3.is-in,
    html.syn-js.syn-auto .grid-cards > .card.is-in,
    html.syn-js.syn-auto .specs.is-in,
    html.syn-js.syn-auto .invitation-banner.is-in {
      opacity: 1;
      transform: none;
    }
  }
}
