/*
  sequence.css — Sekwencja: format zdjęć, rozdziały, oś czasu.
  Trzy dozwolone animacje (patrz CLAUDE.md):
    1) zdjęcie: opacity 0→1, var(--dur-photo-fade) ease-out, przy 15% widoczności
    2) nawigacja: zmiana koloru var(--dur-nav)
    3) pełny ekran: parallax max var(--parallax-max) wysokości
*/

/* ---------- Nagłówek ---------- */

.site-header {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 40;
  min-height: var(--header-height);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-inline: var(--page-margin);
  box-sizing: border-box;
  pointer-events: none;
}

/* Nagłówek zmienia tekst na jasny nad "ciemnymi" sekcjami — ale samo
   zdjęcie nie zawsze jest tam realnie ciemne akurat u samej góry, gdzie
   stoi nagłówek (zmierzone: jedno z otwarć rozdziałów ma tam jasność
   222/255 — biały tekst byłby praktycznie niewidoczny). Stała, delikatna
   ciemna smuga za nagłówkiem, WŁASNA (nie zależna od zdjęcia pod spodem),
   gwarantuje kontrast zawsze, niezależnie od tego, jakie zdjęcie akurat
   otwiera dany rozdział — ważne przy każdym kolejnym landing page'u, nie
   tylko tu. */
.site-header::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: calc(var(--header-height) + 40px);
  background: linear-gradient(to bottom, rgba(16, 16, 16, 0.45), transparent);
  opacity: 0;
  transition: opacity var(--dur-nav) ease-out;
  pointer-events: none;
}

.site-header.is-on-dark::before {
  opacity: 1;
}

.site-header__mark {
  font-family: var(--font-sans);
  font-weight: var(--weight-medium);
  font-size: 13px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--color-ink);
  transition: color var(--dur-nav) ease-out;
  pointer-events: auto;
}

.site-header__nav {
  display: flex;
  gap: var(--sp-3);
  pointer-events: auto;
}

.site-header__nav a {
  text-decoration: none;
  color: var(--color-graphite);
  transition: color var(--dur-nav) ease-out;
}

.site-header__nav a:hover,
.site-header__nav a:focus-visible {
  color: var(--color-ink);
}

.site-header__nav a[aria-current="page"] {
  color: var(--color-ink);
}

/* Nad pełnoekranowym zdjęciem (otwarcie, otwarcia rozdziałów) nagłówek
   przechodzi na jasny — zmiana koloru, druga z trzech dozwolonych animacji. */
.site-header.is-on-dark .site-header__mark {
  color: var(--color-paper);
}

.site-header.is-on-dark .site-header__nav a {
  color: rgba(250, 250, 248, 0.75);
}

.site-header.is-on-dark .site-header__nav a:hover,
.site-header.is-on-dark .site-header__nav a:focus-visible {
  color: var(--color-paper);
}

.site-header.is-on-dark .site-header__nav a[aria-current="page"] {
  color: var(--color-paper);
}

/* ---------- Oś dnia: pozioma, przyklejona na stałe do dołu ekranu ----------
   Z zaakceptowanej makiety — zawsze widoczna, cały czas w historii. Jedyne
   miejsce w serwisie z ruchomym znacznikiem w stylu paska postępu: to dosłownie
   oś czasu, nie ozdobna nawigacja. Nie zamieniać na pionową listwę ani na
   statyczny pasek pod kadrem otwierającym. */

/* Strona z osią dnia potrzebuje miejsca na dole, żeby stały pasek
   nie zasłaniał stopki/formularza na stałe. */
body.has-axis {
  padding-bottom: var(--axis-height);
}

.axis {
  position: fixed;
  inset: auto 0 0 0;
  z-index: 35;
  height: var(--axis-height);
  background: var(--color-paper);
  border-top: 1px solid var(--color-hairline);
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 8px;
}

.axis__now {
  display: flex;
  align-items: baseline;
  gap: var(--sp-2);
  padding-inline: var(--page-margin);
}

.axis__now-hour {
  color: var(--color-ink);
}

.axis__now-name {
  color: var(--color-graphite);
}

.axis__track {
  position: relative;
  width: 100%;
  height: 36px;
  max-width: var(--content-max);
  margin-inline: auto;
}

.axis__scale {
  position: absolute;
  left: var(--page-margin);
  right: var(--page-margin);
  top: 0;
  height: 100%;
}

/* Linia i znaczniki pozycjonowane na sztywno w pikselach względem 36px
   ścieżki (nie flexboksem) — celowo, po dwóch błędach w tej sekcji. */
