/* MZPN Plebiscyt – frontend styles */

/* Montserrat hostowany lokalnie (RODO, szczelna CSP). Pliki .woff2 w assets/fonts/,
   ścieżki względne do tego pliku (assets/css/ -> ../fonts/). */
@font-face {
    font-family: 'Montserrat';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('../fonts/montserrat-400.woff2') format('woff2');
}
@font-face {
    font-family: 'Montserrat';
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url('../fonts/montserrat-500.woff2') format('woff2');
}
@font-face {
    font-family: 'Montserrat';
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url('../fonts/montserrat-600.woff2') format('woff2');
}
@font-face {
    font-family: 'Montserrat';
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url('../fonts/montserrat-700.woff2') format('woff2');
}
@font-face {
    font-family: 'Montserrat';
    font-style: normal;
    font-weight: 800;
    font-display: swap;
    src: url('../fonts/montserrat-800.woff2') format('woff2');
}

.mzpn-plebiscyt {
    /* === MOTYW: ciemny + złoto (Piłkarskie Orły Małopolski) === */
    --mzpn-gold: #c0944a;            /* główny złoty akcent: nagłówki, ramki, przyciski */
    --mzpn-gold-dark: #a67e3a;       /* hover / przyciemnienie złota */
    --mzpn-gold-soft: rgba(192, 148, 74, .12);
    --mzpn-ink: #f4f1ea;             /* główny jasny tekst na ciemnym tle */
    --mzpn-muted: #b2b2b2;           /* drugorzędny, szary tekst */
    --mzpn-bg: #0c0c10;              /* głęboka czerń (kontekst strony) */
    --mzpn-surface: #16161c;         /* tło kart */
    --mzpn-surface-2: #1f1f28;       /* podniesione: pola, modale */
    --mzpn-border: rgba(192, 148, 74, .22);   /* subtelna złota ramka */
    --mzpn-navy: #0a1f3c;            /* ciemny granat - akcenty/tła (np. toast) */
    --mzpn-danger: #e0564a;
    --mzpn-danger-soft: rgba(224, 86, 74, .12);
    /* Złoto pełni rolę "primary" w tym motywie - zachowane nazwy zmiennych,
       żeby istniejące komponenty automatycznie dostały złoty kolor. */
    --mzpn-primary: #c0944a;
    --mzpn-primary-dark: #a67e3a;
    --mzpn-accent: #e0564a;
    --mzpn-bg-soft: #1f1f28;
    /* KONFIG: liczba widocznych linii opisu na mobile przed "Rozwiń". */
    --mzpn-bio-lines: 5;
    --mzpn-shadow: 0 12px 32px rgba(0, 0, 0, .45);
    --mzpn-serif: 'Cormorant Garamond', 'Cormorant', Georgia, 'Times New Roman', serif;
    --mzpn-sans: 'Montserrat', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    --mzpn-font: var(--mzpn-sans);
    max-width: 1280px;
    margin: 0 auto;
    padding: 24px 16px;
    font-family: var(--mzpn-sans);
    color: var(--mzpn-ink);
    color-scheme: dark;
}
/* Motyw blokowy ogranicza treść przez --wp--style--global--content-size
   (np. 620px). Nadpisujemy tę zmienną dla bloku, w którym osadzony jest
   plebiscyt, oraz dla jego rodziców z układem "constrained", żeby plugin
   mógł rozciągnąć się do swojej szerokości. */
.entry-content:has(.mzpn-plebiscyt),
.wp-block-post-content:has(.mzpn-plebiscyt),
.is-layout-constrained:has(> .mzpn-plebiscyt) {
    --wp--style--global--content-size: 1280px;
}
.mzpn-plebiscyt h1,
.mzpn-plebiscyt h2,
.mzpn-plebiscyt h3,
.mzpn-plebiscyt legend {
    font-family: var(--mzpn-serif);
    font-variant-numeric: lining-nums; /* cyfry liniowe, wyrównane do wersalików (nie old-style) */
    font-weight: 600;
    color: var(--mzpn-gold);
    letter-spacing: .01em;
}

.mzpn-notice {
    border-radius: 12px;
    padding: 14px 16px;
    margin: 16px 0;
    border: 1px solid var(--mzpn-border);
    background: var(--mzpn-surface);
    color: var(--mzpn-ink);
}
.mzpn-notice-success { background: rgba(74, 168, 110, .12);  border-color: rgba(74, 168, 110, .40); }
.mzpn-notice-error   { background: var(--mzpn-danger-soft);  border-color: rgba(224, 86, 74, .40); }
.mzpn-notice-info    { background: var(--mzpn-gold-soft);    border-color: var(--mzpn-border); }

.mzpn-muted {
    color: var(--mzpn-muted);
    font-size: .95rem;
}

