/* ==========================================================================
   Kartkowany katalog e-folderu (album).

   Geometria książki: kartka to element z dwiema ścianami (przód i tył)
   obracany w 3D wokół grzbietu. Skrypt ustawia tylko rotateY i zmienną
   --cien (0..1, cień w trakcie obrotu), cała reszta wyglądu siedzi tutaj.

   Typografia stron liczona w jednostkach kontenera (cqw), żeby ta sama
   strona wyglądała identycznie w książce, na telefonie i na arkuszu A4
   w druku - skaluje się z kartką, nie z oknem.

   Bez inline styles i bez inline <style>: docelowy .htaccess wymusza CSP
   z style-src 'self', a wersja bez skryptu wchodzi arkuszem bez-js.css
   podpiętym w <noscript>.
   ========================================================================== */

/* Napisy wersalikowe albumu - etykiety sekcji, pigułki, przyciski, stopki -
   stały na IBM Plex Mono. Krój maszynowy czytał się jako „cybersecurity”,
   a album ma sprzedawać remont taboru (Iwona, 16.09.2026), stąd Figtree:
   miękki grotesk bez maszynowego rysunku. Szerszy krój przy tym samym
   odstępie robi się rozwleczony, więc tracking schodzi z 0.18em.
   Nadpisanie siedzi tutaj, a nie w tokens.css, bo tamten plik obsługuje
   też showcase - tamta strona zostaje na starych krojach. */
:root {
  --font-mono: "Figtree", "IBM Plex Sans", "Segoe UI", Arial, sans-serif;
  --track-mono: 0.12em;
}

* { box-sizing: border-box; }

html { height: 100%; }

body {
  margin: 0;
  min-height: 100vh;
  height: 100dvh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  font-family: var(--font-body);
  color: var(--steel-bright);
  background:
    radial-gradient(120% 90% at 50% 20%, var(--ink-raise) 0%, var(--ink) 62%),
    var(--ink);
}

img { max-width: 100%; -webkit-user-drag: none; }

/* --- pasek górny ----------------------------------------------------------
   Z powrotem granatowy - "ten pasek musi byc ponownie granatowy" (Iwona,
   21.09 wieczorem); bialy z siodmej rundy wypadl. Tlo sceny przeswituje,
   znak w oficjalnej wersji bialo-pomaranczowej na ciemne tlo. Wybor
   jezyka (EN DE PL) i pobranie PDF zostaja w prawym gornym rogu. */

.pasek {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0.6rem clamp(1rem, 3vw, 2rem);
  background: transparent;
  border-bottom: 1px solid var(--hair-dark);
}

.pasek-znak { flex: none; }

.pasek-tytul {
  font-family: var(--font-mono);
  font-size: var(--step-mono);
  letter-spacing: var(--track-mono);
  text-transform: uppercase;
  color: var(--steel);
}

.pasek-prawy {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

.jezyki {
  display: flex;
  gap: 0.35rem;
  font-family: var(--font-mono);
  font-size: var(--step-mono);
  letter-spacing: 0.14em;
}

.jezyk {
  padding: 0.35rem 0.55rem;
  border-radius: 999px;
  color: var(--steel);
  text-decoration: none;
  border: 1px solid transparent;
  transition: color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}

a.jezyk:hover { color: var(--white); border-color: var(--hair-dark); }

.jezyk--biezacy { color: var(--white); border-color: rgba(255, 255, 255, 0.35); }

/* Tytuł paska schodzi pierwszy, gdy robi się ciasno; na najwezszych
   ekranach przycisk PDF i pigulki jezyka schodza o stopien, zeby
   "PDF herunterladen" nie wystawalo poza ekran. */
@media (max-width: 40rem) {
  .pasek-tytul { display: none; }
  .pasek { gap: 0.5rem; }
  .pasek-prawy { gap: 0.3rem; min-width: 0; }
  .jezyk { padding: 0.3rem 0.4rem; }
  .pasek .przycisk--pdf {
    font-size: 0.62rem;
    letter-spacing: 0.08em;
    padding: 0.45rem 0.7rem;
  }
}

/* Najwezsze ekrany: znak o wlos mniejszy, pigulki bez luzu - pasek ma
   siedziec w 320 px bez przewijania. */
@media (max-width: 22rem) {
  .pasek { gap: 0.35rem; padding-left: 0.6rem; padding-right: 0.6rem; }
  .pasek-znak { width: 62px; height: 28px; }
  .jezyki { gap: 0.1rem; }
  .jezyk { padding: 0.3rem 0.3rem; letter-spacing: 0.1em; }
  .pasek .przycisk--pdf { font-size: 0.58rem; padding: 0.4rem 0.55rem; }
}

/* --- sterowanie dolne ------------------------------------------------------ */

.ster {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 1rem;
  padding: 0.75rem clamp(1rem, 3vw, 2rem) 1rem;
}

.ster-srodek {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1.1rem;
}

/* Pasek rozwiniety w dziesiatej rundzie (21.09): szesc skokow po lewej,
   odnosniki zewnetrzne i film po prawej. Wierszy moze byc wiecej niz
   jeden, wiec grupy lamia sie zamiast wypychac pasek poza ekran. */
.skroty { display: flex; flex-wrap: wrap; gap: 0.15rem 0.4rem; }

.skroty--prawe { justify-content: flex-end; }

/* Stopien i tracking dobrane tak, zeby dziewiec skroconych hasel Iwony
   ("zeby pasek miescil sie w jednym wierszu", 21.09 20:43) siedzialo
   w jednym wierszu takze na srednich oknach. */
.skrot {
  appearance: none;
  background: transparent;
  border: 0;
  padding: 0.4rem 0.4rem;
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--steel);
  text-decoration: none;
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease-out);
}

.skrot:hover { color: var(--white); }

/* Prawa strona dolnego paska: przycisk skoku na koniec / powrotu na
   poczatek (siodma runda, 21.09) - jezyk i PDF pojechaly na gorny pasek. */
