/* Wygenerowano automatycznie: 2026-07-21 22:47:16 */

/* --- File: 1.fonts.css --- */
/* 1. FONTS.CSS - Ładowanie fontów. */

/* Dosis - Regular (400) - Treść główna */
@font-face {
  font-family: 'Dosis';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/dosis-v34-latin_latin-ext-regular.woff2') format('woff2');
}

/* Dosis - SemiBold (600) - Pogrubienia i przyciski */
@font-face {
  font-family: 'Dosis';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('../fonts/dosis-v34-latin_latin-ext-600.woff2') format('woff2');
}

/* Dosis - ExtraBold (800) - Nagłówki */
@font-face {
  font-family: 'Dosis';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url('../fonts/dosis-v34-latin_latin-ext-800.woff2') format('woff2');
}

/* --- File: 2.colors.css --- */
/**
 * 2_colors.css
 * ZYXAK CRM by Paweł Pijanowski dla TONdance Szkoła Tańca w Łodzi
 * 2026-07-19 16:10
 */

/* ==========================================================================
   2. COLORS.CSS - Definicje kolorów (Dark Mode Default & Light Theme)
   Klimat: Szkoła Tańca (Salsa, Bachata, Kizomba) - Zgodne z oryginalnym Logo
   ========================================================================== */

/* ==========================================================================
   JAK KORZYSTAĆ Z MACIERZY KOLORÓW (Primary, Secondary, Success, Error, itd.)
   ==========================================================================
   --color-[nazwa]:           Główne tło elementu (np. żółty przycisk akcji).
   --color-[nazwa]-hover:     Stan po najechaniu myszką na element bazowy (:hover).
   --color-[nazwa]-contrast:  Kolor tekstu/ikony leżącej BEZPOŚREDNIO na elemencie bazowym 
                              (np. czarny tekst na żółtym przycisku zachowuje WCAG).
   --color-[nazwa]-alpha:     Półprzezroczyste tło (15-20%) - idealne pod delikatne alerty, 
                              etykiety (badges) i podświetlenia w menu.
   --color-[nazwa]-text:      Kolor tekstu do czytania na standardowym tle strony 
                              (np. czerwony komunikat błędu pod inputem).
   --color-[nazwa]-muted:     Ciemne/zgaszone obramowanie do delikatnych alertów.
   ========================================================================== 
*/

:root {
    /* =========================================
       DARK MODE (Domyślny - Klubowy Parkiet)
       ========================================= */
    
    /* --- BRAND: PRIMARY (Żółty z logo) --- */
    /* Użycie: Główne przyciski Call-to-Action ("Zapisz się", "Kup karnet"), mocne wyróżnienia. */
    --color-primary: #FFCC00; 
    --color-primary-hover: #FFD633;
    --color-primary-contrast: #000000;
    --color-primary-alpha: rgba(255, 204, 0, 0.15); 
    --color-primary-text: #FFD633; 
    --color-primary-muted: #3E320E; 

    /* --- BRAND: SECONDARY (Klubowa Fuksja - Nocny Vibe) --- */
    /* Użycie: Elementy budujące klimat, przyciski drugorzędne, podświetlenia aktywnych zakładek, efekty glow (cienie pod elementami). */
    --color-secondary: #D946EF; 
    --color-secondary-hover: #E879F9;
    --color-secondary-contrast: #000000;
    --color-secondary-alpha: rgba(217, 70, 239, 0.15);
    --color-secondary-text: #F0ABFC;
    --color-secondary-muted: #3D1244;

    /* --- STATUS: SUCCESS (Zielony z logo) --- */
    /* Użycie: Komunikaty powodzenia ("Zapisano na zajęcia", "Płatność przeszła"), tagi "Aktywny". */
    --color-success: #6BA443; 
    --color-success-hover: #7EBB53; 
    --color-success-contrast: #FFFFFF; 
    --color-success-alpha: rgba(107, 164, 67, 0.15);
    --color-success-text: #95D16A; 
    --color-success-muted: #1A2E0F;

    /* --- STATUS: ERROR (Czerwony z logo) --- */
    /* Użycie: Walidacja formularzy ("Błędne hasło"), przyciski destrukcyjne ("Usuń konto"), tagi "Odrzucono". */
    --color-error: #DB2C29; 
    --color-error-hover: #EF3E3B; 
    --color-error-contrast: #FFFFFF; 
    --color-error-alpha: rgba(219, 44, 41, 0.15);
    --color-error-text: #FF8A88; 
    --color-error-muted: #3D0A08;

    /* --- STATUS: WARNING (Pomarańczowy) --- */
    /* Użycie: Ostrzeżenia nietrafne (np. "Karnet wygasa za 2 dni"), alerty wymagające uwagi. */
    --color-warning: #F59E0B; 
    --color-warning-hover: #FBBF24; 
    --color-warning-contrast: #000000; 
    --color-warning-alpha: rgba(245, 158, 11, 0.15);
    --color-warning-text: #FCD34D; 
    --color-warning-muted: #452902; 

    /* --- STATUS: INFO (Niebieski z logo) --- */
    /* Użycie: Komunikaty neutralne ("Masz 1 nową wiadomość"), paski informacyjne. */
    --color-info: #005A8C; 
    --color-info-hover: #0073B3; 
    --color-info-contrast: #FFFFFF;
    --color-info-alpha: rgba(0, 90, 140, 0.2); 
    --color-info-text: #66BDEB; 
    --color-info-muted: #001C2E;

    /* --- LINKI --- */
    /* Użycie: Standardowe linki w tekście (<a>). Dziedziczą klubową fuksję dla zachowania klimatu. */
    --color-link: #E879F9; 
    --color-link-muted: #3D1244;

    /* --- TŁA (SURFACE ARCHITECTURE) --- */
    /* Głęboka czerń na pasek nawigacji idealnie wyeksponuje oryginalne logo bez ramek */
    --color-bg-nav: #000000; 
	--color-avatar-nav: #FFFFFF; 
    
	--color-bg-table: #161616; /* Kolor tła tabeli */
	--color-bg-table-hover: #14212c; /* Hover wiersza - tło tabeli lekko zabarwione błękitem (--color-info) */
	
    /* Parter: Główna 'podłoga' aplikacji (body). Zgaszona czerń nie męczy oczu przy czytaniu */
    --color-bg-main: #202020; /* #121212; */ 
    
    /* Pierwsze piętro: Tło dla komponentów leżących na stronie (Karty, Panele, Artykuły) */
    --color-bg-surface: #2a2a2a; 
    
    /* Drugie piętro: Elementy 'oderwane' od strony i pływające (Dropdowny, Tooltipy, Modale) */
    --color-bg-surface-alt: #363636; 
    
    /* Zasłona: Półprzezroczysta czerń wrzucana ZA modala, aby przyciemnić aplikację pod spodem */
    --color-bg-overlay: rgba(0, 0, 0, 0.75); 

    /* --- TYPOGRAFIA I IKONY --- */
    /* Base: Jasny, ale nie 100% biały. Do głównych nagłówków (H1-H6) i podstawowych paragrafów. */
    --color-text: #F9FAFB; 
    
    /* Tekst w tabeli (.data-table td): ta sama biel co --color-text, ale przygaszona do 80% - czysta biel na dużych powierzchniach tabeli męczy wzrok. */
    --color-text-table: rgba(249, 250, 251, 0.8); 
    
    /* Dimmed: Tekst drugorzędny. Używaj do podtytułów, okruszków, małych opisów pod polami. */
    --color-text-dimmed: #D1D5DB; 
    
    /* Muted: Najmniej ważny tekst. Używaj do placeholderów w inputach, stopek praw autorskich, stanów disabled. */
    --color-text-muted: #6B7280;
    
    /* Icon: Kolor ikon w menu i interfejsie. Zapobiega "krzyczeniu" ikon na równi z tekstem. */
    --color-icon: #A1A1AA; 

    /* --- INTERAKCJE I LINIE --- */
    /* Border: Cienkie, standardowe linie podziału (tabelki, granice kart, <hr>). */
    --color-border: #3f3f3f;
    
    /* Focus: Ramka aktywacji (Accessibility). Odpala się gdy klikniesz input lub używasz klawisza Tab. Jaskrawy żółty. */
    --color-border-focus: var(--color-primary); 
    
    /* Strong: Wyraźna ramka, np. granica aktywnego inputa na hover, lub wydzielenie głównego sidebaru. */
   --color-border-strong: #595959; 

    /* --- CIENIE --- */
    /* Sm: Delikatny cień dla kart (surface) podnoszący je lekko z tła. */
    --shadow-sm: 0 0.0625em 0.125em 0 rgb(0 0 0 / 0.5);
    
    /* Md: Mocny cień dla elementów pływających (modale, dropdowny), aby wybiły się mocno do przodu. */
    --shadow-md: 0 0.5em 0.375em -0.0625em rgb(0 0 0 / 0.5); 
    
    /* --- KOMPONENTY: INPUT / SELECT --- */
    /* Specyficzne kolory dla formularzy. */
    --color-input-bg: #0c4a6e;
    --color-input-border: #38bdf8;
    --color-input-text: #e0f2fe;

    /* --- WYKRESY (Chart.js) --- */
    /* CELOWO osobne od --color-text-dimmed/--color-border: canvas (bez
       wygładzania czcionek jak w HTML, przy małych 9-12px ticks) potrzebuje
       mocniejszego kontrastu niż zwykły przygaszony tekst UI, żeby opisy
       osi były dobrze czytelne - patrz ChartTheme.resolveColor() w
       02_2_chart-helpers.js. W dark mode wartość identyczna jak dotychczas
       (tu problemu nie było), w light mode - patrz [data-theme="light"]. */
    --color-chart-axis-text: #D1D5DB;
    --color-chart-grid: #3f3f3f;
}

/* =========================================
   LIGHT MODE (Opcjonalny)
   Komentarze strukturalne takie same jak w Dark Mode.
   ========================================= */
[data-theme="light"] {
    
    /* --- BRAND: PRIMARY --- */
    --color-primary: #FFCC00; 
    --color-primary-hover: #E6B800;
    --color-primary-contrast: #000000; 
    --color-primary-alpha: #FEF08A; 
    --color-primary-text: #A16207; 
    --color-primary-muted: #FFF6D4; 

    /* --- BRAND: SECONDARY --- */
    --color-secondary: #C026D3; 
    --color-secondary-hover: #A21CAF;
    --color-secondary-contrast: #FFFFFF; 
    --color-secondary-alpha: #F5D0FE; 
    --color-secondary-text: #86198F;
    --color-secondary-muted: #FDF4FF;
    
    /* --- STATUS: SUCCESS --- */
    --color-success: #6BA443;
    --color-success-hover: #558732;
    --color-success-contrast: #FFFFFF;
    --color-success-alpha: #DCFCE7; 
    --color-success-text: #2A4518; 
    --color-success-muted: #F0FDF4;
    
    /* --- STATUS: ERROR --- */
    --color-error: #DB2C29;
    --color-error-hover: #A81F1E;
    --color-error-contrast: #FFFFFF;
    --color-error-alpha: #FFE4E6;
    --color-error-text: #881337;
    --color-error-muted: #FFF1F2;

    /* --- STATUS: WARNING --- */
    --color-warning: #F59E0B; 
    --color-warning-hover: #D97706; 
    --color-warning-contrast: #FFFFFF; 
    --color-warning-alpha: #FFEDD5;
    --color-warning-text: #92400E; 
    --color-warning-muted: #FFF7ED; 

    /* --- STATUS: INFO --- */
    --color-info: #005A8C; 
    --color-info-hover: #00436B; 
    --color-info-contrast: #FFFFFF;
    --color-info-alpha: #E0F2FE;
    --color-info-text: #002D47; 
    --color-info-muted: #F0F9FF;

    /* --- LINKI --- */
    --color-link: #C026D3;
    --color-link-muted: #FDF4FF;

    /* --- TŁA (SURFACE) --- */
	--color-bg-table: #FFFFFF; /* Kolor tła tabeli */
	--color-bg-table-hover: #E2F0F4; /* Hover wiersza - tło tabeli lekko zabarwione błękitem (--color-info) */
    --color-bg-nav: #FFFFFF; /* Zmień na #000000, jeśli górna belka ma być czarna również w dzień */
    --color-bg-main: #F9FAFB; 
    --color-bg-surface: #FFFFFF; 
    --color-bg-surface-alt: #EFF0F2; 
    --color-bg-overlay: rgba(0, 0, 0, 0.5); 

    /* --- TYPOGRAFIA I IKONY --- */
    --color-text: #18181B; 
    --color-text-table: rgba(24, 24, 27, 0.8); 
    --color-text-dimmed: #52525B; 
    --color-text-muted: #A1A1AA;
	--color-avatar-nav: #FFFFFF;
    --color-icon: #71717A; 

    /* --- INTERAKCJE I LINIE --- */
    --color-border: #E0E0E0;
    --color-border-focus: var(--color-primary);
    --color-border-strong: #A1A1AA; 

    /* --- CIENIE --- */
    --shadow-sm: 0 0.0625em 0.125em 0 rgb(0 0 0 / 0.05);
    --shadow-md: 0 0.5em 0.375em -0.0625em rgb(0 0 0 / 0.1);
    
    /* --- KOMPONENTY: INPUT / SELECT --- */
    --color-input-bg: #e0f2fe;
    --color-input-border: #0284c7;
    --color-input-text: #0369a1;

    /* --- WYKRESY (Chart.js) --- */
    /* Świadomie CIEMNIEJSZE niż --color-text-dimmed (#52525B) - ticks na
       canvasie przy małym rozmiarze fontu (9-12px, Dosis) wypadały słabo
       widoczne na białym tle mimo formalnie poprawnego kontrastu tekstu
       HTML. Zinc-700 daje wyraźnie mocniejszy, "ciężki" odczyt liczb/dat
       na osiach. Siatka (--color-chart-grid) lekko przyciemniona względem
       --color-border (#E0E0E0), żeby linie poziome też nie ginęły. */
    --color-chart-axis-text: #3F3F46;
    --color-chart-grid: #D4D4D8;
}

/* --- File: 3.base.css --- */
/* 3. BASE.CSS - Normalizacja, Reset i Zmienne strukturalne. */

:root {
  /* Definicja modułu bazowego (szerokość kolumny mobile) */
  --module-base: 22.5rem;
}

/* --- NOWA NORMALIZACJA --- */

html {
	box-sizing: border-box;
    /* Zapobiega systemowym gestom nawigacji na poziomie HTML */
    overscroll-behavior: none;
	touch-action: manipulation;
}

*, *:before, *:after {
	box-sizing: inherit;
}

/* ==========================================================================
   UKRYCIE SUWAKÓW (Przewijanie działa kółkiem/dotykiem, ale brak paska)
   ========================================================================== */
* {
    /* Obsługa Firefox */
    scrollbar-width: none; 
    
    /* Obsługa starszych wersji IE / Edge */
    -ms-overflow-style: none; 
}

/* Obsługa Chrome, Safari, Edge, Opera */
*::-webkit-scrollbar {
    display: none; 
}

body {
	margin: 0;
	width: 100vw;
	width: 100dvw;
	overflow: hidden; /* Pamiętaj, aby mieć wewnątrz kontener z overflow-y: auto */

	/* Style globalne aplikacji (fonty i kolory) */
	font-family: 'Dosis', sans-serif;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	font-weight: 400; 
	line-height: 1.6;
    
	/* UJEDNOLICONE ZMIENNE Z SYSTEMU KOLORÓW (2.colors.css) */
	background-color: var(--color-bg-main);
	color: var(--color-text);

    /* Wyłączenie domyślnego zaznaczania tekstu (odkomentuj w docelowej apce) */
    /*-webkit-user-select: none; /* Safari/Chrome */
    /*user-select: none;         /* Standard */

    /* BLOKADA GESTÓW SYSTEMOWYCH */
    overscroll-behavior: none;
    touch-action: pan-y;
}

/* Kolor zaznaczonego tekstu (np. przy kopiowaniu) spójny z systemem kolorów */
::selection {
    background-color: var(--color-primary);
    color: var(--color-primary-contrast);
}

/* Wyjątek dla pól formularzy - tam zaznaczanie i gesty muszą działać domyślnie */
input, textarea, select, [contenteditable] {
    -webkit-user-select: text;
    user-select: text;
    cursor: text;
    touch-action: manipulation; 
}

button, input, optgroup, select, textarea {
    font-family: inherit;
    font-size: 100%;
    line-height: 1.15;
    margin: 0;
}

button, input {
	overflow: hidden;
}

button, select {
	text-transform: none;
}

button, [type="button"], [type="reset"], [type="submit"] {
	-webkit-appearance: button;
}

button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
	border-style: none;
	padding: 0;
}

button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
    outline: 1px dotted ButtonText;
}

h1, h2, h3, h4, h5, h6, p {
	margin: 0;
	font-size: 1rem; /* Pełna kontrola w REM */
	font-weight: 400;
}

b { font-weight: 600; }
strong { font-weight: 800; }
button { font-weight: 600; }

a {
	text-decoration: none;
    color: var(--color-link); /* Spójne z kolorami z 2.colors.css */
    transition: color 0.2s ease;
}

a:hover {
    color: var(--color-primary);
}

img, video, iframe {
    display: block;
    max-width: 100%;
    height: auto;
}

