﻿@charset "utf-8";
/* ═══════════════════════════════════════════════════════════════
   Les trois effets, en surcouche de styles.css.
   Rien n'est dupliqué : ce fichier n'ajoute que ce qui diffère.
   ═══════════════════════════════════════════════════════════════ */

/* --d doit être héritable : il est posé sur la citation et lu par .dessous */
@property --d  { syntax: "<number>"; initial-value: 0; inherits: true; }
@property --cp { syntax: "<number>"; initial-value: 0; inherits: true;  }
/* --s est posé sur la case et lu par les deux mots qu'elle contient : héritable */
@property --s  { syntax: "<number>"; initial-value: 0; inherits: true; }
@property --o  { syntax: "<number>"; initial-value: 1; inherits: false; }
@property --sp { syntax: "<number>"; initial-value: 0; inherits: true;  }

/* ─── EFFET 1 — le double fond des phrases ─────────────────────
   Ce qui est dit reste dans la serif : c'est leur voix.
   Ce que ça veut dire passe en sans : c'est la lecture du thérapeute.
   La place de la seconde couche est réservée dès le départ — aucune
   hauteur n'est animée, donc aucun reflow au défilement.            */

.citation--double { display: grid; align-content: start; }
.citation--double .dit {
  display: block;
  /* plancher à 0,58 : mesuré 5,35:1 sur --nuit-2, donc lisible à toutes les
     tailles. À 0,42 on tombait à 3,47:1, hors seuil pour les petites citations. */
  opacity: calc(1 - var(--d) * 0.42);
  transition: opacity 260ms var(--e-entree);
}
.citation--double .dessous {
  display: grid; gap: 0.3rem;
  margin-top: 0.9rem; padding-top: 0.85rem;
  border-top: 1px solid color-mix(in oklch, var(--safran) 34%, transparent);
  opacity: calc(var(--d) * 1.7 - 0.55);
  translate: 0 calc((1 - var(--d)) * 9px);
  transition: opacity 260ms var(--e-entree), translate 260ms var(--e-entree);
}
.dessous__label {
  font-family: var(--f-corps); font-size: 0.7rem; font-weight: 700;
  letter-spacing: 0.17em; text-transform: uppercase; color: var(--safran);
}
.dessous__texte {
  font-family: var(--f-corps); font-weight: 400;
  font-size: clamp(0.95rem, 0.9rem + 0.22vw, 1.1rem); line-height: 1.45;
  letter-spacing: 0; color: var(--creme-2);
}
/* le filet d'accent se remplit quand la seconde couche arrive */
.citation--double { position: relative; }
.citation--double::before {
  content: ""; position: absolute; left: -1.1rem; top: 0; width: 2px;
  height: calc(var(--d) * 100%); background: var(--safran);
  transition: height 260ms var(--e-entree);
}

/* ─── EFFET 2 — le curseur duel ⇄ duo ──────────────────────────── */

/* La piste donne au bloc de quoi rester en place pendant que la phrase se
   réécrit : ~100 vh de défilement, puis il repart avec la page. Ce n'est pas
   une scène plein écran — la porte reste le seul moment épinglé de ce genre. */
/* La piste sort du conteneur et prend toute la largeur : quand la carte est
   figée, c'est l'écran entier qui change de tonalité, pas seulement un encadré.
   Le fond est fait de lumière, pas d'une photo — une scène photographique ici
   entrerait en concurrence directe avec la porte, à quinze secondes de là. */
.curseur-piste {
  --teinte: color-mix(in oklch, var(--grenade), var(--safran) calc(var(--cp) * 100%));
  position: relative; height: 190vh;
  width: 100vw; margin: clamp(3rem, 6vw, 4.5rem) 0 0; margin-inline: calc(50% - 50vw);
}
/* Une scène d'exactement une hauteur d'écran, épinglée en haut : la carte y est
   centrée par la grille, donc elle ne descend jamais — quelle que soit sa taille. */
.curseur-scene {
  position: sticky; top: 0; height: 100vh; overflow: hidden;
  display: grid; place-items: center; padding-inline: var(--gouttiere);
  background:
    radial-gradient(78% 52% at calc(24% + var(--cp) * 52%) calc(44% - var(--cp) * 6%),
      color-mix(in oklch, var(--teinte), transparent calc(84% - var(--cp) * 10%)), transparent 66%),
    radial-gradient(120% 66% at 50% 50%, transparent 34%, color-mix(in oklch, var(--nuit) 70%, transparent) 100%),
    color-mix(in oklch, var(--nuit) 92%, var(--teinte));
}
/* Un olivier contre un mur d'ocre. Il entre dans le cadre et s'éclaire pendant
   que la phrase se reformule : ça pousse, ça ne soigne pas. Deux fauteuils vides
   face à face auraient dit « cabinet de psy » — précisément le registre que le
   client refuse ([04] : « thérapeute » jugé intimidant, effet repoussoir). */
