/* ==========================================================================
   Purephotoart · feuille de style du moteur d'animation
   Se superpose à home.css et main.css sans dépendre de leurs variables :
   toutes les couleurs passent par des fallbacks.
   ========================================================================== */

:root {
  --m-ease: cubic-bezier(.16, 1, .3, 1);
  --m-ease-soft: cubic-bezier(.22, .61, .36, 1);
  --m-accent: var(--accent, #ef6a4c);
  --m-paper: var(--paper, var(--white, #f4f0e7));
  --m-ink: var(--ink, var(--black, #0b0b0a));
  --m-shift: 0px;
  --m-zoom: 1;
  --m-skew: 0deg;
  --m-squash: 1;
}

/* `overflow-x: hidden` sur <body> transforme le corps de page en conteneur
   de défilement, ce qui neutralise silencieusement `position: sticky` chez
   ses descendants, donc le fil horizontal et l'image plein écran. `clip`
   coupe exactement le même débordement sans créer ce conteneur.
   Le @supports garde l'ancien comportement sur les navigateurs sans `clip`. */
@supports (overflow: clip) {
  html { overflow-x: clip; }
  body { overflow-x: clip; }
}

/* Les modules JS ne doivent rien casser si le script ne se charge pas :
   on ne masque le contenu que lorsque la classe est posée. */
.motion-ready [data-split] .m-word-in,
.motion-ready [data-stagger] > * {
  will-change: transform, opacity;
}

/* ==========================================================================
   1. Révélations
   ========================================================================== */
/* Version précédente : chaque mot dans un masque `overflow: hidden` pour le
   faire monter depuis le bas. Le masque coupait les jambages (j, g, p) et
   les accents des capitales, d'autant plus avec le line-height serré des
   titres. Les mots montent maintenant sans masque : rien ne peut être
   rogné, quelle que soit la police ou la taille. */
.m-word {
  display: inline-block;
  vertical-align: baseline;
}

.m-word-in {
  display: inline-block;
  transform: translateY(.34em);
  opacity: 0;
  filter: blur(6px);
  transition:
    transform .9s var(--m-ease),
    opacity .65s ease,
    filter .65s ease;
}

[data-split].is-revealed .m-word-in {
  transform: translateY(0);
  opacity: 1;
  filter: blur(0);
}

.motion-ready [data-stagger] > * {
  opacity: 0;
  transform: translateY(38px) scale(.985);
  transition:
    opacity .85s var(--m-ease) var(--m-delay, 0ms),
    transform 1.05s var(--m-ease) var(--m-delay, 0ms);
}

[data-stagger].is-revealed > * {
  opacity: 1;
  transform: none;
}

/* La règle ci-dessus reprend la transform des enfants et effacerait ce
   survol-là, qui existait avant. On le redéclare. */
.steps[data-stagger].is-revealed > li:hover { transform: translateY(-8px); }

/* ==========================================================================
   2. Parallaxe
   ========================================================================== */
[data-parallax]:not([data-parallax-inner]) {
  transform: translate3d(0, var(--m-shift), 0) scale(var(--m-zoom));
  will-change: transform;
}

/* Sur une image cadrée, on bouge l'image dans son cadre plutôt que le
   cadre lui-même : sans quoi le décalage ouvre une bande vide sur le bord.
   L'échelle de 1.18 fournit la marge dans laquelle l'image se déplace. */
[data-parallax-inner] { overflow: hidden; }

[data-parallax-inner] > img,
[data-parallax-inner] > picture > img {
  transform: translate3d(0, var(--m-shift), 0) scale(1.18);
  will-change: transform;
}

/* Le hero portait déjà une animation d'entrée posée sur l'image, qui
   verrouillait sa transform. On la déplace sur le cadre pour libérer
   l'image et lui confier la parallaxe. */
.motion-ready .hero-shot { animation: m-fade-in 1.6s var(--m-ease) both; }
.motion-ready .hero-shot--event { animation-delay: .12s; }
.motion-ready .hero-shot--aerial { animation-delay: .24s; }
.motion-ready .hero-shot img { animation: none; }

@keyframes m-fade-in { from { opacity: 0; } to { opacity: 1; } }

/* Le titre du hero avait son propre fondu : la révélation mot à mot
   le remplace, sinon les deux se superposent. */
.motion-ready .hero h1[data-split] { opacity: 1; animation: none; }

/* ==========================================================================
   3. Section collante à défilement horizontal
   ========================================================================== */
.hscroll {
  position: relative;
  background: var(--m-ink);
}

.hscroll-sticky {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  overflow: hidden;
}

.hscroll-head {
  position: absolute;
  top: clamp(72px, 11vh, 130px);
  left: clamp(20px, 5vw, 72px);
  right: clamp(20px, 5vw, 72px);
  z-index: 3;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px;
  pointer-events: none;
}

.hscroll-head h2 {
  margin: 0;
  font-size: clamp(28px, 4.2vw, 60px);
  font-weight: 300;
  letter-spacing: -.03em;
  line-height: 1;
}

.hscroll-head em {
  font-style: italic;
  color: var(--m-accent);
}

.hscroll-kicker {
  margin: 0 0 12px;
  font-size: 11px;
  letter-spacing: .24em;
  text-transform: uppercase;
  color: var(--m-accent);
}

.hscroll-count {
  font-size: clamp(30px, 5vw, 64px);
  font-weight: 300;
  line-height: 1;
  letter-spacing: -.04em;
  opacity: .55;
  font-variant-numeric: tabular-nums;
}

.hscroll-count b {
  font-weight: 300;
  color: var(--m-accent);
  opacity: 1;
}

.hscroll-track {
  display: flex;
  align-items: center;
  gap: clamp(18px, 3vw, 46px);
  padding: 0 clamp(20px, 12vw, 220px);
  will-change: transform;
}

.hscroll-card {
  position: relative;
  flex: 0 0 auto;
  width: clamp(240px, 30vw, 440px);
  padding: 0;
  border: 0;
  background: none;
  text-align: left;
  cursor: pointer;
  transform:
    perspective(1400px)
    translate3d(0, var(--m-lift, 0px), 0)
    rotateY(var(--m-tiltY, 0deg))
    scale(calc(.9 + var(--m-depth, 0) * .1));
  transition: filter .5s ease;
  filter: brightness(calc(.55 + var(--m-depth, 0) * .45));
  will-change: transform, filter;
}

.hscroll-card--tall { width: clamp(220px, 25vw, 360px); }
.hscroll-card--wide { width: clamp(300px, 42vw, 640px); }

.hscroll-media {
  display: block;
  position: relative;
  overflow: hidden;
  border-radius: 4px;
  aspect-ratio: 3 / 4;
  background: #14140f;
}

.hscroll-card--tall .hscroll-media { aspect-ratio: 2 / 3; }
.hscroll-card--wide .hscroll-media { aspect-ratio: 16 / 10; }

.hscroll-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: translate3d(var(--m-pan, 0%), 0, 0) scale(1.16);
  transition: transform .1s linear;
  will-change: transform;
}

.hscroll-media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, transparent 45%, rgba(0, 0, 0, .68));
  opacity: calc(1 - var(--m-depth, 0) * .6);
  transition: opacity .4s ease;
}

.hscroll-meta {
  position: absolute;
  left: 18px;
  right: 18px;
  bottom: 16px;
  z-index: 2;
  transform: translateY(calc((1 - var(--m-depth, 0)) * 14px));
  opacity: var(--m-depth, 0);
  transition: transform .4s var(--m-ease), opacity .4s ease;
}

.hscroll-meta strong {
  display: block;
  font-size: clamp(15px, 1.4vw, 21px);
  font-weight: 400;
  letter-spacing: -.01em;
}

.hscroll-meta small {
  display: block;
  margin-top: 3px;
  font-size: 11px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--m-accent);
}

.hscroll-card.is-focus .hscroll-media {
  box-shadow: 0 40px 90px -30px rgba(0, 0, 0, .9);
}

.hscroll-foot {
  position: absolute;
  left: clamp(20px, 5vw, 72px);
  right: clamp(20px, 5vw, 72px);
  bottom: clamp(28px, 6vh, 60px);
  z-index: 3;
  display: flex;
  align-items: center;
  gap: 18px;
  pointer-events: none;
}

.hscroll-bar {
  position: relative;
  flex: 1;
  height: 1px;
  background: rgba(244, 240, 231, .16);
}

.hscroll-bar-fill {
  position: absolute;
  inset: 0;
  background: var(--m-accent);
  transform-origin: 0 50%;
  transform: scaleX(0);
}

.hscroll-hint {
  font-size: 10px;
  letter-spacing: .24em;
  text-transform: uppercase;
  color: rgba(244, 240, 231, .5);
  white-space: nowrap;
}

/* Le geste n'est pas le même selon l'appareil : on fait défiler à la
   molette, on fait glisser au doigt. La consigne suit. */
.hscroll-hint--swipe { display: none; }

/* --- Version mobile ------------------------------------------------------
   Le verrouillage vertical n'a pas de sens au doigt : on ne peut pas
   « bloquer » un scroll tactile sans le rendre pénible. En dessous de
   900 px la section redevient donc ce qu'elle est vraiment, un carrousel
   qu'on fait glisser, avec accroche par carte et pagination lisible.
   Tout revient dans le flux : plus de sticky, plus d'absolu, plus de
   hauteur imposée par le JS. */
@media (max-width: 900px) {
  .hscroll { height: auto !important; }

  .hscroll-sticky {
    position: static;
    height: auto;
    display: block;
    padding: clamp(70px, 13vw, 110px) 0 clamp(50px, 10vw, 80px);
    overflow: visible;
  }

  .hscroll-head {
    position: static;
    display: block;
    margin: 0 var(--m-gutter, 20px) clamp(26px, 6vw, 40px);
    pointer-events: auto;
  }
  .hscroll-head h2 { font-size: clamp(30px, 8.5vw, 46px); line-height: 1.02; }
  .hscroll-count { display: none; }

  .hscroll-track {
    display: flex;
    transform: none !important;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: var(--m-gutter, 20px);
    padding: 4px var(--m-gutter, 20px) 22px;
    gap: 12px;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .hscroll-track::-webkit-scrollbar { display: none; }

  /* Une carte occupe la largeur moins la gouttière, et laisse dépasser la
     suivante : c'est ce dépassement qui fait comprendre qu'on peut glisser. */
  .hscroll-card,
  .hscroll-card--tall,
  .hscroll-card--wide {
    width: calc(100vw - var(--m-gutter, 20px) * 2 - 46px);
    max-width: 420px;
    transform: none !important;
    filter: none !important;
    scroll-snap-align: start;
  }

  /* Un seul cadrage sur mobile : trois ratios différents donneraient une
     rangée en dents de scie une fois les cartes à la même largeur. */
  .hscroll-media,
  .hscroll-card--tall .hscroll-media,
  .hscroll-card--wide .hscroll-media { aspect-ratio: 4 / 5; }

  /* `!important` : les règles « cartes 3D » sont déclarées plus bas dans
     le fichier et l'emporteraient autrement. */
  .hscroll-media img { transform: none !important; }
  .hscroll-media::after { opacity: 1; }
  .hscroll-meta { opacity: 1; transform: none; }
  .hscroll-card::before { display: none; }
  .hscroll-card.is-focus .hscroll-media { box-shadow: none; }

  .hscroll-foot {
    position: static;
    margin: clamp(18px, 4vw, 26px) var(--m-gutter, 20px) 0;
    gap: 12px;
  }
  /* La barre est pilotée par le scroll vertical : sans lui, elle resterait
     figée à zéro. On garde seulement l'indication de geste. */
  .hscroll-bar { display: none; }
  .hscroll-hint--scroll,
  .hscroll-hint--series { display: none; }
  .hscroll-hint--swipe { display: inline; color: var(--m-accent); }
}

@media (max-width: 560px) {
  .hscroll-card,
  .hscroll-card--tall,
  .hscroll-card--wide { width: calc(100vw - 40px - 34px); }
  .hscroll-meta { left: 14px; right: 14px; bottom: 13px; }
  .hscroll-meta strong { font-size: 16px; }
}

.motion-reduced .hscroll,
.hscroll.is-static { height: auto !important; }
.motion-reduced .hscroll-sticky,
.hscroll.is-static .hscroll-sticky { position: static; height: auto; padding: 90px 0; }
.motion-reduced .hscroll-track,
.hscroll.is-static .hscroll-track { overflow-x: auto; transform: none !important; }
.motion-reduced .hscroll-card,
.hscroll.is-static .hscroll-card { transform: none !important; filter: none; }
.motion-reduced .hscroll-meta,
.hscroll.is-static .hscroll-meta { opacity: 1; transform: none; }

/* ==========================================================================
   4. Image qui s'ouvre en plein écran
   ========================================================================== */
.expand {
  position: relative;
  height: 260vh;
  background: var(--m-ink);
}

.expand-sticky {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  display: grid;
  place-items: center;
  overflow: hidden;
}

.expand-media {
  position: relative;
  margin: 0;
  overflow: hidden;
  /* Le cœur de l'effet : la largeur et la hauteur interpolent entre un
     cadre centré et le viewport entier, piloté par --m-p. */
  width: calc(46vw + (100vw - 46vw) * var(--m-p, 0));
  height: calc(58vh + (100vh - 58vh) * var(--m-p, 0));
  border-radius: calc(6px * (1 - var(--m-p, 0)));
  box-shadow: 0 60px 120px -50px rgba(0, 0, 0, calc(.9 * (1 - var(--m-p, 0))));
  will-change: width, height;
}

.expand-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: scale(calc(1.3 - .3 * var(--m-p, 0)));
  will-change: transform;
}

.expand-media::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg, rgba(0, 0, 0, .5) 0%, transparent 32%, transparent 58%, rgba(0, 0, 0, .78) 100%);
  opacity: var(--m-p, 0);
  transition: opacity .3s linear;
}