.mzpn-honeypot {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

/* Kategoria - tytuł serif ze złotą linią pod spodem (styl POM) */
.mzpn-category {
    border: none;
    margin: 0 0 60px;
    padding: 0;
    background: transparent;
}
.mzpn-category-title {
    font-family: var(--mzpn-serif);
    font-variant-numeric: lining-nums; /* "4. liga" itp. - cyfry wyrównane do wersalików */
    font-weight: 600;
    font-size: 1.7rem;
    color: var(--mzpn-gold);
    padding: 0 0 12px;
    margin: 0 0 22px;
    border-bottom: 1px solid var(--mzpn-border);
    text-transform: uppercase;
    letter-spacing: .04em;
    line-height: 1.2;
}

/* Wskaźnik pozycji w karuzeli "X / N · przesuń palcem" - widoczny TYLKO na
   mobile (na desktopie karty są w siatce, nie w karuzeli). */
.mzpn-carousel-hint {
    display: none;
    margin: 12px 0 0;
    text-align: center;
    font-size: .82rem;
    font-weight: 600;
    color: var(--mzpn-muted);
    letter-spacing: .01em;
}
.mzpn-carousel-current {
    color: var(--mzpn-primary);
    font-weight: 800;
}

/* Siatka kandydatów (desktop): pionowe kafelki zawijane responsywnie. Liczba kart
   w rzędzie sama dopasowuje się do szerokości (flex-wrap), a niepełna ostatnia linia
   jest wyśrodkowana - dzięki temu wygląda spójnie przy DOWOLNEJ liczbie kandydatów
   (6/8/10...). Szerokość karty = flex-basis na .mzpn-candidate-card (jeden regulator
   gęstości). Na mobile @media zmienia się w poziomą karuzelę. */
.mzpn-candidate-grid {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 22px;
}

/* Kafelek - układ PIONOWY (desktop): okrągłe zdjęcie u góry, pod nim wyśrodkowane
   imię/klub/opis. Stała szerokość bazowa (flex-basis) to jedyny regulator gęstości
   siatki. Karty w jednym rzędzie mają równą wysokość (flex stretch). */
.mzpn-candidate-card {
    position: relative;
    display: flex;
    flex: 1 1 250px;
    max-width: 300px;
    min-height: 380px;
    flex-direction: column;
    align-items: center;
    gap: 0;
    text-align: center;
    background: var(--mzpn-surface);
    border: 1px solid var(--mzpn-border);
    border-radius: 14px;
    padding: 26px 20px 22px;
    cursor: pointer;
    transition: border-color .18s ease, box-shadow .18s ease, transform .12s ease, background-color .18s ease;
    box-shadow: var(--mzpn-shadow);
}
/* Hover tylko na urządzeniach z prawdziwym kursorem (mysz). Na dotyku iOS/
   Android "przykleja" :hover po tapnięciu, co wyglądało jak fałszywe
   zaznaczenie - dlatego na telefonie hover jest wyłączony. */
@media (hover: hover) {
    .mzpn-candidate-card:hover {
        border-color: var(--mzpn-gold);
        box-shadow: 0 10px 28px rgba(0, 0, 0, .5);
        transform: translateY(-2px);
    }
}

/* Kolumna tekstu pod zdjęciem - wyśrodkowana. */
.mzpn-candidate-body {
    width: 100%;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
}

/* Natywny radio jest wizualnie ukryty, ale OBECNY w DOM (wysyłka formularza i
   powiązanie label[for] działają jak dotychczas). Stan zaznaczenia rysuje JS klasą
   .is-checked na karcie (ramka + złoty znacznik ✓). Klik w dowolny obszar karty
   zaznacza kandydata - nie ma osobnego przycisku "Wybierz". */
.mzpn-candidate-card input[type="radio"] {
    position: absolute;
    opacity: 0;
    width: 1px;
    height: 1px;
    pointer-events: none;
}

/* Zaznaczony kafelek - niebieska ramka MZPN (sterowane klasą .is-checked z JS,
   nie :has(input:checked), żeby mieć pełną kontrolę nad odznaczaniem). */
.mzpn-candidate-card.is-checked {
    border-color: var(--mzpn-gold);
    background:
        linear-gradient(180deg, rgba(192, 148, 74, .14) 0%, rgba(192, 148, 74, .05) 100%),
        var(--mzpn-surface);
    box-shadow: 0 0 0 1px var(--mzpn-gold), 0 10px 28px rgba(192, 148, 74, .18);
}

/* Zdjęcie - OKRĄGŁY awatar u góry karty (odstęp pod nim daje .mzpn-candidate-figure). */
.mzpn-candidate-image {
    width: 112px;
    height: 112px;
    border-radius: 50%;
    margin: 0;
    background: var(--mzpn-bg-soft);
    display: grid;
    place-items: center;
    overflow: hidden;
    flex: 0 0 auto;
    align-self: center;
    border: 2px solid var(--mzpn-border);
    transition: border-color .2s ease;
}
.mzpn-candidate-image img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center 25%;
}
.mzpn-avatar-placeholder {
    font-size: 2.2rem;
    font-weight: 800;
    color: var(--mzpn-ink);
}

/* Treść tekstowa - wyśrodkowana pod zdjęciem */
.mzpn-candidate-content {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    width: 100%;
}
.mzpn-candidate-name {
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--mzpn-ink);
    line-height: 1.25;
}
.mzpn-candidate-club {
    color: var(--mzpn-gold);
    font-size: .72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .08em;
}

/* Złota linia oddzielająca klub od opisu */
.mzpn-candidate-divider {
    display: block;
    width: 28px;
    height: 2px;
    background: var(--mzpn-gold);
    margin: 8px 0 2px;
}

/* Opis kandydata (pole "Notka / opis" = kolumna bio). BEZ limitu linii -
   pokazujemy CAŁY tekst; kafelek rośnie na tyle, ile trzeba, a siatka i tak
   zrówna wysokość kafelków w rzędzie do najwyższego. white-space:pre-line
   zachowuje łamania/akapity wpisane w panelu admina. */
.mzpn-candidate-bio {
    color: var(--mzpn-muted);
    font-size: .82rem;
    line-height: 1.55;
    white-space: pre-line;
    text-align: center; /* desktop: wyśrodkowanie; mobile (max-width 768px) nadpisuje na left */
    -webkit-hyphens: auto;
    hyphens: auto;
    -webkit-hyphenate-limit-before: 2;
    -webkit-hyphenate-limit-after: 2;
    hyphenate-limit-chars: 5 2 2;
    width: 100%;
}

/* Sekcja submit */
.mzpn-voter-box,
.mzpn-results,
.mzpn-partners {
    border: 1px solid var(--mzpn-border);
    border-radius: 14px;
    background: var(--mzpn-bg-soft);
    padding: 28px;
    margin: 24px 0;
}
.mzpn-voter-box h2 {
    color: var(--mzpn-ink);
    margin-top: 0;
    margin-bottom: 18px;
    font-size: 1.5rem;
    font-weight: 600;
    letter-spacing: .01em;
}

