/*
 * ════════════════════════════════════════════════════════════════════════════
 *  HERO — wygląd i układ warstw
 * ════════════════════════════════════════════════════════════════════════════
 *
 * Ten plik NIE zawiera animacji. Zawiera tylko stany, które JavaScript
 * przestawia, ustawiając zmienne CSS:
 *
 *   --sky-top / --sky-bottom   kolory gradientu nieba
 *   --shift                    przesunięcie warstwy (parallaks), w px
 *   --tx / --ty                pozycja obiektu ruchomego, w px
 *   --night                    przezroczystość wersji nocnej, 0–1
 *   --c, --c-flower, …         kolory kształtów w zaślepkach SVG
 *
 * Taki podział ma powód: CSS jest szybki w rysowaniu, JavaScript jest dobry
 * w liczeniu. JS liczy więc liczby i wpisuje je do zmiennych, a CSS zamienia
 * je w obraz. Dzięki temu JS nigdy nie dotyka wyglądu bezpośrednio i całą
 * kompozycję da się zrozumieć czytając ten jeden plik.
 */


/* ═══════════════════════ SZKIELET: track + sticky ═══════════════════════ */

.to-hero {
	position: relative;

	/*
	 * Hero zajmuje pełną szerokość swojego rodzica — a `.to-main` żadnej
	 * szerokości nie ogranicza, więc to już jest pełna szerokość strony.
	 *
	 * BYŁO TU `width: 100vw` z ujemnymi marginesami (sztuczka na wyjście
	 * z kontenera). Usunięte, bo `100vw` liczy się RAZEM z pionowym paskiem
	 * przewijania: sekcja wychodziła o ~15 px za okno i strona dostawała
	 * poziomy pasek przewijania, którego nikt nie zamawiał. Przy okazji psuło
	 * to arytmetykę wysokości — okno „miało" 15 px mniej, niż wynikało z tokenów.
	 *
	 * Gdybyś kiedyś wstawiła hero WEWNĄTRZ `.to-container`, wróć do tej sztuczki,
	 * ale w wersji odpornej na pasek: `margin-inline: calc(50% - 50dvw)`.
	 */
}

/*
 * TRACK — dystans do przewinięcia.
 *
 * 500vh znaczy „pięć wysokości ekranu". Tyle trzeba przewinąć, żeby przejść
 * hero od dnia do nocy i jeszcze chwilę postać w nocy.
 *
 * DLACZEGO tak dużo: przy krótszym tracku jedno pociągnięcie trackpada
 * przenosi przez pół cyklu dnia. Zamiast obserwować, jak słońce schodzi,
 * użytkownik dostaje skokową zmianę pory dnia — czyli dokładnie ten bodziec,
 * którego ten projekt ma unikać. Długi track sprawia, że animacja jest
 * powolna i przewidywalna.
 *
 * Uwaga: dystans do przewinięcia to NIE cały track, a track minus jeden
 * ekran (tyle zajmuje przyklejona sceneria). Z tego dystansu animacja
 * zajmuje 78% — resztę stanowi bufor. Patrz `animationSpan`
 * w inc/hero-layers.php.
 */
.to-hero__track {
	height: 500vh;
	position: relative;
}

/*
 * STICKY — to, co widzisz.
 *
 * `position: sticky` z `top: 0` sprawia, że element przewija się razem
 * ze stroną, dopóki nie dotknie górnej krawędzi okna — a potem zostaje
 * przyklejony, dopóki jego rodzic (track) nie przesunie się do końca.
 * To dzięki temu obraz stoi nieruchomo, a przewijanie zmienia porę dnia
 * zamiast przesuwać treść.
 */