.expand-intro {
  position: absolute;
  z-index: 3;
  text-align: center;
  max-width: 30ch;
  padding: 0 24px;
  opacity: calc(1 - var(--m-p, 0) * 2.4);
  transform: translateY(calc(var(--m-p, 0) * -40px));
  pointer-events: none;
}

.expand-intro p {
  margin: 0;
  font-size: clamp(15px, 1.5vw, 19px);
  line-height: 1.5;
  color: rgba(244, 240, 231, .78);
}

.expand-caption {
  position: absolute;
  z-index: 4;
  left: clamp(24px, 6vw, 90px);
  right: clamp(24px, 6vw, 90px);
  bottom: clamp(48px, 9vh, 96px);
  opacity: calc((var(--m-p, 0) - .62) * 3.4);
  transform: translateY(calc((1 - var(--m-p, 0)) * 30px));
  pointer-events: none;
}

.expand-caption .hscroll-kicker { margin-bottom: 10px; }

.expand-caption h2 {
  margin: 0 0 10px;
  font-size: clamp(28px, 5vw, 72px);
  font-weight: 300;
  letter-spacing: -.035em;
  line-height: 1;
}

.expand-caption h2 em { font-style: italic; color: var(--m-accent); }

.expand-caption p {
  margin: 0;
  max-width: 52ch;
  font-size: clamp(14px, 1.3vw, 17px);
  color: rgba(244, 240, 231, .74);
}