/* Wyraźniejszy odstęp + złota kreska oddzielająca kategorie od bloku e-mail/zgody/głosowanie. */
.mzpn-voter-box {
    position: relative;
    margin-top: 80px;
}
.mzpn-voter-box::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: -40px;
    height: 2px;
    border-radius: 2px;
    background: var(--mzpn-gold);
}

.mzpn-field {
    display: flex;
    flex-direction: column;
    gap: 6px;
    font-weight: 600;
    margin-bottom: 16px;
    font-size: .92rem;
}
.mzpn-field input {
    width: 100%;
    box-sizing: border-box;
    padding: 12px 14px;
    border: 1px solid var(--mzpn-border);
    border-radius: 8px;
    background: var(--mzpn-surface-2);
    color: var(--mzpn-ink);
    font: inherit;
    transition: border-color .15s ease, box-shadow .15s ease;
}
.mzpn-field input::placeholder { color: rgba(244, 241, 234, .40); }
.mzpn-field input:focus {
    border-color: var(--mzpn-gold);
    outline: none;
    box-shadow: 0 0 0 3px rgba(192, 148, 74, .22);
}
/* Autofill Chrome/WebKit wymusza własne jasne tło - maskujemy je ciemnym
   wypełnieniem (box-shadow inset) i wymuszamy jasny kolor tekstu. */
.mzpn-field input:-webkit-autofill,
.mzpn-field input:-webkit-autofill:hover {
    -webkit-text-fill-color: var(--mzpn-ink);
    -webkit-box-shadow: 0 0 0 1000px var(--mzpn-surface-2) inset;
    box-shadow: 0 0 0 1000px var(--mzpn-surface-2) inset;
    caret-color: var(--mzpn-ink);
}
.mzpn-field input:-webkit-autofill:focus {
    -webkit-text-fill-color: var(--mzpn-ink);
    -webkit-box-shadow: 0 0 0 1000px var(--mzpn-surface-2) inset;
    box-shadow: 0 0 0 1000px var(--mzpn-surface-2) inset;
    border-color: var(--mzpn-gold);
}

.mzpn-checkbox {
    display: flex;
    gap: 10px;
    align-items: flex-start;
    margin: 12px 0;
    font-size: .92rem;
}
.mzpn-checkbox input {
    margin-top: .25em;
    flex-shrink: 0;
    accent-color: var(--mzpn-primary);
}
.mzpn-checkbox a {
    color: var(--mzpn-primary);
    font-weight: 600;
}

.mzpn-submit {
    border: none;
    border-radius: 4px;
    background: var(--mzpn-primary) !important;
    color: #fff;
    font-weight: 700;
    font-size: 1rem;
    padding: 15px 36px;
    margin-top: 16px;
    cursor: pointer;
    transition: background .15s ease, transform .1s ease;
    letter-spacing: .04em;
    text-transform: uppercase;
    font-family: var(--mzpn-font);
}
.mzpn-submit:hover:not(:disabled) {
    background: var(--mzpn-primary-dark) !important;
    transform: translateY(-1px);
}
.mzpn-submit:disabled {
    background: var(--mzpn-primary) !important;
    opacity: .85;
    cursor: not-allowed;
}

/* === Loading spinner przy submitcie ===
   Aktywny gdy form ma data-submitting="1" (ustawiane przez frontend.js w setSubmitting()).
   Spinner pojawia się PRZED tekstem buttona ("Wysyłanie...").
   Czysto kosmetyczne - bezpieczeństwo i flow są w innym miejscu. */
.mzpn-vote-form[data-submitting="1"] .mzpn-submit {
    padding-left: 56px;
    cursor: progress;
    opacity: 1; /* nadpisuje .mzpn-submit:disabled żeby spinner był wyraźny */
    position: relative;
}
.mzpn-vote-form[data-submitting="1"] .mzpn-submit::before {
    content: '';
    position: absolute;
    left: 24px;
    top: 50%;
    width: 16px;
    height: 16px;
    margin-top: -8px;
    border: 2px solid rgba(255, 255, 255, 0.35);
    border-top-color: #fff;
    border-radius: 50%;
    animation: mzpn-spin 0.7s linear infinite;
}
@keyframes mzpn-spin {
    to { transform: rotate(360deg); }
}

/* Subtelny overlay na całym formularzu żeby user nie klikał innych pól.
   Półprzezroczyste tło + cursor: progress. Nie blokuje fizycznie kliknięć
   (pointer-events: none na overlay), ale daje wizualną informację że
   formularz przetwarza request. */
.mzpn-vote-form[data-submitting="1"] {
    position: relative;
    pointer-events: none;
}
.mzpn-vote-form[data-submitting="1"]::after {
    content: '';
    position: absolute;
    inset: 0;
    background: rgba(12, 12, 16, 0.55);
    pointer-events: none;
    border-radius: 8px;
    z-index: 10;
}
/* Wyjątek: submit button MA być widoczny i interaktywny wizualnie - to on
   pokazuje stan "wysyłania" przez spinner i tekst. */
.mzpn-vote-form[data-submitting="1"] .mzpn-submit {
    position: relative;
    z-index: 11;
    pointer-events: auto;
}

.mzpn-ranking {
    display: grid;
    gap: 8px;
    padding-left: 1.5rem;
}
.mzpn-ranking li {
    padding: 10px 12px;
    border: 1px solid var(--mzpn-border);
    border-radius: 10px;
    background: var(--mzpn-surface);
}
.mzpn-rank-name {
    font-weight: 700;
}
.mzpn-rank-club {
    display: block;
    color: var(--mzpn-muted);
    font-size: .92rem;
}

.mzpn-partners-content {
    display: flex;
    gap: 18px;
    flex-wrap: wrap;
    align-items: center;
}
.mzpn-partners-content img {
    max-height: 72px;
    width: auto;
}

