/* Szkielet strony i prymitywy ukladu.

   Najwazniejsza zmiana wobec starego frontu: strona przewija sie normalnie.
   Wczesniej `body` mial `overflow: hidden`, `main` sztywne `height: 84vh`,
   a odstep pod paskiem gornym mierzyl skrypt (`pageTopGap.js`) i wpisywal go
   w zmienna, ktora kazda strona musiala potem odjac od swojej wysokosci
   (`max-height: calc(100% - var(--page-top-gap))`). Stad bralo sie i to, ze
   przy nizszym oknie tresc wjezdzala pod logo, i to, ze osobny skrypt
   blokowal male rozdzielczosci - bo uklad ich nie przezywal.

   Teraz pasek gorny jest `sticky`, tresc plynie w dol, a przegladarka
   przewija ja sama. Znika przez to caly ten mechanizm razem z jego bledami.

   Nawigacja glowna stoi od tej pory w lewej kolumnie, a nie w pasku.
   Pozycji jest za duzo, zeby zmiescily sie w poziomie - w pasku dochodzilo
   sie do kazdej sekcji przez rozwijane podmenu, czyli dwoma klikneciami
   i bez zadnej informacji, co w srodku. W pionie miejsca nie brakuje, wiec
   sekcje stoja otwarte. Pasek zostaje dla niezalogowanego i dla waskiego
   okna, gdzie menu jest szuflada.
*/