.ster-prawy {
  justify-self: end;
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

/* Rozwiniety pasek nie miesci sie pelnym stopniem na srednich oknach -
   skroty schodza o stopien, zanim znikna calkiem. */
@media (max-width: 82rem) {
  .skrot { font-size: 0.6rem; padding: 0.35rem 0.3rem; }
}

/* Na wąskim ekranie skróty znikają (są w treści katalogu). */
@media (max-width: 47.5rem) {
  .skroty { display: none; }
  .ster { grid-template-columns: auto 1fr auto; padding-left: 0.75rem; padding-right: 0.75rem; }
  .ster-srodek { gap: 0.6rem; }
}

.licznik {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  letter-spacing: 0.12em;
  color: var(--steel-bright);
  min-width: 5.5rem;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

.przycisk {
  appearance: none;
  background: transparent;
  border: 1px solid var(--hair-dark);
  border-radius: 999px;
  color: var(--steel-bright);
  font-family: var(--font-mono);
  font-size: var(--step-mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 0.55rem 1rem;
  cursor: pointer;
  transition:
    border-color var(--dur-fast) var(--ease-out),
    color var(--dur-fast) var(--ease-out),
    background-color var(--dur-fast) var(--ease-out);
}

.przycisk:hover:not([disabled]) { border-color: var(--signal); color: var(--white); }

.przycisk[disabled] { opacity: 0.3; cursor: default; }

.przycisk--strzalka {
  width: 2.7rem;
  height: 2.7rem;
  padding: 0;
  display: grid;
  place-items: center;
  font-size: 1.05rem;
  line-height: 1;
}

.przycisk--pdf {
  color: var(--signal);
  border-color: rgba(241, 101, 33, 0.45);
}

.przycisk--pdf:hover { background: rgba(241, 101, 33, 0.12); border-color: var(--signal); }

/* --- scena i bryła książki ---------------------------------------------- */

.scena {
  position: relative;
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: clamp(0.75rem, 2.5vh, 2rem) 1rem;
  animation: wjazd 0.8s var(--ease-out) both;
}

@keyframes wjazd {
  from { opacity: 0; transform: translateY(16px) scale(0.985); }
}

.ksiazka {
  position: relative;
  perspective: 2600px;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  cursor: grab;
  transition: transform var(--dur-slow) var(--ease-inout);
}

.ksiazka:active { cursor: grabbing; }

.ksiazka[data-tryb="rozkladowka"] {
  width: min(calc(100vw - 3rem), calc((100dvh - 13rem) * 1.5), 62rem);
  aspect-ratio: 3 / 2;
}

.ksiazka[data-tryb="pojedyncza"] {
  width: min(calc(100vw - 1.5rem), calc((100dvh - 12rem) * 0.75), 27rem);
  aspect-ratio: 3 / 4;
}

/* Zamknięta książka jedzie w bok, żeby sama okładka stała na środku sceny:
   okładka leży w prawej połowie bryły, więc na początku całość idzie w lewo. */
.ksiazka[data-tryb="rozkladowka"][data-polozenie="poczatek"] { transform: translateX(-25%); }
.ksiazka[data-tryb="rozkladowka"][data-polozenie="koniec"] { transform: translateX(25%); }

/* Blok nieprzewróconych kartek widać z prawej jako krawędź papieru. */
.ksiazka[data-tryb="rozkladowka"]::before,
.ksiazka[data-tryb="rozkladowka"]::after {
  content: "";
  position: absolute;
  top: 1%;
  bottom: 1%;
  width: 6px;
  z-index: 0;
  transition: opacity var(--dur-mid) var(--ease-out);
}

.ksiazka[data-tryb="rozkladowka"]::after {
  left: 100%;
  border-radius: 0 3px 3px 0;
  background: repeating-linear-gradient(90deg, #f7f8fb 0 1.5px, #c9cde0 1.5px 2.5px);
}

.ksiazka[data-tryb="rozkladowka"]::before {
  right: 100%;
  border-radius: 3px 0 0 3px;
  background: repeating-linear-gradient(270deg, #f7f8fb 0 1.5px, #c9cde0 1.5px 2.5px);
}

.ksiazka[data-polozenie="poczatek"]::before { opacity: 0; }
.ksiazka[data-polozenie="koniec"]::after { opacity: 0; }

/* --- kartka: dwie ściany obracane wokół grzbietu ------------------------- */

.kartka {
  position: absolute;
  top: 0;
  bottom: 0;
  transform-origin: left center;
  transform-style: preserve-3d;
  will-change: transform;
}

.ksiazka[data-tryb="rozkladowka"] .kartka { left: 50%; width: 50%; }
.ksiazka[data-tryb="pojedyncza"] .kartka { left: 0; width: 100%; }

/* Przewrócona kartka w trybie pojedynczym leżałaby poza książką,
   więc po zakończeniu obrotu znika. W locie musi być widoczna. */
.ksiazka[data-tryb="pojedyncza"] .kartka-odwrocona { visibility: hidden; }
.ksiazka .kartka-w-locie { visibility: visible !important; }

.kartka-strona {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  overflow: hidden;
  container-type: size;
  background: var(--paper-raise);
  box-shadow: 0 2px 18px rgba(4, 3, 14, 0.28);
}

.kartka-przod { border-radius: 2px 8px 8px 2px; }
.kartka-tyl { transform: rotateY(180deg); border-radius: 8px 2px 2px 8px; }

.kartka-w-locie .kartka-strona { box-shadow: -16px 24px 42px rgba(4, 3, 14, 0.4); }

/* Stałe zacienienie przy grzbiecie: papier nigdy nie leży idealnie płasko. */
.kartka-przod::before,
.kartka-tyl::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  width: 9%;
  z-index: 2;
  pointer-events: none;
}

.kartka-przod::before { left: 0; background: linear-gradient(90deg, rgba(8, 7, 26, 0.14), rgba(8, 7, 26, 0)); }
.kartka-tyl::before { right: 0; background: linear-gradient(270deg, rgba(8, 7, 26, 0.14), rgba(8, 7, 26, 0)); }

/* Cień ruchomy: rośnie do połowy obrotu i gaśnie, sterowany --cien. */
.kartka-przod::after,
.kartka-tyl::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  opacity: var(--cien, 0);
}

.kartka-przod::after { background: linear-gradient(90deg, rgba(8, 7, 26, 0.4), rgba(8, 7, 26, 0) 62%); }
.kartka-tyl::after { background: linear-gradient(270deg, rgba(8, 7, 26, 0.4), rgba(8, 7, 26, 0) 62%); }

/* Rewers kartki w trybie pojedynczym: goły papier. */
.kartka-rewers { background: var(--paper); }

/* --- strona: wspólny układ ----------------------------------------------- */

.strona {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  padding: 6cqw 7cqw;
  background: var(--paper-raise);
  color: var(--slate);
}

/* Nagłówki o stopień mniejsze w całym albumie - piąta runda uwag Iwony
   (20.09). Od dziesiątej rundy (21.09) JEDEN stopień H1 na wszystkich
   stronach ("Contents i Industrial... to H1, powinny być tej samej
   wysokości") i krój węższy zamiast mniejszego ("inny rodzaj czcionki,
   węższy") - Archivo ma oś szerokości 75-125%, więc zwężenie schodzi
   z dawnych 112% na 88% w tej samej rodzinie. */
.strona h2 {
  margin: 2.2cqw 0 3cqw;
  font-family: var(--font-display);
  font-stretch: 88%;
  font-weight: 800;
  font-size: 4.7cqw;
  line-height: 1.08;
  letter-spacing: var(--track-tight);
  color: var(--navy);
}

.strona p { font-size: 3.1cqw; line-height: 1.5; margin: 0 0 2.6cqw; }

.strona-lead { color: var(--navy); font-weight: 600; }

/* Strony gęste w treść: ciaśniejsze odstępy wokół tytułu (stopień jest
   już wspólny dla całego albumu). */
.strona--gesta h2 { margin: 1.4cqw 0 2cqw; }

/* Jasny granat w tle strony grup warsztatowych (siodma runda uwag Iwony,
   21.09) - ta sama rodzina co wypelnienia sylwetki, o wlos ciemniejsza
   przy dolnej krawedzi, zeby kartka nie robila sie plaska. */
.strona--tlo-granat { background: linear-gradient(165deg, #eef0f9 0%, #e1e4f3 100%); }

.strona--gesta .strona-lead { margin-bottom: 2cqw; }

/* Stopien i tracking mniejsze od osmej rundy (21.09): kickery nosza
   pelna strukture naglowkow Iwony (najdluzszy: "Service Portfolio · 1.
   Maintenance, Overhaul & Modernisation") i musza siedziec w jednym
   wierszu paska. Separator to kropka, nie myslnik - "tu mogly zostac
   kropki" (Iwona, dziesiata runda, 21.09). */
.kicker {
  font-family: var(--font-mono);
  font-size: 2.1cqw;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--signal-dim);
  white-space: nowrap;
}

.kicker--jasny { color: var(--signal); }

.strona-glowka { padding-bottom: 1.8cqw; border-bottom: 1px solid var(--hair-light); }

.strona-tresc { flex: 1; min-height: 0; display: flex; flex-direction: column; }

.strona-stopka {
  margin-top: auto;
  padding-top: 2.2cqw;
  border-top: 1px solid var(--hair-light);
  display: flex;
  justify-content: space-between;
  font-family: var(--font-mono);
  font-size: 2.3cqw;
  letter-spacing: 0.1em;
  color: var(--steel-dim);
}

/* Na lewych (parzystych) stronach rozkladowki numer strony siedzi w lewym
   dolnym rogu, przy zewnetrznej krawedzi - jak w drukowanym albumie
   (siodma runda uwag Iwony, 21.09). */
.strona-stopka--lewa { flex-direction: row-reverse; }

/* --- komponenty treści ----------------------------------------------------- */

/* Miejsce na zdjęcie, którego jeszcze nie ma. Znika razem z materiałem od PTS. */
.kadr-atrapa {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 14cqw;
  border: 1px dashed var(--steel);
  border-radius: 4px;
  background:
    repeating-linear-gradient(0deg, rgba(34, 30, 94, 0.045) 0 1px, transparent 1px 6cqw),
    repeating-linear-gradient(90deg, rgba(34, 30, 94, 0.045) 0 1px, transparent 1px 6cqw);
  margin-bottom: 3cqw;
}

.kadr-atrapa--rosnie { flex: 1; min-height: 16cqw; }

/* Atrapa na ciemnej stronie zamknięcia - wideo w przygotowaniu. */
.kadr-atrapa--ciemna {
  min-height: 16cqw;
  margin-bottom: 0;
  border-color: rgba(255, 255, 255, 0.35);
  background:
    repeating-linear-gradient(0deg, rgba(255, 255, 255, 0.05) 0 1px, transparent 1px 6cqw),
    repeating-linear-gradient(90deg, rgba(255, 255, 255, 0.05) 0 1px, transparent 1px 6cqw);
}

.kadr-atrapa--ciemna .kadr-etykieta { color: var(--steel); }

.kadr-etykieta {
  padding: 1cqw 2cqw;
  font-family: var(--font-mono);
  font-size: 2.3cqw;
  letter-spacing: var(--track-mono);
  text-transform: uppercase;
  text-align: center;
  color: var(--steel-dim);
}

.chipy {
  list-style: none;
  margin: 0 0 3cqw;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 2cqw;
}

.chip {
  padding: 1.2cqw 2.6cqw;
  border: 1px solid var(--hair-light);
  border-radius: 999px;
  font-family: var(--font-mono);
  font-size: 2.4cqw;
  letter-spacing: var(--track-mono);
  text-transform: uppercase;
  color: var(--navy);
}

/* Chipy z piktogramami pojazdów ze strony PTS ("4 ikony ze strony").
   Ikony większe i pomarańczowe (uwaga Iwony o widoczności, kolor
   wskazany przez Olivera 19.09 - pomarańcz siedzi w plikach SVG). */
.chipy--pojazdy { gap: 1.4cqw; margin-bottom: 1.2cqw; }

.chipy--pojazdy .chip {
  display: inline-flex;
  align-items: center;
  gap: 1.1cqw;
  padding: 0.8cqw 2cqw;
  font-size: 2.1cqw;
}

.chipy--pojazdy .chip img { width: auto; height: 3.8cqw; }

/* Pas ikon na całą szerokość strony: segmenty łączą się ze sobą - jedna
   ramka, wspólne kreski między polami zamiast osobnych pigułek
   ("ikonki muszą się łączyć na całej przestrzeni", uwagi Iwony 20.09). */
.chipy--pas {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0;
  margin: 1cqw 0 2.6cqw;
  border: 1px solid var(--hair-light);
  border-radius: 4px;
  overflow: hidden;
}

.chipy--pas .chip {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1cqw;
  padding: 2.2cqw 1cqw;
  border: 0;
  border-radius: 0;
  text-align: center;
}

.chipy--pas .chip + .chip { border-left: 1px solid var(--hair-light); }

.chipy--pas .chip img { height: 5.6cqw; }

/* Wariant podzespołów: krata 2x2, ikony duże, pas rośnie na wolną
   wysokość strony - "czy możemy ułożyć te ikony 2x2? Powiększą się
   i wypełnią tę pustą przestrzeń" (Iwona, dziesiąta runda, 21.09).
   Kreski siatki: lewa krawędź tylko między kolumnami, górna między
   rzędami - nth-child wygrywa specyficznością z ".chip + .chip". */
.chipy--krata {
  flex: 1;
  min-height: 0;
  grid-template-columns: 1fr 1fr;
  /* Rzedy ROWNE niezaleznie od wysokosci ikon ("tej samej wielkosci
     zrob wszystkie komorki") - samo 1fr nie wystarcza, bo fr nie
     schodzi ponizej min-content i wiersz z najwyzsza ikona
     (lokomotywa) i tak rozpychal krate. */
  grid-auto-rows: minmax(0, 1fr);
}

.chipy--krata .chip { padding: 2cqw 1cqw; font-size: 2.5cqw; gap: 1.6cqw; }

/* Przy duzej skali wychodzi na jaw, ze rysunki maja w viewBoxach ROZNE
   marginesy: przy wspolnej wysokosci pudelka lokomotywa (tusz 156/200)
   wyglada na mala i zagubiona, a tramwaj z pantografem na sciesniety
   ("tu sie cos rozjezdza", Oliver po wdrozeniu dziesiatej rundy).
   Wysokosci per ikona wyrownuja DLUGOSC pojazdu do ~23cqw; wysokosci
   sylwetek zostaja naturalne dla typu (lokomotywa krotsza i wyzsza). */
.chipy--krata .chip img { height: 7.7cqw; }

.chipy--krata .chip:nth-child(2) img { height: 9cqw; }

.chipy--krata .chip:nth-child(3) img { height: 7.9cqw; }

.chipy--krata .chip:nth-child(4) img { height: 8.1cqw; }

.chipy--krata .chip:nth-child(2n+1) { border-left: 0; }

.chipy--krata .chip:nth-child(n+3) { border-top: 1px solid var(--hair-light); }

.cta-rzad { display: flex; flex-wrap: wrap; gap: 2.4cqw; margin-top: auto; }

.przycisk-strona {
  display: inline-block;
  padding: 2.2cqw 3.6cqw;
  border: 1px solid var(--navy);
  border-radius: 999px;
  background: transparent;
  font-family: var(--font-mono);
  font-size: 2.5cqw;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--navy);
  cursor: pointer;
}

.przycisk-strona--glowny {
  background: var(--signal);
  border-color: var(--signal);
  color: var(--white);
}

.przycisk-strona--jasny { border-color: var(--steel); color: var(--white); }

/* Kafle: cztery duże na stronie o PTS, sześć drobniejszych przy drugim życiu. */
.kafle {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2.6cqw;
  margin: 1cqw 0 3cqw;
}

.kafel {
  padding: 2.4cqw 2.6cqw;
  border: 1px solid var(--hair-light);
  border-left: 0.9cqw solid var(--signal);
  border-radius: 4px;
  font-size: 2.7cqw;
  line-height: 1.35;
  font-weight: 600;
  color: var(--navy);
}

.kafle--drobne { grid-template-columns: 1fr 1fr 1fr; }

.kafle--drobne .kafel { font-size: 2.35cqw; padding: 1.8cqw 2.2cqw; }

/* Kafelki typów pojazdów "z rysunkami i napisami": piktogram nad nazwą. */
.kafle--pojazdy .kafel {
  display: grid;
  gap: 0.6cqw;
  justify-items: start;
  padding: 1.4cqw 2cqw;
}

.kafle--pojazdy .kafel img { width: auto; height: 4.2cqw; }

/* Kafle "O PTS" dojezdzaja do samego dolu strony i rosna razem z nia
   (Iwona, 21.09: "te zdjecia zrobic do samego dolu strony") - siatka
   przejmuje cala wolna wysokosc, a kadry porzucaja sztywna proporcje
   i wypelniaja komorki. */
.kafle--do-dolu {
  flex: 1;
  grid-auto-rows: 1fr;
  margin-bottom: 0;
}

.kafle--do-dolu .kafel--foto { aspect-ratio: auto; min-height: 16cqw; }

/* Kafle rosnące na wypełnienie strony - drugie życie po rozbiciu portfolio
   02 na trzy strony (uwagi Iwony, 20.09): tekst zostaje, ikony rosną. */
.kafle--rosna {
  flex: 1;
  grid-template-columns: 1fr 1fr;
  grid-auto-rows: 1fr;
  gap: 2.4cqw;
  margin-top: 2cqw;
  margin-bottom: 0;
}

.kafle--rosna .kafel {
  align-content: center;
  justify-items: center;
  text-align: center;
  gap: 1.3cqw;
  font-size: 2.5cqw;
  padding: 1.4cqw;
}

.kafle--rosna .kafel img { height: 6.4cqw; }

/* Naglowek referencji blizej listy Scope - "strzalka w lewo znaczy
   zmniejszyc" (Iwona, dziesiata runda, 21.09); oddech listy Scope
   urosl w zamian (.strona--zakres .lista--zwarta). */
.naglowek-listy--odstep { margin-top: 1.2cqw; }

/* Kafle o PTS ze zdjęciami wskazanymi w docx Iwony ("wybrane zdjęcia
   w pliku", 19.09). Fotografia pod granatowym cieniem czytelności od
   dołu, napis na bieli, sygnałowy grzbiet kafla zostaje. Filtr jak na
   okładce, żeby kadry grały z resztą materiałów PTS. */
.kafel--foto {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: flex;
  align-items: flex-end;
  aspect-ratio: 16 / 9;
  padding: 0;
  transition: transform var(--dur-mid) var(--ease-out), box-shadow var(--dur-mid) var(--ease-out);
}

/* Najechanie powiększa kafel razem z napisem (uwaga Iwony, 20.09).
   Skala na całym kaflu, nie na samym zdjęciu - napis rośnie razem z nim. */
.kafel--foto:hover {
  transform: scale(1.045);
  z-index: 1;
  box-shadow: 0 6px 22px rgba(8, 7, 26, 0.28);
}

/* Rozjasnione na prosbe Iwony (osma runda, 21.09): "potrzebujemy jakos
   rozjasnic te zdjecia" - brightness w gore, cien czytelnosci pod
   napisem lzejszy i zaczyna nizej. */
.kafel-foto {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: saturate(0.92) contrast(1.02) brightness(1.14);
  z-index: -2;
}

.kafel--foto::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: linear-gradient(180deg, rgba(20, 17, 59, 0) 45%, rgba(20, 17, 59, 0.68) 100%);
}

.kafel-napis {
  padding: 1.4cqw 2.2cqw 1.6cqw;
  color: var(--white);
  text-shadow: 0 1px 6px rgba(8, 7, 26, 0.55);
}

/* Wyróżnione zdanie zamykające stronę. */
.wyroznik {
  margin-top: auto;
  padding: 2.4cqw 3cqw;
  border-left: 0.9cqw solid var(--signal);
  background: rgba(241, 101, 33, 0.07);
  font-weight: 600;
  color: var(--navy);
}

/* Wyroznik strony etapow jest przyciskiem-odnosnikiem do Partnership
   Offer - "tu link powinien isc do partnership offer" (Iwona, dziesiata
   runda, 21.09). Reset przycisku + afordancja: strzalka i hover. */
button.wyroznik {
  display: block;
  width: 100%;
  border: 0;
  border-left: 0.9cqw solid var(--signal);
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-out);
}

button.wyroznik:hover { background: rgba(241, 101, 33, 0.14); }

.wyroznik--odnosnik::after { content: " \2192"; color: var(--signal); }

.strona--etapy .wyroznik {
  font-size: 2.6cqw;
  line-height: 1.45;
  margin-bottom: 0;
}

/* --- etapy jako tor z przystankami -----------------------------------------
   "Jak na stronie PTS jest oferta i po najechaniu pojawia się tekst"
   (uwagi Iwony, 20.09): rysunek toru z pts-website - pionowa linia,
   pomarańczowe węzły, duże tytuły etapów. Opis wysuwa się po najechaniu
   albo po tapnięciu (ksiazka.js przełącza .etap--otwarty). Bez skryptu
   i na wydruku opisy stoją rozwinięte (bez-js.css i @media print).
   Od 21.09 (ósma runda) strona wraca na białe tło - granatowa karta
   "wskazywała na nową sekcję" (Iwona); typografia zjechała na granat. */

.tor-etapy {
  list-style: none;
  counter-reset: etap;
  flex: 1;
  margin: 1cqw 0 3cqw;
  padding: 0 0 0 3.4cqw;
  display: flex;
  flex-direction: column;
  justify-content: space-evenly;
  border-left: 0.35cqw solid rgba(34, 30, 94, 0.28);
}

.etap {
  counter-increment: etap;
  position: relative;
  padding-left: 4.4cqw;
}

/* Węzeł przystanku na linii toru. */
.etap::before {
  content: "";
  position: absolute;
  left: -4.35cqw;
  top: 1.5cqw;
  width: 1.7cqw;
  height: 1.7cqw;
  border-radius: 50%;
  background: var(--signal);
  box-shadow: 0 0 0 0.55cqw rgba(241, 101, 33, 0.22);
}

/* Numer etapu pelnym sygnalem - "wyraziste bardziej 01 02 03" (siodma
   runda uwag Iwony, 21.09); kontur z poprzedniej wersji ginal na
   granacie. */
.etap::after {
  content: "0" counter(etap);
  position: absolute;
  left: -1.4cqw;
  top: 0.2cqw;
  font-family: var(--font-display);
  font-weight: 900;
  font-size: 3.4cqw;
  line-height: 1;
  color: var(--signal);
}

.etap-tytul {
  appearance: none;
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: transparent;
  text-align: left;
  font-family: var(--font-display);
  font-stretch: 88%;
  font-weight: 800;
  font-size: 3.6cqw;
  line-height: 1.15;
  letter-spacing: var(--track-tight);
  color: var(--navy);
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}

.etap:hover .etap-tytul,
.etap--otwarty .etap-tytul { color: var(--signal); transform: translateX(0.6cqw); }

/* Opis wysuwa się po najechaniu albo tapnięciu. max-height zamiast
   height: auto, bo auto się nie animuje; 14cqw mieści najdłuższy opis DE. */
.etap-opis {
  display: block;
  max-height: 0;
  overflow: hidden;
  opacity: 0;
  font-size: 2.5cqw;
  line-height: 1.45;
  color: var(--slate);
  transition: max-height var(--dur-mid) var(--ease-out), opacity var(--dur-mid) var(--ease-out), padding-top var(--dur-mid) var(--ease-out);
}

.etap:hover .etap-opis,
.etap--otwarty .etap-opis { max-height: 14cqw; opacity: 1; padding-top: 0.7cqw; }

/* Pociag zjezdzajacy po linii toru do wskazanego przystanku (siodma
   runda uwag Iwony, 21.09). Wspolrzedne w px ustawia ksiazka.js przez
   CSSOM (atrybut style blokuje CSP) wzgledem pojemnika tresci; tutaj
   tylko wyglad i plynny zjazd. Bez skryptu i na wydruku schodzi. */
.strona--etapy .strona-tresc { position: relative; }

.tor-pociag {
  position: absolute;
  left: 0;
  top: 0;
  width: 3.2cqw;
  height: auto;
  pointer-events: none;
  filter: drop-shadow(0 0.4cqw 0.9cqw rgba(4, 3, 14, 0.28));
  transition: top 0.5s var(--ease-out);
}

.naglowek-listy {
  margin: 1cqw 0 2cqw;
  font-family: var(--font-mono);
  font-size: 2.5cqw;
  letter-spacing: var(--track-mono);
  text-transform: uppercase;
  color: var(--signal-dim);
}

.lista {
  list-style: none;
  margin: 0 0 2.6cqw;
  padding: 0;
  display: grid;
  gap: 1.6cqw;
}

.lista li {
  position: relative;
  padding-left: 3.2cqw;
  font-size: 2.6cqw;
  line-height: 1.4;
}

.lista li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 1.35cqw;
  width: 1.5cqw;
  height: 1.5cqw;
  border-radius: 1px;
  background: var(--signal);
}

