/* ============================================================
   Components. Everything inherits from tokens.css variables —
   rebranding an app should rarely require touching this file.
   ============================================================ */

.wrap { max-width: var(--maxw); margin: 0 auto; padding: 0 20px; }
/* anchor targets land below the sticky header */
main [id] { scroll-margin-top: 74px; }

/* --------- header --------- */
.site-header {
  position: sticky; top: 0; z-index: 50;
  background: var(--panel-2); backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--line);
}
.site-header .wrap {
  display: flex; align-items: center; gap: 18px; height: 60px;
}
.logo {
  display: inline-flex; align-items: center; gap: 9px;
  font-family: var(--f-display); font-weight: 800; font-size: 20px;
  color: var(--chalk); letter-spacing: -.02em;
  transition: transform .15s;
}
.logo:hover { transform: translateY(-1px); }
.logo em { color: var(--accent-deep); font-style: normal; }
/* icon mark next to the wordmark (favicon.svg's sibling). Default: initial on
   the brand gradient; per-app replace the letter with a simple geometric SVG. */
.logo-mark {
  width: 26px; height: 26px; border-radius: 7px; flex: none;
  background: var(--grad); color: #fff;
  display: grid; place-items: center;
  font-size: 14px; font-weight: 800; letter-spacing: 0;
}
.logo-mark svg { width: 16px; height: 16px; }
/* nav centered, standout CTA pinned right (reference: boiska header) */
.site-nav { flex: 1; display: flex; gap: 4px; justify-content: center; }
.site-nav a {
  padding: 8px 12px; border-radius: var(--r-sm); font-size: 14px;
  font-weight: 500; color: var(--dim); white-space: nowrap;
}
.site-nav a:hover { background: var(--accent-soft); color: var(--accent-deep); }
.nav-cta { padding: 8px 18px; font-size: 13.5px; border-radius: 999px; flex: none; white-space: nowrap; }
/* Progi liczone dla 6 pozycji w NAJDŁUŻSZYM języku (niemiecki) + przełącznik języka.
   CTA duplikuje pierwszą pozycję nawigacji, więc znika pierwsze. Selektor
   `.site-header .nav-cta` celowo silniejszy niż `.btn` niżej w pliku — samo
   `.nav-cta` przegrywało z `.btn { display: inline-block }` i CTA nie znikało nigdy. */
@media (max-width: 1080px) { .site-header .nav-cta { display: none; } }
@media (max-width: 1000px) { .site-nav a { padding: 8px 8px; font-size: 13px; } }
@media (max-width: 820px) { .site-nav { display: none; } .site-header .wrap { justify-content: space-between; } }

/* --------- hero: FULL-VIEWPORT first paint (one scene on screen) ---------
   copy left, interactive mini-map right, scroll hint at the bottom.
   FULL-BLEED: tło i struktura idą na całą szerokość okna, treść zostaje
   wyśrodkowana do --maxw (`.hero-grid.wrap`). Hero zamknięte w `.wrap`
   ucinało strukturę po bokach — na wąskim ekranie ma ją CROPOWAĆ, nie kadrować
   do kolumny tekstu. */
.hero {
  min-height: calc(100vh - 60px);
  display: flex; align-items: center;
  padding: 40px 0 110px; position: relative;
  max-width: none; width: 100%;
  overflow: hidden;              /* crop struktury zamiast rozpychania strony */
}
.hero > .hero-grid { width: 100%; }
.hero::before {
  content: ''; position: absolute; inset: -60px -40vw 0;
  background: var(--halo); pointer-events: none; z-index: -1;
}
/* --------- SLOT: tematyczna struktura w tle hero (docs/10) ---------
   Domyślnie generyczny plan w perspektywie. Każda apka podmienia SVG na kształt
   swojej encji. Musi być widoczna — patrz komentarz w index.html. */
/* Kadr liczony na WYSOKOŚĆ SVG (stała proporcja), nie na wysokość kontenera:
   rozciąganie szerokiego kształtu na wysokie pudło (albo `slice`) wycina środek
   i zbliża obraz. Przycięcie przy wąskim ekranie robi `overflow: hidden` .hero. */
/* CAŁA struktura w kadrze, wyśrodkowana, z perspektywą i przekrzywieniem.
   Szerokość dobrana tak, by bounding box po rotateZ mieścił się w oknie —
   `overflow: hidden` na .hero nic wtedy nie ucina. Bez maski kadrującej:
   czytelność treści bierze się z krycia, nie z zasłaniania grafiki. */
/* Rozmiar ograniczony matematyką kadru: po obrotach bounding box ≈ 1,05·W,
   więc przy W = 94% okna grafika dochodzi niemal do krawędzi i nic nie zostaje
   ucięte. Mniejszy rotateX = mniej spłaszczenia i lepsze wypełnienie hero. */
.hero-art {
  position: absolute; z-index: 0; pointer-events: none;
  top: 50%; left: 50%; width: min(2100px, 96%); height: auto;
  transform: translate(-50%, -50%);
  perspective: 2200px;
  /* Krycie na CAŁYM kontenerze, nie tylko na liniach: wygasza wszystkie
     elementy grafiki jednym mnożnikiem, więc proporcje między nimi zostają,
     a tekst nad nią czyta się bez wysiłku. */
  opacity: .5;
}
.hero-art svg {
  width: 100%; height: auto; display: block;
  transform: rotateX(36deg) rotateZ(-6deg);
  transform-origin: 50% 50%;
}
/* Im większa grafika, tym więcej jej trafia pod tekst — krycie idzie wtedy
   w dół, nie w górę. Widoczna, ale nie konkuruje z treścią. */
.art-grid { fill: none; stroke: var(--accent); stroke-width: 3; opacity: .18; }
.art-marks { fill: var(--accent-2); opacity: .16; }
@media (max-width: 880px) {
  .hero-art { width: 140%; top: 58%; }
  .art-grid { opacity: .13; }
}
/* treść nad strukturą tła */
.hero > .hero-grid, .hero > .scroll-hint { position: relative; z-index: 1; }

/* dot-grid texture over the hero, fading out downwards — visibly there */
.hero::after {
  content: ''; position: absolute; inset: 0 -40vw; z-index: -1; pointer-events: none;
  background-image: radial-gradient(var(--accent-soft) 1.6px, transparent 2.1px);
  background-size: 21px 21px;
  -webkit-mask-image: linear-gradient(180deg, #000 10%, transparent 85%);
  mask-image: linear-gradient(180deg, #000 10%, transparent 85%);
}
/* organic hero/content boundary: full-bleed wave filling the next band color */
.hero-wave {
  position: absolute; bottom: -1px; left: 50%; transform: translateX(-50%);
  width: 100vw; line-height: 0; pointer-events: none;
}
.hero-wave svg { width: 100%; height: 58px; display: block; }
.scroll-hint {
  position: absolute; bottom: 78px; left: 50%; transform: translateX(-50%);
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  font-family: var(--f-mono); font-size: 11px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--faint);
}
.scroll-hint::after { content: '↓'; font-size: 15px; animation: bob 1.7s ease-in-out infinite; }
@keyframes bob { 50% { transform: translateY(5px); } }
@media (max-height: 620px), (max-width: 880px) {
  .hero { min-height: 0; padding-bottom: 84px; }
  .scroll-hint { display: none; }
}
@media (prefers-reduced-motion: reduce) { .scroll-hint::after { animation: none; } }
.hero-grid {
  display: grid; grid-template-columns: 1.05fr .95fr; gap: 44px; align-items: center;
}
@media (max-width: 880px) { .hero-grid { grid-template-columns: 1fr; gap: 28px; } }
.hero h1 {
  font-family: var(--f-display); font-weight: 800; color: var(--chalk);
  font-size: clamp(30px, 4.5vw, 50px); line-height: 1.12; letter-spacing: -.025em;
  max-width: 18ch;
}
.hero h1 em {
  font-style: normal;
  background: var(--grad); -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: var(--accent-deep);
}
.hero .lead { margin: 18px 0 0; max-width: 56ch; color: var(--dim); font-size: 17px; }
/* stat row: big numbers + small-caps labels, hairline dividers (ref: boiska) */
.hero-stats { display: flex; margin-top: 28px; flex-wrap: wrap; row-gap: 14px; }
.hero-stats > div {
  padding: 0 26px 0 0; margin-right: 26px; border-right: 1px solid var(--line);
  font-family: var(--f-mono); font-size: 11px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--faint);
}
.hero-stats > div:last-child { border-right: 0; margin-right: 0; padding-right: 0; }
.hero-stats b {
  display: block; font-family: var(--f-display); font-weight: 800;
  font-size: 28px; letter-spacing: -.02em; color: var(--chalk); margin-bottom: 2px;
}
.hero-stats > div:nth-child(2n) b { color: var(--accent-deep); }

/* eyebrow — numbered section label ("01 — baza") */
.eyebrow {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--f-mono); font-size: 12px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--accent-deep); margin-bottom: 14px;
}
.eyebrow::before { content: ''; width: 22px; height: 2px; background: var(--accent); }
/* in the hero it becomes a live badge pill with a pulsing dot */
.hero .eyebrow {
  border: 1px solid var(--line); background: var(--panel-2);
  border-radius: 999px; padding: 7px 14px 7px 12px; margin-bottom: 20px;
}
.hero .eyebrow::before {
  width: 7px; height: 7px; border-radius: 50%;
  animation: dotpulse 2.2s ease-in-out infinite;
}
@keyframes dotpulse { 50% { opacity: .35; } }
@media (prefers-reduced-motion: reduce) { .hero .eyebrow::before, .pl-dot { animation: none !important; } }

/* hero mini-map (SVG Poland + record dots, app.js renders) */
.hero-map { position: relative; }
/* soft glow pooling behind the country shape */
.hero-map::before {
  content: ''; position: absolute; inset: 6% 2%; z-index: -1; border-radius: 50%;
  background: radial-gradient(closest-side, var(--accent-soft), var(--accent-2-soft) 55%, transparent 75%);
}
.hero-map svg { width: 100%; height: auto; display: block; }

/* choropleth: 5 discrete density steps built from one accent, so any brand
   palette works without touching this file */
