/* ============================================================================
   18-prezentacje.css — ekrany dotyczące OFERTY POKAZYWANEJ KLIENTOWI:
   konfigurator i kartoteka prezentacji (wybór szablonu z podglądem), materiały
   prezentacyjne konstrukcji, lista atrakcji, demografia + ROI (WorldPop),
   analityka prezentacji (sesje, czas na sekcji).
   Czego TU NIE MA: sama prezentacja oglądana przez klienta to osobna strona
   generowana na serwerze (src/server/offerHtmlGenerator) i szablony
   szablon-nowy.html — mają własne, wbudowane arkusze i nie znają tych tokenów.
   ============================================================================ */
/* === 1. KONFIGURATOR I KARTOTEKA PREZENTACJI ==============================
   Oba okna to ten sam pojemnik na pełnym ekranie: podgląd szablonu 16:9 musi
   dostać realną przestrzeń, inaczej nie widać, co się właściwie wybiera. */
.modal.presentation-options-modal { width: calc(100vw / var(--skala-ui) - var(--s-2)); height: calc(100dvh / var(--skala-ui) - var(--s-2)); max-height: none; border-radius: 0; }
/* Skan 13.09.2026: okno ma 100vw − 8 px, a tło okien daje 20 px wyściółki — okno wystawało za prawą
   i dolną krawędź (bez prawej ramki, „Zapisz" przy krawędzi). Tło zwężone jak przy materiale i ekipie. */
.modal-backdrop.presentation-options-backdrop { padding: var(--s-1); }
/* Formularz sam rozdaje wysokość sekcjom. Selektor musi być mocniejszy niż
   `.modal > form` z 05-komponenty — stamtąd przychodzi grid i duży padding. */
.modal.presentation-options-modal > form { display: flex; flex-direction: column; gap: var(--s-3); padding: var(--s-4); }
/* Pasek kontekstu: co dokładnie wejdzie do prezentacji (zakres konstrukcji). */
.presentation-options-summary { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); flex: 0 0 auto; padding: var(--s-2) var(--s-3); border: 1px solid var(--line); border-radius: var(--r); background: var(--surface-2); }
.presentation-options-summary strong { font-weight: var(--w-bold); }
.presentation-options-summary span { color: var(--text-muted); font-size: var(--t-xs); }
/* Wyciete 11.08.2026 — martwe reguly, zero wystapien w public/js. Szczegoly: AUDYT-CSS-2026-08-11.md B9. */
/* Lista szablonów celowo wąska — to jeden wybór, nie formularz na pół ekranu. */
.tpl-template-field { flex: 0 0 auto; max-width: 420px; }
/* Podgląd to iframe 1280×720 skalowany skryptem: dziecko jest position:absolute,
   więc ramka MUSI mieć własną wysokość. Proporcja 16:9 = format slajdu. */
/* Wysokość = to, co zostaje w oknie (flex 1 1 0), szerokość z proporcji 16:9, najwyżej 100 %.
   Wcześniej ramka brała 16:9 od PEŁNEJ szerokości (~1080 px wysokości) i wypychała notkę pod
   podglądem poza okno — slajd był ucięty w połowie. fit() w 10-offer-html.js skaluje iframe
   do tego, co ramka faktycznie ma. */
.tpl-preview-box { flex: 1 1 0; align-self: center; width: auto; max-width: 100%; aspect-ratio: 16 / 9; min-height: 180px; overflow: hidden; border: 1px solid var(--line-strong); border-radius: var(--r); background: var(--surface-3); }
.tpl-preview-note { flex: 0 0 auto; color: var(--text-muted); font-size: var(--t-sm); }
/* „Kopiuj link" ma być niewidoczny do czasu wygenerowania linku — globalne
   `.button { display: inline-flex }` wygrywało z [hidden] i rozpychało stopkę. */
