/* purchase-picker.css — WSPÓLNY komponent zakupowy: cennik pakietów,
 * siatka dodatków i rozpisany koszyk.
 *
 * ŁADOWANY PRZEZ DWA EKRANY, w tej samej postaci:
 *   - kadr_step2.html  — checkout (wybór pakietu + dodatki + podsumowanie),
 *   - kadr_step3.html  — dokup w panelu klienta (widok `.addon-picker-view`).
 *
 * DLACZEGO OSOBNY PLIK (2026-08-28): reguły mieszkały w css/kadr_step3.css,
 * czyli w arkuszu ładowanym wyłącznie przez panel. Gdy ten sam układ trafił do
 * checkoutu, były dokładnie dwie drogi: skopiować je do <style> w step2 albo
 * wyprowadzić do wspólnego pliku. Kopia znaczyłaby, że korekta wiersza pakietu
 * przechodzi na jednym ekranie i nie przechodzi na drugim — a klient widzi oba
 * w odstępie kilku minut (płaci w checkoucie, dokupuje w panelu). To ta sama
 * decyzja, co przy css/review-card.css (karta opinii wspólna z /opinie)
 * i css/reno-style-picker.css (picker stylu wspólny ze step1).
 *
 * NAZWY KLAS ZOSTAJĄ `addon-*` mimo przeprowadzki. Zmiana prefiksu dotknęłaby
 * kilkunastu selektorów w js/step3/render/addon.js i reguł, które o nim nie
 * wiedzą (`--press-transform` w kadr_step3.css wymienia `.addon-count`
 * z nazwy) — czyli byłaby ryzykiem bez zysku. W obu miejscach znaczą to samo:
 * `addon-count` = wiersz pakietu, `addon-extra` = kafelek dodatku,
 * `addon-cart` = podsumowanie koszyka.
 *
 * DWA WARIANTY KONTROLKI, JEDEN WYGLĄD:
 *   - panel (step3) renderuje `<button role="radio">` / `<button role="checkbox">`
 *     i steruje stanem klasą `.is-selected` / `.is-checked`,
 *   - checkout (step2) renderuje `<label>` z UKRYTYM WIZUALNIE natywnym
 *     `<input type="radio">` / `<input type="checkbox">` w środku.
 * Różnica nie jest kaprysem: picker w step2 przeszedł 2026-08 na natywne
 * inputy, bo wersja z `role="radio" tabindex="0"` dawała się zafokusować,
 * ale NIE dawała wybrać z klawiatury (brak handlera keydown). Natywna
 * kontrolka załatwia strzałki, spację i grupowanie po `name` za darmo.
 * Stan wizualny w OBU wariantach niesie klasa nadawana przy renderze —
 * inputy dokładają wyłącznie semantykę i obsługę klawiatury, więc reguły
 * kolorystyczne nie muszą istnieć w dwóch wersjach.
 *
 * TOKENY: plik nie deklaruje ANI JEDNEGO koloru. Czyta `--variant-selected-*`,
 * `--variant-hover-border`, `--karta`, `--linia`, `--linia-mocna`, `--zielen-*`,
 * `--papier-cien`, `--plakietka-tlo`, `--mosiadz-600`, `--tekst`, `--tekst-mut`
 * i `--font-family` — wszystkie z css/tokens.css, który MUSI być podlinkowany
 * przed tym arkuszem na obu stronach.
 *
 * TOUCH TARGETY: każdy wiersz cennika i każdy kafelek dodatku jest w całości
 * celem kliknięcia (minimum 64 px wysokości). Przy drżeniu rąk i powiększonej
 * czcionce mały cel jest główną przyczyną nietrafionych kliknięć, a to są
 * ekrany, na których klient wydaje pieniądze.
 */

/* =====================================================================
   UKRYCIE WIZUALNE — natywna kontrolka wariantu `<label>` (step2)
   =====================================================================
   Input zostaje w drzewie dostępności i w kolejności tabulacji (dlatego NIE
   `display:none`), ale ma zerowy rozmiar i `position:absolute` — więc nie
   zajmuje komórki gridu ani miejsca w kolumnie kafelka.

   `.addon-sr-only` obsługuje tę samą technikę dla doklejanych etykiet
   tekstowych („Cena regularna” / „Cena po rabacie”), które rozstrzygają,
   która z dwóch kwot w wierszu obowiązuje przy aktywnym rabacie polecenia.
   Bez nich czytnik czyta „70,98 zł 56,78 zł” bez rozróżnienia: `<s>` nie jest
   domyślnie anonsowane. Jedna reguła dla obu zastosowań — dwie kopie tego
   samego zestawu właściwości to dwie okazje, żeby jedna została po następnej
   zmianie. */
.addon-count__input,
.addon-extra__input,
.addon-sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: 0;
    padding: 0;
    border: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
}

/* Fokus klawiaturą rysowany na WIDOCZNYM znaczniku, bo sam input jest
   niewidoczny. Kształt obrysu identyczny z `.addon-count:focus-visible`
   wariantu przyciskowego, żeby oba ekrany reagowały na Tab tak samo. */
