/* ========================================================================
   TOKENY

   Każdy kolor, promień i odstęp w tym pliku przechodzi przez zmienną —
   wcześniej te same literały (#2e7db5, #f9f9f9, #ddd...) były wpisane
   w kilkudziesięciu miejscach, więc druga wersja kolorystyczna wymagałaby
   przepisania całego arkusza. Motyw zmienia dziś wyłącznie ta jedna sekcja.

   Domyślny motyw jest CIEMNY (:root), jasny to nadpisanie na
   [data-theme="light"] — odwrotnie niż zwykle, bo tak ustaliliśmy dla tego
   serwisu. Wybór użytkownika trafia do localStorage i jest ustawiany na
   <html> jeszcze przed pierwszym malowaniem (patrz skrypt w <head>
   template.html), więc przy jasnym motywie nie ma mignięcia ciemnym tłem.

   prefers-color-scheme celowo NIE jest tu respektowane: skoro domyślny
   motyw to ciemny niezależnie od systemu, to dodanie media query tylko
   rozjechałoby wartość domyślną z tym, co pokazuje przełącznik. */
:root {
    color-scheme: dark;

    --bg: #0f1720;
    --surface: #17212c;
    --surface-2: #1e2a37;
    --surface-3: #26333f;
    --surface-raised: #1b2634;

    --border: #2b3947;
    --border-soft: #222e3a;
    --border-strong: #3a4a5a;
    --border-brand: #2c4459;

    --text-strong: #f1f5f9;
    --text: #dbe4ed;
    --text-muted: #9fb0c0;
    --text-faint: #7b8b9a;

    /* Jaśniejszy niż marka z motywu jasnego (#1f6fa8): na ciemnym tle ten
       sam granat spadłby poniżej kontrastu 4.5:1 dla tekstu linków. */
    --brand: #58b0e8;
    --brand-hover: #82c6f2;
    --brand-strong: #8fcdf5;
    --brand-soft: #1b2f41;
    --brand-soft-2: #21394d;
    --brand-selected: #24425a;
    --on-brand: #08131c;
    --on-inverse: #f1f5f9;

    --table-head-bg: #223140;
    --tooltip-bg: #0b141c;
    --danger: #ff6b6b;
    --warning: #ffa94d;
    --accent-highlight: #ffc94d;
    --flame-bg: #1e2b3a;
    --flame-border: #32465c;

    /* Kolor ikony rybki w kalendarzu brań i lewego akcentu kart gatunków —
       patrz komentarz przy .species-card niżej. W motywie ciemnym musi być
       jaśniejszy niż w jasnym, żeby akcent nie zlał się z tłem karty. */
    --accent-fish: #8fbe3a;
    /* Rybki słabszych okresów ("słabe", "przeciętne") — żółtawy odcień, inny
       niż pomarańczowe --warning ("ochrona"). Kontrast z tłem >= 3:1. */
    --accent-fish-weak: #d4b94a;
    --cat-water: #43c07a;

    /* Mapa: Leaflet dostaje te wartości JS-em (patrz readMapTheme()
       w app.js), bo kolory regionów ustawia się obiektem stylu, a nie CSS-em. */
    --map-bg: #111b25;
    --map-region: #3a6a8c;
    --map-region-hover: #55a0cc;
    --map-region-selected: #6cc2f5;
    --map-region-border: #0f1720;

    /* Na ciemnym tle cień prawie nie istnieje — warstwy rozdziela tu przede
       wszystkim jaśniejsze tło i ramka, więc cienie są subtelne i służą
       tylko elementom naprawdę unoszonym (banner cookie, lightbox). */
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
    --shadow-md: 0 4px 16px rgba(0, 0, 0, 0.45);

    --radius-xs: 6px;
    --radius-sm: 8px;
    --radius: 12px;

    /* Skala odstępów 4/8/12/16/24/32 — wcześniej w arkuszu mieszały się
       2, 4, 6, 8, 10, 12, 14, 16, 18 i 20px bez żadnego rytmu. */
    --space-1: 4px;
    --space-2: 8px;
    --space-3: 12px;
    --space-4: 16px;
    --space-5: 24px;
    --space-6: 32px;

    /* Skala typograficzna. Wcześniej wszystko mieściło się między 0.85rem
       a 1.1rem — h1 był praktycznie tej samej wielkości co akapit, więc
       strona nie miała hierarchii. Nagłówki tabel danych zostają małe
       (osobne reguły niżej): tam liczy się gęstość, nie skala. */
    --fs-h1: clamp(1.5rem, 1.15rem + 1.4vw, 1.95rem);
    --fs-h2: clamp(1.15rem, 1.02rem + 0.5vw, 1.35rem);
    --fs-h3: 1.05rem;
    --fs-body: 1rem;
    --fs-sm: 0.9rem;
    --fs-xs: 0.82rem;
}

:root[data-theme="light"] {
    color-scheme: light;

    --bg: #ffffff;
    --surface: #f6f8fa;
    --surface-2: #eef2f6;
    --surface-3: #e3eaf1;
    --surface-raised: #ffffff;

    --border: #dde4ec;
    --border-soft: #e9eef3;
    --border-strong: #c6d1dc;
    --border-brand: #cfe0ee;

    --text-strong: #0f1b26;
    --text: #1f2d3a;
    --text-muted: #5a6b7b;
    --text-faint: #7d8c9a;

    /* Ciemniejszy niż dawne #2e7db5, które na białym tle dawało 3.9:1 —
       poniżej progu AA dla tekstu. Ten ma 5.1:1. */
    --brand: #1f6fa8;
    --brand-hover: #16547f;
    --brand-strong: #16547f;
    --brand-soft: #eaf2f9;
    --brand-soft-2: #dfecf6;
    --brand-selected: #d3e6f4;
    --on-brand: #ffffff;
    --on-inverse: #ffffff;

    --table-head-bg: #2c3e50;
    --tooltip-bg: #2e3a45;
    --danger: #b00020;
    --warning: #b35309;
    --accent-highlight: #d98324;
    --flame-bg: #eff4f9;
    --flame-border: #d5e3f0;

    --accent-fish: #769e27;
    --accent-fish-weak: #9a8214;
    --cat-water: #1e8f52;

    --map-bg: #eef3f8;
    --map-region: #9cc8e4;
    --map-region-hover: #5ba3d4;
    --map-region-selected: #1f6fa8;
    --map-region-border: #ffffff;

    --shadow-sm: 0 1px 2px rgba(16, 32, 48, 0.06);
    --shadow-md: 0 4px 16px rgba(16, 32, 48, 0.12);
}

/* Ikona oceny w kalendarzu brań: sylwetka drapieżnika (spiczasty pysk,
   wklęsła linia grzbietu) narysowana WPROST pod ~18 px w siatce 24x24 —
   nie zmniejszona z większego rysunku. Poprzednie podejście (obrys
   wytrasowany z logotypu) miało pełny detal płetw i przy tym rozmiarze
   zlewało się w plamę; ten kształt sprawdzony był pikselowo w 1x na
   ekranie bez retiny w kilku wariantach rozmiaru/grubości, zanim trafił
   tutaj. Zaokrąglone, "słodkie" kontury (poprzednia rybka logotypu)
   celowo odrzucone — to one czytały się jako infantylne, nie sama
   konwencja rybek (którą i konkurencyjne serwisy wędkarskie stosują).

   Maska CSS, nie <img>/inline <svg> per ikona: w kalendarzu potrafi być
   kilkadziesiąt komórek, każda z 1-5 ikonami — osobne znaczniki SVG
   dorzuciłyby kilka kB do indeksowanego HTML-a, a maska kosztuje jedną
   deklarację w arkuszu i ~45 znaków znacznika na ikonę. Kolor niesie
   background-color (nie fill w SVG), więc ikona sama podąża za motywem
   przez --accent-fish. */
:root {
    --fish-mask: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%3E%3Cpath%20fill-rule='evenodd'%20fill='%23000'%20d='M23%2012C20%208.5%2016.5%206.2%2012.5%205.6C9.4%205.1%206.9%206.8%205.7%209.4L1%205.6L2.7%2012L1%2018.4L5.7%2014.6C6.9%2017.2%209.4%2018.9%2012.5%2018.4C16.5%2017.8%2020%2015.5%2023%2012ZM16.8%2010.1a1.4%201.4%200%201%200%200.01%200Z'/%3E%3C/svg%3E");
}

.fish-icon {
    display: inline-block;
    width: 18px;
    height: 18px;
    vertical-align: -3px;
    background-color: var(--accent-fish);
    -webkit-mask: var(--fish-mask) center / contain no-repeat;
    mask: var(--fish-mask) center / contain no-repeat;
    flex: 0 0 auto;
}

.fish-icon + .fish-icon {
    margin-left: 2px;
}

.fish-icon--weak {
    background-color: var(--accent-fish-weak);
}

* {
    box-sizing: border-box;
}

html {
    /* Skok do kotwicy (#faq i odsyłacze wewnątrz strony) dostawiał docelowy
       nagłówek dokładnie do górnej krawędzi okna, bez ani piksela oddechu. */
    scroll-padding-top: var(--space-5);
}

body {
    /* Gołe "sans-serif" na Windows/Mac/iPhone ląduje na Arial/Helvetica —
       obie mają tylko wagi 400 i 700, więc .tab-btn { font-weight: 500 }
       niżej po cichu cofałoby się do 400 (font bez wariantu 500 dostaje
       najbliższy dostępny — reguła z CSS Fonts, nie błąd przeglądarki) i
       zmiana byłaby niewidoczna na 3 z 4 docelowych systemów. Ten stos
       wymusza font systemowy z prawdziwą wagą medium wszędzie, gdzie jest
       dostępny: San Francisco na Mac/iPhone, Roboto na Androidzie (oba mają
       realne 500), Segoe UI na Windows z fallbackiem na Arial na resztę. */
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
        "Helvetica Neue", Arial, sans-serif;
    /* Wyśrodkowanie treści przeniosło się z <body> do .shell: nagłówek
       i stopka mają dziś tło na pełną szerokość okna, a samo body nie może
       być już kolumną 1100px, bo wtedy to tło kończyłoby się razem z nią. */
    margin: 0;
    padding: 0;
    background: var(--bg);
    color: var(--text);
    font-size: var(--fs-body);
    line-height: 1.6;
    -webkit-text-size-adjust: 100%;
    /* Stopka przy dolnej krawędzi okna także na krótkich stronach (kontakt,
       404): bez tego wisiała w połowie ekranu z pustym tłem pod spodem.
       Banner cookie i lightbox są position: fixed, więc wypadają z układu
       i nie liczą się jako kolumny tego flexa. */
    min-height: 100dvh;
    display: flex;
    flex-direction: column;
}

/* Kolumna treści — to, czym wcześniej było samo <body>. */
.shell {
    /* body jest teraz flex column (patrz wyżej), a .shell jednym z jego
       elementów. margin: 0 auto na cross-axis wyłącza domyślne stretch, więc
       bez jawnego width .shell wracał do shrink-to-fit po treści (szerokość
       najszerszego dziecka, np. mapy w układzie wierszowym) zamiast do
       szerokości viewportu — stąd rozjazd layoutu i mapa "uciekająca" poza
       ekran na wąskich telefonach. */
    width: 100%;
    max-width: 1100px;
    margin: 0 auto;
    padding: 0 var(--space-4);
}