.curseur-scene__lieu {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: 62% 42%;
  opacity: calc(0.12 + var(--cp) * 0.20);
  filter: saturate(calc(0.85 + var(--cp) * 0.35)) brightness(calc(0.52 + var(--cp) * 0.5));
  transform: scale(calc(1.16 - var(--cp) * 0.16)) translateY(calc(var(--cp) * -1.5%));
  transform-origin: 66% 100%;
}

/* La teinte du bloc fait le même trajet que la phrase : grenade au départ,
   safran à l'arrivée. C'est ce qui donne envie de rester le temps que ça se fasse. */
/* Plus de cadre : le texte est posé directement sur la scène. Le voile qui
   suit remplace le fond de la carte — invisible, mais c'est lui qui tient le
   contraste au-dessus du mur d'ocre en pleine lumière. */
.curseur {
  position: relative; z-index: 2;
  width: min(100%, 52rem); margin-inline: auto;
}
.curseur::before {
  content: ""; position: absolute; inset: -30% -16%; z-index: -2;
  background: radial-gradient(62% 60% at 44% 50%,
    color-mix(in oklch, var(--nuit) 93%, transparent) 0%,
    color-mix(in oklch, var(--nuit) 72%, transparent) 52%,
    transparent 78%);
}
/* la teinte du moment, très étalée, par-dessus le voile */
.curseur__lueur {
  position: absolute; inset: -34% -20%; z-index: -1; pointer-events: none;
  border-radius: 50%; filter: blur(58px);
  background: radial-gradient(56% 56% at calc(24% + var(--cp) * 54%) 44%,
    color-mix(in oklch, var(--teinte), transparent calc(86% - var(--cp) * 10%)), transparent 70%);
}
.curseur__corps { position: relative; z-index: 1; }
.curseur__surtitre {
  margin: 0 0 0.5rem; font-size: var(--pas-menu); font-weight: 700;
  letter-spacing: 0.17em; text-transform: uppercase; color: var(--safran);
}
.curseur__titre {
  margin: 0; font-family: var(--f-corps); font-weight: 400;
  font-size: clamp(0.98rem, 0.94rem + 0.2vw, 1.1rem);
  line-height: 1.4; color: var(--creme-2);
}
.curseur__scene { margin: clamp(1.6rem, 3.4vw, 2.6rem) 0 clamp(1.5rem, 3vw, 2.2rem); }
/* La phrase devient le sujet de l'écran. Alignée à gauche, pas centrée : une
   ligne centrée se recentrerait à chaque mot remplacé — elle nagerait. */
.curseur__phrase {
  margin: 0; font-family: var(--f-titre); line-height: 1.14; letter-spacing: -0.015em;
  font-size: clamp(1.55rem, 0.95rem + 2.9vw, 3.9rem);
}
/* La case interpole entre la largeur du mot sortant et celle du mot entrant
   (--wd et --wu, mesurés en JS). Oui, c'est une largeur animée — la règle
   habituelle l'interdit parce que ça provoque des reflows. Ici il s'agit de
   quatre boîtes sur une seule ligne, pilotées par un glissement : le coût est
   nul et l'alternative — des cases figées au mot le plus long — laisse des
   trous béants dans la phrase. Si le JS ne tourne pas, width redevient auto. */
.slot {
  display: inline-grid; vertical-align: top;
  width: calc(var(--wd) + (var(--wu) - var(--wd)) * clamp(0, (var(--cp) - var(--s)) * 7 + 0.5, 1));
}
.slot > .mot { grid-area: 1 / 1; justify-self: start; white-space: nowrap; }
.mot {
  opacity: var(--o);
  filter: blur(calc(clamp(0, 1 - var(--o), 1) * 3px));
  transition: opacity 140ms var(--e-entree), filter 140ms var(--e-entree);
}
/* pente 14 : les deux mots ne se croisent qu'un instant, à mi-opacité */
.mot--duel { color: var(--creme); --o: calc((var(--s) - var(--cp)) * 14 + 0.5); }
.mot--duo  { color: var(--safran); --o: calc((var(--cp) - var(--s)) * 14 + 0.5); }

.curseur__repli { display: none; }

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

/* Jauge verticale, en lecture seule : elle suit l'axe du doigt, elle ne se
   manipule pas. Une barre horizontale, ici, promettrait un glisser latéral
   qui n'existe pas — c'est le seul vrai défaut d'axe de cet effet. */
