/* ── Import czcionki Manrope (opcjonalnie, jeśli nie ładuje się z motywu) ── */
@import url('https://fonts.googleapis.com/css2?family=Manrope:wght@300;400;500;600;700&display=swap');

/* ── Zmienne dopasowane w 100% do MUMIN Opinie ────────────────────────────── */
/* Paleta (2026-08): --primary-color był płaskim ciemnym szarym (#444752), potem na chwilę
   zastąpiony granatem/indygo (#33477e) dla całej strony (przyciski, linki, nagłówki, akcenty) -
   cofnięte na wyraźną prośbę: czcionka/tekst (nagłówki, linki, akcenty) wraca do czarno-szarego,
   TYLKO pasek nagłówka strony zostaje niebieski. Działa to bez osobnej zmiany .site-header,
   bo ten od początku używał osobnej zmiennej (--primary-color-dark), nie --primary-color - więc
   cofnięcie --primary-color nie dotyka paska nagłówka. --bg-subtle ujednolica trzy prawie
   identyczne, osobno dobrane szarości teł hover (#f4f5f6/#f2f3f5/#eeeeee) w jeden token.
   --danger-color ujednolica dwa różne czerwienie używane zamiennie dla tego samego znaczenia
   (błąd formularza vs. przycisk zgłoszenia). */
/* Płynne przejście MPA między stronami (Cross-Document View Transitions) - np. "Dodaj pierwszą
   opinię" z listy (patrz posts.ts/browser.ts) nawiguje wprost na profil, gdzie ?dodaj_opinie=1
   sam otwiera modal opinii (patrz post_detail.ts) - bez tego był to twardy "przeskok" (biały
   ekran między stronami, potem modal). Sama deklaracja wystarcza - wspierające przeglądarki dają
   domyślny cross-fade za darmo, bez JS; nieobsługujące po prostu ją ignorują i nawigują jak
   dotąd, więc to czysty progresywny dodatek, nie zmiana zachowania. */
@view-transition {
    navigation: auto;
}

@media (prefers-reduced-motion: reduce) {
    ::view-transition-group(*),
    ::view-transition-old(*),
    ::view-transition-new(*) {
        animation: none !important;
    }
}

:root {
    --primary-color:       #444752;  /* Ciemny szaro-antracytowy - przyciski, linki, nagłówki, akcenty */
    --primary-color-dark:  #1f2c54;  /* Granat - WYŁĄCZNIE pasek nagłówka strony (celowo nie pochodna --primary-color) */
    --primary-color-hover: #5c606d;  /* Jaśniejszy odcień szarości - hover na wypełnionych przyciskach */
    --text-color:    #404040;      /* Główny kolor tekstu wg --directorist-color-body */
    --text-muted:    #6c757d;      /* Drugoplanowy tekst (meta, placeholdery) - był rozrzuconym literałem */
    --bg-color:      #ffffff;      /* Tło strony */
    --bg-subtle:     #f2f4fa;      /* Delikatne tło hover/track, spójne z granatem zamiast czystej szarości */
    --border-color:  #cccccc;      /* Obramowanie wyszukiwarek/formularzy */
    --border-hover:  #999999;      /* Obramowanie po najechaniu na pola formularzy */
    --card-border:   #e9e9e9;      /* Delikatniejsze obramowanie dla kart komentarzy */
    --star-color:    #f28100;      /* Ostrzegawczy/pomarańczowy kolor z Directorist */
    --danger-color:  #c22e3a;      /* Błędy/zgłoszenia - ujednolicone (były dwa różne czerwienie); też słaba ocena (patrz .rating-tier-poor) */
    --danger-bg:     #fbeceb;      /* Tło hover przy akcjach niebezpiecznych (np. "Zgłoś") */
    --rating-good:   #2e7d4f;      /* Wysoka średnia ocena (patrz ratingTierClass w posts.ts) - jedyny zielony akcent na stronie */
    --font-main:     'Manrope', sans-serif;
    --spacing-sm:    0.5rem;
    --spacing-md:    1rem;
    --spacing-lg:    2rem;
}

/* ── Reset i podstawa ─────────────────────────────────────────────────────── */
*, *::before, *::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

html {
    /* Zabezpieczenie na wypadek, gdyby coś (długi nieprzełamany tekst, mocno wypełniony
       .compare-bar na wąskim ekranie itp.) mimo wszystko wystawało poza szerokość ekranu -
       bez tego takie przepełnienie dawałoby poziomy scrollbar całej strony na telefonie.
       CELOWO tylko na <html>, NIE na <body>: gdy oba mają overflow-x inny niż "visible",
       przeglądarka na KAŻDYM z nich osobno wymusza też overflow-y:auto (tego się nie da
       uniknąć nawet jawnym overflow-y:visible - tak działa specyfikacja) - <body> stawałoby
       się wtedy własnym, niezależnym kontenerem przewijania i PRZYCINAŁO wszystko, co z niego
       wystaje (np. rozwijaną listę podpowiedzi wyszukiwania - patrz .search-suggestions),
       zamiast pozwolić temu normalnie "wystawać" nad resztą strony. */
    overflow-x: hidden;
}

body {
    font-family: var(--font-main);
    color: var(--text-color);
    background-color: var(--bg-color);
    font-size: 16px;
    line-height: 1.6;
    max-width: 900px;
    margin: 0 auto;
    padding: var(--spacing-md);
    /* "anywhere" (nie "break-word") - liczy się też przy wyliczaniu min-content w flexboksach,
       więc długi nieprzełamany ciąg (link, nazwisko bez spacji) w komentarzu/nagłówku faktycznie
       się łamie zamiast rozpychać kartę/wiersz poza ekran na wąskim telefonie. */
    overflow-wrap: anywhere;
}

/* Delikatne powiększenie CAŁEJ strony - ale TYLKO na urządzeniach z myszką (pointer: fine).
   Wcześniej to samo osiągał "zoom: 120%" bez tego warunku, uzależniony jedynie od szerokości
   ekranu (@media max-width: 640px wyłączał go z powrotem) - telefon obrócony poziomo albo
   duży tablet ma szerokość CSS > 640px (np. iPhone w poziomie ~844px), więc zoom wracał i
   strona znów wyglądała na "powiększoną"/przybliżoną, a nagłówek się rozjeżdżał. pointer:fine
   jest true tylko dla myszy/trackpada - telefony i tablety (w KAŻDEJ orientacji) mają
   pointer:coarse i nigdy go nie dostają. */
@media (min-width: 641px) and (pointer: fine) {
    body {
        zoom: 110%;
        font-size: 17px;
    }
}

h1, h2, h3 {
    color: var(--primary-color);
    margin-top: var(--spacing-md);
    font-weight: 700;
}

h1 { 
    font-size: 2.5rem;
    margin-top: 0px; /* Zmniejsza odstęp nad imieniem i nazwiskiem do zera */
 }
h2 { font-size: 2rem; }
h3 { font-size: 1.5rem; }

/* ── Nagłówek widoku wykładowcy w stylu RMP: ciemny pasek na pełną szerokość,
   przyklejony do góry (nie chowa się przy scrollowaniu) ─────────────────── */
.site-header {
    /* Rozciąga się do krawędzi kontenera strony (nie do krawędzi przeglądarki przez vw) -
       ze "zoom" na body (patrz reset wyżej) przeliczenia oparte o vw/50vw rozjeżdżały się i
       przesuwały cały pasek w bok. Ujemny margines o wielkości paddingu body jest bezpieczny,
       bo nie zależy od jednostek viewportu. */
    position: sticky;
    top: 0;
    z-index: 50;
    margin: 0 calc(-1 * var(--spacing-md)) var(--spacing-md) calc(-1 * var(--spacing-md));
    display: flex;
    align-items: center;
    gap: var(--spacing-md);
    background-color: var(--primary-color-dark);
    padding: 12px var(--spacing-md);
}

/* Przycisk "wstecz", tuż przed logiem - ten sam wygląd/rozmiar co .site-menu-toggle po
   przeciwnej stronie paska, dla symetrii. Ikona to SVG (nie znak "←" z fontu) - glif tekstowy
   siedzi w swoim polu znaku inaczej w zależności od fontu systemowego (inny na Linuksie, Windows,
   macOS), więc każdy pikselowy "top: -Npx" dopasowany na jednej maszynie rozjeżdżał się na innej.
   SVG renderuje się identycznie wszędzie, więc zwykłe flexowe wyśrodkowanie wystarcza - bez
   dodatkowego "top" na svg (dawna wersja miała stały -1px skalibrowany pod stare, wersalikowe
   logo "MUMIN"; "MójProf" ma "j" z ogonkiem, więc ten hack przesuwał strzałkę w złą stronę). */
.site-back-btn {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: none;
    border: none;
    color: #ffffff;
    cursor: pointer;
    width: 26px;
    padding: 4px 0;
    border-radius: 6px;
}

.site-back-btn:hover {
    background-color: rgba(255, 255, 255, 0.14);
}

/* Na stronie głównej nie ma dokąd wracać, więc zamiast strzałki jest pusty placeholder - ikonka
   z dawnej wersji przeniosła się na stałe do samego loga (.site-header-logo-mark) zamiast pojawiać
   się tylko tutaj. Sama szerokość co .site-back-btn (26px), żeby "MójProf" nie przeskakiwał w
   poziomie przy przechodzeniu między stroną główną a podstronami. */
.site-header-mark {
    flex-shrink: 0;
    width: 26px;
}

.site-header-logo {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    gap: 6px;
    color: #ffffff;
    font-weight: 800;
    font-size: 1.15rem;
    letter-spacing: 0.03em;
    text-decoration: none;
}

.site-header-logo:hover {
    opacity: 0.85;
}

.site-header-logo-mark {
    flex-shrink: 0;
}

/* Akcent koloru gwiazdek/ocen (ten sam --star-color co reszta serwisu) na części wordmarku -
   bez tego samo pogrubione białe "MójProf" nie różniło się niczym od dowolnego innego napisu
   w nagłówku, więc nie czytało się jak logo. */
.site-header-logo-accent {
    color: var(--star-color);
}

.site-header-search {
    flex: 1 1 auto;
    max-width: 380px;
    min-width: 0; /* pozwala się skurczyć obok loga zamiast wypychać nagłówek poza ekran */
}

.site-header-search #search-input {
    width: 100%;
    max-width: none;
    height: 30px;
    padding-top: 0;
    padding-bottom: 0;
    background-color: #f1f1f1;
    border: none;
    box-shadow: none;
}

/* Linki nawigacyjne (FAQ/Kontakt/Regulamin) - część .site-header zamiast osobnego, gołego
   wiersza tekstu nad treścią (patrz base.html) - dzięki temu widoczne na KAŻDEJ stronie, także
   tych, które nadpisują {% block header %} (np. post_detail.html), bo te nadpisania rozszerzają
   teraz tylko {% block header_search %}. Schowane za jednym przyciskiem-hamburgerem zamiast
   stałego rzędu linków - ten sam panel (bez osobnej wersji mobile) działa identycznie na każdej
   szerokości ekranu, patrz siteHeaderMenu.ts. margin-left:auto dosuwa przycisk do prawej
   krawędzi paska, obok loga (i ew. wyszukiwarki pomiędzy). */
.site-header-menu {
    position: relative;
    margin-left: auto;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    gap: 0.35rem;
}

/* Link "Przedmioty" - widoczny tylko w widoku MIMUW (patrz mimuw_subjects_link w
   context_processors.py), tuż przed hamburgerem. Ten sam wygląd/hover co .site-menu-toggle
   obok, żeby czytał się jako część tego samego paska akcji nagłówka, nie osobny element. */
/* Tło WIDOCZNE OD RAZU (nie tylko na hover jak dawniej) - na wyraźną prośbę, żeby linki
   przełączające między Prowadzący/Przedmioty/Koła naukowe (wpia_nav_link/mimuw_nav_link w
   context_processors.py) czytały się jako osobne, klikalne przyciski w nagłówku, nie zwykłe
   podpisy obok logo. Wypełnienie --star-color (ten sam pomarańcz co akcent w logu/gwiazdki oceny)
   zamiast przezroczystej bieli - na granatowym tle paska ta pierwsza ledwo było widać (zbyt
   zbliżony odcień), pomarańcz kontrastuje wyraźnie i czyta się jak realny przycisk, nie
   podświetlenie. line-height:1 (nie odziedziczone z body) - wyrównuje wysokość pigułki z
   .site-menu-toggle obok (ten też ma line-height:1), inaczej różne wysokości linii dawały
   niedopasowane o kilka pikseli obwódki mimo wspólnego align-items:center na rodzicu. */
.site-header-subjects-link {
    color: var(--primary-color-dark);
    font-size: 0.92rem;
    font-weight: 700;
    line-height: 1;
    text-decoration: none;
    white-space: nowrap;
    padding: 7px 12px;
    border-radius: 999px;
    background-color: var(--star-color);
}

.site-header-subjects-link:hover {
    background-color: #ffffff;
}

.site-menu-toggle {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    background: none;
    border: none;
    color: #ffffff;
    font-size: 1.4rem;
    line-height: 1;
    cursor: pointer;
    padding: 4px 8px;
    border-radius: 6px;
}

.site-menu-toggle:hover,
.site-menu-toggle[aria-expanded="true"] {
    background-color: rgba(255, 255, 255, 0.14);
}

.site-menu-panel {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    z-index: 60;
    display: none;
    flex-direction: column;
    min-width: 220px;
    background-color: var(--bg-color);
    border: 1px solid var(--card-border);
    border-radius: 10px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
    padding: 6px;
}

.site-menu-panel.open {
    display: flex;
}

.site-menu-panel a {
    color: var(--text-color);
    text-decoration: none;
    padding: 10px 12px;
    border-radius: 6px;
    font-size: 0.9rem;
    font-weight: 500;
    white-space: nowrap;
}

.site-menu-panel a:hover {
    background-color: var(--bg-subtle);
}

.site-menu-divider {
    border: none;
    border-top: 1px solid var(--card-border);
    margin: 6px 4px;
}

/* Ten sam wygląd co .site-menu-panel a wyżej - button zamiast <a>, bo to akcja (otwiera baner
   zgody ponownie), nie nawigacja do osobnej strony. */
.site-menu-cookie-btn {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    background: none;
    border: none;
    color: var(--text-color);
    text-decoration: none;
    padding: 10px 12px;
    border-radius: 6px;
    font-size: 0.9rem;
    font-weight: 500;
    font-family: inherit;
    white-space: nowrap;
    text-align: left;
    cursor: pointer;
}

.site-menu-cookie-btn:hover {
    background-color: var(--bg-subtle);
}

a {
    color: var(--primary-color);
    text-decoration: underline;
    transition: opacity 0.2s ease;
}

a:hover {
    text-decoration: none;
    opacity: 0.8;
}

p {
    padding-left: 5px;
}

ul {
    padding-left: 1.5rem;
}

.error { 
    color: var(--danger-color);                /* Zmienna --directorist-color-danger */
    font-size: 0.85em; 
    display: block;
    margin-bottom: 5px;
}

/* ── Odstępy ──────────────────────────────────────────────────────────────── */
#header-rating {
    margin-bottom: var(--spacing-md); 
}

#comment-form {
    margin-top: 0px; /* Zmniejszono odstęp nad polem komentarza */
}

#status-bar {
    font-size: 0.9rem;
    color: var(--text-muted);                /* --directorist-color-placeholder */
    margin-bottom: var(--spacing-md);
}

/* Podpowiedź pod (koniec) listą wykładowców - patrz browser.ts. Wyśrodkowana i stonowana,
   podobnie jak .search-suggestion-hint, ale trochę większa/z paddingiem pionowym - przy pustej
   liście to JEDYNA treść na stronie, więc musi się dać zauważyć, nie tylko "być obecna". */
.browse-search-hint {
    text-align: center;
    color: var(--text-muted);
    font-size: 0.95rem;
    padding: var(--spacing-lg) var(--spacing-md);
}

/* ── Sortowanie: ikona + rozwijana lista opcji (patrz renderSortMenu w generics.ts) ────────
   Zamiast stałego "Sortuj według: [select]" - opcje schowane pod ikoną, żeby nie zajmowały
   miejsca/uwagi, dopóki użytkownik faktycznie nie chce zmienić sortowania. ── */
.sort-menu {
    position: relative;
    flex-shrink: 0;
}

/* Dosuwa ikonę do prawej krawędzi wiersza (.controls / .lecturer-header-row są flex row bez
   justify-content:space-between) - margin-left:auto na FLEX ITEMIE zjada całą wolną przestrzeń
   przed nim. Musi być na #sort-menu-container (to on jest bezpośrednim dzieckiem tych flex
   kontenerów w HTML), NIE na .sort-menu (to dopiero element w środku, dorzucany przez JS -
   margines na nim nie miałby żadnego wolnego miejsca w rodzicu, do którego mógłby się rozciągnąć). */
#sort-menu-container {
    margin-left: auto;
}

.sort-menu-toggle {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    background-color: #ffffff;
    color: var(--text-color);
    cursor: pointer;
    transition: border-color 0.2s ease, background-color 0.2s ease, color 0.2s ease;
}

.sort-menu-toggle:hover {
    border-color: var(--border-hover);
}

.sort-menu-toggle:focus {
    outline: none;
}

.sort-menu-toggle:focus-visible {
    outline: 2px solid var(--primary-color);
    outline-offset: 2px;
}

.sort-menu-toggle[aria-expanded="true"] {
    background-color: var(--primary-color);
    border-color: var(--primary-color);
    color: #ffffff;
}

/* Wariant z widocznym napisem "Sortuj" obok strzałek (patrz renderSortMenu w generics.ts,
   toggleLabelText) - używany tylko na widoku wykładowcy, gdzie sama ikona ginęła. Rośnie w
   szerokość zamiast zostać kwadratem (width:auto nadpisuje sztywne 38px wyżej), pozycja rzędu
   bez zmian - #sort-menu-container nadal dosuwa go do prawej krawędzi (patrz niżej). */
.sort-menu-toggle--labeled {
    width: auto;
    padding: 0 12px;
    gap: 6px;
    font-family: inherit;
    font-size: 0.85rem;
    font-weight: 600;
}

.sort-menu-dropdown {
    display: none;
    position: absolute;
    top: 100%;
    right: 0;
    margin-top: 4px;
    background-color: var(--bg-color);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
    min-width: 200px;
    overflow: hidden auto;
    max-height: min(340px, 60vh);
    z-index: 20;
}

.sort-menu-dropdown.open {
    display: block;
}

.sort-menu-option {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    display: block;
    width: 100%;
    padding: 10px 14px;
    border: none;
    background: none;
    color: var(--text-color);
    text-align: left;
    font-family: inherit;
    font-size: 0.9rem;
    cursor: pointer;
    border-bottom: 1px solid var(--card-border);
}

.sort-menu-option:last-child {
    border-bottom: none;
}

.sort-menu-option:hover {
    background-color: var(--bg-subtle);
}

.sort-menu-option.active {
    color: var(--primary-color);
    font-weight: 600;
}

/* Znacznik ✓ przed aktywną opcją - :before zamiast tekstu w JS, żeby nie przesuwał etykiety
   przy każdej zmianie sortowania (zajmuje miejsce zawsze, tylko czasem jest niewidoczny). */
.sort-menu-option::before {
    content: "✓";
    display: inline-block;
    width: 1.1em;
    color: var(--primary-color);
    visibility: hidden;
}

.sort-menu-option.active::before {
    visibility: visible;
}

/* Filtr "Grupy przedmiotów" (katalog przedmiotów) - dzieli komponent z "Sortuj", ale nazwy grup
   USOS bywają dużo dłuższe niż zwykłe opcje sortowania - szerszy panel, żeby tekst zajmował
   mniej linii w pionie (na wyraźną prośbę). */
.category-filter-menu .sort-menu-dropdown {
    min-width: 340px;
    max-width: min(90vw, 440px);
}

/* Sekcja "Semestr" DOKŁADANA do panelu "Sortuj" (patrz appendSemesterSection w
   subjectBrowser.ts) - na wyraźną prośbę, żeby nie zajmować osobnego miejsca w pasku kontrolek
   obok wyszukiwarki. Przyciski (nie sort-menu-option) - to filtr, nie kolejna opcja sortowania,
   więc celowo inny kształt (rząd małych pigułek), żeby nie sugerować, że to ta sama lista. */
.sort-menu-divider {
    border: none;
    border-top: 1px solid var(--card-border);
    margin: 4px 0;
}

.sort-menu-section-label {
    padding: 6px 14px 2px;
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--text-muted);
}

.sort-menu-semester-row {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
    padding: 4px 14px 10px;
}

.sort-menu-semester-btn {
    -webkit-appearance: none;
    appearance: none;
    cursor: pointer;
    font-size: 0.8rem;
    padding: 4px 10px;
    border-radius: 999px;
    border: 1px solid var(--border-color);
    background-color: #ffffff;
    color: var(--text-color);
}

.sort-menu-semester-btn.active {
    background-color: var(--primary-color);
    border-color: var(--primary-color);
    color: #ffffff;
}

/* ── Lista komentarzy (Pojedyncza karta) ──────────────────────────────────── */
#comment-list article,
.comment {
    border: 1px solid var(--card-border);
    border-radius: 8px;
    padding: 10px var(--spacing-md) var(--spacing-md) var(--spacing-md);
    margin-bottom: var(--spacing-md);
    background-color: var(--bg-color);
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.04);
}

#comment-list article:last-child,
.comment:last-child {
    margin-bottom: 0;
}

/* ── Formularz komentarzy ─────────────────────────────────────────────────── */
/* .comment-form-box - ten sam wygląd dla głównego formularza (#comment-form ma tę klasę w HTML)
   i formularzy "+" otwieranych przy nagłówkach przedmiotów (.comment-group-quick-form).
   Celowo BEZ ID w selektorach - #comment-form już ma tę klasę, a granie o specyficzność
   z regułami opartymi o ID (silniejszymi niż zwykła klasa) parokrotnie psuło tu layout. */