.expand-caption a {
  pointer-events: auto;
}

@media (max-width: 860px) {
  .expand { height: 200vh; }
  .expand-media {
    width: calc(78vw + (100vw - 78vw) * var(--m-p, 0));
    height: calc(52vh + (100vh - 52vh) * var(--m-p, 0));
  }
}

.motion-reduced .expand,
.expand.is-static { height: auto; }
.motion-reduced .expand-sticky,
.expand.is-static .expand-sticky { position: static; height: auto; }
.motion-reduced .expand-media,
.expand.is-static .expand-media { width: 100%; height: 70vh; }
.motion-reduced .expand-intro,
.expand.is-static .expand-intro { display: none; }
.motion-reduced .expand-caption,
.expand.is-static .expand-caption { opacity: 1; transform: none; }

/* ==========================================================================
   5. Cartes 3D + tooltip
   ========================================================================== */
[data-tilt]:not(.hscroll-card) {
  transform:
    perspective(1100px)
    rotateX(var(--m-rx, 0deg))
    rotateY(var(--m-ry, 0deg))
    scale(var(--m-scale, 1));
  will-change: transform;
}

/* La brillance passe par ::before : les vignettes du site utilisent déjà
   ::after pour leur dégradé de légende, il ne faut pas l'écraser. */
