/* ═════════════════════════════════════════════════════════════
   DRON - WARUNKI LOTU
   Mobile-first. Skalowanie przez clamp(), @media tylko tam gdzie
   uklad naprawde sie zmienia (siatka kafli, szerokosc tresci).
   ═════════════════════════════════════════════════════════════ */

/* ── KROJ ──
   Outfit jako font zmienny: jeden plik na subset pokrywa caly zakres
   grubosci 400-700, wiec kilka wag nie kosztuje kolejnych pobran.
   Pliki lezą lokalnie, bo aplikacja ma dzialac bez sieci; woff2 jest juz
   skompresowane wewnetrznie, wiec na laczu licza sie 1:1 (47 kB razem). */
@font-face {
  font-family: 'Outfit';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('../fonts/outfit-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Outfit';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('../fonts/outfit-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ── TOKENY ── */
:root {
  --bg: #0b0e11;
  /* Drabinka powierzchni: tlo -> karta -> element w karcie. Karty odcinaja sie
     PRZEDE WSZYSTKIM jasnoscia, obwodka tylko dopowiada. Odwrotnie niz wczesniej,
     gdzie o krawedzi decydowala kreska, a powierzchnie byly prawie rowne. */
  --panel: #161d25;          /* tlo kart */
  /* NIE PODNOSIC. Zmierzone: `--zle` na tym tle daje 4,58:1, czyli prog AA
     z zapasem 0,08. Przy #1f2831 schodzi do 4,36 i prog pada. */
  --panel-2: #1c242d;        /* tlo elementow wewnatrz kart */
  /* Dwie grubosci kreski zamiast jednej. `--line` obrysowuje to, co jest
     osobnym obiektem (karta, pigulka, przycisk), `--line-2` rozdziela tresc
     wewnatrz jednego obiektu. Wczesniej jedna wartosc robila obie rzeczy
     i wnetrze kart bylo pokreslone tak samo mocno jak ich krawedzie. */
  --line: #232c36;
  --line-2: #1e2731;
  --txt: #e9eef4;            /* tekst glowny = kolor "warunki normalne" */
  --txt-2: #a3b1bf;          /* tekst drugorzedny */
  --txt-3: #8896a6;          /* podpisy, jednostki - 5,0:1 na --panel-2, prog AA */

  /* Zielen i czerwien nasycone mocniej niz podpowiada gust: aplikacja jest
     czytana w slonecu, na telefonie, przez osobe ktora rozroznia barwy slabo.
     Rozjezdzaja sie tez JASNOSCIA, nie samym odcieniem - to ta roznica niesie
     informacje, gdy odcien zawodzi. */
  --dobre: #2ee06f;          /* warunki dobre */
  /* #ff2f26 bylo mocniejsze, ale przy pelnym nasyceniu schodzilo do 4,24:1
     na --panel-2, czyli pod prog AA. Ta wartosc to najbardziej nasycona
     czerwien, ktora prog jeszcze trzyma (zmierzone: 4,58:1). */
  --zle: #ff4438;            /* warunki zle */
  --akcent: #6aaeff;

  --r: 16px;                 /* promien zaokraglen - jedno zrodlo prawdy */
  /* Wypelnienie karty jako token, bo elementy klikalne w srodku musza umiec
     wyjsc poza nie na pelna szerokosc - patrz `.rozwin summary`. */
  --karta-pad: clamp(20px, 5.5vw, 26px);
  --r-s: 11px;
  --sz-max: 640px;           /* maksymalna szerokosc tresci */

  /* ── SKALA TEKSTU ──
     Jeden ciag rozmiarow dla calej aplikacji. Wczesniej kazdy blok
     mial wlasne wartosci i tekst byl nierowny. */
  --fs-xxs: .7rem;           /* 11,2 px - liczniki modeli, os czasu; podloga skali */
  --fs-xs: .78rem;           /* 12,5 px - podpisy i etykiety sekcji */
  --fs-sm: .875rem;          /* 14 px - tekst drugoplanowy */
  --fs-md: 1rem;             /* 16 px - tekst podstawowy; aplikacja bywa czytana
                                w slonecu, wiec podstawa nie schodzi ponizej 16 px */
  --fs-lg: 1.125rem;         /* 18 px */

  --font: 'Outfit', system-ui, -apple-system, "Segoe UI", sans-serif;
  /* Liczby ida tym samym krojem, ale z cyframi tabelarycznymi - kolumny
     wartosci maja sie zgadzac w pionie bez przeskakiwania. */
  --mono: 'Outfit', system-ui, sans-serif;

  /* --t = intensywnosc czerwieni (0..1), ustawiana z JS na elemencie */
  --t: 0;
  --stan: var(--txt-3);
}

*, *::before, *::after { box-sizing: border-box; }

/* Zaznaczenie w kolorze akcentu, nie w systemowym granacie. Dotyczy tego, co
   warto skopiowac: wspolrzednych i wartosci. */
::selection { background: color-mix(in srgb, var(--akcent) 30%, transparent); }

html {
  -webkit-text-size-adjust: 100%;
  /* Pozwala animowac wysokosc miedzy 0 a `auto` - bez tego rozwijane sekcje
     musialyby miec zaszyta wysokosc w pikselach. */
  interpolate-size: allow-keywords;
}

/* Tlo nie przewija sie, gdy stoi nad nim okno modalne. Czysty CSS zamiast
   zapamietywania i przywracania pozycji przewijania z JS. */
html:has(dialog[open]) { overflow: hidden; }

body {
  margin: 0;
  min-height: 100dvh;
  background: var(--bg);
  color: var(--txt);
  font: 400 16px/1.55 var(--font);
  /* PO skrocie `font`, bo ten resetuje ustawienia cyfr do wartosci poczatkowych */
  font-variant-numeric: tabular-nums;
  padding: 0 clamp(12px, 4vw, 20px) calc(28px + env(safe-area-inset-bottom));
  overscroll-behavior-y: contain;
}

h2, h3, h4 { margin: 0; font-weight: 600; }
p { margin: 0; }

button { font: inherit; color: inherit; cursor: pointer; }

/* ═════════════ DOTYK ═════════════
   Niebieska poswiata WebKita zdradza strone. Usuwamy ja, ale reakcja na
   dotkniecie musi czyms zostac zastapiona - inaczej interfejs sprawia
   wrazenie, ze nie zarejestrowal stukniecia. Zastepuje ja `:active` nizej.
   `touch-action: manipulation` kasuje przy okazji zoom przy dwukliku,
   ktory na kontrolkach jest wylacznie pomylka. */
* { -webkit-tap-highlight-color: transparent; }

button,
summary,
label,
.przelacznik,
.legenda,
.klucz__etyk,
.kafel__etyk {
  touch-action: manipulation;
  user-select: none;
  -webkit-user-select: none;
}

/* Wartosci i wspolrzedne zostaja zaznaczalne - to jedyne, co warto skopiowac. */
.stopka__info, .klucz__val, .szczegol__val { user-select: text; -webkit-user-select: text; }

/* Wspolna reakcja na dotkniecie. Krotka i plytka: ma potwierdzic trafienie,
   a nie odgrywac scenki. */
/* .985, nie .97. Skok o trzy procent na karcie wielkosci ekranu wyglada jak
   klikniecie w zabawke; ledwie zauwazalne przygniecenie potwierdza trafienie
   i nie odciaga uwagi. */
button:active,
summary:active { scale: .985; }
button, summary { transition: scale .12s ease-out; }

/* ═════════════ RUCH ═════════════
   Krzywa `wyjscie` to ta sama, ktorej uzywaja paski i kompas - jedno zrodlo
   charakteru ruchu w calej aplikacji. Wszystko ponizej to ruch WEJSCIA:
   pojawia sie raz i nie powtarza, wiec nie odciaga od czytania. */
:root { --wyjscie: cubic-bezier(.22, 1, .36, 1); }

@keyframes wejscie {
  from { opacity: 0; translate: 0 8px; }
  to { opacity: 1; translate: 0 0; }
}
@keyframes wejscie-fade {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* Ikony SVG rysowane kreska - jeden wspolny styl zamiast atrybutow w HTML */
svg { width: 1em; height: 1em; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }

/* Tresc wylacznie dla czytnika ekranu - poza ekranem, ale nie `display: none`
   ani `visibility: hidden`, bo te dwa wylaczaja tez odczyt. */
.tylko-czytnik {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ═════════════ SKALA KOLOROW ═════════════
   zielony - dobrze, bialy - normalnie, czerwony - zle.
   Przejscie bieli w czerwien jest plynne i sterowane przez --t, ale startuje
   od 50%: przekroczenie normy ma byc widoczne OD RAZU, a nie dopiero przy
   limicie. Przy poprzednim progu 35% "uwaga" zaczynala sie od bladego lososia
   stojacego tuz obok prawie bialej "normy" - dwa stany, jeden kolor. */
.st-dobre { --stan: var(--dobre); --tint: color-mix(in srgb, var(--dobre) 11%, transparent); }
.st-norma { --stan: var(--txt); --tint: transparent; }
.st-uwaga,
.st-zle {
  --stan: #ff7a70; /* zapas dla przegladarek bez color-mix */
  --stan: color-mix(in oklab, var(--txt), var(--zle) calc(50% + var(--t) * 50%));
  --tint: color-mix(in srgb, var(--zle) calc(10% + var(--t) * 12%), transparent);
}

/* Podbarwienie kladzie sie warstwa NAD kolorem tla, wiec ten sam mechanizm
   dziala na kazdym podlozu - i na --panel, i na --panel-2. Zastapilo paski
   akcentowe przy krawedzi, ktore byly najbardziej rozpoznawalnym znakiem
   interfejsu generowanego maszynowo. */
.wiatr__rzad,
.kosmos__poz,
.kafel { background-image: linear-gradient(var(--tint, transparent), var(--tint, transparent)); }

/* ── PASEK GORNY ── */
.pasek {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  gap: 8px;
  max-width: var(--sz-max);
  margin: 0 auto;
  padding: max(10px, env(safe-area-inset-top)) 0 10px;
  background: linear-gradient(var(--bg) 68%, transparent);
}

.pasek__miejsce {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  /* 8px, nie 10: pigulka ma teraz dwie linie i przy dawnym wypelnieniu
     rosla wyzsza od okraglych przyciskow o kilkanascie pikseli. */
  padding: 8px 13px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: var(--fs-md);
  text-align: left;
}
.pasek__miejsce > span {
  flex: 1;
  min-width: 0;
}
/* Kazda linia ucina sie osobno. `text-overflow` dziala wylacznie na elemencie,
   ktory sam jest blokiem z `nowrap`, wiec ustawienie go na rodzicu nie objeloby
   zadnej z dwoch linii. */
.pasek__nazwa b,
.pasek__nazwa em {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Interlinia z `body` (1,55) rozpychalaby pasek - tu obie linie stoja ciasno. */
.pasek__nazwa b { font-weight: 500; line-height: 1.25; }
.pasek__nazwa em {
  font-style: normal;
  font-size: var(--fs-xs);
  line-height: 1.35;
  color: var(--txt-3);
}
/* Wysokosc DWOCH linii zawsze, takze gdy dolnej jeszcze nie ma - inaczej pigulka
   jest nizsza podczas „Ustalam pozycje” i wyzsza po odpowiedzi geokodowania,
   wiec cala strona podskakuje w trakcie ladowania.

   Rezerwa siedzi na RODZICU, nie na pustej linii. Gdy stala na linii, sama nazwa
   ladowala na gornej krawedzi pigulki i wisiala nad pustym miejscem; teraz
   `justify-content` stawia pojedyncza linie na srodku, a dwie wypelniaja blok.
   Wysokosc liczona z tych samych wartosci, ktore opisuja obie linie. */
.pasek__nazwa {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: calc(var(--fs-md) * 1.25 + var(--fs-xs) * 1.35);
}
.pasek__miejsce svg { font-size: 1.15em; color: var(--txt-2); flex: none; }
.pasek__strzalka { font-size: .95em !important; }

.pasek__ikona {
  flex: none;
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 50%;
  font-size: 1.2rem;
  color: var(--txt-2);
  transition: color .22s, border-color .22s, scale .12s;
}
.pasek__ikona:hover { color: var(--txt); border-color: #33404c; }
.pasek__ikona--kreci svg { animation: obrot .8s linear infinite; }
@keyframes obrot { to { transform: rotate(360deg); } }

/* ── UKLAD TRESCI ── */
.tresc {
  display: flex;
  flex-direction: column;
  gap: 16px;
  max-width: var(--sz-max);
  margin: 0 auto;
  /* BEZ `both`: wypelnienie do przodu trzymaloby opacity z ostatniej klatki
     i bilo `.tresc--odswieza` nizej, ktore ma te tresc przygaszac. */
  animation: wejscie .45s var(--wyjscie);
}
/* BEZ tej reguly `hidden` na .tresc nic nie robi: autorskie `display: flex`
   powyzej bije regule UA `[hidden] { display: none }`. Skutkiem byl spinner
   ladowania wjezdzajacy OBOK starej tresci przy kazdym odswiezeniu.
   Przy okazji przelaczenie display none/flex restartuje animacje wejscia,
   wiec nie trzeba doklejac klasy z JS. */
.tresc[hidden] { display: none; }

/* Odswiezanie przy juz widocznej tresci: zostaje na ekranie i tylko przygasa.
   Wyrzucanie jej na rzecz pelnoekranowego spinnera zabieralo kontekst
   i podskakiwalo, bo spinner ma 70% wysokosci ekranu. */
.tresc--odswieza {
  opacity: .5;
  pointer-events: none;
  transition: opacity .2s;
}

.karta {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: var(--karta-pad);
}
/* „Cicha” znaczy bez pudelka: ani tla, ani obwodki. Zostaje sam wcięty rzad
   tekstu, jak wiersz w liscie ustawien - dwa mniej pojemnikow na ekranie. */
.karta--cicha {
  background: transparent;
  border-color: transparent;
  /* Bez pudelka wypelnienie karty nie ma czego wypelniac - odstep daje `gap`
     w `.tresc` i `.strefa`. Zostaje tyle, zeby rzad nie kleil sie do sasiada. */
  padding: 4px 6px;
}

/* ═════════════ STREFA WYBRANEJ GODZINY ═════════════
   Opakowanie na wszystko, co opisuje jedna godzine. Nie jest kosmetyczne:
   element `sticky` jedzie dokladnie tak dlugo, jak dlugo widac jego rodzica,
   wiec bez tego pasek godziny zostawalby na ekranie nad sekcjami, ktorych
   juz nie dotyczy. Odstep powtarza `gap` z `.tresc`, bo strefa wchodzi tam
   jako jeden element i przejmuje rytm za swoje dzieci. */
.strefa {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

/* ── PASEK GODZINY ──
   `--pasek-h` to zmierzona wysokosc paska gornego, ustawiana z JS. CSS nie
   odczyta wysokosci innego elementu, a liczba zaszyta na sztywno rozjedzie sie
   z `env(safe-area-inset-top)` i z dwuwierszowa nazwa miejscowosci. Wartosc
   zapasowa w `var()` jest tylko na wypadek, gdyby JS jeszcze nie zdazyl. */
.godzina {
  position: sticky;
  top: var(--pasek-h, 68px);
  z-index: 5;
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 8px 8px 14px;
  border: 1px solid color-mix(in srgb, var(--stan) 30%, var(--line));
  border-radius: 999px;
  background: var(--panel);
  font-size: var(--fs-sm);
}
.godzina__czas {
  flex: none;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: var(--txt);
}
/* Powod ustepuje miejsca jako pierwszy - godzina i przycisk powrotu musza
   byc w calosci, jego mozna przyciac. */
.godzina__powod {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--stan);
}
.godzina__teraz {
  position: relative;
  flex: none;
  padding: 6px 13px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--panel-2);
  color: var(--txt-2);
  font-size: var(--fs-xs);
}
/* Pole trafienia rozciagniete poza obrys do wymaganych 40 px. Sam przycisk
   zostaje niski, zeby przyklejony pasek nie zjadal ekranu - roslby wtedy
   o kolejne 12 px na kazdym przewinieciu strefy. */
.godzina__teraz::after { content: ""; position: absolute; inset: -8px -5px; }
/* Przycisk GASNIE zamiast znikac. Chowany `display: none` zmienial wysokosc
   przyklejonego paska przy kazdym przejsciu miedzy „teraz” a wybrana godzina,
   wiec skakala cala strefa pod nim. `visibility` trzyma wysokosc i szerokosc,
   a przy okazji zdejmuje przycisk z kolejnosci tabulacji i z drzewa
   dostepnosci - czyli robi to samo, co `hidden`, tylko bez skoku. */
.godzina__teraz--pusty { visibility: hidden; pointer-events: none; }

.karta__tyt {
  font-size: var(--fs-xs);
  letter-spacing: .11em;
  text-transform: uppercase;
  color: var(--txt-3);
  margin-bottom: 16px;
}

/* ═════════════ WERDYKT ═════════════ */
.werdykt {
  position: relative;
  overflow: hidden;
  /* Kolor stanu dotyka krawedzi i tla, ale ledwie. Mocniejsza poswiata robila
     z werdyktu baner; przy tych wartosciach czyta sie jako podswietlona
     powierzchnia, a informacje niesie i tak napis. */
  border: 1px solid color-mix(in srgb, var(--stan) 26%, var(--line));
  border-radius: var(--r);
  background:
    radial-gradient(130% 100% at 50% 0%, color-mix(in srgb, var(--stan) 11%, transparent), transparent 72%),
    var(--panel);
  padding: clamp(24px, 7vw, 34px) clamp(18px, 5vw, 24px) clamp(16px, 4vw, 20px);
  text-align: center;
}

/* 700, nie 800. Przy 3,8 rem sam rozmiar niesie juz cala wage, a najciezszy
   stopien Outfita w tej skali robi sie masywny zamiast stanowczy. Ciasniejszy
   trakting domyka litery w jeden blok - to on daje wrazenie drogiego napisu. */
.werdykt__stan {
  font-size: clamp(2.4rem, 13vw, 3.8rem);
  font-weight: 700;
  line-height: 1.04;
  letter-spacing: -.035em;
  color: var(--stan);
}

.werdykt__powod {
  margin-top: 10px;
  font-size: var(--fs-md);
  color: var(--txt-2);
}

.werdykt__czas {
  margin-top: 12px;
  font-size: var(--fs-xs);
  color: var(--txt-3);
}

/* ── OKNO LOTU ──
   Odpowiedz na "to kiedy" zaraz przy werdykcie. Prowadzi na os czasu,
   zamiast kazac jej szukac dwa ekrany nizej. */
.okno {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin-top: 12px;
  padding: 8px 15px;
  background: color-mix(in srgb, var(--stan) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--stan) 30%, transparent);
  border-radius: 999px;
  font-size: var(--fs-md);
  font-weight: 600;
  color: var(--stan);
  transition: background .22s, scale .12s;
}
/* BEZ tej reguly `hidden` na .okno nic nie robi: autorskie `display: inline-flex`
   powyzej bije regule UA `[hidden] { display: none }`. Skutkiem byla pusta
   pigulka z sama ikona zegara, widoczna zanim dojda dane. To samo dotyczylo
   juz .tresc i .stan - kazda ma swoja regule nizej albo wyzej. */
.okno[hidden] { display: none; }
.okno:hover:not(:disabled) { background: color-mix(in srgb, var(--stan) 20%, transparent); }
.okno:disabled { cursor: default; opacity: .75; font-weight: 400; }
.okno svg { font-size: 1.05em; flex: none; }

/* ── KLUCZOWE LICZBY ──
   Osiem parametrow o najwiekszej wadze w regulach, widocznych bez rozwijania
   czegokolwiek. CELOWO bez obudowy w kafle: to jest dowod pod werdyktem,
   czesc tego samego bloku, a nie kolejna sekcja. Podzial niosa kreski
   o szerokosci wlosa - tansze niz ramki i nie mnozy pudelek na ekranie.

   Uklad zalezny od szerokosci: na telefonie 2 kolumny x 4 rzedy,
   od 560 px 4 kolumny x 2 rzedy. Powod zmiany: przy czterech kolumnach na 360 px
   komorka miala ~70 px i najdluzsze etykiety („Temperatura”, „Widocznosc”) szly
   w wielokropek. Dwie kolumny daja ~150 px - etykieta miesci sie w calosci.
   Reguly nth-child ponizej ZAKLADAJA dokladnie 8 pozycji (patrz `KLUCZOWE`
   w app.js). Dolozenie dziewiatej wymaga poprawki kresek. */
.klucz {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  /* BEZ `gap`. Odstep robi wypelnienie komorek, bo tylko wtedy kreska miedzy
     rzedami ma gdzie usiasc - `gap` to pusta przestrzen siatki, w ktorej nie da
     sie nic narysowac. Wypelnienie daje przy okazji symetrie: 10 px nad kreska
     i 10 px pod nia. */
  margin-top: 16px;
  padding-top: 13px;
  border-top: 1px solid var(--line-2);
}
.klucz__poz {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 10px 6px;
  min-width: 0;
}
/* Skrajne rzedy bez wypelnienia od strony krawedzi bloku: nad pierwszym jest juz
   kreska sekcji, pod ostatnim konczy sie karta. */
.klucz__poz:nth-child(-n + 2) { padding-top: 0; }
.klucz__poz:nth-child(n + 7) { padding-bottom: 0; }
/* Kreska pozioma miedzy rzedami. Pelna szerokosc bloku, bez przerw. */
.klucz__poz:nth-child(n + 3) { border-top: 1px solid var(--line-2); }

/* Kreski pionowe rysuje pseudoelement, nie `border-left`. Powod: obwodka
   biegnie przez cala wysokosc komorki razem z wypelnieniem i tworzylaby
   z kreska pozioma rowny krzyz - uklad robilby sie tabela. Wciecie o kilka
   pikseli od gory i dolu sprawia, ze pionowe rozdzielaja liczby, a pozioma
   rozdziela rzedy, i zadna nie dotyka drugiej. */
.klucz__poz:not(:nth-child(2n + 1))::before {
  content: "";
  position: absolute;
  left: 0;
  top: 13px;
  bottom: 13px;
  border-left: 1px solid var(--line-2);
}
/* Skrajne rzedy nie maja nad soba (pod soba) kreski poziomej, wiec i wciecia. */
.klucz__poz:nth-child(-n + 2)::before { top: 0; }
.klucz__poz:nth-child(n + 7)::before { bottom: 0; }

.klucz__etyk {
  /* Przy dwoch kolumnach etykieta ma ~150 px i miesci sie w calosci - stad brak
     przycinania wielokropkiem. Zawijanie zostawione wlaczone jako zabezpieczenie
     dla waskich ekranow i wiekszej czcionki systemowej. */
  font-size: clamp(.66rem, 2.8vw, .72rem);
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--txt-3);
}

/* Od 560 px wraca uklad 4 x 2: kolumna ma wtedy ponad 100 px i etykiety
   mieszcza sie bez wielokropka. Kazda regula oparta na nth-child musi tu dostac
   odpowiednik dla czterech kolumn ORAZ wyzerowanie wariantu dwukolumnowego -
   inaczej kreski i wypelnienia zostaja po starym ukladzie. */
@media (min-width: 560px) {
  .klucz { grid-template-columns: repeat(4, 1fr); }
  .klucz__poz { padding: 10px 6px 0; }
  .klucz__poz:nth-child(-n + 4) { padding: 0 6px 10px; }
  .klucz__poz:nth-child(n + 3) { border-top: 0; }
  .klucz__poz:nth-child(n + 5) { border-top: 1px solid var(--line-2); }
  .klucz__poz::before { content: none; }
  .klucz__poz:not(:nth-child(4n + 1))::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    border-left: 1px solid var(--line-2);
  }
  .klucz__poz:nth-child(-n + 4)::before { bottom: 13px; }
  .klucz__poz:nth-child(n + 5)::before { top: 13px; }
  /* W czterech kolumnach nie ma miejsca na zawiniecie - jedna linia,
     a nadmiar (wieksza czcionka systemowa) ucina wielokropek. */
  .klucz__etyk { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
}
.klucz__val {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: clamp(1.15rem, 5.2vw, 1.3rem);
  font-weight: 600;
  line-height: 1.1;
  color: var(--stan);
}
.klucz__val i { font-style: normal; font-size: .58em; color: var(--txt-3); margin-left: 3px; }

/* ── ROZWINIECIE WERDYKTU ── */
.rozwin { margin-top: 16px; text-align: left; }

.rozwin summary {
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  /* PELNA SZEROKOSC KARTY, nie tylko obszaru tresci. Ujemny margines zdejmuje
     wypelnienie karty, wlasne wypelnienie stawia tekst z powrotem na miejscu.
     Bez tego podswietlenie dotkniecia konczylo sie 20-26 px przed krawedzia
     i wygladalo, jakby klikalo sie prostokat w srodku elementu, a nie caly
     element. Przy okazji kreska nad przyciskiem siega teraz obu krawedzi. */
  margin-inline: calc(-1 * var(--karta-pad));
  padding: 10px var(--karta-pad);
  font-size: var(--fs-sm);
  color: var(--txt-2);
  cursor: pointer;
  border-top: 1px solid var(--line-2);
}
.rozwin summary:active { background: var(--panel-2); }
.rozwin summary::-webkit-details-marker { display: none; }
.rozwin summary::after {
  content: "";
  width: 7px; height: 7px;
  border-right: 1.6px solid currentColor;
  border-bottom: 1.6px solid currentColor;
  rotate: 45deg;
  translate: 0 -2px;
  transition: rotate .2s;
}
.rozwin[open] summary::after { rotate: -135deg; translate: 0 2px; }

/* Plynna wysokosc rozwinieć. `interpolate-size: allow-keywords` na <html>
   pozwala animowac do `auto`, wiec nie trzeba nigdzie zaszywac pikseli.
   Obejmuje cztery miejsca naraz: szczegoly werdyktu, karte GPS, komplet
   parametrow w panelu slupka i wpisywanie wspolrzednych w oknie miejsc.
   Przegladarka bez ::details-content zwija skokowo, jak dotad. */
.rozwin::details-content,
.recznie::details-content {
  block-size: 0;
  overflow: clip;
  transition: block-size .32s var(--wyjscie), content-visibility .32s allow-discrete;
}
.rozwin[open]::details-content,
.recznie[open]::details-content { block-size: auto; }

/* OBWODKA FOKUSA RYSOWANA DO SRODKA. Wszystko w rozwinieciach siedzi w pojemniku
   z `overflow: clip` - to on pozwala animowac wysokosc do `auto`. Przyciecie idzie
   dokladnie po krawedzi pojemnika, a pola i przyciski maja pelna szerokosc, wiec
   obwodka rysowana NA ZEWNATRZ byla ucinana z lewej i prawej: wygladalo to, jakby
   nad polem lezal inny element. `overflow-clip-margin` nie jest tu wyjsciem -
   poszerzylby przyciecie takze w pionie i przy zwinietym rozwinieciu wystawalby
   pasek tresci. Ta sama regula obejmuje naglowek `summary`, ktory od czasu
   podswietlenia na pelna szerokosc tez konczy sie na krawedzi karty. */
.rozwin :focus-visible,
.recznie :focus-visible { outline-offset: -2px; }

.rozwin__tresc {
  display: grid;
  gap: 1px;
  margin-top: 4px;
}

.szczegol {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 8px 10px;
  border-radius: var(--r-s);
  background: var(--panel-2);
  font-size: var(--fs-sm);
}
.szczegol__nazwa { color: var(--txt-2); }
.szczegol__nazwa i {
  display: block;
  font-style: normal;
  font-size: var(--fs-xs);
  color: var(--txt-3);
}
.szczegol__val {
  flex: none;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--stan);
}

/* Karta zwijana - naglowek niesie skrot, wiec zwiniety stan tez informuje. */
/* `overflow: hidden`, bo naglowek siega teraz krawedzi karty. Bez tego jego
   podswietlenie wychodzi poza zaokraglone rogi i karta traci ksztalt. */
.rozwin--karta { margin-top: 0; padding-block: 0; overflow: hidden; }
.rozwin--karta summary {
  justify-content: space-between;
  gap: 12px;
  padding: clamp(15px, 4vw, 19px) var(--karta-pad);
  border-top: 0;
}
.rozwin--karta[open] summary { padding-bottom: 12px; }
.rozwin__tyt {
  font-size: var(--fs-xs);
  letter-spacing: .11em;
  text-transform: uppercase;
  color: var(--txt-3);
}
.rozwin__skrot {
  margin-left: auto;
  font-family: var(--mono);
  font-size: var(--fs-sm);
  color: var(--txt-2);
}
.rozwin--karta > *:last-child { padding-bottom: clamp(15px, 4vw, 19px); }

/* ═════════════ PROFIL PIONOWY WIATRU ═════════════
   Kazdy wiersz tlumaczy sie sam: etykieta mowi czego dotyczy, wartosc
   z jednostka siedzi w tym samym elemencie co pasek. Wczesniej liczba
   wisiala obok paska i wymagala legendy, zeby wiedziec czym jest. */
/* Odstep MIEDZY parami musi wyraznie przewyzszac odstep WEWNATRZ pary.
   Wczesniej gap siedzial na `.profil`, a `.poziom` sa dziecmi `.profil__rzedy`,
   wiec miedzy parami bylo 0 px, a wewnatrz 7 px - etykieta lezala blizej
   cudzego paska niz wlasnego i nie bylo wiadomo, ktorego dotyczy. */
.profil { display: grid; gap: 16px; }
.profil__rzedy { display: grid; gap: 28px; }

.profil__gora {
  margin-bottom: 4px;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  font-size: var(--fs-xs);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--txt-3);
}
.profil__info {
  font-family: var(--mono);
  font-size: var(--fs-sm);
  letter-spacing: 0;
  text-transform: none;
  color: var(--txt-2);
}

.poziom { display: grid; gap: 7px; }

.poziom__gora {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}

/* Jeden rozmiar, jeden krój - kontrast wylacznie przez wage i kolor.
   Wczesniej etykieta mieszala trzy rozne traktowania w jednej frazie. */
.poziom__etyk {
  font-size: var(--fs-md);
  font-weight: 400;
  color: var(--txt-3);
}
.poziom__etyk b {
  font-weight: 600;
  color: var(--txt);
}
.poziom--pulap .poziom__etyk b { color: var(--stan); }

.poziom__zrodlo {
  flex: none;
  font-size: var(--fs-xs);
  font-weight: 500;
  color: var(--txt-3);
}

.poziom__pas {
  position: relative;
  display: flex;
  align-items: center;
  height: 34px;
  border-radius: 8px;
  background: var(--panel-2);
  overflow: hidden;
}
/* --w = udzial w skali siegajacej limitu wiatru */
.poziom__pas > i {
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--w);
  background: color-mix(in srgb, var(--stan) 26%, transparent);
  border-right: 2px solid var(--stan);
  transition: width .5s cubic-bezier(.22, 1, .36, 1);
}
.poziom__val {
  position: relative;
  padding-left: 13px;
  font-size: var(--fs-md);
  font-weight: 600;
  color: var(--txt);
}

.profil__notka {
  font-size: var(--fs-xxs);
  color: var(--txt-3);
}
.profil__notka:empty { display: none; }

/* ═════════════ WIERSZE WIATRU ═════════════ */
/* Bez `margin-top`: blok stoi teraz zaraz pod naglowkiem karty, ktory ma
   wlasny odstep dolny. Profil pionowy przeniosl sie do rozwiniecia. */
.wiatr {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

/* Cialo rozwiniecia w karcie wiatru. `.kierunek` i `.zgodnosc` przynosza wlasne
   kreski i odstepy, wiec wrapper daje tylko oddech pod przyciskiem. */
.wiatr-wiecej { padding-top: 14px; }

.wiatr__rzad {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: baseline;
  gap: 3px 12px;
  padding: 11px 13px;
  border-radius: var(--r-s);
  border: 1px solid var(--line);
  background-color: var(--panel-2);
}

.wiatr__opis { font-size: var(--fs-md); color: var(--txt-2); }
.wiatr__opis em {
  display: block;
  font-style: normal;
  font-size: var(--fs-xs);
  color: var(--txt-3);
}

.wiatr__val { font-family: var(--mono); font-variant-numeric: tabular-nums; white-space: nowrap; }
.wiatr__val b { font-size: 1.5rem; font-weight: 600; color: var(--stan); }
.wiatr__val i { font-style: normal; font-size: var(--fs-xs); color: var(--txt-3); margin-left: 4px; }

.wiatr__zakres {
  grid-column: 1 / -1;
  font-size: var(--fs-xs);
  color: var(--txt-3);
}

/* ── ROZA WIATROW ── */
.kierunek {
  display: flex;
  align-items: center;
  gap: 15px;
  margin-top: 20px;
  padding-top: 20px;
  border-top: 1px solid var(--line-2);
}

.kierunek__roza {
  position: relative;
  flex: none;
  width: 56px;
  height: 56px;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: var(--panel-2);
}

/* --kat ustawiany z JS: kierunek, W KTORY zniesie drona.
   Grot rysowany przez clip-path, a nie trojkatem z obramowan - ksztalt
   jest wtedy jednoznaczny i nie zalezy od kolejnosci wlasciwosci border. */
.kierunek__igla {
  position: absolute;
  inset: 0;
  rotate: var(--kat);
  transition: rotate .5s cubic-bezier(.22, 1, .36, 1);
}
.kierunek__igla::before {
  content: "";
  position: absolute;
  top: 6px;
  left: 50%;
  translate: -50% 0;
  width: 15px;
  height: 19px;
  background: var(--akcent);
  /* wierzcholek u gory (0 stopni = polnoc), wciecie u dolu */
  clip-path: polygon(50% 0%, 100% 100%, 50% 76%, 0% 100%);
}

.kierunek__n {
  position: absolute;
  top: -2px;
  left: 50%;
  translate: -50% -100%;
  font-size: var(--fs-xs);
  color: var(--txt-3);
}

.kierunek__txt b {
  font-family: var(--mono);
  font-size: var(--fs-lg);
  font-weight: 600;
}
.kierunek__txt span { display: block; font-size: var(--fs-sm); color: var(--txt-2); }

/* ── ZGODNOSC MODELI ── */
.zgodnosc {
  margin-top: 20px;
  padding-top: 20px;
  border-top: 1px solid var(--line-2);
}

.zgodnosc__gora {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 10px;
  font-size: var(--fs-sm);
  color: var(--txt-2);
  margin-bottom: 7px;
}
.zgodnosc__gora span:last-child { color: var(--txt-3); font-size: var(--fs-xs); }

.zgodnosc__pas {
  height: 6px;
  border-radius: 999px;
  background: var(--panel-2);
  overflow: hidden;
}
/* --p = procent zgodnosci; 100% to identyczne wyniki wszystkich modeli */
.zgodnosc__pas span {
  display: block;
  height: 100%;
  width: var(--p);
  border-radius: inherit;
  background: var(--stan);
  transition: width .6s cubic-bezier(.22, 1, .36, 1);
}

/* ── LINK-PRZYCISK ──
   Wczesniej zwykly podkreslony link; teraz element interfejsu w stylu strony. */
.link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 12px;
  padding: 7px 13px;
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: var(--fs-sm);
  color: var(--txt-2);
  transition: color .22s, border-color .22s, background .22s, scale .12s;
}
.link:hover { color: var(--txt); border-color: var(--akcent); background: transparent; }

/* ═════════════ KAFLE ═════════════ */
.kafle {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px;
}
@media (min-width: 430px) {
  .kafle { grid-template-columns: repeat(3, 1fr); }
}

.kafel {
  background-color: var(--panel);
  border: 1px solid var(--line-2);
  border-radius: var(--r);
  padding: 15px;
}
.kafel__etyk {
  display: block;
  font-size: var(--fs-xs);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--txt-3);
  margin-bottom: 7px;
}
.kafel__val {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: clamp(1.35rem, 6vw, 1.6rem);
  font-weight: 600;
  color: var(--stan);
  line-height: 1.1;
}
.kafel__val i { font-style: normal; font-size: .6em; color: var(--txt-3); margin-left: 4px; }
.kafel__pod {
  display: block;
  margin-top: 6px;
  font-size: var(--fs-xs);
  line-height: 1.45;
  color: var(--txt-3);
}