.pl-reg {
  fill: var(--bg-2); stroke: var(--bg); stroke-width: 1.6; stroke-linejoin: round;
  transition: fill .15s, transform .15s; transform-origin: center;
}
.pl-reg[data-step="1"] { fill: color-mix(in srgb, var(--accent) 14%, var(--bg-2)); }
.pl-reg[data-step="2"] { fill: color-mix(in srgb, var(--accent) 30%, var(--bg-2)); }
.pl-reg[data-step="3"] { fill: color-mix(in srgb, var(--accent) 48%, var(--bg-2)); }
.pl-reg[data-step="4"] { fill: color-mix(in srgb, var(--accent) 68%, var(--bg-2)); }
.pl-reg[data-step="5"] { fill: color-mix(in srgb, var(--accent) 88%, var(--bg-2)); }
.pl-reg[data-region] { cursor: pointer; }
/* obrys lądu po przycięciu clipPath — domyka kształt kraju */
.pl-coast { fill: none; stroke: var(--line); stroke-width: 1.4; }
.pl-reg[data-region]:hover, .pl-reg[data-region]:focus-visible {
  fill: var(--accent-2); outline: none;
}
/* density legend */
.pl-legend {
  display: flex; align-items: center; gap: 5px; margin-top: 12px;
  font-family: var(--f-mono); font-size: 10.5px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--faint);
}
.pl-legend i { width: 22px; height: 8px; border-radius: 2px; }
.pl-legend i[data-step="1"] { background: color-mix(in srgb, var(--accent) 14%, var(--bg-2)); }
.pl-legend i[data-step="2"] { background: color-mix(in srgb, var(--accent) 30%, var(--bg-2)); }
.pl-legend i[data-step="3"] { background: color-mix(in srgb, var(--accent) 48%, var(--bg-2)); }
.pl-legend i[data-step="4"] { background: color-mix(in srgb, var(--accent) 68%, var(--bg-2)); }
.pl-legend i[data-step="5"] { background: color-mix(in srgb, var(--accent) 88%, var(--bg-2)); }
.pl-open { margin-top: 14px; padding: 9px 18px; font-size: 14px; }

/* natywny "×" czyszczący pole musi mieć łapkę — bez tego wygląda na dekorację */
.searchbar input::-webkit-search-cancel-button { cursor: pointer; }
.searchbar input::-webkit-search-decoration { cursor: pointer; }

/* --------- autocomplete pod polem szukania ---------
   Odpowiedź musi być tam, gdzie użytkownik patrzy — nie 800 px niżej. */
.searchwrap { position: relative; z-index: 20; max-width: 640px; }
.q-sug {
  position: absolute; left: 0; right: 0; top: calc(100% + 8px);
  background: var(--popup); border: 1px solid var(--line);
  border-radius: var(--r-md); box-shadow: 0 16px 40px rgba(11, 20, 28, .16);
  overflow: hidden;
}
.q-sug ul { list-style: none; }
.q-sug li + li { border-top: 1px solid var(--line); }
.q-sug a { display: flex; align-items: center; gap: 11px; padding: 11px 14px; }
.q-sug li.on a, .q-sug a:hover { background: var(--accent-soft); }
.sug-dot { width: 9px; height: 9px; border-radius: 50%; flex: none; }
.q-sug b { display: block; font-size: 14px; color: var(--chalk); font-weight: 600; }
.q-sug small { display: block; font-size: 12px; color: var(--faint); }
.q-sug-all {
  display: block; width: 100%; padding: 11px 14px; cursor: pointer;
  background: var(--bg-2); border: 0; border-top: 1px solid var(--line);
  font-size: 13px; font-weight: 600; color: var(--accent-deep); text-align: left;
  transition: background .13s;
}
.q-sug-all:hover { background: var(--accent-soft); }
.q-sug-empty { padding: 13px 14px; font-size: 13.5px; color: var(--dim); }

/* licznik pod polem: sygnał dla filtrów/kafli/mapy (bez wpisanej frazy) */
.q-hint { margin-top: 10px; font-size: 13.5px; }
.q-hint a {
  display: inline-block; color: var(--accent-deep); font-weight: 600;
  border-bottom: 1px solid var(--accent-soft); transition: transform .13s;
}
.q-hint a:hover { transform: translateX(2px); border-bottom-color: var(--accent); }
.q-hint b { font-family: var(--f-mono); }
.q-hint-empty { color: var(--faint); }

/* poziome słupki danych (kafle/panele metryk) — fallback tła jest KONIECZNY:
   bez niego słupki bez inline `background` są niewidoczne */
.bar-track { height: 12px; border-radius: 999px; background: var(--bg-2); overflow: hidden; }
.bar-track i {
  display: block; height: 100%; border-radius: 999px; min-width: 6px;
  background: var(--accent);
  animation: bargrow .9s cubic-bezier(.2, .8, .2, 1) both;
}
@keyframes bargrow { from { transform: scaleX(0); transform-origin: left; } }
@media (prefers-reduced-motion: reduce) { .bar-track i { animation: none; } }

/* top-cities strip (lives in the hero, under the searchbar) */
.city-strip { display: flex; flex-wrap: wrap; gap: 8px; margin: 16px 0 4px; }
.city-strip .chip b { color: var(--accent-deep); font-family: var(--f-mono); font-weight: 500; margin-left: 2px; }

/* --------- search + filters --------- */
.searchbar {
  display: flex; gap: 10px; max-width: 640px; margin: 26px 0 0;
  background: var(--panel-2); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: 8px; box-shadow: var(--shadow);
}
.searchbar:focus-within {
  border-color: var(--accent);
  box-shadow: 0 8px 30px rgba(11, 20, 28, .07), 0 0 0 4px var(--accent-soft);
}
.searchbar input {
  flex: 1; border: 0; background: transparent; outline: none;
  padding: 10px 14px; font-size: 16px;
}
.searchbar button {
  border: 0; background: var(--grad-cta); color: var(--accent-ink);
  border-radius: var(--r-md); padding: 10px 22px; font-weight: 600;
  cursor: pointer; transition: filter .15s, transform .1s;
}
.searchbar button:hover { filter: brightness(1.1); transform: translateY(-1px); }

.filters {
  display: flex; flex-wrap: wrap; gap: 14px 28px; justify-content: center;
  margin: 22px auto 0; max-width: 920px;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: 14px 22px;
}
/* on home the filter panel FLOATS across the hero/results boundary
   (depth instead of a divider line) */