.addon-count__input:focus-visible ~ .addon-count__mark,
.addon-extra__input:focus-visible ~ .addon-extra__head .addon-extra__mark {
    outline: 2px solid var(--variant-selected-border);
    outline-offset: 3px;
}

/* =====================================================================
   CENNIK — lista pakietów
   ===================================================================== */
.addon-counts {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

/* Wiersz pakietu. Grid trójkolumnowy: znacznik / treść / kwota. Kwota
   `justify-self: end` i `tabular-nums`, żeby przecinki dziesiętne stały
   w jednej pionowej linii — kolumna liczb, którą da się porównać wzrokiem
   bez czytania. */
.addon-count {
    position: relative;
    display: grid;
    grid-template-columns: 28px 1fr auto;
    align-items: center;
    gap: 14px;
    width: 100%;
    min-height: 76px;
    padding: 16px 18px;
    background: var(--karta);
    border: 2px solid var(--linia);
    /* Wspólny promień z blokiem metod płatności (step2) — patrz tokens.css. */
    border-radius: var(--karta-promien);
    text-align: left;
    font-family: var(--font-family);
    cursor: pointer;
    transition: border-color 0.18s ease, background-color 0.18s ease, box-shadow 0.18s ease;
}
.addon-count:hover:not(.is-selected) {
    border-color: var(--variant-hover-border);
}
.addon-count:active {
    transform: scale(0.99);
}
.addon-count:focus-visible {
    outline: 2px solid var(--variant-selected-border);
    outline-offset: 2px;
}
.addon-count.is-selected {
    border-color: var(--variant-selected-border);
    background: var(--variant-selected-bg);
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
}

/* Znacznik wyboru — pusty okrąg gdy niewybrany, wypełniony z ptaszkiem gdy
   wybrany. Ptaszek jest w DOM ZAWSZE (opacity, nie display), żeby zmiana
   stanu była przejściem, a nie podmianą węzła: reconcile morfuje dzieci
   pozycyjnie, więc stała struktura jest warunkiem działania `transition`. */
.addon-count__mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    border: 2px solid var(--linia-mocna);
    background: var(--karta);
    color: white;
    flex-shrink: 0;
    transition: background-color 0.18s ease, border-color 0.18s ease;
}
.addon-count__mark svg {
    width: 14px;
    height: 14px;
    opacity: 0;
    transition: opacity 0.18s ease;
}
.addon-count.is-selected .addon-count__mark {
    background: var(--variant-selected-border);
    border-color: var(--variant-selected-border);
}
.addon-count.is-selected .addon-count__mark svg {
    opacity: 1;
}

.addon-count__body {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
}
.addon-count__title {
    font-size: 17px;
    font-weight: 700;
    color: var(--tekst);
    line-height: 1.25;
}
/* Metadane w jednym wierszu z zawijaniem — na wąskim ekranie pigułka
   „oszczędzasz" schodzi pod cenę jednostkową zamiast ją ściskać. */
.addon-count__meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
}
.addon-count__unit {
    font-size: 13px;
    color: var(--tekst-mut);
    font-variant-numeric: tabular-nums;
}
/* Oszczędność KWOTĄ, nie procentem: przy demografii 50+ złotówki czytają się
   natychmiast, a „31% taniej" wymaga policzenia, ile to jest z czego. */
.addon-count__savings {
    padding: 3px 9px;
    border-radius: 999px;
    background: var(--plakietka-tlo);
    color: var(--zielen-900);
    font-size: 12px;
    font-weight: 600;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}
/* Plakietka ma WŁASNE tło (`--plakietka-tlo`), o stopień głębsze niż
   wypełnienie zaznaczonego wiersza. Do 2026-08-28 dzieliła tło z wierszem
   i na tym jednym — wybranym, z najwyższą oszczędnością — znikała; ratował
   ją wtedy wyjątek nadający jej biel. Wyjątek zniknął razem z przyczyną:
   osobny token rozwiązuje to w każdym stanie wiersza naraz, zamiast łatać
   ten jeden. */