/* Poniżej ~768px: jedna kolumna szerokich kart poziomych (mobile) */
@media (max-width: 768px) {
    /* KARUZELA: na mobile siatka kart staje się poziomą karuzelą z natywnym
       przewijaniem i przyciąganiem (scroll-snap). Widać jedną dużą hero-kartę
       zawodnika, a sąsiednia "wystaje" z prawej (peek) - sygnał, że można
       przesuwać palcem. Bez ciężkiego JS, przewijanie jest natywne i płynne. */
    /* FULL-BLEED: sama karuzela wychodzi poza marginesy kontenera na pełną
       szerokość ekranu (100vw, wyśrodkowana) - wystające karty dojeżdżają do
       samych krawędzi, co daje "immersyjny" efekt. Tytuł kategorii, licznik i
       formularz zostają z normalnymi marginesami. */
    .mzpn-candidate-grid {
        display: flex;
        flex-wrap: nowrap;
        justify-content: flex-start;
        gap: 12px;
        overflow-x: auto;
        scroll-snap-type: x mandatory;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
        width: 100vw;
        margin-left: calc(50% - 50vw);
        padding: 2px 0 8px;
    }
    .mzpn-candidate-grid::-webkit-scrollbar { display: none; }
    /* Boczne "rozpychacze", żeby pierwsza i ostatnia karta też mogły się
       wyśrodkować (zamiast kleić do krawędzi) - dzięki temu ZAWSZE widać
       podgląd sąsiednich kart po obu stronach (sygnał, że można przesuwać). */
    .mzpn-candidate-grid::before,
    .mzpn-candidate-grid::after {
        content: '';
        flex: 0 0 20%;
    }

    /* Hero-karta: jedna na ekran (~60% szerokości), zdjęcie u góry, tekst pod
       spodem. Wyrównanie wysokości robi JS (equalize() w initBioToggles): mierzy
       najwyższą ZWINIĘTĄ kartę w danej karuzeli i ustawia jej wysokość jako
       min-height pozostałych (inline) - najwyższa jest "w sam raz", krótsze
       dorównują do niej bez nadmiaru. Tu min-height:0 tylko zeruje bazowe 380px
       z desktopu; rozwinięta karta rośnie ponad podłogę niezależnie, bo siatka
       ma align-items:flex-start (zwijanie/rozwijanie nie rozpycha sąsiadów). */
    .mzpn-candidate-card {
        flex: 0 0 60%;
        max-width: none;
        min-height: 0;
        scroll-snap-align: center;
        flex-direction: column;
        align-items: center;
        text-align: center;
        gap: 0;
        padding: 20px 16px 16px;
    }

    .mzpn-candidate-image {
        width: 104px;
        height: 104px;
        align-self: center;
        margin: 0 0 12px;
    }
    .mzpn-candidate-body {
        width: 100%;
        align-items: center;
    }
    .mzpn-candidate-content {
        align-items: center;
    }
    .mzpn-candidate-name { font-size: 1.1rem; }
    .mzpn-candidate-divider { margin: 10px 0 8px; }
    /* Opis: pełna szerokość, ale czytany do lewej (lepsza czytelność długiego
       tekstu niż wyśrodkowanie). */
    .mzpn-candidate-bio {
        width: 100%;
        display: block;
        position: relative;
        text-align: left;
        -webkit-hyphens: auto;
        hyphens: auto;
        font-size: .85rem;
        transition: max-height .3s ease;
    }

    .mzpn-carousel-hint { display: block; }
}
@media (max-width: 640px) {
    .mzpn-plebiscyt {
        padding: 20px 12px;
    }
    .mzpn-results,
    .mzpn-partners {
        padding: 16px;
    }
    .mzpn-voter-box {
        padding: 25px 20px;
    }
}
@media (max-width: 400px) {
    /* Na wąskich telefonach maksymalnie ograniczamy paddingi STRONY i sekcji
       pobocznych, żeby widget Turnstile (~300px) zmieścił się bez wystawania.
       Sam formularz (voter-box) zostawiamy z wygodniejszym paddingiem. */
    .mzpn-plebiscyt {
        padding: 16px 8px;
    }
    .mzpn-results,
    .mzpn-partners {
        padding: 14px 10px;
    }
    .mzpn-voter-box {
        padding: 20px 12px;
    }
}
@media (max-width: 480px) {
    /* Na małych telefonach karta wciąż węższa niż ekran, by widać było sąsiednie */
    .mzpn-candidate-card {
        flex: 0 0 64%;
        padding: 18px 14px 14px;
    }
    .mzpn-candidate-image {
        width: 96px;
        height: 96px;
    }
}

/* Modal ostrzegawczy (niepełne głosowanie) */
.mzpn-modal[hidden] { display: none; }
.mzpn-modal {
    position: fixed;
    inset: 0;
    z-index: 99999;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
}
.mzpn-modal-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, .62);
}
.mzpn-modal-box {
    position: relative;
    background: var(--mzpn-surface-2);
    border: 1px solid var(--mzpn-border);
    border-radius: 14px;
    max-width: 440px;
    width: 100%;
    padding: 32px 28px 28px;
    box-shadow: 0 24px 60px rgba(0, 0, 0, .6);
    text-align: center;
}
.mzpn-modal-icon {
    width: 60px;
    height: 60px;
    border-radius: 50%;
    background: var(--mzpn-gold-soft);
    color: var(--mzpn-gold);
    font-size: 34px;
    font-weight: 700;
    line-height: 60px;
    margin: 0 auto 16px;
}
.mzpn-modal-box h3 {
    margin: 0 0 8px;
    font-size: 1.55rem;
    color: var(--mzpn-gold);
    font-family: var(--mzpn-serif);
    font-weight: 600;
    letter-spacing: .01em;
}
.mzpn-modal-box p {
    margin: 0 0 20px;
    font-size: 15px;
    line-height: 1.6;
    color: var(--mzpn-muted);
}
.mzpn-modal-box strong { color: var(--mzpn-ink); }
.mzpn-modal-actions {
    display: flex;
    gap: 10px;
}
.mzpn-modal-btn {
    flex: 1;
    padding: 12px;
    border-radius: 4px;
    font-size: 14px;
    font-weight: 700;
    cursor: pointer;
    border: 1px solid transparent;
    transition: background .15s, border-color .15s;
    font-family: var(--mzpn-sans);
    text-transform: uppercase;
    letter-spacing: .06em;
}
.mzpn-modal-btn-secondary {
    background: transparent;
    border-color: var(--mzpn-border);
    color: var(--mzpn-ink);
}
.mzpn-modal-btn-secondary:hover { background: var(--mzpn-surface); border-color: var(--mzpn-gold); }
.mzpn-modal-btn-primary {
    background: var(--mzpn-gold);
    color: #14130f;
}
.mzpn-modal-btn-primary:hover { background: var(--mzpn-gold-dark); }
@media (max-width: 480px) {
    .mzpn-modal-actions { flex-direction: column-reverse; }
}