.comment-form-box {
    background-color: var(--bg-color);
    padding: 8px var(--spacing-md); /* Symetryczny odstęp góra/dół - patrz margin-top/-bottom: 0
        na przycisku w .comment-form-bottom-row, który wcześniej dokładał się do tego paddingu */
    border: 1px solid var(--border-color);
    border-radius: 8px;
    margin-bottom: var(--spacing-md); /* Odstęp między formularzem a pierwszym komentarzem */
    transition: padding 0.3s ease, border-color 0.3s ease, margin-bottom 0.3s ease;
}

/* Gdy CAŁA zawartość formularza jest już schowana (pola od razu, komunikat po 5s - patrz
   comments.ts), obramowanie/padding tego kontenera muszą zniknąć razem z nią - inaczej zostaje
   pusta "ramka" bez treści w środku. */
.comment-form-box.comment-form-collapsed {
    padding-top: 0;
    padding-bottom: 0;
    padding-left: 0;
    padding-right: 0;
    border-color: transparent;
    margin-bottom: 0;
}

/* :not(.notify-email-field) - ten widżet (patrz renderNotifyEmailField w generics.ts) jest też
   <label>, ale ma WŁASNY układ kolumnowy (patrz .notify-email-field niżej) - bez tego wyłączenia
   "display: block" stąd wygrywało z ".notify-email-field" (ta sama specyficzność: klasa+typ vs
   1 klasa), psując wyrównanie etykiety/pola/przycisków tego widżetu. Wyłączenie U ŹRÓDŁA
   (zamiast walki o specyficzność w drugą stronę) gwarantuje efekt niezależnie od kolejności reguł
   w pliku. */
.comment-form-box label:not(.notify-email-field) {
    display: block;
    margin-bottom: var(--spacing-md); /* Odstęp do pola poniżej */
}

/* Etykieta OBOK pola (nie nad nim) - "Przedmiot: [input]".
   Specyficzność musi pobić ".comment-form-box label" (klasa+typ), więc dublujemy .comment-form-box
   tutaj - inaczej "display: block" stamtąd wygrywa i etykieta wraca nad pole zamiast obok. */
.comment-form-box .subject-picker {
    display: flex;
    align-items: center;
    gap: 8px;
}

.field-label-text {
    flex-shrink: 0;
    font-weight: 600;
    font-size: 0.95rem;
    color: var(--text-color);
    white-space: nowrap;
}

/* "(opcjonalnie)" po głównym tekście etykiety (patrz labelOptional w renderSubjectPicker) -
   mniejsza, niepogrubiona, przygaszona - dopowiedzenie, nie część głównego pytania, więc nie
   powinno z nim wizualnie konkurować o uwagę. */
.field-label-optional {
    font-size: 0.8rem;
    font-weight: 400;
    color: var(--text-muted);
}

/* Etykieta NAD polem komentarza (patrz bodyLabel w comments.ts) - w odróżnieniu od
   .field-label-text OBOK pola (Ocena:/Przedmiot:), ta musi się dać zawinąć na wąskich ekranach
   i chcemy pod nią normalny odstęp do textarea (stąd display: block + margin, zamiast domyślnego
   inline .field-label-text). */
.comment-body-label {
    display: block;
    white-space: normal;
    /* 8px - to samo co .add-review-dialog .comment-form-row .field-label-text niżej (Ocena:/
       Przedmiot:) - był tu 6px, niespójne z resztą etykieta-nad-polem w modalu i jedno ze źródeł
       "losowych" odstępów (zgłoszenie). */
    margin-bottom: 8px;
}

/* Wiersz "gwiazdki" + "przedmiot" obok siebie, w jednej linii. Etykiety są teraz obok
   swoich pól (nie nad nimi), więc obie kolumny mają zbliżoną wysokość - wyśrodkowujemy. */
.comment-form-row {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    /* 11px (nie var(--spacing-md), 16px) - celowo TAKI SAM jak gap w .comment-form-bottom-row
       niżej, żeby odstęp między wierszem gwiazdek/przedmiotu a wierszem "wybrałbyś ponownie"/
       przyciskiem wysyłki (gdy oba wiersze się zawiną, np. na telefonie) był symetryczny. */
    gap: 11px;
    margin-bottom: 9px;
}

.comment-form-row > label {
    margin-bottom: 0;
}

.comment-form-row .subject-picker {
    flex: 1 1 240px;
    max-width: 420px; /* żeby nie "rozpychało" wiersza */
    min-width: 0; /* pozwala się skurczyć przy zawijaniu na wąskich ekranach */
}

.comment-form-row .rating-field {
    flex: 0 0 auto;
    margin-left: 1px;
}

/* Odstęp WEWNĄTRZ .rating-field - dopóki mieściła tylko "Ocena:" + gwiazdki, brak jawnego gap
   nie było widać (dwa elementy, przypadkowa spacja tekstowa między nimi wystarczała). Odkąd
   dokłada się tu też "Łatwość zaliczenia:" + druga ikonka (patrz initCommentForm w comments.ts),
   gwiazdki i pytanie o łatwość stykały się bez odstępu (zgłoszenie) - jawny flex+gap na całym
   polu naprawia to niezależnie od tego, ile par etykieta+widget akurat w nim jest. */
.rating-field {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
}

/* Dropdown roku akademickiego (patrz renderYearPicker w subjectComments.ts) - haczyk TYLKO do
   stylowania samego <select> (patrz .academic-year-select niżej); layout pola (rozmiar,
   wyrównanie, odstęp od etykiety) w całości dziedziczy z klasy "rating-field" (patrz JS) - ten
   sam kształt co "Ocena:", żeby wyglądało identycznie jak u wykładowców. */
.academic-year-select {
    min-width: 0;
    /* Kompaktowe - zbliżone wysokością do gwiazdek obok "Ocena:", nie pełnowymiarowe pole
       formularza (bazowe .styled-select ma 10px/36px/10px/12px, za wysokie obok krótkiej
       etykiety w jednej linii). */
    padding: 3px 22px 3px 7px;
    font-size: 0.82rem;
    background-size: 12px;
    background-position: right 7px center;
}

.comment-form-row .comment-form-context-field {
    flex: 0 0 auto;
}

/* Dolny wiersz formularza - "Wybrałbyś ponownie?" po lewej (gdy włączone - patrz
   WOULD_TAKE_AGAIN_ENABLED), przycisk wysyłki zawsze po prawej (margin-left: auto na przycisku,
   nie justify-content na kontenerze - dzięki temu przycisk trzyma się prawej krawędzi także wtedy,
   gdy pole "Wybrałbyś ponownie?" jest schowane i wiersz ma tylko ten jeden element). */
.comment-form-bottom-row {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    /* 11px - patrz notka przy .comment-form-row wyżej (symetria między oboma wierszami). */
    gap: 11px;
}

.comment-form-bottom-row .would-take-again-field {
    flex: 0 0 auto;
    margin-left: 3px;
}

/* Specyficzność musi pobić ".comment-form-box button:not(...)" niżej (obecnie 5 wykluczeń
   przez :not() - PILNUJ, żeby tu było ich tyle samo lub więcej, inaczej to zerowanie po cichu
   przegrywa mimo kolejności w pliku, tak jak przy ".comment-form-box .subject-picker" wyżej -
   dokładnie to się stało, gdy tamta reguła urosła z 3 do 5 wykluczeń, a ta tu została przy 3:
   margin-top: var(--spacing-sm) (8px) z tamtej reguły znowu wygrywał, dokładając się do
   16px odstępu z .comment-form-bottom-row (gap) i dając 24px zamiast 16px nad przyciskiem
   "Podziel się opinią". Bez tego zerowania margines przycisku niepotrzebnie dokładałby się też
   do paddingu .comment-form-box i odstępu od bodyError nad nim (patrz zgłoszenie: za duży
   odstęp między textarea a dolną krawędzią formularza). */
.comment-form-box .comment-form-bottom-row button:not(.star):not(.search-suggestion-item):not(.would-take-again-btn):not(.difficulty-btn):not(.notify-email-followup-dismiss):not(.notify-email-followup-link):not(.comment-form-btn-light) {
    margin-left: auto;
    margin-top: 0;
    margin-bottom: 0;
}

/* ── Opcjonalny e-mail do powiadomienia o decyzji moderacyjnej (patrz renderNotifyEmailField
   w generics.ts) - kolumnowo (etykieta nad polem), nie w rzędzie jak .lecturer-field, żeby
   dobrze wyglądało w widżecie "zostaw e-mail" pod formularzem (patrz .notify-email-followup
   niżej). ── */
.notify-email-field {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin: 6px 0;
}

/* .field-label-text jest globalnie white-space: nowrap i font-weight: 600 (dobre dla krótkich
   etykiet OBOK pola, np. "Wydział:") - tu etykieta to całe zdanie NAD polem, więc musi się móc
   zawinąć (inaczej w węższych kontenerach ucina się poza widoczną szerokość) i nie powinna być
   pogrubiona (to instrukcja/podpowiedź, nie etykieta pola formularza). */
.notify-email-field .field-label-text {
    white-space: normal;
    font-weight: 400;
}

.notify-email-field input[type="email"] {
    padding: 8px 10px;
    border: 1px solid var(--border-color);
    border-radius: 6px;
    font-family: inherit;
    font-size: 0.9rem;
    color: var(--text-color);
    background-color: #ffffff;
}

/* ── "Wybrał(a)byś ponownie?" - Tak/Nie obok przycisku wysyłki w formularzu opinii (patrz
   .comment-form-bottom-row wyżej) ─────────────────────────────────────────────────────── */
.would-take-again-field {
    display: flex;
    align-items: center;
    gap: 8px;
}

/* .field-label-text jest globalnie white-space: nowrap ORAZ flex-shrink: 0 (dobre dla krótkich
   etykiet typu "Ocena:" - patrz notka przy .notify-email-field .field-label-text wyżej, ten sam
   powód co do white-space) - etykieta egzaminu "Czy poleciłbyś/poleciłabyś ten egzamin
   ponownie?" (patrz examWouldTakeAgainField w comments.ts) jest całym zdaniem. Samo
   white-space:normal nie wystarcza - flex-shrink:0 nie pozwala fleksowemu elementowi się
   zwęzić, więc mimo dopuszczonego zawijania przeglądarka i tak liczy jego "wolałbym" (hypothetical)
   szerokość jako całą linijkę tekstu i wystawia ją poza widoczną szerokość ekranu na telefonie -
   stąd zerowanie też flex-shrink tutaj (zgłoszenie: "dziwny zoom" po kliknięciu "Oceń od razu
   egzamin" w momencie odsłonięcia sekcji egzaminu - w rzeczywistości wystająca, niezawinięta
   etykieta, nie faktyczny zoom przeglądarki). Krótsza etykieta zajęć ("Czy polecił(a)byś
   innym?") i tak mieści się w jednej linii, więc reguła jej nie zmienia wizualnie. */
.would-take-again-field .field-label-text {
    white-space: normal;
    flex-shrink: 1;
    min-width: 0;
}

.would-take-again-buttons {
    display: flex;
    gap: 6px;
}

.would-take-again-btn {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    border: 1px solid var(--border-color);
    border-radius: 999px;
    background-color: transparent;
    color: var(--text-color);
    padding: 6px 14px;
    font-family: inherit;
    font-size: 0.85rem;
    font-weight: 400;
    cursor: pointer;
    transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease;
}

.would-take-again-btn:hover {
    border-color: var(--primary-color);
}

.would-take-again-btn.active {
    background-color: var(--primary-color);
    border-color: var(--primary-color);
    color: #ffffff;
}

/* ── Odznaka "N% wybrałoby ponownie" obok gwiazdek (lista, detail, porównanie) ────────── */
.would-take-again-badge {
    display: inline-block;
    margin-left: 8px;
    font-size: 0.85rem;
    color: var(--text-color);
    opacity: 0.8;
    white-space: nowrap;
}

.rating-summary-would-take-again {
    margin-left: 0;
    margin-top: 2px;
}

/* Odznaka jest w karcie porównania na osobnej linijce (patrz compareView.ts renderCard) -
   margin-left:8px z wersji "obok gwiazdek" tylko przesuwałby ją niepotrzebnie w prawo. */
.compare-card .would-take-again-badge {
    margin-left: 0;
}

/* Trudność zajęć/egzaminu (Comment.class_difficulty/exam_difficulty, Post.avg_class_difficulty/
   avg_exam_difficulty) - RMP-style zwykły tekst, na wyraźną prośbę bez gwiazdek/płomyków (patrz
   renderDifficultyText w generics.ts) - ten sam wygląd co .would-take-again-badge obok, żeby nie
   mnożyć stylów drobnych odznak w nagłówku opinii/podsumowania.
 */
.difficulty-text-badge {
    display: inline-block;
    margin-left: 8px;
    font-size: 0.85rem;
    color: var(--text-color);
    opacity: 0.8;
    white-space: nowrap;
}

.rating-summary-difficulty {
    margin-left: 0;
    margin-top: 2px;
}

.compare-card .difficulty-text-badge {
    margin-left: 0;
}

/* Wariant "sama ikonka" (renderEaseOfPassingIcon) - w komórce siatki .teacher-plain-list odstęp
   robi już column-gap tej siatki, margin-left:8px z wersji tekstowej tylko dokładałby zbędną
   przerwę; trochę większy/pełny kolor niż przygaszony tekst z liczbą - sama ikona bez liczby obok
   musi być bardziej "widoczna", żeby zachęcić do najechania/dotknięcia po wyjaśnienie w dymku. */
.difficulty-icon-only {
    margin-left: 0;
    font-size: 1.1rem;
    opacity: 1;
}

/* Dymek z wyjaśnieniem (patrz attachTapTooltip w generics.ts) - .tap-tooltip-target dostaje
   position:relative (punkt odniesienia dla dymka) i cursor:help (sygnalizuje "tu jest coś do
   wyjaśnienia" na desktopie, obok natywnego title). Dymek pokazuje się PRZEZ CSS :hover (mysz) i
   PRZEZ klasę .visible dokładaną z JS po kliknięciu/dotknięciu (telefon) - stąd dwa selektory. */
.tap-tooltip-target {
    position: relative;
    cursor: help;
}

.tap-tooltip-bubble {
    position: absolute;
    bottom: calc(100% + 6px);
    left: 50%;
    transform: translateX(-50%);
    background: var(--text-color);
    color: var(--bg-color);
    padding: 4px 9px;
    border-radius: 6px;
    font-size: 0.75rem;
    font-weight: 500;
    line-height: 1.3;
    white-space: normal;
    width: max-content;
    max-width: 220px;
    text-align: center;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.15s ease;
    z-index: 20;
}

.tap-tooltip-target:hover .tap-tooltip-bubble,
.tap-tooltip-bubble.visible {
    opacity: 1;
}

.comment-form-box input[type="text"],
.comment-form-box input[type="email"],
.comment-form-box textarea {
    display: block;
    width: 100%;
    padding: 10px 12px;
    margin-bottom: 0px; /* Zmniejszono odstęp pod textarea */
    border: 1px solid var(--border-color);
    border-radius: 8px;
    font-family: inherit;
    font-weight: 400;
    font-size: 1rem;
    color: var(--text-color);
    background-color: #ffffff;
    transition: border-color 0.2s ease;
}

/* Formularz kontaktowy (patrz contact.html/contact.ts) - jedyne miejsce, gdzie .comment-form-box
   ma zwykły <select>, więc dokładamy odstęp pod nim (input/textarea mają margin-bottom:0 wyżej,
   bo tam odstęp daje label kolejnego pola, ale select nie ma nic pod sobą oprócz drugiego pola). */
.comment-form-box select.styled-select {
    margin-bottom: var(--spacing-md);
}

/* Formularz kontaktowy ma krótkie, jednowierszowe etykiety (nie pytania jak w formularzu
   komentarza) - pełny odstęp .comment-form-box label wyżej (spacing-md) wizualnie odrywał
   etykietę od pola pod nią bardziej niż potrzeba. Specyficzność ID+typ bije klasa+typ+:not()
   z reguły ogólnej, więc nie trzeba tam nic wyłączać. */
#contact-form label {
    margin-bottom: var(--spacing-sm);
}

/* Pole przedmiotu jest w wierszu obok etykiety (patrz .subject-picker wyżej), więc zamiast
   pełnej szerokości ma po prostu wypełnić to, co zostało obok tekstu etykiety */
.comment-form-box .subject-picker input[type="text"] {
    width: auto;
    flex: 1 1 auto;
    min-width: 0;
    /* Strzałka w tle (ta sama co .styled-select) sygnalizuje "to jest lista do wyboru", nie
       tylko pole do wpisywania - kliknięcie od razu pokazuje wszystkie opcje (patrz
       renderSubjectPicker w comments.ts), więc wpisywanie jest opcjonalne, nie konieczne. */
    padding-right: 32px;
    background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23404040' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e");
    background-repeat: no-repeat;
    background-position: right 10px center;
    background-size: 16px;
}

.comment-form-box input[type="text"]:focus,
.comment-form-box input[type="email"]:focus,
.comment-form-box textarea:focus {
    outline: none;
    border-color: var(--primary-color);
}

.comment-form-box textarea {
    resize: vertical;
    /* Domyślne overflow przeglądarki dla textarea to "auto" na obu osiach - na macOS potrafi to
       (razem z pionowym scrollbarem, gdy treść jest wyższa niż pole) wywołać też poziomy
       scrollbar, mimo że tekst się zawija i nigdy nie powinien przewijać w bok. */
    overflow-x: hidden;
    min-height: 90px;
}

/* Safari (macOS/iOS) ma znany, długoletni bug: domyślnie NIE zawija tekstu placeholdera w
   textarea (traktuje go jak jedną linię), przez co wystaje poza pole - Chrome/Firefox zawijają
   go poprawnie bez tej reguły. white-space:pre-wrap + word-wrap wymusza zawijanie też na Safari,
   bez wpływu na przeglądarki, które już działały dobrze. */
.comment-form-box textarea::placeholder {
    white-space: pre-wrap;
    word-wrap: break-word;
}

/* ── Płynne chowanie fragmentu formularza (patrz comments.ts) ────────────────────────────── */
/* Sztuczka z grid-template-rows: 1fr -> 0fr - pozwala animować "wysokość: do zera" bez
   znajomości rzeczywistej wysokości treści (na co nie pozwala zwykłe height/max-height) i bez
   przeskoku strony - reszta layoutu płynnie przesuwa się w górę razem ze zwężającym się wierszem
   grida, zamiast skakać w momencie, gdy element nagle dostaje display: none. */
.collapsible {
    display: grid;
    grid-template-rows: 1fr;
    transition: grid-template-rows 0.35s ease;
}

.collapsible-inner {
    min-height: 0;
    transition: opacity 0.2s ease;
}

.collapsible-collapsed {
    grid-template-rows: 0fr;
}

/* overflow:hidden TYLKO gdy faktycznie zwinięte/zwijane, nie na stałe - inaczej przycina też
   wszystko, co z tej treści "wystaje" w normalnym, otwartym stanie (np. rozwijaną listę
   podpowiedzi przedmiotu - .search-suggestions - która jest position:absolute i celowo wychodzi
   poza naturalną wysokość wiersza). Podczas zwijania ma to być ukryte (i wygląda lepiej, gdy
   znika razem ze zwężającym się wierszem), ale w spoczynku (otwarte) nic nie powinno być cięte. */
.collapsible-collapsed .collapsible-inner {
    overflow: hidden;
    opacity: 0;
}

/* ── Winorośl wokół pola opinii (patrz vine.ts) ───────────────────────────── */
/* .vine-wrap ma dokładnie ten sam layout-box co textarea (position:relative, bez paddingu) -
   SVG rysuje poza nim (overflow: visible) bez przesuwania sąsiednich pól formularza. */
.vine-wrap {
    position: relative;
}

.vine-svg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    overflow: visible;
    pointer-events: none;
}

.vine-stem {
    fill: none;
    stroke: #7a9e5e;
    stroke-width: 2.5;
    stroke-linecap: round;
    /* stroke-dasharray == długość ścieżki (ustawiane w JS); stroke-dashoffset odsłania ją
       stopniowo od zera do pełnej długości - to właśnie daje efekt "wzrostu" łodygi. */
    transition: stroke-dashoffset 0.12s ease-out;
}

.vine-leaf-blade {
    fill: #6e9c4f;
}

.vine-leaf-vein {
    fill: none;
    stroke: #557a3c;
    stroke-width: 0.8;
    opacity: 0.6;
}

.vine-leaf {
    transform-box: fill-box;
    /* 0% 50% == lokalny punkt (0,0) ścieżki listka (patrz LEAF_PATH w vine.ts) - tam, gdzie
       listek "wyrasta" z łodygi - wyliczone z jego bounding boksu (x:0-18, y:-6.5..6.5). */
    transform-origin: 0% 50%;
    transform: scale(0) rotate(-18deg);
    opacity: 0;
    transition: transform 0.32s cubic-bezier(.34, 1.56, .64, 1), opacity 0.2s ease;
}

.vine-leaf-revealed {
    transform: scale(1) rotate(0deg);
    opacity: 1;
}

.vine-petal {
    fill: #f2a6c8;
}

.vine-flower-center {
    fill: var(--star-color);
}

.vine-flower {
    transform-box: fill-box;
    transform-origin: 50% 50%; /* kwiat jest promieniście symetryczny wokół lokalnego (0,0) */
    transform: scale(0) rotate(-30deg);
    opacity: 0;
    transition: transform 0.6s cubic-bezier(.34, 1.56, .64, 1), opacity 0.4s ease;
    transition-delay: var(--bloom-delay, 0s);
}

.vine-blooming .vine-flower {
    transform: scale(1) rotate(0deg);
    opacity: 1;
}