main.shell {
    padding-top: var(--space-5);
    padding-bottom: var(--space-6);
    /* Rozpycha kolumnę body (flex) tak, żeby stopka usiadła przy dolnej
       krawędzi okna nawet na krótkiej stronie. */
    flex: 1 0 auto;
}

/* Liczby w tabelach i podsumowaniach mają równą szerokość znaku, więc
   kolumny ocen/temperatur/ciśnień nie "drgają" między wierszami. */
.calendar-table,
.meteogram-table,
#dailyWeatherTable,
.forecast-summary,
#forecastInfo {
    font-variant-numeric: tabular-nums;
}

/* ========================================================================
   NAGŁÓWEK

   Do tej pory <body> zaczynał się wprost od paska zakładek — strona nie
   miała ani nazwy, ani żadnego znaku firmowego, co jest bodaj najmocniejszym
   sygnałem "to prototyp, nie serwis". Nagłówek niesie markę, nawigację
   i przełącznik motywu. */
/* position+z-index (nie samo position) izoluje nagłówek we własnym
   kontekście warstwowania — bez tego dawne .tab-submenu (z-index: 30) przegrywało
   z panelami Leaflet (#map, patrz mapa województw): #map/.map-column mają
   position:relative BEZ z-index, więc same nie izolują, a wewnętrzne panele
   Leaflet dostają z-index 200–700 wprost od biblioteki. Te 200–700 bąbelkowały
   więc aż do document roota i tam ubijały podmenu mimo z-index:30 na nim —
   30 przegrywa ze 200+ niezależnie od tego, że podmenu jest w DOM PO mapie.
   800: wyżej niż najwyższy pas Leaflet (700), niżej niż .cookie-consent
   (1000) i lightbox zdjęć (2000) — nagłówek ma być nad treścią strony, nie
   nad kontrolkami, które i tak nakładają się na wszystko. */
.site-header {
    position: relative;
    z-index: 800;
    background: var(--bg);
    border-bottom: 1px solid var(--border);
}

.site-header-bar {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding-top: var(--space-3);
    padding-bottom: var(--space-3);
}

.brand {
    display: flex;
    align-items: center;
    gap: 10px;
    /* Odpycha przełącznik motywu do prawej krawędzi bez dodatkowego
       kontenera pomiędzy. */
    margin-right: auto;
    color: var(--text-strong);
    text-decoration: none;
}

/* Znak firmowy: logotyp "głębia" (rybka w granatowym krążku z pierścieniem
   w kolorze marki). Celowo TEN SAM plik co favicon — /favicon.png, 128 px,
   4,5 kB — a nie osobna kopia w /static: to dokładnie ten sam obraz, więc
   druga kopia znaczyłaby tylko tyle, że kiedyś jedna z nich zostanie
   zaktualizowana, a druga nie.

   Raster, nie inline SVG: badge ma gradientowy krążek, pierścień i pełny
   rysunek rybki — jako ścieżki wektorowe wyszedłby cięższy niż ten PNG.
   Granatowy krążek działa na obu motywach, więc znak nie musi zmieniać
   koloru; rozmiary są w atrybutach width/height w HTML-u, żeby układ nie
   przeskakiwał przed wczytaniem obrazka. */
.brand-mark {
    flex: 0 0 auto;
    width: 32px;
    height: 32px;
}

.brand-text {
    display: flex;
    flex-direction: column;
    line-height: 1.2;
}

.brand-name {
    font-size: 1.05rem;
    font-weight: 600;
    letter-spacing: -0.01em;
}

.brand-tagline {
    font-size: 0.75rem;
    color: var(--text-muted);
}

.brand:hover .brand-name {
    color: var(--brand);
}

.theme-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* 40px to cel dotyku zgodny z WCAG 2.5.5, tak jak .tab-btn niżej. */
    width: 40px;
    height: 40px;
    flex: 0 0 auto;
    padding: 0;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--surface);
    color: var(--text-muted);
    cursor: pointer;
}

.theme-toggle:hover {
    border-color: var(--brand);
    color: var(--brand);
}

.theme-toggle:focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: 2px;
}

.theme-toggle svg {
    width: 20px;
    height: 20px;
}

/* Przełącznik pokazuje motyw, na KTÓRY przełącza, a nie ten, który jest
   włączony: w ciemnym widać słońce ("włącz jasny"), w jasnym księżyc.
   Obie ikony są w HTML-u, CSS chowa nieaktualną — dzięki temu ikona jest
   poprawna już w pierwszej klatce, bez czekania na JS. */
.theme-toggle .icon-light { display: none; }
.theme-toggle .icon-dark { display: block; }
:root[data-theme="light"] .theme-toggle .icon-light { display: block; }
:root[data-theme="light"] .theme-toggle .icon-dark { display: none; }

.about-section {
    /* 960px jak treść pozostałych podstron (strona główna, kalendarze,
       gatunki) — artykuły z 720px wyglądały na węższe niż reszta serwisu. */
    max-width: 960px;
    margin: 0 0 var(--space-5);
    padding: var(--space-4) var(--space-5);
    background: var(--surface);
    border: 1px solid var(--border-soft);
    border-radius: var(--radius);
}

.about-section:last-child {
    margin-bottom: 0;
}

.about-section h1 {
    font-size: var(--fs-h1);
    line-height: 1.2;
    letter-spacing: -0.015em;
    margin: 0 0 var(--space-3);
    color: var(--text-strong);
}

.about-section .intro {
    font-size: 1.05rem;
    color: var(--text);
    margin: 0 0 var(--space-4);
    line-height: 1.6;
}

.about-section h2 {
    font-size: var(--fs-h2);
    line-height: 1.3;
    letter-spacing: -0.01em;
    margin: var(--space-5) 0 var(--space-2);
    color: var(--text-strong);
}

.about-section h3 {
    font-size: var(--fs-h3);
    margin: var(--space-4) 0 var(--space-1);
    color: var(--text-strong);
}

.about-section p {
    margin: 0 0 var(--space-3);
    font-size: var(--fs-body);
    line-height: 1.65;
    color: var(--text-muted);
}

.about-section ul {
    margin: 0 0 var(--space-3);
    padding-left: var(--space-5);
    font-size: var(--fs-body);
    line-height: 1.65;
    color: var(--text-muted);
}

.about-section li {
    margin-bottom: 2px;
}

/* Zdjęcie gatunku obok akapitu, w tej samej wąskiej .about-section co reszta
   prozy (patrz komentarz przy .tab-panel[data-tab-panel="species"] niżej) —
   w odróżnieniu od katalogu gatunków ryb to nie osobna karta, tylko lekki
   dodatek do istniejącego akapitu, więc miniatura jest mniejsza i nie
   poszerza kolumny. */
.plant-blurb {
    display: flex;
    gap: 12px;
    align-items: flex-start;
    margin: 0 0 8px;
}

.plant-blurb img {
    flex: 0 0 84px;
    width: 84px;
    height: auto;
    border-radius: var(--radius-sm);
    /* Bez tła — ten sam powód co .species-media img: większość tych zdjęć
       (poza rzęsą wodną, która i tak jest pełnokadrowa) to wycinanki RGBA na
       przezroczystym tle, a wymuszone tu #fff rysowało biały prostokąt na
       lekko szarym tle .about-section (#f9f9f9) zamiast dać roślinie wtopić
       się w kartę. */
    cursor: zoom-in;
}

.plant-blurb p {
    margin: 0;
    flex: 1;
    min-width: 0;
}

@media (max-width: 480px) {
    .plant-blurb img {
        flex-basis: 64px;
        width: 64px;
    }
}

.table-scroll {
    overflow-x: auto;
}

.fish-food-table {
    width: 100%;
    border-collapse: collapse;
    margin: var(--space-5) 0;
    box-shadow: var(--shadow-sm);
    font-size: clamp(0.72rem, 0.62rem + 0.5vw, 0.9rem);
}

.fish-food-table th,
.fish-food-table td {
    padding: clamp(6px, 1vw, 15px) clamp(6px, 1.2vw, 15px);
    border: 1px solid var(--border);
    text-align: left;
}

.fish-food-table thead tr {
    background: var(--table-head-bg);
    color: var(--on-inverse);
    font-weight: bold;
}

.fish-food-table tbody tr:nth-child(even) {
    background: var(--surface);
}

.fish-food-table tbody tr:last-child {
    border-bottom: 2px solid var(--table-head-bg);
}

.fish-food-table .cat-tree {
    font-weight: bold;
    color: var(--text-faint);
}

.fish-food-table .cat-water {
    font-weight: bold;
    color: var(--cat-water);
}

/* Zielony jak ikona rybki (--accent-fish) — dawniej niebieski, osobny
   odcień, który zrywał spójność z resztą rybnych akcentów serwisu. */
.fish-food-table .species-fish {
    font-weight: bold;
    color: var(--accent-fish);
}

.fish-food-table .species-latin {
    color: var(--text-faint);
}

/* Odsyłacze do kart gatunków w /gatunki-ryb, wstawiane w treści kalendarza
   wędkarskiego (tabele pokarmowe i akapity "Żerujące ryby: …") wszędzie
   tam, gdzie pada nazwa gatunku mającego własną kartę. Ten sam zielony co
   --accent-fish, żeby rybka-ikona, kolumna gatunków w tabeli i te odsyłacze
   czytały się jako jeden, spójny system, nie trzy różne konwencje kolorów. */
.fish-link {
    color: var(--accent-fish);
    font-weight: inherit;
    text-decoration: underline;
    text-underline-offset: 2px;
}

.fish-link:hover,
.fish-link:focus-visible {
    color: var(--cat-water);
}

/* Bez wąskiej kolumny obok mapy (patrz .map-column w template.html) #details
   ma do dyspozycji całą szerokość .layout, więc katalog gatunków i kalendarz
   sezonowy — jedyne dwie zakładki bez mapy — mogą z tej szerokości
   skorzystać zamiast zostawać przy domyślnych 720px z .about-section:
   pierwszy ma karty ze zdjęciem obok opisu, drugi (na żądanie) ma wyglądać
   tak samo szeroko jak katalog gatunków, żeby obie bezmapowe zakładki były
   spójne.

   FAQ (fishing) i "Pogoda we wrześniu" (weather) dochodzą z tego samego
   powodu, mimo że te zakładki mapę mają: oba akapity mieszkają w osobnym,
   PEŁNOSZEROKIM panelu narzędziowym pod mapą (patrz "Narzędzia pełnej
   szerokości" w template.html), nie w wąskiej kolumnie obok niej — mapa
   u góry strony nie zabiera im miejsca. Bez tej reguły to jedyny akapit
   w całym panelu węższy niż kalendarz/tabele/forecastInfo/CTA dookoła. */
.tab-panel[data-tab-panel="species"] .about-section,
.tab-panel[data-tab-panel="seasonal"] .about-section,
.tab-panel[data-tab-panel="fishing"] .about-section,
.tab-panel[data-tab-panel="weather"] .about-section {
    max-width: 960px;
}