.addon-count__total {
    justify-self: end;
    font-size: 19px;
    font-weight: 700;
    /* Kwota ZIELENIĄ, nie kolorem tekstu: to jedyna liczba w wierszu, którą
       klient realnie wyda, a zieleń jest w tym serwisie kolorem wartości
       (oszczędność, potwierdzenie, przycisk płatności). Czerń robiła z niej
       kolejny fragment opisu. */
    color: var(--zielen-900);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* Plakietka wiersza — kotwiczona do prawego górnego rogu, wychodzi poza
   ramkę (translateY), żeby nie zabierać wysokości treści. pointer-events:none,
   bo cały wiersz jest jednym przyciskiem i plakietka nie może przechwytywać
   kliknięć. */
.addon-count__badge {
    position: absolute;
    top: 0;
    right: 14px;
    transform: translateY(-50%);
    padding: 3px 12px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 700;
    line-height: 1.5;
    color: white;
    white-space: nowrap;
    pointer-events: none;
}
.addon-count__badge.is-popular {
    background: var(--mosiadz-600);
}
.addon-count__badge.is-album {
    background: var(--variant-selected-border);
}
/* Wiersz checkoutu BEZ pigułek (finalny mockup 2026-09-06 — plakietki
   „Oszczędzasz X%" i wrapper `.addon-pkg__badges` usunięte razem z ich
   rolą): rekomendację/kategorię niesie podpis W karcie nad tytułem
   (`.addon-count__podpis` niżej), a oszczędność linia „taniej o X zł"
   pod kwotą (`.addon-count__total-taniej`). Bazowa `.addon-count__badge`
   z wariantami is-popular/is-album wyżej zostaje — używa jej dokup
   w panelu (js/step3/render/addon.js). */

/* Podpis nad tytułem wiersza — pierwsza linia treści, ciszej od tytułu
   (rozmiar), ale pełnym kolorem: to część oferty, nie metadana. */
.addon-count__podpis {
    font-size: 14px;
    font-weight: 700;
    color: var(--tekst);
    line-height: 1.3;
}

/* „taniej o 22,95 zł" pod kwotą — zieleń wartości (jak dotąd kwota),
   domyka kolumnę cen: przekreślona kotwica → cena → zysk. */
.addon-count__total-taniej {
    font-size: 12.5px;
    font-weight: 700;
    color: var(--zielen-700);
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

/* Wiersz „Bez nowych zdjęć" — koszyk z samym montażem. Bez kwoty po prawej
   (nie ma pakietu do wyceny), więc grid schodzi do dwóch kolumn. Stłumiony
   wizualnie: to wyjście dla klienta, który wie, czego chce, a nie propozycja
   konkurująca z cennikiem. */
.addon-count--none {
    grid-template-columns: 28px 1fr;
    min-height: 64px;
    border-style: dashed;
}
.addon-count--none .addon-count__title {
    font-size: 15px;
    color: var(--tekst-mut);
}

/* =====================================================================
   DODATKI — siatka czterech kafelków
   ===================================================================== */
.addon-extras {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

/* Nagłówek sekcji — wersaliki, mała czcionka, stłumiony kolor. Re-frame'uje
   siatkę z „lista opcji" w „pytanie, na które odpowiadasz". Klient parsuje
   pytanie przed kliknięciem.

   LINIA BIEGNIE OBOK TEKSTU, NIE NAD NIM (poprawka 2026-08-28). Wcześniej był
   to `border-top` na całą szerokość, z nagłówkiem pod spodem — czyli linia
   ZAMYKAŁA cennik, a nie otwierała sekcję dodatków. Wizualnie należała do
   bloku wyżej: między kreską a wierszem „10 zdjęć" nie było nic, co by je
   rozdzielało, więc czytało się to jak podkreślenie ostatniego pakietu,
   a nie jak początek nowego pytania.

   Teraz kreska wychodzi Z tekstu i dobiega do prawej krawędzi — nagłówek
   i linia są jednym elementem, a sekcja zaczyna się dokładnie tam, gdzie
   zaczyna się pytanie.

   `::after` z `flex: 1`, a nie druga kreska w markupie: to jest ozdoba
   nagłówka, nie treść. Element w DOM musiałby dostać `aria-hidden`,
   a czytnik ekranu i tak nie ma z czego skorzystać. */
.addon-extras__caption {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 0;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--tekst-mut);
}
.addon-extras__caption::after {
    content: '';
    flex: 1;
    /* min-width: 0 — bez tego `flex: 1` na pustym pseudo-elemencie nie skurczy
       się poniżej swojej bazy w wąskich kontenerach i kreska wypchnęłaby
       nagłówek do zawinięcia. */
    min-width: 0;
    height: 1px;
    background: var(--linia);
}

/* Dwie kolumny na każdej szerokości. Cztery dodatki układają się w kwadrat
   2×2 — kształt, który da się ogarnąć jednym spojrzeniem, w odróżnieniu od
   kolumny czterech pasków. Na wąskich ekranach kafelek dostaje wariant
   kompaktowy (media query niżej), a nie jedną kolumnę. */
.addon-extras__grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
}

/* Kafelek dodatku. Ikona i znacznik w jednym wierszu na górze, potem tytuł,
   opis i kwota — kwota ZAWSZE na dole, wyrównana między kafelkami dzięki
   `margin-top: auto`. Bez tego kafelki o różnej długości opisu miałyby kwoty
   na różnych wysokościach, czyli klient musiałby ich szukać. */
.addon-extra {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-height: 150px;
    padding: 14px;
    background: var(--karta);
    border: 2px solid var(--linia);
    /* Wspólny promień z blokiem metod płatności (step2) — patrz tokens.css. */
    border-radius: var(--karta-promien);
    text-align: left;
    font-family: var(--font-family);
    cursor: pointer;
    transition: border-color 0.18s ease, background-color 0.18s ease, box-shadow 0.18s ease;
}
.addon-extra:hover:not(.is-checked) {
    border-color: var(--variant-hover-border);
}
.addon-extra:active {
    transform: scale(0.99);
}
.addon-extra:focus-visible {
    outline: 2px solid var(--variant-selected-border);
    outline-offset: 2px;
}
.addon-extra.is-checked {
    border-color: var(--variant-selected-border);
    background: var(--variant-selected-bg);
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
}

.addon-extra__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 8px;
}
.addon-extra__icon {
    display: inline-flex;
    width: 22px;
    height: 22px;
    /* Zieleń w OBU stanach. Stan niesie znacznik po prawej — ikona ma mówić,
       CZEGO dotyczy dodatek, a nie czy jest zaznaczony. Wygaszanie jej na
       szaro przy niezaznaczonym kafelku czytało się jak „niedostępne",
       co przy demografii 50+ jest kosztownym nieporozumieniem na ekranie
       zakupowym. */
    color: var(--zielen-700);
}
.addon-extra__icon svg {
    width: 100%;
    height: 100%;
    display: block;
}