/* the float crosses the WAVE only — deeper overlap reads as a layout bug */
#wyniki .filters {
  position: relative; z-index: 5; margin-top: -46px;
  background: var(--panel-2); box-shadow: var(--shadow);
}
@media (max-width: 880px) { #wyniki .filters { margin-top: -30px; } }
.fgroup { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.flabel {
  font-size: 11px; font-weight: 600; letter-spacing: .08em;
  text-transform: uppercase; color: var(--faint); margin-right: 2px;
}
.chip {
  border: 1px solid var(--line); background: var(--panel-2);
  border-radius: 999px; padding: 7px 15px; font-size: 13.5px;
  font-weight: 500; color: var(--dim); cursor: pointer;
  transition: all .15s;
}
.chip:hover {
  border-color: var(--accent); color: var(--accent-deep);
  background: var(--accent-soft); transform: translateY(-1px);
}
.chip.on {
  background: var(--accent); border-color: var(--accent);
  color: var(--accent-ink); box-shadow: 0 3px 12px var(--accent-soft);
}
.filters select {
  appearance: none; -webkit-appearance: none;
  border: 1px solid var(--line); background: var(--panel-2);
  border-radius: 999px; padding: 7px 36px 7px 14px; font-size: 13.5px;
  color: var(--dim); cursor: pointer; outline: none; transition: all .15s;
  /* custom chevron with breathing room from the right edge */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23697580' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 14px center;
}
.filters select:hover { border-color: var(--accent); color: var(--accent-deep); background-color: var(--accent-soft); transform: translateY(-1px); }
/* the popup list itself — explicit colors so it never falls back to UA theme */
.filters select option { background: var(--popup); color: var(--ink); }

/* --------- results grid --------- */
.results { padding: 36px 0 60px; }
.results-meta {
  display: flex; align-items: baseline; gap: 12px; margin-bottom: 18px;
  padding-bottom: 12px; border-bottom: 1px solid var(--line);
  color: var(--faint); font-size: 14px;
}
.results-meta b { color: var(--chalk); font-size: 16px; font-family: var(--f-display); }
.grid {
  display: grid; gap: 18px;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
}
.card {
  position: relative; overflow: hidden;
  background: var(--panel-2); border: 1px solid var(--line);
  border-radius: var(--r-md); padding: 20px 20px 20px 24px;
  display: flex; flex-direction: column; gap: 8px;
  transition: transform .15s, box-shadow .15s, border-color .15s;
}
.card .cstripe { position: absolute; left: 0; top: 0; bottom: 0; width: 4px; opacity: .85; }
.card::after {
  content: '→'; position: absolute; right: 16px; top: 16px;
  color: var(--accent-deep); opacity: 0; transform: translateX(-6px);
  transition: opacity .15s, transform .15s; font-weight: 600;
}
.card:hover {
  transform: translateY(-2px); box-shadow: var(--shadow);
  border-color: var(--accent);
}
.card:hover::after { opacity: 1; transform: none; }
.card h3 {
  font-family: var(--f-display); font-size: 17px; font-weight: 700;
  color: var(--chalk); line-height: 1.3;
}
.card .meta { font-size: 13.5px; color: var(--dim); }
.card .badges {
  display: flex; flex-wrap: wrap; gap: 6px; margin-top: auto;
  padding-top: 12px; border-top: 1px solid var(--line);
}
/* ikonka lokalizacji przy mieście — meta bez niej to szary tekst bez zaczepienia */
.ico-pin {
  width: 13px; height: 13px; flex: none; display: inline-block;
  vertical-align: -2px; margin-right: 4px;
  fill: none; stroke: var(--accent); stroke-width: 2.1;
  stroke-linecap: round; stroke-linejoin: round;
}
/* skrót opisu — karta bez treści jest pustym prostokątem */
.card-desc {
  font-size: 13.5px; line-height: 1.5; color: var(--dim); margin-top: 4px;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
  overflow: hidden;
}
/* narzędzia karty (porównywarka, dystans) w narożniku — bez własnego wiersza */
.card-tools {
  position: absolute; top: 13px; right: 13px; z-index: 2;
  display: flex; flex-direction: column; align-items: flex-end; gap: 5px;
}
.card:has(.card-tools) h3 { padding-right: 94px; }
/* strzałka hover siedzi w prawym DOLNYM narożniku — w górnym bywają kontrolki
   (porównywarka, dystans) i oba elementy nachodziłyby na siebie */
.card::after { top: auto; bottom: 17px; right: 17px; }
.card .badges { padding-right: 28px; }
.badge {
  font-size: 11.5px; font-weight: 600; letter-spacing: .02em;
  background: var(--accent-soft); color: var(--accent-deep);
  border-radius: 6px; padding: 3px 8px;
}
.badge.muted { background: var(--bg-2); color: var(--faint); }

.more-row { text-align: center; margin-top: 28px; }
.btn {
  display: inline-block; border: 1px solid var(--line); cursor: pointer;
  background: var(--panel-2); color: var(--ink); font-weight: 600;
  border-radius: var(--r-md); padding: 11px 26px; transition: all .15s;
}
.btn:hover { border-color: var(--accent); color: var(--accent-deep); background: var(--accent-soft); transform: translateY(-1px); }
.btn.primary { background: var(--grad-cta); border-color: transparent; color: var(--accent-ink); }
.btn.primary:hover { filter: brightness(1.1); color: var(--accent-ink); background: var(--grad-cta); }

.empty { text-align: center; color: var(--faint); padding: 50px 0; }

/* --------- content sections (SEO copy on home) --------- */
.section { padding: 44px 0; border-top: 1px solid var(--line); }

/* --------- full-bleed background bands ---------
   The page must NOT be one flat background top-to-bottom — sections sit on
   alternating bands (reference: boiskawpolsce). Wrap a section:
   <section class="band alt"><div class="wrap section">…</div></section>
   Variants: (none)=page bg · alt=--bg-2 · soft=accent tint · dark=inverted. */
.band { border-top: 1px solid var(--line); }
.band.flush { border-top: 0; } /* junction handled by a wave/overlap instead */
.band .section { border-top: 0; padding: 52px 0; }
.band.alt { background: var(--bg-2); }
.band.soft { background: linear-gradient(135deg, var(--accent-soft), var(--accent-2-soft)); }
/* dark band = local token flip; every component inside inherits automatically.
   .hero.dark reuses the same flip = full-bleed dark hero variant (boiska-style) */
.band.dark, .hero.dark {
  background: #101a2b;
  --ink: #e8edf4; --chalk: #ffffff;
  --dim: rgba(232, 237, 244, .78); --faint: rgba(232, 237, 244, .62);
  --line: rgba(255, 255, 255, .14);
  --panel: rgba(255, 255, 255, .05); --panel-2: rgba(255, 255, 255, .07);
  --accent-deep: var(--accent); --accent-2-deep: var(--accent-2);
  --accent-soft: rgba(255, 255, 255, .09); --accent-2-soft: rgba(255, 255, 255, .07);
}
.band.dark .ghost { opacity: .4; }
.hero.dark { --popup: #182338; }
.hero.dark::before { opacity: 1.6; } /* halo świeci mocniej na ciemnym */

/* --------- VARIANT HOOKS — każda apka wybiera inną kombinację (docs/07) ---- */
/* hero texture: kropki (default) / ukośne linie / brak */
.hero.tex-lines::after {
  background-image: repeating-linear-gradient(135deg, var(--accent-soft) 0 2px, transparent 2px 16px);
  background-size: auto;
}
.hero.tex-none::after { display: none; }
/* hero centered: copy na środku, mapa pod spodem węższa */
.hero.v-center .hero-grid { grid-template-columns: 1fr; text-align: center; }
.hero.v-center .hero-copy h1, .hero.v-center .lead { margin-left: auto; margin-right: auto; }
.hero.v-center .searchbar, .hero.v-center .city-strip, .hero.v-center .hero-stats { justify-content: center; margin-left: auto; margin-right: auto; }
.hero.v-center .hero-map { max-width: 560px; margin: 0 auto; }
/* karty: pasek typu na górze zamiast z lewej */
.v-topbar .card { padding-left: 20px; }
.v-topbar .cstripe { left: 0; right: 0; top: 0; bottom: auto; width: auto; height: 4px; }

/* outro band — closing headline + CTA pair */
.outro { text-align: center; }
.outro h2 { font-family: var(--f-display); font-size: clamp(24px, 3.4vw, 36px); color: var(--chalk); letter-spacing: -.02em; }
.outro p { color: var(--dim); max-width: 56ch; margin: 12px auto 22px; }
.outro .row { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; }
.section h2 {
  font-family: var(--f-display); font-weight: 700; color: var(--chalk);
  font-size: clamp(22px, 3vw, 30px); letter-spacing: -.02em; margin-bottom: 14px;
}
.section p { color: var(--dim); max-width: 72ch; margin-bottom: 12px; }
.section ul { color: var(--dim); max-width: 72ch; padding-left: 22px; }
.section li { margin-bottom: 6px; }

.section h2 em {
  font-style: normal;
  background: var(--grad); -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: var(--accent-deep);
}

/* --- pattern: feature rows + item-page mockup (section "karta rekordu") --- */
.split {
  display: grid; grid-template-columns: 1.1fr .9fr; gap: 40px;
  align-items: center; margin-top: 10px;
}
@media (max-width: 860px) { .split { grid-template-columns: 1fr; } }
.feature-rows { list-style: none; counter-reset: fr; }
.feature-rows li {
  counter-increment: fr; position: relative;
  /* constant padding — the hover tint must not hug the number badge */
  padding: 14px 14px 14px 64px; border-bottom: 1px solid var(--line);
  transition: background .15s, transform .15s;
}
.feature-rows li:last-child { border-bottom: 0; }
.feature-rows li::before {
  content: counter(fr, decimal-leading-zero); position: absolute; left: 14px; top: 16px;
  font-family: var(--f-mono); font-size: 12px; font-weight: 600;
  color: var(--accent-deep); background: var(--accent-soft);
  border-radius: 6px; padding: 3px 7px;
}
.feature-rows li:nth-child(2n)::before { color: var(--accent-2-deep); background: var(--accent-2-soft); }
.feature-rows li:hover { background: var(--accent-soft); border-radius: var(--r-sm); transform: translateX(3px); }
.feature-rows b { display: block; color: var(--chalk); font-size: 15.5px; }
.feature-rows span { color: var(--dim); font-size: 14px; }

.mock-card {
  background: var(--panel-2); border: 1px solid var(--line);
  border-radius: var(--r-md); padding: 22px; box-shadow: var(--shadow);
  transition: transform .2s;
}
.mock-card:hover { transform: translateY(-2px); }
.mock-head b { font-family: var(--f-display); font-size: 19px; color: var(--chalk); display: block; }
.mock-head > span { font-size: 13px; color: var(--dim); }
.mock-head .badges { display: flex; gap: 6px; flex-wrap: wrap; margin: 10px 0 14px; }
.mock-row {
  display: flex; justify-content: space-between; gap: 12px;
  padding: 9px 0; border-top: 1px solid var(--line); font-size: 13.5px;
}
.mock-row span { color: var(--faint); }
.mock-row b { color: var(--ink); font-weight: 600; }
.mock-stars { margin-top: 12px; color: var(--accent); font-size: 17px; letter-spacing: 2px; }
.mock-stars i { font-style: normal; color: var(--dim); font-size: 12.5px; letter-spacing: 0; margin-left: 6px; }

/* --- pattern: numbered steps joined by a connector rail --- */
.steps {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 26px;
  margin-top: 22px; counter-reset: st;
}
@media (max-width: 720px) { .steps { grid-template-columns: 1fr; } }
.step { counter-increment: st; position: relative; padding-top: 44px; }
/* the numeric coin */
.step::before {
  content: counter(st); position: absolute; top: 0; left: 0;
  width: 30px; height: 30px; border-radius: 50%;
  display: grid; place-items: center;
  font-family: var(--f-mono); font-size: 13px; font-weight: 600;
  color: var(--accent-ink); background: var(--accent);
}
/* rail linking the coins (desktop only) */
.step::after {
  content: ''; position: absolute; top: 14px; left: 40px; right: -26px;
  height: 2px; background: var(--line);
}
/* ostatni krok domyka szynę: biegnie do krawędzi i kończy się kropką akcentu (meta),
   zamiast urywać rząd na ostatniej monecie */
.step:last-child::after {
  right: 0; top: 10px; height: 10px;
  background:
    radial-gradient(circle at calc(100% - 5px) 50%, var(--accent) 0 4px, transparent 4.5px),
    linear-gradient(var(--line), var(--line)) left center / calc(100% - 10px) 2px no-repeat;
}
@media (max-width: 720px) { .step::after { display: none; } }
.step b { display: block; font-family: var(--f-display); font-size: 18px; color: var(--chalk); margin-bottom: 6px; }
.step p { color: var(--dim); font-size: 14.5px; }

/* --- pattern: full-color CTA band before the footer --- */
.cta-band {
  display: flex; align-items: center; justify-content: space-between; gap: 24px;
  flex-wrap: wrap; margin: 30px auto 50px;
  background: var(--grad); color: var(--accent-ink);
  border-radius: var(--r-lg); padding: 34px 36px;
}
/* explicit colors — .cta-band can sit inside a .section, whose h2/p colors
   (dark ink) would otherwise leak onto the gradient */
.cta-band h2 { font-family: var(--f-display); font-size: clamp(20px, 2.6vw, 28px); letter-spacing: -.02em; color: var(--accent-ink); }
.cta-band p { margin-top: 6px; color: var(--accent-ink); opacity: .88; max-width: 56ch; }
.btn.ghost-inverse {
  background: rgba(255, 255, 255, .16); border: 1px solid rgba(255, 255, 255, .45);
  color: var(--accent-ink); backdrop-filter: blur(4px);
}
.btn.ghost-inverse:hover { background: rgba(255, 255, 255, .28); color: var(--accent-ink); transform: translateY(-1px); }

.faq details {
  border: 1px solid var(--line); border-radius: var(--r-md);
  background: var(--panel-2); padding: 14px 18px; margin-bottom: 10px;
  transition: border-color .15s;
}
.faq details:hover, .faq details[open] { border-color: var(--accent); }
/* Otwarte pytanie NIE dostaje tintu akcentu: FAQ często leży na bandzie
   `soft`/`alt`, która sama jest tintem — tint na tincie daje brudne tło
   i psuje kontrast długiego tekstu. Czysta biel + akcentowa ramka. */
.faq details[open] { background: var(--popup); }
.faq details[open] p { color: var(--ink); }
.faq summary { font-weight: 600; cursor: pointer; color: var(--chalk); }
.faq summary:hover { color: var(--accent-deep); }
.faq details p { margin-top: 10px; }

/* --------- item (detail) page --------- */
.breadcrumb { padding: 18px 0 0; font-size: 13px; color: var(--faint); }
.breadcrumb a:hover { color: var(--accent-deep); }
.item-head { padding: 18px 0 8px; }
.item-head h1 {
  font-family: var(--f-display); font-weight: 800; color: var(--chalk);
  font-size: clamp(26px, 4vw, 40px); letter-spacing: -.02em; line-height: 1.15;
}
.item-head .sub { margin-top: 8px; color: var(--dim); font-size: 15px; }
.item-badges { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }

.item-layout {
  display: grid; grid-template-columns: 1fr 340px; gap: 24px; padding: 24px 0 60px;
}
@media (max-width: 860px) { .item-layout { grid-template-columns: 1fr; } }
/* no Supabase -> #community gets [hidden]; collapse the dead 340px column too */
.item-layout > aside:has(> #community[hidden]) { display: none; }
.item-layout:has(> aside > #community[hidden]) { grid-template-columns: 1fr; }

.panel {
  background: var(--panel-2); border: 1px solid var(--line);
  border-radius: var(--r-md); padding: 20px;
}
.panel + .panel { margin-top: 16px; }
.panel h2 {
  font-family: var(--f-display); font-size: 18px; font-weight: 700;
  color: var(--chalk); margin-bottom: 12px;
}
.facts { width: 100%; border-collapse: collapse; font-size: 14.5px; }
.facts td { padding: 9px 0; border-bottom: 1px solid var(--line); }
.facts td:first-child { color: var(--faint); width: 45%; }
.facts tr:last-child td { border-bottom: 0; }

#map { height: 300px; border-radius: var(--r-sm); background: var(--bg-2); }
.map-note { font-size: 12.5px; color: var(--faint); margin-top: 8px; }
.map-note a:hover, .pin-pop a:hover { color: var(--accent); text-decoration: underline; }

/* community: rating + report */
.stars { display: flex; gap: 4px; font-size: 26px; cursor: pointer; user-select: none; }
.stars span { color: var(--line); transition: color .1s, transform .1s; }
.stars span:hover { color: var(--accent); transform: scale(1.15); }
.stars span.lit { color: var(--accent); }
.rating-avg { font-size: 13.5px; color: var(--dim); margin-top: 8px; }
.report-form textarea {
  width: 100%; min-height: 80px; border: 1px solid var(--line);
  border-radius: var(--r-sm); padding: 10px; background: var(--bg);
  outline: none; resize: vertical; font-size: 14px;
}
.report-form textarea:focus { border-color: var(--accent); }
.report-form .btn { margin-top: 10px; }
.form-note { font-size: 12.5px; color: var(--faint); margin-top: 8px; }

.related h2 { margin: 10px 0 14px; }

/* --------- footer --------- */
.site-footer {
  border-top: 1px solid var(--line); background: var(--bg-2);
  padding: 34px 0; margin-top: 20px; font-size: 13.5px; color: var(--faint);
}
.site-footer .wrap { display: flex; flex-wrap: wrap; gap: 18px; justify-content: space-between; }
.site-footer a { transition: color .12s, transform .12s; display: inline-block; }
.site-footer a:hover { color: var(--accent-deep); transform: translateX(2px); }
.site-footer nav { display: flex; gap: 16px; flex-wrap: wrap; }

/* --------- baner zgody: karta w lewym dolnym rogu, na telefonie pełna szerokość ---------
   Wąski pasek z tekstem 12,5 px był niezauważalny (uwaga 2026-10-08). Karta ma tytuł,
   jedno zdanie, link do polityki i dwa RÓWNORZĘDNE przyciski — odmowa tak samo łatwa
   jak zgoda. Solidne tło (--popup), bo karta leży na mapie i kolorowych bandach. */
.cookiebar {
  position: fixed; left: 20px; bottom: 20px; z-index: 1200;
  width: min(400px, calc(100vw - 40px));
  background: var(--popup); color: var(--ink);
  border: 1px solid var(--line); border-top: 4px solid var(--accent);
  border-radius: var(--r-lg); box-shadow: 0 18px 48px rgba(10, 16, 28, .22);
  padding: 20px 22px 18px; font-size: 14.5px; line-height: 1.55;
  animation: cookie-in .28s ease-out both;
}
.cookiebar-h { display: block; font-family: var(--f-display); font-size: 18px; color: var(--chalk); margin-bottom: 6px; }
.cookiebar p { margin: 0; color: var(--dim); }
.cookiebar a { color: var(--accent-deep); text-decoration: underline; font-weight: 600; white-space: nowrap; }
.cookiebar-row { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 16px; }
.cookiebar-row .btn { padding: 11px 14px; font-size: 14.5px; text-align: center; }
@keyframes cookie-in { from { opacity: 0; transform: translateY(12px); } }
@media (max-width: 520px) {
  .cookiebar { left: 12px; right: 12px; bottom: 12px; width: auto; }
}
@media (prefers-reduced-motion: reduce) { .cookiebar { animation: none; } }

/* --------- wejścia elementów (fx.js dokłada .in) ---------
   FAIL-SAFE: chowamy WYŁĄCZNIE pod `html.js-fx`, a tę klasę ustawia fx.js.
   Treść jest domyślnie widoczna, animacja jest opt-in. Bez tego wystarczyła
   awaria (albo brak) fx.js, żeby `opacity: 0` zjadło całą listę — realny błąd
   na /mapa 03.09. Nigdy nie zostawiaj treści czekającej na JS. */
.reveal { opacity: 1; transform: none; }
.js-fx .reveal { opacity: 0; transform: translateY(14px); transition: opacity .45s ease, transform .45s ease; }
.js-fx .reveal.in { opacity: 1; transform: none; }
/* kaskada TYLKO dla 6 pierwszych kart w siatce — dalej wszystko wchodzi razem,
   żeby szybki scroll na telefonie nigdy nie wyprzedził animacji */
.js-fx .grid > .reveal:nth-child(2) { transition-delay: 40ms; }
.js-fx .grid > .reveal:nth-child(3) { transition-delay: 80ms; }
.js-fx .grid > .reveal:nth-child(4) { transition-delay: 120ms; }
.js-fx .grid > .reveal:nth-child(5) { transition-delay: 160ms; }
.js-fx .grid > .reveal:nth-child(6) { transition-delay: 200ms; }
@media (prefers-reduced-motion: reduce) {
  .js-fx .reveal { opacity: 1; transform: none; transition: none; }
}

/* --------- tiles (type + voivodeship grids on home) --------- */
.tile-grid {
  display: grid; gap: 12px; margin-top: 18px;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
}
.tile {
  position: relative; overflow: hidden; text-align: left; cursor: pointer;
  background: var(--panel-2); border: 1px solid var(--line);
  border-radius: var(--r-md); padding: 16px 16px 18px;
  display: flex; flex-direction: column; gap: 2px;
  transition: transform .15s, border-color .15s, box-shadow .15s;
}
.tile:hover {
  transform: translateY(-2px); border-color: var(--accent);
  box-shadow: var(--shadow); background: var(--accent-soft);
}
.tile b {
  font-family: var(--f-display); font-weight: 800; font-size: 26px;
  color: var(--accent-deep); letter-spacing: -.02em;
}
#voiv-tiles .tile:nth-child(2n) b { color: var(--accent-2-deep); }
#voiv-tiles .tile:nth-child(2n):hover { border-color: var(--accent-2); background: var(--accent-2-soft); }
.tile span { font-size: 13px; color: var(--dim); }
.tile i { position: absolute; left: 0; top: 0; bottom: 0; width: 3px; }

/* --------- strona mapy (/mapa): jedna szyna + scena ---------
   Mobile-first: filtry -> mapa -> karty (kolejność DOM). Desktop od 981px
   przenosi .mapx-head i .mapx-list do lewej kolumny gridem, więc na wąskim
   ekranie nie trzeba nic przestawiać ani chować.

   NIE dodawaj drugiej szyny z listą po prawej. Trójpodział
   „filtry | mapa | lista" to układ, po którym rozpoznaje się serwisy
   konkurencji (docs/09-oryginalnosc.md), a na telefonie rozpada się na trzy
   niezależne ekrany. W szynie lecą TE SAME karty co na stronie głównej. */
.mapx { display: grid; }

.mapx-head {
  padding: 14px 16px 12px; background: var(--bg-2);
  border-bottom: 1px solid var(--line);
  display: flex; flex-direction: column; gap: 12px;
}
.mapx-find { position: relative; }
.mapx-find .ico-search {
  position: absolute; left: 12px; top: 50%; transform: translateY(-50%);
  width: 17px; height: 17px; color: var(--faint); pointer-events: none;
}
.mapx-find input {
  width: 100%; border: 1px solid var(--line); background: var(--panel-2);
  color: var(--ink); border-radius: var(--r-sm); outline: none;
  padding: 11px 12px 11px 38px; font: inherit; font-size: 14px;
}
.mapx-find input:focus-visible { border-color: var(--accent); box-shadow: 0 0 0 3px var(--halo); }
.mapx-find input::-webkit-search-cancel-button { cursor: pointer; }
.mapx-find input::-webkit-search-decoration { cursor: pointer; }
.mapx-geo { justify-content: center; }

/* filtry w szynie: grupy jedna pod drugą, chipy w grupie nadal poziomo */
.mapx-head .filters {
  background: none; border: 0; padding: 0; margin: 0; max-width: none;
  flex-direction: column; align-items: stretch; gap: 12px; justify-content: flex-start;
}
.mapx-head .fgroup { align-items: center; }
.mapx-head .flabel { width: 100%; }
.mapx-head .filters select { width: 100%; }

.mapx-legend { display: flex; flex-wrap: wrap; gap: 6px 14px; font-size: 12.5px; color: var(--dim); }
.mapx-legend span { display: inline-flex; align-items: center; gap: 7px; }
.mapx-legend i { width: 9px; height: 9px; border-radius: 50%; flex: none; }

.mapx-bar {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  padding-top: 10px; border-top: 1px solid var(--line);
}
.mapx-count { font-size: 13px; color: var(--dim); }
.mapx-count b { font-family: var(--f-display); font-size: 17px; color: var(--chalk); }
.mapx-reset {
  border: 0; background: none; cursor: pointer; padding: 2px 0; font: inherit;
  font-size: 12.5px; font-weight: 600; color: var(--accent-deep);
  border-bottom: 1px solid transparent;
}
.mapx-reset:hover { border-bottom-color: var(--accent); }
.mapx-reset:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 2px; }

.mapx-stage { background: var(--bg-2); }
#bigmap { height: 46vh; min-height: 300px; background: var(--bg-2); }

.mapx-list { padding: 14px 16px 30px; background: var(--bg); }
.mapx-items { list-style: none; display: flex; flex-direction: column; gap: 12px; }
.mapx-item { position: relative; }
.mapx-item.is-hit .card { border-color: var(--accent); box-shadow: 0 0 0 3px var(--halo); }
.mapx-empty { padding: 24px 4px; font-size: 13.5px; color: var(--dim); }
.mapx-foot { margin-top: 14px; }
.mapx-foot .btn { width: 100%; justify-content: center; }

@media (min-width: 981px) {
  .mapx {
    grid-template-columns: 384px 1fr; grid-template-rows: auto 1fr;
    height: calc(100vh - 60px);
  }
  .mapx-head { grid-column: 1; grid-row: 1; border-right: 1px solid var(--line); }
  .mapx-list {
    grid-column: 1; grid-row: 2; overflow-y: auto;
    border-right: 1px solid var(--line); overscroll-behavior: contain;
  }
  .mapx-stage { grid-column: 2; grid-row: 1 / span 2; }
  #bigmap { height: 100%; min-height: 0; }
}

/* pinezka podświetlona z szyny (hover/tab na karcie) i odwrotnie */
.pin-wrap .pin { transition: transform .12s ease; }
.pin-wrap.is-hot .pin { transform: scale(1.9); }
.leaflet-marker-icon.is-hot { z-index: 600 !important; }
.marker-cluster.is-hot { outline: 3px solid var(--accent); border-radius: 50%; }

/* leaflet marker pin (divIcon) */
.pin {
  display: block; width: 14px; height: 14px; border-radius: 50%;
  border: 2px solid #fff; box-shadow: 0 1px 4px rgba(0, 0, 0, .35);
}
.pin-pop b { font-family: var(--f-display); }
.pin-pop div { color: var(--dim); font-size: 12.5px; margin: 2px 0 6px; }
.pin-pop a { color: var(--accent-deep); font-weight: 600; font-size: 13px; }
/* podpis „Tu jesteś" przy punkcie lokalizacji na mapie w hero (archetyp D) */
.leaflet-tooltip.me-tip {
  background: var(--accent); color: var(--accent-ink); border: 0; border-radius: 999px;
  padding: 3px 10px; font-weight: 700; font-size: 12px; box-shadow: var(--shadow, 0 2px 8px rgba(0,0,0,.18));
}
.leaflet-tooltip-top.me-tip::before { border-top-color: var(--accent); }

/* --------- geolokalizacja w hero --------- */
.hero-actions { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 16px; }
.hero-actions .btn.on { background: var(--accent-2); border-color: var(--accent-2); color: #fff; }
.geo-note { margin-top: 9px; font-size: 12.5px; color: var(--accent-deep); }
.card-dist {
  font-family: var(--f-mono); font-size: 11px; font-weight: 600;
  color: var(--accent-deep); background: var(--accent-soft);
  border-radius: 999px; padding: 3px 8px;
}
#sort-note { color: var(--accent-deep); font-size: 13px; margin-left: 6px; }

/* --------- porównywarka: przycisk na karcie, tacka, modal z tabelą ---------
   Wzorzec "comparison surface" — to on odróżnia katalog od listy linków. */
.cmp-btn {
  display: inline-flex; align-items: center; gap: 7px;
  border: 1px solid var(--line); background: var(--bg);
  border-radius: 999px; padding: 5px 12px 5px 8px;
  font-size: 12px; font-weight: 600; color: var(--faint); cursor: pointer;
  transition: all .15s;
}
.cmp-btn i {
  width: 13px; height: 13px; border: 1.5px solid var(--line);
  border-radius: 4px; flex: none; transition: all .15s;
}
.cmp-btn:hover { border-color: var(--accent); color: var(--accent-deep); transform: translateY(-1px); }
.cmp-btn:hover i { border-color: var(--accent); }
.cmp-btn.on { border-color: var(--accent); background: var(--accent-soft); color: var(--accent-deep); }
.cmp-btn.on i { background: var(--accent); border-color: var(--accent); position: relative; }
.cmp-btn.on i::after {
  content: '✓'; position: absolute; inset: 0; color: var(--accent-ink);
  font-size: 10px; line-height: 13px; text-align: center;
}
.compare-tray {
  position: fixed; left: 50%; bottom: 18px; transform: translateX(-50%); z-index: 1100;
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  background: var(--panel-2); border: 1px solid var(--line);
  border-radius: 999px; box-shadow: var(--shadow); padding: 10px 14px;
  font-size: 13.5px; color: var(--dim);
}
.compare-tray b { font-family: var(--f-mono); color: var(--chalk); }
.compare-tray .btn { padding: 7px 16px; font-size: 13px; }
.compare-tray .btn:disabled { opacity: .5; cursor: not-allowed; }
.compare-modal {
  position: fixed; inset: 0; z-index: 1200; padding: 20px;
  background: rgba(11, 20, 28, .55); backdrop-filter: blur(3px);
  display: grid; place-items: center;
}
.compare-box {
  background: var(--popup); border-radius: var(--r-lg); box-shadow: var(--shadow);
  padding: 24px; width: min(960px, 100%); max-height: 88vh; overflow: hidden;
  display: flex; flex-direction: column;
}
.compare-head { display: flex; align-items: center; gap: 14px; margin-bottom: 14px; }
.compare-head h2 { font-family: var(--f-display); font-size: 22px; color: var(--chalk); }
.compare-head .btn { margin-left: auto; padding: 6px 12px; }
.compare-scroll { overflow: auto; }
.compare-table { width: 100%; border-collapse: collapse; font-size: 14px; min-width: 460px; }
.compare-table th {
  text-align: left; color: var(--faint); font-weight: 600; font-size: 12px;
  letter-spacing: .06em; text-transform: uppercase;
  padding: 12px 12px 12px 0; border-bottom: 1px solid var(--line);
  white-space: nowrap; vertical-align: top;
}
.compare-table td {
  padding: 12px; border-bottom: 1px solid var(--line);
  border-left: 1px solid var(--line); vertical-align: top;
  color: var(--ink); line-height: 1.55; text-wrap: pretty;
}
.compare-table tr:first-child td { background: var(--accent-soft); }
.compare-table tr:last-child td, .compare-table tr:last-child th { border-bottom: 0; }
.compare-table small { color: var(--faint); }
.compare-table .yes { color: var(--ok); font-weight: 700; }
.compare-table .no { color: var(--faint); }
.compare-table .nd { color: var(--faint); font-style: normal; font-size: 12.5px; }
@media (max-width: 620px) {
  .compare-box { padding: 20px 16px; max-height: 92vh; }
  .compare-head .btn { margin-left: 0; }
}

/* --------- mega footer (generated by pipeline between FOOTER markers) --------- */
.footgrid {
  display: grid; grid-template-columns: 1.6fr 1fr 1fr 1fr; gap: 30px;
  padding-bottom: 26px;
}
@media (max-width: 800px) { .footgrid { grid-template-columns: 1fr 1fr; } }
.fcol h4 {
  font-family: var(--f-mono); font-size: 11px; font-weight: 600;
  letter-spacing: .12em; text-transform: uppercase; color: var(--faint);
  margin-bottom: 10px;
}
.fcol nav { display: flex; flex-direction: column; gap: 7px; }
.fcol a { color: var(--dim); font-size: 13.5px; }
.fcol a:hover { color: var(--accent-deep); }
.fcol a b { color: var(--faint); font-family: var(--f-mono); font-weight: 500; font-size: 12px; }
.fbrand .logo { font-size: 18px; }
.fbrand p { margin-top: 10px; font-size: 13px; color: var(--faint); max-width: 34ch; }
.footbottom {
  border-top: 1px solid var(--line); padding-top: 16px;
  display: flex; flex-wrap: wrap; gap: 10px; justify-content: space-between;
  font-size: 12.5px; color: var(--faint);
}

/* Łamanie wierszy: `pretty` unika sierot na końcu akapitu, `balance` wyrównuje
   nagłówki. Uzupełnia twarde spacje z UI.nbsp (nie zastępuje ich). */
p, .lead, .card-desc, .section p, .feature-rows span, .step p { text-wrap: pretty; }
h1, h2, h3 { text-wrap: balance; }

/* --------- static content pages (narrow, CENTERED column — long text in the
   full 1120px wrap reads lopsided, see retro #1) --------- */
.page { padding: 40px 0 60px; max-width: 780px; margin: 0 auto; }
.page h1 {
  font-family: var(--f-display); font-weight: 800; color: var(--chalk);
  font-size: clamp(26px, 4vw, 40px); letter-spacing: -.02em; margin-bottom: 20px;
}
.page h2 { font-family: var(--f-display); font-weight: 700; color: var(--chalk); font-size: 22px; margin: 26px 0 10px; }
.page p, .page li { color: var(--dim); max-width: 72ch; margin-bottom: 10px; }
.page ul { padding-left: 22px; }

/* --------- indeks miast (/miasta): hub linkowania wewnętrznego ---------
   Wszystkie kafle siedzą w statycznym HTML, cities-page.js tylko je chowa. */
.cx-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 18px; margin-top: 22px; }
.cx-find { position: relative; flex: 1 1 280px; max-width: 420px; }
.cx-find .ico-search {
  position: absolute; left: 13px; top: 50%; transform: translateY(-50%);
  width: 17px; height: 17px; color: var(--faint); pointer-events: none;
}
.cx-find input {
  width: 100%; border: 1px solid var(--line); background: var(--panel-2);
  color: var(--ink); border-radius: 999px; outline: none;
  padding: 12px 16px 12px 40px; font: inherit; font-size: 14.5px;
}
.cx-find input:focus-visible { border-color: var(--accent); box-shadow: 0 0 0 3px var(--halo); }
.cx-find input::-webkit-search-cancel-button { cursor: pointer; }
.cx-find input::-webkit-search-decoration { cursor: pointer; }
.cx-count { font-size: 13.5px; color: var(--dim); }
.cx-count b { font-family: var(--f-display); font-size: 17px; color: var(--chalk); }

.cx-chips { display: flex; flex-wrap: wrap; gap: 8px; margin: 18px 0 6px; }
.cx-chips .chip b { font-family: var(--f-mono); font-weight: 500; margin-left: 3px; color: inherit; }

.cx-group { margin-top: 34px; scroll-margin-top: 76px; }
.cx-gh {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px;
  padding-bottom: 10px; border-bottom: 1px solid var(--line);
  font-family: var(--f-display); font-size: 20px; color: var(--chalk);
}
.cx-gh span { font-family: var(--f-body); font-size: 13px; font-weight: 400; color: var(--dim); }
.cx-groups .tile-grid { grid-template-columns: repeat(auto-fill, minmax(168px, 1fr)); margin-top: 14px; }

.cx-tile { padding: 13px 14px 14px; gap: 3px; }
.cx-tile b {
  font-family: var(--f-display); font-weight: 700; font-size: 15.5px;
  letter-spacing: -.01em; color: var(--chalk);
}
.cx-tile:hover b { color: var(--accent-deep); }
.cx-tile span { font-size: 12.5px; }

/* PUŁAPKA: atrybut [hidden] to display:none o specyficzności (0,0,1), a .tile
   ustawia display:flex o (0,1,0) — samo hidden NIE zadziała na kaflu. Selektor
   klasa+atrybut (0,2,0) wygrywa. To samo dotyczy każdego komponentu z własnym
   display, który chowasz atrybutem. */
.cx-tile[hidden], .cx-group[hidden] { display: none; }
.cx-empty { margin-top: 28px; font-size: 14px; color: var(--dim); }

/* dwa wyjścia ze strony miasta: do wyszukiwarki i do indeksu miast */
.city-back { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 26px; }

/* ================= RUCH =================================================
   Trzy warstwy, w kolejności wartości:
   A. REAKCJA NA DOTYK — na telefonie nie ma `:hover`, więc bez `:active`
      stuknięcie w kartę nie daje ŻADNEJ odpowiedzi. To, a nie brak wlatywania,
      czyta się jako „martwa strona".
   B. RUCH JAKO ODPOWIEDŹ NA AKCJĘ — przejście listy po zmianie filtra i skok
      licznika. Ruch informacyjny: pokazuje, że to klik użytkownika coś zrobił.
   C. WEJŚCIA (wyżej, .reveal) — najmniej warte, dlatego fail-safe i skąpe.

   Twarde reguły: nigdy nie animuj elementu LCP; nigdy `opacity: 0` czekające
   na JS; reakcja ≤200 ms, wejście ≤450 ms; zero parallaxu i przechwytywania
   scrolla; wszystko gaszone przez prefers-reduced-motion. */

/* --------- A. dotyk --------- */
.card, .tile, .chip, .btn, .cx-tile, .q-sug a, .mapx-reset, .sug-more {
  -webkit-tap-highlight-color: transparent;
}
.card:active, .tile:active, .cx-tile:active, .chip:active, .btn:active {
  transform: scale(.985);
  transition-duration: .08s;
}
/* Na dotyku `:hover` zostaje PRZYKLEJONY po stuknięciu — palec nie „odjeżdża"
   jak kursor. Zdejmujemy więc przesunięcia hover tam, gdzie hovera nie ma;
   zmiany koloru zostają, bo nie kłamią o stanie. */
@media (hover: none) {
  .card:hover, .tile:hover, .chip:hover, .btn:hover,
  .filters select:hover, .city-strip .chip:hover { transform: none; }
  .card:hover .cstripe, .tile:hover i { width: 3px; }
}

/* --------- B. reakcja na akcję --------- */
/* podmiana zawartości listy: krótkie wejście dzieci, restart przez klasę */
.fx-swap > * { animation: fx-swap-in .18s ease both; }
@keyframes fx-swap-in {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: none; }
}
/* licznik: liczba skacze, gdy się zmieni */
.fx-pop { animation: fx-pop .22s ease; }
@keyframes fx-pop {
  0% { transform: scale(1); }
  40% { transform: scale(1.14); }
  100% { transform: scale(1); }
}

/* --------- szkielet ładowania (statyczny w HTML, JS go nadpisuje) --------- */
.sk {
  border: 1px solid var(--line); border-radius: var(--r-md);
  background: var(--panel-2); overflow: hidden; position: relative;
}
.sk-card { min-height: 148px; }
.sk-row { min-height: 96px; list-style: none; }
.sk::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent, var(--bg-2), transparent);
  transform: translateX(-100%);
  animation: sk-shimmer 1.25s ease-in-out infinite;
}
@keyframes sk-shimmer { to { transform: translateX(100%); } }

@media (prefers-reduced-motion: reduce) {
  .fx-swap > * { animation: none; }
  .fx-pop { animation: none; }
  .sk::after { animation: none; }
  .card:active, .tile:active, .cx-tile:active, .chip:active, .btn:active { transform: none; }
}

/* --------- przełącznik języka (docs/11-i18n.md) ---------
   Wypełnia go build tylko w apkach wielojęzycznych. Zostaje widoczny na
   telefonie, gdzie .site-nav znika — inaczej użytkownik z /en nie ma jak
   wrócić do polskiej wersji. Cel dotyku min. 24x24 px (WCAG 2.5.8). */
.lang-switch {
  display: flex; gap: 2px; flex: none; margin-right: 10px; padding: 2px;
  border: 1px solid var(--line); border-radius: 999px; background: var(--panel-2);
}
.lang-switch a {
  min-width: 34px; padding: 7px 9px; border-radius: 999px; line-height: 1;
  font-size: 12px; font-weight: 600; letter-spacing: .04em; text-align: center; color: var(--dim);
}
.lang-switch a:hover { color: var(--accent-deep); background: var(--accent-soft); }
.lang-switch a[aria-current] { background: var(--accent); color: var(--accent-ink); }
.lang-switch a:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
@media (max-width: 820px) { .lang-switch { margin: 0 0 0 auto; } }

/* ================= WZORCE SEKCJI (przeniesione z kortów do fabryki) =================
   Tabela porównawcza, pasek-uwaga, cztery kroki, mapa obok kafli. Powstały
   w kortywpolsce, ale to wzorce ogólne — używaj ich zamiast gołych akapitów. */
.split-map { grid-template-columns: .85fr 1.15fr; align-items: start; }
@media (max-width: 860px) { .split-map { grid-template-columns: 1fr; } }

/* tabela porównawcza (reużywa .compare-table z porównywarki): 3 kolumny + nagłówek wiersza */
#type-tiles { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 640px) { #type-tiles { grid-template-columns: 1fr; } }
.disc-compare { margin-top: 26px; }
/* Czytelność (uwaga 03.09): kolumny były za wąskie, krótkie zdania łamały się
   na dwa wiersze. Szersze minimum + powietrze + naprzemienne tło + text-wrap. */
.disc-table { min-width: 880px; font-size: 14.5px; }
.disc-table th { width: 16%; background: var(--bg-2); padding-left: 12px; }
.disc-table td { width: 28%; line-height: 1.55; text-wrap: pretty; }
.disc-table th, .disc-table td { padding-top: 14px; padding-bottom: 14px; }
.disc-table tbody tr:nth-child(even) td { background: rgba(255, 255, 255, .45); }
.disc-table tbody tr:hover td { background: var(--accent-soft); }
.disc-table tr:first-child td { background: var(--panel-2); font-size: 16px; }
.disc-table tr:first-child b { font-family: var(--f-display); font-weight: 800; }
.disc-table .btn { padding: 7px 14px; font-size: 13px; white-space: nowrap; }
@media (max-width: 900px) {
  .disc-table th { position: sticky; left: 0; z-index: 1; box-shadow: 1px 0 0 var(--line); }
}
.disc-note { font-size: 12.5px; color: var(--faint); margin-top: 12px; max-width: 72ch; }
p, .lead, .card-desc, .section p, .feature-rows span, .step p { text-wrap: pretty; }
h1, h2, h3, .section h2 { text-wrap: balance; }

/* cztery kroki zamiast trzech */
.steps.steps-4 { grid-template-columns: repeat(4, 1fr); gap: 22px; }
/* 2 kolumny: szyna kroku 2 prowadziłaby w pustkę za krawędzią — chowamy wszystkie */
@media (max-width: 980px) { .steps.steps-4 { grid-template-columns: repeat(2, 1fr); } .steps.steps-4 .step::after { display: none; } }
@media (max-width: 620px) { .steps.steps-4 { grid-template-columns: 1fr; } }

/* pasek-uwaga: jedna myśl na pełną szerokość */
.note-strip {
  margin-top: 28px; padding: 18px 22px;
  background: var(--accent-soft); border-left: 3px solid var(--accent); border-radius: var(--r-sm);
  display: grid; grid-template-columns: minmax(0, .8fr) minmax(0, 1.2fr); gap: 8px 26px; align-items: baseline;
}
@media (max-width: 760px) { .note-strip { grid-template-columns: 1fr; } }
.note-strip b { font-family: var(--f-display); font-size: 16px; color: var(--chalk); }
.note-strip span { color: var(--dim); font-size: 14px; }

/* ================= ARCHETYP D „Mapa jako strona" (docs/09) =================
   Hero = żywa mapa (#livemap, app.js: initLiveMap). Mobile-first: karta nad
   mapą (kolejność w DOM), mapa 52vh i bez przeciągania palcem (strona musi
   się przewijać). Desktop: mapa na całą scenę, karta pływa po lewej. */
.hero-map-stage { position: relative; display: flex; flex-direction: column; background: var(--bg-2); }
.livemap { order: 2; height: 52vh; min-height: 320px; background: var(--bg-2); z-index: 0; }
.livemap.livemap-off { display: none; }
.map-float { order: 1; padding: 18px 16px 20px; }
.float-card {
  background: var(--panel-2); border: 1px solid var(--line); border-radius: var(--r-lg);
  box-shadow: var(--shadow); padding: 22px 20px;
}
.float-card h1 {
  font-family: var(--f-display); font-size: clamp(28px, 4.2vw, 44px); line-height: 1.08;
  letter-spacing: -.02em; color: var(--chalk); margin: 6px 0 10px;
}
.float-card h1 em {
  font-style: normal; background: var(--grad); -webkit-background-clip: text;
  background-clip: text; color: transparent;
}
.float-card .lead { color: var(--dim); font-size: 15.5px; margin-bottom: 14px; }
.float-stats { display: flex; flex-wrap: wrap; gap: 6px 18px; margin-bottom: 14px; font-size: 13.5px; color: var(--dim); }
.float-stats b { font-family: var(--f-display); font-size: 20px; color: var(--chalk); margin-right: 4px; }
.float-card .hero-actions { margin-top: 14px; display: flex; flex-wrap: wrap; gap: 10px; }
.float-card .city-strip { margin-top: 14px; }
@media (min-width: 981px) {
  .hero-map-stage { display: block; height: min(86vh, 820px); min-height: 600px; }
  .livemap { position: absolute; inset: 0; height: auto; min-height: 0; }
  .map-float {
    position: relative; z-index: 2; height: 100%; max-width: var(--maxw); margin: 0 auto;
    padding: 28px 24px; display: flex; align-items: center; pointer-events: none;
  }
  .float-card { width: 450px; pointer-events: auto; background: rgba(255, 255, 255, .95); backdrop-filter: blur(6px); }
}

/* ================= EV: infografika złączy =================
   Rysunki gniazd w SVG (Type 2, CCS, CHAdeMO) — tematyczna struktura strony
   zamiast dekoracji w tle (docs/10). Klasy cpin-*, bo .pin to znacznik mapy. */
.plugs { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 18px; margin-top: 24px; }
@media (max-width: 900px) { .plugs { grid-template-columns: 1fr; } }
.plug {
  background: var(--panel-2); border: 1px solid var(--line); border-radius: var(--r-lg);
  padding: 22px; display: grid; grid-template-columns: 92px 1fr; gap: 18px; align-items: start;
  transition: border-color .15s, box-shadow .15s;
}
.plug:hover { border-color: var(--accent); box-shadow: var(--shadow); }
.plug svg { width: 92px; height: auto; }
.plug-body { fill: var(--bg-2); stroke: var(--chalk); stroke-width: 3; }
.plug-ccs .plug-body { stroke: var(--accent); }
.cpin { fill: var(--panel-2); stroke: var(--chalk); stroke-width: 2.5; }
.cpin-s { fill: var(--chalk); }
.cpin-dc { fill: var(--accent-2-soft); stroke: var(--accent-2-deep); stroke-width: 3; }
.plug figcaption b { display: block; font-family: var(--f-display); font-size: 18px; color: var(--chalk); margin-bottom: 4px; }
.plug figcaption span { display: block; font-size: 14px; color: var(--dim); }
.plug-link { display: inline-block; margin-top: 10px; font-size: 13.5px; font-weight: 600; color: var(--accent-deep); }
.plug-link:hover { text-decoration: underline; }

/* ================= EV: kalkulator czasu ładowania (calc.js) ================= */
.calc {
  margin-top: 22px; background: var(--panel-2); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: 22px; box-shadow: var(--shadow);
}
.panel .calc { margin-top: 6px; padding: 0; border: 0; box-shadow: none; background: none; }
.calc-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 14px 18px; }
.calc-f { display: flex; flex-direction: column; gap: 6px; font-size: 13.5px; color: var(--dim); }
.calc-f select {
  border: 1px solid var(--line); background: var(--popup); border-radius: var(--r-sm);
  padding: 9px 10px; font-size: 14.5px; color: var(--ink); cursor: pointer;
}
.calc-f select:focus-visible { border-color: var(--accent); }
.calc-f input[type="range"] { accent-color: var(--accent); cursor: pointer; width: 100%; min-height: 24px; }
.calc-f b { color: var(--chalk); font-family: var(--f-display); }
.calc-out { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; margin-top: 20px; }
.calc-out div { background: var(--accent-soft); border-radius: var(--r-md); padding: 14px 16px; }
.calc-out span { display: block; font-size: 12.5px; color: var(--dim); }
.calc-out b { display: block; font-family: var(--f-display); font-size: 26px; color: var(--accent-deep); line-height: 1.15; }
.calc-note { margin-top: 12px; font-size: 12.5px; color: var(--faint); max-width: 80ch; }


