/*
 * ISP 4.0 — szablon frontu „Nowoczesny" (warstwa PREZENTACJI).
 * Serwowany statycznie (bez Vite), niezależny od front.css Klasyka — na stronie
 * Nowoczesnego ładuje się WYŁĄCZNIE ten plik, więc klasy z makiety nie kolidują
 * z Klasykiem. Kolory pochodzą z TOKENÓW palety wstrzykiwanych inline przez
 * layout (zmienne --color-*); tu podane wartości to tylko fallback (paleta
 * domyślna), gdyby wstrzyknięcia zabrakło. Reszta tokenów (typografia, odstępy,
 * geometria) jest palette-niezależna i żyje na stałe w :root.
 *
 * Źródło wyglądu: makieta szablon_nowoczesny/ (zrodla-next/app/globals.css).
 * ETAP (b): rama — nagłówek, korpus 2-kol z railem, stopka. Pasy strony głównej
 * i widoki modułów dochodzą w kolejnych etapach.
 */

:root {
  /* Kolory — FALLBACK (nadpisywane inline z tokenów palety przez layout). */
  --color-primary: #263c70;
  --color-primary-strong: #182950;
  --color-accent: #b78a3d;
  --color-accent-soft: #f2e7d2;
  --color-surface: #ffffff;
  --color-surface-muted: #f4f2ed;
  --color-page: #eae8e3;
  --color-text: #20242c;
  --color-text-muted: #656b75;
  --color-border: #dcd9d1;
  /* OBRYS FOKUSU IDZIE Z ZAKRESU SEKCJI (07.09.2026, A6), nie ze stałej.
     Do tej pory stała `--color-focus: #0c6cb5` — systemowy niebieski, dokładnie
     ten, który UI-STYLE odrzuca: na panelu hero miał 2,60:1, na stopce 2,87:1
     przy progu 3:1 dla elementu nietekstowego. Poniżej wartość dla pasów
     JASNYCH (ciemny akcent palety, 4,81–6,86:1); pas ciemny i akcentowy
     podmienia ją na biel serwerowo (SectionBackgrounds), a stopka i panel hero
     — własnym zakresem. Zmienna `--color-focus` nadal przyjeżdża z layoutu,
     ale nikt jej już nie czyta. */
  --section-focus: var(--color-accent-strong, var(--color-primary));

  /* Geometria / odstępy / typografia — palette-niezależne. */
  /* JEDNA SIATKA TREŚCI (31.07.2026) — jak w Klasyku. Wcześniej dwa tokeny:
     76rem dla pasów tekstowych i 86rem dla siatek kafli, przez co treść
     zaczynała się w dwóch różnych miejscach. Wyrównane w GÓRĘ, do szerszej
     wartości. Tła zostają na całą szerokość okna. */
  --tresc-max: 86rem;
  --tresc-pad: var(--space-lg);
  /* WCIĘCIE DO LINII TREŚCI — jeden token dla tła na całą szerokość i treści
     na wspólnej siatce; pełne uzasadnienie przy tej samej zmiennej
     w public/css/front.css. Wartość liczy się względem bloku zawierającego
     DANY element, więc ten sam token działa i w pasie, i w kolumnie głównej. */
  --tresc-wciecie: max(var(--tresc-pad), calc((100% - var(--tresc-max)) / 2));
  --sidebar-width: 17rem;
  --section-space: clamp(2.75rem, 5vw, 4.5rem);
  /* JEDEN token odstępu pionowego pasa — zastąpił trzy różne clamp-y rozsiane
     po pasach (home-module / gallery-band / daily-thought-band). Ta sama
     wartość i zasada co Klasyk (public/css/front.css → --band-space). */
  --band-space: clamp(2.25rem, 4.5vw, 4rem);
  --column-gap: clamp(2rem, 4vw, 4.5rem);
  --space-2xs: 0.375rem;
  --space-sm: 0.75rem;
  --space-md: 1rem;
  --space-lg: 1.5rem;
  --space-xl: 2rem;
  --space-2xl: 3rem;
  --card-radius: 0.875rem;

  /* ============================================================
     SKALA WARSTW (26.07.2026) — JEDNA dla całego frontu.

     Powstała po realnym błędzie: przycisk nakładki baneru wyświetlał się NAD
     powiększonym zdjęciem w galerii. Przyczyną nie była za wysoka liczba przy
     przycisku, tylko to, że LIGHTBOX SIEDZIAŁ WEWNĄTRZ TREŚCI — a element
     pozycjonowany w środku kontenera, który tworzy własny kontekst nakładania
     (u nas robi to `container-type`), nie może przebić się nad rodzeństwo tego
     kontenera, choćby miał z-index 1000. Dlatego lightbox jest teraz
     WYPROWADZANY DO <body> (`x-teleport`), a warstwy mają jedną skalę.

     ZASADA: nowy element z podniesioną warstwą bierze zmienną z tej listy.
     Żadnych liczb wpisywanych wprost — inaczej za pół roku znów nie będzie
     wiadomo, co nad czym leży.
     ============================================================ */
  --z-tlo: 0;              /* wzory i zdjęcia w tle sekcji */
  --z-tresc: 1;            /* treść sekcji nad tłem */
  --z-plakietka: 2;        /* plakietki na zdjęciach, ikona odtwarzania, nakładka baneru */
  --z-sterowanie: 3;       /* strzałki karuzeli */
  --z-rozwijane: 30;       /* podmenu nagłówka, menu mobilne */
  --z-naglowek: 60;        /* przyklejony nagłówek */
  --z-belka: 70;           /* belka zgody na ciasteczka */
  --z-nakladka: 80;        /* nakładka „pełne informacje" */
  --z-zdjecie: 90;         /* POWIĘKSZONE ZDJĘCIE — nad wszystkim */
  --shadow-card: 0 1rem 2.5rem rgba(31, 35, 43, 0.09);
  --header-min-height: 6.5rem;
  --text-body: 1rem;
  --line-body: 1.7;

  --font-ui: Arial, Helvetica, sans-serif;
  --font-serif: Georgia, "Times New Roman", serif;

  /* E2 — ZAKRES SEKCJI (tła pasów strony głównej). Sekcja nadpisuje te zmienne
     inline (serwerowo, z palety — App\Support\Front\SectionBackgrounds), a
     wnętrza widgetów konsumują JE zamiast palety. Wartości poniżej =
     DZISIEJSZE kolory, więc wariant „jasne" nie nadpisuje niczego i render
     jest identyczny jak przed E2.
     Stoją w :root, bo layout wstrzykuje tam paletę — deklaracja
     `--x: var(--paleta)` rozwiązuje się NA ELEMENCIE, na którym stoi. */
  --section-bg: transparent;
  --section-text: var(--color-text);
  --section-heading: var(--color-primary-strong);
  --section-muted: var(--color-text-muted);
  --section-border: var(--color-border);
  --section-link: var(--color-primary);
  --section-accent: var(--color-accent);
  --card-bg: var(--color-surface);
  --card-text: var(--color-text);
  --card-heading: var(--color-primary-strong);
  --card-muted: var(--color-text-muted);
  --card-border: var(--color-border);
  --card-bg-alt: var(--color-surface-muted);
  --section-accent-ink: var(--color-accent-strong, var(--color-accent));
  --card-link: var(--color-primary);
  /* STANY KART — wartości dla pasa JASNEGO. Pas ciemny i akcentowy podmienia je
     serwerowo (App\Support\Front\SectionBackgrounds), bo tam cień — półprzezroczysta
     czerń — nie istnieje i najechanie musi mówić TŁEM i OBWÓDKĄ. Bez tych trzech
     w :root reguły stanów na jasnym pasie rozwiązywałyby się do niczego. */
  --card-bg-hover: var(--card-bg);          /* na jasnym mówi cień i obwódka, tło zostaje */
  --card-bg-active: var(--color-surface-muted);
  --card-border-hover: var(--color-accent-strong, var(--color-accent));
  /* Tło WIERSZA listy — osobne od kafla, bo wiersz nie ma cienia i tło jest
     jego głównym sygnałem. Pas ciemny i akcentowy podmienia je serwerowo. */
  --row-bg-hover: var(--color-surface-muted);
  --row-bg-active: var(--color-border);

  /* PODŁOGA CZYTELNOŚCI TEKSTU FUNKCJONALNEGO (07.09.2026).
     Drobny tekst, który NIESIE TREŚĆ — minuta w godzinie Mszy, etykieta rodzaju
     na kaflu — bywa liczony jako ułamek stopnia sąsiada i po cichu schodzi za
     nisko (tak powstało 9,86 px w stopce Klasyka i 9,9 px na kaflu Multimediów
     Nowoczesnego). Token trzyma tę granicę w JEDNYM miejscu, zamiast pamiętać
     o niej przy każdym nowym wariancie. Ta sama wartość i ta sama nazwa stoi
     w public/css/front.css. Pilnuje TypographyFloorTest. */
  --text-floor: 11px;
}

/* PAS STRONY GŁÓWNEJ (Nowoczesny) — ta sama zasada co Klasyk (section.front-section):
   tło na CAŁĄ szerokość okna, treść wyśrodkowana do kontenera przez padding
   poziomy; container-type = element ograniczający treść, więc siatki wewnątrz
   zwijają się według szerokości TREŚCI (kontenera/komórki), nie okna.
   `--section-content` to szerokość TREŚCI pasa — wspólna siatka (`--tresc-max`).

   UWAGA (03.08.2026): ten komentarz nie miał zamknięcia, przez co połykał całą
   regułę niżej. Skutek był niewidoczny w kodzie i bardzo widoczny na stronie:
   ŻADEN pas Nowoczesnego nie miał wcięcia bocznego, więc treść szła od krawędzi
   okna, a siatki kafli liczyły kolumny wg szerokości OKNA, nie kontenera.
   Ten sam rodzaj usterki co w motywie panelu (commit e8c5c4b). */
.mod-section {
  --section-content: var(--tresc-max);
  background: var(--section-bg);
  color: var(--section-text);
  padding-block: var(--band-space);
  padding-inline: var(--tresc-wciecie);
  container-type: inline-size;
}

/* ============================================================
   RAMA PASA DLA WIDOKÓW DZIEDZICZONYCH PO KLASYKU (07.09.2026)

   `frontView()` przy braku widoku Nowoczesnego CICHO spada na widok Klasyka —
   ten renderuje się wtedy z klasami `.front-section` / `.section-title` /
   `.kicker` / `.section-head`, których ten arkusz NIE ZNAŁ WCALE. Skutek: pas
   bez tła (wybrane w panelu tło pasa nie robiło nic, mimo że sekcja niosła
   zmienne zakresu), bez wcięcia bocznego (treść od krawędzi okna), bez rytmu
   `--band-space` i z nagłówkiem poza systemem nagłówków.

   PRZENOSIMY ZACHOWANIE, NIE WYGLĄD: układ i mechanika jak w `front.css`
   (full-bleed przez padding, `container-type` na elemencie ograniczającym
   treść), wartości i typografia — własne, z tokenów Nowoczesnego.

   Dotyczy dziś bloku „czeka na treść" (front/partials/widget-awaiting) i strony
   błędu; każdy następny wspólny widok dostanie to samo bez dopisywania reguł.
   Pilnuje tego BandFrameTest.
   ============================================================ */
.front-section {
  background: var(--section-bg);
  color: var(--section-text);
}
/* Pas pełnej szerokości = tylko element <section>. Wariant `<div>` (strona
   błędu) zostaje zwykłym blokiem treści — tak samo jak w Klasyku. */
section.front-section {
  --section-content: var(--tresc-max);
  margin: 0;
  padding-block: var(--band-space);
  padding-inline: var(--tresc-wciecie);
  container-type: inline-size;
}
/* Pas W STREFIE DWUKOLUMNOWEJ mieszka w kolumnie, którą wcina już `.mod-body__inner` —
   rytm marginesowy zamiast odstępu pasa. Ta sama para reguł co dla `.mod-section`. */
.mod-main section.front-section { padding-block: 0; margin-block: var(--space-2xl); }
.mod-main section.front-section:first-child { margin-top: 0; }
.mod-main section.front-section:last-child { margin-bottom: 0; }

/* NAGŁÓWEK PASA — język Nowoczesnego (te same wartości co `.section-heading h2`
   i `.section-kicker` niżej), ale stopień pisma mierzony KONTENEREM (`cqi`),
   nie oknem: nagłówek w wąskiej komórce rzędu ma zejść, a nie stać obok
   sąsiada w tym samym stopniu. `container-type` stoi wyżej na tym samym pasie. */
.section-head {
  display: flex;
  align-items: end;
  justify-content: space-between;
  gap: var(--space-lg);
  margin-bottom: var(--space-xl);
}
.kicker {
  display: block;
  margin-bottom: var(--space-sm);
  color: var(--section-accent-ink, var(--color-accent-strong));
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.section-title {
  margin: 0;
  color: var(--section-heading);
  font-family: var(--font-serif);
  font-size: clamp(1.85rem, 3cqi, 2.7rem);
  font-weight: 500;
  line-height: 1.02;
  letter-spacing: -0.03em;
}

/* Minimalny reset (front nie korzysta z resetu Tailwinda). */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--color-page);
  color: var(--color-text);
  font-family: var(--font-ui);
  font-size: var(--text-body);
  line-height: var(--line-body);
}
img { max-width: 100%; }
a { color: inherit; }
button, summary, a { -webkit-tap-highlight-color: transparent; }
/* Pola formularza (filtr kategorii, wyszukiwarka) NIE BYŁY tu objęte — reguła
   wymieniała tylko odnośniki, przyciski i [tabindex] (uzupełnione 25.07.2026,
   przy budowie warstwy fokusu Klasyka). */
:is(a, button, summary, input, select, textarea, [tabindex]):focus-visible {
  outline: 3px solid var(--section-focus);
  outline-offset: 4px;
}
.serif { font-family: var(--font-serif); }
[x-cloak] { display: none !important; }

/* Cała strona na białej powierzchni (poza ciemną stopką). */
.mod-root { background: var(--color-surface); }

/* ============================================================
   TŁO STRONY (12.09.2026) — jak w bazie Klasyka i Łukasza, z jedną różnicą:
   w Nowoczesnym gruntem jest BIEL `.mod-root`/`.mod-body`, a nie ton strony,
   więc to ona ustępuje tłu (decyzja Bartka z 12.09.2026). Karty, nagłówek,
   rail i pasy z własnym tłem zostają kryjące.
   Uzasadnienie warstwy i `z-index: -1` — front-base.css, ta sama sekcja.
   ============================================================ */
html[data-tlo] .mod-root,
html[data-tlo] .mod-body { background: transparent; }
html[data-tlo="zdjecie"],
html[data-tlo="zdjecie"] body { background: transparent; }
html[data-tlo="zdjecie"] body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -1;
  background: var(--tlo-strony) center / cover no-repeat;
  pointer-events: none;
}

/* PRZEJDŹ DO TREŚCI (07.09.2026, A23) — pierwszy przystanek klawisza Tab.

   UKRYCIE PRZEZ WYPROWADZENIE POZA EKRAN, nie `display: none` ani
   `visibility: hidden`: te dwa WYJMUJĄ element z kolejności tabulacji, więc
   odnośnik nigdy by fokusu nie dostał i nie miał jak się pokazać. Po
   otrzymaniu fokusu wjeżdża w widok — w pełni widoczny, nie półprzezroczysty.

   Kolor obrysu z zakresu sekcji, jak wszędzie; odnośnik leży na tle strony,
   czyli poza pasami, więc bierze zapas z `:root`.
   Cel skoku (`<main id="tresc">`) ma `tabindex="-1"`, ale NIE gasimy mu obrysu:
   `outline: none` jest w tym arkuszu zakazane (FocusVisibleTest), a i tak nie
   byłoby potrzebne — fokus po skoku z odnośnika nie jest fokusem KLAWIATUROWYM
   w rozumieniu `:focus-visible`, więc przeglądarka obrysu tam nie rysuje.
   Sprawdzone na żywo w obu szablonach. */
.mod-skip {
  position: fixed;
  top: var(--space-sm);
  left: var(--space-sm);
  z-index: calc(var(--z-naglowek) + 1);
  transform: translateY(-200%);
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  padding: 0 var(--space-lg);
  border-radius: 999px;
  background: var(--color-primary-strong);
  color: var(--color-surface);
  font-size: 0.85rem;
  font-weight: 800;
  text-decoration: none;
  box-shadow: var(--shadow-card);
  transition: transform var(--motion-state) var(--motion-ease-state);
}
/* `:focus`, NIE `:focus-visible` — wyjątek świadomy i jedyny w tym arkuszu.
   Odnośnika pominięcia nie da się złapać myszą (leży poza ekranem), więc
   rozróżnienie „klawiatura kontra kliknięcie" nic tu nie wnosi, a `:focus` jest
   ściśle szerszy: pokazuje odnośnik w każdym przypadku, w którym zrobiłby to
   `:focus-visible`, i w kilku, w których tamten by się zawahał. Odnośnik, który
   przy fokusie się nie pokazał, jest gorszy niż jego brak. */
.mod-skip:focus { transform: translateY(0); }

/* ============================ NAGŁÓWEK ============================ */
/* PAS pełnej szerokości okna (tło) — WNĘTRZE trzyma szerokość kontenera.
   Dzięki temu przyklejony nagłówek sięga krawędzi ekranu i nie wygląda jak
   pudełko pływające nad zdjęciem baneru (poprawka 24.07.2026). */
.parish-header { background: var(--color-surface); }
.parish-header__inner {
  max-width: var(--tresc-max);
  margin: 0 auto;
  min-height: var(--header-min-height);
  padding: var(--space-lg);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-xl);
  position: relative;
  /* Kurczenie przyklejonego nagłówka po przewinięciu — patrz niżej. */
  transition: min-height 180ms ease, padding 180ms ease;
}
.parish-brand { display: flex; gap: var(--space-md); align-items: center; text-decoration: none; min-width: 0; }
/* Logo skalowane wysokością, proporcje zachowane, bez kadrowania (jak Klasyk). */
.parish-brand__logo { height: 3.4rem; width: auto; max-width: 15rem; object-fit: contain; display: block; flex: 0 0 auto; }
.parish-brand__text { display: grid; }
.parish-brand strong { font-family: var(--font-serif); font-size: 1.18rem; color: var(--color-primary-strong); font-weight: 500; }
.parish-brand small { color: var(--color-text-muted); font-size: 0.82rem; }

/* row-gap celowo ZWARTY: gdy menu zejdzie do dwóch linii (zanim zadziała
   „Więcej"), odstęp między liniami ma wyglądać na zamierzony, a nie zostawiać
   pojedynczej pozycji-sieroty daleko pod resztą (poprawka 18.07.2026). */
.main-navigation {
  display: flex;
  align-items: center;
  column-gap: clamp(1rem, 2.2vw, 2rem);
  row-gap: 0.1rem;
  flex-wrap: wrap;
}
.main-navigation__group { position: relative; }
.main-navigation a, .main-navigation__label {
  min-height: 2.75rem;
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  color: var(--color-text);
  font-size: 0.88rem;
  font-weight: 800;
  text-decoration: none;
  position: relative;
  background: none;
  border: 0;
  cursor: pointer;
  font-family: inherit;
}
.main-navigation > a::after, .main-navigation__group > a::after, .main-navigation__label::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0.25rem;
  height: 2px;
  background: var(--color-accent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 180ms ease;
}
.main-navigation > a:hover::after,
.main-navigation__group:hover > a::after,
.main-navigation__group:hover .main-navigation__label::after,
.main-navigation a.is-current::after,
.main-navigation__label.is-current::after { transform: scaleX(1); }
/* Oznaczenie strony, na której jesteśmy: podkreślenie akcentem + mocniejszy
   kolor tekstu. Oba z tokenów palety, więc każda paleta dostaje swój wariant.
   Podkreślenie jest GRUBSZE niż hover — inaczej „gdzie jestem" i „na co
   najechałem" wyglądałyby identycznie. */
.main-navigation a.is-current,
.main-navigation__label.is-current { color: var(--color-primary-strong); }
/* Akcent PRZYCIEMNIONY: pasek niesie informację „tu jesteś", więc musi mieć
   kontrast (jasny akcent ma na białym 2,6–3,1:1, ten wariant 6,0–6,9:1 we
   wszystkich czterech paletach). Hover zostaje przy jasnym akcencie. */
.main-navigation > a.is-current::after,
.main-navigation__group > a.is-current::after,
.main-navigation__label.is-current::after {
  height: 3px;
  background: var(--color-accent-strong, var(--color-accent));
}
/* Pozycja w rozwijanym podmenu (podkreślenia tam nie ma — jest tło i kolor). */
.main-navigation__submenu a.is-current {
  background: var(--color-surface-muted);
  color: var(--color-primary-strong);
}
.mobile-navigation a.is-current {
  color: var(--color-primary-strong);
  box-shadow: inset 3px 0 0 var(--color-accent-strong, var(--color-accent));
}
.main-navigation__caret { font-size: 0.7rem; color: var(--color-text-muted); }

/* Rozwijane podmenu (poziom 2) */
.main-navigation__submenu {
  position: absolute;
  z-index: var(--z-rozwijane);
  top: 100%;
  left: 0;
  min-width: 13rem;
  margin: 0;
  padding: var(--space-sm) 0;
  list-style: none;
  background: #fff;
  border: 1px solid var(--color-border);
  border-radius: var(--card-radius);
  box-shadow: var(--shadow-card);
  opacity: 0;
  visibility: hidden;
  transform: translateY(0.35rem);
  transition: opacity 160ms ease, transform 160ms ease, visibility 160ms;
}
.main-navigation__group:hover .main-navigation__submenu,
.main-navigation__group:focus-within .main-navigation__submenu {
  opacity: 1; visibility: visible; transform: translateY(0);
}
.main-navigation__submenu a {
  min-height: 2.6rem;
  width: 100%;
  padding: 0 var(--space-lg);
  font-weight: 700;
  font-size: 0.85rem;
}
.main-navigation__submenu a::after { content: none; }
.main-navigation__submenu a:hover { background: var(--color-surface-muted); color: var(--color-primary); }

/* ---- Dopasowanie nagłówka: poziomy 1-3 (patrz front/partials/header-fit) ---- */
.main-navigation .is-header-overflow { display: none !important; }
/* Pomiar: bez zawijania I bez kurczenia pozycji (flex-shrink:1 fałszowałby
   naturalną szerokość menu — patrz bliźniacza reguła w front.css). */
.main-navigation[data-header-measuring] { flex-wrap: nowrap !important; }
.main-navigation[data-header-measuring] > * {
  flex: 0 0 auto !important;
  white-space: nowrap !important;
}
/* Podmenu „Więcej" wyrównane do PRAWEJ (pozycja stoi przy prawej krawędzi). */
[data-header-more] .main-navigation__submenu { left: auto; right: 0; }
.main-navigation__submenu .main-navigation__submenu-child {
  padding-left: calc(var(--space-lg) * 2);
  font-weight: 600;
  font-size: 0.8rem;
  color: var(--color-text-muted);
}

/* UWAGA: próg MUSI odpowiadać progowi menu desktopowego TEGO szablonu
   (`@media (max-width: 52rem)` chowa .main-navigation), a nie 900 px Klasyka.
   Przy niedopasowaniu w pasie 833-900 px nagłówek dostawał poziom 2, ale CSS
   go nie stosował — menu zostawało obok nazwy i łamało się na dwie linie
   z sierotą (dokładnie objaw zgłoszony 18.07.2026). */
@media (min-width: 52.0625rem) {
  /* Poziom 2 i 3: blok logo+nazwa we własnym rzędzie, menu w rzędzie pod nim —
     oba wyśrodkowane (typografia i odstępy z tokenów szablonu bez zmian). */
  .parish-header[data-header-level="2"] .parish-header__inner,
  .parish-header[data-header-level="3"] .parish-header__inner {
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: var(--space-md);
  }
  .parish-header[data-header-level="2"] .parish-brand,
  .parish-header[data-header-level="3"] .parish-brand { justify-content: center; text-align: center; }
  .parish-header[data-header-level="2"] .parish-brand__text,
  .parish-header[data-header-level="3"] .parish-brand__text { justify-items: center; }
  .parish-header[data-header-level="2"] .main-navigation,
  .parish-header[data-header-level="3"] .main-navigation { justify-content: center; }
}

/* ---- Przyklejony nagłówek (ustawienie: Wygląd strony → Tożsamość) ---- */
/* Sticky dostaje PAS (pełna szerokość okna), nie wnętrze — tło nieprzezroczyste,
   żeby przewijana treść pod nim nie prześwitywała. */
.parish-header[data-sticky] {
  position: sticky;
  top: 0;
  z-index: var(--z-naglowek);
  /* Kompensacja skoku: gdy nagłówek się kurczy, tyle samo dokładamy pod nim,
     więc treść strony NIE PODSKAKUJE (--header-shrink liczy header-fit). */
  margin-bottom: 0;
  transition: margin-bottom 180ms ease, box-shadow 180ms ease;
}
.parish-header[data-sticky][data-condensed] {
  margin-bottom: var(--header-shrink, 0px);
  box-shadow: 0 1px 0 var(--color-border), 0 6px 18px rgba(0, 0, 0, 0.06);
}

/* Kurczenie na DESKTOPIE: przyklejony nagłówek w układzie wyśrodkowanym
   (nazwa w swoim rzędzie, menu pod spodem) zasłaniał zbyt dużo strony.
   Po przewinięciu wraca do jednego rzędu — nazwa mała z lewej, menu z prawej.
   NAZWA ZOSTAJE (i dalej jest odnośnikiem do strony głównej): bez niej nie
   wiadomo, gdzie się jest, i nie ma jak wrócić na górę serwisu. */
@media (min-width: 52.0625rem) {
  .parish-header[data-sticky][data-condensed] .parish-header__inner {
    flex-direction: row !important;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-lg);
    min-height: 0;
    padding-top: var(--space-sm);
    padding-bottom: var(--space-sm);
    /* Nic nie spada do drugiej linii — nadmiar pozycji chowa „Więcej ▾". */
    flex-wrap: nowrap !important;
  }
  .parish-header[data-sticky][data-condensed] .main-navigation { flex-wrap: nowrap !important; }
  .parish-header[data-sticky][data-condensed] .parish-brand {
    justify-content: flex-start !important;
    text-align: left !important;
  }
  .parish-header[data-sticky][data-condensed] .parish-brand__text { justify-items: start !important; }
  .parish-header[data-sticky][data-condensed] .parish-brand__logo { height: 2.2rem; }
  .parish-header[data-sticky][data-condensed] .parish-brand small { display: none; }
  .parish-header[data-sticky][data-condensed] .parish-brand strong { font-size: 1rem; }
  .parish-header[data-sticky][data-condensed] .main-navigation { justify-content: flex-end !important; }
}
html { scroll-padding-top: calc(var(--header-h, 0px) + 12px); }

/* Mobilne menu (przełącznik + panel) — sterowane Alpine `mobileMenu` z layoutu */
.mobile-nav-button { display: none; }
.mobile-navigation { display: none; }

/* ============================ KORPUS ============================ */
.mod-body { background: var(--color-surface); }
.mod-body__inner {
  max-width: var(--tresc-max);
  margin: 0 auto;
  padding: var(--section-space) var(--space-lg);
}
.two-column-zone {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--sidebar-width);
  gap: var(--column-gap);
  align-items: start;
}
.two-column-zone--single { grid-template-columns: minmax(0, 1fr); }
.mod-main { min-width: 0; }
/* Pas W STREFIE (kolumna główna obok railu) NIE jest pełnoszerokościowy — mieszka
   w kolumnie, którą wcina .mod-body__inner. Rytm marginesowy zamiast band-space;
   padding poziomy z bazy (.mod-section → space-lg w wąskiej kolumnie) zostaje jako
   wcięcie karty. container-type z .mod-section działa dalej → siatki w strefie
   zwijają się według szerokości kolumny. */
.mod-main .mod-section { padding-block: 0; margin-block: var(--space-2xl); }
.mod-main .mod-section:first-child { margin-top: 0; }
.mod-main .mod-section:last-child { margin-bottom: 0; }
/* PAS Z TŁEM W STREFIE ODDYCHA TAKŻE W PIONIE (13.09.2026) — ta sama poprawka
   co w front-base.css: przy zerze tekst stał 3–5 px od krawędzi tła. Odstęp =
   boczny (`--tresc-pad`). „Ma tło" = zmienna z wariantu tła na korzeniu
   (App\Support\Front\SectionBackgrounds) ALBO pas malowany z klasy układu
   (Karty-linki: ciemny z założenia szablonu). Pas przyklejony poza regułą. */