:active {
    -webkit-tap-highlight-color: transparent; 
}

/* Zmodyfikowany reset tylko dla przycisków i inputów (bez globalnego hover z błędem) */
button, input {
    background-color: transparent;
    border: none;
}

/* ==========================================================================
   GLOBALNE ZARZĄDZANIE FOCUS (Zamiast :focus-visible)
   ========================================================================== */

/* Domyślnie TWARDO WYŁĄCZAMY focus dla wszystkich elementów. 
   Zapobiega to "zawieszaniu" się focusa na ekranach dotykowych po kliknięciu. */
*:focus {
    outline: none !important;
}

/* WŁĄCZNIK FOCUS (DOSTĘPNOŚĆ / KLAWIATURA)
   Jeśli w przyszłości będziesz chciał globalnie włączyć focus 
   (np. przy nawigacji tabulatorem), odkomentuj poniższy blok:
*/

/*
*:focus {
    outline: 0.125rem solid var(--color-border-focus) !important;
    outline-offset: 0.125rem !important;
}
*/
/* ========================================================================== */

[data-column] {
	display: flex;
	flex-direction: column;
	position: relative;
}

[data-row] {
	display: flex;
	flex-direction: row;
	position: relative;
    align-items: center;
}

/* ==========================================================================
   NOWOCZESNE EFEKTY SCROLLOWANIA (Scroll-driven Animations CSS)
   ========================================================================== */

/* Definicja animacji - z niczego w delikatny cień z Twojego Themingu */
@keyframes sticky-shadow-appear {
    from { box-shadow: none; }
    to   { box-shadow: var(--shadow-md); }
}

/* UNIWERSALNA KLASA: .sticky-shadow
  Dodaj ją do dowolnego nagłówka (np. <header class="sticky-shadow">), 
  aby przykleił się do góry i rzucał cień, gdy zawartość pod nim jest przewijana.
*/
.sticky-shadow {
    position: sticky;
    top: 0;
    z-index: 50; /* Gwarantuje, że pasek będzie nad scrollowanym tekstem */
    
    /* Natywny CSS Scroll Timeline (standard 2026) */
    animation: sticky-shadow-appear linear both;
    animation-timeline: scroll(nearest block); /* Nasłuchuje najbliższego scrolla */
    animation-range: 0 1.5rem; /* Cień płynnie pojawia się przez pierwsze 1.5rem scrollowania */
}

/* --- NOWOŚĆ: CIEŃ DOLNY --- */
@keyframes sticky-shadow-bottom-appear {
    0%, 95% { box-shadow: var(--shadow-md); }
    100% { box-shadow: none; }
}

/* AUTOMATYCZNY CIEŃ DOLNY DLA PANELI
   Dzięki ::after omijamy potrzebę wklejania pustych divów do HTMLa.
   Zadziała automatycznie na każdym komponencie z klasą .panel
*/
.panel::after {
    content: ''; /* Wymagane dla pseudoelementów */
    position: sticky;
    bottom: 0;
    height: 0;
    width: 100%;
    flex-shrink: 0; /* Zapobiega ewentualnemu ściskaniu we flexboxie */
    z-index: 50;
    pointer-events: none; /* Nie blokuje kliknięć pod spodem */
    
    /* Genialny trik: odwracamy element w osi Y. 
       Dzięki temu gotowy cień z Themingu (skierowany w dół) rzuca cień do GÓRY! */
    transform: scaleY(-1); 
    
    /* Domyślnie brak cienia (gdy nie ma paska przewijania) */
    box-shadow: none; 
    
    animation: sticky-shadow-bottom-appear linear both;
    animation-timeline: scroll(nearest block);
}

/* --- EKRAN BLOKADY (Orientation Lock) --- */
body::after {
    content: "Obróć urządzenie";
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    width: 100dvw;
    height: 100vh;
    height: 100dvh;
    background-color: #000000; /* Twarda czerń do zablokowania tła */
    color: #FFFFFF;
    z-index: 9999;
    
    display: flex; 
    justify-content: center;
    align-items: center;
    
    font-size: 2rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.25rem;
    
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.3s ease;
}

body.orientation-locked::after {
    opacity: 1;
    pointer-events: all;
}

/* --- File: 4.layout.css --- */
:root {	--visible-panels: 1; /* Domyślnie 1 (mobile) */	}
@media (min-width: 45rem)		{ :root { --visible-panels: 2; } }
@media (min-width: 67.5rem) 	{ :root { --visible-panels: 3; } }
@media (min-width: 90rem) 		{ :root { --visible-panels: 4; } }
@media (min-width: 112.5rem) 	{ :root { --visible-panels: 5; } }

:root {
	/* Obliczenia szerokości paneli w zależności od zmiennej --visible-panels (ustawianej w media queries) */
	--w1to2: calc(22.5em * min(var(--visible-panels), 2));
	--w1to3: calc(22.5em * min(var(--visible-panels), 3));
	--w1to4: calc(22.5em * min(var(--visible-panels), 4));
}

/* Klasy szerokości kolumn */
.w-1of6     { display: flex; flex-direction: row; flex-wrap: wrap; min-width: 3.75em;  width: 3.75em;  max-width: 3.75em; }
.w-1of5     { display: flex; flex-direction: row; flex-wrap: wrap; min-width: 4.5em;   width: 4.5em;   max-width: 4.5em; }
.w-1of4     { display: flex; flex-direction: row; flex-wrap: wrap; min-width: 5.625em; width: 5.625em; max-width: 5.625em; }
.w-1of3     { display: flex; flex-direction: row; flex-wrap: wrap; min-width: 7.5em;   width: 7.5em;   max-width: 7.5em; }
.w-1of2     { display: flex; flex-direction: row; flex-wrap: wrap; min-width: 11.25em; width: 11.25em; max-width: 11.25em; }
.w-1        { display: flex; flex-direction: row; flex-wrap: wrap; min-width: 22.5em;  width: 22.5em;  max-width: 22.5em; }
.w-2        { display: flex; flex-direction: row; flex-wrap: wrap; min-width: 45em;    width: 45em;    max-width: 45em; } /* prawdopodobnie do skasowania */

/* Dynamiczne szerokości */
.w-1to2     { display: flex; flex-direction: row; flex-wrap: wrap; min-width: min(var(--w1to2), 100%); width: var(--w1to2); max-width: 100%; }
.w-1to3     { display: flex; flex-direction: row; flex-wrap: wrap; min-width: min(var(--w1to2), 100%); width: var(--w1to3); max-width: 100%; }
.w-1to4     { display: flex; flex-direction: row; flex-wrap: wrap; min-width: min(var(--w1to2), 100%); width: var(--w1to4); max-width: 100%; }

html {
	font-size: calc(100dvw / (var(--visible-panels) * 22.5));
}

body {
	margin: 0; /* Zabezpieczenie przed paskami przewijania */
	width: 100vw; height: 100vh; width: 100dvw; height: 100dvh;
	background-color: var(--color-bg-main);
	color: var(--color-text);
	display: flex;
	flex-direction: column;
	justify-content: space-between;
}

/* ==========================================================================
   NARZĘDZIA I PRZYCISKI
   ========================================================================== */

/* .spin - obracająca się ikona "ładowania" (<iconify-icon icon="mdi:loading"
   class="spin">), używana w wielu miejscach CRM (02_1_table-engine.js,
   07_1_kurs-filters.js, 06_3_lekcje-details.js) - klasa BYŁA już od dawna
   dodawana przez JS, ale nigdzie w CSS nie istniała jej definicja, więc
   ikona się nie kręciła (błąd znaleziony i naprawiony - patrz rozmowa).
   1s/linear/infinite - płynny, stały obrót bez przyspieszeń/zwolnień. */
@keyframes spin {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}

.spin {
    display: inline-block;
    animation: spin 1s linear infinite;
}

.toolButton {
	display: inline-flex; flex-direction: column;
	width: 3.5rem; height: 3.5rem;
	margin: 0.25rem;
	justify-content: center; align-items: center;
	background-color: transparent;
	border: 0.0625rem solid transparent;
	border-radius: 0.5rem;
	cursor: pointer;
	transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
	color: var(--color-text-dimmed);
	fill: var(--color-text-dimmed);
	outline: none;
	gap: 0.2rem;
}

.toolButton iconify-icon, .toolButton svg { font-size: 1.5rem; }
.toolButton div { font-size: 0.7rem; }
nav .toolButton div { text-transform: uppercase; }

.toolButton:not(:disabled):hover {
	background-color: var(--color-bg-surface-alt);
	color: var(--color-text);
	border-color: var(--color-border);
}

.toolButton:active {
	border-color: var(--color-border-focus);
	color: var(--color-text);
	background-color: var(--color-bg-surface);
	box-shadow: 0 0 0 0.125rem var(--color-primary-alpha); 
}

.toolButton:disabled {
	opacity: 0.5;
	cursor: not-allowed;
	pointer-events: none;
	filter: grayscale(100%);
}

.toolButton.active-tool {
	border-color: var(--color-border);
	background-color: var(--color-bg-surface);
	box-shadow: inset 0 0.1rem 0.225rem rgba(0,0,0,0.1); 
}

/* ==========================================================================
   PASKI NAWIGACYJNE
   ========================================================================== */
#topBar {
	width: 100vw; height: 4rem;
	background-color: var(--color-bg-nav);
	border-bottom: 0.0625rem solid var(--color-border);
	flex-shrink: 0;
}
#bottomBar {
	width: 100vw; height: 4rem;
	background-color: var(--color-bg-nav);
	border-top: 0.0625rem solid var(--color-border);
	flex-shrink: 0;
	justify-content: center;
}

#leftButton  { width: 4rem; height: 4rem; margin-left:  0.5rem; }
#rightButton { width: 4rem; height: 4rem; margin-right: 0.5rem; }
#middleMenu  { flex-grow: 1; height: 4rem; background-color: transparent; }

#backButton {
	width: 4rem; height: 4rem;
	background-color: transparent; 
	color: var(--color-icon);
}
#logo {
	display: flex; justify-content: left; align-items: center;
	height: 4rem;
	background-color: transparent;
	margin-left: 0.5rem;
}
#topBar nav {
	display: flex;
	flex-grow: 1;
	height: 4rem;
	background-color: transparent;
	justify-content: center;
}

/* ==========================================================================
   UKRYWANIE ELEMENTÓW W ZALEŻNOŚCI OD KOLUMN
   ========================================================================== */
html:is([data-view-columns='3'], [data-view-columns='4'], [data-view-columns='5']) #leftButton,
html:is([data-view-columns='3'], [data-view-columns='4'], [data-view-columns='5']) #bottomBar {
	display: none;
}

html:is([data-view-columns='2'], [data-view-columns='3'], [data-view-columns='4'], [data-view-columns='5']) #rightButton {
	display: none; 
}

/* ==========================================================================
   MENU I AVATAR
   ========================================================================== */
.app-menu {
	display: flex;
	align-items: center;
	justify-content: center;
	height: 100%;
	/* Kontekst pozycjonowania dla .module-indicator (absolute) poniżej -
	   w widoku mobile (data-view-columns='1') ta reguła jest i tak
	   nadpisywana przez position:absolute z sekcji niżej (dropdown), co
	   również jest poprawnym kontekstem pozycjonowania. */
	position: relative;
}

/* ==========================================================================
   WSKAŹNIK AKTYWNEGO MODUŁU (przesuwająca się kreska pod przyciskiem)
   ========================================================================== */
/* Pozycja (left/width) ustawiana z JS w updateModuleIndicator()
   (1_layout.js), na podstawie getBoundingClientRect() aktualnie aktywnego
   przycisku (.toolButton.module-active) - transition niżej daje płynne
   przesunięcie/zmianę szerokości przy każdym przełączeniu modułu. */
.module-indicator {
	position: absolute;
	bottom: 0;
	left: 0;
	width: 0;
	height: 0.2rem;
	background-color: var(--color-primary);
	border-radius: 9999px 9999px 0 0;
	pointer-events: none; /* Czysto wizualny - nie przechwytuje kliknięć w przyciski pod/nad nim */
	opacity: 0; /* Domyślnie ukryty - brak jeszcze aktywnego modułu (ekran startowy) */
	transition: left 0.25s cubic-bezier(0.4, 0.0, 0.2, 1), width 0.25s cubic-bezier(0.4, 0.0, 0.2, 1), opacity 0.2s ease;
}

/* W widoku mobile .app-menu staje się rozwijanym menu w kolumnie (przyciski
   pełnej szerokości, jeden pod drugim - patrz reguły niżej w tym pliku) -
   podkreślenie "pod przyciskiem" nie ma tam wizualnego sensu, więc wskaźnik
   jest w tym układzie całkowicie ukrywany. */
html[data-view-columns='1'] .module-indicator {
	display: none;
}

#hamburgerButton {
	display: none;
	align-self: center;
	margin-right: 0.5rem;
}

html[data-view-columns='1'] #hamburgerButton {
	display: flex;
}

html[data-view-columns='1'] .app-menu {
	display: none;
	position: absolute;
	top: 4.5rem;
	right: 4.5rem;
	background-color: var(--color-bg-surface-alt);
	border: 1px solid var(--color-border);
	padding: 0.5rem;
	border-radius: 0.5rem;
	z-index: 1000;
	flex-direction: column;
	box-shadow: var(--shadow-md);
	height: auto;
}

html[data-view-columns='1'] .app-menu.open {
	display: flex;
}

html[data-view-columns='1'] .app-menu .toolButton {
	width: 12rem;
	flex-direction: row;
	justify-content: flex-start;
	height: auto;
	padding: 0.8rem 1rem;
	margin: 0.1rem;
}

html[data-view-columns='1'] .app-menu .toolButton iconify-icon,
html[data-view-columns='1'] .app-menu .toolButton svg {
	margin-right: 1rem;
}

html[data-view-columns='1'] nav .toolButton div {
	font-size: 0.9rem;
}

#avatar {
	width: 4rem; height: 4rem;
	background-color: transparent;
	position: relative;
	cursor: pointer;
}

#avatar img {border: 0.125rem solid var(--color-avatar-nav);}

#panelMenu {
	position: absolute;
	display: flex; flex-direction: column;
	align-items: center;
	top: 4.5rem;
	right: 0.8rem;
	background-color: var(--color-bg-surface-alt);
	border: 1px solid var(--color-border);
	padding: 1rem;
	border-radius: 0.5rem;
	z-index: 1000;
	min-width: 10rem;
	box-shadow: var(--shadow-md);
}

#panelMenu.hidden { display: none; }

/* ==========================================================================
   ZASŁONA POD OKNEM USTAWIEŃ (panele / motyw)
   ========================================================================== */
#settingsOverlay {
	display: none;
	position: fixed;
	top: 4rem; /* Zaczyna się pod topBar - belka z logo i awatarem pozostaje odsłonięta */
	left: 0;
	right: 0;
	bottom: 0;
	background-color: rgba(0, 0, 0, 0.45);
	backdrop-filter: blur(0.25rem);
	-webkit-backdrop-filter: blur(0.25rem);
	z-index: 999; /* Pod #panelMenu (z-index 1000), żeby okno ustawień było klikalne */
	transition: opacity 0.2s ease;
}

#settingsOverlay.visible {
	display: block;
}

/* ==========================================================================
   FEEDBACK WIZUALNY PODCZAS DŁUGIEGO PRZYTRZYMANIA WIERSZA (mobile)
   ========================================================================== */
.data-table tr.touch-pressing td {
	background-color: var(--color-primary-alpha) !important;
	transition: background-color 0.15s ease;
}

#panelMenu p {
	width: 100%;
	color: var(--color-text-dimmed);
	margin-bottom: 0.25rem;
}

#panelMenu .select {
	display: inline-flex; gap: 0.5rem; padding: 0.5rem; margin-top: 0;
	background-color: var(--color-bg-main);
	border-radius: 9999px;
	border: solid var(--color-border) 0.125rem;
}

#panelMenu button {
	display: flex; justify-content: center; align-items: center;
	width: 2.5rem; height: 2.5rem;
	font-size: 1.2rem;
	background: var(--color-border);
	color: var(--color-text);
	border: none;
	cursor: pointer;
	border-radius: 50%;
	transition: all 0.2s ease;
}

#panelMenu button:hover {
	background: var(--color-primary-alpha);
	color: var(--color-primary);
}

#panelMenu button.active {
	background: var(--color-primary);
	color: var(--color-primary-contrast);
	font-weight: bold;
	box-shadow: inset 0 0.1rem 0.225rem rgba(0,0,0,0.5);
	cursor: default;
}

/* ==========================================================================
   UKŁAD PANELI GŁÓWNYCH (Wysuwanie na wierzch jako Overlay)
   ========================================================================== */

#mainContainer {
    position: relative;
    overflow: hidden; /* Zapobiega pojawianiu się dolnego paska przewijania podczas wysuwania */
}

#filtersPanel, #detailsView, #detailedViewExtended {
	/* Płynna, naturalna animacja wysuwania */
	transition: transform 0.3s cubic-bezier(0.4, 0.0, 0.2, 1);
	background-color: var(--color-bg-main);
	height: 100%;
	top: 0;
	bottom: 0;
}