/* ── Przyciski (Wygląd dopasowany do przycisków na stronie) ───────────────── */
/* :not(.star) - gwiazdki oceny to też <button> (dla dostępności), ale mają własny, kompaktowy styl niżej */
.comment-form-box button:not(.star):not(.search-suggestion-item):not(.would-take-again-btn):not(.difficulty-btn):not(.notify-email-followup-dismiss):not(.notify-email-followup-link):not(.comment-form-btn-light) {
    background-color: var(--primary-color);
    color: #ffffff;
    border: none;
    padding: 10px 24px;
    border-radius: 8px;
    font-size: 1rem;
    font-weight: 600;
    cursor: pointer;
    font-family: inherit;
    transition: background-color 0.2s ease, transform 0.1s ease;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    margin-top: var(--spacing-sm);
    margin-bottom: var(--spacing-sm);
}

.comment-form-box button:not(.star):not(.search-suggestion-item):not(.would-take-again-btn):not(.difficulty-btn):not(.notify-email-followup-dismiss):not(.notify-email-followup-link):hover {
    background-color: var(--primary-color-hover); /* Odpowiednik hover z motywu */
    color: #ffffff;
    text-decoration: none;
}

.comment-form-box button:not(.star):not(.search-suggestion-item):not(.would-take-again-btn):not(.difficulty-btn):not(.notify-email-followup-dismiss):not(.notify-email-followup-link):active {
    transform: translateY(1px);
}

/* ── Głosowanie (Łapki) ───────────────────────────────────────────────────── */
.comment .upvote-btn,
.comment .downvote-btn {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    font: inherit;
    background-color: transparent;
    cursor: pointer;
    padding: 3px 8px;
    margin-top: 12px;
    margin-right: 10px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    transition: all 0.2s ease;
    display: inline-block;
    user-select: none;
    font-size: 0.9rem;
    color: var(--text-color);
}

.comment .upvote-btn::-moz-focus-inner,
.comment .downvote-btn::-moz-focus-inner {
    border: 0;
}

.comment .upvote-btn:focus,
.comment .downvote-btn:focus {
    outline: none;
}

.comment .upvote-btn:focus-visible,
.comment .downvote-btn:focus-visible {
    outline: 2px solid var(--primary-color);
    outline-offset: 2px;
}

.comment .upvote-btn:hover,
.comment .downvote-btn:hover {
    background-color: var(--bg-subtle);
}

.comment .active-vote {
    background-color: var(--bg-subtle);
    border-color: var(--primary-color);
    color: var(--primary-color);
    font-weight: 700;
}

.comment .vote-icon {
    vertical-align: -3px;
    margin-right: 2px;
}

.comment .vote-icon-down {
    transform: scaleY(-1);
}

/* ── Menu "⋮" komentarza (zgłaszanie) - w prawym dolnym rogu karty, na tej samej
   wysokości co łapki głosowania, żeby nie wydłużało karty komentarza. ── */
.comment {
    position: relative;
}

.comment-menu {
    position: absolute;
    right: var(--spacing-sm);
    bottom: 6px;
}

.comment-menu-toggle {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    background: none;
    border: none;
    cursor: pointer;
    padding: 4px 10px;
    font-size: 1.2rem;
    line-height: 1;
    color: var(--text-muted);
    border-radius: 8px;
    transition: background-color 0.2s ease, color 0.2s ease;
}

.comment-menu-toggle:hover,
.comment-menu-toggle[aria-expanded="true"] {
    background-color: var(--bg-subtle);
    color: var(--text-color);
}

.comment-menu-dropdown {
    display: none;
    position: absolute;
    right: 0;
    bottom: 100%;
    margin-bottom: 4px;
    background-color: var(--bg-color);
    border: 1px solid var(--card-border);
    border-radius: 8px;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.15);
    min-width: 130px;
    overflow: hidden auto;
    max-height: min(340px, 60vh);
    /* WYŻEJ niż .site-header (z-index:50) - gdy komentarz jest tuż pod przyklejonym nagłówkiem,
       rozwinięte menu (otwiera się w górę, "bottom: 100%") mogłoby inaczej wylądować częściowo
       POD nagłówkiem: widoczne (nagłówek jest nieprzezroczysty, więc raczej niewidoczne) i, co
       gorsza, nieklikalne - przyciski "Wyślij zgłoszenie"/"Anuluj" wyglądałyby na martwe. */
    z-index: 55;
}

.comment-menu-dropdown.open {
    display: block;
}

.comment-menu-dropdown .report-btn {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    font: inherit;
    background-color: transparent;
    cursor: pointer;
    display: block;
    width: 100%;
    text-align: left;
    padding: 10px 14px;
    border: none;
    font-size: 0.9rem;
    color: var(--danger-color);
    transition: background-color 0.2s ease;
}

.comment-menu-dropdown .report-btn:hover {
    background-color: var(--danger-bg);
}

.comment-menu-dropdown .report-btn:disabled {
    cursor: default;
    color: var(--text-muted);
    font-weight: 600;
}

/* ── Formularz zgłoszenia (powód/wyjaśnienie/kontakt - art. 16 DSA, patrz comments.ts) ──── */
.report-form {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 10px 12px 12px;
    width: 260px;
}

/* [hidden] i .report-form (display:flex) mają tę samą specyficzność (0,1,0) - bez tej reguły
   o wyższej specyficzności o tym, kto wygrywa, decydowałaby wyłącznie kolejność w arkuszu (a
   ta akurat faworyzowała .report-form), więc `reportForm.hidden = true` w JS (comments.ts:
   Anuluj, stan po sukcesie) nic wizualnie nie zmieniał - formularz zostawał widoczny. */
.report-form[hidden] {
    display: none;
}

.report-form select {
    box-sizing: border-box;
    width: 100%;
    min-width: 0;
    font-size: 0.85rem;
    padding: 8px 30px 8px 10px;
}

.report-form textarea,
.report-form input[type="email"],
.report-form input[type="text"] {
    box-sizing: border-box;
    width: 100%;
    font: inherit;
    font-size: 0.85rem;
    padding: 6px 8px;
    border: 1px solid var(--card-border);
    border-radius: 6px;
    background-color: var(--bg-color);
    color: var(--text-color);
    resize: vertical;
}

.report-form-checkbox-label {
    display: flex;
    align-items: flex-start;
    gap: 6px;
    font-size: 0.78rem;
    color: var(--text-muted);
    line-height: 1.3;
}

.report-form-checkbox-label input[type="checkbox"] {
    flex-shrink: 0;
    margin-top: 2px;
}

.report-form .error {
    margin-bottom: 0;
}

.report-form-actions {
    display: flex;
    gap: 8px;
    justify-content: flex-end;
}

.report-form-actions button {
    font: inherit;
    font-size: 0.85rem;
    padding: 5px 10px;
    border-radius: 6px;
    cursor: pointer;
}

.report-form-actions button[type="submit"] {
    background-color: var(--danger-color);
    color: white;
    border: none;
}

.report-form-cancel {
    background-color: transparent;
    border: 1px solid var(--card-border);
    color: var(--text-color);
}

/* Potwierdzenie po udanym wysłaniu zgłoszenia (patrz comments.ts) - widoczne przez chwilę w
   miejscu formularza, zanim menu się samo zamknie, żeby wysłanie było namacalnie potwierdzone. */
.report-success-message {
    margin: 0;
    padding: 14px;
    color: var(--rating-good);
    font-size: 0.9rem;
    font-weight: 600;
    text-align: center;
}

/* ── Oceny (Gwiazdki) ─────────────────────────────────────────────────────── */
.star {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    background: none;
    border: none;
    padding: 0;
    font: inherit;
    color: #cccccc;
    cursor: pointer;
    transition: color 0.15s ease, transform 0.1s ease;
    user-select: none;
    display: inline-block;
}

.star::-moz-focus-inner {
    border: 0;
}

.star:focus {
    outline: none;
}

.star:focus-visible {
    outline: 2px solid var(--primary-color);
    outline-offset: 2px;
    border-radius: 3px;
}

.star.active {
    color: var(--star-color);      /* Złoty/pomarańczowy kolor ostrzegawczy z Directorist */
}

.comment-form-box .star:hover {
    transform: scale(1.25);
    color: #d97400;                /* Ciemniejszy odcień pomarańczowego */
}

/* ── Trudność przedmiotu (🔥, osobna skala od oceny - tylko moduł "Przedmioty") ────────────── */
/* Emoji renderuje się w pełnym kolorze niezależnie od CSS `color`, więc stan
   aktywny/nieaktywny (w odróżnieniu od .star wyżej) różnicujemy przez opacity+grayscale,
   nie kolor. */
.difficulty-rating {
    display: inline-flex;
    align-items: center;
    gap: 1px;
    line-height: 1;
}

.difficulty-icon {
    font-size: 0.85rem;
    opacity: 0.25;
    filter: grayscale(1);
}

.difficulty-icon.active {
    opacity: 1;
    filter: none;
}

/* ── Płomyki ŚREDNIEJ trudności - wypełnienie ciągłe (co 1/10), nie tylko całe płomyki (patrz
   showPartialDifficulty w subjects.ts) - ten sam mechanizm co .star-partial-bg/fg (gwiazdki
   średniej oceny), ALE różnicowany przez opacity+grayscale (.difficulty-icon/.difficulty-icon.active
   wyżej), nie przez `color` - 🔥 jest emoji, renderuje się w pełnym kolorze niezależnie od CSS
   `color` (patrz notka przy .difficulty-icon wyżej). ── */
.difficulty-icon-partial {
    position: relative;
    display: inline-block;
    line-height: 1;
}

.difficulty-icon-partial-bg,
.difficulty-icon-partial-fg {
    display: block;
}

.difficulty-icon-partial-fg {
    position: absolute;
    top: 0;
    left: 0;
    overflow: hidden;
    white-space: nowrap;
}

/* Zwięzła odznaka średniej trudności (karta listy/podsumowanie przedmiotu) - ten sam kształt
   co .would-take-again-badge (patrz tam), spójna z resztą odznak obok gwiazdek. */
.difficulty-badge {
    display: inline-block;
    margin-left: 8px;
    font-size: 0.85rem;
    color: var(--text-color);
    opacity: 0.8;
    white-space: nowrap;
}

/* W podsumowaniu strony przedmiotu (.rating-summary-headline - kolumna wyśrodkowana) odznaka
   dokłada się PONIŻEJ "Opinie: N", nie obok niczego - margines lewy z wariantu karty/inline
   tu tylko przesuwałby ją w bok zamiast wyśrodkowywać. */
.rating-summary-headline .difficulty-badge {
    margin: 4px 0 0;
}

/* Interaktywny wybór trudności w formularzu opinii - te same wymiary/zachowanie co
   .star-rating-widget .star (hover-powiększenie, etykieta pod spodem POZYCJONOWANA ABSOLUTNIE -
   patrz .difficulty-rating-hover-label niżej, ten sam powód co .star-rating-hover-label: bez
   tego pojawienie się tekstu etykiety powiększało wysokość widżetu, a przez align-items:center
   na .rating-field sąsiednia etykieta "Trudność:" wizualnie "zjeżdżała w dół", zgłoszenie),
   ale przyciski (nie gwiazdki) różnicowane opacity+grayscale jak .difficulty-icon wyżej.
   Emoji 🔥 ma więcej "wizualnej wagi" niż znak ★ przy tym samym font-size - zamiast zmniejszać
   płomień, .star-rating-widget .star niżej jest zwiększony, żeby to on dorównał płomieniowi
   (na wyraźną prośbę), nie odwrotnie. */
.difficulty-rating-widget {
    position: relative;
    display: inline-block;
    text-align: center;
    line-height: 1;
}

.difficulty-btn {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    background: none;
    border: none;
    padding: 0;
    /* Lekko zmniejszone z 1.3rem (zgłoszenie: "jeszcze zmniejsz") - gwiazdki obok zostały
       zwiększone do 1.45rem jako kompromis wizualny (patrz .star-rating-widget .star), więc
       płomień nie musi już nadrabiać całego dystansu sam. */
    font-size: 1.15rem;
    line-height: 1;
    cursor: pointer;
    opacity: 0.3;
    filter: grayscale(1);
    transition: opacity 0.15s ease, filter 0.15s ease, transform 0.1s ease;
}

.difficulty-btn.active {
    opacity: 1;
    filter: none;
}

.comment-form-box .difficulty-btn:hover {
    transform: scale(1.2);
}

.difficulty-rating-hover-label {
    position: absolute;
    top: calc(100% + 3px);
    left: 50%;
    transform: translateX(-50%);
    white-space: nowrap;
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--text-muted);
}

/* Tylko gwiazdki do WYSTAWIANIA oceny (formularz opinii) - trochę większe niż te do samego
   wyświetlania średniej (showStars() w generics.ts), które też używają klasy .star. */
.star-rating-widget .star {
    /* Lekko większe niż domyślne 1.3rem - kompromis w stronę wizualnej "wagi" płomieni 🔥
       obok (patrz .difficulty-btn), bez robienia z gwiazdek karykaturalnie dużego elementu. */
    font-size: 1.45rem;
}

/* ── Etykieta pod gwiazdkami przy wystawianiu opinii (Wybitny/Świetny/...) ────────── */
/* Etykieta jest "position: absolute" (nie zajmuje miejsca w layoucie) - dzięki temu
   .rating-field ma wysokość samych gwiazdek, tak jak sąsiednie pola w .comment-form-row
   ("wybrałbyś ponownie?", przedmiot), i "align-items: center" na wierszu wyrównuje je
   naprawdę do gwiazdek, a nie do całego (wyższego) bloku gwiazdki+etykieta. */
.star-rating-widget {
    position: relative;
    display: inline-block;
    /* line-height:1 - bez tego odziedziczone 1.6 (z body) dodawało puste miejsce nad/pod samym
       rzędem gwiazdek (widget jest inline-block, więc dostaje odstęp linii otaczającego wiersza),
       przez co pole "Ocena" w formularzu opinii wyglądało na wyraźnie wyższe/"cięższe", niż same
       gwiazdki tego wymagają - szczególnie widoczne na telefonie (patrz .rating-field). */
    line-height: 1;
}

.star-rating-hover-label {
    position: absolute;
    /* "calc(100% - 5px)" (poprzednia wartość) prawie stykało się z gwiazdkami, wizualnie na nie
       nachodząc (zgłoszenie) - teraz wyraźnie POD nimi, nie w nie wchodząc. */
    top: calc(100% + 3px);
    left: 50%;
    transform: translateX(-50%);
    white-space: nowrap;
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--star-color);
}

/* ── Gwiazdki ŚREDNIEJ oceny - wypełnienie ciągłe (co 1/6), nie tylko całe gwiazdki ──
   Dwie nałożone gwiazdki: szara w tle na pełną szerokość, pomarańczowa przycięta do
   procentu wypełnienia - dzięki temu 4.1 i 4.9 widocznie się różnią. */
.star-partial {
    position: relative;
    display: inline-block;
    line-height: 1;
    font-size: inherit;
}

.star-partial-bg,
.star-partial-fg {
    display: block;
}

.star-partial-bg {
    color: #cccccc;
}

.star-partial-fg {
    position: absolute;
    top: 0;
    left: 0;
    overflow: hidden;
    white-space: nowrap;
    color: var(--star-color);
}

/* ── Podsumowanie oceny (jak w Google Maps): paski po lewej, duża liczba/gwiazdki po prawej ── */
.rating-summary {
    display: flex;
    align-items: center;
    gap: var(--spacing-lg);
    margin: var(--spacing-md) 0 var(--spacing-lg);
    flex-wrap: wrap; /* na wąskich ekranach nagłówek spada pod paski zamiast je ściskać */
}

/* Płynne pojawianie/znikanie rozkładu przy przełączaniu zakładek Zajęcia/Egzamin/Pytania (na
   wyraźną prośbę) - patrz setRatingSummaryContent w post_detail.ts, które dokłada/zdejmuje tę
   klasę WOKÓŁ podmiany zawartości (#rating-summary, rodzic .rating-summary). Transition musi
   być na rodzicu, nie na .rating-summary samym - ten jest tworzony na nowo (nowy element) przy
   każdej podmianie, więc nie miałby żadnego "poprzedniego" stanu opacity do animowania. */
#rating-summary {
    transition: opacity 0.16s ease;
}

#rating-summary.rating-summary-fade-out {
    opacity: 0;
}

.rating-summary .rating-distribution {
    flex: 1 1 260px;
    max-width: 380px;
    margin: 0;
}

/* flex:0 0 110px (STAŁA szerokość, nie auto/content-sized) - inaczej rząd pasków (.rating-distribution,
   pierwszy flex-sibling PO tej kolumnie) zaczynałby się w innym miejscu w zależności od tego, czy w
   środku są gwiazdki czy ikony ognia (różna szerokość znaków przy tym samym font-size) - dokładnie to,
   co przy przełączaniu Zajęcia/Egzamin przesuwało linię pasków w prawo (zgłoszenie). Stała szerokość +
   align-items:center niżej sprawiają, że oba warianty (gwiazdki/ogień) są wyśrodkowane w TEJ SAMEJ
   kolumnie, więc paski zawsze zaczynają się w tym samym miejscu niezależnie od aktywnej zakładki. */
.rating-summary-headline {
    display: flex;
    flex-direction: column;
    align-items: center;
    flex: 0 0 110px;
    width: 110px;
}

.rating-summary-number {
    font-size: 2.5rem;
    font-weight: 700;
    line-height: 1;
    color: var(--text-color);
}

/* ── "Temperatura" oceny - koloruje TYLKO skrajne wartości (patrz ratingTierClass w posts.ts).
   Środek zostaje neutralny, żeby lista nie zrobiła się "choinką" - to osobny sygnał od
   pomarańczowych gwiazdek (te mają stały kolor niezależnie od wartości oceny, oznaczają
   "to jest ocena"; ten kolor oznacza "ta ocena jest wysoka/niska"). Reguły MUSZĄ być
   w arkuszu PO .rating-summary-number/.comment-card (ta sama specyficzność - klasa), żeby
   wygrać o color= z nimi. ── */
.rating-tier-good {
    color: var(--rating-good);
}

.rating-tier-poor {
    color: var(--danger-color);
}

.rating-summary-stars {
    /* line-height:1 - domyślne 1.6 (z body) rozciągało pionowy box dużo ponad sam znak "★",
       przez co "Opinie: N" i kciuk pod spodem wypadały niepotrzebnie nisko/daleko od gwiazdek. */
    margin: 4px 0 0;
    font-size: 1.3rem;
    line-height: 1;
}

/* .difficulty-icon (showDifficulty w subjects.ts, reużyty w tym samym kontenerze co gwiazdki -
   patrz renderExamSummaryContent w post_detail.ts) ma WŁASNY font-size (0.85rem, patrz reguła
   .difficulty-icon niżej - potrzebny w INNYCH miejscach, np. karta przedmiotu/komentarza), który
   inaczej biłby odziedziczone 1.3rem z reguły wyżej - w przeciwieństwie do .star (bez własnego
   font-size, więc tam dziedziczenie działa samo) - stąd różnica w rozmiarze między rozkładem
   gwiazdek i ognia na zakładkach Zajęcia/Egzamin (zgłoszenie). inherit tylko TUTAJ, nie globalnie. */
/* Emoji 🔥 ma większą wizualną wagę niż znak ★ przy IDENTYCZNYM font-size (ten sam efekt co
   przy .difficulty-rating-widget .difficulty-btn, patrz notka tam) - inherit (1.3rem, tyle co
   .star) wciąż wyglądało za duże względem gwiazdek, więc tutaj (w odróżnieniu od widgetu, gdzie
   to STAR jest powiększany) idziemy w drugą stronę: zmniejszamy ogień, żeby wizualnie pasował do
   rozmiaru gwiazdek w tym samym miejscu (zgłoszenie). */
.rating-summary-stars .difficulty-icon {
    font-size: 0.85em;
}

.rating-summary-count {
    margin-top: 6px;
    font-size: 0.9rem;
    line-height: 1.2;
    color: var(--text-color);
    opacity: 0.7;
    white-space: nowrap;
}

/* Zastępuje dużą liczbę+ikony, gdy są opinie o egzaminie, ale żadna nie ocenia konkretnie
   trudności (patrz renderExamSummaryContent w post_detail.ts) - zamiast mylącego "0,0" +
   puste ikony (co wygląda jak realna najniższa ocena). */
.rating-summary-number-placeholder {
    font-size: 0.95rem;
    color: var(--text-muted);
    text-align: center;
    max-width: 100px;
}

/* ── Rozkład ocen (ile 5*, 4*, itd.) - jak w Google Maps ──────────────────────────── */
.rating-distribution {
    display: flex;
    flex-direction: column;
    gap: 4px;
    max-width: 320px;
    margin: var(--spacing-sm) 0 var(--spacing-md);
}

.rating-distribution-row {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.85rem;
}