/* ============================================================
   SILNIK RÓŻNORODNOŚCI (app-layout/docs/14-roznorodnosc.md)
   Warianty kafli, persony, pasek statystyki, skala typografii, wzory band,
   sloty motywu encji. Każdy projekt wybiera INNĄ kombinację i zapisuje ją
   w site.config.json → brand.variants.

   Zasada: renderery (app.js, build.mjs) ZAWSZE emitują pełny markup kafla
   (zmienne --k/--seg/--tc, elementy .rk/.tbar/.seg/.tile-go/small), a to
   klasa KONTENERA decyduje, co widać. Zmiana wariantu = zmiana jednej klasy
   w HTML, zero JS.
     --k   udział w maksimum (0..1)     --seg  1..5 (pięciostopniowa skala)
     --tc  kolor typu (tylko kafle typów)
   ============================================================ */

/* --- wspólne: elementy pomocnicze kafla są domyślnie ukryte --- */
.tile { --k: 0; --seg: 1; }
.tile .rk, .tile .tbar, .tile .seg, .tile .tile-go, .tile small { display: none; }
.tile .tile-ico { width: 30px; height: 30px; color: var(--accent-deep); margin-bottom: 6px; }
.tile .tile-ico svg { width: 100%; height: 100%; display: block; }
#voiv-tiles .tile:nth-child(2n) .tile-ico { color: var(--accent-2-deep); }