.axis__line {
  position: absolute;
  left: 0;
  right: 0;
  top: 28px;
  height: 1px;
  background: var(--color-hairline);
}

.axis__tick {
  position: absolute;
  top: 0;
  height: 100%;
  left: var(--tick-pos, 0%);
  /* --tick-shift: dopisywane przez JS (px), tylko gdy ten konkretny
     znacznik koliduje z sąsiednim — patrz komentarz niżej. Domyślnie 0,
     czyli dokładna, "matematyczna" pozycja. */
  transform: translateX(calc(-50% + var(--tick-shift, 0px)));
  width: 40px;
  text-align: center;
  text-decoration: none;
}

.axis__tick-hour {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  white-space: nowrap;
  color: var(--color-graphite);
  transition: color var(--dur-nav) ease-out;
}

/* Kościół (0%) i Pod kościołem (9,5%) leżą na wąskim ekranie tak blisko
   siebie, że ich godziny w standardowym rozmiarze osi dnia (12px, tracking
   0,08em) się na siebie nakładają. Świadomy, lokalny wyjątek od skali
   typografii — tylko w tym jednym, gęstym miejscu, tylko na mobile. */
@media (max-width: 767px) {
  .axis__tick-hour {
    font-size: 10px;
    letter-spacing: 0;
  }
}

/* Ogólny, automatyczny mechanizm na nachodzące na siebie godziny (nie
   tylko jedna, zahardkodowana para) — sequence.js mierzy realne pozycje
   znaczników po wczytaniu i przy zmianie rozmiaru okna; tam, gdzie się
   nakładają, dopisuje --tick-shift (px) na PÓŹNIEJSZYM z pary. Cały
   znacznik — pionowa kreska I liczba razem, nie tylko tekst — przesuwa
   się minimalnie w prawo, tyle ile trzeba, żeby się nie stykały. Godziny
   zostają wszystkie na górze (nie pod linią) — świadome odejście od
   ścisłej matematycznej pozycji na rzecz czytelności: nikt tego nie
   sprawdza pikselomierzem, a wrażenie poprawnego rozkładu czasu na osi
   zostaje zachowane. */

.axis__tick::after {
  content: "";
  position: absolute;
  top: 23px;
  left: 50%;
  transform: translateX(-50%);
  width: 2px;
  height: 10px;
  background: var(--color-graphite);
  transition: background-color var(--dur-nav) ease-out;
}

.axis__tick:hover .axis__tick-hour,
.axis__tick:focus-visible .axis__tick-hour {
  color: var(--color-ink);
}

.axis__tick.is-passed .axis__tick-hour {
  color: var(--color-ink);
}

.axis__tick.is-passed::after {
  background: var(--color-ink);
}

/* Znacznik: trójkąt "play", wskazuje kierunek ruchu (w prawo, w miarę
   scrollowania historii). Rysowany obramowaniem — bez obrazków/SVG. */
.axis__marker {
  position: absolute;
  top: 28px;
  left: var(--marker-pos, 0%);
  width: 0;
  height: 0;
  border-top: 6px solid transparent;
  border-bottom: 6px solid transparent;
  border-left: 10px solid var(--color-ink);
  transform: translate(-30%, -50%);
  pointer-events: none;
  z-index: 1;
}

/* Niewidoczna, większa strefa chwytu na znaczniku — sam trójkąt (10×12px)
   jest za mały, żeby dało się go złapać palcem. --marker-pos ustawiane
   raz, na .axis__scale (rodzicu obu elementów) — dziedziczy je zarówno
   trójkąt, jak i ta strefa, więc zawsze wskazują to samo miejsce. */
.axis__marker-handle {
  position: absolute;
  top: 28px;
  left: var(--marker-pos, 0%);
  width: 32px;
  height: 32px;
  transform: translate(-50%, -50%);
  z-index: 2;
  cursor: grab;
  touch-action: none;
  -webkit-user-select: none;
  user-select: none;
}

.axis__marker-handle.is-dragging {
  cursor: grabbing;
}

/* ---------- Pasek "Sprawdź termin" (tryb landing, po 60% scrolla) ---------- */