.rating-distribution-label {
    flex: 0 0 108px; /* stała szerokość - bez tego dłuższe przymiotniki (np. "Beznadziejny") skracałyby pasek */
    width: 108px;
    color: var(--text-color);
    opacity: 0.8;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.rating-distribution-bar-track {
    flex: 1 1 auto;
    height: 8px;
    background-color: var(--bg-subtle);
    border-radius: 999px;
    overflow: hidden;
    display: block;
}

.rating-distribution-bar-fill {
    display: block;
    height: 100%;
    background-color: var(--star-color);
    border-radius: 999px;
}

.rating-distribution-count {
    flex: 0 0 auto;
    min-width: 18px;
    text-align: right;
    color: var(--text-color);
    opacity: 0.8;
    font-variant-numeric: tabular-nums;
}

/* Wersja w kartach porównania - bez opisów, węższa, mniejsza czcionka (kafle są wąskie) */
.compare-card .rating-distribution {
    max-width: none;
    /* align-self:stretch - karta jest wyśrodkowana (align-items:center), ale pasków rozkładu to
       nie powinno dotyczyć: mają rozciągać się na całą szerokość karty jak dotychczas, inaczej
       .rating-distribution-bar-track (flex:1 1 auto, patrz wyżej) nie miałby się do czego rosnąć
       i słupki skurczyłyby się do zera. text-align:left - bez tego etykiety/liczby dziedziczyłyby
       wyśrodkowanie z .compare-card. */
    align-self: stretch;
    text-align: left;
    margin: 4px 0;
    gap: 2px;
}

.compare-card .rating-distribution-row {
    font-size: 0.7rem;
    gap: 4px;
}

.compare-card .rating-distribution-bar-track {
    height: 5px;
}

.compare-card .rating-distribution-label {
    flex: 0 0 12px;
    width: 12px;
}

.compare-card .rating-distribution-count {
    min-width: 14px;
}

/* ── Kontener paska wyszukiwania i sortowania ─────────────── */
.controls {
    display: flex;
    align-items: center;
    gap: 15px; 
    margin-bottom: var(--spacing-md);
    flex-wrap: wrap; 
}

/* ── Pole wyszukiwania ────────────────────────────────────── */
#search-input {
    flex-grow: 1;
    max-width: 400px; 
    padding: 10px 12px 10px 38px; 
    border: 1px solid var(--border-color);
    border-radius: 8px; 
    font-family: inherit;
    font-size: 0.95rem;
    color: var(--text-color);
    background-color: #ffffff;
    transition: all 0.2s ease;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03);
    
    /* Ikonka lupy (SVG) jako tło */
    background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236c757d' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3ccircle cx='11' cy='11' r='8'%3e%3c/circle%3e%3cline x1='21' y1='21' x2='16.65' y2='16.65'%3e%3c/line%3e%3c/svg%3e");
    background-repeat: no-repeat;
    background-position: left 12px center;
    background-size: 16px;
}

/* Wygląd po najechaniu i kliknięciu */
#search-input:hover {
    border-color: var(--border-hover);
}

#search-input:focus {
    outline: none;
    border-color: var(--primary-color);
}

/* ── Podpowiedzi wyszukiwania na profilu wykładowcy (rozwijana lista pod polem) ───── */
.search-with-suggestions {
    position: relative;
    max-width: 400px;
}

.search-suggestions {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    margin-top: 4px;
    background-color: var(--bg-color);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
    /* Listy potrafią mieć kilkaset pozycji (np. wszystkie uczelnie) - pokazujemy je wszystkie
       (bez ucinania), ale w ograniczonej wysokości z suwakiem, żeby dropdown nie rozpychał
       reszty strony w dół. overflow-x zostaje hidden (jak wcześniej samo "hidden") - żeby
       zaokrąglone rogi kontenera dalej przycinały pierwszy/ostatni element listy. */
    overflow: hidden auto;
    max-height: min(340px, 60vh);
    overscroll-behavior: contain;
    z-index: 20;
}

.search-suggestions.open {
    display: block;
}

.search-suggestion-item {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    display: block;
    width: 100%;
    padding: 10px 14px;
    border: none;
    background: none;
    color: var(--text-color);
    text-decoration: none;
    text-align: left;
    font-family: inherit;
    font-size: 0.9rem;
    cursor: pointer;
    border-bottom: 1px solid var(--card-border);
}

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

.search-suggestion-item:hover,
.search-suggestion-item.keyboard-active {
    background-color: var(--bg-subtle);
}

.search-suggestion-create {
    color: var(--primary-color);
    font-weight: 600;
}

.search-suggestion-create:disabled {
    cursor: default;
    opacity: 0.7;
}

/* Dopisek "(Opinie: N)" przy podpowiedzi osoby, która już ma jakieś opinie (patrz matches.forEach
   w addLecturer.ts) - stonowany, żeby samo imię/nazwisko wciąż było głównym akcentem wiersza. */
.search-suggestion-hint {
    color: var(--text-muted);
    font-size: 0.85em;
}

/* Ostrzeżenie o duplikacie w popupie "Dodaj osobę" (patrz duplicateNotice w addLecturer.ts) -
   pokazuje się zamiast cichego utworzenia drugiego profilu tej samej osoby, gdy jej dokładne
   imię/nazwisko już jest w bazie (a mimo to nie trafiło do podpowiedzi "Czy chodziło Ci o" - np.
   bo jest na innym wydziale niż aktualnie przeglądany). Ten sam wygląd co .error (czerwony,
   ostrzegawczy), ale osobna klasa - .error to zwykły <span> na sam tekst, tu dochodzi jeszcze
   link do istniejącego profilu.
*/
.add-person-duplicate-notice {
    color: var(--danger-color);
    font-size: 0.9rem;
    margin: 4px 0 0;
}

.add-person-duplicate-notice:empty {
    display: none;
    margin: 0;
}

.add-person-duplicate-notice a {
    color: inherit;
    text-decoration: underline;
    font-weight: 600;
}

/* "Wszystkie wydziały" - stała pozycja na dole listy wydziałów (patrz landing2.ts), inny
   akcent niż "+ Dodaj wydział" (kursywa zamiast pogrubienia), żeby nie wyglądały tak samo -
   to nie jest akcja tworząca coś nowego, tylko ucieczka z wyboru. */
.search-suggestion-all {
    color: var(--text-muted);
    font-style: italic;
}

/* Widżet "zostaw e-mail" pokazywany PO udanym dodaniu/zgłoszeniu czegoś, co czeka na moderację
   (patrz renderPostHocNotifyPrompt w notifyEmail.ts) - wspólny dla formularza opinii, dodania
   wykładowcy/wydziału i "+ Dodaj uczelnię/wydział" na stronie wyboru uczelni. margin-top - żeby
   nie "dotykał" formularza/komunikatu powyżej. Bez poziomego paddingu domyślnie (tekst zaczyna
   się w tej samej kolumnie X co komunikat nad nim, który w większości miejsc też go nie ma -
   patrz wyjątek dla /test/ niżej).*/
.notify-email-followup {
    display: flex;
    flex-direction: column;
    gap: 8px;
    /* Był i margin-top, i padding: 10px 0 razem - to 20px odstępu od komunikatu nad nim
       (patrz feedback w comments.ts), wyraźnie więcej niż reszta odstępów w formularzu (9-10px)
       - wyglądało jak dodatkowa pusta linijka. Zostaje tylko margin-top. */
    margin-top: 10px;
}

/* Uczelnia/wydział na /test/ - komunikat nad tym widżetem (.landing-faculty-feedback) ma własne
   12px paddingu (wygląda jak "pigułka" z tłem) - dorównujemy, żeby tekst tego widżetu zaczynał
   się dokładnie w tym samym X, zamiast wystawać bardziej w lewo. */
.landing-search-field .notify-email-followup,
.landing-faculty-section .notify-email-followup {
    padding-left: 12px;
    padding-right: 12px;
}

/* Zdanie-zachęta ze schowanym polem e-mail (patrz expandLink w notifyEmail.ts) - mniejsza,
   przygaszona czcionka, żeby nie konkurowała wagą z komunikatem "Dziękujemy"/"Zapisano" nad nią. */
.notify-email-followup-intro {
    margin: 0;
    font-size: 0.85rem;
    color: var(--text-muted);
}

.notify-email-followup-link {
    background: none;
    border: none;
    padding: 0;
    margin: 0;
    font: inherit;
    color: var(--primary-color);
    text-decoration: underline;
    cursor: pointer;
}

/* :not([hidden]) - inaczej ta reguła (autorska, klasa) wygrywa z domyślnym "[hidden] { display:
   none }" przeglądarki (arkusz autora zawsze bije UA, niezależnie od specyficzności), więc
   ustawienie elementu.hidden = true w notifyEmail.ts nic by nie dawało - sekcja i tak zostawałaby
   widoczna jako flex. */
.notify-email-followup-expand:not([hidden]) {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

/* .notify-email-field ma własny margin-top: 6px (patrz reguła bazowa wyżej) - dobry, gdy stoi w
   zwykłym przepływie, ale tutaj jest PIERWSZYM dzieckiem flexa z własnym "gap: 8px" (wyżej), więc
   ten margines tylko DOKŁADAŁ się do marginesu ".notify-email-followup" nad całym widżetem,
   dając nienaturalnie duży odstęp między komunikatem ("Dziękujemy"/"Zapisano") a "Twój e-mail". */
.notify-email-followup-expand > .notify-email-field:first-child {
    margin-top: 0;
}

.notify-email-followup-feedback {
    color: var(--danger-color);
    font-size: 0.85rem;
}

.notify-email-followup-done {
    color: var(--text-muted);
    font-size: 0.9rem;
}

.notify-email-followup-dismiss {
    background: none;
    border: none;
    padding: 0;
    color: var(--text-muted);
    font-size: 0.85rem;
    font-weight: 400;
    cursor: pointer;
}

.notify-email-followup-actions {
    display: flex;
    align-items: center;
    gap: 14px;
}

/* "Powiadom mnie" dostaje pogrubienie/rozmiar DWA razy - raz z .add-comment-btn (1 klasa), raz
   (wygrywająca) z ogólnej reguły ".comment-form-box button:not(...)" wyżej (4 wykluczenia = 5
   "klas" + typ = specyficzność (0,5,1)) - żeby przebić TĘ drugą, trzeba dorównać/przebić jej
   specyficzność, nie tylko pobić samo .add-comment-btn. Tło/kolor mają zostać takie jak z tej
   ogólnej reguły (spójne z "Podziel się opinią") - mniejszy niż tam padding/font-size, bo to
   drugorzędna akcja w tym widżecie, nie główny CTA formularza. */
.comment-form-box .notify-email-followup-actions button:not(.star):not(.search-suggestion-item):not(.would-take-again-btn):not(.difficulty-btn):not(.notify-email-followup-dismiss) {
    font-weight: 400;
    padding: 7px 16px;
    font-size: 0.9rem;
}

/* Podpowiedź w wyszukiwarce przedmiotu, gdy wydział nie ma jeszcze żadnego własnego (patrz
   renderSubjectPicker w comments.ts) - nieklikalna (to <p>, nie <button>, stąd bez kursora
   wskaźnika i hovera .search-suggestion-item), tylko informacyjna. */
.search-suggestion-hint {
    margin: 0;
    padding: 10px 14px;
    color: var(--text-muted);
    font-size: 0.85rem;
    font-style: italic;
}

/* Wyszukiwarka przedmiotu w formularzu komentarza wypełnia dostępną szerokość kolumny
   (ograniczoną przez .comment-form-row .subject-picker), a nie sztywne 400px jak na profilu. */
.subject-picker-search {
    max-width: 100%;
    width: 100%;
}

/* ── Prompt "Nie znalazłeś wykładowcy?" pod wynikami wyszukiwania ─────────── */
.add-lecturer-prompt {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    flex-wrap: wrap;
    margin-top: var(--spacing-md);
    margin-bottom: var(--spacing-md);
}

.add-lecturer-question {
    padding-left: 0;
    color: var(--text-color);
    opacity: 0.8;
}

/* Powiększony wariant pigułki (patrz large w renderAddPersonButton w addLecturer.ts) - gdy
   przefiltrowana lista wyników mieści się cała na ekranie bez przewijania (patrz
   resultsFitOnScreen w render() w browser.ts), to i tak jedyna sensowna akcja na widoku, więc ten
   sam przycisk ma być od razu wyraźnie widoczny, nie ginąć jako mały dopisek - zgłoszenie: "więcej
   zachęty, może być trochę większy". .add-lecturer-prompt (kontener) zostaje bez zmian - ten sam
   margin/wyrównanie do lewej co zawsze, żeby całość i tak lądowała tam, gdzie byłaby kolejna
   karta, tylko sam przycisk (i etykieta z "do serwisu" - patrz addLecturer.ts) rośnie. */
.add-comment-btn-large {
    padding: 12px 22px;
    border-radius: 8px;
    font-size: 1.05rem;
    font-weight: 700;
}

.add-comment-btn-large .add-comment-btn-icon {
    font-size: 1.2rem;
}

/* Pola "Imię"/"Nazwisko" formularza dodawania wykładowcy - etykieta obok pola,
   tak jak .subject-picker w formularzu komentarza.
   Specyficzność musi pobić ".comment-form-box label" (klasa+typ). */
.comment-form-box .lecturer-field {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 1 1 200px;
}

/* [hidden] (patrz nameField.hidden/facultyPicker.element.hidden w addLecturer.ts, ustawiane po
   rozstrzygnięciu, kim jest dodawana osoba) SAM Z SIEBIE nie wystarczy - domyślny styl
   przeglądarki dla [hidden] i powyższa reguła .lecturer-field mają tę samą specyficzność (jedna
   klasa), a arkusz strony zawsze wygrywa z domyślnym UA, więc bez tego element mimo atrybutu
   hidden zostawał widoczny jako flex. */
.comment-form-box .lecturer-field[hidden] {
    display: none;
}

.comment-form-box .lecturer-field input[type="text"] {
    width: auto;
    flex: 1 1 auto;
    min-width: 0;
}

/* Zablokowane pole wydziału (patrz renderLockedFacultyField w addLecturer.ts) - odróżnia je od
   zwykłych, edytowalnych pól obok (imię/nazwisko), zamiast polegać na niespójnym między
   przeglądarkami domyślnym wyglądzie disabled. */
.comment-form-box .lecturer-field input[type="text"]:disabled {
    background-color: var(--bg-subtle);
    color: var(--text-muted);
    cursor: not-allowed;
}

.comment-form-box .lecturer-field .search-with-suggestions {
    flex: 1 1 auto;
    min-width: 0;
    max-width: none;
}

/* ── Gwiazdki / kiedy dodano / przedmiot / rok - wszystko w jednej linii ──── */
/* flex (nie poleganie na vertical-align) - gwarantuje równe wyrównanie elementów
   o różnej wysokości (przyciski gwiazdek, tekst, odznaki-pigułki). */
.comment-header-row {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 8px;
    /* Rezerwuje miejsce na datę/odznakę źródła w prawym górnym rogu karty (.comment-date - patrz
       niżej, position:absolute, więc SAMA z siebie nie odpycha zwykłej, płynącej treści). Bez
       tego odznaka przedmiotu (patrz .comment-meta), gdy akurat mieściła się w tej samej linii co
       gwiazdki, potrafiła wjechać pod datę/odznakę zamiast się pod nią zawinąć - szerokość dobrana
       pod najdłuższy przypadek (pełna data, np. "17 Sie 2026"), nie pod samą małą plakietkę.
       Dzięki temu ten sam flex-wrap, który już łamie wiersz między parą a przedmiotem (patrz
       .comment-header-primary), teraz robi to też odpowiednio wcześniej, gdy trzeba zrobić
       miejsce na róg karty. */
    padding-right: 90px;
}

/* Gwiazdki + "poleca/odradza" (patrz renderComment w comments.ts) - NIGDY nie mają się
   rozdzielić na osobne linie, w odróżnieniu od .comment-meta (przedmiot) obok, który na wąskim
   telefonie MOŻE zejść do drugiej linii. Bez tego .comment-header-row (flex-wrap:wrap) mógł
   złamać wiersz między gwiazdkami a odznaką "poleca" zamiast między parą a przedmiotem, gdy
   zabrakło miejsca - nagłówek opinii rozjeżdżał się wtedy na 3 linie zamiast maks. 2. */
.comment-header-primary {
    display: flex;
    align-items: center;
    flex-wrap: nowrap;
    flex-shrink: 0;
    gap: 8px;
}

/* Domyślny line-height (1.6, patrz body) rozciąga pionowy box gwiazdek dużo ponad sam
   znak "★", więc elementy wyrównane do środka wiersza (align-items: center) - jak odznaka
   Fandom (.comment-source-badge) - wypadały wizualnie wyżej niż same gwiazdki. */
.comment-header-row .star-rating {
    line-height: 1;
    /* Znak "★" (U+2605) ma spory pusty margines wewnątrz własnego pola znaku (po lewej
       stronie), więc mimo że box .star-rating zaczyna się w tym samym miejscu co tekst
       komentarza pod spodem, sam widoczny czubek gwiazdki wystaje przed niego. Dosuwa
       widoczny czubek do tekstu - wartość zmierzona pikselowo (headless Chromium) pod
       Manrope (patrz --font-main), nie "na oko" - jeśli po zmianie fontu przestanie
       pasować, tu jest miejsce do poprawki. */
    margin-left: 0.29em;
}

/* Data komentarza - w prawym górnym rogu karty, dyskretna (nie w głównym nagłówku,
   żeby nie "rzucała się w oczy" jako pierwsza rzecz - patrz .comment position:relative). */
.comment-date {
    position: absolute;
    top: var(--spacing-sm);
    right: var(--spacing-sm);
    font-size: 0.75rem;
    color: var(--text-color);
    opacity: 0.55;
    font-weight: 400;
}

/* Odznaka źródła dla komentarzy zaimportowanych z zewnętrznego archiwum (Fandom - patrz
   isFandomImportedComment, albo Psych - patrz is_from_psych_import w comments.ts) - stawiana
   obok gwiazdek (patrz .comment-header-row/.compare-comment-header), dyskretne kółko z ikoną "i"
   (patrz renderSourceBadge w comments.ts - SVG, nie tekstowy znak, żeby kropka nie zlewała się
   z trzonem przy tak małym rozmiarze), tooltip z atrybucją pokazuje się po najechaniu. */
.comment-source-badge {
    position: relative; /* punkt odniesienia dla ::after z dymkiem niżej */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 14px;
    height: 14px;
    flex-shrink: 0;
    border-radius: 50%;
    /* Przygaszone o te same 55% co dawniej, ale wymieszane wprost w kolorze (nie przez
       `opacity` na całym elemencie) - `opacity` na elemencie ciągnie za sobą też ::after
       niżej (osobny box, ale w tej samej warstwie kompozycji), więc dymek z tooltipem
       wychodził wyblakły i nieczytelny mimo własnego opacity: 1. */
    background-color: color-mix(in srgb, var(--text-color) 55%, var(--bg-color));
    color: var(--bg-color);
    cursor: help;
}

/* Własny dymek zamiast natywnego title (ten pokazuje się dopiero po ~1-2s) - treść z
   data-tooltip (patrz renderFandomSourceBadge w comments.ts), pokazuje się niemal od razu po
   najechaniu/najechaniu klawiaturą. Tło wyraźnie ciemniejsze niż samo kółko odznaki (patrz wyżej) -
   to osobny czytelny dymek, nie ma powodu, żeby był tak samo przygaszony jak dyskretna odznaka. */
.comment-source-badge::after {
    content: attr(data-tooltip);
    position: absolute;
    bottom: calc(100% + 6px);
    /* right (nie left:50%/transform:translateX(-50%)) - odznaka siedzi tuż przy PRAWEJ krawędzi
       karty komentarza (patrz .comment-date), więc wyśrodkowany dymek regularnie wystawał poza
       prawą krawędź ekranu na telefonie. Mimo niewidoczności (opacity/visibility) dymek jest
       nadal UŁOŻONY w layoucie, więc to poszerzało scrollowalną szerokość całej strony ponad
       szerokość ekranu - przeglądarka mobilna reagowała na to widocznym "przybliżeniem" całej
       strony post-detail (którego nie ma na liście, bo tam odznaka F w ogóle się nie pojawia).
       Dymek rosnący w lewo od prawej krawędzi odznaki nigdy nie wychodzi poza ekran. */
    right: -4px;
    width: max-content;
    max-width: min(220px, calc(100vw - 2 * var(--spacing-md)));
    background-color: #1a1a1a;
    color: #ffffff;
    font-size: 0.7rem;
    font-weight: 400;
    line-height: 1.3;
    padding: 6px 8px;
    border-radius: 6px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.35);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    z-index: 20;
    transition: opacity 0.1s ease;
}

.comment-source-badge:hover::after,
.comment-source-badge:focus-visible::after {
    opacity: 1;
    visibility: visible;
}

/* ── Obrys karty prowadzącego ────────────────────────────────────────────── */
.comment-card {
    border: 1px solid var(--card-border);
    border-radius: 8px;
    padding: 0px 0px var(--spacing-md) var(--spacing-md);
    margin-bottom: var(--spacing-md);
    background-color: var(--bg-color);
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.04);
    display: block;
    text-decoration: none;
    color: inherit;
    transition: border-color 0.2s ease, box-shadow 0.2s ease, transform 0.15s ease;
}

/* Odstęp nad "Imię Nazwisko" (globalny h1,h2,h3 margin-top: var(--spacing-md) wyżej w pliku)
   wizualnie WYGLĄDAŁ większy niż odstęp pod "Porównaj" na dole karty, mimo że w modelu pudełka
   oba są identyczne (16px) - duża czcionka nagłówka ma sporo "powietrza" nad literami z samego
   line-height, którego mała "pigułka" przycisku na dole nie ma. Mniejszy margines kompensuje tę
   różnicę, żeby OBA odstępy wyglądały tak samo, nie tylko liczyły się tak samo. +4px (zamiast
   czystego var(--spacing-sm)) - cała góra karty (nazwisko + gwiazdki/tekst pod nim, oba
   przesuwają się razem, bo dalej w dół pozycjonują się względem h2) wciąż wyglądała odrobinę
   za wysoko względem dolnego marginesu karty (16px), nawet po doliczeniu "powietrza" z line-height.
   margin-bottom (ujemny, w em - NIE w px) ciągnie .comment-card-meta bliżej nagłówka z tego
   samego powodu - "powietrze" pod tekstem jest proporcjonalne do font-size h2, a ten się zmienia
   w @media (max-width: 640px) niżej (2rem -> 1.4rem). Stały px kompensujący to samo (dawniej
   -6px na samym .comment-card-meta) był skalibrowany tylko pod desktopowy rozmiar h2 i na
   telefonie ciągnął całą metę (gwiazdki+tekst albo "Brak opinii") za mocno do góry (zgłoszenie:
   kafelki na telefonie miały treść nie wyśrodkowaną względem obrysu karty). Em skaluje się
   razem z font-size h2 na każdej szerokości ekranu bez osobnej kalibracji. */