/* Ustawienia szerokości grida w zależności od widoku */
html:is([data-view-columns='1'], [data-view-columns='2'], [data-view-columns='3']) #mainGrid { width: 22.5rem; }
html:is([data-view-columns='4'], [data-view-columns='5']) #mainGrid { width: 45rem; }


/* --- PANEL FILTRÓW (Wysuwa się z lewej) --- */
html:is([data-view-columns='1'], [data-view-columns='2']) #filtersPanel {
	position: absolute;
	left: 0; 
	z-index: 100; /* Znajduje się NAD gridem tabeli */
	transform: translateX(-105%); /* Ukryty */
}		
html:is([data-view-columns='3'], [data-view-columns='4'], [data-view-columns='5']) #filtersPanel {
	position: relative;
	z-index: 10;
	transform: translateX(0); /* Zawsze widoczny obok */
}


/* --- PANEL SZCZEGÓŁÓW (Wysuwa się z prawej) --- */
html[data-view-columns='1'] #detailsView {
	position: absolute;
	right: 0;
	z-index: 100; /* Znajduje się NAD gridem tabeli */
	transform: translateX(105%); /* Ukryty */
}
html:is([data-view-columns='2'], [data-view-columns='3'], [data-view-columns='4'], [data-view-columns='5']) #detailsView {
	position: relative;
	z-index: 10;
	transform: translateX(0); /* Zawsze widoczny obok */
}


/* --- PANEL SZCZEGÓŁÓW ROZSZERZONYCH --- */
html:is([data-view-columns='1'], [data-view-columns='2'], [data-view-columns='3'], [data-view-columns='4']) #detailedViewExtended {
	position: absolute;
	right: 0;
	z-index: 100;
	transform: translateX(105%);
}
html[data-view-columns='5'] #detailedViewExtended {
	position: relative;
	z-index: 10;
	transform: translateX(0);
}


/* ==========================================================================
   KLASY AKTYWUJĄCE WYSUNIĘCIE (dodawane dynamicznie przez JS)
   ========================================================================== */
#filtersPanel.open {
	transform: translateX(0) !important;
	box-shadow: 0.5rem 0 2rem rgba(0, 0, 0, 0.4); /* Głęboki cień sugerujący, że to nakładka */
}

#detailsView.open, #detailedViewExtended.open {
	transform: translateX(0) !important;
	box-shadow: -0.5rem 0 2rem rgba(0, 0, 0, 0.4); /* Głęboki cień od prawej strony */
}