.lista--dwie-kolumny { grid-template-columns: 1fr 1fr; column-gap: 5cqw; }

/* Galeria zdjęć zaplecza "jak w eksploratorze plików" (uwagi Iwony,
   20.09): duży kadr na całą wolną wysokość strony, strzałki poprzedni/
   następny i pasek miniatur pod spodem. JS podmienia src dużego kadru
   ze zdjęcia klikniętej miniatury; bez skryptu i na wydruku duży kadr
   pokazuje pierwsze zdjęcie, a miniatury łamią się w siatkę. */
.eksplorator {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 1.6cqw;
  margin-top: 2cqw;
}

.eksplorator-kadr {
  position: relative;
  flex: 1;
  min-height: 24cqw;
  border-radius: 4px;
  overflow: hidden;
}

.eksplorator-foto {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.eksplorator-strzalka {
  appearance: none;
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 5.4cqw;
  height: 5.4cqw;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 999px;
  background: rgba(34, 30, 94, 0.72);
  color: var(--white);
  font-size: 2.6cqw;
  line-height: 1;
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-out);
}

.eksplorator-strzalka:hover { background: var(--signal); }

.eksplorator-strzalka--wstecz { left: 1.6cqw; }
.eksplorator-strzalka--dalej { right: 1.6cqw; }