.mod-main .mod-section:is([style*="--section-bg"], .editorial-links-band):not(.mod-section--flush) { padding-block: var(--tresc-pad); }

/* Zastępczy blok treści (Etap b — do czasu pasów/widoków) */
.mod-placeholder {
  padding: clamp(2.5rem, 6vw, 5rem) var(--space-xl);
  border: 1px dashed var(--color-border);
  border-radius: var(--card-radius);
  background: var(--color-surface-muted);
  text-align: center;
  color: var(--color-text-muted);
}
.mod-placeholder h1 {
  margin: 0 0 var(--space-md);
  color: var(--color-primary-strong);
  font-family: var(--font-serif);
  font-weight: 500;
  font-size: clamp(1.8rem, 3vw, 2.6rem);
  letter-spacing: -0.02em;
}
.mod-placeholder p { margin: 0 auto; max-width: 40rem; }

/* ============================ RAIL / KOLUMNA BOCZNA ============================ */
.parish-sidebar { position: sticky; top: var(--space-lg); align-self: start; display: grid; gap: var(--space-xl); }
.sidebar-menu-card {
  overflow: hidden;
  border: 1px solid var(--color-border);
  border-radius: var(--card-radius);
  background: #fff;
  box-shadow: 0 0.75rem 2rem rgba(31, 35, 43, 0.06);
}
.sidebar-menu-heading { padding: var(--space-lg); border-bottom: 1px solid var(--color-border); background: var(--color-surface-muted); }
.sidebar-menu-heading .sidebar-title { display: block; color: var(--color-primary-strong); font-family: var(--font-serif); font-size: 1.35rem; line-height: 1.15; }
.parish-sidebar ul { list-style: none; margin: 0; padding: 0; }
.parish-sidebar li { border-bottom: 1px solid var(--color-border); }
.parish-sidebar li:last-child { border-bottom: 0; }
.sidebar-row {
  min-height: 3.4rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
  padding: 0.6rem var(--space-md);
}
.sidebar-row a, .sidebar-row .sidebar-plain {
  flex: 1;
  color: var(--color-text);
  text-decoration: none;
  font-size: 0.88rem;
  font-weight: 700;
  line-height: 1.25;
}
.parish-sidebar .sidebar-row:hover { background: var(--color-surface-muted); }
.parish-sidebar .sidebar-row:hover a { color: var(--color-primary); }
.parish-sidebar .sidebar-row.is-current { background: var(--color-accent-soft); box-shadow: inset 3px 0 0 var(--color-accent); }
.parish-sidebar .sidebar-row.is-current a { color: var(--color-primary-strong); }
.sidebar-caret {
  width: 2rem; height: 2rem;
  display: grid; place-items: center;
  border: 0; background: none; cursor: pointer;
  color: #9aa0aa; font-size: 0.8rem;
}
.sidebar-sublist { list-style: none; margin: 0; padding: 0 0 var(--space-sm); background: var(--color-surface-muted); }
.sidebar-sublist li { border-bottom: 0; }
.sidebar-sublist a, .sidebar-sublist .sidebar-plain {
  display: block;
  padding: 0.5rem var(--space-md) 0.5rem var(--space-xl);
  font-size: 0.83rem;
  font-weight: 600;
  color: var(--color-text-muted);
  text-decoration: none;
}
.sidebar-sublist a:hover { color: var(--color-primary); }
/* Aktywna podpozycja kolumny bocznej — brakowało jej (24.07.2026): pozycja
   poziomu 2 oglądanej strony wyglądała identycznie jak pozostałe. */
.sidebar-sublist a.is-current {
  color: var(--color-primary-strong);
  font-weight: 800;
  box-shadow: inset 3px 0 0 var(--color-accent-strong, var(--color-accent));
}
.sidebar-sublist a.is-current { color: var(--color-primary-strong); font-weight: 800; }

/* Karta „porządek mszy" / boks cytatu / polecane w railu */
.rail-quote-box {
  padding: var(--space-lg);
  border: 1px solid var(--color-border);
  border-radius: var(--card-radius);
  background: var(--color-accent-soft);
}
.rail-quote-box__kicker { color: var(--section-accent-ink, var(--color-accent-strong)); font-size: 0.72rem; font-weight: 900; letter-spacing: 0.12em; text-transform: uppercase; margin-bottom: var(--space-sm); }
.rail-quote-box__text { margin: 0; color: var(--color-primary-strong); font-family: var(--font-serif); font-size: 1.05rem; line-height: 1.4; }
.rail-quote-box__author { display: block; margin-top: var(--space-sm); color: var(--color-text-muted); font-size: 0.8rem; font-style: normal; }

.sidebar-toggle { display: none; }