.toolButton.panel-on {
    background-color: var(--color-primary, #005A8C) !important;
    color: var(--color-primary-contrast, #ffffff) !important;
    border-color: var(--color-primary, #005A8C) !important;
    box-shadow: inset 0 4px 8px rgba(0,0,0,0.3) !important;
}
.toolButton.panel-on iconify-icon,
.toolButton.panel-on div {
    color: var(--color-primary-contrast, #ffffff) !important;
    fill: var(--color-primary-contrast, #ffffff) !important;
}

/* ==========================================================================
   PANEL SZCZEGÓŁÓW ROZSZERZONYCH - przyciski sterujące
   ========================================================================== */

/* Trzeci slot w dolnym pasku (mobile / 2 kolumny), analogiczny do
   #leftButton / #rightButton. Celowo BEZ osobnej reguły chowającej per
   liczbę kolumn - #bottomBar i tak znika całkowicie od 3 kolumn wzwyż
   (patrz reguła wyżej), więc ten przycisk pokazuje się automatycznie
   dokładnie tam, gdzie ma się pokazywać: przy 1 i 2 kolumnach. */
#extraButton { width: 4rem; height: 4rem; margin-right: 0.5rem; }

/* Przycisk w nagłówku panelu (Rozwiń/Zwiń w Szczegółach, X w panelu
   Więcej, Wyczyść filtry w Filtrach) - dosunięty CAŁKOWICIE do prawej
   krawędzi nagłówka (bez marginesu, konwencja "przycisku zamknięcia
   okna"). DOMYŚLNIE (nadal używane przez nagłówek Filtrów) position:
   absolute - header ma position:relative (inline w index.php) i domyślne
   wyśrodkowanie tytułu przez flex (patrz .panel header w
   7_main-container.css); ponieważ przycisk jest position:absolute, nie
   bierze udziału w tym flexowym centrowaniu, więc tytuł ("Filtry") zostaje
   wyśrodkowany względem CAŁEJ szerokości panelu, a nie tylko wolnej
   przestrzeni obok przycisku.
   Nagłówki Szczegółów i Więcej mają WŁASNY układ (pole tytułu 16,5rem +
   margines 3rem, patrz #detailsViewTitle/#detailedViewExtendedTitle w
   7_main-container.css) - tam przycisk NIE jest position:absolute, tylko
   zwykłym elementem flex zaraz za tytułem (patrz override niżej), bo pole
   tytułu ma już wyliczoną, stałą szerokość i nie potrzebuje już sztuczki
   z wyjęciem przycisku z przepływu flex. */
.panel-header-btn {
	position: absolute;
	right: 0;
	top: 0;
	width: 3rem;
	height: 100%;
	margin: 0;
	border-radius: 0;
}

/* Override DLA Szczegółów i Więcej (patrz komentarz wyżej) - przycisk NIE
   jest już position:absolute, tylko zwykłym, "statycznym" dzieckiem
   .panel-header-btn-slot niżej (wypełnia go całego - te same wymiary
   3rem/100% co dotąd). */
#detailsView .panel-header-btn,
#detailedViewExtended .panel-header-btn {
	position: static;
}

/* .panel-header-btn-slot - TO JEST prawdziwy element flex w nagłówku
   (kolejność w index.php: najpierw <span id="detailsViewTitle">/
   <span id="detailedViewExtendedTitle">, potem ten div), więc ląduje
   dokładnie w polu 3+16,5=19,5rem -> 22,5rem (patrz #detailsViewTitle/
   #detailedViewExtendedTitle w 7_main-container.css). ISTOTNE: rezerwuje
   te 3rem miejsca w nagłówku ZAWSZE, NIEZALEŻNIE od tego, czy przycisk W
   ŚRODKU jest akurat ukryty (patrz html[data-view-columns='5'] niżej w
   tym pliku, gdzie chowany jest sam <button>, NIE ten div) - dzięki temu
   pole tytułu obok nie "skacze"/nie rozciąga się, gdy przycisk znika przy
   szerokim ekranie (5 kolumn). flex-shrink:0 chroni przed ściśnięciem
   przez flexboksa. */
.panel-header-btn-slot {
	width: 3rem;
	height: 100%;
	flex-shrink: 0;
}

/* Przycisk Rozwiń/Zwiń używa JEDNEJ ikony (strzałka w lewo z kreską -
   "wsuwanie" panelu), a stan otwarty/zamknięty sygnalizowany jest przez
   odbicie lustrzane (zamiast podmiany na drugą ikonę - prościej i mniej
   podatne na błędy niż dwa nakładające się elementy). Ta sama klasa jest
   współdzielona przez przycisk w nagłówku Szczegółów i przycisk na dolnym
   pasku (#btnToggleExtendedMobile), żeby zachowanie było spójne wszędzie
   tam, gdzie sterujemy tym panelem. */
.arrow-toggle-btn iconify-icon {
	transition: transform 0.2s ease;
}
.arrow-toggle-btn.panel-on iconify-icon {
	transform: scaleX(-1);
}

/* Panel Rozszerzony jest widoczny na stałe przy 5 kolumnach (patrz
   #detailedViewExtended w sekcji "UKŁAD PANELI GŁÓWNYCH" wyżej) - oba
   przyciski nim sterujące (toggle w nagłówku Szczegółów oraz X w jego
   własnym nagłówku) tracą wtedy sens i są chowane. */
html[data-view-columns='5'] #btnToggleExtended,
html[data-view-columns='5'] #btnCloseExtended {
	display: none;
}

/* --- File: 5.forms.css --- */
/**
 * 5_forms.css
 * ZYXAK CRM by Paweł Pijanowski dla TONdance Szkoła Tańca w Łodzi
 * 2026-07-21 00:00
 */

/* ==========================================================================
   4. FORMS.CSS - Ustawienia UI oraz Formularzy
   Zgodne z systemem Themingu (Colors.css v2)
   ========================================================================== */

/* ======================== */
/* ===      KARTY       === */
/* ======================== */
.card { 
    background-color: var(--color-bg-surface-alt); 
    padding: 1rem; 
    border-radius: 0.75rem; 
    border: 0.0625rem solid var(--color-border); 
    box-shadow: var(--shadow-md); 
    margin-bottom: 1.5rem;
}

.card h3 { 
    color: var(--color-text); 
    margin-bottom: 0.5rem;
}

.card p { 
    color: var(--color-text-dimmed); 
    line-height: 1.5; 
}

.card2 { 
    border-radius: 0.375rem; 
    border: 0.0625rem solid var(--color-border); 
    background: var(--color-bg-surface); 
    padding: 1rem; 
    margin-bottom: 1rem;
}

/* ======================== */
/* ===  FORM LAYOUT     === */
/* ======================== */
/* Nowa klasa ułatwiająca budowę wierszy w formularzach opartych na Flexbox */
.form-row {
    display: flex; 
    flex-wrap: wrap; 
    flex: 1;
    width: 100%; 
    gap: 2rem; 
    padding: 2rem 1rem 0rem 1rem;
    align-items: flex-start; /* ROZWIĄZANIE: Zapobiega rozciąganiu sąsiadujących kolumn w pionie */
}

/* ======================== */
/* ===     BUTTONS      === */
/* ======================== */
.btn {
    display: inline-flex; 
    padding: 0.75rem 1.5rem; 
    border-radius: 0.5rem; 
    font-weight: 800; 
    text-decoration: none; 
    cursor: pointer; 
    border: none; 
    font-size: 0.95rem; 
    text-align: center; 
    transition: all 0.2s ease; 
	align-items: center;
	justify-content: center;
	gap: 0.5rem;
	width: max-content;
}

/* Brakujący dotąd w całym systemie stan disabled - bez tego atrybut
   disabled działał funkcjonalnie (blokował klik), ale wizualnie przycisk
   wyglądał identycznie jak aktywny, myląc operatora co do tego, czy może
   kontynuować. !important świadomie - ma nadpisać KAŻDY wariant koloru
   (.btn-primary/.btn-secondary/.btn-outline i ewentualne kolejne). */
.btn:disabled {
    background-color: var(--color-bg-surface-alt) !important;
    color: var(--color-text-dimmed) !important;
    border-color: var(--color-border) !important;
    cursor: not-allowed;
    opacity: 0.6;
}

.btn-primary { 
    background-color: var(--color-primary); 
    color: var(--color-primary-contrast); 
}

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

.btn-secondary { 
    background-color: var(--color-secondary); 
    color: var(--color-secondary-contrast); 
}

.btn-secondary:hover { 
    background-color: var(--color-secondary-hover); 
}

.btn-outline { 
    background-color: transparent; 
    border: 0.125rem solid var(--color-border); 
    color: var(--color-text); 
}

.btn-outline:hover { 
    border-color: var(--color-text-dimmed); 
    background-color: var(--color-bg-surface-alt); 
}

.btn-gray { 
    background-color: transparent; 
    border: 0.125rem solid var(--color-border); 
    color: var(--color-text-muted); 
}

.btn-gray:hover { 
    border-color: var(--color-border-strong); 
    background-color: var(--color-bg-surface-alt); 
    color: var(--color-text); 
}

.btn-danger { 
    background-color: var(--color-error-alpha); 
    color: var(--color-error-text); 
    border: 0.0625rem solid var(--color-error); 
}

.btn-danger:hover { 
    background-color: var(--color-error); 
    color: var(--color-error-contrast); 
}

/* ======================== */
/* ===  TAGS & ALERTS   === */
/* ======================== */
.tag { 
    display: inline-block; 
    padding: 0.25rem 0.75rem; 
    border-radius: 9999px; 
    font-size: 0.75rem; 
    font-weight: 700; 
    text-transform: uppercase; 
}

.tag-success { background-color: var(--color-success-alpha); color: var(--color-success-text); }
.tag-error { background-color: var(--color-error-alpha); color: var(--color-error-text); }
.tag-info { background-color: var(--color-info-alpha); color: var(--color-info-text); }
.tag-warning { background-color: var(--color-warning-alpha); color: var(--color-warning-text); }
.tag-muted { background-color: var(--color-bg-surface-alt); color: var(--color-text-muted); }

.alert { 
    position: relative; 
    padding: 1rem; 
    border-radius: 0.5rem; 
    margin-bottom: 1rem; 
    font-size: 0.95rem; 
}

/* Narożniki alertu (zastępują dawny gruby border-left) - ten sam pomysł co
   zasieczki na .input-text::after, tylko 4 "łapki" zamiast jednej belki.
   Kolor łapek pochodzi ze zmiennej --alert-accent, nadawanej per wariant
   niżej (dawniej służył do tego border-color). Jedna warstwa gradientu =
   jedno ramię łapki (1rem długości, 0.25rem grubości); 8 warstw = 4 rogi. */
.alert::after {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;
    background-repeat: no-repeat;
    background-image:
        linear-gradient(var(--alert-accent), var(--alert-accent)),
        linear-gradient(var(--alert-accent), var(--alert-accent)),
        linear-gradient(var(--alert-accent), var(--alert-accent)),
        linear-gradient(var(--alert-accent), var(--alert-accent)),
        linear-gradient(var(--alert-accent), var(--alert-accent)),
        linear-gradient(var(--alert-accent), var(--alert-accent)),
        linear-gradient(var(--alert-accent), var(--alert-accent)),
        linear-gradient(var(--alert-accent), var(--alert-accent));
    background-size:
        1rem 0.25rem,
        0.25rem 1rem,
        1rem 0.25rem,
        0.25rem 1rem,
        1rem 0.25rem,
        0.25rem 1rem,
        1rem 0.25rem,
        0.25rem 1rem;
    background-position:
        top left, top left,
        top right, top right,
        bottom right, bottom right,
        bottom left, bottom left;
}

.alert-success { background-color: var(--color-success-alpha); color: var(--color-success-text); --alert-accent: var(--color-success); }
.alert-error { background-color: var(--color-error-alpha); color: var(--color-error-text); --alert-accent: var(--color-error); }
.alert-info { background-color: var(--color-info-alpha); color: var(--color-info-text); --alert-accent: var(--color-info); }	
.alert-warning { background-color: var(--color-warning-alpha); color: var(--color-warning-text); --alert-accent: var(--color-warning); }	

/* ======================== */
/* ===    INPUT TEXT    === */
/* ======================== */
.input-text { 
    position: relative; 
    display: grid;
	flex: 1;
    grid-template-rows: auto 1fr; 
    grid-template-columns: 1fr; 
    height: auto; 
	margin: 0;
    width: calc(100% - 2rem);
}

/* Klasy min-width dla .input-text - DAWNIEJ min-width: 20.5rem był na
   sztywno w bazowej regule powyżej (WSZYSTKIE .input-text w całym CRM);
   teraz trzeba go nadawać jawnie jedną z tych trzech klas. */
.input-3-min { min-width: 13rem; }
.input-2-min { min-width: 9rem; }
.input-1-min { min-width: 20rem; }

.input-text:has(textarea) { 
    position: relative; 
    height: 100%; 
    margin: 1.5rem 1rem 0 1rem; 
}

.input-text input, 
.input-text textarea, 
.input-text select { 
    grid-row: 2; 
    grid-column: 1; 
    resize: vertical; 
    display: block; 
    width: 100%; 
    height: 2.4rem; 
    padding: 0rem 1rem 0.1rem 2.25rem; 
    font-family: 'Dosis', sans-serif; 
    font-weight: 600; 
    font-size: 1.2rem; 
    color: var(--color-text); 
    border: 0.0625rem solid var(--color-border); 
    border-radius: 0 0 0 0; 
    box-sizing: border-box; 
    outline: none; 
    transition: border-color 0.3s, background-color 0.3s; 
	background-color: transparent;
    
    /* Aktywuje natywny ciemny tryb dla systemowych kontrolek (w tym ikony kalendarza) */
    color-scheme: dark; 
}

/* Wymusza jasne kontrolki systemowe, gdy użytkownik przełączy główny motyw na Light */
[data-theme="light"] .input-text input, 
[data-theme="light"] .input-text textarea, 
[data-theme="light"] .input-text select { 
    color-scheme: light; 
}

/* Ukrywamy natywną ikonkę kalendarza/zegara po prawej (dotąd mały,
   wyszarzony znaczek) na rzecz własnej ikonki po lewej (.input-icon - ten
   sam wzorzec co przy zwykłych polach tekstowych, np. "Data urodzenia").
   Pseudoelement ::-webkit-calendar-picker-indicator NIE jest usuwany,
   tylko czyniony niewidocznym i rozciągany na CAŁĄ powierzchnię pola
   (position:absolute + inset:0 + przezroczystość) - to WCIĄŻ ten sam,
   natywny przycisk, tylko niewidzialny i rozciągnięty, więc kliknięcie
   GDZIEKOLWIEK w input nadal otwiera systemowy kalendarz/zegar (popularna,
   sprawdzona technika na silnikach WebKit/Blink). Przycisk "X"
   (.input-clear, z-index: 4 - patrz sekcja niżej w pliku) pozostaje w pełni
   klikalny: żyje jako osobny element DOM z własnym z-index, podczas gdy
   ten pseudoelement jest WEWNĄTRZ inputa bez jawnego z-index, więc w
   miejscu nakładania się obu, ".input-clear" zawsze wygrywa kliknięcie.
   input[type="time"] dopisany świadomie w TYM SAMYM selektorze co
   input[type="date"] (zamiast duplikować regułę) - identyczny efekt dla
   obu typów pól. Druga część tej zmiany (usunięcie konfliktującego
   nadpisania width/height) jest w sekcji "6. FILTER PANEL..." niżej w
   pliku - bez tamtej poprawki reguła stamtąd (deklarowana PÓŹNIEJ w
   kaskadzie) przywróciłaby małą, 1rem ikonkę. UWAGA: działa w
   przeglądarkach opartych na WebKit/Blink (Chrome, Edge) - tak jak reszta
   hacków na ::-webkit-calendar-picker-indicator w tym pliku; Firefox
   renderuje kontrolki daty/czasu inaczej i tej reguły nie honoruje (brak
   regresji - zobaczy tam swój standardowy widget). */
.input-text input[type="date"]::-webkit-calendar-picker-indicator,
.input-text input[type="time"]::-webkit-calendar-picker-indicator {
    position: absolute;
    inset: 0;
    width: auto;
    height: auto;
    margin: 0;
    padding: 0;
    background: transparent;
    color: transparent;
    opacity: 0;
    cursor: pointer;
}

/* Wygląd "placeholdera" dd.mm.rrrr (i gg:mm w polach czasu) - natywne
   segmenty daty/czasu NIE są prawdziwym ::placeholder (ten pseudoelement
   działa tylko dla text/search/url/tel/email/password/textarea - date/time
   są z niego jawnie wykluczone w specyfikacji), więc bez tej reguły
   dziedziczą pogrubienie (font-weight: 600) i kolor (var(--color-text)) z
   ogólnej reguły ".input-text input" wyżej, NIEZALEŻNIE od tego, czy pole
   jest puste czy ma wartość - stąd "dd.mm.rrrr" wygląda tak samo grubo i
   ciemno jak realna, wpisana data. Naprawiamy to PRZEZ JS (CSS - w
   przeciwieństwie do zwykłych inputów tekstowych - nie ma tu żadnego
   sposobu odróżnienia "puste" od "wypełnione"): domyślnie (BRAK klasy)
   pole wygląda jak placeholder - to bezpieczny stan początkowy przy
   pierwszym renderze / przed jakąkolwiek interakcją JS. Klasa
   "date-has-value" jest dodawana/usuwana przez updateDateClearButton()
   (01_1_layout.js) - dokładnie w tych samych miejscach w całej aplikacji,
   gdzie ta funkcja i tak już zarządza widocznością przycisku "X" - i
   przywraca normalny, pogrubiony wygląd wpisanej wartości. */
.input-text input[type="date"],
.input-text input[type="time"] {
    color: var(--color-text-muted);
    font-weight: 400;
}

.input-text input[type="date"].date-has-value,
.input-text input[type="time"].date-has-value {
    color: var(--color-text);
    font-weight: 600;
}

.input-text select { 
    appearance: none; 
    -webkit-appearance: none;  
    cursor: pointer; 
    padding-right: 2.5rem; 
}

/* Usunięcie domyślnego niebieskiego tła selectów na korzyść nowego koloru */
.input-text select option { 
    background-color: var(--color-bg-surface-alt); 
    color: var(--color-text); 
    font-weight: 600; 
    border: none; 
    outline: none; 
}

.input-text input iconify-icon { font-size: 1.5rem; }

.input-text textarea { 
    padding-top: 0.75rem; 
    font-size: 1.2rem; 
    padding-left: 3.2rem; 
    min-height: 6rem; 
    height: 100%; 
}

.input-text textarea::-webkit-resizer { 
    background-color: transparent; 
    background-image: linear-gradient(135deg, transparent 50%, var(--color-border-strong) 50%);
}

.input-text:focus-within textarea::-webkit-resizer { 
    background-image: linear-gradient(135deg, transparent 50%, var(--color-primary) 50%); 
}

.input-text input::placeholder,
.input-text textarea::placeholder { 
    color: var(--color-text-muted); 
    opacity: 1; 
    font-weight: 400; 
}

/* =========================================================
   LOGIKA HOVER I FOCUS DLA INPUTÓW (Wytyczne Zaktualizowane)
   ========================================================= */

/* HOVER: Tylko przyciemnia/rozjaśnia główne ramki i zasieczki */
.input-text:hover input, 
.input-text:hover textarea, 
.input-text:hover select { 
    border-color: var(--color-border-strong);
	background-color: var(--color-bg-table);	
}
.input-text:hover::after {
    border-color: var(--color-border-strong);
}

/* ACTIVE/FOCUS: Główna ramka (góra i boki) przyciemnia/rozjaśnia się (border-strong), zasieczki na żółto! */
.input-text:focus-within input, 
.input-text:focus-within textarea, 
.input-text:focus-within select { 
    border-color: var(--color-border-strong); 
	background-color: var(--color-bg-surface);
}
.input-text:focus-within::after { 
    border-color: var(--color-primary); 
}

/* BŁĄD WALIDACJI: dotyka WYŁĄCZNIE zasieczek i dolnego podkreślenia (::after) -
   główna ramka inputa (góra/boki) zostaje bez zmian, niezależnie od hover/focus. */
.input-text.input-error::after {
    border-color: var(--color-error) !important;
}

/* Ikonka wewnątrz inputa na focus zmienia się na tekstowy kolor */
.input-text:focus-within .input-icon { 
    color: var(--color-text); 
    fill: var(--color-text);
}

/* Pseudoelement budujący "Zasieczki" i dolną grubą ramkę */
.input-text::after { 
    grid-row: 2; 
    grid-column: 1; 
    content: ''; 
    position: absolute; 
    bottom: 0; 
    left: 0; 
    width: 100%; 
    height: 0.375rem; 
    /* Domyślnie zasieczki przejmują standardowy kolor ramki */
    border-left: 0.135rem solid var(--color-border-strong); 
    border-right: 0.135rem solid var(--color-border-strong); 
    border-bottom: 0.135rem solid var(--color-border-strong); 
    border-radius: 0 0 0 0; 
    box-sizing: border-box; 
    pointer-events: none; 
    z-index: 3; 
    transition: border-color 0.3s; 
}

/* ========================================================= */

.input-text .input-icon { 
    grid-row: 2; 
    grid-column: 1; 
    display: flex; 
    justify-content: center; 
    align-items: center; 
    position: absolute; 
    left: 0.35rem; 
    top: 48%; 
    transform: translateY(-50%); 
    width: 1.5rem; 
    height: 1.5rem; 
    fill: var(--color-icon); 
    pointer-events: none; 
    z-index: 2; 
    transition: fill 0.3s, color 0.3s; 
    font-size: 1.5rem; 
    color: var(--color-icon); 
}

.input-text:has(textarea) .input-icon { 
    top: 1.2rem; 
    transform: translateY(-50%); 
}

.input-label { 
    position: static; 
    margin-bottom: 0.5rem; 
    font-size: 0.85rem; 
    text-transform: uppercase; 
    color: var(--color-text-dimmed); 
    font-weight: 600; 
    pointer-events: none; 
    transition: color 0.3s; 
    font-family: 'Dosis', sans-serif; 
    line-height: 1.3; 
}

.input-text .input-clear, 
.input-text .input-action { 
    grid-row: 2; 
    grid-column: 1; 
    display: flex; 
    position: absolute; 
    right: 0.75rem; 
    top: 50%; 
    transform: translateY(-50%); 
    width: 1.5rem; 
    height: 1.5rem; 
    cursor: pointer; 
    color: var(--color-text-muted); 
    z-index: 4; 
    align-items: center; 
    justify-content: center; 
    transition: color 0.2s; 
    font-size: 1.25rem; 
}

.input-text .input-clear { display: none; }

.input-text .input-clear:hover, 
.input-text .input-action:hover { 
    color: var(--color-text); 
}

.input-text .input-clear svg { 
    width: 1.25rem; 
    height: 1.25rem; 
    fill: currentColor; 
}

.input-text:has(textarea) .input-clear { 
    top: 0.75rem; 
    transform: none; 
}

.input-text input:not(:placeholder-shown) ~ .input-clear, 
.input-text textarea:not(:placeholder-shown) ~ .input-clear { 
    display: flex; 
}

.input-text input:not(:placeholder-shown) { 
    padding-right: 2.5rem; 
}

.input-text .select-arrow { 
    grid-row: 2; 
    grid-column: 1; 
    position: absolute; 
    right: 0.75rem; 
    top: 50%; 
    transform: translateY(-50%); 
    color: var(--color-text-muted); 
    pointer-events: none; 
    z-index: 4; 
    display: flex; 
    font-size: 1.5rem; 
}

.input-text.full { 
    width: 100%; 
    min-width: 0; /* Bezpieczne zerowanie min-width dla optymalizacji flexbox */
    margin: 1rem 0 0 0; 
}

/* ======================== */
/* ===   FILE UPLOAD    === */
/* ======================== */
.file-upload-wrapper { 
    margin: 1.5rem 1rem 0 1rem; 
    display: flex; 
    align-items: center; 
    gap: 1rem; 
    width: calc(100% - 2rem); 
}

.file-upload-input { display: none; }

.file-upload-name { 
    font-size: 0.9rem; 
    color: var(--color-text-dimmed); 
    white-space: nowrap; 
    overflow: hidden; 
    text-overflow: ellipsis; 
    flex: 1; 
}

/* ======================== */
/* ===      RADIO       === */
/* ======================== */
.radio-group { 
    display: flex; 
    flex-direction: column; 
    position: relative; 
    width: calc(100% - 2rem); 
    margin: 1.5rem 1rem 0 1rem; 
}

.radio-group .radio-options { 
    display: flex; 
    flex-direction: column; 
    position: relative; 
    margin-top: 0.5rem;
}

.radio-group .radio-main-label { 
    font-size: 0.85rem; 
    font-weight: 600; 
    text-transform: uppercase; 
    color: var(--color-text-dimmed); 
}

.custom-radio-label { 
    display: flex; 
    align-items: flex-start; 
    cursor: pointer; 
    padding: 0.625rem; 
    border-radius: 0.5rem; 
    transition: background-color 0.2s; 
    position: relative; 
    z-index: 1; 
}

.custom-radio-label:not(:last-child)::before { 
    content: ''; 
    position: absolute; 
    left: 1.25rem; 
    top: 1.3125rem; 
    height: 100%; 
    width: 0; 
    border-left: 0.125rem dashed var(--color-border-strong); 
    z-index: 0; 
}

.custom-radio-input { 
    position: absolute; 
    opacity: 0; 
    cursor: pointer; 
    height: 0; 
    width: 0; 
}

.checkmark { 
    position: relative; 
    height: 1.375rem; 
    width: 1.375rem; 
    background-color: var(--color-bg-surface); 
    border: 0.125rem solid var(--color-border-strong); 
    border-radius: 50%; 
    margin-top: 0.13rem; 
    margin-right: 1rem; 
    transition: all 0.3s cubic-bezier(0.4, 0.0, 0.2, 1); 
    flex-shrink: 0; 
    box-sizing: border-box; 
    z-index: 2; 
}

.custom-radio-label:hover .checkmark { 
    background-color: var(--color-bg-surface-alt); 
}

.checkmark::after { 
    content: ""; 
    position: absolute; 
    display: none; 
    top: 50%; 
    left: 50%; 
    transform: translate(-50%, -50%) scale(0); 
    width: 0.625rem; 
    height: 0.625rem; 
    border-radius: 50%; 
    background-color: var(--color-primary); 
    transition: transform 0.2s cubic-bezier(0.4, 0.0, 0.2, 1); 
}

.custom-radio-input:checked ~ .checkmark::after { 
    display: block; 
    animation: popIn 0.3s forwards; 
}

.custom-radio-input:checked ~ .checkmark { 
    border-color: var(--color-text); 
}

.label-text { 
    font-size: 1.125rem; 
    font-weight: 400; 
    color: var(--color-text-dimmed); 
    transition: color 0.3s; 
    line-height: 1.4; 
    display: flex; 
    flex-direction: column; 
    justify-content: center; 
}

.custom-radio-input:checked ~ .label-text { 
    color: var(--color-text); 
    font-weight: 600; 
    text-shadow: 0 0 0.5rem rgba(255, 255, 255, 0.1); 
}

@keyframes popIn { 
    0% { transform: translate(-50%, -50%) scale(0); } 
    70% { transform: translate(-50%, -50%) scale(1.2); } 
    100% { transform: translate(-50%, -50%) scale(1); } 
}

/* ======================== */
/* ===   CHECKBOXES     === */
/* ======================== */
.checkbox-group { 
    display: flex; 
    flex-direction: column; 
    gap: 0.5rem; 
    position: relative; 
    width: calc(100% - 2rem); 
    margin: 1.5rem 1rem 0 1rem; 
}

.custom-checkbox-label { 
    display: flex; 
    align-items: flex-start; 
    cursor: pointer; 
    padding: 0.625rem; 
    border-radius: 0.5rem; 
    transition: background-color 0.2s; 
    position: relative; 
    z-index: 1; 
}

.custom-checkbox-input { 
    position: absolute; 
    opacity: 0; 
    cursor: pointer; 
    height: 0; 
    width: 0; 
}

.checkbox-mark { 
    position: relative; 
    height: 1.25rem; 
    width: 1.25rem; 
    background-color: var(--color-bg-surface); 
    border: 0.125rem solid var(--color-border-strong); 
    border-radius: 0.2rem; 
    margin-top: 0.17rem; 
    margin-right: 1rem; 
    transition: all 0.3s cubic-bezier(0.4, 0.0, 0.2, 1); 
    flex-shrink: 0; 
    box-sizing: border-box; 
    z-index: 2; 
}

.custom-checkbox-label:hover .checkbox-mark { 
    background-color: var(--color-bg-surface-alt); 
}

.checkbox-mark::after { 
    content: ""; 
    position: absolute; 
    display: none; 
    left: 0.4rem; 
    top: -0.1rem; 
    width: 0.4rem; 
    height: 0.9rem; 
    border: solid var(--color-primary); 
    border-width: 0.15rem; 
    border-top: 0;
    border-left: 0;
    transform: rotate(45deg) scale(0); 
    transition: transform 0.2s cubic-bezier(0.4, 0.0, 0.2, 1); 
}

.custom-checkbox-input:checked ~ .checkbox-mark::after { 
    display: block; 
    animation: checkPopIn 0.3s forwards; 
}

.custom-checkbox-input:checked ~ .checkbox-mark { 
    border-color: var(--color-text); 
    background-color: var(--color-bg-surface); 
}

.checkbox-label-text { 
    font-size: 1.125rem; 
    font-weight: 400; 
    color: var(--color-text-dimmed); 
    transition: color 0.3s; 
    line-height: 1.4; 
    display: flex; 
    flex-direction: column; 
    justify-content: center; 
}

.custom-checkbox-input:checked ~ .checkbox-label-text { 
    color: var(--color-text); 
    font-weight: 600; 
    text-shadow: 0 0 0.5rem rgba(255, 255, 255, 0.1); 
}

@keyframes checkPopIn { 
    0% { transform: rotate(45deg) scale(0); } 
    70% { transform: rotate(45deg) scale(1.2); } 
    100% { transform: rotate(45deg) scale(1); } 
}

/* ======================== */
/* ===   PILL SWITCH    === */
/* ======================== */
.pill-switch-group { 
    display: flex; 
    flex-direction: column; 
    gap: 1rem; 
    position: relative; 
    width: calc(100% - 2rem); 
    margin: 1.5rem 1rem 0 1rem; 
}

.pill-switch-label { 
    display: flex; 
    align-items: center; 
    cursor: pointer; 
    gap: 0.75rem; 
    position: relative; 
    z-index: 1; 
}

.pill-switch-input { 
    position: absolute; 
    opacity: 0; 
    width: 0; 
    height: 0; 
}

.pill-track { 
    width: 3rem; 
    height: 1.5rem; 
    background-color: var(--color-bg-surface); 
    border: 0.125rem solid var(--color-text-muted); 
    border-radius: 1rem; 
    position: relative; 
    transition: all 0.3s; 
    flex-shrink: 0; 
    box-sizing: border-box; 
}

.pill-thumb { 
    width: 1.1rem; 
    height: 1.1rem; 
    background-color: var(--color-text-muted); 
    border-radius: 50%; 
    position: absolute; 
    top: 0.08rem; 
    left: 0.15rem; 
    transition: all 0.3s cubic-bezier(0.4, 0.0, 0.2, 1); 
}

.pill-switch-input:checked ~ .pill-track { 
    background-color: var(--color-bg-surface); 
    border-color: var(--color-text); 
}

.pill-switch-input:checked ~ .pill-track .pill-thumb { 
    transform: translateX(1.4rem); 
    background-color: var(--color-primary); 
}

.pill-switch-label:hover .pill-track { 
    border-color: var(--color-text-muted); 
	background-color: var(--color-bg-surface-alt);
}

.pill-switch-input:checked ~ .pill-label-text { 
    color: var(--color-text); 
    font-weight: 600; 
    text-shadow: 0 0 0.5rem rgba(255, 255, 255, 0.1); 
}

.pill-label-text { 
    font-size: 1.125rem; 
    font-weight: 400; 
    color: var(--color-text-dimmed); 
    transition: color 0.3s; 
    line-height: 1.4; 
    display: flex; 
    flex-direction: column; 
    justify-content: center; 
}

/* ======================== */
/* === COMMON DESC TEXT === */
/* ======================== */
.label-desc { 
    font-size: 0.75rem; 
    color: var(--color-text-muted); 
    margin-top: 0.15rem; 
    font-weight: 400; 
    text-shadow: none !important; 
    line-height: 1.3; 
    transition: color 0.3s; 
}

.custom-radio-input:checked ~ .label-text .label-desc, 
.custom-checkbox-input:checked ~ .checkbox-label-text .label-desc, 
.pill-switch-input:checked ~ .pill-label-text .label-desc { 
    color: var(--color-text-dimmed); 
    text-shadow: none !important; 
    font-weight: 400; 
}

/* ======================== */
/* === UNIVERSAL SWITCH === */
/* ======================== */
.switch { 
    position: relative; 
    display: flex;
    flex-direction: column;
    height: auto;
	flex-grow: 1;	
}

.switch-label { 
    position: static; 
    margin-bottom: 0.5rem; 
    font-size: 0.85rem; 
    text-transform: uppercase; 
    color: var(--color-text-dimmed); 
    font-weight: 600; 
    pointer-events: none; 
    transition: color 0.3s; 
    font-family: 'Dosis', sans-serif; 
    display: flex; 
    align-items: center; 
    width: 100%; 
    justify-content: space-between; 
	line-height: 1.3;
}

.switch-options { 
    display: flex; 
    width: 100%; 
    height: 2.5rem; 
    background-color: var(--color-bg-surface); 
    border: 0.0625rem solid var(--color-border); 
    border-radius: 1.375rem; 
    padding: 0.25rem; 
    gap: 0.25rem; 
}

.switch-btn { 
    flex: 1; 
    border: none; 
    background: transparent; 
    padding: 0; 
    border-radius: 1.375rem; 
    cursor: pointer; 
    color: var(--color-text-dimmed); 
    display: flex; 
    justify-content: center; 
    align-items: center; 
    transition: all 0.2s; 
    font-weight: 600; 
    font-size: 1rem; 
}

.switch-btn:hover { 
    color: var(--color-text); 
    background-color: var(--color-bg-surface-alt); 
}

.switch-btn.active { 
    background-color: var(--color-primary); 
    color: var(--color-primary-contrast); 
    box-shadow: var(--shadow-sm); 
    font-weight: 800; 
}

/* Brakujący dotąd stan disabled - !important, żeby wygrał nawet z .active
   (przycisk domyślnie oznaczony jako aktywny "Natychmiast" zostaje z
   klasą .active mimo wyłączenia kanału - patrz krok 5 kreatora wiadomości,
   02_9_message-modal.js). Bez tego przycisk disabled wciąż wyglądałby na
   kolorowy/aktywny mimo realnej blokady kliknięcia. */
.switch-btn:disabled {
    background-color: var(--color-bg-surface-alt) !important;
    color: var(--color-text-dimmed) !important;
    box-shadow: none !important;
    cursor: not-allowed;
    opacity: 0.6;
}

/* ======================== */
/* === SELECTABLE ITEM  === */
/* ======================== */
.selectable-item { 
    user-select: none; 
    cursor: pointer; 
    transition: background-color 0.1s ease, border-left-color 0.1s ease; 
    border-left: 0.25rem solid transparent; 
    min-height: 4rem; 
    padding: 0.5rem 1rem; 
    display: flex; 
    align-items: center;
}

.selectable-item.selected { 
    background-color: var(--color-primary-alpha) !important; 
    border-left-color: var(--color-primary) !important; 
    position: relative; 
}

.selectable-item.selected h4 { 
    color: var(--color-primary-text); 
    font-weight: 600; 
}

/* ======================== */
/* ===   MODAL WINDOW   === */
/* ======================== */
.modal-overlay { 
    position: fixed; 
    top: 0; 
    left: 0; 
    width: 100%; 
    height: 100%; 
    background: var(--color-bg-overlay); 
    backdrop-filter: blur(0.125rem); 
    z-index: 2000; 
    display: none; 
    align-items: center; 
    justify-content: center; 
}

.modal-container { 
    width: 45rem; /* Dokładnie 2 panele (2 x 22.5rem) dla standardowego/szerokiego wyświetlania */
    max-height: calc(100dvh - 2rem); 
    background: var(--color-bg-surface-alt); 
    border-radius: 0.75rem; 
    box-shadow: var(--shadow-md); 
    border: 0.0625rem solid var(--color-border); 
    display: flex; 
    flex-direction: column; 
}

.modal-header { 
    display: flex; 
    width: 100%; 
    height: 4rem; 
    padding: 1rem; 
    border-bottom: 0.0625rem solid var(--color-border); 
    background: var(--color-bg-surface); 
    justify-content: space-between; 
    align-items: center; 
    border-radius: 0.75rem 0.75rem 0 0;
    flex-shrink: 0; 
}

.modal-header h3 { 
    font-weight: 800; 
    text-transform: uppercase; 
    margin: 0; 
    font-size: 1.2rem; 
    color: var(--color-text); 
}

.modal-body { 
    display: flex; 
    flex-direction: column; 
    flex: 1; 
    justify-content: flex-start;
    overflow-y: auto; 
    scrollbar-width: none; /* Ukrywa suwak (Firefox) */
    -ms-overflow-style: none; /* Ukrywa suwak (IE i Edge) */
}

/* Ukrywa suwak (Chrome, Safari, nowszy Edge) */
.modal-body::-webkit-scrollbar {
    display: none;
}

/* Utrzymane dla starszych formularzy, gdyby były dzielone na dwie twarde kolumny */
.modal-column-left, 
.modal-column-right { 
    display: flex; 
    flex-direction: column; 
    width: 22.5rem; 
    padding: 0 1rem 2rem 1rem; 
    overflow-y: auto; 
    min-height: 0; 
    scrollbar-width: none; /* Ukrywa suwak (Firefox) */
    -ms-overflow-style: none; /* Ukrywa suwak (IE/Edge) */
}

/* Ukrywa suwak (Chrome, Safari, nowszy Edge) dla kolumn */
.modal-column-left::-webkit-scrollbar, 
.modal-column-right::-webkit-scrollbar {
    display: none;
}

.modal-column-right { 
    border-left: solid 0.0625rem var(--color-border); 
}

.modal-footer { 
    display: flex; 
    flex-direction: row; 
    justify-content: flex-end; 
    width: 100%; 
    min-height: 6rem; 
    gap: 1rem; 
    padding: 1.5rem; 
    border-top: 0.0625rem solid var(--color-border); 
    background: var(--color-bg-surface); 
    border-radius: 0 0 0.75rem 0.75rem; 
    flex-shrink: 0; 
}

.modal-footer .btn { 
    display: flex; 
    justify-content: center; 
    align-items: center; 
    text-transform: uppercase; 
    letter-spacing: 0.05rem; 
    font-size: 0.85rem; 
    font-weight: 800; 
}

/* ==========================================================================
   Responsywność Modala (Z zachowanym delikatnym marginesowaniem / skalowaniem)
   ========================================================================== */

/* Dla 2 kolumn (np. tablety, 45rem - 67.49rem) - delikatne skalowanie by 45-remowy modal nie dotykał krawędzi okna */
html[data-view-columns='2'] .modal-container { 
    transform: scale(0.898); 
    transform-origin: center center; 
}

/* Dla 1 kolumny (mobile, do 44.99rem) - modal ma 1 panel (22.5rem) i również jest lekko pomniejszony dla zachowania marginesu */
html[data-view-columns='1'] .modal-container { 
    width: 22.5rem !important; 
    height: auto; 
    max-height: 95dvh; 
    transform: scale(0.878) !important;
    transform-origin: center center;
}

/* Dopasowanie struktury wewnętrznej dla 1 kolumny (dla modalów mających twardy podział lewo/prawo) */
html[data-view-columns='1'] .modal-column-left, 
html[data-view-columns='1'] .modal-column-right { 
    width: 100% !important; 
    border-right: none !important; 
    border-bottom: 0.0625rem solid var(--color-border); 
    padding-bottom: 1rem; 
    margin-bottom: 1rem; 
}

html[data-view-columns='1'] .modal-column-right { 
    border-bottom: none; 
    margin-bottom: 0; 
    padding-bottom: 0; 
    border-left: none;
}

/* ==========================================================================
   5. OPTIMIZATIONS & UTILITIES (Dla formularza użytkowników)
   ========================================================================== */

/* Struktura kolumnowa formularza zastępująca inline flex */
.form-col {
    display: flex;
    flex-direction: column;
	align-items: center;
    flex: 1;
    /*gap: 1.5rem;*/
    min-width: 15rem;
}

/* Wariant .form-col z mniejszym min-width - dwie takie kolumny (+ gap
   1.5rem odziedziczony z .form-row) mieszczą się ZAWSZE obok siebie w
   jednym rzędzie, nawet w wąskim modalu (1 moduł = 22.5rem, po odjęciu
   paddingu .form-row zostaje 20.5rem: 9.5 + 1.5 + 9.5 = 20.5rem dokładnie).
   Użycie: para pól, które mają być stale "pół na pół" w jednym module
   (np. Typ zajęć/Styl, Poziom/Podpoziom, Data rozpoczęcia/zakończenia w
   module Kursy) - w przeciwieństwie do .form-col (min-width: 15rem), która
   przy wąskim modalu przechodzi pod siebie (np. Instruktor 1/Instruktor 2). */
.form-col-half {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-width: 9.5rem;
}

/* Wiersz kodu pocztowego i miasta zastępujący inline styles */
.zip-city-row {
    display: flex;
    gap: 1rem;
    margin: 0;
    flex: 1;
    min-width: 20.5rem;
}
.zip-city-row .input-text {
    margin: 0;
}
.zip-city-row .input-text:first-child {
    min-width: 7.5rem; 
    flex: 1;
}
.zip-city-row .input-text:last-child {
    min-width: 12rem;
    flex: 2;
}

/* Klasy pomocnicze i rozszerzenia dla switchy ról oraz płci */
.switch.full-width {
    margin: 0;
    width: 100%;
}

.switch-options.wrap {
    flex-wrap: wrap;
    height: auto;
    padding: 0.25rem;
    margin: 0.0625rem;
}

/* Ostre narożniki kontenera dla pól wielokrotnego wyboru (np. Role) */
.switch-options.wrap.sharp-corners {
    border-radius: 0.25rem;
}

/* Mocno zaokrąglone narożniki kontenera dla pól jednokrotnego wyboru (np. Transport) */
.switch-options.wrap.rounded-corners {
    border-radius: 1.375rem;
}

.switch-options.wrap .switch-btn {
    flex: 1 1 6rem;
    padding: 0.4rem 0.1rem;
    border-radius: 1.375rem; /* Zmiana: Przyciski są zaokrąglone mocno (jak Status), niezależnie od kontenera */
}

/* Specyficzne poprawki dla przesyłania avatara i specyficznych pól */
.input-text input[type="file"] {
    padding-top: 0.35rem;
    padding-left: 2.25rem;
    font-size: 0.85rem;
}

.input-text-avatar-preview {
    width: 2.25rem;
    height: 2.25rem;
    border-radius: 50%;
    object-fit: cover;
    position: absolute;
    right: 0.5rem;
    top: 50%;
    transform: translateY(-50%);
    border: 2px solid var(--color-primary);
    pointer-events: none;
    background: var(--color-bg-surface-alt);
}

.input-text-zip input {
    padding-left: 0.5rem;
    text-align: center;
}

/* Małe alerty */
.alert-sm {
    margin-bottom: 1rem;
    font-size: 0.8rem;
    width: calc(100% - 2rem);
}

/* Czerwona gwiazdka wymaganego pola */
.required-star {
    font-size: 0.7rem;
    color: var(--color-warning);
}

/* Klasy pomocnicze (Utilities) */
.w-full { width: 100% !important; }
.h-full { height: 100% !important; }
.m-0 { margin: 0 !important; }
.max-w-sm { max-width: 20.5rem !important; }


/* ==========================================================================
   6. FILTER PANEL & ADDITIONAL COMPONENT UTILITIES (Refaktoryzacja)
   ========================================================================== */

/* Sekcje filtrów */
.filter-section {
    margin-top: 2.5rem;
    padding-top: 1.5rem;
    border-top: 1px solid var(--color-border);
}

.filter-section-title {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.95rem;
    font-weight: 800;
    color: var(--color-primary);
    text-transform: uppercase;
    letter-spacing: 0.05rem;
}

.filter-section-title iconify-icon {
    font-size: 1.25rem;
}

/* Poziomy Tańca - wiersze i etykiety */
.filter-level-row {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0.75rem;
}

.filter-level-row input { padding-left: 0rem;}

.filter-level-label {
    width: 5.5rem;
    flex-shrink: 0;
    font-size: 0.8rem;
    font-weight: 800;
    color: var(--color-text-dimmed);
    text-transform: uppercase;
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 0.2rem;
    transition: color 0.2s;
}

.filter-level-label:hover {
    color: var(--color-primary);
}

.filter-level-label iconify-icon {
    opacity: 0.6;
    font-size: 1rem;
}

.filter-separator {
    color: var(--color-text-muted);
}

/* Inputy filtrów */
.filter-input-wrapper {
    flex: 1;
    min-width: 0;
    margin: 0;
}

/* Wypełnione pole - tło takie samo jak przy hover (var(--color-bg-table),
   ta sama zmienna co w regule ".input-text:hover input" wyżej w pliku),
   niezależnie od tego, czy pole jest akurat zaznaczone/aktywne. Reguła
   ŚWIADOMIE OGÓLNA (bez gate'owania przez [data-filter-name]) - dotyczy
   WSZYSTKICH pól .input-text w całym CRM (filtry ORAZ formularze), na
   wyraźne życzenie: "tak jak w filtrach" ma teraz obowiązywać wszędzie,
   nie tylko tam. Specyficzność selektora (3x :not()) celowo WYŻSZA niż
   ".input-text:focus-within input" wyżej w pliku, więc wypełnione pole
   zachowuje to tło również gdy jest akurat aktywne/focus - dokładnie tak,
   jak dotąd działało w filtrach. Bez pól date/time (patrz reguła niżej -
   tam :placeholder-shown nie działa wiarygodnie) i bez <select> (na
   wyraźne życzenie - "tak jak w filtrach", które celowo pomijają select). */
.input-text input:not([type="date"]):not([type="time"]):not(:placeholder-shown),
.input-text textarea:not(:placeholder-shown) {
    background-color: var(--color-bg-table);
}

/* <select> - :placeholder-shown nie istnieje dla tego elementu, więc
   "wypełnione" wykrywane jest inaczej: przez :has() sprawdzające, czy
   AKTUALNIE zaznaczona <option> to NIE ta z value="" (pusta opcja
   placeholder - "-- Wybierz --" przy pojedynczej edycji/nowym rekordzie,
   "-- Bez zmian --" przy edycji masowej - oba warianty w buildSelectOptions()
   konsekwentnie używają value="" dla tej pozycji w CAŁYM CRM). Specyficzność
   selektora (atrybut + pseudo-klasa :checked wewnątrz :has()) celowo WYŻSZA
   niż ".input-text:focus-within select" wyżej w pliku, z tego samego powodu
   co przy input/textarea wyżej - wypełniony select zachowuje to tło też
   podczas aktywnej interakcji (otwarty dropdown/focus). */
.input-text select:not(:has(option[value=""]:checked)) {
    background-color: var(--color-bg-table);
}

/* Pola date/time: :placeholder-shown nie działa tu wiarygodnie (patrz
   komentarz przy .date-has-value w sekcji "INPUT TEXT" wyżej w pliku) -
   detekcja "ma wartość" idzie przez klasę .date-has-value, dodawaną/
   usuwaną przez updateDateClearButton() (01_1_layout.js) - WSZĘDZIE tam,
   gdzie pole date/time w ogóle wywołuje tę funkcję na onchange (filtry
   ORAZ formularze, np. kurs_data_start/kurs_data_end w 07_4_kurs-form.js) -
   stąd reguła też ŚWIADOMIE OGÓLNA, bez gate'owania przez [data-filter-name]. */
.input-text input[type="date"].date-has-value,
.input-text input[type="time"].date-has-value {
    background-color: var(--color-bg-table);
}

.filter-input-number {
    padding-left: 0.5rem;
    padding-right: 2rem;
    font-size: 1.2rem;
    text-align: center;
    min-width: 0;
    width: 100%;
}

/* Ta sama poprawka specyficzności co przy .filter-input-date - bez tego
   ogólna reguła ".input-text input" (padding-left: 2.25rem) wygrywa i
   zostaje martwy odstęp z lewej. */
.input-text input.filter-input-number {
    padding-left: 0.5rem;
}

.filter-input-date {
    padding-left: 2rem;
    padding-right: 0.5rem;
    font-size: 1.2rem;
    min-width: 0;
    width: 100%;
}

/* Wyższa specyficzność (.input-text input.filter-input-date) potrzebna,
   żeby faktycznie wygrać z ogólną regułą ".input-text input" - ujednolicone
   do 2rem (patrz też uwaga w komentarzu pod regułą :has() niżej - dotąd
   pola BEZ ikonki miały tu węższe 0.5rem, ale w praktyce każde pole
   filter-input-date w aplikacji ma już własną ikonkę po lewej, więc to
   rozróżnienie przestało mieć zastosowanie). */
.input-text input.filter-input-date {
    padding-left: 2rem;
}

/* Pola filter-input-date, które MAJĄ własną ikonkę po lewej (np. "Zakres:
   Od/Do" w filtrach Lekcji, Kursów i Kursantów) - ten sam odstęp 2rem co
   reguła wyżej, żeby cała rodzina pól filter-input-date była spójna
   niezależnie od tego, czy selektor :has(.input-icon) akurat pasuje.
   Selektor :has(.input-icon) i tak zostaje (wyższa specyficzność - 3
   klasy/pseudoklasy + tag vs. 2 klasy + tag) na wypadek, gdyby w
   przyszłości pojawiło się pole filter-input-date bez ikonki i wymagało
   innej wartości - wtedy wystarczy zmienić TYLKO regułę wyżej. */
.input-text:has(.input-icon) input.filter-input-date {
    padding-left: 2rem;
}

/* Padding-left dla WSZYSTKICH pól input[type="date"] w całej aplikacji
   (nie tylko filtrów) - 2rem, jednolity odstęp pod ikonkę z lewej (np.
   "Konkretny dzień"/"Data startu kursu" w filtrach, "Data urodzenia" w
   formularzach). Selektor z atrybutem [type="date"] ma wyższą specyficzność
   niż ogólna reguła ".input-text input" (2.25rem), więc wygrywa niezależnie
   od kolejności w kaskadzie. */
.input-text input[type="date"] {
    padding-left: 2rem;
}

/* Prawa strona (padding + pozycja X) - WSPÓLNE dla wszystkich pól daty
   ORAZ CZASU w całej aplikacji, nie tylko w filtrach. input[type="time"]
   dopisany świadomie w tych samych selektorach co input[type="date"]
   (zamiast duplikować regułę). Sam wygląd/rozciągnięcie natywnego
   ::-webkit-calendar-picker-indicator (niewidoczny, na całą powierzchnię
   pola) jest ustawiony WYŁĄCZNIE w sekcji "INPUT TEXT" wyżej w pliku -
   celowo NIE nadpisujemy tu już jego width/height (to nadpisywało
   1rem/1rem i cofało poprzednią zmianę, bo ta reguła jest w kaskadzie
   PÓŹNIEJ). padding-right zostaje zarezerwowany pod przycisk "X" (patrz
   input-clear niżej), mimo że natywna ikonka nie jest już widoczna. */
.input-text input[type="date"],
.input-text input[type="time"] {
    padding-right: 2.05rem;
}

.input-text input[type="date"] ~ .input-clear,
.input-text input[type="time"] ~ .input-clear {
    right: 0.4rem;
}

/* Grupowanie filtrów (zastępuje inline margins) */
.filter-group {
    width: 100%;
    margin: 1.5rem 0 0 0;
}

.filter-group-label {
    margin-bottom: 0.5rem;
    font-size: 0.85rem;
    text-transform: uppercase;
    color: var(--color-text-dimmed);
    font-weight: 600;
}

.filter-row-flex {
    display: flex;
    gap: 0.5rem;
    margin-top: 1.5rem;
    width: 100%;
}

/* Style przycisków w zawiniętych opcjach switch-options (np. Role, Transport) */
.switch-btn.wrap-btn-33 {
    flex: 1 1 calc(33.333% - 0.5rem);
    padding: 0.5rem 0.2rem;
    font-size: 0.8rem;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.2rem;
    border-radius: 0.375rem; /* nadpisuje zaokrąglenie typu "pill" ze standardowego .switch-btn */
}

.switch-btn.wrap-btn-33 iconify-icon {
    font-size: 1.15rem;
}

/* --- Utilities dla form.js (roles checkboxes) --- */
.form-row-roles {
    padding: 0;
    gap: 0.5rem;
    justify-content: center;
}

.checkbox-mark-roles {
    margin-right: 0.5rem;
    margin-top: 0.05rem;
}

.text-sm {
    font-size: 0.95rem;
}

.flex-center-gap-sm {
    display: flex;
    align-items: center;
    gap: 0.35rem;
}

/* Marginesy Utilities */
.mt-6 { margin-top: 1.5rem !important; }
.mt-10 { margin-top: 2.5rem !important; }
.mb-4 { margin-bottom: 1.5rem !important; }


/* ==========================================================================
   7. WYSZUKIWARKA POWIĄZANEGO REKORDU (np. "Powiązane konto Kursanta"
   w module Instruktorzy) - input tekstowy z podpowiedziami w dropdownie.
   ========================================================================== */
.user-search-select {
    position: relative;
}

.user-search-dropdown {
    position: absolute;
    top: 100%;
    left: 0;
    width: 100%;
    margin: 0;
    padding: 0.25rem 0.25rem 0 0.25rem;
    background: var(--color-bg-surface-alt);
    border: 0.0625rem solid var(--color-border);
    border-radius: 0.5rem;
    border-top-left-radius: 0;
    border-top-right-radius: 0;
    box-shadow: var(--shadow-md);
    max-height: 16rem;
    overflow-y: auto;
    z-index: 50;
}

.user-search-item {
    padding: 0.6rem 0.9rem;
    cursor: pointer;
    border-bottom: 0.0625rem solid var(--color-border);
    transition: background-color 0.15s ease;
}

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

.user-search-item:hover {
    background-color: var(--color-bg-surface);
}

/* ==========================================================================
   MARKDOWN EDITOR (.md-editor) - patrz 02_8_markdown-editor.js
   Kolumny (.modal-column-left/.modal-column-right) i mechanizm 1<->2
   dziedziczone 1:1 z reguł powyżej w tym pliku - te nowe reguły dotyczą
   WYŁĄCZNIE dodatkowego togglera Edytuj/Podgląd na wąskim widoku.
   ========================================================================== */

.md-editor {
    display: flex;
    flex-direction: column;
    width: 100%;
    max-height: 100%;
    overflow: hidden;
}

.md-editor-columns {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    width: 100%;
    justify-content: space-between;
}

/* Niezależna od .modal-column-left/.modal-column-right (patrz komentarz w
   02_8_markdown-editor.js) - własne, kompletne właściwości kolumny, żeby
   komponent nie zależał od stylów przypiętych do innego typu modala. */
.md-editor-col {
    display: flex;
    flex-direction: column;
    width: 20.5rem;
    overflow-y: auto;
    min-height: 0;
    scrollbar-width: none; /* Firefox */
    -ms-overflow-style: none; /* IE/Edge */
}

.md-editor-col::-webkit-scrollbar {
    display: none; /* Chrome, Safari, nowszy Edge */
}

/* Toggle "Edytuj/Podgląd" - niewidoczny na szerokim widoku (tam obie
   kolumny i tak stoją obok siebie, przełącznik byłby zbędny). Sam
   przełącznik to zwykły .switch/.switch-btn (patrz 07_4_kurs-form.js,
   np. Status techniczny) - żadnych własnych reguł wizualnych tutaj poza
   widocznością całego wrappera. */
.md-editor-mobile-toggle {
    display: none;
}

html[data-view-columns='1'] .md-editor-mobile-toggle {
    display: flex;
    margin-bottom: 0.5rem;
}

/* Efekt WYŁĄCZNIE pod wąskim widokiem - na szerszych ta klasa (dodawana/
   usuwana przez MarkdownEditor.init() niezależnie od szerokości ekranu)
   celowo nie ma żadnego działania, obie kolumny zostają widoczne obok
   siebie tak jak wszędzie indziej w systemie. */
html[data-view-columns='1'] .md-editor-col-hidden-mobile {
    display: none !important;
}

.md-editor-preview {
    padding: 0.5rem 0;
    overflow-y: auto;
}

/* Pusty podgląd (przed pierwszym wpisaniem treści) nie powinien wyglądać
   jak błąd - delikatny placeholder tekstowy zamiast pustego prostokąta. */
.md-editor-preview:empty::before {
    content: 'Podgląd pojawi się tutaj, gdy zaczniesz pisać.';
    color: var(--color-text-dimmed);
    font-style: italic;
    font-size: 0.85rem;
}

/* ==========================================================================
   KREATOR WIADOMOŚCI (.wiz-*) - patrz 02_9_message-modal.js
   Listy radio/checkbox specyficzne dla kreatora (kategoria/szablon w kroku
   1, kandydaci kurs/event w kroku 4) - nie było w systemie gotowego
   komponentu "przewijana lista radiową", stąd nowe, wąskie klasy.
   ========================================================================== */

.wiz-radio-list {
    display: flex;
    flex-direction: column;
    max-height: 14rem;
    overflow-y: auto;
    border: 0.0625rem solid var(--color-border);
    border-radius: 0.5rem;
    background: var(--color-bg-surface);
}

.wiz-kandydat-list {
    display: flex;
    flex-direction: column;
    overflow-y: auto;
    border: 0.0625rem solid var(--color-border);
    border-radius: 0.5rem;
    background: var(--color-bg-surface);
}

.wiz-radio-item,
.wiz-kandydat-item {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.6rem 0.75rem;
    border-bottom: 0.0625rem solid var(--color-border);
    cursor: pointer;
    font-size: 0.9rem;
    color: var(--color-text);
    transition: background-color 0.15s;
}

.wiz-radio-item:last-child,
.wiz-kandydat-item:last-child {
    border-bottom: none;
}

.wiz-radio-item:hover,
.wiz-kandydat-item:hover {
    background-color: var(--color-bg-surface-alt);
}

.wiz-radio-item input[type="radio"],
.wiz-kandydat-item input[type="radio"] {
    flex-shrink: 0;
    accent-color: var(--color-primary);
}

.wiz-radio-empty {
    padding: 0.75rem;
    font-size: 0.85rem;
    color: var(--color-text-dimmed);
    font-style: italic;
}

.wiz-checkbox-line {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.9rem;
    color: var(--color-text);
    cursor: pointer;
}

.wiz-checkbox-line input[type="checkbox"] {
    accent-color: var(--color-primary);
    width: 1.1rem;
    height: 1.1rem;
    flex-shrink: 0;
}

/* Wrapper strukturalny treści kroku kreatora - bez paddingu (usunięty na
   życzenie), modal-body i ten wrapper są teraz oba bez odstępu od
   krawędzi; odstęp, jeśli potrzebny, ma żyć w treści poszczególnych
   kroków (np. .form-row ma już własny padding). */
.wiz-step-inner {
    padding: 0;
}

/* Pasek szybkich emotikon (krok 2 kreatora wiadomości - temat/treść
   e-maila) - patrz insertEmojiAtCursor() w 02_9_message-modal.js. */
.wiz-emoji-bar {
    display: flex;
    flex-wrap: wrap;
    width: 100%;
}

.wiz-emoji-btn {
    font-size: 1rem;
    line-height: 1;
    padding: 0.4rem 0.6rem;
    border: none;
    border-radius: 0.5rem;
    background: transparent;
    cursor: pointer;
    transition: background-color 0.15s, transform 0.1s;
}

.wiz-emoji-btn:hover {
    background-color: var(--color-bg-surface-alt);
    transform: scale(1.15);
}

/* Licznik znaków SMS-a w prawym dolnym rogu textarea (krok 3 kreatora) -
   .input-text ma już position:relative w bazowej regule, więc to jedyna
   dodatkowa reguła potrzebna do pozycjonowania. pointer-events:none, żeby
   nie blokował klikania/zaznaczania tekstu pod spodem. */
.wiz-sms-counter {
    position: absolute;
    right: 0.75rem;
    bottom: 0.4rem;
    font-size: 0.75rem;
    color: var(--color-text-dimmed);
    pointer-events: none;
    background: var(--color-bg-surface);
    padding: 0 0.25rem;
    border-radius: 0.25rem;
}

/* Lista odbiorców jako karty (krok 5 kreatora wiadomości) - buildUserCardHtml()
   z 02_5_card.js zwraca gotowy .entity-card.user-card, tu tylko układ
   siatki. Dwie kolumny mieszczą się naturalnie w modalu 45rem (2x20.5rem +
   gap), na węższym ekranie wrap zejdzie do jednej kolumny sam z siebie -
   bez potrzeby osobnej reguły pod data-view-columns. */
.wiz-odbiorcy-lista {
    display: flex;
    flex-wrap: wrap;
    align-content: flex-start;
    gap: 0.5rem;
    height: calc(100vh - 23.75rem);
    overflow-y: auto;
    padding: 1rem;
}

.wiz-odbiorcy-lista > .entity-card {
    flex: 1 1 20.5rem;
    min-width: 0;
}


/* --- File: 6.prose.css --- */
/* 6. PROSE.CSS - Typografia artykułów (PROSE). */
/* Wersja kompletna: REM, zmienne systemowe oraz rozszerzenia redakcyjne */

/* Klasa .prose służy do stylowania "czystego tekstu" np. z CMS/Markdown */
.prose {
    max-width: var(--module-base);
    color: var(--color-text);
    line-height: 1.6;
    margin-left: auto; 
    margin-right: auto;
}

.prose h1, .prose h2, .prose h3, .prose h4 {
    color: var(--color-text);
    margin-top: 1.5rem;
    margin-bottom: 0.6rem;
    line-height: 1.3;
}

.prose h1 {
    font-size: 2.0rem; /*Orginalnie 2.2rem */
    letter-spacing: -0.02rem;
    font-weight: 800;
}

.prose h2 { 
    font-size: 1.7rem; 
    padding-bottom: 0.3rem;
    font-weight: 800;
    width: 100%;
}

.prose h3 {
    font-size: 1.35rem;
    font-weight: 800;
    width: 100%;
}

.prose p {
    font-weight: 400;
    margin-bottom: 1.25rem;
}

/* Linki w tekście */
.prose a {
    color: var(--color-secondary);
    text-decoration: underline;
    text-decoration-thickness: 0.125rem;
    text-underline-offset: 0.125rem;
    font-weight: 600;
    transition: all 0.2s ease;
}
.prose a:hover {
    color: var(--color-secondary-hover);
    background-color: var(--color-secondary-alpha);
    text-decoration: none;
}

/* Listy */
.prose ul, .prose ol {
    margin-bottom: 1.25rem;
    padding-left: 1.5rem;
}
.prose li { margin-bottom: 0.5rem; }

.prose ul li::marker {
    color: var(--color-primary); 
    font-size: 1.2rem;
}
.prose ol li::marker {
    color: var(--color-text-dimmed);
    font-weight: bold;
}

/* Cytaty */
.prose blockquote {
    border-left: 0.25rem solid var(--color-primary);
    margin: 1.5rem 0;
    padding: 1rem 1.5rem;
    background-color: var(--color-bg-surface-alt);
    border-radius: 0 0.5rem 0.5rem 0;
    font-style: italic;
    color: var(--color-text-dimmed);
}

/* Kod śródliniowy */
.prose code {
    font-family: monospace;
    background-color: var(--color-bg-surface-alt);
    padding: 0.2rem 0.4rem;
    border-radius: 0.25rem;
    font-size: 0.9rem;
    color: var(--color-secondary);
    border: 0.0625rem solid var(--color-border);
}

.prose strong {
    color: var(--color-text);
    font-weight: 800;
}

.prose hr {
    width: 100%;
    border: 0;
    border-top: 0.0625rem solid var(--color-border);
    margin: 2rem 0;
}

/* =======================================================
   ROZSZERZENIA REDAKCYJNE
   ======================================================= */

.prose .lead {
    font-size: 1.15rem;
    color: var(--color-text);
    font-weight: 600;
    line-height: 1.5;
    margin-bottom: 2rem;
}

.prose figure {
    margin: 2.5rem 0;
    width: 100%;
}

.prose figure img {
    width: 100%;
    height: auto;
    border-radius: 0.5rem;
    border: 0.0625rem solid var(--color-border);
    box-shadow: var(--shadow-sm);
    display: block;
}

.prose figcaption {
    font-size: 0.85rem;
    color: var(--color-text-muted);
    text-align: center;
    margin-top: 0.75rem;
    font-style: italic;
}

.prose iframe {
    width: 100%;
    aspect-ratio: 16 / 9;
    border-radius: 0.5rem;
    border: 0.0625rem solid var(--color-border);
    margin: 2.5rem 0;
    display: block;
}

.prose table {
    width: 100%;
    border-collapse: collapse;
    margin: 2.5rem 0;
    font-size: 0.95rem;
    display: block;
    overflow-x: auto;
    white-space: nowrap; 
    scrollbar-width: thin;
    scrollbar-color: var(--color-border) transparent;
}

.prose table::-webkit-scrollbar { height: 0.35rem; display: block; }
.prose table::-webkit-scrollbar-thumb { background-color: var(--color-border); border-radius: 1rem; }
.prose table::-webkit-scrollbar-thumb:hover { background-color: var(--color-primary); }

.prose th, .prose td {
    padding: 0.75rem 1rem;
    border-bottom: 0.0625rem solid var(--color-border);
}

.prose th {
    font-weight: 800;
    color: var(--color-text);
    background-color: var(--color-bg-surface-alt);
}

.prose tr:hover td { background-color: var(--color-bg-surface); }

.article-meta {
    display: flex;
    align-items: center;
    gap: 1rem;
    margin-bottom: 2rem;
    padding-bottom: 1rem;
    border-bottom: 0.0625rem solid var(--color-border);
}

.meta-avatar {
    width: 3rem; height: 3rem;
    border-radius: 50%;
    object-fit: cover;
    border: 0.125rem solid var(--color-border);
}

.meta-author { font-weight: 800; color: var(--color-text); }
.meta-details { font-size: 0.85rem; color: var(--color-text-muted); }

.prose .drop-cap::first-letter {
    float: left;
    font-size: 3.5rem;
    line-height: 0.8;
    font-weight: 800;
    margin-right: 0.5rem;
    margin-top: 0.2rem;
    color: var(--color-primary);
}

/* --- CTA BOX --- */
.prose-cta {
    display: flex;
    flex-direction: column;
    background-color: var(--color-bg-surface-alt);
    border: 0.0625rem solid var(--color-border);
    border-left: 0.35rem solid var(--color-primary);
    padding: 1.5rem;
    border-radius: 0.5rem;
    margin: 2.5rem 0;
}

.prose-cta h3 { margin-top: 0 !important; color: var(--color-primary) !important; }
.prose-cta p { margin-bottom: 1.5rem !important; }

/* Przycisk (a lub button) wypchnięty do prawej */
.prose-cta .btn {
    align-self: flex-end;
}

/* Ochrona przycisku przed kaskadą linków .prose a */
.prose .btn-primary {
    color: var(--color-primary-contrast) !important;
    text-decoration: none !important;
    background-color: var(--color-primary) !important;
}

.prose .btn-primary:hover {
    background-color: var(--color-primary-hover) !important;
    color: var(--color-primary-contrast) !important;
}

/* ========================================= */
/* === KARTA SZCZEGÓŁÓW (WIDOK BOCZNY)   === */
/* ========================================= */

.detail-card {
    width: var(--module-base);
    display: flex;
    flex-direction: column;
    background-color: var(--color-bg-surface);
    border: 0.0625rem solid var(--color-border);
    border-radius: 0.75rem; 
    box-shadow: var(--shadow-md);
    overflow: hidden;
}

.detail-photo-wrapper {
    width: 100%; height: 20rem;
    background-color: var(--color-bg-surface-alt);
    border-bottom: 0.0625rem solid var(--color-border);
}

.detail-photo-wrapper img { width: 100%; height: 100%; object-fit: cover; }

.detail-header {
    padding: 1.5rem;
    text-align: center;
    border-bottom: 0.0625rem solid var(--color-border);
}

.detail-title {
    display: block;
    font-size: 0.8rem;
    color: var(--color-primary-text);
    font-weight: 700;
    text-transform: uppercase;
    margin-bottom: 0.5rem;
}

.detail-name {
    font-size: 1.75rem;
    font-weight: 800;
    color: var(--color-text);
    line-height: 1.1;
}

.detail-shortcuts {
    background-color: var(--color-bg-surface-alt);
    padding: 1rem 1.5rem;
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    border-bottom: 0.0625rem solid var(--color-border);
}

.shortcuts-row {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    color: var(--color-text-dimmed);
    font-size: 0.9rem;
    transition: color 0.2s;
}

.shortcuts-row:hover { color: var(--color-primary); }
.shortcuts-row iconify-icon { font-size: 1.5rem; color: var(--color-icon); }

.detail-body { padding: 1.5rem; }
.detail-body .prose { font-size: 0.95rem; }

/* --- File: 7.main-container.css --- */
/**
 * 7_main-container.css
 * ZYXAK CRM by Paweł Pijanowski dla TONdance Szkoła Tańca w Łodzi
 * 2026-07-19 16:00
 */

#mainContainer {
			display: flex; width: 100vw; width: 100dvw;
			flex-direction: row;
			flex-grow: 1;
			overflow: hidden;
			position: relative;
		}
		
		#mainContainer .panel {
			height: 100%;
			display: flex; 
			flex-direction: column;
			width: 22.5rem;
			flex-shrink: 0;
			border-right: 1px solid var(--color-border);
			position: relative; 
            timeline-scope: --panel-scroller;
		}
		
		#mainContainer .panel header {
			display: flex;
			justify-content: center;
			align-items: center;
			width: 100%;
			height: 4rem;
			flex-shrink: 0; 
			font-size: 1.25rem;
			font-weight: 800;
			background-color: var(--color-bg-surface-alt); 
            /* Border zamieniony na box-shadow (inset) - TEN SAM problem co
               przy .data-table th (patrz komentarz przy tamtej regule
               niżej w pliku): ta belka wisi bezpośrednio nad przewijaną
               treścią panelu (.content, napędzaną przez
               animation-timeline: --panel-scroller), więc zwykły
               border-bottom potrafi przy przewijaniu pokazywać
               subpikselową szczelinę, przez którą prześwituje przewijana
               zawartość. Cień "unoszenia" (dawniej jedyna treść tej
               animacji) i ta stała, zastępująca border kreska są teraz
               animowane RAZEM w jednym box-shadow (patrz keyframes
               sticky-shadow-appear niżej) - inset-owa część jest obecna
               identycznie w "from" i "to", więc nigdy nie znika w trakcie
               animacji, mimo że box-shadow jako właściwość jest w całości
               nadpisywany przez każdą klatkę animacji. */
            z-index: 50; 
            animation: sticky-shadow-appear linear both;
            animation-timeline: --panel-scroller;
            animation-range: 0 1.5rem; 
		}

		#mainContainer .panel .content {
			display: flex;
            flex-direction: column;
            flex-grow: 1;
			padding: 1rem;
            overflow-y: auto; 
			overflow-x: hidden;
            scroll-timeline-name: --panel-scroller;
            scrollbar-width: none; 
            -ms-overflow-style: none; 
            /* Tekst w panelach (Filtry, Panel Główny, Szczegóły, Więcej) -
               bardziej zwarty niż globalne line-height:1.6 z 3_base.css
               (dobre do czytania prozy, ale zbyt luźne dla gęstego UI:
               etykiet, list, kafelków). .prose (6_prose.css) ma WŁASNE,
               jawne line-height:1.6 na klasie - jako bardziej specyficzna
               reguła nadal wygrywa tutaj, więc treści redakcyjne (opis
               kursu itp.) zostają czytelne, mimo tego overrides. */
 
		}

		/* --- NAGŁÓWKI "Szczegóły" i "Więcej" - pole tytułu jako sztywny
		   blok zamiast wyśrodkowania na CAŁĄ szerokość panelu (zachowanie
		   domyślne #mainContainer .panel header wyżej, nadal używane przez
		   Filtry i Panel Główny - CELOWO nietknięte, dotyczy WYŁĄCZNIE tych
		   dwóch paneli). Margines lewy 3rem + pole tytułu 16,5rem + pole
		   przycisku 3rem (patrz .panel-header-btn w 4_layout.css, już
		   szerokie na 3rem, position:absolute - nie trzeba go zmieniać) =
		   dokładnie 22,5rem, czyli pełna szerokość panelu. Tytuł, który się
		   nie mieści w jednej linijce, jest ucinany wielokropkiem
		   (overflow/text-overflow/white-space) zamiast zawijania się czy
		   rozpychania nagłówka - dotyczy zarówno zwykłego jednoliniowego
		   tytułu (textContent), jak i wariantu dwuliniowego {main,sub}
		   (patrz TableEngine.setDetailsTitle() / appController.showExtendedPanel()
		   w JS - tam każda z dwóch linii ma DODATKOWO WŁASNY ellipsis, bo są
		   to osobne <div>y wewnątrz tego pola, nie jeden tekst). flex-shrink:0
		   zapobiega ściśnięciu pola przez flexboksa poniżej 16,5rem. */
		#detailsView header, #detailedViewExtended header {
			justify-content: flex-start;
		}
		#detailsViewTitle, #detailedViewExtendedTitle {
			margin-left: 3rem;
			width: 16.5rem;
			flex-shrink: 0;
			overflow: hidden;
			text-overflow: ellipsis;
			white-space: nowrap;
			text-align: center;
			line-height: 1.2;
		}

        #mainContainer .panel .content::-webkit-scrollbar { display: none; }

        @keyframes sticky-shadow-appear {
            from { box-shadow: inset 0 -1px 0 var(--color-border); }
            to   { box-shadow: inset 0 -1px 0 var(--color-border), var(--shadow-md); }
        }

        @keyframes sticky-shadow-bottom-appear {
            0%, 95% { box-shadow: var(--shadow-md); }
            100% { box-shadow: none; }
        }

        #mainContainer .panel::after {
            content: ''; 
            position: absolute; 
            bottom: 0; left: 0;
            width: 100%; height: 0; 
            z-index: 50;
            pointer-events: none; 
            transform: scaleY(-1); 
            animation: sticky-shadow-bottom-appear linear both;
            animation-timeline: --panel-scroller;
        }

        /* ======================================================== */
        /* --- DODANE STYLE DLA SILNIKA TABELI ---                  */
        /* ======================================================== */
        
        .data-table-container { 
            width: 100%; 
            flex: 1 1 0; 
            overflow-x: auto; 
            overflow-y: auto; 
            scrollbar-width: none; 
            -ms-overflow-style: none; 
            position: relative; /* Kontekst pozycjonowania dla .table-loading-overlay
                                    - dzięki temu nakładka trzyma się środka WIDOCZNEGO
                                    okna przewijania (klatka .data-table-container), a
                                    nie środka całej (potencjalnie szerszej niż panel)
                                    przewijanej tabeli w środku. */
        }
        
        .data-table-container::-webkit-scrollbar:vertical { display: none; }
        .data-table-container::-webkit-scrollbar:horizontal { height: 6px; }
        .data-table-container::-webkit-scrollbar-thumb:horizontal {
            background: var(--color-border-strong);
            border-radius: 3px;
        }

        /* ======================================================== */
        /* --- NAKŁADKA ŁADOWANIA DANYCH TABELI ---                 */
        /* ======================================================== */
        /* Wstawiana/usuwana z JS (TableEngine.showTableLoadingOverlay() /
           hideTableLoadingOverlay(), 02_1_table-engine.js) jako dziecko
           .data-table-container - CELOWO nie jako wiersz <tr> w <tbody>,
           bo wiersz tabeli przewija się razem z (szerszą niż panel)
           tabelą w poziomie i potrafi wypaść poza widok. position:absolute
           + inset:0 względem pozycjonowanego .data-table-container daje
           środek WIDOCZNEGO okna przewijania, niezależnie od aktualnego
           przewinięcia w obu osiach. */
        .table-loading-overlay {
            position: absolute;
            top: 0; left: 0; right: 0; bottom: 0;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            gap: 0.75rem;
            background-color: var(--color-bg-surface);
            z-index: 45; /* Nad .data-table th (z-index: 40) */
            animation: table-loading-fade-in 0.15s ease;
        }

        .table-loading-overlay iconify-icon {
            font-size: 2.5rem;
            color: var(--color-primary);
        }

        .table-loading-overlay span {
            font-weight: 700;
            color: var(--color-text-dimmed);
            font-size: 0.95rem;
            letter-spacing: 0.02rem;
        }

        @keyframes table-loading-fade-in {
            from { opacity: 0; }
            to   { opacity: 1; }
        }
        
        /* UWAGA (zmiana architektury): width/min-width poniżej to WYŁĄCZNIE
           fallback. Realną szerokość (i min-width) tabeli ustawia teraz
           DYNAMICZNIE TableEngine.applyTableWidth() w 02_1_table-engine.js,
           jako sumę zadeklarowanych szerokości kolumn (config.columns)
           BIEŻĄCEGO modułu - inline style zawsze nadpisuje wartości poniżej.
           Dzięki temu tabela może być szersza (albo węższa) niż 45rem,
           niezależnie od tego, czy panel #mainGrid ma 22.5rem czy 45rem -
           .data-table-container (overflow-x:auto powyżej) daje scroll
           poziomy zawsze, gdy tabela jest szersza niż panel, dokładnie tak
           jak dotychczas działo się to WYŁĄCZNIE przy panelu 22.5rem.
           Żaden moduł nie musi już sumować swoich kolumn do dokładnie
           45rem - to była wcześniej twarda konwencja, teraz jest to
           wyłącznie automatycznie liczone przez silnik. Wartości 100%/45rem
           zostają tu jako bezpieczny fallback na wypadek błędu ładowania
           JS (patrz applyTableWidth() - jeśli nie znajdzie żadnej
           zadeklarowanej szerokości kolumny, nie nadpisuje inline stylu). */
        .data-table { 
            width: 100%; 
            min-width: 45rem; 
            table-layout: fixed; 
            border-collapse: collapse; 
            font-size: 0.95rem; 
            background-color: var(--color-bg-table); 
        }
        
        /* Wysokość wiersza: min-height (zamiast sztywnego height) + auto -
           pozwala wierszowi naturalnie urosnąć, gdy komórka potrzebuje
           więcej miejsca niż jedna linia tekstu (patrz moduł Lekcje,
           06_2_lekcje-columns.js: kolumny Data+Godzina, Nazwa, Instruktor
           renderują wielolinijkową treść przez wrapper z inline
           `white-space: normal`, nadpisujący domyślne `white-space: nowrap`
           z .data-table td poniżej).
           BEZPIECZNE dla pozostałych modułów (Kursanci, Instruktorzy,
           Schowek): żaden z ich obecnych render() nie nadpisuje
           white-space na 'normal', więc ich treść pozostaje jednoliniowa
           (ucinana elipsą jak dotychczas) i wiersz naturalnie zmierzy się
           dokładnie na min-height: 4rem - zero zmiany wizualnej. */
        .data-table tr {
            min-height: 4rem;
            height: auto;
        }
        
        /* Linie siatki nagłówka: box-shadow (inset), NIE border.
           POWÓD: przy position:sticky (nagłówek przykleja się do góry
           panelu podczas przewijania) zwykły `border-right`/
           `border-bottom` potrafi w niektórych przeglądarkach (głównie
           silniki oparte na Chromium) pokazywać przy przewijaniu
           subpikselową szczelinę w miejscu granicy komórki - przez tę
           szczelinę widać "prześwitującą" przewijaną zawartość tabeli pod
           nagłówkiem. box-shadow z inset jest malowany jako część tła
           komórki (ta sama warstwa co background-color), więc nie ma tego
           efektu. Kolor: var(--color-border) (na życzenie - poprzednia
           wersja używała var(--color-border-strong) dla większego
           kontrastu, ale to podniesienie zostało cofnięte). */
        .data-table th { 
            position: sticky; 
            top: 0; 
            background-color: var(--color-bg-surface-alt); 
            padding: 0 0.5rem; 
            text-align: left; 
            font-weight: 800; 
            color: var(--color-text-dimmed); 
            box-shadow: inset -1px 0 0 var(--color-border), inset 0 -1px 0 var(--color-border);
            z-index: 40; 
            height: 3rem;
            overflow: hidden;
            white-space: nowrap;
            user-select: none; 
        }
        
        .data-table th:last-child {
            /* Ostatnia kolumna: bez pionowej linii z prawej (to krawędź
               tabeli, nie granica między komórkami) - tylko dolna. */
            box-shadow: inset 0 -1px 0 var(--color-border);
        }
        
        .data-table th:hover.sortable-header {
            background-color: var(--color-bg-surface);
            color: var(--color-primary);
        }
        
        .data-table td { 
            padding: 0 0.5rem; 
            border-bottom: 1px solid var(--color-border); 
            color: var(--color-text-table); 
            cursor: pointer; 
            transition: background-color 0.1s; 
            vertical-align: middle;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }
        
        .data-table th:first-child, .data-table td:first-child { padding: 0; }
        .data-table tr:hover td { background-color: var(--color-bg-table-hover); }
        .data-table tr.selected td { background-color: var(--color-primary-alpha); color: var(--color-primary-text); }

        /* Lekcja odwołana (06_2_lekcje-columns.js, kolumna "Nr" -
           .lekcja-odwolana-marker na ikonie mdi:cancel) - cały wiersz
           przygaszony/rozjaśniony. Celowo JEDNA reguła (opacity) wspólna
           dla light i dark, bez rozróżniania motywu: opacity blenduje
           treść wiersza w stronę tła .data-table (var(--color-bg-table)) -
           w jasnym motywie tło jest jasne, więc wiersz wizualnie
           "rozjaśnia się"; w ciemnym motywie tło jest ciemne, więc ten sam
           wiersz "przygasza się" - dokładnie te dwa efekty, o które
           proszono, bez znajomości mechanizmu przełączania motywu.
           :has() na poziomie <tr> (nie na .data-table td bezpośrednio),
           żeby przygasić też np. tło komórki przy hover w tym wierszu. */
        .data-table tr:has(.lekcja-odwolana-marker) {
            opacity: 0.5;
        }
        
        /* ======================================================== */
        /* --- PANCERNA PAGINACJA ---                               */
        /* ======================================================== */

        .pagination { 
            display: none; /* JS aktywuje display: flex */
            flex-direction: row !important; /* Wymuszenie poziomu */
            justify-content: space-between !important; 
            align-items: center !important; 
            height: 4.5rem; 
            padding: 0 1rem; 
            background-color: var(--color-bg-surface-alt);
            border-top: 1px solid var(--color-border);
            font-size: 0.85rem;
            width: 100%;
            box-sizing: border-box;
        }

        /* Lewa strona - Wybór ilości rekordów */
        .pag-limit-container { 
            display: flex !important; 
            flex-direction: row !important; /* Wymuszenie poziomu */
            align-items: center !important; 
            gap: 0.5rem; 
            flex: 1; 
            justify-content: flex-start;
            color: var(--color-text-dimmed); 
        }

        /* Środek - Przyciski nawigacyjne */
        .pag-center-container { 
            display: flex !important; 
            flex-direction: row !important; /* To blokuje układanie w pionie! */
            align-items: center !important; 
            justify-content: center !important; 
            gap: 0.4rem; 
        }

        /* Prawa strona - Licznik rekordów */
        .pag-right-container { 
            display: flex !important; 
            flex-direction: row !important; /* Wymuszenie poziomu */
            align-items: center !important; 
            gap: 0.3rem;
            flex: 1; 
            justify-content: flex-end; 
            color: var(--color-text-dimmed); 
        }

        .pagination button { 
            width: 2.2rem; 
            height: 2.2rem; 
            border-radius: 0.4rem; 
            border: 1px solid var(--color-border); 
            background: var(--color-bg-surface); 
            color: var(--color-text); 
            cursor: pointer; 
            
            /* Zapobiega renderowaniu jako blok Flex - inline-flex ratuje sytuację */
            display: inline-flex !important; 
            flex-direction: row !important;
            justify-content: center !important; 
            align-items: center !important; 
            
            transition: all 0.2s; 
            padding: 0;
            margin: 0;
        }
        
        .pagination button:hover:not(:disabled) { 
            background: var(--color-bg-surface-alt); 
            border-color: var(--color-border-strong); 
        }
        
        .pagination button.active { 
            background: var(--color-primary); 
            color: var(--color-primary-contrast); 
            border-color: var(--color-primary); 
            font-weight: bold; 
        }
        
        .pagination button:disabled { 
            opacity: 0.5; 
            cursor: not-allowed; 
        }

        /* --- Responsywność paginacji (Ukrywanie elementów na ekranach 1, 2, 3 kolumny) --- */
        
        /* 1. Ukrywamy etykietę "Na stronie" oraz wszystkie 4 strzałki (<<, <, >, >>) */
        html:is([data-view-columns='1'], [data-view-columns='2'], [data-view-columns='3']) .pag-hide-small { 
            display: none !important; 
        }

        /* 2. Ukrywamy tekst "Rekordy: " wyzerowaniem fontu w kontenerze, 
              oraz chowamy przedział liczbowy (np. 1-50) i słówko "z" */
        html:is([data-view-columns='1'], [data-view-columns='2'], [data-view-columns='3']) .pag-right-container { 
            font-size: 0 !important; 
            flex: none !important; /* Blokada rozpychania prawej sekcji */
        }
        
        html:is([data-view-columns='1'], [data-view-columns='2'], [data-view-columns='3']) .pag-right-container strong:first-child,
        html:is([data-view-columns='1'], [data-view-columns='2'], [data-view-columns='3']) .pag-right-container span { 
            display: none !important; 
        }

        /* 3. Zostawiamy widoczną wyłącznie globalną liczbę rekordów */
        html:is([data-view-columns='1'], [data-view-columns='2'], [data-view-columns='3']) .pag-right-container strong:last-child { 
            font-size: 0.85rem !important; 
        }

        /* 4. Gwarancja zmieszczenia w 22.5rem - redukcja rozmiarów i blokada flexa */
        html:is([data-view-columns='1'], [data-view-columns='2'], [data-view-columns='3']) .pag-limit-container { 
            flex: none !important; 
        }
        
        html:is([data-view-columns='1'], [data-view-columns='2'], [data-view-columns='3']) .pagination {
            padding: 0 0.5rem !important; /* Węższe odstępy boczne na komórkach */
        }
        
        html:is([data-view-columns='1'], [data-view-columns='2'], [data-view-columns='3']) .pagination button {
            width: 1.8rem !important; /* Mniejsze przyciski stron */
            height: 1.8rem !important;
            font-size: 0.85rem !important;
        }

        /* ======================================================== */
        
        .detail-photo-wrapper img {
            width: 100% !important;
            height: 100% !important;
            border-radius: 0 !important;
            object-fit: cover !important;
        }

        /* Avatar instruktora w tabeli głównej (03_2.../05_2_instructors-columns.js) -
           instruktor_avatar_html to zaufany HTML z PHP, którego <img> ma inline
           border-radius:50% (styl okrągłego avatara użyty gdzie indziej w CRM) -
           w tabeli Instruktorów chcemy kwadrat z zaokrąglonymi rogami 0.875rem,
           więc nadpisujemy tu inline styl z backendu (stąd !important) zamiast
           dublować logikę renderowania avatara w PHP tylko dla tego widoku. */
        .instructor-avatar-frame img {
            width: 100% !important;
            height: 100% !important;
            border-radius: 0 !important;
            object-fit: cover !important;
        }

        /* ==========================================================================
           FAB (Floating Action Button) "Edytuj" - panel Szczegóły
           Wspólny dla WSZYSTKICH modułów (Kursanci, Instruktorzy, przyszłe) -
           widoczność sterowana wyłącznie przez TableEngine.updateToolbar()
           w 2_table-engine.js. Domyślnie ukryty w CSS, żeby nie mignął przed
           pierwszym wywołaniem updateToolbar() po załadowaniu strony.
           ========================================================================== */
        .panel-fab {
            display: none;
            position: absolute;
            right: 1.5rem;
            bottom: 1.5rem;
            width: 3.5rem;
            height: 3.5rem;
            border-radius: 50%;
            border: none;
            background-color: var(--color-primary);
            color: var(--color-primary-contrast);
            align-items: center;
            justify-content: center;
            font-size: 1.6rem;
            cursor: pointer;
            box-shadow: var(--shadow-md);
            z-index: 60; /* nad przewijaną .content i jej cieniami (z-index 50) */
            transition: background-color 0.2s ease, transform 0.15s ease;
        }

        .panel-fab:hover {
            background-color: var(--color-primary-hover);
        }

        .panel-fab:active {
            transform: scale(0.94);
        }