.eksplorator-licznik {
  position: absolute;
  right: 1.6cqw;
  bottom: 1.4cqw;
  padding: 0.4cqw 1.4cqw;
  border-radius: 999px;
  background: rgba(34, 30, 94, 0.82);
  font-family: var(--font-mono);
  font-size: 2cqw;
  letter-spacing: var(--track-mono);
  color: var(--white);
  font-variant-numeric: tabular-nums;
}

/* 17 kadrow od Iwony (osma runda, 21.09) - dwa rzedy po dziewiec. */
.eksplorator-miniatury {
  display: grid;
  grid-template-columns: repeat(9, 1fr);
  gap: 0.9cqw;
}

.miniatura {
  appearance: none;
  padding: 0;
  border: 0.28cqw solid transparent;
  border-radius: 3px;
  overflow: hidden;
  background: transparent;
  cursor: pointer;
  opacity: 0.72;
  /* Bez tego obrazek nie pozwala kolumnie siatki zejsc ponizej swojej
     szerokosci wrodzonej i 9. miniatura wystaje poza kartke. */
  min-width: 0;
  transition: opacity var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}

.miniatura img {
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  display: block;
}

.miniatura:hover { opacity: 1; }

.miniatura--aktywna { opacity: 1; border-color: var(--signal); }

/* Sześć grup warsztatowych - po rozbiciu zaplecza na dwie strony mają
   własną kartkę i oddychają: dwie kolumny, większy stopień. */
.grupy {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.6cqw 2.8cqw;
  margin-bottom: 0.8cqw;
}

.grupy--luzne {
  flex: 1;
  grid-template-columns: 1fr 1fr;
  align-content: space-evenly;
  gap: 3cqw 5cqw;
  margin-top: 1cqw;
}

.strona p.grupa-tytul {
  margin: 0 0 0.6cqw;
  font-size: 2.2cqw;
  line-height: 1.25;
  font-weight: 700;
  color: var(--navy);
}

.grupy--luzne p.grupa-tytul { font-size: 2.7cqw; margin-bottom: 1cqw; }

.lista--grupa { gap: 0.5cqw; margin: 0; }

.lista--grupa li { font-size: 1.9cqw; line-height: 1.28; padding-left: 2.4cqw; }

/* Punktory grup delikatniejsze - drobne kółko w połowie krycia zamiast
   pełnego sygnałowego kwadratu (uwagi Iwony, 20.09). */
.lista--grupa li::before {
  top: 1cqw;
  width: 1cqw;
  height: 1cqw;
  border-radius: 50%;
  background: rgba(241, 101, 33, 0.55);
}

.grupy--luzne .lista--grupa { gap: 0.9cqw; }

.grupy--luzne .lista--grupa li { font-size: 2.3cqw; line-height: 1.34; }

/* Historie transformacji: od piatej rundy uwag (20.09) kazda historia
   zajmuje DWIE kartki. Od dziesiatej rundy (21.09) duzy tytul pojazdu
   stoi na stronie ZDJECIOWEJ nad kadrami, a strona tekstowa zaczyna sie
   od leadu - naglowki przestaly byc pomieszane miedzy stronami (Iwona). */
.strona--historia h2 { font-size: 4.7cqw; margin: 1cqw 0 0.6cqw; }

/* Etykieta serii POD tytulem historii ("pod nim A rolling stock
   transformation story"). Selektor przez .strona p, bo gola klasa
   przegrywa specyficznoscia ze ".strona p". */
.strona p.historia-etykieta {
  margin: 0.2cqw 0 0;
  font-family: var(--font-mono);
  font-size: 2.3cqw;
  letter-spacing: var(--track-mono);
  text-transform: uppercase;
  color: var(--signal-dim);
}

/* Strona tekstowa historii zaczyna sie od leadu - oddech od kickera. */
.strona--historia p.strona-lead { margin-top: 2cqw; }

/* Oznaczenie serii w jednym wierszu z tytulem historii (dziewiata runda,
   21.09) - mono mniejszym stopniem na wspolnej linii bazowej. */
.strona--historia h2 .historia-oznaczenie {
  margin-left: 1.4cqw;
  font-family: var(--font-mono);
  font-size: 2.4cqw;
  font-weight: 400;
  font-stretch: 100%;
  letter-spacing: var(--track-mono);
  text-transform: uppercase;
  color: var(--steel-dim);
  white-space: nowrap;
}

[lang="de"] .strona--historia h2 .historia-oznaczenie { font-size: 2.05cqw; }

/* Zdanie otwierające zakres prac historii ("...including:") i lista
   pełnego zakresu z docx Iwony (19.09). */
.strona p.historia-opis { margin: 0 0 1.4cqw; font-size: 2.45cqw; line-height: 1.4; }

.lista--historia { gap: 1cqw; margin: 0; }

.lista--historia li { font-size: 2.25cqw; line-height: 1.32; padding-left: 2.8cqw; }

.lista--historia li::before { top: 1.1cqw; width: 1.3cqw; height: 1.3cqw; }

/* Strona tekstowa historii ma teraz cala kartke dla siebie - lista
   oddycha wiekszym stopniem i odstepem. */
.lista--historia-luzna { flex: 1; align-content: space-evenly; gap: 1.8cqw 4cqw; margin-top: 1cqw; }

.lista--historia-luzna li { font-size: 2.5cqw; line-height: 1.42; }

.historia-foto {
  width: 100%;
  height: 100%;
  min-height: 10cqw;
  object-fit: cover;
  display: block;
}

/* Wideo wnetrza po modernizacji LINT41 w slocie filmu na stronie obszarow
   modernizacji (dziewiata runda, 21.09) - wypelnia wolna wysokosc kartki
   jak wczesniejsza atrapa, gra bez dzwieku w petli, gdy strona jest na
   widoku (ksiazka.js, wideoPetli). */
.film-wypelnia {
  display: block;
  flex: 1;
  width: 100%;
  min-height: 16cqw;
  object-fit: cover;
  border-radius: 4px;
  background: var(--navy);
}

/* Ramka wokol filmu w slocie - nosi plakietke z nazwa pojazdu
   ("dobrze by dodac Modernised Lint41", Iwona, dziesiata runda, 21.09).
   Rosnie flexem zamiast samego wideo, film wypelnia ja absolutnie. */
.film-kadr {
  position: relative;
  flex: 1;
  min-height: 16cqw;
  border-radius: 4px;
  overflow: hidden;
  background: var(--navy);
}

.film-kadr .film-wypelnia {
  position: absolute;
  inset: 0;
  height: 100%;
  min-height: 0;
  border-radius: 0;
}

/* Strona zdjeciowa historii: kadry przed/po jeden nad drugim na calej
   wolnej wysokosci kartki, kazdy z duza plakietka BEFORE/AFTER. Bez
   animacji - "musi byc przejrzyste" dla osob nietechnicznych (Iwona,
   21.09): zrozumienie nie moze wymagac ani czekania na przenikanie,
   ani zadnej interakcji. Wczesniejszy crossfade z 20.09 wypadl. */
.przemiana {
  flex: 1;
  min-height: 30cqw;
  margin-top: 2cqw;
  display: grid;
  grid-template-rows: 1fr 1fr;
  gap: 2cqw;
}

.przemiana-kadr { position: relative; border-radius: 4px; overflow: hidden; }

.przemiana-kadr .historia-foto { position: absolute; inset: 0; height: 100%; }

.kadr-nadpis {
  position: absolute;
  left: 0.8cqw;
  bottom: 0.8cqw;
  padding: 0.4cqw 1.2cqw;
  border-radius: 999px;
  background: rgba(34, 30, 94, 0.82);
  font-family: var(--font-mono);
  font-size: 1.9cqw;
  letter-spacing: var(--track-mono);
  text-transform: uppercase;
  color: var(--white);
}

/* Plakietki przed/po wieksze i w gornym rogu kadru; "po" sygnalowa,
   zeby roznica stanow byla widoczna od pierwszego spojrzenia. */
.przemiana .kadr-nadpis {
  left: 1.2cqw;
  top: 1.2cqw;
  bottom: auto;
  padding: 0.7cqw 2cqw;
  font-size: 2.5cqw;
}

.kadr-nadpis--po { background: var(--signal); }

.dopisek {
  font-size: 2.4cqw;
  line-height: 1.45;
  color: var(--steel-dim);
}

/* Dopisek zamykający stronę współpracy - ciaśniej, bo kartkę dzieli formularz. */
.strona p.dopisek--maly { font-size: 2.15cqw; line-height: 1.35; margin-bottom: 0; }

/* Certyfikaty: znaki ze strony jakości PTS, klik otwiera PDF certyfikatu
   w nowej karcie. Od 20.09 komplet dziewięciu pozycji ze strony (3x3);
   dopisek "kliknij znak" jeździ przy kursorze (ksiazka.js + data-podpowiedz
   na .certy), więc nie zajmuje już wiersza na stronie. */
.certy {
  flex: 1;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  align-content: space-evenly;
  gap: 1.8cqw;
  margin: 1.6cqw 0 0;
}

/* Plakietka wyglada jak przycisk, nie jak pole tabeli - "zrob jakas ramke
   zeby bylo widoczne ze sa klikalne" (Iwona, 21.09): biala karta z wyrazna
   ramka i cieniem, strzalka otwarcia w rogu, uniesienie po najechaniu. */