/* ═════════════ GPS I KOSMOS ═════════════ */
.kosmos {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(96px, 1fr));
  gap: 10px;
}

.kosmos__poz {
  padding: 12px;
  border-radius: var(--r-s);
  border: 1px solid var(--line-2);
  background-color: var(--panel-2);
}
.kosmos__etyk { display: block; font-size: var(--fs-xs); color: var(--txt-3); margin-bottom: 5px; }
.kosmos__poz b {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 1.45rem;
  font-weight: 600;
  color: var(--stan);
}
.kosmos__pod {
  display: block;
  margin-top: 4px;
  font-size: var(--fs-xs);
  line-height: 1.45;
  color: var(--txt-3);
}

.notka {
  margin-top: 14px;
  font-size: var(--fs-xs);
  line-height: 1.55;
  color: var(--txt-3);
}

/* ═════════════ OS CZASU ═════════════ */
.os__gora {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 16px;
}
.os__gora .karta__tyt { margin-bottom: 0; }

.przelacznik {
  display: flex;
  gap: 2px;
  padding: 2px;
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: 999px;
}
.przelacznik__opcja {
  padding: 6px 13px;
  background: none;
  border: 0;
  border-radius: 999px;
  font-size: var(--fs-xs);
  color: var(--txt-3);
  white-space: nowrap;
  transition: background .22s, color .22s, scale .12s;
}
.przelacznik__opcja:hover { color: var(--txt-2); }
.przelacznik__opcja--wybrana {
  background: var(--panel);
  color: var(--txt);
  font-weight: 600;
}
.os {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);   /* minmax(0,...) - bez tego kolumny
                                          nie zejda ponizej swojej tresci */
  align-items: end;
  gap: var(--odstep);
  height: 130px;
}