/* Katalog gatunków: tutaj .about-section jest kontenerem CAŁEJ strony, a nie
   kartą — kartami są poszczególne gatunki niżej. Bez zdjęcia chromu karta
   siedziałaby w karcie i żadna nie odcinałaby się od drugiej. */
.tab-panel[data-tab-panel="species"] .about-section {
    background: none;
    border: none;
    padding-left: 0;
    padding-right: 0;
}

.species-list {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    margin-top: var(--space-5);
}

/* Każdy gatunek to osobna karta. Zieloną kreskę rozdzielającą karty zastąpił
   akcent na lewej krawędzi — ten sam odcień (patrz --accent-fish), więc
   związek z ikoną rybki z kalendarza brań zostaje, ale nie dubluje się już
   z krawędzią samej karty. */
.species-card {
    display: flex;
    gap: var(--space-4);
    padding: var(--space-4);
    background: var(--surface);
    border: 1px solid var(--border-soft);
    border-left: 3px solid var(--accent-fish);
    border-radius: var(--radius);
}

.species-media {
    flex: 0 0 200px;
}

.species-media img {
    width: 100%;
    height: auto;
    display: block;
    border-radius: var(--radius-sm);
    /* Bez tła: pliki w /static/ryby/ to gotowe wycinanki na przezroczystym
       tle (RGBA, nie spłaszczone do białego), a #f9f9f9 karty (.about-section)
       jest lekko szare — wymuszone tu #fff rysowało więc widoczny biały
       prostokąt wokół każdej ryby zamiast wtapiać ją w tło karty. */
    cursor: zoom-in;
}

/* .species-media, nie sama klasa: karty gatunków siedzą w .about-section,
   a ".about-section p" (klasa+element, specyficzność 0,1,1) bije samą
   klasę ".species-photo-credit" (0,1,0) i nadpisywał tu font-size/margin/
   line-height/color, mimo że ta reguła jest niżej w pliku. */
.species-media .species-photo-credit {
    margin: var(--space-2) 0 0;
    font-size: 12px;
    line-height: 1.3;
    color: var(--text-faint);
    text-align: center;
}

/* Wspólny wygląd dla przypisów gatunków i disclaimerów prawnych na dole
   treści (prognozy/poradniki) — ta sama, przygaszona "drobna czcionka"
   niezależnie od tego, na jakiej to stronie. */
.page-disclaimer {
    margin: var(--space-3) 0 0;
    padding-top: var(--space-3);
    border-top: 1px solid var(--border);
    font-size: var(--fs-xs);
    color: var(--text-faint);
}

.species-body {
    flex: 1;
    min-width: 0;
}

.species-body h2 {
    font-size: var(--fs-h3);
    margin: 0 0 var(--space-3);
    color: var(--text-strong);
}

.species-latin {
    font-weight: normal;
    font-style: italic;
    color: var(--text-faint);
}

.species-facts {
    margin: 0;
    font-size: var(--fs-sm);
    line-height: 1.6;
    color: var(--text-muted);
}

/* Etykiety pól ("Okres ochronny", "Wymiar ochronny"...) jako drobny nadtytuł,
   nie kolejny pogrubiony akapit — dzięki temu w karcie widać od razu, gdzie
   kończy się jedna pozycja, a zaczyna następna. */
.species-facts dt {
    font-size: var(--fs-xs);
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-faint);
    margin-top: var(--space-3);
}

.species-facts dt:first-child {
    margin-top: 0;
}

.species-facts dd {
    margin: 2px 0 0;
}

.species-conditions {
    margin: 0;
    padding-left: 20px;
}

/* --accent-fish łączy kolor ikony rybki w kalendarzu brań z lewym akcentem
   kart gatunków — jeden odcień na całą "rybią" część serwisu. Kreska <hr>
   między kartami gatunków zniknęła (karty mają teraz własne krawędzie),
   kolor żyje dalej jako lewy akcent .species-card wyżej. */

/* Zdjęcie na górze /gatunki-ryb/<gatunek> — ta sama wycinanka i podpis co
   w karcie (.species-media), tylko większa i w przepływie artykułu. */
.species-media.species-hero {
    max-width: 360px;
    margin: 0 0 var(--space-4);
}

/* Odsyłacz z karty na /gatunki-ryb do pełnej strony gatunku. */
.species-more {
    margin: var(--space-3) 0 0;
    font-weight: 600;
}

@media (max-width: 480px) {
    .species-card {
        flex-direction: column;
    }

    .species-media {
        flex: none;
        max-width: 220px;
    }
}

/* Listing /poradniki: karty w responsywnej siatce, nie w pionowym stosie jak
   .species-list — to spis wielu osobnych tekstów, nie kolejne pozycje jednego
   katalogu, więc siatka lepiej pokazuje, ile ich jest na pierwszy rzut oka. */
.guide-list {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: var(--space-4);
    margin-top: var(--space-4);
}

.guide-card {
    display: flex;
    flex-direction: column;
    padding: var(--space-4);
    background: var(--surface);
    border: 1px solid var(--border-soft);
    border-left: 3px solid var(--accent-fish);
    border-radius: var(--radius);
    text-decoration: none;
    color: inherit;
}

.guide-card:hover {
    border-color: var(--border-strong);
}

.guide-card-title {
    font-size: var(--fs-h3);
    color: var(--text-strong);
    margin: 0 0 var(--space-1);
}

/* Data pierwszej publikacji artykułu — ten sam <time datetime="..."> co
   .guide-byline w samym artykule (patrz porady-i-triki/<slug>.html), więc
   czytelnik widzi ją już na liście, zanim w ogóle otworzy tekst. */
.guide-card-date {
    display: block;
    font-size: var(--fs-xs);
    color: var(--text-faint);
    margin: 0 0 var(--space-2);
}

.guide-card-excerpt {
    font-size: var(--fs-sm);
    color: var(--text-muted);
    line-height: 1.5;
    margin: 0;
}

/* Data/autor pod H1 artykułu z /poradniki — sygnał E-E-A-T, że tekst ma
   realnego autora i datę, nie jest anonimowym wygenerowanym snippetem. */
.guide-byline {
    font-size: var(--fs-xs);
    color: var(--text-faint);
    margin: calc(-1 * var(--space-2)) 0 var(--space-4);
}

.guide-back {
    max-width: 960px;
    margin: 0 0 var(--space-3);
    font-size: var(--fs-sm);
}

/* Zdjęcie w treści poradnika — w przeciwieństwie do .plant-blurb img (mała
   miniatura obok tekstu) to samodzielna ilustracja na całą szerokość kolumny,
   bo poradniki nie mają gęstego katalogu kart, gdzie miniatura musi być mała.
   Klikalne przez tę samą lightboksową listę w app.js (patrz initImageLightbox). */
.guide-image {
    margin: 0 0 var(--space-4);
}

.guide-image img {
    display: block;
    width: 100%;
    height: auto;
    border-radius: var(--radius-sm);
    cursor: zoom-in;
}

.guide-image figcaption {
    margin-top: var(--space-2);
    font-size: var(--fs-xs);
    color: var(--text-faint);
    text-align: center;
}

/* Chmura tagów na stronach miesięcy kalendarza wędkarskiego — słowa kluczowe
   tematu miesiąca (sezon, gatunki, zjawiska). Rozmiar rośnie z .tag-lg/.tag-sm
   tylko wizualnie (efekt "chmury"), nie niesie żadnej semantyki wagi. Tagi bez
   sensownego celu linkowania to <span>, te z nim — <a> tej samej klasy, żeby
   wizualnie nie różniły się od resztu chmury. */
.tag-cloud {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin: 0 0 var(--space-4);
}

.tag-pill {
    display: inline-block;
    padding: 4px 12px;
    background: var(--surface-2);
    border: 1px solid var(--border-soft);
    border-radius: 999px;
    color: var(--text-muted);
    font-size: var(--fs-sm);
    line-height: 1.4;
    text-decoration: none;
}

a.tag-pill:hover {
    border-color: var(--border-strong);
    color: var(--text);
}

.tag-pill.tag-lg {
    font-size: var(--fs-body);
    color: var(--text);
}

.tag-pill.tag-sm {
    font-size: var(--fs-xs);
}

/* Nawigacja między miesiącami na kalendarz-wedkarski/<miesiąc>.html — osobna
   chmura od .tag-cloud tematycznego (sezon/gatunki), więc własna klasa
   .month-nav na kontenerze, ale te samo .tag-pill na pigułkach, żeby obie
   chmury wyglądały jak jedna rodzina komponentów. Aktualny miesiąc to
   .tag-pill.is-current — wypełniony kolorem marki, nie <a> (nie ma sensu
   linkować do strony, na której już się jest). */
.month-nav {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin: 0 0 var(--space-4);
    padding-bottom: var(--space-4);
    border-bottom: 1px solid var(--border-soft);
}

/* Chmura województw (weather/region_pages.py: region_cloud_html) — ten sam
   komponent co pigułki miesięcy, ale stoi na końcu karty, więc bez dolnej
   kreski i odstępu, które w kalendarzu oddzielają pigułki od treści. */
/* Przełącznik województwa na /prognoza-na-weekend — nad treścią, więc z dolną
   kreską jak pigułki miesięcy; nagłówek bez dużego odstępu nad pigułkami. */
.about-section h2.weekend-switcher-title {
    margin-bottom: var(--space-2);
    font-size: var(--fs-body);
}

.month-nav.region-cloud {
    margin-bottom: 0;
    padding-bottom: 0;
    border-bottom: 0;
}

.tag-pill.is-current {
    background: var(--brand);
    border-color: var(--brand);
    color: var(--on-brand);
    font-weight: 600;
}

/* #weatherMonthNav (prognoza-pogody, patrz template.html/app.js) używa
   .tag-pill na <button>, nie na <a>/<span> jak reszta chmur tagów — dopisać
   reset przeglądarkowych domyślnych stylów przycisku (font, cursor), których
   .tag-pill wyżej nigdy nie musiał dotykać. */
button.tag-pill {
    font: inherit;
    cursor: pointer;
    appearance: none;
}

button.tag-pill:hover {
    border-color: var(--border-strong);
    color: var(--text);
}

/* kalendarz-wedkarski/<miesiąc>.html: dwie kolumny desktopowe — treść
   miesiąca (.kalendarz-main) i chmura tematyczna przeniesiona na bok
   (.kalendarz-sidebar), zamiast siedzieć w głównym przepływie tuż pod
   .month-nav. Poniżej @media (max-width: 720px) wraca do jednej kolumny,
   sidebar spada pod główną treść. */
.kalendarz-layout {
    display: grid;
    grid-template-columns: 1fr 260px;
    align-items: start;
    gap: var(--space-5);
    max-width: 960px;
    /* Od lewej, jak reszta podstron — wyśrodkowana siatka zaczynała się
       w innym miejscu niż menu. */
    margin: 0;
}

.kalendarz-main.about-section,
.kalendarz-sidebar.about-section {
    max-width: none;
    margin-bottom: 0;
    /* Domyślne min-width: auto na elemencie siatki każe mu być co najmniej
       tak szeroki, jak jego najszerszy "nieściskalny" potomek (tu: szeroka
       .fish-food-table) — mimo że .table-scroll ma własne overflow-x: auto.
       Bez zera tutaj kolumna główna wypychała całą siatkę poza 960px zamiast
       oddać przewijanie tabeli .table-scroll. */
    min-width: 0;
}