@layer layout {
    /* --- powloka ------------------------------------------------------- */
    .app {
        position: relative;
        display: grid;
        grid-template-rows: auto 1fr auto;
        min-height: 100dvh;
        /* `clip`, nie `hidden`: przycina przypadkowy poziomy overflow
           (szeroka tabela, kafelek) bez blokowania przewijania w pionie
           i bez wylaczania `position: sticky` w menu. */
        overflow-x: clip;
    }

    /* Druga kolumna - ta z menu glownym - dochodzi tylko po zalogowaniu.
       Strony logowania, resetu hasla i bledow menu nie maja, wiec tresc
       idzie u nich na cala szerokosc.

       Miejsca w siatce sa przypisane wprost, a nie zostawione
       automatycznemu ukladaniu, bo `.app` ma jeszcze dwoje dzieci poza
       trescia (odsylacz "przejdz do tresci" i tlo szuflady) i przy
       automacie potrafily zajac cudzy tor. */
    .app--with-nav {
        grid-template-columns: var(--nav-width) minmax(0, 1fr);
        /* Ile miejsca zabiera menu. Rzeczy przypiete do okna, a nalezace do
           tresci - komunikaty w `06-overlays` - przesuwaja sie o polowe tej
           wartosci, zeby staly na srodku tresci, a nie na srodku ekranu. */
        --nav-offset: var(--nav-width);
    }

    /* Menu nie stoi w siatce - jest przypiete do okna (patrz `.app-sidebar`
       nizej), wiec zadnego toru nie zajmuje. Pierwsza kolumna zostaje pusta
       i sluzy juz tylko za odsuniecie tresci na jego szerokosc. */
    .app--with-nav > .app-bar     { grid-column: 2; grid-row: 1; display: none; }
    .app--with-nav > .app-main    { grid-column: 2; grid-row: 2; }
    .app--with-nav > .app-footer  { grid-column: 2; grid-row: 3; }

    /* Monogram firmowy jako znak wodny, przypiety do okna - przy przewijaniu
       stoi w miejscu.

       Plik ma czarne tlo, a nie przezroczyste, wiec wstawiony wprost jako
       `background-image` rysuje na plotnie twardy czarny prostokat. Stad
       `mix-blend-mode: screen`: przy tym trybie czern nie zmienia niczego pod
       spodem, a widac wylacznie jasniejszy od niej monogram.

       `cover` - tak samo, jak bylo przed przebudowa. Probowalem tu
       `min(55vw, 820px)` i to widac przy zmianie skali strony: `vw` liczy sie
       w pikselach CSS, wiec przy kazdym powiekszeniu znak zmienial rozmiar
       *i* pozycje wzgledem tresci. `cover` zawsze wypelnia swoj prostokat,
       wiec przy powiekszaniu stoi w miejscu.

       Prostokat obejmuje cala szybe razem z kolumna menu (`inset: 0`), ale
       samo tlo jest w nim odsuniete od lewej o szerokosc menu - patrz
       `background-position` nizej. Sa to dwie rozne rzeczy i mieszanie ich
       bylo tu wczesniej bledem: zwezenie prostokata zmienia takze skale
       znaku, bo wzgledem prostokata liczy sie `cover`.

       `--nav-offset` sluzy wiec dwom rzeczom naraz i obie sa o to samo:
       odsuniecie znaku spod menu tutaj i srodek komunikatu w `06-overlays`.
       Tam, gdzie kolumny z menu nie ma - u niezalogowanego i przy waskim
       oknie, gdzie menu jest szuflada - obie wracaja do zera. */
    .app::before {
        content: "";
        position: fixed;
        inset: 0;
        z-index: -1;
        pointer-events: none;
        background-image: url("../images/background-image.ed27d5f2a761.png");
        background-repeat: no-repeat;
        /* Wysrodkowany w poziomie znak chowal sie za menu: monogram siedzi
           w lewej jednej trzeciej pliku, a `cover` przy szerokim oknie
           wypycha obraz mocno w lewo poza szybe. Lewa krawedz obrazu idzie
           wiec na prawa krawedz menu - `--nav-offset` daje zero tam, gdzie
           kolumny z menu nie ma (niezalogowany, waskie okno z szuflada),
           wiec znak wraca wtedy pod lewa krawedz okna.

           Przesuwa sie polozenie tla, a nie krawedz prostokata jak przed
           poprawka: wzgledem prostokata liczy sie tez `cover`, wiec zwezenie
           go zmienialoby przy okazji skale znaku. */
        background-position: var(--nav-offset, 0px) center;
        background-size: cover;
        /* `screen` jest konieczne, bo plik ma czarne tlo zamiast
           przezroczystego - przy tym trybie czern nie zmienia niczego pod
           soba, a zostaje sam monogram (`#242424` w pliku).

           Wyciszenie jest juz tylko decyzja o wygladzie, a nie ograniczeniem.
           Bylo nim, dopoki karty byly ze szkla i monogram przechodzil przez
           tresc - wtedy kazde podniesienie tej liczby zabieralo kontrast
           podpisom pol. Powierzchnie sa kryjace (`01-tokens`), wiec znak
           zostaje na plotnie i nie ma juz pod soba niczego do czytania:
           mozna go tu przyciemnic albo rozjasnic bez patrzenia na nic poza
           tym, jak wyglada. `ui_redesign` mial obraz pelna sila. */
        mix-blend-mode: screen;
        opacity: 0.5;
    }

    /* --- pasek gorny -----------------------------------------------------
       Zostaje w dwoch sytuacjach: u niezalogowanego, gdzie menu nie ma,
       a znak firmowy ma stac, i przy waskim oknie, gdzie miesci przycisk
       otwierajacy szuflade z menu. */
    .app-bar {
        position: sticky;
        top: 0;
        z-index: var(--z-sticky);
        display: flex;
        align-items: center;
        gap: var(--space-sm);
        min-height: var(--app-bar-height);
        padding-inline: var(--content-pad);
        background: color-mix(in srgb, var(--canvas) 82%, transparent);
        backdrop-filter: blur(12px);
        border-bottom: 1px solid var(--border);
    }

    /* Znak firmowy. Ten sam w pasku i u gory menu bocznego, wiec ma wlasna
       nazwe zamiast `.app-bar__brand` - inaczej menu siegaloby po klase
       paska, ktorego przy nim nie ma. */
    .brand {
        display: inline-flex;
        align-items: center;
        gap: var(--space-xs);
        min-width: 0;
        color: var(--text);
        text-decoration: none;
        white-space: nowrap;
    }

    .brand img {
        flex: none;
        width: 1.75rem;
        height: 1.75rem;
        object-fit: contain;
    }

    .brand__name {
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        font-size: var(--text-lg);
        font-weight: var(--weight-medium);
        letter-spacing: -0.01em;
    }

    .brand__version {
        color: var(--text-faint);
        font-family: var(--font-mono);
        font-size: var(--text-2xs);
    }

    /* Przycisk otwierajacy szuflade. Na szerokim ekranie nie istnieje - menu
       stoi tam na stale. */
    .nav-toggle {
        display: none;
        flex: none;
        align-items: center;
        justify-content: center;
        width: var(--control-height);
        height: var(--control-height);
        margin-inline-start: calc(-1 * var(--space-xs));
        color: var(--text-muted);
        font-size: var(--text-xl);
        border-radius: var(--radius-sm);
        transition: color var(--dur-fast) var(--ease),
                    background var(--dur-fast) var(--ease);
    }

    .nav-toggle:hover {
        color: var(--text);
        background: var(--surface-hover);
    }

    /* Dzwonek przy prawej krawedzi paska. Wlasnej reguly `display` nie
       potrzebuje: pasek gorny zalogowanego uzytkownika pokazuje sie dopiero
       ponizej progu szuflady, wiec i przycisk istnieje tylko tam.

       `margin-inline-start: auto` odsuwa go od znaku firmowego na sam koniec
       wiersza, a `relative` jest kotwica dla kropki nieprzeczytanych (stoi
       w sekcji nawigacji w `05-components.css`). */
    .app-bar__action {
        position: relative;
        flex: none;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: var(--control-height);
        height: var(--control-height);
        margin-inline-start: auto;
        color: var(--text-muted);
        font-size: var(--text-xl);
        border-radius: var(--radius-sm);
        transition: color var(--dur-fast) var(--ease),
                    background var(--dur-fast) var(--ease);
    }

    .app-bar__action:hover {
        color: var(--text);
        background: var(--surface-hover);
    }

    /* --- menu glowne ------------------------------------------------------
       `sticky` w torze siatki, a nie `fixed`: dzieki temu tresc odsuwa sama
       siatka i nie trzeba jej odejmowac szerokosci menu marginesem, ktory
       przy kazdej zmianie `--nav-width` trzeba by poprawiac w drugim
       miejscu. */
    /* Menu stoi w kadrze na stale.

       Bylo `sticky` w pierwszej kolumnie siatki i przy dlugiej stronie
       odjezdzalo w gore razem z trescia - na samym dole znak firmowy byl juz
       poza ekranem. Element `sticky` trzyma sie tylko do dolnej krawedzi
       SWOJEGO pudelka, a tym jest tor siatki, czyli wysokosc `.app`. Dokument
       jest od niej wyzszy o `--page-tail` z `.page`: ogon pustki pod trescia
       wchodzi w ujemny margines, zeby srodkowanie w pionie liczylo sie
       symetrycznie, wiec tresc wystaje pod spod `.app` i o te kilkadziesiat
       pikseli da sie jeszcze przewinac - juz razem z menu.

       Dlatego `fixed`, a nie lepienie tamtej roznicy: menu jest obudowa okna,
       a nie trescia strony, i nie ma powodu, zeby jego polozenie w ogole
       zalezalo od tego, jak wysoka jest tresc obok. Tak samo stoi ono ponizej
       60rem, gdzie od poczatku jest szuflada `fixed`. */
    .app-sidebar {
        position: fixed;
        inset-block-start: 0;
        inset-inline-start: 0;
        z-index: var(--z-sticky);
        display: flex;
        flex-direction: column;
        width: var(--nav-width);
        height: 100dvh;
        padding: var(--space-md) var(--space-xs) var(--space-xs);
        /* Szyba liczona z plotna, nie z karty. Karta to biel o niskim
           kryciu, wiec menu zbudowane z niej rozjasnialoby monogram zamiast
           go przygaszac - a znak ma wychodzic zza menu, nie swiecic przez
           nie. `ui_redesign` klad tu panel `rgba(18,18,20,0.92)` i to samo
           robi ta wartosc: czern plotna przy 92% krycia. */
        background: color-mix(in srgb, var(--canvas) 92%, transparent);
        backdrop-filter: blur(12px);
        border-inline-end: 1px solid var(--border);
    }

    .app-sidebar__brand {
        flex: none;
        justify-content: flex-start;   /* was: center */
        width: 100%;
        margin-bottom: var(--space-md);
        padding-inline: var(--space-xs);
        text-align: left;              /* was: center */
    }

    /* Sama nawigacja przewija sie niezaleznie od dolu menu. Przy rozwinietych
       sekcjach obu hubow lista ma kilkanascie pozycji - gdyby przewijalo sie
       cale menu, jezyk, wylogowanie i profil schodzilyby pod krawedz okna. */
    .app-sidebar__nav {
        flex: 1;
        min-height: 0;
        overflow-y: auto;
        overscroll-behavior: contain;
        scrollbar-width: thin;
        scrollbar-color: var(--border-strong) transparent;
    }

    .app-sidebar__foot {
        flex: none;
        margin-top: var(--space-xs);
        padding-top: var(--space-xs);
        border-top: 1px solid var(--hairline);
    }

    /* Tlo szuflady. Poza waskim ekranem nie ma go wcale. */
    .nav-backdrop {
        position: fixed;
        inset: 0;
        z-index: calc(var(--z-overlay) - 1);
        display: none;
        background: #00000073;
    }

    /* Ponizej tego progu menu nie ma juz wlasnej kolumny - zjezdza z lewej
       jako szuflada, a nad trescia staje pasek z przyciskiem. Prog jest ten
       sam, przy ktorym `.split` sklada liste sekcji nad tresc: ponizej 60rem
       strona nie ma zadnej kolumny bocznej. */
    @media (max-width: 60rem) {
        .app--with-nav {
            grid-template-columns: minmax(0, 1fr);
            --nav-offset: 0px;
        }

        .app--with-nav > .app-bar {
            display: flex;
            grid-column: 1;
        }

        .app--with-nav > .app-main,
        .app--with-nav > .app-footer {
            grid-column: 1;
        }

        .nav-toggle {
            display: inline-flex;
        }

        /* Przypiecie do okna menu ma juz wyzej - tu dochodzi to, czym
           szuflada rozni sie od kolumny: waskie okno, cien, wyjscie za lewa
           krawedz i wjazd po klknieciu w przycisk. Stoi tez nad trescia,
           a nie obok niej, wiec i wyzej w kolejce warstw. */
        .app-sidebar {
            z-index: var(--z-overlay);
            width: min(var(--nav-width), 80vw);
            box-shadow: var(--shadow-lg);
            transform: translateX(-100%);
            transition: transform var(--dur-med) var(--ease);
        }

        body[data-nav-open] .app-sidebar {
            transform: none;
        }

        body[data-nav-open] .nav-backdrop {
            display: block;
        }

        /* Przy otwartej szufladzie tresc pod spodem nie jedzie razem
           z palcem. */
        body[data-nav-open] {
            overflow: hidden;
        }
    }

    /* --- tresc ----------------------------------------------------------
       Tresc stoi na srodku wysokosci okna, a nie przy jego gornej krawedzi.
       Krotka strona - logowanie, potwierdzenie wyslania maila, pusta lista,
       karta z jednym formularzem - zbierala sie dotad pod paskiem i zostawiala
       pod soba pol ekranu pustki.

       Srodkuje `align-content`, a nie policzona `min-height`: tor `1fr`
       siatki `.app` ma juz dokladnie te wysokosc, ktora zostaje po pasku
       gornym i stopce, wiec nie ma czego odejmowac ze wzoru.

       Tresc wyzsza od tego toru rozpycha go soba - `1fr` nie schodzi ponizej
       wlasnej zawartosci - wiec przy dlugiej liscie wolnego miejsca nie ma,
       srodkowanie nie ma czego przesuwac i nic nie znika za gorna krawedzia.
       To wlasnie mial na sumieniu stary uklad (`.container > .row.center`
       o stalej wysokosci): srodkowal, ale reszte tresci przycinal.

       `grid-template-columns: minmax(0, 1fr)` trzyma tor przy szerokosci
       okna. Domyslne `auto` liczy sie z najszerszej tresci, wiec bez tego
       szeroka tabela (SPC, statystyki) rozpychalaby strone w poziomie. */
    .app-main {
        display: grid;
        grid-template-columns: minmax(0, 1fr);
        align-content: center;
        width: 100%;
        min-width: 0;
    }

    /* `--page-tail` to przewijalna pustka pod ostatnia trescia: miejsce,
       ktore zostaje pod ostatnim wierszem listy po dojechaniu na sam dol.

       Ujemny margines zabiera dokladnie tyle, ile ogon doklada do dolnego
       wypelnienia, wiec pudelko, ktorym `.app-main` mierzy srodkowanie, ma
       tyle samo miejsca nad trescia, co pod nia. Bez tego krotka strona
       stalaby o polowe ogona za wysoko - przy 84 px pod trescia i 16 px nad
       nia karta logowania siadala 34 px nad srodkiem okna.

       Sama pustka nie znika: na krotkiej stronie miesci sie w wolnym miejscu
       pod trescia, na dlugiej wystaje pod dolna krawedz `.app-main`. Tego
       nikt tu nie obcina, wiec wysokosc dokumentu i przewijanie sa takie
       same, jak przed zmiana.

       `width` jest podana wprost, bo `.app-main` jest siatka: marginesy
       `auto` biora w niej pierwszenstwo przed rozciagnieciem dziecka na caly
       tor i strona zwezilaby sie do szerokosci wlasnej tresci - karta
       z krotkim formularzem stanelaby na 240 px. `width: 100%` daje jej
       szerokosc toru, `max-width` ja przycina, a marginesy srodkuja to, co
       zostanie. */
    .page {
        --page-tail: var(--space-2xl);
        width: 100%;
        max-width: var(--content-max);
        margin-inline: auto;
        margin-block-end: calc(-1 * var(--page-tail));
        padding: var(--content-pad);
        padding-bottom: calc(var(--content-pad) + var(--page-tail));
    }

    /* Slupek ikon (telefon alarmowy, powiadomienia) stoi na telefonie
       w prawym dolnym rogu okna - patrz `06-overlays`. Jest przypiety do
       okna, wiec konca strony nie odsuwa: bez tego ostatni wiersz listy
       konczyl sie pod nim i nie dalo sie go dotknac. */
    @media (max-width: 48rem) {
        .page {
            --page-tail: calc(var(--space-2xl) + var(--control-height));
        }
    }

    /* Strony logowania, resetu hasla i bledow: jedna waska kolumna.
       Pion zalatwia `.app-main` - wczesniej stalo tu wlasne srodkowanie
       oparte o `min-height: calc(100dvh - var(--app-bar-height) - 8rem)`,
       czyli o zgadniete 8rem na pasek i marginesy. Zgadywanie wychodzilo
       na wierzch przy niskim oknie: kolumna byla wyzsza od miejsca, ktore
       dostala, i strona przewijala sie o te kilka pikseli za duzo. */
    .page--narrow {
        max-width: 26rem;
    }

    .page--wide {
        max-width: none;
    }

    /* --- stopka ----------------------------------------------------------
       Zostala tylko na ekranie powitalnym - w aplikacji stopki nie ma. Pasek
       z telefonem, e-mailem i adresem strony powtarzal sie pod kazdym ekranem
       i wszedzie niosl to samo; telefon alarmowy klient ma w slupku ikon przy
       prawej krawedzi. Trzeci tor siatki `.app` zwija sie wtedy do zera, wiec
       tresc siega do dolu okna. */
    .app-footer {
        padding: var(--space-md) var(--content-pad);
        border-top: 1px solid var(--border);
    }

    .app-footer__note {
        color: var(--text-faint);
        font-size: var(--text-sm);
        text-align: center;
    }

    /* --- naglowek strony ------------------------------------------------ */
    .page-head {
        display: flex;
        flex-wrap: wrap;
        align-items: flex-end;
        gap: var(--space-sm) var(--space-md);
        margin-bottom: var(--space-lg);
    }

    .page-head__text {
        min-width: 0;
    }

    .page-head h1,
    .page-head h2 {
        font-size: var(--text-2xl);
        letter-spacing: -0.015em;
    }

    .page-head__sub {
        margin-top: var(--space-3xs);
        color: var(--text-muted);
        font-size: var(--text-sm);
    }

    .page-head__actions {
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        gap: var(--space-xs);
        margin-inline-start: auto;
    }

    /* Na telefonie akcje naglowka schodza pod tytul i zajmuja caly wiersz.
       `margin-inline-start: auto` odpycha je od tytulu tylko dopoki oba
       mieszcza sie w jednym rzedzie; po zawinieciu zostawal z niego pas
       pustki po lewej, a wyszukiwarka - jedyna akcja naglowka na wiekszosci
       list - kurczyla sie do szerokosci wlasnego napisu przy prawej
       krawedzi. */
    @media (max-width: 48rem) {
        .page-head__actions {
            width: 100%;
            margin-inline-start: 0;
        }

        .page-head__actions > form,
        .page-head__actions > .search {
            flex: 1 1 100%;
        }
    }

    /* --- uklad z menu bocznym -------------------------------------------
       Jeden uklad na wszystkie strony, ktore maja boczna liste sekcji:
       frezarka i jej podstrony, profil, "Moja firma", "Zarzadzaj",
       rejestracja. Wczesniej kazda z nich miala wlasny arkusz z wlasna
       siatka - i wlasnymi rozjazdami.

       `align-items: start` sprawia, ze menu nie rozciaga sie na wysokosc
       tresci, a `position: sticky` trzyma je w kadrze przy dlugiej liscie. */
    .split {
        display: grid;
        grid-template-columns: var(--side-menu-width) minmax(0, 1fr);
        align-items: start;
        gap: var(--space-lg);
    }

    /* Strona z menu bocznym stoi przy gornej krawedzi, a nie posrodku okna.

       `.app-main` srodkuje tresc w pionie - to dobre dla karty logowania
       i krotkiego komunikatu, ale nie dla strony, ktora ma wlasne menu
       sekcji. Wysokosc tresci zmienia sie tam z sekcji na sekcje, a razem
       z nia wedrowalo menu: przy 1400x900 slupek "Profilu" stal 144 px
       nizej niz slupek "Kalibracji", wiec kazde przejscie miedzy sekcjami
       przesuwalo pozycje, w ktora sie wlasnie kliknelo.

       Warunek celuje w rodzica przez `:has()`, bo srodkowanie siedzi na
       `.app-main`, a o ukladzie decyduje `.split` w srodku - dziecko nie
       cofnie `align-content` rodzica zadnym `align-self`. */
    .app-main:has(.split) {
        align-content: start;
    }

    /* Odstep od gory bez wysokosci paska: ponizej 60rem menu sekcji i tak
       przestaje byc `sticky`, a powyzej paska gornego juz nie ma - menu
       glowne stoi w kolumnie obok. */
    .split__side {
        position: sticky;
        top: var(--space-md);
    }

    .split__main {
        min-width: 0;
    }

    /* Przy waskim oknie menu przechodzi nad tresc i staje sie pozioma
       lista przewijana palcem. */
    @media (max-width: 60rem) {
        .split {
            grid-template-columns: minmax(0, 1fr);
        }

        .split__side {
            position: static;
        }
    }

    /* --- panel parku maszynowego -----------------------------------------
       Jedna kolumna na cala szerokosc - tak samo dla klienta, serwisanta
       i admina.

       Stal tu wczesniej drugi uklad, `.park--with-side`: waski slupek
       z lewej na karte raportow wsparcia i tresc w drugiej kolumnie. Raporty
       zastapily zgloszenia, wiec slupek nie ma czego trzymac - a zostawiony
       pusty zsuwal panel pracownika o 15rem w prawo. */
    .park {
        display: grid;
        grid-template-columns: minmax(0, 1fr);
        gap: var(--space-lg);
    }

    /* --- prymitywy ------------------------------------------------------
       Cztery uklady, ktorych aplikacja uzywa bez przerwy. Maja nazwy od
       tego, co robia, a nie od strony, na ktorej stoja - dlatego dziala
       wszedzie i nie mnozy sie na kazdej podstronie osobno. */

    /* Pionowy rytm miedzy dziecmi. */
    .stack {
        display: flex;
        flex-direction: column;
        gap: var(--stack-gap, var(--space-md));
    }

    .stack--tight { --stack-gap: var(--space-xs); }
    .stack--loose { --stack-gap: var(--space-lg); }

    /* Rzad elementow, ktory zawija sie sam. */
    .cluster {
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        gap: var(--cluster-gap, var(--space-xs));
    }

    .cluster--between { justify-content: space-between; }
    .cluster--end { justify-content: flex-end; }
    .cluster--loose { --cluster-gap: var(--space-md); }

    /* Siatka, ktora sama decyduje o liczbie kolumn na podstawie szerokosci
       elementu, a nie punktow lamania.

       `auto-fit`, nie `auto-fill`: przy `auto-fill` przegladarka tworzy tyle
       kolumn, ile sie miesci, takze pustych - dwie karty wyniku kalibracji
       ladowaly przez to w dwoch pierwszych z czterech torow, a polowa rzedu
       zostawala pusta. `auto-fit` zwija tory bez zawartosci, wiec karty
       rozkladaja sie na cala szerokosc. */
    .grid {
        display: grid;
        /* `min(..., 100%)` wokol dolnej granicy toru, a nie sama granica:
           `minmax(22rem, 1fr)` znaczy "nigdy wezej niz 352 px" takze wtedy,
           gdy kontener ma ich 343 - i wtedy siatka wystaje poza strone,
           ciagnac za soba poziomy pasek przewijania calego dokumentu.
           Widac to bylo na stronie frezarki (`.grid--wide`) przy 375 px.

           Przy szerokim oknie ten zapis nie zmienia niczego: 100% kontenera
           jest tam wielokrotnie wieksze od granicy, wiec `min()` zwraca
           granice. */
        grid-template-columns: repeat(auto-fit, minmax(min(var(--grid-min, 16rem), 100%), 1fr));
        gap: var(--grid-gap, var(--space-md));
    }

    .grid--wide { --grid-min: 22rem; }
    .grid--narrow { --grid-min: 11rem; }

    /* Para "podpis - wartosc", z ktorej zlozone sa wszystkie karty danych. */
    .fields {
        display: grid;
        /* Ta sama oslona, co przy `.grid` wyzej - strony podaja tu wlasne
           `--fields-min` i przy waskim ekranie latwo je przekroczyc. */
        grid-template-columns: repeat(auto-fit, minmax(min(var(--fields-min, 12rem), 100%), 1fr));
        gap: var(--space-sm) var(--space-md);
    }
}
