/* ============================================================
   SKÓRA WSPÓLNA — jeden system wizualny dla całego serwisu.
   Etap 14.

   DLACZEGO JASNO. Do trzynastego etapu każde miasto miało własną
   ciemną skórę: Kraków mosiądz na grafitzie, Warszawa rdza,
   Przemyśl patyna na atramentowym granacie. Wyglądało to dobrze
   przy jednym zdjęciu i źle przy wszystkim innym — właściciel
   powiedział wprost, że „strona jest tak ciemna, że ciężko coś
   dostrzec”. Przy kilkuset słowach noty ma rację: jasnoszara
   szaryfowa czcionka na prawie czarnym tle to nie jest krój do
   czytania, tylko do oglądania.

   Doszło do tego drugie: w serwisie mają stanąć aparaty i artykuły.
   Siedem osobnych rejestrów barwnych nie da się rozciągnąć na
   działy, których jeszcze nie ma. Stąd JEDEN system — jedna paleta,
   jedna typografia, jedna siatka — a nie siedem wariantów.

   Stara jasność tła nie zniknęła bez śladu: skan nadal leży na
   passe-partout, tyle że teraz to jest jasny karton na jasnym
   stole, a nie biała kartka w ciemnym pokoju. Fotografia z XIX
   wieku ma półtony w sepii i szarościach — na ciemnym tle oko
   traci je pierwsze.

   CO SIĘ NIE ZMIENIŁO: skan idzie w całości, w naturalnych
   proporcjach, bez kadrowania i bez korekty (WYMAGANIA 21).
   Nigdzie nie ma object-fit.

   RAMKA BIERZE PROPORCJE ZE SKANU. Wcześniej gablota miała sztywną
   wysokość, ustawioną pod pocztówkę — czyli pod format poziomy.
   Na stronach z fotografią gabinetową (Mielec 66 pionowych na 68,
   Rzeszów 41 na 44) pionowy skan kurczył się do jednej trzeciej
   szerokości i pływał w pustce. Teraz `--ar` niesie proporcje
   awersu, a gablota układa się pod nie.
   ============================================================ */

:root{
  /* papier i atrament */
  --bg:            #f4f1ea;   /* tło strony — ciepły papier */
  --bg-deep:       #e9e4d9;   /* tło gabloty, ciemniejsze od strony */
  --bg-raise:      #fffdf8;   /* płaszczyzny wyniesione: powiększenie */
  --mat:           #ffffff;   /* passe-partout pod skanem */
  --mat-edge:      #cfc7b6;

  --line:          #d6cec0;
  --line-soft:     #e4ddd0;

  --ink:           #1b232c;   /* tekst główny — kontrast 13:1 na tle */
  --ink-soft:      #414c58;   /* nota, wstęp — kontrast 8,6:1 */
  --ink-faint:     #6b7682;   /* podpisy techniczne — kontrast 4,8:1 */

  /* Jeden akcent na cały serwis, nie siedem. Ciemna zieleń patyny —
     jedyny kolor, który po wyjęciu z ciemnych skór nie zrobił się
     ani krzykliwy, ani brudny na jasnym papierze. */
  --pat:           #2f6152;
  --pat-soft:      #4b7d6d;
  --pat-dim:       #86998f;

  --shadow-card:   0 2px 8px rgba(40,34,24,.10), 0 10px 26px rgba(40,34,24,.09);
  --shadow-deep:   0 22px 70px rgba(40,34,24,.28);

  /* zapasowe proporcje gabloty, gdy karta nie poda własnych */
  --ar:            4/3;
  /* dokąd może urosnąć gablota bardzo wysokiego skanu */
  --stage-max:     540px;
}

*{box-sizing:border-box}
html{scroll-behavior:smooth; -webkit-text-size-adjust:100%}
@media (prefers-reduced-motion: reduce){
  html{scroll-behavior:auto}
  *{animation-duration:.001ms !important; animation-iteration-count:1 !important; transition-duration:.001ms !important;}
}

body{
  margin:0;
  background:
    radial-gradient(1020px 560px at 6% -10%, rgba(47,97,82,.045), transparent 60%),
    radial-gradient(900px 520px at 96% 0%, rgba(120,105,70,.05), transparent 58%),
    var(--bg);
  color:var(--ink);
  font-family:"Source Serif 4", Georgia, serif;
  font-size:17.5px;
  line-height:1.68;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
}