.reach-bar {
  position: fixed;
  /* siada tuż nad osią dnia, która jest zawsze widoczna u dołu — nie mogą się nakładać */
  inset: auto 0 var(--axis-height) 0;
  z-index: 34;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--page-margin);
  /* Puls "bicia serca" po wylądowaniu (sequence.js) skaluje ten element —
     środek transformacji na dole, żeby pasek rósł w górę, w stronę treści,
     a nie równo w obie strony (nakładając się na oś dnia pod spodem). */
  transform-origin: center bottom;
  /* Był var(--color-paper) — czyli niemal ten sam odcień co tło strony pod
     spodem. Wjazd paska był więc ledwo zauważalny (papier na papierze).
     Ciemne tło (istniejący token, nie nowy kolor — Sygnał #A63D2E zostaje
     zarezerwowany wyłącznie dla galerii klienta) daje wyraźny, ale wciąż
     stonowany kontrast przy pojawieniu się, bez żadnej nowej animacji. */
  background: var(--color-night);
  /* Druga próba (@keyframes z przeskokiem + poświatą) okazała się
     niewidoczna na Chrome/Firefox mimo poprawnego kodu (zweryfikowanego
     osobno) — najpewniej konflikt animation+transition na tych samych
     właściwościach. Wracam do najprostszego, sprawdzonego mechanizmu
     (sam transition — Twoja pierwsza wersja NIM działała, tylko była za
     szybka), ale zmieniam KONCEPCJĘ zamiast dalej kombinować z tym samym:
     pasek nie wjeżdża z dołu (peryferyjnie, poza polem uwagi), tylko SPADA
     Z GÓRY — startuje nad ekranem (-100vh) i ląduje na docelowym miejscu.
     Po drodze przecina środek ekranu, czyli dokładnie to, na co akurat
     patrzy widz — to strukturalnie rozwiązuje problem "peryferyjności",
     zamiast próbować go obejść samym tempem czy efektem. */
  transform: translateY(-100vh);
  transition: transform var(--dur-reveal) cubic-bezier(0.34, 1.56, 0.64, 1);
}

.reach-bar.is-visible {
  transform: translateY(0);
}

.reach-bar p {
  color: rgba(250, 250, 248, 0.75);
}

/* Kreska pod tekstem była stała (border-bottom) — ten sam wygląd co nowe
   wyróżnienie pojedynczego słowa (.u-emphasis, patrz base.css), więc
   "tylko" w zdaniu obok zaczęło wyglądać jak link. Rozwiązanie: strzałka
   "→" jako stały wskaźnik klikalności, linia tylko przy hover/focus. */
.reach-bar__cta {
  text-decoration: none;
  color: var(--color-night-ink);
  border-bottom: 1px solid transparent;
  white-space: nowrap;
}

.reach-bar__cta:hover,
.reach-bar__cta:focus-visible {
  border-bottom-color: var(--color-night-ink);
}

/* ---------- Otwarcie ---------- */

.opening {
  position: relative;
  width: 100vw;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
  background: var(--color-loading);
}

.opening__media {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
}

.opening__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  opacity: 0;
  transition: opacity var(--dur-photo-fade) var(--ease-out);
}

.opening__img.is-loaded {
  opacity: 1;
}

.opening__overlay {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  gap: var(--sp-1);
  padding-bottom: var(--sp-7);
  padding-inline: var(--page-margin);
  text-align: center;
  color: #FAFAF8;
}

.opening__overlay::before {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 60%;
  background: linear-gradient(to top, rgba(16, 16, 16, 0.55), transparent);
  pointer-events: none;
}

.opening__names,
.opening__place,
.opening__motto {
  position: relative;
}

.opening__place {
  color: rgba(250, 250, 248, 0.85);
}

/* Motto dostaje własny głos — nie jest metadaną jak miejscowość, więc nie
   dzieli jej stylu. Większy rozmiar (skala "Śródtytuł"), pełna biel, zdanie
   (nie wersaliki — to zdanie, nie nawigacja ani godzina). Spokojnie, ale
   żeby zapamiętać. */
.opening__motto {
  font-family: var(--font-sans);
  font-weight: var(--weight-regular);
  font-size: var(--fs-subtitle);
  letter-spacing: normal;
  text-transform: none;
  color: #FAFAF8;
  margin-top: var(--sp-2);
}

/* ---------- Rozdział ---------- */

.chapter {
  margin-top: var(--gap-chapters);
}

.chapter:first-of-type {
  margin-top: 0;
}

.chapter__head {
  padding-inline: var(--page-margin);
  max-width: var(--content-max);
  margin-inline: auto;
  margin-bottom: var(--sp-4);
  display: flex;
  align-items: baseline;
  gap: var(--sp-2);
}