.kalendarz-sidebar-label {
    margin: 0 0 var(--space-2);
    font-size: var(--fs-xs);
    color: var(--text-faint);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.kalendarz-sidebar .tag-cloud {
    margin-bottom: 0;
}

/* Fazy Księżyca miesiąca w jednym poziomym pasku (#moonMonthStrip, wypełniany
   przez initMoonMonthStrip() w app.js) — ten sam .scroll-arrow/.meteogram-container
   co przy meteogramie: strzałki są w ogóle widoczne tylko <=720px (patrz baza
   .scroll-arrow niżej w pliku), więc na desktopie pasek przewija się myszą/
   trackpadem, a na mobile dostaje wyraźną, ale delikatną strzałkę tam, gdzie
   dzień nie mieści się w widoku. */
.moon-strip-container {
    position: relative;
    margin: 0 0 var(--space-4);
}

.moon-strip-scroll {
    display: flex;
    gap: var(--space-2);
    overflow-x: auto;
    scroll-behavior: auto;
    padding: var(--space-2) 2px var(--space-3);
}

/* Ikona (MOON_ICONS — te same emoji co .astro-icon na karcie astronomicznej)
   + widoczna nazwa fazy (MOON_LABELS) + data ze skrótem miesiąca pod spodem
   — nie sam numer dnia, bo w oderwaniu od nagłówka strony był nieczytelny.
   Karta szersza niż poprzednia wersja z samym numerkiem, żeby "Garb
   przybywający" zmieścił się w dwóch liniach bez zawijania na trzy. */
.moon-day {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    flex: 0 0 auto;
    width: 72px;
    padding: var(--space-2) 4px;
    border-radius: var(--radius);
    text-align: center;
}

/* <a>, nie <span> — patrz initMoonMonthStrip w app.js: linkuje do sekcji tej
   fazy w /porady-i-triki/taktyka-na-fazy-ksiezyca. display: block + brak
   podkreślenia, żeby nadal wyglądała jak zwykła ikona, nie jak tekstowy
   link. */
.moon-day-icon {
    display: block;
    font-size: 1.8rem;
    line-height: 1;
    text-decoration: none;
}

/* 0.62rem, nie fs-xs (0.82rem) — nawet najdłuższa nazwa fazy ("Garb
   przybywający"/"Sierp przybywający") musi zmieścić się w dwóch liniach przy
   72px szerokości karty bez ucinania. font-weight na .is-today celowo NIE
   pogrubia nazwy fazy (patrz niżej) — pogrubiony długi wyraz jest szerszy
   i właśnie on nie mieścił się w karcie. */
.moon-day-phase {
    font-size: 0.62rem;
    line-height: 1.2;
    color: var(--text);
    min-height: 2.1em;
    overflow-wrap: break-word;
}

.moon-day-date {
    font-size: var(--fs-xs);
    color: var(--text-faint);
}

.moon-day.is-today {
    background: var(--brand-soft);
}

.moon-day.is-today .moon-day-phase {
    color: var(--brand);
}

.moon-day.is-today .moon-day-date {
    color: var(--brand);
    font-weight: 700;
}

/* Bazowa .scroll-arrow (kółko z białym tłem, patrz niżej w pliku) była
   pomyślana pod meteogram, gdzie stoi nad pustym marginesem tabeli. Tutaj
   krótkie, wąskie karty dni nachodziły na to kółko i wyglądało to źle, więc
   nadpisujemy na sam glif strzałki — bez tła/cienia/obwódki, w kolorze
   tekstu (ciemny na jasnym motywie, jasny na ciemnym, automatycznie przez
   var(--text-strong)), żeby nic nie zasłaniał ikon księżyca pod spodem. */
.moon-strip-container .scroll-arrow {
    background: none;
    box-shadow: none;
    opacity: 1;
    color: var(--text-strong);
    font-size: 1.4rem;
}

.moon-strip-container .scroll-arrow:active {
    color: var(--brand);
}

/* Oddziela sekcję faz Księżyca od reszty treści miesiąca (kalendarz-wedkarski/
   <miesiąc>.html) — --border-soft, nie --border, żeby kreska nie konkurowała
   wzrokowo z nagłówkami h2 poniżej. */
.month-section-divider {
    border: none;
    border-top: 1px solid var(--border-soft);
    margin: var(--space-5) 0;
}

/* Symulator faz Księżyca (porady-i-triki/taktyka-na-fazy-ksiezyca) — dwa widoki:
   "z kosmosu" (Słońce, orbita Księżyca wokół Ziemi) i "z Ziemi" (sama
   sylwetka fazy). Kolory Słońca/Ziemi/Księżyca są NA STAŁE (nie z motywu
   jasny/ciemny) — to realne obiekty astronomiczne, nie elementy UI, więc
   nie mają powodu zmieniać koloru z przełącznikiem motywu. Kontury/linie
   pomocnicze używają var(--on-inverse) — to jedyny token w palecie, który
   jest jasny w OBU motywach (tekst na ciemnym/markowym tle), więc zostaje
   widoczny na ciemnym dysku Księżyca niezależnie od tego, czy strona jest
   akurat w motywie jasnym czy ciemnym. */
.moon-widget {
    max-width: 960px;
    margin: 0 0 var(--space-4);
    padding: var(--space-4) var(--space-5);
    background: var(--surface);
    border: 1px solid var(--border-soft);
    border-radius: var(--radius);
}

.moon-widget-top-labels {
    display: flex;
    justify-content: space-between;
    gap: var(--space-3);
    margin-bottom: var(--space-2);
    font-size: var(--fs-xs);
    color: var(--text-faint);
    text-align: center;
}

.moon-widget-top-labels span:first-child {
    flex: 0 0 68%;
}

.moon-widget-top-labels span:last-child {
    flex: 0 0 28%;
}

.moon-widget-diagram {
    display: block;
    width: 100%;
    height: auto;
}

.moon-widget-sun {
    fill: #f0b93d;
}

.moon-widget-earth {
    fill: var(--brand);
}

.moon-widget-orbit {
    fill: none;
    stroke: var(--on-inverse);
    stroke-opacity: 0.35;
    stroke-width: 1.5;
    stroke-dasharray: 3 4;
}

.moon-widget-divider {
    stroke: var(--on-inverse);
    stroke-opacity: 0.35;
    stroke-width: 1.5;
}

.moon-widget-divider-dashed {
    stroke-dasharray: 3 4;
}

.moon-widget-arrow-line {
    stroke: var(--on-inverse);
    stroke-opacity: 0.6;
    stroke-width: 2;
}

.moon-widget-arrow-head {
    fill: var(--on-inverse);
    fill-opacity: 0.6;
}

.moon-widget-marker-dark,
.moon-widget-phase-base {
    fill: #14171f;
}

.moon-widget-marker-light,
.moon-widget-phase-light {
    fill: #f2ecd9;
}

.moon-widget-phase-outline {
    fill: none;
    stroke: var(--on-inverse);
    stroke-opacity: 0.7;
    stroke-width: 1.5;
}

.moon-widget-bottom-labels {
    display: flex;
    margin-top: var(--space-2);
    font-size: var(--fs-xs);
    color: var(--text-faint);
    text-align: center;
}

.moon-widget-bottom-labels span:nth-child(1) {
    flex: 0 0 15%;
}

.moon-widget-bottom-labels span:nth-child(2) {
    flex: 0 0 48%;
}

.moon-widget-bottom-labels span:nth-child(3) {
    flex: 0 0 22%;
}

.moon-widget-name {
    margin: var(--space-4) 0 var(--space-3);
    padding-top: var(--space-4);
    border-top: 1px solid var(--border-soft);
    text-align: center;
    font-size: var(--fs-h3);
    color: var(--text-strong);
}

.moon-widget-controls {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    font-size: var(--fs-sm);
    color: var(--text-muted);
}

.moon-widget-day-value {
    flex: 0 0 auto;
    min-width: 4.5em;
    color: var(--text-strong);
    font-weight: 600;
}

.moon-widget-controls input[type="range"] {
    flex: 1;
    accent-color: var(--brand);
}

@media (max-width: 480px) {
    .moon-widget-top-labels {
        font-size: 10px;
    }
}

/* Pasek zakładek mieszka teraz w .site-header, więc nie niesie już własnego
   marginesu ani dolnej kreski — odstęp od treści daje padding main.shell,
   a kreskę border-bottom nagłówka. */
.tabs {
    display: flex;
    gap: 0;
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: thin;
}

/* Płaskie menu: zamiast pudełek z zaokrąglonymi rożkami zakładki dzieli
   tylko delikatna pionowa kreska (border-right), a aktywną/najechaną
   wskazuje kolor tekstu i podkreślenie u dołu, nie tło całego przycisku. */
.tab-btn {
    display: inline-block;
    /* 13px pionowo (nie dawne 10px): z font-size 0.9rem daje to ~44px
       całkowitej wysokości przycisku — to dolna granica wygodnego celu
       dotyku wg WCAG 2.5.5 / wytycznych Apple i Google, a menu było
       wcześniej wyraźnie poniżej niej. */
    padding: 13px 18px;
    border: none;
    /* Pionowe kreski między zakładkami zniknęły razem z "pudełkowym" menu —
       zakładki rozdziela dziś sam odstęp, a aktywną wskazuje kolor
       i podkreślenie. Kreski dublowały tę rolę i zagęszczały pasek. */
    border-bottom: 3px solid transparent;
    margin-bottom: -1px;
    background: none;
    border-radius: 0;
    cursor: pointer;
    font-size: var(--fs-sm);
    /* 500 (medium), nie 700 (bold): ma być trochę bardziej widoczne niż
       zwykły tekst, ale zostawić wyraźny odstęp do 600 na .tab-btn.active
       niżej — inaczej spoczynkowa i wybrana zakładka ważyłyby tyle samo
       i menu straciłoby sygnał "który tab jest aktywny". */
    font-weight: 500;
    font-variant: small-caps;
    letter-spacing: 0.03em;
    /* Stonowany kolor w spoczynku, pełny kontrast dopiero na aktywnej
       zakładce niżej: kolor jest tu drugim — obok wagi — nośnikiem sygnału
       "który tab jest wybrany", i jedynym, który zadziała na pewno, nawet
       gdyby font-weight gdzieś po cichu cofnął się do 400 (font bez
       prawdziwej wagi 500 dostaje najbliższą dostępną). */
    color: var(--text-muted);
    white-space: nowrap;
    flex: 0 0 auto;
    text-decoration: none;
}

/* Złamanie etykiety na dwa wyrazy (patrz template.html) — ukryte na desktopie,
   gdzie każda zakładka mieści się w jednej linii. Ukryty <br>, nie tekst
   zawijany naturalnie: naturalne zawijanie łamałoby każdą etykietę przy innej
   szerokości ("Prognoza Pogody" jest krótsza niż pozostałe dwie), więc część
   zakładek miałaby jedną linię, a część dwie — niespójna wysokość paska. Ten
   sam, wymuszony punkt złamania dla wszystkich daje spójny wygląd całego menu
   w każdej szerokości mobilnej. */
.tab-break {
    display: none;
}

.tab-btn:hover {
    background: var(--brand-soft);
    color: var(--brand);
}

.tab-btn:focus-visible,
.link-btn:focus-visible,
.link-btn-inline:focus-visible,
.footer-contact a:focus-visible,
.calendar-table td.clickable:focus-visible,
.meteogram-table th.day-header:focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: 2px;
}