.comment-card h2 {
    margin-top: calc(var(--spacing-sm) + 4px);
    margin-bottom: -0.15em;
}

/* Wydział pod nazwiskiem na karcie - tylko w widoku całej uczelni (patrz showFacultyName w
   browser.ts/renderPost w posts.ts). "?" na końcu tekstu (dopisywany w renderPost dla
   niepotwierdzonych) celowo bez dodatkowego stylu - to zwykły znak zapytania w tekście, nie
   osobny badge, żeby nie było zbyt krzykliwe na liście. */
.comment-card-faculty {
    margin: -4px 0 4px;
    color: var(--text-muted);
    font-size: 0.9em;
}

/* Cała karta jest linkiem (patrz renderPost w posts.ts) - do tej pory bez żadnej reakcji na
   najechanie, więc nic nie sygnalizowało "to jest klikalne". Delikatne uniesienie + obwódka
   w kolorze marki, bez zmiany layoutu (stąd transform zamiast np. zmiany marginesu). */
.comment-card:hover {
    border-color: var(--primary-color);
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.12);
    transform: translateY(-2px);
}

/* ── Stylizowany <select> (strzałka, zaokrąglenie) - używany np. przez sortowanie porównania ── */
.styled-select {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    width: auto;
    min-width: 150px;
    background-color: #ffffff;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    padding: 10px 36px 10px 12px;
    font-family: inherit;
    font-weight: 400;
    font-size: 1rem;
    color: var(--text-color);
    cursor: pointer;
    transition: border-color 0.2s ease;

    background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23404040' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e");
    background-repeat: no-repeat;
    background-position: right 10px center;
    background-size: 16px;
}

.styled-select:hover {
    border-color: var(--border-hover);
}

.styled-select:focus {
    outline: none;
    border-color: var(--primary-color);
}

/* ── Odznaka przedmiotu na komentarzu ─────────────────────────────────────── */
.comment-meta {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px;
}

.comment-subject-badge {
    display: inline-flex;
    align-items: center;
    line-height: 1;
    font-size: 0.75rem;
    font-weight: 600;
    padding: 4px 10px;
    border-radius: 999px;
    background-color: var(--bg-subtle);
    color: var(--primary-color);
}

/* Kategoria USOS na karcie przedmiotu (moduł "Przedmioty", patrz subjects.ts) - ten sam
   kształt co .comment-subject-badge wyżej, dla spójności odznak w całym serwisie. */
.subject-card-categories {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin: 4px 0 8px;
}

.subject-category-badge {
    display: inline-flex;
    align-items: center;
    line-height: 1;
    font-size: 0.72rem;
    font-weight: 600;
    padding: 3px 9px;
    border-radius: 999px;
    background-color: var(--bg-subtle);
    color: var(--primary-color);
}

/* Semestr (tylko widok szczegółów przedmiotu, na wyraźną prośbę - nie na karcie listy) - ten sam
   kształt co .subject-category-badge, ale wypełniony (nie tylko obrys koloru tekstu), żeby
   wizualnie odróżnić "kiedy jest prowadzony" od "do jakiej specjalności należy". */
.subject-semester-badge {
    background-color: var(--primary-color);
    color: #ffffff;
}

/* Grupy przedmiotu na widoku szczegółów - rozwijane (patrz subject_detail.html), przedmiot
   bywa w wielu grupach naraz i lista pigułek na stałe zajmowała za dużo pionowego miejsca.
   Semestr (patrz .subject-semester-badge) pokazuje się jako pierwsza pigułka wewnątrz, po
   rozwinięciu - na wyraźną prośbę, żeby nie zajmował miejsca jako osobny, zawsze widoczny wiersz. */
.subject-groups-details {
    margin: 4px 0 8px;
}

.subject-groups-details summary {
    cursor: pointer;
    font-size: 0.85rem;
    color: var(--text-muted);
    user-select: none;
}

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

.subject-groups-details[open] summary {
    margin-bottom: 6px;
}

.subject-groups-details .subject-card-categories {
    margin: 0;
}

/* ── "Prowadzący" (subject_detail, subjectYearDirectory.ts) ─────────────────────────────────
   Patrz subjectTeacherLinks.ts. Nagłówek sekcji mniejszy niż standardowe <h2> gdzie indziej -
   te sekcje są pomocnicze, mają nie konkurować wizualnie z tytułem strony (<h1>) tuż nad nimi. */
.subject-links-header-row {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--spacing-sm);
    margin: 0 0 6px;
    min-height: 0;
}

.subject-links-heading {
    font-size: 0.95rem;
    font-weight: 700;
    color: var(--text-color);
    margin: 0;
}

/* "Wszyscy prowadzący" (buildTeachersEditor) - lekko wyeksponowany względem reszty nagłówków
   .subject-links-heading (np. "Przedmioty tego roku" obok) - na wyraźną prośbę, ale "lekko":
   tylko trochę większy + kolor marki, nie osobny styl. */
.subject-links-heading-emphasized {
    font-size: 1.05rem;
    color: var(--primary-color);
}

/* Mała okrągła ikonka kredki (patrz EDIT_ICON_SVG w subjectTeacherLinks.ts) zamiast dawniejszej
   pigułki z napisem "Edytuj" (na wyraźną prośbę) - dopiero klik odsłania "×" przy każdej pozycji
   i pole dodania nowej; ".active" (po kliknięciu, ikonka zmienia się na "✓") ma wypełnione tło,
   żeby było jasne, że tryb edycji jest już włączony. flex-shrink:0 - nie ma się ściskać, gdy
   tekst obok (.year-summary-text) jest długi. margin-left:auto - ląduje po prawej stronie
   .subject-links-header-row, gdyby kiedyś ta gałąź (nie externalEditButton) znów była używana. */
.subject-links-edit-btn {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 20px;
    height: 20px;
    border: none;
    background-color: var(--bg-color);
    color: var(--text-muted);
    border-radius: 50%;
    padding: 0;
    cursor: pointer;
    margin-left: auto;
}

/* min-width:0 - pozwala tekstowi się skrócić/zawinąć zamiast rozpychać rodzica i spychać
   .subject-links-edit-btn poza widoczną szerokość przy bardzo długiej nazwie przedmiotu.
   flex:1 1 auto - wypełnia miejsce zostawione przez rodzica (patrz .year-directory-section
   summary/.year-subject-details summary niżej), dociskając ikonkę "Edytuj" i strzałkę do
   PRAWEGO krańca linii, niezależnie od długości nazwy przedmiotu/roku. */
.year-summary-text {
    flex: 1 1 auto;
    min-width: 0;
}

.subject-links-edit-btn:hover {
    background-color: var(--bg-subtle);
    color: var(--text-color);
}

/* "Porównaj wszystkich" obok nagłówka "Prowadzący" (patrz buildTeachersEditor w
   subjectTeacherLinks.ts) - .add-comment-btn to za duży/wysoki przycisk na ten ciasny wiersz
   nagłówka obok małej pigułki .subject-links-edit-btn, więc dociskamy padding/font-size do tej
   samej skali co reszta subject-links-header-row. */
.subject-links-compare-btn.add-comment-btn {
    padding: 2px 10px;
    font-size: 0.75rem;
}

.subject-links-edit-btn.active {
    background-color: var(--primary-color);
    color: #ffffff;
}

.subject-links-empty {
    font-size: 0.85rem;
    color: var(--text-muted);
    margin: 0 0 6px;
}

.removable-chip-row {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-bottom: 8px;
}

/* Prowadzący - zwykłą (większą) czcionką, NIE pigułki (na wyraźną prośbę). Siatka na CAŁEJ
   liście (nie per wiersz - patrz .teacher-plain-row niżej) - to jedyny sposób, żeby kolumny
   (nazwisko/ocena/poleca/łatwość) NAPRAWDĘ wyrównały się do najszerszej treści w danej kolumnie
   automatycznie ("ma być po prostu równo", nie zgadywana stała szerokość w rem - ta wcześniejsza
   wersja, minmax(0, 13rem), i tak nie dawała stałej szerokości, bo minmax nadal skraca się do
   treści). max-content x4 (nazwisko/ocena/poleca/łatwość) + auto (usuń, tylko w edycji, ma
   wypełnić resztę, żeby "×" nie odjeżdżał zbyt daleko w prawo na krótkich wierszach). */
.teacher-plain-list {
    display: grid;
    grid-template-columns: max-content max-content max-content max-content auto;
    align-items: center;
    column-gap: 10px;
    row-gap: 6px;
    margin-bottom: 8px;
    font-size: 1.05rem;
}

/* Dzieci .teacher-plain-row (nazwisko + 4 komórki z renderContent) stają się bezpośrednimi
   elementami siatki .teacher-plain-list wyżej - stąd "display: contents", nie "grid": ten div
   sam w sobie ma zniknąć z layoutu, uczestniczą w nim tylko jego dzieci. Cofnięte na telefonie
   (patrz @media niżej) - tam wracamy do prostego, zawijanego wiersza, bo tabelowe kolumny nie
   mieszczą się na wąskim ekranie (zgłoszenie: "w poziomie się przesuwa"). */
.teacher-plain-row {
    display: contents;
}

.teacher-plain-row-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 40vw;
}

/* Podkreślenie WIDOCZNE OD RAZU (nie tylko na hover jak dawniej) - na wyraźną prośbę, żeby było
   jasne, że te nazwiska są klikalne, nie zwykły tekst listy. Cieńsze/przygaszone na spoczynku
   (text-decoration-color), pełny kolor dopiero na hover - żeby lista i tak czytała się jako
   nazwiska, nie jak gęsto podkreślony blok tekstu. */
.teacher-plain-row a {
    color: var(--primary-color);
    text-decoration: underline;
    text-decoration-color: color-mix(in srgb, var(--primary-color) 35%, transparent);
    text-decoration-thickness: 1px;
    text-underline-offset: 2px;
}

.teacher-plain-row a:hover {
    text-decoration-color: currentColor;
}

.year-subject-elective-badge {
    margin-left: 8px;
    font-size: 0.7rem;
}

/* .subject-category-badge (patrz wyżej) dostaje tu link zamiast gołego tekstu + mały "×" -
   gap zamiast paddingu z prawej, żeby "×" nie przywierał do samego tekstu nazwiska/przedmiotu. */
.removable-chip {
    gap: 6px;
}

/* .subject-category-badge (nie tylko .removable-chip) - obejmuje też renderPlainChip
   (initPostSubjectsSection), gołą pigułkę-link bez "×" na profilu wykładowcy. */
.subject-category-badge a {
    color: inherit;
    text-decoration: none;
}

.subject-category-badge a:hover {
    text-decoration: underline;
}

.removable-chip-remove {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    border: none;
    background: none;
    padding: 0;
    width: 14px;
    height: 14px;
    line-height: 1;
    font-size: 0.85rem;
    color: var(--text-muted);
    cursor: pointer;
}

.removable-chip-remove:hover {
    color: var(--danger-color);
}

.removable-chip-remove::-moz-focus-inner {
    border: 0;
}

/* ── Widok "wybierz rok" (subjectYearDirectory.ts, browse_subjects_by_year.html) ──────────── */
.year-directory-section {
    border: 1px solid var(--card-border);
    border-radius: var(--spacing-sm);
    padding: 10px 14px;
    margin-bottom: var(--spacing-sm);
}

/* display:flex BEZPOŚREDNIO na <summary> (nie na jakimś owiniętym w środku spanie) - próba
   owinięcia zawartości w osobny element z display:flex/inline-flex i width:100% (poprzednia
   wersja tej reguły) NIE działała (zgłoszenie: "strzałki się rozjechały"): natywny marker
   <summary> (display:list-item) zajmuje kawałek pierwszej linii, a dziecko o width:100%
   WZGLĘDEM CAŁEJ szerokości <summary> (czyli szerszej niż to, co zostało obok markera) już się
   tam nie mieści i ląduje na WŁASNEJ, drugiej linii - zweryfikowane empirycznie (Playwright,
   bounding rect dziecka), nie tylko teoretycznie z dokumentacji CSS. Zamiast tego - dokładnie
   ten sam, sprawdzony już w tym pliku wzorzec co .faq-question niżej: <summary> SAM staje się
   kontenerem flex, natywny marker jest schowany (list-style:none + ::-webkit-details-marker),
   a strzałkę rysujemy sami jako ::before na początku (patrz niżej, na wyraźną prośbę po LEWEJ
   stronie, nie po prawej jak .faq-question) - wtedy nie ma już żadnego "markera obok flexa",
   więc problem znika przy okazji. */
.year-directory-section summary {
    display: flex;
    align-items: center;
    gap: 8px;
    list-style: none;
    cursor: pointer;
    font-weight: 700;
    font-size: 1.05rem;
    color: var(--text-color);
    user-select: none;
}

.year-directory-section summary::-webkit-details-marker {
    display: none; /* to samo co list-style:none wyżej, ale dla Chrome/Safari (webkit) */
}

/* Własna strzałka zamiast schowanego wyżej natywnego markera - ::before (nie ::after), żeby
   lądowała na LEWYM końcu linii, przed tekstem (na wyraźną prośbę - wszystkie strzałki po
   lewej). Ten sam SVG-chevron co .faq-question::after niżej w tym pliku, tu jednak obrócony o
   -90deg w spoczynku (strzałka W PRAWO - "rozwiń") i do 0deg po rozwinięciu (W DÓŁ - na
   wyraźną prośbę, zamiast poprzedniego 0deg/180deg "w dół"/"w górę"). */
.year-directory-section summary::before {
    content: "";
    flex-shrink: 0;
    width: 14px;
    height: 14px;
    background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23404040' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e");
    background-repeat: no-repeat;
    background-position: center;
    background-size: 14px;
    transition: transform 0.2s ease;
    transform: rotate(-90deg);
}

.year-directory-section[open] summary::before {
    transform: rotate(0deg);
}

.year-directory-section summary:hover {
    color: var(--primary-color);
}

.year-directory-section[open] summary {
    margin-bottom: 6px;
}

.year-subject-list {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

/* Wiersz przedmiotu - opakowuje .year-subject-details (patrz renderSubjectDetails w
   subjectYearDirectory.ts) + ewentualny "×" (usuń przedmiot z TEGO roku) jako rodzeństwo, NIE
   dziecko <details> - inaczej "×" byłby niewidoczny, dopóki ktoś nie rozwinie wiersza. */
.year-subject-row {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    padding: 4px 0;
    border-bottom: 1px solid var(--card-border);
}

.year-subject-row:last-child {
    border-bottom: none;
}

.year-subject-details {
    flex: 1;
    min-width: 0;
}

/* Bez pogrubienia (w odróżnieniu od nagłówka roku wyżej, .year-directory-section summary) - to
   już nie link do osobnej strony, tylko sam przełącznik rozwiń/zwiń, nie ma potrzeby wizualnie
   "krzyczeć" tak samo mocno jak rok. Reszta (flex/schowany marker/własna strzałka) - patrz
   komentarz przy .year-directory-section summary wyżej, ten sam problem i to samo rozwiązanie. */
.year-subject-details summary {
    display: flex;
    align-items: center;
    gap: 8px;
    list-style: none;
    cursor: pointer;
    font-weight: 400;
    color: var(--text-color);
    user-select: none;
}

.year-subject-details summary::-webkit-details-marker {
    display: none;
}

.year-subject-details summary::before {
    content: "";
    flex-shrink: 0;
    width: 14px;
    height: 14px;
    background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23404040' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e");
    background-repeat: no-repeat;
    background-position: center;
    background-size: 14px;
    transition: transform 0.2s ease;
    transform: rotate(-90deg);
}

.year-subject-details[open] summary::before {
    transform: rotate(0deg);
}

.year-subject-details summary:hover {
    color: var(--primary-color);
}

.year-subject-details-body {
    margin: 6px 0 4px 4px;
}

/* "×" (usuń przedmiot z roku) - patrz .year-subject-row wyżej, jest teraz rodzeństwem
   .year-subject-details, nie potrzebuje już margin-left:auto (flex gap już go odsuwa). */

/* Pole "Dodaj prowadzącego/przedmiot" - własna klasa (nie goły .search-with-suggestions) tylko
   po to, żeby ograniczyć szerokość (domyślnie na całą szerokość kontenera, jak w formularzu
   opinii - tutaj to osobna, wąska sekcja, więc pełna szerokość wyglądałaby nie na miejscu). */
.subject-link-search {
    max-width: 320px;
    margin-bottom: var(--spacing-sm);
}

/* Pigułka "poleca/odradza ponowny wybór" na POJEDYNCZEJ opinii (patrz
   renderCommentWouldTakeAgainBadge w comments.ts) - ten sam kształt co .comment-subject-badge
   (spójna linia odznak w .comment-meta), kolor przejęty z .rating-tier-good/poor, żeby "poleca"
   i "odradza" niosły to samo znaczenie koloru co dobra/zła średnia gwiazdek gdzie indziej. */
.comment-would-take-again-badge {
    display: inline-flex;
    align-items: center;
    line-height: 1;
    font-size: 0.75rem;
    font-weight: 600;
    padding: 4px 10px;
    border-radius: 999px;
    background-color: var(--bg-subtle);
}

.comment-would-take-again-badge.would-take-again-yes {
    color: var(--rating-good);
}

.comment-would-take-again-badge.would-take-again-no {
    color: var(--danger-color);
}

/* ── Grupowanie komentarzy wg przedmiotu ──────────────────────────────────── */
.comment-group {
    margin-bottom: var(--spacing-lg);
}

.comment-group-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--spacing-sm);
    border-bottom: 2px solid var(--card-border);
    padding-bottom: 4px;
    margin-bottom: var(--spacing-sm);
}

/* Etykiety typu "Dodaj komentarz do tego przedmiotu" są dłuższe niż inne przyciski tego typu
   (np. "+ Porównaj") - bez tego, na wąskich telefonach wychodziły poza ekran zamiast się zawijać. */
.comment-group-header .add-comment-btn {
    flex-shrink: 1;
    max-width: 100%;
    white-space: normal;
    text-align: left;
}

.comment-group-title {
    display: flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
}

.comment-group-collapse-btn {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    flex-shrink: 0;
    width: 24px;
    height: 24px;
    padding: 0;
    border: none;
    background-color: transparent;
    cursor: pointer;
    background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23404040' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e");
    background-repeat: no-repeat;
    background-position: center;
    background-size: 18px;
    transition: transform 0.2s ease;
}

.comment-group-collapse-btn::-moz-focus-inner {
    border: 0;
}

.comment-group-collapse-btn:focus {
    outline: none;
}

.comment-group-collapse-btn:focus-visible {
    outline: 2px solid var(--primary-color);
    outline-offset: 2px;
    border-radius: 4px;
}

.comment-group-collapsed .comment-group-collapse-btn {
    transform: rotate(-90deg);
}

.comment-group-collapsed .comment-group-list,
.comment-group-collapsed .comment-group-quick-form {
    display: none;
}

.comment-group-header h3 {
    margin-top: 0;
}

.add-comment-btn {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    flex-shrink: 0;
    border: 1px solid var(--border-color);
    border-radius: 999px;
    background-color: transparent;
    color: var(--primary-color);
    padding: 6px 14px;
    font-family: inherit;
    font-size: 0.85rem;
    font-weight: 600;
    white-space: nowrap;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    transition: background-color 0.2s ease, border-color 0.2s ease, transform 0.1s ease;
}

.add-comment-btn-icon {
    font-size: 1.1rem;
    line-height: 1;
}

.add-comment-btn::-moz-focus-inner {
    border: 0;
}

.add-comment-btn:focus {
    outline: none;
}

.add-comment-btn:focus-visible {
    outline: 2px solid var(--primary-color);
    outline-offset: 2px;
}

.add-comment-btn:hover {
    background-color: var(--bg-subtle);
    border-color: var(--primary-color);
}

.add-comment-btn:active {
    transform: translateY(1px);
}

/* Podświetlenie przycisku, którego formularz jest właśnie otwarty */
.add-comment-btn.active {
    background-color: var(--primary-color);
    border-color: var(--primary-color);
    color: #ffffff;
}

.add-comment-btn.active:hover {
    background-color: var(--primary-color-hover);
}

/* Ciemny, wypełniony wariant "Dodaj" pod wynikami wyszukiwania (patrz emphasized w
   renderAddPersonButton w addLecturer.ts) - używany, gdy duży przycisk obok wyszukiwarki jest
   schowany (lista dłuższa niż MANY_POSTS_THRESHOLD w browser.ts), więc to jedyny sposób dodania
   osoby na tej stronie i ma być od razu widoczny, nie wyglądać jak drugorzędna akcja. Ten sam
   wygląd co .add-comment-btn.active (żeby nie mnożyć wariantów kolorystycznych), tylko osobna
   klasa - .active ma tu inne, niezwiązane znaczenie (otwarty formularz). */
.add-comment-btn.add-comment-btn-emphasized {
    background-color: var(--primary-color);
    border-color: var(--primary-color);
    color: #ffffff;
}

.add-comment-btn.add-comment-btn-emphasized:hover {
    background-color: var(--primary-color-hover);
}

/* Stały, wyraźny przycisk "Dodaj osobę" obok wyszukiwarki (patrz renderAddPersonButton w
   addLecturer.ts) - to teraz jedyny sposób dodania kogoś, kogo nie ma na liście, więc ma być
   ciemny i widoczny od razu, nie chowany pod wynikami jak dawniej "Nie znalazłeś wykładowcy?". */