.to-hero__sticky {
	position: sticky;

	/*
	 * Przykleja się POD paskiem nawigacji, nie do samej góry okna — i to jest
	 * warunek braku przeskoku na starcie.
	 *
	 * DLACZEGO: hero zaczyna się dokładnie tam, gdzie kończy się pasek. Gdyby
	 * sceneria celowała w `top: 0`, musiałaby najpierw przejechać wysokość paska
	 * w górę, zanim by się przykleiła — czyli pierwszy ruch kółkiem przesuwałby
	 * CAŁY ogród, a nie zmieniał porę dnia. Dokładnie ten skok. Gdy punkt
	 * przyklejenia zgadza się z pozycją startową hero, scena stoi nieruchomo
	 * od pierwszego piksela.
	 *
	 * `--to-admin-bar` to pasek administratora WordPressa: przy zalogowanym
	 * użytkowniku góra strony jest o niego przesunięta, więc punkt przyklejenia
	 * też musi zjechać — inaczej wraca ten sam skok, widoczny WYŁĄCZNIE dla
	 * osoby zalogowanej. Skrypt nic o tym nie wie i wiedzieć nie musi:
	 * czyta gotowe `top` z CSS.
	 *
	 * Wysokość bierzemy z `--to-scene-h` (main.css) — tam odejmuje się wszystko,
	 * co zabiera ekran: pasek administratora, pasek nawigacji i stopkę w trybie
	 * jednoekranowym. Inaczej dół kompozycji (ziemia, plan przedni) wychodziłby
	 * pod krawędź okna albo schował się za stopką.
	 */
	top: calc(var(--to-admin-bar) + var(--to-header-space));
	height: var(--to-scene-h);

	/* Bez tego warstwy wychodzące za kadr (słońce zjeżdżające pod horyzont)
	 * byłyby widoczne i rozciągałyby stronę. */
	overflow: hidden;
}


/* ═════════════════════════════ SCENERIA ═════════════════════════════ */

.to-hero__scene {
	position: absolute;
	inset: 0;

	/* Nowy kontekst nakładania — warstwy układają się tylko wewnątrz
	 * scenerii i nie konkurują z nagłówkiem strony. */
	isolation: isolate;
}

/*
 * NIEBO — gradient, nie obrazek.
 * Dwa kolory wpisuje JavaScript. Wartości domyślne (dzień) są tutaj,
 * żeby niebo było poprawne także przed uruchomieniem skryptu.
 */