/* ============================ STOPKA ============================ */
.parish-footer { background: #202329; color: #fff; }
.parish-footer__main {
  max-width: var(--tresc-max);
  margin: 0 auto;
  display: grid;
  gap: clamp(2rem, 5vw, 5rem);
  padding: clamp(3rem, 5vw, 4.75rem) var(--space-lg);
}
/* KOLUMNA STOPKI (01.08.2026) — przycisk domykający przy DOLNEJ krawędzi, żeby
   kolumny miały akcje na jednej linii. Ten sam mechanizm co w Klasyku. */
.footer-block { min-width: 0; display: flex; flex-direction: column; }
.footer-block__foot { margin-top: auto; padding-top: var(--space-sm); }
.footer-block__label {
  margin: 0 0 var(--space-lg);
  color: #fff;
  font-family: var(--font-serif);
  font-size: 1.35rem;
  font-weight: 500;
  line-height: 1.2;
}
.footer-contact__name { margin-bottom: var(--space-md); color: #fff; font-family: var(--font-serif); font-size: 1.35rem; }
.footer-contact__lines { display: grid; gap: var(--space-sm); color: #c2c6ce; font-size: 0.88rem; line-height: 1.5; }
.footer-contact__lines a { color: inherit; text-decoration: none; }
.footer-contact__lines a:hover { color: #fff; text-decoration: underline; text-underline-offset: 0.2em; }
.footer-donation { display: grid; gap: var(--space-2xs); margin-top: var(--space-lg); color: #aeb3bd; font-size: 0.78rem; }
.footer-donation strong { color: #fff; font-size: 0.88rem; }
.footer-donation .footer-donation__value { white-space: pre-line; }
.footer-schedule { color: #c2c6ce; font-size: 0.88rem; line-height: 1.6; }
.footer-schedule p { margin: 0 0 var(--space-md); }
.footer-schedule strong { color: #fff; }
/* FLEX, NIE SIATKA — kafle ostatniego rzędu rozrastają się na wolne miejsce,
   więc rząd nigdy nie urywa się w połowie (patrz komentarz w Klasyku). */
.footer-gallery-grid {
  --thumb-gap: var(--space-sm);
  display: flex;
  flex-wrap: wrap;
  gap: var(--thumb-gap);
  justify-content: center;
}
.footer-gallery-tile {
  position: relative;
  display: block;
  flex: 1 1 calc(33.333% - var(--thumb-gap));
  max-width: calc(50% - var(--thumb-gap) / 2);
  aspect-ratio: 1.35;
  overflow: hidden;
  background: #111318;
}
/* Czas i krzywa z WARSTWY RUCHU — dawne `250ms ease` było własną wartością
   obok tokenów (i nie reagowało na „ogranicz ruch"). */
.footer-gallery-grid img { width: 100%; height: 100%; display: block; object-fit: cover; transition: transform var(--motion-state) var(--motion-ease-state), opacity var(--motion-state) var(--motion-ease-state); }
.footer-gallery-tile:hover img { transform: scale(1.04); opacity: 0.84; }

.footer-gallery-tile__overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: flex-end;
  padding: var(--space-2xs) var(--space-xs);
  background: linear-gradient(180deg, rgba(10, 12, 16, 0) 35%, rgba(10, 12, 16, 0.88) 100%);
  color: #fff;
  font-size: 0.7rem;
  font-weight: 700;
  line-height: 1.25;
  opacity: 0;
  transform: translateY(var(--motion-rise, 10px));
  transition: opacity var(--motion-state) var(--motion-ease-state),
              transform var(--motion-state) var(--motion-ease-state);
}
.footer-gallery-tile:hover .footer-gallery-tile__overlay,
.footer-gallery-tile:focus-visible .footer-gallery-tile__overlay { opacity: 1; transform: translateY(0); }
.footer-gallery-tile__title { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.footer-gallery-grid .img-placeholder { display: grid; place-items: center; color: #6a7078; }
.footer-link { display: inline-flex; align-items: center; gap: var(--space-2xs); margin-top: var(--space-md); color: #e0c98f; font-size: 0.8rem; font-weight: 800; text-decoration: none; }
.footer-link:hover { color: #fff; }
.footer-rich { color: #c2c6ce; font-size: 0.88rem; line-height: 1.6; }
.footer-rich p { margin: 0 0 var(--space-sm); }
.footer-rich a { color: #e0c98f; }

/* Pas Polecanych w stopce (logotypy) — style pasa dojdą przy pasach; tu baza. */
.footer-promoted { border-top: 1px solid rgba(255,255,255,0.1); }
.footer-promoted__inner {
  max-width: var(--tresc-max);
  margin: 0 auto;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: clamp(1.5rem, 4vw, 3rem);
  padding: var(--space-lg);
}
.footer-promoted__inner img { max-height: 3.25rem; width: auto; }

.parish-footer__bottom {
  min-height: 5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: var(--space-md) var(--space-xl);
  padding: var(--space-md) var(--space-lg);
  background: #111318;
  color: #fff;
}
.parish-footer__bottom .footer-social { display: inline-flex; gap: var(--space-md); }
.parish-footer__bottom .footer-social a { color: #c2c6ce; display: inline-flex; }
.parish-footer__bottom .footer-social a:hover { color: #fff; }
.parish-footer__brand { display: inline-flex; align-items: center; gap: var(--space-sm); opacity: 0.85; font-size: 0.82rem; }
.parish-footer__brand strong { font-family: var(--font-serif); font-size: 1rem; color: #fff; }

/* ============================ PAS: AKTUALNOŚCI (strona główna) ==== */
/* Odstęp z tokenu band-space (.mod-section) — dawny margines usunięty; w strefie
   zeruje go .mod-main .mod-section (rytm marginesowy kolumny, patrz niżej). */
.mod-news:last-child { margin-bottom: 0; }
.section-heading {
  display: flex;
  align-items: end;
  justify-content: space-between;
  gap: var(--space-lg);
  margin-bottom: var(--space-xl);
}
.section-kicker {
  display: block;
  color: var(--section-accent-ink, var(--color-accent-strong));
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  margin-bottom: var(--space-sm);
}
.section-heading h2 {
  margin: 0;
  color: var(--section-heading);
  font-family: var(--font-serif);
  font-size: clamp(1.85rem, 3vw, 2.7rem);
  font-weight: 500;
  line-height: 1.02;
  letter-spacing: -0.03em;
}
.all-news-link, .read-more {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  color: var(--card-link);
  font-weight: 700;
  text-decoration: none;
  text-underline-offset: 0.3em;
  white-space: nowrap;
}
.all-news-link:hover, .read-more:hover { text-decoration: underline; }

/* Zastępnik zdjęcia — jak w Klasyku: wyłącznie zmienne zakresu, spokojna
   powierzchnia z pociągnięciem akcentu, wyciszony znak. Poprawne na pasie
   ciemnym/akcentowym i w każdej z czterech palet (18.07.2026). */
.img-placeholder {
  display: grid;
  place-items: center;
  background:
    linear-gradient(135deg, transparent 0%, color-mix(in srgb, var(--section-accent) 12%, transparent) 100%),
    var(--card-bg-alt);
  color: color-mix(in srgb, var(--card-muted) 55%, transparent);
  font-size: 1.6rem;
  line-height: 1;
}

/* Kafel wyróżniony (poziomy: zdjęcie + treść) */
.featured-card {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
  overflow: hidden;
  border-radius: var(--card-radius);
  background: var(--card-bg-alt);
  box-shadow: var(--shadow-card);
  text-decoration: none;
}
.featured-card__image { display: block; min-height: 20rem; overflow: hidden; }
/* Wpis bez zdjęcia nie ma kolumny na zdjęcie (15.09.2026) — treść na całą szerokość. */
.featured-card.featured-card--textonly { grid-template-columns: minmax(0, 1fr); }

/* WYPEŁNIENIE KAFLA BEZ ZDJĘCIA TEKSTEM (15.09.2026).
   Siatka wyrównuje wysokość kafli w wierszu, więc kafel bez zdjęcia obok kafla
   ze zdjęciem miał pod tekstem pustą połowę karty. Akapit wypełniający ma
   `flex-basis: 0` — NIE podbija wysokości wiersza (tę wyznacza sąsiad), tylko
   zajmuje całą wolną przestrzeń; skrypt `data-wypelnij` (front.js) ustawia
   liczbę pełnych wierszy, żeby tekst kończył się wielokropkiem, a nie przeciętą
   linią. Minimum czterech wierszy obowiązuje, gdy w wierszu siatki nie ma
   kafla ze zdjęciem (albo kafel stoi sam, jak na telefonie). */
.news-card--textonly .news-card__content { flex: 1 1 auto; display: flex; flex-direction: column; }
.news-card__fill,
.mod-archive-card__fill {
  flex: 1 1 0;
  min-height: 6em;
  min-height: calc(4 * 1lh);
  overflow: hidden;
  display: -webkit-box;
  -webkit-box-orient: vertical;
}
/* KAFEL Z KRÓTKĄ TREŚCIĄ NIE ROZCIĄGA SIĘ (15.09.2026, decyzja właściciela).
   Gdy cały tekst mieści się z zapasem co najmniej jednego wiersza, rozciągnięcie
   do sąsiada dawało pustkę pod tekstem. Skrypt `data-wypelnij` dokłada wtedy
   klasę `--short`: kafel ma własną wysokość, krótszy w wierszu jest w porządku.
   Bez JS zostaje tryb wypełniania. */
.news-card--short,
.mod-archive-card--short { align-self: start; }
.news-card--short .news-card__fill,
.mod-archive-card--short .mod-archive-card__fill { flex: 0 0 auto; min-height: 0; }
.featured-card__image img,
.news-card__image img { display: block; width: 100%; height: 100%; object-fit: cover; transition: transform 300ms ease; }
.featured-card__image:hover img, .news-card__image:hover img { transform: scale(1.03); }
.featured-card__content { padding: clamp(1.5rem, 3vw, 2.75rem); display: flex; flex-direction: column; justify-content: center; }
.featured-card__content :is(h2, h3) { margin: var(--space-sm) 0; line-height: 1.16; }
.featured-card__content :is(h2, h3) a {
  color: var(--card-heading);
  font-family: var(--font-serif);
  font-size: clamp(1.35rem, 2vw, 1.9rem);
  font-weight: 500;
  line-height: 1.16;
  letter-spacing: -0.02em;
  text-decoration: none;
}
.featured-card__content :is(h2, h3) a:hover { text-decoration: underline; text-underline-offset: 0.2em; }
.featured-card__content p { color: var(--card-muted); margin: 0 0 var(--space-lg); }
.featured-card .read-more { margin-top: auto; }

/* Metadane (kategoria · data) */
.news-meta { display: flex; align-items: center; gap: var(--space-sm); font-size: 0.76rem; margin-bottom: var(--space-2xs); }
.news-meta span { color: var(--card-link); font-weight: 800; text-transform: uppercase; letter-spacing: 0.06em; }
.news-meta time { color: var(--card-muted); }
.news-meta time::before { content: "·"; margin-right: var(--space-sm); }

/* REGUŁA 1 (31.07.2026): liczba kolumn wynika z minimalnej szerokości kafla
   liczonej z kontenera, a nie z trzech progów (te dawały skok 3→2→1 i nic
   pomiędzy — w pasie pełnej szerokości kafel rozdymał się do 420 px, a tuż za
   progiem kurczył o połowę).
     pełny  → 22cqi ≈ 280 → 4 kafle    połowa → 220 → 2    ⅓ → 220 → 1 */
/* ============================================================
   POJEDYNCZY KAFEL NIE ROZCIĄGA SIĘ NA CAŁY PAS (02.08.2026).

   `auto-fit` ZWIJA puste ścieżki, więc siatka z jednym kaflem oddawała mu całą
   szerokość pasa — jedna galeria wyglądała jak baner. `auto-fill` ścieżek NIE
   zwija: kafel dostaje dokładnie tę szerokość, którą miałby w PEŁNYM rzędzie,
   staje przy lewej krawędzi treści, a reszta rzędu zostaje pusta.

   Liczba kolumn przy pełnym rzędzie się NIE zmienia — oba tryby liczą ścieżki
   tak samo; różnią się wyłącznie tym, co robią z pustymi.
   ============================================================ */
/* Niepełny rząd kafli — witryna kontra przeglądanie (02.08.2026).
   Ten sam mechanizm co w Klasyku, opis przy `.front-root--home` w front.css. */
.mod-root--home { --kafle-justify: center; }
/* Lista siatek — patrz komentarz przy `.front-root--home` w front.css. */
.mod-root--home :is(
  .news-card-grid,
  .editorial-links-grid,
  .sacrament-grid,
  .event-grid
) {
  /* ZWIJANIE ZAMIAST SIATKI (03.08.2026) — ten sam mechanizm co w Klasyku,
     pełne uzasadnienie przy tej samej regule w public/css/front.css: kafle
     rosną do wypełnienia rzędu, a wzrost pojedynczego ogranicza `--kafel-max`
     (bez tej zmiennej kafel nie rośnie wcale). */
  display: flex;
  flex-wrap: wrap;
}
.mod-root--home :is(
  .news-card-grid,
  .editorial-links-grid,
  .sacrament-grid,
  .event-grid
) > * {
  flex: 1 1 var(--kafel);
  max-width: var(--kafel-max, var(--kafel));
  min-width: 0;
}

.news-card-grid {
  display: grid;
  /* Trzy kafle na pełnej szerokości (1376 px treści → 443 px kafel), nie
     cztery — patrz uzasadnienie przy .news-grid w front.css. */
  --kafel: clamp(220px, 26cqi, 340px);
  --kafel-max: 450px;
  grid-template-columns: repeat(auto-fill, minmax(min(var(--kafel), 100%), 1fr));
  justify-content: var(--kafle-justify, start);
  gap: var(--space-lg);
  margin-top: var(--space-xl);
}
.news-card {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--card-border);
  border-radius: var(--card-radius);
  overflow: hidden;
  background: var(--card-bg);
  text-decoration: none;
}
.news-card__image { display: block; height: 11rem; overflow: hidden; background: var(--card-bg-alt); }
.news-card__content { padding: var(--space-lg); }
.news-card__content :is(h2, h3) { margin: var(--space-sm) 0 0; line-height: 1.2; }
.news-card__content :is(h2, h3) a {
  color: var(--card-heading);
  font-family: var(--font-serif);
  font-size: 1.18rem;
  font-weight: 500;
  /* INTERLINIA NA NAGŁÓWKU, NIE TYLKO NA ODNOŚNIKU (15.09.2026): nagłówek
     dziedziczył 1,7 z tekstu ciała i to on wyznaczał wysokość wiersza — mniejsza
     wartość na odnośniku nic nie dawała, a dwuwierszowy tytuł rozpadał się na
     dwa napisy. Ta sama poprawka w karcie archiwum, kaflu wyróżnionym i nazwisku
     duszpasterza. */
  line-height: 1.2;
  text-decoration: none;
}
.news-card__content :is(h2, h3) a:hover { text-decoration: underline; text-underline-offset: 0.2em; }
.news-card__content p { color: var(--card-muted); font-size: 0.9rem; line-height: 1.55; margin: var(--space-sm) 0 0; }

/* Karuzela wyróżnionych (>1, tryb „karuzela") */
.news-carousel { position: relative; }
.news-carousel__viewport { overflow: hidden; border-radius: var(--card-radius); }
.news-carousel__track { display: flex; transition: transform 400ms ease; }
.news-carousel__slide { min-width: 100%; }
.news-carousel__arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 2.75rem; height: 2.75rem;
  display: grid; place-items: center;
  border: 0;
  border-radius: 50%;
  background: rgba(15, 25, 46, 0.72);
  color: #fff;
  font-size: 1.4rem;
  cursor: pointer;
  backdrop-filter: blur(6px);
}
.news-carousel__arrow--prev { left: var(--space-md); }
.news-carousel__arrow--next { right: var(--space-md); }
.news-carousel__arrow:hover { background: var(--section-heading); }
.news-carousel__dots { display: flex; justify-content: center; gap: var(--space-sm); margin-top: var(--space-md); }
.news-carousel__dot { width: 0.6rem; height: 0.6rem; border: 0; border-radius: 50%; background: var(--section-border); cursor: pointer; padding: 0; }
.news-carousel__dot.is-active { background: var(--section-accent); }
.news-featured-pinned { display: grid; gap: var(--space-lg); }

/* ============================ HERO (baner strony głównej) ============= */
.parish-hero {
  /* HERO STOI POZA ZAKRESEM SEKCJI, a jest ciemne — zdjęcie z maską albo kolor
     główny palety. Obrys fokusu musi więc iść bielą; ciemny akcent z `:root`
     miał tu 1,99:1 przy progu 3:1 (07.09.2026, A6). Zakres obejmuje wszystko,
     co na hero da się złapać klawiaturą: przycisk „Informacje podstawowe",
     krzyżyk panelu, sterowanie pokazem i odnośnik nakładki. */
  --section-focus: #FFFFFF;
  height: 34rem;
  position: relative;
  display: flex;
  align-items: stretch;
  justify-content: center;
  overflow: hidden;
  isolation: isolate;
  background: var(--color-primary-strong);
}
/* W trybie „Informacje podstawowe" hero musi pomiescic rozwiniety panel z 3
   kolumnami — inaczej jego gora jest przycinana przez overflow:hidden sekcji
   (defekt istniejacy, uwydatniony przez wiekszy odstep z punktu 3). Wysokosc
   dotyczy WYLACZNIE tego trybu; pozostale nakladki zostaja bez zmian. */
.parish-hero--info { height: auto; min-height: 40rem; }
.parish-hero__stage { position: absolute; inset: 0; z-index: -2; }
.parish-hero__slide { position: absolute; inset: 0; opacity: 0; transition: opacity 900ms ease; }
.parish-hero__slide.is-active { opacity: 1; }
.parish-hero__slide img { width: 100%; height: 100%; object-fit: cover; }
.parish-hero__mask { position: absolute; inset: 0; z-index: -1; background: linear-gradient(180deg, rgba(8,18,36,0.25), rgba(8,18,36,0.72)); }
.parish-hero__placeholder {
  position: absolute; inset: 0; z-index: -2;
  display: grid; place-items: center; text-align: center;
  background: linear-gradient(135deg, var(--color-primary), var(--color-primary-strong));
  color: #fff;
}
.parish-hero__placeholder .serif { font-family: var(--font-serif); font-size: clamp(2rem, 4vw, 3.4rem); font-weight: 500; letter-spacing: -0.02em; }
.hero-overlay { align-self: center; max-width: 52rem; padding: var(--space-xl); text-align: center; color: #fff; text-decoration: none; }
.hero-overlay__quote { margin: 0; font-family: var(--font-serif); font-size: clamp(1.6rem, 3vw, 2.6rem); font-weight: 500; line-height: 1.25; letter-spacing: -0.02em; text-shadow: 0 2px 20px rgba(0,0,0,0.35); }
.hero-overlay__author { margin: var(--space-md) 0 0; font-size: 0.9rem; font-weight: 700; color: rgba(255,255,255,0.85); }
.hero-overlay__cta { display: inline-flex; align-items: center; gap: var(--space-sm); min-height: 3rem; padding: 0 var(--space-xl); border-radius: 999px; background: var(--color-accent); color: #18233c; font-weight: 800; text-decoration: none; }
.hero-info { position: absolute; inset: 0; display: flex; flex-direction: column; justify-content: flex-end; }
/* PUNKT 1: w stanie ZWINIĘTYM hero nie jest niczym przyciemniane — widać czyste
   zdjęcie, a czytelność przycisku zapewnia jego własny cień (.hero-toggle).
   Dawne przyciemnienie CAŁEGO hero po rozwinięciu zeszło na sam panel (niżej). */

/* ROZWINIĘTY PANEL ROZPYCHA HERO, NIE JEST PRZYCINANY (06.09.2026, A4).

   BYŁO: `.hero-info` leżało `absolute` ZAWSZE, czyli poza przepływem — hero
   zostawał przy swoim `min-height: 40rem`, a wszystko poniżej znikało pod jego
   `overflow: hidden`. Zmierzone przed poprawką: panel w jednej kolumnie miał
   1537 px na telefonie i 2201 px na tablecie przy 640 px pasa, więc dwie trzecie
   danych parafii było fizycznie nieosiągalne — bez przewijania i bez żadnego
   sygnału, że coś jeszcze jest.

   JEST: po rozwinięciu panel WCHODZI W PRZEPŁYW jako pozycja flex hero. Pas
   rośnie do treści, `min-height` zostaje minimum, a zdjęcie (`__stage`,
   inset: 0) samo wypełnia nową wysokość. To samo rozwiązanie co w Klasyku
   (`.front-banner-info.is-open`, Runda 3).

   `justify-content: flex-start`, bo w stanie otwartym `.hero-info` bywa wyższe
   od panelu (min-height hero) — treść ma wtedy zaczynać się u góry, a wolne
   miejsce zostawać na dole, tam gdzie leży przycisk otwierający.

   TŁO: dwie warstwy w JEDNYM elemencie — na dole warstwa przyciemniająca
   zdjęcie, na niej kolor palety z kryciem 94%, więc zdjęcie delikatnie przebija.
   Tło niesie KONTENER, a nie panel: inaczej dwie półprzezroczyste warstwy
   nałożyłyby się i przyciemniły podwójnie. */
.hero-info.is-open {
  position: relative;
  inset: auto;
  flex: 1 1 100%;
  align-self: stretch;
  justify-content: flex-start;
  background:
    linear-gradient(rgba(var(--color-primary-strong-rgb), 0.94), rgba(var(--color-primary-strong-rgb), 0.94)),
    rgba(10, 12, 18, 0.28);
}
.hero-info__panel {
  width: min(calc(100% - 3rem), var(--tresc-max));
  margin: 0 auto;
  /* Kotwica dla krzyżyka zamykającego — róg PANELU, nie całego hero. */
  position: relative;
  display: none;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(1.5rem, 4vw, 4rem);
  /* Mniej powietrza nad nagłówkami kolumn (było clamp(3rem, 6vw, 5rem), czyli
     80 px na desktopie). Dolne wcięcie zostaje duże — na panelu leży przycisk
     otwierający i musi mieć własne miejsce. */
  padding: clamp(var(--space-xl), 4vw, var(--space-2xl)) var(--space-lg) 6rem;
  color: #fff;

  /* ============================================================
     ZAKRES ZMIENNYCH PANELU (06.09.2026, A2 + A18)

     Panel składają WSPÓLNE partiale (info-blocks, mass-schedule,
     office-details, contact-details) — te same, które stoją na jasnym pasie
     i w kolumnie bocznej, więc same z siebie przynoszą kolory dla JASNEGO tła.
     Bez tego zakresu brały je wprost z `:root` i lądowały na granacie: tytuł
     bloku 1,00:1 (dosłownie kolor tła), godziny Mszy 1,04:1, przycisk „Zobacz…"
     1,24:1, etykiety grup 2,42:1.

     Wariant ustawiamy RAZ, DLA CAŁEGO OBSZARU — nie przy pojedynczych
     selektorach. Inaczej następny wspólny partial wpadnie w tę samą dziurę,
     a poprawka będzie polegała na dopisaniu kolejnej łaty.

     AKCENT NA CIEMNYM — zmierzone na tle panelu (94% primary_strong nad
     przyciemnionym zdjęciem), wszystkie cztery palety, najgorszy przypadek
     (zdjęcie białe):
       surowy akcent (--color-accent)   3,30–4,44:1  ← poniżej progu tekstu
       --color-accent-on-dark           4,27–5,66:1  ← ikony (próg 3:1)
       --color-accent-soft              8,28–10,60:1 ← podetykiety (próg 4,5:1)
       biel                            10,06–12,68:1 ← nagłówki, godziny, przyciski
     Drobniejszy tekst dostaje jaśniejszy wariant. Pilnuje tego
     BannerRenderTest::test_hero_info_panel_accent_variants_meet_contrast_on_every_palette.

     Rodziny `--section-*` i `--card-*` ustawiamy w całości, a nie po jednej
     zmiennej — połowicznie ustawiona rodzina to dokładnie ten stan, z którego
     wziął się ten defekt. */
  --section-text: #FFFFFF;
  --section-heading: #FFFFFF;
  /* TEKST WYCISZONY (14.09.2026) — brakujący członek rodziny, o której komentarz
     wyżej mówi „w całości": bez niego panel dziedziczył szary dla JASNEGO tła
     i każdy wyciszony napis wspólnego partiala (np. dwukropek godziny) stawał
     się ciemny na granacie. Ta sama wyciszona biel, którą panel ma dla kart. */
  --section-muted: var(--card-muted);
  /* PODETYKIETY: nazwy grup godzin, dni dyżurów biura, „Numer konta" i „BLIK".
     Drobne kapitaliki, więc próg 4,5:1 — stąd najjaśniejszy wariant akcentu. */
  --section-text-soft: var(--color-accent-soft);
  /* AKCENT GRAFICZNY (ikony bloków, wierszy kontaktu i telefonu dyżurnego). */
  --section-accent: var(--color-accent-on-dark);
  --section-accent-ink: var(--color-accent-on-dark);
  /* Włosowe kreski panelu: między grupami godzin i nad danymi do wpłat. */
  --section-border: rgba(255, 255, 255, 0.16);
  --card-text: #FFFFFF;
  --card-heading: #FFFFFF;
  --card-muted: rgba(255, 255, 255, 0.78);
  /* Przycisk „Zobacz…" bierze stąd napis i obrys, a po najechaniu ZAMIENIA je
     z tłem — dlatego `--card-bg` musi być kolorem panelu, nie powierzchni. */
  --card-link: #FFFFFF;
  --card-bg: var(--color-primary-strong);
}
.hero-info__panel.is-open { display: grid; }

/* KOLUMNY (06.09.2026, B3 + B4 — reguła Klasyka w języku Nowoczesnego).
   Nagłówek z ikoną i przycisk wyśrodkowane w KAŻDEJ kolumnie; treść
   wyśrodkowana TYLKO przy Mszach, bo tam są same liczby. Biuro i Kontakt to
   wiersze danych różnej długości — wyśrodkowane robiły z nich „choinkę". */
.hero-info__block {
  min-width: 0;
  display: flex;
  flex-direction: column;
  padding: var(--space-lg);
  text-align: center;
}
/* Kreska ROZDZIELA kolumny, więc nie ma jej przy pierwszej — inaczej panel
   zaczyna się kreską przy krawędzi (A17). Krycie 0.30 zostaje świadomie
   mocniejsze niż w Klasyku. Po zwinięciu do jednej kolumny kreska znika:
   nie ma już czego rozdzielać, a pionowe kreski przy stosie bloków wyglądały
   na zabłąkane (reguła w bloku responsywnym niżej). */
.hero-info__block + .hero-info__block { border-left: 1px solid rgba(255, 255, 255, 0.30); }
.hero-info__block.info-block--office .info-block__body,
.hero-info__block.info-block--contact .info-block__body { text-align: left; }
.hero-info__panel .info-block__title { justify-content: center; }
/* Treść rozpycha kolumnę, a przycisk siada przy DOLNEJ krawędzi — trzy przyciski
   stoją wtedy równo, niezależnie od tego, ile treści jest nad każdym z nich. */
.hero-info__block .info-block__body { flex: 1 1 auto; }
.hero-info__block .info-block__more { margin-top: auto; align-self: center; }
/* Nadpisanie prozy artykułowej (ciemny kolor + większy pierwszy akapit) na
   wypadek, gdyby do panelu wróciła adnotacja — kolor bierze z zakresu wyżej. */
.hero-info__block .rich-text, .hero-info__block .rich-text > p:first-child { color: var(--card-muted); font-size: 0.92rem; line-height: 1.6; }
.hero-info__block .rich-text p { margin: 0 0 0.6rem; }

/* ETYKIETY GRUP GODZIN (B7): wyśrodkowane pod wyśrodkowanymi godzinami, kolor
   z `--section-text-soft` (zakres wyżej), a między grupami cienka linia.
   Przy lewej krawędzi wyglądały na pomyłkę, skoro godziny stoją na środku. */
.hero-info__panel .mass-schedule__day { text-align: center; }
.hero-info__panel .mass-schedule__group + .mass-schedule__group {
  padding-top: var(--space-sm);
  border-top: 1px solid var(--section-border);
}
/* DYŻURY BIURA (B8): DNI w akcencie, GODZINY białe (dziedziczą kolor panelu) —
   inaczej jedno i drugie zlewa się w jeden ciąg i nie widać, gdzie kończy się
   dzień, a zaczyna godzina. */
.hero-info__panel .office-details__days { color: var(--section-text-soft); }

/* KRZYŻYK ZAMYKAJĄCY (06.09.2026, A5).

   Przycisk otwierający ZOSTAJE na dole hero i przełącza w obie strony — to
   język Nowoczesnego i tym różni się od Klasyka, który przycisk chowa. Sam
   przełącznik jednak nie wystarcza: po rozwinięciu panelu stoi kilkaset pikseli
   niżej, poza polem widzenia. Krzyżyk leży `absolute`, czyli POZA PRZEPŁYWEM —
   nie odbiera treści ani piksela, a stoi tam, gdzie zamknięcia szuka się
   odruchowo.

   RYSUNEK Z JEDNEJ RODZINY co przycisk otwierający i jego strzałka `▾`: ta sama
   pigułka, ta sama włosowa kreska obrysu, ten sam kolor i ta sama grubość pisma.
   2,75 rem (44 px) to powyżej progu celu dotykowego (WCAG 2.5.8 mówi o 24 px). */
.hero-info__close {
  position: absolute;
  top: var(--space-md);
  right: var(--space-md);
  z-index: 2;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, 0.72);
  border-radius: 999px;
  background: transparent;
  color: #fff;
  font: inherit;
  font-size: 1.35rem;
  font-weight: 800;
  line-height: 1;
  cursor: pointer;
  transition: background-color var(--motion-state) var(--motion-ease-state),
              color var(--motion-state) var(--motion-ease-state);
}
.hero-info__close:hover { background: rgba(255, 255, 255, 0.16); }
/* Wciśnięcie ODWRACA pigułkę — jedyny stan działający na dotyku. Wymiary
   zostają te same (żadnego `transform: scale`), więc nic wokół się nie rusza. */
.hero-info__close:active { background: #fff; color: var(--color-primary-strong); }
/* Obrys fokusu przychodzi z zakresu `.parish-hero` (biel) — od 07.09.2026 nie ma
   już potrzeby powtarzać go przy każdym przycisku hero z osobna. */


.hero-toggle {
  position: absolute; left: 50%; bottom: var(--space-lg); transform: translateX(-50%);
  z-index: 2; min-height: 3.25rem;
  display: inline-flex; align-items: center; gap: var(--space-sm);
  padding: 0 var(--space-lg); border: 1px solid rgba(255,255,255,0.72); border-radius: 999px;
  background: rgba(15,25,46,0.82); color: #fff; cursor: pointer;
  /* PUNKT 1: zdjęcie w stanie zwiniętym jest czyste, więc czytelność
     przycisku zapewnia jego własny, subtelny cień. */
  box-shadow: 0 0.5rem 1.5rem rgba(0, 0, 0, 0.28);
  font: inherit; font-size: 0.82rem; font-weight: 800;
  transition: background-color var(--motion-state) var(--motion-ease-state),
              color var(--motion-state) var(--motion-ease-state),
              border-color var(--motion-state) var(--motion-ease-state);
}
.hero-toggle:hover { background: var(--color-primary-strong); }
/* WCIŚNIĘCIE (A22) — pigułka odwraca się tak samo jak krzyżyk, więc oba
   przyciski panelu reagują jednym gestem. Strzałka idzie za kolorem napisu,
   bo bierze go z `currentColor`. */
.hero-toggle:active { background: #fff; color: var(--color-primary-strong); border-color: #fff; }

.hero-toggle .caret { transition: transform var(--motion-state) var(--motion-ease-state); }
.hero-toggle .caret.is-rotated { transform: rotate(180deg); }

/* STEROWANIE POKAZEM SLAJDÓW (07.09.2026, A20) — ta sama pigułka co przycisk
   „Informacje podstawowe" i krzyżyk panelu, w rogu, żeby nie wchodziła w drogę
   nakładce. Obrys fokusu własny, biały: przycisk leży na ZDJĘCIU, czyli poza
   jakimkolwiek zakresem sekcji, a zdjęcie bywa dowolnie jasne. */
.hero-slides-toggle {
  position: absolute;
  right: var(--space-lg);
  bottom: var(--space-lg);
  z-index: 2;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, 0.72);
  border-radius: 999px;
  background: rgba(15, 25, 46, 0.82);
  color: #fff;
  font: inherit;
  font-size: 0.8rem;
  line-height: 1;
  cursor: pointer;
  box-shadow: 0 0.5rem 1.5rem rgba(0, 0, 0, 0.28);
  transition: background-color var(--motion-state) var(--motion-ease-state),
              color var(--motion-state) var(--motion-ease-state);
}
.hero-slides-toggle:hover { background: var(--color-primary-strong); }
.hero-slides-toggle:active { background: #fff; color: var(--color-primary-strong); }


/* ============================ PAS: home-module (wspólny) ============== */
/* Odstęp pasa z tokenu band-space + wcięcie treści z .mod-section (dawne
   `padding: clamp() space-lg` USUNIĘTE — jeden rytm). Zostaje sama linia u góry. */
.home-module { border-top: 1px solid var(--section-border); }
/* Wnętrze: bez własnego max-width — treść wcina już padding .mod-section do
   --section-content (1160 tekst / 1320 siatki), więc tu tylko semantyczny blok. */
.home-module__inner { margin: 0 auto; }
.home-module__heading { display: flex; align-items: end; justify-content: space-between; gap: var(--space-lg); margin-bottom: var(--space-lg); }
.home-module__heading h2 { margin: 0; color: var(--section-heading); font-family: var(--font-serif); font-size: clamp(1.85rem, 3vw, 2.7rem); font-weight: 500; line-height: 1.02; letter-spacing: -0.03em; }
.home-module__heading > a, .home-module__footer > a { display: inline-flex; align-items: center; gap: var(--space-2xs); color: var(--section-link); font-size: 0.8rem; font-weight: 900; text-decoration: none; white-space: nowrap; }
.home-module__heading > a:hover, .home-module__footer > a:hover { text-decoration: underline; }
.home-module__footer { display: flex; justify-content: flex-end; margin-top: var(--space-lg); }

/* Ogłoszenia-skrót */
/* Tło i włosowa obwódka to DOMYŚLNE wartości zakresu tego pasa (styl inline
   wariantu je nadpisze) — dzięki temu pas uczestniczy w wyborze tła. */
/* ⚠️ TŁO PASA NIE SIEDZI W KLASIE (12.09.2026). Ogłoszenia, Intencje na dziś
   i Duszpasterze miały tu `--section-bg` na sztywno (akcent zmiękczony, biel,
   przygaszone) — wariant „jasne" nie wstawia stylu inline, więc klasa wygrywała
   i wybór w panelu NIC nie zmieniał; przy tle strony pas zasłaniał je u siebie.
   Tło daje wyłącznie wariant (App\Support\Front\SectionBackgrounds). Pilnuje
   SectionBackgroundsTest. */
.announcements-band { border-bottom: 1px solid var(--section-rule, rgba(var(--color-accent-rgb), 0.24)); }
.mod-ann__title { margin: 0 0 var(--space-sm); color: var(--section-heading); font-family: var(--font-serif); font-size: clamp(1.4rem, 2.2vw, 2rem); font-weight: 500; line-height: 1.15; }
.mod-ann__meta { display: inline-flex; align-items: center; gap: var(--space-sm); margin-bottom: var(--space-md); color: var(--section-muted); font-size: 0.82rem; font-weight: 700; }
/* Kropka koloru szat — wypelnienie NIGDY nie idzie z palety; na mocnych
   tlach zmienia sie tylko pierscien (E2). */
/* Zapas pierścienia to TON STRONY, nie biel (12.09.2026): poza pasem o własnym
   tle kropka leży na tle strony, a przy tle w kolorze albo zdjęciu biały
   pierścień robił się jasną obwódką na kolorze. */
.mod-ann__dot { width: 0.75rem; height: 0.75rem; border: 2px solid var(--section-dot-ring, var(--color-page)); border-radius: 50%; box-shadow: 0 0 0 1px var(--card-border); display: inline-block; }
.mod-ann__body { max-width: 52rem; color: var(--section-text); line-height: 1.7; }
.mod-ann__body.rich-text p { margin: 0 0 var(--space-md); }
/* Rząd akcji domykający blok — do PRAWEJ (01.08.2026), jak w Klasyku. */
.mod-ann__actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--space-md); margin-top: var(--space-lg); }
.mod-ann__archive { color: var(--section-link); font-size: 0.8rem; font-weight: 900; text-decoration: none; }
.mod-ann__archive:hover { text-decoration: underline; text-underline-offset: 0.2em; }

/* ---- Ogłoszenia — tryb KOMPAKT (pas trójdzielny: skrót ogłoszeń | Ewangelia
   dnia | feed katolicki) — flex + min-width:0, bez stałych szerokości, więc
   rząd zwęża się do kolumny ⅓ bez przelewania treści. */
.front-ann-compact__heading { font-family: var(--font-serif); font-size: 1.25rem; font-weight: 500; color: var(--section-heading, var(--section-text)); margin: 0 0 var(--space-md); }
.front-ann-compact__row { display: flex; align-items: flex-start; gap: var(--space-sm); text-decoration: none; color: inherit; min-width: 0; }
.front-ann-compact__icon { flex: 0 0 auto; width: 1.35rem; height: 1.35rem; color: var(--color-primary, var(--section-accent)); margin-top: 0.1rem; }
.front-ann-compact__body { display: flex; flex-direction: column; gap: 0.25rem; min-width: 0; }
.front-ann-compact__title { font-weight: 700; color: var(--section-text); line-height: 1.4; }
.front-ann-compact__row:hover .front-ann-compact__title { color: var(--color-primary); }
.front-ann-compact__date { font-size: 0.82rem; color: var(--section-muted); display: inline-flex; align-items: center; gap: 0.4rem; }
/* Jak w Klasyku: na mocnych pasach przycisk sie obrysowuje, hover wypelnia. */
.btn-dark { display: inline-flex; align-items: center; min-height: 3rem; padding: 0 var(--space-lg); border-radius: 999px; background: var(--section-btn-bg, var(--color-primary)); color: var(--section-btn-ink, #fff); font-weight: 800; text-decoration: none; }
.btn-dark:hover { background: var(--section-btn-bg-hover, var(--color-primary-strong)); color: var(--section-btn-ink-hover, #fff); }

/* Intencje na dziś */
/* .intentions-band — bez własnego tła, patrz komentarz przy .announcements-band. */
.liturgical-day { display: inline-flex; align-items: center; gap: var(--space-sm); margin-bottom: var(--space-md); color: var(--section-muted); font-size: 0.82rem; font-weight: 700; }
.mass-row { display: grid; gap: var(--space-md); }
.mass-row--one { grid-template-columns: minmax(0, 34rem); }
.mass-row--two { grid-template-columns: repeat(2, minmax(0, 1fr)); max-width: 48rem; }
.mass-row--many { grid-template-columns: none; grid-auto-flow: column; grid-auto-columns: minmax(11rem, 1fr); overflow-x: auto; padding: 0.15rem 0.1rem 0.55rem; scroll-snap-type: x proximity; -webkit-overflow-scrolling: touch; overscroll-behavior-inline: contain; }
/* Intencje (msze dnia) — dwie msze obok siebie zwijają się według KONTENERA
   (23.07.2026, „miękki" przypadek z audytu: ten sam mechanizm je poprawia). */
@container (max-width: 34rem) { .mass-row--two { grid-template-columns: 1fr; max-width: none; } }
.mass-row article { min-width: 0; min-height: 8rem; display: flex; flex-direction: column; padding: var(--space-md); border: 1px solid var(--card-border); border-radius: var(--card-radius); background: var(--card-bg-alt); scroll-snap-align: start; }
.mass-row article > header { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; padding-bottom: 0.65rem; border-bottom: 1px solid var(--card-border); }
.mass-row time { color: var(--section-link); font-family: var(--font-serif); font-size: 1.4rem; font-weight: 500; }
.mass-row article > header .mass-type { padding: 0.25rem 0.45rem; border-radius: 999px; background: var(--section-accent-soft, var(--color-accent-soft)); color: var(--card-link); font-size: 0.55rem; font-weight: 900; text-transform: uppercase; }
.mass-row .mass-intentions { margin: 0.6rem 0 0; padding: 0; list-style: none; color: var(--section-text); font-size: 0.78rem; line-height: 1.5; }
.mass-row .mass-intentions li { margin-bottom: 0.3rem; }
.mass-row .mass-free { margin-top: 0.6rem; color: var(--section-muted); font-size: 0.78rem; font-style: italic; }

/* Duszpasterze-pas */
.pastors-band { --section-content: var(--tresc-max); border-bottom: 1px solid var(--section-border); }
.pastor-row { display: grid; gap: clamp(1.25rem, 3vw, 2.5rem); }
.pastor-row--one { grid-template-columns: minmax(0, 48rem); }
.pastor-row--one article { display: grid; grid-template-columns: 11rem 1fr; gap: 1.75rem; align-items: center; }
.pastor-row--two { grid-template-columns: repeat(2, minmax(0, 1fr)); max-width: 58rem; }
.pastor-row--two article { display: grid; grid-template-columns: 8rem 1fr; gap: 1.25rem; align-items: center; }
.pastor-row--many { grid-template-columns: none; grid-auto-flow: column; grid-auto-columns: minmax(10rem, 1fr); overflow-x: auto; padding: 0.25rem 0.15rem 0.75rem; scroll-snap-type: x proximity; -webkit-overflow-scrolling: touch; overscroll-behavior-inline: contain; }
.pastor-row--many article { min-width: 0; text-align: center; scroll-snap-align: start; }
.pastor-row article { text-decoration: none; }
/* Obwódka zdjęcia — ton strony zamiast bieli, z tego samego powodu co pierścień
   kropki wyżej (12.09.2026). Na pasie z własnym tłem zakres nadpisuje token. */
.pastor-photo { width: 7rem; height: 7rem; display: grid; place-items: center; margin: 0 auto; border: 4px solid var(--section-dot-ring, var(--color-page)); border-radius: 50%; background: var(--section-accent-soft, var(--color-accent-soft)); color: var(--card-link); box-shadow: 0 0.7rem 1.8rem rgba(31,35,43,0.1); overflow: hidden; }
.pastor-row--one .pastor-photo { width: 11rem; height: 11rem; }
.pastor-photo img { width: 100%; height: 100%; object-fit: cover; }
.pastor-photo svg { width: 2.7rem; height: 2.7rem; }
.pastor-copy h3 { margin: 0.55rem 0 0.15rem; color: var(--card-heading); font-family: var(--font-serif); font-size: 1rem; font-weight: 500; line-height: 1.2; }
.pastor-role { margin: 0; color: var(--section-accent-ink, var(--color-accent-strong)); font-size: 0.65rem; font-weight: 900; text-transform: uppercase; }
/* Duszpasterze zwijają się według KONTENERA (23.07.2026): dwie osoby obok
   siebie → jedna kolumna w wąskim pasie; kompozycja pozioma zdjęcie+tekst →
   pion, gdy komórka jest za wąska. --many (przewijany rząd) bez zmian. */
@container (max-width: 44rem) { .pastor-row--two { grid-template-columns: 1fr; max-width: none; } }
@container (max-width: 30rem) {
  .pastor-row--one article, .pastor-row--two article { grid-template-columns: 1fr; text-align: center; }
  .pastor-row--one .pastor-photo { width: 9rem; height: 9rem; }
}

/* Karty-linki (editorial, ciemny pas) */
/* Pas kart-linkow jest w tym szablonie CIEMNY z zalozenia (uklad = szablon).
   Deklarujemy to jako DOMYSLNE wartosci zakresu, wiec wybor wariantu przez
   parafie (styl inline) i tak je nadpisze. */
/* Ciemny pas + szeroki kontener treści; odstęp/wcięcie z .mod-section
   (dawne `padding: section-space space-lg` USUNIĘTE — jeden rytm). */
.editorial-links-band {
  --section-content: var(--tresc-max);
  --section-bg: var(--color-primary);
  --section-text: #fff;
  --section-heading: #fff;
  --section-muted: rgba(255, 255, 255, 0.78);
  --card-heading: var(--color-primary-strong);
}
.editorial-links-inner { margin: 0 auto; }
.editorial-links-kicker { display: block; margin-bottom: var(--space-sm); color: var(--section-accent-on-dark, var(--color-accent-on-dark)); font-size: 0.75rem; font-weight: 800; letter-spacing: 0.14em; text-transform: uppercase; }
.editorial-links-inner > h2 { margin: 0 0 var(--space-xl); font-family: var(--font-serif); font-size: clamp(2rem, 4vw, 3.4rem); font-weight: 500; line-height: 1; letter-spacing: -0.035em; }
/* REGUŁA 1 — jak wyżej. Karta redakcyjna jest szersza od kafla aktualności
   (nagłówek krojem szeryfowym + akapit), więc i próg jest wyższy.
     pełny  → 26cqi ≈ 330 → 3 karty    połowa → 280 → 2    ⅓ → 280 → 1

   ⚠️ UDZIAŁ MUSI ZOSTAWIĆ MIEJSCE NA ODSTĘPY (16.09.2026). Do tego dnia stało
   tu 31cqi, choć komentarz mówił 26 — i to 31 było błędem, nie opis. Trzy karty
   po 31% to 93% szerokości siatki, a odstępy dokładają jeszcze ~9% (2 × 43 px
   przy 1440 px), więc trzecia karta spadała pod spód w KAŻDEJ kolumnie głównej
   (mieściła się dopiero od ~1234 px siatki, czyli w pasie pełnej szerokości).
   Przy 26% w kolumnie głównej (950 px) obowiązuje podłoga 280 px: 3 × 280 + 86
   = 926 px, więc trzy karty wchodzą i rosną do ~288 px. Dokładając odstęp albo
   ruszając udział, sprawdź rachunek 3 × karta + 2 × odstęp ≤ szerokość siatki. */
.editorial-links-grid {
  display: grid;
  --kafel: clamp(280px, 26cqi, 400px);
  --kafel-max: 450px;
  grid-template-columns: repeat(auto-fill, minmax(min(var(--kafel), 100%), 1fr));
  justify-content: var(--kafle-justify, start);
  gap: clamp(1.5rem, 3vw, 2.75rem);
}
@container (max-width: 34rem) { .editorial-links-grid { gap: var(--space-2xl); } }
.editorial-link-card { min-width: 0; display: flex; flex-direction: column; }
.editorial-link-card header { margin-bottom: var(--space-lg); }
/* STOPIEŃ PISMA LICZY SIĘ OD KARTY, NIE OD OKNA (16.09.2026).
   Dotąd nagłówek rósł z szerokością OKNA (2vw), a karta brała szerokość
   z kontenera, który przy szerokim oknie już nie rośnie — obie wartości szły
   więc w przeciwne strony: przy 1440 px „Posługa duszpasterska" mieściła się
   w jednym wierszu z zapasem 2 px, a od 1600 px pismo miało już 30 px i tytuł
   łamał się na dwa wiersze na KAŻDYM szerszym ekranie. Udział `cqi` liczy się
   od siatki, czyli rośnie i maleje razem z kartą (zasada „wymiary z kontenera,
   nie z okna" — REGUŁA 1 wyżej).
   `text-wrap: balance` dotyczy tytułów, które i tak się nie zmieszczą: dłuższy
   nagłówek dzieli się wtedy po równo, zamiast zostawiać samotne słowo. Tekstu
   NIE UCINAMY — nazwa modułu parafialnego ma być widoczna w całości. */
.editorial-link-card h3 { margin: 0; font-family: var(--font-serif); font-size: clamp(1.35rem, 2.85cqi, 1.75rem); font-weight: 500; line-height: 1.15; text-wrap: balance; }
.editorial-link-card header p { margin: var(--space-2xs) 0 0; color: var(--section-muted); font-size: 0.9rem; }
.editorial-link-image { display: block; aspect-ratio: 16 / 10; overflow: hidden; border-radius: var(--card-radius); background: var(--card-heading); }
.editorial-link-image img { width: 100%; height: 100%; object-fit: cover; transition: transform 300ms ease; }
.editorial-link-image:hover img { transform: scale(1.03); }
.editorial-link-description { margin: var(--space-lg) 0; color: var(--section-muted); font-size: 0.94rem; line-height: 1.65; }
.editorial-link-button { min-height: 3rem; align-self: flex-start; display: inline-flex; align-items: center; gap: var(--space-sm); margin-top: auto; padding: 0 var(--space-lg); border-radius: 999px; background: var(--section-accent); color: #18233c; font-size: 0.84rem; font-weight: 800; text-decoration: none; }

/* Pas galerii (Galerie I Multimedia) — szeroki kontener; tło pełne okno i
   odstęp/wcięcie z .mod-section (dawne `max-width/margin/padding` na SAMYM pasie
   USUNIĘTE — inaczej tło kończyło się na kontenerze, a nie na krawędzi okna). */
.gallery-band { --section-content: var(--tresc-max); }
.gallery-band__heading { margin-bottom: var(--space-xl); }
.gallery-band__heading h2 { margin: 0; color: var(--section-heading); font-family: var(--font-serif); font-size: clamp(1.85rem, 3vw, 2.7rem); font-weight: 500; line-height: 1.02; letter-spacing: -0.03em; }
/* Zwijanie według KONTENERA: siatka z większym kaflem wiodącym → 2 → 1. */
.gallery-grid { display: grid; grid-template-columns: 1.35fr repeat(3, 1fr); gap: clamp(0.75rem, 1.5vw, 1.25rem); }
@container (max-width: 60rem) {
  .gallery-grid { grid-template-columns: repeat(2, 1fr); }
  .gallery-tile { height: 18rem; }
  .gallery-tile--lead { grid-column: span 2; height: 24rem; }
}
@container (max-width: 34rem) {
  .gallery-grid { grid-template-columns: 1fr; }
  .gallery-tile--lead { grid-column: auto; height: 18rem; }
}
.gallery-tile { position: relative; min-width: 0; height: 21rem; overflow: hidden; border-radius: var(--card-radius); background: var(--card-heading); color: #fff; text-decoration: none; display: block; }
.gallery-tile__img { width: 100%; height: 100%; object-fit: cover; transition: transform 350ms ease; }
.gallery-tile:hover .gallery-tile__img { transform: scale(1.035); }
/* PRZYCIEMNIENIE ZAKOTWICZONE POD NAPISEM — uzasadnienie i pomiary jak
   w front-base.css, ta sama sekcja. Tu różnica jest jedna: przyciemnienie żyło
   w OSOBNEJ warstwie (`__shade`, `inset: 0`) rozciągniętej na cały kafel, więc
   pod literami dawało tyle, ile wynikało z wysokości kafla.

   Zmierzone w katalogu (`.mod-tiles-grid`, kafel 16rem = 256 px, 1440 px):
   góra liter 53 px od dołu przy tytule jednowierszowym i 82 px przy
   dwuwierszowym, a rampa `transparent 35% → 0,88` ma w tym drugim miejscu
   dopiero ~0,45 krycia. Kontrast: 3,70:1 bez okładki, 3,00:1 na białym zdjęciu.
   Na stronie głównej kafel ma 21rem i ta SAMA reguła daje 6,24–7,26:1 — inna
   wysokość, inny wynik. Właśnie o to chodzi.

   PODZIAŁ RÓL PO ZMIANIE:
     `__shade`   — NASTRÓJ ZDJĘCIA, nic nie gwarantuje. Stąd zejście z 0,88 na
                   0,30: fotografia jest odsłonięta wyżej niż dotąd.
     `__content` — PRZYCIEMNIENIE POD TEKSTEM, przyklejone do dołu kafla, rampa
                   kończy się tam, gdzie zaczyna się tekst (`--tile-scrim`).

   ⚠️ RAMPA MUSI WYSTARCZAĆ SAMA, BEZ `__shade`. Gdyby próg opierał się na obu
   warstwach naraz, zależałby znowu od wysokości kafla — czyli wróciłaby dokładnie
   ta usterka, tylko trudniejsza do zauważenia. Dlatego 0,62, tak samo jak
   w bazie, mimo że pomiar z `__shade` pod spodem daje 7,86–9,21:1, czyli więcej
   niż wymagane 4,5:1.

   Strażnik: tests/Feature/Front/GalleryTileScrimTest.php */
.gallery-tile__shade { position: absolute; inset: 0; background: linear-gradient(180deg, transparent 45%, rgba(8,18,36,0.30) 100%); }
.gallery-tile__overlay, .gallery-tile__content {
  --tile-scrim: 4rem;
  position: absolute;
  inset: auto 0 0 0;
  display: grid;
  gap: var(--space-sm);
  padding: var(--tile-scrim) var(--space-lg) var(--space-lg);
  background: linear-gradient(180deg,
    rgba(8, 18, 36, 0) 0,
    rgba(8, 18, 36, 0.62) var(--tile-scrim),
    rgba(8, 18, 36, 0.88) 100%);
}
.gallery-tile__meta { display: flex; flex-wrap: wrap; gap: var(--space-md); color: rgba(255,255,255,0.82); font-size: 0.75rem; font-weight: 700; }
.gallery-tile__title, .gallery-tile__content strong { font-family: var(--font-serif); font-size: clamp(1.2rem, 1.7vw, 1.65rem); font-weight: 500; line-height: 1.18; margin: 0; }

/* Multimedia-skrót (kafle jak galeria + play) */
.video-tile__play { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 3.4rem; height: 3.4rem; display: grid; place-items: center; border-radius: 50%; background: rgba(15,25,46,0.72); color: #fff; z-index: 1; }
.video-tile__duration { position: absolute; top: var(--space-sm); right: var(--space-sm); padding: 0.15rem 0.45rem; border-radius: 0.4rem; background: rgba(0,0,0,0.7); color: #fff; font-size: 0.72rem; font-weight: 700; z-index: 1; }
/* Etykieta rodzaju („Playlista wideo", „Audio") na kaflu Multimediów. Stopień
   pisma z PODŁOGI CZYTELNOŚCI, nie z ułamka sąsiada: 0.62rem dawało 9,9 px,
   czyli poniżej granicy dla tekstu, który niesie treść. Pigułka, kolor
   i miejsce bez zmian. */
.cat-badge--float { position: absolute; top: var(--space-sm); left: var(--space-sm); padding: 0.2rem 0.5rem; border-radius: 999px; background: var(--section-accent); color: var(--color-text); font-size: max(var(--text-floor), 0.62rem); font-weight: 900; text-transform: uppercase; z-index: 1; }

/* Myśl dnia */
/* Kolory pasa pochodzą z ZAKRESU SEKCJI (E2) — tło maluje .mod-section.
   Domyślny wariant tego pasa to „ciemne". */
/* Domyslny wariant tego pasa to ciemny (rejestr widgetu); wartosci ponizej
   obowiazuja, gdy parafia wybierze wariant jasny/przygaszony. */
/* Odstęp/wcięcie z .mod-section (dawna dokładka `padding: clamp() space-lg`
   USUNIĘTA — jeden rytm dla wszystkich pasów). Zostają same linie. */
.daily-thought-band { border-top: 1px solid var(--section-rule, rgba(var(--color-accent-rgb), 0.24)); border-bottom: 1px solid var(--section-rule, rgba(var(--color-accent-rgb), 0.24)); }
.daily-thought-inner { max-width: var(--tresc-max); margin: 0 auto; display: grid; grid-template-columns: 13rem minmax(0, 1fr); gap: var(--column-gap); align-items: center; }
.daily-thought-label { display: flex; flex-direction: column; justify-content: center; gap: var(--space-md); padding-right: var(--space-xl); border-right: 1px solid var(--section-rule, rgba(var(--color-accent-rgb), 0.45)); color: var(--section-link); font-size: 0.78rem; font-weight: 800; letter-spacing: 0.14em; text-transform: uppercase; }
.daily-thought-label__mark { font-family: var(--font-serif); font-size: 2rem; color: var(--section-accent-ink, var(--color-accent-strong)); line-height: 1; }
.daily-thought-band blockquote { margin: 0; }
/* PISMO OD PASA, NIE OD OKNA (16.09.2026) — pas Myśli dnia zwęża się przy
   szerokim oknie (kontener ma sufit), a pismo liczone od okna w tym samym
   czasie rosło: przy 2560 px cytat miał 34,2 px w polu 656 px zamiast 32 px
   w polu 685 px przy 1440. Pas jest już kontenerem zapytań (`.mod-section`),
   więc wystarczy zmienić samą miarę. */
.daily-thought-band blockquote p { max-width: 52rem; margin: 0; color: var(--section-heading); font-family: var(--font-serif); font-size: clamp(1.325rem, 3.4cqi, 2.137rem); font-weight: 500; line-height: 1.32; letter-spacing: -0.018em; }
.daily-thought-band blockquote footer { margin-top: var(--space-md); color: var(--section-muted); font-size: 0.85rem; font-weight: 800; font-style: normal; }

/* Pasek akcji (Polecane, strefa action_bar) — pełnoszerokościowe banery */
.mod-promoted-bar { display: grid; gap: var(--space-md); }
/* BEZ OBWÓDKI (03.08.2026) — jak w Klasyku; tu ramkę rysował cień wewnętrzny
   tej reguły, własnej dla pozycji paska. Kafle Aktualności i kart-linków mają
   swoje reguły z tym samym tokenem i zostają nietknięte. Najechanie zachowuje
   uniesienie i cień rzucany — znika wyłącznie pierścień. */
.mod-promoted-bar__item {
  display: block;
  overflow: hidden;
  border-radius: var(--card-radius);
  text-decoration: none;
  box-shadow: none;
  transition: box-shadow 220ms ease, transform 220ms ease;
}
.mod-promoted-bar__item:hover {
  transform: translateY(-3px);
  box-shadow: 0 1.4rem 3rem rgba(31, 35, 43, 0.16);
}
.mod-promoted-bar__item:active {
  transform: none;
  box-shadow: none;
  filter: brightness(0.97);
}
.mod-promoted-bar__item img { display: block; width: 100%; height: auto; }

/* POZYCJA BEZ GRAFIKI (25.07.2026, Etap 4 pracy nocnej).
   Wcześniej: wyśrodkowany napis na szarym prostokącie — wyglądał dokładnie jak
   niewczytany obrazek. Teraz ZAMIERZONY baner: tło z rozjaśnionego akcentu,
   tytuł do lewej, strzałka „prowadzi dalej" do prawej.

   Nowoczesny mówi tu własnym językiem — pierścień i uniesienie zamiast paska
   akcentu z lewej, którym posługuje się Klasyk. */
.mod-promoted-bar__content {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-lg);
  padding: var(--space-lg) var(--space-xl);
  background: var(--promo-bg, var(--color-accent-soft, var(--card-bg-alt)));
  font-family: var(--font-ui);
  font-size: 1.15rem;
  font-weight: 600;
  line-height: 1.35;
  color: var(--promo-ink, var(--card-link, var(--color-primary-strong)));
  text-align: left;
}
/* Strzałka jako pseudo-element PRZYPIĘTY do pozycji — nigdy osobny element
   z marginesami (ta sama zasada, co przy separatorze godzin Mszy). */
.mod-promoted-bar__content::after {
  content: "→";
  flex: 0 0 auto;
  transition: transform 220ms ease;
}
.mod-promoted-bar__item:hover .mod-promoted-bar__content::after { transform: translateX(5px); }
/* Pozycja Z PRZYCISKIEM nie dokłada drugiej strzałki — tę niesie już przycisk. */
.mod-promoted-bar__content[data-cta]::after { content: none; }

/* PRZYKLEJANIE PASA (01.08.2026) — pełne uzasadnienie przy tej samej regule
   w public/css/front.css. Nowoczesny ma dodatkowo własne wcięcie treści
   (.mod-body__inner), więc i jemu trzeba zdjąć odstęp pionowy. */
.mod-promoted-bar[data-flush] { gap: 0; }
.mod-promoted-bar[data-flush] .mod-promoted-bar__item { border-radius: 0; }
/* TŁO DO KRAWĘDZI OKNA, TREŚĆ NA WSPÓLNEJ SIATCE (02.08.2026) — ta sama
   technika co w Klasyku (pełne uzasadnienie w public/css/front.css). Nowoczesny
   ma dodatkowo własny kontener treści (.mod-body__inner z max-width), więc
   w tym trybie zdejmujemy także jego ograniczenie — inaczej to ono zatrzymałoby
   tło na linii kontenera. */
.mod-section--flush { padding-block: 0; padding-inline: 0; }
.mod-section--flush .mod-body__inner { padding-block: 0; padding-inline: 0; max-width: none; }
.mod-promoted-bar[data-flush] .mod-promoted-bar__content {
  padding-inline: var(--tresc-wciecie);
  /* Pas akcentu z lewej to gest KARTY. Przy krawędzi okna zostawał jako
     pionowy pasek innego koloru niż baner — i przesuwał tekst o swoje
     4 px, więc napis nie stawał dokładnie na linii tytułów sekcji. */
  border-left: 0;
}
.mod-promoted-bar[data-flush] .mod-promoted-bar__item { border-radius: 0; }
.mod-section:has(+ .mod-section--flush) { padding-bottom: 0; }
.mod-section--flush + .mod-section { padding-top: 0; }
/* Granica pasa i strefy dwukolumnowej — uzasadnienie przy tej samej regule
   w public/css/front.css. */
[data-motion-enter-list]:has(> .mod-section--flush:last-child) + .mod-body > .mod-body__inner { padding-top: 0; }
.mod-body:has(+ [data-motion-enter-list] > .mod-section--flush:first-child) > .mod-body__inner { padding-bottom: 0; }
.mod-main .mod-section--flush { margin-block: 0; }
.mod-main .mod-section:has(+ .mod-section--flush) { margin-bottom: 0; }
.mod-main .mod-section--flush + .mod-section { margin-top: 0; }

/* TRZY TRYBY POZYCJI (02.08.2026) — App\Enums\PromotedLinkMode; zmienne
   `--promo-*` z App\Support\Front\PromotedTones, wspólne dla obu szablonów.
   Pełne uzasadnienie przy tych samych regułach w public/css/front.css.
   `banner` nie nadpisuje niczego — to render sprzed wprowadzenia trybów. */
.mod-promoted-bar__item[data-mode="color"],
.mod-promoted-bar__item[data-mode="photo"] {
  background: var(--promo-bg);
}
.mod-promoted-bar__item[data-mode="photo"] {
  position: relative;
  display: flex;
  min-height: clamp(190px, 20vw, 320px);
}
/* Zdjęcie poza przepływem — uzasadnienie przy tej samej regule w front.css. */
.mod-promoted-bar__item[data-mode="photo"] img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.mod-promoted-bar__item[data-mode="photo"] .mod-promoted-bar__content {
  position: relative;
  flex: 1;
  background: rgba(var(--promo-overlay), var(--promo-overlay-alpha, 0.45));
}

/* ---------------------------------------------------------------------------
   POLECANE — STREFA „KOLUMNA BOCZNA" (12.08.2026)

   Do tej pory Nowoczesny nie rysował tej strefy wcale (w widoku railu stała
   notatka „do zrobienia"), więc kafle wskazane w module Wyróżnione nie
   pojawiały się na stronie i nic o tym nie mówiło.

   Język tej skórki, nie przepisany Klasyk: kafel jest KARTĄ railu — tą samą,
   co menu boczne i boks „Myśl dnia" (obwódka, promień, biel, delikatny cień),
   z uniesieniem na najechanie znanym z pasa akcji. Tryby pozycji (gotowy baner
   / fotografia z tytułem / sam ton) i zmienne tonu `--promo-*` są wspólne dla
   obu szablonów — pochodzą z rekordu, nie ze skórki.
   --------------------------------------------------------------------------- */
.mod-promoted-tiles { display: flex; flex-direction: column; gap: var(--space-md); }
.mod-promoted-tiles__item {
  display: block;
  overflow: hidden;
  border: 1px solid var(--color-border);
  border-radius: var(--card-radius);
  background: #fff;
  box-shadow: 0 0.75rem 2rem rgba(31, 35, 43, 0.06);
  text-decoration: none;
  /* Ruch z warstwy tokenów — nowy kod nie wpisuje czasów na sztywno
     (pas akcji ma je jeszcze własne, jako inwentarz stanu sprzed tej warstwy). */
  transition: box-shadow var(--motion-state) var(--motion-ease-state),
              transform var(--motion-state) var(--motion-ease-state);
}
.mod-promoted-tiles__item:hover {
  transform: translateY(-3px);
  box-shadow: 0 1.4rem 3rem rgba(31, 35, 43, 0.16);
}
.mod-promoted-tiles__item:active { transform: none; box-shadow: none; filter: brightness(0.97); }
/* Gotowy baner idzie bez obwódki — grafika ma własny brzeg. */
.mod-promoted-tiles__item[data-mode="banner"] { border: 0; }
.mod-promoted-tiles__img { display: block; width: 100%; height: auto; }

.mod-promoted-tiles__content {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  align-items: flex-start;
  padding: var(--space-lg);
  background: var(--promo-bg, var(--color-accent-soft, var(--card-bg-alt)));
  font-family: var(--font-ui);
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.35;
  color: var(--promo-ink, var(--card-link, var(--color-primary-strong)));
  text-align: left;
}
.mod-promoted-tiles__content[data-align="center"] { align-items: center; text-align: center; }
.mod-promoted-tiles__content[data-align="end"] { align-items: flex-end; text-align: right; }

/* TON POZYCJI — kolor tła i obwódki z katalogu tonów (te same zmienne co w pasie). */
.mod-promoted-tiles__item[data-mode="color"],
.mod-promoted-tiles__item[data-mode="photo"] { background: var(--promo-bg); border-color: var(--promo-border); }

/* FOTOGRAFIA Z TYTUŁEM — zdjęcie POZA PRZEPŁYWEM, żeby o wysokości kafla
   decydowała minimalna wysokość kadru albo długość tytułu, a nie proporcja
   pliku (ta sama pułapka co w pasie akcji, zmierzona w przeglądarce). */
.mod-promoted-tiles__item[data-mode="photo"] { position: relative; display: flex; min-height: 8.5rem; }
.mod-promoted-tiles__item[data-mode="photo"] .mod-promoted-tiles__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.mod-promoted-tiles__item[data-mode="photo"] .mod-promoted-tiles__content {
  position: relative;
  flex: 1;
  justify-content: center;
  background: rgba(var(--promo-overlay), var(--promo-overlay-alpha, 0.45));
}

/* Cały kafel klikalny mimo przycisku — warstwa rozciągnięta z odnośnika. */
.mod-promoted-tiles__item:has(.mod-promoted-tiles__cta) { position: relative; }
.mod-promoted-tiles__cta::after { content: ""; position: absolute; inset: 0; }
.mod-promoted-tiles__cta { position: relative; z-index: 1; }
.mod-promoted-tiles__title { min-width: 0; }

/* WYRÓWNANIE treści pozycji bez grafiki (`start` = dzisiejsze rozstawienie). */
.mod-promoted-bar__content[data-align="center"] { justify-content: center; text-align: center; }
.mod-promoted-bar__content[data-align="end"] { justify-content: flex-end; text-align: right; }

/* PRZYCISK POZYCJI — system akcji w kolorach TONU POZYCJI; zapasy = tokeny pasa. */
.btn--promo {
  background: var(--promo-btn-bg, var(--section-action-bg, var(--color-primary-strong)));
  color: var(--promo-btn-ink, var(--section-action-ink, var(--color-text-inverse, #FFFFFF)));
  border-color: transparent;
}
.btn--promo:hover {
  background: var(--promo-btn-bg-hover, var(--section-action-bg-hover, var(--color-primary-strong)));
  color: var(--promo-btn-ink, var(--section-action-ink, var(--color-text-inverse, #FFFFFF)));
}
/* Cały baner klikalny mimo przycisku — warstwa rozciągnięta z odnośnika. */
.mod-promoted-bar__item:has(.mod-promoted-bar__cta) { position: relative; }
.mod-promoted-bar__cta::after { content: ""; position: absolute; inset: 0; }
.mod-promoted-bar__cta { position: relative; z-index: 1; }
.mod-promoted-bar__title { min-width: 0; }

/* Informacje-kafle (widget „icons") */
.mod-info-strip { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-lg); }
.mod-info-card { padding: var(--space-xl) var(--space-lg); border: 1px solid var(--card-border); border-radius: var(--card-radius); background: var(--card-bg); box-shadow: var(--shadow-card); }
.mod-info-card__mark { display: inline-grid; place-items: center; width: 2.75rem; height: 2.75rem; margin-bottom: var(--space-md); border-radius: 50%; background: var(--section-accent-soft, var(--color-accent-soft)); color: var(--card-link); }
.mod-info-card__mark svg { width: 1.4rem; height: 1.4rem; display: block; }
.mod-info-card h2, .mod-info-card h3 { margin: 0 0 var(--space-sm); color: var(--card-heading); font-family: var(--font-serif); font-size: 1.25rem; font-weight: 500; }
.mod-info-card .footer-schedule, .mod-info-card .rich-text, .mod-info-card__list { color: var(--card-text); font-size: 0.9rem; line-height: 1.6; }
.mod-info-card__list div { margin-bottom: var(--space-2xs); }
.mod-info-card a { color: var(--card-link); }

/* ============================ RESPONSYWNOŚĆ ============================ */
/* Siatki pasów (gallery/editorial/news-card) zwijają się teraz według KONTENERA
   (@container przy definicji każdej), nie według szerokości ekranu — dawne
   nadpisania @media dla nich USUNIĘTE, żeby widget w wąskiej kolumnie na
   szerokim monitorze też się zwijał. */
@media (max-width: 62rem) {
  .hero-info__panel { grid-template-columns: 1fr; }
  /* Jedna kolumna = nie ma czego rozdzielać. Kreska zostawała i trzy pionowe
     linie wisiały z lewej strony stosu bloków (06.09.2026, A17). */
  .hero-info__block + .hero-info__block { border-left: 0; }
}
@media (max-width: 62rem) {
  .two-column-zone { grid-template-columns: 1fr; }
  .parish-sidebar { position: static; }
  .parish-footer__main { grid-template-columns: 1fr 1fr !important; }
}

@media (max-width: 52rem) {
  .main-navigation { display: none; }
  /* Przyklejony nagłówek na telefonie: po przewinięciu zwija się do wąskiego
     paska (nazwa + przycisk menu), logo i podtytuł chowamy — pełny nagłówek
     wraca po powrocie na samą górę. */
  .parish-header[data-sticky][data-condensed] .parish-header__inner {
    min-height: 0;
    padding-top: var(--space-sm);
    padding-bottom: var(--space-sm);
  }
  .parish-header[data-sticky][data-condensed] .parish-brand__logo,
  .parish-header[data-sticky][data-condensed] .parish-brand small { display: none; }
  .parish-header[data-sticky][data-condensed] .parish-brand strong {
    font-size: 1rem;
    display: block;
    max-width: 100%;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .mobile-nav-button {
    width: 3rem; height: 3rem;
    display: grid; place-items: center;
    border: 1px solid var(--color-border);
    border-radius: 50%;
    background: #fff;
    color: var(--color-primary);
    cursor: pointer;
  }
  .mobile-nav-button span { display: block; width: 1.15rem; height: 2px; background: currentColor; box-shadow: 0 -6px 0 currentColor, 0 6px 0 currentColor; }
  .mobile-navigation {
    position: absolute;
    z-index: var(--z-rozwijane);
    top: calc(100% - 0.25rem);
    left: var(--space-lg);
    right: var(--space-lg);
    display: grid;
    padding: var(--space-sm) var(--space-lg);
    background: #fff;
    border: 1px solid var(--color-border);
    border-radius: var(--card-radius);
    box-shadow: var(--shadow-card);
  }
  .mobile-navigation a, .mobile-navigation span {
    padding: var(--space-md) 0;
    border-bottom: 1px solid var(--color-border);
    text-decoration: none;
    font-weight: 800;
    font-size: 0.95rem;
  }
  .mobile-navigation a:last-child, .mobile-navigation span:last-child { border-bottom: 0; }
  .mobile-navigation .mobile-navigation__child { padding-left: var(--space-lg); font-weight: 600; font-size: 0.9rem; color: var(--color-text-muted); }

  /* Rail → rozwijany akordeon nad treścią */
  .parish-sidebar { display: block; }
  .sidebar-menu-card { display: none; }
  .parish-sidebar.is-collapsible .sidebar-toggle {
    min-height: 3.4rem;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 var(--space-lg);
    border: 1px solid var(--color-border);
    border-radius: var(--card-radius);
    background: var(--color-surface-muted);
    color: var(--color-primary);
    font-weight: 800;
    cursor: pointer;
  }
  .parish-sidebar.is-open .sidebar-menu-card { display: block; margin-top: var(--space-md); }
}

@media (max-width: 38rem) {
  .parish-header__inner { padding-left: var(--space-md); padding-right: var(--space-md); min-height: 6rem; }
  .parish-brand strong { font-size: 1.05rem; }
  .parish-brand small { font-size: 0.75rem; }
  .mod-body__inner { padding-left: var(--space-md); padding-right: var(--space-md); }
  .parish-footer__main { grid-template-columns: 1fr !important; gap: var(--space-2xl); padding-left: var(--space-md); padding-right: var(--space-md); }
  /* liczbę kafli w rzędzie ustala flex — reguła zbędna */
}

/* ============================ PODSTRONY (widoki modułów) ============== */
/* Nagłówek podstrony (pełnoszerokościowy pas, treść wyrównana do content-max) */
.mod-page-heading {
  padding: clamp(2.5rem, 5vw, 4.5rem) max(var(--space-lg), calc((100vw - var(--tresc-max)) / 2));
  background: var(--color-surface-muted);
  border-top: 1px solid var(--color-border);
  border-bottom: 1px solid var(--color-border);
}
/* KONTENER ZAPYTAŃ NA TREŚCI PASA NAGŁÓWKA (16.09.2026) — warunek tego, żeby
   tytuł i zajawka poniżej liczyły się od SZEROKOŚCI TREŚCI, a nie od okna.
   Bez tej deklaracji miara `cqi` po cichu spada do rozmiaru okna (sprawdzone
   doświadczalnie: wstawione wartości wpadały w sufit `clamp` i nic się nie
   zmieniało), czyli usterka zostaje, a kod wygląda na naprawiony.
   Wewnątrz pasa nie ma żadnej innej reguły liczonej od kontenera — jedyna taka
   w tym arkuszu, `.section-title`, tu nie występuje (komponent wstawia okruszki,
   nadkreślnik, tytuł, zajawkę i slot), więc deklaracja niczego nie przesłania. */
.mod-page-heading__inner { max-width: var(--tresc-max); margin: 0 auto; container-type: inline-size; }
.mod-page-heading h1 {
  max-width: 62rem;
  margin: 0.45rem 0 0.75rem;
  color: var(--color-primary-strong);
  font-family: var(--font-serif);
  /* PISMO OD TREŚCI PASA, NIE OD OKNA (16.09.2026). Pas nagłówka ma stałą
     szerokość treści (992 px), a pismo liczone od okna rosło do 70,4 px —
     dłuższy tytuł wpisu łamał się przez to na dwa wiersze na każdym ekranie
     od 1440 px w górę. Sufit 3,6 rem zamiast 4,4: przy tej szerokości treści
     wyższy i tak był nieosiągalny, a w szerszym układzie przywracałby łamanie. */
  font-size: clamp(2.4rem, 5.6cqi, 3.6rem);
  font-weight: 500;
  line-height: 1;
  letter-spacing: -0.04em;
}
.mod-page-heading__intro { max-width: 42rem; margin: 0; color: var(--color-text-muted); }
.mod-page-heading .section-kicker { margin-bottom: 0; }

.front-breadcrumbs { display: flex; align-items: center; flex-wrap: wrap; gap: 0.4rem; margin-bottom: 1.5rem; color: var(--color-text-muted); font-size: 0.72rem; }
.front-breadcrumbs a { color: var(--color-primary); text-decoration: none; text-underline-offset: 0.2em; }
.front-breadcrumbs a:hover { text-decoration: underline; }
.front-breadcrumbs .sep { opacity: 0.6; }

/* Siatka archiwum (2 kolumny) + bogata karta */
.mod-archive-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.25rem; }
.mod-archive-card { min-width: 0; display: flex; flex-direction: column; overflow: hidden; border: 1px solid var(--color-border); border-radius: var(--card-radius); background: #fff; box-shadow: var(--shadow-card); }
.mod-archive-card__image { position: relative; height: 13rem; display: block; overflow: hidden; background: var(--color-surface-muted); }
.mod-archive-card__image img { width: 100%; height: 100%; display: block; object-fit: cover; transition: transform 280ms ease; }
.mod-archive-card__image:hover img { transform: scale(1.025); }
.mod-archive-card__badge { position: absolute; left: 0.9rem; bottom: 0.9rem; padding: 0.4rem 0.65rem; border-radius: 999px; background: var(--color-primary); color: #fff; font-size: 0.62rem; font-weight: 900; }
.mod-archive-card__copy { display: flex; flex-direction: column; flex: 1; padding: 1.2rem; }
/* Karta bez zdjęcia (15.09.2026): plakietka kategorii w bloku tekstu, nad datą. */
.mod-archive-card__badge--inline { position: static; align-self: flex-start; margin-bottom: 0.55rem; }
.mod-archive-card time { display: flex; align-items: center; gap: 0.4rem; color: var(--color-text-muted); font-size: 0.7rem; font-weight: 700; }
.mod-archive-card :is(h2, h3) { margin: 0.55rem 0; font-size: 1.35rem; line-height: 1.2; }
.mod-archive-card :is(h2, h3) a { color: var(--color-primary-strong); font-family: var(--font-serif); font-size: 1.35rem; font-weight: 500; line-height: 1.2; text-decoration: none; }
.mod-archive-card :is(h2, h3) a:hover { text-decoration: underline; text-underline-offset: 0.2em; }
.mod-archive-card p { margin: 0 0 1rem; color: var(--color-text-muted); font-size: 0.85rem; line-height: 1.55; }
.mod-archive-card .read-more { margin-top: auto; font-size: 0.72rem; font-weight: 900; }

/* Paginacja */
.mod-pagination { display: flex; justify-content: center; flex-wrap: wrap; gap: 0.4rem; margin-top: 2rem; }
.mod-pagination a, .mod-pagination span { min-width: 2.65rem; min-height: 2.65rem; display: grid; place-items: center; padding: 0 0.75rem; border: 1px solid var(--color-border); border-radius: 0.55rem; color: var(--color-primary); font-size: 0.72rem; font-weight: 900; text-decoration: none; }
.mod-pagination .is-active { border-color: var(--color-primary); background: var(--color-primary); color: #fff; }
.mod-pagination .is-disabled { color: #a3a7ae; border-color: var(--color-border); pointer-events: none; }
.mod-pagination .gap { border: 0; }

/* STAN PUSTY — kolory z ZAKRESU SEKCJI, nie z palety na sztywno (07.09.2026).
   Na pasie ciemnym i akcentowym stawiał wcześniej jasne pudełko z przygaszonym
   napisem, bo trzy stałe (`--color-text-muted`, `--color-border`,
   `--color-surface-muted`) opisują wyłącznie pas jasny. Ten sam zestaw zmiennych
   co `.front-empty` w Klasyku. */
.mod-empty {
  padding: var(--space-2xl) var(--space-lg);
  text-align: center;
  /* Napis bierze token KARTY, nie pasa: pudełko stanu pustego ma własne tło
     (`--card-bg-alt`), więc para `--card-muted` / `--card-bg-alt` jest tą,
     która była liczona razem. Z `--section-muted` na pasie akcentowym wychodziło
     4,44:1 w palecie bordowej — poniżej progu. */
  color: var(--card-muted, var(--color-text-muted));
  border: 1px dashed var(--section-border, var(--color-border));
  border-radius: var(--card-radius);
  background: var(--card-bg-alt, var(--color-surface-muted));
}
/* WNĘTRZE STANU PUSTEGO (07.09.2026, A13–A15). Pusty ekran ma powiedzieć, co
   dalej: zdanie główne, pod nim podpowiedź, a na końcu WYJŚCIA. Wyjścia idą
   komponentem akcji w rozmiarze drobnym — to nie jest główna akcja strony,
   tylko sposób wydostania się z zawężenia. Kolory z zakresu sekcji, więc
   pudełko działa też na pasie ciemnym i akcentowym. */
.mod-empty { display: grid; gap: var(--space-sm); justify-items: center; }
.mod-empty__lead { margin: 0; font-size: 1.02rem; color: var(--card-text, var(--color-text)); }
.mod-empty__hint { margin: 0; font-size: 0.9rem; color: var(--card-muted, var(--color-text-muted)); }
.mod-empty__ways { display: flex; flex-wrap: wrap; gap: var(--space-md); justify-content: center; margin-top: var(--space-sm); }

/* Wpis: nagłówek artykułu + proza (wąsy) */
.mod-article { min-width: 0; }
.mod-article__category { display: inline-flex; margin-bottom: 0.75rem; padding: 0.42rem 0.7rem; border-radius: 999px; background: var(--color-primary); color: #fff; font-size: 0.62rem; font-weight: 900; text-transform: uppercase; text-decoration: none; }
.mod-article__meta { display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem; margin-bottom: 0.75rem; }
.mod-article__date { color: var(--color-text-muted); font-size: 0.72rem; font-weight: 700; }
/* Zajawka wpisu stoi W PASIE NAGŁÓWKA (slot komponentu), a nie w treści
   artykułu — jej pole ma stałe 768 px (sufit 48 rem), podczas gdy pismo liczone
   od okna rosło do 24 px. Miara od kontenera trzyma proporcję pola. */
.mod-article__lead { max-width: 48rem; margin: 0 0 1rem; color: var(--color-text-muted); font-family: var(--font-serif); font-size: clamp(1.15rem, 2.1cqi, 1.4rem); line-height: 1.4; }
.mod-article__byline { color: var(--color-text-muted); font-size: 0.8rem; font-weight: 700; margin-bottom: 1rem; }
.mod-article__hero { margin: 0 0 2rem; }
.mod-article__hero img { width: 100%; max-height: 34rem; display: block; object-fit: cover; border-radius: var(--card-radius); }

/* Proza (rich-text) — Georgia serif, wąsy */
.rich-text { color: var(--section-text-prose, #333842); font-family: var(--font-serif); font-size: 1.08rem; line-height: 1.8; }
.rich-text > p:first-child { color: var(--section-heading); font-size: 1.22rem; line-height: 1.65; }
.rich-text p { margin: 0 0 1.1rem; }
.rich-text h2 { margin: 2.25rem 0 0.75rem; color: var(--section-heading); font-size: 1.8rem; font-weight: 500; line-height: 1.2; }
.rich-text h3 { margin: 1.75rem 0 0.6rem; color: var(--section-heading); font-size: 1.4rem; font-weight: 500; }
.rich-text h4 { margin: 1.5rem 0 0.5rem; color: var(--section-heading); font-size: 1.15rem; font-weight: 700; }
.rich-text ul, .rich-text ol { padding-left: 1.4rem; margin: 0 0 1.1rem; }
.rich-text li { margin: 0.35rem 0; }
.rich-text a { color: var(--section-link); text-underline-offset: 0.2em; }
.rich-text img { max-width: 100%; height: auto; border-radius: 0.65rem; }
.rich-text blockquote { clear: both; margin: 2.25rem 0; padding: 1.25rem 1.5rem; border-left: 4px solid var(--section-accent); background: var(--section-accent-soft, var(--color-accent-soft)); color: var(--section-heading); font-size: 1.25rem; line-height: 1.45; }
.rich-text blockquote p { margin: 0; }
.rich-text table { width: 100%; border-collapse: collapse; margin: 1.5rem 0; font-size: 0.95rem; }
.rich-text th, .rich-text td { padding: 0.6rem 0.8rem; border: 1px solid var(--section-border); text-align: left; }
.rich-text figure { margin: 1.5rem 0; }
.rich-text figcaption { margin-top: 0.5rem; color: var(--section-muted); font-size: 0.78rem; font-family: var(--font-ui); }

/* Galeria wpisu (siatka + lightbox) */
.mod-article-gallery { clear: both; margin-top: 2.5rem; padding-top: 1.5rem; border-top: 1px solid var(--color-border); }
.mod-article-gallery h2 { margin: 0 0 1rem; font-family: var(--font-serif); font-size: 1.45rem; font-weight: 500; color: var(--color-primary-strong); }
.mod-article-gallery .photo-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.65rem; }
.mod-article-gallery .photo-grid__btn { padding: 0; border: 0; background: none; cursor: pointer; }
.mod-article-gallery .photo-grid__img { width: 100%; aspect-ratio: 1.4; display: block; object-fit: cover; border-radius: 0.55rem; }

/* Karuzela galerii wpisu (nad treścią) */
.post-carousel { position: relative; margin-bottom: 2rem; }
.post-carousel__viewport { overflow: hidden; border-radius: var(--card-radius); }
.post-carousel__track { display: flex; transition: transform 400ms ease; }
.post-carousel__slide { min-width: 100%; margin: 0; }
.post-carousel__img { width: 100%; max-height: 34rem; display: block; object-fit: cover; }
.post-carousel__caption { padding: 0.6rem var(--space-md); color: var(--color-text-muted); font-size: 0.78rem; }
.post-carousel__dots { margin-top: var(--space-md); }

/* Lightbox */
.lightbox { position: fixed; inset: 0; z-index: var(--z-zdjecie); display: flex; align-items: center; justify-content: center; padding: var(--space-xl); background: rgba(8, 14, 26, 0.92); }
.lightbox__img { max-width: 92vw; max-height: 86vh; object-fit: contain; }
.lightbox__close { position: absolute; top: var(--space-lg); right: var(--space-lg); width: 3rem; height: 3rem; border: 0; border-radius: 50%; background: rgba(255,255,255,0.14); color: #fff; font-size: 1.6rem; cursor: pointer; }
.lightbox__nav { position: absolute; top: 50%; transform: translateY(-50%); width: 3.25rem; height: 3.25rem; border: 0; border-radius: 50%; background: rgba(255,255,255,0.14); color: #fff; font-size: 1.8rem; cursor: pointer; }
.lightbox__nav--prev { left: var(--space-lg); }
.lightbox__nav--next { right: var(--space-lg); }
/* Licznik „N z M" i obrys fokusu w nakładce (29.07.2026) — nakładka stoi poza
   zakresem sekcji, więc bierze własne, zawsze jasne kolory na swoim ciemnym tle. */
.lightbox__counter { position: absolute; bottom: var(--space-lg); left: 50%; transform: translateX(-50%); margin: 0; padding: 0.3rem 0.75rem; border-radius: 0.4rem; background: rgba(255,255,255,0.14); color: #fff; font-size: 0.85rem; }
.lightbox button:focus-visible { outline: 3px solid #fff; outline-offset: 3px; }

/* Wiersz powrotu — wyrównany do LEWEJ, patrz komentarz w Klasyku. */
.mod-back-foot { display: flex; justify-content: flex-start; margin-top: 2rem; }
.mod-back-link { display: inline-flex; align-items: center; gap: 0.45rem; margin-top: 2rem; color: var(--color-primary); font-size: 0.82rem; font-weight: 900; text-decoration: none; }
.mod-back-link:hover { text-decoration: underline; text-underline-offset: 0.2em; }

/* ---- Powiązanie wpis ↔ galeria (29.07.2026) ----
   MARKUP jest wspólny z Klasykiem (front.partials.post-gallery-link,
   gallery-used-in) — tutaj żyje wyłącznie wygląd, zgodnie z zasadą „szablon to
   warstwa prezentacji". Klasy `.post-gallery-link__*` powtarzają się celowo:
   front.css NIE ładuje się na stronach Nowoczesnego, więc nie ma kolizji. */
/* Kafle galerii z kategorii pod treścią podstrony — patrz front.css. */
.mod-static .mod-tiles-grid { margin: 2rem 0; }

.post-gallery-link { margin: 2rem 0 0; }
.post-gallery-link__anchor {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  padding: 1rem 1.1rem;
  background: var(--color-surface-muted);
  border: 1px solid var(--color-border);
  border-radius: var(--card-radius);
  color: inherit;
  text-decoration: none;
  transition: border-color var(--motion-state) var(--motion-ease-state), background-color var(--motion-state) var(--motion-ease-state);
}
.post-gallery-link__anchor:hover { border-color: var(--color-accent-strong, var(--color-accent)); background: var(--color-surface); }
.post-gallery-link__anchor:active { background: var(--color-surface-muted); }
.post-gallery-link__icon { flex: 0 0 auto; display: inline-flex; color: var(--color-accent-strong, var(--color-accent)); }
.post-gallery-link__icon svg { width: 1.6rem; height: 1.6rem; }
.post-gallery-link__text { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; }
.post-gallery-link__label { font-size: 0.72rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-text-muted); font-weight: 700; }
.post-gallery-link__title { font-family: Georgia, 'Times New Roman', serif; font-size: 1.05rem; color: var(--color-primary); overflow-wrap: anywhere; }
.post-gallery-link__count { margin-left: auto; flex: 0 0 auto; font-size: 0.8rem; color: var(--color-text-muted); }
@media (max-width: 32rem) {
  .post-gallery-link__anchor { flex-wrap: wrap; }
  .post-gallery-link__count { margin-left: 0; width: 100%; }
}

.gallery-used-in { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.5rem; margin-top: 0.6rem; font-size: 0.88rem; }
.gallery-used-in__label { color: var(--color-text-muted); }
.gallery-used-in__link { color: var(--color-accent-strong, var(--color-accent)); font-weight: 800; text-decoration: none; }
.gallery-used-in__link:hover { text-decoration: underline; text-underline-offset: 0.2em; }
.gallery-used-in__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.25rem; }

/* Nagłówek kategorii (obraz + opis) */
.mod-cat-head { display: flex; gap: var(--space-lg); align-items: center; }
.mod-cat-head__img { width: 6rem; height: 6rem; object-fit: cover; border-radius: var(--card-radius); flex: 0 0 auto; }

/* ============================ MODUŁY — wspólne elementy ============== */
/* Przyciski */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 0.4rem; min-height: 2.9rem; padding: 0 var(--space-lg); border-radius: 999px; font-weight: 800; text-decoration: none; cursor: pointer; border: 1px solid transparent; font-size: 0.85rem; }
/* ROZMIAR DROBNY — ten sam komponent, mniejszy. `.btn--action-sm` wystawia
   komponent akcji (`<x-front.action size="small">`) i do 07.09.2026 nie miał tu
   ŻADNEJ reguły: gęste wiersze (nawigacja pod wpisem, wyjścia z archiwów,
   stopka) dostawały przyciski w pełnym rozmiarze — zmierzone 46–48 px wysokości
   przy 13,6 px pisma. Zmienia się WYŁĄCZNIE stopień pisma i wcięcia, reszta
   wspólna z `.btn`. (Do 11.09.2026 selektor dzielił z `.btn--sm`, którego
   żaden widok nie używał — zdjęty razem z martwymi klasami.) */
.btn--action-sm { min-height: 2.5rem; padding: 0 var(--space-md); font-size: 0.78rem; }

/* ============================ AKCJE — DWA WARIANTY ====================
   Ten sam system co w Klasyku (UI-STYLE.md → „Akcje na froncie"), w języku
   Nowoczesnego: pigułka (`border-radius: 999px` z `.btn`), grubszy krój,
   mniejszy stopień pisma. Tokeny zakresu pasa są WSPÓLNE (--section-action-*,
   App\Support\Front\SectionBackgrounds), więc odwracanie wariantów na pasie
   ciemnym i akcentowym działa tu identycznie — bez powielania logiki.
   Zapasy w var() to wartości dla pasa jasnego. */
.btn--action, .btn--action-quiet {
  transition: background-color var(--motion-state) var(--motion-ease-state),
              border-color var(--motion-state) var(--motion-ease-state),
              color var(--motion-state) var(--motion-ease-state);
}
.btn--action {
  background: var(--section-action-bg, var(--color-primary));
  color: var(--section-action-ink, #fff);
  border-color: transparent;
}
.btn--action:hover {
  background: var(--section-action-bg-hover, var(--color-primary-strong));
  color: var(--section-action-ink-hover, #fff);
}
.btn--action-quiet {
  background: transparent;
  color: var(--section-action-quiet-ink, var(--color-primary));
  border-color: var(--section-action-quiet-border, var(--color-primary));
}
.btn--action-quiet:hover {
  background: var(--section-action-quiet-bg-hover, var(--color-surface-muted));
  color: var(--section-action-quiet-ink-hover, var(--color-primary));
}
/* Strzałka rysowana przez komponent — odsuwa się marginesem, nie `transform`,
   żeby przycisk nie zmieniał wymiarów. */
.btn__arrow { flex: 0 0 auto; transition: margin-left var(--motion-state) var(--motion-ease-state); }
.btn--action:hover .btn__arrow,
.btn--action-quiet:hover .btn__arrow { margin-left: 0.25rem; }
/* WARIANT WSTECZ: strzałka stoi PRZED napisem i wskazuje w lewo, więc przy
   najechaniu odsuwa się w LEWO, nie w prawo — ruch ma iść za kierunkiem, w
   którym przycisk prowadzi. */
.btn--action-back:hover .btn__arrow { margin-left: 0; margin-right: 0.25rem; }
.link-more { color: var(--color-primary); font-weight: 800; text-decoration: none; }
.link-more:hover { text-decoration: underline; text-underline-offset: 0.2em; }
.front-post__foot { margin-top: 2rem; }

/* Nagłówek szczegółu (gallery/video/doc show) — w page-heading */
.mod-detail-meta { display: flex; flex-wrap: wrap; gap: var(--space-md); margin-top: 0.5rem; color: var(--color-text-muted); font-size: 0.8rem; }
.mod-detail-meta .author { font-style: italic; }
.mod-detail-desc { max-width: 48rem; margin: 0.75rem 0 0; color: var(--color-text-muted); }

/* Filtr kategorii (chipy) — Multimedia */
.mm-filter { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-bottom: 1.75rem; }
.mm-chip { min-height: 2.7rem; display: inline-flex; align-items: center; padding: 0 1rem; border: 1px solid var(--color-border); border-radius: 999px; background: #fff; color: var(--color-text); font-size: 0.72rem; font-weight: 800; text-decoration: none; }
.mm-chip:hover { border-color: var(--color-primary); }
.mm-chip.is-active { border-color: var(--color-primary); background: var(--color-primary); color: #fff; }

/* Zakładki (strona statyczna, archiwum ogłoszeń) */
.front-tabs__bar { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-bottom: var(--space-lg); border-bottom: 1px solid var(--color-border); }
.front-tabs__tab { min-height: 2.9rem; padding: 0 var(--space-lg); border: 0; border-bottom: 3px solid transparent; background: none; color: var(--color-text-muted); font: inherit; font-size: 0.85rem; font-weight: 800; cursor: pointer; margin-bottom: -1px; }
.front-tabs__tab:hover { color: var(--color-primary); }
/* WCIŚNIĘCIE (07.09.2026, A21) — jedyny stan działający na dotyku, więc
   zakładka bez niego nie potwierdza dotknięcia niczym. Klasyk ma to od dawna. */
.front-tabs__tab:active { color: var(--color-primary-strong); background: var(--color-surface-muted); }
.front-tabs__tab.is-active { color: var(--color-primary-strong); border-color: var(--section-accent-ink, var(--color-accent-strong)); }
.front-tabs__panel { padding-top: var(--space-lg); }
.front-tabs__announcements { margin-top: var(--space-md); }

/* Osadzenie wideo (fasada) — wspólne (content-video-embed, gallery-videos, videos/show) */
.video-embed { position: relative; aspect-ratio: 16 / 9; overflow: hidden; border-radius: var(--card-radius); background: var(--color-primary-strong); }
.video-embed iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.video-embed__facade { position: absolute; inset: 0; width: 100%; height: 100%; padding: 0; border: 0; background: none; cursor: pointer; }
.video-embed__thumb { width: 100%; height: 100%; object-fit: cover; display: block; }
.video-embed__thumb--placeholder { background: linear-gradient(135deg, var(--color-primary), var(--color-primary-strong)); }
.video-embed__play { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 4.2rem; height: 4.2rem; display: grid; place-items: center; border-radius: 50%; background: rgba(15,25,46,0.78); color: #fff; }
.video-embed__play--sm { width: 3.2rem; height: 3.2rem; }
.content-video { margin: 1.75rem 0; }
.video-list { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-lg); }
.video-item { margin: 0; }
.video-item__frame { position: relative; }
.video-item__duration { position: absolute; right: 0.6rem; bottom: 0.6rem; padding: 0.15rem 0.45rem; border-radius: 0.4rem; background: rgba(0,0,0,0.72); color: #fff; font-size: 0.72rem; font-weight: 700; }
.video-item__caption { padding: 0.75rem 0.25rem 0; }
.video-item__title { color: var(--color-primary-strong); font-family: var(--font-serif); font-size: 1.05rem; font-weight: 500; }
.video-item__desc { color: var(--color-text-muted); font-size: 0.85rem; line-height: 1.5; margin-top: 0.25rem; }
.video-item__error { display: grid; place-items: center; aspect-ratio: 16/9; border-radius: var(--card-radius); background: var(--color-surface-muted); color: var(--color-text-muted); font-size: 0.85rem; }

/* Odtwarzacz audio */
.video-audio-player { display: flex; flex-direction: column; gap: var(--space-md); padding: var(--space-lg); border: 1px solid var(--color-border); border-radius: var(--card-radius); background: var(--color-surface-muted); }
.video-audio-player__cover { width: 100%; max-height: 22rem; object-fit: cover; border-radius: var(--card-radius); }
.video-audio-player__el, .audio-item__player { width: 100%; }
.audio-list { display: grid; gap: var(--space-md); }
.audio-item { padding: var(--space-md) var(--space-lg); border: 1px solid var(--color-border); border-radius: var(--card-radius); background: #fff; }
.audio-item__title { color: var(--color-primary-strong); font-family: var(--font-serif); font-size: 1.05rem; margin-bottom: 0.5rem; }

/* Plik w treści (wąs) */
.content-file { margin: 1.5rem 0; }
.content-file__link { display: inline-flex; align-items: center; gap: 0.5rem; color: var(--color-primary); font-weight: 700; text-decoration: none; }
.content-file__card { display: flex; align-items: center; gap: var(--space-md); padding: var(--space-md) var(--space-lg); border: 1px solid var(--color-border); border-radius: var(--card-radius); background: #fff; text-decoration: none; box-shadow: var(--shadow-card); max-width: 26rem; }
.content-file__card-thumb { width: 3rem; height: 3rem; display: grid; place-items: center; border-radius: 0.5rem; background: var(--color-accent-soft); color: var(--color-primary); flex: 0 0 auto; }
.content-file__card-thumb img { width: 100%; height: 100%; object-fit: cover; border-radius: 0.5rem; }
.content-file__card-title { display: block; color: var(--color-primary-strong); font-weight: 700; font-family: var(--font-ui); }
.content-file__card-sub { display: flex; align-items: center; gap: 0.5rem; margin-top: 0.2rem; }
.content-file__badge { padding: 0.1rem 0.4rem; border-radius: 0.3rem; background: var(--color-primary); color: #fff; font-size: 0.6rem; font-weight: 900; }
.content-file__badge--pdf { background: #a3352b; }
.content-file__badge--word { background: #2b579a; }
.content-file__badge--excel { background: #217346; }
.content-file__size { color: var(--color-text-muted); font-size: 0.72rem; }

/* Obraz oblany w treści (wąs, side=left/right) */
.content-image { margin: 1.5rem 0; }
.content-image--left { float: left; width: 44%; margin: 0.4rem 1.5rem 1.25rem 0; }
.content-image--right { float: right; width: 44%; margin: 0.4rem 0 1.25rem 1.5rem; }
.content-image img { width: 100%; display: block; border-radius: 0.65rem; }
.content-image figcaption { margin-top: 0.5rem; color: var(--color-text-muted); font-size: 0.78rem; font-family: var(--font-ui); }

/* Biblioteka dokumentów (PDF) */
.doc-list { display: grid; gap: var(--space-md); }
.doc-item { display: grid; grid-template-columns: 6.5rem 1fr; gap: var(--space-lg); padding: var(--space-lg); border: 1px solid var(--color-border); border-radius: var(--card-radius); background: #fff; box-shadow: var(--shadow-card); }
.doc-item__thumb { display: grid; place-items: center; aspect-ratio: 3/4; overflow: hidden; border-radius: 0.5rem; background: var(--color-surface-muted); color: var(--color-primary); text-decoration: none; }
.doc-item__thumb img { width: 100%; height: 100%; object-fit: cover; }
.doc-item__title { color: var(--color-primary-strong); font-family: var(--font-serif); font-size: 1.2rem; }
.doc-item__meta { display: flex; flex-wrap: wrap; gap: var(--space-md); margin: 0.4rem 0; color: var(--color-text-muted); font-size: 0.75rem; }
.doc-item__desc { color: var(--color-text-muted); font-size: 0.88rem; margin: 0.25rem 0 0.75rem; }
.doc-item__actions { display: flex; flex-wrap: wrap; gap: var(--space-sm); }
.doc-item__missing { color: var(--color-error, #a33a45); font-size: 0.8rem; }
.doc-viewer { aspect-ratio: 3/4; max-height: 80vh; border: 1px solid var(--color-border); border-radius: var(--card-radius); overflow: hidden; }
.doc-viewer iframe { width: 100%; height: 100%; border: 0; }
.doc-viewer__fallback { margin-top: 0.75rem; color: var(--color-text-muted); font-size: 0.8rem; }

/* Galerie w treści („wąsy") renderowane klasycznymi partialami — spójny wygląd
   na Nowoczesnym (klasy współdzielone: photo-grid/collage/masonry/strip). */
.front-empty { padding: var(--space-2xl) var(--space-lg); text-align: center; color: var(--color-text-muted); border: 1px dashed var(--color-border); border-radius: var(--card-radius); background: var(--color-surface-muted); }
.photo-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.65rem; }
.photo-grid__btn, .photo-collage__btn, .photo-masonry__btn, .photo-strip__btn { padding: 0; border: 0; background: none; cursor: pointer; }
/* Autor pojedynczego zdjęcia — pokazywany tylko wtedy, gdy różni się od autora
   całej galerii (ten stoi w nagłówku). Brak autora nie zostawia pustego miejsca,
   bo element w ogóle się nie renderuje. */
.photo-grid__author { display: block; margin-top: 4px; font-size: .78rem; color: var(--color-text-muted, #6b6b6b); text-align: left; }
.photo-grid__img, .photo-collage__img, .photo-masonry__img, .photo-strip__img { width: 100%; display: block; object-fit: cover; border-radius: 0.55rem; }
.photo-grid__img { aspect-ratio: 1.4; }
.photo-collage { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0.65rem; }
.photo-collage__item:first-child { grid-column: span 2; grid-row: span 2; }
.photo-masonry { columns: 3; column-gap: 0.65rem; }
.photo-masonry__btn { display: block; margin-bottom: 0.65rem; break-inside: avoid; width: 100%; }
.photo-strip-wrap { position: relative; }
.photo-strip { display: flex; gap: 0.65rem; overflow-x: auto; scroll-snap-type: x mandatory; }
.photo-strip__btn { flex: 0 0 auto; width: 18rem; scroll-snap-align: start; }
.photo-strip__img { height: 12rem; }
.photo-strip__arrow { position: absolute; top: 50%; transform: translateY(-50%); width: 2.5rem; height: 2.5rem; border: 0; border-radius: 50%; background: rgba(15,25,46,0.72); color: #fff; cursor: pointer; }
.photo-strip__arrow--prev { left: 0.4rem; }
.photo-strip__arrow--next { right: 0.4rem; }
@media (max-width: 40rem) { .photo-grid, .photo-collage { grid-template-columns: 1fr 1fr; } .photo-masonry { columns: 2; } }

/* Katalog kafli (galerie, multimedia) — jednolita siatka */
.mod-tiles-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); gap: var(--gallery-gap, 1rem); }
.mod-tiles-grid .gallery-tile { height: 16rem; }
.mod-tiles-kicker { margin: 1.75rem 0 0.75rem; color: var(--section-accent-ink, var(--color-accent-strong)); font-size: 0.72rem; font-weight: 900; letter-spacing: 0.14em; text-transform: uppercase; }

/* Duszpasterze (widok modułu) */
.mod-pastors-group { margin-bottom: var(--space-2xl); }
.mod-pastors-group__heading { margin: 0 0 var(--space-lg); color: var(--color-primary-strong); font-family: var(--font-serif); font-size: 1.7rem; font-weight: 500; }
.mod-pastors-grid { display: grid; gap: var(--space-lg); }
.mod-pastor { display: grid; grid-template-columns: 9rem 1fr; gap: var(--space-lg); padding: var(--space-lg); border: 1px solid var(--color-border); border-radius: var(--card-radius); background: #fff; box-shadow: var(--shadow-card); }
/* Obwódka portretu ze zmiennej powierzchni karty (była wpisana na stałe biel —
   na pasie ciemnym robiła jasny pierścień). Sylwetka zastępcza wyciszona
   i wpisana w koło z zapasem. */
.mod-pastor__photo { width: 9rem; height: 9rem; display: grid; place-items: center; overflow: hidden; border-radius: 50%; background: var(--card-bg-alt); color: color-mix(in srgb, var(--card-muted) 45%, transparent); border: 4px solid var(--card-bg); box-shadow: 0 0.5rem 1.5rem rgba(31,35,43,0.1); }
.mod-pastor__photo img { width: 100%; height: 100%; object-fit: cover; }
.mod-pastor__photo svg { width: 47%; height: 47%; }
.mod-pastor__name { margin: 0; color: var(--color-primary-strong); font-family: var(--font-serif); font-size: 1.4rem; font-weight: 500; line-height: 1.2; }
.mod-pastor__status { margin: 0.25rem 0 0.75rem; color: var(--color-text-muted); font-size: 0.85rem; }
.mod-pastor__role { color: var(--section-accent-ink, var(--color-accent-strong)); font-weight: 900; text-transform: uppercase; font-size: 0.72rem; }
.mod-pastor__sep { margin: 0 0.4rem; }
.mod-pastor__about, .mod-pastor__duties { color: var(--color-text); font-size: 0.92rem; line-height: 1.6; margin-bottom: 0.6rem; }
.mod-pastor__duties-label { color: var(--color-primary-strong); font-weight: 700; }
.mod-pastor__facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); gap: 0.5rem 1.25rem; margin: 0.75rem 0; }
.mod-pastor__facts .fact { display: flex; flex-direction: column; }
.mod-pastor__facts dt { color: var(--color-text-muted); font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.06em; font-weight: 800; }
.mod-pastor__facts dd { margin: 0; color: var(--color-text); font-size: 0.85rem; }
/* „Inne funkcje" i „Poprzednie parafie" (07.09.2026, A12) — dane, których ten
   widok wcześniej nie renderował wcale. Podtytuł drobny jak etykieta faktu,
   pod nim lista: nazwa i, gdy jest, okres przy prawej krawędzi. */
.mod-pastor__table { margin: 0.75rem 0 0; }
.mod-pastor__table-title {
  margin: 0 0 0.35rem;
  color: var(--color-text-muted);
  font-family: var(--font-ui);
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.mod-pastor__rows { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.2rem; }
.mod-pastor__rows li {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.2rem 0.75rem;
  padding-bottom: 0.2rem;
  border-bottom: 1px solid var(--color-border);
  font-size: 0.85rem;
}
.mod-pastor__rows li:last-child { border-bottom: 0; }
.mod-pastor__rows-name { color: var(--color-text); }
.mod-pastor__rows-meta { color: var(--color-text-muted); font-size: 0.78rem; font-variant-numeric: tabular-nums; white-space: nowrap; }
.mod-pastor__contact { display: flex; flex-wrap: wrap; gap: var(--space-md); margin: 0.75rem 0 0; }
.mod-pastor__contact a { color: var(--color-primary); font-weight: 700; font-size: 0.85rem; }

/* Intencje (widok tygodnia) */
.mod-intentions-nav { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-md); margin-bottom: var(--space-xl); }
.mod-intentions-nav a { min-height: 2.75rem; display: inline-flex; align-items: center; padding: 0 var(--space-lg); border: 1px solid var(--color-border); border-radius: 999px; color: var(--color-primary); font-weight: 800; font-size: 0.8rem; text-decoration: none; }
.mod-intentions-nav a:hover { border-color: var(--color-primary); }
.mod-intentions-nav__range { margin-left: auto; color: var(--color-text-muted); font-size: 0.82rem; font-weight: 700; }
.mod-intentions-day { margin-bottom: var(--space-lg); border: 1px solid var(--color-border); border-radius: var(--card-radius); overflow: hidden; background: #fff; box-shadow: var(--shadow-card); }
.mod-intentions-day__head { padding: var(--space-lg); background: var(--color-primary); color: #fff; }
.mod-intentions-day__date { margin: 0; font-family: var(--font-serif); font-size: 1.35rem; font-weight: 500; }
.mod-intentions-day__feast { display: flex; align-items: center; gap: 0.5rem; margin-top: 0.35rem; color: #d7deec; font-size: 0.8rem; }
/* PLAKIETKA KOLORU SZAT — do 07.09.2026 arkusz Nowoczesnego nie miał reguły
   BAZOWEJ (jedyne wystąpienie to obwódka w pasku dnia intencji niżej), więc
   `<span>` z samym `background` renderował się jako 0 × 0 px: czytnik ekranu
   dostawał `aria-label`, a widzący nie dostawał NIC. Zachowanie jak w Klasyku. */
.liturgical-dot {
  display: inline-block;
  width: 0.7rem;
  height: 0.7rem;
  flex: 0 0 auto;
  border-radius: 50%;
  /* KOLOR WYPEŁNIENIA TO KOLOR SZAT — nigdy nie barwimy go paletą. Na mocnych
     tłach dokładamy pierścień w kolorze tekstu pasa, żeby ciemna kropka nie
     zginęła; na jasnych pierścień ma zerową grubość. */
  box-shadow: 0 0 0 var(--section-dot-ring-width, 0) var(--section-dot-ring, transparent);
  border: 1px solid rgba(0, 0, 0, 0.18);
  vertical-align: middle;
  margin-right: 0.4rem;
}
/* Widoczny opis szat przy kropce („szaty zielone") — kolor nie może być jedynym
   nośnikiem informacji. */
.liturgical-dot__text {
  font-size: 0.8rem;
  letter-spacing: 0.04em;
  color: var(--section-muted, var(--color-text-muted));
  font-style: italic;
  white-space: nowrap;
}
.mod-intentions-day__feast .liturgical-dot { border: 1px solid rgba(255,255,255,0.5); }
.mod-intentions-day__desc { margin-top: 0.35rem; color: #d7deec; font-size: 0.82rem; }
.mod-intentions-masses { margin: 0; }
.mod-intentions-mass { display: grid; grid-template-columns: 7rem 1fr; gap: var(--space-md); padding: var(--space-md) var(--space-lg); border-top: 1px solid var(--color-border); }
.mod-intentions-mass:first-child { border-top: 0; }
.mod-intentions-mass__time { color: var(--color-primary); font-family: var(--font-serif); font-size: 1.25rem; font-weight: 500; }
.mod-intentions-mass__type { display: block; margin-top: 0.2rem; padding: 0.15rem 0.4rem; border-radius: 999px; background: var(--color-accent-soft); color: var(--color-primary); font-size: 0.58rem; font-weight: 900; text-transform: uppercase; width: fit-content; }
.mod-intentions-mass__list { margin: 0; padding: 0; list-style: none; color: var(--color-text); font-size: 0.92rem; line-height: 1.55; }
.mod-intentions-mass__list li { margin-bottom: 0.3rem; }
.mod-intentions-mass__desc { color: var(--color-text-muted); font-size: 0.85rem; margin-bottom: 0.35rem; }
.mod-intentions-free { color: var(--color-text-muted); font-style: italic; font-size: 0.88rem; }

/* Strona statyczna */
.mod-static { min-width: 0; }
.mod-static__subtitle { max-width: 48rem; color: var(--color-text-muted); font-family: var(--font-serif); font-size: clamp(1.15rem, 2vw, 1.4rem); margin: 0 0 1.5rem; }

/* Archiwum ogłoszeń */
.mod-ann-current { margin-bottom: var(--space-2xl); padding-bottom: var(--space-xl); border-bottom: 1px solid var(--color-border); }
.mod-ann-current__head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--space-md); margin-bottom: var(--space-md); }
.mod-ann-current__date { display: inline-flex; align-items: center; gap: 0.5rem; color: var(--color-text-muted); font-size: 0.85rem; font-weight: 700; }
/* OSTATNIE AKTUALNOŚCI pod wpisem (02.08.2026) — odpowiednik „Poprzednich
   ogłoszeń"; w środku zwykła siatka kart archiwum tego szablonu. */
.mod-news-recent { margin-top: var(--space-2xl); padding-top: var(--space-xl); border-top: 1px solid var(--color-border); }

/* Kategoria w wierszu meta bywa ODNOŚNIKIEM (nagłówek strony wpisu) — musi
   wyglądać dokładnie tak jak napis na kaflu, bez podkreślenia. */
.news-meta__category { color: var(--card-link); font-weight: 800; text-transform: uppercase; letter-spacing: 0.06em; text-decoration: none; }
.news-meta__category:hover { text-decoration: underline; }

.mod-ann-archive__list { list-style: none; margin: 0; padding: 0; }
.mod-ann-archive__row { border-top: 1px solid var(--color-border); }
.mod-ann-archive__link { display: flex; align-items: center; gap: 0.6rem; padding: 0.7rem 0; color: var(--color-text); text-decoration: none; }
.mod-ann-archive__link:hover { color: var(--color-primary); }
.mod-ann-archive__date { color: var(--color-text-muted); font-size: 0.78rem; font-variant-numeric: tabular-nums; }
.mod-ann-archive__name { font-weight: 600; }

/* Pasy strony głównej — tablet i telefon.
   Siatki WIDGETÓW (editorial-links-grid, news-card-grid, gallery-grid, pastor-row,
   mass-row) zwijają się według KONTENERA (@container przy definicjach), więc ich
   dawne nadpisania @media stąd USUNIĘTE — zostają tylko elementy spoza widgetów
   (kompozycje wewnętrzne, podstrony, hero). */
@media (max-width: 52rem) {
  .daily-thought-inner { grid-template-columns: 10rem minmax(0, 1fr); }
  .home-module__heading { align-items: flex-start; flex-direction: column; }
  .mod-info-strip { grid-template-columns: 1fr; }
}
@media (max-width: 40rem) {
  .parish-hero { height: 30rem; }
  /* Tryb „Informacje podstawowe" musi ZOSTAĆ przy wysokości automatycznej także
     tutaj (06.09.2026, A4). Reguła wyżej stoi w pliku PÓŹNIEJ niż
     `.parish-hero--info` i ma tę samą specyficzność, więc po cichu przywracała
     stałą wysokość — i rozwinięty panel znów był przycinany, akurat na telefonie,
     gdzie ma jedną kolumnę i jest najwyższy. Zwinięty pas zostaje niski dzięki
     `min-height`, otwarty rośnie do treści. */
  .parish-hero--info { height: auto; min-height: 30rem; }
  .compact-list { grid-template-columns: 1fr; }
  .daily-thought-inner { grid-template-columns: 1fr; gap: var(--space-lg); }
  .daily-thought-label { flex-direction: row; align-items: center; padding: 0 0 var(--space-md); border-right: 0; border-bottom: 1px solid var(--section-rule, rgba(var(--color-accent-rgb), 0.45)); }
  .daily-thought-label__mark { font-size: 1.5rem; }
  .mod-promoted-bar, .mod-info-strip { padding-left: var(--space-md); padding-right: var(--space-md); }
  .mod-archive-grid { grid-template-columns: 1fr; }
  .mod-article-gallery .photo-grid { grid-template-columns: 1fr; }
  .rich-text { font-size: 1rem; }
  .video-list { grid-template-columns: 1fr; }
  .doc-item { grid-template-columns: 1fr; }
  .doc-item__thumb { max-width: 8rem; }
  .mod-pastor { grid-template-columns: 1fr; text-align: center; }
  .mod-pastor__photo { margin: 0 auto; }
  .mod-pastor__facts, .mod-pastor__contact { justify-content: center; }
  .mod-intentions-mass { grid-template-columns: 1fr; gap: 0.5rem; }
  .content-image--left, .content-image--right { float: none; width: 100%; margin: 1.25rem 0; }
  .mod-intentions-nav__range { margin-left: 0; width: 100%; }
}

/* Ograniczenie ruchu (prefers-reduced-motion) obsługuje JEDEN zapis dla obu
   szablonów — public/css/motion.css. Nie dopisywać tu drugiego: różniły się
   i jeden z nich wyłączał przejścia zamiast skracać ich czas. */

/* ============================================================
   E2 Etap 3 — nakładka „wzór" (łuki/arkady)
   Kafel jest INLINE w Blade (front/partials/section-pattern.blade.php), bo
   zewnętrzny SVG nie dziedziczy currentColor i nie dałoby się go zabarwić
   paletą. Tu tylko pozycjonowanie i kolor.
   ============================================================ */
.front-pattern {
  position: absolute;
  inset: 0;
  z-index: 0;              /* POD treścią sekcji */
  color: var(--pattern-ink);
  pointer-events: none;    /* wzór nie łapie zdarzeń myszy */
  overflow: hidden;
}
.front-pattern__svg { width: 100%; height: 100%; display: block; }
/* Treść pasa musi lec NAD wzorem/zdjęciem (oba są pierwszym dzieckiem sekcji). */
/* Także `.front-section` (pas z widoku dziedziczonego po Klasyku) — bez tego
   przy tle „wzór" nakładka SVG, choć ma `z-index: 0`, malowałaby się NAD
   nieposycjonowaną treścią sekcji. */
:is(.mod-section, .front-section) > *:not(.front-pattern):not(.front-section-photo) { position: relative; z-index: 1; }
.front-pattern__rect { fill: var(--wzor-desktop); }
/* Węższe ekrany — mniejszy kafel (600 → 360). Przełączamy WŁAŚCIWOŚCIĄ CSS
   (fill), nie atrybutem SVG, więc media query działa pewnie. */
@media (max-width: 900px) {
  .front-pattern__rect { fill: var(--wzor-mobile); }
}

/* Zdjęcie w tle sekcji (wariant „Zdjęcie", zmiana decyzji 19.07.2026) — ten sam
   mechanizm co Klasyk (public/css/front.css), tylko podpięty pod .mod-section. */
.front-section-photo {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}
.front-section-photo__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.front-section-photo__mask {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, var(--section-photo-mask, 0.65));
}

/* ============================================================
   ZAKRES ZMIENNYCH STOPKI (07.09.2026, A3)

   Stopka jest zawsze CIEMNA i stoi POZA zakresem sekcji, a składają ją WSPÓLNE
   partiale (mass-schedule, office-details, contact-details) — te same, które
   stoją na jasnym pasie. Bez własnego zakresu brały kolory z `:root`, czyli
   warianty dla JASNEGO tła, i lądowały na `#202329`: godzina Mszy miała
   **1,06:1** (kolor tekstu strony na prawie czarnym), etykiety grup 2,67:1.
   Ten sam defekt i ta sama naprawa co w panelu „Informacje podstawowe" na hero
   (A2, partia 1) — wariant ustawiamy RAZ, DLA CAŁEGO OBSZARU, nie przy
   pojedynczych selektorach.

   Podetykiety (nazwy grup godzin, „Numer konta", „BLIK") idą najjaśniejszym
   wariantem akcentu — zgodnie z regułą „ZŁOTO to ikona i podetykieta, BIEL to
   napis". Kontrast na `#202329` liczony we wszystkich czterech paletach,
   pilnuje FooterScopeContrastTest.
   ============================================================ */
.parish-footer {
  --section-text: #FFFFFF;
  --section-heading: #FFFFFF;
  --section-muted: rgba(255, 255, 255, 0.75);
  --section-text-soft: var(--color-accent-soft);
  --section-border: rgba(255, 255, 255, 0.16);
  /* Obrys fokusu na prawie czarnym: ciemny akcent z `:root` miałby tu 2,87:1. */
  --section-focus: #FFFFFF;
  /* Te dwa ZOSTAJĄ z poprzedniej decyzji i nie są przeoczeniem: `--card-bg-alt`
     i `--card-muted` malują wyłącznie ZASTĘPNIK miniatury, który na ciemnym tle
     ma być ledwie widoczny, a nie świecić. Tekstu nie niosą. */
  --card-bg-alt: rgba(255, 255, 255, 0.06);
  --card-muted: rgba(255, 255, 255, 0.45);
  --section-accent: rgba(255, 255, 255, 0.10);
}

/* HERO BEZ GRAFIKI (18.07.2026) — ta sama decyzja co w Klasyku: pas zostaje
   (niesie tożsamość i przycisk „Informacje podstawowe”), ale jest ZWARTY.
   Wysokość 34rem / 40rem jest przewidziana pod zdjęcie i rozwinięty panel;
   bez zdjęcia zostawiała pustą przestrzeń między napisem a przyciskiem.
   Dwie klasy = wyższa specyficzność niż `.parish-hero--info`. */
.parish-hero--placeholder { height: auto; min-height: 0; padding: clamp(2.5rem, 5vh, 4rem) var(--space-lg); }
.parish-hero--placeholder.parish-hero--info { min-height: 0; }
/* Bez zdjęcia treść hero idzie NORMALNYM PRZEPŁYWEM (kolumna: nazwa, potem
   panel „Informacje podstawowe”). Domyślnie oba elementy są pozycjonowane
   absolutnie względem wysokiego pasa — w wariancie zwartym nachodziłyby na
   siebie. Tło gradientu przenosimy na samą sekcję. */
.parish-hero--placeholder {
  flex-direction: column;
  align-items: center;
  gap: var(--space-lg);
  background: linear-gradient(135deg, var(--color-primary), var(--color-primary-strong));
}
.parish-hero--placeholder .parish-hero__placeholder {
  position: static; inset: auto; z-index: auto; padding: 0; background: none;
}
.parish-hero--placeholder .hero-info { position: static; inset: auto; width: 100%; }

/* Ikona sekcji (front/partials/section-icon.blade.php) — wspólny partial
   obu szablonów, więc klasa musi istnieć też tutaj. */
.front-section-icon { display: inline-block; width: 1.25rem; height: 1.25rem; vertical-align: -0.2em; }
.front-section-icon svg { width: 100%; height: 100%; display: block; }
/* Ikona przy etykiecie wpłat w stopce (konto, BLIK) — w linii z tekstem. */
.front-footer__icon { display: inline-block; width: 0.95rem; height: 0.95rem; vertical-align: -0.15em; margin-right: 0.35rem; }
.front-footer__icon svg { width: 100%; height: 100%; display: block; }

/* Zastępnik brakującej miniatury — wspólny partial obu szablonów. */
.img-placeholder { display: grid; place-items: center; }
.media-placeholder__icon { display: block; width: 28%; min-width: 20px; max-width: 44px; opacity: 0.5; }
.media-placeholder__icon svg { width: 100%; height: 100%; display: block; }

/* Biuro parafialne — struktura (wspólny partial obu szablonów). */
.office-details { display: grid; gap: var(--space-sm); }
.office-details__location { margin: 0; line-height: 1.5; }
.office-details__hours { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.15rem; }
.office-details__row { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.2rem 0.6rem; }
.office-details__days { font-weight: 700; }
.office-details__time { white-space: nowrap; }
.office-details__note, .office-details__closed { font-size: 0.82rem; color: var(--color-text-muted); }
.office-details__closed { margin: 0; line-height: 1.5; }

/* Telefon dyżurny — wyróżniony, bo to najpilniej szukany numer na stronie. */
.office-duty {
  display: flex;
  gap: 0.6rem;
  align-items: flex-start;
  padding: 0.6rem 0.75rem;
  border-left: 3px solid var(--color-accent);
  background: var(--color-surface-muted);
  border-radius: 0 var(--card-radius) var(--card-radius) 0;
}
.office-duty__icon { display: block; width: 1.2rem; height: 1.2rem; flex: 0 0 auto; margin-top: 0.1rem; color: var(--section-accent, var(--color-accent)); }
.office-duty__icon svg { width: 100%; height: 100%; display: block; }
.office-duty__label { font-size: 0.7rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-text-muted); }
.office-duty__phone { display: inline-block; font-size: 1.05rem; font-weight: 800; color: var(--color-primary); text-decoration: none; }
.office-duty__note { font-size: 0.8rem; color: var(--color-text-muted); line-height: 1.45; }

/* Na ciemnym tle (nakładka hero, stopka) — tekst i tło muszą się odwrócić. */
.hero-info .office-duty, .parish-footer .office-duty { background: rgba(255,255,255,0.08); border-left-color: var(--color-accent-on-dark); }
.hero-info .office-duty__phone, .parish-footer .office-duty__phone { color: #fff; }
.hero-info .office-duty__label, .hero-info .office-duty__note,
.hero-info .office-details__note, .hero-info .office-details__closed,
.parish-footer .office-duty__label, .parish-footer .office-duty__note,
.parish-footer .office-details__note, .parish-footer .office-details__closed { color: rgba(255,255,255,0.75); }

/* Generowane podstrony „Msze i nabożeństwa" / „Kontakt" (Etap 3). */
.mod-page-block { margin: 0 0 var(--space-2xl); }
.mod-page-block:last-child { margin-bottom: 0; }
.mod-page-block__title {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  margin: 0 0 var(--space-md);
  font-family: var(--font-serif);
  font-size: clamp(1.3rem, 2.2vw, 1.7rem);
  font-weight: 500;
  color: var(--section-heading, var(--color-primary-strong));
}
.mod-page-block__icon { display: block; width: 1.4rem; height: 1.4rem; flex: 0 0 auto; color: var(--section-accent, var(--color-accent)); }
.mod-page-block__icon svg { width: 100%; height: 100%; display: block; }

/* Lista nabożeństw i dane kontaktowe — wspólne partiale obu szablonów. */
.devotions-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.5rem; }
.devotions-list__row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.2rem 0.75rem;
  padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--color-border);
}
.devotions-list__row:last-child { border-bottom: 0; padding-bottom: 0; }
.devotions-list__name { font-weight: 800; color: var(--section-text, var(--color-text)); }
.devotions-list__schedule { color: var(--section-text-soft, var(--color-text-muted)); }
.devotions-list__note { font-size: 0.82rem; color: var(--color-text-muted); }

.contact-details { display: grid; gap: var(--space-sm); }
.contact-details__name { font-family: var(--font-serif); font-size: 1.1rem; color: var(--section-heading, var(--color-primary-strong)); }
.contact-details__lines { display: grid; gap: 0.4rem; }
.contact-details__row { display: flex; align-items: flex-start; gap: 0.5rem; }
.contact-details__icon { display: block; width: 1.05rem; height: 1.05rem; flex: 0 0 auto; margin-top: 0.15rem; color: var(--section-accent, var(--color-accent)); }
.contact-details__icon svg { width: 100%; height: 100%; display: block; }
.contact-details__payments { display: grid; gap: 0.6rem; padding-top: var(--space-sm); border-top: 1px solid var(--section-border, var(--color-border)); }
/* Podetykieta („Numer konta", „BLIK") — ten sam token co nazwy grup godzin,
   więc na ciemnym panelu obie idą jednym wariantem akcentu, a nie dwoma. */
.contact-details__label { display: flex; align-items: center; gap: 0.4rem; font-size: 0.7rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--section-text-soft, var(--color-text-muted)); }
.contact-details__value { line-height: 1.5; }

/* Porządek Mszy — PREZENTACJA TYPOGRAFICZNA (25.07.2026).
   Ta sama struktura HTML co w Klasyku, inny język: zapis standardowy „7:30",
   krój bezszeryfowy, bez ramek i plakietek, dużo oddechu między godzinami.
   Nic nie może wyglądać jak przycisk. */
/* JEDNA LICZBA NA WARIANT: stopień pisma godziny. Wszystko inne z niej wynika —
   szerokość komórki, górna granica rzędu, a przez test także progi kontenerowe.
   Wcześniej stopień pisma i szerokość komórki były dwiema niezależnymi liczbami
   w dwóch miejscach arkusza; zmiana jednej po cichu rozjeżdżała podział.

   Mnożnik 2,8: zmierzona najszersza godzina „10:30" (cyfry tabelaryczne,
   widoczny dwukropek) zajmuje 2,61 em — reszta to oddech wokół niej.
   Nie `em` na komórce: rząd ma inny stopień pisma niż godzina, więc to samo
   `2.8em` znaczyłoby w obu miejscach co innego. */
.mass-schedule {
  --time-size: 1.35rem;
  --time-cell: calc(var(--time-size) * 2.8);
  display: grid;
  gap: var(--space-lg);
  /* Zawijanie zależne od SZEROKOŚCI KOMPONENTU, nie ekranu — ten sam porządek
     stoi w pasie, w wąskim railu, w stopce i w nakładce baneru. */
  container-type: inline-size;
  container-name: mass;
}
.mass-schedule__group { display: grid; gap: 0.5rem; }
.mass-schedule__day {
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--section-text-soft, var(--color-text-muted));
}
/* Flex, nie grid — `justify-content: center` środkuje ostatni NIEPEŁNY rząd
   (5 godzin → 3 + 2 pod spodem). Szerokość komórki liczona z --cols, którą
   podaje serwer (App\Support\Front\MassTime::columns). */
/* RZĄD MIEŚCI DOKŁADNIE `--cols` GODZIN (06.09.2026). Sama komórka z górną
   granicą szerokości nie wystarcza: gdy podstawa flexa jest szersza od tej
   granicy, komórki kurczą się i w rzędzie mieści się ich WIĘCEJ, niż policzył
   serwer — sześć godzin przy podziale 3 + 3 wychodziło jako 5 + 1, czyli
   dokładnie sierota, której ta reguła ma zakazywać. Górna granica na RZĘDZIE
   domyka kontrakt; `margin-inline: auto` środkuje zwężony rząd w kolumnie. */
.mass-schedule__times {
  --gap: 0.5rem;
  --cols: var(--cols-6, 6);
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--gap);
  /* `width`, nie `max-width`: rząd jest POZYCJĄ SIATKI (`.mass-schedule__group`
     to grid), a tam automatyczne marginesy każą przeglądarce liczyć szerokość
     „do treści" — wychodziła z tego liczba mniejsza od sumy komórek i rząd
     łamał się mimo swobodnego miejsca. Szerokość JAWNA znosi to liczenie.
     +1px na zaokrąglenia subpikselowe: rząd o szerokości CO DO PIKSELA równej
     swojej treści łamie ostatnią komórkę. */
  width: min(100%, calc(var(--cols) * var(--time-cell) + (var(--cols) - 1) * var(--gap) + 1px));
  margin-inline: auto;
}
.mass-schedule__times > .mass-time {
  /* `0 1` (nie `0 0`) plus górna granica szerokości: przy PEŁNYM rzędzie komórki
     kurczą się do wyliczonej szerokości, a przy grupie z mniejszą liczbą godzin
     NIE rozciągają się na całą kolumnę — dwie godziny stały wcześniej rozstrzelone
     na przeciwnych końcach. Odstęp jest stały, a cała grupa wyśrodkowana
     (`justify-content` wyżej). 2,3 em przy zmierzonych 1,90 em, które zajmuje
     najszersza godzina („10:30", cyfry tabelaryczne) — zapas na odetchnięcie,
     bez rozjeżdżania. */
  flex: 0 1 calc((100% - (var(--cols) - 1) * var(--gap)) / var(--cols));
  max-width: var(--time-cell);
}
/* Każdy próg bierze GOTOWY podział policzony przez serwer dla tej szerokości —
   nie obcina liczby kolumn, bo obcinanie łamałoby regułę o sierocie w ostatnim
   rzędzie (siedem godzin obcięte do sześciu dałoby 6 + 1 zamiast 4 + 3).

   PROGI PRZELICZONE DLA TYPOGRAFII NOWOCZESNEGO (06.09.2026). Były przepisane
   z Klasyka (16 / 11 / 8 rem) i to był błąd: Klasyk pisze godzinę „10³⁰" krojem
   szeryfowym z UKRYTYM dwukropkiem i minutami w indeksie, więc mieści się w 36 px.
   Nowoczesny pisze „10:30" bezszeryfowo, z widocznym dwukropkiem (decyzja, która
   zostaje) — zmierzone 56,3 px przy 21,6 px pisma, czyli 2,61 em. Przy starych
   progach panel trzymał sześć godzin w rzędzie na 356 px i sąsiednie godziny
   sklejały się w „10:3012:0018:00".

   ⚠️ PRÓG MUSI ZOSTAĆ LICZBĄ WPISANĄ WPROST — warunek `@container` nie czyta
   zmiennych CSS (tak samo jak `@media`), więc nie da się go policzyć z tokenu
   w arkuszu. Żeby mimo to nie rozjechał się po cichu przy zmianie stopnia pisma,
   liczy go z `--time-size` i `--gap` STRAŻNIK:
   MassScheduleRowTest::test_container_thresholds_follow_the_cell_token.

   Liczone od komórki (2,8 × 1,35 rem = 3,78 rem) i odstępu 0,5 rem:
     6 godzin → 6 × 3,78 + 5 × 0,5 = 25,18 rem → próg 25,5 rem
     4 godziny → 4 × 3,78 + 3 × 0,5 = 16,62 rem → próg 17 rem
     3 godziny → 3 × 3,78 + 2 × 0,5 = 12,34 rem → próg 12,5 rem
   Próg zaokrąglamy W GÓRĘ: w dół oznaczałby rząd wybrany dla szerokości,
   w której się już nie mieści. Progi biorą wariant WIĘKSZY (1,35 rem), bo jeden
   zestaw obsługuje wszystkie umiejscowienia; w wariancie zwartym zostaje zapas. */
@container mass (max-width: 25.5rem) {
  .mass-schedule__times { --cols: var(--cols-4, 4); }
}
@container mass (max-width: 17rem) {
  .mass-schedule__times { --cols: var(--cols-3, 3); }
}
@container mass (max-width: 12.5rem) {
  .mass-schedule__times { --cols: var(--cols-2, 2); }
}
.mass-time {
  display: block;
  text-align: center;
  white-space: nowrap;
  font-family: var(--font-ui);
  font-size: var(--time-size);
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: 0.01em;
  font-variant-numeric: tabular-nums lining-nums;
  color: var(--section-text, var(--color-text));
}
/* Dwukropek jest tu WIDOCZNY (zapis standardowy) — chowa go tylko Klasyk.
   KOLOR WYCISZONY Z ZAKRESU, NIE PRZEZROCZYSTOŚĆ (14.09.2026). `opacity: 0.55`
   dawała inny wynik nad każdym tłem: 3,62:1 na białej karcie, 3,01:1 na pasie
   akcentowym. `--section-muted` ustawia każdy zakres (pas jasny, przygaszony,
   ciemny, akcentowy, stopka, panel nakładki banera) i przechodzi próg wszędzie.
   Pilnuje SidebarBandInsetsTest. */
.mass-time__sep { color: var(--section-muted); }
/* Wariant zwarty (kolumna boczna) — mniejszy stopień pisma, a komórka i rząd
   idą za nim same. */
.mass-schedule--compact { gap: var(--space-md); --time-size: 1.1rem; }
.mass-schedule--compact .mass-schedule__times { --gap: 0.5rem; }
.mass-schedule__notes { font-size: 0.85rem; line-height: 1.55; }

/* PODSTRONA „MSZE I NABOŻEŃSTWA" — WSZYSTKO DO LEWEJ (06.09.2026, A27).

   Etykieta grupy stała przy lewej krawędzi, a rząd godzin na środku — dwa
   wyrównania w jednym bloku czytały się jak pomyłka składu.

   ⚠️ TO NIE JEST ODWRÓCENIE DECYZJI B7. Panel „Informacje podstawowe", stopka
   i ściągawka w kolumnie bocznej ZOSTAJĄ wyśrodkowane i tak ma być: tam godziny
   stoją zwartym rzędem bez niczego obok, więc środek jest ich naturalną osią.
   Na podstronie rząd sąsiaduje z etykietą grupy, adnotacją i nagłówkiem sekcji —
   wszystkim, co zaczyna się przy lewej krawędzi. Różnica wynika z SĄSIEDZTWA,
   nie z upodobania; pełny zapis w docs/UI-STYLE.md. Nie ujednolicać w żadną stronę.
   Dotyczy OBU szablonów — Klasyk ma tę samą regułę w public/css/front.css. */
.mod-page-block .mass-schedule__day { text-align: left; }
.mod-page-block .mass-schedule__times { justify-content: flex-start; margin-inline: 0; }
.mod-page-block .mass-time { text-align: left; }


/* Wspólne wnętrze bloku Informacji. */
.info-block__title {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0 0 var(--space-sm);
  font-family: var(--font-serif);
  font-size: 1.2rem;
  font-weight: 500;
  color: var(--card-heading, var(--color-primary-strong));
}
.info-block__icon { display: block; width: 1.25rem; height: 1.25rem; flex: 0 0 auto; color: var(--section-accent, var(--color-accent)); }
.info-block__icon svg { width: 100%; height: 100%; display: block; }
/* Przycisk „zobacz całość" — rola drugorzędna, kolor dziedziczony, więc jeden
   wygląd działa na jasnym pasie, na ciemnej stopce i na nakładce na zdjęciu. */
.info-block__more {
  display: inline-block;
  margin-top: var(--space-sm);
  padding: 0.45rem 1rem;
  font-size: 0.85rem;
  font-weight: 800;
  color: var(--card-link, var(--color-primary));
  border: 1px solid currentColor;
  border-radius: 999px;
  background: transparent;
  text-decoration: none;
  transition: background-color 180ms ease, color 180ms ease;
}
.info-block__more:hover,
.info-block__more:active {
  background: var(--card-link, var(--color-primary));
  color: var(--card-bg, #fff);
}

/* Ściągawka w kolumnie bocznej. */
.front-sidebar-info { display: grid; gap: var(--space-md); margin-bottom: var(--space-lg); }
.sidebar-info-box { padding: var(--space-md); background: #fff; border: 1px solid var(--color-border); border-radius: var(--card-radius); }
.sidebar-info-box .info-block__title { font-size: 1rem; }
.info-phone { display: grid; gap: 0.5rem; }
.info-phone__number { display: inline-block; font-size: 1.05rem; font-weight: 800; color: var(--color-primary); text-decoration: none; }
.info-phone__duty { padding-top: 0.5rem; border-top: 1px solid var(--color-border); }
.info-phone__label { font-size: 0.7rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-text-muted); }
.info-phone__note { font-size: 0.8rem; color: var(--color-text-muted); line-height: 1.45; }

/* Nakładka „Zobacz pełne informacje" — tylko desktop. */
.info-overlay { position: fixed; inset: 0; z-index: var(--z-nakladka); display: grid; place-items: center; }
.info-overlay[hidden] { display: none; }
@media (max-width: 52rem) { .info-overlay { display: none; } }

/* BŁĄD NOWOCZESNEGO (Etap 4): treść nakładki baneru była wyrównana do DOŁU.
   Kolumny mają się zaczynać u góry panelu, jak każda inna treść.

   `align-items: start` ZDJĘTE 06.09.2026 — pełny zapis, razem z powodem i z tym,
   czym intencja Etapu 4 jest teraz spełniona, w docs/UI-STYLE.md → „Panel
   »Informacje podstawowe« Nowoczesnego". W skrócie: kurczyło kolumny do wysokości
   treści, więc przycisk „Zobacz…" nie miał się o co oprzeć. `align-content`
   zostaje: dotyczy rozkładu RZĘDÓW siatki, nie wysokości kolumn. */
.hero-info__panel { align-content: start; }

/* Pas wielokolumnowy — rzędy widgetów (punkt 1, 19.07.2026). Ten sam mechanizm
   co Klasyk; próg desktopu Nowoczesnego to 52rem.
   `justify-content: center` na rzędzie: pełny rząd (suma 12) i tak wypełnia
   całą szerokość komórkami, więc środkowanie nic tam nie zmienia; niepełny
   rząd (np. ½ + ⅓) zostaje wyśrodkowany zamiast wyrównany do lewej (poprawka
   26.07.2026 — ujednolicenie z rzędem godzin Mszy i samotnym widgetem w
   rzędzie, `.home-row--solo` niżej, które niepełny rząd już środkowały). */
.home-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-xl);
  align-items: stretch;
  /* Rząd renderuje się POZA strefą (pełne okno), więc SAM ogranicza treść do
     kontenera-szerokiego i dostaje rytm pasa (jak Klasyk). */
  max-width: var(--tresc-max);
  margin-inline: auto;
  padding-inline: var(--space-lg);
  padding-block: var(--band-space);
}
.home-row__cell { flex: 0 0 100%; min-width: 0; }
.home-row__cell > * { height: 100%; }
/* Widget w komórce rzędu nie jest pełnoszerokościowym pasem — rytm i wcięcie
   daje rząd, nie każda karta: zerujemy padding pasa z .mod-section. */
.home-row__cell .mod-section { padding: 0; }
/* …ALE KOMÓRKA Z TŁEM ma wcięcie ze wszystkich stron (13.09.2026). Zero wyżej
   jest dobre, dopóki blok nie ma tła; z tłem tekst dotykał wszystkich czterech
   krawędzi. Klasyk/Łukasz wcinają każdą komórkę (front-base.css → `--trio-pad`);
   tu tylko te z tłem, żeby nie przestawić bloków bez tła. */
.home-row__cell .mod-section:is([style*="--section-bg"], .editorial-links-band) { padding: var(--space-lg); }

/* REGUŁA 4 (31.07.2026) — akcja domykająca blok stoi przy dolnej krawędzi,
   także gdy widgety dzielą rząd i mają wyrównane wysokości. Komórka daje już
   `height: 100%`, brakowało łańcucha kolumn flex, żeby `margin-top: auto` miało
   od czego się odbić: pas → wnętrze → wiersz domykający.

   Ta sama zasada co w Klasyku, inne nazwy klas — bo to warstwa prezentacji
   szablonu. Lista klas jest wspólna ze strażnikiem (WidgetAdaptationTest),
   który sprawdza KAŻDY szablon osobno: klasa Klasyka musi być wymieniona w
   front.css, klasa Nowoczesnego w front-modern.css. */
.home-row__cell .mod-section,
.home-row__cell .home-module__inner,
.home-row__cell .front-gospel,
.home-row__cell .front-extnews { display: flex; flex-direction: column; }
.home-row__cell .home-module__footer,
.home-row__cell .mod-section-foot,
.home-row__cell .mod-ann__actions,
.home-row__cell .section-foot,
.home-row__cell .front-gospel__foot,
.home-row__cell .front-extnews__foot { margin-top: auto; }

@media (min-width: 52.0625rem) {
  .home-row__cell--half  { flex: 0 0 calc(50% - var(--space-xl) / 2); }
  .home-row__cell--third { flex: 0 0 calc(33.333% - var(--space-xl) * 2 / 3); }
}

/* ============================================================
   WIDGETY TREŚCI ZEWNĘTRZNYCH (23.07.2026) — Nowoczesny.
   Te same klasy co Klasyk (widoki różnią się ramą, nie wnętrzem);
   kolory ze zmiennych zakresu sekcji.
   ============================================================ */

/* ---- Ewangelia dnia ---- */
.front-gospel__day { display: flex; align-items: center; gap: var(--space-sm); font-weight: 700; color: var(--section-text); }
.front-gospel__ref { margin: 0.4rem 0 var(--space-md); color: var(--section-muted); font-size: 0.9rem; }
.front-gospel__text-title { margin: 0 0 0.5rem; font-family: var(--font-serif); font-size: 1.25rem; font-weight: 500; color: var(--section-heading); }
.front-gospel__body { margin: 0; color: var(--section-text); line-height: 1.7; }
.front-gospel__foot { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--space-sm) var(--space-md); margin-top: var(--space-lg); }
.front-gospel__foot > a { color: var(--section-link); font-size: 0.8rem; font-weight: 900; text-decoration: none; }
.front-gospel__foot > a:hover { text-decoration: underline; }
.front-gospel__credit { display: block; margin: var(--space-md) 0 0; font-size: 0.78rem; color: var(--section-muted); }
.front-gospel__credit a { color: inherit; }

/* Forma krótka/pełna Z SZEROKOŚCI KONTENERA (nie z ustawienia w panelu). */
@container (max-width: 34rem) {
  .front-gospel__body { display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; }
}

/* ---- Transmisja na żywo ---- */
.front-live__embed { max-width: 54rem; }
.front-live__link-tile {
  display: flex; align-items: center; gap: var(--space-sm);
  padding: var(--space-md) var(--space-lg);
  background: var(--card-bg); border: 1px solid var(--card-border);
  border-radius: var(--card-radius); color: var(--card-text);
  text-decoration: none; font-weight: 700;
}
.front-live__icon { flex: 0 0 auto; width: 1.5rem; height: 1.5rem; color: var(--color-primary, var(--section-accent)); }

/* ---- Wiadomości katolickie ---- */
.front-extnews__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0; }
.front-extnews__item { display: flex; gap: var(--space-sm); padding: var(--space-sm) 0; border-bottom: 1px solid var(--card-border); }
.front-extnews__item:last-child { border-bottom: 0; }
.front-extnews__icon { flex: 0 0 auto; width: 1.1rem; height: 1.1rem; margin-top: 0.2rem; color: var(--color-primary, var(--section-accent)); }
.front-extnews__body { display: flex; flex-direction: column; gap: 0.2rem; min-width: 0; }
.front-extnews__title { font-weight: 700; color: var(--section-text); text-decoration: none; line-height: 1.45; }
a.front-extnews__title:hover { color: var(--color-primary); }
.front-extnews__meta { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; font-size: 0.78rem; color: var(--section-muted); }
.front-extnews__source { font-weight: 700; }
.front-extnews__foot { margin-top: var(--space-md); font-size: 0.72rem; color: var(--section-muted); line-height: 1.5; }

/* ============================================================
   SAKRAMENTY I POSŁUGI (23.07.2026) — Nowoczesny. Te same klasy co Klasyk
   (widoki różnią się ramą, nie wnętrzem); zwijanie według KONTENERA.
   ============================================================ */
.sacrament-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  /* Szerokość kafla dobrana tak, żeby przy pełnej szerokości wyszły CZTERY
     i żeby pełny rząd wypełniał pas prawie bez luzu — jak w Klasyku. */
  --kafel: clamp(150px, 23.5cqi, 300px);
  --kafel-max: 340px;
  grid-template-columns: repeat(auto-fill, minmax(min(var(--kafel), 100%), 1fr));
  justify-content: var(--kafle-justify, start);
  gap: var(--space-xl) var(--space-md);
}
.sacrament-grid__cell { min-width: 0; }
.sacrament-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-sm);
  text-align: center;
  text-decoration: none;
  color: inherit;
}
.sacrament-tile__photo {
  width: 7.25rem;
  height: 7.25rem;
  border-radius: 50%;
  overflow: hidden;
  background: var(--section-accent-soft, var(--color-accent-soft));
  /* Ton strony zamiast bieli (12.09.2026) — kafle sakramentów leżą wprost na
     tle strony, więc przy tle w kolorze albo zdjęciu biała obwódka odcinałaby
     się jako obcy pierścień. Na pasie z własnym tłem token nadpisuje zakres. */
  border: 4px solid var(--section-dot-ring, var(--color-page));
  box-shadow: 0 0.7rem 1.8rem rgba(31, 35, 43, 0.1);
  color: var(--card-link);
  display: grid;
  place-items: center;
  transition: transform 0.2s ease;
}
.sacrament-tile__photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.sacrament-tile__icon { width: 44%; height: 44%; }
.sacrament-tile:hover .sacrament-tile__photo { transform: translateY(-3px); }
.sacrament-tile__caption {
  font-family: var(--font-serif);
  font-size: 1rem;
  font-weight: 500;
  line-height: 1.25;
  color: var(--section-heading);
  text-wrap: balance;
}
.sacrament-tile:hover .sacrament-tile__caption { color: var(--color-primary); }

@container (max-width: 30rem) {
  .sacrament-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-lg) var(--space-sm); }
  .sacrament-tile__photo { width: 5.75rem; height: 5.75rem; }
  .sacrament-tile__caption { font-size: 0.9rem; }
}

/* Podtytuł kafla Aktualności — wspólna klasa dla kafla, wyróżnionego i archiwum.
   ZWYKŁY TEKST W KOLORZE TEKSTU (15.09.2026). Do tej pory były to kapitaliki
   w kolorze akcentu: pełne zdanie wersalikami krzyczało mocniej niż tytuł,
   a pod nim zaczynał się zwykły tekst — dwa style jednego fragmentu obok siebie.
   Wersaliki zostają wyłącznie w plakietkach kategorii i krótkich etykietach.
   Pilnuje TypographyFloorTest (także dla Nowoczesnego). */
.news-card__subtitle {
  margin: 0.35rem 0 0;
  font-size: 0.9rem;
  font-weight: 400;
  color: var(--card-text, var(--color-text));
  line-height: 1.5;
}

/* Ikona odtwarzania na kaflu galerii WIDEO (Nowoczesny) — na okładce, biel
   poprawna niezależnie od tła (biała lista strażnika). */
.gallery-tile__play {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: var(--z-plakietka);
  width: 3.4rem;
  height: 3.4rem;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  background: rgba(8, 18, 36, 0.55);
  border: 2px solid rgba(255, 255, 255, 0.9);
  transition: background 0.2s ease, transform 0.2s ease;
  pointer-events: none;
}
.gallery-tile--video:hover .gallery-tile__play { transform: translate(-50%, -50%) scale(1.06); }

/* Widgety w kolumnie bocznej (rail, placement 'sidebar', 23.07.2026) — zwarty
   odstęp zamiast rytmu pełnego pasa; górna linia home-module niepotrzebna w railu. */
.parish-sidebar .mod-section {
  padding: 0;
  margin: 0 0 var(--space-lg);
  background: transparent;
}
.parish-sidebar .mod-section:last-child { margin-bottom: 0; }
.parish-sidebar .home-module { border-top: 0; }
.parish-sidebar .mod-section .front-pattern,
.parish-sidebar .mod-section .front-section-photo { display: none; }

/* Mapa na podstronie Kontakt — patrz front.css (ten sam wariant, Nowoczesny
   nie ładuje front.css, więc reguły muszą tu być powtórzone). */
.front-map { display: flex; flex-direction: column; gap: 8px; }
.front-map__iframe {
  width: 100%;
  aspect-ratio: 4 / 3;
  border: 0;
  border-radius: var(--radius-md, 10px);
}
/* Odnośnik mapy = akcja z systemu (patrz Klasyk). */
.front-map__foot { margin-top: 10px; }
.mod-page-block--map { margin-bottom: 28px; }
.front-map--page .front-map__iframe { aspect-ratio: 16 / 9; min-height: 320px; }
@media (max-width: 52rem) {
  .front-map--page .front-map__iframe { aspect-ratio: 4 / 3; min-height: 260px; }
}

/* Pomiar wysokości nagłówka (skrypt front/partials/header-fit): oba stany —
   pełny i zwinięty — mierzymy z WYŁĄCZONYMI przejściami, inaczej dostalibyśmy
   wysokość w połowie animacji. Atrybut żyje ułamek milisekundy, w tej samej
   klatce, więc nic nie zdąży mrugnąć. */
[data-header-measuring-height],
[data-header-measuring-height] * { transition: none !important; }

/* ============================================================
   STANY INTERAKCJI — NOWOCZESNY (25.07.2026, Etap 3 pracy nocnej)

   WŁASNY JĘZYK, nie ta sama propozycja co w Klasyku w innej palecie:

     Klasyk mówi PODKREŚLENIEM i miękkim cieniem — jak drukowana strona.
     Nowoczesny mówi UNIESIENIEM i PIERŚCIENIEM — element odrywa się od
     powierzchni i dostaje obrys dookoła, a nie kreskę pod spodem.
     Przejścia są dłuższe (220 ms wobec 200 ms) i płynniejsze.

   Reguły wspólne dla obu szablonów zostają w mocy:
     * akcent znaczy „tu jesteś"; najechanie mówi własnym kolorem elementu,
     * żaden stan nie zmienia WYMIARÓW — `translateY` przesuwa element, ale
       nie zmienia jego pudełka, więc sąsiedzi stoją nieruchomo; `scale`
       na kartach jest z tego powodu zakazane (na zdjęciu W ŚRODKU karty
       jest dozwolone — kadr się nie rusza, bo ma `overflow: hidden`),
     * wciśnięcie czytelne samo z siebie (jedyny stan na dotyku),
     * fokus klawiatury obsługuje jedna globalna reguła wyżej.

   Uniesienie znika samo przy systemowym ograniczeniu ruchu — globalna reguła
   `prefers-reduced-motion` zeruje czas przejść.
   ============================================================ */

/* ---- Karty: aktualności, redakcyjna, galeria, playlista ----
   UNIESIENIE = mocniejszy cień + drobne przesunięcie w górę. */
.news-card, .featured-card, .gallery-tile, .playlist-tile {
  transition: box-shadow 220ms ease, transform 220ms ease, border-color 220ms ease;
}
.news-card:hover, .featured-card:hover, .gallery-tile:hover, .playlist-tile:hover {
  transform: translateY(-3px);
  box-shadow: 0 1.4rem 3rem rgba(31, 35, 43, 0.16);
}
/* Wciśnięcie: karta wraca na powierzchnię i lekko przygasa — kierunek
   odwrotny do uniesienia, czytelny bez kursora. */
.news-card:active, .featured-card:active, .gallery-tile:active, .playlist-tile:active {
  transform: none;
  box-shadow: var(--shadow-card);
  filter: brightness(0.97);
}

/* ---- DRUGI SYGNAŁ: CIEŃ NIE WYSTARCZA (07.09.2026, A19) ----

   Uniesienie wyżej mówi WYŁĄCZNIE cieniem, a cień jest półprzezroczystą
   czernią: na pasie ciemnym i akcentowym nie widać go w ogóle, więc kafel nie
   reagował tam ani na najechanie, ani na wciśnięcie. To ten sam defekt, który
   Klasyk naprawił 25.07.2026 tokenami `--card-bg-hover` / `--card-border-hover`
   / `--card-bg-active` — Nowoczesny nie używał ich ani razu.

   Wzorzec jest już w kaflu Wydarzeń (partia 2) i tu go POWTARZAMY, a nie
   wymyślamy trzeciego wariantu: obwódka plus przesunięcie tła, oba z zakresu.
   Na pasie jasnym tło zostaje (`--card-bg-hover` = `--card-bg`) i sygnał niesie
   obwódka; na ciemnym i akcentowym jest odwrotnie. Żaden stan nie zmienia
   wymiarów — obwódka ma tę samą grubość, zmienia się jej kolor. */
.news-card { transition: background-color var(--motion-state) var(--motion-ease-state); }
.news-card:hover { background: var(--card-bg-hover); border-color: var(--card-border-hover); }
.news-card:active { background: var(--card-bg-active); border-color: var(--card-border-hover); }
/* Kafel wyróżniony i kafle ZDJĘCIOWE nie mają obwódki: tam drugim sygnałem jest
   pierścień wpuszczony do środka (`inset`), więc nie rusza wymiarów, a leży NA
   kaflu — widać go tak samo na zdjęciu, jak na jednolitym tle. */
.featured-card { transition: background-color var(--motion-state) var(--motion-ease-state), box-shadow var(--motion-state) var(--motion-ease-state); }
.featured-card:hover { background: var(--card-bg-hover); box-shadow: inset 0 0 0 2px var(--card-border-hover), 0 1.4rem 3rem rgba(31, 35, 43, 0.16); }
.featured-card:active { background: var(--card-bg-active); box-shadow: inset 0 0 0 2px var(--card-border-hover); }
.gallery-tile:hover, .playlist-tile:hover { box-shadow: inset 0 0 0 2px var(--card-border-hover), 0 1.4rem 3rem rgba(31, 35, 43, 0.16); }
.gallery-tile:active, .playlist-tile:active { box-shadow: inset 0 0 0 2px var(--card-border-hover); }
/* Tytuł kafla przesuwa się ku barwie nagłówków — trzeci sygnał tam, gdzie tytuł
   nie jest już nią pomalowany. Na pasie ciemnym i akcentowym przesunięcia NIE MA
   (oba tokeny są tam bielą) i to jest stan przyjęty: niosą pozostałe dwa. */
.news-card__content h3 a { transition: color var(--motion-state) var(--motion-ease-state); }

/* ---- WIERSZ LISTY — własny token, nie kaflowy ----
   Wiersz nie ma cienia, więc tło jest jego GŁÓWNYM sygnałem; `--row-bg-*` są
   liczone osobno od `--card-bg-*` właśnie dlatego. Wcześniej wiersz brał stałą
   `--color-surface-muted` i na ciemnym pasie nie reagował. */
.article-list__item { transition: background-color var(--motion-state) var(--motion-ease-state); }
.article-list__item:hover { background: var(--row-bg-hover, var(--color-surface-muted)); }
.article-list__item:active { background: var(--row-bg-active, var(--color-surface-muted)); }

/* ---- Nawigacja ----
   Podkreślenie aktywnej pozycji zostaje (to „tu jesteś"), najechanie samo
   rozjaśnia tekst — bez kreski, żeby nie udawało stanu aktywnego. */
.main-navigation a:active, .main-navigation__label:active { color: var(--color-primary-strong); }
.mobile-navigation a:active { background: var(--color-surface-muted); }
.sidebar-row:active { background: var(--color-surface-muted); }
.sidebar-sublist a:active { background: var(--color-surface-muted); }

/* ---- Okruszki nawigacyjne ----
   Klasa `front-breadcrumbs` jest WSPÓLNA z Klasykiem (jeden komponent, dwie
   typografie — decyzja B2, 09.09.2026), więc czas przejścia musi iść z tokenu
   po obu stronach. Do 09.09.2026 stało tu `180ms ease` jako wyjątek w wykazie
   ruchu; okazało się, że to nie jest wyjątek, tylko ta sama wartość wpisana
   ręcznie: `--motion-state` Nowoczesnego to dokładnie 180 ms, a `ease` jest
   z definicji `cubic-bezier(0.25, 0.1, 0.25, 1)`, czyli `--motion-ease-state`.
   Jedna klasa, dwa źródła czasu rozjechałyby się przy pierwszej zmianie
   tokenu — i nikt by tego nie zauważył, bo wyglądałyby tak samo do tej chwili. */
.front-breadcrumbs a { transition: color var(--motion-state) var(--motion-ease-state); }
.front-breadcrumbs a:hover { color: var(--color-primary-strong); text-decoration: underline; text-underline-offset: 0.2em; }
.front-breadcrumbs a:active { opacity: 0.75; }

/* ---- Odnośniki „→" ----
   Strzałka siedzi w napisie, więc odsuwamy ją odstępem między słowami:
   ruch jest, a wymiary zostają. */
.all-news-link, .read-more, .link-more {
  transition: word-spacing 220ms ease, color 220ms ease;
}
.all-news-link:hover, .read-more:hover, .link-more:hover { word-spacing: 5px; }
.all-news-link:active, .read-more:active, .link-more:active { word-spacing: 5px; opacity: 0.8; }

/* ---- Kafel sakramentu — PIERŚCIEŃ, nie podkreślenie ---- */
.sacrament-tile__photo { transition: box-shadow 220ms ease; }
.sacrament-tile:hover .sacrament-tile__photo {
  box-shadow: 0 0 0 4px var(--card-bg, #fff), 0 0 0 6px currentColor;
}
.sacrament-tile:active .sacrament-tile__photo {
  box-shadow: 0 0 0 4px var(--card-bg, #fff), 0 0 0 6px currentColor;
  filter: brightness(0.95);
}

/* ---- Filtr kategorii ---- */
.mm-chip { transition: background-color 180ms ease, border-color 180ms ease, color 180ms ease; }
.mm-chip:hover { border-color: var(--color-text-muted); }
.mm-chip:active { background: var(--color-surface-muted); }

/* ---- Stopka ---- */
.parish-footer a { transition: color 180ms ease, opacity 180ms ease; }
.parish-footer a:hover { text-decoration: underline; text-underline-offset: 0.2em; }
.parish-footer a:active { opacity: 0.75; }

/* Zakres akcji dla ciemnej stopki + wzmocnienie specyficzności — jak w Klasyku. */
.parish-footer {
  --section-action-quiet-ink: #FFFFFF;
  --section-action-quiet-border: rgba(255, 255, 255, 0.72);
  --section-action-quiet-bg-hover: #FFFFFF;
  --section-action-quiet-ink-hover: #202329;
}
.parish-footer .btn--action-quiet { color: var(--section-action-quiet-ink); text-decoration: none; }
.parish-footer .btn--action-quiet:hover { color: var(--section-action-quiet-ink-hover); text-decoration: none; }

/* ---- Przyciski ---- */
.btn { transition: background-color 220ms ease, color 220ms ease, border-color 220ms ease; }
.btn:active { filter: brightness(0.93); }

/* Rząd z JEDNYM węższym widgetem — wyśrodkowany zamiast dosuniętego do lewej
   (25.07.2026, Etap 5). Szerokość komórki zostaje ta, którą ustawiła parafia;
   zmienia się wyłącznie położenie w pasie. Od 26.07.2026 `.home-row` bazowo
   też środkuje (patrz wyżej) — ta reguła jest więc dziś nadmiarowa, zostaje
   jednak jako jawne udokumentowanie zamiaru dla tego konkretnego przypadku
   (klasa nadana w home-rows.blade.php), gdyby kiedyś reguły się rozjechały. NOWOCZESNY */
.home-row--solo { justify-content: center; }

/* ============================================================
   ARCHIWUM AKTUALNOŚCI — OŚ CZASU (25.07.2026, Etap 7 pracy nocnej)
   Własny język Nowoczesnego: pionowa linia z kropką przy każdym okresie
   zamiast typograficznych separatorów, którymi mówi Klasyk.
   ============================================================ */
.mod-archive-filter { margin-bottom: var(--space-lg); }
/* ============================================================
   NAWIGACJA PO CZASIE W ARCHIWACH (07.09.2026)

   Katalog Galerii i archiwum Ogłoszeń używają WSPÓLNYCH klas rzędów
   (`news-archive-*`) — render dostały 31.07.2026, ale arkusz Nowoczesnego nie
   miał dla nich ANI JEDNEJ reguły: rocznik i miesiące renderowały się jako
   zbity ciąg podkreślonych odnośników, w którym miesiąc pusty nie różnił się
   od klikalnego, a bieżący od pozostałych.

   ZACHOWANIE jak w Klasyku: rzędy przewijają się W BOK zamiast zawijać
   (dziesięć lat albo trzynaście miesięcy w zawiniętym rzędzie zjadłoby pół
   ekranu telefonu), a pasek przewijania jest ukryty — pojawia się dopiero przy
   nadmiarze treści i zabiera wysokość, więc przy przełączaniu miesiąca cała
   treść pod rzędem podskakiwała. Wygląd własny: rocznik jak zakładka
   z podkreśleniem, miesiąc jako drobna pigułka podrzędna wobec niego.
   ============================================================ */
.news-archive-years,
.news-archive-months { scrollbar-width: none; }
.news-archive-years::-webkit-scrollbar,
.news-archive-months::-webkit-scrollbar { display: none; }
.news-archive-years,
.news-archive-months {
  display: flex;
  flex-wrap: nowrap;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  gap: var(--space-2xs);
  margin: 0 0 var(--space-md);
  padding-bottom: var(--space-2xs);
}
.news-archive-years { border-bottom: 1px solid var(--section-border, var(--color-border)); }
.news-archive-years__item,
.news-archive-months__item {
  flex: 0 0 auto;
  white-space: nowrap;
  text-decoration: none;
  color: var(--section-text, var(--color-text));
  transition: color var(--motion-state) var(--motion-ease-state),
              border-color var(--motion-state) var(--motion-ease-state),
              background-color var(--motion-state) var(--motion-ease-state);
}
/* ROCZNIK — zakładka: podkreślenie zamiast pigułki, żeby rząd lat czytał się
   jako nadrzędny wobec rzędu miesięcy pod nim. */
.news-archive-years__item {
  padding: 0.4rem 0.75rem;
  margin-bottom: -1px;
  border-bottom: 3px solid transparent;
  font-family: var(--font-serif);
  font-size: 1.15rem;
  font-weight: 500;
}
.news-archive-years__item:hover { border-bottom-color: var(--section-border, var(--color-border)); }
.news-archive-years__item:active { color: var(--section-heading, var(--color-primary-strong)); }
.news-archive-years__item.is-active {
  color: var(--section-heading, var(--color-primary-strong));
  border-bottom-color: var(--section-accent-ink, var(--color-accent-strong));
}
/* MIESIĄC — drobna pigułka. */
.news-archive-months__item {
  padding: 0.4rem 0.7rem;
  border: 1px solid transparent;
  border-radius: 999px;
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.news-archive-months__item:hover { border-color: var(--section-border, var(--color-border)); }
.news-archive-months__item:active { background: var(--card-bg-alt, var(--color-surface-muted)); }
/* Pigułka bieżąca niesie WŁASNE, nieprzezroczyste tło, więc bierze stałe tokeny
   palety, nie zmienne zakresu — ma wyglądać tak samo niezależnie od tego, na
   czym leży (jak `.mm-chip.is-active` obok). Prefiks `.mod-root` przebija
   globalne `a { color: inherit }`; bez niego napis dziedziczy kolor tekstu
   strony i ginie na własnym tle. */
.mod-root .news-archive-months__item.is-active {
  background: var(--color-primary-strong);
  border-color: var(--color-primary-strong);
  color: var(--color-surface);
}
/* Miesiąc bez wpisów: przygaszony i NIE jest odnośnikiem (w markupie to <span>),
   więc rząd mówi wprost, kiedy parafia publikowała, a kiedy milczała. */
.news-archive-months__item.is-empty {
  color: var(--section-muted, var(--color-text-muted));
  opacity: 0.45;
  cursor: default;
}

.mod-years {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
  margin-bottom: var(--space-xl);
  padding-bottom: var(--space-md);
  border-bottom: 1px solid var(--card-border);
}
.mod-years__item {
  display: inline-flex;
  align-items: baseline;
  gap: 0.4rem;
  padding: 0.45rem 0.9rem;
  border-radius: 999px;
  text-decoration: none;
  color: var(--color-text);
  box-shadow: inset 0 0 0 1px var(--card-border);
  transition: box-shadow 180ms ease, background-color 180ms ease;
}
.mod-years__item:hover { box-shadow: inset 0 0 0 1px var(--color-text-muted); }
.mod-years__item:active { background: var(--color-surface-muted); }
.mod-years__item.is-active {
  background: var(--color-primary-strong);
  color: #fff;
  box-shadow: none;
}
.mod-years__year { font-weight: 700; }
.mod-years__count { font-size: 0.75rem; opacity: 0.7; }

.mod-timeline { display: grid; gap: var(--space-2xl); }
.mod-timeline__period { position: relative; display: grid; gap: var(--space-md); }
.mod-timeline__head { display: flex; align-items: center; gap: 0.75rem; }
.mod-timeline__dot {
  width: 0.7rem;
  height: 0.7rem;
  border-radius: 50%;
  background: var(--section-accent-ink, var(--color-accent-strong));
  flex: 0 0 auto;
}
.mod-timeline__label {
  font-size: 0.78rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--section-accent-ink, var(--color-accent-strong));
}
/* Pionowa linia łącząca okresy — rysowana pseudo-elementem nagłówka, więc
   nie dokłada elementu do przepływu. */
@container (min-width: 40rem) {
  .mod-timeline__period::before {
    content: "";
    position: absolute;
    left: 0.32rem;
    top: 1.2rem;
    bottom: calc(var(--space-2xl) * -1);
    width: 1px;
    background: var(--card-border);
  }
  .mod-timeline__period:last-child::before { display: none; }
}

/* ============================================================
   ZAREZERWOWANE MIEJSCE BLOKU (27.07.2026) — patrz front.css.
   Ten sam kontrakt tokenów (--section-muted/--section-border), inna typografia,
   bo Nowoczesny ma własną skalę.
   ============================================================ */
.front-awaiting__text {
  margin: 0;
  padding: var(--space-lg) 0;
  color: var(--section-muted);
  font-size: 0.95rem;
  line-height: 1.65;
  text-align: center;
  border-top: 1px solid var(--section-border);
}

/* ---- Strony błędów (30.07.2026, C1 z audytu frontu) ----
   Ten sam widok co w Klasyku (resources/views/errors/partials/parish-body),
   własne klasy modułu. 500/503 nie ładują tego arkusza — mają styl w sobie. */
.front-error { max-width: 44rem; }
.front-error__title { margin: 0 0 0.75rem; font-family: var(--font-display, Georgia, serif); font-size: clamp(1.5rem, 3.4vw, 2.1rem); line-height: 1.2; color: var(--section-heading, var(--color-text)); }
.front-error__body { margin: 0 0 1.5rem; color: var(--section-muted, var(--color-text-muted)); line-height: 1.65; }
.front-error__ways { margin-bottom: 2rem; }
.front-error__more { padding-top: 1.25rem; border-top: 1px solid var(--section-border, var(--color-border)); }
.front-error__more-label { display: block; margin-bottom: 0.6rem; font-size: 0.75rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--section-muted, var(--color-text-muted)); }
.front-error__list { margin: 0; padding: 0; list-style: none; display: flex; flex-wrap: wrap; gap: 0.5rem 1.75rem; }
.front-error__list li { display: flex; align-items: center; min-height: 28px; }

/* Podstawiony tydzień intencji (naprawa C2, 30.07.2026) — jak w Klasyku:
   informacja, nie ostrzeżenie. */
.mod-intentions-fallback { margin: 0 0 1.25rem; padding: 0.75rem 1rem; border-left: 3px solid var(--section-accent, var(--color-accent)); background: var(--section-surface-2, var(--color-surface-muted)); color: var(--section-ink, var(--color-text)); font-size: 0.95rem; line-height: 1.55; }

/* ---- Ogłoszenia: poprzednie wpisy i sąsiedzi (30.07.2026, naprawa H2) ---- */
.mod-section-foot { display: flex; justify-content: flex-end; margin-top: 1.5rem; }
/* Wiersz domykający stronę ogłoszenia — ten sam partial co w Klasyku, klasy
   ostylowane osobno w tym arkuszu (Nowoczesny nie ładuje front.css). Boki są
   zawsze obecne, więc krańce nie zostawiają dziury. */
.front-footnav { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 0.75rem 1.5rem; margin-top: 2rem; padding-top: 1.25rem; border-top: 1px solid var(--section-border, var(--color-border)); }
.front-footnav__side { min-width: 0; }
.front-footnav__side--end { justify-self: end; }
/* Sąsiad jako PRZYCISK (02.08.2026) — wygląd z systemu akcji, tu zostaje sam
   układ dwuwierszowej etykiety. Patrz komentarz w Klasyku. */
.front-footnav__neighbour { min-width: 0; max-width: 100%; text-align: left; }
.front-footnav__text { min-width: 0; display: block; }
.front-footnav__role { display: block; font-size: 0.66rem; letter-spacing: 0.09em; text-transform: uppercase; opacity: 0.8; }
.front-footnav__title { display: block; max-width: 22ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 400; }
.front-footnav__exits { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 0.5rem 0.75rem; }
@media (max-width: 40rem) {
  .front-footnav { grid-template-columns: 1fr 1fr; grid-template-areas: "start end" "exits exits"; }
  .front-footnav__side--start { grid-area: start; }
  .front-footnav__side--end { grid-area: end; }
  .front-footnav__exits { grid-area: exits; justify-content: flex-start; }
  .front-footnav__title { max-width: 14ch; }
}

/* Jak w Klasyku: odnośnik do archiwum przy prawej krawędzi bloku, także po
   zawinięciu w wąskiej kolumnie. */
/* `margin-left: auto` usunięte razem z `space-between` — patrz Klasyk. */

/* Tekst wyłącznie dla czytników ekranu (odpowiednik .front-sr-only z Klasyka).
   Chowamy przez clip-path, NIE przez display:none — element ma zostać w drzewie
   dostępności. Używa go ukryty `h1` strony głównej (naprawa H1, 30.07.2026). */
.mod-sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }

/* Strona „Ewangelia dnia" — te same klasy co Klasyk (widoki różnią się ramą,
   nie wnętrzem), kolory z tokenów tego szablonu. */
.front-gospel-page__day { font-weight: 700; color: var(--section-text); margin: 0 0 var(--space-2xs); }
.front-gospel-page__ref { color: var(--section-muted); margin: 0 0 var(--space-lg); }
.front-gospel-page__player { margin: 0 0 var(--space-xl); }
.front-gospel-page__player audio { width: 100%; max-width: min(100%, 34rem); }
.front-gospel-page__text { max-width: var(--proza-max); font-family: var(--font-serif); font-size: 1.05rem; line-height: 1.75; }
.front-gospel-page__text p { margin: 0 0 var(--space-md); }
.front-gospel-page__note {
  max-width: var(--proza-max);
  padding: var(--space-md) var(--space-lg);
  border-left: 3px solid var(--section-accent, var(--color-accent));
  background: var(--section-surface, var(--color-surface-muted));
  margin: 0 0 var(--space-xl);
}
/* KOMPLET CZYTAŃ (01.08.2026) — ten sam partial co w Klasyku, tutaj w typografii
   Nowoczesnego (proza szeryfowa, tokeny odstępów). */
.front-gospel-readings { max-width: var(--proza-max); }
/* Nagłówek formularza mszy — tylko w dni z dwoma kompletami czytań. */
.front-gospel-readings__mass {
  margin: var(--space-2xl) 0 var(--space-lg);
  padding-top: var(--space-lg);
  border-top: 2px solid var(--color-accent);
  font-family: var(--font-serif);
  font-size: 1.3rem;
  font-weight: 600;
}
.front-gospel-readings__mass:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
.front-gospel-reading + .front-gospel-reading { margin-top: var(--space-xl); padding-top: var(--space-lg); border-top: 1px solid var(--card-border); }
.front-gospel-reading__name {
  margin: 0 0 var(--space-2xs);
  font-size: 0.75rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--section-muted);
  font-weight: 800;
}
.front-gospel-reading__ref { margin: 0 0 var(--space-3xs, 2px); font-weight: 700; }
.front-gospel-reading__intro { margin: 0 0 var(--space-sm); color: var(--section-muted); font-style: italic; }
.front-gospel-reading__response {
  margin: 0 0 var(--space-sm);
  padding-left: var(--space-sm);
  border-left: 3px solid var(--color-accent);
  font-weight: 700;
}
.front-gospel-reading__body { font-family: var(--font-serif); font-size: 1.05rem; line-height: 1.75; }
.front-gospel-reading__body p { margin: 0 0 var(--space-md); }
.front-gospel-reading__body p:last-child { margin-bottom: 0; }

.front-gospel-page__reflection { max-width: var(--proza-max); margin-top: var(--space-xl); padding-top: var(--space-lg); border-top: 1px solid var(--card-border); }
.front-gospel-page__reflection-title { margin: 0 0 var(--space-sm); font-family: var(--font-serif); font-size: 1.3rem; font-weight: 500; }
.front-gospel-page__reflection p { margin: 0; color: var(--section-muted); }
.front-gospel-page__sources { margin-top: var(--space-2xl); padding-top: var(--space-lg); border-top: 1px solid var(--card-border); font-size: 0.875rem; }
.front-gospel-page__sources-title { margin: 0 0 var(--space-sm); font-size: 0.75rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--section-muted); font-weight: 800; }
.front-gospel-page__sources ul { list-style: none; margin: 0 0 var(--space-md); padding: 0; display: flex; flex-wrap: wrap; gap: var(--space-2xs) var(--space-lg); }
.front-gospel-page__sources-role { color: var(--section-muted); }

/* Szukanie w archiwum aktualności — odpowiednik .news-search z Klasyka
   (ten sam mechanizm, oprawa wg tego szablonu). */
.mod-search {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .5rem;
  margin: 0 0 1.5rem;
}
.mod-search__field {
  flex: 1 1 220px;
  min-width: 0;
  padding: .55rem .8rem;
  font: inherit;
  color: var(--color-text);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: 4px;
}
.mod-search__submit {
  flex: 0 0 auto;
  padding: .55rem 1rem;
  font: inherit;
  font-weight: 600;
  color: var(--color-text-inverse, #fff);
  cursor: pointer;
  background: var(--color-primary);
  border: 1px solid transparent;
  border-radius: 4px;
}
.mod-search__clear { flex: 0 0 auto; font-size: .9rem; color: var(--color-text-muted); }
/* ==========================================================================
   PODSTRONA ZAMKNIĘTA KODEM DOSTĘPU
   Ten sam układ co w Klasyku, tokeny Nowoczesnego. Skromnie i na środku —
   to nie jest ekran błędu ani logowania, tylko krótka prośba o kod.
   Widok: front/modern/page-locked.blade.php
   ========================================================================== */
.front-locked__box {
    max-width: 32rem;
    margin: var(--space-lg) auto;
    padding: var(--space-lg);
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: 12px;
    text-align: center;
}

.front-locked__heading { margin: 0 0 .5rem; font-weight: 800; font-size: 1.05rem; color: var(--color-text); }
.front-locked__intro { margin: 0 0 1.25rem; color: var(--color-text-muted); }

.front-locked__form { display: flex; flex-direction: column; align-items: stretch; gap: .6rem; text-align: left; }
.front-locked__label { font-weight: 800; font-size: .85rem; color: var(--color-text); }

.front-locked__input {
    padding: .7rem .85rem;
    font-size: 1rem;
    color: var(--color-text);
    background: var(--color-page);
    border: 1px solid var(--color-border);
    border-radius: 8px;
}

/* Czerwień wpisana wprost, nie z palety: żadna z palet parafii nie ma koloru
   błędu, a komunikat „kod nieprawidłowy" musi być rozpoznawalny niezależnie
   od tego, którą wybrała parafia. */
.front-locked__error { margin: 0; color: #9a2b2b; font-size: .9rem; font-weight: 800; }

.front-locked__submit { align-self: flex-start; margin-top: .25rem; }
.front-locked__help { margin: 1.25rem 0 0; font-size: .85rem; color: var(--color-text-muted); }


/* Pytania i odpowiedzi — ta sama mechanika co w Klasyku (patrz front.css),
   tylko powierzchnie i odstępy z tego szablonu. */
.faq-block { margin-top: 2.5rem; }
.faq-block__heading { font-size: 1.5rem; font-weight: 600; margin-bottom: 1rem; letter-spacing: -0.01em; }
.faq-block__list { display: grid; gap: 0.5rem; }

.faq-item {
  border: 1px solid var(--color-border);
  border-radius: 10px;
  background: var(--color-surface);
}

.faq-item__question {
  padding: 0.9rem 1.1rem;
  font-weight: 600;
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
}

.faq-item__question::-webkit-details-marker { display: none; }

.faq-item__question::before {
  content: '+';
  flex: 0 0 auto;
  font-weight: 400;
  color: var(--color-accent-strong, var(--color-accent));
}

.faq-item[open] > .faq-item__question::before { content: '−'; }
.faq-item__answer { padding: 0 1.1rem 1.1rem; }

/* Zdjęcie główne nad treścią wpisu — odpowiednik .front-post__lead-image
   z Klasyka (ten sam partial, oprawa wg tego szablonu). */
.mod-article__lead-image {
  margin: 0 0 1.5rem;
}
.mod-article__lead-image img {
  display: block;
  width: 100%;
  height: auto;
  max-height: 70vh;
  object-fit: contain;
  background: var(--color-surface-muted, var(--color-surface));
}

/* ==========================================================================
   FORMULARZE PARAFII — te same klasy co w Klasyku (patrz front.css).
   Osobny arkusz, bo szablon Nowoczesny celowo nie ładuje front.css; wygląd
   dopasowany do jego powierzchni, zachowanie identyczne.
   ========================================================================== */
.front-form { margin: 32px 0; padding: 24px 26px; background: var(--color-surface-muted, var(--color-surface)); border: 1px solid var(--color-border); border-radius: 12px; }
.front-form__heading { margin: 0 0 6px; font-size: 1.35rem; }
.front-form__intro { margin: 0 0 18px; color: var(--color-text-muted); }
.front-form__ok { margin: 0 0 16px; padding: 12px 16px; background: var(--color-surface); border-left: 4px solid var(--color-accent-strong, var(--color-accent)); border-radius: 8px; }
.front-form__closed { margin: 0; color: var(--color-text-muted); font-style: italic; }
.front-form__body { display: grid; gap: 18px; }
.front-form__field { display: grid; gap: 6px; }
.front-form__label { font-weight: 700; font-size: 0.9rem; }
.front-form__required { color: var(--color-accent-strong, var(--color-accent)); }
.front-form__control { width: 100%; padding: 11px 13px; font: inherit; color: var(--color-text); background: var(--color-surface); border: 1px solid var(--color-border); border-radius: 8px; }
.front-form__control:focus-visible { outline: 2px solid var(--section-focus, var(--color-accent-strong, var(--color-accent))); outline-offset: 2px; }
.front-form__field.is-invalid .front-form__control { border-color: #a4343a; }
.front-form__help { margin: 0; font-size: 0.85rem; color: var(--color-text-muted); }
.front-form__error { margin: 0; font-size: 0.85rem; color: #a4343a; }
.front-form__error--top { padding: 12px 16px; background: var(--color-surface); border-left: 4px solid #a4343a; border-radius: 8px; }
.front-form__check { display: grid; grid-template-columns: auto 1fr; gap: 10px; align-items: start; cursor: pointer; }
.front-form__check input { margin-top: 4px; }
.front-form__check-text { font-size: 0.9rem; line-height: 1.55; }
.front-form__radios { margin: 0; padding: 0; border: 0; display: grid; gap: 8px; }
.front-form__submit { justify-self: start; }
.front-form__confirm { padding: 16px 20px; background: var(--color-surface-muted, var(--color-surface)); border-left: 4px solid var(--color-accent-strong, var(--color-accent)); border-radius: 8px; }
.front-form__confirm.is-failed { border-left-color: #a4343a; }
.front-form__trap { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* ==========================================================================
   PAS „WYDARZENIA" NA STRONIE GŁÓWNEJ — WŁASNY JĘZYK NOWOCZESNEGO (07.09.2026)

   Do tej pory blok nie miał własnego widoku i spadał na Klasyka: wiersze
   z kartką daty przy lewej krawędzi. Nowoczesny mówi kaflami (Aktualności,
   katalog galerii, karty strony głównej), więc i tu jest siatka kafli.
   Klasy `.event-card*` niżej ZOSTAJĄ — to lista i archiwum modułu, inny widok.

   KOMPLET STANÓW, I NIE SAMYM CIENIEM. Cień jest półprzezroczystą czernią:
   na pasie ciemnym i akcentowym nie widać go w ogóle, więc kafel oparty na nim
   nie reagowałby tam wcale (A19 z rekonesansu). Najechanie niesie tu TRZY
   sygnały naraz — obwódkę, przesunięcie tła kafla i przesunięcie koloru tytułu
   ku barwie nagłówków — wszystkie z tokenów zakresu, więc każdy wariant tła
   dostaje własne wartości. Na pasie ciemnym i akcentowym przesunięcia koloru
   NIE MA (tytuł i tekst są tam z definicji bielą) i to jest stan przyjęty:
   niosą wtedy pozostałe dwa.

   Żaden stan nie zmienia WYMIARÓW — obwódka zostaje tej samej grubości i tylko
   zmienia kolor, cień leży poza pudełkiem. Sąsiednie kafle stoją nieruchomo.
   ========================================================================== */
.event-grid {
  display: grid;
  /* Te same zmienne co siatka Aktualności — kafle rosną do wypełnienia rzędu,
     a niepełny rząd środkuje się razem z resztą pasów strony głównej. */
  --kafel: clamp(220px, 26cqi, 340px);
  --kafel-max: 450px;
  grid-template-columns: repeat(auto-fill, minmax(min(var(--kafel), 100%), 1fr));
  justify-content: var(--kafle-justify, start);
  gap: var(--space-lg);
  margin-top: var(--space-xl);
}
.event-tile {
  position: relative;
  display: flex;
  border: 1px solid var(--card-border);
  border-radius: var(--card-radius);
  background: var(--card-bg);
  transition: background-color var(--motion-state) var(--motion-ease-state),
              border-color var(--motion-state) var(--motion-ease-state),
              box-shadow var(--motion-state) var(--motion-ease-state);
}
.event-tile__link {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  flex: 1 1 auto;
  min-width: 0;
  padding: var(--space-lg);
  color: var(--card-text);
  text-decoration: none;
}
/* KARTKA DATY — plakietka, nie ozdoba: to po nią oko idzie najpierw. Kolory
   z zakresu, więc na ciemnym pasie odwraca się razem z resztą. */
.event-tile__date {
  display: inline-flex;
  align-items: baseline;
  gap: 0.35rem;
  align-self: flex-start;
  padding: 0.3rem 0.6rem;
  border-radius: 999px;
  background: var(--section-accent-soft, var(--color-accent-soft));
  color: var(--card-link);
}
.event-tile__day { font-size: 1.15rem; font-weight: 800; line-height: 1; }
.event-tile__month { font-size: 0.7rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.1em; }
.event-tile__title {
  margin: 0;
  color: var(--card-text);
  font-family: var(--font-serif);
  font-size: 1.18rem;
  font-weight: 500;
  line-height: 1.3;
  transition: color var(--motion-state) var(--motion-ease-state);
}
.event-tile__when { margin: 0; display: flex; flex-wrap: wrap; gap: 0.2rem 0.6rem; color: var(--card-muted); font-size: 0.85rem; }
.event-tile__hour { font-weight: 800; color: var(--card-text); }
.event-tile__cancelled { margin: 0; font-size: 0.85rem; font-weight: 700; color: var(--section-danger, #a4343a); }
.event-tile__facts { list-style: none; margin: auto 0 0; padding: 0; display: grid; gap: 0.2rem; color: var(--card-muted); font-size: 0.85rem; }
.event-tile__fact--signup { color: var(--card-link); font-weight: 800; }
/* Plakietka kategorii — własny odnośnik, poza celem kliknięcia kafla. */
.event-tile__category {
  position: absolute;
  top: var(--space-sm);
  right: var(--space-sm);
  padding: 0.2rem 0.55rem;
  border-radius: 999px;
  background: var(--card-bg-alt);
  color: var(--card-link);
  font-size: 0.62rem;
  font-weight: 900;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
}
.event-tile__category:hover { background: var(--card-link); color: var(--card-bg); }

/* ---- STANY KAFLA ---- */
.event-tile:hover {
  border-color: var(--card-border-hover);
  background: var(--card-bg-hover);
  box-shadow: var(--shadow-card);
}
.event-tile:hover .event-tile__title { color: var(--card-heading); }
/* WCIŚNIĘCIE — jedyny stan działający na dotyku, więc czytelny sam z siebie:
   tło schodzi głębiej, cień znika (kafel wraca na powierzchnię). */
.event-tile:active {
  border-color: var(--card-border-hover);
  background: var(--card-bg-active);
  box-shadow: none;
}
/* Odwołany termin — widoczny, ale wyraźnie inny. */
.event-tile.is-cancelled .event-tile__title { text-decoration: line-through; }
.event-tile.is-cancelled .event-tile__date { opacity: 0.55; }

/* ==========================================================================
   WYDARZENIA — te same klasy co w Klasyku (patrz front.css). Osobny arkusz,
   bo Nowoczesny celowo nie ładuje tamtego; zachowanie identyczne.
   ========================================================================== */
.event-list { display: flex; flex-direction: column; gap: 14px; margin: 20px 0; }
.event-card { position: relative; background: var(--color-surface); border: 1px solid var(--color-border); border-radius: 12px; }
.event-card__link { display: grid; grid-template-columns: auto 1fr auto; gap: 18px; align-items: center; padding: 16px 18px; text-decoration: none; color: inherit; }
.event-card__link:hover { background: var(--color-surface-muted, var(--color-surface)); }
.event-card__link:focus-visible { outline: 2px solid var(--section-focus, var(--color-accent-strong, var(--color-accent))); outline-offset: -2px; }
.event-card__date { display: grid; place-items: center; width: 62px; padding: 8px 0; background: var(--color-surface-muted, var(--color-surface)); border: 1px solid var(--color-border); border-radius: 10px; }
.event-card__day { font-size: 1.5rem; font-weight: 800; line-height: 1; }
.event-card__month { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.1em; color: var(--color-text-muted); }
.event-card__body { min-width: 0; }
.event-card__title { margin: 0 0 4px; font-size: 1.15rem; }
.event-card__when { margin: 0; font-size: 0.88rem; color: var(--color-text-muted); display: flex; flex-wrap: wrap; gap: 10px; }
.event-card__hour { font-weight: 700; color: var(--color-text); }
.event-card__facts { list-style: none; margin: 6px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px 16px; font-size: 0.88rem; color: var(--color-text-muted); }
.event-card__fact--signup { color: var(--color-accent-strong, var(--color-accent)); font-weight: 700; }
.event-card__img { width: 96px; height: 72px; object-fit: cover; border-radius: 10px; }
.event-card__category { position: absolute; top: 12px; right: 14px; padding: 2px 9px; font-size: 0.7rem; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; text-decoration: none; color: var(--color-accent-strong, var(--color-accent)); background: var(--color-surface-muted, var(--color-surface)); border-radius: 999px; }
.event-card.is-cancelled .event-card__title, .event-card.is-cancelled .event-card__date { opacity: .55; }
.event-card.is-cancelled .event-card__title { text-decoration: line-through; }
.event-card__cancelled { margin: 4px 0 0; font-size: 0.88rem; font-weight: 700; color: var(--section-danger, #a4343a); }
.event-list__exit { margin: 20px 0 0; }

.event-page__when { margin: 8px 0 0; font-size: 1rem; font-weight: 700; }
.event-page__repeat { font-weight: 400; color: var(--color-text-muted); }
.event-page__cancelled { margin: 12px 0 0; padding: 12px 16px; background: var(--color-surface-muted, var(--color-surface)); border-left: 4px solid #a4343a; border-radius: 8px; font-weight: 700; }
.event-page__notes { margin: 16px 0; padding: 12px 16px; background: var(--color-surface-muted, var(--color-surface)); border-radius: 8px; }
.event-page__categories { margin: 0 0 8px; display: flex; flex-wrap: wrap; gap: 6px; }

.event-facts { margin: 26px 0; padding: 20px 22px; background: var(--color-surface-muted, var(--color-surface)); border-radius: 12px; }
.event-facts__heading { margin: 0 0 10px; font-size: 1.15rem; }
.event-facts__list { display: grid; grid-template-columns: auto 1fr; gap: 6px 18px; margin: 0; }
.event-facts__list dt { font-weight: 700; color: var(--color-text-muted); }
.event-facts__list dd { margin: 0; }
.event-facts__account { font-variant-numeric: tabular-nums; }

.event-terms { margin: 26px 0; }
.event-terms__heading { margin: 0 0 6px; font-size: 1.15rem; }
.event-terms__rule { margin: 0 0 10px; color: var(--color-text-muted); }
.event-terms__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; }
.event-terms__item { display: flex; gap: 10px; align-items: baseline; padding: 7px 12px; background: var(--color-surface-muted, var(--color-surface)); border-radius: 8px; }
.event-terms__item.is-cancelled .event-terms__when { text-decoration: line-through; opacity: .6; }
.event-terms__badge { font-size: 0.72rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.06em; color: #a4343a; }
.event-terms__toggle { margin-top: 10px; }

@media (max-width: 640px) {
  .event-card__link { grid-template-columns: auto 1fr; }
  .event-card__img { display: none; }
}

/* ==========================================================================
   ARTYKUŁY — te same klasy co w Klasyku (patrz front.css).
   ========================================================================== */
.article-list { margin: 28px 0; }
.article-list__heading { margin: 0 0 12px; font-size: 1.15rem; }
.article-list__items { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.article-list__item { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 14px; padding: 10px 12px; border-bottom: 1px solid var(--section-border, var(--color-border)); }
.article-list__item:last-child { border-bottom: 0; }
.article-list__link { font-size: 1.02rem; text-decoration: none; color: var(--section-link, var(--color-text)); }
.article-list__link:hover { text-decoration: underline; }
.article-list__link:focus-visible { outline: 2px solid var(--section-focus, var(--color-accent-strong, var(--color-accent))); outline-offset: 3px; }
.article-list__item.is-featured .article-list__link { font-weight: 800; }
.article-list__date { font-size: 0.85rem; color: var(--section-muted, var(--color-text-muted)); }
.article-page__back { margin: 20px 0 0; }

/* Klauzula zgody — rozwijany blok pod ptaszkiem (patrz front.css). */
.front-form__consent { margin: 6px 0 0 32px; font-size: 0.82rem; }
.front-form__consent-summary { cursor: pointer; color: var(--color-text-muted); text-decoration: underline; }
.front-form__consent-summary:focus-visible { outline: 2px solid var(--section-focus, var(--color-accent-strong, var(--color-accent))); outline-offset: 2px; }
.front-form__consent-text { margin: 8px 0 0; padding: 12px 14px; color: var(--color-text-muted); line-height: 1.6; background: var(--color-surface); border-radius: 8px; }