/* --- v-bars: kafel + słupek udziału pod etykietą --- */
.tile-grid.v-bars .tile .tbar {
  display: block; height: 6px; margin-top: 10px; border-radius: 999px;
  background: var(--bg-2); overflow: hidden;
}
.tile-grid.v-bars .tile .tbar::before {
  content: ''; display: block; height: 100%; width: calc(var(--k) * 100%);
  border-radius: inherit; background: var(--tc, var(--accent));
  transition: width .4s ease-out;
}
#voiv-tiles.v-bars .tile:nth-child(2n) .tbar::before { background: var(--accent-2); }

/* --- v-heat: natężenie tła od udziału + pięciosegmentowy wskaźnik, bez ramek.
       Tint maks. 22% akcentu na panelu: tekst --accent-deep i --dim zostają
       czytelne; powyżej tego progu sprawdź kontrast ręcznie. --- */
.tile-grid.v-heat .tile {
  border-color: transparent;
  background: color-mix(in srgb, var(--accent) calc(var(--k) * 22%), var(--panel-2));
}
.tile-grid.v-heat .tile:hover { border-color: var(--accent); }
.tile-grid.v-heat .tile .seg {
  display: block; width: 100%; height: 7px; margin-top: 10px;
  background-image:
    repeating-linear-gradient(90deg, var(--tc, var(--accent)) 0 calc(100% / var(--seg) - 3px), transparent calc(100% / var(--seg) - 3px) calc(100% / var(--seg))),
    repeating-linear-gradient(90deg, var(--line) 0 calc(20% - 3px), transparent calc(20% - 3px) 20%);
  background-size: calc(var(--seg) * 20%) 100%, 100% 100%;
  background-repeat: no-repeat;
}
#voiv-tiles.v-heat .tile:nth-child(2n) .seg { background-image:
  repeating-linear-gradient(90deg, var(--accent-2) 0 calc(100% / var(--seg) - 3px), transparent calc(100% / var(--seg) - 3px) calc(100% / var(--seg))),
  repeating-linear-gradient(90deg, var(--line) 0 calc(20% - 3px), transparent calc(20% - 3px) 20%); }