.cert {
  position: relative;
  display: grid;
  justify-items: center;
  align-content: center;
  gap: 1cqw;
  padding: 1.6cqw 1.4cqw 1.2cqw;
  border: 1px solid rgba(34, 30, 94, 0.3);
  border-radius: 4px;
  background: var(--white);
  box-shadow: 0 2px 8px rgba(8, 7, 26, 0.1);
  font-family: var(--font-mono);
  font-size: 2.1cqw;
  letter-spacing: 0.08em;
  color: var(--navy);
  text-decoration: none;
  transition:
    border-color var(--dur-fast) var(--ease-out),
    box-shadow var(--dur-fast) var(--ease-out),
    transform var(--dur-fast) var(--ease-out);
}

/* Strzalka pobrania w dol w prawym gornym rogu plakietki - "jak przy
   downloadzie" (siodma runda uwag Iwony, 21.09). */
.cert:not(.cert--bez-pdf)::after {
  content: "\2193";
  position: absolute;
  top: 0.7cqw;
  right: 1.1cqw;
  font-size: 2.3cqw;
  line-height: 1;
  color: var(--signal);
}

.cert:hover {
  border-color: var(--signal);
  transform: translateY(-0.4cqw);
  box-shadow: 0 6px 16px rgba(8, 7, 26, 0.18);
}

/* IQNet to członkostwo w sieci, nie certyfikat z plikiem - plakietka
   bez odnośnika, bez strzalki i bez reakcji na najechanie. */
.cert--bez-pdf:hover {
  border-color: rgba(34, 30, 94, 0.3);
  transform: none;
  box-shadow: 0 2px 8px rgba(8, 7, 26, 0.1);
}

.cert-znak { width: auto; height: 7.6cqw; object-fit: contain; }

/* Podpowiedź "kliknij znak" przy kursorze nad plakietką certyfikatu.
   Element tworzy i pozycjonuje ksiazka.js (przez CSSOM, nie atrybut
   style - CSP); tutaj tylko wygląd. */
.podpowiedz-kursor {
  position: fixed;
  z-index: 40;
  max-width: 20rem;
  padding: 0.35rem 0.8rem;
  border-radius: 999px;
  background: rgba(34, 30, 94, 0.92);
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  color: var(--white);
  pointer-events: none;
}

.podpowiedz-kursor[hidden] { display: none; }

/* Ścieżki kontaktu: trzy karty będące odnośnikami mailto. */
.sciezki { display: grid; gap: 2.6cqw; margin-bottom: 2.6cqw; }

.sciezka {
  display: grid;
  gap: 1cqw;
  padding: 3cqw 3.4cqw;
  border: 1px solid var(--hair-light);
  border-radius: 4px;
  text-decoration: none;
  transition: border-color var(--dur-fast) var(--ease-out);
}

.sciezka:hover { border-color: var(--signal); }

.sciezka-tytul {
  display: inline-flex;
  align-items: center;
  gap: 1.4cqw;
  font-size: 3.1cqw;
  font-weight: 700;
  color: var(--navy);
}

.sciezka-ikona { flex: none; width: 3.2cqw; height: 3.2cqw; color: var(--signal); }

.sciezka-opis { font-size: 2.5cqw; line-height: 1.45; color: var(--slate); }

/* Ścieżki zwarte: na stronie oferty współpracy dzielą kartkę z formularzem.
   Od 20.09 wyraźniejsze - "bardziej widoczne te I need maintenance"
   (uwagi Iwony): większy tytuł, sygnałowy grzbiet, więcej światła. */
.sciezki--zwarte { gap: 1cqw; margin-bottom: 1.6cqw; }

.sciezki--zwarte .sciezka { padding: 1.15cqw 2.4cqw; gap: 0.45cqw; border-left: 0.7cqw solid var(--signal); }

.sciezki--zwarte .sciezka-tytul { font-size: 2.7cqw; }

.sciezki--zwarte .sciezka-opis { font-size: 2.05cqw; line-height: 1.32; }

/* Wiecej powietrza u gory strony wspolpracy: naglowek w dol od kickera,
   sciezki w dol od naglowka ("lets discuss w dol troche i te i need
   maintenance tez troche w dol", Iwona 21.09). Przyrost dobrany bramka
   przepelnien - PL i DE maja mniejszy zapas niz EN. */
.strona--wspolpraca h2 { margin-top: 2.6cqw; margin-bottom: 2.8cqw; }

/* Formularz współpracy dojeżdża do samego dołu kartki (uwagi Iwony,
   20.09): nagłówek formularza spycha go na dół, pole wiadomości rośnie. */
.strona--wspolpraca .formularz-naglowek { margin-top: auto; }

.strona--wspolpraca .formularz { margin-bottom: 0.8cqw; }

/* Formularz współpracy: pola w dwóch kolumnach. Wysyłka to mailto składane
   w ksiazka.js - hosting jest statyczny i nie ma dokąd POST-ować. */
.formularz {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.1cqw 2.4cqw;
  margin-bottom: 1.2cqw;
}

.formularz-pole {
  display: grid;
  gap: 0.4cqw;
  font-family: var(--font-mono);
  font-size: 1.8cqw;
  letter-spacing: var(--track-mono);
  text-transform: uppercase;
  color: var(--steel-dim);
}

.formularz input,
.formularz select,
.formularz textarea {
  width: 100%;
  padding: 0.9cqw 1.5cqw;
  border: 1px solid var(--hair-light);
  border-radius: 3px;
  background: var(--white);
  font-family: var(--font-body);
  font-size: 2.4cqw;
  color: var(--slate);
}

.formularz textarea { resize: none; }

.formularz input:focus,
.formularz select:focus,
.formularz textarea:focus { outline: 2px solid var(--signal); outline-offset: 1px; }

/* Przycisk siedzi obok pola wiadomości w ostatnim rzędzie siatki. */
.formularz .przycisk-strona { justify-self: start; align-self: end; padding: 1.6cqw 3cqw; }

/* Odnośnik CTA siedzi w stopce strony, pod kreską, kolorem i stopniem
   stopki - "chodzi o to, żeby ten tekst był dyskretny" (Iwona, 19.09).
   Zastępuje napis Public Transport Service; numer strony zostaje,
   bo na numerach wiszą spis treści i kickery. */
.stopka-link {
  color: inherit;
  text-decoration: none;
}

.stopka-link:hover { color: var(--signal); }

/* Wyjatek od dyskretnej stopki: CTA referencji na stronie Scope stoi
   wyraznie w tresci, pod kartami - "ten tekst powinien byc bardziej
   widoczny, na tej stronie" (Iwona, 21.09 wieczorem). */
.odnosnik-wyrazny {
  margin: 1.8cqw 0 0;
  align-self: flex-start;
  font-family: var(--font-mono);
  font-size: 2.4cqw;
  letter-spacing: var(--track-mono);
  text-transform: uppercase;
  color: var(--signal);
  text-decoration: none;
}

.odnosnik-wyrazny::after { content: " \2192"; }

.odnosnik-wyrazny:hover { text-decoration: underline; }

/* Spis treści: pozycje są skokami do stron katalogu. Rozłożone na całą
   wysokość kartki do dołu - "wyjustować do dołu contents" (uwagi Iwony,
   20.09). */
.spis {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  margin-top: 1cqw;
}

.spis-pozycja {
  appearance: none;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--hair-light);
  display: flex;
  align-items: baseline;
  gap: 2.4cqw;
  padding: 1.9cqw 0.4cqw;
  font-family: inherit;
  font-size: 3cqw;
  line-height: 1.3;
  font-weight: 600;
  text-align: left;
  color: var(--navy);
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease-out);
}

.spis-pozycja:hover { color: var(--signal); }

.spis-pozycja--wcieta { padding-left: 3.6cqw; }

.spis-nr {
  font-family: var(--font-mono);
  font-size: 2.3cqw;
  letter-spacing: var(--track-mono);
  color: var(--signal-dim);
}

/* Oferta wspolpracy krojem etykiet grup - "dla logiki wizualnej ta sama
   czcionka co About PTS i Service Portfolio" (Iwona, dziesiata runda,
   21.09). Pozycja zostaje klikalnym wierszem z numerem. */
.spis-pozycja--naczelna {
  font-family: var(--font-mono);
  font-size: 2.4cqw;
  letter-spacing: var(--track-mono);
  text-transform: uppercase;
  font-weight: 400;
  color: var(--signal-dim);
}

/* Pas grupy stoi w rownym odstepie od linii nad soba i pozycji pod soba -
   "jest przyklejony do gornej" (siodma runda uwag Iwony, 21.09; poprawka
   w dziewiatej, bo margines nigdy nie dzialal). Selektor przez .strona p:
   gola klasa przegrywala ze ".strona p" i pas szedl z margin-top 0
   oraz pelnym stopniem akapitu - stad sklejenie z gorna linia. */
.strona p.spis-grupa {
  margin: 2.3cqw 0 0.4cqw;
  padding: 0 0.4cqw;
  font-family: var(--font-mono);
  font-size: 2.4cqw;
  line-height: 1.4;
  letter-spacing: var(--track-mono);
  text-transform: uppercase;
  color: var(--signal-dim);
}

/* Pierwsza grupa spisu (About PTS, szosta runda) zaczyna liste - bez
   gornego marginesu miedzygrupowego. */
.spis p.spis-grupa:first-child { margin-top: 0.4cqw; }

/* Oferta wspolpracy stoi poza grupami - odrobine wiekszy odstep pokazuje,
   ze to naglowek innego rzedu (siodma runda, 21.09). */
.spis .spis-pozycja:not(.spis-pozycja--wcieta) { margin-top: 1.6cqw; }

/* Karty realizacji referencyjnych ze zdjęciem. Od 20.09 dzielą kartkę
   z listą Scope, więc kadry są niższe (21/9), a typografia zwarta. */
.refy {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2.4cqw;
  margin-bottom: 0;
}

.ref {
  border: 1px solid var(--hair-light);
  border-radius: 4px;
  overflow: hidden;
  display: grid;
  gap: 0.7cqw;
  padding-bottom: 1.6cqw;
  align-content: start;
}

.ref-foto {
  width: 100%;
  /* height: auto wygrywa z prezentacyjnym hintem atrybutu height="",
     bez tego aspect-ratio jest ignorowane i karta rośnie do zdjęcia. */
  height: auto;
  aspect-ratio: 21 / 9;
  object-fit: cover;
  display: block;
}

/* Selektory przez .strona p - gole klasy przegrywaja specyficznoscia
   ze ".strona p" i typografia kart bierze wtedy bazowy stopien akapitu. */
.strona p.ref-tytul { margin: 1.2cqw 2.4cqw 0; font-size: 2.7cqw; line-height: 1.25; font-weight: 700; color: var(--navy); }