.add-person-btn {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    flex-shrink: 0;
    border: 1px solid var(--primary-color);
    border-radius: 8px;
    background-color: var(--primary-color);
    color: #ffffff;
    padding: 10px 16px;
    font-family: inherit;
    font-size: 0.9rem;
    font-weight: 600;
    white-space: nowrap;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    transition: background-color 0.2s ease, border-color 0.2s ease, transform 0.1s ease;
}

.add-person-btn:hover {
    background-color: var(--primary-color-hover);
    border-color: var(--primary-color-hover);
}

.add-person-btn:active {
    transform: translateY(1px);
}

.add-person-btn:focus {
    outline: none;
}

.add-person-btn:focus-visible {
    outline: 2px solid var(--primary-color);
    outline-offset: 2px;
}

/* Pusty wydział (0 osób) - patrz gałąź "state.posts.length === 0" w render() w browser.ts.
   Przerywana ramka zamiast pełnej .comment-card, żeby od razu czytać się jako "tu jeszcze nic
   nie ma", a nie jako karta osoby. */
.empty-faculty-state {
    text-align: center;
    padding: var(--spacing-lg) var(--spacing-md);
    border: 1px dashed var(--card-border);
    border-radius: 8px;
}

.empty-faculty-heading {
    margin: 0 0 4px;
    font-size: 1.1rem;
    font-weight: 600;
}

.empty-faculty-subtext {
    margin: 0;
    color: var(--text-muted);
}

/* Nagłówek "Czy chodziło Ci o:" nad podpowiedziami w popupie "Dodaj osobę" (patrz
   renderSuggestions w addLecturer.ts) - sam tekst, nie klikalny (stąd div, nie
   .search-suggestion-item) - attachDropdownKeyboardNav w generics.ts pomija go, bo szuka tylko
   przycisków tej drugiej klasy. */
.search-suggestions-header {
    padding: 8px 14px;
    font-size: 0.8rem;
    color: var(--text-muted);
    border-bottom: 1px solid var(--card-border);
}

/* Wydział znany z kontekstu strony (patrz facultyContextEl w openAddPersonDialog w
   addLecturer.ts) - pasek NAD tytułem dialogu (nie pole formularza w ramce - nie da się go tu
   zmienić). Ujemny margines = pełna szerokość dialogu poza jego wewnętrznym paddingiem (patrz
   .add-review-dialog), zaokrąglone TYLKO górne rogi (te same 12px co dialog), żeby wyglądało jak
   osobny pasek nad główną treścią, a nie kolejna linijka tekstu w formularzu. :empty - gdy wydział
   NIE jest znany z góry (widok całej uczelni, wybiera się go w formularzu niżej), ten element
   zostaje bez treści i ma się wtedy w ogóle nie renderować (bez tego byłby widoczny jako pusty,
   ale wciąż podświetlony pasek). */
.add-person-faculty-note {
    margin: -8px -24px 16px;
    padding: 10px 24px;
    background-color: var(--bg-subtle);
    border-radius: 12px 12px 0 0;
    color: var(--text-muted);
    font-size: 0.85rem;
}

.add-person-faculty-note:empty {
    display: none;
}

/* Podziękowanie + status moderacji po dodaniu osoby (patrz showAfterCloseNotice w
   addLecturer.ts) - pokazuje się DOPIERO po zamknięciu popupu, jako baner nad treścią strony,
   ten sam wzorzec co dawny .quick-review-thanks-banner (lewy pasek + przezroczyste tło w
   kolorze akcentu, tu w zielonym - to potwierdzenie sukcesu, nie ostrzeżenie/podpowiedź). */
.add-person-thanks-banner {
    background: rgba(46, 125, 79, 0.12);
    border-left: 3px solid var(--rating-good);
    border-radius: 8px;
    padding: var(--spacing-md);
    margin-bottom: var(--spacing-md);
    color: var(--text-color);
    font-size: 0.95rem;
    line-height: 1.5;
}

.add-person-thanks-banner p {
    margin: 0 0 var(--spacing-sm) 0;
}

.add-person-thanks-banner p:last-child {
    margin-bottom: 0;
}

.comment-group-quick-form:not(:empty) {
    margin-bottom: var(--spacing-md);
}

.comment-group-empty {
    color: var(--text-muted);
    font-size: 0.9rem;
    font-style: italic;
    padding-left: var(--spacing-sm);
}

/* Pusty stan całej listy komentarzy (zero opinii, nie tylko pusta jedna grupa/przedmiot -
   patrz .comment-group-empty wyżej) - bardziej widoczny niż ta druga, bo to jedyna treść
   na stronie w tym miejscu, nie mały dopisek pod nagłówkiem sekcji. */
.comments-empty {
    color: var(--text-color);
    opacity: 0.75;
    font-size: 0.95rem;
    text-align: center;
    padding: var(--spacing-lg) var(--spacing-md);
    border: 1px dashed var(--card-border);
    border-radius: 8px;
}

/* ── Przycisk "Porównaj" na karcie wykładowcy ─────────────────────────────── */
.comment-card {
    position: relative;
}

.compare-toggle-btn {
    margin: var(--spacing-sm) 0 0 var(--spacing-md);
    padding: 4px 11px;
    font-size: 0.78rem;
}

.compare-toggle-btn .add-comment-btn-icon {
    font-size: 0.95rem;
}

/* .comment-card-meta (gwiazdki+"Porównaj" albo "Brak opinii") jest zwykłym block divem (bez
   flex) - gwiazdki (inline-flex) i <button> w środku leżą więc obok siebie jak tekst, a
   "Porównaj" przeskakuje pod spód TYLKO gdy faktycznie zabraknie poziomego miejsca (zgłoszenie:
   wcześniejszy flex-direction: column zjeżdżał "Porównaj" do osobnej linijki nawet przy mnóstwie
   wolnego miejsca obok gwiazdek). Odstęp do h2 wyżej jest ściągany przez margin-bottom na samym
   h2 (patrz tam), nie tutaj - w em, żeby skalował się razem z font-size nagłówka na każdym
   ekranie, zamiast osobnej kalibracji px per-breakpoint. */
.comment-card-meta {
    margin-top: 0;
}

/* .comment-card-no-reviews - neutralny placeholder zamiast pustych/zerowych gwiazdek - te
   wyglądałyby jak realna, słaba ocena, nie jak "jeszcze nikt nie ocenił". Czysto statyczny tekst
   (był tu wcześniej klikalny <button> z hover->"Dodaj opinię" i popupem - świadomie usunięty: na
   telefonie hover nie istnieje, więc nic tego nie zapowiadało, a funkcja niepotrzebnie
   komplikowała kartę). margin-left: 0 - lewa krawędź liter ma się pokrywać z lewą krawędzią h2
   wyżej (ten sam left padding karty, patrz .comment-card). */
.comment-card-no-reviews {
    display: block;
    margin: 2px 0 0 0;
    color: var(--text-muted);
    font-style: italic;
    font-size: 0.9em;
    line-height: 1.2;
}

/* Nazwisko i imię wykładowcy razem z przyciskiem "Porównaj" w jednej linii (nie w osobnym
   wierszu pod spodem, jak w .lecturer-header-row niżej) - align-items: center, bo h1 jest dużo
   wyższy niż mała "pigułka" przycisku. */
.lecturer-name-row {
    display: flex;
    align-items: center;
    gap: var(--spacing-md);
    flex-wrap: wrap;
}

/* Wydział pod imieniem/nazwiskiem (patrz confirmed_faculty w views.post_detail) - tylko dla
   potwierdzonego, jednoznacznego wydziału; celowo stonowany (nie ma pretendować do bycia
   breadcrumbem), głównie ważny na uczelniach bez ustalonej listy wydziałów do przeglądania. */
.lecturer-faculty-line {
    display: block;
    margin-top: -8px;
    margin-bottom: var(--spacing-sm);
    color: var(--text-muted);
    text-decoration: none;
}

.lecturer-faculty-line:hover {
    text-decoration: underline;
}

/* Wiersz "Dodaj opinię" + sortowanie, w jednej linii, równo. */
.lecturer-header-row {
    display: flex;
    align-items: center;
    gap: var(--spacing-md);
    flex-wrap: wrap;
    margin: var(--spacing-sm) 0 var(--spacing-md);
}

#compare-button-container .compare-toggle-btn {
    margin: 0;
}

/* Podpowiedź limitu opinii (patrz addReviewBtn w post_detail.ts) - ukryta domyślnie
   (visibility+opacity zamiast display:none, żeby transition faktycznie zadziałał), pojawia się
   na chwilę obok przycisku "Dodaj opinię" i sama znika. */
.add-review-hint {
    font-size: 0.8rem;
    color: var(--text-muted);
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.2s ease;
}

.add-review-hint.visible {
    opacity: 1;
    visibility: visible;
}

/* Przycisk "Dodaj opinię" w nagłówku - tej samej wielkości/koloru co Opublikuj/Wróć */
.add-review-btn {
    background-color: var(--primary-color);
    color: #ffffff;
    border: 1px solid var(--primary-color);
    padding: 10px 24px;
    border-radius: 8px;
    font-size: 1rem;
    font-weight: 600;
    cursor: pointer;
    font-family: inherit;
    transition: background-color 0.2s ease, color 0.2s ease, transform 0.1s ease;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.add-review-btn:hover {
    background-color: var(--primary-color-hover);
}

.add-review-btn:active {
    transform: translateY(1px);
}

/* Gdy formularz jest otwarty - przycisk robi się jasny (zamiast ciemnego wypełnienia),
   żeby było widać że stan się zmienił (tak samo jak inne przyciski "+" w formularzach).
   ".limit-reached" (patrz hasAlreadyReviewedThisPost w post_detail.ts) - user już dodał opinię
   do tego profilu i nie doda kolejnej (limit "jedna opinia na profil") - ten sam jasny wygląd
   od razu, zanim jeszcze kliknie, zamiast zachęcającego pomarańczowego wypełnienia. */
.add-review-btn.active,
.add-review-btn.limit-reached {
    background-color: transparent;
    color: var(--primary-color);
    border-color: var(--border-color);
}

.add-review-btn.active:hover,
.add-review-btn.limit-reached:hover {
    background-color: var(--bg-subtle);
    border-color: var(--primary-color);
}

/* Główny formularz jest domyślnie schowany - otwiera go przycisk "Dodaj opinię" */
#comment-form {
    display: none;
}

#comment-form.comment-form-open {
    display: block;
}

/* ── Modal "Dodaj opinię" (patrz ADD_REVIEW_MODAL_ENABLED w generics.ts) ─────────────────────
   Natywny <dialog>, budowany w JS (post_detail.ts) przez przeniesienie #comment-form do środka -
   stąd selektor niżej musi pobić samo "#comment-form { display: none }" wyżej (specyficzność
   klasa+typ+ID > samo ID), żeby formularz był widoczny, gdy dialog jest otwarty. Przy wyłączonej
   fladze ta reguła po prostu nigdy nie ma się do czego zastosować (dialog nigdy nie powstaje) -
   strona wraca 1:1 do starego zachowania bez zmian w szablonie HTML. showModal()/close() (nie
   ręczny overlay+backdrop div) dają za darmo: wyśrodkowanie i renderowanie w "top layer"
   (niezależnie od położenia w drzewie DOM czy przodków z overflow/transform), pułapkę fokusu,
   zamykanie Escape, oraz ::backdrop. */
dialog.add-review-dialog #comment-form {
    display: block;
}

.add-review-dialog {
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%) scale(0.96);
    margin: 0;
    /* Było 32px, potem 20px góra - dalej za dużo pustej przestrzeni nad tytułem (zgłoszenie: "biały
       pasek kompletnie out"). 8px - to samo co odsunięcie × (patrz .add-review-dialog-close niżej)
       - tytuł ma dodatkowo padding-right (patrz .add-review-dialog-title), żeby długie imię i
       nazwisko nigdy nie renderowało się POD przyciskiem, tylko zawinęło wcześniej. */
    padding: 8px 24px 24px;
    border: none;
    border-radius: 12px;
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.25);
    /* 480-720px to standardowy zakres szerokości modala z formularzem (mieści etykietę + pole w
       jednej linii bez zawijania, ale nie jest "ekranowo" szerokie na desktopie). */
    width: min(560px, calc(100vw - 2 * var(--spacing-md)));
    max-height: 80vh;
    overflow-y: auto;
    background-color: var(--bg-color);
    color: var(--text-color);
    /* Lekkie pojawienie się (fade+scale) zamiast domyślnego "snap" przy showModal()/close() -
       szczególnie widoczne, gdy modal to CEL nawigacji z listy (patrz ?dodaj_opinie=1 w
       post_detail.ts - "Dodaj pierwszą opinię"): bez tego, zaraz po twardym przejściu MPA,
       dialog wyskakiwał na całej stronie bez żadnego przejścia. @starting-style + `allow-discrete`
       niżej - standardowy sposób animowania natywnego <dialog>, bez JS; przeglądarki bez wsparcia
       dostają dokładnie dotychczasowe, natychmiastowe zachowanie. */
    opacity: 0;
    transition: opacity 0.18s ease, transform 0.18s ease, overlay 0.18s ease allow-discrete, display 0.18s ease allow-discrete;
}

.add-review-dialog[open] {
    transform: translate(-50%, -50%) scale(1);
    opacity: 1;
}

@starting-style {
    .add-review-dialog[open] {
        transform: translate(-50%, -50%) scale(0.96);
        opacity: 0;
    }
}

/* "Lekko przyciemnij tło" - trochę ciemniej niż domyślne 0.5, żeby modal wyraźniej odcinał się
   od reszty strony pod spodem. Przyciemnianie się animuje razem z modalem (patrz wyżej) - ten sam
   `allow-discrete` powód. */
.add-review-dialog::backdrop {
    background-color: rgba(0, 0, 0, 0);
    transition: background-color 0.18s ease, overlay 0.18s ease allow-discrete, display 0.18s ease allow-discrete;
}

.add-review-dialog[open]::backdrop {
    background-color: rgba(0, 0, 0, 0.68);
}

@starting-style {
    .add-review-dialog[open]::backdrop {
        background-color: rgba(0, 0, 0, 0);
    }
}

@media (prefers-reduced-motion: reduce) {
    .add-review-dialog,
    .add-review-dialog::backdrop {
        transition: none;
    }
}

/* Formularz w środku nie potrzebuje własnej ramki/paddingu - dialog już je ma. */
.add-review-dialog .comment-form-box {
    border: none;
    padding: 0;
    margin-bottom: 0;
}

/* Tytuł zawiera imię i nazwisko wykładowcy (patrz dialogTitle w post_detail.ts) - nie ma już
   osobnego podtytułu pod nim, więc odstęp do pierwszego pola ("Ocena:") to ten sam 16px co
   między wszystkimi innymi polami niżej (patrz .collapsible-inner), nie osobna wartość. */
.add-review-dialog-title {
    font-size: 1.25rem;
    margin-bottom: 16px;
    /* Miejsce na × (patrz .add-review-dialog-close - position: absolute, right: 8px, ~32px
       szerokości) - bez tego długie imię i nazwisko mogłoby renderować się POD przyciskiem
       zamiast wcześniej zawinąć się do kolejnej linii (padding niżej góra dialogu jest teraz
       bardzo mały, więc oba elementy zaczynają się na tej samej wysokości). */
    padding-right: 36px;
}

/* ── Układ pól WEWNĄTRZ modala: w pełni pionowy stos, etykieta ZAWSZE nad polem (poza "Ocena:" -
   patrz .rating-field niżej, celowo kompaktowe obok siebie), jeden spójny odstęp (16px - siatka
   8px; było 24px, za dużo - zgłoszenie: "prawie cała linijka") między każdą parą etykieta+pole,
   niezależnie od tego, czym to pole jest. Stary układ (patrz .comment-form-row/
   .comment-form-bottom-row wyżej) był strojony pod szeroki, jednowierszowy kontener inline - w
   węższym (i przybliżonym o 110%, patrz zoom na body) oknie modala ten sam układ "rozjeżdżał
   się": pole przedmiotu kurczyło się do nieczytelnej szerokości, odstępy między sekcjami różniły
   się od siebie. Zamiast łatać stare reguły, modal dostaje własny, w pełni przewidywalny layout
   oparty o flex + gap (nie o osobno strojone margin-bottom na każdym elemencie - stąd zerowanie
   ich niżej). ── */
.add-review-dialog .collapsible-inner {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

/* Puste <span class="error"> (patrz initCommentForm w comments.ts) nie powinny "zjadać" odstępu
   z gap wyżej, tak jakby były realną, widoczną treścią - inaczej pole z akurat pustym błędem obok
   siebie miałoby WIĘKSZY odstęp niż pole bez takiego (niewidocznego) sąsiada. :empty dopasowuje
   TYLKO span bez żadnej treści (JS czyści .textContent = "" po każdej próbie wysyłki) - gdy błąd
   faktycznie się pojawia, przestaje być :empty i wraca do normalnego wyświetlania. */
.add-review-dialog .error:empty {
    display: none;
}

.add-review-dialog .comment-form-row,
.add-review-dialog .comment-form-bottom-row {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 16px;
    margin: 0;
}

/* Etykieta NAD polem (nie obok) - ta sama zasada co .comment-body-label, teraz też dla
   "Przedmiot..." i "Z którego wydziału..." (patrz .subject-picker niżej - dzieli tę klasę z
   .faculty-picker, patrz renderFacultyPicker w comments.ts), żeby te pola mają identyczny rytm
   (etykieta, mały odstęp, pole). NIE .rating-field ("Ocena:") - ta zostaje kompaktowa, etykieta
   OBOK gwiazdek (patrz .rating-field niżej), na wyraźną prośbę - i NIE .would-take-again-field,
   której etykieta dostaje odstęp z własnego flex gap (patrz niżej), więc dodatkowy margin-bottom
   tutaj by go podwoił. */
.add-review-dialog .subject-picker .field-label-text {
    display: block;
    white-space: normal;
    margin-bottom: 8px;
}

/* "Ocena:" obok gwiazdek, w jednej linii (na wyraźną prośbę - poprzednia wersja, etykieta NAD
   gwiazdkami, zajmowała niepotrzebnie dużo pionowej przestrzeni). Domyślny inline flow (span +
   inline-block .star-rating-widget) wystarcza - bez flex, dokładnie jak przed przebudową modala. */
.add-review-dialog .rating-field {
    margin-left: 0;
}

.add-review-dialog .rating-field .field-label-text {
    margin-right: 8px;
}

/* .subject-picker (nie ".comment-form-row .subject-picker") - obejmuje zarówno przedmiot
   (zagnieżdżony w .comment-form-row) jak i picker wydziału (patrz .faculty-picker w
   renderFacultyPicker w comments.ts - dzieli klasę .subject-picker, ale wisi bezpośrednio w
   .collapsible-inner, bez .comment-form-row nad sobą) - oba potrzebują tego samego resetu. */
.add-review-dialog .subject-picker {
    /* ".comment-form-row .subject-picker { flex: 1 1 240px }" (patrz reguła wyżej w pliku) było
       myślane pod POZIOMY wiersz (240px = szerokość) - .comment-form-row w modalu jest teraz
       flex-direction: column (patrz reguła wyżej), więc ten sam flex-basis zacząłby liczyć się
       jako WYSOKOŚĆ (240px+ przez flex-grow: 1) zamiast szerokości, robiąc z pola przedmiotu
       ogromną, pustą kolumnę. flex: 0 1 auto (bez grow, naturalna wysokość) to resetuje. */
    flex: 0 1 auto;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    max-width: none;
    min-width: 0;
}

/* Lekko mniejsze niż domyślne pole tekstowe (10px/12px pionowo/poziomo, patrz baza wyżej) - w
   modalu, obok krótkiej etykiety nad nim, pełnowymiarowe pole wyglądało nieproporcjonalnie duże. */
.add-review-dialog .subject-picker input[type="text"] {
    padding: 8px 32px 8px 10px;
    font-size: 0.9rem;
}

/* Rozwijana lista (patrz .search-suggestions - baza 340px/60vh) rozwijała się niemal do samego
   dołu modala (zgłoszenie) - w kompaktowym modalu, z mniejszym marginesem u góry/dołu niż stary,
   pełnoekranowy inline kontekst, ten sam limit wyglądał na nieproporcjonalnie wysoki. Krótsza
   lista (dalej przewijalna - overflow: hidden auto dziedziczy się z bazy) zostawia widoczny
   kawałek reszty formularza pod spodem. */
.add-review-dialog .subject-picker .search-suggestions {
    max-height: 200px;
}

/* Wydział: etykieta obok pola w JEDNEJ linii, jeśli się mieści - w odróżnieniu od przedmiotu
   wyżej (zawsze kolumnowo, na wyraźną prośbę). flex-wrap zamiast media query - gdy zabraknie
   miejsca (wąski telefon), pole samo spada pod etykietę na drugą linię. */
.add-review-dialog .faculty-picker {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
}

.add-review-dialog .faculty-picker .field-label-text {
    display: inline;
    white-space: normal;
    margin-bottom: 0;
}

.add-review-dialog .faculty-picker .search-with-suggestions {
    flex: 1 1 200px;
    min-width: 0;
}

/* Popup "Dodaj osobę" (patrz addLecturer.ts) - te same wymiary co zwykłe "Dodaj opinię" (patrz
   .add-review-dialog wyżej), ale na czas, gdy podpowiedzi (position:absolute) mogą się jeszcze
   otworzyć, BEZ przycinania overflow - dzięki temu mają prawo wystawać poza sam obrys popupu (na
   ciemne tło pod spodem), zamiast być ucinane na jego krawędzi albo wymuszać sztucznie większy/
   wyższy dialog, żeby się w nim zmieściły (próbowaliśmy tego wcześniej - zgłoszenie: "trochę to
   zmniejsz jednak"). Po rozstrzygnięciu, kim jest dodawana osoba, podpowiedzi już się nie otworzą
   ponownie - JS (patrz restoreDialogScroll w addLecturer.ts) przywraca wtedy zwykłe
   overflow-y:auto inline'em, żeby dało się przescrollować do przycisku wysyłki, gdy cały
   formularz opinii jest wyższy niż ekran (zgłoszenie: "Podziel się opinią" ucięte na dole). */
.add-person-dialog {
    overflow: visible;
}

/* Tytuł "Dodaj osobę" -> "Imię i nazwisko" - odstęp minimalnie mniejszy niż bazowe 16px
   (patrz .add-review-dialog-title), bo tu nie ma dłuższego podtytułu pod tytułem jak przy opinii. */
.add-person-dialog .add-review-dialog-title {
    margin-bottom: 11px;
}

.add-review-dialog textarea {
    min-height: 110px;
}

/* "Polecasz tę osobę? [Tak] [Nie]" w jednym wierszu, gdy się mieści (patrz baza CSS wyżej) - na
   wąskim telefonie flex-wrap zsuwa przyciski pod etykietę zamiast wypychać je poza modal. */
.add-review-dialog .would-take-again-field {
    flex-wrap: wrap;
}

/* Przycisk wysyłki na pełną szerokość - jasny, jednoznaczny "primary" CTA modala (starsze
   "margin-left: auto" z .comment-form-bottom-row wyżej pcha przycisk w prawo TYLKO gdy zostaje mu
   wolne miejsce - przy width: 100% nie ma czego rozdzielać, więc nie trzeba tamtej reguły
   nadpisywać osobno). Też min-height 44px (Apple/Google HIG - minimalny wygodny obszar dotyku). */
.add-review-dialog .comment-form-bottom-row button[type="submit"] {
    width: 100%;
    min-height: 44px;
}

.add-review-dialog-close {
    position: absolute;
    top: var(--spacing-sm);
    right: var(--spacing-sm);
    background: none;
    border: none;
    font-size: 1.5rem;
    line-height: 1;
    cursor: pointer;
    color: var(--text-muted);
    padding: 4px 8px;
}

.add-review-dialog-close:hover {
    color: var(--text-color);
}

/* ── Pływający pasek "koszyka" porównania (widoczny na każdej stronie poza
   samą stroną porównania) - celowo mały i stonowany, żeby nie przeszkadzał. ── */
.compare-bar {
    position: fixed;
    left: 50%;
    bottom: var(--spacing-sm);
    transform: translateX(-50%);
    z-index: 100;
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    background-color: var(--bg-color);
    color: var(--text-color);
    border: 1px solid var(--card-border);
    padding: 5px 10px;
    border-radius: 999px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
    max-width: calc(100% - 2 * var(--spacing-md));
    font-size: 0.8rem;
}

/* Pierwsze w życiu przeglądarki pojawienie się paska (patrz shouldShowIntroAnimation w
   compareBar.ts) - dwa krótkie "pulsy" w kolorze marki, żeby zwrócić uwagę na pasek, który
   użytkownicy normalnie przeoczają. transform musi za każdym razem zawierać translateX(-50%) -
   inaczej animacja zresetowałaby wyśrodkowanie z reguły wyżej. */
.compare-bar-intro {
    animation: compare-bar-intro-pulse 1.3s ease-in-out 0.15s 2;
}

@keyframes compare-bar-intro-pulse {
    0%, 100% {
        transform: translateX(-50%) scale(1);
        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
    }
    50% {
        transform: translateX(-50%) scale(1.07);
        box-shadow: 0 4px 18px rgba(242, 129, 0, 0.55);
    }
}

.compare-bar-count {
    font-weight: 500;
    white-space: nowrap;
    opacity: 0.8;
}

.compare-bar-link {
    color: var(--primary-color);
    background-color: var(--bg-subtle);
    border-radius: 999px;
    padding: 4px 10px;
    text-decoration: none;
    font-weight: 600;
    white-space: nowrap;
    transition: background-color 0.2s ease;
}

.compare-bar-link:hover {
    background-color: #e6e7ea;
}

.compare-bar-clear {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    border: none;
    background-color: transparent;
    color: var(--text-color);
    opacity: 0.6;
    padding: 4px 6px;
    font-family: inherit;
    font-size: inherit;
    font-weight: 500;
    cursor: pointer;
    white-space: nowrap;
    transition: opacity 0.2s ease, color 0.2s ease;
}

.compare-bar-clear:hover {
    opacity: 1;
    color: var(--danger-color);
}

/* ── Baner o zmianie nazwy (przekierowanie ze starej domeny muminopinie.pl) - patrz
   OldDomainRedirectMiddleware w pages/middleware.py i base.html ── */
.rename-banner {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--spacing-md);
    background-color: var(--primary-color);
    color: #ffffff;
    padding: var(--spacing-sm) var(--spacing-md);
    text-align: center;
}

