/* Przejście między stronami — jakby cały serwis był jednym dużym arkuszem, a kamera tylko się po nim
   przesuwała: nagłówek i dolny pasek stoją w miejscu, rusza się sama treść. Wariant losuje się przy
   każdym wejściu (skrypt „pagereveal” w <head>, bez powtórki z rzędu):
   - scroll — stara treść odjeżdża w górę, nowa wjeżdża od dołu jednym pasem, na styku linia „1:100”;
   - pan    — to samo w bok, jak przesuwanie wzroku po rysunku;
   - zoom   — kamera przeskakuje na kolejny detal „przez biel” (stara treść gaśnie, potem pojawia się nowa);
   - morph  — nie losowany: po kliknięciu karty projektu jej zdjęcie przelatuje w kadr strony projektu.
   Z otwartego menu na telefonie przejście zaczyna się od czystego menu (js/menu.js nie wygasza go przy wyjściu).
   Sam transform i opacity — ruch prowadzi kompozytor, nie gubi klatek, gdy nowa strona się wczytuje.
   Natywne View Transitions (Chrome/Edge, Safari 18.2+); przeglądarka bez typów przejść dostaje „scroll”,
   bez View Transitions — zwykłe przejście. „Ogranicz ruch” — bez przejścia. */

@view-transition { navigation: auto; }

.masthead { view-transition-name: masthead; }
.quickbar { view-transition-name: quickbar; }

/* Linia na styku starej i nowej treści (wariant scroll); na co dzień schowana nad górną krawędzią. */
.vt-plotter {
    position: fixed; left: 0; right: 0; top: -40px; z-index: 90; height: 22px;
    pointer-events: none; view-transition-name: plotter;
}
.vt-plotter::before { content: ""; position: absolute; left: 0; right: 0; top: 0; height: 1px; background: var(--ink-strong); }
.vt-plotter::after {
    content: "1:100"; position: absolute; right: var(--gutter); top: 5px;
    font-family: var(--mono); font-size: 10px; letter-spacing: 0.14em; color: var(--ink-strong);
}
::view-transition-old(plotter) { display: none; }
::view-transition-new(plotter) { animation: none; opacity: 1; }
/* Grupy, które stoją w miejscu (cały ekran, nagłówek, pasek kontaktu): bez domyślnej animacji przeglądarki.
   Ta animuje szerokość i wysokość — chodzi na wątku głównym i przeliczała style w każdej klatce przejścia. */
::view-transition-group(root),
::view-transition-group(masthead),
::view-transition-group(quickbar) { animation: none; }

/* scroll (domyślny) — stara i nowa treść jednym pasem, bez nakładania się. */
::view-transition-old(root) { animation: vt-up-out 0.6s cubic-bezier(0.65, 0, 0.35, 1) both; }
::view-transition-new(root) { animation: vt-up-in 0.6s cubic-bezier(0.65, 0, 0.35, 1) both; }
::view-transition-group(plotter) { animation: vt-seam-up 0.6s cubic-bezier(0.65, 0, 0.35, 1) both; }

/* pan — to samo w bok */
html:active-view-transition-type(pan)::view-transition-old(root) { animation-name: vt-side-out; }
html:active-view-transition-type(pan)::view-transition-new(root) { animation-name: vt-side-in; }

/* zoom — „przez biel”: stara treść przybliża się i gaśnie w pierwszej połowie, nowa pojawia się w drugiej.
   Teksty obu stron nigdy nie leżą na sobie (zwykłe przenikanie dawało nieczytelną plątaninę liter). */
html:active-view-transition-type(zoom)::view-transition-old(root) { animation: vt-zoom-out 0.6s linear both; }
html:active-view-transition-type(zoom)::view-transition-new(root) { animation: vt-zoom-in 0.6s linear both; }

/* morph — wejście z karty projektu (js/project-morph.js): zdjęcie z karty przelatuje w kadr nagłówka projektu,
   a strony pod nim przechodzą „przez biel”. Nagłówek i pasek kontaktu zostają nad lecącym zdjęciem. */
html:active-view-transition-type(morph)::view-transition-old(root) { animation: vt-zoom-out 0.6s linear both; }
html:active-view-transition-type(morph)::view-transition-new(root) { animation: vt-zoom-in 0.6s linear both; }
::view-transition-group(project-photo) {
    overflow: clip; animation-duration: 0.6s; animation-timing-function: cubic-bezier(0.65, 0, 0.35, 1);
}
/* Karta 4:3, kadr projektu 16:10 — oba obrazy kadrowane do lecącej ramki zamiast rozciągania. */
::view-transition-old(project-photo),
::view-transition-new(project-photo) { height: 100%; object-fit: cover; }
::view-transition-group(masthead),
::view-transition-group(quickbar) { z-index: 2; }

/* Styk widać tylko w wariancie scroll; w pozostałych linia zostaje nad ekranem. */
html:active-view-transition-type(pan)::view-transition-group(plotter),
html:active-view-transition-type(zoom)::view-transition-group(plotter),
html:active-view-transition-type(morph)::view-transition-group(plotter) { animation: none; }

@keyframes vt-up-out { to { transform: translateY(-100vh); } }
@keyframes vt-up-in { from { transform: translateY(100vh); } }
/* Głowica stoi 40 px nad ekranem — stąd +40 px: linia leży dokładnie na styku obu treści. Gaśnie przed
   końcem, żeby nie wisiała pod nagłówkiem, gdy ruch zwalnia. */
@keyframes vt-seam-up {
    0% { transform: translateY(calc(100vh + 40px)); opacity: 1; }
    75% { opacity: 1; }
    100% { transform: translateY(40px); opacity: 0; }
}
@keyframes vt-side-out { to { transform: translateX(-100vw); } }
@keyframes vt-side-in { from { transform: translateX(100vw); } }
@keyframes vt-zoom-out {
    0% { transform: none; opacity: 1; animation-timing-function: cubic-bezier(0.4, 0, 1, 1); }
    45%, 100% { transform: scale(1.04); opacity: 0; }
}
@keyframes vt-zoom-in {
    0%, 45% { transform: scale(0.97); opacity: 0; animation-timing-function: cubic-bezier(0, 0, 0.2, 1); }
    100% { transform: none; opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
    @view-transition { navigation: none; }
}