/* Podmenu "Porady i Triki" (trzy pozycje — patrz kolumna HTML w każdym
   <header>). .site-nav (nie .tabs) jest kontekstem pozycjonowania: .tabs ma
   overflow-x: auto (przewijanie zakładek na wąskich ekranach), a overflow
   inny niż "visible" na jednej osi w CSS wymusza klipowanie na obu — rozwinięte
   position:absolute dziecko .tabs byłoby więc ucinane w pionie. .site-nav
   nie ma overflow, więc nie klipuje. */
.site-nav {
    position: relative;
}

.tab-btn.active {
    background: none;
    color: var(--brand);
    border-bottom-color: var(--brand);
    font-weight: 600;
}

.tab-panel {
    display: none;
}

.tab-panel.active {
    display: block;
}

/* Panele "narzędziowe" (kalendarz brań, tabele pogody) pełnej szerokości pod
   .layout — patrz template.html. Bez własnego marginesu zlepiałyby się
   wizualnie z mapą/podsumowaniem tuż nad nimi. */
.tool-section {
    margin-top: 20px;
}

.layout {
    display: flex;
    gap: var(--space-5);
    align-items: flex-start;
}

.map-column {
    flex: 0 0 340px;
    position: relative;
}

#map {
    width: 100%;
    height: 400px;
    /* Bez ramki 2px: gruby, szary obrys sprawiał, że mapa wyglądała jak
       wklejony obrazek w kadrze. Sama mapa jest teraz kartą — tło + delikatna
       ramka w kolorze reszty kart. */
    border: 1px solid var(--border-soft);
    border-radius: var(--radius);
    background: var(--map-bg);

    /* Mapa nie jest przeciągalna (dragging: false w app.js), więc Leaflet nie
       włącza swojej blokady zaznaczania tekstu - a ta włącza się dopiero na
       starcie przeciągania. Bez tego kliknięcie w województwo z minimalnym
       ruchem myszy zaczynało natywne zaznaczanie/przeciąganie grafiki. */
    user-select: none;
    -webkit-user-select: none;
    -webkit-user-drag: none;
    -webkit-tap-highlight-color: transparent;
}

#map.pulse {
    border-color: var(--brand);
}

/* Kliknięcie w województwo ustawia w Chrome fokus na <path> (kształty SVG są
   focusowalne myszą), a domyślny "outline: auto" jest tam malowany jako
   nieprzezroczysty biały prostokąt wielkości bounding boxa województwa,
   przykrywający sąsiednie regiony. Te ścieżki nie mają tabindexu i mapa ma
   keyboard: false, więc fokus nigdy nie przychodzi z klawiatury - nie ma tu
   czego wskazywać i outline można zdjąć bez straty dla dostępności.
   Zaznaczenie widać po kolorze (regionSelectedStyle w app.js). */
#map svg path:focus {
    outline: none;
}

/* Grow a region under the cursor for easier targeting - mouse/trackpad only.
   Touch devices report (hover: none), so this never fires on tap and can't
   cause the iOS "first tap only hovers" double-tap trap. */
@media (hover: hover) and (pointer: fine) {
    #map svg path {
        transition: transform 0.15s ease;
        transform-box: fill-box;
        transform-origin: center;
    }

    #map svg path:hover {
        transform: scale(1.08);
    }
}

.region-tooltip {
    background: var(--tooltip-bg);
    color: var(--on-inverse);
    border: none;
    border-radius: var(--radius-xs);
    padding: 4px 8px;
    font-size: 0.85rem;
    font-weight: 600;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);
}

/* Miasta wojewódzkie na mapie (CITY_MARKERS w app.js): kropka + stały,
   drobny podpis bez dymka. pointer-events: none — klik trafia w województwo. */
.leaflet-interactive.city-dot,
.city-dot {
    fill: var(--text-strong);
    fill-opacity: 0.9;
    stroke: var(--map-bg);
    stroke-width: 1;
    pointer-events: none;
}

.leaflet-tooltip.city-label {
    background: none;
    border: none;
    box-shadow: none;
    padding: 0;
    color: var(--text-strong);
    font-size: 10px;
    font-weight: 600;
    line-height: 1;
    text-shadow: 0 0 2px var(--map-bg), 0 0 3px var(--map-bg);
    pointer-events: none;
}

.leaflet-tooltip.city-label::before {
    display: none;
}

.region-tooltip::before {
    border-top-color: var(--tooltip-bg);
}

@media (prefers-reduced-motion: no-preference) {
    #map.pulse {
        animation: mapPulse 1.8s ease-in-out infinite;
    }

    @keyframes mapPulse {
        0%, 100% { box-shadow: 0 0 0 0 rgba(46, 125, 181, 0.45); }
        50% { box-shadow: 0 0 0 7px rgba(46, 125, 181, 0); }
    }
}

/* Dawniej pełny, niebieski prostokąt nad mapą — najmocniejszy akcent
   kolorystyczny całej strony zużyty na podpowiedź, nie na treść. Teraz
   to podpis mapy: ten sam komunikat, waga wizualna adekwatna do roli. */
.map-cta {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin: 0 0 var(--space-2);
    padding: 0;
    background: none;
    color: var(--text-muted);
    font-size: var(--fs-sm);
    font-weight: 500;
}

.map-cta::before {
    content: "";
    flex: 0 0 auto;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--brand);
}

#details {
    flex: 1;
    min-width: 0;
    /* Bez własnego paddingu: przesuwał treść o 12px w prawo względem sekcji
       pełnej szerokości pod mapą, więc nagłówki w kolumnie i pod nią nie
       stały w jednej linii. */
    padding: 0;
}

#regionHeader[hidden] {
    display: none;
}

#regionHeader {
    margin-bottom: var(--space-2);
}

/* Nazwa województwa to nadtytuł nad <h1>, nie osobny nagłówek: wcześniej
   miała ten sam rozmiar co h1 pod nią, więc czytało się to jak dwa
   konkurujące tytuły. */
#regionTitle {
    margin: 0;
    font-size: var(--fs-xs);
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--brand);
}

/* Nagłówek podstrony. Kiedyś rolę h1 pełnił tekst w panelu "Info", ale każda
   zakładka jest teraz osobną stroną i potrzebuje własnego h1. */
.page-title {
    font-size: var(--fs-h1);
    line-height: 1.2;
    letter-spacing: -0.015em;
    margin: 0 0 var(--space-4);
    color: var(--text-strong);
}

.empty-state {
    max-width: 640px;
    padding: var(--space-4) var(--space-5);
    background: var(--surface);
    border: 1px solid var(--border-soft);
    border-radius: var(--radius);
}

.empty-state[hidden] {
    display: none;
}

.empty-state p {
    margin: 0 0 10px;
    font-size: 0.95rem;
    color: var(--text);
}

.empty-state ul {
    margin: 0 0 12px;
    padding-left: 20px;
    font-size: 0.9rem;
    line-height: 1.5;
    color: var(--text-muted);
}

.empty-state li {
    margin-bottom: 2px;
}

.link-btn {
    background: none;
    border: none;
    padding: 0;
    font-size: 0.9rem;
    font-weight: bold;
    color: var(--brand);
    cursor: pointer;
    text-decoration: underline;
}

.link-btn:hover {
    color: var(--brand-hover);
}

#forecastInfo {
    font-size: 0.9rem;
    background: var(--surface);
    padding: 12px;
    border-radius: var(--radius);
}

#forecastInfo:empty {
    display: none;
}

.forecast-header {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-bottom: 8px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--border);
}

.forecast-header h3 {
    margin: 0;
    font-size: 1rem;
}

.rating-display {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 8px;
}


/* Większa niż domyślne 18px z .fish-icon: to pojedyncza, wyeksponowana
   ocena obok nazwy kategorii, a nie gęsta kolumna tabeli. */
.rating-fish .fish-icon {
    width: 20px;
    height: 20px;
    vertical-align: -4px;
}

.rating-label {
    font-size: 0.9rem;
    color: var(--text-muted);
}

#forecastInfo p {
    margin: 4px 0;
}

.score-reasons {
    margin-bottom: 8px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--border);
}

.score-reasons-title {
    margin: 0 0 4px;
    font-size: 0.9rem;
    font-weight: bold;
    color: var(--brand);
}

.score-reasons ul {
    margin: 0;
    padding-left: 18px;
    font-size: 0.9rem;
    color: var(--text);
}

.score-reasons li {
    margin-bottom: 2px;
}

/* Najsilniejszy minus przy ocenie "dobre" i wyżej (compute_caveat) — pod
   listą plusów, żeby "dobre" nie wyglądało na bezwarunkowe. */
.score-caveat {
    margin: 6px 0 0;
    font-size: 0.9rem;
    color: var(--warning);
}

.error {
    color: var(--danger);
}

/* Ostrzeżenia pogodowe w #forecastInfo (patrz stormWarning w app.js) —
   wcześniej kolory były wpisane w atrybut style, więc nie dało się ich
   przestawić razem z motywem. */
.weather-alert {
    font-weight: 600;
}

.weather-alert-severe {
    color: var(--danger);
}

.weather-alert-warning {
    color: var(--warning);
}

.fish-calendar {
    margin-bottom: 12px;
    position: relative;
}

.calendar-wrap {
    overflow-x: auto;
}

.meteogram-container {
    position: relative;
}

.scroll-arrow {
    display: none;
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    border: none;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.85);
    color: var(--brand);
    font-size: 1.2rem;
    line-height: 1;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
    opacity: 0.8;
    cursor: pointer;
    z-index: 2;
    transition: opacity 0.15s ease;
}

.scroll-arrow:active {
    opacity: 1;
}

.scroll-arrow[hidden] {
    display: none;
}

.scroll-arrow-left {
    left: 2px;
}

.scroll-arrow-right {
    right: 2px;
}

.calendar-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 1.5rem;
    margin-top: 8px;
}

/* min-width 118px = 5 ikon po 18px + 4 odstępy po 2px (98px treści) +
   padding 10px z każdej strony. Bez pustych, wyszarzonych ikon liczba
   ikon w komórce zależy od oceny (1-5), więc bez tego wyliczonego minimum
   kolumny "skakałyby" w szerokości między wierszami — z nim stoją równo,
   a mimo to nie ma sztucznie dorysowanych pustych rybek.
   white-space: nowrap, żeby przy 5 ikonach na styk z minimum nic nie
   złamało się do drugiej linii — przewija się cała tabela (.calendar-wrap),
   nie zawija pojedyncza komórka. */
.calendar-table td {
    border: 1px solid var(--border);
    padding: 14px 10px;
    text-align: center;
    background: var(--surface);
    min-width: 118px;
    white-space: nowrap;
}

.calendar-table td.clickable {
    cursor: pointer;
}

.calendar-table td.clickable:hover {
    background: var(--brand-soft);
}

.calendar-table td.selected {
    background: var(--brand-selected);
    box-shadow: inset 0 0 0 2px var(--brand);
}