/* --- v-rank: ranking w dwóch kolumnach: miejsce · nazwa · słupek · liczba.
       Dla kafli regionów i typów (b = liczba, span = nazwa). --- */
.tile-grid.v-rank { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 4px 36px; margin-top: 14px; }
@media (max-width: 720px) { .tile-grid.v-rank { grid-template-columns: 1fr; } }
.tile-grid.v-rank .tile {
  flex-direction: row; align-items: center; gap: 12px;
  padding: 9px 10px 9px 42px; border: 0; border-bottom: 1px solid var(--line);
  border-radius: var(--r-sm); background: none; box-shadow: none; overflow: visible;
}
.tile-grid.v-rank .tile:hover { transform: translateX(3px); background: var(--accent-soft); border-color: transparent; box-shadow: none; }
.tile-grid.v-rank .tile i { display: none; }
.tile-grid.v-rank .tile .rk {
  display: block; position: absolute; left: 4px; top: 50%; transform: translateY(-50%);
  width: 28px; text-align: right; font-style: normal;
  font-family: var(--f-mono); font-size: 12px; color: var(--faint);
}
.tile-grid.v-rank .tile:nth-child(-n+3) .rk { color: var(--accent-deep); font-weight: 700; font-size: 13px; }
.tile-grid.v-rank .tile span { order: 1; flex: 0 0 148px; font-size: 14px; color: var(--ink); line-height: 1.25; }
.tile-grid.v-rank .tile .tbar {
  order: 2; display: block; flex: 1 1 auto; height: 8px; margin: 0;
  border-radius: 999px; background: var(--bg-2); overflow: hidden;
}
.tile-grid.v-rank .tile .tbar::before {
  content: ''; display: block; height: 100%; width: calc(var(--k) * 100%);
  border-radius: inherit; background: var(--accent); transition: width .4s ease-out;
}
.tile-grid.v-rank .tile:nth-child(2n) .tbar::before { background: var(--accent-2); }
.tile-grid.v-rank .tile b { order: 3; flex: 0 0 48px; text-align: right; font-size: 17px; }
@media (max-width: 420px) { .tile-grid.v-rank .tile span { flex-basis: 112px; } }