@media (min-width: 768px) {
  .chapter__head {
    margin-bottom: var(--sp-5);
  }
}

.chapter__head .u-hour {
  color: var(--color-graphite);
}

/* Pełny ekran otwierający rozdział */
.chapter__opener {
  position: relative;
  width: 100vw;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
  background: var(--color-loading);
  margin-bottom: var(--gap-photos);
}

.chapter__opener .photo {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Wyjątek dla zdjęć otwierających rozdział, w których bohaterowie są
   rozłożeni na CAŁĄ szerokość poziomego kadru (np. troje dzieci:
   lewo/środek/prawo) — przy standardowym pełnoekranowym cover (100dvh)
   żadne przycięcie BOKÓW nie uratowałoby wszystkich naraz. Zamiast tego:
   przycinamy tylko górę/dół (pusta ściana, podłoga) — to bezpieczne, nikogo
   nie ucina — a kontener robi się węższy (proporcje bliższe oryginałowi
   zdjęcia), więc mniej czerni niż przy pokazaniu całego zdjęcia na środku
   pełnego 100dvh ekranu. Zasada z CLAUDE.md: przycinać można, ale nigdy
   kosztem bohaterów kadru. Wartości (aspect-ratio, object-position)
   dobrane i sprawdzone wizualnie DLA TEGO KONKRETNEGO zdjęcia — przy innym
   zdjęciu do tej klasy trzeba je przeliczyć na nowo, nie kopiować w ciemno. */
@media (max-width: 767px) {
  .chapter__opener--fit-subjects {
    height: auto;
    aspect-ratio: 2560 / 1150;
  }

  .chapter__opener--fit-subjects .photo {
    object-position: center 32%;
  }
}

/* Reszta zdjęć rozdziału */
.chapter__body {
  display: flex;
  flex-direction: column;
  gap: var(--gap-photos);
}

/* ---------- Formaty zdjęć ---------- */

.photo {
  width: 100%;
  height: auto;
  background: var(--color-loading);
  opacity: 0;
  transition: opacity var(--dur-photo-fade) var(--ease-out);
}

.photo.is-loaded {
  opacity: 1;
}

.photo-wrap {
  margin: 0;
}

.photo-wrap figcaption {
  margin-top: var(--sp-2);
  padding-inline: var(--page-margin);
  color: var(--color-graphite);
}

/* Szeroki: 10 z 12 kolumn, wyśrodkowany (domyślny, poziomy) */
.photo-wrap--wide {
  /* width (jawna, policzona), nie max-width — .chapter__body jest flexem
     (dla gap), a pudełko bez jawnej szerokości wewnątrz flexa z
     margin-inline:auto to "shrink-to-fit": silniki liczą to niespójnie
     (złapane realnie: Chrome dawał sensowną szerokość, Firefox zapadał się
     do niemal zera). width:min(...) jest zawsze konkretną wartością —
     nie zależy od tego, jak dany silnik dopowiada brakujący rozmiar. */
  width: min(100%, var(--content-max));
  margin-inline: auto;
  padding-inline: var(--page-margin);
}

@media (min-width: 1024px) {
  .photo-wrap--wide {
    /* Ten box ma już max-width:content-max + margin-inline:auto — jest więc
       wyśrodkowany i przycięty do 1280px SAM w sobie. Padding tu ma dołożyć
       TYLKO jeden wcięty kolumnowy odstęp z każdej strony (10 z 12 kolumn),
       liczony od content-max, nie od 100% (które to 100% odnosi się do
       kontenera-rodzica, czyli realnej szerokości viewportu — dodanie stąd
       odstępu do centrowania powielałoby to, co już robi margin-inline:auto,
       i zdjęcie kurczyło się do ułamka zamierzonej szerokości). */
    padding-inline: calc(var(--content-max) / 12);
  }
}

/* Pion: 5 z 12 kolumn, do lewej lub prawej krawędzi kolumny — nigdy do środka.
   Na mobile: pełna szerokość. */
.photo-wrap--tall {
  width: 100%;
}

@media (min-width: 1024px) {
  .photo-wrap--tall {
    /* width, nie max-width — patrz komentarz przy .photo-wrap--wide. */
    width: min(100%, var(--content-max));
    margin-inline: auto;
    display: flex;
  }

  .photo-wrap--tall .photo {
    /* Ten sam błąd co przy --wide: 100% to szerokość kontenera-flex
       .photo-wrap--tall (który ma już JEDNOSTRONNY padding = page-margin),
       więc odjęcie page-margin*2 od tego 100% podwójnie liczyło margines.
       Liczone teraz wprost od content-max (te same 12 kolumn co --wide). */
    width: calc(var(--content-max) / 12 * 5);
  }

  .photo-wrap--tall.photo-wrap--left {
    justify-content: flex-start;
    padding-left: var(--page-margin);
  }

  .photo-wrap--tall.photo-wrap--right {
    justify-content: flex-end;
    padding-right: var(--page-margin);
  }
}

/* Dyptyk: dwa zdjęcia z tej samej sekundy, obok siebie */
.photo-wrap--diptych {
  /* width, nie max-width — patrz komentarz przy .photo-wrap--wide. */
  width: min(100%, var(--content-max));
  margin-inline: auto;
  padding-inline: var(--page-margin);
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-2);
}