.curseur__jauge {
  position: absolute; right: clamp(0.9rem, 3vw, 3rem); top: 50%; translate: 0 -50%;
  z-index: 3; height: min(42vh, 20rem);
  display: grid; grid-template-rows: auto minmax(2rem, 1fr) auto;
  justify-items: center; gap: 0.7rem;
}
.curseur__bout {
  font-size: 0.68rem; font-weight: 700; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--creme-2);
  transition: color var(--t-survol) var(--e-entree);
}
.curseur__bout--duo { color: color-mix(in oklch, var(--safran) calc(var(--cp) * 85%), var(--creme-2)); }
.curseur__rail {
  width: 2px; height: 100%; border-radius: 999px; overflow: hidden;
  background: color-mix(in oklch, var(--braise) 90%, transparent);
}
.curseur__fil {
  display: block; width: 100%; height: 100%; border-radius: 999px;
  background: linear-gradient(180deg, var(--grenade), var(--safran));
  transform: scaleY(var(--cp)); transform-origin: 50% 0;
}

/* L'invite disparaît dès que la bascule démarre. */
.curseur__invite {
  display: flex; align-items: center; gap: 0.45rem;
  margin: 1.4rem 0 0; font-size: var(--pas-menu); font-weight: 700;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--creme-2);
  opacity: calc(1 - var(--cp) * 8);
}
.curseur__invite svg {
  width: 15px; height: 15px; fill: none; stroke: var(--safran);
  stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
}

.curseur__note {
  margin: 1.1rem 0 0; min-height: 3em; font-size: 0.97rem; line-height: 1.5;
  color: var(--creme-2); max-width: 52ch;
}

/* ─── EFFET 3 — le ciel : la page se réchauffe au défilement ─────
   Les fonds de section deviennent translucides à 80 % (sombres) et
   92 % (clairs) : assez pour que la lumière traverse, pas assez pour
   que les contrastes mesurés s'effondrent.                          */

{ background: var(--nuit); }
body { background: transparent; }

.ciel {
  position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background:
    radial-gradient(92% 72% at calc(14% + var(--sp) * 64%) calc(88% - var(--sp) * 76%),
      color-mix(in oklch, var(--safran), transparent calc(80% - var(--sp) * 32%)), transparent 64%),
    radial-gradient(72% 62% at calc(86% - var(--sp) * 62%) calc(10% + var(--sp) * 72%),
      color-mix(in oklch, var(--grenade), transparent calc(84% - var(--sp) * 12%)), transparent 62%),
    color-mix(in oklch, var(--nuit), var(--braise) calc(var(--sp) * 100%));
}

.hero,
.passage,
.passage__scene { background-color: color-mix(in oklch, var(--nuit) 80%, transparent); }
.phrases        { background-color: color-mix(in oklch, var(--nuit-2) 80%, transparent); }
.prix,
.inscription    { background-color: color-mix(in oklch, var(--nuit) 82%, transparent); }
.pied           { background-color: color-mix(in oklch, var(--nuit-2) 86%, transparent); }
.programme,
.lui            { background-color: color-mix(in oklch, var(--miel) 92%, transparent); }
.direct         { background-color: color-mix(in oklch, var(--platre) 92%, transparent); }
.questions      { background-color: color-mix(in oklch, var(--platre) 92%, transparent); }

/* ─── Mouvement réduit ─────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .citation--double .dit { opacity: 1; }
  .citation--double .dessous { opacity: 1; translate: none; }
  .citation--double::before { height: 100%; }
  /* La bascule ne se joue plus : les deux phrases sont posées côte à côte,
     et le bloc redevient un bloc ordinaire dans le flux. */
  .curseur-piste { height: auto; }
  .curseur-scene { position: static; height: auto; padding-block: clamp(3rem, 7vw, 5rem); }
  .curseur-scene__lieu { opacity: 0.18; filter: saturate(1.05) brightness(0.8); transform: none; }
  /* .curseur garde `position: relative` : son voile est en absolu et, sans
     ancêtre positionné, il se calait sur le viewport — 230 px de débordement. */
  .curseur__phrase, .curseur__jauge, .curseur__invite, .curseur__lueur { display: none; }
  .curseur::before { display: none; }
  .curseur__repli {
    display: grid; gap: 0.9rem; margin: 0;
    font-family: var(--f-titre); line-height: 1.2;
    font-size: clamp(1.25rem, 1rem + 1.2vw, 1.9rem); color: var(--creme);
  }
  .curseur__repli em {
    display: block; font-family: var(--f-corps); font-style: normal;
    font-size: var(--pas-menu); font-weight: 700; letter-spacing: 0.15em;
    text-transform: uppercase; color: var(--safran); margin-bottom: 0.25rem;
  }
  .curseur__repli span:last-child { color: var(--safran); }
  .mot { filter: none; }
  .ciel { --sp: 0.45; }
}