.presentation-copy-link-button[hidden] { display: none; }
/* #53: opublikowana oferta ma cenę inną niż dzisiejsza kalkulacja (klient widzi starą). */
.offer-price-stale { display: inline-flex; align-items: center; align-self: center; padding: 1px var(--s-2); border: 1px solid color-mix(in srgb, var(--danger) 35%, transparent); border-radius: var(--r-pill); background: var(--danger-soft); color: var(--danger); font-size: var(--t-xs); font-weight: var(--w-bold); white-space: nowrap; }
/* === 2. MATERIAŁY PREZENTACYJNE KONSTRUKCJI ===============================
   Zakładki Rendery / Rendery 360 / 3DVista. Wygląd zakładki bierze się
   z `.context-tab` (19-modale-tresc) — tu tylko układ i sygnał „są pliki". */
.presentation-tabs { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.presentation-tab.is-ready { color: var(--ok-strong); }
.presentation-tab.is-ready::after { content: ""; display: inline-block; width: var(--s-2); height: var(--s-2); margin-left: var(--s-1); border-radius: var(--r-pill); background: var(--ok); vertical-align: middle; }
.presentation-tab-panel { display: none; min-height: 0; }
.presentation-tab-panel.is-active { display: flex; flex-direction: column; min-height: 0; }
/* Instrukcja wgrywania nad listą plików (np. wymagany .zip z eksportu 3DVista). */
.presentation-tab-note { margin: var(--s-2) 0; color: var(--text-muted); line-height: var(--lh-base); }
.presentation-tab-note code { padding: 0 var(--s-1); border-radius: var(--r-sm); background: var(--surface-3); font-family: var(--font-mono); font-size: var(--t-xs); }
/* === 3. LISTA ATRAKCJI — popover nad wierszem konstrukcji =================
   position:fixed, bo pozycję wylicza skrypt względem klikniętej komórki. */
.offer-attractions-popover { position: fixed; z-index: var(--z-dymek); overflow: hidden; max-height: min(360px, calc(100vh / var(--skala-ui) - var(--s-5))); border: 1px solid var(--line-strong); border-radius: var(--r); background: var(--surface); box-shadow: var(--cien-2); }
.offer-attractions-popover-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s-3); padding: var(--s-2) var(--s-3); border-bottom: 1px solid var(--line); background: var(--surface-2); }
.offer-attractions-popover-head strong { font-weight: var(--w-bold); }
.offer-attractions-popover-head span { color: var(--text-muted); font-size: var(--t-xs); }
.offer-attractions-popover-list { display: grid; gap: var(--s-1); max-height: 288px; overflow: auto; padding: var(--s-2); }
.offer-attractions-popover-list p { color: var(--text-muted); }
/* Wiersz: nazwa atrakcji + licznik sztuk w pigułce po prawej. */
.offer-attractions-popover-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: var(--s-2); padding: var(--s-1) var(--s-2); border: 1px solid var(--line); border-radius: var(--r-sm); }
.offer-attractions-popover-row span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.offer-attractions-popover-row strong { min-width: var(--s-5); padding: 0 var(--s-2); border-radius: var(--r-pill); background: var(--accent-soft); color: var(--accent-strong); font-size: var(--t-xs); font-weight: var(--w-bold); text-align: center; }
/* === 4. DEMOGRAFIA I ROI (WorldPop) ======================================
   Analiza siedzi w rozwijanym panelu okna projektu. Karty (mapa, miasto,
   promienie) mają jeden szkielet: ramka + nagłówek z linią + treść. */