/* Wykres z opisana osia Y - liczby nad slupkami nie mowily czym sa. */
.os__ramka { display: grid; grid-template-columns: auto 1fr; gap: 10px; }

.os__y {
  writing-mode: vertical-rl;
  rotate: 180deg;
  align-self: stretch;
  display: grid;
  place-items: center;
  padding-bottom: 22px;   /* wyrownanie do slupkow, z pominieciem podpisow godzin */
  font-size: var(--fs-xs);
  letter-spacing: .04em;
  color: var(--txt-3);
  white-space: nowrap;
}

.os__pole { min-width: 0; }

/* Pasek etykiet dob nad wykresem - kazda etykieta zajmuje tyle kolumn,
   ile blokow przypada na ta dobe. */
.os-dni {
  display: grid;
  grid-template-columns: repeat(var(--kolumn, 1), minmax(0, 1fr));
  gap: var(--odstep, 4px);
  margin-bottom: 8px;
}
.os-dni:empty { display: none; }
.os-dni span {
  grid-column: span var(--ile);
  font-size: var(--fs-xs);
  color: var(--txt-3);
  border-bottom: 1px solid var(--line-2);
  padding-bottom: 4px;
}

.os { --odstep: clamp(3px, 1.2vw, 6px); }

/* Granica doby - bez niej "02" po "23" nie mowi ktorego dnia dotyczy */
.godz--nowy-dzien { position: relative; }
.godz--nowy-dzien::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 16px;
  left: calc(var(--odstep) / -2);
  width: 1px;
  background: var(--line);
}