.rename-banner-text {
    margin: 0;
    font-size: 0.95rem;
}

.rename-banner-close {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    border: none;
    background: transparent;
    color: inherit;
    font-size: 1.4rem;
    line-height: 1;
    cursor: pointer;
    padding: 0 var(--spacing-sm);
    flex-shrink: 0;
}

/* ── Baner zgody na cookies (Google Analytics) - patrz cookieConsent.ts ── */
.cookie-consent-banner {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 200;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: var(--spacing-md);
    background-color: var(--bg-color);
    color: var(--text-color);
    border-top: 1px solid var(--card-border);
    padding: var(--spacing-sm) var(--spacing-md);
    box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.12);
    /* Wjazd od dołu - patrz cookieConsent.ts po co (nie tylko estetyka) */
    transform: translateY(100%);
    opacity: 0;
    transition: transform 0.25s ease, opacity 0.25s ease;
}

.cookie-consent-banner-visible {
    transform: translateY(0);
    opacity: 1;
}

.cookie-consent-text {
    margin: 0;
    /* Nie "flex: 1 1 320px" (rosnący) - inaczej tekst zajmuje całą dostępną szerokość i
       wypycha przyciski na sam prawy kraj baneru, zamiast trzymać je tuż obok tekstu jako
       jedną wyśrodkowaną grupę (patrz justify-content: center na .cookie-consent-banner). */
    flex: 0 1 auto;
    max-width: 60ch;
    font-size: 0.95rem;
}

.cookie-consent-text a {
    color: var(--primary-color);
    text-decoration: underline;
}

.cookie-consent-actions {
    display: flex;
    gap: var(--spacing-sm);
    flex-shrink: 0;
}

.cookie-consent-btn {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    border: none;
    border-radius: 8px;
    padding: 10px 20px;
    /* Oba przyciski tej samej szerokości niezależnie od długości tekstu ("Odrzuć" vs
       "Akceptuj") - żaden nie ma być wizualnie ani dotykowo większym celem od drugiego. */
    min-width: 112px;
    font-size: 0.95rem;
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
    transition: background-color 0.2s ease, transform 0.1s ease;
}

.cookie-consent-btn:active {
    transform: translateY(1px);
}

.cookie-consent-btn-primary {
    background-color: var(--primary-color);
    color: #ffffff;
}

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

.cookie-consent-btn-secondary {
    background-color: var(--bg-subtle);
    color: var(--text-color);
    border: 1px solid var(--card-border);
}

.cookie-consent-btn-secondary:hover {
    background-color: #e6e7ea;
}

/* ── Strona porównania: kontrolki nad kaflami (sortowanie komentarzy, czyszczenie) ── */
.compare-controls {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    margin-bottom: var(--spacing-md);
    flex-wrap: wrap;
}

.compare-controls #compare-clear-btn {
    margin-left: auto;
}

.compare-controls label {
    font-size: 0.85rem;
}

.compare-controls .sort-menu-toggle {
    width: 32px;
    height: 32px;
}

.compare-controls .sort-menu-toggle svg {
    width: 15px;
    height: 15px;
}

.compare-clear-btn {
    color: var(--danger-color);
    border-color: #e3a29c;
}

.compare-clear-btn:hover {
    background-color: var(--danger-bg);
    border-color: var(--danger-color);
}

/* ── Strona porównania: karty obok siebie, przewijane w poziomie, jak najwęższe,
   żeby zmieścić ich na ekranie jak najwięcej. ── */
.compare-scroll {
    display: flex;
    align-items: flex-start;
    gap: var(--spacing-sm);
    overflow-x: auto;
    padding-bottom: var(--spacing-md);
    scroll-snap-type: x proximity;
}

.compare-card {
    /* flex-grow:1 zamiast 0 - gdy kart jest mało (1-2), rozrastają się i zajmują więcej miejsca
       zamiast zostawiać pustą przestrzeń obok wąskiej kolumny kart. max-width ogranicza to do
       rozsądnej szerokości czytania (nie ma potrzeby zapełniać całego ekranu jedną kartą na
       szerokim desktopie - węższa kolumna tekstu czyta się wygodniej). Gdy kart jest dużo i już
       przepełniają wiersz, wolnej przestrzeni do rozdzielenia nie ma, więc flex-grow nic nie
       zmienia - zachowanie identyczne jak wcześniej (przewijanie w bok, stała szerokość ~170px,
       pilnowana przez min-width przy flex-shrink). */
    flex: 1 1 170px;
    min-width: 170px;
    max-width: 320px;
    scroll-snap-align: start;
    border: 1px solid var(--card-border);
    border-radius: 8px;
    padding: var(--spacing-sm);
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.04);
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 6px;
}

.compare-card h2 {
    margin-top: 0;
    font-size: 0.95rem;
    line-height: 1.25;
    /* min-height jest dokładany w JS (patrz alignCardHeadings w compareView.ts), nie na sztywno
       tutaj - inaczej krótkie nazwiska zawsze marnowałyby miejsce na "na wszelki wypadek" drugą
       linijkę, nawet gdy żadna karta w bieżącym zestawie jej nie potrzebuje. */
}

.compare-card h2 a {
    color: inherit;
    text-decoration: none;
}

.compare-card h2 a:hover {
    text-decoration: underline;
}

/* ── Podgląd komentarzy w karcie porównania - kompaktowa wersja .comment ──── */
.compare-comments {
    display: flex;
    flex-direction: column;
    /* Karta jest wyśrodkowana (.compare-card, align-items:center) - same komentarze celowo z
       tego wyłączone, zostają wyrównane do lewej i na pełną szerokość jak dotychczas, bo tekst
       opinii wyśrodkowany czytałoby się dużo gorzej. */
    align-self: stretch;
    text-align: left;
    gap: 6px;
}

.compare-comment {
    border-top: 1px solid var(--card-border);
    padding-top: 6px;
    font-size: 0.78rem;
}

.compare-comment-header {
    display: flex;
    align-items: center;
    gap: 4px;
    flex-wrap: wrap;
}

.compare-comment-header .star-rating {
    line-height: 1;
}

.compare-comment-header .star-rating .star {
    font-size: 0.75rem;
}

.compare-comment-header .comment-date {
    position: static;
    font-size: 0.7rem;
}

.compare-comment-body {
    margin: 2px 0 0;
    white-space: pre-line;
    word-break: break-word;
}

.compare-comments-empty {
    font-size: 0.78rem;
    color: var(--text-muted);
    font-style: italic;
}

.compare-show-more-btn,
.compare-remove-btn {
    font-size: 0.75rem;
    padding: 4px 10px;
}

/* "Pokaż więcej" jest wewnątrz .compare-comments (lewo, jak reszta opinii) - "Usuń z
   porównania" jest poza nią, bezpośrednio w .compare-card, więc wyśrodkowuje się razem z resztą
   karty (patrz .compare-card, align-items:center) i celowo NIE dostaje tu align-self:flex-start. */
.compare-show-more-btn {
    align-self: flex-start;
}

/* ── Landing page /test/ - wybór uczelni, potem wykładowcy (jak w RateMyProfessors) ──
   Wszystko wyśrodkowane: nagłówek, wyszukiwarki, lista, linki. ── */
.landing-page {
    text-align: center;
}

#landing-container {
    max-width: 460px;
    margin: var(--spacing-lg) auto 0 auto;
    display: flex;
    flex-direction: column;
    gap: var(--spacing-sm);
}

.landing-heading {
    font-weight: 700;
    color: var(--primary-color);
    font-size: 1.1rem;
}

/* Pole wyszukiwania (uczelni i wykładowcy) - ten sam styl co #search-input gdzie indziej,
   ale jako klasa, bo na tej stronie mogą być dwa takie pola naraz (uczelnia + wykładowca). */
.landing-text-input {
    width: 100%;
    padding: 10px 12px 10px 38px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    font-family: inherit;
    font-size: 0.95rem;
    color: var(--text-color);
    background-color: #ffffff;
    transition: border-color 0.2s ease;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03);

    background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236c757d' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3ccircle cx='11' cy='11' r='8'%3e%3c/circle%3e%3cline x1='21' y1='21' x2='16.65' y2='16.65'%3e%3c/line%3e%3c/svg%3e");
    background-repeat: no-repeat;
    background-position: left 12px center;
    background-size: 16px;
}

.landing-text-input:hover {
    border-color: var(--border-hover);
}

.landing-text-input:focus {
    outline: none;
    border-color: var(--primary-color);
}

/* Strzałka po prawej (obok lupy po lewej z .landing-text-input) - sygnalizuje "to lista do
   wyboru, nie tylko wyszukiwarka" (kliknięcie od razu pokazuje wszystkie wydziały - patrz
   renderFacultyOptions w landing.ts). Ta sama strzałka co przy przedmiocie w formularzu opinii
   (.comment-form-box .subject-picker input[type="text"]). Musi być PO .landing-text-input
   w arkuszu (ta sama specyficzność, oba na tym samym elemencie) - inaczej pojedyncza lupa
   z bazowej reguły by to nadpisała. */
.landing-faculty-input {
    padding-right: 32px;
    background-image:
        url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236c757d' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3ccircle cx='11' cy='11' r='8'%3e%3c/circle%3e%3cline x1='21' y1='21' x2='16.65' y2='16.65'%3e%3c/line%3e%3c/svg%3e"),
        url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23404040' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e");
    background-repeat: no-repeat, no-repeat;
    background-position: left 12px center, right 10px center;
    background-size: 16px, 16px;
}

/* Oba pola (uczelnia, wydział) na pełną szerokość kontenera (nie sztywne 400px jak np.
   w nagłówku profilu wykładowcy), z rozwijaną listą podpowiedzi wyrównaną do lewej. Przy
   uczelni ta klasa jest na WRAPPERZE (patrz landing.ts: universityWrapper), a samo pole to
   zagnieżdżony .search-with-suggestions (osobny element - stąd też trzeba to jawnie zejść
   na niego niżej, inaczej zostawałby wąski (max-width:400px) i nie wyśrodkowany w 460px
   kontenerze). Przy wydziale obie klasy są na TYM SAMYM elemencie, więc już działało. */
.landing-search-field {
    width: 100%;
    max-width: none;
}

.landing-search-field .search-with-suggestions {
    width: 100%;
    max-width: none;
}

.landing-search-field .search-suggestions {
    text-align: left;
}

/* Krok 2 (wybór wydziału) jest w DOM od razu, tylko schowany (hidden) - dzięki temu pojawia
   się dokładnie tam, gdzie byłby "pod" krokiem 1, bez skoku/zmiany layoutu reszty strony przy
   wyborze uczelni. WAŻNE: "display: flex" musi być pod ":not([hidden])" - bez tego reguła
   autorska (ta sama specyficzność co atrybut [hidden] w arkuszu przeglądarki, ale załadowana
   później) wygrywała i CAŁKOWICIE kasowała działanie atrybutu hidden. */
.landing-faculty-section:not([hidden]) {
    display: flex;
}

.landing-faculty-section {
    flex-direction: column;
    gap: var(--spacing-sm);
    margin-top: var(--spacing-sm);
}

.landing-browse-link {
    font-size: 0.85rem;
    color: var(--text-color);
    opacity: 0.7;
}

/* Komunikat po dodaniu nowego wydziału (patrz createFaculty w landing.ts) - pusty (:empty),
   dopóki nic się nie stało, więc nie zajmuje miejsca w layoucie na krok 2. */
.landing-faculty-feedback:not(:empty) {
    font-size: 0.85rem;
    color: var(--text-color);
    background-color: var(--bg-subtle);
    border-radius: 8px;
    padding: 10px 12px;
}

/* "Pigułka" wybranej uczelni - zastępuje pole wyszukiwania w tym samym miejscu (krok 1)
   i przejmuje rolę nagłówka (który się chowa) - stąd ten sam wygląd co .landing-heading,
   wyśrodkowana, bez obwódki/tła. Mały "×" tuż obok nazwy cofa wybór i przywraca
   wyszukiwarkę. WAŻNE: "display: flex" musi być pod ":not([hidden])" - patrz analogiczna
   notka przy .landing-faculty-section. */
.landing-university-pill:not([hidden]) {
    display: flex;
}

.landing-university-pill {
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    padding: 10px 12px;
}

.landing-university-pill-name {
    font-weight: 700;
    color: var(--primary-color);
    font-size: 1.1rem;
}

.landing-university-pill-clear {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    flex: 0 0 auto;
    border: none;
    background: none;
    color: var(--text-color);
    opacity: 0.6;
    font-size: 1.2rem;
    line-height: 1;
    cursor: pointer;
    padding: 0;
    transition: opacity 0.2s ease, color 0.2s ease;
}

.landing-university-pill-clear:hover {
    opacity: 1;
    color: var(--primary-color);
}

/* Zawęża odstęp pod h1 tylko wtedy, gdy zaraz po nim jest .page-tagline (strona wyszukiwania) -
   h1 jest współdzielony z innymi widokami (np. profil wykładowcy), więc nie można ruszyć jego
   marginesu globalnie. Kolejność: h1 -> .page-tagline -> .page-subtitle (nazwa uczelni/wydziału
   POD taglinem, nie nad nim). */
h1:has(+ .page-tagline) {
    margin-bottom: 6px;
}

.page-tagline {
    display: block;
    padding-left: 0;
    margin: 0 0 2px;
    color: var(--text-muted);
    font-size: 0.9rem;
}

.page-subtitle {
    display: block;
    padding-left: 0;
    color: var(--primary-color);
    margin: 0 0 12px;
    font-size: 0.95rem;
    font-weight: 700;
    letter-spacing: 0.01em;
}

/* ── FAQ: pytania rozwijane ───────────────────────────────────────────────
   <details>/<summary> zamiast własnego JS - treść jest statyczna, więc rozwijanie/zwijanie i
   dostępność klawiaturowa "za darmo" z przeglądarki. Sama strzałka to ten sam SVG chevron co
   .comment-group-collapse-btn (spójny język ikon w serwisie), tylko inna konwencja obrotu:
   w dół = "rozwiń" (stan domyślny), w górę (180deg) = "zwiń" - bardziej czytelne dla FAQ niż
   obrót o 90 stopni używany przy grupach komentarzy. */
.faq-list {
    margin-top: var(--spacing-md);
}

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

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

.faq-question {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--spacing-sm);
    padding: var(--spacing-sm) 0;
    font-weight: 600;
    cursor: pointer;
    list-style: none; /* chowa domyślny trójkącik <summary> w Firefoksie */
}

.faq-question::-webkit-details-marker {
    display: none; /* to samo w Chrome/Safari (webkit) */
}

.faq-question::after {
    content: "";
    flex-shrink: 0;
    width: 18px;
    height: 18px;
    background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23404040' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e");
    background-repeat: no-repeat;
    background-position: center;
    background-size: 18px;
    transition: transform 0.2s ease;
}

.faq-item[open] .faq-question::after {
    transform: rotate(180deg);
}

.faq-answer {
    padding: 0 0 var(--spacing-md) 0;
    color: var(--text-color);
    line-height: 1.6;
}

.faq-answer p + p {
    margin-top: 0.6em;
}

/* ── Telefony (≤640px) ─────────────────────────────────────────────────────
   Duże nagłówki (h1 na imię/nazwisko, na nazwę uczelni) dobrane pod desktop zajmują
   nieproporcjonalnie dużo miejsca na wąskim ekranie telefonu i częściej łamią się na kilka
   linii niż trzeba. Zmniejszamy je TYLKO tutaj, żeby nie ruszać wyglądu na desktopie. */