.to-hero__sky {
	position: absolute;
	inset: 0;
	background-image: linear-gradient(
		to bottom,
		var(--sky-top, #A9C7CE) 0%,
		var(--sky-bottom, #F3EDE0) 100%
	);
}


/* ═════════════════════════════ WARSTWY ═════════════════════════════ */

.to-hero__layer {
	position: absolute;

	/* Warstwy są dekoracją — nie mogą przechwytywać kliknięć przeznaczonych
	 * dla przycisku CTA leżącego wyżej. */
	pointer-events: none;

	/* translate3d zamiast translateY: wypycha rysowanie na kartę graficzną,
	 * więc przewijanie zostaje płynne nawet przy kilku warstwach.
	 * --shift ustawia JavaScript (parallaks). */
	transform: translate3d(0, var(--shift, 0px), 0);

	/* Obiecuje przeglądarce, że będziemy zmieniać tylko te dwie rzeczy.
	 * Pozwala jej przygotować warstwę z góry i nie przeliczać układu strony. */
	will-change: transform, opacity;
}

/* ── Warstwy rozciągnięte na całą scenę ─────────────────────────────────── */

.to-hero__layer--full {
	inset: 0;
	width: 100%;
	height: 100%;
}

/* Zaślepka SVG wypełnia warstwę; przycinanie ustala preserveAspectRatio
 * wpisane w każdym pliku SVG. */
.to-hero__layer--full > svg {
	width: 100%;
	height: 100%;
	display: block;
}

/*
 * Malowany PNG. `cover` przycina obrazek tak, by wypełnił kadr bez
 * deformacji — czyli poświęca boczne pasy zamiast rozciągać rysunek.
 * Dlatego w projekcie ilustracji boczne pasy nie mogą nieść nic ważnego.
 */
.to-hero__layer--full picture,
.to-hero__layer--full img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* Który fragment zostaje, gdy obraz jest przycinany.
 * Roślinność trzyma się DOŁU (tam jest ziemia), gwiazdy GÓRY (tam jest niebo). */
.to-hero__layer--anchor-bottom img { object-position: center bottom; }
.to-hero__layer--anchor-top img    { object-position: center top; }

/* ── Obiekty ruchome: słońce, księżyc, zwierzęta ─────────────────────────── */

/*
 * Pozycję ustawia JavaScript w PIKSELACH, przez --tx / --ty.
 *
 * DLACZEGO w pikselach, a nie w procentach przez `left`/`top`:
 * zmiana `left` każe przeglądarce przeliczyć układ strony (layout) —
 * przy sześćdziesięciu klatkach na sekundę to widoczne zacinanie.
 * `transform` pomija ten etap i działa na gotowej warstwie.
 * Skrypt zna rozmiar scenerii i sam przelicza procenty na piksele.
 *
 * Drugie `translate(-50%, -50%)` przesuwa obiekt o połowę JEGO rozmiaru,
 * więc podana pozycja oznacza ŚRODEK obiektu, nie jego lewy górny róg.
 * Tak wygodniej myśleć: „słońce jest tutaj", a nie „lewy róg słońca jest tam".
 */
.to-hero__layer--spot {
	left: 0;
	top: 0;

	/* Szerokość w pikselach, liczoną w skali KANWY, podaje JavaScript przez
	 * --w. Zapasowa wartość `--size` w procentach scenerii działa, dopóki
	 * skrypt nie policzy pierwszej klatki (albo gdy JS w ogóle nie wystartuje). */
	width: var(--w, calc(var(--size, 10) * 1%));
	transform: translate3d(var(--tx, 0px), var(--ty, 0px), 0) translate(-50%, -50%);
}

.to-hero__layer--spot > svg,
.to-hero__layer--spot img {
	width: 100%;
	height: auto;
	display: block;
}

/* ── Wersja nocna nałożona na dzienną ───────────────────────────────────── */

/*
 * Leży dokładnie na warstwie dziennej. --night idzie od 0 (dzień)
 * do 1 (noc), więc obrazek nocny wyłania się przez dzienny.
 * To najłagodniejsze przejście, jakie da się zrobić: nic się nie rusza,
 * jedna warstwa po prostu gęstnieje.
 */
.to-hero__night {
	position: absolute;
	inset: 0;
	opacity: var(--night, 0);
}

.to-hero__night picture,
.to-hero__night img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/*
 * AWARYJNE PRZYCIEMNIENIE.
 * Gdy warstwa ma już malowany dzień, ale nocy jeszcze nie namalowano,
 * noc udajemy filtrem: mniej jasności, mniej nasycenia, przesunięcie
 * barwy w stronę błękitu. Odpowiada to warstwom dopasowania z Photoshopa
 * (Hue/Saturation −25/−30 + Color Balance ku niebieskiemu).
 *
 * To rozwiązanie TYMCZASOWE. Malowana wersja *-night.png zawsze wygląda
 * lepiej, bo filtr przygasza obraz równomiernie, a w naturze noc zabiera
 * kolory nierówno.
 */
.to-hero__layer[data-mode="img"]:not([data-has-night-art]) picture {
	filter:
		brightness(calc(1 - 0.42 * var(--night, 0)))
		saturate(calc(1 - 0.3 * var(--night, 0)))
		hue-rotate(calc(var(--night, 0) * -12deg));
}


/* ════════════════════════ TREŚĆ NA SCENERII ════════════════════════ */

.to-hero__copy {
	position: absolute;

	/* Gdy pasek nakłada się na scenerię (tryb jednoekranowy), treść musi zejść
	 * spod niego — stąd --to-hero-top-inset. Poza tym trybem token ma zero. */
	top: calc(var(--to-hero-top-inset) + 5%);
	left: 50%;
	transform: translateX(-50%);
	z-index: 5;
	width: min(90%, 720px);
	text-align: center;
}

/*
 * Kolor tekstu przechodzi z atramentu w kremowy razem z nadejściem nocy —
 * inaczej napis zniknąłby na granatowym niebie. Zmienne ustawia JavaScript.
 * `transition` na kolorze jest tu dodatkowym zabezpieczeniem: gdyby skrypt
 * ustawił kolor skokowo (np. przyciskiem pory dnia), zmiana i tak będzie miękka.
 */
.to-hero__title {
	color: var(--hero-ink, var(--k2-atrament));
	transition: color var(--to-transition);
}

.to-hero__tagline {
	margin-top: var(--to-space-xs);
	margin-inline: auto;
	color: var(--hero-ink-soft, var(--k2-atrament-miekki));
	font-size: clamp(1rem, 2vw, 1.2rem);
	font-weight: 700;
	transition: color var(--to-transition);
	max-width: 34ch;
}

.to-hero__cta {
	margin-top: var(--to-space-m);
	pointer-events: auto;
}


/* ═════════════════════ STOPKA KADRU ═════════════════════ */

/*
 * Jedna kolumna w dole kadru: podpowiedź, pod nią sterowanie. To JEDYNY
 * element pozycjonowany bezwzględnie — hint i pigułki żyją już w normalnym
 * przepływie wewnątrz niego, więc nie trzeba ręcznie dobierać im odstępów
 * od krawędzi.
 *
 * `pointer-events` po kolumnie wyłączamy, a włączamy dopiero na samym
 * sterowaniu: pas jest szeroki na cały kadr i bez tego przechwytywałby
 * kliknięcia na scenerii w miejscach, gdzie nic nie ma.
 */
.to-hero__footer {
	position: absolute;

	/*
	 * Nisko, bo pigułka musi siedzieć NA TRAWIE — na malowanej murawie planu
	 * przedniego, nie nad jej krawędzią. Przy 40px (--to-space-l) górna krawędź
	 * guzika wypadała na wysokości linii trawy i wystawała na niebo, tym bardziej
	 * im węższe okno: sceneria jest wpasowana przez `object-fit: cover`, więc
	 * skaluje się z SZEROKOŚCIĄ kadru, a odstęp podany w pikselach nie.
	 *
	 * Zmierzone w przeglądarce (zapas między górną krawędzią guzika a linią trawy):
	 * 1024×768 → 69px, 1280×800 → 23px, 1440×900 → 47px, 1920×1080 → 62px,
	 * telefon 390×844 → 86px. Przy 40px odstępu przypadek 1280×800 wypadał na 0.
	 *
	 * OGRANICZENIE, którego odstępem się nie naprawi: w skrajnie spłaszczonym oknie
	 * (np. 1600×700) `cover` docina ilustrację tak mocno w pionie, że w środku
	 * dolnej krawędzi nie ma już żadnej murawy — guzik leży wtedy na tym, co
	 * zostało z planu środkowego. To kwestia kompozycji obrazu, nie tej wartości.
	 *
	 * Jeśli murawa zostanie przemalowana wyżej lub niżej, odstęp trzeba sprawdzić
	 * od nowa — jest dobrany do konkretnej ilustracji.
	 */
	bottom: var(--to-space-s);
	left: 50%;
	transform: translateX(-50%);
	z-index: 6;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--to-space-s);
	width: max-content;
	max-width: calc(100% - var(--to-space-m));
	pointer-events: none;
}

/*
 * Znika po pierwszym drgnieniu przewijania — przekazała już informację.
 * Prototyp miał tu pulsującą strzałkę; usunęłam ją, bo to animacja
 * startująca sama, a zasada mówi „ruch tylko na żądanie".
 */
.to-hero__hint {
	margin: 0;
	max-width: none;

	/*
	 * Podpowiedź NIE idzie za kolorem tekstu hero.
	 *
	 * DLACZEGO: nagłówek leży na niebie, więc w dzień może być atramentowy.
	 * Ta linijka leży na PLANIE PRZEDNIM — malowanej, ciemnej zieleni — i tam
	 * atrament po prostu znika. Dostaje więc kolor papieru na stałe, plus
	 * miękki cień, bo nie kontrolujemy, co pod nią zostanie namalowane:
	 * na jaśniejszym liściu sam papier też by zniknął.
	 *
	 * Papier, nie biel — biały tekst jest w tym projekcie zakazany.
	 */
	color: var(--k2-papier);
	text-shadow: 0 1px 10px rgb(46 66 56 / 0.65);
	font-size: 0.8rem;
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	text-align: center;
	opacity: var(--hint-opacity, 0.9);
	transition: opacity var(--to-transition), color var(--to-transition);
}


/* ═════════════════════════ STEROWANIE ═════════════════════════ */

/*
 * Jedyny element interfejsu w kadrze. Miejsce na ekranie bierze
 * ze .to-hero__footer, więc tutaj zostaje tylko wygląd samej pigułki
 * i przywrócenie klikalności (kolumna nad nią ma pointer-events: none).
 *
 * Kolor jest PEŁNY, nie półprzezroczysty: ciemna zieleń planu przedniego
 * z napisem w kolorze papieru — ten sam kontrast, jaki miał wciśnięty
 * przycisk „Dzień". Pełne krycie jest tu warunkiem czytelności, bo pigułka
 * leży na malowanej roślinności, a nie na gładkim niebie.
 *
 * Ten sam wygląd o każdej porze dnia — ciemna zieleń trzyma kontrast
 * z kremowym napisem zarówno nad dniem, jak i nad granatem nocy,
 * więc nie ma czego przełączać.
 */
.to-hero__calm {
	display: flex;
	align-items: center;
	gap: var(--to-space-2xs);
	padding: var(--to-space-2xs) var(--to-space-s);
	border-radius: var(--to-radius-pill);
	background-color: var(--k2-lisc-gleboki);
	color: var(--k2-papier);
	font-size: 0.85rem;
	font-weight: 700;
	cursor: pointer;
	pointer-events: auto;
}

/*
 * accent-color w kolorze papieru, nie zieleni: na ciemnozielonym tle pigułki
 * zaznaczony kwadracik musi być JAŚNIEJSZY od niego, inaczej zniknie
 * w tle i nie widać, czy tryb jest włączony.
 */
.to-hero__calm input {
	width: 18px;
	height: 18px;
	accent-color: var(--k2-papier);
	cursor: pointer;
}


/* ═══════════════════════ TRYB SPOKOJNY ═══════════════════════ */

/*
 * Co się zmienia po włączeniu:
 *   • track skraca się do jednego ekranu → przewijanie NIE zmienia pory dnia
 *   • podpowiedź o przewijaniu znika, bo przestaje być prawdziwa
 *   • porę dnia zmienia się wyłącznie przyciskami, bardzo powolnym
 *     przenikaniem (o wolniejsze wygładzanie dba JavaScript)
 *
 * Nie wyłączamy animacji całkowicie — odbieramy jej samodzielność.
 * Różnica jest istotna: użytkownik nadal może zobaczyć zachód słońca,
 * ale tylko jeśli sam o to poprosi.
 */
/*
 * Track skrócony DO WYSOKOŚCI SCENERII, nie do „jednego ekranu": wtedy nie
 * zostaje ani piksela do przewinięcia. Przy `100vh` zostawałby pasek wysokości
 * menu (i stopki), czyli dało się przewinąć w pustkę — mały ruch, którego nikt
 * nie zamawiał, a tryb spokojny ma go właśnie odbierać.
 */
.to-hero--calm .to-hero__track {
	height: var(--to-scene-h);
}

.to-hero--calm .to-hero__hint {
	display: none;
}

/*
 * BRAMKA SENSORYCZNA — ustawienie systemowe.
 * Zachowuje się jak tryb spokojny, tylko włącza się sam.
 * JavaScript dodatkowo zaznacza wtedy przełącznik, żeby stan widoczny
 * na stronie zgadzał się z rzeczywistością.
 */
@media (prefers-reduced-motion: reduce) {

	.to-hero__track {
		height: var(--to-scene-h);
	}

	.to-hero__hint {
		display: none;
	}

	/* Przejścia kolorów zostają, ale są natychmiastowe —
	 * przenikanie barwy nie jest ruchem, jednak przy tym ustawieniu
	 * nie ryzykujemy niczego. */
	.to-hero__layer,
	.to-hero__night,
	.to-hero__title,
	.to-hero__tagline {
		transition: none;
	}
}


/* ═══════════════════════════ TELEFON ═══════════════════════════ */

@media (max-width: 640px) {

	/* Krótszy track: na telefonie przewija się palcem, więc ten sam dystans
	 * w pikselach pokonuje się szybciej i mniejszą liczbą gestów. */
	.to-hero__track {
		height: 380vh;
	}

	.to-hero__copy {
		top: calc(var(--to-hero-top-inset) + 4%);
	}

	/* Węższy margines boczny — na telefonie każdy piksel szerokości się liczy.
	 * Odstęp od dołu zostaje ten sam co na dużym ekranie (patrz .to-hero__footer). */
	.to-hero__footer {
		max-width: calc(100% - var(--to-space-s));
	}

	.to-hero__hint {
		display: none;
	}
}