/* --- v-cloud: chmura chipów, rozmiar od udziału. Dla kafli MIAST
       (b = nazwa, span = liczba): /miasta i miasta w regionie. --- */
.tile-grid.v-cloud { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.tile-grid.v-cloud .tile {
  flex-direction: row; align-items: baseline; gap: 7px;
  padding: 6px 13px; border-radius: 999px;
  font-size: calc(13px + var(--k) * 7px);
}
.tile-grid.v-cloud .tile i { display: none; }
.tile-grid.v-cloud .tile b { font-size: 1em; font-weight: 700; }
.tile-grid.v-cloud .tile span { font-size: max(11.5px, .72em); font-family: var(--f-mono); color: var(--faint); }
.tile-grid.v-cloud .tile:hover { transform: translateY(-1px) scale(1.02); }

/* --- v-poster: kafle-plakaty dla TYPÓW: ikona motywu (entity.typeIcons),
       wielka liczba w kolorze typu, nazwa, opis (entity.typeDesc), wiersz
       „Przeglądaj →". Kafel wiodący (atrybut data-lead na kontenerze) stoi na
       pełnym akcencie — tekst --accent-ink, więc para jest pod strażnikiem
       kontrastu. Hover kafla wiodącego przez brightness, nie --accent-deep
       (deep bywa tylko kolorem tekstu, patrz contrastSkip). --- */
.tile-grid.v-poster { grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 14px; }
.tile-grid.v-poster .tile { padding: 24px 22px 20px; min-height: 240px; border-radius: var(--r-lg); gap: 4px; }
.tile-grid.v-poster .tile i { display: none; }
.tile-grid.v-poster .tile .tile-ico { width: 34px; height: 34px; color: var(--tc, var(--accent-deep)); margin-bottom: 10px; }
.tile-grid.v-poster .tile b { font-size: clamp(36px, 4vw, 48px); line-height: 1; color: var(--tc, var(--accent-deep)); }
.tile-grid.v-poster .tile span {
  font-family: var(--f-display); font-weight: 700; font-size: 16.5px;
  color: var(--chalk); letter-spacing: -.01em; margin-top: 4px;
}
.tile-grid.v-poster .tile small { display: block; font-size: 13.5px; line-height: 1.45; color: var(--dim); margin-top: 6px; text-wrap: pretty; }
.tile-grid.v-poster .tile .tile-go {
  display: block; margin-top: auto; padding-top: 16px; font-style: normal;
  font-family: var(--f-mono); font-size: 11.5px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--accent-deep); transition: transform .15s;
}
.tile-grid.v-poster .tile:hover .tile-go { transform: translateX(3px); }
.tile-grid.v-poster .tile.is-lead { background: var(--accent); border-color: var(--accent); }
.tile-grid.v-poster .tile.is-lead:hover { background: var(--accent); filter: brightness(.94); }
.tile-grid.v-poster .tile.is-lead b, .tile-grid.v-poster .tile.is-lead span,
.tile-grid.v-poster .tile.is-lead .tile-ico, .tile-grid.v-poster .tile.is-lead .tile-go { color: var(--accent-ink); }
.tile-grid.v-poster .tile.is-lead small { color: var(--accent-ink); opacity: .86; }

/* --- persony: sekcja „Dla kogo" — karty publiczności. Ikona motywu z lewej,
       etykieta roli jako pigułka w rogu, zdanie, link do PRZEFILTROWANEJ listy
       (deep-link ?typ= / ?x=). Karta jest linkiem, nie ozdobą. --- */
.personas { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 14px; margin-top: 22px; }
.persona {
  position: relative; display: flex; flex-direction: column; gap: 8px;
  background: var(--panel-2); border: 1px solid var(--line); border-radius: var(--r-lg);
  padding: 22px 22px 18px; color: inherit;
  transition: transform .15s, border-color .15s, box-shadow .15s;
}
.persona:hover { transform: translateY(-2px); border-color: var(--accent); box-shadow: var(--shadow); }
.persona .p-ico {
  width: 42px; height: 42px; border-radius: 12px; display: grid; place-items: center;
  background: var(--accent-soft); color: var(--accent-deep); margin-bottom: 4px;
}
.persona:nth-child(2n) .p-ico { background: var(--accent-2-soft); color: var(--accent-2-deep); }
.persona .p-ico svg { width: 22px; height: 22px; display: block; }
.persona .p-tag {
  position: absolute; top: 16px; right: 16px; padding: 4px 9px; border-radius: 999px;
  font-family: var(--f-mono); font-size: 10.5px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--accent-deep); background: var(--accent-soft);
}
.persona:nth-child(2n) .p-tag { color: var(--accent-2-deep); background: var(--accent-2-soft); }
.persona b { font-family: var(--f-display); font-size: 17.5px; color: var(--chalk); letter-spacing: -.01em; padding-right: 70px; }
.persona p { font-size: 14px; color: var(--dim); margin: 0; max-width: none; }
.persona .p-go { margin-top: auto; padding-top: 12px; font-size: 13.5px; font-weight: 600; color: var(--accent-deep); }
.persona:hover .p-go { text-decoration: underline; }

/* --- pasek statystyki: jedna liczba (data-n), jedno zdanie, jeden przycisk.
       Na własnej, cienkiej bandzie; w .band.dark liczba świeci akcentem. --- */
