/* Terrae Caravelli — transitions entre les pages (View Transitions inter-documents). Claude, 02/10/2026.
   Le site se vit comme un seul film : l'en-tête reste immobile ; un voile d'organza réel passe ; l'image de la porte d'une page
   devient le héros de la suivante. Les noms et le sens du passage sont posés par transitions-pages.js (pageswap / pagereveal) ;
   cette feuille ne fait que la chorégraphie des pseudo-éléments ::view-transition-*.
   Cartes d'archives : jamais de filtre, de mélange ni d'opacité intermédiaire, ni sur elles ni sur leurs parents ; elles ne sont
   que déplacées (fenêtre qui change autour d'elles, taille naturelle), dévoilées par masque, ou recouvertes par le voile.
   Animations sur le fil du compositeur partout où c'est possible (translate, scale, opacity en marche d'escalier) : le voile
   couvre toute la fenêtre au moment de la bascule, si bien qu'aucun bord de découpe ne dépend du fil principal.
   Spécificité : chaque règle commence par html:not(#tp)[data-tp-passage] (1,1,1) pour passer devant les anciens passages
   (entracte, cinema, experience, immersion-ui, raccords-maison, dramaturgie-cine) sans toucher à leurs fichiers. */
@view-transition { navigation: auto; }

@property --tp-r { syntax: '<percentage>'; inherits: false; initial-value: 0%; }