/* SIATKA, nie flex - i to nie jest kosmetyka.
   W kolumnie flex `height: var(--h)` na slupku liczylo sie od calej wysokosci
   kolumny (130 px), wiec juz przy --h okolo 63% suma tresci przekraczala
   pojemnosc i flex-shrink scinal slupek do miejsca, ktore akurat zostalo.
   Skutek: KAZDY slupek mial identyczne 81,3 px niezaleznie od wartosci,
   a os "Porywy" nie niosla zadnej informacji wysokoscia.
   W siatce srodkowy rzad `1fr` jest wlasnym torem slupka i procent liczy sie
   od niego, wiec 100% i 63% to znowu dwie rozne wysokosci. */
.godz {
  display: grid;
  grid-template-rows: auto 1fr auto;
  align-items: end;
  justify-items: center;
  gap: 5px;
  height: 100%;
  min-width: 0;
  padding: 0;
  background: none;
  border: 0;
  border-radius: 8px;
}
.godz--wybrana { background: var(--panel-2); }
.godz:active { background: var(--panel-2); }

/* Kropka oznacza blok, w ktorym o kolorze zdecydowal nie wiatr, tylko
   inny parametr - inaczej niski slupek na czerwono nie mial wyjasnienia. */
.godz__inny {
  font-style: normal;
  color: var(--stan);
  margin-left: 1px;
}