.calendar-table th {
    border: 1px solid var(--border);
    padding: 8px;
    text-align: center;
    background: var(--surface-3);
    font-weight: bold;
    font-size: 1rem;
}

.calendar-table tr:first-child td {
    background: var(--surface-2);
    font-weight: bold;
}

.calendar-table td:first-child {
    background: var(--surface-2);
    font-weight: bold;
    text-align: left;
    font-size: 0.95rem;
}

.astro-date {
    font-size: 1rem;
    margin: 0 0 10px;
    color: var(--text-strong);
}

.astro-info {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin-top: 4px;
}

.astro-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    background: var(--surface);
    border-radius: var(--radius-sm);
}

.astro-icon {
    font-size: 1.4rem;
    line-height: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    flex-shrink: 0;
}

.astro-label {
    flex: 1;
    font-size: 0.9rem;
    color: var(--text);
}

.astro-value {
    font-weight: bold;
    font-size: 0.95rem;
    color: var(--text-strong);
}

.section-caption {
    font-size: var(--fs-h2);
    line-height: 1.3;
    letter-spacing: -0.01em;
    margin: 0 0 var(--space-2);
    color: var(--text-strong);
}

.section-subcaption {
    font-size: var(--fs-sm);
    line-height: 1.6;
    margin: 0 0 var(--space-3);
    color: var(--text-muted);
    max-width: 68ch;
}

/* Zapowiedź zakładki "Kalendarz Wędkarski" w miejscu, skąd przeniosła się
   treść sezonowa — bez tego wyglądałoby na pusty, nagły koniec panelu.
   Tło #f9f9f9 i brak max-width dopasowane do #forecastInfo/.forecast-summary
   obok — to ten sam "Narzędzia pełnej szerokości" panel (patrz komentarz
   w template.html), #eef3f8 to kolor mapy/hoverów, nie treści.

   max-width: none nadpisuje 68ch z .section-subcaption — bez tego tło tego
   akapitu wychodziło węższe niż sąsiednie #forecastInfo/.forecast-summary,
   mimo że komentarz wyżej od dawna zakładał tę samą szerokość. Margines
   góra+dół (zamiast samego dołu) daje ten sam odstęp od sąsiada niezależnie
   od tego, co stoi nad/pod tym blokiem. */
.seasonal-cta {
    max-width: none;
    margin: 20px 0;
    padding: 10px 14px;
    background: var(--surface);
    border-radius: var(--radius);
    font-size: 0.9rem;
    color: var(--text);
}

.seasonal-cta a {
    color: var(--brand);
    font-weight: 600;
}

/* Odsyłacz do zakładki "Gatunki Ryb" z kalendarza brań — bez tego strona
   z prognozą dla gatunku nie miała linku prowadzącego do niej wprost.
   max-width/margin jak w .seasonal-cta wyżej — ten sam powód. */
.species-cta {
    max-width: none;
    margin: 20px 0;
    padding: 10px 14px;
    background: var(--surface);
    border-radius: var(--radius);
    font-size: 0.9rem;
    color: var(--text);
}

.species-cta a {
    color: var(--brand);
    font-weight: 600;
}

.fish-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 16px;
    margin: 0 0 12px;
    padding: 8px 12px;
    list-style: none;
    background: var(--surface);
    border-radius: var(--radius-sm);
    font-size: 0.85rem;
    color: var(--text-muted);
}

.fish-legend li {
    display: flex;
    align-items: center;
    white-space: nowrap;
}

/* Mniejsza niż domyślne 18px z .fish-icon: legenda tłumaczy skalę, nie
   pokazuje realnej oceny — nie musi konkurować wizualnie z kalendarzem pod nią. */
.fish-legend .fish-icon {
    width: 15px;
    height: 15px;
    vertical-align: -2px;
}

/* Odstęp między rybkami tylko z .fish-icon + .fish-icon (jak w kalendarzu) —
   `gap` na .fish-legend li dokładałby się do tego marginesu i rozstaw rybek
   w legendzie nie zgadzałby się z rozstawem w samym kalendarzu pod spodem.
   Odstęp przed etykietą ("słabe"/"przeciętne"...) dostaje więc ostatnia
   rybka w grupie, nie kontener. */
.fish-legend .fish-icon:last-child {
    margin-right: 6px;
}

.meteogram-wrap,
.daily-weather-wrap {
    overflow-x: auto;
}

.daily-weather-wrap {
    margin-bottom: 16px;
}

#dailyWeatherTable td[data-day] {
    cursor: pointer;
}

#dailyWeatherTable td[data-day]:hover {
    background: var(--brand-soft);
}

#dailyWeatherTable .daynight-label {
    background: var(--surface-2);
    color: var(--text-muted);
    font-size: 0.7rem;
}

#dailyWeatherTable .daynight-label:hover {
    background: var(--brand-soft-2);
}

.meteogram-table {
    border-collapse: collapse;
    font-size: 0.75rem;
    white-space: nowrap;
}

.meteogram-table th,
.meteogram-table td {
    border: 1px solid var(--border);
    padding: 3px 4px;
    text-align: center;
}

.meteogram-table th.day-header {
    background: var(--surface-3);
    font-weight: bold;
    cursor: pointer;
}

.meteogram-table th.day-header:hover {
    background: var(--brand-soft-2);
}

.meteogram-table th.day-header.selected {
    background: var(--brand);
    color: var(--on-brand);
}

.meteogram-table .row-label {
    text-align: left;
    background: var(--surface-2);
    font-weight: bold;
    font-size: 0.8rem;
    position: sticky;
    left: 0;
}

.meteogram-table .weather-icon {
    font-size: 1.1rem;
}

.wind-arrow {
    display: inline-block;
    font-size: 1rem;
}

/* Podsumowanie prognozy zdaniami (patrz _build_forecast_summary w
   weather/site_pages.py). Ma czytać się jak akapit, a nie jak kolejny widżet —
   to ta sama treść co kalendarz obok, tyle że do przeczytania. Tło #f9f9f9,
   to samo co #forecastInfo/.seasonal-cta/.species-cta — #f5f9fc było osobnym
   odcieniem bez uzasadnienia, obok siebie widać było różnicę. */
/* Linia "Prognoza zaktualizowana: …" pod podsumowaniem (template.html,
   znacznik FORECAST_UPDATED) — drobny, przygaszony tekst, nie konkuruje
   z samą prognozą. */
.forecast-updated {
    margin: var(--space-2) 0 var(--space-3);
    font-size: var(--fs-xs);
    color: var(--text-faint);
}

.forecast-updated:empty {
    display: none;
}

.forecast-summary {
    margin: 0 0 20px;
    padding: 14px 16px;
    background: var(--surface);
    border-radius: var(--radius);
}

.forecast-summary:empty {
    display: none;
}

.forecast-summary h2 {
    margin: 0 0 var(--space-3);
    font-size: var(--fs-h2);
    line-height: 1.3;
    letter-spacing: -0.01em;
    color: var(--text-strong);
}

.forecast-summary h3 {
    margin: var(--space-4) 0 var(--space-2);
    font-size: var(--fs-h3);
    color: var(--text-strong);
}

.forecast-summary p {
    margin: 0 0 var(--space-2);
    line-height: 1.65;
    color: var(--text-muted);
}

.forecast-summary .summary-lead {
    font-size: 1.05rem;
    color: var(--text);
}

.forecast-summary strong {
    color: var(--text-strong);
}

/* "Najlepszy moment w tym tygodniu" (i jego odpowiednik dla drapieżników,
   .summary-week-best-predators z 🦈 zamiast 🔥) to zdania w prognozie, które
   mają poruszyć, a nie tylko poinformować — dostają więc własną oprawę.
   Reszta podsumowania zostaje rzeczowa, bo inaczej wyróżnienie przestałoby
   cokolwiek znaczyć.

   Tło jest CHŁODNE (stopień jaśniejsze od --surface), nie ciepłe: bursztyn
   dobrany pod kolor płomienia wychodził na granatowym interfejsie brudnym
   brązem. Ciepło niesie tylko złota krawędź po lewej i samo emoji —
   punktowo, na chłodnym tle, zamiast rozlane na cały panel.

   Zwykły blok, NIE flex: elementy <strong> wewnątrz zdania (data, pora,
   ocena) stawały się wtedy osobnymi elementami flex i układały się w kolumny
   obok siebie zamiast płynąć jako jedno zdanie. */
/* Selektor przez .forecast-summary, nie sam .summary-week-best: reguła
   `.forecast-summary p` wyżej ma wyższą specyficzność (klasa + element),
   więc samodzielna klasa przegrywała i `color` nie działał — wyróżnione
   zdanie było przygaszone tak samo jak proza dookoła. */
.forecast-summary .summary-week-best {
    margin: var(--space-4) 0 0;
    padding: var(--space-3) var(--space-4);
    border: 1px solid var(--flame-border);
    border-left: 3px solid var(--accent-highlight);
    border-radius: var(--radius-sm);
    background: var(--flame-bg);
    color: var(--text);
}

/* Emoji (🔥 albo 🦈) nieco większe niż tekst i lekko "unoszone" — to nośnik
   emocji w tym zdaniu, a w rozmiarze tekstu ginęłyby między literami. */
.best-flame,
.shark-emoji {
    display: inline-block;
    margin-right: var(--space-2);
    font-size: 1.25em;
    line-height: 1;
    vertical-align: -0.1em;
}

/* Delikatne tętnienie, tylko dla tych, którzy nie prosili o ograniczenie
   animacji. Skala, nie kolor: emoji renderuje każdy system po swojemu,
   więc filtry kolorystyczne dawałyby różny efekt na różnych platformach. */
@media (prefers-reduced-motion: no-preference) {
    .best-flame,
    .shark-emoji {
        display: inline-block;
        animation: flamePulse 2.4s ease-in-out infinite;
    }

    @keyframes flamePulse {
        0%, 100% { transform: scale(1); }
        50% { transform: scale(1.14); }
    }
}

.forecast-summary .summary-days {
    margin: 0;
    padding-left: 20px;
    line-height: 1.6;
}

/* FAQ (patrz weather/faq.py). <details> zamiast 27 rozwiniętych pytań —
   treść w zwiniętym <details> i tak jest w HTML-u, więc boty ją widzą. */
/* Pytania są pogrupowane tematycznie (patrz FISHING_FAQ_GROUPS w
   weather/faq.py): 24 pytania w jednej, płaskiej liście dawały pół ekranu
   identycznych wierszy, po których nie dało się nawigować wzrokiem. */
.faq-group {
    margin: 0 0 var(--space-5);
}

.faq-group:last-child {
    margin-bottom: 0;
}

.faq-group-title {
    margin: 0 0 var(--space-2);
    padding-bottom: var(--space-2);
    border-bottom: 2px solid var(--border-brand);
    font-size: var(--fs-xs);
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--brand);
}

.faq-item {
    border-bottom: 1px solid var(--border-soft);
}

.faq-item:last-child {
    border-bottom: none;
}

.faq-item summary {
    cursor: pointer;
    padding: var(--space-3) var(--space-1);
    font-weight: 600;
    line-height: 1.45;
    list-style-position: outside;
}

.faq-item summary:hover {
    color: var(--brand);
}