/* --- File: 8.cards.css --- */
/* 8.cards.css
   ZYXAK CRM by Paweł Pijanowski dla TONdance Szkoła Tańca w Łodzi
   09.07.2026 12:00
*/

/* ==========================================================================
   BAZOWA KARTA ENCJI (.entity-card)
   Wspólny szkielet dla wszystkich "kart wiersza osoby" w CRM - awatar +
   imię/nazwisko + metadane. Warianty (.user-card, .instructor-card) różnią
   się WYŁĄCZNIE promieniem zaokrąglenia lewej krawędzi karty i awatara -
   reszta (wysokość, padding, kolory, prawa krawędź, typografia) jest
   wspólna i żyje tutaj, żeby nie duplikować identycznych reguł. Karta
   musi zawsze nosić DWIE klasy razem: bazową + wariant, np.
   class="entity-card user-card" (patrz buildUserCardHtml()/
   buildInstructorCardHtml() w 02_5_card.js).
   ========================================================================== */

.entity-card {
    position: relative;
    display: flex;
    align-items: center;
    gap: 0.75rem;

    height: 4rem;
    padding: 0.25rem;

    /* Kolory jak .card2 (5_forms.css) - spójność z resztą "kart drugiego
       poziomu" (osadzonych wewnątrz .detail-body, na tle .card2 gdzie
       jeszcze nie przepisane). */
    background-color: var(--color-bg-surface);
    border: 0.0625rem solid var(--color-border);

    /* Prawa krawędź - wspólna dla wszystkich wariantów, tylko lewa różni
       się per wariant (patrz .user-card/.instructor-card niżej). */
    border-top-right-radius: 0.375rem;
    border-bottom-right-radius: 0.375rem;

    overflow: hidden;
}