.godz__val {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  color: var(--txt-3);
}
.godz__val b { font-weight: 400; }
.os--gesty .godz__czas { font-size: var(--fs-xxs); }

/* Przy 48 h kolumny maja kilkanascie pikseli i liczby zlewalyby sie ze soba.
   Zostaje ksztalt slupka, opisana os Y i kropka; dokladne wartosci sa
   po dotknieciu. */
.os--gesty .godz__val b { display: none; }
.os--gesty .godz__inny { margin: 0; font-size: 1.1em; }

/* --h = wysokosc slupka w procentach skali; skala wspolna dla calej osi */
.godz__slup {
  width: 100%;
  align-self: end;
  height: var(--h);
  min-height: 4px;
  /* Kapsulka, nie prostokat z lekko sciete rogiem. Przy 48 h slupek ma
     kilkanascie pikseli szerokosci, wiec pelne zaokraglenie daje czytelny
     ksztalt zamiast rozmytego naroznika. */
  border-radius: 999px;
  background: var(--stan);
  opacity: .9;
  transition: height .5s var(--wyjscie);
  /* Wejscie przez scaleY, a NIE przez height: wysokosc ma juz wlasne
     przejscie linijke wyzej i dwie animacje bilyby sie o te sama wlasciwosc.
     Do tego scaleY idzie po kompozytorze. --i = numer slupka z JS. */
  transform-origin: bottom;
  animation: slup .45s var(--wyjscie) backwards;
  animation-delay: calc(var(--i, 0) * 18ms);
}
@keyframes slup { from { scale: 1 0; opacity: 0; } }
/* Przy dokladaniu zrodel os przerysowuje sie kilka razy w ciagu sekundy.
   Wejscie ma zagrac raz - potem slupki zmieniaja sie samym `height`,
   ktore ma wlasne przejscie i wyglada na aktualizacje, nie na restart. */