/* Znacznik zaznaczenia — ta sama gramatyka co w cenniku (pusty okrąg /
   wypełniony z ptaszkiem), inny kształt kontrolki niosłby fałszywy komunikat
   o wykluczaniu się opcji. */
.addon-extra__mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    border: 2px solid var(--linia-mocna);
    background: var(--karta);
    color: white;
    flex-shrink: 0;
    transition: background-color 0.18s ease, border-color 0.18s ease;
}
.addon-extra__mark svg {
    width: 13px;
    height: 13px;
    opacity: 0;
    transition: opacity 0.18s ease;
}
.addon-extra.is-checked .addon-extra__mark {
    background: var(--variant-selected-border);
    border-color: var(--variant-selected-border);
}
.addon-extra.is-checked .addon-extra__mark svg {
    opacity: 1;
}

.addon-extra__title {
    font-size: 15px;
    font-weight: 700;
    color: var(--tekst);
    line-height: 1.3;
}
.addon-extra__desc {
    font-size: 13px;
    line-height: 1.4;
    color: var(--tekst-mut);
}
.addon-extra__price {
    margin-top: auto;
    padding-top: 6px;
    font-size: 14px;
    font-weight: 700;
    color: var(--zielen-900);
    font-variant-numeric: tabular-nums;
}

/* Podpowiedź o rekomendowanej liczbie animacji do montażu. Stoi POZA siatką —
   dotyczy jakości filmu, nie samego zaznaczenia; w środku kafelka wyglądałaby
   jak warunek zaznaczenia, czyli jak bramka, której świadomie nie ma
   (usunięta 2026-08-19). */
.addon-extras__hint {
    margin: 0;
    padding: 0 2px;
    font-size: 12px;
    line-height: 1.4;
    color: var(--tekst-mut);
}

/* =====================================================================
   KOSZYK — rozpiska + suma
   =====================================================================
   Kremowe tło (stone-100) odcina koszyk od białych kontrolek wyżej: to nie
   jest kolejna rzecz do klikania, tylko podsumowanie tego, co klient już
   wyklikał. Kolor bursztynowy zarezerwowany dla wiersza rabatu — jedynej
   liczby na minusie i jedynej, która ma się rzucić w oczy. */
.addon-cart {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 16px 18px;
    background: var(--papier-cien);
    border-radius: 14px;
}

/* TEKST PEŁNY, NIE STŁUMIONY — i to jest korekta z 2026-08-28.
   Pozycje koszyka dostały początkowo `--tekst-mut`, bo są opisem, a nie
   nagłówkiem. Na białej karcie ten stopień działa (4,85:1); na beżowym
   podsumowaniu (`--papier-cien`) spada do 4,24:1 i pozycje robią się blade —
   a to jest jedyne miejsce na ekranie, gdzie klient sprawdza, ZA CO płaci.
   Poprzednia, chłodna wersja tego bloku miała tu 8,98:1 i czytała się lepiej;
   `--tekst` daje 11,92:1.

   Hierarchię wobec wiersza „Razem" niesie ROZMIAR i GRUBOŚĆ (14 px regular
   vs 17 px bold), nie wygaszenie koloru. Na ciepłym tle stłumiony szary nie
   ma dość miejsca między sobą a tłem, żeby być jednocześnie cichszy
   i czytelny — więc przestaje być hierarchią, a zostaje samą stratą. */