[data-tilt]::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  opacity: 0;
  transition: opacity .45s ease;
  background: radial-gradient(
    360px circle at var(--m-gx, 50%) var(--m-gy, 50%),
    rgba(255, 255, 255, .26),
    transparent 62%
  );
  mix-blend-mode: soft-light;
}

[data-tilt].is-tilting::before { opacity: 1; }

/* Parallaxe interne : l'image glisse dans son cadre en sens inverse du
   curseur, la légende suit dans le même sens mais moins vite. Deux plans
   à vitesses différentes suffisent à lire la profondeur, et ça survit à
   l'overflow: hidden, qui aurait aplati un vrai translateZ. */
/* Les vignettes du site déclarent déjà `:hover img { transform: scale() }`.
   On reprend la main en montant à la même spécificité, motion.css étant
   chargé après, l'égalité nous revient. */
[data-tilt] img,
[data-tilt]:hover img,
[data-tilt].is-tilting img {
  transform:
    translate3d(var(--m-px, 0px), var(--m-py, 0px), 0)
    scale(calc(1.07 + var(--m-hover, 0) * .04));
  backface-visibility: hidden;
  will-change: transform;
}

[data-tilt].is-tilting { --m-hover: 1; }
[data-tilt].is-tilting img { transition: filter .4s ease; filter: brightness(1.05); }