.strona p.ref-klient {
  margin: 0 2.4cqw;
  font-family: var(--font-mono);
  font-size: 2cqw;
  letter-spacing: var(--track-mono);
  text-transform: uppercase;
  color: var(--signal-dim);
}

.strona p.ref-opis { margin: 0 2.4cqw; font-size: 2.25cqw; line-height: 1.38; }

/* Uklad poziomy kart referencji - na stronie Scope dzielą kartkę z listą,
   więc zdjęcie idzie w lewą kolumnę na całą wysokość karty, tekst obok. */
.refy--poziome { grid-template-columns: 1fr; gap: 1.6cqw; }

.refy--poziome .ref {
  grid-template-columns: 30cqw 1fr;
  grid-template-rows: auto auto 1fr;
  gap: 0 2.6cqw;
  padding-bottom: 0;
}

.refy--poziome .ref-foto {
  grid-row: 1 / 4;
  height: 100%;
  min-height: 13cqw;
  aspect-ratio: auto;
}

.strona .refy--poziome p.ref-tytul { margin: 1.3cqw 2cqw 0.4cqw 0; }

.strona .refy--poziome p.ref-klient { margin: 0 2cqw 0.7cqw 0; }

.strona .refy--poziome p.ref-opis { margin: 0 2cqw 1.3cqw 0; }

/* Akapity wstępu na stronach gęstych w treść. Selektor przez .strona p,
   bo goła klasa przegrywa specyficznością z ".strona p" i nie działa wcale. */
.strona p.strona-akapit-zwarty { font-size: 2.55cqw; line-height: 1.42; margin-bottom: 1.8cqw; }

/* Podtytuły pod H1 (lead stron) to jeden poziom H2 i jeden stopień -
   "teksty pod Quality i Rolling stock to H2, powinny być tej samej
   wielkości" (Iwona, dziesiąta runda, 21.09). Reguła stoi ZA
   strona-akapit-zwarty, żeby wygrać kaskadę przy tej samej
   specyficzności - leady bywają zapisane oboma klasami naraz. */
.strona p.strona-lead { font-size: 2.7cqw; line-height: 1.45; }

/* Dwa akapity wstępu w szpaltach - strona zaplecza niesie ich najwięcej. */
.szpalty { column-count: 2; column-gap: 4cqw; margin-bottom: 1.2cqw; }

.szpalty p { font-size: 2.12cqw; line-height: 1.36; margin: 0 0 1.2cqw; }

/* Interaktywna sylwetka pojazdu: strefy podświetlają się po kliknięciu,
   nazwa obszaru wchodzi do paska pod rysunkiem (ksiazka.js).
   flex: none, bo jako element kolumny flex SVG dawał się zgniatać do
   połowy wysokości zamiast zgłosić przepełnienie bramce. */
/* Po zejsciu Scope na osobna strone sylwetka jest glownym obrazem kartki
   i rosnie - "grafiki i zdjecia pierwszoplanowe" (uwagi Iwony, 20.09).
   Od 21.09 (szosta runda) kadr jest wyzszy o siec trakcyjna i posadzke
   (viewBox 420x150). Od 21.09 (siodma runda) pociag schodzi na dol
   kartki, a pigulka z nazwa obszaru stoi NAD nim - jej marginesy auto
   daja rowny odstep od pasa ikon u gory i od rysunku pod nia. */
.sylwetka {
  flex: none;
  display: block;
  width: auto;
  /* Kadr rosnie, a marginesy auto rozkladaja reszte wolnej wysokosci
     po rowno - "martwi mnie tak duzo pustej przestrzeni" (Iwona,
     21.09 wieczorem, po "ta pusta przestrzen wyglada dziwnie"). */
  height: 36cqw;
  max-width: 100%;
  margin: auto;
}

/* Swietlny skan jezdzacy wzdluz pojazdu - ruch, ktory pokazuje, ze
   rysunek zyje. Transformacja w jednostkach viewBoxu (px = user units). */
.sylwetka-skan {
  pointer-events: none;
  animation: sylwetka-skan 7s ease-in-out infinite;
}

@keyframes sylwetka-skan {
  0% { transform: translateX(0); }
  64%, 100% { transform: translateX(444px); }
}

.strefa { cursor: pointer; }

/* Najechanie wyglada jak zaznaczenie - ta sama droga co strefa aktywna,
   zeby bylo widac, ze rysunek reaguje (uwaga Iwony, 19.09). */
.strefa:hover *,
.strefa--aktywna * { stroke: var(--signal); }

.strefa:hover [fill="#221e5e"],
.strefa--aktywna [fill="#221e5e"] { fill: var(--signal); }

/* Pulsujace punkty na strefach - znak, ze rysunek jest klikalny.
   Kropka z bialym obrysem, fala rozchodzi sie i gasnie. */
.strefa:hover .punkt-kropka,
.strefa--aktywna .punkt-kropka { stroke: var(--white); }

.strefa--aktywna .punkt { display: none; }

.punkt-kropka {
  fill: var(--signal);
  stroke: var(--white);
  stroke-width: 1.6;
}

.punkt-fala {
  fill: none;
  stroke: var(--signal);
  stroke-width: 1.2;
  transform-box: fill-box;
  transform-origin: center;
  animation: puls-punktu 2.4s ease-out infinite;
}

@keyframes puls-punktu {
  0% { transform: scale(0.6); opacity: 0.9; }
  70%, 100% { transform: scale(2); opacity: 0; }
}

/* Etykieta nad rysunkiem to zwykly naglowek sekcji jak "Scope" - bez
   pigulki i przerywanej ramki ("sugeruje przycisk, a to nie jest
   przycisk. Myslalam o takim samym naglowku jak Scope", Iwona, 21.09
   wieczorem). Klik w strefe dalej podmienia jej tekst; stan aktywny
   gra kolorem. Selektor przez .strona p, bo gola klasa przegrywa ze
   ".strona p". */
.strona p.sylwetka-etykieta {
  /* Wiekszy oddech od pasa ikon - "troche wiekszy odstep" (Iwona,
     21.09 w nocy). */
  margin: 4cqw 0 2cqw;
  font-family: var(--font-mono);
  /* Taki sam REALNY stopien jak Scope na kolejnej stronie: .naglowek-listy
     deklaruje 2.5cqw, ale gola klasa od zawsze przegrywa ze ".strona p"
     i Scope renderuje sie 3.1cqw - etykieta rowna sie do stanu
     faktycznego, nie do martwej deklaracji (Iwona: "wysokosc tej
     czcionki taka sama jak na kolejnej stronie, tu jest mniejsza"). */
  font-size: 3.1cqw;
  line-height: 1.4;
  letter-spacing: var(--track-mono);
  text-transform: uppercase;
  color: var(--signal-dim);
}

.strona p.sylwetka-etykieta--aktywna { color: var(--signal); }

/* Wariant listy dla stron, gdzie lista dzieli kartkę z kaflami. */
.lista--zwarta { gap: 1cqw; }

.lista--zwarta li { font-size: 2.3cqw; line-height: 1.32; }

/* Strona zakresu SP01 bez powtorzonego naglowka (siodma runda, 21.09).
   Wolna wysokosc kartki zjada LISTA Scope (flex: 1, wiersze rozlozone),
   a referencje stoja zwartym blokiem przy swoim naglowku - "na tej
   stronie nadal problem z odstepami" (Iwona, 21.09 wieczorem):
   wczesniejsze space-evenly na kartach robilo dziure miedzy naglowkiem
   referencji a pierwsza karta. */
.strona--zakres .lista--zwarta { flex: 1; align-content: space-evenly; gap: 2.3cqw 5cqw; }

.strona--zakres .refy--poziome { gap: 1.6cqw; }

/* Punkty Key Areas w rownych wierszach dwoch kolumn - kolejnosc biegnie
   kolumna w dol jak w docx, a wspolna wysokosc wierszy wyrownuje punktory
   miedzy kolumnami ("wizualnie wyrownaj te punkty", Iwona 21.09). */
.lista--rowna {
  grid-auto-flow: column;
  grid-template-rows: repeat(6, minmax(0, 1fr));
  align-items: start;
  gap: 1.2cqw 5cqw;
}

/* Key Areas dojezdzaja do dolu strony podzespolow (uwagi Iwony, 20.09).
   Od 21.09 (siodma runda) z oddechem od dolnej krawedzi - blok i pas ikon
   ida odrobine wyzej. Tytul podzespolow idzie od dziesiatej rundy
   wspolnym stopniem H1 - wezszy kroj miesci go w dwoch wierszach. */
.obszary-dol { margin-top: auto; }

.strona--podzespoly .obszary-dol { margin-bottom: 2.6cqw; }

/* Krata ikon rosnie miedzy akapitami a Key Areas (flex: 1 w chipy--krata),
   wiec margines auto zszedl - przerwe trzyma zwykly odstep. */
.strona--podzespoly .chipy--pas { margin: 2cqw 0; }

.obszary-dol .lista { margin-bottom: 1cqw; }

/* --- okładka i strony ciemne ----------------------------------------------- */

.strona--ciemna {
  position: relative;
  padding: 8cqw;
  color: var(--steel-bright);
  background: linear-gradient(160deg, var(--navy-soft) 0%, var(--navy) 46%, var(--ink-raise) 100%);
}

/* Sygnałowy pasek przy grzbiecie, jak przeszycie okładki. */
.strona--ciemna::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 1.4cqw;
  background: var(--signal);
}

/* Delikatny połysk lakierowanej okładki. */
.strona--okladka::after,
.strona--tyl::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(115deg, transparent 42%, rgba(255, 255, 255, 0.06) 52%, transparent 62%);
}

.okladka-znak { width: 34cqw; height: auto; }

.okladka-znak--maly { width: 26cqw; }

/* Biale logo mono w prawym gornym rogu na granacie - final Iwony
   (21.09, noc): kolorowa wersja na jasnej gorze wygladala sztucznie,
   "wstaw biale i pociagnij granat do gory"; prawy rog zostal z dosylki
   Olivera. */
.strona--okladka .okladka-znak { align-self: flex-end; width: 26cqw; margin-top: 0.4cqw; }

.strona--tyl .okladka-znak { align-self: center; }

.okladka-srodek { flex: 1; display: flex; flex-direction: column; justify-content: center; gap: 3cqw; }

