:root {
	/* Stała wysokość kontrolki: pigułka statusu, whiteframe, chip. */
	--form-default-size: 20px;
	/* Minimalna wysokość wiersza pola — jedna dla wartości i dla formularza. Pole przełącza się
	   między nimi w tym samym wierszu, więc różne minima znaczyły skok wiersza przy otwarciu
	   edytora. 24px, bo tyle potrzebują pigułka statusu, ikony akcji i dwuliniowy adres. */
	--form-min-height: 24px;
	--filter-box-height: 300px;
	--font-xs: 80%;
	--font-sm: 90%;
	/* Skala etykiet pól i nagłówków kolumn tabel (liczba, nie procent — dzieli się przez nią przy korektach). */
	--label-scale: 0.84;
	--font-normal: inter-regular, 'Segoe UI', ubuntu-regular, sans-serif;
	--sidebar-width: 24rem;
	--sidebar-mini-width: 6.4rem;
	--sidebar-flyout-width: 22rem;
	--sidebar-bg-soft: rgba(255, 255, 255, 0.05);
	--sidebar-bg-soft-strong: rgba(255, 255, 255, 0.09);
	--sidebar-font-size: 1em;
	--sidebar-suboption-font-size: 0.95em;
	--sidebar-icon-size: 1.15em;
	--sidebar-icon-width: 1.5em;
	--sidebar-row-radius: 0.5em;
	--sidebar-transition: 300ms cubic-bezier(0.4, 0, 0.2, 1);
	--topbar-height: 50px;
	--scrollbar-width: 8px;

	/* ===== KOLORY — tokeny semantyczne (Faza 0 dark-mode refactor) =====
	   Wartości = obecny light. Każda reguła ma docelowo czytać TYLKO var(--color-*).
	   Dark mode = przepisanie tych tokenów w html[data-theme="dark"] (patrz niżej).
	   Mapa/uzasadnienie: claude-docs/css-refactor-plan.md */
	/* Powierzchnie / tło */
	--color-bg-app: #e0e0e0;
	--color-bg-app-darker: #bfbfbf;
	--color-surface: #ffffff;
	--color-surface-muted: #f6f7f8;
	--color-surface-alt: #f1f1f1;
	--color-surface-highlight: #e6e6ff;
	/* Tekst */
	--color-text-primary: #000000;
	--color-text-secondary: #4b4c51;
	--color-text-muted: #888888;
	--color-text-inverse: #ffffff;
	/* Szarosc zaliczonego punktu trasy — wspolna dla kolumny statusu (.stop-status-finished)
	   i chipow postepu trasy (route-btn-past); ta sama w obu motywach, wiec bez nadpisania w dark */
	--color-status-finished-text: #888;
	/* Obramowania */
	--color-border: #dddddd;
	--color-border-strong: #aaaaaa;
	--color-border-input: #e1e2e5;
	/* Akcent (marka) */
	--color-accent: #6162F1;
	--color-accent-hover: #3B3DAB;
	--color-accent-strong: #8889FD;
	--color-accent-deep: #494BCF;
	--color-accent-soft-bg: #eff0ff;
	--color-accent-soft: rgba(97, 98, 241, 0.18);
	/* Nakładki / cienie */
	--color-overlay-dark: rgba(0, 0, 0, 0.05);
	--color-row-hover: rgba(0, 0, 0, 0.04);
	--color-shadow: rgba(0, 0, 0, 0.3);
	/* Sidebar / topbar chrome */
	--color-sidebar-bg: #0C0A1B;
	--color-sidebar-bg-elevated: #14122a;
	--color-sidebar-text: #d9dbe5;
	--color-sidebar-text-muted: #8a8f9e;
	/* Status: sukces */
	--color-success: #258F00;
	--color-success-bg: #258F00;
	--color-success-hover: #1B6700;
	--color-success-soft-bg: #e4fcdf;
	--color-success-text: #047B52;
	/* Status: błąd */
	--color-danger: #ED0B0B;
	--color-danger-hover: #7D0404;
	--color-danger-alt: #dc3545;
	--color-danger-soft-bg: #feeeee;
	--color-danger-text: #B91E15;
	/* Status: ostrzeżenie */
	--color-warning: #FAA619;
	--color-warning-hover: #C88514;
	--color-warning-soft-bg: #faf1e0;
	--color-warning-text: #B54708;
	/* Tekst ostrzeżenia na tle --color-surface-highlight — zwykły ma tam kontrast 4.43:1, poniżej WCAG AA */
	--color-warning-text-on-highlight: #9A3D06;
	/* Status: info */
	--color-info: #2870EC;
	--color-info-bg: #2870EC;
	--color-info-hover: #0045BC;
	--color-info-soft-bg: #e8f5ff;
	--color-info-text: #175CD3;
	/* Status: fiolet / teal */
	--color-purple: #4A148C;
	--color-purple-soft-bg: #f9edfb;
	--color-teal: #046B6B;
	--color-teal-soft-bg: #dcf2f2;
	/* Soft-bg hover (przyciemnienie tła statusu na hover) */
	--color-success-soft-bg-hover: #a5e2a9;
	--color-danger-soft-bg-hover: #f5b8b8;
	--color-warning-soft-bg-hover: #f9d9bf;
	--color-info-soft-bg-hover: #b0c2ef;
	--color-purple-soft-bg-hover: #e0ccf9;
	--color-teal-soft-bg-hover: #addfdf;
	/* Punkt podjazdu — fiolet jego pinezki na mapie (MapUtilsService, APPROACH_PIN_COLOR), w obu
	   motywach ten sam, bo pinezka na mapie też się nie zmienia. */
	--color-approach: #7b1fa2;
	/* Dalsze barwy palety planów (paski planera): kolor tekstu i obwódki, tło, tło na hover */
	--color-orange: #C2410C; --color-orange-soft-bg: #FFEDD5; --color-orange-soft-bg-hover: #FED7AA;
	--color-yellow: #854D0E; --color-yellow-soft-bg: #FEF9C3; --color-yellow-soft-bg-hover: #FEF08A;
	--color-lime: #3F6212; --color-lime-soft-bg: #ECFCCB; --color-lime-soft-bg-hover: #D9F99D;
	--color-cyan: #0E7490; --color-cyan-soft-bg: #CFFAFE; --color-cyan-soft-bg-hover: #A5F3FC;
	--color-indigo: #3730A3; --color-indigo-soft-bg: #E0E7FF; --color-indigo-soft-bg-hover: #C7D2FE;
	--color-pink: #BE185D; --color-pink-soft-bg: #FCE7F3; --color-pink-soft-bg-hover: #FBCFE8;
	--color-brown: #7C4A2D; --color-brown-soft-bg: #F3E8DD; --color-brown-soft-bg-hover: #E7D3BF;
	--color-slate: #334155; --color-slate-soft-bg: #E2E8F0; --color-slate-soft-bg-hover: #CBD5E1;
	/* Ciemne powierzchnie chrome (btn-menu, panel-heading, dark bary) */
	--color-chrome: #222834;
	--color-chrome-deep: #1a2233;
	--color-scrollbar-thumb: #aaaaaa;
	--color-on-accent: #ffffff;
	--color-chrome-edge: rgba(255, 255, 255, 0.12);
	--color-accent-bg: #6162F1;
	--color-saved-filters-bg: rgba(255, 255, 255, 0.5);
	/* Cienie (wiązki box-shadow) */
	--shadow-1: rgba(60, 64, 67, 0.3) 0px 1px 2px 0px, rgba(60, 64, 67, 0.15) 0px 1px 3px 1px;
	--shadow-2: rgba(0, 0, 0, 0.16) 0px 3px 6px, rgba(0, 0, 0, 0.23) 0px 3px 6px;
	--shadow-card: rgba(50, 50, 93, 0.25) 0px 2px 5px -1px, rgba(0, 0, 0, 0.3) 0px 1px 3px -1px;
	--shadow-thead: rgba(0, 0, 0, 0.12) 0px 1px 3px, rgba(0, 0, 0, 0.24) 0px 1px 2px;
	/* Kolumna weekendu w planerze: na jasnym motywie ciemniejsza od tła, na ciemnym jaśniejsza. */
	--planner-weekend-bg: rgba(0, 0, 0, 0.07);
	/* Kreska zamykająca wiersz zestawu — gruba, bo oddziela sekcje, a nie wiersze w sekcji. */
	--planner-row-separator: #dddddd;
}

/* ===== DARK MODE (html[data-theme="dark"]) =====
   Aktywne przez atrybut data-theme="dark" na <html> (przelacznik w topbarze, persist localStorage 'uniterTheme').
   Brak atrybutu = light (:root powyzej). Paleta: Breeze (KDE Plasma) Dark; statusy wyostrzone.
   Na czas kopiowania zaznaczenia (data-copy-neutral, ponizej) tokeny wracaja do palety jasnej. */
html[data-theme="dark"]:not([data-copy-neutral]) {
	/* Powierzchnie (Breeze: view #1b1e20, window #2a2e32, button #31363b) */
	color-scheme: dark;
	--planner-weekend-bg: rgba(255, 255, 255, 0.07);
	--planner-row-separator: #000000;
	--color-bg-app: #1b1e20;
	--color-bg-app-darker: #16181a;
	--color-surface: #2a2e32;
	--color-surface-muted: #31363b;
	--color-surface-alt: #232629;
	--color-surface-highlight: #2d4257;
	/* Tekst (Breeze: #fcfcfc / inactive #bdc3c7) */
	--color-text-primary: #fcfcfc;
	--color-text-secondary: #bdc3c7;
	--color-text-muted: #a0a6af;
	--color-text-inverse: #fcfcfc;
	/* Bordery / separatory */
	--color-border: #121417;
	--color-border-strong: #1c1f23;
	--color-border-input: #16181c;
	/* Akcent (Breeze highlight #3daee9 / link #1d99f3) */
	--color-accent: #3daee9;
	--color-accent-hover: #5cbef0;
	--color-accent-strong: #3daee9;
	--color-accent-deep: #93cef0;
	--color-accent-soft-bg: #1f3a4d;
	--color-accent-soft: rgba(61, 174, 233, 0.20);
	--color-overlay-dark: rgba(255, 255, 255, 0.07);
	--color-row-hover: rgba(255, 255, 255, 0.10);
	--color-shadow: rgba(0, 0, 0, 0.6);
	/* Sidebar (Breeze darks) */
	--color-sidebar-bg: #121417;
	--color-sidebar-bg-elevated: #1c1f23;
	--color-sidebar-text: #eff0f1;
	--color-sidebar-text-muted: #8a9099;
	/* Statusy WYOSTRZONE (Breeze: green #27ae60, red #da4453, yellow #fdbc4b, blue #3daee9, purple #9b59b6, teal #1abc9c) */
	--color-success: #2ecc71; --color-success-hover: #27ae60; --color-success-soft-bg: #16361f; --color-success-text: #5fdc8a; --color-success-bg: #1a5c34;
	--color-danger: #ed4a57; --color-danger-hover: #c0392b; --color-danger-alt: #ff5c69; --color-danger-soft-bg: #3a1a1e; --color-danger-text: #ff8a93;
	--color-warning: #fdbc4b; --color-warning-hover: #f67400; --color-warning-soft-bg: #3a2e10; --color-warning-text: #fdbc4b; --color-warning-text-on-highlight: #fdbc4b;
	--color-info: #3daee9; --color-info-hover: #1d99f3; --color-info-soft-bg: #15293a; --color-info-text: #5fbdf0; --color-info-bg: #155a8a;
	--color-purple: #b86fd6; --color-purple-soft-bg: #2a1638; --color-teal: #1abc9c; --color-teal-soft-bg: #0e2e2e;
	--color-success-soft-bg-hover: #1d4a28; --color-danger-soft-bg-hover: #4d2226; --color-warning-soft-bg-hover: #4d3d14;
	--color-info-soft-bg-hover: #1d3a52; --color-purple-soft-bg-hover: #3a2050; --color-teal-soft-bg-hover: #154040;
	--color-orange: #fb923c; --color-orange-soft-bg: #3d2412; --color-orange-soft-bg-hover: #542f14;
	--color-yellow: #facc15; --color-yellow-soft-bg: #3a3410; --color-yellow-soft-bg-hover: #4d4513;
	--color-lime: #a3e635; --color-lime-soft-bg: #25330f; --color-lime-soft-bg-hover: #324614;
	--color-cyan: #22d3ee; --color-cyan-soft-bg: #0c2f38; --color-cyan-soft-bg-hover: #11404c;
	--color-indigo: #a5b4fc; --color-indigo-soft-bg: #1e2150; --color-indigo-soft-bg-hover: #292d6b;
	--color-pink: #f472b6; --color-pink-soft-bg: #3b1629; --color-pink-soft-bg-hover: #521d38;
	--color-brown: #d6a57c; --color-brown-soft-bg: #33261c; --color-brown-soft-bg-hover: #453325;
	--color-slate: #cbd5e1; --color-slate-soft-bg: #273142; --color-slate-soft-bg-hover: #334155;
	--color-chrome: #2a2e32; --color-chrome-deep: #1b1e20;
	--color-scrollbar-thumb: #4a4f55;
	--color-on-accent: #ffffff;
	--color-accent-bg: #0f4866;
	--color-saved-filters-bg: #121417;
	--shadow-1: rgba(0, 0, 0, 0.5) 0px 1px 2px 0px, rgba(0, 0, 0, 0.4) 0px 1px 3px 1px;
	--shadow-2: rgba(0, 0, 0, 0.5) 0px 3px 6px, rgba(0, 0, 0, 0.6) 0px 3px 6px;
	--shadow-card: rgba(0, 0, 0, 0.6) 0px 2px 5px -1px, rgba(0, 0, 0, 0.5) 0px 1px 3px -1px;
	--shadow-thead: rgba(0, 0, 0, 0.4) 0px 1px 3px, rgba(0, 0, 0, 0.55) 0px 1px 2px;
}

/* Kopiowanie zaznaczenia (ThemeUtils.neutralizeCopy): przeglądarka wkleja do schowka kolory elementów,
   więc w Excelu lądowałoby tło i tekst motywu. Na czas kopiowania obowiązuje paleta jasna (blok trybu ciemnego
   wyłącza się przez :not([data-copy-neutral])), a powierzchnie są przezroczyste — kopia nie niesie wypełnienia.
   Przepisujemy tokeny, a nie kolory elementów: Chrome składa styl kopii z najbardziej szczegółowej
   pasującej reguły i pomija przy tym !important, ale wartości var() wylicza z bieżących tokenów. Tło samego
   <html> nadaje angular-material (#fafafa), a Chrome dokłada kopii tło najbliższego przodka, który je ma. */
html[data-copy-neutral] {
	background-color: transparent;
	--color-bg-app: transparent;
	--color-bg-app-darker: transparent;
	--color-surface: transparent;
	--color-surface-muted: transparent;
	--color-surface-alt: transparent;
	--color-surface-highlight: transparent;
	--color-row-hover: transparent;
	--color-overlay-dark: transparent;
}

/***************************************************/
/* SCROLLBAR****************************************/
/***************************************************/
::-webkit-scrollbar {
	width: var(--scrollbar-width);
	height: var(--scrollbar-width);
}

::-webkit-scrollbar-track {
	background: transparent;
}

::-webkit-scrollbar-thumb {
	background: var(--color-scrollbar-thumb);
	border-radius: 8px;
	border: 2px solid transparent;
	background-clip: content-box;
}

::-webkit-scrollbar-thumb:hover {
	background: var(--color-text-muted);
	background-clip: content-box;
	border: 2px solid transparent;
}

::-webkit-scrollbar-corner {
	background: transparent;
}

html {
	scrollbar-width: thin;
	scrollbar-color: var(--color-scrollbar-thumb) transparent;
}

/***************************************************/
/* FONTS *******************************************/
/***************************************************/
@font-face {
	font-family: ubuntu-regular;
	src: url(../fonts/ubuntu/ubuntu-regular.ttf);
}

@font-face {
	font-family: ubuntu-condensed;
	src: url(../fonts/ubuntu/ubuntu-condensed.ttf);
}

@font-face {
	font-family: open-sans-regular;
	src: url(../fonts/open-sans/open-sans-regular.ttf);
}

@font-face {
	font-family: inter-regular;
	src: url(../fonts/inter/inter-regular.ttf);
}

@font-face {
	font-family: quicksand-regular;
	src: url(../fonts/quicksand/quicksand-regular.ttf);
}

@font-face {
	font-family: quicksand-medium;
	src: url(../fonts/quicksand/quicksand-medium.ttf);
}

@font-face {
	font-family: quicksand-semibold;
	src: url(../fonts/quicksand/quicksand-semibold.ttf);
}

/***************************************************/
/* HTML ********************************************/
/***************************************************/


body {
	font-family: var(--font-normal);
	background-color: var(--color-bg-app);
	color: var(--color-text-primary);
	display: flex;
	flex-direction: column;
	height: 100vh;
}

h1, h2, h3, h4, h5 {
	font-weight: 600;
	display: block;
	margin: 0px;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

h1 {
	font-size: 130%;
}

h2 {
	font-size: 120%;
}

h3 {
	font-size: 110%;
}

hr {
	margin: 4px 0px;
	border-color: var(--color-border);
}


select[multiple] {
	font-family: var(--font-normal) !important;
	min-height: 130px;
	min-width: 100px;
	display: block;
}

/* Lista wielokrotnego wyboru ma pokazywać kilka pozycji naraz, a nie jedną. Regułę wyżej
   przebijała .form-control — ta sama swoistość, ale stoi niżej w pliku, więc jej min-height
   wygrywał i ściągał listę do wysokości zwykłego pola. Stąd osobna reguła o wyższej
   swoistości zamiast przenoszenia tamtej: dotyczy wszystkich sześciu okien z takim polem
   (strefy zakazane, profil trasowania, użytkownik, polisa, znacznik). */
select[multiple].form-control {
	min-height: 130px;
}

select {
	font-size: inherit;
	font-family: var(--font-normal) !important;
	vertical-align: top;
}

option {
	font-size: inherit;
	font-family: var(--font-normal) !important;
}

.bg-success {
	background-color: var(--color-success-soft-bg) !important;
}

.textarea {
	white-space: pre-line;
	max-height: 150px;
	overflow: auto;
	word-break: break-word;
	overflow-wrap: break-word;
	min-width: 120px;
}

textarea.form-control {
	min-height: 100px;
}

/***************************************************/
/* TABLES ******************************************/
/***************************************************/
table {
	width: 100%;
	cursor: default;
	background: var(--color-surface);
	margin-bottom: 0px;
}

thead {
	position: sticky;
	top: 0;
	z-index: 3;
	background: var(--color-surface);
	box-shadow: var(--shadow-thead);
}

th {
	padding: 2px;
	vertical-align: middle;
	/* outline (not border) so the rule renders correctly under
	   position: sticky thead and ignores border-collapse semantics */
	outline: 1px solid rgba(0, 0, 0, 0.08);
	outline-offset: -1px;
}


.table > tbody > tr > td, .table > tbody > tr > th, .table > tfoot > tr > td, .table > tfoot > tr > th, .table > thead > tr > td, .table > thead > tr > th {
	vertical-align: top;
	padding: 1px;
	text-align: center;
}

tr.dragover,
.item-block.dragover {
    background-color: var(--color-surface-highlight);
}

.table-responsive {
	border-radius: 8px;
	overflow-x: auto;
	-webkit-overflow-scrolling: touch;
}

table-content {
	display: block;
}

.table-centered-form-values td {
	text-align: center;
}

.table-centered-form-values td .form-box {
	text-align: center;
}

.table-centered-form-values td .form-value {
	justify-content: center;
	text-align: center;
}

th > .flex-item {
	display: block;
}

th > sort,
th > triple-price-sort {
	display: flex;
	flex-direction: column;
	justify-content: center;
	width: 100%;
	height: 100%;
}

th > label,
th > triple-price-sort label {
	display: flex;
	align-items: center;
	justify-content: center;
	text-align: center;
	margin: 0;
	padding: 2px 4px;
	background-color: transparent;
	color: inherit;
	border-radius: 4px;
	cursor: pointer;
	min-height: 28px;
	transition: background-color 0.2s ease;
}

th > label:hover,
th > triple-price-sort label:hover {
	background-color: rgba(0, 0, 0, 0.05);
}

/* An amount header without a base price has no <sort> menu — it is plain text: no pointer, no hover, and the
   same colour as the menu headers next to it (their trigger is a `.dropdown a`). */
th > triple-price-sort label.triple-price-sort-static {
	color: var(--color-text-secondary);
	cursor: default;
}

th > triple-price-sort label.triple-price-sort-static:hover {
	background-color: transparent;
}

/* When a <th> holds more than one <sort>, separate the rows with a thin
   divider so adjacent triggers don't visually merge in the now-transparent
   default state. */
th > .sort-dropdown + .sort-dropdown {
	border-top: 1px solid rgba(0, 0, 0, 0.08);
	margin-top: 2px;
	padding-top: 2px;
}

.sort-dropdown {
	width: 100%;
}

/* Full disambiguated column label ("pole [ścieżka]") shown as the sort dropdown's title — the column
   header itself shows only the last segment, so the dropdown carries the whole label. Small and
   distinct (semibold), wraps instead of forcing the menu wide. */
.sort-dropdown .dropdown-menu .dropdown-header {
	white-space: normal;
	word-break: break-word;
	max-width: 260px;
	font-size: var(--font-xs);
	font-weight: 600;
	letter-spacing: 0.02em;
}

.sort-trigger {
	display: flex;
	flex-direction: column;
	justify-content: center;
	width: 100%;
	padding: 2px 4px;
	margin: 2px 0px;
	background-color: transparent;
	border-radius: 4px;
	color: inherit;
	text-decoration: none;
	text-align: left;
	cursor: pointer;
	user-select: none;
	transition: background-color 0.2s ease;
}

/* Sort triggers inside a <th> stay centered (the canonical table-header look). */
th .sort-trigger {
	text-align: center;
}

/* A virtual component-column header renders as a bare .sort-text (no .sort-trigger wrapper), so it misses the
   `th .sort-trigger` centering above — centre it here so it aligns like the field headers. */
.custom-list th .sort-text {
	text-align: center;
}

.sort-trigger:hover,
.sort-trigger:focus {
	background-color: rgba(0, 0, 0, 0.05);
	color: inherit;
	text-decoration: none;
	outline: none;
}

.sort-text {
	display: -webkit-box;
	-webkit-line-clamp: 3;
	-webkit-box-orient: vertical;
	overflow: hidden;
	text-overflow: ellipsis;
	line-height: 1.2;
	max-height: calc(1.2em * 3);
	font-size: var(--font-sm);
	font-weight: 600;
	letter-spacing: 0.02em;
}

.sort-trigger.is-required .sort-text::after {
	content: " *";
	color: var(--color-danger-alt);
}

/* Ikony filtra i sortowania stoją w tekście etykiety, przed nazwą pola — jak ikona w chipie filtra — więc idą za
   wyrównaniem tekstu (środek nagłówka tabeli, prawa krawędź kolumny liczbowej, lewa w bloku listy). */
.sort-indicators {
	display: inline-flex;
	gap: 4px;
	margin-right: 4px;
	font-size: var(--font-xs);
	opacity: 0.7;
}

tbody > tr:hover > td {
	box-shadow: inset 0 0 0 9999px var(--color-row-hover);
	transition: box-shadow 0.15s ease;
}

.no-row-hover tbody > tr:hover > td {
	box-shadow: none;
	transition: none;
}

/* Bootstrap maluje tabelę zagnieżdżoną na biało (.table .table) i wiersz .table-hover na jasnoszaro —
   w ciemnym motywie pod jasnym tekstem dawało to tabelę nie do odczytania. Tabela zagnieżdżona bierze
   tło otoczenia, a podświetlenie wiersza daje wyłącznie reguła wyżej (--color-row-hover, oba motywy). */
.table .table,
.table-hover > tbody > tr:hover {
	background-color: transparent;
}

/* Pin last column to right edge so the row's action stays visible on horizontal scroll —
   only in a table whose last column holds a row action: the options menu (unt-dropdown) or the search tab's
   "Wybierz" button (modal-use-button) standing in a row's last cell marks the table through
   RowOptionsCellMarker (.has-row-options; .td-row-options on the cell only records which actions marked it).
   A table without such an action (last column is a plain value, another button, an empty cell) scrolls whole.
   In a marked table the last cell of EVERY body and footer row is pinned — also rows without a menu of
   their own (the sum row of the custom list, an add row) — so the right edge stays one straight column.
   Applied to main list tables ([colspan-table]), Bootstrap tables (.table) and the custom list
   (.sticky-last-col). Opt-out per table by adding class .no-sticky-last-col.
   Skip full-width cells (continuation/expanded rows) — matched by their own [colspan]
   attribute, NOT by tr:not(:has(td[colspan])): a :has() that any row mutation re-evaluates
   made every click/hover recompute styles for the whole table (~11 s at 100 rows). */
[colspan-table].has-row-options:not(.no-sticky-last-col) > thead > tr > th:last-child,
[colspan-table].has-row-options:not(.no-sticky-last-col) > tbody > tr > td:last-child:not([colspan]),
[colspan-table].has-row-options:not(.no-sticky-last-col) > tfoot > tr > td:last-child:not([colspan]),
.table.has-row-options:not(.no-sticky-last-col) > thead > tr > th:last-child,
.table.has-row-options:not(.no-sticky-last-col) > tbody > tr > td:last-child:not([colspan]),
.table.has-row-options:not(.no-sticky-last-col) > tfoot > tr > td:last-child:not([colspan]),
.sticky-last-col.has-row-options > thead > tr > th:last-child,
.sticky-last-col.has-row-options > tbody > tr > td:last-child:not([colspan]),
.sticky-last-col.has-row-options > tfoot > tr > td:last-child:not([colspan]) {
	position: sticky;
	right: 0;
	background-color: var(--color-surface);
	box-shadow: -4px 0 8px -2px var(--color-shadow);
	z-index: 2;
}

[colspan-table].has-row-options:not(.no-sticky-last-col) > thead > tr > th:last-child,
.table.has-row-options:not(.no-sticky-last-col) > thead > tr > th:last-child,
.sticky-last-col.has-row-options > thead > tr > th:last-child {
	z-index: 4;
}

/* Przyklejona komorka ma wlasne tlo (inaczej przewijana tresc bylaby pod nia widoczna), wiec w wyroznionym
   wierszu — z otwartym podgladem albo rozwinieta sekcja — musi wziac to samo tlo co reszta wiersza, zeby nie
   zostawiac jasnej wyrwy na jego koncu. */
[colspan-table].has-row-options:not(.no-sticky-last-col) > tbody > tr.active-preview > td:last-child:not([colspan]),
[colspan-table].has-row-options:not(.no-sticky-last-col) > tbody > tr.section-expanded > td:last-child:not([colspan]),
.table.has-row-options:not(.no-sticky-last-col) > tbody > tr.active-preview > td:last-child:not([colspan]),
.table.has-row-options:not(.no-sticky-last-col) > tbody > tr.section-expanded > td:last-child:not([colspan]),
.sticky-last-col.has-row-options > tbody > tr.active-preview > td:last-child:not([colspan]),
.sticky-last-col.has-row-options > tbody > tr.section-expanded > td:last-child:not([colspan]) {
	background-color: var(--color-surface-highlight);
}

.sticky-last-col.has-row-options > tbody > tr.cl-row-focused > td:last-child:not([colspan]) {
	background-color: var(--color-accent-soft-bg);
}

/* When a dropdown is open inside the sticky last column, raise the cell's z-index
   above other sticky cells (same z-index in later rows would otherwise overlay it)
   and above the sticky thead. The dropdown-menu inside (z-index: 1100) then floats freely.
   The .td-dropdown-open class is toggled from JS exactly where the open state changes
   (unt-dropdown component, field directive) — a td:last-child:has(.open) selector did
   this declaratively, but :has() re-matched styles across the whole table on every
   open/close class flip, freezing large lists for seconds. An unpinned last column needs
   no rule: its cell is not positioned, so it creates no stacking context and the
   dropdown-menu (z-index: 1100) already stands above the sticky thead (z-index: 3). */
[colspan-table].has-row-options:not(.no-sticky-last-col) > tbody > tr > td:last-child.td-dropdown-open,
.table.has-row-options:not(.no-sticky-last-col) > tbody > tr > td:last-child.td-dropdown-open,
.sticky-last-col.has-row-options > tbody > tr > td:last-child.td-dropdown-open {
	z-index: 1101;
}

/* Rows whose select-one-checkbox is checked get the same subtle tint as
   the hover state, so users can see what is currently selected. Scoped to
   <table-content> so the rule doesn't bleed into block-content layouts.
   .row-checked is toggled by the select-one-checkbox component — see the :has()
   performance note above. */
table-content tbody > tr.row-checked > td {
	box-shadow: inset 0 0 0 9999px rgba(0, 0, 0, 0.04);
	transition: box-shadow 0.15s ease;
}


td {
	border-top: 3px solid var(--color-border);
	padding: 2px 1px;
}

[colspan-table] tbody tr.freight-continuation > td {
	border-top: none;
}

/* Stacked field-like elements in a <td> need a small gap or they visually merge. */
td > field,
td > triple-price-field,
td > double-price-field,
td > save-address-button {
	display: block;
	margin: 2px 0;
}

.details-body table thead, .item-block table thead {
	position: unset;
	top: unset;
	z-index: unset;
	box-shadow: unset;
}

.light-green-background-color {
	background-color: var(--color-success-soft-bg);
}


.colspan-table-repeat-end-td {
	padding: 2px 8px 12px 8px;
}

.table-tr-collapse {
	padding: 8px 16px;
	background-color: var(--color-surface-alt);
	margin-bottom: 8px;
	box-shadow: rgba(0, 0, 0, 0.07) 0px 1px 1px, rgba(0, 0, 0, 0.07) 0px 2px 2px, rgba(0, 0, 0, 0.07) 0px 4px 4px, rgba(0, 0, 0, 0.07) 0px 8px 8px, rgba(0, 0, 0, 0.07) 0px 16px 16px;	
}

/***************************************************/
/* CUSTOM ** ***************************************/
/***************************************************/
.font-smaller {
	font-size: 90%;
}

/* "Dokąd jedzie" column — compact, centered, even spacing.
   The default .form-value is flex/space-between/text-left/min-width:40px, which broke the centering, so it is overridden here. */
.last-route-point {
	font-size: var(--font-xs);
	text-align: center;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 2px;
	line-height: 1.2;
}

.last-route-point .form-box {
	min-height: 0;
}

/* Wiersze podsumowania są tylko do odczytu i stoją jeden pod drugim, więc nie obowiązuje
   ich minimalna wysokość pola edytowalnego: przy foncie xs tekst zajmuje ~14px, a wymuszone
   24px dokładało do każdego z trzech wierszy dziesięć pikseli pustego miejsca i rozciągało
   komórkę listy o trzydzieści. Zeruje się tu samo minimum — padding i wyrównanie zostają. */
.last-route-point .form-value {
	justify-content: center !important;
	text-align: center !important;
	min-width: 0 !important;
	min-height: 0;
	padding: 0 !important;
}

.last-route-point .route-point-line {
	display: flex;
	flex-wrap: nowrap;
	align-items: center;
	justify-content: center;
	gap: 4px;
}

.last-route-point .route-point-line > div,
.last-route-point .route-point-line .form-value {
	width: auto !important;
}

.last-route-point .enum-image {
	width: 16px;
	height: 11px;
	margin-right: 4px;
}

/* Podsumowanie w wierszu transportu na liście zamówień stoi obok pojedynczych pól innych kolumn tego
   transportu, więc ma ich wysokość: mieści się w jednej linii, a transport bez punktu czy pozycji zostawia
   puste miejsce — inaczej wartości kolejnych transportów podjeżdżają pod cudze wiersze. */
.last-route-point-row {
	display: flex;
	align-items: center;
	justify-content: center;
	min-height: var(--form-min-height);
}

.last-route-point-row .last-route-point {
	flex-direction: row;
	white-space: nowrap;
	gap: 6px;
}

/* Pola podsumowania są elementami .flex-item, które dzielą szerokość wiersza po równo — w jednej linii
   mają zająć tyle, ile ich treść, inaczej data ucina się w swojej części, a reszta stoi rozsunięta. */
.last-route-point-row .last-route-point field,
.last-route-point-row .last-route-point field > div,
.last-route-point-row .last-route-point .form-box,
.last-route-point-row .last-route-point .route-point-line {
	flex: 0 0 auto;
	width: auto !important;
}

.last-route-point-row .last-route-point .form-value {
	overflow-x: visible;
}

.font-bigger {
	font-size: 110%;
}

/* route-points table header: xs size, primary text colour (same as sort), centred values */
.route-points-header th {
	font-size: var(--font-xs);
	color: var(--color-text-primary);
	text-align: center;
}
/***************************************************/
/* BOOTSTRAP ***************************************/
/***************************************************/
.badge {
	font-size: var(--font-xs);
	font-weight: unset;
	padding: 0px 4px;
	margin: 0px 2px 0px 4px;
	line-height: unset;
	background-color: var(--color-danger-alt);
	color: var(--color-text-inverse);
}

.close {
	opacity: 0.5;
}

.row {
	margin: 0px 0px;
	padding: 0px 0px;
}

.nav-tabs {
	padding:1px 0px 0px 1px;
	cursor: pointer;
	width: 100%;
	border-bottom: 1px solid var(--color-border);
}

/* Bootstrap pulls each tab down 1px (margin-bottom: -1px) so it overlaps the
   bottom border line — drop it so tabs sit on the line instead of over it. */
.nav-tabs>li {
	margin-bottom: 0;
}

.nav-tabs>li>a {
	background-color: var(--color-surface);
	color: var(--color-text-muted);
	border: 1px solid var(--color-surface-highlight);
	border-bottom: 3px solid var(--color-surface);
	margin-bottom: 1px;
	min-width: 120px;
	text-align: center;
	padding: 4px 8px;	
	margin: 4px 1px 0px 1px;
}

.nav-tabs>li.active>a, .nav-tabs>li.active>a:focus, .nav-tabs>li.active>a:hover  {
	cursor: default;
	border: 1px solid var(--color-accent);
	border-bottom: 3px solid var(--color-accent);
	background-color: var(--color-surface-highlight);
	color: var(--color-text-primary);
	font-weight: 600;
}

.nav-tabs>li:not(.active)>a:hover {
	border: 1px solid #6263D5;
	border-bottom: 3px solid #6263D5;
	background-color: var(--highlight-background-color);
}

[class^="col-lg-"],
[class^="col-md-"],
[class^="col-sm-"],
[class^="col-xs-"],
[class*=" col-lg-"],
[class*=" col-md-"],
[class*=" col-sm-"],
[class*=" col-xs-"] {
  padding: 0 2px;
}


.btn {
	margin: 1px 1px;
	padding: 4px 8px;
	font-size: inherit;	
	-webkit-user-select: text;
	-moz-user-select: text; 
	user-select: text;	
}

.btn-text-left {
	text-align: left;
}

input[type="checkbox"], input[type="radio"] {
	margin: 4px 4px;
}

.badge-primary {
	background-color: var(--color-accent-bg);
	color: var(--color-text-inverse);
}

.list-group {
	margin-bottom: 0px;
}

.list-group.rolled-up {
	max-height: 250px;
	overflow-y: auto;
}

.list-group-item {
	margin: 2px 0px 2px 0px;
	padding: 0px 2px;
}

.d-none {
	display: none !important;
}

.d-block {
	display: block !important;
}

@media ( min-width : 992px) {
	.d-lg-block {
		display: block !important;
	}
}

/***************************************************/
/* GRID*********************************************/
/***************************************************/

.wrapper {
	display: grid;
	/* Single column capped at the viewport (min 0) so wide content — e.g. the
	   favourites bar scrolling on its own row — can't blow the grid column out
	   past the screen and push the topbar's right-hand icons off. */
	grid-template-columns: minmax(0, 1fr);
}

.topbar {
	height: 50px;
	background-color: var(--color-sidebar-bg);
	border-bottom: 1px solid var(--color-chrome-edge);
}

/* public pages: pin the paginator to the bottom of the screen while the list scrolls */
.public-paginator {
	position: sticky;
	bottom: 0;
	z-index: 100;
	background: var(--color-surface);
}

/* public pages: pin the topbar to the top of the screen, vertically center its elements */
.public-topbar {
	position: sticky;
	top: 0;
	z-index: 1030;
	display: flex;
	align-items: center;
	flex: 0 0 auto;
}

/* Strona publiczna bez połączenia z serwerem (public-server-connection): komunikat nad paskiem, na całą szerokość. */
.public-server-connection {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	z-index: 2000;
	margin: 0;
	border-radius: 0;
	text-align: center;
}

/* Przełącznik motywu w pasku strony publicznej (public-theme-switcher). */
.public-topbar .public-theme-toggle {
	background-color: transparent;
	border: none;
	color: #ffffff;
	margin: 4px;
}

/* Public contract-vehicle list: full-height frame — topbar pinned top, only the list scrolls, paginator pinned to the bottom of the screen. Scoped via :has() so other public pages keep their normal flow. */
.public-frame:has(public-transport-contract-vehicle-by-transport-contract-list),
.public-wrapper:has(public-transport-contract-vehicle-by-transport-contract-list),
[ng-view]:has(public-transport-contract-vehicle-by-transport-contract-list),
public-transport-contract-details,
.public-contract-page,
public-transport-contract-vehicle-by-transport-contract-list,
public-transport-contract-vehicle-by-transport-contract-list paginated-list {
	display: flex;
	flex-direction: column;
	flex: 1 1 auto;
	min-height: 0;
}

public-transport-contract-vehicle-by-transport-contract-list ng-transclude {
	display: block;
	flex: 1 1 auto;
	min-height: 0;
	overflow-y: auto;
}

.public-list-title {
	flex: 0 0 auto;
	padding-left: 12px;
	padding-right: 12px;
}

/* Public full-height list page (body class set by the view): topbar pinned top, only the table
   scrolls — the thead stays sticky inside it — and the paginator sits at the bottom of the screen.
   Same shape as the logged-in lists (.app-content-data > .list-block). */
body.public-list-page .public-wrapper {
	height: 100vh;
	display: flex;
	flex-direction: column;
	overflow: hidden;
}

body.public-list-page .public-wrapper > [ng-view],
body.public-list-page [ng-view] > public-repair-list,
body.public-list-page .public-list-page,
body.public-list-page .public-list-page > paginated-list,
body.public-list-page .public-list-page > paginated-list > ng-transclude {
	flex: 1 1 auto;
	min-height: 0;
	display: flex;
	flex-direction: column;
}

body.public-list-page .public-list-page > paginated-list > ng-transclude > .table-responsive {
	flex: 1 1 auto;
	min-height: 0;
	overflow: auto;
}

/* Uwagi do floty bywaja wielolinijkowe (setki znakow); bez limitu jeden wpis rozciagal tabele panelu na
   kilka tysiecy pikseli i wypychal ostatnie kolumny poza ekran. Pelna tresc jest w tooltipie. */
body.public-list-page .public-list-note {
	max-width: 360px;
	white-space: normal;
	overflow-wrap: anywhere;
	display: -webkit-box;
	-webkit-line-clamp: 3;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

/* Awaria public/bootstrap: AngularJS jeszcze nie wstal, wiec komunikat stoi w statycznej powloce. */
.public-bootstrap-error {
	padding: 24px 16px;
	text-align: center;
	font-size: 18px;
	color: var(--color-danger);
}

/* Ankieta z linku: przy wielu pytaniach treść jest wyższa niż ekran, a body ma stałe 100vh, więc bez
   własnego kontenera przewijania pytania wychodziły poza malowane tło strony. Ramka rośnie na pełną
   wysokość, topbar zostaje przypięty u góry, a przewija się obszar widoku — scrollbar stoi wtedy przy
   krawędzi okna, tak jak przy zwykłym przewijaniu strony. Zakres przez :has(), żeby pozostałe strony
   publiczne zachowały normalny przepływ. */
.public-frame:has(public-survey),
.public-wrapper:has(public-survey) {
	display: flex;
	flex-direction: column;
	flex: 1 1 auto;
	min-height: 0;
}

.public-wrapper:has(public-survey) > [ng-view] {
	flex: 1 1 auto;
	min-height: 0;
	overflow-y: auto;
}

/* Ankieta wypełniana z linku: jedna kolumna pytań, czytana zwykle na telefonie w drodze — stąd wąska
   kolumna, duże odstępy między pytaniami i pola na pełną szerokość. */
.public-survey-page {
	max-width: 800px;
	margin: 0 auto;
	padding: 12px;
}

.public-survey-question {
	border-bottom: 1px solid var(--color-border);
	padding: 12px 0;
}

/* Treść pytania i tytuł ankiety stoją w nagłówkach, a te globalnie ucinają się wielokropkiem. Na stronie
   wypełnianej z linku każde słowo pytania musi być widoczne — tu nagłówek zawija się na kolejne wiersze,
   a nierozdzielny ciąg (np. wklejony adres) łamie się zamiast rozpychać kolumnę. */
.public-survey-question h3,
.public-survey-page .public-list-title h1 {
	white-space: normal;
	overflow: visible;
	text-overflow: clip;
	overflow-wrap: break-word;
}

.public-survey-required {
	color: var(--color-danger);
}

.public-survey-filled {
	background: var(--color-success-soft-bg);
	color: var(--color-success);
	border-radius: 0.5em;
	margin-bottom: 12px;
	padding: 12px;
}

.public-survey-options label {
	display: inline-block;
	font-weight: normal;
	margin-right: 16px;
}

.public-survey-photos {
	margin-top: 8px;
}

.public-survey-photos-required {
	color: var(--color-text-muted);
	font-size: var(--font-sm);
}

.public-survey-actions {
	padding: 16px 0;
	text-align: center;
}

/* paginator: vertically center all its elements */
.app-content-footer > .row {
	display: flex;
	align-items: center;
}

.app-topbar {
	height: 100%;
	width: 100%;
	align-items: center;
	display: flex;
	flex-wrap: nowrap;
	padding: 0px 8px 0px 8px;
}

/* Strona przeciągana z menu bocznego: topbar, na który ją upuszczono, doda ją do ulubionych. */
body.unt-drag-active .app-topbar.unt-dragover {
	box-shadow: inset 0 0 0 2px var(--color-accent);
	background: var(--color-accent-soft-bg);
}

.app-topbar > .inline {
	flex-wrap: nowrap;
	flex-shrink: 0;
}

.app-topbar > .inline:last-child {
	margin-left: auto;
}

.app-topbar .btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	white-space: nowrap;
	flex-shrink: 0;
	height: 36px;
	min-width: 36px;
	padding: 0 8px;
	font-size: 1em;
	line-height: 1;
}

.app-topbar .btn.btn-sidebar-toggle {
	height: var(--topbar-height);
}

.app-topbar .btn > i {
	font-size: 1.15em;
	line-height: 1;
}

.app-topbar .btn > .badge {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 18px;
	height: 18px;
	padding: 0 6px;
	margin: 0 0 0 6px;
	border-radius: 9px;
	font-size: 11px;
	line-height: 1;
}

#sidebar {
	overflow: hidden;
	width: var(--sidebar-width);
	transition: width var(--sidebar-transition);
}

#content {
	display: flex;
	height: calc(100vh - var(--topbar-height));
	/* dvh nadaza za chowanymi paskami przegladarki i — z interactive-widget=resizes-content — za wirtualna
	   klawiatura; 100vh zostaje dla przegladarek, ktore dvh nie znaja. */
	height: calc(100dvh - var(--topbar-height));
}

.app-content {
	padding: 0px;
	width: calc(100vw - var(--sidebar-width));
	overflow: auto;
	display: flex;
	flex-direction: column;
	height: 100%;
	transition: width var(--sidebar-transition);
}

.app-content-header {
	min-height: 40px;
	display: flex;
	flex-wrap: nowrap;
	align-items: center;
	padding: 0px 8px 0px 8px;
	gap: 6px;
}

.app-content-header > .inline:first-child {
	flex: 0 1 auto;
	min-width: 0;
	overflow: hidden;
}

.app-content-header > .inline:first-child h1 {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.app-content-header-buttons {
	flex: 1 1 auto;
	display: flex;
	flex-wrap: nowrap;
	justify-content: flex-end;
	align-items: center;
	gap: 6px;
	min-width: 0;
}

.app-content-header-buttons > *,
.app-content-header-buttons .btn {
	flex-shrink: 0;
	white-space: nowrap;
}

/* Przełącznik układów i „Konfiguruj kolumny" są elementami rzędu przycisków, nie opakowania — select
   (.form-control, display: block) spychał inaczej przycisk do drugiej linii. */
.app-content-header-buttons custom-list-configure-button {
	display: contents;
}

.app-content-data {
	height: calc(100vh - 50px - 20px - 60px);
	border-bottom: 1px solid var(--color-border);
    display: flex;
    flex-direction: column;	
}

.app-content-footer {
	display: grid;	
	align-items: center;	
	overflow: hidden;
	border-top: 1px solid var(--color-border);
	padding-top: 4px;
}

#topbarContent {
	padding: 0px 0px 12px 0px;
}

.details-body {
	display: grid;
	grid-template-rows: auto 1fr;
	height: calc(100vh - 50px);
}

.details-topbar {
	width: 100%;
	overflow: hidden;
	background-color: var(--color-bg-app);
	box-shadow: var(--shadow-card);
	position: relative;
	z-index: 154;
}

/* Topbar detali: 12-torowa siatka CSS zamiast floatow bootstrapa — pola
   trzymaja rowne wiersze niezaleznie od wysokosci wartosci (floaty
   zaczepialy kolejne kolumny o wyzsze pola). Spany wg klas col-lg-N. */
.content-box-details-topbar .row:not(.content-box-header) {
	display: grid;
	grid-template-columns: repeat(12, minmax(0, 1fr));
	column-gap: 8px;
	/* Ujemne marginesy bootstrapowego .row kompensowaly paddingi kolumn,
	   ktore siatka zeruje — bez tego wiersze wystawalyby 15px poza kontener. */
	margin-left: 0;
	margin-right: 0;
}

/* Clearfix bootstrapa (::before/::after z display:table) w kontenerze grid
   stalby sie elementem siatki i zajmowal pierwszy tor, przesuwajac pola. */
.content-box-details-topbar .row:not(.content-box-header)::before,
.content-box-details-topbar .row:not(.content-box-header)::after {
	content: none;
}

.content-box-details-topbar .row:not(.content-box-header) > * {
	grid-column-end: span 12;
	min-width: 0;
	width: auto;
	float: none;
	padding-left: 0;
	padding-right: 0;
}

@media (min-width: 1200px) {
	.content-box-details-topbar .row:not(.content-box-header) > .col-lg-1 {
		grid-column-end: span 1;
	}
	.content-box-details-topbar .row:not(.content-box-header) > .col-lg-2 {
		grid-column-end: span 2;
	}
	.content-box-details-topbar .row:not(.content-box-header) > .col-lg-3 {
		grid-column-end: span 3;
	}
	.content-box-details-topbar .row:not(.content-box-header) > .col-lg-4 {
		grid-column-end: span 4;
	}
	.content-box-details-topbar .row:not(.content-box-header) > .col-lg-6 {
		grid-column-end: span 6;
	}
	.content-box-details-topbar .row:not(.content-box-header) > .col-lg-offset-1 {
		grid-column-start: 2;
	}
}

/* Pasek tytulu detali: strona tytulowa moze sie kurczyc (h1 ma globalny
   ellipsis, ale flex item z min-width:auto nigdy nie schodzil ponizej tresci),
   a blok przyciskow trzyma jeden wiersz i nie jest sciskany. */
.details-topbar .content-box-header .field-horizontal {
	flex: 1 1 auto;
	min-width: 0;
	/* Bazowy .field-horizontal ma space-between — po rozciagnieciu flexem
	   odsuwaloby to tytul od lewej krawedzi w strone przyciskow. */
	justify-content: flex-start;
}

.details-topbar .content-box-header .field-horizontal > span {
	min-width: 0;
}

.details-topbar .content-box-header .inline.text-right {
	flex-shrink: 0;
}

/* bez klasy .in — przyciski nagłówka nie są już ukrywane przy zwiniętej sekcji */
.details-topbar .content-box-header ng-transclude[ng-transclude-slot="headerButtons"] {
	display: inline-flex;
	flex-wrap: nowrap;
	align-items: center;
	gap: 4px;
}

/* Zamknięcie okna podglądu: okno nie ma własnego paska nagłówkowego (tytuł niesie widok
   detali), więc przycisk stoi w rogu nad treścią — w linii z nagłówkiem detali pod nim. */
.entity-details-modal {
	position: relative;
	/* Szerokość przycisku zamknięcia i jego odsunięcie od krawędzi — jedno źródło prawdy dla samego
	   przycisku i dla rezerwacji miejsca w pasku akcji detali pod nim (.details-topbar-header niżej).
	   Bez tego szerokość brała się z paddingu .btn i rozmiaru glifu, więc zmiana przycisku po cichu
	   zjadała zapas rezerwacji i przywracała przykrywanie ostatniej akcji. */
	--details-modal-close-size: 26px;
	--details-modal-close-offset: 10px;
	/* Stala wysokosc okna, bo tresc detali doplywa dopiero odpowiedzia serwera: bez niej okno
	   otwiera sie niskie (zmierzone 417 px), a po wczytaniu skacze do 938 px — i to podskoczenie
	   wyglada jak "niedorobione" ladowanie. Przewija sie .details-content w srodku, dokladnie jak
	   na stronie detali, wiec stala wysokosc niczego nie obcina. Odjete 60 px to marginesy dialogu. */
	height: calc(100vh - 60px);
	max-height: calc(100vh - 60px);
}

.entity-details-modal-close {
	position: absolute;
	top: 6px;
	right: var(--details-modal-close-offset);
	width: var(--details-modal-close-size);
	z-index: 160;
}

/* Zaslona ladowania okna podgladu: detale wchodza do okna puste i wypelniaja sie dopiero
   odpowiedzia serwera, wiec bez niej uzytkownik oglada, jak widok sklada sie z pustych pol.
   Znika, gdy widok detali zglosi wczytanie rekordu (wyjscie on-loaded). Spinner ten sam, co przy pierwszym
   ladowaniu listy (.list-spinner) — to samo czekanie na dane wyglada wszedzie tak samo.
   z-index nizszy niz przycisk zamkniecia, zeby okno dalo sie zamknac w trakcie ladowania. */
.entity-details-modal-loader {
	position: absolute;
	inset: 0;
	z-index: 159;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 16px;
	background: var(--color-bg-app);
	border-radius: inherit;
	color: var(--color-text-muted);
}

/* Zamknięcie okna leży nad paskiem akcji detali (position: absolute), więc pasek musi zostawić mu
   miejsce z prawej — inaczej przykrywa swój ostatni przycisk akcji: przy zamówieniu transportu
   „Opcje zamówienia transportu" kończyło się na 1553 px, a przycisk zamknięcia zaczyna się na
   1521 px, więc etykieta renderowała się ucięta. Rezerwacja liczy się ze zmiennych przycisku, więc
   rośnie razem z nim; stały jest tylko odstęp między nimi.
   Celuje w klasę, a nie w każdy nagłówek wewnątrz .details-topbar: w slocie topbarContent stoją
   nagłówki sekcji (freight-details), których zamknięcie nie zasłania — te zostają przy swoich 4 px
   z .modal-body .row. Klasę nadaje wyłącznie nagłówek paska akcji, w
   details-view-content.component.html. Selektor wymienia też .row, bo właśnie z tamtą regułą
   konkuruje: ma tę samą specyficzność i stoi niżej w pliku, więc bez .row wygrywa jej 4 px. */
.entity-details-modal .row.details-topbar-header {
	padding-right: calc(var(--details-modal-close-size) + var(--details-modal-close-offset) + 6px);
}

/* Detale renderowane w oknie podglądu: wysokość daje okno, nie ekran. Bez tego .details-body
   (calc(100vh - 50px)) jest wyższa niż okno, więc przewija się samo ciało okna i zabiera ze sobą
   pasek nagłówkowy — przewijać ma się wyłącznie .details-content pod nim, jak na stronie. */
.modal-content > .modal-body[entity-details] {
	display: flex;
	flex-direction: column;
	overflow: hidden;
	min-height: 0;
	padding: 0;
}

/* Między ciałem okna a siatką detali stoi komponent encji i jego opakowanie z ng-init —
   oba muszą przepuścić wysokość w dół, inaczej siatka zostaje przy swoim calc(100vh) i
   ciało okna przewija się razem z paskiem. */
.modal-body[entity-details] > *,
.modal-body[entity-details] > * > div,
.modal-body[entity-details] details-view-content {
	display: flex;
	flex-direction: column;
	flex: 1 1 auto;
	min-height: 0;
}

.modal-body[entity-details] .details-body {
	flex: 1 1 auto;
	height: auto;
	min-height: 0;
}

/* Okno z detalami przewozu układa się jak strona detali: pasek zamówienia stoi w miejscu,
   przewija się treść pod nim — i to ona jest kontenerem dla przyklejonego nagłówka przewozu.
   Wysokość daje .modal-content (cap na całe okno), więc calc(100vh) z .details-body się tu
   nie powtarza. */
.modal-content > .modal-body.details-window {
	display: grid;
	grid-template-rows: auto 1fr;
	overflow: hidden;
	padding: 0;
}

.details-window > .details-content {
	min-height: 0;
}

.details-content {
	overflow-y: auto;
	overflow-x: hidden;
	width: 100%;
	padding-bottom: 50px;
	background-color: var(--color-bg-app);
}

.vehicle-actions-icons {
	display: inline-flex;
	gap: 2px;
	margin-left: 6px;
	vertical-align: middle;
}

.lazy-map-prompt {
	padding: 24px;
	text-align: center;
}

/* Treść dymków mapy (<map-popup>) czeka tu, dopóki mapa nie poda jej dymkowi Google / Leafleta — dymek
   przenosi węzeł do siebie, więc widoczny jest tylko tam. */
.map-popup-holder {
	display: none;
}

/* Leaflet popup used as "insert transit point" context menu on OSM map — leave
   room for the close button (X) and keep the action button on a single line. */
.transit-point-insert-popup .leaflet-popup-content {
	margin: 8px 24px 8px 8px;
}

.transit-point-insert-popup .leaflet-popup-content > a.btn {
	white-space: nowrap;
}

.transit-point-insert-modal .content-box {
	margin: 0;
}

/* Lista pozycji wstawienia (punkt przejazdowy, szablon drogi) jest WIDGETEM, nie częścią
   jednego modala: te same klasy niesie modal wstawienia punktu i modal wstawienia szablonu
   drogi. Reguły były zawężone do .transit-point-insert-modal, więc w drugim z nich lista
   renderowała się bez stylu — z punktorami i niewyśrodkowanymi przyciskami. Sąsiednie reguły
   tego samego widoku (.transit-point-mini-map, .transit-point-route-summary) od początku stoją
   bez zawężenia. */
.transit-point-insert-list {
	list-style: none;
	padding: 0;
	margin: 0;
}

.transit-point-insert-row {
	display: flex;
	align-items: flex-start;
	gap: 8px;
	padding: 4px 8px;
}

.transit-point-insert-icon {
	width: 16px;
	text-align: center;
}

.transit-point-insert-row.stop .transit-point-insert-icon {
	color: var(--color-danger-alt);
}

.transit-point-insert-row.transit .transit-point-insert-icon {
	color: var(--color-success);
}

.transit-point-insert-details {
	flex: 1;
	min-width: 0;
}

.transit-point-insert-meta {
	font-size: 12px;
	color: var(--color-text-muted);
}

.transit-point-insert-meta > span:not(:last-child)::after {
	content: " · ";
}

.transit-point-insert-gap {
	text-align: center;
	padding: 4px 0;
}

.vehicle-marker-popup,
.stop-marker-popup,
.traveled-point-popup,
.shape-point-marker-popup,
.transit-point-marker-popup {
	font-size: 11px;
	line-height: 1.4;
	white-space: nowrap;
}

.vehicle-marker-popup > div,
.stop-marker-popup > div,
.traveled-point-popup > div,
.shape-point-marker-popup > div,
.transit-point-marker-popup > div {
	margin-bottom: 2px;
}

/* Wskazany pojazd — ten, ktorego wiersz jest wybrany na liscie obok. Poswiata odroznia go od pozostalych
   ikon, ktore roznia sie tylko kolorem statusu; biala warstwa pod spodem odcina ikone od akcentu, zeby
   wyroznienie bylo widoczne takze na ciemnej mapie. Sam rozmiar nie wystarczal, gdy auta stoja obok siebie. */
.map-marker-focused {
	filter: drop-shadow(0 0 2px var(--color-surface)) drop-shadow(0 0 4px var(--color-accent)) drop-shadow(0 0 7px var(--color-accent));
}

/* Pierwsza linia dymka niesie tozsamosc punktu — pojazd, numer i termin przystanku — wiec wyroznia sie
   od reszty opisu. */
.vehicle-marker-popup .popup-title,
.stop-marker-popup .popup-title {
	font-weight: bold;
}

/* Opis punktu trasy niesie referencję, wymiary, ADR i kontakt w osobnych liniach. Dymek nie łamie
   tekstu (nowrap), więc cały opis zlewał się w jedną długą linię; tu łamie się tylko tam, gdzie opis
   ma nową linię, a szerokość dymka wyznacza najdłuższa z nich — jak pozostałe wiersze dymka. Tak
   samo przy przystanku i przy punkcie przejazdowym. */
.stop-marker-popup .popup-point-info,
.transit-point-marker-popup .popup-point-info {
	white-space: pre;
}

.popup-actions {
	margin-top: 4px;
	display: flex;
	flex-wrap: wrap;
	gap: 2px;
}

/* coords-actions is a wrapper component; let its buttons flow as flex items of .popup-actions */
.popup-actions coords-actions {
	display: contents;
}

.popup-actions .btn {
	flex: none;
}

/* Kierowca w dymku pojazdu: pozostały czas jazdy i pracy stoi w jednej linii z nazwiskiem. */
.marker-popup-driver-time {
	margin-left: 6px;
}

/* Rezerwacje zestawu w dymku to przycisk w rzędzie akcji, za odnośnikiem do detali — nie pasek na całą
   szerokość jak na liście zestawów. */
.popup-actions vehicle-combination-reservation-handler {
	flex: none;
}

.popup-actions vehicle-combination-reservation-handler .btn-fill-container {
	width: auto;
}

.map-context-menu {
	display: flex;
	flex-direction: column;
	gap: 4px;
}

.transit-point-latlng-row {
	display: flex;
	gap: 4px;
}

.transit-point-mini-map-box {
	margin-bottom: 8px;
}

.transit-point-mini-map {
	display: block;
	z-index: 1;
}

/* Planer parkingów (10853): podsumowanie kierowcy nad mapą i listą, mapa obok listy kandydatów. */
.parking-planner-summary {
	display: flex;
	flex-wrap: wrap;
	gap: 4px 16px;
	margin-bottom: 8px;
}

.parking-planner-map-box {
	position: relative;
	height: 480px;
	overflow: hidden;
	margin-bottom: 8px;
}

.parking-planner-map {
	display: block;
	height: 100%;
	z-index: 1;
}

.parking-planner-toolbar {
	display: flex;
	flex-wrap: wrap;
	justify-content: space-between;
	align-items: center;
	gap: 8px;
	margin-bottom: 6px;
}

.parking-planner-table {
	max-height: 520px;
	overflow-y: auto;
}

.parking-planner-table .status-pill {
	display: inline-block;
	min-width: 92px;
	white-space: nowrap;
	text-align: center;
}

/* Planer tankowań (10851): podsumowanie pojazdu nad mapą i listą, filtry nad tabelą stacji. */
.fuel-planner-summary {
	display: flex;
	flex-wrap: wrap;
	gap: 4px 16px;
	margin-bottom: 8px;
}

.fuel-planner-map-box {
	position: relative;
	height: 480px;
	overflow: hidden;
	margin-bottom: 8px;
}

.fuel-planner-map {
	display: block;
	height: 100%;
	z-index: 1;
}

.fuel-planner-toolbar,
.fuel-planner-filters {
	display: flex;
	flex-wrap: wrap;
	justify-content: space-between;
	align-items: center;
	gap: 8px;
	margin-bottom: 6px;
}

.fuel-planner-filters {
	justify-content: flex-start;
}

.fuel-planner-filters label {
	display: inline-flex;
	align-items: center;
	gap: 4px;
	margin: 0;
	font-weight: normal;
}

.fuel-planner-table {
	max-height: 520px;
	overflow-y: auto;
}

.fuel-planner-table .status-pill {
	display: inline-block;
	white-space: nowrap;
	text-align: center;
}

/* Pigułka alertu planera parkingów (10854): rodzaj alertu i akcje w jednej linii komórki listy. */
.parking-alert-pill {
	display: inline-flex;
	align-items: center;
	gap: 2px;
	white-space: nowrap;
}

/* Sterowanie mapą transportu — planowanie kolejności i trasa przebyta w jednej linii nad mapą. */
.freight-map-controls {
	display: flex;
	align-items: center;
	justify-content: flex-end;
	flex-wrap: wrap;
	gap: 6px;
}

.freight-planning-bar {
	display: inline-flex;
	align-items: center;
	gap: 6px;
}

.freight-planning-start {
	width: 70px;
}

.freight-planning-count {
	min-width: 24px;
	text-align: center;
	font-weight: bold;
}

/* Pasek rysowania strefy: wybór kształtu i promień okręgu, nad samą mapą. */
.zone-draw-controls {
	display: flex;
	align-items: center;
	gap: 6px;
	margin-bottom: 6px;
}

.zone-radius {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	margin-left: 10px;
}

.zone-radius-input {
	width: 80px;
}

/* Czym trasa poprowadzona ręcznie różni się od wyliczonej: kilometry, czas, opłaty — każda
   różnica osobno, obok znacznika ręcznej modyfikacji. */
.freight-manual-route-difference {
	margin-left: 10px;
	font-weight: bold;
	white-space: nowrap;
}

/* Kilometry z mapy w trakcie przeliczania trasy są z poprzedniej trasy — przygaszone, żeby nie
   udawały aktualnych. */
.freight-route-distance-pending {
	opacity: 0.5;
}

/* Szablon drogi: zaznaczenie punktu (numer = kolejność klikania), podgląd w modalu i mapa w detalach. */
.pattern-route-point-checkbox {
	white-space: nowrap;
}

.pattern-route-preview-map {
	display: block;
	z-index: 1;
}

/* Mapy tras pod listą: podgląd szablonu w modalu, mapa szablonu i mapa przesyłki w detalach —
   ten sam odstęp od treści nad nimi i ten sam wiersz z dystansem nad mapą (wysokość mapy z .map-box). */
.pattern-route-preview,
.pattern-route-map,
.cargo-details-map {
	margin-top: 8px;
}

.pattern-route-preview-summary,
.pattern-route-map > .flex,
.cargo-details-map > .flex {
	gap: 8px;
	font-size: 12px;
	margin-bottom: 4px;
}

/* Punkty podglądu szablonu: numer w kolejności zaznaczenia, nazwa i — gdy dojazd do punktu
   jest wykluczony z dystansu — oznaczenie, którego sama mapa nie pokazuje. */
.pattern-route-preview-points {
	list-style: none;
	margin: 0 0 4px;
	padding: 0;
	font-size: 12px;
}

.pattern-route-preview-points > li {
	display: flex;
	align-items: baseline;
	gap: 6px;
	padding: 1px 0;
}

.pattern-route-preview-seq {
	flex: none;
	min-width: 16px;
	text-align: right;
	color: var(--color-text-muted);
}

/* Nazwa oddaje miejsce oznaczeniu wykluczenia, a nie odwrotnie: nazwa się skraca wielokropkiem,
   oznaczenie zostaje całe, bo bez niego wiersz nie mówi tego, po co tu jest. */
.pattern-route-preview-name {
	flex: 1;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.pattern-route-preview-skip {
	flex: none;
}

/* Dystans i czas trasy pod mini-mapą modalu wstawiania punktu: obecnej i tej po wstawieniu. */
.transit-point-route-summary {
	margin-top: 6px;
	font-size: 12px;
}

/* Leaflet popup: 4px corners, allow auto-width for our popups, leave room for X.
   Tło/tekst/ogonek czytają tokeny — biały w light, ciemna powierzchnia w dark mode. */
.leaflet-popup-content-wrapper {
	border-radius: 4px;
	background-color: var(--color-surface);
	color: var(--color-text-primary);
}

.leaflet-popup-tip {
	background-color: var(--color-surface);
}

.leaflet-popup-close-button {
	color: var(--color-text-secondary);
}

.leaflet-popup-content:has(.vehicle-marker-popup),
.leaflet-popup-content:has(.stop-marker-popup),
.leaflet-popup-content:has(.traveled-point-popup),
.leaflet-popup-content:has(.shape-point-marker-popup),
.leaflet-popup-content:has(.transit-point-marker-popup) {
	max-width: none !important;
	width: auto !important;
	margin: 6px 22px 6px 8px;
}

/* Google Maps InfoWindow: 4px corners + compact close button (insert-transit-point context menu).
   Tło/tekst/ogonek/krzyżyk czytają tokeny — w light mode = obecny biały dymek,
   w dark mode (html[data-theme="dark"]) automatycznie ciemna powierzchnia. */
.gm-style .gm-style-iw-c {
	border-radius: 4px !important;
	padding: 4px 8px !important;
	background-color: var(--color-surface) !important;
	color: var(--color-text-primary) !important;
}

.gm-style .gm-style-iw-c .gm-ui-hover-effect {
	width: 18px !important;
	height: 18px !important;
	top: 2px !important;
	right: 2px !important;
}

.gm-style .gm-style-iw-c .gm-ui-hover-effect > span {
	width: 14px !important;
	height: 14px !important;
	margin: 2px !important;
	background-color: var(--color-text-secondary) !important;
}

.gm-style .gm-style-iw-d {
	overflow: hidden !important;
	padding-right: 18px;
	background-color: var(--color-surface) !important;
	color: var(--color-text-primary) !important;
}

/* Ogonek dymka (trójkąt pod bąblem) — musi mieć ten sam kolor co powierzchnia. */
.gm-style .gm-style-iw-tc::after {
	background: var(--color-surface) !important;
}

/* Sticky stack inside freight-order-details:
   1. .sticky-freight-tabs       — freight nav-tabs at the top of the scroll area
   2. .sticky-freight-overview   — transport "Ogólne" collapsible
   3. .freight-stops-host header — only the stops collapsible HEADER (title + buttons)
   All have an opaque background and the overview has an upward box-shadow
   that covers any sub-pixel gap above so scrolling content doesn't peek. */
.details-content .sticky-freight-tabs {
	margin: 0;
}

/* Siatka jak w topbarze detali: pola układają się po cztery w rzędzie niezależnie od
   wysokości wartości, zamiast bootstrapowych floatów zaczepiających się o wyższe pola. */
.sticky-freight-overview .row:not(.content-box-header) {
	display: grid;
	grid-template-columns: repeat(12, minmax(0, 1fr));
	column-gap: 8px;
	margin-left: 0;
	margin-right: 0;
}

.sticky-freight-overview .row:not(.content-box-header)::before,
.sticky-freight-overview .row:not(.content-box-header)::after {
	content: none;
}

.sticky-freight-overview .row:not(.content-box-header) > * {
	grid-column-end: span 12;
	min-width: 0;
	width: auto;
	float: none;
	padding-left: 0;
	padding-right: 0;
}

@media (min-width: 1200px) {
	.sticky-freight-overview .row:not(.content-box-header) > .col-lg-3 {
		grid-column-end: span 3;
	}
}

/* Ten sam odcień i obramowanie co topbar detali (.content-box-details-topbar) —
   oba paski niosą dane nagłówkowe, więc mają odróżniać się od treści pod nimi. */
.details-content .sticky-freight-overview {
	background-color: var(--color-border);
	border-top: 1px solid var(--color-border-strong);
	border-bottom: 1px solid var(--color-border-strong);
	border-left: 3px solid var(--color-accent);
	margin: 0;
}

/* Pasek przełącznika transportów stoi między topbarem zamówienia a przyklejoną
   sekcją przewozu, więc nosi ich odcień — na tle aplikacji wyglądał jak jasna
   szczelina rozdzielająca dwa ciemniejsze paski. */
.details-content .freight-tabs-bar {
	position: sticky;
	top: 0;
	z-index: 153;
	display: flex;
	align-items: flex-end;
	gap: 12px;
	padding: 6px 12px 0 12px;
	background-color: var(--color-border);
	box-shadow: var(--shadow-thead);
}

.details-content .freight-tabs-bar .nav-tabs {
	flex: 1 1 auto;
	margin-bottom: 0;
}

/* Trigger statusu w polu (field w trybie status="true") — kolor tla/tekstu
   niesie klasa z EnumColorService, tu tylko uklad jak w dawnym btn-status. */
.form-value.status-trigger {
	justify-content: center;
	font-weight: 600;
	border-radius: 4px;
}

/* Pole niosace termin (alertLevelField w rejestrze konfiguracji pola) — tlo wartosci niesie klasa
   alert-level-bg-* z EnumColorService, ta sama rodzina co ikona terminow encji. Tu zostaje sam promien,
   zeby kolor konczyl sie jak pigulka statusu, a nie ostrym prostokatem. */
.form-value.alert-trigger {
	border-radius: 4px;
}

/* Zagęszczony stos wartości: min-height form-boxa i pionowe paddingi wartości
   rozpychały kwoty tak, że czytały się jak dwa niezależne pola. */
.field-no-vertical-space .form-box {
	min-height: 0;
}

.field-no-vertical-space .form-value {
	padding-top: 0;
	padding-bottom: 0;
}

/* Kolumna mapy przytwierdzona podczas scrollowania sasiedniej kolumny
   (np. przystanki + szacowane koszty) — jak w modalu "Pokaz trasy".
   align-self: flex-start, bo we flexowych wierszach panelu bocznego
   domyslny stretch rozciagnalby kolumne i sticky nie mialby ruchu. */
.sticky-map-col {
	position: sticky;
	top: 0;
	align-self: flex-start;
}

/* Wrapper przewijanych zakladek (unt-tabs-bar) przejmuje w sticky pasku
   flex-sizing, ktore mial goly ul. */
.details-content .freight-tabs-bar .unt-tabs-bar {
	flex: 1 1 auto;
	min-width: 0;
}

.details-content .freight-tabs-bar .freight-active-summary {
	flex: 0 1 auto;
	align-self: center;
	font-size: 13px;
	color: var(--color-text-secondary);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
	padding-bottom: 6px;
}

.details-content .freight-section-title {
	margin: 0;
	padding: 6px 8px;
	font-weight: 600;
	font-size: 14px;
	line-height: 1.4;
	overflow: visible;
	white-space: nowrap;
	flex: 0 0 auto;
}

/* Nagłówek "Podsumowanie" w sekcji rozliczenia transportu: mniejszy niż domyślny
   h4 i odsunięty od listy dodatkowych pozycji nad nim. */
freight-details-settlement h4 {
	font-size: 14px;
	margin-top: 16px;
	margin-bottom: 4px;
}

currency-sums {
	display: block;
	margin-top: 8px;
}

/* Sekcja rozliczenia: stały układ 2 kolumn (na lg+; poniżej jedna kolumna jak dla col-lg).
   Kolumna z polami staje się siatką flex-wrap, a każdy wiersz (field-horizontal) zajmuje 50% —
   pola są uporządkowane tak, że stawka trafia do lewej kolumny, a jej wyliczona kwota do prawej
   (obok siebie), bez trzeciej kolumny. */
@media (min-width: 992px) {
	freight-details-settlement [class*="col-lg"]:has(> .field-horizontal) {
		display: flex;
		flex-wrap: wrap;
		align-items: flex-start;
		column-gap: 8px;
	}

	freight-details-settlement [class*="col-lg"] > .field-horizontal {
		flex: 0 0 calc(50% - 4px);
		max-width: calc(50% - 4px);
	}
}

/* Przełącznik w detalach — transportów w zamówieniu, oddziałów u kontrahenta — nosi ten sam
   rozmiar co zakładki compact pod nim: jest paskiem nawigacji w nagłówku sekcji, a nie główną
   nawigacją widoku. */
/* Selektor musi objąć .unt-tabs-bar, bo jego reguła (padding 8px 16px, 1.05em)
   ma tę samą specyficzność i stoi w pliku niżej — bez tego wygrywa ona. */
.details-content .unt-tabs-bar > .switcher-tabs > li > a {
	white-space: nowrap;
	padding: 2px 10px;
	font-size: 12px;
	line-height: 18px;
	min-width: 0;
}

/* `top` values for the sticky stack are calibrated against the default user
   font-size (~14px). With body { font-size } set from the user's profile
   (see run.js — `angular.element("body").css('font-size', data.fontSize)`),
   the actual heights of nav-tabs and the "Ogólne" collapsible scale with
   font-size, so larger user fonts can shift the boundary by a few pixels.
   The short upward box-shadow (8px) fills any sub-pixel gap between the
   sticky tabs (ends near y=38) and this sticky element (starts at y=38)
   without reaching the "Transporty" h3 above the tabs (tabs are ~35-44px
   tall depending on font, plus the h3 has its own margin and z-index).
   Kolor cienia to odcień obu pasków (--color-border), nie tło aplikacji —
   inaczej sam cień rysuje się nad krawędzią jako jaśniejsza kreska. Drugi cień
   (--shadow-card) pada w dół i pokazuje, że pasek leży nad przewijaną treścią. */
.details-content .sticky-freight-overview {
	position: sticky;
	top: 38px;
	z-index: 152;
	box-shadow: 0 -10px 0 0 var(--color-border), var(--shadow-card);
}

/* Menu „Opcje transportu” stoi w tej przyklejonej sekcji, a position: sticky robi z niej
   stacking context — menu (use-dropdown-position → FixedPositionService ustawia position: fixed,
   z-index 1100) nie wychodzi poza jej warstwę 152, więc pasek przełącznika transportów
   (.freight-tabs-bar, z-index 153) malował się na nim: przy długim menu docisniętym do góry
   viewportu pasek zasłaniał dwie pozycje. Na czas otwarcia podnosimy sekcję ponad pasek — ten sam
   idiom co .cl-detail-wrap i td:last-child.td-dropdown-open. Dwa smaki stanu otwarcia: widgety
   bootstrapowe przełączają .dropdown.open, menu encji (komponent unt-dropdown) — .unt-dropdown.open. */
.details-content .sticky-freight-overview:has(.dropdown.open),
.details-content .sticky-freight-overview:has(.unt-dropdown.open) {
	z-index: 1101;
}

/* Detale transportu też mają przełącznik transportów (.freight-short-nav), ale stoi on
   w zwykłym przepływie nad sekcją i odjeżdża przy przewijaniu — nie jest przyklejonym
   paskiem .freight-tabs-bar z detali zamówienia. Bez paska nad sobą offset bazowej reguły
   zostawiałby szczelinę, przez którą widać przewijaną treść, więc tam sekcja przykleja
   się do samej góry obszaru przewijania. */
.details-content:not(:has(.freight-tabs-bar)) .sticky-freight-overview {
	top: 0;
}

.details-content .sticky-freight-overview .content-box-section {
	margin: 0;
}


/* Chip shown next to the Ogólne title — freight number */

/* Przycisk „Wiadomości” detali transportu i zamówienia — przyklejony do dołu strony, odsunięty w lewo,
   żeby nie nachodził na pływający przycisk asystenta AI (FAB w prawym dolnym rogu). */
.freight-messages-launcher {
	position: fixed;
	max-width: calc(100vw - 250px);
	bottom: 0px;
	right: 100px;
	z-index: 1003;
	padding: 10px;
}

.freight-messages-launcher .btn {
	box-shadow: 0px 1px 4px rgba(0, 0, 0, 0.16), 0px 0px 0px 3px rgba(51, 51, 51, 1);
}

/* Układ strony listy (list-layout): przy otwartej sekcji bocznej lista i sekcja dzielą ekran na pół,
   a poniżej progu lg sekcja zastępuje listę. Jedyne miejsce, które zna te proporcje i próg. */
list-layout {
	display: block;
}

.list-layout-split {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	align-items: start;
}

.list-layout-split > .list-layout-main {
	display: none;
	position: relative;
	padding: 0 2px;
}

@media (min-width: 992px) {
	.list-layout-split {
		grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
	}

	.list-layout-split > .list-layout-main {
		display: block;
	}
}

#list-tab-section {
	position: relative;
	padding: 0 2px;
	height: calc(100vh - 50px);
	overflow-y: auto;
	overflow-x: hidden;
	z-index: 10;
	box-shadow: -10px 0 24px -6px var(--color-shadow);
	border-left: 1px solid var(--color-border-strong);
	background-color: var(--color-bg-app);
}

.list-tab-section-body {
	padding: 0;
}

/* Okno z samą sekcją boczną (?sidePanel=…) — sekcja zakrywa stronę, z której wyrosła, i zajmuje całe
   okno, które planista odsuwa na drugi monitor. Pod nią zostaje zwykła strona, bo to ona prowadzi
   zakładkę; menu i okna dialogowe (z-index ≥ 1050) dalej leżą nad sekcją. */
#list-tab-section.side-panel-window-section {
	position: fixed;
	inset: 0;
	z-index: 1000;
	width: auto;
	max-width: none;
	height: auto;
	padding: 8px 16px;
	box-shadow: none;
	border-left: none;
}

/* Przycisk „w nowym oknie” stoi w sekcji tuż obok jej przycisku zamknięcia, więc nagłówek listy
   i pasek kontrolek mapy zostawiają w tym rogu miejsce na oba przyciski, a nie na jeden. */
.list-tab-section-new-window {
	position: absolute;
	top: 5px;
	right: 40px;
	z-index: 11;
}

#list-tab-section:has(> .list-tab-section-new-window) .app-content-header {
	padding-right: 72px;
}

#list-tab-section:has(> .list-tab-section-new-window) .map-control-actions {
	padding-right: 68px;
}

/* In the side panel, let details-body flow naturally and let #list-tab-section
   handle the scroll. The full-page details view keeps its fixed grid layout. */
#list-tab-section .details-body {
	display: block;
	height: auto;
}

#list-tab-section .details-main {
	display: block;
	overflow: visible;
}

#list-tab-section .details-content {
	overflow: visible;
	height: auto;
	padding-bottom: 0;
}

/* The topbar sticks to the top of the side panel while the body scrolls. */
#list-tab-section .details-topbar {
	overflow: visible;
	height: auto;
	position: sticky;
	top: 0;
	z-index: 5;
	background-color: var(--color-bg-app);
}

/* Podgląd rekordu w sekcji bocznej: sekcję zamyka jej własny przycisk w rogu, więc przycisk
   zamknięcia z paska akcji detali (ten sam komponent, w tym samym miejscu) byłby drugim, leżącym
   dokładnie pod nim. Pasek akcji zostawia temu przyciskowi miejsce z prawej — inaczej przykrywa
   ostatnią akcję, tak jak w oknie podglądu (.entity-details-modal .row.details-topbar-header). */
#list-tab-section .list-tab-section-record .close-list-tab-section-btn {
	display: none;
}

#list-tab-section .list-tab-section-record .row.details-topbar-header {
	padding-right: 36px;
}

.mobile-show {
	display: none;
}

/* Tryb kompaktowy obowiazuje w dwoch kontekstach: w panelu bocznym listy
   (#list-tab-section) i w kolumnie tresci detali przy otwartym podgladzie pliku
   (.details-preview-mode) — stad alias :is(...) na regulach ponizej. */
:is(#list-tab-section, .details-preview-mode) [class^="col-lg-offset-"],
:is(#list-tab-section, .details-preview-mode) [class*=" col-lg-offset-"] {
  margin: unset;
}

:is(#list-tab-section, .details-preview-mode) .mobile-hide {
	display: none;
}

/* Side panel (preview) header: show the list title inline next to the select-all
   checkbox so the header reads "checkbox – title – buttons" on one line, for every
   side list (generalized from the former entity-category-list-only rule). */
:is(#list-tab-section, .details-preview-mode) .app-content-header h1.mobile-hide {
	display: inline-block;
	font-size: 16px;
	font-weight: 600;
	margin: 0 0 0 6px;
}

/* Side panel (preview): tighter horizontal spacing between icons/buttons. */
:is(#list-tab-section, .details-preview-mode) .app-content-header,
:is(#list-tab-section, .details-preview-mode) .app-content-header-buttons,
:is(#list-tab-section, .details-preview-mode) .filter-header {
	gap: 3px;
}

:is(#list-tab-section, .details-preview-mode) .app-content-header {
	padding-left: 4px;
	padding-right: 36px;
}

:is(#list-tab-section, .details-preview-mode) .app-content-header-buttons .btn,
:is(#list-tab-section, .details-preview-mode) .filter-header .btn {
	padding-left: 6px;
	padding-right: 6px;
}

/* Side panel (preview): header / filter / sort buttons collapse to icon-only;
   labels remain available as hover tooltips (title). Dropdown menu item labels
   are preserved. */
:is(#list-tab-section, .details-preview-mode) .app-content-header-buttons .btn span,
:is(#list-tab-section, .details-preview-mode) .filter-header .btn span {
	display: none;
}

:is(#list-tab-section, .details-preview-mode) .dropdown-menu .btn span {
	display: inline;
}

/* When the side panel is open, the narrowed main-list column collapses its header
   button labels to icons too; dropdown menu item labels are preserved. */
.list-layout-split > .list-layout-main .app-content-header-buttons .btn span {
	display: none;
}

.list-layout-split > .list-layout-main .dropdown-menu .btn span {
	display: inline;
}

/* Uwaga: wysokosc .details-content w panelu ustawia regula "flow naturally"
   (height: auto) wyzej w pliku — sztywna wysokosc tutaj ograniczala containing
   block sticky metryki i odklejala ja w trakcie scrollowania podgladu. */

:is(#list-tab-section, .details-preview-mode) .content-box-header {
	display: flex;
}

:is(#list-tab-section, .details-preview-mode) .content-box {
	margin-top: 10px;
	/* Bez bocznych marginesow/paddingu: wcinaly pola sekcji o ~16px wzgledem
	   topbara (wrap-content=false renderuje sie bez content-boxa). */
	margin-left: 0;
	margin-right: 0;
	padding-left: 0;
	padding-right: 0;
}

/* Side-panel layout. Every field is <div class="col-lg-N"><div class="field-horizontal">…</div></div>.
   Each .row and each multi-field container is a flex-wrap row. Single-field
   wrappers take 50% (two per visual row); everything else takes 100%. */

:is(#list-tab-section, .details-preview-mode) [class^="col-"],
:is(#list-tab-section, .details-preview-mode) [class*=" col-"] {
	width: 100%;
	margin: 0;
	padding: 0;
	float: none;
}

/* Exclude .content-box-header and .sticky-box rows — those use bootstrap col
   widths for header layouts (list-statistics, collapsible header, etc.). */
/* CSS grid zamiast flex-wrap + calc(50% - 2px): komorki 2-kolumnowej siatki
   sa z konstrukcji rowne (bez subpikselowych przesuniec przy lamaniu wierszy). */
/* Clearfix bootstrapa jako element siatki/flexa przesuwal pola o ~4px
   (to bylo zrodlo nierownych wierszy w podgladzie). */
:is(#list-tab-section, .details-preview-mode) .row:not(.content-box-header):not(.sticky-box):not(.app-content-header):not(.paginator-row)::before,
:is(#list-tab-section, .details-preview-mode) .row:not(.content-box-header):not(.sticky-box):not(.app-content-header):not(.paginator-row)::after {
	content: none;
}

:is(#list-tab-section, .details-preview-mode) .row:not(.content-box-header):not(.sticky-box):not(.app-content-header):not(.paginator-row),
:is(#list-tab-section, .details-preview-mode) :is(.content-box, [class^="col-"], [class*=" col-"]):has(> .field-horizontal + .field-horizontal) {
	margin: 0;
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	column-gap: 4px;
	row-gap: 0;
	align-items: stretch;
}

/* Domyslnie kazde dziecko zajmuje caly wiersz siatki... */
:is(#list-tab-section, .details-preview-mode) .row:not(.content-box-header):not(.sticky-box):not(.app-content-header):not(.paginator-row) > *,
:is(#list-tab-section, .details-preview-mode) :is(.content-box, [class^="col-"], [class*=" col-"]):has(> .field-horizontal + .field-horizontal) > * {
	grid-column: 1 / -1;
	max-width: 100%;
	width: 100%;
	min-width: 0;
}

/* ...a pojedyncze pola po dwa na wiersz — jedna komorka siatki. */
:is(#list-tab-section, .details-preview-mode) .row:not(.content-box-header):not(.sticky-box):not(.app-content-header):not(.paginator-row) > :is([class^="col-"], [class*=" col-"]):has(> .field-horizontal:only-child),
:is(#list-tab-section, .details-preview-mode) :is(.content-box, [class^="col-"], [class*=" col-"]):has(> .field-horizontal + .field-horizontal) > .field-horizontal {
	grid-column: auto;
}

/* Sekcje (collapsible) w panelu bocznym zawsze jedna pod druga, niezaleznie
   od ukladu kolumn, w ktorym osadzil je widok. */
:is(#list-tab-section, .details-preview-mode) collapsible {
	display: block;
	width: 100%;
}


/***************************************************/
/* MATERIAL ****************************************/
/***************************************************/

button, select, html, textarea, input {
	font-family: var(--font-normal);
}

body.md-default-theme, body, html.md-default-theme, html {
	color: var(--color-text-primary);
}

md-backdrop.md-dialog-backdrop {
	z-index: 992;
}

md-switch {
	margin: 0px;
}

/***************************************************/
/* FIELD**** ***************************************/
/***************************************************/

.field-horizontal {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 2px 4px;
  border-radius: 4px;
  transition: background-color 0.3s ease;  
}

.field-horizontal:hover {
  background-color: rgba(0, 0, 0, 0.05);
}

/* Pola label:wartosc — wszedzie ten sam uklad: wszystkie labele maja rowna
   szerokosc, a blok wartosci (field + ikony field-extension) rowna szerokosc
   dopelnienia. Wartosc rozpycha sie w swoim obszarze, ikony laduja na jego
   prawej krawedzi. Konteksty kompaktowe nadpisuja te reguly selektorami o wyzszej
   specyficznosci. */
.field-horizontal > label,
.field-horizontal > .label,
.field-horizontal > sort,
.field-horizontal > triple-price-sort {
	flex: 0 0 40%;
}

.field-horizontal > field,
.field-horizontal > triple-price-field,
.field-horizontal > double-price-field,
.field-horizontal > [double-price-field],
.field-horizontal > ai-provider-field,
.field-horizontal > ai-model-field,
.field-horizontal > financial-document-corrections-field,
.field-horizontal > .field-computed-value,
.field-horizontal > .field-no-vertical-space {
	flex: 1 1 0;
	min-width: 0;
}

/* Numery korekt stoja obok siebie, tak jak zanim komorka stala sie komponentem: wtedy kazdy
   <div> powtorzenia byl bezposrednim elementem flex kontenera .field-horizontal, a teraz jednym
   jego elementem jest caly komponent. Bez zawijania — .field-horizontal nigdy nie deklaruje
   flex-wrap, wiec przed wyodrebnieniem numery zostawaly w jednym rzedzie (28 px) niezaleznie od
   szerokosci okna; z flex-wrap: wrap komorka rosla do 52/76 px juz przy 1366 px. Regula obejmuje
   wylacznie ten kontener — w komorce tabeli komponent zostaje blokowy, bo tam numery ukladaly sie
   w kolumne takze przed wyodrebnieniem. */
.field-horizontal > financial-document-corrections-field {
	display: flex;
	column-gap: 8px;
}

/* Numer, ktory sie nie miesci, jest przycinany wielokropkiem zamiast wystawac na etykiete
   sasiedniego pola: element powtorzenia jako flex item ma domyslne min-width: auto, wiec nie
   schodzil ponizej szerokosci tresci i numery wyjezdzaly poza slot wartosci. nowrap trzyma tez
   pojedynczy dlugi numer w jednej linii — bez niego zawijal sie w widgecie i podnosil komorke
   ponad 28 px. Pelny numer zostaje w szczegolach korekty (menu pola) i w komorce tabeli, ktorej
   te reguly nie dotycza (komponent poza .field-horizontal zostaje blokowy). */
.field-horizontal > financial-document-corrections-field > div {
	min-width: 0;
}

.field-horizontal > financial-document-corrections-field .form-value > span {
	overflow: hidden;
	white-space: nowrap;
	text-overflow: ellipsis;
}

.field-horizontal .field-extension {
	margin-left: auto;
}


label, .label {
	display: flex;
	flex: 1;
	font-size: var(--font-sm);
	font-weight: 600;
	cursor: default;
	color: var(--color-text-primary);
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
	text-overflow: ellipsis;
}

/* Etykiety pól w wierszach danych (detale, ich topbar i zakładki, statystyki) odróżniają się od wartości krojem,
   a nie wagą: zwykła grubość, wersaliki i mniejszy rozmiar tekstu (--label-scale). Pogrubione etykiety w tym samym
   rozmiarze co wartość zlewały się z nią. Formularzy w oknach (form-row) to nie dotyczy, a etykiety z kontrolką
   w środku (opcja radiowa, pole wyboru) to tekst wyboru, nie nazwa pola — też nie. */
.field-horizontal > label:not(:has(> input)),
.statistics-section .pair label {
	font-size: calc(var(--label-scale) * 100%);
	font-weight: normal;
	text-transform: uppercase;
}

/* Nagłówki kolumn tabel to etykiety tabel — też wersalikami i w tej samej skali (wersaliki czytają się w mniejszym
   stopniu). */
thead th {
	font-size: calc(var(--label-scale) * 100%);
	text-transform: uppercase;
}

/* W nagłówku maleje tylko jego tekst. Etykieta (label, sama ma 90%) bierze rozmiar nagłówka, zamiast zmniejszać się
   drugi raz. Menu rozwijane (.dropdown-menu dziedziczy rozmiar) wraca do pełnego rozmiaru — dzielimy przez skalę
   nagłówka. Ikonki edycji kolumn listy własnej są celowo małe (--font-xs względem nagłówka), więc zachowują ten
   rozmiar, skorygowany o skalę nagłówka. */
thead th label {
	font-size: inherit;
}

thead th .dropdown-menu {
	font-size: calc(100% / var(--label-scale));
	text-transform: none;
}

.custom-list thead th.cl-th-editable :is(.cl-th-grip, .cl-th-remove) {
	font-size: calc(var(--font-xs) / var(--label-scale));
}

.field-extension {
	word-break: break-all;
	color: var(--color-text-muted);
	font-size: var(--font-sm);
	padding: 1px;
	border-radius: 4px;
}

/* Obwoluta z nazwa edytowanego pola nad obszarem edycji — widoczna na mobile
   (mobile-show), gdzie dropdown-arkusz jest oderwany od pola. Neutralna
   powierzchnia (--color-surface-alt: jasna w light, ciemniejsza od arkusza
   w dark) i drobniejsza czcionka odrozniaja naglowek od obszaru edycji. */
.dropdown-menu .field-edit-header {
	padding: 6px 12px;
	margin-bottom: 4px;
	font-size: 0.85em;
	font-weight: 600;
	background-color: var(--color-surface-alt);
	color: var(--color-text-secondary);
	border-bottom: 1px solid var(--color-border-strong);
}

.dropdown-menu .field-edit-header .fa-pencil {
	margin-right: 6px;
	opacity: 0.7;
}

/* Akcje dropdownu pola (zapisz/anuluj/kopiuj...) — przygaszone tlo odroznia
   je od listy wartosci do wyboru. Tlo na <li>, nie na linku: link dostaje
   background-color: transparent z reguly wspolnej dla [dropdown-option]
   (mocniejszy selektor), wiec pomalowany link zostalby przebity — przez
   przezroczysty link widac tlo <li>, takze w stanie hover. :has pilnuje,
   zeby <li> bez opcji nic nie malowalo — ng-if wkladek stoi na <li>, ale
   details-button na widoku, do ktorego prowadzi, chowa sam link (ng-if
   wewnatrz komponentu), a jego <li> zostaje. Selektor
   descendant, nie dziecko: czesc <li> akcji stoi wewnatrz wspolnych
   komponentow menu (field-menu-actions), przez ktore kombinator dziecka
   nie siega. */
.dropdown-menu li.field-action:has([dropdown-option]) {
	background-color: var(--color-surface-muted);
}

/* Wspolne pozycje menu przystanku stoja w <ul> przez element komponentu — gospodarz bez
   wlasnego boxa, zeby jego <li> lezaly w layoutcie tak jak pozostale pozycje menu. */
auto-resolve-report-menu {
	display: contents;
}

/* Pozycje menu przejścia do detali (details-menu-options) stoją w <ul> chipa przez element komponentu — gospodarz
   bez własnego boxa, jak wyżej. */
details-menu-options {
	display: contents;
}

/* Mrugniecie inputa edycji po ponownym kliknieciu w edytowane pole —
   wskazuje uzytkownikowi, gdzie wprowadza sie nowa wartosc. */
@keyframes field-input-attention-blink {
	0%, 100% {
		box-shadow: 0 0 0 0 transparent;
	}
	50% {
		box-shadow: 0 0 0 3px var(--color-accent);
	}
}

.field-input-attention {
	animation: field-input-attention-blink 0.35s ease-in-out 2;
}

/* Pole w trakcie edycji (otwarty dropdown) — wiersz jest wyrozniony, ale sama
   wartosc wyglada na nieedytowalna (przygaszona, kursor domyslny): edycja
   odbywa sie w inpucie dropdownu, nie w polu. */
.form-box.dropdown.open > .form-value {
	opacity: 0.5;
	background-color: var(--color-surface-muted);
	border-radius: 4px;
	cursor: default;
}

/* .field-editor-open is toggled by the field directive alongside td-dropdown-open —
   a .field-horizontal:has(.form-box.dropdown.open) selector re-matched styles across
   every block-list row on each editor open/close (see the sticky-column note above).
   The cheap :focus-within variant stays declarative. */
.field-horizontal.field-editor-open,
.field-horizontal:has(unt-autocomplete:focus-within) {
	background-color: var(--color-surface-highlight);
}

.dropdown a {
	color: var(--color-text-secondary);
}

.form-box, unt-autocomplete, bool-select, unt-datetime-picker {
	min-height: var(--form-min-height);
	align-items: center;
	width: 100%;
}

/* Kontrolka formularza to ngModel gospodarza, a rysuje sie sam select — gospodarz nie ma wlasnego pudelka,
   wiec select uklada sie w rodzicu tak, jakby stal tam bezposrednio (flex, input-group, kolumny siatki). */
form-select {
	display: contents;
}

.form-value {
	display: flex;
	justify-content: space-between;
	align-items: center;
	text-align: left;
	width: 100%;
	overflow-x: auto;
	min-width: 40px;
	padding: 2px 4px;
	word-break: normal;
	min-height: var(--form-min-height);
}

.form-value >span {
	max-width: 100%;
}

/* Adres to jedno dlugie slowo: token czy identyfikator w sciezce nie ma ani spacji, ani lacznika, wiec
   przegladarka nie ma gdzie go zlamac i wartosc wyjezdza za pole (zostawal poziomy przewijak, a widac bylo
   sam poczatek). Lamiemy wiec gdziekolwiek, ale najwyzej na dwie linie — dalej wielokropek, zeby wiersz listy
   nie rosl przy kazdym dlugim adresie. Calosc jest w tytule elementu, w edytorze pola i pod ikona kopiowania. */
.form-value > span.field-value-link {
	overflow-wrap: anywhere;
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	line-clamp: 2;
	overflow: hidden;
}

/* Wartosc z postfiksem (jednostka, waluta, procent) czyta sie jako calosc, wiec zostaje w jednej linii —
   bez tego w waskiej kolumnie sam postfiks spadal do nastepnego wiersza. Klase dostaja wylacznie pola,
   ktore postfiks maja, zeby zwykle teksty (nazwy, opisy, uwagi) zawijaly sie jak dotad. */
.form-value > span.field-value-with-postfix {
	white-space: nowrap;
}

.field-value-extension {
	display: flex;
}

/* Topbar detali ma kolumny po 1/6 szerokosci, wiec obok wartosci pola encji nie miesci sie caly rzad ikon
   rozszerzenia (np. cztery przyciski ciagnika) i .details-topbar {overflow: hidden} ucinal ostatnie.
   Ikony zawijaja sie do kolejnego rzedu zamiast wychodzic za krawedz. */
.details-topbar .field-value-extension {
	flex-wrap: wrap;
	justify-content: flex-end;
}

.type-Country {
	white-space: nowrap;
	min-width: 56px;
}

.type-Country .form-value {
	justify-content: flex-start;
}

/* Data zostaje w jednej linii. Domyslne word-break: normal na .form-value lamie ja w kazdym miejscu,
   w ktorym przegladarka widzi okazje: na spacji przed godzina (31-08-2026 14:30) i po dywizie w samej
   dacie (31-/08-2026). W waskiej kolumnie dawalo to dwuwierszowa wartosc, ktora czyta sie jak dwie
   rozne dane. Poziomy overflow .form-value zostaje, wiec nic sie nie gubi. */
.type-LocalDate,
.type-LocalDateTime,
.type-Date {
	white-space: nowrap;
}

/* Kod pocztowy i miasto rowniez zostaja w jednej linii. Kraj ma to z .type-Country wyzej, ale tamten
   selektor idzie po TYPIE pola, a te dwa sa zwyklymi napisami — nowrap na .type-String zlamalby zawijanie
   kazdego opisu w aplikacji. Stad hak po nazwie pola (field-name-*, obok type-* na tym samym .form-box):
   "62-800" lamie sie po dywizie, "Kedzierzyn-Kozle" tak samo, a adres rozbity na dwa wiersze czyta sie
   jak dwie osobne wartosci. Oba pola sa z natury krotkie, wiec regula moze isc po nazwie, nie po encji. */
.field-name-code,
.field-name-city {
	white-space: nowrap;
}

.form-value.textarea>span {
	white-space: break-spaces;
	min-width: 120px;
}

.form-value.textarea {
	align-items: flex-start;
}


.field-enabled {
	cursor: pointer;
	border-radius: 4px;
	border: 1px solid transparent;	
	border-bottom: 1px solid var(--color-bg-app);
	background: var(--color-surface-muted);
	min-height: var(--form-min-height);
}

.field-disabled {
	cursor: default;
	border: 1px solid transparent;
}

.field-enabled:hover {
	cursor: default;
	border: 1px solid var(--color-accent-strong);
	background-color: var(--color-surface);
	box-shadow: var(--shadow-1);
}

.field-disabled:hover {
	cursor: pointer;
}

.field-disabled-with-dropdown {
	background-color: var(--color-surface-muted);
	min-height: var(--form-min-height);
	border-radius: 4px;
	color: var(--color-accent-deep);
	font-weight: 600;
}

.open>.field-enabled {
	opacity: 0.5;
}

.field-disabled-with-dropdown:hover {
	text-decoration: underline;
}

.input-group>textarea {
	white-space: pre-wrap;
	resize: vertical;
	height: 100px;
	min-width: 250px;
}

.input-group>input, select {
	min-width: 110px;
}

.field-required, .table>thead>tr>th .field-required {
	color: var(--color-danger-alt);
	font-weight: 700;
}

/* Kwota dwuwalutowa jest sama stosem (klasa na elemencie komponentu) — blok, jak <div>, ktorym stos byl. */
double-price-field {
	display: block;
}

.field-no-vertical-space {
	flex: 2;
	text-align: left;
	padding: 0px 4px;
}

.field-no-vertical-space .form-box {
	display: flex;
	flex-direction: column;
	white-space: nowrap;
	margin: 0px;
	min-height: unset;
}

/* Wartosc pola zwykle trzyma --form-min-height, zeby wiersz nie skakal przy otwarciu
   edytora i zeby zmiescila sie pigulka statusu albo dwuliniowy adres. W zageszczonym
   stosie minimum liczy sie od kazdej linii osobno i rozpycha komorke — dlatego tutaj
   wartosc nie ma minimum. Selektor dwuklasowy wygrywa nad .field-enabled i
   .field-disabled-with-dropdown, ktore to samo minimum stawiaja na tym elemencie. */
.field-no-vertical-space .form-value {
	min-height: 0;
}

.form-value.field-enabled.field-mark-null {
	cursor: pointer;
	border: 1px solid transparent;
	border-bottom: 1px solid var(--color-danger-soft-bg);
	transition: border-color 0.3s ease, background-color 0.3s ease;
	background-color: var(--color-surface-muted);
}

.form-value.field-enabled.field-mark-null:hover {
	cursor: pointer;
	box-shadow: unset;
	background-color: var(--color-surface-muted);
	border: 1px solid var(--color-warning-hover);
	box-shadow: var(--shadow-1);
}


.text-red .form-value {
	color: red;
}

.form-control {
	border: 1px solid transparent;
	border-bottom: 1px solid var(--color-bg-app);
	font-size: inherit;
	height: unset;
	min-height: var(--form-min-height);
	box-shadow: unset;
	padding: 4px;
	background: var(--color-surface-muted);

}

.form-control:focus, .form-control:hover {
	border: 1px solid var(--color-accent-strong);
	box-shadow: var(--shadow-1);
}

.form-control[disabled], .form-control[readonly], fieldset[disabled] .form-control 	{
	/* Override Bootstrap's hardcoded #eee — in dark mode a light-gray bg under
	   light text made disabled fields unreadable. Themed recessed surface keeps
	   contrast with --color-text-primary in both modes. */
	background-color: var(--color-surface-alt);
	opacity: 0.5;
}


/***************************************************/
/* MODAL**** ***************************************/
/***************************************************/

.modal-dialog {
	margin: unset;
}


.modal-backdrop.in {
	opacity: 0.7;
}

.modal-content {
	background-color: var(--color-bg-app);
	/* 60px = 30px góra + 30px dół (spójne z marginesem .modal-dialog). Cap na cały modal;
	   content (.modal-body) dopasowuje się i skroluje w tej granicy, header/footer statyczne. */
	max-height: calc(100vh - 60px);
	overflow: hidden;
	z-index: 1050;
	display: flex;
	flex-direction: column;
}

/* Każde okno jest komponentem, więc między .modal-content a treścią okna stoi element tego
   komponentu — uib nadaje mu atrybut modal-instance i po nim go tu wskazujemy. W układzie brać
   udziału nie może: całe okno to łańcuch flexa .modal-content > nagłówek / treść / stopka, w którym
   przewija się wyłącznie treść. `display: contents` wypisuje element z drzewa pudełek, więc dzieci
   okna zostają pozycjami flexa .modal-content dokładnie tak, jak przed przerobieniem okien na
   komponenty; selektory poniżej przechodzą ten jeden poziom jawnie. */
.modal-content > [modal-instance] {
	display: contents;
}

.modal-content > [modal-instance] > entity-modal {
	display: flex;
	flex-direction: column;
	flex: 1 1 auto;
	min-height: 0;
	overflow: hidden;
}

/* Nagłówek okna to albo element komponentu <modal-header>, albo ręcznie napisany .modal-header
   (okna, które nagłówek rysują same). W obu wypadkach jest pozycją flexa .modal-content i ma
   trzymać swoją wysokość — treść rośnie i skroluje w .modal-body, nie tutaj. Element komponentu
   domyślnie jest liniowy, więc dostaje blok jawnie. */
.modal-content > [modal-instance] > entity-modal > modal-header,
.modal-content > [modal-instance] > entity-modal > .modal-header,
.modal-content > [modal-instance] > modal-header,
.modal-content > [modal-instance] > .modal-header {
	display: block;
	flex: 0 0 auto;
}

.modal-content > [modal-instance] > entity-modal > .modal-body,
.modal-content > [modal-instance] > .modal-body {
	flex: 1 1 auto;
	overflow-y: auto;
	min-height: 0;
	padding-bottom: 0;
}

.modal-content > [modal-instance] > .modal-footer {
	flex: 0 0 auto;
}

/* entity-modal: prawdziwa stopka jako rodzeństwo PONIŻEJ .modal-body (header 0 0 auto /
   body 1 1 auto, skroluje / footer 0 0 auto). Zastępuje dawne przyklejanie przycisków
   wewnątrz body — stopka jest pod treścią, nie nakłada się na nią (np. na mapę-picker). */
.modal-content > [modal-instance] > entity-modal > .modal-footer-row {
	flex: 0 0 auto;
}

/* Sticky tylko dla modali trzymających przyciski WEWNĄTRZ przewijanego .modal-body
   (modale nie-entity). entity-modal ma realną stopkę .modal-footer-row (rodzeństwo poza
   .modal-body), więc nie łapie tej reguły — bez bezczynnego sticky i zbędnego cienia. */
.modal-content .modal-body modal-buttons {
	display: block;
	position: sticky;
	bottom: 0;
	background: var(--color-bg-app);
	z-index: 10;
	box-shadow: 0 -4px 8px -2px rgba(0, 0, 0, 0.12);
	padding-top: 4px;
}

.modal-header {
	border: 0px;
	padding: 12px 12px 8px 12px;
	background-color: var(--color-bg-app);
	box-shadow: var(--shadow-card);
	position: relative;
	z-index: 153;
}

.modal-header > .row {
	display: flex;
	align-items: center;
}

.modal-header h1 {
	margin: 0;
}

/* Opcja, ktora cos odbiera (odpiecie, usuniecie), czyta sie kolorem — wspolna regula pozycji menu
   maluje je jednym kolorem mocniejszym selektorem, wiec czerwien wymaga tej samej wagi. */
.dropdown-menu [dropdown-option].text-danger {
	color: var(--color-danger-text);
}

/* Powiązania pliku: chipsy jak w kolekcji encji pola, łamane do kolejnych wierszy przy wielu powiązaniach */
.entity-file-holders-chips,
.cost-relations-chips {
	display: flex;
	flex-wrap: wrap;
	gap: 2px;
	margin-bottom: 2px;
}

/* Tryb modala (tworzenie / wyszukiwanie) obok nazwy encji — czytany po nazwie, więc lżejszy od niej */
.modal-header-mode {
	margin-left: 6px;
	font-weight: normal;
	color: var(--color-text-muted);
}

/* Uniform field heights in modal body — buttons match, textarea and multi-select excepted.
   Lista wielokrotnego wyboru jest wyjeta, bo stala wysokosc jednego wiersza znaczy dla niej
   "pokaz jedna pozycje z kilkudziesieciu" — to ta regula, nie sama formatka, sciagala wybor
   krajow i typow pojazdow do dwoch widocznych wierszy we wszystkich oknach naraz. */
.modal-body input.form-control:not([type="checkbox"]):not([type="radio"]),
.modal-body select.form-control:not([multiple]),
.modal-body md-autocomplete {
	height: 32px;
	min-height: 32px;
}

.modal-body md-autocomplete .md-whiteframe-1dp {
	height: 32px;
}

.modal-body md-autocomplete input:not(.md-input) {
	height: 32px;
}

.modal-body textarea.form-control {
	height: auto;
	min-height: 32px;
}

.modal-body .field-horizontal .btn {
	height: 32px;
	min-height: 32px;
	line-height: 1;
	padding: 4px 8px;
}

/* Required-but-empty fields in modals get a highlighted border (replaces the "*" indicator).
   AngularJS removes ng-invalid-required as soon as a value is entered, so the highlight
   disappears automatically. */
.modal-body .form-control.ng-invalid-required,
.modal-body form-select.ng-invalid-required > select,
.modal-body unt-datetime-picker.ng-invalid-required .form-control,
.modal-body unt-autocomplete.ng-invalid-required md-autocomplete {
	border: 1px solid var(--color-danger-alt);
}

.modal-body unt-autocomplete.ng-invalid-required md-autocomplete {
	box-shadow: 0 0 0 1px #f53224;
	border-radius: 2px;
}

/* Paleta koloru tagu: rzędy próbek jak w palecie planu, a pod nimi własny kolor dla barw spoza
   palety. Próbka niesie kolor w stylu, bo tag trzyma hex, a nie klasę motywu. Wybrana próbka
   dostaje obwódkę, bo sam kolor tła nie mówi, który jest wybrany. */
.tag-color-picker {
	display: flex;
	flex-direction: column;
	gap: 4px;
}

.tag-color-row {
	display: flex;
	flex-wrap: wrap;
	gap: 4px;
}

.tag-color-swatch {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 24px;
	height: 20px;
	border: 1px solid var(--color-border-strong);
	border-radius: 4px;
	padding: 0;
	font: inherit;
	appearance: none;
	cursor: pointer;
}

.tag-color-swatch-empty {
	background-color: var(--color-surface);
	color: var(--color-text-secondary);
	border-style: dashed;
}

.tag-color-swatch.selected, .tag-color-custom.selected {
	outline: 2px solid var(--color-text-primary);
	outline-offset: 1px;
}

/* Natywna kontrolka wygląda inaczej w każdej przeglądarce — dostaje rozmiar i obwódkę próbki. */
.tag-color-custom {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	width: fit-content;
	margin: 0;
	border-radius: 4px;
	font-weight: normal;
	cursor: pointer;
}

.tag-color-custom input[type="color"] {
	width: 36px;
	height: 22px;
	padding: 1px;
	border: 1px solid var(--color-border-input);
	border-radius: 4px;
	background: var(--color-surface);
	cursor: pointer;
}

/* Pusta wartość („Bez koloru”, „Automatyczny”) — pole nie udaje wybranego koloru. */
.tag-color-custom.empty input[type="color"] {
	border-style: dashed;
	border-color: var(--color-border-strong);
}

.tag-color-custom.empty input[type="color"]::-webkit-color-swatch {
	background: transparent !important;
	border-color: transparent;
}

.tag-color-custom.empty input[type="color"]::-moz-color-swatch {
	background: transparent !important;
	border-color: transparent;
}

.modal-section-header {
	margin: 8px 0px 8px 0px;
}

/* Sekcja pól modala odczytu stoi w jednej kolumnie na pełnej szerokości, więc slot wartości ma
   ponad tysiąc pikseli. Status jest tam domyślnie wyśrodkowany i rozciągnięty na cały slot — co
   w wąskiej komórce listy wygląda jak znacznik, a tutaj odrzucało „Odpoczynek" o kilkaset pikseli
   od wartości sąsiednich pól. Obie rzeczy trzeba zdjąć razem: samo zwężenie pigułki zostawiało ją
   wyśrodkowaną, a samo wyrównanie do lewej zostawiało ją rozciągniętą. */
.tacho-entry-fields .form-value.status-trigger {
	justify-content: flex-start;
}

.tacho-entry-fields .status-pill {
	width: auto;
}

/* Wartość policzona filtrem w szablonie, a nie wyrenderowana przez <field>, powtarza pudełko
   wartości pola — ten sam padding i ta sama przezroczysta ramka — żeby jej tekst zaczynał się
   dokładnie tam, co tekst sąsiednich pól, a nie pięć pikseli wcześniej. */
.field-horizontal > .field-computed-value {
	padding: 2px 4px;
	border: 1px solid transparent;
}

.modal-body {
	border-top: 1px solid transparent;
	border-bottom: 1px solid transparent;
}

.modal-body .content-box {
	margin: 0px 8px 8px 8px;
}

.modal-body .row {
	padding: 4px
}

.modal-footer {
	padding: 2px;
	border: 0px;
}

/* Tryb szeroki: 30px marginesu góra/dół (symetrycznie). Wysokość: content dopasowuje się,
   max do calc(100vh - 60px) = 30+30 (patrz .modal-content), header/footer statyczne. */
.modal-dialog.modal-xl {
	width: 95vw;
	margin: 30px auto;
	padding: 0;
}

/* Pozycje w oknie wystawiania dokumentu z transakcji: nazwa i opis dostają resztę miejsca, kolumny
   liczb i list mają stałą szerokość (bez niej pole ilości ściskało się do zera), a pola stoją u góry
   wiersza, gdy nazwa ma kilka linii. */
.financial-document-creator-items {
	table-layout: fixed;
}

.financial-document-creator-items th:nth-child(1),
.financial-document-creator-items th:nth-child(11) {
	width: 36px;
}

.financial-document-creator-items th:nth-child(2) {
	width: 30%;
}

.financial-document-creator-items th:nth-child(3) {
	width: 16%;
}

.financial-document-creator-items th:nth-child(4) {
	width: 90px;
}

.financial-document-creator-items th:nth-child(n+5):nth-child(-n+10) {
	width: 120px;
}

.financial-document-creator-items td {
	vertical-align: top;
}

/* Wąski ekran: 8px marginesu ze WSZYSTKICH stron (góra/dół przez margin + max-height,
   boki przez width). Dotyczy każdego modala — i xl, i nie-xl (np. popupy z lupy pola). */
@media (max-width: 767px) {
	.modal-dialog,
	.modal-dialog.modal-xl {
		width: calc(100vw - 16px);
		margin: 8px auto;
	}
	.modal-content {
		max-height: calc(100vh - 16px);
	}
}

/* unt-dropdown pozycjonuje menu jako position:fixed wg btn.offset() (współrzędne względem
   dokumentu/viewportu). Bootstrap nadaje .modal.in .modal-dialog transform: translate(0,0),
   a NIEZEROWY transform czyni z .modal-dialog containing block dla position:fixed — wtedy menu
   trafia względem modala, nie viewportu, i jest przesunięte o offset modala (margines góra/lewo).
   transform:none usuwa to przechwycenie w stanie spoczynku; animacja wjazdu (.modal.fade ->
   translate(0,-25%) -> none, none = identyczność) działa dalej. */
.modal.in .modal-dialog {
	transform: none;
}

.form-value.warning {
	border: 1px solid var(--color-danger);
}

.form-horizontal .form-group {
  margin-right: 0px;
  margin-left: 0px;
}

.form-group {
  margin-bottom: 4px;
}

/* Trwające żądanie z unt-click ma własną klasę .unt-click-pending (nadaje ją i zdejmuje ClickGuardUtils),
   bo "disabled" należy do ng-class szablonu. Wygląd stanu w toku stoi przy każdym gospodarzu obok jego reguły .disabled
   (tu, .auth-btn, [dropdown-option]) — dokładnie tak, jak wyglądał, gdy handler nadawał
   "disabled" — a nie w jednej regule na każdy element: pointer-events: none na dowolnym gospodarzu
   blokowało też jego dzieci (krzyżyk alertu w czasie POST-a). Drugie kliknięcie w czasie żądania i tak
   odrzuca strażnik klasy w ClickGuardUtils; pointer-events to tylko kursor i wygląd. */
.btn.disabled, .btn[disabled], .btn.unt-click-pending {
	pointer-events: none;
}

/* Wartości Bootstrapowego .btn.disabled — selektora z webjara nie da się rozszerzyć, więc stan w toku
   dostaje kopię. */
.btn.unt-click-pending {
	cursor: not-allowed;
	opacity: .65;
	box-shadow: none;
}

/* Wysyłka wiadomości w toku: samolot na przycisku „Wyślij" staje się kręcącym się wskaźnikiem — przy
   dużym załączniku żądanie trwa długo, a samo wyszarzenie przycisku nie mówi, że coś się dzieje
   (9973). Glif \f110 to fa-spinner; animacja ta sama co wskaźnika listy. */
.btn.unt-click-pending .fa-paper-plane::before {
	content: "\f110";
}

.btn.unt-click-pending .fa-paper-plane {
	animation: list-spin 1s linear infinite;
}

.disabled-block {
	pointer-events: none;
	opacity: 0.4;
}

.modal-body .input-group-addon {
	padding: 6px;
	font-size: inherit;
}

/***************************************************/
/* MATERIAL ******************************************/
/***************************************************/
.md-standard-list-container.md-autocomplete-suggestions-container,
	.md-virtual-repeat-container.md-autocomplete-suggestions-container {
	z-index: 1200;
}

md-autocomplete {
	border-radius: 4px;
	width: 100%;
	min-width: unset;
	overflow: hidden;
	height: unset;
	border-bottom: 1px solid var(--color-border);
	background: var(--color-surface-muted);
}

md-autocomplete input:not(.md-input), .md-autocomplete-suggestions li {
	font-size: inherit;
}

md-autocomplete input:not(.md-input), md-autocomplete md-autocomplete-wrap 	{
	box-shadow: none;
}

md-autocomplete input:not(.md-input) {
	font-size: inherit;
	padding: 2px 4px;
	border-radius: 2px;
	background: var(--color-surface-muted);
	line-height: unset;
	height: unset;
}


.md-whiteframe-1dp, .md-whiteframe-z1 {
	box-shadow: none;
	height: var(--form-default-size);
}

.md-autocomplete-suggestions 
.md-autocomplete-suggestion {
	font-size: inherit;
	padding: 2px 4px;
	line-height: 24px;
	height: 28px;	
}

md-autocomplete .md-show-clear-button button {
	line-height: unset;
	text-align: center;
	width: 30px;
	height: unset;
	border: none;
	background: transparent;
	margin: unset;
}

.md-autocomplete-suggestions-container,
.md-virtual-repeat-container.md-autocomplete-suggestions-container {
  min-width: 360px !important;
  margin-top: 4px;
  background-color: var(--color-surface) !important;
  border: 1px solid var(--color-chrome-edge);
  border-radius: 6px;
  box-shadow: var(--shadow-card);
  max-width: 90vw;
}

li.md-autocomplete-suggestion {
  white-space: normal !important;
  height: auto !important;
  min-height: 28px !important;
  overflow: visible !important;
  line-height: 1.3 !important;
  padding: 4px 10px !important;
  border-bottom: 1px solid var(--color-surface-alt);
  font-size: inherit !important;
}

li.md-autocomplete-suggestion:last-child {
  border-bottom: none;
}

li.md-autocomplete-suggestion span {
  white-space: normal !important;
  word-break: break-word !important;
  display: block !important;
  font-weight: normal !important;
  font-size: inherit !important;
}

li.md-autocomplete-suggestion .highlight {
  font-weight: normal !important;
}

/***************************************************/
/* MAP OSM******************************************/
/***************************************************/
.leaflet-top, .leaflet-bottom {
	position: absolute;
	pointer-events: none;
}

.leaflet-popup-content {
	margin: 5px;
	font-family: var(--font-normal);
	font-size: 1.2rem;
}

/***************************************************/
/* NAVBAR*******************************************/
/***************************************************/
.navbar {
	margin-bottom: 0px;
	border-radius: 0px;
	display: flex;
}

.navbar-nav {
	float: none;
	margin: 0;
}

.navbar-nav>li {
	float: none;
}

/***************************************************/
/* SIDEBAR *****************************************/
/***************************************************/
.sidebar {
	background-color: var(--color-sidebar-bg);
	color: var(--color-sidebar-text);
	font-size: var(--sidebar-font-size);
	height: 100%;
}

#sidebar-wrapper {
	display: flex;
	flex-direction: column;
	height: 100%;
	width: 100%;
}

label {
	padding-left: 0px;
	margin: unset;
}

/* equal-width icons across the sidebar and the topbar burger that visually extends it */
.sidebar i,
.btn.btn-sidebar-toggle > i {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: var(--sidebar-icon-width);
	font-size: var(--sidebar-icon-size);
	flex-shrink: 0;
	padding: 0;
}

/* SEARCH */
.sidebar .navbar-top {
	flex-shrink: 0;
	padding: 0.75em 0.75em 0.5em 0.75em;
}

.menu-search {
	padding: 0;
	border: 0;
}

.menu-search .input-group {
	background-color: var(--sidebar-bg-soft);
	border: 1px solid transparent;
	border-radius: var(--sidebar-row-radius);
	display: flex;
	align-items: center;
	transition: background var(--sidebar-transition), border-color var(--sidebar-transition), box-shadow var(--sidebar-transition);
}

.menu-search .input-group:focus-within {
	background-color: var(--sidebar-bg-soft-strong);
	border-color: var(--color-accent);
	box-shadow: 0 0 0 3px var(--color-accent-soft);
}

#sidebar-input {
	background: transparent;
	color: var(--color-text-inverse);
	border: 0;
	padding: 0.4em 0.75em;
	font-size: inherit;
	box-shadow: none;
	height: auto;
}

#sidebar-input::placeholder {
	color: var(--color-sidebar-text-muted);
}

#sidebar-input:focus {
	outline: none;
	box-shadow: none;
}

.menu-search .input-group-addon {
	background: transparent;
	border: 0;
	color: var(--color-sidebar-text-muted);
	padding: 0 0.625em;
	cursor: pointer;
	transition: color var(--sidebar-transition);
}

.menu-search .input-group-addon:hover {
	color: var(--color-text-inverse);
}

/* MAIN MENU */
.navbar-main {
	flex: 1;
	overflow-y: auto;
	overflow-x: hidden;
	scrollbar-width: thin;
	padding: 0.25em 0.5em 0.5em 0.5em;
	height: auto;
}

.navbar-main .navbar-nav {
	margin: 0;
	padding: 0;
	width: 100%;
	float: none;
}

.sidebar .nav > li {
	float: none;
	list-style: none;
}

.sidebar .nav > li > a {
	display: flex;
	align-items: center;
	gap: 0.625em;
	padding: 0.675em 0.75em;
	color: var(--color-sidebar-text-muted);
	background-color: transparent;
	cursor: pointer;
	white-space: nowrap;
	text-decoration: none;
	transition: background var(--sidebar-transition), color var(--sidebar-transition);
}

.sidebar .nav > li.active > a,
.sidebar .nav > li.expanded > a {
	color: var(--color-text-inverse);
}

.sidebar .nav > li > a:hover,
.sidebar .nav > li > a:focus,
.sidebar .nav > li.active.dropdown > a:hover,
.sidebar .nav > li.expanded.dropdown > a:hover {
	background-color: var(--sidebar-bg-soft);
	color: var(--color-text-inverse);
}

.sidebar .nav > li:not(.dropdown).active > a {
	background-color: var(--color-accent-bg);
	color: var(--color-text-inverse);
	box-shadow: 0 1px 8px var(--color-accent-soft);
}

/* chevron indicator on group headers */
.sidebar .dropdown-toggle::after {
	content: '';
	display: inline-block;
	width: 0.4em;
	height: 0.4em;
	margin-left: auto;
	border-right: 2px solid currentColor;
	border-bottom: 2px solid currentColor;
	transform: rotate(-45deg);
	opacity: 0.6;
	transition: transform var(--sidebar-transition), opacity var(--sidebar-transition);
}

.sidebar .nav > li.active > .dropdown-toggle::after,
.sidebar .nav > li.expanded > .dropdown-toggle::after {
	transform: rotate(45deg);
	opacity: 1;
}

/* SUBOPTIONS — collapse/expand via max-height + opacity transitions so both directions animate.
   100vh is a generous upper bound for max-height; the visual stops at the content's natural height,
   then the property continues toward 100vh for the remainder of the transition. */
.navbar-main .dropdown-menu {
	display: block;
	position: relative;
	float: none;
	background: transparent;
	color: var(--color-sidebar-text-muted);
	border: 0;
	box-shadow: none;
	padding: 0.125em 0 0.25em 0;
	margin: 0;
	min-width: 0;
	font-size: var(--sidebar-suboption-font-size);
	width: 100%;
	max-height: 0;
	overflow: hidden;
	opacity: 0;
	z-index: auto;
	transition:
		max-height var(--sidebar-transition) ease-out,
		opacity var(--sidebar-transition) ease-out;
}

body:not(.sidebar-mini) .navbar-main li.active .dropdown-menu,
body:not(.sidebar-mini) .navbar-main li.expanded .dropdown-menu,
body:not(.sidebar-mini) .navbar-main.search-active li .dropdown-menu {
	max-height: 100vh;
	opacity: 1;
}

/* Subtle colour flash signalling the state change.
   `.flash-expand` / `.flash-collapse` are added by the directive for one transition cycle.
   Expand flash is delayed and slower so the user first sees the submenu appear,
   then notices the green tint highlighting what just opened. */
@keyframes sidebar-submenu-flash-expand {
	0%   { background-color: transparent; }
	25%  { background-color: rgba(108, 218, 130, 0.25); }
	100% { background-color: transparent; }
}

@keyframes sidebar-submenu-flash-collapse {
	from { background-color: rgba(232, 102, 102, 0.22); }
	to   { background-color: transparent; }
}

body:not(.sidebar-mini) .navbar-main .dropdown-menu.flash-expand {
	animation: sidebar-submenu-flash-expand 600ms ease-out 250ms;
}

body:not(.sidebar-mini) .navbar-main .dropdown-menu.flash-collapse {
	animation: sidebar-submenu-flash-collapse var(--sidebar-transition);
}

.navbar-main .dropdown-menu > li > a {
	display: flex;
	align-items: center;
	padding: 0.4625em 0.625em 0.4625em 2.625em;
	color: var(--color-sidebar-text-muted);
	background-color: transparent;
	white-space: nowrap;
	text-overflow: ellipsis;
	overflow: hidden;
	transition: background var(--sidebar-transition), color var(--sidebar-transition);
}

.navbar-main .dropdown-menu > li > a:hover,
.navbar-main .dropdown-menu > li > a:focus {
	background-color: var(--sidebar-bg-soft);
	color: var(--color-text-inverse);
}

.navbar-main .dropdown-menu > li > a > .menu-suboption-content {
	flex: 1 1 auto;
	min-width: 0;
}

.navbar-main .dropdown-menu > li > a > .badge {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
	min-width: 18px;
	height: 18px;
	padding: 0 6px;
	margin: 0 0 0 8px;
	border-radius: 9px;
	font-size: 11px;
	line-height: 1;
}

.navbar-main .dropdown-menu > li.active > a {
	background-color: var(--color-accent-bg);
	color: var(--color-text-inverse);
	box-shadow: 0 1px 8px var(--color-accent-soft);
}

.menu-suboption-content {
	display: flex;
	align-items: center;
	gap: 0.5em;
	width: 100%;
	overflow: hidden;
}

.menu-suboption-content .content {
	overflow: hidden;
	text-overflow: ellipsis;
}

.label-menu-short {
	display: none;
	width: var(--sidebar-icon-width);
	font-weight: 700;
	font-size: 0.85em;
	text-align: center;
	color: var(--color-sidebar-text-muted);
}

/* --- SIDEBAR CONTROL BUTTONS ----------------------------------------------
   Topbar burger (hides the sidebar) and sidebar bottom toggle (collapses to mini)
   share visual identity so the user reads them as the same kind of control.
   `.btn.btn-menu.btn-sidebar-toggle` selector uses all three classes to outrank
   the dark `.btn.btn-menu` background defined later in the file. */
.navbar-bottom {
	flex-shrink: 0;
	padding: 0;
	border-top: 1px solid rgba(255, 255, 255, 0.06);
}

.btn.btn-menu.btn-sidebar-toggle,
.sidebar .navbar-bottom .btn.btn-menu {
	height: var(--topbar-height);
	padding: 0;
	margin: 0;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	background-color: transparent;
	color: var(--color-sidebar-text-muted);
	border: 0;
	border-radius: 0;
	transition: background var(--sidebar-transition), color var(--sidebar-transition);
}

.btn.btn-menu.btn-sidebar-toggle:hover,
.btn.btn-menu.btn-sidebar-toggle:focus,
.btn.btn-menu.btn-sidebar-toggle.active,
.btn.btn-menu.btn-sidebar-toggle:active,
.sidebar .navbar-bottom .btn.btn-menu:hover,
.sidebar .navbar-bottom .btn.btn-menu:focus,
.sidebar .navbar-bottom .btn.btn-menu.active,
.sidebar .navbar-bottom .btn.btn-menu:active {
	background-color: var(--sidebar-bg-soft);
	color: var(--color-text-inverse);
	border: 0;
}

/* Burger pulls left to occupy the same column as the sidebar-mini. */
.btn.btn-menu.btn-sidebar-toggle {
	width: var(--sidebar-mini-width);
	margin-left: -8px;
}

/* Bottom toggle fills its container. */
.sidebar .navbar-bottom .btn.btn-menu {
	width: 100%;
}

/* FAVORITE-VIEWS (topbar) — uses the .menu-option class */
.menu-option {
	margin: 0px 8px;
}

a.menu-option {
	color: var(--color-sidebar-text-muted);
}

a.menu-option:hover,
a.menu-option:focus {
	background-color: var(--color-chrome);
	color: var(--color-text-inverse);
}

a.menu-option.active {
	background-color: var(--color-accent-bg);
	color: var(--color-text-inverse);
	box-shadow: 0 1px 8px var(--color-accent-soft);
}

/* Favourites bar: one row that scrolls sideways when crowded — the topbar has a
   fixed height, so wrapping would clip the extra rows. favorite-views is the
   bounded, clipped box (the topbar's flex item); the inner list scrolls inside
   it. A vertical mouse wheel scrolls it via unt-wheel-scroll-x, which toggles
   can-scroll-left / can-scroll-right so the inset edge shadows below appear only
   on the side where items are actually hidden — under the logo on the left,
   under the refresh / icon buttons on the right. */
favorite-views {
	display: block;
	position: relative;
	flex: 1 1 0;
	min-width: 0;
	height: 100%;
	overflow: hidden;
}

.favorite-views-list {
	display: flex;
	height: 100%;
	flex-wrap: nowrap;
	align-items: center;
	justify-content: flex-start;
	overflow-x: auto;
	overflow-y: hidden;
	padding: 0 4px;
	scrollbar-width: none;
	-ms-overflow-style: none;
}

.favorite-views-list::-webkit-scrollbar {
	display: none;
}

/* Edge shadows painted over the scrolling items so it is obvious that content
   slides under the neighbouring topbar elements. */
favorite-views::before,
favorite-views::after {
	content: "";
	position: absolute;
	top: 0;
	bottom: 0;
	width: 56px;
	z-index: 2;
	pointer-events: none;
	opacity: 0;
	transition: opacity 0.15s ease;
}

/* The topbar background is near-black, so a faint translucent black barely shows;
   ramp to fully opaque at the edge so the light chips visibly fade out into it. */
favorite-views::before {
	left: 0;
	background: linear-gradient(to right, rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, 0.75) 40%, rgba(0, 0, 0, 0) 100%);
}

favorite-views::after {
	right: 0;
	background: linear-gradient(to left, rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, 0.75) 40%, rgba(0, 0, 0, 0) 100%);
}

favorite-views:has(.favorite-views-list.can-scroll-left)::before,
favorite-views:has(.favorite-views-list.can-scroll-right)::after {
	opacity: 1;
}

/* unt-tabs: zakladki zawsze w jednym wierszu, przewijane poziomo tak jak
   ulubione widoki w topbarze (unt-wheel-scroll-x + ukryty scrollbar).
   Cienie i strzalki na nieprzewijanym wrapperze .unt-tabs-bar sygnalizuja
   zakladki ukryte poza krawedzia (klasy can-scroll-* ustawia dyrektywa). */
.unt-tabs-bar {
	position: relative;
}

.unt-tabs-bar > .nav-tabs {
	display: flex;
	flex-wrap: nowrap;
	overflow-x: auto;
	overflow-y: hidden;
	scrollbar-width: none;
	-ms-overflow-style: none;
}

.unt-tabs-bar > .nav-tabs::-webkit-scrollbar {
	display: none;
}

/* Zakładki wewnątrz bloku — punkt trasy ma ich tyle, ile punktów ma trasa, więc pasek musi być
   niski: mniejsza czcionka i padding, bez marginesu pod paskiem. Zakładki na górze ekranu
   zostają bez zmian, bo tam wysokość paska nie mnoży się przez liczbę wierszy. */
.unt-tabs-compact > .unt-tabs-bar > .nav-tabs > li > a {
	padding: 2px 10px;
	font-size: 12px;
	line-height: 18px;
}

.unt-tabs-compact > .unt-tabs-bar > .nav-tabs {
	margin-bottom: 0;
}

.unt-tabs-bar > .nav-tabs > li {
	flex: 0 0 auto;
}

/* Zakladki sa zawsze w jednym wierszu, wiec moga byc wieksze niz bazowe
   nav-tabs (4px 8px) — nie ryzykuja zawijania na kilka rzedow. */
.unt-tabs-bar > .nav-tabs > li > a {
	white-space: nowrap;
	padding: 8px 16px;
	font-size: 1.05em;
}

.unt-tabs-bar::before,
.unt-tabs-bar::after {
	content: "";
	position: absolute;
	top: 0;
	bottom: 0;
	width: 40px;
	z-index: 2;
	pointer-events: none;
	opacity: 0;
	transition: opacity 0.15s ease;
}

.unt-tabs-bar::before {
	left: 0;
	background: linear-gradient(to right, var(--color-bg-app) 0%, transparent 100%);
}

.unt-tabs-bar::after {
	right: 0;
	background: linear-gradient(to left, var(--color-bg-app) 0%, transparent 100%);
}

.unt-tabs-bar:has(> .nav-tabs.can-scroll-left)::before,
.unt-tabs-bar:has(> .nav-tabs.can-scroll-right)::after {
	opacity: 1;
}

.unt-tabs-arrow {
	position: absolute;
	top: 0;
	bottom: 0;
	z-index: 3;
	display: none;
	align-items: center;
	padding: 0 6px;
	cursor: pointer;
	color: var(--color-text-secondary);
}

.unt-tabs-arrow:hover {
	color: var(--color-text-primary);
}

.unt-tabs-arrow-left {
	left: 0;
}

.unt-tabs-arrow-right {
	right: 0;
}

.unt-tabs-bar:has(> .nav-tabs.can-scroll-left) > .unt-tabs-arrow-left,
.unt-tabs-bar:has(> .nav-tabs.can-scroll-right) > .unt-tabs-arrow-right {
	display: flex;
}

.favorite-views-list > .menu-option {
	display: inline-flex;
	align-items: center;
	flex-shrink: 0;
	margin: 0 4px;
	padding: 4px 8px;
	border-radius: 4px;
	cursor: grab;
	line-height: 1.3;
}

.favorite-views-list > .menu-option.sortable-dragging {
	cursor: grabbing;
	opacity: 0.6;
}

.favorite-views-list > .menu-option.sortable-dragover-before {
	box-shadow: inset 3px 0 0 var(--color-accent);
}

.favorite-views-list > .menu-option.sortable-dragover-after {
	box-shadow: inset -3px 0 0 var(--color-accent);
}

/* SIDEBAR MINI */
.sidebar-mini #sidebar {
	width: var(--sidebar-mini-width);
}

.sidebar-mini .app-content {
	width: calc(100vw - var(--sidebar-mini-width));
}

.sidebar-mini .menu-search {
	display: none;
}

.sidebar-mini .sidebar .navbar-top {
	padding: 0.5em 0.5em 0.25em 0.5em;
}

/* remove horizontal padding so each row reaches the sidebar's right edge
   and the cursor can travel from the icon to the flyout without losing :hover */
.sidebar-mini .navbar-main {
	padding-left: 0;
	padding-right: 0;
}

.sidebar-mini .sidebar .nav > li > a {
	justify-content: center;
	padding: 0.725em 0;
	gap: 0;
	border-radius: 0;
}

.sidebar-mini .sidebar .nav > li > a > span:not(.label-menu-short) {
	display: none;
}

.sidebar-mini .sidebar .dropdown-toggle::after {
	display: none;
}

/* highlight the icon when its group contains the current route */
.sidebar-mini .sidebar .nav > li.dropdown.active > a {
	position: relative;
	color: var(--color-accent);
	background-color: var(--color-accent-soft);
}

.sidebar-mini .sidebar .nav > li.dropdown.active > a::before {
	content: '';
	position: absolute;
	left: 0;
	top: 0.5em;
	bottom: 0.5em;
	width: 3px;
	border-radius: 0 2px 2px 0;
	background-color: var(--color-accent-bg);
}

/* FLYOUT submenu (mini mode) — position: fixed to escape navbar-main's overflow clip.
   `border-left: transparent` creates the visual gap from the sidebar while keeping the element's
   hit area continuous, so the cursor can travel from the icon to the flyout without losing :hover.
   Show/hide is controlled by opacity + visibility transitions for smooth appear and disappear.
   JS sets --flyout-top/--flyout-bottom/--flyout-max-height. */
.sidebar-mini .navbar-main li .dropdown-menu {
	display: block;
	position: fixed;
	top: var(--flyout-top, var(--topbar-height));
	bottom: var(--flyout-bottom, auto);
	left: var(--sidebar-mini-width);
	width: var(--sidebar-flyout-width);
	max-height: var(--flyout-max-height, calc(100vh - var(--topbar-height) - 1rem));
	overflow-y: auto;
	padding: 0.5em;
	background-color: var(--color-sidebar-bg-elevated);
	background-clip: padding-box;
	border: 1px solid rgba(255, 255, 255, 0.06);
	border-left: 0.6rem solid transparent;
	/* compensate the 0.6rem transparent left border so the padding-box (visible card)
	   has the same curve on all four corners */
	border-radius:
		calc(var(--sidebar-row-radius) + 0.5rem)
		var(--sidebar-row-radius)
		var(--sidebar-row-radius)
		calc(var(--sidebar-row-radius) + 0.5rem)
		/
		var(--sidebar-row-radius);
	box-shadow: 0.6rem 0 3.2rem rgba(0, 0, 0, 0.45);
	font-size: var(--sidebar-font-size);
	z-index: 200;
	opacity: 0;
	visibility: hidden;
	transform: translateX(-0.4em);
	animation: none;
	transition:
		opacity 180ms cubic-bezier(0.4, 0, 0.2, 1),
		transform 180ms cubic-bezier(0.4, 0, 0.2, 1),
		visibility 0s linear 180ms;
}

.sidebar-mini .navbar-main li.dropdown:hover > .dropdown-menu,
.sidebar-mini .navbar-main li.dropdown.expanded > .dropdown-menu {
	opacity: 1;
	visibility: visible;
	transform: translateX(0);
	transition:
		opacity 180ms cubic-bezier(0.4, 0, 0.2, 1),
		transform 180ms cubic-bezier(0.4, 0, 0.2, 1),
		visibility 0s;
}

.sidebar-mini .navbar-main .dropdown-menu > li > a {
	padding: 0.45em 0.75em;
	justify-content: flex-start;
}

.sidebar-mini .navbar-main .dropdown-menu > li > a > .menu-suboption-content {
	justify-content: flex-start;
}

.sidebar-mini .navbar-main .dropdown-menu > li > a > .menu-suboption-content > .content {
	display: inline;
}

.sidebar-mini .navbar-main .dropdown-menu .label-menu-short {
	display: none;
}

/* SIDEBAR HIDE */
.sidebar-hide #sidebar {
	width: 0;
}

.sidebar-hide .app-content {
	width: 100vw;
}

.input-group-btn {
	font-size: inherit;
}

.app-content-footer input {
	max-width: 50px;
}

/* Blok plików dostosowuje się do kolumny, w której stoi — sztywne minimum 300px
   wypychało go poza wyróżnioną kolumnę modalu i poza szerokość telefonu. */
.entity-file-block {
	width: 100%;
	min-width: 0;
	padding: 4px;
	background-color: var(--color-surface-muted);
	border-radius: 8px;
}

/* Wiersz pliku jest nierozdzielny, więc długa nazwa musi się skracać, a nie rozpychać
   blok. Pełna nazwa zostaje w tytule elementu. */
.entity-file-block .unt-file-list__filename {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	min-width: 0;
}

.drop-box {
	border: 2px dashed var(--color-text-muted);
	border-radius: 4px;
	text-align: center;
	padding: 4px;
	margin: 2px;
	white-space: nowrap;
	background-color: var(--color-bg-app);
}

.drop-box:hover {
	background-color: var(--color-surface-muted);
}

.drop-box.dragover {
	border: 1px dashed var(--color-text-secondary);
}


.drop-box.drop-box-uploading {
	cursor: not-allowed;
	pointer-events: none;
}

.entity-file-block .list-group-item {
	background-color: var(--color-surface);
	color: var(--color-text-primary);
	border: 1px solid var(--color-border);
}

.view {
	display: none;
	margin-bottom: 0px;
}


/* login */
.error {
	padding: 15px;
	margin-bottom: 20px;
	border: 1px solid transparent;
	border-radius: 0px;
	color: var(--color-danger-text);
	background-color: var(--color-danger-soft-bg);
	border-color: var(--color-danger-soft-bg);
}

.msg {
	padding: 15px;
	margin-bottom: 20px;
	border: 1px solid transparent;
	border-radius: 0px;
	color: var(--color-info-text);
	background-color: var(--color-info-soft-bg);
	border-color: var(--color-info-soft-bg);
}

.login-logo-wrapper {
	max-width: 550px;
	margin: auto;
	display: flex;
	justify-content: center;
	margin-bottom: 40px;
	padding: 12px 0px 12px 0px;
}

.logo-res {
	max-height: 400px;
	max-width: -webkit-fill-available;
	max-width: -moz-available;
	max-width: fill-available;
}

/* error page */
.error-box {
	margin-top: 25vh;
}

/***************************************************/
/* btn - MENU ************************************/
/***************************************************/
.btn.btn-menu {
	background-color: var(--color-chrome);
	border: 1px solid var(--color-chrome);
	text-align: center;
	color: var(--color-text-inverse);
}

.btn.btn-menu.focus, .btn.btn-menu:focus {
	background-color: var(--color-chrome);
	color: var(--color-text-inverse);
}

.btn.btn-menu:hover {
	background-color: var(--color-chrome);
	color: var(--color-text-inverse);
}

.btn.btn-menu.active, .btn.btn-menu:active {
	background-color: var(--color-chrome);
	color: var(--color-text-inverse);
}

.btn.btn-menu.active.focus, .btn.btn-menu.active:focus, .btn.btn-menu.active:hover,
	.btn.btn-menu:active.focus, .btn.btn-menu:active:focus, .btn.btn-menu:active:hover
	{
	background-color: var(--color-chrome);
	color: var(--color-text-inverse);
}

.btn.btn-menu.btn-autorefresh-on,
.btn.btn-menu.btn-autorefresh-on.focus, .btn.btn-menu.btn-autorefresh-on:focus,
.btn.btn-menu.btn-autorefresh-on:hover,
.btn.btn-menu.btn-autorefresh-on.active, .btn.btn-menu.btn-autorefresh-on:active {
	background-color: var(--color-success);
	border-color: var(--color-success);
}

.btn.btn-menu.btn-autorefresh-off,
.btn.btn-menu.btn-autorefresh-off.focus, .btn.btn-menu.btn-autorefresh-off:focus,
.btn.btn-menu.btn-autorefresh-off:hover,
.btn.btn-menu.btn-autorefresh-off.active, .btn.btn-menu.btn-autorefresh-off:active {
	background-color: var(--color-danger-alt);
	border-color: var(--color-danger-alt);
}

/***************************************************/
/* btn - status ************************************/
/***************************************************/
.btn.btn-status, .btn.btn-status.focus, .btn.btn-status:focus, .btn.btn-status.active,
	.btn.btn-status:active, .btn.btn-status.active.focus, .btn.btn-status.active:focus,
	.btn.btn-status.active:hover, .btn.btn-status:active.focus, .btn.btn-status:active:focus,
	.btn.btn-status:active:hover {
	box-shadow: unset;
	vertical-align: middle;
	text-align: center;
	padding: 0px 8px 0px 8px;
	height: var(--form-default-size);
	border: 1px solid var(--color-text-primary);
	width: 100%;
	font-weight: 600;
}

.btn.btn-status.active.grey-light, .timeline-block.grey-light, .plan-color-swatch.grey-light {
	background-color: var(--color-surface-alt);
	color: var(--color-text-secondary);
	border-color: var(--color-text-secondary);
	font-weight: 600;
}

.btn.btn-status.active.grey-light:hover, .timeline-block.grey-light:hover,
	.timeline-block.grey-light.active {
	background-color: var(--color-border-input);
	Color: var(--color-text-secondary);
	border-color: var(--color-text-secondary);
}

.btn.btn-status.active.very-light-cyan, .timeline-block.very-light-cyan, .plan-color-swatch.very-light-cyan
	{
	background-color: var(--color-teal-soft-bg);
	color: var(--color-teal);
	border-color: var(--color-teal);
}

.btn.btn-status.active.very-light-cyan:hover, .timeline-block.very-light-cyan:hover,
	.timeline-block.very-light-cyan.active {
	background-color: var(--color-teal-soft-bg-hover);
	color: var(--color-teal);
	border-color: var(--color-teal);
}

.btn.btn-status.active.light-cream-yellow, .timeline-block.light-cream-yellow, .plan-color-swatch.light-cream-yellow
	{
	background-color: var(--color-warning-soft-bg);
	color: var(--color-warning-text);
	border-color: var(--color-warning-text);
}

.btn.btn-status.active.light-cream-yellow:hover, .timeline-block.light-cream-yellow:hover,
	.timeline-block.light-cream-yellow.active {
	background-color: var(--color-warning-soft-bg-hover);
	color: var(--color-warning-text);
	border-color: var(--color-warning-text);
}

.btn.btn-status.active.light-mint-green, .timeline-block.light-mint-green, .plan-color-swatch.light-mint-green
	{
	background-color: var(--color-success-soft-bg);
	color: var(--color-success-text);
	border-color: var(--color-success-soft-bg-hover);
}

.btn.btn-status.active.light-mint-green:hover, .timeline-block.light-mint-green:hover,
	.timeline-block.light-mint-green.active {
	background-color: var(--color-success-soft-bg-hover);
	color: var(--color-success-text);
	border-color: var(--color-success-text);
}

.btn.btn-status.active.light-pink-white, .timeline-block.light-pink-white, .plan-color-swatch.light-pink-white
	{
	background-color: var(--color-purple-soft-bg);
	color: var(--color-purple);
	border-color: var(--color-purple);
}

.btn.btn-status.active.light-pink-white:hover, .timeline-block.light-pink-white:hover,
	.timeline-block.light-pink-white.active {
	background-color: var(--color-purple-soft-bg-hover);
	color: var(--color-purple);
	border-color: var(--color-purple);
}

.btn.btn-status.active.light-lemon-yellow, .timeline-block.light-lemon-yellow, .plan-color-swatch.light-lemon-yellow
	{
	background-color: var(--color-warning-soft-bg);
	color: var(--color-warning-text);
	border-color: var(--color-warning-text);
}

.btn.btn-status.active.light-lemon-yellow:hover, .timeline-block.light-lemon-yellow:hover,
	.timeline-block.light-lemon-yellow.active {
	background-color: var(--color-warning-soft-bg-hover);
	color: var(--color-warning-text);
	border-color: var(--color-warning-text);
}

.btn.btn-status.active.light-sky-blue, .timeline-block.light-sky-blue, .plan-color-swatch.light-sky-blue {
	background-color: var(--color-info-soft-bg);
	color: var(--color-info-hover);
	border-color: var(--color-info-hover);
}

.btn.btn-status.active.light-sky-blue:hover, .timeline-block.light-sky-blue:hover,
	.timeline-block.light-sky-blue.active {
	background-color: var(--color-info-soft-bg-hover);
	color: var(--color-info-hover);
	border-color: var(--color-info-hover);
}

.btn.btn-status.active.light-baby-blue, .timeline-block.light-baby-blue, .plan-color-swatch.light-baby-blue
	{
	background-color: var(--color-info-soft-bg);
	color: var(--color-info-text);
	border-color: var(--color-info-text);
}

.btn.btn-status.active.light-baby-blue:hover, .timeline-block.light-baby-blue:hover,
	.timeline-block.light-baby-blue.active {
	background-color: var(--color-info-soft-bg-hover);
	color: var(--color-info-text);
	border-color: var(--color-info-text);
}

.btn.btn-status.active.light-salmon-pink, .timeline-block.light-salmon-pink, .plan-color-swatch.light-salmon-pink
	{
	background-color: var(--color-danger-soft-bg);
	color: var(--color-danger-text);
	border-color: var(--color-danger-text);
}

.btn.btn-status.active.light-salmon-pink:hover, .timeline-block.light-salmon-pink:hover,
	.timeline-block.light-salmon-pink.active {
	background-color: var(--color-danger-soft-bg-hover);
	color: var(--color-danger-text);
	border-color: var(--color-danger-text);
}

/* Dalsze kolory planów — paski planera i próbki palety planu (PLAN_COLORS). */
.timeline-block.light-orange, .plan-color-swatch.light-orange {
	background-color: var(--color-orange-soft-bg);
	color: var(--color-orange);
	border-color: var(--color-orange);
}

.timeline-block.light-orange:hover, .timeline-block.light-orange.active {
	background-color: var(--color-orange-soft-bg-hover);
	color: var(--color-orange);
	border-color: var(--color-orange);
}

.timeline-block.light-yellow, .plan-color-swatch.light-yellow {
	background-color: var(--color-yellow-soft-bg);
	color: var(--color-yellow);
	border-color: var(--color-yellow);
}

.timeline-block.light-yellow:hover, .timeline-block.light-yellow.active {
	background-color: var(--color-yellow-soft-bg-hover);
	color: var(--color-yellow);
	border-color: var(--color-yellow);
}

.timeline-block.light-lime, .plan-color-swatch.light-lime {
	background-color: var(--color-lime-soft-bg);
	color: var(--color-lime);
	border-color: var(--color-lime);
}

.timeline-block.light-lime:hover, .timeline-block.light-lime.active {
	background-color: var(--color-lime-soft-bg-hover);
	color: var(--color-lime);
	border-color: var(--color-lime);
}

.timeline-block.light-cyan, .plan-color-swatch.light-cyan {
	background-color: var(--color-cyan-soft-bg);
	color: var(--color-cyan);
	border-color: var(--color-cyan);
}

.timeline-block.light-cyan:hover, .timeline-block.light-cyan.active {
	background-color: var(--color-cyan-soft-bg-hover);
	color: var(--color-cyan);
	border-color: var(--color-cyan);
}

.timeline-block.light-indigo, .plan-color-swatch.light-indigo {
	background-color: var(--color-indigo-soft-bg);
	color: var(--color-indigo);
	border-color: var(--color-indigo);
}

.timeline-block.light-indigo:hover, .timeline-block.light-indigo.active {
	background-color: var(--color-indigo-soft-bg-hover);
	color: var(--color-indigo);
	border-color: var(--color-indigo);
}

.timeline-block.light-pink, .plan-color-swatch.light-pink {
	background-color: var(--color-pink-soft-bg);
	color: var(--color-pink);
	border-color: var(--color-pink);
}

.timeline-block.light-pink:hover, .timeline-block.light-pink.active {
	background-color: var(--color-pink-soft-bg-hover);
	color: var(--color-pink);
	border-color: var(--color-pink);
}

.timeline-block.light-brown, .plan-color-swatch.light-brown {
	background-color: var(--color-brown-soft-bg);
	color: var(--color-brown);
	border-color: var(--color-brown);
}

.timeline-block.light-brown:hover, .timeline-block.light-brown.active {
	background-color: var(--color-brown-soft-bg-hover);
	color: var(--color-brown);
	border-color: var(--color-brown);
}

.timeline-block.light-slate, .plan-color-swatch.light-slate {
	background-color: var(--color-slate-soft-bg);
	color: var(--color-slate);
	border-color: var(--color-slate);
}

.timeline-block.light-slate:hover, .timeline-block.light-slate.active {
	background-color: var(--color-slate-soft-bg-hover);
	color: var(--color-slate);
	border-color: var(--color-slate);
}

.btn.btn-status.active.light-blue-green {
	background-color: var(--color-info-soft-bg);
	color: var(--color-teal);
	border-color: var(--color-teal);
}

.btn.btn-status.active.light-blue-green:hover {
	background-color: var(--color-info-soft-bg);
	color: var(--color-teal);
	border-color: var(--color-warning-text)
}

.btn.btn-status.active.light-grayish-lavender {
	background-color: var(--color-surface-alt);
	color: var(--color-text-secondary);
	border-color: var(--color-text-secondary);
}

.btn.btn-status.active.light-grayish-lavender:hover {
	background-color: var(--color-surface-alt);
	color: var(--color-text-secondary);
	border-color: var(--color-text-secondary);
}

.btn.btn-status.active.light-pastel-green {
	background-color: var(--color-success-soft-bg);
	color: var(--color-success-text);
	border-color: var(--color-success-text);
}

.btn.btn-status.active.light-pastel-green:hover,.timeline-block.light-pastel-green:hover,
	.timeline-block.light-pastel-green.active {
	background-color: var(--color-success);
	color: var(--color-success-hover);
	border-color: var(--color-success-hover);
}
/***************************************************/
/* status class ***********************************/
/***************************************************/
.light-pastel-green	{
	background-color: var(--color-success-soft-bg);
	color: var(--color-success-text);
}

.light-grayish-lavender {
	background-color: var(--color-surface-alt);
	color: var(--color-text-secondary);
}

.light-blue-green {
	background-color: var(--color-info-soft-bg);
	color: var(--color-teal);
}

.item-block-header.grey-light{
	background-color: var(--color-surface-alt);
	color: var(--color-text-secondary);
}

.very-light-cyan{
	background-color: var(--color-teal-soft-bg);
	color: var(--color-teal);
}

.light-cream-yellow {
	background-color: var(--color-warning-soft-bg);
	color: var(--color-warning-text);
}

.light-mint-green {
	background-color: var(--color-success-soft-bg);
	color: var(--color-success-text);
}

.light-pink-white
	{
	background-color: var(--color-purple-soft-bg);
	color: var(--color-purple);
}

.light-lemon-yellow
	{
	background-color: var(--color-warning-soft-bg);
	color: var(--color-warning-text);
}

.light-sky-blue
	{
	background-color: var(--color-info-soft-bg);
	color: var(--color-info-hover);
}

.light-baby-blue{
	background-color: var(--color-info-soft-bg);
	color: var(--color-info-text);
}

.light-salmon-pink {
	background-color: var(--color-danger-soft-bg);
	color: var(--color-danger-text);
}

/***************************************************/
/* btn - default ***********************************/
/***************************************************/
.btn.btn-default {
	background-color: var(--color-surface);
	color: var(--color-text-secondary);
	border: 1px solid var(--color-border-input);
}

.btn.btn-default.focus, .btn.btn-default:focus {
	background-color: var(--color-surface);
	color: var(--color-text-secondary);
	border: 1px solid var(--color-accent-strong);
}

.btn.btn-default:hover {
	background-color: var(--color-surface-muted);
	color: var(--color-text-secondary);
	border: 1px solid var(--color-border-input);
}

.btn.btn-default.active, .btn.btn-default:active, .open>.dropdown-toggle.btn-default
	{
	background-color: var(--color-border-input);
	color: var(--color-text-secondary);
	border: 1px solid var(--color-border-input);
}

.btn.btn-default.active.focus, .btn.btn-default.active:focus, .btn.btn-default.active:hover,
	.btn.btn-default:active.focus, .btn.btn-default:active:focus, .btn.btn-default:active:hover,
	.open>.dropdown-toggle.btn-default.focus, .open>.dropdown-toggle.btn-default:focus,
	.open>.dropdown-toggle.btn-default:hover {
	background-color: var(--color-border-input);
	color: var(--color-text-secondary);
	border: 1px solid var(--color-accent-strong);
}

/***************************************************/
/* btn - var(--color-surface) ***********************************/
/***************************************************/
.btn.btn-white {
	border: 1px solid transparent;
	background-color: var(--color-surface);
	border-color: 0px solid var(--color-text-primary);
	color: var(--color-text-primary);
	font-weight: 400;
	user-select: text;
}

.btn.btn-white.focus, .btn.btn-white:focus {
	background-color: var(--color-surface-muted);
	outline: none;
	box-shadow: none;
	color: var(--color-text-primary);
}

.btn.btn-white:hover {
	background-color: var(--color-surface-muted);
	outline: none;
	box-shadow: none;
	color: var(--color-text-primary);
}

.btn.btn-white.active, .btn.btn-white:active {
	background-color: var(--color-surface-muted);
	color: var(--color-text-primary);
	outline: none;
}

.btn.btn-white.active.focus, .btn.btn-white.active:focus, .btn.btn-white.active:hover,
	.btn.btn-white:active.focus, .btn.btn-white:active:focus, .btn.btn-white:active:hover
	{
	background-color: var(--color-surface-muted);
	color: var(--color-text-primary);
	outline: none;
	box-shadow: none;
}

.details-topbar .btn-default {
	text-align: left;
}

/***************************************************/
/* btn - success ************************************/
/***************************************************/
.btn.btn-success {
	background-color: var(--color-success-bg);
	color: var(--color-text-inverse);
	border: 1px solid var(--color-success);
}

.btn.btn-success.focus, .btn.btn-success:focus {
	background-color: var(--color-success);
	color: var(--color-text-inverse);
	border: 1px solid var(--color-accent-strong);
}

.btn.btn-success:hover {
	background-color: var(--color-success-hover);
	color: var(--color-text-inverse);
	border: 1px solid var(--color-success-hover);
}

.btn.btn-success.active, .btn.btn-success:active, .open>.dropdown-toggle.btn-success
	{
	background-color: var(--color-success-hover);
	color: var(--color-text-inverse);
	border: 1px solid var(--color-success-hover);
}

.btn.btn-success.active.focus, .btn.btn-success.active:focus, .btn.btn-success.active:hover,
	.btn.btn-success:active.focus, .btn.btn-success:active:focus, .btn.btn-success:active:hover,
	.open>.dropdown-toggle.btn-success.focus, .open>.dropdown-toggle.btn-success:focus,
	.open>.dropdown-toggle.btn-success:hover {
	background-color: var(--color-success-hover);
	color: var(--color-text-inverse);
	border: 1px solid var(--color-accent-strong);
}

/***************************************************/
/* btn-success-light ***********************************/
/***************************************************/
.btn.btn-success-light {
	background-color: var(--color-surface);
	color: var(--color-success);
	border: 1px solid var(--color-surface);
}

.btn.btn-success-light.focus, .btn.btn-success-light:focus {
	background-color: var(--color-surface-muted);
	color: var(--color-success);
	border: 1px solid var(--color-success);
}

.btn.btn-success-light:hover {
	background-color: var(--color-surface-muted);
	color: var(--color-success);
	border: 1px solid var(--color-success);
}

.btn.btn-success-light.active, .btn.btn-success-light:active, .open>.dropdown-toggle.btn-success-light
	{
	background-color: var(--color-surface-muted);
	color: var(--color-success);
	border: 1px solid var(--color-success);
}

.btn.btn-success-light.active.focus, .btn.btn-success-light.active:focus,
	.btn.btn-success-light.active:hover, .btn.btn-success-light:active.focus,
	.btn.btn-success-light:active:focus, .btn.btn-success-light:active:hover,
	.open>.dropdown-toggle.btn-success-light.focus, .open>.dropdown-toggle.btn-success-light:focus,
	.open>.dropdown-toggle.btn-success-light:hover {
	background-color: var(--color-surface-muted);
	color: var(--color-success);
	border: 1px solid var(--color-success);
}

/***************************************************/
/* btn - primary ***********************************/
/***************************************************/
.btn.btn-primary {
	background-color: var(--color-accent-bg);
	color: var(--color-text-inverse);
	border: 1px solid var(--color-accent);
}

.btn.btn-primary.focus, .btn.btn-primary:focus {
	background-color: var(--color-accent-bg);
	color: var(--color-text-inverse);
	border: 1px solid var(--color-accent-strong);
}

.btn.btn-primary:hover {
	background-color: var(--color-accent-hover);
	color: var(--color-text-inverse);
	border: 1px solid var(--color-accent-hover);
}

.btn.btn-primary.active, .btn.btn-primary:active, .open>.dropdown-toggle.btn-primary
	{
	background-color: var(--color-accent-hover);
	color: var(--color-text-inverse);
	border: 1px solid var(--color-accent-hover);
}

.btn.btn-primary.active.focus, .btn.btn-primary.active:focus, .btn.btn-primary.active:hover,
	.btn.btn-primary:active.focus, .btn.btn-primary:active:focus, .btn.btn-primary:active:hover,
	.open>.dropdown-toggle.btn-primary.focus, .open>.dropdown-toggle.btn-primary:focus,
	.open>.dropdown-toggle.btn-primary:hover {
	background-color: var(--color-accent-hover);
	color: var(--color-text-inverse);
	border: 1px solid var(--color-success);
}

/***************************************************/
/* btn-primary-light ***********************************/
/***************************************************/
.btn.btn-primary-light {
	background-color: var(--color-surface);
	color: var(--color-accent);
	border: 1px solid var(--color-surface);
}

.btn.btn-primary-light.focus, .btn.btn-primary-light:focus {
	background-color: var(--color-surface-muted);
	color: var(--color-accent);
	border: 1px solid var(--color-accent);
}

.btn.btn-primary-light:hover {
	background-color: var(--color-surface-muted);
	color: var(--color-accent);
	border: 1px solid var(--color-accent);
}

.btn.btn-primary-light.active, .btn.btn-primary-light:active, .open>.dropdown-toggle.btn-primary-light
	{
	background-color: var(--color-surface-muted);
	color: var(--color-accent);
	border: 1px solid var(--color-accent);
}

.btn.btn-primary-light.active.focus, .btn.btn-primary-light.active:focus,
	.btn.btn-primary-light.active:hover, .btn.btn-primary-light:active.focus,
	.btn.btn-primary-light:active:focus, .btn.btn-primary-light:active:hover,
	.open>.dropdown-toggle.btn-primary-light.focus, .open>.dropdown-toggle.btn-primary-light:focus,
	.open>.dropdown-toggle.btn-primary-light:hover {
	background-color: var(--color-surface-muted);
	color: var(--color-accent);
	border: 1px solid var(--color-accent);
}

/***************************************************/
/* btn-secondary ***********************************/
/***************************************************/
.btn.btn-secondary {
	background-color: var(--color-accent-soft-bg);
	color: var(--color-accent-deep);
	border: 1px solid var(--color-accent-soft-bg);
}

.btn.btn-secondary.focus, .btn.btn-secondary:focus {
	background-color: var(--color-accent-bg);
	color: var(--color-accent-deep);
	border: 1px solid var(--color-success);
}

.btn.btn-secondary:hover {
	background-color: var(--color-accent-soft-bg);
	color: var(--color-accent-deep);
	border: 1px solid var(--color-accent-soft-bg);
}

.btn.btn-secondary.active, .btn.btn-secondary:active, .open>.dropdown-toggle.btn-secondary
	{
	background-color: var(--color-accent-soft-bg);
	color: var(--color-accent-deep);
	border: 1px solid var(--color-accent-soft-bg);
}

.btn.btn-secondary.active.focus, .btn.btn-secondary.active:focus, .btn.btn-secondary.active:hover,
	.btn.btn-secondary:active.focus, .btn.btn-secondary:active:focus, .btn.btn-secondary:active:hover,
	.open>.dropdown-toggle.btn-secondary.focus, .open>.dropdown-toggle.btn-secondary:focus,
	.open>.dropdown-toggle.btn-secondary:hover {
	background-color: var(--color-accent-soft-bg);
	color: var(--color-accent-deep);
	border: 1px solid var(--color-success);
}

/***************************************************/
/* btn - warning ***********************************/
/***************************************************/
.btn.btn-warning {
	background-color: var(--color-warning);
	color: var(--color-chrome);
	border: 1px solid var(--color-warning);
}

.btn.btn-warning.focus, .btn.btn-warning:focus {
	background-color: var(--color-warning);
	color: var(--color-chrome);
	border: 1px solid var(--color-accent-strong);
}

.btn.btn-warning:hover {
	background-color: var(--color-warning-hover);
	color: var(--color-chrome);
	border: 1px solid var(--color-warning-hover);
}

.btn.btn-warning.active, .btn.btn-warning:active, .open>.dropdown-toggle.btn-warning
	{
	background-color: var(--color-warning-hover);
	color: var(--color-chrome);
	border: 1px solid var(--color-warning-hover);
}

.btn.btn-warning.active.focus, .btn.btn-warning.active:focus, .btn.btn-warning.active:hover,
	.btn.btn-warning:active.focus, .btn.btn-warning:active:focus, .btn.btn-warning:active:hover,
	.open>.dropdown-toggle.btn-warning.focus, .open>.dropdown-toggle.btn-warning:focus,
	.open>.dropdown-toggle.btn-warning:hover {
	background-color: var(--color-warning-hover);
	color: var(--color-chrome);
	border: 1px solid var(--color-accent-strong);
}

/***************************************************/
/* btn-warning-light ***********************************/
/***************************************************/
.btn.btn-warning-light {
	background-color: var(--color-surface);
	color: var(--color-warning-text);
	border: 1px solid var(--color-surface);
}

.btn.btn-warning-light.focus, .btn.btn-warning-light:focus {
	background-color: var(--color-surface-muted);
	color: var(--color-warning-text);
	border: 1px solid var(--color-warning);
}

.btn.btn-warning-light:hover {
	background-color: var(--color-surface-muted);
	color: var(--color-warning-text);
	border: 1px solid var(--color-warning);
}

.btn.btn-warning-light.active, .btn.btn-warning-light:active, .open>.dropdown-toggle.btn-warning-light
	{
	background-color: var(--color-surface-muted);
	color: var(--color-warning-text);
	border: 1px solid var(--color-warning);
}

.btn.btn-warning-light.active.focus, .btn.btn-warning-light.active:focus,
	.btn.btn-warning-light.active:hover, .btn.btn-warning-light:active.focus,
	.btn.btn-warning-light:active:focus, .btn.btn-warning-light:active:hover,
	.open>.dropdown-toggle.btn-warning-light.focus, .open>.dropdown-toggle.btn-warning-light:focus,
	.open>.dropdown-toggle.btn-warning-light:hover {
	background-color: var(--color-surface-muted);
	color: var(--color-warning-text);
	border: 1px solid var(--color-warning);
}

/***************************************************/
/* btn - info ***********************************/
/***************************************************/
.btn.btn-info {
	background-color: var(--color-info-bg);
	color: var(--color-text-inverse);
	border: 1px solid var(--color-info);
}

.btn.btn-info.focus, .btn.btn-info:focus {
	background-color: var(--color-info);
	color: var(--color-text-inverse);
	border: 1px solid var(--color-accent-strong);
}

.btn.btn-info:hover {
	background-color: var(--color-info-hover);
	color: var(--color-text-inverse);
	border: 1px solid var(--color-info-hover);
}

.btn.btn-info.active, .btn.btn-info:active, .open>.dropdown-toggle.btn-info
	{
	background-color: var(--color-info-hover);
	color: var(--color-text-inverse);
	border: 1px solid var(--color-info-hover);
}

.btn.btn-info.active.focus, .btn.btn-info.active:focus, .btn.btn-info.active:hover,
	.btn.btn-info:active.focus, .btn.btn-info:active:focus, .btn.btn-info:active:hover,
	.open>.dropdown-toggle.btn-info.focus, .open>.dropdown-toggle.btn-info:focus,
	.open>.dropdown-toggle.btn-info:hover {
	background-color: var(--color-info-hover);
	color: var(--color-text-inverse);
	border: 1px solid var(--color-accent-strong);
}

/***************************************************/
/* btn-info-light ***********************************/
/***************************************************/
.btn.btn-info-light {
	background-color: var(--color-surface);
	color: var(--color-info);
	border: 1px solid var(--color-surface);
}

.btn.btn-info-light.focus, .btn.btn-info-light:focus {
	background-color: var(--color-surface-muted);
	color: var(--color-info);
	border: 1px solid var(--color-info);
}

.btn.btn-info-light:hover {
	background-color: var(--color-surface-muted);
	color: var(--color-info);
	border: 1px solid var(--color-info);
}

.btn.btn-info-light.active, .btn.btn-info-light:active, .open>.dropdown-toggle.btn-info-light
	{
	background-color: var(--color-surface-muted);
	color: var(--color-info);
	border: 1px solid var(--color-info);
}

.btn.btn-info-light.active.focus, .btn.btn-info-light.active:focus, .btn.btn-info-light.active:hover,
	.btn.btn-info-light:active.focus, .btn.btn-info-light:active:focus,
	.btn.btn-info-light:active:hover, .open>.dropdown-toggle.btn-info-light.focus,
	.open>.dropdown-toggle.btn-info-light:focus, .open>.dropdown-toggle.btn-info-light:hover
	{
	background-color: var(--color-surface-muted);
	color: var(--color-info);
	border: 1px solid var(--color-info);
}

/***************************************************/
/* btn - danger ***********************************/
/***************************************************/
.btn.btn-danger {
	background-color: var(--color-danger);
	color: var(--color-text-inverse);
	border: 1px solid var(--color-danger);
}

.btn.btn-danger.focus, .btn.btn-danger:focus {
	background-color: var(--color-danger);
	color: var(--color-text-inverse);
	border: 1px solid var(--color-accent-strong);
}

.btn.btn-danger:hover {
	background-color: var(--color-danger-hover);
	color: var(--color-text-inverse);
	border: 1px solid var(--color-danger-hover);
}

.btn.btn-danger.active, .btn.btn-danger:active, .open>.dropdown-toggle.btn-danger
	{
	background-color: var(--color-danger-hover);
	color: var(--color-text-inverse);
	border: 1px solid var(--color-danger-hover);
}

.btn.btn-danger.active.focus, .btn.btn-danger.active:focus, .btn.btn-danger.active:hover,
	.btn.btn-danger:active.focus, .btn.btn-danger:active:focus, .btn.btn-danger:active:hover,
	.open>.dropdown-toggle.btn-danger.focus, .open>.dropdown-toggle.btn-danger:focus,
	.open>.dropdown-toggle.btn-danger:hover {
	background-color: var(--color-danger-hover);
	color: var(--color-text-inverse);
	border: 1px solid var(--color-accent-strong);
}

/***************************************************/
/* btn-danger-light ***********************************/
/***************************************************/
.btn.btn-danger-light {
	background-color: var(--color-surface);
	color: var(--color-danger);
	border: 1px solid var(--color-surface);
}

.btn.btn-danger-light.focus, .btn.btn-danger-light:focus {
	background-color: var(--color-surface-muted);
	color: var(--color-danger);
	border: 1px solid var(--color-accent-strong);
}

.btn.btn-danger-light:hover {
	background-color: var(--color-surface-muted);
	color: var(--color-danger);
	border: 1px solid var(--color-border-input);
}

.btn.btn-danger-light.active, .btn.btn-danger-light:active, .open>.dropdown-toggle.btn-danger-light
	{
	background-color: var(--color-surface-muted);
	color: var(--color-danger);
	border: 1px solid var(--color-border-input);
}

.btn.btn-danger-light.active.focus, .btn.btn-danger-light.active:focus,
	.btn.btn-danger-light.active:hover, .btn.btn-danger-light:active.focus,
	.btn.btn-danger-light:active:focus, .btn.btn-danger-light:active:hover,
	.open>.dropdown-toggle.btn-danger-light.focus, .open>.dropdown-toggle.btn-danger-light:focus,
	.open>.dropdown-toggle.btn-danger-light:hover {
	background-color: var(--color-surface-muted);
	color: var(--color-danger);
	border: 1px solid var(--color-accent-strong);
}

/***************************************************/
/* btn - stop action ***********************************/
/***************************************************/
.btn-fill-container, .search-address li a {
	width: 100%;
	overflow: hidden;
	text-overflow: ellipsis;
}

/* AI-import modal: one entry = the files (chips) and the optional text one record is made of. The entry
   is a drop / paste target of its own (tabindex), so the drop overlay is drawn per entry. */
.ai-import-hint {
	margin: 6px 0;
}
.ai-import-entry {
	position: relative;
	margin-bottom: 10px;
	padding: 10px 12px;
	border: 1px solid var(--color-border);
	border-radius: 8px;
	background: var(--color-surface);
	outline: none;
}
.ai-import-entry:focus-within {
	border-color: var(--color-accent);
}
.ai-import-entry--imported {
	border-color: var(--color-success);
}
.ai-import-entry__dropzone {
	position: absolute;
	inset: 0;
	z-index: 2;
	display: none;
	align-items: center;
	justify-content: center;
	gap: 8px;
	border: 2px dashed var(--color-accent);
	border-radius: 8px;
	background: var(--color-accent-soft);
	color: var(--color-accent);
	pointer-events: none;
}
.ai-import-entry.unt-dragging .ai-import-entry__dropzone {
	display: flex;
}
.ai-import-entry__header {
	display: flex;
	align-items: center;
	gap: 8px;
	margin-bottom: 6px;
}
.ai-import-entry__actions {
	display: inline-flex;
	gap: 4px;
	margin-left: auto;
}
.ai-import-entry__files {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 4px;
	margin-bottom: 6px;
}
.ai-import-entry__file {
	display: inline-flex;
	align-items: center;
	gap: 5px;
	max-width: 280px;
	padding: 3px 8px;
	border-radius: 10px;
	background: var(--color-accent-soft-bg);
	color: var(--color-text-secondary);
	font-size: 12px;
}
.ai-import-entry__file-name {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
.ai-import-entry__file-remove {
	flex-shrink: 0;
	cursor: pointer;
	opacity: 0.7;
}
.ai-import-entry__file-remove:hover {
	opacity: 1;
	color: var(--color-danger);
}
input[type="file"].ai-import-entry__file-input {
	display: none;
}
.ai-import-result {
	margin-top: 6px;
	font-size: 12px;
}
.ai-import-result__sources {
	margin: 4px 0 0;
	padding-left: 0;
	list-style: none;
}
.ai-import-result__sources > li + li {
	margin-top: 4px;
}
.ai-import-result__page {
	padding-left: 18px;
}
.ai-import-bulk-results {
	margin-top: 10px;
}
.ai-import-bulk-results .ai-import-result {
	padding: 6px 0;
	border-top: 1px solid var(--color-border);
}

/* Reading-mode switch (OCR / AI vision / both): the hint under each label says how long it takes. */
.ai-reading-mode {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px;
	margin: 6px 0;
}
.ai-reading-mode__label {
	font-weight: 600;
}
.ai-reading-mode__hint {
	display: block;
	opacity: 0.75;
	font-size: 10px;
}
.ai-reading-mode--compact {
	margin: 0;
}

/* --- ADDRESS SEARCH DROPDOWN ---------------------------------------------- */

.search-address-header {
	display: flex;
	flex-direction: column;
	gap: 8px;
	padding: 12px;
	margin: -6px 0 6px 0;
	background-color: var(--color-accent-soft);
	border-top-left-radius: 0.6em;
	border-top-right-radius: 0.6em;
	border-bottom: 1px solid rgba(97, 98, 241, 0.16);
}

.search-address-label {
	font-size: 0.85em;
	font-weight: 600;
	letter-spacing: 0.02em;
	text-transform: uppercase;
	color: var(--color-accent);
}

.search-address-input.form-control {
	padding: 6px 10px;
	height: auto;
	border: 1px solid rgba(97, 98, 241, 0.25);
	border-radius: 6px;
	background-color: var(--color-surface);
	box-shadow: none;
	transition: border-color var(--sidebar-transition), box-shadow var(--sidebar-transition);
}

.search-address-input.form-control:focus {
	outline: none;
	border-color: var(--color-accent);
	box-shadow: 0 0 0 3px rgba(97, 98, 241, 0.15);
}

/* Toggle button — switch-style indicator so the on/off state is obvious. */
.search-address-paid-toggle {
	display: flex;
	align-items: center;
	gap: 10px;
	width: 100%;
	padding: 6px 10px;
	border: 1px solid rgba(97, 98, 241, 0.18);
	border-radius: 6px;
	background-color: var(--color-surface);
	color: var(--color-text-primary);
	cursor: pointer;
	transition: border-color var(--sidebar-transition), color var(--sidebar-transition);
}

.search-address-paid-toggle:hover,
.search-address-paid-toggle:focus {
	outline: none;
	border-color: var(--color-accent);
}

.search-address-paid-toggle.is-active {
	border-color: var(--color-accent);
	color: var(--color-accent);
}

.search-address-paid-switch {
	position: relative;
	display: inline-block;
	width: 30px;
	height: 16px;
	border-radius: 999px;
	background-color: rgba(20, 18, 42, 0.18);
	flex-shrink: 0;
	transition: background-color var(--sidebar-transition);
}

.search-address-paid-knob {
	position: absolute;
	top: 2px;
	left: 2px;
	width: 12px;
	height: 12px;
	border-radius: 50%;
	background-color: var(--color-surface);
	box-shadow: 0 1px 2px rgba(20, 18, 42, 0.3);
	transition: transform var(--sidebar-transition);
}

.search-address-paid-toggle.is-active .search-address-paid-switch {
	background-color: var(--color-accent-bg);
}

.search-address-paid-toggle.is-active .search-address-paid-knob {
	transform: translateX(14px);
}

.search-address-paid-text {
	font-weight: 500;
}

/* Results list — section labels are compact and styled, no inline list-style. */
.search-address-results {
	padding: 0;
}

.search-address {
	padding-inline-start: 0;
	margin: 0;
	list-style: none;
}

.search-address-section-label {
	padding: 6px 14px 2px 14px;
	font-size: 0.75em;
	font-weight: 600;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--color-sidebar-text-muted);
	list-style: none;
}

.btn.reservared-vehicle {
	background: var(--color-teal);
	color: var(--color-text-inverse);
}

.vehicle-combination-reservation {
	width: 350px;
}


/**************
***FLEX-LIST***
**************/

.flex-list {
	width: 100%;
	max-height: 400px;
	overflow: auto;
	padding: 8px 0px 8px 0px;
}

/* Punkt juz zaliczony (raport przyjazdu jest) — wiersz schodzi na drugi plan, zeby wzrok trafial w to,
   co przed pojazdem: jasnoszare tlo i ciemnoszara kursywa. Kolorem, nie przezroczystoscia — opacity
   komorki przenosila sie na wszystko, co z niej wyrasta, wiec menu wiersza i edytor pola otwieraly sie
   polprzezroczyste, praktycznie niewidoczne. */
.rs-visited > td {
	background-color: var(--color-surface-alt);
	color: var(--color-text-secondary);
	font-style: italic;
}

/* Najblizszy punkt w dwoch wariantach: pojazd jeszcze do niego jedzie (kolor dojazdu na mapie) albo
   juz na nim stoi — przyjazd zaraportowany, wyjazd jeszcze nie. */
.rs-next-heading > td {
	background-color: var(--color-warning-soft-bg-hover);
}

.rs-next-on-site > td {
	background-color: var(--color-success-soft-bg-hover);
}

.rs-next-badge {
	display: inline-block;
	margin-left: 4px;
	padding: 1px 6px;
	border-radius: 8px;
	font-size: 11px;
	font-weight: 600;
	white-space: nowrap;
	color: var(--color-text-inverse);
	background-color: var(--color-warning-text);
}

.rs-next-on-site .rs-next-badge {
	background-color: var(--color-success-text);
}

/* Lista segmentow w modalu trasy. Wysokosc liczona z viewportu, nie stala w pikselach, bo sam modal
   skaluje sie do okna (.modal-content ma max-height: calc(100vh - 60px)) — na niskim ekranie stala
   wartosc zjadlaby miejsce na paginacje, a na wysokim marnowala je. */
.rs-table-scroll {
	max-height: 55vh;
	overflow-y: auto;
}

/* Osadzona lista przewija sie w sobie w OBU osiach. Bez poziomego przewijania szeroka tabela (tryb wlasny
   ma kilkanascie kolumn) rozpychala sekcje do swojej szerokosci, a wyrownane do prawej przyciski naglowka
   — przelaczniki trybu i konfigurator kolumn — wychodzily poza widoczny obszar rozwinietego bloku.
   Obie osie na jednym elemencie, bo do niego przykleja sie sticky thead.

   Wysokosc bierze sie z ekranu, a nie ze stalej: lista ma siegac tyle, ile zostaje pod topbarem detali
   i paskiem zakladek. Odjete 320 px to wlasnie ta rama — topbar, pasek zakladek, naglowek sekcji
   i paginator. Dolna granica 200 px chroni niskie okno: bez niej przy 450 px lista miala 130 px, a ponizej
   320 px znikala. Krotka lista dalej zajmuje tyle, ile ma wierszy — to granica max-height, nie min-height,
   wiec pustym miejscem sekcji nie rozpycha. */
.embedded-list-scroll {
	max-height: max(200px, calc(100vh - 320px));
	overflow: auto;
}

/* To samo dla kazdej innej listy osadzonej w detalach: jej tabela stoi w .table-responsive, ktory juz
   jest przewijakiem poziomym, wiec wystarczy dac mu gorna granice wysokosci, zeby przewijal sie takze
   w pionie. Krotka tabela nic na tym nie traci — granica dziala dopiero, gdy tresc ja przekroczy. */
.details-body .table-responsive {
	max-height: max(200px, calc(100vh - 320px));
	overflow: auto;
}

/* Lista z wlasnym przewijakiem: wewnetrzny .table-responsive przestaje byc przewijakiem w ogole.
   Sam brak granicy wysokosci nie wystarczy — overflow-x czyni z niego scrollport takze w pionie, a do
   NIEGO przyklejalby sie wtedy naglowek, wiec przewijanie zewnetrznej ramy odjezdzaloby razem z nim.
   Regula nie jest zawezona do .details-body, bo te same listy stoja tez w rozwinietym wierszu listy
   stronowej (row-detail, np. pojazd wirtualny): tam wewnetrzny przewijak zostawal i naglowek odjezdzal
   razem z trescia, choc w detalach kontraktu ta sama lista trzymala go u gory. */
.embedded-list-scroll .table-responsive {
	max-height: none;
	overflow: visible;
}

/* W detalach naglowki tabel sa odklejone (.details-body table thead), bo tabele stoja tam w przewijaniu
   calej tresci — przyklejony naglowek trzyletniej tabeli wchodzilby na naglowek sekcji. Lista osadzona
   przewija sie w SOBIE, wiec tutaj naglowek wraca na swoje miejsce i przykleja sie do krawedzi swojego
   kontenera. Reguly stoja po tamtej w pliku, bo maja te sama specyficznosc. */
.embedded-list-scroll table thead,
.details-body .table-responsive table thead {
	position: sticky;
	top: 0;
	z-index: 3;
	background: var(--color-surface);
	box-shadow: var(--shadow-thead);
}

.flex-list-row {
	display: flex;
	flex-wrap: nowrap;
	align-items: center;
}

.btn-icon-only span {
	display: none;
}

.flex-list-item {
	flex: 2; 
}

.flex-list-item-sm {
	flex: 1; 
}

.flex-list-item-lg {
	flex: 3; 
}
/***************/


.children-inline div {
	width: inherit;
	display: inline;
}

.inline {
	display: inline-flex;
	align-items: center;
}

.inline-right {
	display: inline-flex;
	align-items: center;
	justify-content: right;
}

collapsible right-buttons, collapsible ng-transclude[ng-transclude-slot="rightButtons"] {
	display: contents;
}

/* Kontener listy osadzonej przekazuje nagłówek i treść do collapsible przez ng-transclude — obwoluty nie
   mogą zmienić układu, więc treść stoi w sekcji tak, jakby lista wpisała ją tam sama. */
.embedded-list-slot {
	display: contents;
}

/* Link przy tytule sekcji listy osadzonej, który pokazuje i chowa filtry i paginator — tekst, nie
   przycisk, żeby przy kilku wierszach nie dokładał ramki, którą ukrywa. */
/* Przycisk, żeby był osiągalny z klawiatury; wygląda jak link przy tytule sekcji. */
.embedded-list-chrome-toggle {
	display: inline-flex;
	align-items: center;
	gap: 4px;
	margin-left: 8px;
	padding: 0;
	border: 0;
	background: none;
	font-size: var(--font-xs);
	color: var(--color-text-secondary);
	cursor: pointer;
}

.embedded-list-chrome-toggle:hover,
.embedded-list-chrome-toggle:focus {
	color: var(--color-accent);
	text-decoration: none;
}

/* Filtry schowane, a lista nimi zawężona albo ma dalsze strony — kolor mówi, że wiersze nie są kompletne. */
.embedded-list-chrome-toggle.embedded-list-chrome-toggle-incomplete {
	color: var(--color-warning-text-on-highlight);
	font-weight: 600;
}

/***************
***FLEX-BLOCK***
***************/

.flex-container {
	display: flex;
	flex-wrap: wrap;
	justify-content: space-between;
	align-items: center;
	width: 100%;
}

.flex-container-nowrap {
	flex-wrap: nowrap;
}

.flex-item {
	display: flex;
	justify-content: flex-start;
	align-items: center;
	flex: 2 1;
	min-width: 36px;
	padding: 0px 2px;
}


.flex-item-double-width {
	flex-grow: 2;
}


.pair {
	display: flex;
	justify-content: center;
	align-items: center;
}

.pair label {
	flex: 1;
	text-align: right;
	padding-right: 10px;
}

.pair .flex-item, .pair triple-price-field, .pair .field-no-vertical-space {
	flex: 1;
	text-align: left;
}

.pair>* {
	margin: 2px;
	padding: 2px;
	word-break: break-word;
}

/* === STATYSTYKI: ujednolicony wyglad (2 kolumny, field-horizontal, kwoty wyroznione/przygaszone) === */
.statistics-section ul.list-group {
	display: grid;
	grid-template-columns: 1fr 1fr;
	column-gap: 24px;
	row-gap: 0;
	margin-bottom: 0;
}
.statistics-section ul.list-group > .list-group-item {
	border: none;
	background: transparent;
	padding: 0;
}
.statistics-section .pair {
	justify-content: space-between;
	align-items: center;
	padding: 2px 6px;
	border-radius: 4px;
	transition: background-color 0.3s ease;
}
.statistics-section .pair:hover {
	background-color: rgba(0, 0, 0, 0.05);
}
/* Statystyki osadzone w detalach transportu i zamówienia stoją na całej szerokości widoku, a nie w wąskim panelu
   bocznym listy — na szerokim ekranie po cztery w rzędzie. Do 1200 px obowiązuje wspólna reguła jednej statystyki
   w wierszu, więc próg zaczyna się tuż nad nią. */
@media (min-width: 1201px) {
	.statistics-embedded .statistics-section ul.list-group {
		grid-template-columns: repeat(4, minmax(0, 1fr));
	}
}
.statistics-section .pair label {
	flex: 0 1 auto;
	text-align: left;
	font-weight: normal;
	padding-right: 10px;
}
.statistics-section .pair .field-no-vertical-space,
.statistics-section .pair .flex-item,
.statistics-section .pair > field {
	flex: 0 0 auto;
	text-align: right;
}
/* Kwota dwuwalutowa (statystyki + topbar detali): hierarchie niesie wylacznie pogrubienie gornej
   linii. Dolna nie ma wlasnego koloru — dziedziczy kolor tekstu sekcji — i zostaje w pelnym
   rozmiarze. Wczesniej byla zmniejszona do 0.85em i przygaszona --color-sidebar-text-muted
   (tokenem chrome'u sidebara, w obu motywach tym samym szarym #8a8f9e / #8a9099), co na ciemnej
   powierzchni dawalo 4,2:1 przy ~10 px, czyli praktycznie nieczytelna druga waluta. */
/* Stos wartości jedna pod drugą to jedna wielkość w dwóch ujęciach (kwota w walucie
   podstawowej i dodatkowej, wartość i jej przelicznik), nie dwa osobne pola — pierwsza
   jest tą właściwą, więc ją pogrubiamy, a druga stoi przy niej jako uzupełnienie. */
.field-no-vertical-space > field:first-child {
	font-weight: bold;
}

.field-no-vertical-space > field:not(:first-child) {
	font-size: 1em;
}
/* tabela w sekcji statystyk korzysta z content-boxa samej sekcji (collapsible) - bez wewnetrznej, podwojnej obwoluty */
.statistics-section .content-box {
	background: transparent;
	box-shadow: none;
	border-radius: 0;
	margin: 0;
	padding: 0;
}

/* Statystyka transakcji zgrupowana po pojazdach: bez tych trzech regul tabela jest scianna liczb, w
   ktorej nie widac, gdzie konczy sie jeden pojazd. Hierarchie niesie pogrubienie wiersza pojazdu
   (z jego sumami), wciecie rozwinietych kategorii i linia nad wierszem Razem — kolorow nie
   wprowadzamy, zeby wiersze dziedziczyly motyw sekcji. */
.statistic-group-header td {
	font-weight: bold;
	padding-top: 12px;
}
.statistic-group-item {
	padding-left: 32px;
}
.statistic-group-total td {
	font-weight: bold;
	border-top: 1px solid var(--color-border);
}

.flex {
	display: flex;
	width: 100%;
	flex-wrap: nowrap;
	align-items: center;  
	justify-content: space-between;
}

form .flex {
	padding-top: 0px;
}

.dropdown-menu {
	padding: 6px 0;
	font-size: inherit;
	cursor: default;
	min-width: 260px;
	max-width: calc(100vw - 16px);
	max-height: calc(100vh - 100px);
	overflow-y: auto;
	overflow-x: hidden;
	background-color: var(--color-surface);
	background-clip: padding-box;
	/* Wyrazna krawedz + gleboki cien: menu to nakladka (m.in. arkusz edycji
	   pola) i bez tego zlewa sie z trescia o tym samym tle. */
	border: 1px solid var(--color-border-strong);
	border-radius: 0.6em;
	box-shadow: 0 8px 28px var(--color-shadow), 0 0 0 1px var(--color-chrome-edge);
	z-index: 1100;
}

.dropdown-menu .divider,
.dropdown-menu li.divider {
	height: 1px;
	margin: 4px 10px;
	background-color: rgba(20, 18, 42, 0.08);
	overflow: hidden;
}

/* W dark mode jasna powierzchnia dropdownu zamienia się na ciemną — przyciemniony
   token bordera daje wyraźny rowek oddzielający sekcje (jasny dot. light). */
html[data-theme="dark"] .dropdown-menu .divider,
html[data-theme="dark"] .dropdown-menu li.divider {
	background-color: var(--color-border);
}

/* Narrow phones: dropdowns shrink so they don't push off-screen, options get
   tighter padding so they remain tap-friendly without overflowing horizontally. */
@media (max-width: 480px) {
	.dropdown-menu {
		min-width: calc(100vw - 16px);
		max-width: calc(100vw - 16px);
	}
	.dropdown-menu [dropdown-option] {
		padding: 9px 12px;
	}
	.field-li-input,
	.search-address-header {
		padding: 10px;
	}
}

/* === Unified dropdown option styling ===================================
   Every menu row carrying [dropdown-option] (a) is a full-width flex row,
   (b) uses a fixed icon column, (c) reveals an accent stripe on hover/active,
   (d) never changes its background, (e) inherits .btn .btn-default from the
   directive so .btn.disabled { pointer-events:none } continues to work.

   :is() collapses the icon-class / state-pseudo / destructive-trigger lists
   that would otherwise repeat 4–6 times across the rule block. */

.dropdown-menu li {
	display: block;
}

/* Wylogowanie jest zwyklym formularzem POST, wiec opcja menu ma nad soba jeszcze jeden element;
   wyjmujemy go z drzewa pudelek, zeby wiersz wygladal tak samo jak pozostale. */
.dropdown-menu li > form {
	display: contents;
}

/* Shared selector: every standard option row + nested submenu-toggle row uses
   the same layout. Bound to a CSS variable for easy reuse below. */
.dropdown-menu :is([dropdown-option], .unt-dropdown > .dropdown-toggle) {
	position: relative;
	display: flex;
	align-items: center;
	width: 100%;
	padding: 7px 14px;
	margin: 0;
	border: 0;
	border-radius: 0;
	text-align: left;
	white-space: nowrap;
	background-color: transparent;
	color: var(--color-text-primary);
	transition: color var(--sidebar-transition);
}

/* Left accent stripe slides in on hover — visual cue without changing background. */
.dropdown-menu :is([dropdown-option], .unt-dropdown > .dropdown-toggle)::before {
	content: '';
	position: absolute;
	left: 0;
	top: 4px;
	bottom: 4px;
	width: 3px;
	background-color: transparent;
	border-radius: 0 2px 2px 0;
	transform: scaleY(0);
	transition: transform var(--sidebar-transition), background-color var(--sidebar-transition);
}

/* Content wrappers (delete/clone/download/show-file) become transparent in
   the flex layout so their inner icon + label align identically to inline
   options. */
.dropdown-menu [dropdown-option] > :is(delete-button-content, clone-button-content, download-button-content, show-file-button-content) {
	display: contents;
}

/* Postfiks etykiety opcji — "(nowa karta)" obok "Detale". Opcja jest kontenerem flex, wiec spacja
   tekstowa przed nawiasem nie zostawia odstepu: biala spacja na poczatku elementu flex jest ucinana
   i oba napisy sklejaja sie w "Detale(nowa karta)". Odstep daje wiec margines, a nie znak spacji —
   nieograniczony do .dropdown-menu, bo ten sam przycisk stoi tez poza menu (modale importu AI). */
.dropdown-option-postfix {
	margin-left: 4px;
}

.dropdown-menu :is([dropdown-option], .unt-dropdown > .dropdown-toggle) :is(i, .fa, .fas, .far, .fab, .glyphicon) {
	width: 1.5em;
	margin-right: 8px;
	padding: 0;
	text-align: center;
	flex-shrink: 0;
	transition: transform var(--sidebar-transition);
}

/* Safety net: options shipped without an icon still align with icon-having
   rows. Indent the label by the same width the icon column would occupy. */
.dropdown-menu [dropdown-option]:not(:has(> :is(i, .fa, .fas, .far, .fab, .glyphicon, delete-button-content, clone-button-content, download-button-content, show-file-button-content, .status-pill))) {
	padding-left: calc(14px + 1.5em + 8px);
}

/* Hover / focus / keyboard-active share the same cue: accent text, stripe
   slides in, icon nudges 2px right. */
.dropdown-menu :is([dropdown-option], .unt-dropdown > .dropdown-toggle):is(:hover, :focus, :active, .active) {
	background-color: transparent;
	border: 0;
	color: var(--color-accent);
}

.dropdown-menu :is([dropdown-option], .unt-dropdown > .dropdown-toggle):is(:hover, :focus, :active, .active)::before {
	background-color: var(--color-accent-bg);
	transform: scaleY(1);
}

.dropdown-menu :is([dropdown-option], .unt-dropdown > .dropdown-toggle):is(:hover, :focus, .active) :is(i, .fa, .fas, .far, .fab, .glyphicon) {
	transform: translateX(2px);
}

/* Backend marked an option as unavailable via the actionClass / fieldClass / enumClass
   filters → "disabled", or wrapping <li> got .disabled (e.g. field directive form-invalid state).
   Descendant, not child: the option may sit inside a component element (<li><delete-by-ids-button/></li>).
   .btn.disabled, .btn[disabled] blocks pointer-events at runtime; here we
   add the visual treatment so the user reads "you cannot pick this". An option whose
   action is still in flight (.unt-click-pending from unt-click) reads the same way, as it
   did when the handler used to set "disabled". */
.dropdown-menu :is([dropdown-option]:is(.disabled, [disabled], .unt-click-pending), li.disabled [dropdown-option]) {
	color: var(--color-text-muted);
	background-color: transparent;
	opacity: 0.55;
	cursor: not-allowed;
	pointer-events: none;
}

.dropdown-menu :is([dropdown-option]:is(.disabled, [disabled], .unt-click-pending), li.disabled [dropdown-option])::before {
	display: none;
}

.dropdown-menu :is([dropdown-option]:is(.disabled, [disabled], .unt-click-pending), li.disabled [dropdown-option]) :is(i, .fa, .fas, .far, .fab, .glyphicon) {
	transform: none;
}

/* Status-pill inside a disabled option loses its color so it doesn't look
   selectable — keep the chip shape, drop the saturation. */
.dropdown-menu :is([dropdown-option]:is(.disabled, [disabled], .unt-click-pending), li.disabled [dropdown-option]) .status-pill {
	background-color: var(--color-surface-alt);
	color: var(--color-text-muted);
	border-color: var(--color-border-input);
	filter: grayscale(100%);
}

/* Destructive trigger: explicit .dropdown-option-danger class, the
   delete-button-content tag, or a trash / eraser icon. */
.dropdown-menu [dropdown-option]:is(.dropdown-option-danger, :has(delete-button-content), :has(> .fa-trash-can), :has(> .fa-trash), :has(> .fa-eraser)) {
	color: var(--color-danger-alt);
}

.dropdown-menu [dropdown-option]:is(.dropdown-option-danger, :has(delete-button-content), :has(> .fa-trash-can), :has(> .fa-trash), :has(> .fa-eraser)):is(:hover, :focus) {
	color: var(--color-danger-hover);
}

.dropdown-menu [dropdown-option]:is(.dropdown-option-danger, :has(delete-button-content), :has(> .fa-trash-can), :has(> .fa-trash), :has(> .fa-eraser)):is(:hover, :focus)::before {
	background-color: var(--color-danger-alt);
}

/* Primary action (save / add-new — recognised by the floppy-disk icon) wears
   the accent color in its resting state so the user sees it as the confirming
   choice in the menu. */
.dropdown-menu [dropdown-option]:has(> .fa-floppy-disk) {
	color: var(--color-accent);
	font-weight: 500;
}

.open>.dropdown-menu>li>a {
	font-size: inherit;
}

/* Returned-values block: enum lists and search results share the same wrapper
   styling — a soft tinted card so the user reads them as one coherent results
   area. Items inside still use the unified [dropdown-option] hover/active
   treatment (left accent stripe + icon nudge). */
.dropdown-menu .options,
.dropdown-menu .search-address {
	margin: 4px 8px;
	padding: 4px 0;
	list-style: none;
	background-color: rgba(20, 18, 42, 0.04);
	border-radius: 6px;
	overflow: hidden;
}

.dropdown-menu .options > li,
.dropdown-menu .search-address > li {
	list-style: none;
	padding: 0;
	margin: 0;
}

/* Enum image (small svg next to the value label) doesn't get the icon-column
   treatment — keep it tight to the text. */
.dropdown-menu .options [dropdown-option] > .enum-image {
	width: auto;
	height: 1em;
	margin-right: 8px;
	flex-shrink: 0;
}

/* Empty results card disappears so we don't show a blank tinted block. */
.dropdown-menu .options:empty,
.dropdown-menu .search-address:empty {
	display: none;
}

.status-pill {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	padding: 3px 12px;
	border-radius: 4px;
	border: 1px solid;
	font-weight: 600;
	line-height: 1.4;
	text-align: center;
}

/* Color tokens — same palette as .btn.btn-status.active.X used for the displayed
   value, so each option previews exactly what the row will look like once picked. */
.status-pill.grey-light            { background-color: var(--color-surface-alt); color: var(--color-text-secondary); border-color: var(--color-text-secondary); }
.status-pill.very-light-cyan       { background-color: var(--color-teal-soft-bg); color: var(--color-teal); border-color: var(--color-teal); }
.status-pill.light-cream-yellow    { background-color: var(--color-warning-soft-bg); color: var(--color-warning-text); border-color: var(--color-warning-text); }
.status-pill.light-mint-green      { background-color: var(--color-success-soft-bg); color: var(--color-success-text); border-color: var(--color-success-soft-bg-hover); }
.status-pill.light-pink-white      { background-color: var(--color-purple-soft-bg); color: var(--color-purple); border-color: var(--color-purple); }
.status-pill.light-lemon-yellow    { background-color: var(--color-warning-soft-bg); color: var(--color-warning-text); border-color: var(--color-warning-text); }
.status-pill.light-sky-blue        { background-color: var(--color-info-soft-bg); color: var(--color-info-hover); border-color: var(--color-info-hover); }
.status-pill.light-baby-blue       { background-color: var(--color-info-soft-bg); color: var(--color-info-text); border-color: var(--color-info-text); }
.status-pill.light-yellow          { background-color: var(--color-yellow-soft-bg); color: var(--color-yellow); border-color: var(--color-yellow); }
.status-pill.light-orange          { background-color: var(--color-orange-soft-bg); color: var(--color-orange); border-color: var(--color-orange); }
.status-pill.light-salmon-pink     { background-color: var(--color-danger-soft-bg); color: var(--color-danger-text); border-color: var(--color-danger-text); }
.status-pill.light-blue-green      { background-color: var(--color-info-soft-bg); color: var(--color-teal); border-color: var(--color-teal); }
.status-pill.light-grayish-lavender { background-color: var(--color-surface-alt); color: var(--color-text-secondary); border-color: var(--color-text-secondary); }
.status-pill.light-pastel-green    { background-color: var(--color-success-soft-bg); color: var(--color-success-text); border-color: var(--color-success-text); }

/* report-collection-field — inline colored report badge. Kolor bierze się z .status-pill, które
   deklaruje komplet klas palety EnumColorService, więc kolejny status raportu zadziała bez dopisku;
   tutaj zostają tylko różnice kształtu względem pigułki. */
.report-badge-list {
	display: flex;
	flex-wrap: wrap;
	margin-bottom: 2px;
}
.report-badge {
	display: inline-block;
	/* .status-pill rozciąga się na całą szerokość komórki — oznaczenie ma być szerokie na swój tekst. */
	width: auto;
	max-width: 160px;
	min-width: 14px;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	vertical-align: middle;
	padding: 1px 8px;
	margin: 0 2px 2px 0;
	border: 1px solid transparent;
	border-radius: 4px;
	font-weight: 600;
	cursor: pointer;
	text-decoration: none;
}
.report-badge:hover {
	text-decoration: none;
	opacity: 0.85;
}
/* Inside the results card, hover/active gets a soft full-row background tint
   so the whole option reads as highlighted (the left accent stripe alone was
   too subtle — looked like the cue was only at the edge). */
.dropdown-menu .options [dropdown-option]:hover,
.dropdown-menu .options [dropdown-option]:focus,
.dropdown-menu .options [dropdown-option].active,
.dropdown-menu .search-address [dropdown-option]:hover,
.dropdown-menu .search-address [dropdown-option]:focus,
.dropdown-menu .search-address [dropdown-option].active {
	background-color: rgba(97, 98, 241, 0.10);
}

/* Nested dropdown-toggle (e.g. the translator picker inside transport-message)
   blends into the surrounding options instead of looking like a stray
   bootstrap button. It reuses the [dropdown-option] body styling via the
   shared :is() selectors above; only the chevron suffix and submenu-open
   accent are unique to it. */
.dropdown-menu .unt-dropdown {
	display: block;
}

.dropdown-menu .unt-dropdown > .dropdown-toggle {
	box-shadow: none;
}

.dropdown-menu .unt-dropdown > .dropdown-toggle::after {
	content: '\f054';
	font-family: 'Font Awesome 6 Free';
	font-weight: 900;
	margin-left: auto;
	font-size: 0.75em;
	opacity: 0.4;
	flex-shrink: 0;
	transition: transform var(--sidebar-transition), opacity var(--sidebar-transition);
}

.dropdown-menu .unt-dropdown.open > .dropdown-toggle {
	color: var(--color-accent);
}

.dropdown-menu .unt-dropdown > .dropdown-toggle:is(:hover, :focus)::after,
.dropdown-menu .unt-dropdown.open > .dropdown-toggle::after {
	opacity: 1;
	transform: translateX(2px);
}

.content-box {
	padding: 4px 8px 4px 8px;
	margin: 1px 8px 8px 8px;
	border-radius: 8px;
	background: var(--color-surface);
	box-shadow: var(--shadow-card);
}

/* AI-import modal: pin the form (suggestion + file + add/clear buttons) above
   the scrolling drafts list. z-index lifts it over the later-in-DOM drafts that
   would otherwise paint on top while scrolling. */
.ai-import-form-sticky {
	position: sticky;
	top: 0;
	z-index: 5;
}

/* gdy collapsible nie ma treści (np. pusta, ukryta tabela) - nie pokazuj pustego boxa */
.content-box:not(:has(*)) {
	display: none;
}

/* Lewa krawędź akcentem zaznacza zasięg paska nagłówkowego — gdzie się zaczyna i
   dokąd sięga, zanim zacznie się treść widoku. Tak samo znaczona jest przyklejona
   sekcja przewozu, bo oba paski niosą dane nagłówkowe. */
.content-box-details-topbar {
	padding: 4px;
	background-color: var(--color-border);
	border-top: 1px solid var(--color-border-strong);
	border-left: 3px solid var(--color-accent);
}

.content-box-section:hover {
	box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;
}

.content-box-header {
	display: inline-flex;
	align-items: center;
	overflow: visible;
	width: 100%;
	border: 1px solid transparent;
	min-height: 30px;
}

.content-box-header:hover {
	background: rgba(0, 0, 0, 0.05);
}

.highlighted-section {
	background: var(--color-surface-highlight);
	box-shadow: var(--shadow-thead);
}

/* Tabela kluczy obcych jest blokiem, a element komponentu domyślnie jest inline. */
foreign-key-table {
	display: block;
}

/* Wynik zamówienia w nagłówku (suma dystansów, przychodów, zysk): para kwot czyta się jako jedna
   wartość — główna pogrubiona, przeliczenie ciasno pod nią, mniejsze i bez pogrubienia. */
.freight-order-summary {
	padding: 2px 4px;
	border-radius: 4px;
}

.freight-order-summary .field-no-vertical-space .form-value {
	line-height: 1.2;
}

.freight-order-summary .field-no-vertical-space > field:not(:first-child) .form-value {
	font-size: 0.9em;
	font-weight: normal;
}

/* Okno „Uzupełnij” raportu przystanku: wariant daty to wybór w wierszu przyjazdu albo wyjazdu, a wpis
   własny stoi w komórce obok swojego wyboru. */
.report-date-variants th,
.report-date-variants td {
	vertical-align: middle;
}

.report-date-variant {
	display: flex;
	align-items: center;
	gap: 6px;
	margin: 0;
	font-weight: normal;
	white-space: nowrap;
}

/* Trzy liczniki dystansu — z mapy, z licznika i płatny — mieszczą się w dwóch liniach, jak przychód
   i zysk obok, więc wyróżniony blok nie rośnie: podpis nad wartością, mniejsza czcionka i wartość bez
   minimalnej wysokości pola. Zajmują całą komórkę, bez etykiety z lewej — każdy ma własny podpis, a
   w trzech kolumnach obok etykiety nie mieściła się już pięciocyfrowa liczba kilometrów. Co się
   nie mieści, ucina się wielokropkiem zamiast przewijać komórkę. */
.freight-order-distances {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	column-gap: 4px;
	padding: 2px 4px;
}

.freight-order-distances-caption {
	display: block;
	overflow: hidden;
	font-size: var(--font-xs);
	line-height: 1.2;
	color: var(--color-text-muted);
	white-space: nowrap;
	text-overflow: ellipsis;
}

.freight-order-distances .form-box {
	min-height: 0;
	margin: 0;
	white-space: nowrap;
}

.freight-order-distances .form-value {
	min-height: 0;
	padding: 0;
	font-size: 0.9em;
	line-height: 1.2;
}

.freight-order-distances .form-value > span.field-value-with-postfix {
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
}

.content-box>table {
	width: 100%;
	overflow: auto;
}


.content-stop-header {
	position: sticky;
	top: 0;
	z-index: 10;
	background-color: var(--color-surface);
	border-radius: 4px;
	border-bottom: 1px solid var(--color-border-strong);
}

.content-stop {
	background-color: var(--color-surface);
	padding: 8px;
	border-radius: 8px;
	margin: 2px 4px;
}

.current-route {
	background-color: var(--color-success-soft-bg-hover);
}

.late-possibility {
	background-color: var(--color-danger-soft-bg-hover);
	border-color: red;
}

.past-route {
	background-color: var(--color-surface-muted);
	font-style: italic;
}

button.route-btn {
	margin: 1px;
}

/* Punkty zaliczone i przyszle. Tlo, obwodka i kolor tekstu z tokenow — i to dla wszystkich stanow,
   bo bootstrapowe `.btn:hover/.btn:focus` narzuca `color: #333`, ktory w dark mode zlewa sie z
   chipem, a bez wlasnego tla <button> maluje sie systemowym ButtonFace i UA sam go rozjasnia na
   hover. Te chipy nie maja zadnej akcji na klik, wiec zaden feedback hover/active nie jest tu
   potrzebny. !important nadpisuje stany .btn z bootstrapa. */
button.route-btn.route-btn-past,
button.route-btn.route-btn-future {
	background-color: var(--color-surface-muted) !important;
	background-image: none !important;
	border-color: var(--color-text-muted) !important;
	color: var(--color-text-primary) !important;
}

/* Punkt zaliczony wyszarza napis 1:1 z kolumna statusu punktu trasy (.stop-status-finished);
   !important, bo wspolna regula past/future wyzej ustawia kolor z !important. */
button.route-btn.route-btn-past {
	font-style: italic !important;
	color: var(--color-status-finished-text) !important;
}

/* Biezacy punkt. Samo route-btn-current to przypadek "zagrozenie nieobliczone" — neutralne,
   przyciemnione tlo (w dark blisko czerni). Zielone/czerwone tlo dokladaja generyczne klasy
   statusu, ktore kontroler dopina z tego samego flagu latePossibility, co pasek postepu i chip
   rezerwy czasu. Tekst i obwodka zostaja w --color-text-primary, zeby "biezacy" bylo rozpoznawalne
   niezaleznie od statusu, a etykieta czytelna na kazdym z trzech tel. */
button.route-btn.route-btn-current {
	background-color: var(--color-bg-app) !important;
	color: var(--color-text-primary) !important;
	font-weight: bold !important;
	border: 1px solid var(--color-text-primary) !important;
}

button.route-btn.route-btn-current.light-mint-green {
	background-color: var(--color-success-soft-bg) !important;
}

button.route-btn.route-btn-current.light-salmon-pink {
	background-color: var(--color-danger-soft-bg) !important;
}

/* Plakietka z dystansem do punktu: para odwrotna wzgledem powierzchni (tlo = kolor tekstu
   drugorzednego, tekst = kolor powierzchni) — czytelna w obu motywach. Wczesniej tlo
   --color-text-muted + biel z .badge dawalo w dark 2,1:1. */
button.route-btn > .badge {
	background-color: var(--color-text-secondary);
	color: var(--color-surface);
}

/* Punkt przyszly odrozniamy kursywa dystansu, a nie przygaszeniem: wczesniejsze opacity: 0.7 na
   calym chipie rozcienczalo tekst i plakietke do granicy czytelnosci w dark mode. */
button.route-btn.route-btn-future > .badge {
	font-style: italic;
}

.route-row-td {
	text-align: center;
	padding: 4px 8px;
}

.route-time-reserve {
	margin: 0 4px;
	padding: 2px 6px;
	border-radius: 8px;
	white-space: nowrap;
}

.route-progress {
	height: 16px;
	margin: 4px auto 0 auto;
	max-width: 80%;
	position: relative;
}

.route-progress-label {
	position: absolute;
	left: 0;
	right: 0;
	text-align: center;
	line-height: 16px;
	color: var(--color-text-primary);
}

/* Route-progress component (custom-list row/column): centre the route-point buttons over the progress
   bar, which is itself centred (margin auto, max-width 80%). The old monitoring table did this via its
   .route-row-td; the component now owns it so it holds in any custom-list cell. */
freight-route-progress {
	display: block;
	text-align: center;
}

.past-route .form-value {
	color: var(--color-text-secondary);
	font-style: italic;
}


/*--------------------*/
/*-FILTRY-------------*/
/*--------------------*/

.filter-header {
	display: flex;
	padding: 6px 8px;
	gap: 6px;
	align-items: center;
	flex-wrap: nowrap;
	background: var(--color-surface);
	border-radius: 6px 6px 0 0;
	margin-bottom: 0;
	min-width: 0;
}

html[data-theme="dark"] .filter-header {
	background: #16181a;
}

.filter-header > .btn,
.filter-header > .filter-btn-wrap,
.filter-header > .saved-filters-section {
	flex: 0 0 auto;
	white-space: nowrap;
}

.filter-header > .universal-search-wrapper {
	flex: 1 1 auto;
	min-width: 0;
}


.btn-xs {
	line-height: unset;
    padding: 1px;
}

/* Bez z-index: blok jest elementem flexa, więc z-index robił z niego osobną warstwę, a w niej zostawały
   edytor filtra i menu belki (position: fixed, z-index ≥ 1000) — sekcja boczna listy (z-index 10)
   zasłaniała wtedy „Zastosuj”. Menu filtrów mają leżeć nad wszystkim poza oknami. */
.filter-block {
	box-shadow: var(--shadow-2);
	margin: 0px 0px 8px 0px;
}

.list-block {
	overflow: auto;
	height: 100%;
}

/* Przycisk w liście stoi w tym samym wierszu co pola i musi mieć ich wysokość. Bez tego
   wiersz z przyciskiem był wyższy od wiersza z samymi polami (przycisk bez klasy rozmiaru
   30px i btn-sm 31px wobec 24px pustego pola edytowalnego), więc kolumny rozjeżdżały się
   w pionie, a strzałki kolejności stały raz wyżej, raz niżej od sąsiadów. Wysokość bierze
   się z tej samej zmiennej co minimum pola — dwie liczby nie mogą się wtedy rozejść.
   Wyliczenie: line-height + dwa piksele ramki daje dokładnie --form-min-height, a pionowe
   paddingi i marginesy schodzą do zera, bo to one dokładały te kilka pikseli.
   Poziomy padding jest jeden dla wszystkich rozmiarów, bo btn-xs miał go 1px, a btn i btn-sm
   8px — przyciski o równej wysokości wychodziły wtedy dwa razy węższe jedne od drugich
   (menu przystanku 16px obok strzałki 28px). Bok kwadratu jako minimum szerokości pilnuje,
   żeby przycisk z wąską ikoną nie zrobił się węższy od wysokości. */
.list-block .btn {
	min-height: var(--form-min-height);
	min-width: var(--form-min-height);
	line-height: calc(var(--form-min-height) - 2px);
	padding: 0 6px;
	margin: 0 1px;
}

/* Chip łamiący się na kilka linii nie może dziedziczyć interlinii dobranej do przycisku
   jednolinijkowego: tamta równa się wysokości kontrolki, więc nazwisko rozbite na trzy linie
   dostawało trzy razy po 22px i chip rósł do 68px. Interlinia wraca do proporcjonalnej, a za
   wyśrodkowanie tekstu w jednolinijkowym chipie odpowiada teraz flex zamiast interlinii —
   dzięki temu minimalna wysokość kontrolki dalej obowiązuje i chipsy stoją równo z polami. */
.list-block .btn.text-wrap {
	display: inline-flex;
	align-items: center;
	line-height: 1.2;
}

.list-first-load-spinner {
	display: flex;
	justify-content: center;
	align-items: center;
	padding: 60px 0;
}

.list-spinner {
	width: 44px;
	height: 44px;
	border: 4px solid var(--color-surface-alt);
	border-top: 4px solid var(--color-danger-alt);
	border-radius: 50%;
	animation: list-spin 1s linear infinite;
}

@keyframes list-spin {
	0%   { transform: rotate(0deg); }
	100% { transform: rotate(360deg); }
}

/* ===== Ekran ladowania aplikacji =====
   Widoczny od wejscia na "/" do wyrenderowania pierwszego widoku. Musi byc statycznym HTML
   w index.jsp i czystym CSS tutaj, bo w tym oknie czasowym Angular jeszcze nie dziala,
   a uniter.js nie jest nawet pobrany. Wyglad celowo NIE zmienia sie z motywem: tlo jest
   zawsze ciemne (powod przy .app-loader), a spinner i tekst sa dobrane do ciemnego tla. */
.app-loader {
	position: fixed;
	inset: 0;
	z-index: 1300;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 22px;
	/* Ciemne tlo w obu motywach, bo poziomy logotyp Uniter istnieje wylacznie w wersji bialej
	   (logo.svg, ten sam plik co w topbarze i na stronie logowania). Przy okazji nawiazuje do
	   ciemnej strony logowania, z ktorej uzytkownik tu trafia. */
	background: var(--color-sidebar-bg);
	transition: opacity 250ms ease;
}

.app-loader-logo {
	width: 200px;
	max-width: 60vw;
	height: auto;
	animation: app-loader-appear 400ms ease both;
}

.app-loader-spinner {
	width: 28px;
	height: 28px;
	border: 3px solid rgba(255, 255, 255, 0.18);
	border-top: 3px solid var(--color-accent-strong);
	border-radius: 50%;
	animation: list-spin 1s linear infinite;
}

.app-loader.is-hidden {
	opacity: 0;
	pointer-events: none;
}

/* Stan awarii pobierania bootstrapu/bundla: zamiast spinnera i "Ladowanie..." komunikat
   z przyciskiem odswiezenia - uzytkownik nigdy nie zostaje z pusta strona. */
.app-loader-error {
	display: none;
	flex-direction: column;
	align-items: center;
	gap: 14px;
}

.app-loader.has-error > .app-loader-spinner,
.app-loader.has-error > .app-loader-text {
	display: none;
}

.app-loader.has-error .app-loader-error {
	display: flex;
}

.app-loader-refresh {
	padding: 8px 22px;
	border: 1px solid rgba(255, 255, 255, 0.35);
	border-radius: 4px;
	background: transparent;
	color: rgba(255, 255, 255, 0.85);
	font-size: var(--font-sm);
	cursor: pointer;
}

.app-loader-refresh:hover {
	border-color: rgba(255, 255, 255, 0.6);
	background: rgba(255, 255, 255, 0.08);
}

@keyframes app-loader-appear {
	from { opacity: 0; transform: translateY(6px); }
	to   { opacity: 1; transform: none; }
}

.list-empty-message {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	padding: 60px 0;
	gap: 12px;
	color: var(--color-text-muted);
}

.list-empty-message i {
	font-size: 36px;
}

.filter-box {
	min-height: auto;
	background-color: var(--color-surface-highlight);
	border-radius: 4px;
}

.saved-filters-section {
	display: inline-flex;
	align-items: center;
	gap: 4px;
	flex-wrap: nowrap;
	padding: 2px 4px;
	background-color: var(--color-saved-filters-bg);
	border-radius: 4px;
}

.saved-filters-dropdown {
	display: inline-block;
}

.saved-filters-toggle {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	max-width: 240px;
}

.saved-filters-current {
	font-weight: 600;
	max-width: 160px;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}


.saved-filters-menu {
	min-width: 200px;
	max-height: 320px;
	overflow-y: auto;
	padding: 4px 0;
}

.saved-filters-menu > li > a {
	display: flex;
	align-items: center;
	gap: 6px;
	padding: 6px 12px;
}

.saved-filters-menu > li.active > a {
	background-color: var(--color-surface-highlight);
	color: var(--color-text-secondary);
	font-weight: 600;
}

.saved-filters-check {
	color: var(--color-success);
	font-size: var(--font-sm);
	flex: 0 0 12px;
}

.saved-filters-check.invisible {
	visibility: hidden;
}

.saved-filters-empty > a {
	color: var(--color-text-muted);
	font-style: italic;
	cursor: default;
}

.list-tab-selector {
	display: inline-block;
}

.list-tab-selector-toggle {
	max-width: 240px;
}

.list-tab-selector-toggle > i,
.list-tab-selector-toggle > span {
	vertical-align: middle;
}

.list-tab-selector-current {
	display: inline-block;
	font-weight: 600;
	max-width: 160px;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	vertical-align: middle;
}

.list-tab-selector-menu {
	min-width: 200px;
	max-height: 320px;
	overflow-y: auto;
	padding: 4px 0;
}

.list-tab-selector-menu > li > a {
	display: flex;
	align-items: center;
	gap: 6px;
	padding: 6px 12px;
}

.list-tab-selector-menu > li.active > a {
	background-color: var(--color-surface-highlight);
	color: var(--color-text-secondary);
	font-weight: 600;
}

.list-tab-selector-check {
	color: var(--color-success);
	font-size: var(--font-sm);
	flex: 0 0 12px;
}

.list-tab-selector-check.invisible {
	visibility: hidden;
}


/* Save filter dialog — <md-dialog> dokłada $mdDialog wokół komponentu, a treść i przyciski układają się w nim
   tak, jakby stały tam bezpośrednio. */
md-dialog:has(> save-filter-dialog) {
	max-width: 480px;
	width: 90vw;
}

save-filter-dialog {
	display: contents;
}

.save-filter-dialog-title {
	margin: 0 0 16px 0;
	font-size: 18px;
	font-weight: 600;
}

.save-filter-tiles {
	display: flex;
	gap: 12px;
	margin: 16px 0;
	flex-wrap: wrap;
}

.save-filter-tile {
	flex: 1 1 140px;
	min-width: 0;
	padding: 20px 12px;
	border: 2px solid var(--color-bg-app);
	border-radius: 8px;
	text-align: center;
	cursor: pointer;
	transition: all 0.2s ease;
	background-color: var(--color-surface);
	user-select: none;
}

.save-filter-tile:hover {
	border-color: var(--color-accent);
	background-color: var(--color-surface-muted);
}

.save-filter-tile.active {
	border-color: var(--color-accent);
	background-color: var(--color-surface-highlight);
	box-shadow: 0 2px 6px rgba(0,0,0,0.12);
}

.save-filter-tile.disabled {
	opacity: 0.4;
	cursor: not-allowed;
	pointer-events: none;
}

.save-filter-tile-icon {
	font-size: 28px;
	color: var(--color-accent);
	margin-bottom: 8px;
	display: block;
}

.save-filter-tile-title {
	font-weight: 600;
	color: var(--color-text-secondary);
	font-size: 14px;
}

.save-filter-form {
	margin-top: 12px;
}

.save-filter-form label {
	display: block;
	margin-bottom: 6px;
	font-weight: 500;
	color: var(--color-text-secondary);
}

.save-filter-form .form-control {
	width: 100%;
}

.save-filter-warning {
	margin-top: 8px;
	padding: 8px 12px;
	background-color: var(--color-warning-soft-bg);
	border-left: 3px solid var(--color-warning);
	color: var(--color-warning-text);
	border-radius: 4px;
	font-size: 13px;
	display: flex;
	align-items: center;
	gap: 6px;
}

.universal-search-wrapper {
	display: inline-flex;
	align-items: center;
	gap: 4px;
	flex: 1 1 200px;
	min-width: 0;
}

.universal-search-input {
	flex: 1 1 auto;
	min-width: 0;
	padding: 4px 8px;
	line-height: 1.5;
}

.universal-search-btn {
	padding: 4px 10px;
	flex: 0 0 auto;
}

.filter-form-box {
	padding: 0;
}

/* Filter / sort row: mobile-first (stacked), inline on tablets+ */
.filter-separator {
	display: flex;
	flex-direction: column;
	gap: 4px;
	border-radius: 6px;
	padding: 6px 10px;
	width: 100%;
	margin: 2px 0;
	transition: background-color 0.3s ease;
	background-color: transparent;
}

.filter-separator:hover {
	background-color: var(--color-accent-soft-bg);
}

.filter-row-label {
	font-weight: 600;
	color: var(--color-text-secondary);
	line-height: 1.3;
	font-size: var(--font-sm);
	text-transform: uppercase;
	letter-spacing: 0.02em;
}

.filter-row-label label {
	margin: 0;
	font-size: inherit;
}

.filter-row-selector {
	flex: 0 0 auto;
}

.filter-row-value {
	flex: 1 1 auto;
	min-width: 0;
}

.filter-row-actions {
	display: flex;
	gap: 4px;
	flex-wrap: nowrap;
	justify-content: flex-end;
	flex: 0 0 auto;
}

.filter-row-actions .btn {
	min-width: 36px;
	min-height: 36px;
	padding: 6px 10px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
}

.filter-row-value-actions {
	display: flex;
	flex-direction: row;
	align-items: center;
	gap: 6px;
	flex: 1 1 auto;
	min-width: 0;
}

.filter-row-value-actions .filter-row-value {
	flex: 1 1 auto;
	min-width: 0;
}

.sortable-handle {
	flex: 0 0 auto;
	cursor: grab;
	color: var(--color-text-muted);
	padding: 2px 6px;
	display: inline-flex;
	align-items: center;
	user-select: none;
	-webkit-user-select: none;
}

.sortable-handle:hover {
	color: var(--color-text-secondary);
}

.sortable-handle:active {
	cursor: grabbing;
}

.filter-separator.sortable-dragging {
	opacity: 0.4;
}

.filter-separator.sortable-dragover-before {
	box-shadow: inset 0 3px 0 0 var(--color-purple);
}

.filter-separator.sortable-dragover-after {
	box-shadow: inset 0 -3px 0 0 var(--color-purple);
}

@media (min-width: 768px) {
	.filter-separator {
		flex-direction: row;
		align-items: center;
		flex-wrap: wrap;
		gap: 6px;
		padding: 3px 10px;
	}
	.filter-row-label {
		flex: 0 0 20%;
		max-width: 20%;
	}
	.filter-row-selector {
		flex: 0 0 24%;
		max-width: 24%;
	}
	.filter-row-value-actions {
		flex: 1 1 30%;
		min-width: 200px;
	}
	.filter-row-actions .btn {
		min-width: 28px;
		min-height: 28px;
		padding: 4px 8px;
	}
}

.between-range {
	display: flex;
	align-items: center;
	gap: 10px;
	flex-wrap: nowrap;
	width: 100%;
}

.between-range-pair {
	display: flex;
	align-items: center;
	gap: 3px;
	flex: 1 1 0;
	min-width: 0;
}

.between-range-pair > .form-control,
.between-range-pair > unt-datetime-picker {
	flex: 1 1 auto;
	min-width: 0;
}

.between-range-label {
	font-weight: normal;
	margin: 0;
	color: var(--color-text-muted);
	white-space: nowrap;
	font-size: var(--font-sm);
	flex: 0 0 auto;
	padding: 0 2px;
}

.multiselect-fullwidth {
	width: 100%;
}

.multiselect-badge-x {
	cursor: pointer;
	margin-left: 4px;
}

@keyframes filter-row-pulse {
	0%, 100% {
		background-color: rgba(255, 255, 255, 0.5);
		box-shadow: 0 0 0 0 transparent;
	}
	50% {
		background-color: var(--pulse-bg, var(--color-accent-soft-bg));
		box-shadow: 0 0 0 var(--pulse-ring-width, 0) var(--pulse-ring-color, transparent);
	}
}

.filter-btn-wrap.filter-row-highlight {
	animation: filter-row-pulse 0.45s ease-in-out 2;
	--pulse-bg: var(--color-accent-soft-bg);
}

.filter-btn-wrap.filter-row-highlight-duplicate {
	animation: filter-row-pulse 0.5s ease-in-out 3;
	--pulse-bg: var(--color-warning-soft-bg);
	--pulse-ring-width: 2px;
	--pulse-ring-color: var(--color-warning);
}

.filter-box-small .btn {
	margin: 1px 2px 1px 2px;
}

.content-box-header .form-control {
	overflow: hidden;
	text-overflow: ellipsis;
	padding: unset;
}

#filter-select {
	min-width: 200px;
	max-width: 100%;
	overflow: hidden;
	text-overflow: ellipsis;
	margin-right: 5px;
	background-color: var(--color-surface);
	color: var(--color-text-primary);
	border: 1px solid var(--color-border);
	height: var(--form-default-size);
	padding: 2px 4px;
}



/* New structured chip design for simplified filter bar */
.filter-chip,
.sort-chip {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 3px 4px 3px 10px;
	border-radius: 14px;
	font-size: var(--font-sm);
	line-height: 1.3;
	border: 1px solid transparent;
	margin: 0;
	max-width: 100%;
	white-space: nowrap;
}

.filter-chip {
	background: var(--color-info-soft-bg);
	border-color: var(--color-info-soft-bg-hover);
	color: var(--color-info-hover);
}

.sort-chip {
	background: var(--color-purple-soft-bg);
	border-color: var(--color-purple);
	color: var(--color-purple);
}

.filter-chip-icon,
.sort-chip-icon {
	font-size: var(--font-xs);
	opacity: 0.65;
	flex: 0 0 auto;
}

.filter-chip-field,
.sort-chip-field {
	font-weight: 600;
	overflow: hidden;
	text-overflow: ellipsis;
	max-width: 200px;
}

/* Custom-list configurator: show the full field label (incl. the disambiguating "(path)" suffix)
   so it is always clear which field a chip represents — no width cap / truncation here. Long labels
   wrap inside the chip instead of overflowing the panel. */
.custom-list-zone .filter-chip-field {
	max-width: none;
	overflow: visible;
	text-overflow: clip;
	white-space: normal;
}

/* ===== Custom list ("własna lista") — table + configurator ===== */
.custom-list-zone {
	min-height: 120px;
	max-height: 340px;
	overflow-y: auto;
	border: 1px solid transparent;
	border-radius: 4px;
	padding: 8px;
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	align-content: flex-start;
}
/* Reveal the drop-zone borders only once a drag is in progress; the hovered zone gets a stronger highlight. */
body.unt-drag-active .custom-list-zone {
	border-color: #ddd;
	background: rgba(0, 0, 0, 0.02);
}
.custom-list-zone.unt-dragover {
	border-color: #6f42c1;
	background: rgba(111, 66, 193, 0.06);
}
.custom-list-zone .filter-chip {
	cursor: grab;
}
.custom-list-zone .filter-chip.unt-dragging {
	opacity: 0.4;
}
/* Custom-list renders a bare <table> (no Bootstrap `.table` class), so there is no `#ddd` border to fight.
   We supply the baseline Bootstrap gave us — fill width, collapsed borders — plus a
   theme-tokened row separator (light #dddddd unchanged, dark #121417 — correct in dark mode by construction). */
.custom-list > table {
	width: 100%;
	border-collapse: collapse;
}
.custom-list > table > tbody > tr > td {
	vertical-align: middle;
	border-top: 1px solid var(--color-border);
}
/* Stopka sum (10858): wyrozniona od wierszy grubsza linia i pogrubieniem. */
.custom-list > table > tfoot > tr > td {
	vertical-align: middle;
	border-top: 2px solid var(--color-border);
	font-weight: 600;
	background-color: var(--color-surface);
}
/* Checkbox and actions columns shrink to their content; data columns absorb the rest. */
.custom-list table .cl-checkbox,
.custom-list table .cl-actions {
	width: 1%;
	white-space: nowrap;
}
/* Two-row layout: the lower field is a second line under the upper field — same size as the upper
   (not shrunk or muted), both in the data cell and the column header. */
.custom-list .cl-lower {
	margin-top: 2px;
}
/* Expandable row-detail: cl-detail-sticky sizes the block to the visible list width and pins it left.
   Odstep tylko w pionie — odsuwa rozwiniety blok od wiersza, z ktorego wychodzi, i od nastepnego wpisu.
   Poziomego tu nie ma celowo: blok dostaje z dyrektywy sztywna szerokosc rowna widocznemu obszarowi listy,
   wiec padding boczny komorki wypchnalby go poza prawa krawedz i wywolal poziomy scroll. Wciecie w poziomie
   robi wiec sam blok swoim paddingiem. */
.custom-list td.cl-detail {
	padding: 8px 0;
}
/* Rozwinieta sekcja wiersza: wlasna powierzchnia w kolorze akcentu, obwiedziona i zaokraglona, zeby czytalo
   sie ja jako wydzielony blok nalezacy do jednego rekordu, a nie jako kolejny wiersz listy. Regula bez
   prefiksu .custom-list, bo tego samego opakowania uzywaja recznie budowane tabele w detalach. */
.cl-detail-wrap {
	overflow-x: hidden;
	box-sizing: border-box;
	background-color: var(--color-accent-soft-bg);
	border: 1px solid var(--color-border);
	border-left: 4px solid var(--color-accent);
	border-radius: 4px;
	padding: 12px 14px;
}

/* Bootstrapowy .row ma ujemne marginesy boczne, wiec bezposrednio w rozwinietym bloku wystawalby o 15px
   za jego padding — a blok obcina nadmiar (overflow-x), przez co ginela prawa krawedz zawartosci. */
.cl-detail-wrap > .row {
	margin-left: 0;
	margin-right: 0;
}
/* Full-width row component: a colspan cell under the item's main row holding one component (progress, files…).
   Same background as the main row (they are one entry — no separator above), but a stronger bottom border so
   the whole entry is clearly divided from the next one. */
/* Kolumna, ktorej cala trescia jest przycisk rozwijanego menu (opcje transportu, zamowienia, punktu
   trasy). Przycisk jest wezszy od naglowka, wiec dosuniety do lewej wyglada jak zgubiony w komorce —
   srodek jest tu jedynym sensownym zakotwiczeniem. Stos (opcje punktu trasy) centruje kazdy wiersz. */
.cl-cell-center {
	display: flex;
	justify-content: center;
}

.custom-list td.cl-row-component {
	padding: 6px 8px;
	border-top: 0;
	border-bottom: 2px solid var(--color-border-strong);
}
/* Inline column editing on the list header: a drag handle (reorder) + a remove ×, revealed on hover. */
.custom-list th.cl-th-editable {
	position: relative;
}
.custom-list th.cl-th-editable .cl-th-grip,
.custom-list th.cl-th-editable .cl-th-remove {
	position: absolute;
	top: 3px;
	opacity: 0;
	font-size: var(--font-xs);
	transition: opacity 0.1s;
	z-index: 1;
}
.custom-list th.cl-th-editable .cl-th-grip {
	left: 3px;
	cursor: grab;
}
.custom-list th.cl-th-editable .cl-th-remove {
	right: 3px;
	cursor: pointer;
	color: var(--color-danger);
}
.custom-list th.cl-th-editable:hover .cl-th-grip,
.custom-list th.cl-th-editable:hover .cl-th-remove {
	opacity: 0.55;
}
.custom-list th.cl-th-editable .cl-th-grip:hover,
.custom-list th.cl-th-editable .cl-th-remove:hover {
	opacity: 1;
}
.custom-list th.cl-th-editable.unt-dragover {
	box-shadow: inset 3px 0 0 var(--color-purple);
}
/* Saved-layout switcher in the list toolbar (custom-list variant), next to "Konfiguruj" — on the page toolbar
   and in the header of an embedded list, where it stands inline among the section's buttons. */
.app-content-header .cl-toolbar-layout,
.content-box-header .cl-toolbar-layout {
	width: auto;
	height: 30px;
}
/* W nagłówku sekcji przełącznik stoi w jednej linii z przyciskami: ich wysokość, a szerokość ograniczona —
   długa nazwa układu rozpychała nagłówek i spychała „Konfiguruj kolumny" poza ekran (10870, D1); nazwę
   przycina wielokropek z .content-box-header .form-control. */
.content-box-header .cl-toolbar-layout {
	display: inline-block;
	vertical-align: middle;
	height: 27px;
	max-width: 220px;
}
@media (max-width: 767px) {
	.content-box-header .cl-toolbar-layout {
		max-width: 40vw;
	}
}
/* Group-by header row. Background + padding live on the .cl-group-sticky wrapper (not the td), which the
   cl-detail-sticky directive pins to the left at the visible list width — so the value and its background
   stay readable while the wide table is scrolled horizontally. The td itself only spans the columns. */
.custom-list .cl-group-row > td {
	background-color: var(--color-surface-alt);
	/* No separator line — the surface-alt background is the group boundary. */
	border-top: 0;
	padding: 0;
}
.custom-list .cl-group-row .cl-group-sticky {
	background-color: var(--color-surface-alt);
	font-weight: bold;
	padding: 4px 8px;
	white-space: nowrap;
	box-sizing: border-box;
}
/* position:sticky (via cl-detail-sticky) makes these wrappers a stacking context with z-index:auto, which
   traps a fixed dropdown opened inside (e.g. the group value's details editor) below the sticky <thead>.
   While a dropdown is open, lift the wrapper so its dropdown-menu (z-index:1100) floats free — same idiom
   as the sticky-last-col / item-block-collapsed-wrapper rules.
   Two open-state flavours must be matched: Bootstrap widgets toggle `.dropdown.open`, while the entity
   menus (unt-dropdown component) toggle `.unt-dropdown.open` — matching only the first left every ☰ menu
   inside an expanded section painted under the outer list's sticky action column. */
.custom-list .cl-group-row .cl-group-sticky:has(.dropdown.open),
.custom-list .cl-group-row .cl-group-sticky:has(.unt-dropdown.open),
.cl-detail-wrap:has(.dropdown.open),
.cl-detail-wrap:has(.unt-dropdown.open),
.custom-list .cl-detail-wrap:has(.dropdown.open),
.custom-list .cl-detail-wrap:has(.unt-dropdown.open) {
	z-index: 1101;
}

/* Elementy, z których składa się komórka listy własnej (widget pola, wstawiony renderer, poziomy kolekcji),
   nie biorą udziału w układzie — komórka wygląda tak, jakby jej treść stała wprost w <custom-cell>. */
.custom-list custom-cell-content,
.custom-list custom-cell-widget,
.custom-list template-outlet,
.custom-list .cl-stack {
	display: contents;
}
.custom-list .cl-group-label {
	color: var(--color-text-muted);
	font-weight: normal;
	margin-right: 4px;
}
/* The nested level, indented so the eye reads it as a block inside the one above rather than a sibling of it.
   The indent goes on the sticky wrapper's content, not the td, so it survives horizontal scrolling with the
   rest of the header. */
.custom-list .cl-group-row.cl-group-nested .cl-group-sticky {
	padding-left: 28px;
	font-weight: normal;
}
/* The value reuses <field>. Collapse its whole cell chrome to plain inline text next to the label: the root /
   .form-box / .form-value are width:100% blocks, .form-value is flex with its OWN overflow-x:auto (that inner
   scrollbar was hiding the value), and entity fields add a .field-extension. Overriding all of them (rather
   than just the root) is what stops the value dropping below the label and getting an inner scroll. */
.custom-list .cl-group-row custom-cell,
.custom-list .cl-group-row custom-cell field,
.custom-list .cl-group-row custom-cell field > div,
.custom-list .cl-group-row custom-cell .form-box,
.custom-list .cl-group-row custom-cell .form-value,
.custom-list td.cl-row-labeled custom-cell,
.custom-list td.cl-row-labeled custom-cell field,
.custom-list td.cl-row-labeled custom-cell field > div,
.custom-list td.cl-row-labeled custom-cell .form-box,
.custom-list td.cl-row-labeled custom-cell .form-value {
	display: inline !important;
	width: auto !important;
	min-width: 0 !important;
	min-height: 0 !important;
	overflow: visible !important;
	padding: 0 !important;
}
/* Ukrycie tylko w naglowku grupy — to podpis, nie klikalny wiersz. W wierszu danych (.cl-row-labeled)
   .field-extension zostaje widoczny: trzyma przyciski akcji pola encyjnego i kwoty przeliczone na waluty
   systemowe (triple-price-field). */
.custom-list .cl-group-row custom-cell .field-extension,
.custom-list .cl-group-row custom-cell .field-links {
	display: none !important;
}
/* Nazwa pola w pelnoszerokosciowym wierszu wartosci — bez niej sama wartosc (np. termin platnosci) jest
   nie do rozpoznania przy kilku dodanych wierszach. Komponent (pasek postepu, tabela plikow) opisuje sie
   sam, wiec etykiety nie dostaje i zachowuje blokowy layout (td bez .cl-row-labeled). */
.custom-list .cl-row-label {
	color: var(--color-text-muted);
	margin-right: 4px;
}

/* --- Configurator windows (custom-list-configurator-modal, custom-layout-save-modal, custom-list-import-modal) --- */
/* Konfigurator jest szerszy niz zwykle okno xl, ale nie rosnie bez konca na szerokim ekranie. */
.modal-dialog.modal-xl:has(> .modal-content > custom-list-configurator-modal) {
	max-width: 1600px;
}

/* Lancuch flexa okien komponentowych zdejmuje .modal-body dolny odstep (stopka okna encji stoi pod
   nim). Okna konfiguratora maja zwykla stopke .modal-footer, wiec ich tresc zachowuje pelny odstep. */
.modal-content > :is(custom-list-configurator-modal, custom-layout-save-modal, custom-list-import-modal)[modal-instance] > .modal-body {
	padding-bottom: 15px;
}
/* Okna konfiguratora maja stopke z przyciskami od lewej i przyciski wysokosci pola listy — ten sam
   rozmiar co .list-block .btn, z tej samej zmiennej, bo konfigurator otwiera sie nad lista i jej
   przyciski maja wygladac tak samo. */
.modal-content > :is(custom-list-configurator-modal, custom-layout-save-modal, custom-list-import-modal)[modal-instance] > .modal-footer {
	display: flex;
	justify-content: flex-start;
	align-items: center;
	gap: 8px;
}
:is(custom-list-configurator-modal, custom-layout-save-modal, custom-list-import-modal) .btn {
	min-height: var(--form-min-height);
	min-width: var(--form-min-height);
	line-height: calc(var(--form-min-height) - 2px);
	padding: 0 6px;
	margin: 0 1px;
}
custom-list-configurator-modal .cl-layout-bar,
custom-list-configurator-modal .cl-group-bar {
	margin-bottom: 10px;
}
/* One picker per grouping level, side by side on the same bar: "Grupuj po <pole>  i dalej po <pole>". */
custom-list-configurator-modal .cl-group-level {
	margin-right: 12px;
}
/* Searchable group-by picker: a select-like toggle opening a filtered, scrollable field list (a plain
   <select> is unusable with 100+ fields). */
.cl-group-picker {
	display: inline-block;
	position: relative;
	min-width: 220px;
}
.cl-group-picker > .dropdown-toggle {
	cursor: pointer;
	display: flex;
	align-items: center;
	gap: 6px;
}
.cl-group-picker > .dropdown-toggle > span {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
.cl-group-picker .cl-group-caret {
	margin-left: auto;
	color: var(--color-text-muted);
}
.cl-group-picker .cl-group-search {
	padding: 4px 8px;
}
.cl-group-picker .cl-group-options {
	max-height: 260px;
	overflow-y: auto;
	list-style: none;
	margin: 0;
	padding: 0;
}
/* "Groups by list sort" set while the list carries no sort: the mode is chosen but has nothing to follow,
   so the backend arranges the groups by their value instead. The button stays clickable (it cycles the
   modes) and only shows — with its title — that the mode waits for a sort. */
.cl-group-dir.cl-group-dir-waiting {
	opacity: 0.55;
}
custom-list-configurator-modal .cl-search {
	display: inline-block;
	width: 220px;
}

/* Editable column layout: horizontal, wrapping row of two-slot column cards. */
.cl-columns {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	align-content: flex-start;
	min-height: 130px;
	padding: 8px;
}
.cl-col-card {
	width: 200px;
	border: 1px solid #ddd;
	border-radius: 6px;
	padding: 6px;
	background: rgba(0, 0, 0, 0.015);
}
.cl-col-card.unt-dragover {
	border-color: #6f42c1;
	box-shadow: inset 4px 0 0 0 #6f42c1;
}
.cl-col-head {
	display: flex;
	align-items: center;
	gap: 6px;
	margin-bottom: 4px;
}
.cl-col-grip {
	cursor: grab;
	color: #888;
}
.cl-col-remove {
	margin-left: auto;
	cursor: pointer;
	color: #c0392b;
}
.cl-slot {
	min-height: 34px;
	padding: 3px;
	border: 1px dashed transparent;
	border-radius: 4px;
}
body.unt-drag-active .cl-slot {
	border-color: #ddd;
}
.cl-slot.unt-dragover {
	border-color: #6f42c1;
	background: rgba(111, 66, 193, 0.06);
}
.cl-slot-lower {
	margin-top: 4px;
}
.cl-slot .filter-chip {
	cursor: grab;
}
.cl-slot .filter-chip.unt-dragging {
	opacity: 0.4;
}
.cl-slot-placeholder {
	color: #aaa;
	font-size: var(--font-xs);
	font-style: italic;
}
/* Chip badge: multi-value (fa-layer-group) vs single-value (fa-minus) field indicator. */
.cl-multi-icon {
	opacity: 0.55;
	font-size: var(--font-xs);
}
/* Dostępne pola konfiguratora dzielą się na obszary (pola encji, powiązania, głębsze powiązania,
   dodane, komponenty), więc ta jedna strefa układa się w kolumnę — chipsy zawijają się dopiero
   wewnątrz obszaru. Pozostałe strefy (.cl-rows) zostają płaskim workiem chipsów. */
.cl-available {
	flex-direction: column;
	flex-wrap: nowrap;
	gap: 0;
}
.cl-available-group {
	width: 100%;
}
.cl-available-group-head {
	display: flex;
	align-items: center;
	gap: 6px;
	padding: 4px 2px;
	cursor: pointer;
	font-size: var(--font-xs);
	text-transform: uppercase;
	letter-spacing: 0.3px;
	color: #888;
}
.cl-available-group-chips {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	padding-bottom: 6px;
}
/* A field-renderer component (custom widget: progress bar, files…) — teal, set apart from plain (blue) fields. */
.filter-chip.cl-chip-component {
	background: var(--color-teal-soft-bg);
	border-color: var(--color-teal);
	color: var(--color-teal);
}
.cl-component-icon {
	color: var(--color-teal);
	font-size: var(--font-xs);
}
.cl-new-column {
	width: 130px;
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 6px;
	border: 2px dashed #ccc;
	border-radius: 6px;
	padding: 6px;
	color: #888;
}
.cl-new-column.unt-dragover {
	border-color: #6f42c1;
	color: #6f42c1;
}

.filter-chip-op {
	color: rgba(0,0,0,0.55);
	font-weight: normal;
	font-size: var(--font-sm);
	text-transform: lowercase;
}

.filter-chip-value {
	background: rgba(255,255,255,0.85);
	padding: 1px 7px;
	border-radius: 8px;
	font-weight: 500;
	color: var(--color-info-hover);
	overflow: hidden;
	text-overflow: ellipsis;
	max-width: 200px;
}

.filter-chip-close,
.sort-chip-close {
	display: inline-flex;
	width: 18px;
	height: 18px;
	align-items: center;
	justify-content: center;
	border-radius: 50%;
	cursor: pointer;
	margin-left: 2px;
	transition: background 0.15s;
	flex: 0 0 auto;
}

.filter-chip-close:hover {
	background: rgba(13, 71, 161, 0.15);
}

.sort-chip-close:hover {
	background: rgba(74, 20, 140, 0.15);
}

.filter-chip-close i,
.sort-chip-close i {
	font-size: var(--font-xs);
}

.filter-box-small-active>div>table>thead {
	top: var(--filter-box-small-height);
}

.filter-box select.form-control {
	min-width: max-content;
	width: auto;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
}

.filter-scroll-container,
.filter-scroll-container-sort {
	max-height: 320px;
	overflow-y: auto;
	overflow-x: hidden;
	padding: 2px 4px;
}

@media (min-width: 768px) {
	.filter-scroll-container,
	.filter-scroll-container-sort {
		max-height: 70px;
	}
}

.filter-panels-wrapper {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	padding: 4px;
}

.filter-panel,
.sort-panel {
	flex: 1 1 100%;
	min-width: 0;
	padding: 4px;
}

@media (min-width: 992px) {
	.filter-panel,
	.sort-panel {
		flex: 1 1 0;
		min-width: 0;
	}

	.filter-panels-wrapper.only-filters .filter-scroll-container,
	.filter-panels-wrapper.only-orders .filter-scroll-container-sort {
		display: grid;
		grid-auto-flow: column;
		grid-template-columns: 1fr 1fr;
		column-gap: 8px;
		align-content: start;
	}
}

.filter-panel-header,
.sort-panel-header {
	display: flex;
	align-items: center;
	gap: 8px;
	background-color: var(--color-accent-soft-bg);
	padding: 6px 10px;
	border-radius: 4px;
	flex-wrap: nowrap;
}

.filter-panel-title {
	font-size: 14px;
	font-weight: 600;
	margin: 0;
	flex: 0 0 auto;
	color: var(--color-text-secondary);
	white-space: nowrap;
}

.filter-panel-title::after {
	content: ":";
}

.filter-panel-header > md-autocomplete {
	flex: 1 1 0;
	min-width: 0;
	width: auto;
}

.filter-bar-presentation {
	display: flex;
	flex-wrap: wrap;
	padding: 4px 6px;
	gap: 4px;
}

.filter-bar-section {
	display: inline-flex;
	flex-wrap: wrap;
	gap: 4px;
}

.map-box {
	height: 500px;
	z-index: 1 !important;
}

.osm-map-wrapper {
	height: 500px;
}

#list-tab-section .map-box {
	height: calc(100vh - 80px);
	overflow: hidden;
}

/* Wiersz kontrolek mapy na pełną szerokość, by przyciski mogły dosunąć się do prawej krawędzi
   (.row.inline to inline-flex i bez tego kurczyłby się do szerokości treści). */
.row.inline:has(> .map-control) {
	display: flex;
	align-items: center;
	width: 100%;
}

/* Pasek sterowania mapą — jeden rząd o stałej wysokości, w którym przyciski wyrównuje wspólna
   oś. Wysokość stoi tutaj, a nie na grupie przycisków, żeby pasek nie skakał, gdy któraś pozycja
   zniknie (przycisk korków tylko przy mapie Google, opcje POI tylko tam, gdzie są punkty). */
.map-control {
	padding-left: 5px;
	height: 30px;
	flex: 1;
	min-width: 0;
	display: flex;
	align-items: center;
	justify-content: left;
}

/* Grupa przycisków mapy dosunięta do prawej krawędzi (margin-left:auto w flexie .map-control). */
.map-control-actions {
	margin-left: auto;
	display: flex;
	align-items: center;
	gap: 4px;
}

/* Ikona i tekst jako flex-items z odstępem — bez sklejania tekstu z ikoną. */
.map-control-actions .btn {
	display: inline-flex;
	align-items: center;
	gap: 4px;
}

/* Mapa-picker w modalach tworzenia (POI/adres/punkt trasy): bez wiersza kontrolek
   (hideButtons chowa przyciski, a ten wiersz kryje pozostały samotny checkbox autoresize). */
.poi-modal-create-map .row.inline {
	display: none;
}

/* <poi-modal-map> to element własny (domyślnie inline) — robimy z niego blok w kolumnie. */
.poi-modal-create-map {
	display: block;
}

/* Mapa-picker (POI/adres/punkt trasy): stała, użyteczna wysokość 600px w obrębie swojej kolumny.
   Wcześniej height:100% rozciągało kontener do wysokości kolumny pól, a min-height:600px przelewało
   mapę poza tę kolumnę i jaśniejszą ramkę; do tego display:flex na .row psuł rynnę Bootstrapa
   (mapa kleiła się do pól). osm-map-wrapper wyrównuje owijkę OSM do tej samej wysokości co leaflet. */
.poi-modal-create-map .map-box,
.poi-modal-create-map .osm-map-wrapper {
	height: 600px;
}

/* Mapa okna geokodowania punktu trasy — obok narzędzi, na całą wysokość okna. */
.route-point-geocode-map {
	display: block;
}

.route-point-geocode-map .map-box,
.route-point-geocode-map .osm-map-wrapper {
	height: 600px;
}


.list-view-checkbox {
	padding: 2px 5px 2px 5px;
}

.item-block {
	min-width: calc(100vw - var(--sidebar-width) - var(--scrollbar-width) - 24px);	
	max-width: calc(100vw - var(--sidebar-width) - var(--scrollbar-width) - 24px);
	overflow: hidden;
	margin: 8px 12px 24px 12px;
	background-color: var(--color-surface);
	box-shadow: var(--shadow-2);
	border-radius: 8px;
}

.item-block:hover {
	box-shadow: rgba(6, 24, 44, 0.4) 0px 0px 0px 2px, rgba(6, 24, 44, 0.65) 0px 4px 6px -1px, rgba(255, 255, 255, 0.08) 0px 1px 0px inset;
}

.sidebar-hide .item-block {
	min-width: calc(100vw - var(--scrollbar-width) - 24px);
	max-width: calc(100vw - var(--scrollbar-width) - 24px);
}

.sidebar-mini .item-block {
	min-width: calc(100vw - var(--sidebar-mini-width) - var(--scrollbar-width) - 24px);
	max-width: calc(100vw - var(--sidebar-mini-width) - var(--scrollbar-width) - 24px);
}

.item-block-header {
	display: flex;
	align-items: center;
	width: 100%;
	padding: 1px 1px;
	box-shadow: var(--shadow-1);	
}

.item-block-internal-list {
	border-top: 1px solid var(--color-bg-app);
}

.item-block-data {
	padding: 4px;
	border-radius: 8px;
}

[colspan-table] tr.ng-repeat-end td {
    position: relative;
}

[colspan-table] .item-block-collapsed-wrapper {
    display: flex;
    justify-content: flex-start;
    position: sticky;
    left: 0;
    overflow: hidden;
    width: calc(100vw - var(--sidebar-width));
}

/* position: sticky above makes this wrapper a stacking context with
   z-index: auto, which traps any fixed-positioned dropdown opened inside it
   (datetime picker, field / sort / status editors) below the list's sticky
   <thead> (z-index: 3) and header bar. While such a dropdown is open, lift the
   wrapper above the header so its inner dropdown-menu (z-index: 1100) floats
   freely. Same idiom as the sticky-last-col rule earlier in this file.
   `.unt-dropdown.open` is the entity-menu (☰) flavour of the open state — see
   the cl-detail-wrap rule. */
[colspan-table] .item-block-collapsed-wrapper:has(.dropdown.open),
[colspan-table] .item-block-collapsed-wrapper:has(.unt-dropdown.open) {
    z-index: 1101;
}

.sidebar-mini [colspan-table] .item-block-collapsed-wrapper {
    width: calc(100vw - var(--sidebar-mini-width));
}

.sidebar-hide [colspan-table] .item-block-collapsed-wrapper {
    width: 100vw;
}

.item-block-collapsed {
	margin: 8px;
	padding: 8px;
	border-radius: 8px;
	background-color: var(--color-surface-highlight);
	width: 100%;
}

.item-block-internal-box {
	padding: 4px;
}

.view-list-separator {
	border-right: 10px solid var(--color-bg-app);
	
}

.short .app-content-data {
	overflow: auto;
}





.details-list-view .app-content-data {
	height: unset;
	max-height: 500px;
	overflow: auto;
	display: block;
	width: 100%;
}

.content-box-modal-list {
	max-height: calc(100vh - 350px);
	display: block;
	overflow: auto;
}

/* Lista w modalu wyszukiwania ma ten sam uklad co ekran listy (.app-content-data): filtry stoja
   w miejscu, przewija sie wylacznie obszar tabeli, a naglowek zostaje przyklejony u gory.
   Oba kierunki przewijania musza byc na JEDNYM elemencie: thead {position: sticky} przykleja sie
   do najblizszego przewijanego przodka, wiec gdy pionowo przewijal kontener, a poziomo tabela
   w nim, naglowek nie mial do czego sie przykleic (poziomy overflow czyni z elementu scrollport
   takze w pionie, tylko bez ograniczonej wysokosci). */
.modal-list-block {
	display: flex;
	flex-direction: column;
	min-height: 0;
	overflow: hidden;
}

.modal-list-block > filters {
	flex: 0 0 auto;
	display: block;
}

.modal-list-block > .modal-list-scroll {
	flex: 1 1 auto;
	min-height: 0;
	overflow: auto;
}

.content-box-modal-list.financial-settlement-modal-list {
	min-height: 100px;
	max-height: calc(100vh - 600px);
}



.highlight-text {
	font-weight: bold;
}

.bold-text .form-value {
	font-weight: bold;
	text-decoration: underline;
}

.content-box .app-content-footer {
	margin: 4px;
	background-color: unset;
}

.required {
	color: red;
	font-weight: bold;
}

.italic {
	font-style: italic;
}

.bold {
	font-weight: 700;
}

.highlight-green {
	color: var(--color-success-text);
}

.table>tbody>tr.is-processed>td {
	background: var(--color-success-soft-bg);
	color: var(--color-text-primary);
	font-weight: bold;
}

.table>tbody>tr.sms-not-read>td {
	background: var(--color-success-soft-bg);
	color: var(--color-text-primary);
	font-weight: bold;
}

.table>tbody>tr.active>td {
	background: var(--color-text-muted);
	color: var(--color-text-primary);
	font-weight: bold;
}

/***************************************************/
/* SMS MESSAGE CHAT*********************************/
/***************************************************/

.sms-not-read {
	background: var(--color-success-soft-bg);
	color: var(--color-text-primary);
	font-weight: bold;
}

.transport-message .sms-not-read {
	background: var(--color-success-soft-bg);
	color: var(--color-text-primary);
	font-weight: bold;
}





div.filter-separator div span.input-group-btn button {
	height: 34px;
}

.dropdown.open>ul>li>a {
	margin: 0;
}

/****************
      CHAT
****************/
.chat-container {
	height: 500px;
	max-height: calc(100vh - 300px);
	overflow: auto;
}


.chat-container ul {
	list-style: none;
	margin: 0;
}

.chat-container ul li {
	display: inline-block;
	clear: both;
	width: 80%;
}

.chat-container .received .chat-message, .chat-container .sent .chat-message
	{
	border-radius: 10px;
}

.chat-container .received {
	float: right;
	text-align: left
}

.chat-container .sent {
	float: left;
	text-align: left
}

.chat-message {
	margin: 5px 10px 15px 0;
}

.chat-container .sent .chat-message {
	background: var(--color-surface-alt);
	color: var(--color-text-primary);
}

.chat-container .received .chat-message {
	background: var(--color-teal-soft-bg);
	color: var(--color-text-primary);
}



/****************
   END OF CHAT
****************/

/****************************************************/
/* MESSENGER (public contract page) ****************/
/****************************************************/
/* Full-height layout — scoped to the contract page via a body class (other public pages unaffected) */
body.contract-messenger-page .public-wrapper {
	height: 100vh;
	display: flex;
	flex-direction: column;
	overflow: hidden;
}

body.contract-messenger-page .public-topbar {
	flex: 0 0 auto;
}

body.contract-messenger-page .public-wrapper > [ng-view] {
	flex: 1;
	min-height: 0;
	display: flex;
}

/* the AngularJS component element sits between ng-view and .public-contract-page — it must carry the height too */
body.contract-messenger-page .public-wrapper > [ng-view] > public-transport-contract-details {
	flex: 1;
	min-height: 0;
	display: flex;
}

body.contract-messenger-page .public-contract-page {
	flex: 1;
	min-height: 0;
	display: flex;
}

.messenger {
	flex: 1;
	min-height: 0;
	display: flex;
	gap: 12px;
	padding: 8px;
}

.messenger-list {
	flex: 0 0 320px;
	display: flex;
	flex-direction: column;
	border: 1px solid var(--color-border);
	border-radius: 8px;
	background: var(--color-surface);
	overflow: hidden;
}

.messenger-list-header {
	flex: 0 0 auto;
	padding: 8px 10px;
	border-bottom: 1px solid var(--color-border);
}

.messenger-list-header h1 {
	font-size: 1.3em;
	margin: 0 0 8px 0;
}

.messenger-active-filter {
	font-weight: normal;
	font-size: 0.85em;
	margin: 0;
	display: inline-flex;
	align-items: center;
	gap: 4px;
}

.messenger-counts {
	font-size: 0.8em;
	color: var(--color-text-muted);
	margin-top: 4px;
}

.messenger-conversations {
	flex: 1;
	min-height: 0;
	overflow-y: auto;
}

.conversation-item {
	padding: 8px 10px;
	border-bottom: 1px solid var(--color-border);
	cursor: pointer;
}

.conversation-item:hover {
	background: var(--color-row-hover);
}

.conversation-item.selected {
	background: var(--color-surface-highlight);
}

.conversation-item-row {
	display: flex;
	justify-content: space-between;
	align-items: center;
	gap: 8px;
}

/* single-line truncation shared by every text in the conversation list + header */
.conversation-item-name,
.conversation-item-vehicles,
.conversation-item-preview,
.conversation-item-destination,
.conversation-item-info,
.messenger-conversation-header .conversation-title {
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

.conversation-item-name {
	font-weight: bold;
}

.conversation-item-vehicles {
	flex: 0 1 auto;
	min-width: 0;
	font-size: 0.75em;
	color: var(--color-text-muted);
}

.conversation-item-preview {
	font-size: 0.85em;
	color: var(--color-text-secondary);
}

.conversation-badge {
	flex-shrink: 0;
	background: var(--color-accent);
	color: var(--color-on-accent);
	border-radius: 10px;
	padding: 0 7px;
	font-size: 0.75em;
	font-weight: bold;
	min-width: 20px;
	text-align: center;
}

.messenger-conversation {
	flex: 1;
	display: flex;
	flex-direction: column;
	min-width: 0;
	border: 1px solid var(--color-border);
	border-radius: 8px;
	background: var(--color-surface);
	overflow: hidden;
}

.messenger-empty {
	flex: 1;
	display: flex;
	align-items: center;
	justify-content: center;
	color: var(--color-text-muted);
}

/* Watek mieszka we wlasnym komponencie, zeby moc prowadzic wlasna liste wiadomosci obok listy rozmow.
   Niestylowany element wlasny stoi wtedy miedzy kolumna rozmowy a trescia watku i nie przenosi w dol
   ograniczenia wysokosci — bez tego tresc rosla do wysokosci wszystkich dymkow, a pole pisania wyjezdzalo
   pod krawedz okna zamiast zostac przy dole kolumny. Dotyczy to kazdego komunikatora, wiec nowy watek
   trzeba tu dopisac — element wlasny komponentu nie dziedziczy tego po niczym. */
.messenger-conversation > contact-message-thread,
.messenger-conversation > user-message-thread {
	flex: 1;
	display: flex;
	flex-direction: column;
	min-height: 0;
}

.messenger-conversation-body {
	flex: 1;
	display: flex;
	flex-direction: column;
	min-height: 0;
}

.messenger-conversation-header {
	flex: 0 0 auto;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 8px;
	padding: 8px 10px;
	border-bottom: 1px solid var(--color-border);
}

.messenger-conversation-header .conversation-title {
	font-weight: bold;
	font-size: 1.1em;
}

.messenger-location {
	flex: 0 0 auto;
}

.messenger-sort {
	margin-bottom: 6px;
}

.messenger-back {
	display: none;
	flex: 0 0 auto;
}

/* unt-tabs fills the conversation body; only the tab content scrolls */
/* NB: child combinators — scope strictly to the OUTER messenger tabs so nested unt-tabs (e.g. inside a tab's content) are untouched */
.messenger-conversation-body > unt-tabs {
	flex: 1;
	min-height: 0;
	display: flex;
	flex-direction: column;
}

.messenger-conversation-body > unt-tabs > .unt-tabs-bar {
	flex: 0 0 auto;
}

.messenger-conversation-body > unt-tabs > .unt-tabs-bar > ul.nav-tabs {
	margin: 0;
}

.messenger-conversation-body > unt-tabs > [ng-transclude] {
	flex: 1;
	min-height: 0;
	display: flex;
	flex-direction: column;
}

/* collapse the <unt-tab> wrapper so only the active tab's content is a flex child (full width + height) */
.messenger-conversation-body > unt-tabs > [ng-transclude] > unt-tab {
	display: contents;
}

.messenger-conversation-body > unt-tabs > [ng-transclude] > unt-tab > [ng-transclude] {
	flex: 1;
	min-height: 0;
	display: flex;
}

/* tab content components fill remaining height and scroll internally */
.messenger-conversation-body public-transport-contract-vehicle-message-list,
.messenger-conversation-body public-freight-order-by-transport-contract-vehicle-list,
.messenger-conversation-body public-transport-contract-vehicle-map {
	flex: 1;
	min-height: 0;
	display: flex;
}

.public-map {
	flex: 1;
	min-height: 300px;
	display: flex;
}

.public-map freight-details-public-map {
	flex: 1;
	min-height: 0;
	display: block;
}

/* map fills the tab height (override the fixed 500px map box) */
.public-map .osm-map-wrapper,
.public-map .map-box {
	height: calc(100vh - 175px) !important;
}

/* search clear (X) button */
.messenger-search-wrap {
	position: relative;
	margin-bottom: 6px;
}

.messenger-search-wrap .messenger-search {
	margin-bottom: 0;
	padding-right: 26px;
}

.messenger-search-clear {
	position: absolute;
	right: 8px;
	top: 50%;
	transform: translateY(-50%);
	color: var(--color-text-muted);
	cursor: pointer;
}

/* left-list destination + client remarks — small, like the message preview (truncation shared above) */
.conversation-item-destination,
.conversation-item-info {
	font-size: 0.85em;
	color: var(--color-text-muted);
}

/* freight-order layout (fields pulled out of the removed inner tabs) */
.freight-block {
	padding: 4px 0;
}

.freight-header,
.freight-footer {
	display: flex;
	flex-wrap: wrap;
	justify-content: space-between;
	gap: 4px 18px;
	align-items: baseline;
	padding: 4px 0;
}

/* let each field share the row so they spread across the full width instead of hugging the left edge */
.freight-header > *,
.freight-footer > * {
	flex: 1 1 auto;
}

.freight-header-values {
	display: flex;
	flex-wrap: wrap;
	gap: 4px 14px;
	align-items: baseline;
}

/* dark mode: client (received) bubble uses the selected-vehicle highlight colour; keep the light default text for contrast */
html[data-theme="dark"] .chat-container .received .chat-message {
	background: var(--color-surface-highlight);
}

.orders-scroll {
	flex: 1;
	min-height: 0;
	overflow-y: auto;
	padding: 8px;
}

.chat-loading {
	text-align: center;
	padding: 8px;
	color: var(--color-text-muted);
}

.chat-container li.chat-unread .chat-message {
	box-shadow: 0 0 0 2px var(--color-accent);
}

.chat-to-bottom {
	position: absolute;
	right: 18px;
	bottom: 92px;
	z-index: 5;
	width: 38px;
	height: 38px;
	padding: 0;
	border-radius: 50%;
	box-shadow: 0 2px 6px var(--color-shadow);
}

.public-chat {
	position: relative;
	flex: 1;
	display: flex;
	flex-direction: column;
	min-height: 0;
	padding: 8px;
}

.public-chat .chat-container {
	flex: 1;
	height: auto;
	max-height: none;
}

.public-chat .chat-message {
	padding: 6px 10px;
}

.public-chat-composer {
	flex: 0 0 auto;
	display: flex;
	gap: 8px;
	align-items: flex-start;
	padding-top: 8px;
	border-top: 1px solid var(--color-border);
}

.public-chat-input {
	flex: 1;
	min-width: 0;
	display: flex;
	flex-direction: column;
	gap: 6px;
}

.public-chat-input textarea {
	width: 100%;
	max-width: 100%;
	resize: vertical;
}

.public-chat-file {
	width: 100%;
}

.public-chat-send {
	flex: 0 0 auto;
	min-width: 160px;
	display: flex;
	flex-direction: column;
	gap: 6px;
}

/* office contract-message list: themed content cell (was hardcoded white/#ddd — unreadable in dark mode) */
.message-data-cell {
	min-width: 300px;
	padding: 4px 8px;
	margin: 4px;
	border: 1px solid var(--color-border);
	border-radius: 4px;
	background: var(--color-surface);
}

.chat-message-author {
	font-size: 0.75em;
	color: var(--color-text-muted);
	margin-bottom: 2px;
}

.chat-message-date {
	margin-left: 6px;
}

.chat-message-text {
	white-space: pre-wrap;
	word-break: break-word;
}

.chat-message-file {
	margin-top: 4px;
	font-size: 0.85em;
}

/* Master-detail (na waskim ekranie widac ALBO liste rozmow, ALBO rozmowe) wlacza sie klasa
   .messenger-master-detail, nie sam uklad .messenger — modal komunikatora uzywa tych samych klas, ale
   listy rozmow nie ma, wiec chowanie rozmowy zgasiloby mu cala prawa strone. Deklaruja ja layouty,
   ktore rzeczywiscie maja obie kolumny: strona kontraktu i strona komunikatora. */
@media (max-width: 768px) {
	.messenger-master-detail {
		flex-direction: column;
	}
	.messenger-master-detail .messenger-list {
		flex: 1;
	}
	.messenger-master-detail .messenger-conversation {
		display: none;
		flex: 1;
	}
	.messenger-master-detail.has-selection .messenger-list {
		display: none;
	}
	.messenger-master-detail.has-selection .messenger-conversation {
		display: flex;
	}
	.messenger-master-detail .messenger-back {
		display: inline-block;
	}
	/* Otwarta rozmowa zajmuje caly ekran, wiec pasek filtrow listy rozmow nie ma juz czego filtrowac —
	   a zabiera wysokosc watkowi i pokazuje drugie, mylace pole "Wyszukaj tekst" tuz nad szukajka watku. */
	.messenger-view:has(.messenger-master-detail.has-selection) > filters {
		display: none;
	}
}

/* Komunikator wiadomosci transportowej (modal): ten sam uklad, co komunikator kontraktu na stronie
   publicznej — tylko lewa kolumna zamiast listy rozmow trzyma odbiorce i kanal, a pod watkiem stoi
   kompozytor z zakladkami oryginal/tlumaczenie. Mapa to trzeci, opcjonalny panel wchodzacy na klik. */
.modal-body.messenger-modal-body {
	display: flex;
	flex-direction: column;
	overflow: hidden;
}

.messenger-modal-body > .messenger {
	min-height: 65vh;
}

/* Komunikator jako wariant listy: slot bloku renderuje sie w zwyklym przeplywie, wiec wysokosc trzeba
   nadac wprost — inaczej .messenger nie ma czego wypelnic i watek nie ma wlasnego przewijania. */
/* Komunikator „Rozmowy" jest calym widokiem, nie wariantem listy. Wypelnia obszar tresci: pasek filtrow
   stoi w zwyklym przeplywie, a rozmowy z watkiem zabieraja reszte wysokosci i przewijaja sie wylacznie w
   srodku swoich kolumn. Wysokosci nie da sie odziedziczyc — miedzy widokiem a obszarem tresci stoi
   nieostylowany element komponentu, przez ktory height: 100% nie przechodzi — wiec przypinamy do krawedzi
   obszaru tresci caly widok. Sam komunikator jest juz elementem elastycznym (.messenger: flex 1). */
.app-content:has(.messenger-view) {
	position: relative;
}

.messenger-view {
	position: absolute;
	inset: 0;
	display: flex;
	flex-direction: column;
	/* Nizej komunikator przestaje byc uzyteczny — wtedy niech przewinie sie obszar tresci. */
	min-height: 320px;
}

/* Wirtualna klawiatura na telefonie: zmienna ustawia dyrektywa visual-viewport-height i tylko wtedy, gdy
   klawiatura naprawde zaslania dol ekranu, a przegladarka nie skurczyla strony sama (iOS Safari nie zna
   interactive-widget). Bez tego pole pisania zostaje pod klawiatura, a watek jest nie do doczytania. */
.messenger-view[style*="--visual-viewport-height"] {
	height: var(--visual-viewport-height);
	min-height: 0;
}

/* Plywajacy przycisk asystenta siadalby na przycisku wyslij. */
body:has(.messenger-view) ai-assistant-fab {
	display: none;
}

/* Naglowek listy rozmow: szukajka i przycisk nowej rozmowy w jednym rzedzie, filtr pod spodem. */
.messenger-list-header-row {
	display: flex;
	align-items: center;
	gap: 6px;
}

.messenger-new {
	flex: 0 0 auto;
}

/* Sklad grupy: lista na zadanie, bo przy stu osobach nie moze zajmowac miejsca watkowi na stale. */
.messenger-participants {
	flex: 0 0 auto;
	max-height: 30%;
	overflow-y: auto;
	padding: 4px 8px 8px 8px;
}

.messenger-participant {
	display: flex;
	align-items: center;
	gap: 6px;
	padding: 2px 0;
}

.messenger-participant-name {
	flex: 1;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.messenger-participant-admin {
	color: var(--color-warning, #e0a800);
}

.messenger-participant-actions {
	display: flex;
	gap: 4px;
}

/* Filtry watku: szukanie po tresci i zawezenie do wiadomosci z zalacznikiem albo bez. */
.messenger-thread-filters {
	flex: 0 0 auto;
	display: flex;
	gap: 6px;
	padding: 0 8px 6px 8px;
}

.messenger-files-filter {
	flex: 0 0 auto;
	width: auto;
}

.messenger-recipient {
	flex: 1;
	min-height: 0;
	overflow-y: auto;
	padding: 8px 10px;
}

.messenger-channels {
	display: flex;
	flex-wrap: wrap;
	gap: 4px;
}

.messenger-conversation-actions {
	flex: 0 0 auto;
	display: flex;
	align-items: center;
	gap: 6px;
}

.messenger-thread {
	position: relative;
	flex: 1;
	/* Watek nie zwija sie do paska, ale tez nie wypycha pola pisania poza ekran. */
	min-height: 120px;
	display: flex;
	flex-direction: column;
	padding: 0 8px;
}

/* Mapa pojazdu wchodzi na miejsce watku i pola pisania, wiec zajmuje wysokosc, ktora te dwa zwolnily.
   Mapa trzyma wlasna wysokosc (.map-box), a kolumna rozmowy bywa nizsza — stad przewijanie owijki
   zamiast nadpisywania wysokosci samej mapy, ktora obowiazuje w calej aplikacji. */
/* Odnosnik obok wartosci pola, ktore niesie adres (np. link do systemu klienta w zamowieniu).
   Drobny i wyszarzony, bo wartosc jest trescią, a on tylko sposobem jej otwarcia. */
.field-link {
	margin-left: 5px;
	font-size: 0.85em;
	color: var(--color-text-muted);
	/* Kopiowanie wartosci jest samym ng-click, bez href — bez tego kursor mowi „nie ma w co kliknac",
	   podczas gdy :hover ponizej zmienia kolor, czyli ikona reaguje. Deklaracja obejmuje obie ikony. */
	cursor: pointer;
}

/* Grupa odnosnikow pola-adresu: stoi obok pola, nie w nim (patrz komentarz w field.component.html). */
.field-links {
	display: flex;
	align-items: center;
	white-space: nowrap;
}

.field-link:hover {
	color: var(--color-accent);
}

/* Znacznik poczatku watku: informacja, a nie tresc rozmowy — stad drobny, wyszarzony i wysrodkowany. */
.chat-thread-start {
	padding: 6px 0 10px;
	text-align: center;
	font-size: 0.8em;
	color: var(--color-text-muted);
}

.messenger-thread-map {
	flex: 1;
	min-height: 0;
	overflow: auto;
	padding: 0 8px;
}

/* Skok na dol watku: .chat-to-bottom pozycjonuje sie absolutnie, a jego domyslny odstep od dolu jest
   dobrany do kompozytora strony publicznej — tutaj kotwica jest sam watek. */
.messenger-thread .chat-to-bottom {
	right: 24px;
	bottom: 12px;
}

.messenger-thread .chat-container {
	flex: 1;
	height: auto;
	max-height: none;
}

.messenger-thread .chat-message {
	padding: 6px 10px;
}

.messenger-thread .chat-message-author {
	display: flex;
	align-items: center;
	gap: 6px;
}

.messenger-thread .chat-message-author unt-dropdown-transport-message {
	margin-left: auto;
}

/* Kierunek i kanal wiadomosci: strzalka w gore = wyslana tym kanalem, w dol = przyszla tym kanalem. */
.chat-message-channel {
	display: inline-flex;
	align-items: center;
	gap: 3px;
}

.chat-message-read {
	font-size: 0.75em;
	color: var(--color-text-muted);
	margin-top: 4px;
}

.chat-message-actions {
	margin-top: 4px;
}

/* Chipy plikow w dymku: kilka plikow ustawia sie w rzedzie i lamie, a nie jeden pod drugim. */
.chat-message-files {
	display: flex;
	flex-wrap: wrap;
	gap: 4px;
	margin-top: 4px;
}

/* Plik w dymku: miniatura (obraz, pierwsza strona PDF-a) nad chipem z menu pliku. */
.chat-message-file {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 2px;
}

.chat-message-thumbnail {
	cursor: zoom-in;
}

.chat-message-thumbnail img {
	display: block;
	max-height: 100px;
	max-width: 180px;
	object-fit: contain;
	border: 1px solid var(--color-border);
	border-radius: 4px;
	background: var(--color-surface);
}

/* Nieprzeczytana rzuca sie w oczy nie tylko obwodka — sama tresc jest wytluszczona, wiec roznica
   miedzy przeczytana a nie widac takze wtedy, gdy dymki stoja jeden pod drugim. */
.chat-container li.chat-unread .chat-message-text {
	font-weight: bold;
}

.messenger-composer {
	/* kotwica dla nakladki upuszczania pliku */
	position: relative;
	flex: 0 0 auto;
	margin-top: auto;
	padding: 0 8px 8px 8px;
	border-top: 1px solid var(--color-border);
}

/* Pole wiadomosci jest jedna ramka — tekst, licznik znakow, zalacznik i przyciski razem, tak jak w
   czacie asystenta. Klik w wolny obszar ramki ustawia fokus w textarea (focus-on-click). */
.messenger-composer-inputbox {
	display: flex;
	flex-direction: column;
	border: 1px solid var(--color-border-input);
	border-radius: 14px;
	background: var(--color-surface);
	padding: 6px 6px 6px 12px;
	cursor: text;
}

.messenger-composer-inputbox:focus-within {
	border-color: var(--color-accent);
}

.messenger-composer-input {
	width: 100%;
	border: none;
	outline: none;
	background: transparent;
	resize: none;
	overflow-y: hidden;
	padding: 6px 4px;
	font: inherit;
	line-height: 1.4;
	color: var(--color-text-primary);
}

/* Ostrzezenie o podziale wiadomosci stoi przy liczniku znakow i ma sie rzucac w oczy bardziej niz on —
   to nie informacja o dlugosci, tylko o tym, ze kierowca dostanie kilka wiadomosci zamiast jednej. */
.messenger-composer-split {
	display: inline-flex;
	align-items: center;
	gap: 4px;
	font-size: 11px;
	white-space: nowrap;
	color: var(--color-warning-text);
}

.messenger-composer-count {
	font-size: 0.8em;
	color: var(--color-text-muted);
	white-space: nowrap;
}

.messenger-composer-attachment {
	display: inline-flex;
	align-self: flex-start;
	align-items: center;
	gap: 5px;
	max-width: 100%;
	padding: 3px 8px;
	background: var(--color-accent-soft-bg);
	border-radius: 10px;
	font-size: 12px;
	color: var(--color-text-secondary);
}

.messenger-composer-attachment-name {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.messenger-composer-attachment-remove {
	flex-shrink: 0;
	cursor: pointer;
	opacity: 0.7;
}

.messenger-composer-attachment-remove:hover {
	opacity: 1;
	color: var(--color-danger);
}

/* Zakladki tresci, kanal i wybory szablonu w JEDNYM rzedzie nad polem tekstu. Osobny wiersz kosztowal
   35 px stalej wysokosci kompozytora, a te zabiera watek — przy nizszym oknie zostawalo na niego tyle,
   ze widac bylo dwa dymki. */
.messenger-composer-tabs {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-end;
	gap: 8px;
}

/* Bootstrapowe .nav jest blokowe z plywajacymi <li>, wiec w rzedzie flex zajmowalo cala szerokosc
   i spychalo reszte do kolejnych linii — stad wlasny display: flex i szerokosc z tresci. */
.messenger-composer-tabs > .nav-tabs {
	flex: 0 0 auto;
	display: flex;
	width: auto;
	margin: 0;
	border-bottom: none;
}

.messenger-composer-picker {
	display: flex;
	align-items: center;
	gap: 4px;
	flex: 1 1 220px;
	min-width: 0;
}

.messenger-composer-picker unt-autocomplete {
	flex: 1;
	min-width: 0;
}

.messenger-composer-toolbar {
	display: flex;
	justify-content: flex-end;
	align-items: center;
	gap: 6px;
}

/* Tlumacz zostaje po lewej, przyciski spinacza i wysylki po prawej. */
.messenger-composer-toolbar > translator-unt-dropdown {
	margin-right: auto;
}

.messenger-composer-btn {
	margin: 0;
	width: 34px;
	height: 34px;
	padding: 0;
	text-align: center;
	line-height: 32px;
}

.messenger-composer-btn i {
	width: auto;
	height: 1em;
	vertical-align: middle;
}

input[type="file"].messenger-composer-file-input {
	display: none;
}

.messenger-composer-priority {
	display: inline-flex;
	align-items: center;
	gap: 4px;
	margin: 0;
	font-weight: normal;
}

/* Nakladke pokazuje klasa `unt-dragging`, ktora file-dropzone przestawia na czas przeciagania. */
.messenger-dropzone {
	position: absolute;
	inset: 0;
	z-index: 6;
	display: none;
	align-items: center;
	justify-content: center;
	background: var(--color-accent-soft);
	pointer-events: none;
}

.messenger-composer.unt-dragging .messenger-dropzone {
	display: flex;
}

.messenger-dropzone-inner {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 10px;
	padding: 20px 32px;
	border: 2px dashed var(--color-accent);
	border-radius: 14px;
	background: var(--color-surface);
	color: var(--color-accent);
}

.messenger-dropzone-inner i {
	font-size: 26px;
}

.messenger-map {
	flex: 0 0 380px;
	min-width: 0;
	border: 1px solid var(--color-border);
	border-radius: 8px;
	background: var(--color-surface);
	overflow: auto;
	padding: 8px;
}

@media (max-width: 1200px) {
	.messenger-modal-body > .messenger {
		flex-wrap: wrap;
	}
	.messenger-map {
		flex: 1 0 100%;
	}
}
/****************************************************/
/* END OF MESSENGER ********************************/
/****************************************************/
.md-dialog-container {
	z-index: 1200;
}


/* Lista opcji edytora pola: w menu wkladki (<field-menu>) <li> leza w ng-transclude,
   a wspolna lista opcji siedzi w gospodarzu <field-options> — stad warianty
   sciezek obok pierwotnego dziecka .dropdown-menu. */
.dropdown-menu>li>ul, .dropdown-menu>li>unt-datetime-picker>ul,
.field-insert-menu>ng-transclude>li>ul, .field-insert-menu>ng-transclude>li>unt-datetime-picker>ul,
.dropdown-menu li>field-options>ul {
	padding-left: 0;
	max-height: 300px;
	overflow: auto;
	overflow-x: hidden;
}

.dropdown-menu>.active>a {
	color: var(--color-text-primary);
	background-color: var(--color-surface);
	transition: border-color 0.3s ease, background-color 0.3s ease;
}

.dropdown-menu>.active>a:focus, .dropdown-menu>.active>a:hover {
	color: var(--color-accent-deep);
	background-color: var(--color-accent-soft-bg);
}

.dropdown-menu>li>ul>li>a,
.field-insert-menu>ng-transclude>li>ul>li>a,
.dropdown-menu li>field-options>ul>li>a {
	display: block;
}

/* Podpowiedz pozycji wycofanej z uzycia (np. nieaktywny oddzial): zostaje
   do wyboru, ale ma od razu wygladac na nieaktualna. Kolor na wewnetrznym
   span, bo kolor linku nadpisuja reguly :hover i .active menu. */
.option-inactive {
	color: var(--color-text-muted);
	font-style: italic;
}

.option-inactive-badge {
	margin-left: 6px;
	color: var(--color-danger-text);
	font-size: 0.85em;
	font-style: normal;
}




table table thead {
	position: unset;
}

.highlight-row {
	background-color: var(--color-border);
}

.enum-image {
	width: 24px;
	height: 16px;
	object-fit: contain;
	border: 1px solid var(--color-surface-alt);
	padding: 0px;
	margin-right: 4px;
	flex-shrink: 0;
}




/*--------------------------*/
/* FIELD - COLLECTION TABLE */
/*--------------------------*/


.element-collection-container {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    margin-bottom: 4px;
}

.element-number {
    flex-shrink: 0;
    min-width: 30px;
}

.element-input {
    flex-grow: 1;
}

.element-input .form-control {
    width: 100%;
}

.element-action {
    flex-shrink: 0;
}

/*--------------------------*/

.anchor-body {
	padding: 0px 10px 0px 10px;
	margin-bottom: 1px;
}

.anchor-header {
	position: sticky;
	top: 0;
	padding: 10px;
	z-index: 5;
	overflow-y: auto;
	white-space: nowrap;
	padding: 4px;
	background-color: var(--color-info);
	color: var(--color-text-inverse);
	display: flex;
	align-items: center;
	border-radius: 4px;
}




.value-text-button {
	width: 100%;
	display: flex;
}

.value-text {
	width: 100%;
	margin-right: 2px;
}

.value-button {
	float: right;
	padding: 0px 0px 0px 5px;
}

/* MEDIA MAX 768 px */
@media ( min-width : 768px) {
	.modal-dialog {
		margin: 30px auto;
	}
}

/* MEDIA MAX 1200 px */
@media screen and (max-width: 1200px) {

	.flex-list-row {
		display: block;
		flex-wrap: wrap;
	}

	.flex-list-item {
		width: 100%;
		display: block;
	}
	.item-block .item-block-header, .pair {
		display: block;
		width: 100%;
	}
	/* Bloki list na waskim ekranie: pola naglowka i kolumny wierszy danych ida
	   jedno pod drugim zamiast scisnietych obok siebie. Regula celuje w kontener
	   pola jako bezposrednie dziecko wiersza bloku (.flex-container), bo klase
	   .flex-item nosi tez to, co stoi w srodku pola: <sort>, <field>,
	   <field-label>, <search-address>, <triple-price-sort> i <triple-price-field>.
	   Kontener pary etykieta-wartosc (.field-horizontal, .flex) nie
	   zawija: dwa elementy po 100% nie staja tam jeden pod drugim, tylko
	   wypychaja wartosc poza blok, a .item-block { overflow: hidden } ucina ja bez
	   przewijaka. Wewnatrz pola zostaje uklad bazowy (etykieta 40%, wartosc
	   reszta), ten sam, ktory na tej szerokosci dziala w detalach. */
	.item-block .flex-container > .flex-item {
		flex: 0 0 100%;
		width: 100%;
	}
	.item-block [class*="col-"] {
		width: 100%;
	}
	/* Pola na waskim ekranie: kazda kolumna zawierajaca pole (field-horizontal
	   lub bezposrednio <field>, takze col-xs-6) w osobnym wierszu — label po
	   lewej, wartosc po prawej. */
	[class*="col-"]:has(.field-horizontal),
	[class*="col-"]:has(> field) {
		width: 100%;
	}
	.mobile-hide {
		display: none;
	}
	/* .app-topbar .btn (display: inline-flex) jest bardziej specyficzny niz
	   .mobile-hide — bez tej reguly przyciski topbara nie znikaja na mobile. */
	.app-topbar .btn.mobile-hide {
		display: none;
	}
	.mobile-show {
		display: block;
	}
	.app-content-header-buttons .btn:not([dropdown-option]) > span:not(.badge),
	.filter-header .btn:not([dropdown-option]) > span:not(.badge) {
		display: none;
	}
	/* Naglowki collapsible: na mobile przyciski pokazuja same ikony.
	   Kombinator potomka (nie >), bo tekst bywa zagniezdzony w komponencie
	   (np. delete-button-content); .caret i .badge zostaja widoczne. */
	.content-box-header .btn:not([dropdown-option]) span:not(.badge):not(.caret) {
		display: none;
	}
	/* Dropdowny-arkusze (dropdown-position) maja stala szerokosc ekranu —
	   opcje zawijaja sie zamiast wystawac poza arkusz (bootstrap: nowrap).
	   W menu wkladki pola <li> leza w ng-transclude, stad drugi selektor. */
	.dropdown-menu > li > a,
	.field-insert-menu > ng-transclude > li > a {
		white-space: normal;
	}
	/* Przyciemnienie tla jak pod modalem: gigantyczny spread w box-shadow
	   robi backdrop bez dodatkowego DOM; klik w tlo normalnie zamyka menu. */
	.dropdown-menu {
		box-shadow: 0 0 0 100vmax rgba(0, 0, 0, 0.5), 0 8px 28px var(--color-shadow);
	}
	/* Pasek kontrolek mapy: przyciski POI pokazuja same ikony, a pasek moze
	   sie zawijac zamiast generowac poziomy scroll. */
	.map-control {
		flex-wrap: wrap;
		height: auto;
		min-height: 30px;
	}
	.map-control-actions .btn > span {
		display: none;
	}
	/* Statystyki: jedna statystyka na wiersz. */
	.statistics-section ul.list-group {
		grid-template-columns: 1fr;
	}
	.item-block {
		min-width: unset;
	}
	.wrapper {
		display: unset;
	}
	.app-content,
	.sidebar-mini .app-content,
	.sidebar-hide .app-content {
		width: 100vw;
	}
	.freight-messages-launcher {
		max-width: unset;
	}
	#sidebar,
	.sidebar-mini #sidebar,
	.sidebar-hide #sidebar {
		display: block;
		position: fixed;
		top: var(--topbar-height);
		left: 0;
		height: calc(100vh - var(--topbar-height));
		/* As a fixed overlay the drawer must stack above ALL page content
		   (e.g. .details-topbar z-index 154 on the dashboard) — otherwise the
		   content header paints over the open drawer. Sit in the unused 201..991
		   gap: above content, still below modals/dialogs/dropdowns (>=992). */
		z-index: 900;
		width: min(82vw, 32rem);
		box-shadow: 0 2rem 4.8rem rgba(0, 0, 0, 0.5);
		transition: transform var(--sidebar-transition), box-shadow var(--sidebar-transition);
	}
	.sidebar-hide #sidebar,
	.sidebar-mini #sidebar {
		transform: translateX(-100%);
		box-shadow: none;
	}
	/* backdrop while sidebar is open on mobile */
	body:not(.sidebar-hide):not(.sidebar-mini):not(.auth-page):not(.public-page)::before {
		content: '';
		position: fixed;
		top: var(--topbar-height);
		left: 0;
		right: 0;
		bottom: 0;
		background: rgba(0, 0, 0, 0.45);
		backdrop-filter: blur(2px);
		-webkit-backdrop-filter: blur(2px);
		z-index: 899;
		animation: sidebar-backdrop-in var(--sidebar-transition) ease-out;
	}
}
/* END OF MEDIA MAX 1200 px */

@keyframes sidebar-backdrop-in {
	from { opacity: 0; }
	to { opacity: 1; }
}
@media ( max-width : 991px) {
	.hide-on-narrow-screen {
		display: none;
	}
}

/*************************/
/** FREIGHT STOP STATUS **/
/*************************/

.vehicle-combination-work-current {
	font-weight: bold;
}

/* Licznik kopii w stopce modalu: jedna linia z przyciskami, żeby było widać, że jest
   parametrem „Utwórz" stojącego zaraz za nim. Bez tego pole wchodziło w całą szerokość
   i rozjeżdżało stopkę. */
.modal-copies {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	margin-right: 8px;
	vertical-align: middle;
}

.modal-copies__label {
	margin: 0;
	white-space: nowrap;
	font-weight: normal;
}

.modal-copies__input {
	width: 5rem;
	display: inline-block;
}

/* === Strona publiczna przesyłki: tracking dla klienta ===
   Klient dostaje trzy rzeczy na przystanek: co się dzieje, gdzie i kiedy. Identyfikatory
   przystanku, przewozu i zamówienia oraz numery pojazdów zostają wewnątrz systemu — na
   stronie udostępnianej na zewnątrz nie mają czego robić. Stan przystanku niosą kropka
   i tło (klasy .stop-status-*), więc status nie zajmuje własnej kolumny. */
.public-tracking {
	padding: 10px 15px 70px 15px;
}

.tracking-head {
	display: flex;
	flex-wrap: wrap;
	gap: 8px 16px;
	align-items: center;
	justify-content: space-between;
}

.tracking-load {
	color: var(--color-text-muted);
	font-weight: normal;
}

.tracking-list {
	list-style: none;
	margin: 0;
	padding: 0 0 0 22px;
	position: relative;
}

/* Kreska łącząca przystanki kończy się na skrajnych kropkach, nie na krawędziach listy. */
.tracking-list::before {
	content: "";
	position: absolute;
	left: 5px;
	top: 20px;
	bottom: 20px;
	width: 2px;
	background: var(--color-border);
}

.tracking-item {
	position: relative;
	display: grid;
	grid-template-columns: minmax(8rem, 1fr) minmax(0, 2fr) minmax(12rem, auto);
	gap: 2px 18px;
	align-items: baseline;
	padding: 10px 8px;
	border-bottom: 1px solid var(--color-border);
}

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

.tracking-item::before {
	content: "";
	position: absolute;
	left: -21px;
	top: 15px;
	width: 12px;
	height: 12px;
	border-radius: 50%;
	background: var(--color-surface);
	border: 2px solid var(--color-border-strong);
}

/* Przystanek zaliczony ma kropkę wypełnioną, bieżący — w kolorze potwierdzenia. */
.tracking-item.stop-status-finished::before {
	background: var(--color-border-strong);
}

.tracking-item.stop-status-is-on::before {
	background: var(--color-success);
	border-color: var(--color-success);
}

.tracking-action {
	font-weight: 600;
}

.tracking-place {
	display: flex;
	flex-wrap: wrap;
	gap: 0 8px;
	color: var(--color-text-secondary);
}

.tracking-when {
	display: flex;
	flex-direction: column;
	gap: 2px;
}

/* Kraj, kod i miasto stoją obok siebie w jednym wierszu: pole domyślnie zajmuje całą
   szerokość swojego kontenera, więc tutaj musi ustąpić i zająć tyle, ile ma treści. */
.tracking-place > field,
.tracking-place .form-box,
.tracking-place .form-value {
	width: auto;
	flex: 0 0 auto;
	padding-left: 0;
	padding-right: 0;
}

.tracking-when-row {
	display: flex;
	gap: 12px;
	justify-content: space-between;
}

.tracking-when-label {
	color: var(--color-text-muted);
	white-space: nowrap;
}

/* Na wąskim ekranie trzy kolumny stają się trzema wierszami — klient śledzi przesyłkę z telefonu. */
@media (max-width: 700px) {
	.tracking-item {
		grid-template-columns: minmax(0, 1fr);
		padding-bottom: 14px;
	}
}

.stop-status-going-to {
	font-weight: bold;

}

.stop-status-is-on  {
	background-color: var(--color-success-soft-bg-hover);
	font-weight: bold;
}

.stop-status-not-going-yet {
	background-color: var(--color-surface);
	font-weight: normal;
}

.stop-status-finished, .cargo-status-supplied
{
	font-style: normal;
	color: var(--color-text-primary);
	background-color: var(--color-surface-muted);
}

/* Status telematyki: kwadracik w kolorze statusu. Klasy kolorów z EnumColorService niosą
   jasne tło i nasycony kolor tekstu — przy 10 px tło jest nie do rozpoznania, więc
   wypełnieniem jest currentColor. Kształt wynika wprost z klasy statusu, bo każdą z
   dwóch poniższych nosi w tym słowniku dokładnie jeden status: szarą brak wysyłki
   (pusty kwadrat z przerywaną ramką — nic nie pojechało, a to nie jest błąd),
   niebieską wysyłka częściowa (kwadrat wypełniony do połowy). Szara jako jedyna nie
   ma samodzielnej reguły koloru — bez tej currentColor dziedziczyłby kolor otoczenia,
   więc „niewysłane" wychodziło zielone na liście, a czarne w szczegółach. */
.telematics-dot {
	display: inline-block;
	width: 10px;
	height: 10px;
	border-radius: 2px;
	border: 1px solid currentColor;
	background-color: currentColor;
	vertical-align: middle;
}

.telematics-dot.grey-light {
	color: var(--color-text-secondary);
	background-color: transparent;
	border-style: dashed;
}

.telematics-dot.light-baby-blue {
	background-color: transparent;
	background-image: linear-gradient(to right, currentColor 50%, transparent 50%);
}

.freight-telematics {
	display: inline-block;
	position: relative;
}

.freight-telematics-status {
	display: inline-flex;
	align-items: center;
	gap: 4px;
	white-space: nowrap;
}

/* Kwadrat statusu otwiera menu z zadaniami kierowcy — obramowanie, tło i strzałka mówią, że to
   przycisk; jako goły tekst nic nie zdradzało, że po kliknięciu coś się rozwinie. */
a.freight-telematics-status {
	padding: 1px 6px;
	border: 1px solid var(--color-border-strong);
	border-radius: 4px;
	background-color: var(--color-surface-muted);
	color: inherit;
	text-decoration: none;
	cursor: pointer;
}

a.freight-telematics-status:hover,
a.freight-telematics-status:focus {
	border-color: var(--color-info);
	background-color: var(--color-info-soft-bg);
	color: inherit;
	text-decoration: none;
}

/* Menu kwadratu statusu: nie lista pozycji do klikania, tylko podsumowanie zadań, więc
   dostaje własne marginesy zamiast wcięć pozycji menu. */
.telematics-menu {
	min-width: 340px;
	padding: 8px 12px;
}

.telematics-menu .telematics-menu-header {
	font-weight: 600;
	padding-bottom: 4px;
}

.freight-telematics-tasks table {
	width: 100%;
	margin-bottom: 6px;
}

.freight-telematics-tasks th,
.freight-telematics-tasks td {
	padding: 2px 8px 2px 0;
	vertical-align: middle;
	white-space: nowrap;
}

.freight-telematics-tasks th {
	font-weight: 600;
	color: var(--color-text-secondary);
}

.freight-telematics-error {
	color: var(--color-danger-text);
	padding-bottom: 6px;
}

.freight-telematics-confirmed {
	color: var(--color-success-text);
	padding-bottom: 6px;
}

/* Nagłówek przepraw stoi tuż pod mapą — bez odstępu dotykał jej krawędzi i nachodził na tabelę. */
.freight-ferries h2 {
	padding-top: 12px;
	padding-bottom: 8px;
}

/* Wyszukiwarka portu nad listą promów — szerokość pola, nie całej tabeli. */
.freight-ferries-search {
	max-width: 360px;
	margin-bottom: 8px;
}

/* Odcinek, dla którego wybiera się prom — nad wyszukiwarką, żeby wybór nie trafił na sąsiedni. */
.freight-ferries-leg {
	margin-bottom: 8px;
	font-weight: 600;
}

.telematics-legend {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 4px 12px;
	border-top: 1px solid var(--color-border-input);
	padding-top: 6px;
}

.telematics-legend-title {
	font-weight: 600;
	color: var(--color-text-secondary);
}

.telematics-legend-item {
	display: inline-flex;
	align-items: center;
	gap: 4px;
}

.stop-status-finished {
	color: var(--color-status-finished-text);
	font-style: italic;
}

/*******************/
/** PERIOD STATUS **/
/*******************/
.period-status-less-than-7-days {
	background-color: var(--color-info-soft-bg);
	border: 0px solid var(--color-info);
	text-align: center;
	border-radius: 4px;
}

/* W wariancie blokowym tlo karty niesie status zestawu, wiec niski stan paliwa zaznacza czerwony pasek. */
.planner-id-card.fuel-level-low {
	box-shadow: inset 4px 0 0 var(--color-danger);
}
/* Podgląd zestawu: pola paliwa ciągnika przy niskim stanie (10849, D3). */
.field-horizontal.fuel-level-low {
	background-color: var(--color-danger-soft-bg);
}

.period-status-exceeded {
	background-color: var(--color-danger-soft-bg);
	border: 0px solid var(--color-danger);
	text-align: center;
	border-radius: 4px;
}

/********************/
/** SUBSTATUS BAR* **/
/********************/
.substatus-bar {
	width: 100%;
	height: 4px;
	border-radius: 2px;
}

.status-bar-active {
	background-color: var(--color-success);
}

.schedule-start-in-7-days {
	background-color: var(--color-teal);
}

/********************/
/** ACTIVE PREVIEW **/
/********************/
.item-block.active-preview {
	box-shadow: rgba(0, 0, 0, 0.16) 0px 1px 4px, rgb(51, 51, 51) 0px 0px 0px 3px;
	background-color: var(--color-surface-highlight);
}

/* Wiersz z rozwinieta sekcja (pokaz/ukryj) wyroznia sie tak samo jak wiersz z otwartym podgladem —
   w obu przypadkach chodzi o wskazanie wpisu, ktorego dotyczy tresc pokazana obok albo pod nim. */
.table .active-preview, .active-preview,
.table .section-expanded, .section-expanded {
	border-bottom: 2px solid var(--color-bg-app-darker);
	background-color: var(--color-surface-highlight);
}

.active-preview table {
	background-color: rgba(91, 91, 91, 0);
	background-color: var(--color-surface-highlight);
}

/* Wskazany wiersz — pojazd pokazany w tej chwili na mapie obok listy. Wyroznienie jest inne niz przy
   podgladzie i rozwinietej sekcji (tam chodzi o tresc pod wierszem), bo oba stany moga wystapic naraz:
   wskazany pojazd bywa jednoczesnie tym z otwartym podgladem. */
.cl-row-focused > td {
	background-color: var(--color-accent-soft-bg);
	box-shadow: inset 0 -2px 0 var(--color-accent);
}


/********************/
/** FAVORITE ***** **/
/********************/
.favorite table {
	background-color: rgb(0, 255, 0);
}

/********************/
/** SELECTED****** **/
/********************/

/*************/
/** DASHBOARD **/
/*************/
.dashboard-panel {
	background-color: transparent;
	padding: 10px 10px 10px 10px;
	margin-top: 30px;
	border: none;
}

.dashboard-panel-body {
	background-color: var(--color-surface);
	height: 100%;
	box-shadow: var(--shadow-card);
}

.panel-default>.panel-heading {
	color: var(--color-text-inverse);
	background-color: var(--color-chrome-deep);
	border-color: transparent;
}

.panel-default>.panel-heading h2 {
	color: var(--color-text-inverse);
}

.dashboard-panel-body .menu-suboption-content {
	display: flex;
}

.dashboard-panel-body .label-menu-short {
	display: block;
}

.dashboard-panel-body .label-menu-short, .dashboard-panel-body .content
	{
	margin-right: auto;
}

/********************/
/** ROW HIGHLIGHTS **/
/********************/
.row-danger {
	background-color: var(--color-danger-soft-bg);
	border-bottom: 3px solid var(--color-danger);
}

/*************/
/** UTILITY **/
/*************/

.list-without-dots {
	list-style: none;
	padding: 0px;
}

/****************/
/** ANIMATIONS **/
/****************/
.row.ng-enter,
.row.ng-enter.ng-enter-active,
.row.ng-leave,
.row.ng-leave.ng-leave-active,
tr[with-context-menu].ng-enter,
tr[with-context-menu].ng-enter-active,
tr.ng-enter,
tr.ng-enter.ng-enter-active,
.my-view.ng-enter,
.my-view.ng-enter.ng-enter-active,
.my-view.ng-leave,
.my-view.ng-leave.ng-leave-active {
	transition: none;
	opacity: 1;
	height: auto;
}

.justify-center {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
}

.uib-timepicker, .uib-daypicker, .uib-monthpicker, .uib-yearpicker {
	padding: 8px;
	background: var(--color-surface);
}

.uib-timepicker {
	display: flex;
	justify-content: center;
}

.uib-daypicker table tr td:nth-of-type(1n+8) {
	display: none;
}

/* uib-datepicker buttons — chevrons and day cells live inside .dropdown-menu but
   are NOT [dropdown-option]; ensure their icons stay inline and rows align. */
.uib-daypicker .btn.btn-default,
.uib-monthpicker .btn.btn-default,
.uib-yearpicker .btn.btn-default {
	padding: 4px 6px;
	margin: 1px;
	border: 1px solid transparent;
	border-radius: 4px;
	background-color: transparent;
	color: var(--color-text-primary);
	box-shadow: none;
	transition: background-color var(--sidebar-transition), color var(--sidebar-transition), border-color var(--sidebar-transition);
}

.uib-daypicker .btn.btn-default:hover,
.uib-monthpicker .btn.btn-default:hover,
.uib-yearpicker .btn.btn-default:hover {
	background-color: var(--color-accent-soft);
	color: var(--color-accent);
	border-color: transparent;
}

.uib-daypicker .btn.btn-default.active,
.uib-monthpicker .btn.btn-default.active,
.uib-yearpicker .btn.btn-default.active,
.uib-daypicker .btn.btn-info,
.uib-monthpicker .btn.btn-info,
.uib-yearpicker .btn.btn-info {
	background-color: var(--color-accent-bg);
	color: var(--color-on-accent);
	border-color: var(--color-accent);
}

.uib-daypicker .uib-title,
.uib-monthpicker .uib-title,
.uib-yearpicker .uib-title {
	width: 100%;
	font-weight: 600;
}

/* Reset the icon-column rule from .dropdown-menu so chevrons render at their
   natural inline size and stay centered in the prev/next cell. */
.uib-daypicker .glyphicon,
.uib-monthpicker .glyphicon,
.uib-yearpicker .glyphicon {
	width: auto;
	min-width: 0;
	margin: 0;
	padding: 0;
	display: inline-block;
	vertical-align: middle;
}

.uib-daypicker table,
.uib-monthpicker table,
.uib-yearpicker table {
	width: 100%;
	margin: 0;
}

.uib-daypicker th,
.uib-monthpicker th,
.uib-yearpicker th {
	padding: 2px;
	border: 0;
	background-color: transparent;
	box-shadow: none;
}

.uib-daypicker td,
.uib-monthpicker td,
.uib-yearpicker td {
	padding: 0;
	text-align: center;
}

/* Footer action bar of the datetime picker — replace the inline gray slab
   with a cleaner divider so it fits the new dropdown shape. */
unt-datetime-picker > .dropdown-menu > div:last-child {
	background-color: transparent !important;
	border-top: 1px solid rgba(20, 18, 42, 0.08);
	padding: 8px 12px !important;
}

/********************
******FAVORITE*******
*********************/
.favorite {
	background-color: rgb(136, 242, 115)
}

/* Header strip at the top of the field-edit dropdown — sits flush with the
   menu's rounded corners and gives the label + input a calm tinted background
   so it reads as a section header instead of a stray block. */
.dropdown-menu > li:first-child > .field-li-input,
.dropdown-menu > li:first-child > form > .field-li-input,
.field-insert-menu > ng-transclude > li:first-child > .field-li-input,
.field-insert-menu > ng-transclude > li:first-child > form > .field-li-input {
	margin-top: -6px;
	border-top-left-radius: 0.6em;
	border-top-right-radius: 0.6em;
}

.field-li-input {
	display: flex;
	flex-direction: column;
	gap: 4px;
	padding: 10px 12px;
	margin: 0 0 4px 0;
	background-color: var(--color-accent-soft);
}

.field-li-input > form {
	display: flex;
	flex-direction: column;
	gap: 4px;
	margin: 0;
}

.field-li-input > span,
.field-li-input > form > span:not([ng-init]) {
	font-size: 0.85em;
	font-weight: 600;
	letter-spacing: 0.02em;
	text-transform: uppercase;
	color: var(--color-accent);
	margin: 0;
}

.field-li-input .form-control {
	height: auto;
	padding: 6px 10px;
	border: 1px solid rgba(97, 98, 241, 0.25);
	border-radius: 6px;
	background-color: var(--color-surface);
	box-shadow: none;
	transition: border-color var(--sidebar-transition), box-shadow var(--sidebar-transition);
}

.field-li-input .form-control:focus {
	outline: none;
	border-color: var(--color-accent);
	box-shadow: 0 0 0 3px var(--color-accent-soft);
}

.field-li-input textarea.form-control {
	min-height: 60px;
	resize: both;
}

.field-li-input .field-required {
	color: var(--color-danger-alt);
	font-size: 0.85em;
	margin: 0;
}

.close-list-tab-section-btn {
	display: none;
}

#list-tab-section .close-list-tab-section-btn {
	display: block;
}

/* The section's own close button: a compact button pinned to the top-right of the panel, in line with
   the content header's button/options row — not a full-width bar across the top of the section. */
#list-tab-section .close-list-tab-section-btn {
	position: absolute;
	top: 5px;
	right: 4px;
	z-index: 11;
	width: auto;
}

/* Pasek kontrolek mapy dosuwa swoje przyciski do prawej krawedzi sekcji (.map-control-actions ma
   margin-left:auto), a przycisk zamkniecia sekcji stoi w tym samym rogu absolutnie — bez tego zapasu
   oba trafiaja w to samo miejsce i nachodza na siebie. */
#list-tab-section .map-control-actions {
	padding-right: 32px;
}

/* A full list rendered inside a side section (e.g. vehicle-combinations on the freight list) brings its
   own toolbar close-button; the section already supplies one, so hide the nested duplicate. */
#list-tab-section list-view-content .close-list-tab-section-btn {
	display: none;
}

/************
***PLANNER***
*************/

/* Planer wypełnia swój kontener i nic poza tym. Szerokość liczona z okna (100vw minus menu)
   rozjeżdżała się z tym, co kontener naprawdę daje: nie znała stanu menu (pełne, mini, ukryte),
   ani paska przewijania szerszego niż zakładane 8px, ani zwężenia do pół kolumny przy otwartej
   zakładce listy warstwy — każdy z tych przypadków kończył się poziomym paskiem przewijania. */
.planner {
	min-width: 0;
}

.planner .header {
	display: flex;
	flex-direction: column;
	position: sticky;
	top: 0;
	z-index: 2;
	background-color: var(--color-surface);
	border-top: 2px solid var(--color-border);
	border-bottom: 2px solid var(--color-border);
}

.planner .header .management-row {
	display: flex;
	justify-content: space-between;
	align-items: center;
	padding: 4px;
	flex-wrap: wrap;
	gap: 8px;
	border-bottom: 1px solid var(--color-border);
}

.planner-management-block {
	display: flex;
	align-items: center;
	gap: 6px;
	flex-wrap: wrap;
	border: 1px solid var(--color-border);
	border-radius: 4px;
	padding: 4px 6px;
}

.planner-layer-group {
	border: 1px solid var(--color-border-strong);
	border-radius: 4px;
	padding: 1px;
}

.planner .years-row {
	display: flex;
}

.planner .years-row > .planner-identification {
	flex: 0 0 320px;
	max-width: 320px;
	background-color: var(--color-surface-muted);
	border-right: 1px solid var(--color-border);
}

.planner .years-row > .planner-timeline {
	flex: 1 1 auto;
	min-width: 0;
}

.planner .timeline-year {
	flex: 1 1 0;
	min-width: 0;
	text-align: center;
	font-weight: 700;
	background-color: var(--color-surface-muted);
	border-right: 1px solid var(--color-border);
	border-bottom: 1px solid var(--color-border);
	padding: 1px 4px;
}

.planner .header .days-row {
	display: flex;
	flex: 1;
	font-weight: 700;
	vertical-align: middle;
	text-align: center;
	word-break: break-word;
}

.primary-text {
	font-size: var(--font-xs);
	color: var(--color-text-primary);
}

.secondary-text {
	font-size: var(--font-xs);
	color: var(--color-text-muted);
}

.planner .item-block-header {
	background-color: var(--color-surface);
	border: 1px solid var(--color-border);
	margin: 4px 0px 4px 0px;
	box-shadow: var(--shadow-thead);
}

.planner .item-block-header:hover {
	background-color: var(--color-surface);
	border-color: var(--color-text-muted);
}

.planner .item-block-header .flex-item {
	padding: 0px 4px 0px 4px;
}


.planner .content-row >* {
	flex: 1;
}

.planner .content-row .content-row-line {
	display: flex;
	position: relative;
	border-bottom: 2px solid var(--color-border-strong);
}

/* Planer w układzie dwukolumnowym: stała karta zestawu po lewej, przewijalna oś czasu po prawej. */

.planner .planner-identification .highlighted-section {
	max-height: 200px;
	overflow-y: auto;
}

.planner .planner-identification .highlighted-section .flex-container {
	display: flex;
	flex-direction: column;
}

/* Pola sekcji rozwijanej stoją jedno pod drugim, a ich wartości w jednej kolumnie: etykieta ma
   stałą szerokość, więc nie rozjeżdżają się zależnie od długości nazwy pola. */
.planner .planner-identification .highlighted-section > .flex-container > .flex-item {
	width: 100%;
	align-items: baseline;
	gap: 6px;
	padding: 1px 0;
}

.planner .planner-identification .highlighted-section > .flex-container > .flex-item > *:first-child {
	flex: 0 0 45%;
	min-width: 0;
}

.planner .planner-identification .highlighted-section > .flex-container > .flex-item > *:not(:first-child) {
	flex: 1 1 auto;
	min-width: 0;
}

.planner .content-row > .planner-identification,
.planner .header .days-row > .planner-identification {
	flex: 0 0 320px;
	max-width: 320px;
}

.planner .header .days-row > .planner-identification {
	background-color: var(--color-surface-muted);
	border-right: 1px solid var(--color-border);
	display: flex;
	align-items: center;
	justify-content: center;
}

.planner .content-row > .planner-identification {
	background-color: var(--color-surface);
	border-right: 1px solid var(--color-border-strong);
}

.planner .content-row > .planner-identification > ng-transclude {
	display: flex;
	flex-direction: column;
	height: 100%;
}

.planner .content-row > .planner-timeline,
.planner .header .days-row > .planner-timeline {
	flex: 1 1 auto;
	min-width: 0;
}

.planner .planner-timeline-header {
	display: flex;
}

/* Tor niesie komórki dni także na szerokim ekranie, gdzie istnieje tylko po to, by nagłówek
   miał jedno dziecko do przesuwania na wąskim. Bez tego komórki przestałyby się układać w rząd. */
.planner .planner-timeline-track {
	display: flex;
	flex: 1 1 auto;
}

/* Pasek podsumowania nad siatką: ta sama oś dni co nagłówek, więc liczba w komórce stoi dokładnie
   nad kolumną swojego dnia. Wiersz jest niski i stonowany — ma być tłem dla planowania, a nie
   konkurować z paskami transportów. */
.planner .header .summary-row {
	display: flex;
	flex: 1;
	text-align: center;
	border-top: 1px solid var(--color-border);
	background-color: var(--color-surface-muted);
}

.planner .header .summary-row > .planner-identification {
	flex: 0 0 320px;
	max-width: 320px;
	display: flex;
	align-items: center;
	padding: 0 8px;
	font-size: var(--font-xs);
	font-weight: 700;
	border-right: 1px solid var(--color-border);
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

/* Oś dni musi rozciągnąć się na całą szerokość jak w nagłówku — bez tego komórki zbiegają się
   do treści i liczby stoją stłoczone przy lewej krawędzi zamiast nad swoimi dniami. */
.planner .header .summary-row > .planner-timeline {
	flex: 1 1 auto;
	overflow: hidden;
}

.planner .header .summary-row .planner-summary-cell {
	display: flex;
	align-items: center;
	justify-content: center;
	min-height: 22px;
	font-size: var(--font-xs);
	border-right: 1px solid var(--color-border);
}

/* Dzień wykorzystany ponad deklarację — nie błąd, tylko sygnał, że obsługa może się nie domknąć. Ten sam
   zestaw klas stanu w pasku planera, tablicy pul i kolumnie listy, żeby kolor znaczył wszędzie to samo. */
.planner .header .summary-row .planner-summary-exceeded,
.quota-board .planner-summary-exceeded,
.quota-state .planner-summary-exceeded {
	color: var(--color-danger);
	font-weight: 700;
}

/* Dzień zapełniony co do sztuki: jeszcze się mieści, ale nic już nie zostało. */
.planner .header .summary-row .planner-summary-full,
.quota-board .planner-summary-full,
.quota-state .planner-summary-full {
	color: var(--color-warning);
	font-weight: 700;
}

/* Tablica pul. */
.quota-board .quota-board-label {
	white-space: nowrap;
	font-weight: 700;
}

.quota-board .quota-board-weekend {
	background-color: var(--color-surface-muted);
}


/* Komórka z ustaleniem jest klikalna — kursor mówi o tym, zanim użytkownik spróbuje. Dzień bez puli
   zostaje nieedytowalny: pulę zakłada się dla zakresu, a nie przez wypełnianie pustych kratek. */
.quota-board .quota-board-editable {
	cursor: pointer;
}

.quota-board .quota-board-editable:hover {
	background-color: var(--color-surface-alt);
}

.quota-board .quota-board-input {
	width: 70px;
	margin: 0 auto;
	text-align: center;
}

.planner .planner-line-header {
	background-color: var(--color-surface-alt);
	color: var(--color-text-secondary);
	text-align: center;
	padding: 1px 6px;
	border-top: 1px solid var(--color-border);
	border-bottom: 1px solid var(--color-border);
	font-weight: 600;
	letter-spacing: 0.5px;
	text-transform: uppercase;
	line-height: 1.2;
}

.planner .planner-line-header i {
	margin-right: 4px;
	opacity: 0.7;
}

.planner .content-row {
	display: flex;
	align-items: stretch;
	/* Każdy zestaw domyka gruba kreska, żeby było widać, gdzie zaczynają się jego linie czasu. */
	border-bottom: 5px solid var(--planner-row-separator);
}

/* Karta identyfikacji wiersza planera układa się w kolumnę: zaznaczenie i menu stoją własnym wierszem
   nad kierowcami, zamiast zabierać szerokość polom na wąskim ekranie. */
.planner .planner-id-card {
	padding: 4px 8px;
	flex: 1 1 auto;
	display: flex;
	flex-direction: column;
}

.planner .planner-id-card > .planner-id-fields {
	flex: 1 1 auto;
	min-width: 0;
}

.planner .planner-id-card > .planner-id-actions {
	flex: 0 0 auto;
	display: flex;
	align-items: center;
	gap: 6px;
}

.planner .planner-id-card.grey-light {
	color: var(--color-text-secondary);
}

/* Zestaw wskazany na mapie sekcji bocznej — ten sam akcent co wskazany wiersz listy kolumn
   (.cl-row-focused), ale jako obramowanie: tło karty niesie już kolor statusu zestawu. */
.planner .planner-id-card.planner-id-card-focused {
	box-shadow: inset 0 0 0 2px var(--color-accent);
}

.planner-type-lines {
	position: relative;
}

/* Wariant zwykły: pasek łamie treść i mieści cztery do sześciu linii, więc komórka dnia musi
   dać mu na to miejsce. Dotyczy wyłącznie wierszy zestawów — nagłówek dni niesie stałą liczbę
   informacji, więc rośnięcie razem z paskami tylko zabierałoby miejsce. Wariant kompaktowy
   (domyślny) zostaje jednowierszowy. */
.planner.planner-large .content-row .timeline-cell {
	min-height: 104px;
}

.planner.planner-large .timeline-block {
	min-height: 68px;
	white-space: normal;
}

/* Flagi krajów stoją przy krawędziach paska — skrajne punkty trasy czyta się wtedy wprost z jego
   początku i końca, a opis trasy dzieli resztę szerokości. */
.timeline-block-route {
	display: flex;
	align-items: center;
	gap: 4px;
	width: 100%;
}

.timeline-block-route-text {
	flex: 1 1 auto;
	text-align: center;
	overflow: hidden;
	text-overflow: ellipsis;
}

/* Przeciąganie paska: warstwy, które go nie przyjmą, przygasają, więc widać, gdzie pasek może
   wylądować. Pary typów wypisane są wprost, bo CSS nie porównuje atrybutu z atrybutem — a paski
   przeciągane w planerze są dokładnie trzy. */
body[data-planner-drag] .planner [data-planner-type] {
	opacity: 0.25;
	transition: opacity 0.15s ease-out;
}

body[data-planner-drag="freight"] .planner [data-planner-type="FREIGHT"],
body[data-planner-drag="cargo"] .planner [data-planner-type="CARGO"],
body[data-planner-drag="vehicle-combination-plan"] .planner [data-planner-type="VEHICLE_COMBINATION_PLAN"] {
	opacity: 1;
}

/* Paski leżą nad komórkami dni swojego wiersza. W trakcie przeciągania nie mogą łapać zdarzeń:
   upuszczenie na dzień zajęty paskiem trafiało w pasek, a stamtąd do wiersza zestawu, który
   przepina zestaw bez przesunięcia dni — przesunięcie o mniej dni, niż pasek ma, nie robiło nic.
   Komórka dnia (droppable-planner-cell) pod paskiem musi dostać upuszczenie sama. */
body[data-planner-drag] .planner entity-planner-item {
	pointer-events: none;
}

body[data-planner-drag="freight"] .planner [data-planner-type="FREIGHT"] .planner-line-header,
body[data-planner-drag="cargo"] .planner [data-planner-type="CARGO"] .planner-line-header,
body[data-planner-drag="vehicle-combination-plan"] .planner [data-planner-type="VEHICLE_COMBINATION_PLAN"] .planner-line-header {
	background-color: var(--color-warning);
	color: var(--color-text-primary);
}

/* Strona publiczna przewija się całym dokumentem, a nie wewnętrznym kontenerem jak aplikacja po
   zalogowaniu. Przy `height: 100vh` tło body kończyło się na pierwszym ekranie i niżej prześwitywało
   jaśniejsze tło dokumentu — stąd wysokość liczona treścią, z zachowaniem pełnego ekranu na minimum. */
body.public-page {
	height: auto;
	min-height: 100vh;
}

/* Punkt trasy na stronie publicznej: czynność z terminem jest nagłówkiem zwijanej sekcji, a jej
   treść — adres, współrzędne i opis — idzie jedno pod drugim, bo na telefonie wszystko w jednej
   linii wychodziło poza sekcję. */
.public-stop-details {
	display: flex;
	flex-direction: column;
	gap: 2px;
}

.public-stop-title {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 12px;
	margin: 0;
}

.public-stop-address {
	overflow-wrap: anywhere;
}

/* Pozycje pojazdu jako tabela: człony są stałe, więc kolumny trzymają je w jednej linii. */
.public-locations-table {
	font-size: var(--font-xs);
	margin-bottom: 6px;
}

.public-locations-table td,
.public-locations-table th {
	white-space: nowrap;
}

/* Formularz zgłoszenia pozycji: pola jedno pod drugim, żeby zmieścił się na telefonie. */
.public-location-form {
	display: flex;
	flex-direction: column;
	gap: 6px;
	max-width: 320px;
}

/* Trafienia geokodera: jedno pod drugim, każde klikalne — kierowca wybiera swoje miejsce. */
.public-location-results {
	display: flex;
	flex-direction: column;
	gap: 2px;
	max-height: 180px;
	overflow-y: auto;
}

.public-location-result {
	cursor: pointer;
	padding: 4px 6px;
	border: 1px solid var(--color-border);
	border-radius: 4px;
	font-size: var(--font-xs);
}

.public-location-result:hover {
	background-color: var(--color-surface-alt);
}

/* Waga pobrana na załadunku: wartość, jednostka i zapis w jednej linii, a na wąskim ekranie
   zawijane — kierowca wpisuje to jednym ruchem, stojąc przy wadze. */
.public-loaded-weight {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 6px;
}

.public-loaded-weight input {
	width: 110px;
}

.public-loaded-weight select {
	width: 80px;
}

/* Dokumenty punktu w raporcie: wgrywanie i lista plików jedna pod drugą. */
.public-stop-files {
	margin-top: 6px;
}

.public-stop-file {
	display: flex;
	align-items: center;
	gap: 6px;
	margin-top: 4px;
}

/* Współrzędne punktu: link do map i kopiowanie obok siebie, opis czynności pod adresem. */
.public-stop-coords {
	display: flex;
	align-items: center;
	gap: 8px;
	margin-top: 2px;
}

.public-stop-info {
	color: var(--color-text-secondary);
	font-size: var(--font-xs);
	margin-top: 2px;
	white-space: pre-line;
}

/* Kontener wieziony przez ten punkt — numer, rozmiar, PIN i list przewozowy do pobrania. */
.public-stop-container {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px;
	margin: 4px 0;
}

/* Pierwszy wiersz wartości w dymku paska — zakres, po którym poznaje się, o co chodzi. */
.planner-dropdown-lead {
	font-weight: 700;
}

/* Paleta planu: próbka nosi tę samą klasę koloru co pasek, więc obie strony nie mogą się
   rozjechać — wybrany kolor dostaje obwódkę, bo sam kolor tła nie mówi, który jest wybrany. */
.plan-color-picker {
	display: flex;
	flex-wrap: wrap;
	gap: 4px;
}

.plan-color-swatch {
	width: 28px;
	height: 20px;
	border: 1px solid;
	border-radius: 4px;
	padding: 0;
	appearance: none;
	cursor: pointer;
}

.plan-color-swatch.selected {
	outline: 2px solid var(--color-text-primary);
	outline-offset: 1px;
}

/* Dzień, nad którym trzymany jest przeciągany plan. */
.timeline-cell.planner-cell-dragover {
	outline: 2px dashed var(--color-warning);
	outline-offset: -2px;
}

/* Trasa zostaje w jednej linii także w wariancie zwykłym, gdzie reszta paska łamie treść:
   za długa nazwa miejscowości urywa się wielokropkiem, zamiast rozpychać pasek o kolejne wiersze.
   Flaga jest mniejsza niż w listach — na pasku stoi przy tekście, nie w osobnej kolumnie. */
.timeline-block .timeline-block-route,
.timeline-block .timeline-block-route-text {
	white-space: nowrap;
}

.timeline-block .enum-image {
	width: 15px;
	height: 10px;
	margin-right: 2px;
}

/* Pasek kompaktowy ma jeden wiersz, więc trasę skraca do dwóch znaków kodu i nazwy klienta.
   W wariancie zwykłym mieści się pełny opis skrajnych punktów nadzorowanych, a klient dostaje
   własny wiersz. */
.bars-normal-only {
	display: none;
}

.planner-large .bars-compact-only {
	display: none;
}

.planner-large .bars-normal-only {
	display: block;
}

.planner-large .timeline-block-route.bars-normal-only {
	display: flex;
}

/* Pierwsza linia paska — klient ze stawką — czyta się jak jego tytuł, reszta to szczegóły trasy i
   ładunku, więc tę jedną pogrubiamy. Tylko w wariancie zwykłym: kompaktowy mieści jedną linię i
   pogrubienie niczego by w nim nie wyróżniło. */
.planner-large .timeline-block .content > .bars-normal-only:first-child {
	font-weight: bold;
}

/* Transport normalnie zaczyna się załadunkiem i kończy rozładunkiem. Gdy skrajny przystanek robi
   coś innego, krawędź paska z tej strony jest przerywana i w kolorze ostrzeżenia. */
.timeline-block.unusual-start {
	border-left: 3px dashed var(--color-warning);
}

.timeline-block.unusual-end {
	border-right: 3px dashed var(--color-warning);
}

/* Krawędzie paska, za które planista go rozciąga i ściąga — wąski pas przy brzegu, widoczny dopiero
   po najechaniu, żeby nie zabierał miejsca treści. Pasek w trakcie rozciągania leży nad sąsiadami,
   bo podgląd potrafi na nie nachodzić. */
.timeline-block-edge {
	position: absolute;
	top: 0;
	bottom: 0;
	width: 6px;
	cursor: ew-resize;
	z-index: 1;
}

.timeline-block-edge-start {
	left: 0;
}

.timeline-block-edge-end {
	right: 0;
}

.timeline-block:hover .timeline-block-edge,
.timeline-block.timeline-block-resizing .timeline-block-edge {
	background-color: var(--color-border-strong);
	opacity: 0.6;
}

.timeline-block.timeline-block-resizing {
	z-index: 2;
	opacity: 0.85;
}

/* Uchwyt przeciągania wiersza listy i karty zestawu w planerze — sześć kropek przed polem wyboru.
   Przygaszony, dopóki wskaźnik nie stanie nad wierszem, żeby nie konkurował z treścią listy. */
.row-drag-handle {
	display: inline-flex;
	align-items: center;
	padding-right: 4px;
	cursor: grab;
	opacity: 0.45;
}

tr:hover .row-drag-handle,
.item-block:hover .row-drag-handle,
.planner-id-card:hover .row-drag-handle {
	opacity: 1;
}

/* Uchwyt przeniesienia: chwycony przeciąga cały pasek bez Ctrl — na inny dzień albo inny zestaw. */
.timeline-block-grip {
	display: flex;
	align-items: center;
	padding: 0 3px 0 2px;
	cursor: grab;
	opacity: 0.45;
}

.timeline-block:hover .timeline-block-grip {
	opacity: 1;
}

.planner-size-label {
	margin-right: 6px;
	font-size: var(--font-xs);
	white-space: nowrap;
}

.planner-day-label {
	margin-left: 8px;
	font-weight: 700;
	white-space: nowrap;
}

.planner-mobile-nav {
	display: none;
}

/* Wąski ekran: zestaw zajmuje własny wiersz, oś czasu leży pod nim i pokazuje jedną kolumnę,
   przełączaną strzałkami. Paski mają pozycję podaną w procentach całego zakresu, więc oś nie
   ukrywa kolumn, tylko przesuwa cały tor o wielokrotność szerokości widoku. */
@media (max-width: 767px) {
	.planner .header .days-row,
	.planner .content-row {
		flex-direction: column;
	}

	/* Rok znika z osobnego wiersza: odcinek obejmuje cały zakres, więc jego wyśrodkowany
	   napis i tak wypadłby poza widok. Pełną datę z rokiem niesie pasek nawigacji nad osią. */
	.planner .years-row {
		display: none;
	}

	.planner .header .days-row > .planner-identification,
	.planner .content-row > .planner-identification {
		flex: 1 1 auto;
		max-width: none;
		border-right: none;
	}

	/* clip, nie hidden: hidden zostawia kontener przewijalnym programowo, więc pierwsze
	   scrollIntoView na pasku przesuwało oś i rozjeżdżało ją z nagłówkiem dni. */
	.planner .header .days-row > .planner-timeline,
	.planner .content-row > .planner-timeline {
		overflow: clip;
	}

	.planner .planner-timeline-track,
	.planner .planner-type-lines {
		width: calc(var(--planner-columns, 1) * 100%);
		margin-left: calc(var(--planner-column-index, 0) * -100%);
		transition: margin-left 0.2s ease-out;
	}

	/* Tor dni jest elementem elastycznym nagłówka, więc bez tego skurczyłby się do szerokości
	   widoku i nazwy dni rozjechałyby się względem pasków pod nimi. */
	.planner .planner-timeline-track {
		flex: 0 0 auto;
	}

	/* Dzień bieżącej kolumny stoi już w nagłówku osi i w polu daty nad planerem, więc etykieta
	   przy strzałkach powtarzałaby to samo trzeci raz — zostają same strzałki. */
	.planner .planner-day-label {
		display: none;
	}

	/* Wybór trybu nic tu nie zmienia: na wąskim ekranie widać jedną kolumnę naraz niezależnie
	   od tego, czy zakres jest dzienny, czy tygodniowy. */
	.planner .planner-mode-switch {
		display: none;
	}

	.planner-mobile-nav {
		display: flex;
		align-items: center;
		justify-content: space-between;
		gap: 6px;
		width: 100%;
	}

	.planner-mobile-nav .planner-day-label {
		margin-left: 0;
	}

	/* Warstwy zwijają się do samych ikon — nazwy zjadłyby całą szerokość paska. */
	.planner .planner-layer-name {
		display: none;
	}
}

.btn-planner-layer .badge {
	display: none;
}

.btn-planner-layer .icon {
	display: inline-block;
}

.btn-planner-layer:hover .badge {
	display: inline-block;
}

.btn-planner-layer:hover .icon {
	display: none;
}

.timeline-cell {
	display: flex;
	flex: 1;
	border-right: 1px dashed var(--color-border-strong);
	min-height: 45px;
	align-items: center;
	justify-content: space-around;
}

.timeline-cell.past {
	background-color: var(--color-surface-muted);
}

.timeline-cell.today {
	background-color: var(--color-surface-muted);
}

.timeline-cell.future {
	background-color: var(--color-surface);
}

.timeline-cell.weekend {
	background-color: var(--planner-weekend-bg);
}

.timeline-block {
	position: absolute;
	cursor: pointer;
	border-radius: 8px;
	border: 0.5px solid;
	padding: 0px 4px;
	overflow: hidden;
	white-space: nowrap;
	min-width: 24px;
	min-height: 34px;
	top: 50%;
	transform: translateY(-50%);
}

.timeline-block .content {
	display: flex;
	flex: 1;
	flex-direction: column;
	justify-content: space-between;
	align-items: center;
	overflow: hidden;
	text-overflow: ellipsis;
}

.timeline-block .content .item-progress-bar {
  width: 100%;
  border-radius: 10px;
  overflow: hidden;
  text-align: center;
  border: 0.5px solid;
  border-color: darkgreen;
}

/************
***IMPORT_TSL***
*************/



.order-created {
    background-color: var(--color-success-soft-bg);
}


.logo-offset {
	padding: 3px;
}

.btn-sidebar-toggle + .logo-offset {
	margin-left: 1rem;
}

.icon-info {
	margin-right: 4px;
}

/******************
 ENTITY DROPDOWNS
******************/
/* Akcje wiersza — przycisk rozwijania wiersza i menu — stoja w jednym rzedzie. Kolumna akcji jest
   waska (szerokosc jednego przycisku), wiec w zwyklym przeplywie inline lamaly sie na dwie linie.
   Host zostaje inline, zeby do prawej krawedzi dosuwal je text-right komorki, tak jak dosuwa
   pojedyncze menu; blokowy flex zszedlby do wlasnej linii wszedzie, gdzie menu stoi obok innego
   przycisku w tym samym wierszu. */
.unt-dropdown-entity {
	display: inline-flex;
	align-items: center;
	gap: 4px;
}
.unt-dropdown-entity a {
	width: 100%;
	overflow: hidden;
	text-overflow: ellipsis;
	text-align: left;
}

/* w modalach nie ma panelu, który mógłby pokazać podgląd pliku */
.modal-body .file-preview-btn,
.modal-body li.file-preview-item {
	display: none;
}

.unt-dropdown li {
	list-style-type: none;
}

/******************
 TEXT MANAGEMENT
*******************/

.text-wrap {
	white-space: normal;
}

.text-xs {
	font-size: var(--font-xs);
}

[ng-cloak] {
  display: none !important;
}


/* ---------------------------------------------------
   Unt-alert
--------------------------------------------------- */
.unt-alert-panel {
    width: 100%;
    max-height: 60vh;
    padding: 0;
    display: flex;
    flex-direction: column;
}

.unt-alert-panel-footer {
    padding: 2px;
    font-size: var(--font-xs);
    background-color: var(--color-surface-highlight);
    border-top: 1px solid var(--color-border);
    text-align: right;
    position: sticky;
    bottom: 0;
    z-index: 10;
}

.unt-alert-empty {
    padding: 12px;
    color: var(--color-text-muted);
    font-style: italic;
    text-align: center;
}

.unt-alert-list-wrapper {
    max-height: 250px;
    overflow-y: auto;
    transition:
        max-height 0.6s ease,
        padding 0.6s ease,
        margin 0.6s ease;
}

.unt-alert-list {
    display: flex;
    flex-direction: column;
    margin: 0 4px;
    padding-bottom: 4px;
}

/* Nieprzeczytane powiadomienie wyróżnia lewa krawędź i pełna nieprzezroczystość
   — przeczytane zostaje w panelu, tylko przygaszone. */
.unt-alert-unread {
    border-left-width: 4px;
    font-weight: 600;
    cursor: pointer;
}

.unt-alert {
    position: relative;
    width: 100%;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    padding: 2px;
    padding-right: 34px;
    margin-bottom: 5px;

    border: 1px solid;
    border-radius: 4px;
    opacity: 0.85;

    overflow: hidden;
    max-height: 200px;

    transition:
        opacity 0.6s ease,
        transform 0.6s ease,
        max-height 0.6s ease,
        padding 0.6s ease;

    transform: translateY(0);
    opacity: 1;
}

.unt-alert.closing {
    opacity: 0;
    transform: translateY(-6px);
    max-height: 0;
    padding-top: 0;
    padding-bottom: 0;
}

.unt-alert:first-child {
    margin-top: 4px;
}

.unt-alert-success {
    background-color: transparent;
    border-color: var(--color-success-soft-bg);
    color: var(--color-success-text);
}

.unt-alert-info {
    background-color: transparent;
    border-color: var(--color-info-soft-bg);
    color: var(--color-info-text);
}

.unt-alert-warning {
    background-color: var(--color-warning-soft-bg);
    border-color: var(--color-warning-soft-bg);
    color: var(--color-warning-text);
}

.unt-alert-danger {
    background-color: var(--color-danger-soft-bg);
    border-color: var(--color-danger-soft-bg);
    color: var(--color-danger-text);
}

.unt-alert-icon {
    font-size: 18px;
    margin-right: 8px;
}

.unt-alert-text {
    flex: 1;
}

/* Komunikat z backendu niesie podział na linie jako \n (lista punktów, błędy importu). */
.unt-alert-message {
    white-space: pre-line;
}

.unt-alert-description {
    white-space: pre-line;
    font-size: var(--font-xs);
    color: inherit;
    opacity: 0.85;
    margin-top: 2px;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.unt-alert-code {
    font-size: var(--font-xs);
    color: inherit;
    opacity: 0.7;
    margin-top: 2px;
    text-align: right;
}

.unt-alert-link {
    color: inherit;
    font-weight: bold;
    margin-left: 6px;
    text-decoration: underline;
    cursor: pointer;
}
.unt-alert-link:hover {
    opacity: 0.8;
}

.unt-alert-close-btn {
    position: absolute;
    top: 1px;
    right: 6px;
    background: transparent;
    border: none;
    font-size: 20px;
    font-weight: bold;
    cursor: pointer;
    color: rgba(0,0,0,0.6);
}
.unt-alert-close-btn:hover {
    color: rgba(0,0,0,0.9);
}

.unt-alert-progress {
    position: relative;
    width: 100%;
    height: 4px;
    background: rgba(0, 0, 0, 0.22);
    border-radius: 4px;
    margin-top: 8px;
    overflow: hidden;
}

.unt-alert-progress-bar {
    position: absolute;
    left: 0;
    top: 0;
    height: 100%;
    background: rgba(255, 255, 255, 0.55);
    transition: width 0.05s linear;
}

.alert-dropdown-menu {
    position: fixed;
    right: 10px;
    bottom: 10px;

    width: 560px;
    max-width: calc(100vw - 20px);
    max-height: 70vh;

    background-color: var(--color-surface);
    border: 1px solid rgba(0, 0, 0, 0.15);
    border-radius: 4px;
    box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
    /* pod pływającym kafelkiem podglądu (1045), który otwiera się w tym samym rogu, a nad tłem okna (1040) */
    z-index: 1044;

    overflow-y: hidden;
    transition: max-height 0.25s ease;
}

.user-action-log-changes .form-value span {
    white-space: pre-line;
}

.freight-stop-block {
	border-radius: 8px;
	padding: 8px;
	margin: 8px;
	background-color: var(--color-surface-muted);
	box-shadow: var(--shadow-1);
}

/* Odznaka pozostałego czasu kierowcy przy chipie: te same kolory co ikona terminów, bo znaczą
   to samo — jak pilna jest sytuacja. Mniejszy font i nowrap, żeby para liczb nie łamała się na
   dwie linie w wąskiej komórce listy i nie podnosiła wiersza. */
.tacho-times-badge {
	display: inline-flex;
	align-items: center;
	gap: 3px;
	font-size: var(--font-xs);
	font-weight: 600;
	white-space: nowrap;
	vertical-align: middle;
}

.alert-level-ok {
	color: var(--color-teal);
	background: var(--color-surface);
	padding: 2px;
	border-radius: 4px;
	border: 1px solid var(--color-teal);	
}
.alert-level-low {
	color: var(--color-info);
	background: var(--color-surface);
	padding: 2px;
	border-radius: 4px;
	border: 1px solid var(--color-info);	
}
/* Token tekstowy, nie bazowy: --color-warning na jasnej powierzchni daje kontrast 1,99:1, czyli
   pomarańczowy alarm był w jasnym motywie praktycznie nieczytelny. --color-warning-text podnosi to
   do 5,43:1, a w ciemnym motywie oba tokeny wypadają tak samo (8,12:1), więc nic tam nie zmienia. */
.alert-level-medium {
	color: var(--color-warning-text);
	background: var(--color-surface);
	padding: 2px;
	border-radius: 4px;
	border: 1px solid var(--color-warning);	
}
.alert-level-high {
	color: var(--color-danger-alt);
	background: var(--color-surface);
	padding: 2px;
	border-radius: 4px;
	border: 1px solid var(--color-danger-alt);	
}
/* Ikona paliwa przy numerze rejestracyjnym (10849) — paleta ikony trasy; krytyczny jak termin krytyczny. */
.fuel-icon-good {
	color: limegreen;
}
.fuel-icon-medium {
	color: orange;
}
.fuel-icon-low {
	color: red;
}
.fuel-icon-no-data {
	color: gray;
}
.mobile-app-created {
	color: var(--color-text-primary);
}
.mobile-app-logged-in {
	color: limegreen;
}
.mobile-app-logged-out {
	color: var(--color-text-muted);
}

.alert-level-critical {
	color: var(--color-danger-soft-bg);
	background: var(--color-text-primary);
	padding: 2px;
	border-radius: 4px;
	border: 1px solid var(--color-text-primary);
}

/*********************/
/** DEADLINE MATRIX **/
/*********************/
/* Te same progi co ikona alertu (.alert-level-*), tylko jako tlo komorki — dlatego wersje "soft". */
.alert-level-bg-ok {
	background-color: var(--color-teal-soft-bg);
}
.alert-level-bg-low {
	background-color: var(--color-info-soft-bg);
}
.alert-level-bg-medium {
	background-color: var(--color-warning-soft-bg);
}
.alert-level-bg-high {
	background-color: var(--color-danger-soft-bg);
}
/* CRITICAL to najmocniejszy czerwony z rodziny, a nie inwersja jak w ikonie: komorka niesie edytowalne pole,
   ktore dziedziczy kolor tekstu z motywu — na czarnym tle wartosc gasla. Zamiast nadpisywac kolor w kazdym
   stanie pola (podglad, edytor, hover, oba motywy) zostawiamy tlo "soft", przy ktorym tekst motywu jest
   czytelny z definicji, a poziom odrozniamy nasyceniem i grubsza czcionka. */
.alert-level-bg-critical {
	background-color: var(--color-danger-soft-bg-hover);
	font-weight: 700;
}

.deadline-matrix th, .deadline-matrix-owner {
	white-space: nowrap;
}
/* Jedna metryka dla calej macierzy. Bez jawnej wysokosci linii kazda komorka jest tak wysoka, jak jej
   zawartosc: naglowek z <span> inaczej niz goly tekst, a komorka z identyfikacja (tekst + przyciski ikon)
   wyzej niz komorka z sama data — i wtedy pierwsza kolumna podnosi wiersz, a reszta wyglada na obnizona.
   Wysokosc linii ustawiona tu raz zdejmuje ta zaleznosc od zawartosci. */
.deadline-matrix > thead > tr > th,
.deadline-matrix > tbody > tr > td {
	vertical-align: middle;
	line-height: 22px;
	padding: 2px 6px;
}
.deadline-matrix > thead > tr > th {
	text-align: left;
}
/* Przyciski ikon licza sie z wysokoscia linii komorki, zamiast narzucac wlasna. */
.deadline-matrix-owner .btn {
	line-height: inherit;
}
/* Numer rejestracyjny (albo login kierowcy) i ikony informacyjne stoja w jednej linii. Flex siedzi we
   wrapperze, a NIE na samej komorce: <td> z display:flex przestaje byc komorka tabeli, wiec wypada
   z uzgadniania wysokosci wiersza i inaczej rozklada wlasne obramowanie — przy globalnym
   `td { border-top: 3px }` ta jedna kolumna byla przez to przesunieta w pionie wzgledem reszty. */
.deadline-matrix-owner {
	font-weight: 600;
}
.deadline-matrix-owner-content {
	display: flex;
	align-items: center;
	gap: 6px;
}
.deadline-matrix > thead > tr > th:first-child,
.deadline-matrix-owner {
	padding-left: 12px;
}
/* Kolumna akcji zwezona do zawartosci, zeby menu wiersza stalo rowno przy prawej krawedzi tabeli,
   a nie rozpychalo sie kosztem kolumn z terminami. */
.deadline-matrix-actions {
	width: 1%;
	white-space: nowrap;
}
.deadline-matrix-empty {
	color: var(--color-text-muted);
}
/* Termin po liczniku: obok daty (albo zamiast niej) kilometry do terminu. */
.deadline-matrix-cell {
	display: flex;
	align-items: center;
	gap: 6px;
	white-space: nowrap;
}
.deadline-matrix-kms {
	font-weight: 600;
}
/* Termin w komorce i jego menu ("Utworz nastepny termin", 10828) w jednej linii, menu przy prawej krawedzi. */
.deadline-matrix-cell-content {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 6px;
}
.deadline-matrix-cell-content .btn {
	line-height: inherit;
}
/* Pojazd bez odczytu licznika: zamiast kilometrow do terminu sam licznik terminu (10822, D2). */
.deadline-matrix-no-reading {
	color: var(--color-text-muted);
	font-style: italic;
}

.multiselect-container {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    align-items: center;
    height: auto;
    min-height: 34px;
    padding: 4px;
    cursor: text;
}

.multiselect-badge {
    display: flex;
    gap: 6px;
    align-items: center;
    font-size: 12px;
    font-weight: normal;
    padding: 4px 8px;
    border-radius: 4px;
}

.multiselect-input {
    border: none;
    outline: none;
    flex-grow: 1;
    min-width: 60px;
    background: transparent;
}

/* "+" w enum-multiselekcie: zwinięta wyszukiwarka — kompaktowy przycisk dodania kolejnej wartości */
.multiselect-add-btn {
    padding: 2px 8px;
    line-height: 1.4;
}


.multiselect-menu {
    min-width: 300px;
    max-width: 450px;
    white-space: normal;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    box-shadow: 0 4px 12px rgba(0,0,0,0.15);
    max-height: 250px;
    overflow-y: auto;
    z-index: 1060;
    margin: 0;
    padding: 0;
}

.multiselect-dropdown {
    padding: 6px 12px;
    cursor: pointer;
}

.multiselect-dropdown:hover,
.multiselect-dropdown.active {
    background-color: var(--color-surface-muted);
}

.multiselect-no-result-container {
    padding: 6px 12px;
    color: var(--color-text-muted);
    font-style: italic;
}

/***************************************************/
/* MODERN AUTH PAGES (login / reset / 2FA) *********/
/***************************************************/

body.auth-page {
	margin: 0;
	min-height: 100vh;
	background: linear-gradient(135deg, var(--color-sidebar-bg) 0%, var(--color-chrome-deep) 45%, var(--color-accent-hover) 100%);
	color: var(--color-sidebar-text);
	font-family: var(--font-normal);
	display: flex;
	flex-direction: column;
	overflow-x: hidden;
}

/* Tlo stron auth jest ciemne w obu motywach, ale w dark --color-accent-hover to jasny blekit (Breeze)
   i rozswietlilby caly rog — ostatni stopien gradientu bierzemy wtedy z ciemnego --color-accent-bg. */
html[data-theme="dark"] body.auth-page {
	background: linear-gradient(135deg, var(--color-sidebar-bg) 0%, var(--color-chrome-deep) 45%, var(--color-accent-bg) 100%);
}

body.auth-page::before,
body.auth-page::after {
	content: "";
	position: fixed;
	border-radius: 50%;
	filter: blur(80px);
	z-index: 0;
	pointer-events: none;
}

body.auth-page::before {
	top: -120px;
	left: -120px;
	width: 380px;
	height: 380px;
	background: rgba(97, 98, 241, 0.35);
}

body.auth-page::after {
	bottom: -160px;
	right: -160px;
	width: 460px;
	height: 460px;
	background: rgba(40, 112, 236, 0.25);
}

/* Plamy niosa barwe akcentu, a ta jest w dark inna (Breeze #3daee9 / #1d99f3) i swieci slabiej. */
html[data-theme="dark"] body.auth-page::before {
	background: rgba(61, 174, 233, 0.22);
}

html[data-theme="dark"] body.auth-page::after {
	background: rgba(29, 153, 243, 0.16);
}

.auth-shell {
	flex: 1 1 auto;
	display: flex;
	flex-direction: column;
	min-height: 100vh;
	position: relative;
	z-index: 1;
}

.auth-topbar {
	display: flex;
	align-items: center;
	justify-content: space-between;
	padding: 18px 28px 0 28px;
	gap: 16px;
}

.auth-topbar-actions {
	display: flex;
	align-items: center;
	gap: 10px;
}

.auth-topbar .auth-brand {
	display: flex;
	align-items: center;
	gap: 12px;
	color: var(--color-sidebar-text);
	text-decoration: none;
	font-size: 14px;
	letter-spacing: 0.4px;
}

.auth-topbar .auth-brand img {
	height: 32px;
	width: auto;
}

.auth-content {
	flex: 1 1 auto;
	display: flex;
	align-items: safe center;
	justify-content: safe center;
	padding: 32px 20px;
}

.auth-card {
	width: 100%;
	max-width: 460px;
	background: rgba(255, 255, 255, 0.97);
	color: var(--color-text-primary);
	border-radius: 8px;
	padding: 36px 36px 30px 36px;
	box-shadow: 0 24px 60px rgba(0, 0, 0, 0.35);
	position: relative;
	isolation: isolate;
	backdrop-filter: blur(14px);
	-webkit-backdrop-filter: blur(14px);
}

/* Karta jest polprzezroczysta (backdrop-filter), wiec kolor musi isc z alfa — to --color-surface dark. */
html[data-theme="dark"] .auth-card {
	background: rgba(42, 46, 50, 0.97);
}

.auth-card-logo {
	display: flex;
	justify-content: center;
	margin-bottom: 18px;
}

.auth-card-logo img {
	max-height: 60px;
	max-width: 220px;
}

.auth-card h1 {
	font-size: 22px;
	font-weight: 600;
	text-align: center;
	margin-bottom: 6px;
	color: var(--color-text-primary);
}

.auth-card .auth-subtitle {
	text-align: center;
	color: var(--color-text-muted);
	font-size: 13.5px;
	line-height: 1.45;
	margin-bottom: 22px;
	white-space: normal;
	overflow: visible;
	text-overflow: clip;
}

.auth-alert {
	white-space: pre-line;
	border-radius: 4px;
	padding: 11px 14px;
	margin-bottom: 16px;
	font-size: 13px;
	border: 1px solid transparent;
	line-height: 1.4;
}

.auth-alert.alert-error {
	background-color: var(--color-danger-soft-bg);
	border-color: var(--color-danger-soft-bg-hover);
	color: var(--color-danger-text);
}

.auth-alert.alert-success {
	background-color: var(--color-success-soft-bg);
	border-color: var(--color-success-soft-bg-hover);
	color: var(--color-success-text);
}

.auth-field {
	position: relative;
	margin-bottom: 14px;
}

.auth-field i.auth-field-icon {
	position: absolute;
	left: 14px;
	top: 50%;
	transform: translateY(-50%);
	color: var(--color-text-muted);
	font-size: 14px;
	pointer-events: none;
}

.auth-field input.auth-input {
	width: 100%;
	height: 44px;
	border: 1px solid var(--color-border-input);
	border-radius: 4px;
	padding: 0 14px 0 42px;
	font-size: 14px;
	color: var(--color-text-primary);
	background: var(--color-surface);
	transition: border-color 0.15s ease, box-shadow 0.15s ease;
	outline: none;
	box-shadow: none;
}

.auth-field input.auth-input:focus {
	border-color: var(--color-accent-strong);
	box-shadow: 0 0 0 3px var(--color-accent-soft);
}

/* W light pole i karta sa biale i rozdziela je ramka; w dark --color-surface to dokladnie kolor karty,
   wiec pole dostaje powierzchnie o stopien jasniejsza — tak jak .form-control w aplikacji. */
html[data-theme="dark"] .auth-field input.auth-input {
	background: var(--color-surface-muted);
}

.auth-field input.auth-input.has-action {
	padding-right: 56px;
}

.auth-field .auth-field-action {
	position: absolute;
	right: 6px;
	top: 50%;
	transform: translateY(-50%);
	display: flex;
	align-items: center;
	gap: 4px;
}

.auth-field .auth-field-action button {
	border: none;
	background: transparent;
	color: var(--color-text-muted);
	cursor: pointer;
	font-size: 13px;
	padding: 6px 10px;
	border-radius: 4px;
	font-weight: 600;
	transition: background 0.15s ease, color 0.15s ease;
}

.auth-field .auth-field-action button:hover {
	background: var(--color-accent-soft);
	color: var(--color-accent);
}

.auth-field .auth-field-action button:disabled {
	opacity: 0.4;
	cursor: not-allowed;
	color: var(--color-text-muted);
	background: transparent;
}

.auth-field .auth-password-toggle[aria-pressed="true"] {
	color: var(--color-accent);
}

.auth-btn-spaced {
	margin-top: 18px;
}

.auth-row {
	display: flex;
	justify-content: flex-end;
	align-items: center;
	margin-bottom: 18px;
	font-size: 13px;
}

.auth-row a {
	color: var(--color-accent);
	text-decoration: none;
	font-weight: 500;
}

.auth-row a:hover {
	text-decoration: underline;
}

.auth-btn {
	position: relative;
	width: 100%;
	height: 44px;
	border: 1px solid var(--color-accent);
	border-radius: 4px;
	background: var(--color-accent-bg);
	color: var(--color-text-inverse);
	font-weight: 600;
	font-size: 14.5px;
	cursor: pointer;
	transition: background 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
	letter-spacing: 0.3px;
}

/* Klikniety przycisk logowania od razu pokazuje, ze cos sie dzieje - miedzy klikiem
   a pojawieniem sie nowego dokumentu przegladarka nic nie rysuje. */
.auth-btn.disabled, .auth-btn.unt-click-pending {
	pointer-events: none;
	opacity: 0.75;
}

/* Spinner poza przeplywem tekstu, zeby etykieta nie przeskakiwala przy kliknieciu.
   Wysrodkowanie przez margin-top, nie transform - animacja list-spin nadpisuje transform. */
.auth-btn.disabled::after, .auth-btn.unt-click-pending::after {
	content: "";
	position: absolute;
	top: 50%;
	right: 14px;
	width: 14px;
	height: 14px;
	margin-top: -7px;
	border: 2px solid transparent;
	border-top-color: currentColor;
	border-radius: 50%;
	animation: list-spin 1s linear infinite;
}

.auth-btn:hover {
	background: var(--color-accent-hover);
	border-color: var(--color-accent-hover);
	box-shadow: 0 4px 12px rgba(59, 61, 171, 0.3);
}

.auth-btn:active {
	background: var(--color-accent-hover);
	border-color: var(--color-accent-hover);
}

.auth-back-link {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	color: var(--color-text-muted);
	text-decoration: none;
	font-size: 13px;
	margin-bottom: 14px;
	cursor: pointer;
	background: none;
	border: none;
	padding: 0;
}

.auth-back-link:hover {
	color: var(--color-accent);
}

.auth-helper {
	background: var(--color-surface-muted);
	border: 1px solid var(--color-border-input);
	border-radius: 4px;
	padding: 12px 14px;
	font-size: 12.5px;
	color: var(--color-text-muted);
	line-height: 1.5;
	margin-top: 6px;
	white-space: normal;
}

.auth-steps {
	display: flex;
	gap: 6px;
	margin-bottom: 22px;
}

.auth-step {
	flex: 1;
	display: flex;
	flex-direction: column;
	gap: 6px;
}

.auth-step .step-bar {
	height: 4px;
	border-radius: 99px;
	background: var(--color-border-input);
}

.auth-step.is-active .step-bar,
.auth-step.is-done .step-bar {
	background: var(--color-accent-bg);
}

.auth-step.is-done .step-bar {
	background: var(--color-success);
}

.auth-step .step-label {
	font-size: 11px;
	color: var(--color-text-muted);
	text-transform: uppercase;
	letter-spacing: 0.4px;
	font-weight: 600;
	white-space: normal;
	overflow: visible;
	text-overflow: clip;
}

.auth-step.is-active .step-label {
	color: var(--color-accent);
}

.auth-step.is-done .step-label {
	color: var(--color-success-hover);
}

.auth-footer {
	text-align: center;
	color: rgba(244, 246, 251, 0.65);
	font-size: 12px;
	padding: 16px 12px 22px 12px;
}

.auth-footer a {
	color: var(--color-accent-strong);
	text-decoration: none;
}

.auth-footer a:hover {
	text-decoration: underline;
}

/* Language selector */
.lang-switcher {
	position: relative;
}

.lang-switcher-toggle,
.auth-theme-toggle {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	background: rgba(255, 255, 255, 0.08);
	border: 1px solid rgba(255, 255, 255, 0.15);
	color: var(--color-sidebar-text);
	border-radius: 999px;
	padding: 7px 14px;
	font-size: 13px;
	cursor: pointer;
	transition: background 0.15s ease;
}

.lang-switcher-toggle:hover,
.auth-theme-toggle:hover {
	background: rgba(255, 255, 255, 0.15);
}

/* Przelacznik motywu to sama ikona, wiec pigulka wezsza niz przy kodzie jezyka. */
.auth-theme-toggle {
	padding: 7px 11px;
}

.lang-switcher-toggle i {
	font-size: 11px;
	opacity: 0.7;
}

.lang-switcher-menu {
	position: absolute;
	right: 0;
	top: calc(100% + 8px);
	min-width: 180px;
	max-height: 320px;
	overflow-y: auto;
	background: var(--color-surface);
	color: var(--color-text-primary);
	border-radius: 4px;
	box-shadow: 0 12px 36px rgba(0, 0, 0, 0.35);
	padding: 6px 0;
	display: none;
	z-index: 50;
}

.lang-switcher.open .lang-switcher-menu {
	display: block;
}

.lang-switcher-menu a {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 9px 14px;
	color: var(--color-text-primary);
	text-decoration: none;
	font-size: 13.5px;
}

.lang-switcher-menu a:hover {
	background: var(--color-surface-muted);
}

.lang-switcher-menu a.is-active {
	color: var(--color-accent);
	font-weight: 600;
}

.lang-switcher-menu a .lang-code {
	font-weight: 600;
	letter-spacing: 0.4px;
}

.lang-switcher-menu a .lang-name {
	color: var(--color-text-muted);
}

.lang-switcher-menu a.is-active .lang-name {
	color: var(--color-accent);
}

/* 2FA code input */
.auth-code-input {
	letter-spacing: 0.4em;
	text-align: center;
	font-size: 18px;
	padding-left: 14px;
}

@media (max-width: 520px) {
	.auth-card {
		padding: 26px 22px 22px 22px;
	}
	.auth-card h1 {
		font-size: 19px;
	}
	.auth-topbar {
		padding: 14px 16px 0 16px;
	}
	.auth-step .step-label {
		display: none;
	}
	body.auth-page::before {
		width: 220px;
		height: 220px;
		top: -160px;
		left: -160px;
	}
	body.auth-page::after {
		width: 260px;
		height: 260px;
		bottom: -200px;
		right: -200px;
	}
}

.swap-plan-last-search {
	margin-left: 8px;
}

/* Podpis chipa kolekcji encyjnej (kierowcy zestawu, tagi). Stopień wyżej niż najmniejszy rozmiar
   aplikacji: chip stoi sam, bez sąsiedniej etykiety, więc na 80% czytało się gorzej niż reszta wiersza. */
.chip-label {
	font-size: var(--font-sm);
}

.chip-list {
	display: flex;
	flex-wrap: wrap;
	gap: 4px;
	margin-bottom: 2px;
}

.chip-remove {
	margin-left: 6px;
	cursor: pointer;
}
/* Rich HTML editor (used by email-message-modal in previewMode) */
.rich-html-editor-toolbar {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	margin-bottom: 6px;
}

.rich-html-editor-select {
	width: auto;
}

.rich-html-editor-color {
	margin-bottom: 0;
}

.rich-html-editor-color-input {
	width: 0;
	height: 0;
	padding: 0;
	border: 0;
	opacity: 0;
	position: absolute;
}

.rich-html-editor-frame {
	width: 100%;
	min-height: 600px;
	border: 1px solid #dee2e6;
	background: #ffffff;
}

.rich-html-editor-source {
	width: 100%;
	min-height: 600px;
	font-family: 'Courier New', monospace;
	font-size: 12px;
	line-height: 1.5;
	padding: 10px;
	border: 1px solid #dee2e6;
	background: #fafafa;
	color: #333;
	resize: vertical;
}

/* Email message modal */
.email-modal-attachment-previews {
	display: flex;
	flex-wrap: wrap;
	gap: 4px;
	margin-bottom: 8px;
}

.email-modal-footer-collapse {
	margin-top: 8px;
}

/* Files uploader */
.files-uploader-row {
	display: flex;
	align-items: center;
}

.files-uploader-add {
	text-align: center;
	margin-top: 4px;
}

/* Freight-order full-width summary bar (freight-order-list-by-field) */
.freight-order-bar {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	background: var(--color-surface-highlight);
	border-radius: 4px;
	margin-bottom: 4px;
}

/* freight-order-bar: checkbox and the options/collapser hug their content; the data fields share the rest */
.freight-order-bar .fob-min {
	flex: 0 0 auto;
}

.freight-order-bar .fob-fill {
	flex: 1 1 0;
	min-width: 0;
}

/* Na waskim ekranie pola paska ida jedno pod drugim zamiast scisnietych.
   Media query lokalnie (nie w zbiorczym bloku wyzej), bo reguly bazowe
   .fob-fill sa zdefiniowane pozniej i wygralyby kolejnoscia w pliku. */
@media screen and (max-width: 1200px) {
	.freight-order-bar .fob-fill {
		flex: 0 0 100%;
	}
}

/* Freight block: row mixing field cells with action buttons — vertically center */
.freight-fields-row {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
}

/* Freight block (transport) — colored left border by freight status to delimit each transport */
.freight-block {
	border-radius: 10px;
	padding: 8px;
	border: 1px solid var(--color-border);
	border-left: 8px solid;
	margin: 8px 0px 24px 0px;
}

.freight-block.freight-border-INITIAL { border-left-color: #175CD3; }
.freight-block.freight-border-CONFIRMED { border-left-color: #046B6B; }
.freight-block.freight-border-WAREHOUSE { border-left-color: #B54708; }
.freight-block.freight-border-REALIZED { border-left-color: #047B52; }
.freight-block.freight-border-DOCUMENTS { border-left-color: #4A148C; }
.freight-block.freight-border-CONTROL { border-left-color: #B95503; }
.freight-block.freight-border-ACCOUNTING { border-left-color: #001C64; }
.freight-block.freight-border-FINISHED { border-left-color: #4B4C51; }

/* Flex utility: right-align flex children */
.justify-end {
	justify-content: flex-end;
}

/***************************************************/
/* BOOTSTRAP COLOR BRIDGE — bootstrap 3 → nasze tokeny */
/* Ładowane po bootstrap.min.css, więc wygrywa kolejnością. */
/* Cel: spójność palety + tematyzowalność pod dark mode.    */
/* (Docelowo przenieść do components.css przy podziale.)    */
/***************************************************/

/* Linki tekstowe (bootstrap domyślnie #337ab7) */
a {
	color: var(--color-accent);
}

a:hover,
a:focus {
	color: var(--color-accent-hover);
}

/* Kontekstowe kolory tekstu */
.text-success {
	color: var(--color-success-text);
}

.text-danger {
	color: var(--color-danger-text);
}

.text-warning {
	color: var(--color-warning-text);
}

.text-info {
	color: var(--color-info-text);
}

/* Pasek postępu */
.progress {
	background-color: var(--color-surface-alt);
}

.progress-bar {
	background-color: var(--color-accent-bg);
	color: var(--color-text-inverse);
}

.progress-bar-success {
	background-color: var(--color-success);
}

.progress-bar-danger {
	background-color: var(--color-danger);
}

.progress-bar-info {
	background-color: var(--color-info);
}

.progress-bar-warning {
	background-color: var(--color-warning);
}

/* Alerty (bootstrap) + .alert-error (własna, dotąd bez koloru) */
.alert-success {
	background-color: var(--color-success-soft-bg);
	color: var(--color-success-text);
	border-color: var(--color-success-soft-bg-hover);
}

.alert-info {
	background-color: var(--color-info-soft-bg);
	color: var(--color-info-text);
	border-color: var(--color-info-soft-bg-hover);
}

.alert-warning {
	background-color: var(--color-warning-soft-bg);
	color: var(--color-warning-text);
	border-color: var(--color-warning-soft-bg-hover);
}

.alert-danger,
.alert-error {
	background-color: var(--color-danger-soft-bg);
	color: var(--color-danger-text);
	border-color: var(--color-danger-soft-bg-hover);
}

/* Kontekstowe elementy list-group */
.list-group-item-success {
	background-color: var(--color-success-soft-bg);
	color: var(--color-success-text);
}

.list-group-item-info {
	background-color: var(--color-info-soft-bg);
	color: var(--color-info-text);
}

.list-group-item-warning {
	background-color: var(--color-warning-soft-bg);
	color: var(--color-warning-text);
}

.list-group-item-danger {
	background-color: var(--color-danger-soft-bg);
	color: var(--color-danger-text);
}

/***************************************************/
/* EXTRACTED FROM INLINE (Faza 3) — tokenowe, theme-aware */
/* Zastępują inline style="..." w szablonach; docelowo do components.css */
/***************************************************/
.bg-surface {
	background-color: var(--color-surface);
}

.bg-success-soft {
	background-color: var(--color-success-soft-bg);
}

.sticky-surface-header {
	position: sticky;
	top: 0;
	z-index: 10;
	background-color: var(--color-surface);
	border-bottom: 1px solid var(--color-border-strong);
}

.modal-sticky-header {
	position: sticky;
	top: 0;
	z-index: 10;
	padding: 8px 8px;
	background-color: var(--color-bg-app);
	box-shadow: var(--color-shadow) 0px 0.0625em 0.0625em, var(--color-shadow) 0px 0.125em 0.5em, rgba(255, 255, 255, 0.1) 0px 0px 0px 1px inset;
}

.message-card {
	min-width: 300px;
	padding: 4px 8px;
	margin: 4px;
	border: 1px solid var(--color-border);
	border-radius: 4px;
	background: var(--color-surface);
}

.col-divider-x {
	padding: 4px 12px;
	border-left: 1px solid var(--color-border);
	border-right: 1px solid var(--color-border);
}

.settlement-row-alt {
	background-color: var(--color-surface-muted);
	margin-right: 5px;
	padding: 0px 5px;
}

/* Linia pod nagłówkiem sekcji. Ujemny margines wciągał ją o piksel pod obramowanie
   kontenera — w przyklejonych paskach detali (topbar, przełącznik transportów,
   sekcja przewozu) dawało to widoczną jasną szczelinę na styku pasków. */
.collapsible-divider {
	border-bottom: 1px solid var(--color-border-strong);
	margin: 0px;
	padding: 0px;
}

/* Metryka (create/update audyt) — pasek przyklejony do dolu widoku detali,
   domyslnie schowany, wysuwany przyciskiem-uchwytem nad dolna krawedzia. */
common-details {
	display: block;
	position: sticky;
	bottom: 0;
	z-index: 150;
}

.common-details-toggle {
	position: absolute;
	bottom: 100%;
	left: 50%;
	transform: translateX(-50%);
	border-bottom-left-radius: 0;
	border-bottom-right-radius: 0;
}

/* Uchwyt jest wizualnie czescia wysuwanego paska, wiec trzyma ten sam ciemny ton co on —
   inaczej brałby jasne tlo z .btn-default. Wszystkie stany razem, bo .btn.btn-default nadpisuje
   je osobno dla hover/focus/active. Selektor zaczyna sie od elementu common-details, zeby wygrac
   specyficznoscia z blokiem "Opcja A" (.btn.btn-default nizej w pliku): przy rownej specyficznosci
   wygrywala tamta regula i uchwyt dostawal jasne tlo pod biala czcionka. */
common-details .btn.common-details-toggle,
common-details .btn.common-details-toggle:hover,
common-details .btn.common-details-toggle:focus,
common-details .btn.common-details-toggle.focus,
common-details .btn.common-details-toggle:active,
common-details .btn.common-details-toggle.active {
	background-color: var(--color-chrome-deep);
	color: var(--color-text-inverse);
	border-color: var(--color-chrome-deep);
}

/* Najciemniejsza powierzchnia chrome w obu motywach: w dark --color-chrome zrownal sie
   z --color-surface, wiec pasek nie odcinal sie od tresci detali. */
.common-details-bar {
	background-color: var(--color-chrome-deep);
	color: var(--color-text-inverse);
	max-height: 0;
	overflow: hidden;
	transition: max-height 0.25s ease;
}

.common-details-bar.open {
	border-top: 1px solid var(--color-border-strong);
	max-height: 200px;
}

.common-details-grid {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
}

@media screen and (max-width: 1200px) {
	.common-details-grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

.datetime-toolbar {
	display: flex;
	justify-content: space-between;
	padding: 4px 8px;
	background-color: var(--color-surface-muted);
}

/* Pole plików mieści się w swoim bloku: sztywne 400px wychodziło poza wyróżnioną
   kolumnę modalu, która jest węższa. 400px zostaje górnym ograniczeniem, żeby w
   szerokim widoku nie rozciągało się na całą stronę. */
.file-uploader-box {
	width: 100%;
	max-width: 400px;
	padding: 4px;
	background-color: var(--color-surface-muted);
	border-radius: 8px;
}

/***************************************************/
/* DARK-FIX: placeholdery + tekst inputów + bordery tabel (tokeny) */
/***************************************************/
.form-control {
	color: var(--color-text-primary);
}

input::placeholder,
textarea::placeholder,
.form-control::placeholder {
	color: var(--color-text-muted);
	opacity: 1;
}

/* Bootstrap .table-bordered narzuca jasne #ddd bordery — pod token (ciemne w dark) */
.table-bordered,
.table-bordered > thead > tr > th,
.table-bordered > thead > tr > td,
.table-bordered > tbody > tr > th,
.table-bordered > tbody > tr > td,
.table-bordered > tfoot > tr > th,
.table-bordered > tfoot > tr > td {
	border-color: var(--color-border);
}

.nav-tabs > li > a:hover {
	border: 1px solid var(--color-accent);
	border-bottom: 3px solid var(--color-accent);
	background-color: var(--color-surface-highlight);
	color: var(--color-text-primary);
}

#sidebar {
	box-shadow: inset -1px 0 0 var(--color-chrome-edge);
}

/* Przyciski subtelne (Opcja A): jasniejsze tlo + spojny border */
.btn.btn-default,
.btn.btn-white,
.btn.btn-success-light,
.btn.btn-primary-light,
.btn.btn-warning-light,
.btn.btn-info-light,
.btn.btn-danger-light {
	background-color: var(--color-surface-muted);
	border: 1px solid var(--color-border-input);
}
.btn.btn-default:hover,
.btn.btn-white:hover,
.btn.btn-success-light:hover,
.btn.btn-primary-light:hover,
.btn.btn-warning-light:hover,
.btn.btn-info-light:hover,
.btn.btn-danger-light:hover {
	background-color: var(--color-surface);
}
.btn.btn-secondary {
	border: 1px solid var(--color-border-input);
}

/* Bootstrap-bridge: gole .dropdown-menu > li > a (np. entity-shorts-selector) -> tokeny */
.dropdown-menu > li > a {
	color: var(--color-text-primary);
}
.dropdown-menu > li > a:hover,
.dropdown-menu > li > a:focus {
	background-color: var(--color-overlay-dark);
	color: var(--color-accent);
}
.dropdown-menu > li.active > a,
.dropdown-menu > li.active > a:hover,
.dropdown-menu > li.active > a:focus {
	background-color: var(--color-surface-highlight);
	color: var(--color-text-primary);
}

/* Bootstrap-bridge: pola edytowalne -> tlo pola (tokeny), bialy input w dark */
input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]):not([type="range"]):not([type="color"]),
textarea,
select,
.form-control {
	background-color: var(--color-surface-muted);
	color: var(--color-text-primary);
}

/* Bootstrap-bridge: bordery .table (th/thead/td) -> token (jednolite) */
.table > thead > tr > th,
.table > thead > tr > td,
.table > tbody > tr > th,
.table > tbody > tr > td,
.table > tfoot > tr > th,
.table > tfoot > tr > td {
	border-color: var(--color-border);
}

/* Material-bridge: md-dialog (confirm/prompt/alert) + lazy-map-prompt -> ciemny */
md-dialog,
md-dialog.md-default-theme {
	background-color: var(--color-surface) !important;
	color: var(--color-text-primary);
}
md-dialog .md-dialog-content-body {
	padding-top: 16px;
	padding-bottom: 16px;
}
.dialog-message {
	white-space: pre-line;
}
.dialog-message-code {
	margin-top: 12px;
	text-align: right;
	font-size: 11px;
	color: var(--color-text-muted);
}
md-dialog md-dialog-content,
md-dialog .md-dialog-content-body,
md-dialog h2,
md-dialog .md-title,
.lazy-map-prompt {
	color: var(--color-text-primary);
}
md-dialog .md-button {
	color: var(--color-accent);
}
/* md-prompt (np. komentarz anulowania): tekst i placeholder czytelne — Material narzuca ciemny, nadpisujemy tokenami */
md-dialog input,
md-dialog textarea {
	color: var(--color-text-primary);
}
md-dialog input::placeholder,
md-dialog textarea::placeholder,
md-dialog input::-webkit-input-placeholder,
md-dialog textarea::-webkit-input-placeholder {
	color: var(--color-text-muted) !important;
	opacity: 1;
}

/* btn-default-light (np. toggle zapamietanych filtrow) — dopelnia Opcje A */
.btn.btn-default-light {
	background-color: var(--color-surface-muted);
	border: 1px solid var(--color-border-input);
	color: var(--color-text-secondary);
}
.btn.btn-default-light:hover {
	background-color: var(--color-surface);
}

/* .btn-fill-container (toggle bez wariantu, np. entity-shorts-selector) -> subtelny przycisk */
.btn.btn-fill-container {
	background-color: var(--color-surface-muted);
	border: 1px solid var(--color-border-input);
	color: var(--color-text-primary);
}
.btn.btn-fill-container:hover {
	background-color: var(--color-surface);
}

/* Przycisk rezerwacji zestawu (vehicle-combination-reservation-handler) ma .btn-fill-container i przy
   rezerwacji .reservared-vehicle. Regula .btn.reservared-vehicle (wyzej w pliku) ma te sama specyficznosc
   co .btn.btn-fill-container, wiec od 10016 przegrywala i przycisk byl zawsze szary. Wszystkie stany
   razem, bo hover/focus/active nadpisuja tlo osobno (Opcja A, .btn.btn-fill-container:hover). */
.btn.btn-fill-container.reservared-vehicle,
.btn.btn-fill-container.reservared-vehicle:hover,
.btn.btn-fill-container.reservared-vehicle:focus,
.btn.btn-fill-container.reservared-vehicle.focus,
.btn.btn-fill-container.reservared-vehicle:active,
.btn.btn-fill-container.reservared-vehicle.active,
.open > .btn.btn-fill-container.reservared-vehicle.dropdown-toggle {
	background-color: var(--color-teal);
	border-color: var(--color-teal);
	color: var(--color-text-inverse);
}

/* md-dialog refinements: separatory naglowka/akcji + czytelny przycisk + hover (material agresywny -> !important) */
md-dialog md-toolbar,
md-dialog .md-title {
	border-bottom: 1px solid var(--color-border);
	padding-bottom: 8px;
}
md-dialog md-dialog-actions {
	border-top: 1px solid var(--color-border);
}
md-dialog .md-button {
	color: var(--color-accent) !important;
}
md-dialog .md-button:not([disabled]):hover,
md-dialog .md-button:not([disabled]):focus {
	background-color: var(--color-accent-soft) !important;
	color: var(--color-accent) !important;
}

/* Naglowki h1-h6 wersaliki */
h1, h2, h3, h4, h5, h6 {
	text-transform: uppercase;
}

/* md-autocomplete suggestions: dark + hover (wybor pola filtra/sortu) */
.md-autocomplete-suggestions {
	background-color: var(--color-surface) !important;
}
li.md-autocomplete-suggestion {
	color: var(--color-text-primary) !important;
}
li.md-autocomplete-suggestion:hover,
li.md-autocomplete-suggestion.selected {
	background-color: var(--color-overlay-dark) !important;
	color: var(--color-accent) !important;
}

/* Nazwa w collapsible (span, nie h-tag) — wersaliki jak naglowki */
collapsible .content-box-header .field-horizontal > span[i18n] {
	text-transform: uppercase;
	padding-right: 8px;
}

/* ===== Filtry — jednolity tryb: przyciski filtrów + edytor (dropdown) + "+ Filtr" ===== */
.filters2-bar {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 6px 14px;
	padding: 8px 10px;
	background: var(--color-surface);
	box-shadow: none;
	border-radius: 0 0 6px 6px;
	margin-top: 0;
	/* Kreska oddziela pasek od listy pod nim. Na liscie stronowej granice widac jeszcze po zmianie tla,
	   ale w liscie osadzonej pasek i wiersze leza na tej samej powierzchni i bez niej zlewaly sie w calosc. */
	border-bottom: 1px solid var(--color-border);
}
html[data-theme="dark"] .filters2-bar {
	background: #16181a;
	/* Tlo paska to najciemniejsza powierzchnia aplikacji, wiec "rowek" z --color-border (ciemniejszy
	   od tla) nie ma tu czego przyciemnic — kontrast 1,04:1, kreska jest praktycznie niewidoczna.
	   W ciemnym motywie kreska musi byc jasniejsza od paska: --color-surface daje 1,30:1, czyli tyle,
	   ile ma kreska w motywie jasnym (#dddddd na bialym = 1,36:1). */
	border-bottom-color: var(--color-surface);
}
.filters2-bar .filter-buttons + .filter-buttons {
	border-left: 1px solid rgba(128, 128, 128, 0.35);
	padding-left: 14px;
}

/* Przeciąganie chipa: przyciemnienie przeciąganego + wskaźnik miejsca wstawienia w odstępie między chipami */
.filter-btn-wrap.sortable-dragging {
	opacity: 0.45;
}
.filter-btn-wrap.sortable-dragover-before::before,
.filter-btn-wrap.sortable-dragover-after::after {
	content: '';
	position: absolute;
	top: 2px;
	bottom: 2px;
	width: 3px;
	border-radius: 2px;
	background: var(--color-info, #2196f3);
	z-index: 2;
}
.filter-btn-wrap.sortable-dragover-before::before {
	left: -4px;
}
.filter-btn-wrap.sortable-dragover-after::after {
	right: -4px;
}
.filter-buttons { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.filter-btn-wrap { position: relative; display: inline-flex; }
.filter-btn {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	max-width: 460px;
	min-height: 30px;
	border-radius: 15px;
	padding: 4px 11px;
	font-size: var(--font-sm);
	line-height: 1.3;
	border: 1px solid var(--color-info-soft-bg-hover);
	background: var(--color-info-soft-bg);
	color: var(--color-info-hover);
}
.filter-btn .sortable-handle { cursor: grab; opacity: 0.45; font-size: var(--font-xs); }
.filter-btn-icon { font-size: var(--font-xs); opacity: 0.65; flex: 0 0 auto; }
.filter-btn-field { font-weight: 600; overflow: hidden; text-overflow: ellipsis; }
.filter-btn-op { color: inherit; opacity: 0.75; font-weight: normal; text-transform: lowercase; }
.filter-btn-value {
	background: var(--color-surface);
	color: inherit;
	padding: 1px 8px;
	border-radius: 8px;
	font-weight: 500;
	overflow: hidden;
	text-overflow: ellipsis;
	max-width: 240px;
}
.filter-btn-caret { font-size: var(--font-xs); opacity: 0.55; margin-left: 2px; flex: 0 0 auto; }
.filter-btn-empty { background: transparent; border-style: dashed; color: var(--color-text-secondary); }
.filter-btn.active { box-shadow: 0 0 0 2px var(--color-info-hover) inset; }

/* sort — wyróżniony kolorem fioletowym względem filtra (niebieski) */
.filter-btn-sort {
	background: var(--color-purple-soft-bg);
	border-color: var(--color-purple);
	color: var(--color-purple);
}
.filter-btn-sort .filter-btn-op,
.filter-btn-sort .filter-btn-value { color: var(--color-purple); }
.filter-btn-sort.active { box-shadow: 0 0 0 2px var(--color-purple) inset; }

/* przyciski dodawania używają standardowych klas buttonów (.btn-info / .btn-primary) — kolory z motywu */
.add-filter-btn[disabled], .add-sort-btn[disabled],
.add-filter-btn.disabled, .add-sort-btn.disabled {
	opacity: 0.45;
	cursor: not-allowed;
	pointer-events: none;
}
/* Autocomplete wysuwany spod przycisku "+" — filtr, sortowanie, powiazanie pliku z rekordem */
.inline-autocomplete { display: inline-block; min-width: 260px; vertical-align: middle; }
.inline-autocomplete md-autocomplete,
.inline-autocomplete md-autocomplete-wrap { box-shadow: none; background: transparent; height: 32px; }
.inline-autocomplete md-autocomplete input {
	height: 32px;
	line-height: 32px;
	font-size: var(--font-sm);
}

.filter-editor {
	position: absolute;
	top: calc(100% + 4px);
	left: 0;
	z-index: 1050;
	min-width: 320px;
	max-width: 480px;
	background: var(--color-surface);
	color: var(--color-text-primary);
	border: 1px solid var(--color-bg-app-darker);
	border-radius: 8px;
	box-shadow: 0 8px 28px rgba(0,0,0,0.35);
	padding: 12px;
	white-space: normal;
}
.filter-editor .form-control {
	background: var(--color-surface-muted);
	color: var(--color-text-primary);
	border-color: var(--color-bg-app-darker);
}
.filter-editor .dropdown-menu,
.filter-editor .multiselect-menu { z-index: 1100; }
.filter-editor-header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 10px;
	font-weight: 600;
	padding-bottom: 8px;
	margin-bottom: 10px;
	border-bottom: 1px solid var(--color-surface-alt);
}
.filter-editor-field { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.filter-editor-close { cursor: pointer; color: var(--color-text-muted); flex: 0 0 auto; }
.filter-editor-close:hover { color: var(--color-text-primary); }
.filter-editor-body { display: flex; flex-direction: column; gap: 8px; }
.filter-editor-selector select.form-control,
.filter-editor-value .form-control { width: 100%; }
.filter-editor-value .multiselect-fullwidth { width: 100%; }
.filter-editor-actions {
	display: flex;
	align-items: center;
	gap: 8px;
	margin-top: 12px;
	padding-top: 8px;
	border-top: 1px solid var(--color-surface-alt);
}
.filter-editor-apply { margin-left: auto; }

/* hover/focus — czytelne w light i dark (nadpisuje bazowy .btn:hover, który przyciemniał tło/tekst) */
.filters2-bar .filter-btn:hover,
.filters2-bar .filter-btn:focus {
	background: var(--color-info-soft-bg-hover);
	border-color: var(--color-info-hover);
	color: var(--color-info-hover);
}
.filters2-bar .filter-btn-sort:hover,
.filters2-bar .filter-btn-sort:focus {
	background: var(--color-purple-soft-bg-hover);
	border-color: var(--color-purple);
	color: var(--color-purple);
}
/* przyciski dodawania: hover/focus obsługiwane przez standardowe klasy .btn-info / .btn-primary */

/* Wskaźnik rozwinięcia na początku nagłówka: chevron-right, obracany o 90° przy rozwinięciu.
   Obrót stoi przy samej klasie, nie przy strukturze nagłówka collapsible — ten sam wskaźnik nosi
   nagłówek obszaru pól w konfiguratorze listy własnej (.cl-available-group-head), a przypięty do
   struktury obrót tam nie działał: strzałka zostawała pozioma mimo klasy .expanded.
   Obrót zsynchronizowany z animacją collapse (Bootstrap .collapsing: height 0.35s ease). */
.collapsible-toggle-indicator {
	transition: transform 0.35s ease;
}
.collapsible-toggle-indicator.expanded {
	transform: rotate(90deg);
}
collapsible .content-box-header .field-horizontal > .collapsible-toggle-indicator {
	margin-right: 8px;
}

/* Tytuł collapsible: zwinięte -> waga standardowa, rozwinięte -> pogrubione.
   Stan rozpoznawany po klasie .expanded wskaźnika rozwinięcia,
   nie po dowolnym chevronie w nagłówku (dropdowny akcji też mają chevrony).
   Sekcja zablokowana (locked) nie ma wskaźnika i jest zawsze rozwinięta, więc też pogrubiona. */
collapsible .content-box-header:has(.collapsible-toggle-indicator:not(.expanded)) .field-horizontal > span[i18n] {
	font-weight: normal;
}
collapsible .content-box-header:has(.collapsible-toggle-indicator.expanded) .field-horizontal > span[i18n],
collapsible .content-box-header:not(:has(.collapsible-toggle-indicator)) .field-horizontal > span[i18n] {
	font-weight: 700;
}

/* Sekcja z dyrektywą sticky-below: nagłówek (tytuł i przyciski) zostaje pod przyklejonym paskiem wskazanym
   selektorem, dopóki przewija się treść sekcji, i odjeżdża razem z jej końcem. Pozycję daje zmienna
   --sticky-below-top (dyrektywa śledzi wysokość paska), tło — kolor obszaru przewijania, żeby przewijana
   treść nie prześwitywała. Warstwa tuż pod przyklejonym paskiem przewozu (.sticky-freight-overview, 152). */
collapsible[sticky-below] > div > .content-box-section > .content-box-header {
	position: sticky;
	top: var(--sticky-below-top, 0);
	z-index: 151;
	background-color: var(--color-bg-app);
}

/* Taka sekcja obejmuje całą listę kart (punkty trasy) bez własnej ramki — cień przy najechaniu rysowałby
   ją z powrotem wokół wszystkich kart naraz. */
collapsible[sticky-below] > div > .content-box-section:hover {
	box-shadow: none;
}

/* forwarder twin-list header: icons only (half-width lists) */
forwarder-vehicle-combination-list .app-content-header-buttons .mobile-hide,
forwarder-vehicle-combination-list .app-content-header-buttons .dropdown-toggle > span,
forwarder-list-freight-list .app-content-header-buttons .mobile-hide,
forwarder-list-freight-list .app-content-header-buttons .dropdown-toggle > span {
	display: none;
}

/* freight-details: aktywny short kolejności transportu + strzałki w obwolutce */
.freight-short-nav {
	display: inline-block;
	margin: 4px;
}

.freight-short-nav-active {
	padding: 3px 5px;
	border-radius: 6px;
	background-color: var(--color-border-input);
}

.cl-column-count {
	margin-right: 8px;
	font-size: 12px;
	align-self: center;
}

/* AI Assistant chat — kolory z tokenów semantycznych (var(--color-*)), więc dark mode działa automatycznie */
.ai-assistant { display: flex; height: calc(100vh - 50px); width: 100%; overflow: hidden; background: var(--color-surface); color: var(--color-text-primary); }
.ai-assistant__sidebar { width: 260px; min-width: 200px; border-right: 1px solid var(--color-border); display: flex; flex-direction: column; background: var(--color-surface-muted); }
.ai-assistant__new { margin: 10px; }
.ai-assistant__conversations { flex: 1; overflow-y: auto; }
.ai-assistant__clear-all { margin: 8px 10px; color: var(--color-danger); }
.ai-assistant__conversation { display: flex; align-items: center; gap: 8px; padding: 10px 12px; cursor: pointer; border-bottom: 1px solid var(--color-border); color: var(--color-text-secondary); }
.ai-assistant__conversation:hover { background: var(--color-surface-alt); }
.ai-assistant__conversation--active { background: var(--color-surface-highlight); color: var(--color-text-primary); font-weight: 600; }
.ai-assistant__conversation-title { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ai-assistant__conversation-delete { color: var(--color-text-muted); visibility: hidden; }
.ai-assistant__conversation:hover .ai-assistant__conversation-delete { visibility: visible; }
.ai-assistant__conversation-delete:hover { color: var(--color-danger); }
.ai-assistant__main { position: relative; flex: 1; display: flex; flex-direction: column; min-width: 0; }
.ai-assistant__header { padding: 10px 16px; border-bottom: 1px solid var(--color-border); font-weight: 600; }
.ai-assistant__messages { flex: 1; min-height: 0; overflow-y: auto; padding: 16px; display: flex; flex-direction: column; gap: 10px; }
/* Sekcje między historią a composerem (doprecyzowanie, plan do zatwierdzenia, postęp importów) rosną z treścią:
   przy wielu opcjach wypychały composer poza okno czatu, a historia — flex-basis 0 — kurczyła się do zera i nie
   dawała się przewijać. Limit wysokości + własny scroll zostawiają miejsce rozmowie i trzymają composer w oknie. */
.ai-assistant__clarify, .ai-assistant__pending, .ai-assistant__imports { flex: 0 1 auto; min-height: 0; max-height: 45%; overflow-y: auto; }
.ai-assistant__composer { flex: 0 0 auto; }
.ai-assistant__empty { margin: auto; color: var(--color-text-muted); }
/* kolumna: dymek + ikona usunięcia POD dymkiem, wyrównane do strony autora wiadomości */
.ai-assistant__message { display: flex; flex-direction: column; }
.ai-assistant__message--user { align-items: flex-end; }
.ai-assistant__message--assistant { align-items: flex-start; }
.ai-assistant__bubble { position: relative; max-width: 78%; padding: 10px 14px; border-radius: 14px; overflow-wrap: anywhere; line-height: 1.4; }
.ai-assistant__msgbar { display: flex; align-items: center; gap: 10px; }
.ai-assistant__bubble > .ai-assistant__msgbar { margin-bottom: 2px; }
.ai-assistant__think-label { display: inline-flex; align-items: center; gap: 5px; }
/* ikona pod dymkiem, widoczna dopiero po najechaniu na wiadomość — na stałe rozpraszałaby rozmowę */
.ai-assistant__msg-delete { visibility: hidden; margin-top: 2px; color: var(--color-text-muted); opacity: 0.6; font-size: 13px; cursor: pointer; }
.ai-assistant__message:hover .ai-assistant__msg-delete { visibility: visible; }
.ai-assistant__msg-delete:hover { opacity: 1; color: var(--color-danger); }
.ai-assistant__pending-list { margin: 0 0 10px; padding-left: 18px; max-height: 160px; overflow-y: auto; font-size: 0.92em; }
.ai-assistant__pending-list li { margin: 2px 0; }
.ai-assistant__clarify { margin: 0 16px 10px; padding: 10px 14px; border: 1px solid var(--color-info); background: var(--color-info-soft-bg); color: var(--color-text-primary); border-radius: 8px; }
.ai-assistant__clarify-hint { font-size: 12px; color: var(--color-text-secondary); margin-bottom: 8px; }
.ai-assistant__clarify-options { display: flex; flex-wrap: wrap; gap: 6px; }
/* propozycja bywa długa (lista pole=wartość) — bez łamania przycisk obcina treść i opcje są nieczytelne */
.ai-assistant__clarify-options .btn { white-space: normal; text-align: left; word-break: break-word; max-width: 100%; }
.ai-assistant__clarify-group { margin-bottom: 10px; }
.ai-assistant__clarify-group-question { font-size: 13px; font-weight: 600; margin-bottom: 4px; }
.ai-assistant__clarify-send { margin-top: 6px; }
.ai-assistant__clarify-custom { margin-top: 6px; font-size: 13px; }
.ai-assistant__imports { margin: 0 16px 10px; padding: 8px 14px; border: 1px solid var(--color-info); background: var(--color-info-soft-bg); border-radius: 8px; font-size: 12px; }
.ai-assistant__import-row { display: flex; gap: 6px; align-items: center; }
.ai-assistant__message--user .ai-assistant__bubble { background: var(--color-accent); color: var(--color-on-accent); border-bottom-right-radius: 4px; }
/* Bańka użytkownika ma tło w kolorze akcentu, a globalne `a` maluje link DOKŁADNIE tym samym kolorem —
   odnośnik do załączonego pliku był więc niewidoczny, dopóki hover nie zmienił go na inny odcień.
   Wewnątrz tej bańki link bierze kolor jej tekstu, a odróżnia go podkreślenie. */
.ai-assistant__message--user .ai-assistant__bubble a,
.ai-assistant__message--user .ai-assistant__bubble a:hover,
.ai-assistant__message--user .ai-assistant__bubble a:focus { color: var(--color-on-accent); text-decoration: underline; }
.ai-assistant__message--assistant .ai-assistant__bubble { background: var(--color-surface-alt); color: var(--color-text-primary); border-bottom-left-radius: 4px; }
.ai-assistant__bubble--thinking { color: var(--color-text-muted); font-style: italic; }
.ai-assistant__pending { margin: 0 16px 10px; padding: 12px 14px; border: 1px solid var(--color-warning); background: var(--color-warning-soft-bg); color: var(--color-text-primary); border-radius: 8px; }
.ai-assistant__pending-title { font-weight: 600; margin-bottom: 6px; }
.ai-assistant__pending-summary { margin-bottom: 10px; white-space: pre-wrap; }
.ai-assistant__pending-actions { display: flex; gap: 8px; }
.ai-assistant__composer { border-top: 1px solid var(--color-border); padding: 10px 16px; }
.ai-assistant__attachments { display: flex; flex-wrap: wrap; gap: 4px; max-height: 76px; overflow-y: auto; padding: 4px 0; }
.ai-assistant__attachment { display: inline-flex; align-items: center; gap: 5px; max-width: 240px; padding: 3px 8px; background: var(--color-accent-soft-bg); border-radius: 10px; font-size: 12px; color: var(--color-text-secondary); }
.ai-assistant__attachment-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ai-assistant__attachment-remove { cursor: pointer; flex-shrink: 0; opacity: 0.7; }
.ai-assistant__attachment-remove:hover { opacity: 1; color: var(--color-danger); }
.ai-assistant__inputbox { display: flex; flex-direction: column; border: 1px solid var(--color-border-input); border-radius: 14px; background: var(--color-surface); padding: 6px 6px 6px 12px; cursor: text; }
.ai-assistant__inputbox:focus-within { border-color: var(--color-accent); }
.ai-assistant__input { width: 100%; border: none; outline: none; background: transparent; resize: none; overflow-y: hidden; padding: 6px 4px; font: inherit; line-height: 1.4; color: var(--color-text-primary); }
.ai-assistant__toolbar { display: flex; justify-content: flex-end; align-items: center; gap: 6px; }
/* ciasne, kwadratowe buttony przy prawej krawędzi; ikona wyśrodkowana bez flexa (flex rozciągał ikonę) */
.ai-assistant__attach, .ai-assistant__send, .ai-assistant__stop { margin: 0; width: 34px; height: 34px; padding: 0; text-align: center; line-height: 32px; }
.ai-assistant__attach i, .ai-assistant__send i, .ai-assistant__stop i,
.ai-assistant__attach svg, .ai-assistant__send svg, .ai-assistant__stop svg { width: auto; height: 1em; vertical-align: middle; }
/* wyższa swoistość niż bootstrapowe input[type="file"]{display:block}, inaczej pokazuje się natywne „Wybierz plik" */
input[type="file"].ai-assistant__file-input { display: none; }
.ai-assistant__dropzone { position: absolute; inset: 0; z-index: 6; display: none; align-items: center; justify-content: center; background: var(--color-accent-soft); pointer-events: none; }
.ai-assistant__main.unt-dragging .ai-assistant__dropzone { display: flex; }
.ai-assistant__dropzone-inner { display: flex; flex-direction: column; align-items: center; gap: 10px; padding: 26px 40px; border: 2px dashed var(--color-accent); border-radius: 14px; background: var(--color-surface); color: var(--color-accent); font-size: 15px; }
.ai-assistant__dropzone-inner i { font-size: 30px; }
@media (max-width: 768px) { .ai-assistant__sidebar { width: 150px; min-width: 130px; } .ai-assistant__bubble { max-width: 90%; } }
.ai-assistant__usertext { white-space: pre-wrap; }

/* Log wykonania automatyzacji AI: argumenty i wyniki narzędzi to długi JSON bez spacji — bez łamania
   w dowolnym miejscu tabela rozpychała stronę i zostawiał poziomy przewijak. */
.ai-automation-run-log-value { white-space: pre-wrap; overflow-wrap: anywhere; }
.ai-assistant__md > *:first-child { margin-top: 0; }
.ai-assistant__md > *:last-child { margin-bottom: 0; }
.ai-assistant__md p { margin: 0 0 8px; }
.ai-assistant__md ul, .ai-assistant__md ol { margin: 0 0 8px; padding-left: 20px; }
.ai-assistant__md h4, .ai-assistant__md h5, .ai-assistant__md h6 { margin: 8px 0 4px; font-size: 1em; font-weight: 700; }
.ai-assistant__md code { background: var(--color-overlay-dark); padding: 1px 4px; border-radius: 3px; font-size: 0.9em; }
.ai-assistant__md pre { background: #282c34; color: #e6e6e6; padding: 10px 12px; border-radius: 6px; overflow-x: auto; margin: 0 0 8px; }
.ai-assistant__md pre code { background: none; padding: 0; color: inherit; }
.ai-assistant__md a { color: var(--color-accent); }
.ai-assistant__md table { display: block; width: max-content; max-width: 100%; overflow-x: auto; border-collapse: collapse; margin: 0 0 8px; font-size: 0.92em; }
.ai-assistant__md th, .ai-assistant__md td { border: 1px solid var(--color-border); padding: 6px 10px; text-align: left; vertical-align: top; }
.ai-assistant__md th { background: var(--color-surface-alt); font-weight: 700; }
.ai-assistant__md tbody tr:nth-child(even) td { background: var(--color-overlay-dark); }
.ai-assistant__md .align-center { text-align: center; }
.ai-assistant__md .align-right { text-align: right; }
.ai-assistant__msg-file { margin-top: 6px; font-size: 12px; opacity: 0.9; }
.ai-assistant__think { margin: 0 0 8px; font-size: 12px; border: 1px solid var(--color-border); border-radius: 8px; background: var(--color-surface-muted); }
.ai-assistant__think summary { cursor: pointer; padding: 5px 10px; color: var(--color-text-secondary); user-select: none; }
.ai-assistant__think-body { padding: 8px 10px; border-top: 1px dashed var(--color-border); color: var(--color-text-secondary); white-space: pre-wrap; max-height: 260px; overflow-y: auto; }
.ai-assistant__meta { font-size: 11px; color: var(--color-text-muted); white-space: nowrap; }
.ai-assistant__changes { margin: 8px 0 0; font-size: 12px; border: 1px solid var(--color-border); border-radius: 8px; background: var(--color-surface-muted); }
.ai-assistant__changes summary { cursor: pointer; padding: 5px 10px; color: var(--color-text-secondary); user-select: none; flex-wrap: wrap; row-gap: 2px; }
.ai-assistant__changes summary > span { white-space: nowrap; }
.ai-assistant__changes-caret { font-size: 10px; transition: transform 0.15s; }
.ai-assistant__changes[open] .ai-assistant__changes-caret { transform: rotate(90deg); }
.ai-assistant__changes-failed { color: var(--color-danger); }
.ai-assistant__changes-list { margin: 0; padding: 6px 10px; list-style: none; border-top: 1px dashed var(--color-border); max-height: 260px; overflow-y: auto; }
.ai-assistant__change { display: flex; gap: 6px; padding: 2px 0; overflow-wrap: anywhere; }
.ai-assistant__change > .fa-check { color: var(--color-success); margin-top: 2px; }
.ai-assistant__change--failed > .fa-xmark { color: var(--color-danger); margin-top: 2px; }
.ai-assistant__change--skipped > .fa-circle-pause { color: var(--color-warning); margin-top: 2px; }
.ai-assistant__change-action { font-weight: 600; }
.ai-assistant__change-detail { color: var(--color-text-secondary); }
.ai-assistant__queue { margin-bottom: 8px; padding: 8px 10px; background: var(--color-surface-muted); border: 1px solid var(--color-border); border-radius: 8px; }
.ai-assistant__queue-head { font-size: 11px; text-transform: uppercase; letter-spacing: 0.03em; color: var(--color-text-muted); margin-bottom: 4px; }
.ai-assistant__queue-item { display: flex; align-items: center; gap: 8px; padding: 3px 0; font-size: 13px; }
.ai-assistant__queue-text { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ai-assistant__queue-remove { cursor: pointer; color: var(--color-danger); flex-shrink: 0; }
.ai-assistant__queue-add, .ai-assistant__stop { flex-shrink: 0; }

/* Czat osadzony (ai-assistant-chat): element komponentu jest dzieckiem flex swoich kontenerów */
ai-assistant-chat { display: flex; flex: 1; min-width: 0; min-height: 0; }
ai-assistant-chat .ai-assistant__main { flex: 1; min-width: 0; }
.ai-assistant__minibar { display: flex; align-items: center; gap: 6px; padding: 8px 10px; border-bottom: 1px solid var(--color-border); color: var(--color-text-secondary); }
.ai-assistant__minibar-select { flex: 1; min-width: 0; }
/* pływające okienko czatu — otwiera je przycisk asystenta (ai-assistant-fab) na liście i w detalach */
.ai-assistant-popup { position: fixed; right: 24px; bottom: 88px; z-index: 1040; width: 430px; max-width: calc(100vw - 40px); height: 560px; max-height: calc(100vh - 130px); display: flex; background: var(--color-surface); border: 1px solid var(--color-border); border-radius: 12px; box-shadow: 0 8px 30px var(--color-overlay-dark); overflow: hidden; }

/* Pływający przycisk asystenta (FAB) — statycznie w prawym dolnym rogu, czat otwiera się nad nim.
   Sam element komponentu nie tworzy pudełka: przycisk i okienko są pozycjonowane względem okna. */
ai-assistant-fab { display: contents; }
.ai-assistant-fab { position: fixed; right: 24px; bottom: 24px; z-index: 1041; display: flex; align-items: center; justify-content: center; width: 52px; height: 52px; border-radius: 50%; background: var(--color-accent); color: #fff; font-size: 20px; box-shadow: 0 4px 14px var(--color-overlay-dark); cursor: pointer; transition: background-color 0.2s ease, transform 0.2s ease; }
.ai-assistant-fab:hover { background: var(--color-accent-hover); color: #fff; transform: scale(1.06); text-decoration: none; }
.ai-assistant-fab.active { background: var(--color-accent-deep); }

/* Przycisk siada w narożniku nad stopką paginatora i zasłaniał selektor liczby wierszy — stopka listy
   z własnym przyciskiem rezerwuje mu miejsce. Tam, gdzie przycisk jest tylko schowany stylem
   (komunikator), narożnik wraca do pełnej szerokości; w zakładce sekcji bocznej przycisku nie ma
   w ogóle (warunek w list-view-content), więc selektor sąsiedztwa sam tam nie trafia. */
paginator:has(+ ai-assistant-fab) .app-content-footer { padding-right: 88px; }
body:has(.messenger-view) paginator .app-content-footer { padding-right: 0; }

/* Podgląd pliku (file-preview) — sekcja boczna listy i detali */
.list-tab-section-file { display: flex; height: calc(100vh - 50px); }
/* miejsce na absolutnie pozycjonowany przycisk zamknięcia panelu (X), jak w minibarze czatu */
.list-tab-section-file .file-preview-header { padding-right: 48px; }
file-preview { display: flex; flex: 1; min-width: 0; min-height: 0; }
.file-preview { display: flex; flex: 1; flex-direction: column; min-width: 0; min-height: 0; }
.file-preview-header { display: flex; align-items: center; gap: 8px; padding: 8px 12px; border-bottom: 1px solid var(--color-border); }
.file-preview-filename { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
.file-preview-actions { display: flex; gap: 4px; }
.file-preview-frame { flex: 1; width: 100%; border: none; background-color: var(--color-bg-app); }
.file-preview-pdf { flex: 1; overflow: auto; padding: 8px; background-color: var(--color-bg-app); }
.file-preview-pdf-page { display: block; margin: 0 auto 8px; box-shadow: var(--shadow-card); }
.file-preview-image-box { flex: 1; overflow: auto; text-align: center; background-color: var(--color-bg-app); }
.file-preview-image { max-width: 100%; }
.file-preview-unsupported { padding: 24px; text-align: center; color: var(--color-text-muted); }
.file-preview-video-box { display: flex; justify-content: center; padding: 8px; background-color: #000; }
.file-preview-video { width: 100%; max-height: 80vh; }

/* Pomoc: kontakt z BOK w rozwijanym panelu nagłówka listy */
.help-contact { min-width: 360px; max-width: 460px; padding: 8px 14px; white-space: normal; }
.help-contact-title { margin-bottom: 8px; font-weight: bold; }
.help-contact-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 6px; }
.help-contact-row .label { flex: 0 0 auto; width: auto; }
.help-contact-icon { width: 16px; text-align: center; color: var(--color-text-muted); }
.help-contact-value { font-weight: bold; }
.help-contact-note { margin-top: 2px; color: var(--color-text-muted); }
.help-contact-closed { margin-top: 8px; font-weight: bold; }
/* Nazwa instrukcji (instruction-name): klik otwiera instrukcję albo menu wyboru postaci, ikony obok to skróty do postaci */
.instruction-name-link { cursor: pointer; }
.instruction-name-kind { margin-left: 6px; color: var(--color-text-muted); cursor: pointer; }
.instruction-name-kind:hover { color: inherit; }
.instruction-name-size { margin-left: 4px; color: var(--color-text-muted); }
/* znacznik w linii z nazwą — globalne `.label` rozciąga się na całą szerokość komórki */
.instruction-name .instruction-name-badge { display: inline-block; flex: 0 0 auto; width: auto; margin-left: 6px; }

/* Pływający kafelek podglądu (floating-preview): róg okna, nad widokiem; rozwinięty zajmuje większość ekranu */
.floating-preview { position: fixed; right: 16px; bottom: 16px; z-index: 1045; width: 480px; max-width: calc(100vw - 32px); height: 420px; max-height: calc(100vh - 80px); display: flex; flex-direction: column; border: 1px solid var(--color-border-strong); border-radius: 6px; background-color: var(--color-bg-app); box-shadow: 0 10px 30px -6px var(--color-shadow); overflow: hidden; }
/* Warstwa kafelka: nad panelem powiadomień (.alert-dropdown-menu, 1044), który stoi w tym samym rogu i zasłaniał
   podgląd, a pod oknem otwartym dopiero z kafelka (OCR, AI — 1050). Kafelek otwarty z okna staje nad nim: okno
   poziomu n ma w ui-bootstrap warstwę 1050 + 10n, a następne otwarte okno — o 10 wyższą (FloatingPreviewService.modalDepth). */
.floating-preview-over-modal-1 { z-index: 1055; }
.floating-preview-over-modal-2 { z-index: 1065; }
.floating-preview-over-modal-3 { z-index: 1075; }
.floating-preview-expanded { width: calc(100vw - 32px); height: calc(100vh - 80px); }
.floating-preview .file-preview { overflow: auto; }
.floating-preview .file-preview-header { padding-right: 130px; }
.floating-preview-toolbar { position: absolute; top: 8px; right: 8px; z-index: 1; display: flex; gap: 4px; }
/* Menu pliku na pasku kafelka ma wysokość jego przycisków (btn-xs), a pozycji „Podgląd pliku” w nim nie ma —
   plik już widać w kafelku. */
.floating-preview-toolbar .unt-dropdown > .dropdown-toggle { padding: 1px 5px; font-size: 12px; line-height: 1.5; }
.floating-preview li.file-preview-item { display: none; }
/* Przełącznik postaci (preview-variant-switch) nad podglądem pliku — kafelek i detale instrukcji */
.preview-variant-switch { padding: 6px 8px; }
.floating-preview .preview-variant-switch { padding-right: 130px; }
/* Podgląd w detalach instrukcji: w sekcji strony, więc wysokość ograniczona, żeby sekcja nie wypychała reszty */
.instruction-details-preview .file-preview-video { max-height: 60vh; }
.instruction-details-preview .file-preview-pdf { max-height: 70vh; overflow: auto; }

/* sekcja boczna detali: treść detali i podgląd pliku obok siebie */
.details-main { display: flex; min-height: 0; overflow: hidden; }
.details-main .details-content { min-width: 0; }
.details-file-preview { display: flex; flex: 0 0 45%; min-width: 0; border-left: 1px solid var(--color-border-strong); box-shadow: -10px 0 24px -6px var(--color-shadow); background-color: var(--color-bg-app); z-index: 10; }

/* Mobile: podgląd pliku w detalach przykrywa treść na całą szerokość — jak sekcja boczna
   list, która poniżej progu lg zastępuje listę (list-layout). Zamknięcie podglądu
   zdejmuje details-preview-mode i treść detali wraca. */
@media ( max-width : 991px) {
	.details-main .details-preview-mode {
		display: none;
	}

	.details-file-preview {
		flex: 1 1 100%;
		border-left: none;
	}
}

/* =====================================================================
   Komponent <field> (js/app/component/field) — wkladki trybow.
   FixedPositionService pozycjonuje menu wzgledem element.parent(), czyli
   gospodarza wspolnego szkieletu <field-menu> — ten musi byc realnym,
   pustym boxem (a nie display:contents), bo element bez boxa ma offset
   {0,0} i menu ladowaloby w lewym gornym rogu ekranu. Gospodarze wkladek
   pozostaja pustymi blokami, zeby kotwica stala w miejscu dna .form-box,
   czyli tam, gdzie kotwiczylo sie menu monolitycznej dyrektywy field.
   ===================================================================== */
field field-text,
field field-number,
field field-date,
field field-boolean,
field field-enum,
field field-entity,
field field-secret,
field field-details,
field field-enum-collection,
field-menu {
	display: block;
}

/* Wrapper transkluzji szkieletu menu jest przezroczysty dla layoutu —
   <li> wkladki leza w <ul> tak, jakby staly w nim bezposrednio. */
.field-insert-menu > ng-transclude {
	display: contents;
}

/* Kolekcja encji nie ma wlasnego menu do zakotwiczenia (dropdowny chipow
   kotwicza sie w chipach) — tu gospodarz zostaje przezroczysty dla layoutu. */
field field-entity-collection {
	display: contents;
}

/* Wspolne fragmenty menu wkladek (naglowek, koncowka akcji) i wspolna lista
   opcji — gospodarz bez wlasnego boxa: <li>/<ul class="options"> leza
   w layoutcie tak, jakby staly w szablonie wkladki bezposrednio. Selektory
   ich zawartosci musza byc descendant, nie dziecko (por. li.field-action).
   field-interactive grupuje host edytora i oba menu wylacznie po to, by
   kompilowaly sie leniwie — dla layoutu ma byc niewidoczny tak samo. */
field-interactive,
field-menu-actions,
field-options {
	display: contents;
}

/* Menu wkladki nie jest bezposrednim dzieckiem .form-box, wiec bootstrapowe
   .open > .dropdown-menu go nie pokaze — pokazujemy je po wlasnej klasie. */
.form-box.dropdown.open .field-insert-menu {
	display: block;
}

/* ---------- Modal tworzenia transportu ---------- */
.freight-modal-create .freight-modal-basic-data {
	padding: 6px 8px;
	margin-bottom: 8px;
}

.freight-modal-points-header {
	align-items: center;
	justify-content: space-between;
	margin-bottom: 6px;
}

.freight-modal-points-header h4 {
	margin: 0;
}

.freight-modal-point {
	border: 1px solid var(--color-border);
	border-radius: 4px;
	padding: 6px 8px;
	margin-bottom: 6px;
}

.freight-modal-point.active {
	border-color: var(--color-border-strong);
	box-shadow: var(--shadow-thead);
}

.freight-modal-point-header {
	display: flex;
	align-items: center;
	gap: 6px;
	margin-bottom: 6px;
}

.freight-modal-point-header .freight-modal-point-no {
	font-weight: bold;
	min-width: 1.6em;
}

/* Strzałki stoją tu w jednej linii z pozostałymi kontrolkami nagłówka — miejsce na obie trzyma
   sam komponent (ukryta strzałka skrajnego punktu, patrz .seq-button-hidden), więc zostaje
   zdjęcie własnego marginesu pary. */
.freight-modal-point-header .seq-buttons {
	margin: 0;
}

.freight-modal-point-header .freight-modal-point-action {
	width: 140px;
}

.freight-modal-point-header .freight-modal-point-remove {
	margin-left: auto;
}

.freight-modal-point-fields {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 4px 8px;
}

/* Podjazd od poprzedniego zlecenia ciągnika: przełącznik i ostatni punkt poprzedniego zlecenia. */
.freight-modal-approach {
	padding: 6px 8px;
	margin-bottom: 8px;
}

.freight-modal-approach-toggle {
	display: flex;
	align-items: center;
	gap: 6px;
	margin: 0;
	font-weight: bold;
}

.freight-modal-approach-details {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 4px 12px;
	margin: 4px 0;
}

.freight-modal-approach-previous {
	width: auto;
	max-width: 100%;
}

/* Numer 0 punktu podjazdu — w kolorze jego pinezki na mapie, żeby punkt dało się połączyć z mapą
   bez czytania nagłówka. */
.freight-approach-point-no {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 1.6em;
	height: 1.6em;
	border-radius: 50%;
	background-color: var(--color-approach);
	color: var(--color-on-accent);
}

/* Strzałki kolejności obok elementu sekwencji — zwarta para przycisków. */
.seq-buttons {
	display: inline-flex;
	gap: 2px;
	margin: 0 4px;
	vertical-align: middle;
}

/* Skrajny element sekwencji nie ma dokąd pójść w jedną stronę, ale jego strzałka zostaje
   na swoim miejscu — niewidoczna. Usuwanie jej z drzewa zwężało parę do jednego przycisku,
   więc w liście wielu punktów trasy strzałki sąsiednich wierszy stały w różnych kolumnach,
   a kontrolki za nimi skakały w poziomie z wiersza na wiersz. */
.seq-button-hidden {
	visibility: hidden;
}

/* Odcinek pusty / ładowny w nagłówku punktu — sam tekst, bez kolorowej pigułki. */
.freight-stop-leg {
	font-size: 0.9em;
	margin: 0 6px;
}

.freight-form-clone-options label {
	font-weight: normal;
	margin: 0;
}

/* Kwoty i warunki płatności klienta / przewoźnika — zwarta siatka w sekcji danych. */
/* Przełączniki nadzoru, zaliczenia i zwinięcia stoją w nagłówku punktu obok jego numeru. */
.content-stop .flex > freight-stop-collapse-button,
.content-stop .flex > freight-stop-supervised-button,
.content-stop .flex > route-point-visited-button {
	margin-right: 6px;
}

/* Raporty z trasy stoją w karcie przystanku nad jego nagłówkiem — odstęp oddziela je od numeru punktu. */
.content-stop > .freight-stop-route-reports {
	margin-bottom: 8px;
}

/* Wyspa punktu w karcie przystanku: nagłówek, dojazd i miejsce leżą w niej wprost, a nie w sekcji z własnym
   odstępem. Zielone tło bieżącego punktu (.current-route) stoi w arkuszu za .highlighted-section, więc wygrywa. */
.content-stop > .freight-stop-point {
	padding: 4px 8px;
}

/* Dane punktu mają tło topbaru detali (.content-box-details-topbar, .sticky-freight-overview) — czyta się je jak
   dane nagłówkowe przewozu. Bieżący punkt zostaje zielony. Dojazd do punktu (dystans, ETA, zapas czasu) zostaje
   na dotychczasowym tle wyspy, a gdy grozi albo nie grozi spóźnienie — na swoim czerwonym lub zielonym. */
.content-stop > .freight-stop-point:not(.current-route) {
	background-color: var(--color-border);
}

.content-stop > .freight-stop-point:not(.current-route) .freight-stop-eta:not(.light-salmon-pink):not(.light-mint-green) {
	background-color: var(--color-surface-highlight);
}

/* Ładunki, pliki i raport punktu pod danymi przystanku — to samo tło co raporty z trasy, każda sekcja osobnym
   blokiem, odsuniętym od poprzedniego tak samo jak raporty z trasy od nagłówka. */
.content-stop .freight-stop-section {
	margin-top: 8px;
}

/* Podgląd pliku EDI w modalu importu: komunikaty oddzielone linią, tabela ładunków zwarta. */
.edi-import-preview .edi-import-message {
	padding: 8px 0;
	border-top: 1px solid #ddd;
}
.edi-import-preview .edi-import-loads {
	margin-top: 6px;
	margin-bottom: 0;
}

/* Paczka plików EDI: karty jedna pod drugą, kreska rozdziela zawartość dwóch plików
   mocniej niż kreska między komunikatami jednego pliku. */
edi-import-preview {
	display: block;
}

edi-import-preview + edi-import-preview {
	margin-top: 12px;
	padding-top: 8px;
	border-top: 2px solid #bbb;
}

/* W nagłówku karty stoi nazwa pliku, liczba komunikatów i usunięcie pliku z paczki
   dociśnięte do prawej krawędzi — stąd flex, a nie sam tytuł. */
.edi-import-preview > h4 {
	display: flex;
	align-items: center;
	gap: 6px;
	margin-top: 0;
	word-break: break-all;
}

.edi-import-preview > h4 > a {
	margin-left: auto;
	flex: none;
}

/* Numer strony poza zakresem nie jedzie do serwera — bez tego podświetlenia odrzucenie byłoby nieme:
   pole zostaje z wpisaną wartością, a lista stoi w miejscu i użytkownik nie wie dlaczego. Zakres
   podaje min/max pola, więc klasę zapala sam Angular. */
.paginator-row input[type="number"].ng-invalid {
	border: 1px solid var(--color-danger-alt);
}

/* Komórka numerów transportów na liście dokumentów handlowych: numer, rejestracja pojazdu i przejście
   do zamówienia stoją w jednej linii, bo wierszy bywa kilka — jeden transport pod drugim. */
.financial-document-freight { display: flex; align-items: center; gap: 6px; flex-wrap: nowrap; }
.financial-document-freight__registration { color: var(--color-text-secondary); white-space: nowrap; }

/* Okno AI przy pliku: miniatury stron z obrotem do zatwierdzenia. Obrót pokazuje transformacja
   obrazka, bo plik obraca dopiero zapis; `image-orientation: none`, żeby przeglądarka nie prostowała
   zdjęcia po EXIF — serwer obraca piksele, więc miniatura musi pokazywać te same piksele. */
.entity-file-ai-rotation-toolbar { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; margin: 12px 0 6px; }
.entity-file-ai-pages { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 8px; }
.entity-file-ai-page { width: 150px; padding: 6px; border: 1px solid var(--color-border); border-radius: 4px; text-align: center; }
.entity-file-ai-page--changed { border-color: var(--color-accent); }
.entity-file-ai-page__preview { height: 150px; display: flex; align-items: center; justify-content: center; overflow: hidden; }
.entity-file-ai-page__preview img { max-width: 130px; max-height: 130px; image-orientation: none; transition: transform 0.2s ease; }
.entity-file-ai-page__controls { display: flex; align-items: center; justify-content: space-between; margin-top: 6px; }
.entity-file-ai-rotate-90 { transform: rotate(90deg); }
.entity-file-ai-rotate-180 { transform: rotate(180deg); }
.entity-file-ai-rotate-270 { transform: rotate(270deg); }

/* Awizacja pojazdu (vehicle-notification-modal). Lista pól idzie za motywem; podgląd jest „kartką" wiadomości,
   do której trafi awizacja — jasne tło i ciemny tekst w obu motywach, bo kopia HTML zabiera wygląd podglądu
   (copy-rendered-content) i ciemne kolory wkleiłyby się do maila. */
.vehicle-notification-fields { display: flex; flex-direction: column; gap: 4px; }
.vehicle-notification-field { display: flex; align-items: center; justify-content: space-between; padding: 3px 8px; border: 1px solid var(--color-border); border-radius: 4px; background: var(--color-surface); color: var(--color-text-primary); }
.vehicle-notification-field label { display: flex; align-items: center; gap: 6px; margin: 0; font-weight: normal; }
.vehicle-notification-field-order { white-space: nowrap; }
.vehicle-notification-preview { padding: 12px; border: 1px solid var(--color-border); border-radius: 4px; background: #ffffff; color: #000000; }
.vehicle-notification-table { width: auto; border-collapse: collapse; font-family: Arial, sans-serif; font-size: 13px; color: #000000; background: #ffffff; }
.vehicle-notification-table th,
.vehicle-notification-table td { border: 1px solid #b0b0b0; padding: 4px 10px; text-align: left; vertical-align: top; }
.vehicle-notification-table th { background: #eeeeee; font-weight: bold; white-space: nowrap; }
.vehicle-notification-buttons { margin-top: 12px; }

/* Wiersz pliku (entity-file-compact-item): przyciski nagłówka w jednej linii.
   W wąskiej kolumnie listy (np. transakcje w zamówieniu) tytuł z nazwą pliku nie oddawał miejsca,
   a przyciski — zwykłe inline-block w ng-transclude — łamały się na dwa wiersze (od 10742 jest ich pięć).
   Przyciski nie zawijają się i nie kurczą; nazwa pliku skraca się wielokropkiem. */
entity-file-compact-item .content-box-header > .flex > .field-horizontal {
	min-width: 0;
	overflow: hidden;
}
/* Kontener tytułu (transkluzja header-pre) jest elementem flex z domyślnym min-width:auto,
   więc bez tej reguły nie oddaje miejsca i nazwa jest ucinana bez wielokropka. */
entity-file-compact-item .content-box-header > .flex > .field-horizontal > .collapsible-no-toggle {
	flex: 1 1 auto;
	min-width: 0;
	overflow: hidden;
}
entity-file-compact-item .content-box-header > .flex > .inline.text-right {
	flex-shrink: 0;
}
entity-file-compact-item .content-box-header ng-transclude.collapsible-no-toggle {
	display: inline-flex;
	align-items: center;
	flex-wrap: nowrap;
	white-space: nowrap;
}
entity-file-compact-item header-pre .form-box.field-name-filename .form-value {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	display: block;
}
/* ─── MODUŁ ANALIZY (zadanie 10707) ───────────────────────────────────────────
   Reguły modułu Centrum analityczne. Dopisane na końcu arkusza, bo powstały na
   gałęzi rozwijanej równolegle z developem; własnych nazw klas z niczym nie dzielą.
   Konfigurator listy celowo pominięty — develop rozwiązał go własnymi regułami
   `.cl-configurator .modal-content > …`, które są dokładniejsze od naszych. */
/* Kolumna liczbowa: naglowek i dane do prawej. Jedna regula na obie strony, zeby podpis
   nie stal w innym miejscu niz liczba pod nim — wyrownanie kolumny jest cecha kolumny,
   a nie osobno naglowka i osobno komorki. */
.custom-list th.cl-num, .custom-list td.cl-num { text-align: right; }
.custom-list td.cl-num .form-value { justify-content: flex-end; text-align: right; }
.custom-list th.cl-num .cl-th-grip, .custom-list th.cl-num .cl-th-remove { float: left; }
/* Podpis kolumny dziedziczy wyrownanie po swojej kolumnie, zamiast byc zawsze wysrodkowany.
   Regula `th .sort-trigger { text-align: center }` wyzej opisuje kanoniczny naglowek tabeli
   i zostaje dla pozostalych tabel; w liscie wlasnej naglowek ma stac dokladnie tam, gdzie
   dane pod nim — inaczej liczba jest przy prawej krawedzi, a jej nazwa na srodku. */
.custom-list th .sort-trigger,
.custom-list th .sort-text { text-align: inherit; }

/* MODUŁ ANALIZY
   Aplikacja stoi na Bootstrapie 3, który nie zna klas narzędziowych z wersji 4
   (.card, .p-2, .mb-3, .ml-auto). Zamiast wciągać je globalnie, moduł ma tu własny,
   wąski zestaw klas — nazwanych z przedrostkiem, żeby nie kolidowały z niczym innym. */
.analytics-filters { display: flex; align-items: flex-end; gap: 12px; flex-wrap: wrap; margin-bottom: 16px; }
.analytics-filters__field { display: flex; flex-direction: column; gap: 2px; }
.analytics-filters__actions { display: flex; gap: 6px; align-items: flex-end; }
.analytics-filters unt-datetime-picker { display: block; width: 150px; }
.analytics-filters select { width: 160px; }

.analytics-tiles { display: flex; gap: 12px; flex-wrap: wrap; margin-bottom: 16px; }
.analytics-tile { border: 1px solid var(--color-border); border-radius: 4px; padding: 8px 14px; min-width: 130px; }
.analytics-tile__label { display: block; font-size: 11px; color: var(--color-text-muted); }
.analytics-tile__value { display: block; font-size: 18px; font-weight: 600; }
.analytics-tile__delta { font-size: 11px; }

.analytics-chart-box { margin-bottom: 16px; }
.analytics-section-title { font-size: 13px; font-weight: 600; margin: 0 0 8px; }
.analytics-share { width: 120px; }
.analytics-note { font-size: 11px; color: var(--color-text-muted); }

/* Powloka ekranu analizy: naglowek z zakladkami, pasek zakresu, toolbar siatki.
   Aplikacja stoi na Bootstrapie 3, wiec klasy ukladu sa tu wlasne i z przedrostkiem. */
.analytics-header__tabs { margin-left: 16px; }
.analytics-header__tabs .btn.active { background: var(--color-accent); border-color: var(--color-accent); color: var(--color-text-inverse); }
.analytics-header__count { margin-left: auto; color: var(--color-text-muted); font-size: 12px; }

.analytics-range { display: flex; align-items: flex-end; gap: 12px; flex-wrap: wrap; padding: 8px 0 12px; }
.analytics-range__field { display: flex; flex-direction: column; gap: 2px; }
.analytics-range__field > label { font-size: 10px; letter-spacing: .04em; margin: 0; text-transform: uppercase; color: var(--color-text-muted); }
.analytics-range__field unt-datetime-picker { display: block; width: 150px; }
.analytics-range__field select { width: 170px; }
.analytics-range__actions { display: flex; gap: 6px; }
/* Zakres miesiecy to komponent, wiec bez tej reguly jego cztery pola sa JEDNYM dzieckiem
   paska i ukladaja sie pionowo. `display: contents` wypisuje go z drzewa pudelek, wiec pola
   wchodza w rzad paska tak, jakby byly w nim napisane wprost — ta sama sztuczka co przy
   `.analytics-range__slot analytics-filters` nizej. */
.analytics-range analytics-month-range { display: contents; }
/* Sloty filtrow analizy sa tylko pojemnikiem — pola maja stanac w tym samym rzedzie
   co zakres dat, wiec pojemnik nie tworzy wlasnego pudelka. */
/* Sloty filtrow analizy staja w tym samym rzedzie co zakres dat, wiec slot jest wlasnym
   rzedem flex. Transkluzja nazwana zostawia w DOM sam element slotu (<analytics-filters>),
   a ten jest blokiem — bez display:contents wszystkie pola laduja w nim jedno pod drugim. */
.analytics-range__slot { display: flex; align-items: flex-end; gap: 12px; }
.analytics-range__slot analytics-filters { display: contents; }
.analytics-range__slot analytics-filter-select { display: block; }

.analytics-toolbar { display: flex; align-items: center; flex-wrap: wrap; gap: 12px; padding: 6px 0; }
.analytics-toolbar__title { font-weight: 600; }
.analytics-toolbar__actions { margin-left: auto; display: flex; gap: 6px; }

/* Pas kart walutowych nad siatka analizy. Uklad odwzorowuje makiete modulu (wiersz na
   walute w przewijanym oknie, przypiety wiersz zbiorczy pod nim), a kolory bierze z
   palety aplikacji: karta wyglada jak kazde inne pudelko uniter.pro, a barwa niesie
   znaczenie kolumny (VAT, brutto, kwota w walucie podstawowej) tymi samymi odcieniami,
   ktorymi aplikacja oznacza ostrzezenie, sukces i informacje. */
.analytics-summary { margin-bottom: 10px; }
/* Pas walut pokazuje najwyzej CZTERY waluty naraz, reszta schodzi przewijaniem. Firma
   rozliczajaca sie w dziesieciu walutach mialaby inaczej pas na pol ekranu i zepchnelaby
   siatke ponizej krawedzi. Cztery, bo tyle mieści sie nad siatka bez jej chowania, a
   waluty ida od najliczniejszej, wiec te cztery to te, ktorymi firma pracuje najwiecej.
   Wysokosc liczona z wiersza, a nie wpisana na sztywno — zmiana paddingu kafla nie
   rozjedzie sie wtedy z ta regula. */
:root { --analytics-summary-row: 52px; }
.analytics-summary__scroll {
	max-height: calc(4 * (var(--analytics-summary-row) + 6px));
	overflow-y: auto;
	padding-right: 2px;
}
.analytics-summary__row { display: flex; align-items: stretch; gap: 6px; margin-bottom: 6px; }
.analytics-summary__badge {
	align-items: center;
	background: var(--color-sidebar-bg-elevated);
	border-radius: 4px;
	color: var(--color-text-inverse);
	display: flex;
	flex: 0 0 56px;
	font-size: 11px;
	font-weight: 700;
	justify-content: center;
	letter-spacing: .05em;
	text-transform: uppercase;
}
.analytics-summary__badge--total { background: var(--color-accent); }
.analytics-summary__cell {
	background: var(--color-surface);
	border: 1px solid var(--color-border);
	border-radius: 4px;
	flex: 1 1 0;
	min-width: 0;
	padding: 6px 12px;
}
.analytics-summary__cell--highlight { background: var(--color-success-soft-bg); border-color: var(--color-success); }
.analytics-summary__label {
	color: var(--color-text-secondary);
	font-size: 11px;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
.analytics-summary__filters-note { color: var(--color-text-secondary); font-size: 11px; margin-bottom: 4px; }
.analytics-summary__filters-clear { cursor: pointer; margin-left: 6px; }
.analytics-summary__value { color: var(--color-text-primary); font-size: 16px; font-weight: 600; white-space: nowrap; }
.analytics-summary__value--vat { color: var(--color-warning-text); }
.analytics-summary__value--gross { color: var(--color-success-text); }
.analytics-summary__value--primary { color: var(--color-info-text); }
.analytics-summary__value--alert { color: var(--color-danger-text); }
.analytics-summary__value--good { color: var(--color-success-text); }
/* Trendy miesieczne: jedyny ekran modulu bez siatki — tabela porownawcza miesiecy
   i wykres historii, wiec ma wlasne klasy zamiast wspoldzielonych z lista. */
/* Powierzchnie biora sie z tokenow --color-surface*, nie z --color-sidebar-*: sidebar jest
   ciemny w OBU motywach, wiec uzyty jako tlo tabeli dawal ciemna plame z ciemnym tekstem
   w trybie jasnym. Kazdy kolor tutaj ma wyjsc czytelnie w obu motywach. */
.analytics-trend__legend { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; font-size: 11px; max-width: 100%; }
.analytics-trend__legend-item { font-weight: 600; }
.analytics-trend__legend-hint { color: var(--color-text-secondary); }
.analytics-trend__scroll { overflow-x: auto; margin-bottom: 18px; }
/* Ograniczona szerokosc: rozciagnieta na caly ekran tabela odsuwa nazwe miary od jej liczb
   na kilkadziesiat centymetrow i wiersza nie da sie przeczytac jednym spojrzeniem. */
.analytics-trend__table { background: var(--color-surface); max-width: 1100px; min-width: 720px; }
.analytics-trend__table th, .analytics-trend__table td { vertical-align: middle; }
.analytics-trend__table thead th { text-align: right; }
.analytics-trend__table thead th:first-child { width: 190px; }
.analytics-trend__column-month { font-weight: 600; white-space: nowrap; }
.analytics-trend__column-role { font-size: 11px; color: var(--color-text-secondary); font-weight: 400; }
.analytics-trend__metric { text-align: left; white-space: nowrap; }
.analytics-trend__cell { text-align: right; white-space: nowrap; }
.analytics-trend__cell--current { background: var(--color-surface-highlight); }
.analytics-trend__value { font-size: 15px; font-weight: 600; }
.analytics-trend__deltas { display: flex; justify-content: flex-end; gap: 10px; font-size: 11px; }
.analytics-trend__delta small { color: var(--color-text-secondary); font-size: 10px; }
.analytics-trend__delta--up { color: var(--color-success-text); }
.analytics-trend__delta--down { color: var(--color-danger-text); }
.analytics-trend__metrics { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; }
.analytics-chart-view__title { font-weight: 600; margin-bottom: 8px; }

/* Zastrzezenie analizy liczonej przez Uniter, a nie przez urzadzenie (czas pracy kierowcy).
   Tla z tokenow motywu, wiec czytelne w jasnym i ciemnym. */
.analytics-disclaimer { display: flex; gap: 8px; align-items: flex-start; margin: 0 0 10px; padding: 6px 10px; font-size: 12px; background: var(--color-info-soft-bg); color: var(--color-info-text); border: 1px solid var(--color-border); border-radius: 4px; }

/* Jazda dzienna kierowcow (11026): kolory oceny doby z tokenow motywu (jasny i ciemny), a znaczenie niesie tez
   ikona i podpowiedz - sam kolor nie wystarcza. Czerwony = za malo jazdy, przekroczenie to osobny fiolet. */
/* Liczba tuż po kolumnie wyrównanej do prawej (limit dnia) nie może się z nią zlewać (10:006:40). */
.driver-day-after-number { display: inline-block; padding-left: 16px; }
.driver-day-cell { display: inline-flex; align-items: center; gap: 4px; min-width: 2.4em; padding: 1px 8px; border: 1px solid transparent; border-radius: 3px; white-space: nowrap; }
.driver-day-cell--red { background: var(--color-danger-soft-bg); color: var(--color-danger-text); border-color: var(--color-danger-text); }
.driver-day-cell--yellow { background: var(--color-warning-soft-bg); color: var(--color-warning-text); border-color: var(--color-warning-text); }
.driver-day-cell--green { background: var(--color-success-soft-bg); color: var(--color-success-text); border-color: var(--color-success-text); }
.driver-day-cell--exceeded { background: var(--color-purple-soft-bg); color: var(--color-purple); border-color: var(--color-purple); font-weight: 600; }
.driver-day-cell--uncertain { background: transparent; color: var(--color-text-secondary); border: 1px dashed var(--color-text-secondary); }
.driver-day-legend { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 16px; font-size: 12px; color: var(--color-text-secondary); }
.driver-day-legend__item { display: inline-flex; align-items: center; gap: 6px; }
.analytics-driver-day__bar { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: 8px 12px; margin: 0 0 10px; }
.analytics-driver-day__flags { display: flex; flex-direction: column; justify-content: flex-end; gap: 4px; }
.analytics-driver-day__flag { display: flex; align-items: center; gap: 6px; margin: 0; font-weight: normal; }
.analytics-ranking__bar { display: flex; align-items: center; gap: 8px; margin: 16px 0 8px; }

/* Katalog analiz: panele aplikacji (wiec kolory z motywu), ale ulozone w kolumnach,
   a nie w siatce Bootstrapa. Kategorie maja rozna liczbe pozycji, a plywajace kolumny
   o roznej wysokosci zostawiaja dziury i spychaja ostatnia karte kilkaset pikseli
   nizej. Kolumny pakuja karty ciasno, bez wyrownywania do najwyzszej. */
.analytics-catalog { column-count: 4; column-gap: 16px; }
.analytics-catalog .panel { break-inside: avoid; display: inline-block; width: 100%; margin-bottom: 16px; }
@media (max-width: 1400px) { .analytics-catalog { column-count: 3; } }
@media (max-width: 1100px) { .analytics-catalog { column-count: 2; } }
@media (max-width: 767px) { .analytics-catalog { column-count: 1; } }

/* Konfiguracja kosztow analizy „Rentownosc pojazdow": pasek przelacznikow i formularz
   wpisu. Klasy pol (.analytics-range__field) wspoldzielone z paskiem zakresu, zeby
   formularz wygladal jak reszta modulu, a nie jak wstawka. */
.analytics-costs { margin-bottom: 10px; }
/* Panele kosztów i ustawień rentowności to Bootstrapowe .panel-default, którego tło (#fff) i ramka (#ddd)
   są zaszyte w bibliotece i nie znają motywu — w ciemnym wychodził biały prostokąt z jasną ramką.
   Tło i ramka z tokenów motywu, tak jak w pozostałych ekranach analiz. Nagłówek panelu ma już
   własną regułę (.panel-default > .panel-heading). */
.analytics-costs .panel,
.analytics-settings.panel { background-color: var(--color-surface); border-color: var(--color-border); color: var(--color-text-primary); }
.analytics-costs .panel-body,
.analytics-settings .panel-body { background-color: var(--color-surface); }
.analytics-costs__bar { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
.analytics-costs__form { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px; margin-bottom: 12px; }
.analytics-costs__field--grow { flex: 1 1 220px; }

/* Ustawienia rentownosci (11026 K5): sekcje jedna pod druga, kazda z naglowkiem i
   podpowiedzia „co to zmienia"; tabela regul rodzajow kosztow i pas „przed / po" podgladu.
   Tla i obramowania z tokenow powierzchni, zeby ekran wygladal tak samo w obu motywach. */
/* Panel bootstrapowy ma stale biale tlo, wiec w ciemnym motywie naglowki sekcji (dziedziczony jasny tekst)
   znikaly; tlo i tekst panelu biora tokeny motywu, jak pozostale powierzchnie Centrum. */
.analytics-settings { background-color: var(--color-surface); color: var(--color-text-primary); }
.analytics-settings__section { padding: 10px 0; border-top: 1px solid var(--color-border); }
.analytics-settings__section:first-of-type { border-top: 0; }
.analytics-settings__title { font-size: 14px; font-weight: 600; margin: 0 0 8px; color: var(--color-text-primary); }
.analytics-settings__subtitle { font-size: 13px; font-weight: 600; margin: 8px 0 6px; }
.analytics-settings__value { font-weight: 600; margin-bottom: 4px; }
.analytics-settings__rules select.form-control { width: auto; min-width: 160px; }
.analytics-settings__types-list { display: flex; flex-wrap: wrap; gap: 6px 16px; }
.analytics-settings__types-list label { font-weight: normal; margin: 0; }
.analytics-settings__preview { background: var(--color-surface-alt); padding: 10px; border-radius: 4px; }
.analytics-settings__changed td { font-weight: 600; }
.analytics-settings__readonly { color: var(--color-warning-text); }

/* Ranking destynacji: kolor frachtu na kilometr. Progi sa konfigurowalne, wiec kolor
   niesie tu tresc, a nie ozdobe — mowi, czy relacja jest oplacalna, jednym spojrzeniem.
   Kolory z tokenow statusow, wiec czytelne w obu motywach. */
.analytics-destinations__table { min-width: 900px; }
.analytics-rate--green { color: var(--color-success-text); font-weight: 600; }
.analytics-rate--blue { color: var(--color-info-text); font-weight: 600; }
.analytics-rate--orange { color: var(--color-warning-text); font-weight: 600; }
.analytics-rate--red { color: var(--color-danger-text); font-weight: 600; }

/* Kwota kolorowana znakiem (filtr signClass): zysk i marża szacowana, zadanie 11039. Wartość rysuje <field>,
   więc kolor schodzi także na jego wnętrze; tokeny motywu są zdefiniowane w obu motywach. */
.amount-positive, .amount-positive * { color: var(--color-success-text); }
.amount-negative, .amount-negative * { color: var(--color-danger-text); }

/* Dymek nagłówka kolumny listy własnej — wyjaśnia, jak liczy się wartość kolumny. */
.cl-th-hint { margin-left: 4px; color: var(--color-text-muted); cursor: help; }

/* Zakladka wykresu: pasek wyboru (po czym grupowac, ktora miara, jaki typ) nad plotnem. */
.analytics-chart-view__bar { display: flex; align-items: flex-end; gap: 12px; margin-bottom: 12px; }
.analytics-chart-view__canvas { max-width: 1100px; }

/* Zakladka grupowania: wybor wartosci + tabela sum z przypietym wierszem SUMA. */
/* Pasek wyboru zakladki grupowania: po czym grupowac i w ktorej walucie. */
.analytics-group__bar { display: flex; align-items: flex-end; gap: 12px; margin-bottom: 12px; }
/* Kolumn miar jest tyle, ile analiza ich liczy — tabela rośnie z nimi, a nie ma stałej szerokości. */
.analytics-group__table { width: auto; min-width: 640px; }
.analytics-group__total td { border-top: 2px solid var(--color-border-strong); font-weight: 600; }

/* Poziomy suwak tabel analiz (11026, poprawki 6). Kolumn jest tyle, ile włączył użytkownik (nawet 40),
   a tabela miała width:100% bez dolnej granicy szerokości komórek, więc przeglądarka ściskała je do
   najdłuższego słowa zamiast przewijać. Tak jak w innych modułach przewija się sama tabela: komórka ma
   minimalną szerokość, a tabela żyje w przewijaku (overflow:auto), dzięki czemu nagłówek jedzie razem
   z treścią, a kafle i pasek filtrów nad nią stoją w miejscu. Na stronie samodzielnej (.app-content-data)
   przewijak dostaje resztę wysokości po kaflach; w powłoce analytics-view-content przewija już
   .list-block, więc tam przewijak wewnętrzny jest wyłączony (inaczej nagłówek odklejałby się od niego). */
.analytics-aggregate > table > thead > tr > th,
.analytics-aggregate > table > tbody > tr > td { min-width: 110px; }
.app-content-data > analytics-aggregate-table,
.app-content-data > analytics-group-table { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.app-content-data > analytics-group-table > .analytics-group { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
/* Rentowność pojazdów: otwarty panel KD/KDO albo ustawień jest wyższy niż .app-content-data (stała wysokość ekranu),
   więc treść wylewała się poza obszar, a stopka z licznikiem (1-N/N) stojąca tuż pod nim rysowała się na tabeli
   rodzajów kosztów. Przy otwartym panelu przewija się cały obszar, a tabela pod panelem ma naturalną wysokość
   (inaczej min-height:0 ścisnęłoby ją do zera). Zamknięty panel = układ jak dotąd, z przewijaniem samej tabeli. */
.app-content-data:has(> analytics-vehicle-costs .panel) { overflow-y: auto; }
.app-content-data:has(> analytics-vehicle-costs .panel) > analytics-aggregate-table,
.app-content-data:has(> analytics-vehicle-costs .panel) > analytics-group-table { flex: 0 0 auto; }
/* Ta sama dolna granica szerokości na listach analiz z powłoki analytics-view-content (siatka
   custom-list): bez niej wiele włączonych kolumn zwężało się zamiast przewijać. Kolumny checkboxa i
   akcji zostają wąskie, a komórki z colspan (nagłówki grup) nie dostają minimum. */
analytics-view-content .custom-list > table > thead > tr > th:not(.cl-checkbox):not(.cl-actions),
analytics-view-content .custom-list > table > tbody > tr > td:not(.cl-checkbox):not(.cl-actions):not([colspan]) { min-width: 110px; }
.analytics-aggregate, .analytics-group__scroll { flex: 1 1 auto; min-height: 0; overflow: auto; }
.list-block .analytics-aggregate, .list-block .analytics-group__scroll { overflow: visible; }
/* Nagłówki miar: kilka kolumn kwotowych w dwóch walutach daje długie podpisy, które zlewały się
   w jeden pas. Tło z --color-surface-muted (nie z --color-sidebar-*, który jest ciemny w obu motywach),
   oddech w komórce i zawijanie, żeby sąsiednie podpisy nie wchodziły na siebie. */
.analytics-group__table > thead > tr > th { padding: 8px 12px; background: var(--color-surface-muted); vertical-align: bottom; line-height: 1.25; white-space: normal; min-width: 96px; }
.analytics-group__table > tbody > tr > td, .analytics-group__table > tfoot > tr > td { padding: 6px 12px; }

/* Katalog analiz — kafle kategorii na stronie wejsciowej modulu. */

/* Kolumna liczbowa z widgetem trójwalutowym: sama kwota bazowa siada do prawej regułą
   `td.cl-num .form-value`, ale kwoty przeliczone (.field-extension) i ich wspólna obwoluta
   zostawały wyśrodkowane — nagłówek stał po prawej, a dane pod nim po środku. Widget ma
   trzy linie, więc do prawej musi iść cały, nie tylko pierwsza. */
.custom-list td.cl-num .field-no-vertical-space,
.custom-list td.cl-num .field-extension {
	text-align: right;
}

.custom-list td.cl-num .field-no-vertical-space .form-value {
	justify-content: flex-end;
	text-align: right;
}

.message-template-item-name-preview {
	white-space: pre-wrap;
}

/* Zużycie i limity zapytań do płatnych dostawców map (10970) — karta na dostawcę */
.map-usage-summary-list {
	display: flex;
	flex-direction: column;
	gap: 12px;
}

.map-usage-summary {
	border: 1px solid var(--color-border);
	border-radius: 6px;
	background: var(--color-surface);
	padding: 10px 12px;
}

.map-usage-summary-header {
	display: flex;
	align-items: center;
	gap: 8px;
	margin-bottom: 6px;
}

.map-usage-summary-provider {
	font-weight: 600;
	color: var(--color-text-primary);
}

.map-usage-summary-header .label {
	width: auto;
	flex: 0 0 auto;
}

.map-usage-summary-table {
	width: 100%;
	margin-bottom: 6px;
}

.map-usage-summary-table th {
	font-weight: 500;
	color: var(--color-text-secondary);
	white-space: nowrap;
}

.map-usage-summary-limit {
	min-width: 90px;
}

.map-usage-summary-table .text-warning {
	color: var(--color-warning-text);
}

.map-usage-summary-table .text-danger {
	color: var(--color-danger);
}

.map-usage-summary-threshold {
	display: flex;
	align-items: center;
	gap: 8px;
	color: var(--color-text-secondary);
}

.map-usage-summary-threshold field {
	display: block;
	flex: 0 0 90px;
	width: 90px;
}

.map-usage-summary-hint {
	margin: 0;
	color: var(--color-text-muted);
	font-size: var(--font-xs);
}

.map-usage-links {
	display: flex;
	gap: 16px;
}

/* Ikona paliwa przy numerze rejestracyjnym z otwartym alertem planera tankowań (10852) — pulsująca ramka. */
.btn.fuel-alert-active {
	border-color: var(--bs-warning, #f0ad4e);
	box-shadow: 0 0 0 2px rgba(240, 173, 78, 0.5);
	animation: fuel-alert-pulse 1.6s ease-in-out infinite;
}

@keyframes fuel-alert-pulse {
	50% {
		box-shadow: 0 0 0 4px rgba(240, 173, 78, 0.15);
	}
}

/* ===== Cel frachtu zestawu (10966) =====
   Kolory tylko z tokenów, więc pierścień i dymek działają w obu motywach. */
.freight-target {
	--freight-target-color: var(--color-text-muted);
	position: relative;
	display: inline-flex;
	align-items: center;
	gap: 6px;
	cursor: default;
}

.freight-target--ACHIEVED {
	--freight-target-color: var(--color-success);
}

.freight-target--ON_TRACK {
	--freight-target-color: var(--color-success-text);
}

.freight-target--AT_RISK {
	--freight-target-color: var(--color-warning);
}

.freight-target--BEHIND {
	--freight-target-color: var(--color-danger);
}

/* Procent stoi w środku pierścienia, a pierścień jest obrócony, więc napis leży obok svg (nie w nim),
   żeby nie obracać go razem z łukiem. Wielkość dobrana tak, by „112%" mieściło się w wierszu listy. */
.freight-target__ring-box {
	position: relative;
	display: inline-block;
	width: 34px;
	height: 34px;
	flex: none;
}

.freight-target__ring {
	display: block;
	width: 100%;
	height: 100%;
	transform: rotate(-90deg);
}

.freight-target__percent {
	position: absolute;
	inset: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 10px;
	font-weight: 600;
	line-height: 1;
	color: var(--color-text-primary);
}

.freight-target__track,
.freight-target__arc {
	fill: none;
	stroke-width: 4;
}

/* Tor z koloru tekstu przygaszonego, a nie z --color-border: ten w ciemnym motywie niemal znika,
   a okrąg ma być widoczny także przy 0%. */
.freight-target__track {
	stroke: color-mix(in srgb, var(--color-text-muted) 40%, transparent);
}

/* Koniec łuku ucięty (butt): zaokrąglony zamieniał małe wartości w kropkę zamiast fragmentu okręgu. */
.freight-target__arc {
	stroke: var(--freight-target-color);
	stroke-linecap: butt;
}

/* Puchar przy osiągniętym celu: znaczek w rogu pierścienia, na tle powierzchni, żeby był czytelny w obu motywach. */
.freight-target__trophy {
	position: absolute;
	top: -4px;
	right: -6px;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 14px;
	height: 14px;
	border-radius: 50%;
	font-size: 8px;
	line-height: 1;
	background: var(--color-surface);
	color: var(--color-success);
	border: 1px solid var(--color-success);
}

.freight-target__tip {
	position: absolute;
	top: 100%;
	left: 0;
	z-index: 1060;
	min-width: 240px;
	padding: 8px 10px;
	background: var(--color-surface);
	color: var(--color-text-primary);
	border: 1px solid var(--color-border-strong);
	border-radius: 4px;
	box-shadow: var(--shadow-2);
	white-space: normal;
}

.freight-target__status {
	color: var(--freight-target-color);
	margin-bottom: 4px;
}

.freight-target__table td:last-child {
	text-align: right;
	padding-left: 12px;
	white-space: nowrap;
}

.freight-target__freights {
	margin-top: 6px;
	max-height: 120px;
	overflow-y: auto;
}