.project-population-panel { overflow: hidden; border: 1px solid var(--line-strong); border-radius: var(--r); background: var(--surface); }
.project-population-panel > summary { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: var(--s-3); min-height: var(--h-control); padding: var(--s-2) var(--s-3); border-bottom: 1px solid var(--line); background: var(--surface-2); font-weight: var(--w-bold); cursor: pointer; list-style: none; }
.project-population-panel > summary::-webkit-details-marker { display: none; }
/* Strzałka jako chevron Lucide (13.09.2026 — był znak ▸/▾ z czcionki zastępczej), obrót przy rozwinięciu. */
.project-population-panel > summary::before { content: ""; width: 14px; height: 14px; background-color: var(--accent-strong); -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m9 18 6-6-6-6'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m9 18 6-6-6-6'/%3E%3C/svg%3E") center / contain no-repeat; transition: transform var(--szybko) ease; }
.project-population-panel[open] > summary::before { transform: rotate(90deg); }
/* Ostrzeżenie po prawej stronie nagłówka (np. brak adresu instalacji). */
.project-population-panel > summary > small { justify-self: end; color: var(--danger); font-size: var(--t-xs); }
.project-population-panel.is-empty > summary { border-bottom: 0; }
.project-population-panel[open].is-empty > summary { border-bottom: 1px solid var(--line); }
.project-population-body { display: grid; gap: var(--s-3); padding: var(--s-3); }
.project-population-meta, .project-population-empty { display: grid; gap: var(--s-1); padding: var(--s-2) var(--s-3); border: 1px solid var(--line); border-radius: var(--r); background: var(--surface-2); }
.project-population-meta small { color: var(--text-muted); font-size: var(--t-xs); }
/* Brak danych to nie awaria, tylko ostrzeżenie — stąd ton pomarańczowy. */
.project-population-empty { border-color: var(--warn-strong); background: var(--warn-soft); color: var(--warn-strong); }
/* Karty sekcji i ich nagłówki: jedna definicja dla mapy, miasta i promieni. */
.project-population-map-card, .project-population-city, .project-population-radius { overflow: hidden; border: 1px solid var(--line-strong); border-radius: var(--r); background: var(--surface); }
.project-population-map-card > header, .project-population-city > header, .project-population-radius > header, .project-population-section-title { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: var(--s-3); padding: var(--s-2) var(--s-3); border-bottom: 1px solid var(--line); background: var(--accent-soft); }
.project-population-map-card > header strong, .project-population-city > header strong, .project-population-radius > header strong, .project-population-section-title strong { display: block; font-weight: var(--w-bold); }
.project-population-map-card > header span, .project-population-city > header span, .project-population-section-title span { justify-self: end; max-width: 420px; color: var(--text-muted); font-size: var(--t-xs); text-align: right; }
.project-population-city > header b, .project-population-radius > header span { justify-self: end; font-weight: var(--w-bold); }
/* J1: suma narastająca strefy dojazdu („Łącznie do tej granicy”) — pod nagłówkiem pasma, na całą szerokość. */
.project-population-radius > header small { grid-column: 1 / -1; color: var(--text-muted); font-size: var(--t-xs); }
.project-population-map-card.is-empty > header { border-bottom: 0; background: var(--warn-soft); }
/* Tytuł grupy stoi samodzielnie — dostaje własną ramkę zamiast należeć do karty. */
.project-population-section-title { border: 1px solid var(--line-strong); border-radius: var(--r); }
.project-population-city.is-empty { display: grid; gap: var(--s-1); padding: var(--s-3); }
.project-population-radius-list { display: grid; gap: var(--s-3); }
/* Mapa: kafle rastrowe + warstwa SVG. J3 (27.09.2026): kolory z palety stref (tokeny --strefa-*, 00-tokens.css) —
   ta sama paleta w legendzie, na liście stref, w PDF i na slajdzie „Rynek”. Kafle są jasne w obu motywach, więc
   linie, halo i podpisy nie zależą od motywu; granica miasta grafitowa, przerywana. */
.project-population-map { position: relative; height: clamp(300px, 48vw / var(--skala-ui), 410px); overflow: hidden; background: var(--surface-3); isolation: isolate; }
.project-population-map-tiles, .project-population-map-overlay { position: absolute; inset: 0; }
.project-population-map-tiles { z-index: 1; }
.project-population-map-tile { position: absolute; width: 256px; height: 256px; max-width: none; user-select: none; }
/* Warstwa rysunku nie łapie myszy — pod nią przeciąga się mapę. */
.project-population-map-overlay { z-index: 2; pointer-events: none; }
/* SVG nie dziedziczy currentColor, więc fill/stroke podajemy wprost. Pasmo = strefa minus strefa wewnętrzna
   (evenodd) — nakładające się strefy nie robią brudnej plamy, a ulice i nazwy widać przez 14 % koloru. */
.project-population-map-band { fill: var(--strefa); fill-opacity: 0.14; fill-rule: evenodd; stroke: none; }
.project-population-map-boundary-halo, .project-population-map-ring-halo { fill: none; stroke: var(--strefa-halo); stroke-opacity: 0.9; stroke-width: 5; stroke-linejoin: round; stroke-linecap: round; }
.project-population-map-boundary { fill: none; stroke: var(--strefa-granica); stroke-width: 2; stroke-dasharray: 7 5; stroke-linejoin: round; }
.project-population-map-ring { fill: none; stroke: var(--strefa); stroke-width: 2.4; stroke-linejoin: round; stroke-linecap: round; }
:is(.project-population-map-band, .project-population-map-ring, .project-population-map-label, .project-population-map-legend i, .project-population-radius).is-strefa-1 { --strefa: var(--strefa-1); }
:is(.project-population-map-band, .project-population-map-ring, .project-population-map-label, .project-population-map-legend i, .project-population-radius).is-strefa-2 { --strefa: var(--strefa-2); }
:is(.project-population-map-band, .project-population-map-ring, .project-population-map-label, .project-population-map-legend i, .project-population-radius).is-strefa-3 { --strefa: var(--strefa-3); }
:is(.project-population-map-band, .project-population-map-ring, .project-population-map-label, .project-population-map-legend i, .project-population-radius).is-strefa-4 { --strefa: var(--strefa-4); }
/* Etykieta „siedzi” na brzegu strefy — stąd przesunięcie o połowę własnego rozmiaru. Tło w kolorze strefy, biały napis
   (≥ 4,5 : 1 w każdej z czterech barw) i jasna obwódka, żeby odcinała się od kafli. */
.project-population-map-label { position: absolute; z-index: 3; min-width: var(--s-7); padding: var(--s-1); border: 2px solid var(--strefa-halo); border-radius: var(--r-pill); background: var(--strefa, var(--strefa-2)); box-shadow: var(--cien-1); color: var(--strefa-halo); font-size: var(--t-xs); font-weight: var(--w-bold); line-height: 1; text-align: center; white-space: nowrap; transform: translate(-50%, -50%); pointer-events: none; }
/* Punkt instalacji — jasna obwódka trzyma go czytelnym na każdym kaflu. */
.project-population-map-center { position: absolute; z-index: 4; width: var(--s-4); height: var(--s-4); border: 3px solid var(--strefa-halo); border-radius: var(--r-pill); background: var(--strefa-punkt); box-shadow: var(--cien-2); transform: translate(-50%, -50%); pointer-events: none; }
/* Legenda w rogu mapy na białym półprzezroczystym tle: kolor + „do 20 min · 196 097 osób” (suma do granicy strefy). */
.project-population-map-legend { position: absolute; left: var(--s-2); bottom: var(--s-2); z-index: 5; display: grid; gap: 2px; max-width: calc(100% - 2 * var(--s-2)); padding: var(--s-1) var(--s-2); border-radius: var(--r-sm); background: color-mix(in srgb, var(--strefa-halo) 90%, transparent); box-shadow: var(--cien-1); color: var(--strefa-napis); font-size: var(--t-xs); font-weight: var(--w-bold); pointer-events: none; }
.project-population-map-legend span { display: flex; align-items: center; gap: var(--s-1); white-space: nowrap; }
.project-population-map-legend i { flex: none; width: 14px; height: 4px; border-radius: 2px; background: var(--strefa); }
.project-population-map-legend i.is-granica { height: 0; border-top: 2px dashed var(--strefa-granica); border-radius: 0; background: none; }
.project-population-map-legend.is-compact { top: var(--s-2); bottom: auto; grid-auto-flow: column; gap: var(--s-2); }
/* Lista stref: kropka w kolorze strefy przy nazwie — widać, który wiersz należy do której linii na mapie (POPR-n45: kropka zamiast paska). */
.project-population-radius[class*="is-strefa-"] > header strong::before { content: ""; display: inline-block; width: 10px; height: 10px; margin-right: var(--s-2); border-radius: var(--r-pill); background: var(--strefa); vertical-align: 1px; }
.project-population-map-attribution { position: absolute; right: var(--s-1); bottom: var(--s-1); z-index: 5; padding: 0 var(--s-1); border-radius: var(--r-sm); background: var(--surface); color: var(--text-muted); font-size: var(--t-xs); }
.project-population-map-loading { position: absolute; inset: 0; display: grid; place-items: center; color: var(--text-muted); }
/* KPI i podsumowanie promieni to paski komórek rozdzielonych linią — wspólna reguła. */
.project-population-kpis, .project-population-radius-summary { display: grid; border-bottom: 1px solid var(--line); }
.project-population-kpis { grid-template-columns: repeat(5, minmax(0, 1fr)); }
.project-population-radius-summary { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.project-population-kpis > div, .project-population-radius-summary span { min-width: 0; padding: var(--s-2) var(--s-3); border-right: 1px solid var(--line); background: var(--surface-2); }
.project-population-kpis > div { display: grid; gap: var(--s-1); }
.project-population-kpis > div:last-child, .project-population-radius-summary span:last-child { border-right: 0; }
.project-population-kpis span { color: var(--text-muted); font-size: var(--t-xs); }
.project-population-kpis strong, .project-population-radius-summary span { font-weight: var(--w-bold); }
.project-population-kpis small { overflow: hidden; color: var(--text-muted); font-size: var(--t-xs); text-overflow: ellipsis; white-space: nowrap; }
/* Wiersz wieku: nazwa | udział | liczba. Tło ciemnieje z wiekiem, żeby dzieci
   (grupa docelowa placu zabaw) były najjaśniejsze i najlepiej widoczne. */
.project-population-age-row { display: grid; grid-template-columns: minmax(92px, 1fr) 90px minmax(118px, auto); align-items: center; gap: var(--s-3); min-height: var(--h-control); padding: var(--s-2) var(--s-3); border-bottom: 1px solid var(--line); }
.project-population-age-row:last-child { border-bottom: 0; }
.project-population-age-row.is-kid { background: color-mix(in srgb, var(--accent) 7%, var(--surface)); }
.project-population-age-row.is-teen { background: var(--surface-2); }
.project-population-age-row.is-adult { background: var(--surface-3); }
.project-population-age-row span { color: var(--text-muted); font-size: var(--t-xs); }
.project-population-age-row b { justify-self: end; font-weight: var(--w-bold); }
.project-population-age-row small { justify-self: end; color: var(--text-muted); font-size: var(--t-xs); }
/* Kreska „poniżej tego progu ROI już nie liczy" — ostrzeżenie, nie zwykły wiersz. */
.project-population-age-divider { display: block; padding: var(--s-2) var(--s-3); border-bottom: 1px solid var(--warn); background: var(--warn-soft); }
.project-population-age-divider span { color: var(--warn-strong); font-size: var(--t-xs); font-weight: var(--w-bold); }
/* === 5. ANALITYKA PREZENTACJI ============================================
   Zakładka Dashboardu: wiersz prezentacji rozwija panel „czas wg sekcji"
   (lewo) + „sesje" (prawo). Kafle i tabela bazowa są w 16-dashboard.css. */
.dash-pres-row { cursor: pointer; }
.dash-pres-row.is-open { background: var(--surface-2); }
.dash-pres-caret { width: var(--s-5); color: var(--text-muted); }
/* Panel szczegółów zajmuje całą komórkę — własny padding komórki by go zdublował. */
.dash-pres-detail-row > td { padding: 0; background: var(--surface-2); }
.dash-pres-detail { display: grid; grid-template-columns: minmax(220px, 280px) minmax(0, 1fr); gap: var(--s-4); padding: var(--s-3) var(--s-4); border-bottom: 1px solid var(--line); }
.dash-pres-detail h4 { margin-bottom: var(--s-2); color: var(--text-muted); font-size: var(--t-sm); }
.dash-pres-detail-msg { padding: var(--s-3) var(--s-4); color: var(--text-muted); }
/* Czas na sekcji: nazwa, pasek proporcjonalny, wartość. Szerokość paska ustawia
   skrypt inline na <i> — CSS daje tylko tor i kolor. */
.dash-sec-list { display: grid; gap: var(--s-2); }
.dash-sec-row { display: grid; gap: var(--s-1); }
.dash-sec-name { font-weight: var(--w-medium); }
.dash-sec-bar { display: block; height: var(--s-2); overflow: hidden; border-radius: var(--r-pill); background: var(--surface-3); }
.dash-sec-bar i { display: block; height: 100%; border-radius: var(--r-pill); background: var(--accent); }
.dash-sec-row b { color: var(--text-muted); font-size: var(--t-xs); font-variant-numeric: tabular-nums; }
/* Sesje: pod-tabela + drobne znaczniki (sekcja, urządzenie, kontekst). */
.dash-subtable td, .dash-subtable th { font-size: var(--t-sm); text-align: left; }
.dash-pres-secs { white-space: normal; }
.dash-pill-sec, .dash-ctx-chip { display: inline-block; margin: 0 var(--s-1) var(--s-1) 0; padding: 0 var(--s-2); border: 1px solid var(--line); border-radius: var(--r-pill); background: var(--surface-2); color: var(--text-muted); font-size: var(--t-xs); font-variant-numeric: tabular-nums; }
.dash-ctx-chip { white-space: nowrap; }
/* Chip aktywności na akcencie — to jedyna wartość, którą się w sesjach porównuje. */
/* Scalone z 16-dashboard 05.08.2026. --ton pochodzil stamtad i karmi reguly
   korzystajace z tonu — dlatego wedruje razem z reszta. */
.dash-chip-act { --ton: var(--accent); border-color: color-mix(in srgb, var(--accent) 38%, transparent); background: color-mix(in srgb, var(--accent) 14%, var(--surface)); color: var(--text); }
.dash-sess-dev { font-weight: var(--w-medium); }
.dash-sess-ctx { margin-top: var(--s-1); line-height: var(--lh-base); }
/* === RESPONSYWNOŚĆ — progi 1180 / telefon (980 nic tu nie zmienia) ======== */
@media (max-width: 1180px) {
  /* Pięć KPI obok siebie robi się nieczytelne; panel sesji traci drugą kolumnę. */
  .project-population-kpis { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .dash-pres-detail { grid-template-columns: minmax(0, 1fr); }
}
:where(:root[data-ui="mobile"]) .modal.presentation-options-modal { width: calc(100vw / var(--skala-ui)); height: calc(100dvh / var(--skala-ui)); }
/* Paski komórek stają się listą — linia rozdzielająca przechodzi z boku na dół. */
:where(:root[data-ui="mobile"]) .project-population-kpis, :where(:root[data-ui="mobile"]) .project-population-radius-summary { grid-template-columns: minmax(0, 1fr); }
:where(:root[data-ui="mobile"]) .project-population-kpis > div, :where(:root[data-ui="mobile"]) .project-population-radius-summary span { border-right: 0; border-bottom: 1px solid var(--line); }
/* PRZ-09: czerwone ostrzeżenie („Adres zmieniony — sprawdź ponownie") pod wynikiem, nie obok — obok zabierało
   prawie całą szerokość i wynik łamał się po jednym słowie w linii, a ostrzeżenie na niego nachodziło. */
:where(:root[data-ui="mobile"]) .project-population-panel > summary > small { grid-column: 2 / -1; justify-self: start; }
:where(:root[data-ui="mobile"]) .project-population-age-row { grid-template-columns: minmax(0, 1fr) auto; }
:where(:root[data-ui="mobile"]) .project-population-age-row small { grid-column: 2; }
/* Nagłówki kart przestają być dwukolumnowe — podpis ląduje pod tytułem. */
:where(:root[data-ui="mobile"]) .project-population-map-card > header, :where(:root[data-ui="mobile"]) .project-population-city > header, :where(:root[data-ui="mobile"]) .project-population-radius > header, :where(:root[data-ui="mobile"]) .project-population-section-title { grid-template-columns: minmax(0, 1fr); }
:where(:root[data-ui="mobile"]) .project-population-map-card > header span, :where(:root[data-ui="mobile"]) .project-population-city > header span, :where(:root[data-ui="mobile"]) .project-population-section-title span { justify-self: start; text-align: left; }
/* --- Populacja: siatka wieku (z dawnego 28, K17) --- */
.project-population-age-grid { display: grid; grid-template-columns: minmax(0, 1fr); }
.presentation-options-form { background: var(--surface-2); }

/* ============================ TRYB PREZENTACJI (G7, 27.09.2026) ============ */
/* Okno na cały ekran (public/js/okna/tryb-prezentacji.js) — duże liczby i dwa wykresy na spotkanie z klientem.
   Skórka W1: szare tło okna, białe grupy. Jeden kolor danych (akcent) — jedna seria na wykres, więc bez legendy;
   wartości podpisane wprost nad słupkami i obok pasków (nie tylko kolorem). */
.modal.tryb-prezentacji-modal { width: calc(100vw / var(--skala-ui) - var(--s-4)); height: calc(100dvh / var(--skala-ui) - var(--s-4)); max-height: none; }
.modal-backdrop:has(> .modal.tryb-prezentacji-modal) { padding: var(--s-2); }
.modal.tryb-prezentacji-modal > header [data-tryb-prezentacji-pelny-ekran] { margin-left: auto; }
.tryb-prezentacji { display: grid; align-content: start; gap: var(--s-4); min-height: 0; padding: 0 var(--s-5) var(--s-5); overflow: auto; }
.tp-liczby { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: var(--s-4); }
.tp-kafelek { display: grid; align-content: start; gap: var(--s-1); padding: var(--s-5); border-radius: var(--grupa-r); background: var(--surface); }
.tp-kafelek strong { color: var(--text); font-size: clamp(var(--t-xl), 2.4vw / var(--skala-ui), var(--t-3xl)); white-space: nowrap; font-weight: var(--w-bold); line-height: 1.1; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.tp-kafelek span { color: var(--text); font-size: var(--t-md); }
.tp-kafelek small { color: var(--text-muted); font-size: var(--t-xs); }
.tp-wykresy { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: var(--s-4); }
.tp-karta { display: grid; align-content: start; gap: var(--s-4); padding: var(--s-5); border-radius: var(--grupa-r); background: var(--surface); }
.tp-karta h3 { font-size: var(--t-lg); font-weight: var(--w-bold); }
/* Słupki: dzieci wg wieku */
.tp-slupki { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: var(--s-3); height: 240px; }
.tp-slupek { display: grid; grid-template-rows: auto minmax(0, 1fr) auto; justify-items: center; gap: var(--s-1); min-width: 0; }
.tp-slupek b { font-size: var(--t-md); font-variant-numeric: tabular-nums; }
.tp-slupek small { color: var(--text-muted); font-size: var(--t-xs); white-space: nowrap; }
.tp-slupek-tor { position: relative; display: block; width: min(64px, 100%); border-bottom: 1px solid var(--line); }
.tp-slupek-tor > span { position: absolute; inset: auto 0 0; border-radius: 4px 4px 0 0; background: var(--accent); }
/* Paski: strefa zabaw i wiek dzieci (oś 0–15 lat) */
.tp-zakresy { display: grid; gap: var(--s-3); }
.tp-zakres { display: grid; grid-template-columns: minmax(96px, 160px) minmax(0, 1fr) 72px; align-items: center; gap: var(--s-3); }
.tp-zakres-nazwa { overflow: hidden; font-size: var(--t-base); text-overflow: ellipsis; white-space: nowrap; }
.tp-zakres b { font-size: var(--t-base); font-variant-numeric: tabular-nums; white-space: nowrap; }
.tp-zakres-tor { position: relative; display: block; height: 14px; border-radius: 4px; background: var(--surface-2); }
.tp-zakres-tor > span { position: absolute; inset-block: 0; border-radius: 4px; background: var(--accent); }
.tp-zakres-os .tp-zakres-tor { height: 16px; background: none; }
.tp-zakres-os i { position: absolute; top: 0; color: var(--text-muted); font-size: var(--t-xs); font-style: normal; transform: translateX(-50%); }
/* Etapy projektu: pasek w kolorze etapu — pełny = gotowy, połowa = w toku, blady = czeka */
.tp-etapy { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: var(--s-2); margin: 0; padding: 0; list-style: none; }
.tp-etapy li { display: grid; gap: var(--s-1); min-width: 0; }
.tp-etap-pasek { height: 8px; border-radius: 4px; background: linear-gradient(90deg, var(--tp-etap) var(--tp-postep, 0%), color-mix(in srgb, var(--tp-etap) 22%, var(--surface-2)) 0); }
.tp-etapy li.is-w-toku { --tp-postep: 50%; }
.tp-etapy li.is-gotowy { --tp-postep: 100%; }
.tp-etapy strong { overflow: hidden; font-size: var(--t-base); text-overflow: ellipsis; white-space: nowrap; }
.tp-etapy small { color: var(--text-muted); font-size: var(--t-xs); }
/* Telefon: okno na cały ekran jak każde, wykresy jeden pod drugim, etapy w dwóch rzędach. */
:root[data-ui="mobile"] .tryb-prezentacji { padding: 0 var(--s-4) var(--s-4); }
:root[data-ui="mobile"] .tp-liczby { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-2); }
/* POPR2-n24: telefon — pasek wieku na całą szerokość pod nazwą strefy (było: tor ok. 55 px między nazwą a „6–25 lat”,
   a liczby osi zlewały się w „0 510152025”). Nazwa i wiek w jednym rzędzie, tor pod nimi; oś pod torem na pełną szerokość. */
:root[data-ui="mobile"] .tp-zakres { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "nazwa wiek" "tor tor"; gap: var(--s-1) var(--s-3); }
:root[data-ui="mobile"] .tp-zakres-nazwa { grid-area: nazwa; }
:root[data-ui="mobile"] .tp-zakres > b { grid-area: wiek; }
:root[data-ui="mobile"] .tp-zakres > .tp-zakres-tor { grid-area: tor; }
:root[data-ui="mobile"] .tp-zakres.tp-zakres-os { grid-template-areas: "tor tor"; }
:root[data-ui="mobile"] .tp-zakres-os > :not(.tp-zakres-tor) { display: none; }
:root[data-ui="mobile"] .tp-zakres-os i:first-child { transform: none; }
:root[data-ui="mobile"] .tp-zakres-os i:last-child { transform: translateX(-100%); }
:root[data-ui="mobile"] .tp-kafelek { padding: var(--s-4); }
:root[data-ui="mobile"] .tp-kafelek strong { font-size: var(--t-xl); white-space: normal; }
/* Telefon nie ma trybu pełnego ekranu dla stron (iPhone) — okno i tak zajmuje cały ekran. */
:root[data-ui="mobile"] [data-tryb-prezentacji-pelny-ekran] { display: none; }
:root[data-ui="mobile"] .tp-wykresy { grid-template-columns: minmax(0, 1fr); }
:root[data-ui="mobile"] .tp-etapy { grid-auto-flow: row; grid-template-columns: repeat(2, minmax(0, 1fr)); }
:root[data-ui="mobile"] .tp-slupki { height: 180px; }