h1,h2,h3{font-family:"Old Standard TT", Georgia, serif; font-weight:700; margin:0; text-wrap:balance}
a{color:var(--pat); text-underline-offset:3px}
a:hover{color:#1f463b}
button{font:inherit; color:inherit}
:focus-visible{outline:2px solid var(--pat); outline-offset:3px}

.skip-link{
  position:absolute; left:-999px; top:0; z-index:300;
  background:var(--pat); color:#fff; padding:10px 16px;
  font-family:"Inter", system-ui, -apple-system, "Segoe UI", sans-serif; font-size:13px;
}
.skip-link:focus{left:12px; top:12px}

/* ---------- pasek przyklejony do góry (Etap 15, D-42) ----------

   Do czternastego etapu nagłówek wymieniał sześć miast obok siebie,
   zawijał się na telefonie do dwóch rzędów i ODJEŻDŻAŁ przy przewijaniu.
   Przy ósmym mieście urósłby do trzech rzędów: rząd odsyłaczy rośnie
   z liczbą stron, a miejsca na ekranie nie przybywa.

   Teraz jest wąski pasek, który zostaje na wierzchu: znak i nazwa po
   lewej (odsyłacz na stronę główną), nazwa bieżącej strony pośrodku,
   rozwijana lista siedmiu podstron po prawej. Lista nie rośnie wszerz
   — rośnie w dół, we własnym okienku.

   DWA PRZYKLEJONE PASKI NA PULPICIE, JEDEN NA TELEFONIE. Pod tym stoi
   drugi: filtry (.index). Oba miały `top:0`, więc drugi wjechałby pod
   pierwszy i zniknął. Dlatego wysokość paska jest zapisana w `--nav-h`
   i filtry przyklejają się DOKŁADNIE POD nim. Jedna liczba rządzi obiema
   rzeczami — inaczej przy każdej zmianie wysokości paska trzeba by
   pamiętać o drugim miejscu, a nikt nie pamięta.

   ETAP 17 (D-45): na telefonie drugiego paska już nie ma. Filtry są
   szufladą wysuwaną spod paska przyciskiem „Filtry", obok „Miasta" —
   szczegóły przy `@media (max-width:720px)` na końcu pliku. */

:root{ --nav-h:48px; }

.sg-bar{
  position:sticky; top:0; z-index:120;
  background:rgba(255,253,248,.94);
  backdrop-filter:blur(9px);
  border-bottom:1px solid var(--line);
}
.sg-bar-inner{
  max-width:1320px; margin:0 auto; padding:0 32px; height:var(--nav-h);
  display:flex; align-items:center; gap:16px;
}

/* znak + nazwa = odsyłacz na stronę główną. To jest cały „powrót
   na stronę główną" — nie ma osobnego przycisku, bo logo w nagłówku
   jest miejscem, w które i tak każdy klika. */
.sg-home{
  display:flex; align-items:center; gap:9px; flex:0 0 auto;
  text-decoration:none; color:var(--pat); transition:color .18s ease;
}
.sg-home:hover{color:#1f463b}
.sg-mark{display:block; flex:0 0 auto}
.sg-word{
  font-family:"Old Standard TT", Georgia, serif; font-style:italic;
  font-size:16.5px; line-height:1; white-space:nowrap;
}
.sg-here{
  flex:1 1 auto; min-width:0; margin:0; text-align:center;
  font-family:"Old Standard TT", Georgia, serif; font-style:italic;
  font-size:15.5px; color:var(--ink);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}

/* Rozwijana lista miast. <details>/<summary> — działa BEZ JavaScriptu,
   także wtedy, gdy skrypt strony się nie wczyta. Skrypty różnią się
   między miastami (Jarosław umie karty jednostronne, Kraków ma starszy
   filtr) i nawigacja nie ma prawa od nich zależeć. */
.sg-menu{flex:0 0 auto; position:relative}
.sg-menu > summary, .ix-drawer > summary{
  list-style:none; cursor:pointer; -webkit-user-select:none; user-select:none;
  display:inline-flex; align-items:center; gap:7px;
  font-weight:500; font-family:"Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size:12.5px; letter-spacing:.03em; color:var(--ink-soft);
  background:var(--bg-raise); border:1px solid var(--line);
  padding:6px 12px; transition:color .18s ease, border-color .18s ease;
}
.sg-menu > summary::-webkit-details-marker,
.ix-drawer > summary::-webkit-details-marker{display:none}
.sg-menu > summary::marker, .ix-drawer > summary::marker{content:""}
.sg-menu > summary::after, .ix-drawer > summary::after{
  content:""; width:0; height:0; margin-top:1px;
  border-left:4px solid transparent; border-right:4px solid transparent;
  border-top:5px solid var(--pat-soft);
}
.sg-menu > summary:hover, .ix-drawer > summary:hover{color:var(--pat); border-color:var(--pat-soft)}
.sg-menu[open] > summary, .ix-drawer[open] > summary{color:var(--pat); border-color:var(--pat-soft)}
.sg-menu[open] > summary::after, .ix-drawer[open] > summary::after{transform:rotate(180deg)}

/* WEJŚCIE DO WYSZUKIWARKI (Etap 27, TOR 2/3 z D-58). Stoi w pasku obok
   „Miasta", czyli w jedynym miejscu, które jest takie samo na wszystkich
   34 stronach serwisu. Wygląda jak sąsiednie rozwijaki i tak samo się
   zachowuje — z jedną różnicą: to zwykły odsyłacz, nie <details>, bo
   prowadzi na inną stronę, a nie otwiera okienka.

   Szkło powiększające jest `aria-hidden` — obok stoi słowo „Szukaj”
   napisane literami, więc czytnik ekranu ma przeczytać je, a nie opisywać
   obrazek drugi raz (tak samo jak znak w pasku, D-43). */
.sg-szukaj{
  flex:0 0 auto; display:inline-flex; align-items:center; gap:7px;
  text-decoration:none;
  font-weight:500; font-family:"Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size:12.5px; letter-spacing:.03em; color:var(--ink-soft);
  background:var(--bg-raise); border:1px solid var(--line);
  padding:6px 12px; transition:color .18s ease, border-color .18s ease;
}
.sg-szukaj:hover{color:var(--pat); border-color:var(--pat-soft)}
.sg-szukaj[aria-current="page"]{color:var(--pat); border-color:var(--pat-soft)}
.sg-szukaj svg{display:block; flex:0 0 auto}

/* Rozwijak „Filtry" — od Etapu 23 wejście do filtrów NA OBU SZEROKOŚCIACH.
   D-45 świadomie zostawił pulpit nietknięty (rzędy stały rozwinięte,
   przycisku nie było). Pomiar Etapu 23 pokazał cenę: pasek + rozwinięte
   rzędy = 209–211 px z 900, czyli 23% pulpitu na stałe — i właściciel
   odrzucił to przy odbiorze. Odwrócenie jest świadome, z pomiarem: D-54. */
.ix-drawer{display:block; flex:0 0 auto}
.sg-list{
  position:absolute; right:0; top:calc(100% + 8px); z-index:130;
  min-width:232px; margin:0; padding:5px 0; list-style:none;
  background:var(--bg-raise); border:1px solid var(--line);
  box-shadow:var(--shadow-card);
}
.sg-list a{
  display:flex; align-items:baseline; justify-content:space-between; gap:16px;
  padding:8px 16px; text-decoration:none; color:var(--ink);
  font-family:"Old Standard TT", Georgia, serif; font-size:17px; line-height:1.3;
}
.sg-list a:hover{background:rgba(47,97,82,.07); color:var(--pat)}
.sg-list a[aria-current="page"]{color:var(--pat); font-style:italic}
.sg-list .sg-n{
  font-family:"Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size:11.5px; color:var(--ink-faint); flex:0 0 auto;
  font-variant-numeric:tabular-nums;
}
.site-foot-x{color:var(--pat); text-decoration:none; border-bottom:1px solid var(--line)}
.site-foot-x:hover{border-bottom-color:var(--pat-soft)}

/* ---------- wstęp ----------
   Etap 23 (D-54): strona miejska ma pokazywać zdjęcia, nie ścianę tekstu.
   Odstępy wstępu zwężone (72/52 → 46/34 itd.) i widoczny zostaje TYLKO
   PIERWSZY AKAPIT — dalsze akapity wchodzą pod „czytaj dalej"
   (.lede-more). Proza właściciela zostaje co do słowa; zmienia się
   wyłącznie to, czy jest rozwinięta na wejściu. */
.hero{padding:46px 0 34px; max-width:1320px; margin:0 auto; padding-left:32px; padding-right:32px}
.hero-inner{max-width:800px}
.eyebrow{
  margin:0 0 14px; font-weight:500; font-family:"Inter", system-ui, -apple-system, "Segoe UI", sans-serif; font-size:12px;
  letter-spacing:.2em; text-transform:uppercase; color:var(--pat);
}
.hero h1{
  font-size:clamp(33px, 5.2vw, 54px); line-height:1.12; font-style:italic;
  margin-bottom:18px; letter-spacing:-.01em;
}
.lede{font-size:18.6px; line-height:1.7; color:var(--ink-soft); max-width:64ch; margin:0}
.lede + .lede{margin-top:15px}
/* rozwijak dalszych akapitów wstępu — <details>, bez JavaScriptu,
   tym samym mechanizmem co lista miast (D-42) i filtry (D-45) */
.lede-more{margin:0}
.lede-more > summary{
  list-style:none; cursor:pointer; -webkit-user-select:none; user-select:none;
  display:inline-flex; align-items:center; margin-top:12px; width:fit-content;
  font-weight:500; font-family:"Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size:12px; letter-spacing:.08em; text-transform:uppercase;
  color:var(--pat); padding:2px 1px 4px; border-bottom:1px solid var(--pat-dim);
  transition:color .18s ease, border-color .18s ease;
}
.lede-more > summary::-webkit-details-marker{display:none}
.lede-more > summary::marker{content:""}
.lede-more > summary:hover{color:#1f463b; border-bottom-color:var(--pat-soft)}
.lede-more[open] > summary .lm-w{display:none}
.lede-more:not([open]) > summary .lm-z{display:none}
.lede-more > .lede{margin-top:15px}
.hero-rule{border:0; border-top:1px solid var(--line); margin:24px 0 16px; max-width:800px}
.hero-stats{display:flex; gap:52px; flex-wrap:wrap}
.hero-stats > div{display:flex; flex-direction:column; gap:5px}
.hero-stats b{
  font-family:"Old Standard TT", serif; font-weight:700; font-size:30px;
  color:var(--pat); font-variant-numeric:tabular-nums; line-height:1;
}
.hero-stats span{
  font-weight:500; font-family:"Inter", system-ui, -apple-system, "Segoe UI", sans-serif; font-size:11.5px; letter-spacing:.13em;
  text-transform:uppercase; color:var(--ink-faint);
}

/* ---------- zdjęcie na wejściu (Etap 28, D-60) ----------
   Kolumna tekstu `.hero-inner` ma 800 px w środku 1320-pikselowego `.hero`
   — na pulpicie stoi obok niej puste miejsce, dokładnie tam, gdzie wchodzi
   zdjęcie. `.hero--foto` dostają WYŁĄCZNIE strony, których warstwa niesie
   `hero.zdjecie: true` (dziś: Przemyśl, Jarosław, Warszawa) — Kraków,
   Rzeszów, Jasło i Mielec przeszły odbiór i tej klasy nigdy nie dostają,
   więc te reguły nie zmieniają ani piksela na ich stronach.

   W znaczniku zdjęcie stoi PO `.hero-inner` — na pulpicie flex w wierszu
   kładzie je naturalnie po prawej, bez sztucznego `order`. Na telefonie
   marginesu nie ma (D-60: „tam odpowiedź musi być inna”) i dopiero tam
   `order:-1` przenosi zdjęcie NAD wstęp. */
.hero--foto{display:flex; flex-wrap:wrap; align-items:flex-start; gap:44px}
.hero--foto .hero-inner{flex:1 1 420px; max-width:800px}
.hero-photo{
  display:block; flex:1 1 320px; max-width:420px;
  border:1px solid var(--line); box-shadow:var(--shadow-card);
  text-decoration:none; overflow:hidden; background:var(--bg-raise);
  transition:border-color .18s ease;
}
.hero-photo:hover, .hero-photo:focus-visible{border-color:var(--pat-soft)}
.hero-photo img{display:block; width:100%; height:auto}

/* ---------- filtry w szufladzie (Etap 17 telefon, Etap 23 wszędzie) ----------

   Do Etapu 22 to były DWA różne układy: na telefonie szuflada wysuwana
   spod paska (D-45), na pulpicie drugi przyklejony pasek z rozwiniętymi
   rzędami. Pomiar Etapu 23 pokazał, że rozwinięte rzędy kosztują pulpit
   170–211 px z 900 (do 23% ekranu) na stałe, na każdej stronie — a
   właściciel odrzucił stronę przy odbiorze właśnie za „menu, które
   zabiera pół strony". Od Etapu 23 szuflada jest JEDNA, ta sama na obu
   szerokościach: panel schowany, wysuwa się przyciskiem „Filtry" w pasku.

   STEROWANIE BEZ JAVASCRIPTU, jak dotąd: `<details class="ix-drawer">`
   w pasku trzyma stan, `body:has(.ix-drawer[open])` przenosi go na panel.
   Panel nie siedzi wewnątrz `<details>` — uzasadnienie w D-45. Przyciski
   to te same elementy `.ix[data-cat]`/`.ix[data-era]`, skrypty miast
   nietknięte. */
.index{
  display:none;
  position:fixed; top:var(--nav-h); left:0; right:0; z-index:110;
  max-height:calc(100vh - var(--nav-h));
  max-height:calc(100dvh - var(--nav-h));
  overflow-y:auto; overscroll-behavior:contain;
  background:var(--bg-raise);
  border-bottom:1px solid var(--line);
  box-shadow:var(--shadow-card);
}
body:has(.ix-drawer[open]) .index{display:block}
.index-inner{max-width:1320px; margin:0 auto; padding:2px 32px 16px}
.index-row{display:flex; align-items:center; flex-wrap:wrap; gap:6px; padding:12px 0 2px}
.index-row + .index-row{border-top:1px solid var(--line-soft)}
.index-label{
  font-weight:500; font-family:"Inter", system-ui, -apple-system, "Segoe UI", sans-serif; font-size:11px; letter-spacing:.16em;
  text-transform:uppercase; color:var(--ink-faint);
  display:block; width:100%; margin:0 0 3px;
}
.ix{
  appearance:none; cursor:pointer;
  font-family:"Old Standard TT", Georgia, serif; font-size:15.5px; letter-spacing:.015em;
  color:var(--ink-soft); position:relative; white-space:nowrap; line-height:1.25;
  padding:8px 13px; border:1px solid var(--line); background:var(--bg);
  transition:color .18s ease, border-color .18s ease;
}
.ix:hover{color:var(--ink)}
.ix.is-on{color:var(--pat); border-color:var(--pat)}
.ix sup{
  font-family:"Inter", system-ui, -apple-system, "Segoe UI", sans-serif; font-size:10.5px; vertical-align:super;
  margin-left:5px; color:var(--ink-faint); letter-spacing:0;
}
.ix.is-on sup{color:var(--pat-soft)}
.ix[disabled]{opacity:.4; cursor:default}
.ix[disabled]:hover{color:var(--ink-soft)}
/* kreski między nazwami działów miały sens w jednym rzędzie; w zawiniętej
   siatce guzików rozjeżdżają się na końcach wierszy */
.ix-sep{display:none}
.index-row-era .ix{font-size:14.5px; font-style:italic}
.ix-count{
  display:block; width:100%; margin:14px 0 0; padding-left:0;
  font-family:"Inter", system-ui, -apple-system, "Segoe UI", sans-serif; font-size:12px; letter-spacing:.06em;
  color:var(--ink-faint); white-space:nowrap;
}
.ix-reset{
  appearance:none; background:none; border:0; cursor:pointer; white-space:nowrap;
  padding:8px 0 8px 4px;
  font-weight:500; font-family:"Inter", system-ui, -apple-system, "Segoe UI", sans-serif; font-size:11px; letter-spacing:.12em;
  text-transform:uppercase; color:var(--ink-faint); transition:color .18s ease;
}
.ix-reset:hover{color:var(--pat)}
.ix-reset[hidden]{display:none}

/* ---------- siatka kart ---------- */
/* filtry nie stoją już nad siatką (Etap 23), więc zjazd do niej omija
   wyłącznie pasek */
.plates{max-width:1320px; margin:0 auto; padding:30px 32px 20px;
  scroll-margin-top:calc(var(--nav-h) + 8px)}
/* Nota nad siatką i stopka to ZDANIA, nie etykiety — Etap 15, D-41.
   Do czternastego etapu obie stały w kroju maszynowym w 11 px, czyli
   w tym samym, co sygnatura katalogowa. Zdanie czyta się inaczej niż
   numer: idzie w nim o ciąg, nie o pojedynczy znak. Wracają więc do
   kroju tekstu czytanego i do stopnia, w którym da się je przeczytać. */
.plate-note{
  margin:0 0 34px; max-width:66ch;
  font-family:"Source Serif 4", Georgia, serif; font-size:14.5px; line-height:1.75;
  color:var(--ink-faint); letter-spacing:0;
}
.plate-grid{
  display:grid; grid-template-columns:repeat(auto-fill, minmax(300px, 1fr));
  gap:54px 34px; align-items:start;
}
/* KOTWICA KARTY (Etap 27). Od tego etapu każda karta ma `id` z sygnatury
   (`#pt-4-72`), bo wynik wyszukiwarki musi mieć dokąd prowadzić. Bez tej
   linijki przeglądarka ustawia kartę DOKŁADNIE przy górnej krawędzi okna,
   czyli pod przyklejonym paskiem — karta jest wtedy na ekranie, ale jej
   góra siedzi za paskiem i wygląda to na chybienie. Ta sama poprawka,
   co przy `.plates` wyżej, i z tego samego powodu. */
.pc{display:flex; flex-direction:column; min-width:0;
  scroll-margin-top:calc(var(--nav-h) + 16px)}
.pc[hidden]{display:none}

/* GABLOTA. Proporcje bierze ze skanu (--ar podaje generator z nagłówka
   pliku JPEG), nie odwrotnie. `max-height` chroni przed kartami bardzo
   wysokimi — wtedy skan zmniejsza się sam, dalej w swoich proporcjach. */
.pc-stage{
  position:relative;
  aspect-ratio:var(--ar); max-height:var(--stage-max);
  background:
    linear-gradient(158deg, rgba(255,255,255,.6), transparent 56%),
    var(--bg-deep);
  border:1px solid var(--line);
  display:flex; align-items:center; justify-content:center;
  padding:16px; perspective:1400px;
}
.pc-flipper{
  position:relative; width:100%; height:100%;
  transform-style:preserve-3d; transition:transform .62s cubic-bezier(.4,.05,.2,1);
}
.pc[data-flip="back"] .pc-flipper{transform:rotateY(180deg)}
.pc-face{
  position:absolute; inset:0; margin:0; padding:0; border:0; background:none;
  display:flex; align-items:center; justify-content:center;
  cursor:zoom-in; backface-visibility:hidden; -webkit-backface-visibility:hidden;
}
.pc-face-back{transform:rotateY(180deg)}
/* passe-partout: tło + padding. NIGDY object-fit — skan idzie w całości,
   w naturalnych proporcjach. Obrys robi outline, żeby nie wchodził w pomiar. */
.pc-face img{
  max-width:100%; max-height:100%; width:auto; height:auto; display:block;
  background:var(--mat); padding:6px;
  outline:1px solid var(--mat-edge);
  box-shadow:var(--shadow-card);
  transition:box-shadow .25s ease, transform .25s ease, outline-color .25s ease;
}
.pc-face:hover img{
  box-shadow:0 4px 12px rgba(40,34,24,.16), 0 16px 38px rgba(40,34,24,.14);
  transform:translateY(-2px);
  outline-color:var(--pat-soft);
}

/* pasek pod gablotą: odwracanie karty */
.pc-tools{display:flex; justify-content:flex-end; align-items:center; min-height:30px; padding:7px 0 0}
.pc-flip{
  display:inline-flex; align-items:center; gap:7px;
  background:none; border:0; border-bottom:1px solid var(--line);
  color:var(--ink-faint); cursor:pointer; padding:2px 1px 4px;
  font-weight:500; font-family:"Inter", system-ui, -apple-system, "Segoe UI", sans-serif; font-size:11px; letter-spacing:.13em;
  text-transform:uppercase; transition:color .18s ease, border-color .18s ease;
}
.pc-flip:hover{color:var(--pat); border-bottom-color:var(--pat-soft)}
.pc[data-flip="back"] .pc-flip{color:var(--pat); border-bottom-color:var(--pat-soft)}
.pc-flip .gl{font-size:12px; line-height:1; transition:transform .5s ease}
.pc[data-flip="back"] .pc-flip .gl{transform:rotate(180deg)}
.pc-oneside{
  font-weight:500; font-family:"Inter", system-ui, -apple-system, "Segoe UI", sans-serif; font-size:11px; letter-spacing:.13em;
  text-transform:uppercase; color:var(--ink-faint);
}

/* nota katalogowa */
.pc-text{padding:10px 2px 0; display:flex; flex-direction:column; gap:8px}
.pc-title{font-size:19px; line-height:1.26; font-style:italic; color:var(--ink)}
.pc-meta{
  margin:0; font-weight:500; font-family:"Inter", system-ui, -apple-system, "Segoe UI", sans-serif; font-size:11.5px;
  letter-spacing:.075em; text-transform:uppercase; color:var(--ink-faint);
}
.pc-meta .sep{color:var(--pat-dim); margin:0 6px}
.pc-body{margin:2px 0 0; font-size:15.6px; line-height:1.62; color:var(--ink-soft)}
/* NOTA ZWINIĘTA DO DWÓCH LINIJEK (Etap 23, D-54). Etap 22 dał karcie
   bogatą notę z `opis_pl` (200–250 px tekstu) i karta przestała mieścić
   się w oknie razem ze skanem. Zwijamy, NIE skracamy (WYMAGANIA 29):
   w HTML-u stoi cała nota, przycina ją CSS, a skrypt powiększenia czyta
   pełny textContent z .pc-body — w powiększeniu nota jest zawsze cała.
   Steruje <details class="pc-more"> przez :has(), bez JavaScriptu, jak
   szuflada filtrów (D-45). Karta bez .pc-more (krótka nota) nie jest
   przycinana wcale. */
.pc-text:has(.pc-more:not([open])) .pc-body{
  display:-webkit-box; -webkit-box-orient:vertical;
  -webkit-line-clamp:2; line-clamp:2; overflow:hidden;
}
.pc-more{margin:-2px 0 0}
.pc-more > summary{
  list-style:none; cursor:pointer; -webkit-user-select:none; user-select:none;
  display:inline-flex; align-items:center; width:fit-content;
  font-weight:500; font-family:"Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size:11px; letter-spacing:.13em; text-transform:uppercase;
  color:var(--ink-faint); padding:2px 1px 4px; border-bottom:1px solid var(--line);
  transition:color .18s ease, border-color .18s ease;
}
.pc-more > summary::-webkit-details-marker{display:none}
.pc-more > summary::marker{content:""}
.pc-more > summary:hover{color:var(--pat); border-bottom-color:var(--pat-soft)}
.pc-more[open] > summary .pm-w{display:none}
.pc-more:not([open]) > summary .pm-z{display:none}
.pc-sig{
  margin:6px 0 0; padding-top:9px; border-top:1px solid var(--line-soft);
  font-family:"Inter", system-ui, -apple-system, "Segoe UI", sans-serif; font-size:11.5px; letter-spacing:.09em;
  color:var(--ink-faint);
}
.plates-empty{margin:70px 0; text-align:center; color:var(--ink-faint); font-style:italic}

/* ---------- stopka ---------- */
.site-foot{border-top:1px solid var(--line); margin-top:46px; background:rgba(255,253,248,.6)}
.site-foot-inner{margin:0 auto; padding:32px 32px 78px; max-width:880px}
.site-foot p{
  margin:0; font-family:"Source Serif 4", Georgia, serif; font-size:14.5px; line-height:1.75;
  color:var(--ink-faint);
}
.site-foot p + p{margin-top:14px}

/* ---------- powiększenie ---------- */
.lb{position:fixed; inset:0; z-index:200; display:flex; align-items:center; justify-content:center}
.lb[hidden]{display:none}
/* Zasłona musi być gęsta: pod spodem leży jasna siatka kart i przy
   rzadkiej zasłonie przebijała przez tło powiększenia. */
.lb-veil{position:absolute; inset:0; background:rgba(26,22,16,.80)}
.lb-shell{
  position:relative; z-index:1; display:flex;
  width:min(1240px, calc(100% - 132px)); max-height:calc(100% - 60px);
  background:var(--bg-raise); border:1px solid var(--line); box-shadow:var(--shadow-deep);
}
.lb-stage{
  position:relative; margin:0; flex:1 1 auto; min-width:0;
  display:flex; align-items:center; justify-content:center;
  background:linear-gradient(160deg, rgba(255,255,255,.7), transparent 58%), var(--bg-deep);
  padding:30px 30px 62px;
  /* Głębokie powiększenie (Etap 30) przybliża `#lb-frame` ponad rozmiar
     okna — bez tego zoomowany skan malowałby się poza gablotą, na panelu
     tekstu obok. Klip przy krawędzi ramki, jak w każdej przeglądarkowej
     przeglądarce zdjęć. */
  overflow:hidden;
}
/* Sama gablota transformacji — patrz komentarz w generator_stron.py przy
   `#lb-frame`. Bez własnego rozmiaru: jako element flex bez rozciągania
   (`align-items:center` w rodzicu) chowa się dokładnie do wymiarów
   `#lb-img`, więc nie zmienia ani piksela wyglądu przy zoomie=100%. */
.lb-frame{touch-action:none; cursor:zoom-in}
.lb-frame.lb-frame--zoom{cursor:grab}
.lb-frame.lb-frame--zoom:active{cursor:grabbing}
.lb-img{
  max-width:100%; max-height:min(78vh, 720px); width:auto; height:auto; display:block;
  background:var(--mat); padding:8px; outline:1px solid var(--mat-edge);
  box-shadow:0 6px 18px rgba(40,34,24,.20), 0 22px 60px rgba(40,34,24,.18);
  -webkit-user-drag:none; user-select:none;
}
.lb-flip{
  position:absolute; left:50%; bottom:18px; transform:translateX(-50%);
  display:inline-flex; align-items:center; gap:8px;
  background:rgba(255,253,248,.94); border:1px solid var(--pat-dim); color:var(--ink-soft);
  font-family:"Inter", system-ui, -apple-system, "Segoe UI", sans-serif; font-size:12px; letter-spacing:.12em;
  text-transform:uppercase; padding:9px 18px; cursor:pointer; white-space:nowrap;
}
.lb-flip:hover{color:var(--pat); border-color:var(--pat-soft)}
.lb-side{
  flex:0 0 378px; max-width:378px; padding:34px 32px 28px; overflow-y:auto;
  border-left:1px solid var(--line-soft); display:flex; flex-direction:column; gap:13px;
}
.lb-pos{
  margin:0; font-family:"Inter", system-ui, -apple-system, "Segoe UI", sans-serif; font-size:11px;
  letter-spacing:.14em; color:var(--ink-faint); font-variant-numeric:tabular-nums;
}
.lb-meta{
  margin:0; font-weight:500; font-family:"Inter", system-ui, -apple-system, "Segoe UI", sans-serif; font-size:11.5px;
  letter-spacing:.09em; text-transform:uppercase; color:var(--ink-faint);
}
.lb-meta .sep{color:var(--pat-dim); margin:0 7px}
.lb-title{font-size:26px; line-height:1.2; font-style:italic; margin:0}
.lb-body{margin:0; font-size:16.5px; line-height:1.7; color:var(--ink-soft)}
.lb-sig{
  margin:auto 0 0; padding-top:16px; border-top:1px solid var(--line-soft);
  font-family:"Inter", system-ui, -apple-system, "Segoe UI", sans-serif; font-size:11.5px; letter-spacing:.09em; color:var(--ink-faint);
}
.lb-keys{
  margin:10px 0 0; font-family:"Inter", system-ui, -apple-system, "Segoe UI", sans-serif; font-size:10.5px;
  letter-spacing:.1em; text-transform:uppercase; color:var(--ink-faint);
}
.lb-x, .lb-nav{
  position:absolute; z-index:3; background:rgba(255,253,248,.92);
  border:1px solid var(--pat-dim); color:var(--ink-soft); cursor:pointer;
  display:flex; align-items:center; justify-content:center; line-height:1;
  transition:color .18s ease, border-color .18s ease;
}
.lb-x:hover, .lb-nav:hover{color:var(--pat); border-color:var(--pat-soft)}
.lb-x{top:22px; right:26px; width:42px; height:42px; font-size:20px}
.lb-nav{top:50%; transform:translateY(-50%); width:46px; height:66px; font-size:22px}
.lb-prev{left:26px}
.lb-next{right:26px}
body.lb-open{overflow:hidden}

/* ---------- responsywność ---------- */
@media (max-width:1080px){
  .lb-shell{width:calc(100% - 108px)}
  .lb-side{flex-basis:322px}
}
@media (max-width:900px){
  .lb{padding:0}
  .lb-shell{flex-direction:column; width:100%; height:100%; max-height:100%; border:0}
  .lb-stage{flex:0 0 auto; padding:22px 18px 56px}
  .lb-img{max-height:44vh}
  .lb-side{flex:1 1 auto; max-width:none; border-left:0; border-top:1px solid var(--line-soft); padding:24px 22px 84px}
  /* pas wygaszający pod strzałkami — inaczej przewijany tekst noty biegnie
     przez przyciski i robi się nieczytelny w połowie zdania */
  .lb-shell::after{
    content:""; position:absolute; left:0; right:0; bottom:0; height:78px;
    background:linear-gradient(180deg, rgba(255,253,248,0) 0%, var(--bg-raise) 58%);
    pointer-events:none; z-index:2;
  }
  .lb-title{font-size:22px}
  .lb-nav{top:auto; bottom:14px; transform:none; width:44px; height:44px}
  .lb-prev{left:14px}
  .lb-next{right:14px}
  .lb-x{top:12px; right:12px}
  .lb-keys{display:none}
}
@media (max-width:720px){
  /* Pasek niższy o 6 px: przyklejone paski zjadają ekran, na którym mają
     stać skany. Do Etapu 16 stały tu DWA takie paski (nagłówek + filtry)
     i razem zabierały 14,6% ekranu telefonu. Od Etapu 17 zostaje jeden —
     filtry przeniosły się do szuflady (D-45, koniec tego pliku). */
  :root{--nav-h:42px}
  /* jedna kolumna na całą szerokość — gablota może urosnąć, bo skan
     dostaje całą szerokość ekranu i nie ma po co go dławić */
  :root{--stage-max:78vh}
  body{font-size:17px}
  .hero, .index-inner, .plates, .site-foot-inner{padding-left:20px; padding-right:20px}
  .plate-note{font-size:10.5px; line-height:1.8; margin-bottom:28px}
  .sg-bar-inner{padding-left:20px; padding-right:20px; gap:11px}
  /* NAZWA SERWISU SCHODZI Z PASKA NA TELEFONIE (Etap 17). W pasku stoją
     teraz dwa rozwijaki, nie jeden, i zabrakło miejsca: zmierzone przy
     390×844, nazwa bieżącej strony kurczyła się do 38 px, a potrzebowała
     67 px („Warszawa"), więc sześć z siedmiu stron pokazywało „Prz…".
     Po zdjęciu napisu zostaje jej 226 px — mieści się każda.
     Zostaje sam znak: on jest odsyłaczem na stronę główną (D-43), niesie
     nazwę w `aria-label`, a nazwa serwisu i tak stoi w karcie przeglądarki
     i w stopce. Na pulpicie napis zostaje. */
  .sg-word{display:none}
  .sg-home{padding:8px 6px; margin-left:-6px}
  .sg-here{font-size:14.5px}
  .sg-menu > summary, .ix-drawer > summary{font-size:12px; padding:6px 10px}
  /* TRZECI PRZYCISK W PASKU (Etap 27). Na stronie miejskiej stoją teraz
     „Filtry", „Szukaj" i „Miasta" — o jeden więcej, niż mierzył Etap 17.
     Na 390 px słowo „Szukaj" schodzi i zostaje samo szkło powiększające,
     dokładnie tak, jak wcześniej zeszła nazwa serwisu (`.sg-word`):
     ikona niesie znaczenie, `aria-label` niesie słowo dla czytnika ekranu,
     a nazwa bieżącej strony nie ma się z czym bić o miejsce. */
  .sg-szukaj{padding:6px 9px; gap:0}
  .sg-szukaj .sg-szukaj-txt{display:none}
  .sg-list{min-width:210px}
  .hero{padding-top:38px; padding-bottom:28px}
  .lede{font-size:18px}
  .hero-stats{gap:28px}
  /* Na pulpicie zdjęcie stoi obok wstępu, w pustym marginesie po prawej
     (patrz `.hero--foto` wyżej). Telefon tego marginesu nie ma — D-60
     rozstrzyga, że tam zdjęcie idzie NAD wstęp, nie obok niego. */
  .hero--foto{flex-direction:column; gap:20px}
  .hero-photo{order:-1; max-width:none}
  .plate-grid{grid-template-columns:1fr; gap:46px}

  /* SZUFLADA FILTRÓW NIE MA TU JUŻ WŁASNYCH REGUŁ. Od Etapu 17 (D-45)
     szuflada była telefoniczna i cały jej styl siedział w tym bloku;
     historia przewijaka, który zjadał gesty, jest opisana w D-45.
     Etap 23 (D-54) dał tę samą szufladę pulpitowi i reguły przeszły
     do części wspólnej arkusza — sekcja „filtry w szufladzie" wyżej.
     Tu zostają wyłącznie telefoniczne stopnie pisma. */
  .ix{font-size:15px}
  .index-row-era .ix{font-size:14px}
}

/* Wybrany filtr przy ZAMKNIĘTEJ szufladzie: bez tego dałoby się odfiltrować
   kolekcję, zamknąć szufladę i zapomnieć, dlaczego kart jest mniej.
   Nazwa działu i lat nie mieści się w pasku, więc sygnałem jest sam
   przycisk „Filtry" — w barwie patyny, tak jak zaznaczony filtr. */
body:has(.ix[data-cat].is-on:not([data-cat="*"])) .ix-drawer > summary,
body:has(.ix[data-era].is-on:not([data-era="*"])) .ix-drawer > summary{
  color:var(--pat); border-color:var(--pat-soft);
}

/* ---------- strony fotografów (Etap 19, D-48) ----------

   Strona fotografa ma cztery warstwy z czterech różnych źródeł i każda
   musi być rozpoznawalna: liczby policzone, fakty wycięte z kart,
   ustalenia właściciela ze źródłami i życiorys, którego jeszcze nie ma.
   Stąd `.brak` — zdanie o braku życiorysu nie może wyglądać jak treść. */

.brak{color:var(--ink-faint); font-style:italic}

.fg-blok{max-width:1320px; margin:0 auto; padding:0 32px 34px}
.fg-blok h2{
  font-family:"Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  font-weight:500; font-size:11px; letter-spacing:.16em; text-transform:uppercase;
  color:var(--ink-faint); padding-bottom:11px; margin:26px 0 18px;
  border-bottom:1px solid var(--line-soft);
}
.fg-tresc{max-width:70ch}
.fg-tresc p{margin:0 0 12px; color:var(--ink-soft)}
/* podnagłówki życiorysu (Etap 31): Jak pracował / Co po nim zostało /
   Wystawy i publikacje / Gdzie szukać dalej / Źródła */
.fg-tresc h3{
  font-family:"Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  font-weight:600; font-size:13.5px; letter-spacing:.02em;
  color:var(--ink); margin:22px 0 8px;
}
.fg-tresc h3:first-child{margin-top:0}
.fg-tresc .fg-zrodla{margin:0}
.fg-zrodla{
  font-family:"Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size:12.5px; color:var(--ink-faint);
}
.fg-nota{
  max-width:70ch; margin:0 0 18px;
  font-family:"Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size:12.5px; line-height:1.7; color:var(--ink-faint);
}

/* fakty z kart: nazwa po lewej, treść po prawej, na telefonie jedno pod drugim */
.fg-fakty{
  display:grid; grid-template-columns:minmax(150px, 210px) 1fr;
  gap:9px 26px; margin:0; max-width:96ch;
}
.fg-fakty dt{
  font-family:"Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size:11.5px; letter-spacing:.06em; text-transform:uppercase;
  color:var(--ink-faint); padding-top:3px;
}
.fg-fakty dd{margin:0; color:var(--ink)}

/* znak zakładu — CAŁE rewersy, nigdy wycinek (WYMAGANIA 21, Z-39) */
.fg-znaki{
  display:grid; grid-template-columns:repeat(auto-fill, minmax(190px, 1fr));
  gap:22px;
}
.fg-znaki figure{margin:0}
.fg-znaki img{
  width:100%; height:auto; display:block;
  background:var(--mat); padding:6px;
  outline:1px solid var(--mat-edge); box-shadow:var(--shadow-card);
}
.fg-znaki figcaption{
  margin-top:7px;
  font-family:"Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size:11px; letter-spacing:.05em; color:var(--ink-faint);
}

/* spis kart */
.fg-karty{list-style:none; margin:0; padding:0; max-width:96ch}
.fg-karty li{border-bottom:1px solid var(--line-soft)}
.fg-karty a, .fg-karty li.fg-bez{
  display:flex; align-items:baseline; gap:8px 20px; flex-wrap:wrap;
  padding:11px 4px; text-decoration:none; color:inherit;
  transition:background .18s ease;
}
.fg-karty a:hover{background:rgba(47,97,82,.055); color:var(--pat)}
.fg-syg{
  font-family:"Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size:11.5px; letter-spacing:.05em; color:var(--ink-faint);
  flex:0 0 96px; font-variant-numeric:tabular-nums;
}
.fg-tyt{flex:1 1 260px; min-width:0; font-size:16.5px; line-height:1.35}
.fg-mia{
  font-family:"Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size:11.5px; color:var(--ink-faint); flex:0 0 auto;
}
.fg-bez .fg-tyt{color:var(--ink-faint); font-style:italic; font-size:15px}

/* odsyłacz przy nazwisku na karcie kolekcji */
.pc-autor{color:inherit; text-decoration:none; border-bottom:1px solid var(--pat-dim)}
.pc-autor:hover{color:var(--pat); border-bottom-color:var(--pat-soft)}

@media (max-width:720px){
  .fg-blok{padding-left:20px; padding-right:20px}
  .fg-fakty{grid-template-columns:1fr; gap:2px 0}
  .fg-fakty dd{margin-bottom:12px}
  .fg-znaki{grid-template-columns:repeat(auto-fill, minmax(150px, 1fr)); gap:16px}
  .fg-syg{flex-basis:100%}
}