.os--cicho .godz__slup { animation: none; }
.godz--teraz .godz__slup { opacity: 1; box-shadow: 0 0 0 1px var(--bg), 0 0 0 2px var(--stan); }

.godz__czas {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  color: var(--txt-2);
}
.godz--teraz .godz__czas { color: var(--txt); font-weight: 600; }

/* Godzina wskazana przez przycisk okna lotu - krotkie pulsowanie obwodki */
.godz--wskazana .godz__slup {
  outline: 2px solid var(--akcent);
  outline-offset: 3px;
  border-radius: 999px;
}

.legenda {
  margin-top: 18px;
  padding-top: 16px;
  border-top: 1px solid var(--line-2);
}

.legenda__stany {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 18px;
  font-size: var(--fs-sm);
  color: var(--txt-2);
}
.legenda__stany span { display: inline-flex; align-items: center; gap: 7px; }

.legenda__opis {
  margin-top: 10px;
  font-size: var(--fs-xs);
  line-height: 1.6;
  color: var(--txt-3);
}

.kropka { width: 8px; height: 8px; border-radius: 50%; }
.kropka--dobre { background: var(--dobre); }
.kropka--norma { background: var(--txt); }
.kropka--zle { background: var(--zle); }

/* ═════════════ WIEK DANYCH ═════════════ */
.zrodla { display: grid; gap: 2px; }

.zrodlo {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 9px 11px;
  border-radius: var(--r-s);
  background: var(--panel-2);
  font-size: var(--fs-sm);
}
.zrodlo__nazwa { color: var(--txt-2); }
.zrodlo__nazwa i {
  display: block;
  font-style: normal;
  font-size: var(--fs-xs);
  color: var(--txt-3);
}
.zrodlo__czas {
  flex: none;
  font-family: var(--mono);
  font-size: var(--fs-xs);
  color: var(--stan);
}
.zrodlo--brak .zrodlo__czas { color: var(--txt-3); }
.zrodlo--laduje .zrodlo__czas { color: var(--txt-3); }

/* ── MALE KOLKO PRZY WARTOSCI ──
   Satelity dochodza PO tym, jak reszta aplikacji jest juz gotowa (Celestrak
   potrafi milczec do konca limitu), wiec ich miejsce musi mowic "jeszcze leci",
   a nie "nie ma". Rozmiar w `em`, zeby siedzialo w linii z liczba, obok ktorej
   stoi - raz przy `--fs-xs` w wieku danych, raz przy duzej liczbie na karcie. */
.mini-kreci {
  display: inline-block;
  width: 1em;
  height: 1em;
  vertical-align: -.1em;
  border: 2px solid var(--line);
  border-top-color: var(--txt-3);
  border-radius: 50%;
  animation: obrot .7s linear infinite;
}

/* Przy ograniczonym ruchu globalna regula na dole pliku zatrzymalaby kolko
   po jednym obrocie i zostalby nieruchomy pierscien udajacy ikone. Wtedy
   znika, a stan niesie samo slowo przy nim ("Pobieram orbity"). */
@media (prefers-reduced-motion: reduce) {
  .mini-kreci { display: none; }
}

/* ═════════════ STOPKA ═════════════ */
.stopka { display: flex; gap: 24px; }
.stopka__poz span { font-size: var(--fs-xs); color: var(--txt-3); display: block; }
.stopka__poz b { font-family: var(--mono); font-size: var(--fs-md); font-weight: 500; }

/* Kreska nad pomiarem oddzielala go od wschodu i zachodu. Te przeniosly sie
   do strefy godziny, wiec gdy blok stoi sam w karcie, nie ma czego oddzielac. */