.stat-strip { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 16px 40px; align-items: center; padding: 30px 0; }
.stat-strip .ss-n {
  font-family: var(--f-display); font-weight: 800; line-height: .95;
  font-size: clamp(36px, 4.8vw, 56px); letter-spacing: -.03em; color: var(--accent-deep);
}
.stat-strip .ss-n small {
  display: block; margin-top: 8px; font-family: var(--f-mono); font-weight: 500;
  font-size: 11px; letter-spacing: .12em; text-transform: uppercase; color: var(--faint);
}
.stat-strip p { margin: 0; color: var(--dim); max-width: 58ch; font-size: 15px; }
@media (max-width: 760px) { .stat-strip { grid-template-columns: 1fr; gap: 14px; } }

/* --- oś: skala typografii sekcji (klasa na <body>). t-poster = duże nagłówki,
       t-caps = wersaliki. Można łączyć. --- */
body.t-poster .section h2 { font-size: clamp(30px, 4.4vw, 48px); line-height: 1.04; letter-spacing: -.03em; margin-bottom: 18px; max-width: 24ch; }
body.t-poster .outro h2 { font-size: clamp(30px, 4.4vw, 46px); max-width: none; margin-left: auto; margin-right: auto; }
body.t-poster .cta-band h2 { font-size: clamp(22px, 2.8vw, 30px); max-width: none; }
body.t-caps .section h2, body.t-caps .outro h2, body.t-caps .cta-band h2 { text-transform: uppercase; letter-spacing: .01em; }

/* --- wzory band. Tylko na bandach bez własnego gradientu (domyślna, .alt,
       .dark); .soft ma gradient i wzór by go nadpisał. --- */
.band.pat-lines { background-image: repeating-linear-gradient(135deg, var(--accent-soft) 0 1px, transparent 1px 24px); }
.band.pat-grid {
  background-image: linear-gradient(var(--line) 1px, transparent 1px), linear-gradient(90deg, var(--line) 1px, transparent 1px);
  background-size: 64px 64px;
}
.band.pat-dots { background-image: radial-gradient(var(--accent-soft) 1.3px, transparent 1.8px); background-size: 20px 20px; }

/* --- wiersze cech z ikonami motywu zamiast numerów --- */
.feature-rows.v-icons li::before { display: none; }
.feature-rows.v-icons li { padding-left: 66px; }
.feature-rows.v-icons .fr-ico {
  position: absolute; left: 12px; top: 13px; width: 38px; height: 38px; border-radius: 11px;
  display: grid; place-items: center; background: var(--accent-soft); color: var(--accent-deep);
}
.feature-rows.v-icons li:nth-child(2n) .fr-ico { background: var(--accent-2-soft); color: var(--accent-2-deep); }
.feature-rows.v-icons .fr-ico svg { width: 20px; height: 20px; display: block; }

/* --- układ nagłówka z boku: .v-side-head (eyebrow + h2 + lead, sticky)
       w lewej kolumnie, .v-side-body po prawej. Łamie rytm „nagłówek nad
       treścią" powtarzany w każdej sekcji. --- */
@media (min-width: 900px) {
  .v-side-row { display: grid; grid-template-columns: minmax(0, .85fr) minmax(0, 1.6fr); gap: 16px 56px; align-items: start; }
  /* sticky ograniczone do .v-side-row: Chrome liczy obszar przyklejenia od całego kontenera
     siatki, więc nagłówek w jednej siatce z bandą CTA nachodził na bandę */
  .v-side-row > .v-side-head { position: sticky; top: 84px; }
  .v-side-row > .v-side-head h2 { max-width: none; }
}

/* --- ilustracja motywu w tle SEKCJI (nie tylko hero): SVG w kolorze akcentu,
       niskie krycie, poza kolumną treści. Tylko na bandzie z klasą has-art —
       overflow:hidden na każdej bandzie uciąłby pływający panel filtrów. --- */
.band.has-art { position: relative; overflow: hidden; }
.band.has-art > .wrap { position: relative; z-index: 1; }
.sec-art { position: absolute; z-index: 0; pointer-events: none; color: var(--accent); opacity: .16; }
.sec-art svg { width: 100%; height: auto; display: block; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.sec-art.right { right: -3%; top: 50%; transform: translateY(-50%); width: min(520px, 40vw); }
.sec-art.left { left: -3%; bottom: -8%; width: min(460px, 36vw); }
@media (max-width: 760px) { .sec-art { opacity: .1; width: 70vw; } }

/* --- miniatura motywu w mockupie karty (plan kortu, piktogram stacji) --- */
.mock-art { margin: 12px 0 4px; padding: 10px 12px; border-radius: var(--r-sm); background: var(--accent-soft); color: var(--accent-deep); }
.mock-art svg { width: 100%; height: auto; display: block; fill: none; stroke: currentColor; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }

/* --- szyna kroków przerywana (kabel, trasa, linia boczna) --- */
.steps.v-dash .step::after { background: repeating-linear-gradient(90deg, var(--line) 0 8px, transparent 8px 14px); }
.steps.v-dash .step:last-child::after {
  background:
    radial-gradient(circle at calc(100% - 5px) 50%, var(--accent) 0 4px, transparent 4.5px),
    repeating-linear-gradient(90deg, var(--line) 0 8px, transparent 8px 14px) left center / calc(100% - 10px) 2px no-repeat;
}

/* --- ikona motywu w etykiecie sekcji --- */
.eyebrow .ico { display: inline-grid; place-items: center; width: 16px; height: 16px; margin-right: 6px; vertical-align: -3px; color: var(--accent-deep); }
.eyebrow .ico svg { width: 14px; height: 14px; display: block; }

/* dotyk: przesunięcia hover zostają przyklejone po stuknięciu (docs/07, Ruch A) */
@media (hover: none) {
  .tile-grid.v-rank .tile:hover, .tile-grid.v-cloud .tile:hover, .persona:hover,
  .tile-grid.v-poster .tile:hover .tile-go { transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .tile-grid.v-bars .tile .tbar::before, .tile-grid.v-rank .tile .tbar::before { transition: none; }
}

/* --- karty rekordów: warianty .v-cover / .v-spec / .v-facts na KONTENERZE (.grid, .mapx-items).
       cardHTML zawsze emituje okładkę (.ccover z entity.typeArt), blok liczbowy (.cstat
       z entity.cardStat) i fakty (.cfacts z extras[].icon); domyślnie są ukryte. --- */
.card { --tc: var(--accent); }
.card .cmain { display: flex; flex-direction: column; gap: 8px; flex: 1 1 auto; min-width: 0; }
.card .ccover, .card .cstat, .card .cfacts { display: none; }

/* v-cover: okładka w kolorze typu z planem / piktogramem; typ przenosi się na okładkę */
.v-cover .card { padding-top: 0; }
.v-cover .card .cstripe { display: none; }
.v-cover .card .ccover {
  display: block; position: relative; flex: none; height: 98px;
  margin: 0 -20px 6px -24px;
  /* tint w gradiencie + ukośne linie w kolorze typu: na bandzie .alt sam tint zlewał się z tłem */
  background:
    repeating-linear-gradient(135deg, color-mix(in srgb, var(--tc) 22%, transparent) 0 1px, transparent 1px 11px),
    linear-gradient(180deg, color-mix(in srgb, var(--tc) 26%, var(--panel-2)), color-mix(in srgb, var(--tc) 14%, var(--panel-2)));
  border-top: 4px solid var(--tc);
  border-bottom: 1px solid color-mix(in srgb, var(--tc) 35%, var(--line));
  overflow: hidden;
}
.v-cover .card .ccover svg {
  position: absolute; left: 18px; top: 50%; transform: translateY(-50%);
  width: 46%; max-width: 180px; height: auto; color: var(--tc); opacity: .88;
  fill: none; stroke: currentColor; transition: transform .2s;
}
.v-cover .card .ccover svg[viewBox="0 0 24 24"] { width: 64px; opacity: .35; }
.v-cover .card:hover .ccover svg { transform: translateY(-50%) scale(1.04); }
.v-cover .card .ctype {
  position: absolute; right: 14px; bottom: 12px; font-style: normal;
  font-family: var(--f-mono); font-size: 11px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase;
  color: var(--tc); background: var(--panel-2); border: 1px solid var(--line); padding: 3px 8px; border-radius: 999px;
}
.v-cover .card .badge.x-type { display: none; }
.v-cover .card:has(.card-tools) h3 { padding-right: 0; }
.v-cover .card .card-desc { -webkit-line-clamp: 2; }

/* v-spec: blok liczbowy z lewej (np. moc w kW), treść z prawej */
.v-spec .card {
  display: grid; grid-template-columns: 78px minmax(0, 1fr);
  grid-template-rows: auto auto auto 1fr auto; gap: 6px 14px; align-items: start;
}
.v-spec .card .ccover { grid-column: 1 / -1; }
.v-spec .card .cmain { display: contents; }          /* dzieci .cmain stają się polami siatki */
.v-spec .card .cstat { grid-column: 1; grid-row: 1 / span 2; }
.v-spec .card h3, .v-spec .card .meta { grid-column: 2; }
.v-spec .card .cfacts, .v-spec .card .card-desc, .v-spec .card .badges { grid-column: 1 / -1; }
.v-spec .card .badges { align-self: end; margin-top: 0; }
.v-spec .card .cstat {
  display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center;
  padding: 12px 6px 10px; border-radius: var(--r-sm); color: var(--tc);
  background: color-mix(in srgb, var(--tc) 12%, var(--panel-2));
}
.v-spec .card .cstat b { font-family: var(--f-display); font-size: 24px; line-height: 1; letter-spacing: -.02em; }
.v-spec .card .cstat small { margin-top: 5px; font-family: var(--f-mono); font-size: 10px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--faint); }
.v-spec .card .cstat.is-empty { color: var(--faint); background: var(--bg-2); }
.v-spec .card .badge.x-stat { display: none; }

/* v-facts: potwierdzone cechy bool jako chipy z ikoną; badge'e bool znikają (dublowały) */
.v-facts .card .cfacts { display: flex; flex-wrap: wrap; gap: 6px; list-style: none; margin: 0; padding: 0; }
.v-facts .card .cfacts li {
  display: inline-flex; align-items: center; gap: 5px; font-size: 12.5px; font-weight: 600;
  color: var(--accent-deep); background: var(--accent-soft); padding: 3px 9px 3px 7px; border-radius: 999px;
}
.v-facts .card .cfacts svg { width: 14px; height: 14px; display: block; flex: none; }
.v-facts .card .badge.x-bool { display: none; }
/* gdy po schowaniu typu i booli nie zostaje żaden badge, nie zostawiamy pustej linii z kreską */
.v-cover.v-facts .card .badges:not(:has(.badge.x-enum, .badge.x-num, .badge.x-text)) { display: none; }

/* układ v-side: banda CTA pod pytaniami idzie na pełną szerokość sekcji, nie w prawą kolumnę */
/* banda CTA leży POZA .v-side-row, jako zwykły blok na pełną szerokość sekcji */
.section.v-side > .cta-band { margin-left: 0; margin-right: 0; width: 100%; }