@media (min-width: 768px) {
  .photo-wrap--diptych {
    grid-template-columns: 1fr 1fr;
  }
}

/* ---------- Parallax (pełny ekran, max 4% wysokości) ---------- */

[data-parallax] .photo,
[data-parallax] .opening__img {
  will-change: transform;
}

/* JS ustawia --parallax-y (px); przy braku JS/reduced-motion zostaje 0 */
.chapter__opener .photo,
.opening__img {
  transform: translateY(var(--parallax-y, 0px)) scale(1.08);
}

@media (prefers-reduced-motion: reduce) {
  .chapter__opener .photo,
  .opening__img {
    transform: none;
  }

  .reach-bar {
    transition-duration: 1ms;
  }
}

/* ---------- Zakończenie ---------- */

.closing {
  margin-top: var(--gap-chapters);
}

.closing__frame {
  position: relative;
  width: 100vw;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
  background: var(--color-loading);
}

.closing__frame .photo {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.closing__text {
  padding-block: var(--sp-7);
  text-align: center;
}

.closing__text p + p {
  margin-top: var(--sp-2);
}

.closing__text .u-body {
  max-width: var(--measure-body);
  margin-inline: auto;
}

/* ---------- Formularz ---------- */

.inquiry {
  background: var(--color-night);
  color: var(--color-night-ink);
  padding-block: var(--sp-7);
  margin-top: var(--gap-chapters);
}

.inquiry__head {
  margin-bottom: var(--sp-5);
  max-width: var(--measure-body);
}

.inquiry__head .u-section-title {
  color: var(--color-night-ink);
}

.inquiry__head p {
  margin-top: var(--sp-2);
  color: rgba(250, 250, 248, 0.7);
}

.inquiry form {
  display: grid;
  gap: var(--sp-3);
  max-width: 640px;
}

@media (min-width: 768px) {
  .inquiry form {
    grid-template-columns: 1fr 1fr;
  }

  .inquiry form .field--full {
    grid-column: 1 / -1;
  }
}

.field {
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
}

.field label {
  color: rgba(250, 250, 248, 0.7);
}

.field input,
.field textarea {
  background: transparent;
  border: none;
  border-bottom: 1px solid rgba(250, 250, 248, 0.3);
  color: var(--color-night-ink);
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  padding: var(--sp-1) 0;
  transition: border-color var(--dur-nav) ease-out;
}

.field input:focus,
.field textarea:focus {
  outline: none;
  border-bottom-color: var(--color-night-ink);
}

.field textarea {
  resize: vertical;
  min-height: 96px;
}

.inquiry .consent {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-2);
  font-size: var(--fs-meta);
  color: rgba(250, 250, 248, 0.7);
  text-transform: none;
  letter-spacing: normal;
  font-weight: var(--weight-regular);
}

.inquiry .consent input {
  margin-top: 4px;
}

.inquiry__submit {
  justify-self: start;
  background: var(--color-night-ink);
  color: var(--color-ink);
  border: none;
  padding: var(--sp-2) var(--sp-4);
  font-family: var(--font-sans);
  font-weight: var(--weight-medium);
  font-size: var(--fs-meta);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  cursor: pointer;
  transition: opacity var(--dur-nav) ease-out;
}

.inquiry__submit:hover,
.inquiry__submit:focus-visible {
  opacity: 0.8;
}

/* ---------- Stopka ---------- */

.site-footer {
  padding: var(--sp-4) var(--page-margin);
  background: var(--color-night);
  color: rgba(250, 250, 248, 0.5);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2);
  flex-wrap: wrap;
}

.site-footer__signature {
  width: 120px;
  height: auto;
  color: rgba(250, 250, 248, 0.6);
}