/* Karta Kursanta - lewe rogi 2rem = połowa ze STAŁEJ wysokości karty
   (4rem) - realne półkole "wokół" awatara niezależnie od szerokości karty.
   Procentowe border-radius liczyłoby poziomy promień od SZEROKOŚCI, a nie
   wysokości, więc przy karcie szerszej niż 4rem dałoby spłaszczoną elipsę
   zamiast półkola - stąd wartość w rem, nie w %. */
.user-card {
    border-top-left-radius: 2rem;
    border-bottom-left-radius: 2rem;
}

/* Karta Instruktora - te same proporcje karty co Kursant, ale mniej
   "okrągły" lewy róg (1.125rem zamiast pełnego półkola 2rem) - świadome
   zróżnicowanie wizualne między dwoma typami encji. */
.instructor-card {
    border-top-left-radius: 1.125rem;
    border-bottom-left-radius: 1.125rem;
}

/* Awatar z lewej - identyczny rozmiar (3.5rem) dla obu wariantów, tylko
   zaokrąglenie różni się per typ encji (patrz .user-card-avatar/
   .instructor-card-avatar niżej). */
.entity-card-avatar {
    flex-shrink: 0;
    width: 3.5rem;
    height: 3.5rem;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    background-color: var(--color-bg-surface-alt);
}