:root {
  --tp-duree: 1600ms;            /* avancer, revenir */
  --tp-duree-langue: 1200ms;     /* changer de langue */
  --tp-duree-heros: 1550ms;      /* la porte devient le héros */
  --tp-courbe-pose: cubic-bezier(.16, .84, .24, 1);    /* arrivée lente (jeton « arrivée » de la scénographie) */
  --tp-courbe-recul: cubic-bezier(.45, .05, .25, 1);   /* voile (jeton de la scénographie) */
  --tp-courbe-heros: cubic-bezier(.62, .02, .18, 1);   /* porte : départ retenu, pose douce */
  --tp-courbe-voile: cubic-bezier(.5, .1, .5, .9);      /* le voile : symétrique (mi-temps = mi-course), départ franc */
  --tp-voile-fond: url(conciergerie/voile-nuit-1280.webp);   /* l'organza de la Conciergerie, filmé de nuit */
  --tp-fond: var(--rm-voile, #06100c);
}
@media (orientation: portrait) { :root { --tp-voile-fond: url(conciergerie/voile-nuit-portrait.webp); } }
html:has(> body.page-italia) { --tp-voile-fond: url(voiles/italia-voile.jpg); }      /* l'organza d'Italia, lumière chaude */
html:has(> body.page-champagne) { --tp-voile-fond: url(voiles/champagne-voile.jpg); } /* l'organza de Champagne, craie */

/* Le calque du voile : vide, fixe, hors de toute interaction ; il n'existe que pendant un passage. Bande verticale de 160 vh
   (20 vh de lisière en haut et en bas, 120 vh d'étoffe pleine) ; bande horizontale de 160 vw pour la langue. */
.tp-voile { position: fixed; left: 0; top: 0; width: 100vw; height: 160vh; pointer-events: none; z-index: 2147483000; view-transition-name: tp-voile; contain: strict; }
html[data-tp-passage="langue"] .tp-voile { width: 160vw; height: 100vh; }

/* ── Plans : racine 0 · héros entrant ou sortant 1 · voile 2 · porte → héros 3 · titre 4 · en-tête 5 ──────────────────── */
html:not(#tp)[data-tp-passage]::view-transition { background-color: var(--tp-fond); }
html:not(#tp)[data-tp-passage]::view-transition-group(root) { animation: none; }
html:not(#tp)[data-tp-passage]::view-transition-group(.tp-entrant), html:not(#tp)[data-tp-passage]::view-transition-group(.tp-sortant) { z-index: 1; }
html:not(#tp)[data-tp-passage]::view-transition-group(tp-voile) { z-index: 2; }
html:not(#tp)[data-tp-passage]::view-transition-group(.tp-morph), html:not(#tp)[data-tp-passage]::view-transition-group(.tp-porte), html:not(#tp)[data-tp-passage]::view-transition-group(.tp-porte-texte) { z-index: 3; }
html:not(#tp)[data-tp-passage]::view-transition-group(tp-titre) { z-index: 4; }
html:not(#tp)[data-tp-passage]::view-transition-group(tp-entete) { z-index: 5; }

/* ── Le voile : il monte, couvre, respire, se lève ──────────────────────────────────────────────────────────────────── */
html:not(#tp)[data-tp-passage]::view-transition-group(tp-voile) {
  background: var(--tp-voile-fond) center / cover no-repeat, var(--tp-fond);
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 12.5%, #000 87.5%, transparent 100%);
  mask-image: linear-gradient(to bottom, transparent 0, #000 12.5%, #000 87.5%, transparent 100%);
  animation: tp-voile-monte var(--tp-duree) var(--tp-courbe-voile) both;
}
html:not(#tp)[data-tp-passage]::view-transition-old(tp-voile), html:not(#tp)[data-tp-passage]::view-transition-new(tp-voile) { animation: none; opacity: 0; }
/* Un seul geste continu, symétrique : à mi-passage, le haut de la bande est à -30 vh et l'étoffe pleine couvre toute la
   fenêtre avec 10 vh de marge de chaque côté (du haut de la bande à -20 vh jusqu'à -40 vh) ; c'est là, et seulement là, que
   la page bascule. Toutes ces animations (translate, scale, opacity) tournent sur le compositeur, sur la même horloge :
   mesuré le 02/10, le voile continue et la bascule reste sous lui quand le fil principal se bloque 600 ms. */
@keyframes tp-voile-monte { from { translate: 0 100vh; } to { translate: 0 -160vh; } }
@keyframes tp-voile-descend { from { translate: 0 -160vh; } to { translate: 0 100vh; } }

/* ── La page : l'ancienne recule sous le voile, la nouvelle apparaît sous lui (bascule nette à mi-passage) et se pose ───── */
html:not(#tp)[data-tp-passage]::view-transition-old(root) { animation: tp-ancien-recule var(--tp-duree) var(--tp-courbe-recul) both; mix-blend-mode: normal; }
html:not(#tp)[data-tp-passage]::view-transition-new(root) { animation: tp-bascule var(--tp-duree) step-end both, tp-nouveau-pose var(--tp-duree) linear both; mix-blend-mode: normal; }
@keyframes tp-ancien-recule { 0% { scale: 1; translate: 0 0; } 50%, 100% { scale: .955; translate: 0 -2.5vh; } }
@keyframes tp-bascule { 0% { opacity: 0; } 50%, 100% { opacity: 1; } }
@keyframes tp-nouveau-pose { 0%, 50% { scale: 1.035; translate: 0 2vh; animation-timing-function: var(--tp-courbe-pose); } 100% { scale: 1; translate: 0 0; } }

/* ── Revenir : le voile descend, l'ancienne page recule vers le bas ─────────────────────────────────────────────────── */
html:not(#tp)[data-tp-passage="retour"]::view-transition-group(tp-voile) { animation-name: tp-voile-descend; }
html:not(#tp)[data-tp-passage="retour"]::view-transition-old(root) { animation-name: tp-ancien-recule-bas; }
html:not(#tp)[data-tp-passage="retour"]::view-transition-new(root) { animation-name: tp-bascule, tp-nouveau-pose-retour; }
@keyframes tp-ancien-recule-bas { 0% { scale: 1; translate: 0 0; } 50%, 100% { scale: .955; translate: 0 2.5vh; } }
@keyframes tp-nouveau-pose-retour { 0%, 50% { scale: 1.035; translate: 0 -2vh; animation-timing-function: var(--tp-courbe-pose); } 100% { scale: 1; translate: 0 0; } }

/* ── Changer de langue : une bande d'organza passe de gauche à droite ; la page ne bouge pas, seuls les mots changent ─── */
html:not(#tp)[data-tp-passage="langue"] { --tp-duree: var(--tp-duree-langue); }
html:not(#tp)[data-tp-passage="langue"]::view-transition-group(tp-voile) {
  -webkit-mask-image: linear-gradient(to right, transparent 0, #000 12.5%, #000 87.5%, transparent 100%);
  mask-image: linear-gradient(to right, transparent 0, #000 12.5%, #000 87.5%, transparent 100%);
  animation-name: tp-voile-passe;
}
html:not(#tp)[data-tp-passage="langue"]::view-transition-old(root) { animation: none; }
html:not(#tp)[data-tp-passage="langue"]::view-transition-new(root) { animation: tp-bascule var(--tp-duree) step-end both; }
@keyframes tp-voile-passe { from { translate: -160vw 0; } to { translate: 100vw 0; } }

/* ── L'en-tête : immobile, au-dessus de tout ; seul l'onglet courant change ─────────────────────────────────────────── */
html:not(#tp)[data-tp-passage]::view-transition-group(tp-entete) { animation: none; }
html:not(#tp)[data-tp-passage]::view-transition-old(tp-entete) { animation: tp-sort 520ms ease 260ms both; }
html:not(#tp)[data-tp-passage]::view-transition-new(tp-entete) { animation: tp-entre 520ms ease 260ms both; }
html:not(#tp)[data-tp-passage]::view-transition-new(tp-entete):only-child { animation: tp-entre 420ms ease both; }
html:not(#tp)[data-tp-passage]::view-transition-old(tp-entete):only-child { animation: tp-sort 420ms ease both; }
@keyframes tp-sort { to { opacity: 0; } }
@keyframes tp-entre { from { opacity: 0; } }

/* ── La porte devient le héros ──────────────────────────────────────────────────────────────────────────────────────── */
html:not(#tp)[data-tp-passage]::view-transition-group(.tp-heros) { animation-duration: var(--tp-duree-heros); animation-timing-function: var(--tp-courbe-heros); }
html:not(#tp)[data-tp-passage]::view-transition-image-pair(.tp-heros) { isolation: auto; }
html:not(#tp)[data-tp-passage]::view-transition-old(.tp-heros), html:not(#tp)[data-tp-passage]::view-transition-new(.tp-heros) {
  height: 100%; object-fit: cover; mix-blend-mode: normal; animation: none; opacity: 1;
}
/* La carte n'est jamais agrandie : taille naturelle, centrée ; seule la fenêtre (le groupe) change autour d'elle (cadrage).
   La photo de la porte, elle, couvre son cadre. */
html:not(#tp)[data-tp-passage]::view-transition-new(.tp-heros), html:not(#tp)[data-tp-passage]::view-transition-old(.tp-sortant),
html:not(#tp)[data-tp-passage]::view-transition-old(.tp-porte.tp-morph) { object-fit: none; object-position: 50% 50%; }
html:not(#tp)[data-tp-passage]::view-transition-new(.tp-porte.tp-morph) { object-fit: cover; }
/* Avancer : la photo de la porte (dessous) s'efface en fondu — c'est une photo —, la carte (dessus) se dévoile par masque,
   du bas vers le haut, comme le voile qui se lève. */
html:not(#tp)[data-tp-passage]::view-transition-old(.tp-morph) { animation: tp-photo-sort var(--tp-duree-heros) linear both; }
html:not(#tp)[data-tp-passage]::view-transition-new(.tp-morph) {
  -webkit-mask-image: linear-gradient(to top, #000 calc(var(--tp-r) - 16%), transparent var(--tp-r));
  mask-image: linear-gradient(to top, #000 calc(var(--tp-r) - 16%), transparent var(--tp-r));
  animation: tp-revele-masque var(--tp-duree-heros) var(--tp-courbe-heros) both;
}
/* Revenir : la carte quittée (dessous) ne pâlit jamais ; la photo de la porte (dessus) la recouvre par masque, de haut en bas. */
html:not(#tp)[data-tp-passage]::view-transition-old(.tp-porte.tp-morph) { animation: none; }
html:not(#tp)[data-tp-passage]::view-transition-new(.tp-porte.tp-morph) {
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(var(--tp-r) - 16%), transparent var(--tp-r));
  mask-image: linear-gradient(to bottom, #000 calc(var(--tp-r) - 16%), transparent var(--tp-r));
}
@keyframes tp-photo-sort { 0%, 55% { opacity: 1; } 92%, 100% { opacity: 0; } }
@keyframes tp-revele-masque { 0%, 38% { --tp-r: 0%; } 92%, 100% { --tp-r: 116%; } }
/* Une porte sans répondant (aucun héros visible à l'arrivée) : la photo s'efface seule. */
html:not(#tp)[data-tp-passage]::view-transition-old(.tp-porte):only-child { animation: tp-sort 700ms ease both; }
/* Le texte et le bouton de la porte restent à leur place et s'effacent pendant que l'image s'envole. */
html:not(#tp)[data-tp-passage]::view-transition-group(.tp-porte-texte) { animation: none; }
html:not(#tp)[data-tp-passage]::view-transition-old(.tp-porte-texte) { animation: tp-sort 380ms ease both; }

/* ── Héros entrant (aucune porte en face) ou sortant (sans répondant) : sous le voile ; bascule nette quand il couvre tout ;
   le héros entrant se pose avec un peu plus d'élan que la page (profondeur). ─────────────────────────────────────────── */
html:not(#tp)[data-tp-passage]::view-transition-new(.tp-entrant) { animation: tp-bascule var(--tp-duree) step-end both, tp-heros-pose var(--tp-duree) linear both; }
html:not(#tp)[data-tp-passage="retour"]::view-transition-new(.tp-entrant) { animation-name: tp-bascule, tp-heros-pose-retour; }
html:not(#tp)[data-tp-passage]::view-transition-old(.tp-sortant) { animation: tp-efface var(--tp-duree) step-end both, tp-heros-recule var(--tp-duree) var(--tp-courbe-recul) both; }
html:not(#tp)[data-tp-passage="retour"]::view-transition-old(.tp-sortant) { animation-name: tp-efface, tp-heros-recule-bas; }
@keyframes tp-efface { 0% { opacity: 1; } 50%, 100% { opacity: 0; } }
@keyframes tp-heros-pose { 0%, 50% { translate: 0 6vh; animation-timing-function: var(--tp-courbe-pose); } 100% { translate: 0 0; } }
@keyframes tp-heros-pose-retour { 0%, 50% { translate: 0 -6vh; animation-timing-function: var(--tp-courbe-pose); } 100% { translate: 0 0; } }
@keyframes tp-heros-recule { 0% { translate: 0 0; } 50%, 100% { translate: 0 -5vh; } }
@keyframes tp-heros-recule-bas { 0% { translate: 0 0; } 50%, 100% { translate: 0 5vh; } }

/* ── Le titre (arrivée par la porte) : apparition par lignes, la découpe descend pendant que le bloc monte de 24 px ───── */
html:not(#tp)[data-tp-passage]::view-transition-group(tp-titre) { animation-duration: var(--tp-duree); }
html:not(#tp)[data-tp-passage]::view-transition-new(tp-titre) { animation: tp-titre-entre 1050ms var(--tp-courbe-pose) 620ms both; mix-blend-mode: normal; }
@keyframes tp-titre-entre {
  from { clip-path: inset(-12% -2% 100% -2%); translate: 0 24px; opacity: 0; }
  30% { opacity: 1; }
  to { clip-path: inset(-12% -2% -12% -2%); translate: 0 0; opacity: 1; }
}

/* ── Les anciens passages cèdent pendant les nôtres : brume procédurale et seuil de raccords-maison ─────────────────── */
html:not(#tp)[data-tp-passage]::view-transition-group(tc-brume), html:not(#tp)[data-tp-passage]::view-transition-group(raccords-seuil) { display: none; }

/* ── Calme : mouvement réduit, contraste renforcé, couleurs forcées, impression — aucun passage animé ───────────────── */
@media (prefers-reduced-motion: reduce), (prefers-contrast: more), (forced-colors: active), print {
  .tp-voile { display: none; }
  html:not(#tp)::view-transition-group(*), html:not(#tp)::view-transition-old(*), html:not(#tp)::view-transition-new(*) { animation: none !important; }
}