.addon-cart__line {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    padding-bottom: 10px;
    border-bottom: 1px solid var(--linia-mocna);
    font-size: 14px;
    color: var(--tekst);
}
.addon-cart__label {
    /* Skraca się przed kwotą: `min-width: 0` zdejmuje domyślne
       `min-width: auto` flexboxa, przez które długa etykieta („10 × animacja
       10 s") wypychała kwotę poza prawą krawędź zamiast się zawinąć. */
    min-width: 0;
}
.addon-cart__amount {
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.addon-cart__line.is-discount {
    border-bottom-style: dashed;
    color: var(--mosiadz-600);
    font-weight: 700;
}

/* ----- WARIANT `--flush`: koszyk bez własnej powierzchni ----------------
   Używa go paragon w przyklejonym pasku checkoutu (kadr_step2.html): rozpiska
   siedzi tam WEWNĄTRZ białej karty razem z wierszem podsumowania, więc drugi
   kafel — beżowy, z własnym promieniem i paddingiem — kładłby powierzchnię na
   powierzchni. Wariant zdejmuje z koszyka wszystko, co jest powierzchnią
   (tło, promień, padding, odstępy między wierszami), i przenosi padding na
   POJEDYNCZE WIERSZE. Dzięki temu kreski biegną od krawędzi do krawędzi karty
   gospodarza, zamiast wisieć wciętym prostokątem w jej środku.

   MODYFIKATOR, NIE ZESTAW ZMIENNYCH: to jest drugi wygląd tego samego
   komponentu, więc jego definicja ma stać przy pierwszym — w tym pliku.
   Rozsypana na sześć custom properties ustawianych z arkusza strony byłaby
   wiedzą o komponencie trzymaną poza komponentem.

   Panel dokupu w step3 nie używa tego wariantu i zostaje bez zmian. */
.addon-cart--flush {
    gap: 0;
    padding: 0;
    background: transparent;
    border-radius: 0;
}
.addon-cart--flush .addon-cart__line {
    padding: 11px 16px;
    /* Kreska cieńsza tonalnie (`--linia`, nie `--linia-mocna`): na bieli
       mocniejsza linia dzieliła paragon na osobne pasy zamiast rytmizować
       jedną listę. Na beżu potrzebowała tej mocy, tutaj nie. */
    border-bottom-color: var(--linia);
}
/* Ostatni wiersz bez kreski — kreska nad dolną krawędzią karty rysowałaby
   podwójną linię. Gdy rozpiska ma wiersz „Razem", to on jest ostatnim
   dzieckiem i reguła nie zabiera kreski wierszowi nad nim. */
.addon-cart--flush .addon-cart__line:last-child {
    border-bottom: 0;
}
.addon-cart--flush .addon-cart__total {
    padding: 12px 16px 14px;
}

/* Suma — bez górnej ramki, bo ostatni wiersz rozpiski już ją narysował
   od spodu. Dwa bloki: etykieta z ceną jednostkową pod spodem, kwota
   z oszczędnością pod spodem. */
.addon-cart__total {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
}
.addon-cart__total-label,
.addon-cart__total-value {
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.addon-cart__total-value {
    align-items: flex-end;
    text-align: right;
}
.addon-cart__total-label strong {
    font-size: 17px;
    font-weight: 700;
    color: var(--tekst);
}
.addon-cart__total-value strong {
    font-size: 26px;
    font-weight: 700;
    line-height: 1.1;
    color: var(--zielen-900);
    font-variant-numeric: tabular-nums;
}
/* „23,33 zł za zdjęcie" — ten sam powód co wyżej. Kwota na beżu, 12 px:
   przy `--tekst-mut` schodziła do 4,24:1, czyli poniżej AA dla tekstu tej
   wielkości. Cichsza od sumy zostaje rozmiarem (12 px vs 26 px) i grubością. */
.addon-cart__sub {
    font-size: 12px;
    color: var(--tekst);
    font-variant-numeric: tabular-nums;
}
.addon-cart__saved {
    font-size: 12px;
    font-weight: 600;
    color: var(--zielen-700);
    font-variant-numeric: tabular-nums;
}
/* ----- WĄSKIE EKRANY --------------------------------------------------- */
@media (max-width: 480px) {
    /* Siatka dodatków ZOSTAJE 2×2 (poprawka 2026-08-30; wcześniej schodziła
       do jednej kolumny). Cztery dodatki w kwadracie ogarnia się jednym
       spojrzeniem bez scrolla — kafelek na pół szerokości telefonu (~160 px)
       dostaje wariant kompaktowy: mniejszy padding i fonty. */
    .addon-extra {
        min-height: 0;
        padding: 10px;
        gap: 4px;
    }
    .addon-extra__title {
        font-size: 14px;
    }
    /* BEZ line-clamp (zdjęty 2026-08-31; wcześniej opis cięty do dwóch
       linii z wielokropkiem). Clamp zakładał, że da się skalibrować długość
       copy pod liczbę linii — a liczba linii nie jest stała: Safari na
       iOS zawyża drobny tekst (font boosting, brak text-size-adjust w tym
       serwisie), więc opis mieszczący się w emulacji był ucięty na
       prawdziwym iPhonie. Ucięty opis dodatku to obietnica, której klient
       nie może doczytać W MOMENCIE decyzji o dopłacie. Kafelek ma urosnąć
       o linię — wiersz siatki i tak wyrównuje się do wyższego sąsiada,
       a kwota trzyma się dołu przez `margin-top: auto`. Dyscyplinę
       długości niesie samo copy (limit ~33 znaków przy UPSELL_EXTRAS
       w js/step2.js). */
    .addon-extra__desc {
        font-size: 12px;
    }
    .addon-extra__price {
        font-size: 13px;
    }
    .addon-count {
        padding: 14px;
        gap: 10px;
    }
    .addon-count__title {
        font-size: 16px;
    }
    .addon-count__total {
        font-size: 17px;
    }
    /* Wcięcie bloku dodatków podąża za zmniejszonym paddingiem wiersza
       pakietu — linia otwierająca ma zaczynać się w tym samym pionie,
       co jego treść. */
    .addon-pkg__extras {
        margin: 0 14px 14px;
        gap: 8px;
    }
    .addon-row {
        padding: 10px 12px;
        gap: 10px;
    }
    .addon-row__title {
        font-size: 14px;
    }
    .addon-row__desc {
        font-size: 12px;
    }
    .addon-row__price {
        font-size: 13px;
    }
    .addon-cart__total-value strong {
        font-size: 23px;
    }
}

/* =====================================================================
   WARIANTY CHECKOUTU (step2) — rabat polecenia i dodatek spod progu
   =====================================================================
   Dwie sytuacje, których panel nie ma, a checkout ma zawsze. Reguły siedzą
   TUTAJ, a nie w <style> step2, bo są stanami TEGO komponentu — trzymane
   osobno rozjechałyby się z nim przy pierwszej korekcie geometrii wiersza. */

/* Cena pakietu z przekreśloną kotwicą NAD kwotą do zapłaty. Od 2026-09-03
   nośnik OBU rabatów checkoutu: ilościowego (przekreślona cena regularna
   pakietu — zastąpiła chip „oszczędzasz X", który stawiał obok siebie dwie
   podobne kwoty) i rabatu z polecenia (przekreślona cena przed rabatem).
   Którą kotwicę przekreślić, wybiera step2.js (`struckPrice`).
   Układ kolumnowy, nie obok siebie — nie poszerza wiersza, więc telefon (dwie
   kwoty w wąskiej kolumnie) nie wymaga osobnego layoutu. */
.addon-count__total--rabat {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 1px;
    line-height: 1.15;
}
.addon-count__total-old {
    font-size: 13px;
    font-weight: 500;
    color: var(--tekst-mut);
    text-decoration: line-through;
    text-decoration-thickness: 1.5px;
}

/* =====================================================================
   KARTA PAKIETU Z DODATKAMI W ŚRODKU (checkout, 2026-09-01)
   =====================================================================
   W checkoucie każdy pakiet jest KARTĄ (`.addon-pkg`): wiersz cennika
   (`.addon-count--bare`) jest jej nagłówkiem, a ZAZNACZONA karta rozwija
   pod nim listę „Dodatki do N zdjęć" (`.addon-pkg__extras` z wierszami
   `.addon-row`). Dodatki liczą się z rozmiaru wybranego pakietu, więc
   mieszkają w nim, a nie w osobnej sekcji „Chcesz coś dodać?" — ta siatka
   (`.addon-extras*` wyżej) zostaje w pliku, bo używa jej nadal dokup
   w panelu (js/step3/render/addon.js).

   DWA KOLORY, DWA ZNACZENIA — oba z tokens.css, nie z makiety:
     zieleń (`--variant-selected-*`)  = wybrany PAKIET (jak dotąd),
     mosiądz (`--mosiadz-600/-100`)   = zaznaczony DODATEK.
   Dodatek w zieleni ginąłby na miętowym tle zaznaczonej karty — stan
   „w koszyku" musi być widoczny WEWNĄTRZ stanu „wybrany pakiet", więc
   dostaje własny kolor zamiast tego samego o stopień mocniej. */

/* Karta pakietu — przejmuje chrome dawnego wiersza `.addon-count`
   (ramka, tło, promień, stany hover/selected). position: relative —
   kotwica dla absolutnie pozycjonowanej plakietki `.addon-count__badge`,
   która w checkoucie jest dzieckiem karty, nie wiersza. */
.addon-pkg {
    position: relative;
    background: var(--karta);
    border: 2px solid var(--linia);
    border-radius: 14px;
    transition: border-color 0.18s ease, background-color 0.18s ease, box-shadow 0.18s ease;
}
/* Zaznaczenie ZIELENIĄ, ale bez miętowego wypełnienia tła (finalny mockup
   2026-09-06 — dzienna wycieczka w czerwień zawrócona tym samym mockupem):
   stan sygnalizuje ramka + wypełniony znacznik, tło karty bez zmiany.
   Wspólne tokeny `--variant-selected-*`, jak w reszcie lejka. */
.addon-pkg:hover:not(.is-selected) {
    border-color: var(--variant-hover-border);
}
.addon-pkg.is-selected {
    border-color: var(--variant-selected-border);
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
}
/* Stan zaznaczenia niesie KARTA, nie wiersz — znacznik wiersza czyta go
   z rodzica. Lustrzane odbicie reguł `.addon-count.is-selected` wyżej. */
.addon-pkg.is-selected .addon-count__mark {
    background: var(--variant-selected-border);
    border-color: var(--variant-selected-border);
}
.addon-pkg.is-selected .addon-count__mark svg {
    opacity: 1;
}

/* Wiersz cennika wewnątrz karty — geometria `.addon-count` zostaje (grid
   znacznik/treść/kwota), chrome schodzi na kartę. `:active` na całej karcie
   robiłby „kliknięcie" także przy przełączaniu dodatków, więc skala zostaje
   na wierszu. padding-block 19px (nie 16 z bazy) — wiersze checkoutu
   podniesione o ~6 px (2026-09-06), więcej światła wokół treści; reguła
   stoi PO mobilnym override bazy, więc obowiązuje też ≤480 px. */
.addon-count--bare {
    min-height: 78px;
    padding-top: 19px;
    padding-bottom: 19px;
    background: transparent;
    border: 0;
    box-shadow: none;
}
/* Kwota w checkoucie CIEMNA, nie zielona (finalny mockup 2026-09-06) —
   zieleń w kolumnie kwot nosi teraz linię zysku „taniej o X zł"
   (`.addon-count__total-taniej`); dwie zielone kwoty jedna nad drugą
   zlewałyby cenę z zyskiem. Panel dokupu zostaje przy zieleni z bazy. */
.addon-count--bare .addon-count__total {
    color: var(--tekst);
}


/* Blok dodatków — wcięty do światła karty, otwarty linią pod wierszem
   pakietu. margin zamiast paddingu na karcie: linia ma biec od krawędzi
   do krawędzi ŚWIATŁA (jak w makiecie), a nie całej karty. */
.addon-pkg__extras {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin: 0 18px 16px;
    padding-top: 14px;
    border-top: 1px solid var(--linia);
}
.addon-pkg__caption {
    margin: 0;
    font-size: 13px;
    font-weight: 500;
    color: var(--tekst-mut);
}

/* Wiersz dodatku — cała powierzchnia jest celem kliknięcia (touch target
   jak wszędzie w tym komponencie); treść po lewej, okrągły znacznik po
   prawej. Checkbox natywny, ukryty wizualnie (`.addon-extra__input` —
   klasa wspólna z siatką panelu, bo JS checkoutu selektorami po niej
   odtwarza fokus i deleguje `change`). */
.addon-row {
    position: relative;
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: 12px;
    width: 100%;
    padding: 12px 14px;
    background: var(--karta);
    border: 2px solid var(--linia);
    border-radius: 12px;
    text-align: left;
    font-family: var(--font-family);
    cursor: pointer;
    transition: border-color 0.18s ease, background-color 0.18s ease;
}
/* Hover mosiądzem, nie zielenią: hover ma ZAPOWIADAĆ stan po kliknięciu
   (tokens.css), a kliknięcie tego wiersza kończy się mosiądzem. Pełny ton
   zamiast stopnia pośredniego — jaśniejszego mosiądzu nie ma w palecie,
   a checked odróżnia się i tak tłem oraz wypełnionym znacznikiem. */
.addon-row:hover:not(.is-checked) {
    border-color: var(--mosiadz-600);
}
.addon-row:active {
    transform: scale(0.99);
}
.addon-row.is-checked {
    border-color: var(--mosiadz-600);
    background: var(--mosiadz-100);
}

.addon-row__body {
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-width: 0;
}
.addon-row__head {
    display: flex;
    align-items: center;
    gap: 8px;
}
.addon-row__icon {
    display: inline-flex;
    width: 20px;
    height: 20px;
    flex-shrink: 0;
    /* Zieleń jak w siatce panelu (ikona mówi CZEGO dotyczy dodatek,
       nie czy jest zaznaczony) — ale w zaznaczonym wierszu przechodzi
       w mosiądz: na kremowym tle `--mosiadz-100` zielona ikona byłaby
       jedynym elementem spoza gamy stanu. */
    color: var(--zielen-700);
}
.addon-row.is-checked .addon-row__icon {
    color: var(--mosiadz-600);
}
.addon-row__icon svg {
    width: 100%;
    height: 100%;
    display: block;
}
.addon-row__title {
    font-size: 15px;
    font-weight: 700;
    color: var(--tekst);
    line-height: 1.3;
}
.addon-row__desc {
    font-size: 13px;
    line-height: 1.4;
    color: var(--tekst-mut);
}
/* Na kremowym `--mosiadz-100` stłumiony szary spada poniżej AA — ta sama
   lekcja co pozycje koszyka na `--papier-cien` (komentarz przy
   `.addon-cart__line`): hierarchię niesie rozmiar, nie wygaszenie. */
.addon-row.is-checked .addon-row__desc {
    color: var(--tekst);
}
.addon-row__price {
    padding-top: 3px;
    font-size: 14px;
    font-weight: 700;
    color: var(--zielen-900);
    font-variant-numeric: tabular-nums;
}
/* Działanie w nawiasie — „(5 × 9,98 zł)": objaśnienie kwoty, nie druga
   kwota, więc ciszej (waga i kolor), tym samym stopniem co opis. */
.addon-row__calc {
    font-weight: 500;
    color: var(--tekst-mut);
}
.addon-row.is-checked .addon-row__calc {
    color: var(--tekst);
}

/* Znacznik — ta sama gramatyka co w cenniku (pusty okrąg → wypełniony
   z ptaszkiem), wypełnienie mosiądzem zamiast zieleni: patrz nagłówek
   sekcji. Ptaszek zawsze w DOM (opacity), jak w `.addon-count__mark`. */
.addon-row__mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    border: 2px solid var(--linia-mocna);
    background: var(--karta);
    color: white;
    flex-shrink: 0;
    transition: background-color 0.18s ease, border-color 0.18s ease;
}
.addon-row__mark svg {
    width: 13px;
    height: 13px;
    opacity: 0;
    transition: opacity 0.18s ease;
}
.addon-row.is-checked .addon-row__mark {
    background: var(--mosiadz-600);
    border-color: var(--mosiadz-600);
}
.addon-row.is-checked .addon-row__mark svg {
    opacity: 1;
}
/* Fokus klawiaturą na widocznym znaczniku (input jest ukryty) — ten sam
   kolor obrysu co wszędzie na stronie, niezależnie od gamy stanu wiersza. */
.addon-extra__input:focus-visible ~ .addon-row__mark {
    outline: 2px solid var(--variant-selected-border);
    outline-offset: 3px;
}

/* Wiersz promocyjny (pamiątkowy film w cenie pakietu) — ramka przerywana
   odróżnia ofertę z przekreśloną ceną od zwykłych dopłat. */
.addon-row--promo {
    border-style: dashed;
}

/* Wiersz dodatku, który NIE JEST jeszcze dostępny w wybranym pakiecie
   (pamiątkowy film poniżej progu FILM_BUNDLE_MIN_PHOTOS).

   To SKRÓT, nie kontrolka wyboru: kliknięcie podnosi pakiet do progu
   i zaznacza film (uzasadnienie przy renderLockedFilmRow w js/step2.js —
   etykieta ceny zapowiada oba skutki: „dodaj z pakietem 5 zdjęć").

   Stąd inny wygląd: stłumione beżowe tło bez ramki (nie konkuruje
   z prawdziwymi kontrolkami) i mosiądz ceny — ten sam co plakietka
   „Najczęstszy wybór", bo mówi „rozważ większy pakiet". Znacznika brak:
   pusty okrąg sugerowałby checkbox, który zostanie zaznaczony w miejscu. */
.addon-row--locked {
    background: var(--papier-cien);
    border-color: transparent;
}
.addon-row--locked:hover {
    border-color: var(--mosiadz-600);
}
.addon-row--locked .addon-row__icon,
.addon-row--locked .addon-row__price {
    color: var(--mosiadz-600);
}
.addon-row--locked .addon-row__price {
    font-size: 13px;
}

/* Linia „wgrane X / pozostałe N dodasz w panelu” (step2). Treść dynamiczna
   z jednego źródła (uploadedPhotosCount × rozmiar pakietu, packageUploadInfo
   w js/step2.js). Od 2026-09-06 renderowana POD listą pakietów (wariant
   `--lista` niżej, mockup) — wcześniej wewnątrz karty wybranego pakietu,
   gdzie rozpychała kartę i znikała przy zmianie zaznaczenia. */
.addon-note {
    display: flex;
    align-items: center;
    gap: 7px;
    margin: 0;
    padding: 0 2px;
    font-size: 13px;
    font-weight: 500;
    line-height: 1.4;
    color: var(--zielen-700);
}
.addon-note[hidden] {
    display: none;
}
/* Wariant POD LISTĄ pakietów (`.addon-note--lista`) mieszka w inline <style>
   kadr_step2.html, nie tutaj: ma wyglądać identycznie jak tamtejszy
   `.email-hint` (stłumiony szary hint), a ten kolor jest literałem strony,
   nie tokenem — deklaracja obok pierwowzoru nie może się z nim rozjechać. */
/* Ikona przez maskę CSS — kolor z `background-color`, plik z modyfikatora.
   Ścieżka względem TEGO pliku (css/), stąd `../assets`. */
.addon-note__icon {
    flex-shrink: 0;
    width: 15px;
    height: 15px;
    background-color: var(--zielen-700);
    -webkit-mask-size: contain;
    mask-size: contain;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    mask-position: center;
}
.addon-note__icon--upload {
    -webkit-mask-image: url('../assets/icons/upload-simple.svg');
    mask-image: url('../assets/icons/upload-simple.svg');
}
.addon-note__icon--check {
    -webkit-mask-image: url('../assets/icons/check.svg');
    mask-image: url('../assets/icons/check.svg');
}