.imgw:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
.imgw {
  margin-top: 13px;
  padding-top: 13px;
  border-top: 1px solid var(--line-2);
  font-size: var(--fs-sm);
  line-height: 1.5;
  color: var(--txt-2);
}
.imgw__etyk {
  display: block;
  font-size: var(--fs-xs);
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--txt-3);
  margin-bottom: 4px;
}

.stopka__info {
  text-align: center;
  font-family: var(--mono);
  font-size: var(--fs-xs);
  color: var(--txt-3);
}

/* ── ATRYBUCJA I ODNOSNIKI DOKUMENTU ──
   Wymog licencji zrodel (Open-Meteo CC BY 4.0, OpenStreetMap ODbL, regulamin
   danych IMGW), a przy okazji jedyne wejscie do dokumentu z zastrzezeniem
   i polityka prywatnosci. Stoi na koncu i ma stac cicho: to nie jest tresc,
   po ktora sie tu przychodzi, ale musi byc widoczna bez szukania. */
.atryb {
  margin: 14px 0 0;
  text-align: center;
  font-size: var(--fs-xxs);
  line-height: 1.6;
  color: var(--txt-3);
  /* Odnosniki lamia sie na telefonie w dowolnym miejscu - bez tego dwa
     ostatnie zrodla wychodzily poza kolumne tekstu. */
  text-wrap: pretty;
}
.atryb + .atryb { margin-top: 8px; }
.atryb a {
  color: var(--txt-2);
  text-decoration-color: var(--line);
  text-underline-offset: 2px;
  transition: color .22s, text-decoration-color .22s;
}
.atryb a:hover { color: var(--txt); text-decoration-color: var(--akcent); }

/* Nazwa aplikacji trzyma sie stopki - pasek gorny jest zajety przez wybor
   miejsca i dwie ikony, a to jedyne miejsce, gdzie nazwa niczego nie zaslania. */
.marka {
  margin-top: 20px;
  text-align: center;
  font-size: var(--fs-xxs);
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--txt-3);
  opacity: .65;
}

/* ── WSKAZNIK ODSWIEZANIA GESTEM ──
   --ptr = przesuniecie w px, ustawiane z JS podczas ciagniecia. Przy zerze
   element stoi 44 px NAD krawiedzia ekranu, wiec nie trzeba go chowac
   osobno przez opacity ani hidden. */
.ptr {
  position: fixed;
  top: 0;
  left: 50%;
  z-index: 9;
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  margin-left: -18px;
  border-radius: 50%;
  background: var(--panel);
  border: 1px solid var(--line);
  color: var(--txt-3);
  font-size: 1.15rem;
  translate: 0 calc(var(--ptr, 0px) - 44px);
  transition: translate .3s var(--wyjscie), color .15s, border-color .15s;
}
/* W trakcie ciagniecia wskaznik ma isc za palcem bez opoznienia - przejscie
   na `translate` sprawiloby, ze wlecze sie kilka klatek za nim. */
.ptr--ciagnie { transition: color .15s, border-color .15s; }

/* Prog przekroczony: puszczenie odswiezy. Zmiana koloru I obrot strzalki -
   sam kolor bylby tu jedynym nosnikiem informacji. */
.ptr--gotowy { color: var(--akcent); border-color: var(--akcent); }
.ptr--gotowy svg { rotate: 180deg; }
.ptr svg { transition: rotate .2s var(--wyjscie); }

.ptr--kreci svg { animation: obrot .8s linear infinite; rotate: none; }

/* ═════════════ STANY: LADOWANIE, BLAD ═════════════ */
.stan {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 15px;
  min-height: 70dvh;
  text-align: center;
  font-size: var(--fs-md);
  color: var(--txt-2);
}
.stan[hidden] { display: none; }

/* ── EKRAN POWITALNY ──
   Pokazywany raz, przed pierwszym zapytaniem o GPS. Ma zmiescic sie bez
   przewijania na telefonie, wiec `min-height` idzie na pelna wysokosc okna,
   a nie na 70% jak w pozostalych stanach. */
.stan--start {
  min-height: 100dvh;
  gap: 0;
  justify-content: center;
  max-width: 30rem;
  margin: 0 auto;
}
.start__tyt {
  margin: 0;
  font-size: clamp(2rem, 9vw, 2.6rem);
  font-weight: 700;
  letter-spacing: .04em;
  line-height: 1;
  color: var(--txt);
}
/* Rozwiniecie skrotu pod nim, mniejsze i bez wersalikow: nazwa jest zartem,
   ktory dziala tylko wtedy, gdy widac oba czlony naraz. */
.start__tyt em {
  display: block;
  margin-top: 6px;
  font-style: normal;
  font-size: .34em;
  font-weight: 400;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--txt-3);
}
.start__lead {
  margin: 22px 0 0;
  font-size: var(--fs-md);
  text-wrap: pretty;
}
/* Zastrzezenie w jednym zdaniu, na tle karty - ma sie odciac od zachety,
   nad ktora stoi. Pelna wersja jest w informacje.html. */
.start__uwaga {
  margin: 18px 0 0;
  padding: 13px 16px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--r-s);
  font-size: var(--fs-sm);
  color: var(--txt-3);
  text-wrap: pretty;
}
.start__uwaga b { color: var(--txt-2); font-weight: 600; }
.stan--start .btn { margin-top: 24px; }
.start__gps {
  margin: 16px 0 0;
  font-size: var(--fs-xs);
  color: var(--txt-3);
  text-wrap: pretty;
}
.start__dok { margin: 22px 0 0; font-size: var(--fs-xs); }
.start__dok a { color: var(--txt-3); text-underline-offset: 2px; }
.start__dok a:hover { color: var(--txt-2); }
.stan:not([hidden]) { animation: wejscie-fade .3s var(--wyjscie); }
.stan__ikona { font-size: 2.4rem; color: var(--zle); }

.spinner {
  width: 30px;
  height: 30px;
  border: 2px solid var(--line);
  border-top-color: var(--akcent);
  border-radius: 50%;
  animation: obrot .7s linear infinite;
}

.btn {
  padding: 11px 22px;
  background: var(--akcent);
  color: #06121f;
  border: 0;
  border-radius: 999px;
  font-weight: 600;
  font-size: var(--fs-md);
}
.btn:hover { filter: brightness(1.1); }

/* ═════════════ OKNA MODALNE ═════════════ */
.dlg {
  width: min(100%, 470px);
  max-height: 88dvh;
  margin: auto auto 0;
  padding: 20px clamp(14px, 4vw, 20px) calc(20px + env(safe-area-inset-bottom));
  background: var(--panel);
  color: var(--txt);
  border: 1px solid var(--line);
  border-radius: var(--r) var(--r) 0 0;
  overflow-y: auto;
  /* Pasek przewijania w oknie ustawien rozbijal siatke pol - ukryty,
     przewijanie dzialacem gestem i kolkiem bez zmian. */
  scrollbar-width: none;
  /* Dojechanie do konca listy w oknie nie przewija strony pod spodem. */
  overscroll-behavior: contain;

  /* Arkusz wjezdza z dolu i wyjezdza tak samo. `allow-discrete` na `display`
     i `overlay` jest tu konieczne: bez niego okno znika natychmiast po
     .close() i animacji wyjscia nie widac wcale. */
  opacity: 0;
  translate: 0 24px;
  transition: opacity .22s, translate .3s var(--wyjscie),
              display .3s allow-discrete, overlay .3s allow-discrete;
}
.dlg[open] { opacity: 1; translate: 0 0; }
@starting-style { .dlg[open] { opacity: 0; translate: 0 24px; } }
.dlg::-webkit-scrollbar { width: 0; height: 0; }