/* Caly blok tekstu lezy na granacie ("zeby tekst juz byl na granatowym",
   Iwona 21.09 20:18). Kotwica u gory bloku - tytul stoi w tym samym
   miejscu w kazdym jezyku. Bazowe margin-top: auto przycisku musi
   zejsc, bo inaczej to ono zjada wolna przestrzen i tytul klei sie
   do logo - pulapka z piatej rundy. */
.strona--okladka .okladka-srodek {
  position: relative;
  justify-content: flex-start;
  padding-top: 20cqw;
  /* Rytm bloku: ciasniejsze, ROWNE odstepy wewnatrz i gwarantowany
     oddech przed kickerem na dole - bez niego przycisk i kicker
     sklejaly sie w jedna pomaranczowa plame (Oliver, 21.09). */
  gap: 2.4cqw;
  padding-bottom: 4cqw;
}

/* Zdjecie kol JEDNA kopia na calej kartce, normalnie, bez lustra
   ("daj to zdjecie, ale bez lustrzanego, uzyj go normalnie i daj
   troche tej niebieskiej poswiaty na calosc" - Oliver, 21.09 pozna
   noc; lustro z 21:48 wypadlo). Warstwy foto/welon/cien dziedziczy
   z bazy .strona--foto jak tylna okladka. Pionowy kadr 3:4 bierze
   srodkowe 50% szerokosci poziomego oryginalu i gubi OBA kola
   (slepa uliczka kadru kanalu z 21:22), wiec okno jedzie na lewa
   czesc zdjecia: lewe kolo w calosci w kadrze, kanal uchodzi w glab
   po prawej. */
.strona--okladka .okladka-foto { object-position: 8% 50%; }

/* Poswiata wg wzoru Olivera ("taka poswiata jak na tym zdjeciu
   i perfecto jest" - zrzut z gestym, rownym zalaniem granatem):
   mocniejszy welon barwy plus polprzezroczysta granatowa warstwa
   na calosci - zdjecie schodzi do roli tla, bialy tekst gra pierwsza
   role. Ciezar dalej przy samej gorze i na dole pod kickerem. */
.strona--okladka .okladka-welon { opacity: 0.4; }

.strona--okladka .okladka-cien {
  background: linear-gradient(180deg,
    rgba(20, 17, 59, 0.62) 0%,
    rgba(34, 30, 94, 0.5) 14%,
    rgba(34, 30, 94, 0.48) 80%,
    rgba(8, 7, 26, 0.6) 100%);
}

.strona--okladka .cta-rzad { margin-top: 0.6cqw; }

/* .strona h2 ustawia granat i wygrywa z sama klasa tytulu, wiec nadpisanie
   dla ciemnych stron musi scigac sie ta sama droga: przez .strona. */
.strona--ciemna h2 { color: var(--white); }

.okladka-tytul,
.kontakt-tytul {
  margin: 0;
  font-family: var(--font-display);
  font-stretch: 88%;
  font-weight: 900;
  line-height: 1.04;
  letter-spacing: var(--track-tight);
  color: var(--white);
}

/* Stopień dobrany tak, żeby "One Partner." / "End-to-End Rail Solutions."
   trzymały się dokładnie dwóch wierszy (uwagi Iwony, 20.09); dłuższe
   biegi PL i DE schodzą niżej blokiem [lang] na końcu pliku. */
.okladka-tytul { font-size: 5.6cqw; }
.kontakt-tytul { font-size: 5.4cqw; }

/* Strona kontaktu: tresc plynie od gory (nie ze srodka), zeby naglowek
   stal na tej samej wysokosci co naglowek strony wspolpracy obok -
   "your next rolling stock wyzej, rowny z poprzednia strona" (siodma
   runda, 21.09). Logo z prawego dolnego rogu wypadlo, ramka filmu rosnie
   i centruje sie w odzyskanej przestrzeni. */
.strona--kontakt .okladka-srodek { justify-content: flex-start; gap: 2.2cqw; }

.strona--kontakt .kontakt-tytul { margin-top: 2.6cqw; }

/* Od 20.09 (uwagi Iwony): naglowek Contact na samej gorze jak na jasnych
   stronach, film w ramce na stronie. */
.strona-glowka--ciemna { border-bottom-color: rgba(255, 255, 255, 0.16); }

/* Kontakt niesie duzo tresci jak na ciemna strone - padding schodzi
   do poziomu stron jasnych, zeby film miescil sie na kartce. */
.strona--kontakt { padding: 6cqw 7cqw; }

/* Ramka filmu na stronie kontaktu - zastepuje seans po zamknieciu
   folderu, "zeby nikt jej nie przeoczyl". Te same klasy przycisku
   i plakatu co dawny seans, inna oprawa: kadr w treści strony. */
.strona-seans {
  position: relative;
  align-self: center;
  width: 100%;
  max-width: 78cqw;
  margin: auto 0;
  border-radius: 6px;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.2);
  box-shadow: 0 8px 26px rgba(4, 3, 14, 0.4);
}

.seans-wideo {
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  display: block;
}

/* Przycisk startu leży na plakacie i przyciemnia go pod napisem. */
.seans-start {
  appearance: none;
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1.6cqw;
  background: linear-gradient(180deg, rgba(8, 7, 26, 0.18), rgba(8, 7, 26, 0.55));
  border: 0;
  font-family: var(--font-mono);
  font-size: 2.2cqw;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--white);
  cursor: pointer;
}

.seans-play {
  display: grid;
  place-items: center;
  width: 7cqw;
  height: 7cqw;
  border-radius: 999px;
  background: var(--signal);
  font-size: 2.6cqw;
  line-height: 1;
  padding-left: 0.5cqw;
  transition: transform var(--dur-fast) var(--ease-out);
}

.seans-start:hover:not([disabled]) .seans-play { transform: scale(1.08); }

.seans-podpis {
  padding: 0.6cqw 1.8cqw;
  border-radius: 999px;
  background: rgba(8, 7, 26, 0.55);
}

/* Zapowiedź, dopóki plik filmu nie wejdzie na serwer. */
.strona-seans--wkrotce .seans-start { cursor: default; }

.strona-seans--wkrotce .seans-play { display: none; }

/* Kreska subtelniejsza - ciensza i krotsza (siodma runda uwag Iwony,
   21.09); dotyczy przedniej i tylnej okladki. */
.okladka-kreska { width: 14cqw; height: 0.35cqw; background: var(--signal); }

.okladka-lead {
  margin: 0;
  max-width: 46ch;
  font-size: 3cqw;
  line-height: 1.55;
  color: var(--steel-bright);
}

.okladka-stopka {
  margin: auto 0 0;
  font-family: var(--font-mono);
  font-size: 2.3cqw;
  letter-spacing: var(--track-mono);
  text-transform: uppercase;
  color: var(--steel-dim);
}

/* "InnoTrans 2026 · Berlin" bez dat na samym dole okladki, wysrodkowany.
   Bialy jak w mocku - na okladce zostaje jeden kolor tekstu
   (uwaga Iwony, 21.09 20:18). */
.okladka-stopka--kicker { font-size: 2.6cqw; color: var(--white); text-align: center; }

/* Strona kontaktu: przyciski i dane na granacie. */
.strona--kontakt .cta-rzad { margin-top: 1cqw; }

.kontakt-dane { margin-top: 3cqw; display: grid; gap: 0.6cqw; }

.kontakt-dane .naglowek-listy { color: var(--signal); margin-bottom: 1cqw; }

.kontakt-adres { color: var(--steel-bright); }

.kontakt-lacza a {
  color: var(--white);
  text-decoration: none;
  border-bottom: 1px solid rgba(255, 255, 255, 0.25);
}

.kontakt-lacza a:hover { border-bottom-color: var(--signal); }

.strona--tyl .okladka-srodek { align-items: flex-start; }

/* Tylna okladka na zdjeciu wnetrza hali zamiast gladkiego granatu
   (Iwona, dziesiata runda, 21.09) - te same trzy warstwy co przednia
   okladka, ale cien czytelnosci mocniejszy przy lewej krawedzi i na
   dole, bo dane kontaktowe leza w lewej kolumnie srodka kartki. */
.strona--tyl .okladka-cien {
  background:
    linear-gradient(90deg,
      rgba(20, 17, 59, 0.58) 0%,
      rgba(20, 17, 59, 0.36) 55%,
      rgba(20, 17, 59, 0.22) 100%),
    linear-gradient(180deg,
      rgba(20, 17, 59, 0.34) 0%,
      rgba(20, 17, 59, 0.24) 45%,
      rgba(20, 17, 59, 0.62) 100%);
}

.strona--tyl .okladka-srodek,
.strona--tyl .okladka-stopka { text-shadow: 0 1px 8px rgba(8, 7, 26, 0.6); }

/* --- okładka na zdjęciu ----------------------------------------------------
   Zdjęcie wchodzi trzema warstwami, bo jedna nie załatwia obu rzeczy naraz:
   fotografia ma wyglądać jak reszta materiałów PTS, a tekst ma być czytelny
   na każdym jej fragmencie.
   1. sama fotografia pod filtrem „Deep Blue” z księgi znaku (s. 15),
   2. welon koloru - granat nałożony trybem `color`, więc zdjęcie traci własną
      barwę, a zachowuje rysunek światła,
   3. cień czytelności - gradient najmocniejszy tam, gdzie leży tekst.
   Gradient tła z .strona--ciemna zostaje pod spodem jako zapas na wypadek,
   gdyby zdjęcie się nie wczytało.
   -------------------------------------------------------------------------- */

.strona--foto { position: relative; isolation: isolate; }

.okladka-foto {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: saturate(0.86) contrast(1.04);
  z-index: -2;
}

.okladka-welon {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: rgba(29, 40, 122, 1);
  opacity: 0.2;
  mix-blend-mode: color;
}

/* Okładka niesie tekst na całej wysokości - od znaku u góry po adres na dole -
   więc przyciemnienie nie może być winietą przy krawędziach. Środek zostaje
   najjaśniejszy, bo tam zdjęcie ma cokolwiek pokazać.
   Od 20.09 (uwagi Iwony) całość zeszła o stopień jaśniej; od 21.09 (ósma
   runda) góra jeszcze jaśniejsza - podwozie nad kanałem ma być widoczne.
   Czytelność tekstu trzymają cienie tekstu z reguł .strona--foto niżej. */
.okladka-cien {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    linear-gradient(90deg,
      rgba(20, 17, 59, 0.52) 0%,
      rgba(20, 17, 59, 0.26) 52%,
      rgba(20, 17, 59, 0) 88%),
    linear-gradient(180deg,
      rgba(20, 17, 59, 0.28) 0%,
      rgba(20, 17, 59, 0.14) 46%,
      rgba(20, 17, 59, 0.72) 100%);
}