.faq-item summary:focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: 2px;
}

.faq-item[open] summary {
    color: var(--brand-strong);
}

.faq-answer {
    padding: 0 4px 14px;
}

.faq-answer p {
    margin: 0 0 10px;
    line-height: 1.6;
}

.faq-answer p:last-child {
    margin-bottom: 0;
}

/* Stopka na pełną szerokość okna z własnym tłem — wcześniej była wąskim,
   wyśrodkowanym wierszem linków bez żadnego tła, więc strona nie tyle się
   kończyła, co urywała. */
.site-footer {
    margin-top: var(--space-6);
    padding: var(--space-5) 0;
    border-top: 1px solid var(--border);
    background: var(--surface);
    font-size: var(--fs-sm);
    color: var(--text-muted);
}

.site-footer-inner {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-4) var(--space-5);
}

.footer-brand {
    display: flex;
    align-items: center;
    gap: 10px;
    color: var(--text-strong);
    text-decoration: none;
}

.footer-brand .brand-mark {
    width: 26px;
    height: 26px;
}

.footer-brand .brand-name {
    font-size: 0.95rem;
}

.footer-contact {
    margin: 0;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2) var(--space-4);
}

.footer-contact a {
    color: var(--text-muted);
    text-decoration: none;
}

.footer-contact a:hover {
    color: var(--brand);
    text-decoration: underline;
}

.footer-attribution {
    margin: var(--space-4) 0 0;
    padding-top: var(--space-4);
    border-top: 1px solid var(--border);
    font-size: var(--fs-xs);
    color: var(--text-faint);
}

.footer-attribution a {
    color: inherit;
}

.link-btn-inline {
    background: none;
    border: none;
    padding: 0;
    margin: 0;
    font: inherit;
    font-size: 0.85rem;
    color: var(--brand);
    cursor: pointer;
    text-decoration: underline;
}

.link-btn-inline:hover {
    color: var(--brand-hover);
}

.cookie-consent {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 1000;
    background: var(--surface-raised);
    border-top: 1px solid var(--border-strong);
    box-shadow: var(--shadow-md);
    max-height: 90vh;
    overflow-y: auto;
}

.cookie-consent-inner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 16px;
    max-width: 1100px;
    margin: 0 auto;
    padding: 16px;
}

.cookie-consent-text {
    flex: 1 1 400px;
}

.cookie-consent-text h2 {
    margin: 0 0 6px;
    font-size: 1rem;
    color: var(--text);
}

.cookie-consent-text p {
    margin: 0;
    font-size: 0.85rem;
    line-height: 1.5;
    color: var(--text-muted);
}

.cookie-consent-text a {
    color: var(--brand);
}

.cookie-consent-actions {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    flex: 0 0 auto;
}

.cookie-btn {
    padding: 10px 18px;
    border-radius: var(--radius-sm);
    font-size: 0.9rem;
    cursor: pointer;
    white-space: nowrap;
}

.cookie-btn-primary {
    border: 1px solid var(--brand);
    background: var(--brand);
    color: var(--on-brand);
}

.cookie-btn-primary:hover {
    background: var(--brand-hover);
    border-color: var(--brand-hover);
}

.cookie-btn-secondary {
    border: 1px solid var(--border-strong);
    background: var(--surface-raised);
    color: var(--text);
}

.cookie-btn-secondary:hover {
    background: var(--surface-2);
}

.cookie-settings-panel {
    max-width: 1100px;
    margin: 0 auto;
    padding: 0 16px 16px;
    border-top: 1px solid var(--border-soft);
}

.cookie-settings-panel h3 {
    margin: 12px 0 8px;
    font-size: 0.95rem;
    color: var(--text);
}

.cookie-setting-row {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    margin-bottom: 10px;
    font-size: 0.85rem;
    line-height: 1.5;
    color: var(--text-muted);
}

.cookie-setting-row input {
    margin-top: 3px;
    flex-shrink: 0;
}

.cookie-setting-note {
    margin: -4px 0 10px 26px;
    font-size: 0.78rem;
    color: var(--text-faint);
}

.cookie-link-btn {
    background: none;
    border: none;
    padding: 0;
    font: inherit;
    font-size: 0.78rem;
    color: var(--brand);
    text-decoration: underline;
    cursor: pointer;
}

/* Podgląd zdjęć (Gatunki Ryb / Kalendarz Wędkarski) na pełny ekran — patrz
   initImageLightbox() w app.js. z-index wyżej niż .cookie-consent (1000),
   żeby banner cookie nie zasłaniał podglądu, gdyby oba były naraz widoczne. */
.image-lightbox {
    position: fixed;
    inset: 0;
    z-index: 2000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 32px;
    background: rgba(0, 0, 0, 0.75);
    cursor: zoom-out;
}

.image-lightbox[hidden] {
    display: none;
}

.image-lightbox img {
    /* Zdjęcia to wycinanki na przezroczystym tle (patrz komentarz przy
       .species-media img/.plant-blurb img) — w miniaturze wtapiają się
       w szare tło karty, ale powiększone na ciemnym tle lightboksa
       zawisłyby w próżni bez żadnego gruntu pod sobą. Białe tło + padding
       dają im tu "kartkę", której miniatura celowo już nie ma. */
    max-width: 100%;
    max-height: 100%;
    background: #fff;
    padding: 20px;
    border-radius: 6px;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.35);
    object-fit: contain;
    cursor: default;
}

.image-lightbox-close {
    position: absolute;
    top: 16px;
    right: 16px;
    width: 40px;
    height: 40px;
    border: none;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.9);
    color: var(--text);
    font-size: 1.4rem;
    line-height: 1;
    cursor: pointer;
}

.image-lightbox-close:hover {
    background: #fff;
}

@media (max-width: 720px) {
    .layout {
        flex-direction: column;
        /* align-items: flex-start (reguła bazowa) ma sens tylko w układzie
           wierszowym z desktopu — trzyma mapę przy górnej krawędzi, żeby nie
           rozciągała się na wysokość kolumny z treścią. W układzie kolumnowym
           ta sama właściwość działa na oś poziomą: bez nadpisania #details
           kurczył się do naturalnej szerokości najszerszego dziecka (tabeli
           kalendarza/meteogramu) zamiast do szerokości ekranu, więc cała
           strona przewijała się w bok. stretch każe mu wypełnić szerokość
           kolumny, a wewnętrzne .calendar-wrap/.meteogram-wrap/.table-scroll
           (overflow-x: auto) same skalują szeroką tabelę w środku. */
        align-items: stretch;
    }

    .map-column {
        flex: none;
        width: 100%;
    }

    #map {
        width: 100%;
        height: 340px;
    }

    .tabs {
        gap: 2px;
    }

    .tab-btn {
        flex: 1 1 0;
        padding: 8px 4px;
        font-size: 0.82rem;
        text-align: center;
        line-height: 1.25;
    }

    /* Odsłania .tab-break (patrz baza .tab-btn) — każda etykieta łamie się
       w tym samym, ustalonym miejscu (po pierwszym wyrazie), a nie tam, gdzie
       akurat starcza jej miejsca. Bez tego "Prognoza Pogody" (krótsza niż
       pozostałe dwie) zostałaby w jednej linii, a sąsiednie zakładki w dwóch
       — różna wysokość przycisków w tym samym rzędzie. white-space zostaje
       na nowrap (z bazy .tab-btn): sam <br> wymusza złamanie niezależnie od
       tego, więc nowrap tylko pilnuje, żeby nie doszło do trzeciej linii. */
    .tab-break {
        display: block;
    }

    .scroll-arrow {
        display: flex;
    }

    .scroll-arrow[hidden] {
        display: none;
    }

    .kalendarz-layout {
        grid-template-columns: 1fr;
    }
}

/* Przegląd roku na hubie /kalendarz-wedkarski (_year_overview_html). */
.kalendarz-hub-lead {
    color: var(--text);
}

.year-overview-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--fs-sm);
}

.year-overview-table caption {
    caption-side: bottom;
    text-align: left;
    padding-top: var(--space-2);
    font-size: var(--fs-xs);
    color: var(--text-faint);
}

.year-overview-table th,
.year-overview-table td {
    padding: 6px var(--space-2);
    border-bottom: 1px solid var(--border-soft);
    text-align: left;
    vertical-align: top;
    color: var(--text);
}

.year-overview-table thead th {
    background: var(--table-head-bg);
    color: var(--text-strong);
}

.year-overview-table td:nth-child(2) {
    white-space: nowrap;
}

/* Tabele w artykułach (porady-i-triki/*) — opisowe kolumny tekstu, nie krótkie
   wartości jak w tabeli roku, więc mają się normalnie zawijać; pierwsza
   kolumna (warunki/gatunek) nie może zabrać całej szerokości. */
.guide-table td:nth-child(2) {
    white-space: normal;
}

.guide-table th[scope="row"] {
    width: 30%;
}

/* Tabela pór dnia (weather/calendar_pages.py: _time_of_day_table_html) — kolumna 2
   to lista linków do gatunków, nie krótka wartość jak w innych tabelach roku,
   więc ma się normalnie zawijać. */
.tod-table td:nth-child(2) {
    white-space: normal;
}

/* ========================================================================
   KIEDY JAKIE RYBY BIORĄ (weather/species_calendar.py) */
.sc-scroll {
    overflow-x: auto;
    margin: 0 0 var(--space-3);
}

.sc-local-note {
    color: var(--warning);
}

.sc-note {
    font-size: var(--fs-xs);
}

/* Tekstowa "szybka ściąga" nad tabelą z rybkami — ta sama informacja
   słowami (miesiące, okres ochronny, pora, metody), czytelna dla botów. */
.species-quick-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--fs-xs);
    margin-bottom: var(--space-4);
}

.species-quick-table caption {
    caption-side: bottom;
    text-align: left;
    padding-top: var(--space-2);
    color: var(--text-faint);
}

.species-quick-table th,
.species-quick-table td {
    padding: 6px var(--space-2);
    border-bottom: 1px solid var(--border-soft);
    text-align: left;
    vertical-align: top;
    color: var(--text);
    min-width: 90px;
}

.species-quick-table thead th {
    background: var(--table-head-bg);
    color: var(--text-strong);
}

/* ========================================================================
   PASEK SEKCJI "KALENDARZ WĘDKARSKI" (section_nav_html w weather/site_pages.py)

   Jedna zakładka w menu, trzy podstrony: co bierze w miesiącu, kalendarz
   brań dzień po dniu, kiedy jakie ryby biorą. Pasek stoi na górze każdej
   z nich w tym samym miejscu, więc przełączanie wygląda jak zakładki,
   a każda podstrona ma własny adres pod własną frazę. */
/* Od lewej krawędzi, jak menu i treść pozostałych podstron (.shell). */
.section-nav {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin: 0 0 var(--space-4);
}

.section-nav-link {
    padding: var(--space-2) var(--space-3);
    border: 1px solid var(--border);
    border-radius: 999px;
    background: var(--surface);
    color: var(--text);
    font-size: var(--fs-sm);
    font-weight: 500;
    text-decoration: none;
}

.section-nav-link:hover {
    border-color: var(--border-brand);
    color: var(--brand-hover);
}