@media (min-width: 560px) {
  .dlg { margin: auto; border-radius: var(--r); }
}
.dlg::backdrop {
  background: #000a;
  backdrop-filter: blur(3px);
  opacity: 0;
  transition: opacity .25s, display .25s allow-discrete, overlay .25s allow-discrete;
}
.dlg[open]::backdrop { opacity: 1; }
@starting-style { .dlg[open]::backdrop { opacity: 0; } }
.dlg h2 { font-size: 1.15rem; margin-bottom: 14px; }

/* Godzina, ktorej dotyczy rozpisanie na modele. */
.dlg__godzina {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-sm);
  color: var(--txt);
  margin: -6px 0 14px;
}
.dlg h3 {
  font-size: var(--fs-xs);
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--txt-3);
  margin: 22px 0 10px;
}

.dlg__zamknij { position: absolute; top: 14px; right: 14px; }
.dlg__zamknij button {
  width: 32px; height: 32px;
  display: grid; place-items: center;
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: 50%;
  color: var(--txt-2);
  font-size: var(--fs-sm);
}
.dlg__zamknij button:hover { color: var(--txt); }

.dlg__wstep {
  margin: -6px 0 16px;
  font-size: var(--fs-sm);
  line-height: 1.6;
  color: var(--txt-2);
}
.dlg__wstep b { color: var(--txt); font-weight: 600; }

.dlg__blad {
  margin-top: 12px;
  padding: 11px 13px;
  border-radius: var(--r-s);
  background: color-mix(in srgb, var(--zle) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--zle) 35%, transparent);
  font-size: var(--fs-sm);
  line-height: 1.5;
  color: var(--txt);
}
.dlg__blad[hidden] { display: none; }

.dlg__akcje {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 18px;
  padding-top: 16px;
  border-top: 1px solid var(--line-2);
}
.dlg__akcje .link { margin-top: 0; }

/* ── LISTA MIEJSC ── */
.miejsce {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 13px;
  margin-bottom: 6px;
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: var(--r-s);
  text-align: left;
}
.miejsce svg { font-size: 1.15em; color: var(--txt-2); flex: none; }
.miejsce > button[data-wybierz] {
  flex: 1;
  min-width: 0;
  /* Przycisk zamiast spana - patrz komentarz w app.js. Zdejmujemy wyglad
     kontrolki, zeby wiersz listy wygladal tak samo jak wczesniej. */
  padding: 0;
  background: none;
  border: 0;
  text-align: left;
  font-size: var(--fs-md);
  cursor: pointer;
}
.miejsce em { display: block; font-style: normal; font-size: var(--fs-xs); color: var(--txt-3); }
.miejsce--aktywne { border-color: var(--akcent); }
.miejsce--aktywne svg { color: var(--akcent); }

.miejsce__usun {
  flex: none;
  width: 30px; height: 30px;
  display: grid; place-items: center;
  background: none;
  border: 0;
  border-radius: 50%;
  color: var(--txt-3);
  font-size: var(--fs-sm);
}
.miejsce__usun:hover { color: var(--zle); background: #ff5a521a; }

.lista-miejsc:empty { display: none; }

/* ── POLA TEKSTOWE ── */
.szukaj input,
.recznie input {
  width: 100%;
  padding: 12px 13px;
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: var(--r-s);
  color: var(--txt);
  font: inherit;
  font-size: var(--fs-md);
}
.szukaj input:focus-visible,
.recznie input:focus-visible { outline: 2px solid var(--akcent); outline-offset: -2px; }

.szukaj__wyniki:not(:empty) { margin-top: 6px; display: flex; flex-direction: column; gap: 4px; }
.szukaj__wynik {
  width: 100%;
  padding: 11px 13px;
  background: none;
  border: 1px solid var(--line);
  border-radius: var(--r-s);
  text-align: left;
  font-size: var(--fs-md);
}
.szukaj__wynik:hover { background: var(--panel-2); border-color: var(--akcent); }
.szukaj__wynik em { display: block; font-style: normal; font-size: var(--fs-xs); color: var(--txt-3); }

.recznie { margin-top: 14px; }
.recznie summary { font-size: var(--fs-sm); color: var(--akcent); cursor: pointer; }
.recznie__pola { display: grid; gap: 9px; margin: 13px 0; }
.recznie label { font-size: var(--fs-xs); color: var(--txt-3); display: grid; gap: 5px; }

/* ═════════════ PROGI ═════════════ */
.progi { display: grid; gap: 6px; }

.prog {
  padding: 11px 12px;
  border-radius: var(--r-s);
  background: var(--panel-2);
}

.prog__etyk { display: block; font-size: var(--fs-md); margin-bottom: 9px; }
.prog__etyk em {
  display: block;
  font-style: normal;
  font-size: var(--fs-xs);
  color: var(--txt-3);
}

.prog__pola { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }

.prog__pole { display: grid; gap: 4px; }
.prog__podpis {
  font-size: var(--fs-xs);
  letter-spacing: .04em;
  color: var(--txt-3);
  text-align: center;
}

/* Kontrolka liczbowa z wlasnymi przyciskami - natywne strzalki
   `input[type=number]` sa nieostylowalne i wygladaly jak z innej strony. */
.prog__kontrolka {
  display: grid;
  grid-template-columns: 26px 1fr 26px;
  align-items: stretch;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 8px;
  overflow: hidden;
}
.prog__kontrolka:focus-within { border-color: var(--akcent); }

.prog__krok {
  display: grid;
  place-items: center;
  background: none;
  border: 0;
  padding: 0;
  color: var(--txt-3);
  font-size: var(--fs-md);
  font-weight: 600;
  line-height: 1;
  transition: color .15s, background .15s, scale .09s;
}
.prog__krok:hover { color: var(--txt); background: var(--panel-2); }

.prog input[type="number"] {
  width: 100%;
  min-width: 0;
  padding: 8px 0;
  background: none;
  border: 0;
  color: var(--txt);
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-md);
  text-align: center;
  /* natywne strzalki wylaczone - zastapione przyciskami obok */
  appearance: textfield;
  -moz-appearance: textfield;
}
.prog input[type="number"]::-webkit-outer-spin-button,
.prog input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.prog input:focus-visible { outline: none; }

/* ═════════════ TABELA MODELI ═════════════ */
.modele-grupa { margin-bottom: 20px; }
.modele-grupa h4 {
  margin-bottom: 10px;
  font-size: var(--fs-xs);
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--txt-3);
}
.modele-grupa h4 span {
  display: block;
  margin-top: 4px;
  font-family: var(--mono);
  font-size: 1.05em;
  letter-spacing: 0;
  text-transform: none;
  color: var(--akcent);
}

.modele-wiersz {
  display: grid;
  grid-template-columns: 92px 1fr 58px;
  align-items: center;
  gap: 11px;
  padding: 7px 0;
  font-size: var(--fs-sm);
}
.modele-wiersz + .modele-wiersz { border-top: 1px solid var(--line-2); }
.modele-wiersz--brak { color: var(--txt-3); }

/* --p = pozycja wartosci na skali min-max grupy
   --med = pozycja mediany, dziedziczona z .modele-grupa */
.modele-pas {
  height: 5px;
  border-radius: 999px;
  background: var(--panel-2);
  position: relative;
}
.modele-pas::after {
  content: "";
  position: absolute;
  top: 50%;
  left: var(--p);
  translate: -50% -50%;
  width: 9px; height: 9px;
  border-radius: 50%;
  background: var(--akcent);
}
/* Pionowa kreska mediany - widac od razu, ktore modele odstaja i w ktora strone */
.modele-pas--med::before {
  content: "";
  position: absolute;
  top: -4px;
  bottom: -4px;
  left: var(--med);
  width: 2px;
  translate: -50% 0;
  background: var(--txt-3);
  border-radius: 1px;
}
.modele-wiersz b {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-weight: 500;
  text-align: right;
}

/* ── DOSTEPNOSC ── */
:focus-visible { outline: 2px solid var(--akcent); outline-offset: 2px; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}