/* Zdjecie ma pod tekstem wlasny rysunek, wiec sam gradient nie wystarcza:
   pomaranczowy nadtytul potrafi trafic na jasny slup hali. Cien jest na tyle
   szeroki i rozmyty, zeby nie bylo go widac jako obwodki. */
.strona--foto .kicker,
.strona--foto .okladka-lead,
.strona--foto .okladka-stopka { text-shadow: 0 1px 8px rgba(8, 7, 26, 0.6); }

.strona--foto .okladka-tytul { text-shadow: 0 2px 18px rgba(8, 7, 26, 0.45); }

/* --- strona cyber: animacja toru z RailGuard Sentinel ----------------------
   "Tu potrzebujemy tę animację co na railguard" (Iwona, Teams 20.09).
   Kartka przechodzi na ciemną stronę w języku RGS, a pod treścią ksiazka.js
   rysuje zaadaptowany hero z railguardsentinel.eu: widok z kabiny na tor,
   słupy trakcyjne i semafory. Canvas leży pod cieniem czytelności; gradient
   .strona--ciemna zostaje pod spodem jako zapas na wersję bez skryptu
   i na druk, gdzie canvas schodzi. */

.strona--cyber { isolation: isolate; padding: 6cqw 7cqw; }

.cyber-tor {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: -2;
}

/* Najciemniej u góry, gdzie leży tekst; horyzont sceny (ok. 2/3 wysokości)
   zostaje odsłonięty, a sam dół ciemnieje pod stopkę. */
.cyber-cien {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: linear-gradient(180deg,
    rgba(8, 7, 26, 0.8) 0%,
    rgba(8, 7, 26, 0.58) 38%,
    rgba(8, 7, 26, 0.16) 62%,
    rgba(8, 7, 26, 0.06) 82%,
    rgba(8, 7, 26, 0.42) 100%);
}

.strona--cyber .strona-glowka { border-bottom-color: rgba(255, 255, 255, 0.16); }

.strona--cyber h2,
.strona--cyber p,
.strona--cyber .lista li { text-shadow: 0 1px 8px rgba(8, 7, 26, 0.55); }

.lista--cyber { gap: 2cqw; margin: 1cqw 0 3cqw; }

.lista--cyber li { font-size: 2.75cqw; line-height: 1.45; }

/* Tresc rozciaga sie na cala strone (uwagi Iwony, 20.09): lista rosnie
   flexem i rozklada pozycje, przycisk na railguardsentinel.eu jest
   wyraznym CTA zamiast linku w stopce. */
.lista--cyber-pelna { flex: 1; align-content: space-evenly; margin-bottom: 1cqw; }

.lista--cyber-pelna li { font-size: 2.9cqw; line-height: 1.5; }

.cta-rzad--cyber { margin: 0; }

/* Tekst w przycisku wysrodkowany, gdy zlamie sie w dwa wiersze
   (siodma runda, 21.09). */
.cta-rzad--cyber .przycisk-strona { text-align: center; }

/* Dopisek o projekcie B+R mniejszym stopniem przy dolnej krawedzi,
   z wyraznym oddechem od przycisku nad soba (siodma runda, 21.09).
   Selektor przez .strona p - gola klasa przegrywa ze ".strona p"
   i dopisek szedl pelnym stopniem akapitu. */
.strona--cyber p.dopisek {
  margin: 3cqw 0 0;
  font-size: 2.05cqw;
  line-height: 1.4;
  color: var(--steel);
}

.strona--cyber .strona-stopka {
  border-top-color: rgba(255, 255, 255, 0.16);
  color: var(--steel);
}

/* --- podpowiedź ------------------------------------------------------------ */

.wskazowka {
  margin: 1.1rem 0 0;
  font-family: var(--font-mono);
  font-size: var(--step-mono);
  letter-spacing: var(--track-mono);
  text-transform: uppercase;
  color: var(--steel);
  animation: pulsowanie 2.8s ease-in-out infinite;
}

@keyframes pulsowanie {
  0%, 100% { opacity: 0.45; }
  50% { opacity: 0.95; }
}

body.bez-podpowiedzi .wskazowka { display: none; }

/* --- ograniczony ruch ------------------------------------------------------ */

@media (prefers-reduced-motion: reduce) {
  .scena { animation: none; }
  .ksiazka { transition: none; }
  .wskazowka { animation: none; }
  .punkt-fala { animation: none; }
  /* Nieruchomy pas skanu bylby plama na rysunku - schodzi caly. */
  .sylwetka-skan { display: none; }
  /* Pociag etapow staje w miejscu zamiast zjezdzac. */
  .tor-pociag { transition: none; }
}

/* --- kompaktowanie wersji niemieckiej --------------------------------------
   Niemiecki bieg tekstu jest o 20-30% dłuższy od angielskiego przy tych
   samych polach. Zamiast skracać treść Iwony, gęste strony DE schodzą
   o stopień w typografii. Zakres dobrany bramką przepełnień, nie okiem. */

/* DE trzyma jeden wspolny stopien H1 dla calego albumu, o wlos mniejszy
   niz EN/PL - dluzsze slowa przy wspolnym stopniu 4.7 lamaly tytuly
   w trzeci wiersz. */
[lang="de"] .strona h2 { font-size: 4.3cqw; }

[lang="de"] .strona p.strona-akapit-zwarty { font-size: 2.35cqw; line-height: 1.36; }

[lang="de"] .strona p.strona-lead { font-size: 2.5cqw; }

[lang="de"] .lista--zwarta { gap: 0.9cqw; }

[lang="de"] .lista--zwarta li { font-size: 2.2cqw; line-height: 1.28; }

[lang="de"] .sylwetka { height: 33cqw; }

[lang="de"] .chipy--pojazdy .chip { font-size: 1.95cqw; }

[lang="de"] .kafle--drobne .kafel { font-size: 2.15cqw; padding: 1.5cqw 1.9cqw; }

[lang="de"] .strona p.historia-opis { font-size: 2.25cqw; }

[lang="de"] .lista--historia li { font-size: 2.05cqw; line-height: 1.28; }

[lang="de"] .lista--historia-luzna li { font-size: 2.25cqw; line-height: 1.34; }

[lang="de"] .refy--poziome { gap: 1.2cqw; }

[lang="de"] .strona p.ref-opis { font-size: 2.05cqw; line-height: 1.32; }

[lang="de"] .sciezki--zwarte .sciezka-opis { font-size: 1.95cqw; line-height: 1.28; }

/* Najdluzszy bieg tekstu nie zostawia na powietrze prawie nic -
   naglowek wspolpracy schodzi w dol o wlos, nie o krok. */
[lang="de"] .strona--wspolpraca h2 { margin-top: 1.8cqw; margin-bottom: 2.2cqw; }

[lang="de"] .formularz { gap: 0.9cqw 2.4cqw; }

/* Tytul okladki JEDNYM stopniem 5.6cqw we wszystkich jezykach
   ("dla wszystkich jezykow ustaw te sama pierwsza strone" - Oliver,
   przed ogloszeniem folderu w firmie; wczesniejsze 5.2 PL / 5 DE
   wypadly). Zmierzone po fontach: PL i EN trzymaja dwa wiersze,
   DE lamie sie na trzy niezaleznie od stopnia (5.6 vs 5 nie zmienia
   liczby wierszy, bieg niemiecki jest za dlugi na dwa), wiec wspolny
   stopien nic nie psuje, a wyrownuje kroj miedzy wersjami. */

[lang="de"] .etap-tytul { font-size: 3.1cqw; }

[lang="de"] .etap-opis { font-size: 2.3cqw; line-height: 1.36; }

[lang="de"] .kontakt-tytul { font-size: 4.6cqw; }

/* Naglowek kontaktu DE rowna sie do naglowka wspolpracy DE, ktory
   schodzi w dol o wlos, nie o krok. */
[lang="de"] .strona--kontakt .kontakt-tytul { margin-top: 1.8cqw; }

/* Hierarchia naglowkow Service Portfolio (siodma runda uwag Iwony,
   21.09): rozdzial otwiera headline 1 (strony 7 i 9), a strony
   wewnetrzne rozdzialu - Key Areas of Modernisation i Stages from
   assessment - ida stopniem drugim. Reguly stoja ZA blokiem [lang="de"],
   zeby wygrac kaskade z tamtejszym kompaktowaniem naglowkow. */
.strona h2.naglowek-drugi { font-size: 3.8cqw; }

[lang="de"] .strona h2.naglowek-drugi { font-size: 3.5cqw; }

/* Kropki zamiast kwadratow na liscie Key Areas of Modernisation
   (siodma runda, 21.09) - lista--rowna zyje tylko na tej stronie. */
.lista--rowna li::before { border-radius: 50%; }

/* --- druk: kartka na arkusz A4 --------------------------------------------- */

#druk { display: none; }

@media print {
  @page { size: A4 portrait; margin: 0; }

  body { display: block; height: auto; overflow: visible; background: var(--white); }

  .pasek,
  .scena,
  .ster { display: none !important; }

  #druk { display: block; }

  .druk-karta {
    width: 210mm;
    height: 296mm;
    container-type: size;
    overflow: hidden;
    break-after: page;
    page-break-after: always;
  }

  .druk-karta .strona {
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }

  /* Galeria eksploratora na papierze nie klika - strzałki i licznik
     schodzą, duży kadr pokazuje pierwsze zdjęcie, miniatury zostają
     siatką kadrów. */
  .eksplorator-strzalka,
  .eksplorator-licznik { display: none; }

  /* Sylwetka na papierze nie jest klikalna - punkty i jezdzacy skan
     schodza z wydruku. Etykieta zostaje: od 21.09 wieczorem to naglowek
     sekcji jak Scope, nie podpowiedz kliku. */
  .punkt,
  .sylwetka-skan { display: none; }

  /* Pociag etapow bez skryptu nie ma pozycji - schodzi z wydruku. */
  .tor-pociag { display: none; }

  /* Opisy etapów na papierze stoją rozwinięte - najechanie nie istnieje. */
  .etap-opis { max-height: none; opacity: 1; padding-top: 0.7cqw; }

  /* Ramka filmu nie gra na papierze - zostaje plakat bez przycisku. */
  .seans-start { display: none; }

  /* Canvas animacji nie drukuje niczego - na papier idzie granatowy
     gradient strony ciemnej, bez cienia liczonego pod scenę. */
  .cyber-tor,
  .cyber-cien { display: none; }
}