/* === Pola wymagane: gwiazdka + dopisek === */
.mzpn-req {
    color: var(--mzpn-accent);
    font-weight: 700;
}
.mzpn-required-note {
    font-size: .82rem;
    color: var(--mzpn-muted);
    margin: 10px 0 0;
}
.mzpn-field-label {
    display: inline;
}

/* === Walidacja inline: e-mail === */
.mzpn-field-error {
    display: none;
    color: var(--mzpn-accent);
    font-size: .82rem;
    font-weight: 600;
    margin-top: 4px;
}
.mzpn-field.has-error input {
    border-color: var(--mzpn-accent);
    box-shadow: 0 0 0 3px rgba(232, 36, 42, .12);
}
.mzpn-field.has-error .mzpn-field-error {
    display: block;
}

/* === Walidacja zgód: czerwone podświetlenie === */
.mzpn-checkbox.has-error span {
    color: var(--mzpn-accent);
}
.mzpn-checkbox.has-error input {
    outline: 2px solid var(--mzpn-accent);
    outline-offset: 2px;
}
.mzpn-consent-error {
    color: var(--mzpn-accent);
    font-size: .85rem;
    font-weight: 600;
    margin: 4px 0 12px;
}

/* === Czysta strona po głosowaniu === */
.mzpn-postvote {
    margin: 0 auto;
    background: var(--mzpn-surface);
    border: 1px solid var(--mzpn-border);
    border-radius: 14px;
    padding: 44px 32px;
    text-align: center;
}
.mzpn-postvote-icon {
    width: 72px;
    height: 72px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 0 auto 22px;
}
.mzpn-postvote-icon svg {
    width: 38px;
    height: 38px;
}
.mzpn-postvote-success .mzpn-postvote-icon { background: rgba(74, 168, 110, .16); color: #6fcf97; }
.mzpn-postvote-info .mzpn-postvote-icon { background: var(--mzpn-gold-soft); color: var(--mzpn-gold); }
.mzpn-postvote-confirm .mzpn-postvote-icon { background: var(--mzpn-danger-soft); color: var(--mzpn-danger) !important; }
.mzpn-postvote-confirm h2 { color: var(--mzpn-danger) !important; }
.mzpn-postvote h2 {
    font-family: var(--mzpn-serif);
    font-size: 2rem;
    font-weight: 600;
    color: var(--mzpn-gold);
    text-transform: uppercase;
    margin: 0 0 14px;
    line-height: 1.15;
    letter-spacing: .03em;
}
.mzpn-postvote p {
    color: var(--mzpn-muted);
    font-size: 1rem;
    line-height: 1.65;
    margin: 0 0 28px;
}
.mzpn-postvote-btn {
    display: inline-block;
    background: var(--mzpn-gold);
    color: #14130f !important;
    padding: 14px 36px;
    font-size: .95rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .08em;
    border-radius: 4px;
    text-decoration: none;
    transition: background .15s;
}
.mzpn-postvote-btn:hover { background: var(--mzpn-gold-dark); }

/* === Komunikat: nie wybrano żadnego kandydata === */
.mzpn-no-candidate-error {
    color: var(--mzpn-danger);
    font-size: .95rem;
    font-weight: 600;
    background: var(--mzpn-danger-soft);
    border: 1px solid rgba(224, 86, 74, .40);
    border-radius: 6px;
    padding: 12px 16px;
    margin: 0 0 20px;
    text-align: center;
}

/* Kontener lazy-load Turnstile (renderowany w trybie explicit przez frontend.js).
   Pusty do momentu pierwszej interakcji z formularzem - rezerwujemy odstęp. */
.mzpn-turnstile-slot { margin: 16px 0; min-height: 0; width: 100%; }
.mzpn-turnstile-slot:empty { margin: 0; }

/* Gwiazdka pola wymaganego trzyma się ostatniego znaku (nie spada sama do nowej linii) */
.mzpn-req-wrap {
    white-space: nowrap;
}

/* =========================================================================
   v1.9.21 - ulepszony wybór kandydata na mobile
   ========================================================================= */

/* Zaznaczenie wybranej karty pokazujemy znacznikiem ✓ NA ZDJĘCIU (.mzpn-candidate-check)
   - jednolicie na desktopie i mobile. Dawny znacznik w rogu karty (::after) usunięty. */

/* =========================================================================
   v1.9.22 - "hero" wybór na mobile (złota ramka + kremowe tło + poświata,
   złoty znacznik ✓ na zdjęciu, szersza karta, bez pigułki).
   Desktop pozostaje bez zmian (niebieski stan + pigułka + znacznik w rogu).
   ========================================================================= */

/* Owijka zdjęcia - nośnik pozycji dla znacznika ✓ (przejmuje rolę flex-itemu
   po .mzpn-candidate-image; samo zdjęcie zachowuje rozmiar/okrąg/przycięcie). */
.mzpn-candidate-figure {
    position: relative;
    flex: 0 0 auto;
    align-self: center;
    margin: 0 0 18px;
    line-height: 0;
}

/* Złoty znacznik ✓ na zdjęciu - domyślnie ukryty, pokazywany gdy karta wybrana
   (jednolicie na desktopie i mobile; dawny znacznik w rogu karty usunięty). */
.mzpn-candidate-check {
    position: absolute;
    top: 0;
    right: 0;
    width: 30px;
    height: 30px;
    border-radius: 50%;
    background: var(--mzpn-gold);
    color: #14130f;
    border: 3px solid var(--mzpn-surface);
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 2px 6px rgba(184, 148, 90, .4);
    z-index: 2;
    opacity: 0;
    transform: scale(.6);
    pointer-events: none;
    transition: opacity .18s ease, transform .22s cubic-bezier(.34, 1.56, .64, 1);
}
.mzpn-candidate-check svg { display: block; }

/* Wybrana karta: pokaż znacznik ✓ na zdjęciu + złota obwódka zdjęcia (desktop i mobile). */
.mzpn-candidate-card.is-checked .mzpn-candidate-check { opacity: 1; transform: scale(1); }
.mzpn-candidate-card.is-checked .mzpn-candidate-image { border-color: var(--mzpn-gold); }

/* Kolory ikon w hincie przesuwania (hint jest display:none na desktopie). */
.mzpn-hint-hand  { color: var(--mzpn-ink); flex: 0 0 auto; }
.mzpn-hint-hand svg { display: block; }
.mzpn-hint-inner {
    display: inline-flex;
    align-items: center;
    gap: 10px;
}
/* Klikalne strzałki karuzeli (mobile) - przewijają o jedną kartę. */
.mzpn-carousel-nav {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    padding: 0;
    border: 1px solid var(--mzpn-border);
    border-radius: 999px;
    background: var(--mzpn-surface);
    color: var(--mzpn-gold);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: background .15s ease, border-color .15s ease, transform .1s ease, opacity .15s ease;
}
.mzpn-carousel-nav svg { display: block; }
.mzpn-carousel-nav:hover { border-color: var(--mzpn-primary); }
.mzpn-carousel-nav:active { transform: scale(.92); background: var(--mzpn-bg-soft); }
.mzpn-carousel-nav:focus-visible { outline: 3px solid rgba(192, 148, 74, .40); outline-offset: 2px; }
.mzpn-carousel-nav[disabled] { opacity: .35; cursor: default; pointer-events: none; }

/* Brak "double-tap to zoom": szybkie podwójne stuknięcie w przycisk/kartę nie
   przybliża strony. Swipe (pan) i pinch-zoom dwoma palcami działają normalnie. */
.mzpn-plebiscyt button,
.mzpn-plebiscyt .mzpn-candidate-card,
.mzpn-plebiscyt .mzpn-bio-toggle {
    touch-action: manipulation;
}
.mzpn-hint-text {
    color: var(--mzpn-ink);
    font-weight: 700;
    font-size: .92rem;
    letter-spacing: .01em;
}

@media (max-width: 768px) {
    /* Więcej powietrza w karuzeli, żeby poświata wybranej karty nie była ucinana.
       align-items:flex-start => KAŻDA karta ma własną, niezależną wysokość. Dzięki
       temu rozwinięcie jednej karty nie zmienia wysokości sąsiednich (przy 5-liniowym
       przycięciu biografii zwinięte karty i tak wyglądają równo). */
    .mzpn-candidate-grid {
        align-items: stretch;
        padding: 16px 0 18px;
    }
    .mzpn-candidate-grid::before,
    .mzpn-candidate-grid::after {
        flex: 0 0 18%;
    }

    /* Szersza karta-hero + mocniejsze zaokrąglenie. */
    .mzpn-candidate-card {
        flex: 0 0 72%;
        padding: 22px 18px 20px;
        border-radius: 16px;
    }

    /* Stan WYBRANO na mobile = złota ramka + kremowe tło + ciepła poświata. */
    .mzpn-candidate-card.is-checked {
        border-color: var(--mzpn-gold);
        background:
            linear-gradient(180deg, rgba(192, 148, 74, .14) 0%, rgba(192, 148, 74, .05) 100%),
            var(--mzpn-surface);
        box-shadow: 0 0 0 1px var(--mzpn-gold), 0 10px 28px rgba(192, 148, 74, .18);
    }
    /* Na mobile znacznik w rogu karty (v1.9.21) chowamy - jest badge na zdjęciu. */
    .mzpn-candidate-card.is-checked::after { display: none; }
    .mzpn-candidate-card.is-checked .mzpn-candidate-check { display: flex; }

    /* Większe zdjęcie + wyśrodkowanie owijki; badge nieco większy. */
    .mzpn-candidate-figure {
        align-self: center;
        margin: 0 0 14px;
    }
    .mzpn-candidate-image {
        width: 118px;
        height: 118px;
        margin: 0;
    }
    .mzpn-candidate-check {
        top: -2px;
        right: -2px;
        width: 28px;
        height: 28px;
    }
    /* Złota obwódka zdjęcia wybranego kandydata. */
    .mzpn-candidate-card.is-checked .mzpn-candidate-image {
        border-color: var(--mzpn-gold);
    }

    .mzpn-candidate-name { font-size: 1.25rem; }
    .mzpn-candidate-bio  { font-size: .9rem; }

    /* Łańcuch flex: karta (o wysokości ustawionej przez JS) -> body -> content
       wypełniają wysokość, a rozpychacz (flex:1) między opisem a przyciskiem chłonie
       cały nadmiar. Dzięki temu nadmiar wysokości ląduje NAD przyciskiem (przycisk
       siedzi na dole), a nie pod nim. Zdjęcie ma stałą wysokość (nie rośnie). */
    .mzpn-candidate-figure { flex: 0 0 auto; }
    .mzpn-candidate-body { flex: 1 1 auto; }
    .mzpn-candidate-content { flex: 1 1 auto; }
    .mzpn-bio-spacer { flex: 1 1 auto; min-height: 0; }

    /* Hint przesuwania: strzałki + dłoń + tekst, wyśrodkowane. */
    .mzpn-carousel-hint {
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 10px;
        margin-top: 16px;
    }
}

@media (max-width: 480px) {
    /* Na wąskich telefonach karta jeszcze nieco szersza, mniejsze podglądy. */
    .mzpn-candidate-card {
        flex: 0 0 78%;
        padding: 20px 16px 18px;
    }
    .mzpn-candidate-grid::before,
    .mzpn-candidate-grid::after {
        flex: 0 0 16%;
    }
    .mzpn-candidate-image {
        width: 108px;
        height: 108px;
    }
}

/* =========================================================================
   v1.9.25 - przycinanie opisu do 2 linii + przycisk Rozwiń/Zwiń (mobile).
   Desktop bez zmian (pełny opis, brak przycinania).
   ========================================================================= */
.mzpn-bio-toggle { display: none; }

@media (max-width: 768px) {
    /* Stała wysokość = N wierszy (min = max): krótkie bio dopełnia się w środku do
       N linii, dłuższe jest przycięte do N. Dzięki temu karty mają zbliżoną
       wysokość BEZ podłogi na .mzpn-candidate-card - więc karta z pełnym opisem
       (Szumiec) jest "w sam raz", bez pustego dołu pod "Rozwiń". Rozwinięcie
       zdejmuje max-height (reguła .is-expanded niżej), min-height już nie ogranicza. */
    /* EKSPERYMENT: pełny opis na każdej karcie (bez przycięcia). Równe wysokości
       robi siatka (align-items:stretch) - krótsze karty dorównują do najwyższej,
       tak jak na desktopie. */
    .mzpn-candidate-bio {
        min-height: 0;
        max-height: none;
        overflow: visible;
    }
    .mzpn-candidate-bio::after {
        content: '';
        position: absolute;
        left: 0;
        right: 0;
        bottom: 0;
        height: 1.6em;
        background: linear-gradient(to bottom, rgba(22, 22, 28, 0) 0%, var(--mzpn-surface) 100%);
        pointer-events: none;
        opacity: 0;
        transition: opacity .15s ease;
    }
    /* Zanikanie tylko gdy tekst faktycznie przycięty i karta zwinięta. */
    .mzpn-candidate-card.is-truncated:not(.is-expanded) .mzpn-candidate-bio::after {
        opacity: 1;
    }
    /* Wybrana karta ma ciepłe złote tło -> gradient w cieplejszym ciemnym tonie. */
    .mzpn-candidate-card.is-checked .mzpn-candidate-bio::after {
        background: linear-gradient(to bottom, rgba(27, 24, 19, 0) 0%, #1b1813 100%);
    }
    /* Po rozwinięciu - pełny tekst, bez przycięcia i bez zanikania. */
    .mzpn-candidate-card.is-expanded .mzpn-candidate-bio {
        max-height: none;
        overflow: visible;
    }
    /* Przycisk "Rozwiń" jest w układzie, POD opisem (nie nachodzi na tekst). Rozpychacz
       (.mzpn-bio-spacer) wypycha go na sam dół karty, więc nadmiar miejsca ląduje NAD
       przyciskiem, nigdy pod nim. Wyrównanie wysokości kart robi JS (equalize). */
    .mzpn-bio-toggle {
        display: inline-flex;
        align-items: center;
        gap: 4px;
        margin: 0;
        color: var(--mzpn-primary);
        font-size: .82rem;
        font-weight: 700;
        cursor: pointer;
        -webkit-user-select: none;
        user-select: none;
    }
    .mzpn-bio-toggle[hidden] { display: none; }
    .mzpn-bio-toggle-text {
        display: grid;                 /* oba napisy w jednej komórce - nakładają się */
    }
    .mzpn-bio-toggle-label {
        grid-area: 1 / 1;              /* ten sam obszar = brak skoku szerokości przycisku */
        transition: opacity .15s ease;
    }
    .mzpn-bio-toggle-label--less { opacity: 0; }
    .mzpn-candidate-card.is-expanded .mzpn-bio-toggle-label--more { opacity: 0; }
    .mzpn-candidate-card.is-expanded .mzpn-bio-toggle-label--less { opacity: 1; }
    .mzpn-bio-toggle-icon {
        display: block;
        transition: transform .3s ease;
    }
    .mzpn-candidate-card.is-expanded .mzpn-bio-toggle-icon {
        transform: rotate(180deg);
    }
}

/* =========================================================================
   v1.9.31 - poszanowanie preferencji "reduce motion" (bez animacji wysokości).
   ========================================================================= */
@media (prefers-reduced-motion: reduce) {
    .mzpn-candidate-bio { transition: none; }
    .mzpn-candidate-bio::after { transition: none; }
    .mzpn-bio-toggle-label { transition: none; }
    .mzpn-bio-toggle-icon { transition: none; }
}

/* Nagłówek (imię + klub) - na desktopie przezroczysty (display:contents), żeby nie
   zmieniał układu pionowej karty. Na mobile (blok niżej) staje się centrującą ramką. */
.mzpn-candidate-heading { display: contents; }

/* =========================================================================
   WARIANT 2 - AKORDEON W LIŚCIE (mobile, max-width:768px)
   Pionowa lista zamiast karuzeli. Zdjęcie pływa w lewo, tekst opływa je z
   prawej i schodzi pod spód po rozwinięciu; chevron w prawym górnym rogu.
   Tap w chevron rozwija opis (akordeon: jedna karta otwarta naraz - logika
   w JS, doToggle), tap w pozostałą część karty = wybór kandydata. Opisy
   mieszczące się w 3 liniach nie dostają chevronu (check() w JS).
   Ten blok celowo NADPISUJE układ karuzeli (jest ostatni w pliku).
   ========================================================================= */
@media (max-width: 768px) {
    /* Lista pionowa - koniec poziomego scrolla, snapu i pełnoekranowego marginesu */
    .mzpn-candidate-grid {
        display: flex;
        flex-direction: column;
        align-items: stretch;
        flex-wrap: nowrap;
        gap: 12px;
        overflow-x: visible;
        scroll-snap-type: none;
        width: auto;
        margin-left: 0;
        padding: 0;
    }
    .mzpn-candidate-grid::before,
    .mzpn-candidate-grid::after { content: none; display: none; }

    /* Karta = media-object na całą szerokość, naturalna wysokość */
    .mzpn-candidate-card {
        display: block;
        position: relative;
        flex: 0 0 auto;
        width: auto;
        max-width: none;
        min-height: 0;
        scroll-snap-align: none;
        text-align: left;
        gap: 0;
        padding: 14px;
        border-radius: 14px;
    }

    /* Zdjęcie pływa w lewo - tekst je opływa (zwinięty obok, rozwinięty schodzi pod) */
    .mzpn-candidate-figure {
        float: left;
        align-self: auto;
        margin: 0 14px 6px 0;
    }
    .mzpn-candidate-image { width: 76px; height: 76px; margin: 0; }
    .mzpn-candidate-check { top: -2px; right: -2px; width: 24px; height: 24px; }

    /* Body/content jako bloki (nie flex), żeby tekst opływał float */
    .mzpn-candidate-body { display: block; width: auto; flex: 0 0 auto; }
    .mzpn-candidate-content { display: block; width: auto; flex: 0 0 auto; text-align: left; gap: 0; position: relative; }
    /* Nagłówek (imię+klub) obok zdjęcia, wyśrodkowany w pionie do wysokości zdjęcia.
       display:flex => sam siada OBOK floatu (nowy kontekst), min-height = zdjęcie. */
    .mzpn-candidate-heading {
        display: flex;
        flex-direction: column;
        justify-content: center;
        min-height: 76px;
    }
    .mzpn-candidate-name { display: block; font-size: 1.15rem; line-height: 1.25; }
    .mzpn-candidate-club { display: block; margin-top: 2px; }
    .mzpn-candidate-divider { display: none; }
    .mzpn-bio-spacer { display: none; }

    /* Opis pełną szerokością pod zdjęciem (clear), przycięty do 5 linii (max-height).
       Zamiast "…" - miękki FADE dolnej linii przez mask-image: jest NIEZALEŻNY od
       koloru tła karty (więc nic się nie podświetla na wybranej karcie) i nie zostawia
       ucinanych fragmentów słów. Tekst do lewej, bez auto-dzielenia wyrazów. */
    .mzpn-candidate-bio {
        display: block;
        clear: left;
        width: auto;
        margin-top: 8px;
        font-size: .9rem;
        line-height: 1.6;
        text-align: left;
        -webkit-hyphens: auto;
        hyphens: auto;
        -webkit-hyphenate-limit-before: 2;
        -webkit-hyphenate-limit-after: 2;
        hyphenate-limit-chars: 5 2 2;
        max-height: calc(5 * 1.6em);
        overflow: hidden;
        transition: max-height .3s ease;
    }
    .mzpn-candidate-card.is-expanded .mzpn-candidate-bio {
        max-height: none;
        overflow: visible;
    }
    /* Maska dwuwarstwowa: warstwa 1 = pełne krycie wszystkich linii oprócz ostatniej;
       warstwa 2 = TYLKO dolna linia (1.6em), gasnąca w prawo do przezroczystości -
       czyli wygaszamy końcówkę ostatniego słowa, a nie całą linię. Niezależne od tła. */
    .mzpn-candidate-card.is-truncated:not(.is-expanded) .mzpn-candidate-bio {
        -webkit-mask-image:
            linear-gradient(#000, #000),
            linear-gradient(to right, #000 calc(100% - 10em), transparent calc(100% - 4.5em));
        -webkit-mask-size: 100% calc(100% - 1.6em), 100% 1.6em;
        -webkit-mask-position: left top, left bottom;
        -webkit-mask-repeat: no-repeat, no-repeat;
        mask-image:
            linear-gradient(#000, #000),
            linear-gradient(to right, #000 calc(100% - 10em), transparent calc(100% - 4.5em));
        mask-size: 100% calc(100% - 1.6em), 100% 1.6em;
        mask-position: left top, left bottom;
        mask-repeat: no-repeat, no-repeat;
    }
    .mzpn-candidate-bio::after { content: none; }

    /* "więcej" W JEDNEJ LINII z końcem tekstu: absolutnie w prawym dolnym rogu opisu
       (kotwica = .mzpn-candidate-content). Tekst pod spodem wygasza maska wyżej. */
    .mzpn-bio-toggle {
        position: absolute;
        right: 0;
        bottom: 0;
        display: flex;
        align-items: center;
        gap: 4px;
        margin: 0;
        padding: 0;
        background: none;
        color: var(--mzpn-primary);
        font-size: .9rem;
        font-weight: 700;
        line-height: 1.6;
    }
    .mzpn-bio-toggle-text { display: grid; }
    .mzpn-bio-toggle-icon { width: 15px; height: 15px; }
    /* Po rozwinięciu nie ma wygaszania - "zwiń" wraca do układu, wyśrodkowane pod opisem */
    .mzpn-candidate-card.is-expanded .mzpn-bio-toggle {
        position: static;
        justify-content: center;
        width: 100%;
        margin-top: 8px;
    }

    /* Lista nie używa podpowiedzi/strzałek karuzeli */
    .mzpn-carousel-hint { display: none; }
}