.entity-card-avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.user-card-avatar {
    border-radius: 50%;
}

.instructor-card-avatar {
    border-radius: 0.875rem;
}

/* Sam <img> wewnątrz awatara MUSI dostać ten sam promień co kontener -
   overflow:hidden na .entity-card-avatar wycina go wizualnie wg promienia
   kontenera, ALE gotowy, zaufany avatar_html z backendu (UserHtmlHelper::
   renderAvatar / InstruktorHtmlHelper::renderAvatar) często niesie WŁASNY,
   zaszyty inline style="border-radius:...". Inline style ma wyższą
   specyficzność niż zwykła reguła klasy, więc bez !important tutaj obraz
   wewnątrz nadal wyglądałby jak koło (albo cokolwiek ustawił backend)
   niezależnie od kształtu kontenera. */
.user-card-avatar img {
    border-radius: 50% !important;
}

.instructor-card-avatar img {
    border-radius: 0.875rem !important;
}

/* Blok tekstowy (imię/nazwisko + druga linia metadanych) - wspólny dla
   obu wariantów. */
.entity-card-info {
    min-width: 0;
    flex: 1;
}

.entity-card-name {
    font-size: 1.2rem;
    font-weight: 700;
    color: var(--color-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.entity-card-meta {
    position: relative;
    bottom: 0.25rem;
    font-size: 0.8rem;
    color: var(--color-text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ==========================================================================
   PRZYCISKI AKCJI (.card-actions / .card-action-btn)
   Współdzielone przez OBIE karty (.user-card i .instructor-card) - stąd
   neutralna nazwa (bez prefiksu "user-"), mimo że historycznie powstały
   najpierw przy karcie Kursanta (Schowek). Karta Instruktora używa ich
   teraz do: przycisku "Pokaż/ukryj wynagrodzenie" (góra) i przycisku
   "Zobacz powiązanego kursanta" (dół) - patrz buildInstructorCardHtml()
   w 02_5_card.js.
   ========================================================================== */

/* Kontener na przyciski akcji - ZWYKŁY element w nadrzędnym flex (karta),
   NIE position:absolute - to zwalnia .entity-card-info z rezerwowania
   miejsca z prawej, więc imię/nazwisko ma do dyspozycji całą pozostałą
   szerokość karty. flex-shrink:0, bo ma stałą, przewidywalną szerokość
   (szerokość przycisku) niezależnie od tego, ile miejsca zostanie dla
   .entity-card-info. Wysokość 3.5rem = ta sama co awatar, żeby oba
   elementy ładnie się wyrównały w wierszu karty. */
.card-actions {
    flex-shrink: 0;
    height: 3.5rem;
    padding: 0;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    align-items: center;
}

/* Dwa przyciski (np. Lekcje - Kursant: "usuń z listy obecności" + "dodaj
   do Schowka"; Instruktor: "wynagrodzenie" + "powiązany kursant") -
   justify-content:space-between wyżej rozsuwa je maksymalnie góra/dół
   same z siebie. JEDEN przycisk - space-between z pojedynczym dzieckiem
   ustawiłby go przy GÓRNEJ krawędzi (zachowanie flex przy jednym
   elemencie), więc auto-margin od góry spycha go w dół, zgodnie z
   ustaleniem "jeśli jeden przycisk, to na dole". */
.card-actions > *:only-child {
    margin-top: auto;
}

.card-action-btn {
    width: 1.6rem;
    height: 1.6rem;
    padding: 0;
    border: none;
    background: transparent;
    color: var(--color-text-muted);
    cursor: pointer;
    font-size: 1rem;
    transition: color 0.2s;
}

.card-action-btn:hover {
    color: var(--color-text);
}

/* ==========================================================================
   PANEL WYNAGRODZENIA - KARTA INSTRUKTORA (.instructor-card-wyn-panel)
   Wysuwany/chowany PANEL Z DANYMI PROFILOWYMI wynagrodzenia instruktora
   (solo/duet: podstawa, od osoby, próg - z tabeli zx_instruktor), toggle'owany
   przyciskiem na karcie (patrz buildInstructorCardHtml() w 02_5_card.js).
   To COŚ INNEGO niż stały pasek wynagrodzenia EFEKTYWNEGO na daną lekcję
   (lekcjeBuildInstruktorWynagrodzenieBlock() w 06_3_lekcje-details.js) -
   oba mogą występować pod tą samą kartą jednocześnie, jeden nad drugim.
   Domyślnie ukryty (display:none, ustawiane inline przez JS przy
   toggle'owaniu) - sama zawartość (kolory/siatka/czcionka) jest w gestii
   wywołującego (przekazywana jako trusted HTML), tutaj tylko odstęp od
   karty nad nim. */
/* Domyślnie ZWINIĘTY (max-height:0 + overflow:hidden) - klasa .open
   (dodawana/usuwana przez toggleInstructorCardWynPanel w 02_5_card.js)
   rozsuwa go w dół animacją, a jej usunięcie chowa go z powrotem do góry.
   max-height:20rem przy .open to celowo "z zapasem" stała wartość (NIE
   rzeczywista wysokość treści, której JS tu nie mierzy) - wystarczająco
   duża, żeby pomieścić tytuł + siatkę kwot bez ucinania, prostsza niż
   liczenie scrollHeight w JS. margin-bottom przechodzi razem z max-height,
   żeby przy zwiniętym stanie panel nie zostawiał pustego odstępu pod
   kartą. */
.instructor-card-wyn-panel {
    margin-top: 0;
    margin-right: 0.375rem;
    margin-bottom: 0;
    margin-left: 1.125rem;
    border-radius: 0;
    max-height: 0;
    overflow: hidden;
    opacity: 0;
    transition: max-height 0.25s ease, opacity 0.2s ease, margin-bottom 0.25s ease;
}

.instructor-card-wyn-panel.open {
    max-height: 20rem;
    margin-bottom: 0.5rem;
    opacity: 1;
}

/* Tytuł na górze wysuwanego panelu - ten sam wzorzec typografii co inne
   nagłówki sekcji w panelach szczegółów (np. INSTRUCTOR_SECTION_HEADER_STYLE
   w 05_3_instructors-details.js), tylko bez dolnej linii/paddingu - panel
   jest mały, nie potrzebuje pełnego separatora sekcji. */
.instructor-card-wyn-panel-title {
    font-size: 0.75rem;
    font-weight: 800;
    color: var(--color-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.05rem;
    text-align: center;
    padding: 0.5rem;
    background-color: var(--color-bg-surface-alt);
}


/* --- File: 9_detail-sections.css --- */
/* 9. DETAIL-SECTIONS.CSS - Wspólne style paneli Szczegóły. */
/* ZYXAK CRM by Paweł Pijanowski dla TONdance Szkoła Tańca w Łodzi */
/* 2026-07-19 19:15 */

/*
 * .detail-section-header - nagłówek <h3> pojedynczej sekcji wewnątrz
 * panelu Szczegóły (np. "Terminarz", "Instruktorzy", "Opis" w Kursie/
 * Evencie, "Kursy"/"Aktywność" w Kursancie, "Dodawanie kursantów do
 * schowka"). Wcześniej ten sam zestaw właściwości był zduplikowany jako
 * string JS (KURS_DETAILS_SECTION_HEADER_STYLE / EVENT_DETAILS_SECTION_
 * HEADER_STYLE / sectionHeaderStyle w 03_3_users-details.js /
 * SCHOWEK_KURSEVENT_SECTION_HEADER_STYLE) w każdym pliku *-details.js
 * osobno - wyciągnięte tutaj, żeby zmiana wizualna (np. ten margin-top)
 * wymagała edycji JEDNEGO miejsca, a nie N-plików.
 *
 * UWAGA: pliki *-details.js renderują <h3 class="detail-section-header">
 * - ta klasa musi więc istnieć w arkuszu ładowanym na każdej stronie z
 * panelem Szczegóły (patrz index.php, kolejność <link> arkuszy).
 */
.detail-section-header {
    font-size: 0.95rem;
    font-weight: 800;
    color: var(--color-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.05rem;
    margin-top: 2rem;
    margin-bottom: 0.75rem;
    border-bottom: 1px solid var(--color-border);
    padding-bottom: 0.25rem;
}