.section-nav-link[aria-current],
.section-nav-link[aria-pressed="true"] {
    background: var(--brand-soft-2);
    border-color: var(--brand);
    color: var(--brand-strong);
    font-weight: 600;
}

/* Podstrony generowane (kalendarz-wedkarski, kalendarz-bran, fazy-ksiezyca): ta sama szerokość co
   treść innych podstron (960px, od lewej krawędzi menu). */
.calendar-page.about-section {
    max-width: 960px;
}

.sc-now {
    margin: 0 0 var(--space-3);
    padding: var(--space-3) var(--space-4);
    border: 1px solid var(--border-brand);
    border-radius: var(--radius-sm);
    background: var(--brand-soft);
}

.about-section .sc-now h2 {
    margin-top: 0;
}

.sc-month-list {
    margin-bottom: 0;
}

/* Ilustracja "koło roku" na górze /kalendarz-bran, zaraz pod H1
   (scripts/generate_bite_wheel.py). Opływa ją wstęp i ramka .sc-now
   (flow-root, żeby tło ramki nie wchodziło pod obrazek); tabela dni
   zaczyna się już pod nią (clear). */
.bite-wheel {
    float: right;
    width: 220px;
    margin: 0 0 var(--space-3) var(--space-4);
}

.bite-wheel img {
    width: 100%;
    height: auto;
    display: block;
}

.bite-wheel figcaption {
    margin-top: var(--space-2);
    font-size: 12px;
    line-height: 1.3;
    color: var(--text-faint);
    text-align: center;
}

.calendar-page .sc-now {
    display: flow-root;
}

.bite-calendar {
    clear: both;
}

/* Na telefonie mniejsza i dalej opływana — jako osobny blok spychała
   wstęp poniżej pierwszego ekranu. Podpis wtedy znika (za wąsko). */
@media (max-width: 600px) {
    .bite-wheel {
        width: 120px;
        margin: 4px 0 var(--space-2) var(--space-3);
    }

    .bite-wheel figcaption {
        display: none;
    }
}

/* Kalendarz brań tydzień po tygodniu na /kalendarz-bran
   (weather/bite_calendar.py). Dwie kolumny zamiast siatki 7 dni — ta na
   telefonie nie mieściła rybek. Ocena sezonowa przygaszona, żeby nie
   wyglądała na równie pewną jak prognoza. */
.bite-calendar-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--fs-xs);
    margin-bottom: var(--space-3);
}

.bite-calendar-table caption {
    caption-side: bottom;
    text-align: left;
    padding-top: var(--space-2);
    color: var(--text-faint);
}

.bite-calendar-table th,
.bite-calendar-table td {
    padding: 6px var(--space-2);
    border-bottom: 1px solid var(--border-soft);
    text-align: left;
    vertical-align: top;
    color: var(--text);
}

.bite-calendar-table thead th {
    background: var(--table-head-bg);
    color: var(--text-strong);
}

.bite-calendar-table tbody th {
    white-space: nowrap;
    color: var(--text-strong);
}

.bite-days {
    list-style: none;
    margin: 0 0 var(--space-2);
    padding: 0;
}

.bite-days li + li {
    margin-top: 4px;
}

.bite-day {
    display: inline-block;
    min-width: 6.5em;
    font-weight: bold;
}

.bite-fish {
    display: inline-block;
    min-width: 98px;
    white-space: nowrap;
}

.bite-hist {
    margin: 0;
    color: var(--text-muted);
}

.bite-hist .bite-fish {
    opacity: 0.55;
}

.bite-hist-label {
    display: inline-block;
    min-width: 6.5em;
}

.bite-best {
    margin-bottom: var(--space-2);
}

/* Miniatury gatunków przy H3 na /kalendarz-bran (species_sections_html).
   Zdjęcie i podpis CC to kopia z góry /gatunki-ryb/<gatunek>; bez
   lightboxa (template-kalendarz.html go nie ma), więc zdjęcie jest
   linkiem do strony gatunku zamiast powiększenia. */
.sc-species {
    display: flex;
    gap: var(--space-4);
    align-items: flex-start;
}

.sc-species > p {
    margin-top: 0;
}

.sc-species-photo {
    flex: 0 0 160px;
    margin: 0;
}

.sc-species-photo img {
    width: 100%;
    height: auto;
    display: block;
    border-radius: var(--radius-sm);
}

/* Ta sama specyficzność co .species-media .species-photo-credit — patrz
   komentarz przy tamtej regule. */
.sc-species-photo .species-photo-credit {
    margin: var(--space-2) 0 0;
    font-size: 12px;
    line-height: 1.3;
    color: var(--text-faint);
    text-align: center;
}

@media (max-width: 480px) {
    .sc-species {
        flex-direction: column;
        gap: var(--space-2);
    }

    .sc-species-photo {
        flex: none;
        max-width: 220px;
    }
}

/* Na telefonie trzy równe kolumny zamiast trzech pełnych wierszy — pasek
   nie może zepchnąć treści poniżej pierwszego ekranu. */
@media (max-width: 560px) {
    /* Tyle równych kolumn, ile przycisków (2 w poradach)… */
    .section-nav {
        display: grid;
        grid-auto-flow: column;
        grid-auto-columns: 1fr;
        gap: 6px;
    }

    /* …ale od 5 przycisków (kalendarz, odkąd doszedł "Kalendarz solunarny")
       pięć kolumn po ~55 px nie mieści "Kalendarz faz Księżyca" — wtedy trzy
       kolumny w dwóch rzędach. Przeglądarka bez :has() zostaje przy jednym
       rzędzie, tylko ciaśniejszym. */
    .section-nav:has(> :nth-child(5)) {
        grid-auto-flow: row;
        grid-template-columns: repeat(3, 1fr);
    }

    .section-nav-link {
        display: flex;
        align-items: center;
        justify-content: center;
        padding: 6px 8px;
        border-radius: var(--radius-sm);
        font-size: 0.8rem;
        line-height: 1.25;
        text-align: center;
    }
}

.year-overview-table tr.is-current {
    background: var(--brand-soft);
}

.year-overview-table tbody th {
    white-space: nowrap;
}

.yo-protected {
    display: block;
    margin-top: 2px;
    font-size: var(--fs-xs);
    color: var(--warning);
}

.yo-scroll {
    overflow-x: auto;
    margin: 0 0 var(--space-3);
}

/* Okruszki na podstronach sekcji "Kalendarz Wędkarski" (weather/calendar_pages.py). */
.breadcrumbs {
    margin: 0 0 var(--space-3);
    font-size: var(--fs-xs);
    color: var(--text-faint);
}

.breadcrumbs a {
    color: var(--text-muted);
}

/* Tabela roku na telefonie: sześć kolumn przewija się w bok, kolumna miesiąca
   zostaje na miejscu, a tekstowe kolumny nie ściskają się do jednego słowa. */
@media (max-width: 720px) {
    .year-overview-table td {
        min-width: 150px;
    }

    .year-overview-table td:nth-child(2) {
        min-width: 0;
    }

    .year-overview-table tbody th {
        position: sticky;
        left: 0;
        z-index: 1;
        background: var(--surface);
    }

    .year-overview-table tr.is-current th {
        background: var(--brand-soft);
    }
}

/* Tabele w artykułach (.guide-table): nagłówek wiersza to opis warunków, nie
   krótka nazwa miesiąca jak w tabeli roku — zawija się zamiast rozpychać
   tabelę, a na telefonie kolumny są węższe niż w tabeli roku. */
.guide-table tbody th {
    white-space: normal;
}

@media (max-width: 720px) {
    .guide-table td {
        min-width: 100px;
    }

    .guide-table tbody th {
        width: auto;
        min-width: 100px;
    }
}

/* Wykresy na /prognoza-w-praktyce (inline SVG z fish_project_test/
   archiwum_open_meteo/wykresy.py) — kolory z tokenów, więc działają w obu
   motywach bez osobnych plików. */
.pw-figure {
    margin: 0 0 var(--space-3);
    overflow-x: auto;
}

.pw-chart {
    display: block;
    width: 100%;
    min-width: 520px;
    height: auto;
}

.pw-chart-grid { stroke: var(--border-soft); stroke-width: 1; }
.pw-chart-day { stroke: var(--border-soft); stroke-width: 1; stroke-dasharray: 2 3; }
.pw-chart-axis { fill: var(--text-faint); font-size: 11px; }
.pw-chart-score { fill: none; stroke: var(--brand); stroke-width: 2.5; stroke-linejoin: round; }
.pw-chart-pressure { fill: none; stroke: var(--text-muted); stroke-width: 1.5; stroke-dasharray: 5 4; }
.pw-chart-storm { font-size: 13px; }

/* Przełącznik grupy ryb nad tabelą prognozy (template.html, app.js
   initFishGroupToggle) — te same pigułki co pasek sekcji, ale jako <button>. */
button.section-nav-link {
    font-family: inherit;
    cursor: pointer;
}

.fish-group-toggle {
    margin: 0 0 var(--space-2);
}

/* Gatunki w grupach pod przełącznikiem; po wybraniu grupy druga przygasa. */
.fish-group-species {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-1) var(--space-4);
    margin: 0 0 var(--space-3);
    font-size: var(--fs-xs);
    color: var(--text-muted);
}

.fish-group-species a {
    color: var(--text-muted);
}

.fish-group-species-item {
    transition: opacity 0.15s;
}

.fish-group-block[data-active="predators"] .fish-group-species-item[data-group="peaceful"],
.fish-group-block[data-active="peaceful"] .fish-group-species-item[data-group="predators"] {
    opacity: 0.45;
}

/* Nazwy grup ("Drapieżniki:", "Ryby spokojnego żeru:") w tym samym złotym
   kolorze co "ochrona: …" w tabeli roku (.yo-protected) — na stronie głównej
   w linii z gatunkami i w zdaniach o grupach w podsumowaniu. Wybraną grupę
   pokazuje przygaszenie drugiej, więc kolor nazwy zostaje ten sam. */
.fish-group-species-item strong,
.summary-group-line .group-label,
.summary-week-best-predators .group-label {
    color: var(--warning);
}

.summary-groups {
    color: var(--text);
}

/* Każda grupa ryb w osobnej linii (drapieżniki / ryby spokojnego żeru). */
.summary-group-line {
    display: block;
}

.sc-group {
    display: block;
    font-size: 0.72rem;
    font-weight: 400;
    color: var(--text-faint);
}

.fish-group-block[hidden] {
    display: none;
}

/* Ramka "Księżycowy czy solunarny?" na /kalendarz-ksiezycowy
   i /kalendarz-solunarny (moon_vs_solunar_html w weather/calendar_pages.py).
   Neutralna, nie w kolorze marki jak .sc-now — to wskazówka nawigacyjna,
   a nie odpowiedź na pytanie strony. */
.calendar-compare {
    margin: 0 0 var(--space-4);
    padding: var(--space-3) var(--space-4);
    background: var(--surface);
    border: 1px solid var(--border-soft);
    border-radius: var(--radius-sm);
}

.about-section .calendar-compare-title {
    margin: 0 0 var(--space-2);
    font-weight: 600;
}

.calendar-compare ul {
    margin: 0;
    padding: 0;
    list-style: none;
}

.calendar-compare li + li {
    margin-top: var(--space-2);
}