@media (max-width: 640px) {
    /* Body NIE dostaje tu własnego, zmniejszonego paddingu (było --spacing-sm, 8px) - to
       robiło wrażenie "przyklejonej do krawędzi" treści na telefonie (karty, nagłówki, tekst
       komentarzy zaczynały się dosłownie 8px od krawędzi ekranu). Dziedziczy więc ten sam
       --spacing-md (16px) co desktop - .site-header niżej też wraca do tej samej wartości
       zamiast własnej, mniejszej (patrz tam), żeby oba paddingi się zgadzały. */

    h1 { font-size: 1.75rem; }
    h2 { font-size: 1.4rem; }
    h3 { font-size: 1.2rem; }

    /* Podsumowanie (liczba/gwiazdki/Opinie/kciuk) i rozkład MAJĄ stać obok siebie w jednej
       linii, tak jak na desktopie - nie każde na swojej pełnej linii pod spodem. Węższy
       flex-basis/max-width (niż domyślne 260/380px) - to jest to, co faktycznie pozwala im się
       zmieścić obok siebie na wąskim telefonie: krótsze paski, mniej "pustej" nienabarwionej
       przestrzeni w każdym z nich, i mniej miejsca zajęte przez całe podsumowanie. */
    .rating-summary {
        gap: var(--spacing-sm);
    }

    .rating-summary .rating-distribution {
        /* max-width:none (nie 200px jak wcześniej) - flex-grow:1 ma teraz wypełnić CAŁĄ
           przestrzeń, jaka zostaje obok podsumowania (to jedyny rosnący element w wierszu -
           .rating-summary-headline ma stałą szerokość, patrz notka tam), zamiast kończyć się
           z pustym miejscem po prawej stronie ekranu. flex-basis 170px zostaje - to wciąż to,
           co pozwala się zmieścić OBOK podsumowania zamiast zejść pod spód na wąskich telefonach. */
        flex: 1 1 170px;
        max-width: none;
    }

    .rating-summary-number {
        font-size: 1.8rem;
    }

    /* Pola dotykowe, które na desktopie (z myszką) mogą być małe, ale na telefonie są za
       ciasne do wygodnego stuknięcia palcem (rekomendowane min. ok. 32-44px). */
    .comment-group-collapse-btn {
        width: 32px;
        height: 32px;
    }

    /* Lista prowadzących (buildTeachersEditor) - tabelowa siatka (.teacher-plain-list, kolumny
       max-content) ma sens na desktopie, ale na wąskim telefonie 4-5 kolumn obok siebie by się
       nie zmieściło (zgłoszenie: "w poziomie się przesuwa") - wracamy do prostego, zawijanego
       wiersza: nazwisko, potem wszystkie odznaki jedna po drugiej, zawijane na kolejne linie w
       razie potrzeby, pełna szerokość ekranu.
     */
    .teacher-plain-list {
        display: flex;
        flex-direction: column;
        gap: 8px;
    }

    .teacher-plain-row {
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        column-gap: 8px;
        row-gap: 2px;
    }

    .teacher-plain-row-name {
        white-space: normal;
        max-width: 100%;
        /* flex-basis:100% - zmusza nazwisko na WŁASNĄ linię, odznaki zawijają się pod spodem,
           zamiast próbować zmieścić się obok długiego nazwiska w tej samej wąskiej linii. */
        flex-basis: 100%;
    }

    /* Strona porównania - karty przewijane w poziomie (patrz .compare-scroll) mają sens na
       desktopie, gdzie mieści się kilka naraz obok siebie, ale na wąskim telefonie każda karta
       byłaby ściśnięta do ułamka szerokości ekranu (min-width 170px to ponad połowa typowego
       375px) - czytelniej jest przewijać je PIONOWO, jedna pod drugą, na pełną szerokość, niż w
       bok, wąsko. */
    .compare-scroll {
        flex-direction: column;
        overflow-x: visible;
    }

    .compare-card {
        width: 100%;
        min-width: 0;
        max-width: none;
    }

    .comment-menu-toggle {
        padding: 10px 15px;
        font-size: 1.4rem;
    }

    /* Gwiazdki do WYSTAWIANIA oceny na telefonie - wcześniejsza wersja (2.1rem + 6px paddingu,
       ~44px/gwiazdkę) miała być wygodnym celem dotyku, ale na prośbę okazała się po prostu za
       duża/"gigantyczna". Tylko odrobinę większe niż desktopowe 1.3rem (bez paddingu) - wciąż
       trochę więcej niż zero, żeby nie wrócić do najciaśniejszego celu dotyku na stronie. */
    .star-rating-widget .star {
        font-size: 1.3rem;
        padding: 3px;
    }

    /* Łapki (upvote/downvote) pod komentarzem - na desktopie 0.9rem tekstu + 3px/8px paddingu
       wystarcza (klika się myszką). Pierwsza mobilna wersja (8px/14px, 1rem) była za duża -
       przyciski z pustym "obrysem" wokół samego 👍/👎 - to trochę skromniejszy, wciąż wygodniejszy
       niż desktopowy, kompromis. */
    .comment .upvote-btn,
    .comment .downvote-btn {
        padding: 5px 10px;
        font-size: 0.9rem;
    }

    /* .add-comment-btn to WSPÓLNA klasa dziesiątek przycisków w całym serwisie (Porównaj, Dodaj
       opinię, Pokaż więcej, Usuń z porównania, Wyczyść wszystko, Wyślij...) - jedna zmiana tu
       podnosi wygodę dotyku wszędzie naraz, bez osobnego dostrajania każdego miejsca z osobna.
       Pierwsza mobilna wersja (10px/16px, 1.05rem) robiła zbyt duże, puste "pigułki" na liście
       wykładowców (dużo miejsca wokół "+ Porównaj") - mniejszy padding i font-size bliższy
       desktopowemu, żeby kafelki na liście były trochę niższe. */
    .add-comment-btn {
        padding: 7px 13px;
        font-size: 0.92rem;
    }

    .add-comment-btn-icon {
        font-size: 1.05rem;
    }

    /* .compare-toggle-btn ma na desktopie swój OSOBNY, mniejszy rozmiar (patrz wyżej) - bez tej
       reguły przegrywał na telefonie z ogólnym .add-comment-btn powyżej (ta sama specyficzność,
       ale zdefiniowany później w pliku), więc "+ Porównaj" na karcie wykładowcy wychodził
       większy niż na desktopie zamiast tylko dotykowo wygodniejszy. */
    .compare-toggle-btn {
        padding: 5px 12px;
        font-size: 0.82rem;
    }

    /* Przycisk-hamburger menu w nagłówku - nie miał osobnego rozmiaru na telefonie, tylko
       domyślny (desktopowy) padding liczony z font-size, co dawało ok. 36×30px. */
    .site-menu-toggle {
        padding: 8px 10px;
        font-size: 1.6rem;
    }

    /* Pole wyszukiwania W NAGŁÓWKU (widok wykładowcy/porównania - patrz .site-header-search
       wyżej) - osobne od głównego #search-input na liście (to ma już wystarczającą wysokość z
       paddingu). 30px stałej wysokości było najniższym polem dotykowym na stronie. */
    .site-header-search #search-input {
        height: 38px;
    }

    /* Pływający pasek koszyka porównania - przy kilku wybranych wykładowcach albo dłuższej
       liczbie ("Do porównania: 12") jego zawartość mogłaby nie zmieścić się na wąskim ekranie.
       Zamiast łamać ją na kilka linii (co psuje kształt "pigułki"), zostaje w jednej linii i
       przewija się w bok - tak samo jak karty na stronie porównania (.compare-scroll). */
    .compare-bar {
        max-width: calc(100% - 2 * var(--spacing-md));
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }

    .compare-bar-count,
    .compare-bar-link,
    .compare-bar-clear {
        flex-shrink: 0;
    }

    /* Pasek jest celowo mały/stonowany na desktopie (patrz komentarz przy .compare-bar wyżej),
       ale na telefonie to jedyny sposób dojścia do porównania poza samą listą - "Zobacz
       porównanie" i "Usuń" miały tylko ~26-28px wysokości, najciaśniejsze cele w tym pasku. */
    .compare-bar {
        padding: 6px 10px;
        font-size: 0.82rem;
        gap: 6px;
    }

    .compare-bar-link {
        padding: 6px 11px;
    }

    .compare-bar-clear {
        padding: 6px 8px;
    }

    /* Pole wyszukiwania + sortowanie mają zostać w jednej linii tak długo, jak się da - na
       desktopie .controls się zawija (flex-wrap: wrap), bo jest miejsce, żeby sortowanie
       zjechało pod spód, ale na wąskim ekranie to wygląda na "zgubiony" przycisk. Przycisk
       "Dodaj osobę" (patrz #add-person-container niżej) dochodzi teraz do tej pary jako TRZECI
       element w tym samym pasku - między wyszukiwarką a sortowaniem robi się wtedy naprawdę
       ciasno (zgłoszenie: cała trójka "tłoczy się", "Sortuj" łamie się w środku wyrazu). Zamiast
       trzymać sztywne nowrap (i pozwalać przyciskom się ściskać/łamać tekst), .controls wraca do
       zawijania - z kolejnością wizualną (order niżej) ustawioną tak, że to WŁAŚNIE Dodaj osobę,
       jako ostatni w tej kolejności, schodzi jako pierwszy do nowej linii, gdy zabraknie miejsca
       na wszystkie trzy naraz. Wyszukiwarka+Sortuj (oba z małym flex-basis, patrz niżej) prawie
       zawsze mieszczą się razem - to one pozostają "po staremu" w jednej linii. */
    .controls {
        flex-wrap: wrap;
    }

    #sort-menu-container {
        order: 2;
    }

    #add-person-container {
        order: 3;
    }

    #search-input {
        max-width: none;
        min-width: 0;
        /* Bazowy (przed rozciągnięciem przez flex-grow:1) rozmiar liczony do decyzji, co się
           jeszcze mieści w linii - mały, żeby Sortuj (a potem Dodaj osobę, patrz order wyżej)
           miały szansę zmieścić się obok, zamiast to wyszukiwarka (jako pierwsza w kolejności)
           zajmowała całą dostępną szerokość jeszcze przed sprawdzeniem, czy starczy miejsca na
           resztę. */
        flex-basis: 90px;
    }

    /* Dialog "Dodaj osobę"/"Dodaj pierwszą opinię" (patrz .add-review-dialog wyżej) na desktopie
       stoi na samym środku ekranu (top:50%) - na telefonie klawiatura ekranowa potrafi zakryć
       dolną połowę widocznego obszaru, gdy pole "Imię i nazwisko" jest akurat aktywne, a to
       WŁAŚNIE tam (tuż pod polem) wyskakują podpowiedzi (zgłoszenie: "klawiatura zasłania cały
       dropdown"). Adres top:50% liczy się względem layout viewportu, który (bez własnego
       <meta name="viewport" interactive-widget=...> w base.html) NIE kurczy się razem z
       pojawieniem klawiatury - środek ekranu "sprzed" klawiatury może więc wypaść już POD nią.
       Zamiast centrować dialog pionowo, na telefonie zaczyna się blisko góry - tam klawiatura
       (rosnąca od dołu) ma szansę zakryć już tylko sam koniec formularza opinii (i tak
       scrollowalny wewnątrz dialogu, patrz overflow-y:auto wyżej), nie samo pole z podpowiedziami
       tuż pod tytułem. */
    .add-review-dialog {
        top: 4vh;
        transform: translate(-50%, 0) scale(0.96);
    }

    .add-review-dialog[open] {
        transform: translate(-50%, 0) scale(1);
    }

    @starting-style {
        .add-review-dialog[open] {
            transform: translate(-50%, 0) scale(0.96);
        }
    }

    /* Pasek nagłówka na telefonie: logo + (ew. wyszukiwarka) + przycisk menu mieszczą się w
       jednej linii bez zawijania (menu jest teraz jednym przyciskiem, nie rzędem linków - patrz
       .site-header-menu wyżej), więc wystarczy tylko drobna korekta pionowego paddingu/rozmiaru
       loga - poziomy margines/padding zostaje TAKI SAM jak na desktopie (--spacing-md), bo body
       wyżej już nie ma własnego, mniejszego paddingu na telefonie. */
    .site-header {
        padding-top: 10px;
        padding-bottom: 10px;
        /* Logo + przyciski Prowadzący/Przedmioty/Koła naukowe (WPiA, patrz wpia_nav_link w
           context_processors.py) + hamburger razem mogą być za szerokie na jedną linię na wąskim
           telefonie ("Wszyscy prowadzący" samo w sobie jest długie) - zamiast wypychać poziomy
           scroll/ścisk (zgłoszenie: "dziwnie wystają"), menu z przyciskami schodzi na WŁASNĄ,
           drugą linię (patrz margin-left:auto na .site-header-menu - na drugiej linii i tak
           ląduje po prawej, ten sam efekt co dotąd na jednej linii).
         */
        flex-wrap: wrap;
        row-gap: 6px;
    }

    .site-header-logo {
        font-size: 1rem;
    }

    /* Mniejsze niż na desktopie - na wąskim ekranie każdy zaoszczędzony piksel się liczy, a te
       przyciski i tak są teraz na własnej linii (patrz .site-header wyżej), więc nie muszą
       konkurować o miejsce z logiem w jednym rzędzie. */
    .site-header-subjects-link {
        font-size: 0.82rem;
        padding: 5px 10px;
    }

    /* Wiersz "Dodaj opinię" + "Sortuj" (.lecturer-header-row, widok wykładowcy) - na wąskim
       ekranie oba elementy razem z wyszukiwarką w nagłówku nad nimi czasem się nie mieszczą
       (zgłoszenie: "Sortuj się tłoczy i robi w pionie" - tekst łamał się litera po literze
       w zwężonym przycisku). flex-shrink:0 jako siatka bezpieczeństwa - gdyby mimo wszystko
       zabrakło miejsca (np. przy widocznym .add-review-hint), oba przyciski schodzą w CAŁOŚCI
       do kolejnej linijki zamiast się ściskać. Docelowo do tego nie powinno dochodzić, patrz
       niżej - napis "Sortuj" znika na telefonie, więc oba przyciski prawie zawsze mieszczą się
       razem w jednej linii. */
    .add-review-btn {
        flex-shrink: 0;
    }

    #sort-menu-container {
        flex-shrink: 0;
    }

    /* Napis "Sortuj" obok strzałek (.sort-menu-toggle--labeled, patrz renderSortMenu w
       generics.ts) był potrzebny na desktopie, bo sama ikona ginęła - na telefonie, obok
       "Dodaj opinię", to właśnie ten napis zabierał miejsce potrzebne, żeby oba przyciski
       zmieściły się w jednej linii. Zamiast tolerować zawijanie (mniej czytelne, przycisk
       "osierocony" po prawej stronie pustej linii), wracamy do samej ikony - tak jak już działa
       na liście wykładowców (.controls, browser.ts) - 38×38px to nadal wygodny cel dotykowy. */
    .sort-menu-toggle-label {
        display: none;
    }

    .sort-menu-toggle--labeled {
        width: 38px;
        padding: 0;
    }

    /* Pola tekstowe (wyszukiwarka) MUSZĄ mieć font-size min. 16px na telefonie - poniżej tego
       progu iOS Safari samo dosuwa zoom przy dotknięciu pola (i strona zostaje "powiększona"
       aż użytkownik ręcznie oddali), więc pole traci swój desktopowy rozmiar 0.95rem (15.2px
       przy 16px bazy) tylko tutaj. */
    #search-input,
    .landing-text-input {
        font-size: 16px;
    }

    .cookie-consent-banner {
        justify-content: stretch;
    }

    .cookie-consent-actions {
        width: 100%;
    }

    .cookie-consent-btn {
        flex: 1 1 0;
    }
}

/* ── Podział zajęcia/egzamin na stronie wykładowcy (na razie tylko WPiA UW) ─────────────── */
.dimension-tabs {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
    margin: var(--spacing-md) 0;
}

.dimension-tab-btn {
    -webkit-appearance: none;
    appearance: none;
    cursor: pointer;
    font-family: inherit;
    font-size: 0.85rem;
    padding: 6px 14px;
    border-radius: 999px;
    border: 1px solid var(--border-color);
    background-color: #ffffff;
    color: var(--text-color);
    transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease;
}

.dimension-tab-btn:hover {
    border-color: var(--primary-color);
}

.dimension-tab-btn.active {
    background-color: var(--primary-color);
    border-color: var(--primary-color);
    color: #ffffff;
}

/* Sekcja "Egzamin" w formularzu opinii - wizualnie oddzielona od oceny zajęć wyżej, schowana za
   przełącznikiem "Oceń od razu egzamin" (patrz comment-exam-buttons-row niżej) - domyślnie
   zwinięta, żeby nie rozdymać formularza samą swoją obecnością. */
.comment-exam-section {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-top: var(--spacing-sm);
    padding-top: var(--spacing-sm);
    border-top: 1px dashed var(--border-color);
}

/* Para "Oceń od razu egzamin"/"Oceń od razu zajęcia" (ciemny - domyślny styl przycisku w
   .comment-form-box, bez własnej klasy) / "Dodaj opinię" (jasny, patrz .comment-form-btn-light
   niżej) - bez ikony strzałki (na wyraźną prośbę - poprzednia wersja miała ::before z "▸"/"▾"). */
.comment-exam-buttons-row {
    display: flex;
    gap: var(--spacing-sm);
    flex-wrap: wrap;
}

/* Zerowanie margin-top/bottom - domyślny styl przycisku w .comment-form-box (patrz reguła z
   długą listą :not() wyżej w pliku, specyficzność (0,7,1)) dokłada var(--spacing-sm) góra/dół
   KAŻDEMU przyciskowi bez własnej klasy (czyli przełącznikowi "Oceń od razu X", ale NIE
   .comment-form-btn-light obok niego) - w tym jednym, wspólnym wierszu ta asymetria robiła z
   niego widocznie wyższy pasek niż sam przycisk "Dodaj opinię" (zgłoszenie: "przycisk dodaj
   opinię zrobił się jakiś wysoki"). Powtórzone tu wykluczenia (ten sam wzorzec co
   .notify-email-followup-actions button wyżej w pliku) - żeby przebić tamtą regułę, trzeba
   dorównać/przebić jej specyficzność, nie tylko dodać nową, "lżejszą" regułę. */
.comment-exam-buttons-row button:not(.star):not(.search-suggestion-item):not(.would-take-again-btn):not(.difficulty-btn):not(.notify-email-followup-dismiss):not(.notify-email-followup-link):not(.comment-form-btn-light) {
    margin-top: 0;
    margin-bottom: 0;
}

.comment-exam-section-fields {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-top: 4px;
}

/* Klaster pól (zajęcia LUB egzamin, w zależności od tego, który jest akurat "primary" - patrz
   setExamPrimaryFn w comments.ts) - musi sam nieść swój wewnętrzny odstęp między polami, bo po
   przeniesieniu do primaryClusterHost/comment-exam-section-fields nie jest już bezpośrednim
   dzieckiem .collapsible-inner (patrz gap tam niżej w pliku). */
.comment-primary-cluster {
    display: flex;
    flex-direction: column;
}

.add-review-dialog .comment-primary-cluster {
    gap: 16px;
}

/* display: contents - primaryClusterHost sam nie ma być pudełkiem w layoucie, żeby klaster w
   środku liczył się jako bezpośredni flex-item .collapsible-inner (ten sam 16px gap w modalu, co
   między pozostałymi polami formularza), a nie zagnieżdżony o jeden poziom głębiej. */
.comment-primary-cluster-host {
    display: contents;
}

.comment-exam-body {
    color: var(--text-color);
    opacity: 0.9;
}

/* Jasny wariant przycisku wysyłki "Dodaj opinię" (patrz examButtonsRow w comments.ts) - obok
   ciemnego "Oceń od razu egzamin" (który zostaje bez własnej klasy, więc dostaje domyślny,
   ciemny styl przycisku w .comment-form-box - patrz reguła wyżej z długą listą :not()). Wpisany
   do tej samej listy :not() na regułach ciemnego przycisku, żeby jej NIE dziedziczyć. */
.comment-form-btn-light {
    background-color: transparent;
    color: var(--primary-color);
    border: 1px solid var(--primary-color);
    padding: 10px 24px;
    border-radius: 8px;
    font-size: 1rem;
    font-weight: 600;
    cursor: pointer;
    font-family: inherit;
    transition: background-color 0.2s ease, color 0.2s ease;
    display: inline-flex;
    align-items: center;
}

.comment-form-btn-light:hover {
    background-color: var(--bg-subtle);
}

/* Podsumowanie na zakładce "Egzamin"/"Pytania na egzaminie" - reużywa DOKŁADNIE te same klasy
   co .rating-summary dla gwiazdek (patrz renderRatingSummary w posts.ts) - renderExamSummaryContent
   w post_detail.ts buduje identyczną strukturę (headline + .rating-summary-bars), więc nie
   potrzeba tu żadnych własnych stylów nadpisujących layout (poprzednia wersja to robiła i
   wyglądała inaczej niż rozkład gwiazdek - zgłoszenie naprawione przez usunięcie tego nadpisania,
   nie dodanie kolejnego). */

/* Lista pytań egzaminacyjnych - zwykłe linie z myślnikiem, NIE karty komentarzy (na wyraźną
   prośbę) - pytanie to sam tekst, bez oceny/autora/daty, więc nie potrzebuje wizualnego
   wyróżnienia karty (obramowanie/cień/padding), tylko zwarty, listowy wygląd. */
.exam-question-line {
    display: flex;
    align-items: baseline;
    gap: 6px;
    padding: 4px 0;
    border-bottom: 1px solid var(--card-border);
}

.exam-question-line:last-child {
    border-bottom: none;
}

.exam-question-bullet {
    flex-shrink: 0;
    color: var(--text-muted);
}

/* Osobisty checklist "przerobione" (patrz renderExamQuestion w examQuestions.ts) - kółko z lewej,
   kliknięcie odznacza/zaznacza, stan trzyma się w localStorage między sesjami. Rozmiar/border
   dobrany tak, żeby wizualnie pasował do wysokości reszty linii (nie dominował nad tekstem). */
.exam-question-check {
    flex-shrink: 0;
    width: 16px;
    height: 16px;
    margin-top: 2px;
    padding: 0;
    border: 1.5px solid var(--text-muted);
    border-radius: 50%;
    background: none;
    cursor: pointer;
}

.exam-question-check[aria-checked="true"] {
    background-color: var(--text-muted);
    border-color: var(--text-muted);
}

/* Odhaczone pytanie robi się szare/przekreślone (na wyraźną prośbę: "robi się szare") - dotyczy
   samego tekstu, nie kółka checklisty, żeby ono dalej było czytelne/klikalne. */
.exam-question-line-done .exam-question-text {
    color: var(--text-muted);
    text-decoration: line-through;
}

/* Jedna odznaka źródła "W" nad CAŁĄ listą pytań (patrz renderExamQuestionsList w post_detail.ts),
   zamiast przy każdym pytaniu z osobna - na wyraźną prośbę. Dyskretny, przygaszony podpis + samo
   kółko odznaki (.comment-source-badge, reużyte z comments.ts). */
.exam-questions-source-row {
    display: flex;
    align-items: center;
    gap: 6px;
    padding-bottom: var(--spacing-sm);
    margin-bottom: var(--spacing-sm);
    border-bottom: 1px solid var(--card-border);
    font-size: 0.75rem;
    color: var(--text-muted);
}

.kolo-naukowe-description {
    color: var(--text-color);
    margin-bottom: var(--spacing-md);
}