[data-tilt] .gallery-caption,
[data-tilt] > span:not(.hscroll-meta) {
  transform: translate3d(var(--m-cx, 0px), calc(var(--m-cy, 0px) + var(--m-cap-y, 0px)), 0);
  transition: transform .4s var(--m-ease), opacity .4s ease;
}

[data-tilt]:not(.is-tilting) > span:not(.hscroll-meta) { --m-cap-y: 6px; }

/* Les cartes du fil horizontal cumulent leur position de piste et
   l'inclinaison du curseur : les deux se composent dans une seule
   transform, sinon la dernière déclarée efface l'autre. */
.hscroll-card[data-tilt] {
  transform:
    perspective(1400px)
    translate3d(0, var(--m-lift, 0px), 0)
    rotateY(calc(var(--m-tiltY, 0deg) + var(--m-ry, 0deg)))
    rotateX(var(--m-rx, 0deg))
    scale(calc((.9 + var(--m-depth, 0) * .1) * var(--m-scale, 1)));
}

.hscroll-card[data-tilt] img,
.hscroll-card[data-tilt]:hover img,
.hscroll-card[data-tilt].is-tilting img {
  transform: translate3d(calc(var(--m-pan, 0%) + var(--m-px, 0px)), var(--m-py, 0px), 0) scale(1.16);
}

.m-tip {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 9000;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 9px 14px;
  border-radius: 2px;
  background: var(--m-accent);
  color: #fff;
  pointer-events: none;
  opacity: 0;
  transition: opacity .28s ease;
  max-width: 260px;
}

.m-tip.is-visible { opacity: 1; }

.m-tip-label {
  font-size: 13px;
  font-weight: 500;
  line-height: 1.25;
}

.m-tip-hint {
  font-size: 9px;
  letter-spacing: .2em;
  text-transform: uppercase;
  opacity: .8;
}

.m-tip:empty,
.m-tip-label:empty + .m-tip-hint { display: none; }

@media (hover: none), (pointer: coarse) {
  .m-tip { display: none; }
}

/* ==========================================================================
   6. Bandeau à vitesse variable
   ========================================================================== */
.m-rail {
  overflow: hidden;
  white-space: nowrap;
}

.m-rail-track {
  display: inline-flex;
  align-items: center;
  will-change: transform;
}

/* Quand le JS pilote le bandeau, l'animation CSS d'origine doit se taire :
   les deux écriraient dans la même transform. */
.motion-ready [data-marquee-x] > * { animation: none; will-change: transform; }

/* ==========================================================================
   7. Inertie
   ========================================================================== */
[data-inertia] {
  transform: skewY(var(--m-skew, 0deg)) scaleY(var(--m-squash, 1));
  will-change: transform;
}

/* ==========================================================================
   8. Transition de page
   ========================================================================== */
.m-veil {
  position: fixed;
  inset: 0;
  z-index: 9500;
  background: var(--m-ink);
  opacity: 1;
  pointer-events: none;
  transition: opacity .6s var(--m-ease);
}

body.m-entered .m-veil { opacity: 0; }
body.m-leaving .m-veil { opacity: 1; transition-duration: .36s; }

/* ==========================================================================
   9. Cadran de progression
   ========================================================================== */
.m-dial {
  position: fixed;
  right: clamp(16px, 2.4vw, 34px);
  bottom: clamp(16px, 2.4vw, 34px);
  z-index: 700;
  width: 46px;
  height: 46px;
  display: grid;
  place-items: center;
  opacity: 0;
  transform: scale(.82);
  transition: opacity .45s ease, transform .45s var(--m-ease);
  pointer-events: none;
}

.m-dial.is-visible { opacity: 1; transform: scale(1); }

.m-dial svg { position: absolute; inset: 0; transform: rotate(-90deg); }

.m-dial circle {
  fill: none;
  stroke-width: 1.5;
}

.m-dial .m-dial-bg { stroke: rgba(244, 240, 231, .18); }
.m-dial .m-dial-ring { stroke: var(--m-accent); transition: stroke-dashoffset .1s linear; }

.m-dial-label {
  font-size: 10px;
  letter-spacing: .04em;
  font-variant-numeric: tabular-nums;
  color: var(--m-paper);
}

@media (max-width: 700px) { .m-dial { display: none; } }

/* ==========================================================================
   10. Mouvement réduit : on éteint tout
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  .m-word-in,
  [data-stagger] > * { transform: none !important; opacity: 1 !important; transition: none !important; }
  [data-parallax],
  [data-parallax-inner] > img,
  [data-tilt],
  [data-inertia] { transform: none !important; }
  .m-veil { display: none; }
  .m-tip { display: none; }
  .hscroll-card { filter: none !important; }
}
