/* Runda 6 (porządki w rolach/uprawnieniach) — lekki finetuning: te same
   kolory co dotąd (akcent #0a3ea3 to już "marka" tej apki, patrz przyciski/
   linki poniżej), tylko wyciągnięte do zmiennych zamiast powtarzane
   dziesiątki razy jako gołe hexy. Zastosowane na razie w NOWYCH elementach
   (sidebar, karty) — reszta istniejących komponentów (tabele, przyciski,
   status-badge) zostaje wizualnie identyczna, to porządkowanie pod spodem,
   nie nowy wygląd tego, co już działa dobrze. */
:root {
    --color-accent: #0a3ea3;
    --color-accent-hover: #08306f;
    /* Runda 11: bg a touch cooler/darker than near-white so the white
       cards (surface) actually read as raised. Border a shade deeper to
       match. Conservative — the accent / brand identity is untouched. */
    --color-bg: #eef1f5;
    --color-surface: #ffffff;
    --color-sidebar-bg: #eef1f6;
    --color-sidebar-active-bg: #dce6f7;
    --color-border: #d7dce3;
    --color-text: #1a1a1a;
    --color-text-muted: #555;
    --color-success-bg: #d1e7dd;
    --color-success-text: #0f5132;
    --radius-sm: 6px;
    --radius-md: 10px;
    --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.04), 0 4px 12px -6px rgba(0, 0, 0, 0.12);
}

/* max-width/margin przeniesione do .app-main (patrz sekcja "Boczny panel
   nawigacyjny" niżej) — .mobile-body (mobile.html) i .login-page
   (login.html) mają WŁASNE, w pełni samodzielne reguły wycentrowania i
   działają bez zmian niezależnie od tego, co dzieje się tutaj. */
body {
    font-family: system-ui, -apple-system, sans-serif;
    margin: 0;
    padding: 0;
    color: var(--color-text);
    background-color: var(--color-bg);
    /* Runda 11 (pkt 13): kill the double-tap-to-zoom gesture (and the
       ~300ms tap delay it implies). iOS ignores user-scalable=no in the
       viewport meta, but honours this. */
    touch-action: manipulation;
}

h1 {
    font-size: 1.5rem;
}

/* Wiersz pól filtrów pod nagłówkami kolumn — każde pole ma być wąskie
   i mieścić się w swojej kolumnie, a nie wyglądać jak zwykły nagłówek.
   padding-top: 0 (bez odpowiadającego mu padding-bottom) przyklejało pole
   do górnej krawędzi wiersza, zostawiając całą "poduszkę" pod spodem —
   input wyglądał na przesunięty do góry zamiast wyśrodkowany. Ten sam,
   mały odstęp z obu stron trzyma pole blisko nagłówka nad nim, ale już
   symetrycznie. */
.column-filters th {
    padding-top: 0.4rem;
    padding-bottom: 0.4rem;
    background-color: var(--color-surface);
}

/* Kolumna "Aktywne role" (companies.html) — cztery checkboxy jako labele
   space-joined w JS zawijały się w środku etykiety, gdy zabrakło miejsca
   w komórce (checkbox jednej roli na końcu wiersza, jej tekst na
   początku następnego) — jedna rola na linię jest czytelna niezależnie od
   szerokości kolumny. */
.roles-cell label {
    display: block;
    white-space: nowrap;
}

.column-filters input {
    width: 100%;
    box-sizing: border-box;
    padding: 0.35rem 0.5rem;
    font-size: 0.85rem;
    font-weight: normal;
    border: 1px solid #ccc;
    border-radius: 4px;
}

/* border-collapse: separate + border-spacing: 0 (NOT collapse) — needed for
   border-radius to actually round the table's corners; with collapse, the
   cells' own borders paint over the container's rounded edge and the
   corners come out square regardless. tbody tr:last-child td below drops
   the last row's own bottom border, since the table's border already
   closes it off (collapse:collapse gave up on that; separate needs it
   said explicitly, else the last row prints a double line). */
table {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    margin-top: 1rem;
    background-color: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-card);
    overflow: hidden;
}

th, td {
    text-align: left;
    padding: 0.9rem 1.2rem;
    border-bottom: 1px solid var(--color-border);
}

tbody tr:last-child td {
    border-bottom: none;
}

/* Ta sama tonacja co --color-sidebar-bg — nagłówki tabel dostają ten sam
   odcień co panel boczny, żeby lista i nawigacja czytały się jako jedna,
   spójna całość, zamiast dwóch niezależnie dobranych szarości. */
th {
    background-color: var(--color-sidebar-bg);
    font-weight: 600;
}

/* Kolorowe "znaczniki" statusu — pomagają dyspozytorowi od razu zobaczyć,
   na jakim etapie jest dokument, bez czytania samego słowa. white-space:
   nowrap — bez tego dłuższe etykiety (np. "Podpisany (kierowca)") łamały
   się na dwie linie WEWNĄTRZ pigułki, przez co wyglądała nieproporcjonalnie
   wysoko w porównaniu do jednolinijkowych sąsiadek ("Nowy") — teraz każda
   pigułka jest zawsze jedną linią, szerokość różni się (zależnie od
   długości etykiety), ale wysokość jest zawsze taka sama. */
.status-badge {
    display: inline-block;
    padding: 0.2rem 0.6rem;
    border-radius: 999px;
    font-size: 0.85rem;
    font-weight: 500;
    white-space: nowrap;
}

.status-new {
    background-color: #e0e0e0;
    color: #333;
}

.status-scanned {
    background-color: #fff3cd;
    color: #7a5a00;
}

.status-signed {
    background-color: #cfe2ff;
    color: #0a3ea3;
}

.status-awaiting_consignee_external {
    background-color: #e2d9f3;
    color: #4a2a82;
}

.status-closed {
    background-color: #d1e7dd;
    color: #0f5132;
}

/* Wiersz zastępczy w tbody na czas ładowania / braku wyników / błędu —
   patrz renderMessageRow() w app.js. */
.table-message {
    text-align: center;
    color: #555;
    padding: 1.5rem;
}

/* --- Widok szczegółów dokumentu (document.html) --- */

/* Link nawigacyjny na górze strony — używany zarówno do "powrotu" (widok
   szczegółów -> lista), jak i do przejścia "do przodu" (lista -> historia). */
.nav-link {
    display: inline-block;
    margin-bottom: 0.5rem;
    color: #333;
    text-decoration: none;
}

.nav-link:hover {
    text-decoration: underline;
}

.page-description {
    color: #555;
    margin-top: 0;
}

/* Lista <dt>/<dd> z polami dokumentu — dwie kolumny: etykieta i wartość. */
.document-fields {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: 0.4rem 1rem;
    margin: 1rem 0;
}

.document-fields dt {
    font-weight: 600;
    color: #555;
}

.document-fields dd {
    margin: 0;
}

#action-section, #pdf-section, #flag-section {
    margin: 1.5rem 0;
}

#action-section button, #pdf-section button, #flag-section button {
    padding: 0.6rem 1.2rem;
    font-size: 1rem;
    background-color: #0a3ea3;
    color: white;
    border: none;
    border-radius: 6px;
    cursor: pointer;
}

#action-section button:hover:not(:disabled), #pdf-section button:hover:not(:disabled), #flag-section button:hover:not(:disabled) {
    background-color: #08306f;
}

#action-section button:disabled, #pdf-section button:disabled, #flag-section button:disabled {
    background-color: #999;
    cursor: default;
}

/* doc_flagged marker (Krok 5) — a distinct warning color, since this is
   about a document needing attention, unlike the neutral action buttons. */
#flag-section button {
    background-color: #a33;
}

#flag-section button:hover:not(:disabled) {
    background-color: #822;
}

.flag-indicator {
    color: #a33;
    font-weight: 600;
}

/* Kolumna flagi na liście dokumentów (index.html) — wąska, sama ikona,
   żeby nie rozciągać tabeli tak jak zrobiłaby to pełna kolumna tekstowa. */
#documents-table th:first-child,
#documents-table td:first-child {
    width: 2rem;
    padding-left: 1rem;
    padding-right: 0.4rem;
    text-align: center;
}

.events-list {
    list-style: none;
    padding: 0;
}

.events-list li {
    padding: 0.6rem 0;
    border-bottom: 1px solid #ddd;
}

.events-list-empty {
    color: #555;
}

.event-timestamp {
    color: #777;
    font-size: 0.85rem;
}

/* UUID pod każdym zdarzeniem w historii JEDNEGO dokumentu — ten sam powód
   co .uuid-cell niżej (w Historii zdarzeń): długi, techniczny identyfikator,
   który ma być czytelny, ale nie przyciągać uwagi. */
.event-uuid {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.75rem;
    color: #999;
    margin-bottom: 0.2rem;
}

/* --- Historia zdarzeń (history.html) --- */

/* UUID jest długi i nikt go nie czyta na głos — monospace + stonowany
   kolor + mniejsza czcionka, żeby nie dominował nad resztą wiersza, ale
   dalej dało się go skopiować, gdyby był potrzebny (np. do zgłoszenia). */
.uuid-cell {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.8rem;
    color: #777;
    white-space: nowrap;
}

/* Kolumna "Kto" pokazuje trzy linie naraz (kierowca, pojazd, referencja
   klienta) — mniejsza czcionka i węższe odstępy między liniami sprawiają,
   że mieści się to czytelnie w jednej komórce, zamiast rozciągać wiersz. */
.performed-by-cell {
    font-size: 0.85rem;
    line-height: 1.5;
}

/* --- Logowanie (login.html) --- */

/* Węższy, wyśrodkowany kontener — formularz logowania nie musi (i nie
   powinien) rozciągać się na całą szerokość strony jak tabele z danymi. */
.login-page {
    max-width: 360px;
    margin: 4rem auto;
    padding: 0 1rem;
    box-sizing: border-box;
}

.login-page .language-switcher {
    display: flex;
    justify-content: flex-end;
}

.login-form {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}

/* Runda 8: login.js swaps the field set (#login-fields) for the driver
   variant — display: contents keeps its label/input children as direct
   participants in .login-form's flex column (a plain block wrapper would
   make <label> flow inline again). */
#login-fields {
    display: contents;
}

.login-form label {
    font-size: 0.85rem;
    color: #555;
    margin-top: 0.6rem;
}

/* Runda 11: Bolt-inspired — roomy fields with a soft grey fill instead of a
   thin outline, so the form reads as a stack of tap targets on a phone. */
.login-form input {
    padding: 0.85rem 0.9rem;
    font-size: 1rem;
    background-color: #f2f3f5;
    border: 1px solid transparent;
    border-radius: 10px;
}

.login-form input:focus {
    outline: none;
    background-color: #fff;
    border-color: var(--color-accent, #0a3ea3);
}

/* Runda 11 — driver step 1: country picker + national number on one row. */
.login-phone-row {
    display: flex;
    gap: 0.5rem;
}

.login-phone-row .country-select {
    flex: 0 0 auto;
    padding: 0.85rem 0.6rem;
    font-size: 1rem;
    background-color: #f2f3f5;
    border: 1px solid transparent;
    border-radius: 10px;
}

.login-phone-row input {
    flex: 1 1 auto;
    min-width: 0;
}

/* `> button` — only the form's own submit button. */
.login-form > button {
    margin-top: 1.25rem;
    padding: 0.9rem 1.2rem;
    font-size: 1rem;
    font-weight: 600;
    background-color: #0a3ea3;
    color: white;
    border: none;
    border-radius: 10px;
    cursor: pointer;
}

.login-form > button:hover {
    background-color: #08306f;
}

.error-message {
    margin-top: 1rem;
    padding: 0.6rem 0.8rem;
    background-color: #f8d7da;
    color: #842029;
    border-radius: 6px;
}

/* --- Boczny panel nawigacyjny (Runda 6 — zastępuje dawny poziomy pasek,
   który przestał się mieścić po dojściu "Testowe kody QR"). auth.js:
   renderUserBar buduje treść #user-bar, teraz elementu <nav>, nie <div> —
   patrz każdy z 8 plików back-office'owych: <div class="app-shell">
   <nav id="user-bar" class="sidebar">...<main class="app-main">. --- */

/* align-items: stretch (default) — NOT flex-start: with flex-start the
   sidebar's own min-height: 100vh became its FULL height, so on a page
   taller than one viewport (a long table) the sidebar stopped at 100vh
   while .app-main kept going, leaving a gap at the bottom. Stretch makes
   the sidebar match whichever sibling is taller. */
.app-shell {
    display: flex;
    min-height: 100vh;
}

.sidebar {
    width: 220px;
    flex-shrink: 0;
    box-sizing: border-box;
    min-height: 100vh;
    background-color: var(--color-sidebar-bg);
    border-right: 1px solid var(--color-border);
    padding: 1rem 0.75rem;
    display: flex;
    flex-direction: column;
    transition: width 0.15s ease;
}

/* Stan zwinięty (auth.js: localStorage, per przeglądarka) — panel kurczy
   się do wąskiej szyny z samym przyciskiem rozwijania, treść się chowa
   zamiast np. zamieniać się w pasek samych ikon — apka nie ma dziś
   żadnego zestawu ikon, a chowanie tekstu bez ikon byłoby nieczytelne. */
body.sidebar-collapsed .sidebar {
    width: 44px;
    padding: 1rem 0.5rem;
}

body.sidebar-collapsed .sidebar-links,
body.sidebar-collapsed .sidebar-footer {
    display: none;
}

.sidebar-toggle {
    align-self: flex-end;
    width: 28px;
    height: 28px;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background-color: var(--color-surface);
    cursor: pointer;
    margin-bottom: 0.75rem;
    position: relative;
}

/* Strzałka rysowana samym borderem, bez ikon/obrazków — obraca się o 180°
   w stanie zwiniętym, więc zawsze wskazuje "w tę stronę, w którą panel się
   otworzy", nie trzeba dwóch osobnych glifów. */
.sidebar-toggle::before {
    content: '';
    position: absolute;
    top: 50%;
    left: 55%;
    width: 6px;
    height: 6px;
    border-left: 2px solid var(--color-text-muted);
    border-bottom: 2px solid var(--color-text-muted);
    transform: translate(-50%, -50%) rotate(45deg);
    transition: transform 0.15s ease;
}

body.sidebar-collapsed .sidebar-toggle::before {
    transform: translate(-50%, -50%) rotate(225deg);
}

.sidebar-links {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
}

.sidebar .nav-link {
    display: block;
    padding: 0.55rem 0.7rem;
    border-radius: var(--radius-sm);
    margin-bottom: 0;
    white-space: nowrap;
}

.sidebar .nav-link:hover {
    background-color: var(--color-surface);
    text-decoration: none;
}

/* Aktywna strona — pasek akcentu po lewej zamiast samego podświetlenia
   tła, żeby było widać "gdzie jestem" nawet boczno-kątem oka. */
.sidebar .nav-link-active {
    background-color: var(--color-sidebar-active-bg);
    color: var(--color-accent-hover);
    font-weight: 600;
    box-shadow: inset 3px 0 0 var(--color-accent);
}

.sidebar-footer {
    margin-top: auto;
    padding-top: 1rem;
    border-top: 1px solid var(--color-border);
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.sidebar-footer .user-info {
    color: var(--color-text-muted);
    font-size: 0.85rem;
    line-height: 1.3;
}

/* max-width podniesiony z 1280px — na typowym biurkowym monitorze (1440px+)
   tabele kończyły się daleko przed prawą krawędzią ekranu, zostawiając dużo
   pustego miejsca obok panelu bocznego. 1600px nadal ogranicza długość
   wiersza na bardzo szerokich ekranach, ale wykorzystuje realną szerokość
   typowego okna znacznie lepiej. */
.app-main {
    flex: 1;
    min-width: 0;
    max-width: 1600px;
    margin: 0 auto;
    padding: 2rem 1rem;
    box-sizing: border-box;
}

/* --- Zakładki "Użytkownicy / Kierowcy / Magazynierzy" (Runda 6) —
   users.js/drivers.js/warehouse-keepers.js: renderSubTabs. Te same trzy
   strony co dotąd, tylko spięte wspólnym paskiem, żeby dało się między
   nimi przełączać bez powrotu do panelu bocznego. --- */
.sub-tabs {
    display: flex;
    gap: 0.25rem;
    border-bottom: 1px solid var(--color-border);
    margin-bottom: 1.25rem;
}

.sub-tab-link {
    padding: 0.6rem 1rem;
    color: var(--color-text-muted);
    text-decoration: none;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
}

.sub-tab-link:hover {
    color: var(--color-text);
}

.sub-tab-link-active {
    color: var(--color-accent);
    font-weight: 600;
    border-bottom-color: var(--color-accent);
}

/* --- Przyciski "+ Dodaj..." (Runda 6) — formularz jest teraz domyślnie
   schowany (`hidden`), ten przycisk go pokazuje. Styl "drugorzędny" (obrys,
   nie wypełnienie) — ten sam wzorzec co .mobile-secondary-button, żeby nie
   konkurował wizualnie z głównym przyciskiem submit wewnątrz formularza. --- */
.add-toggle-button {
    display: inline-block;
    margin-top: 1rem;
    padding: 0.55rem 1rem;
    font-size: 0.95rem;
    background-color: var(--color-surface);
    color: var(--color-accent);
    border: 1px solid var(--color-accent);
    border-radius: var(--radius-sm);
    cursor: pointer;
}

.add-toggle-button:hover {
    background-color: #eef3fc;
}

/* --- "Szczegóły" w tabelach i "Wyloguj" w panelu (Runda 7) — oba były
   zwykłymi linkami tekstowymi (.nav-link: bez obrysu, bez tła), przez co
   nie było widać, że to klikalne AKCJE, nie nawigacja do innej strony w
   ramach tej samej hierarchii. Ten sam "drugorzędny" obrys co
   .add-toggle-button powyżej — spójny język wizualny dla każdego przycisku
   w apce, tylko bez jego margin-top (tu button stoi W WIERSZU tabeli /
   W KOLUMNIE stopki panelu, nie nad formularzem). --- */
.table-action-button {
    display: inline-block;
    padding: 0.35rem 0.8rem;
    font-size: 0.85rem;
    background-color: var(--color-surface);
    color: var(--color-accent);
    border: 1px solid var(--color-accent);
    border-radius: var(--radius-sm);
    text-decoration: none;
    white-space: nowrap;
}

.table-action-button:hover {
    background-color: #eef3fc;
    text-decoration: none;
}

.logout-button {
    display: inline-block;
    padding: 0.5rem 0.9rem;
    font-size: 0.9rem;
    text-align: center;
    background-color: var(--color-surface);
    color: var(--color-accent);
    border: 1px solid var(--color-accent);
    border-radius: var(--radius-sm);
    text-decoration: none;
}

.logout-button:hover {
    background-color: #eef3fc;
    text-decoration: none;
}

/* --- Przyciski akcji na company.html (Runda 6): dezaktywuj/aktywuj/usuń
   firmę lub użytkownika. .danger-button (usuń) reużywa dokładnie te same
   kolory co #flag-section button (document.html) — ta sama semantyka
   "nieodwracalne/wymaga uwagi", nie nowy kolor wprowadzony tylko dla tej
   strony. --- */
#company-actions {
    display: flex;
    gap: 0.6rem;
    margin: 1rem 0;
}

#company-actions button,
.user-actions-cell button {
    padding: 0.5rem 0.9rem;
    font-size: 0.9rem;
    border-radius: var(--radius-sm);
    cursor: pointer;
}

#toggle-active-button,
.toggle-user-active-button {
    background-color: var(--color-surface);
    color: var(--color-accent);
    border: 1px solid var(--color-accent);
}

#toggle-active-button:hover,
.toggle-user-active-button:hover {
    background-color: #eef3fc;
}

/* border: 1px solid transparent, NOT none — every other action button next
   to this one (#toggle-active-button, .toggle-user-active-button,
   .add-toggle-button) has a real 1px border, and since none of these
   buttons set an explicit width, that border adds to their intrinsic size.
   A borderless .danger-button ended up 2px shorter/narrower than its
   neighbors — "przycisk usuń jest nierówny". A transparent border keeps
   the same footprint without adding a visible outline. */
.danger-button {
    background-color: #a33;
    color: white;
    border: 1px solid transparent;
}

.danger-button:hover:not(:disabled) {
    background-color: #822;
}

.danger-button:disabled {
    background-color: #ccc;
    color: #777;
    cursor: not-allowed;
}

.user-actions-cell {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    align-items: center;
}

.user-actions-cell .reset-credentials-form {
    flex-basis: 100%;
    margin-top: 0.4rem;
}

/* --- Karty (Runda 6) — sekcje na nowych stronach (profile.html, przyszła
   company.html) dostają lekkie obramowanie/cień zamiast gołego bloku
   tekstu, bez zmiany istniejących komponentów (tabele/status-badge
   zostają, jak były). --- */
.card {
    background-color: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-card);
    padding: 1.25rem 1.5rem;
}

/* .form-message.form-message-success (combined selector, not a lone
   class) — deliberately higher specificity than the plain .form-message
   rule further down (line ~551, color: red), which otherwise wins on
   source order alone since both are single-class selectors of equal
   specificity. Caught by checking getComputedStyle in the browser, not by
   eye — the two colors look close enough at normal text size to miss. */
.form-message.form-message-success {
    color: var(--color-success-text);
}

/* --- Przełącznik języka (i18n.js: renderLanguageSwitcher) ---
   Mały, tekstowy — nie ma konkurować wizualnie z resztą paska. Aktywny
   język jest po prostu wyszarzony/disabled, więc "co jest teraz wybrane"
   widać bez dodatkowego oznaczenia. */
.language-switcher {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    font-size: 0.85rem;
    color: #777;
}

.language-switcher-select {
    padding: 0.15rem 0.4rem;
    font-size: 0.8rem;
    background: white;
    border: 1px solid #ccc;
    border-radius: 4px;
    cursor: pointer;
    color: #333;
}

/* --- Formularz dodawania kierowcy (drivers.html) --- */

/* :not([hidden]) — Runda 6: these forms now start `hidden` (see
   drivers.html/warehouse-keepers.html/users.html/companies.html's
   "+ Dodaj..." toggle) — a plain `.inline-form { display: flex }` would
   outrank the browser's own `[hidden] { display: none }` rule (same class-
   beats-attribute-selector issue already documented on .scan-modal/
   .qr-display in this file, camera_qr round) and show the form anyway
   despite `hidden` being set. Caught the same way that one was: it
   rendered open on page load before any click. */
.inline-form:not([hidden]) {
    display: flex;
    flex-wrap: wrap;
    gap: 0.6rem;
    align-items: center;
    margin-top: 1rem;
}

.inline-form input {
    padding: 0.5rem 0.7rem;
    font-size: 0.95rem;
    border: 1px solid #ccc;
    border-radius: 6px;
}

/* Runda 11: country dial-code picker before the phone field
   (drivers.html / warehouse-keepers.html, filled from countries.js). */
.inline-form .country-select {
    padding: 0.5rem 0.4rem;
    font-size: 0.95rem;
    border: 1px solid #ccc;
    border-radius: 6px;
    background: #fff;
}

.inline-form button {
    padding: 0.55rem 1rem;
    font-size: 0.95rem;
    background-color: #0a3ea3;
    color: white;
    border: none;
    border-radius: 6px;
    cursor: pointer;
}

.inline-form button:hover {
    background-color: #08306f;
}

.form-message {
    margin-top: 0.6rem;
    color: #842029;
}

/* --- Stronicowanie (Runda 7) — pagination.js. Renderowane pod tabelą,
   TYLKO gdy wyników jest więcej niż jedna strona (patrz renderPagination:
   pusty div, gdy wszystko mieści się na jednej) — nie zajmuje miejsca,
   kiedy nie jest potrzebne. --- */
.pagination {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
    margin-top: 1rem;
}

.pagination-page {
    min-width: 2.2rem;
    padding: 0.4rem 0.6rem;
    font-size: 0.9rem;
    text-align: center;
    background-color: var(--color-surface);
    color: var(--color-accent);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    cursor: pointer;
}

.pagination-page:hover {
    background-color: #eef3fc;
}

.pagination-page-active {
    background-color: var(--color-accent);
    color: white;
    border-color: var(--color-accent);
    cursor: default;
}

/* --- Widok mobilny (mobile.html, mobile-document.html) ---
   Węższy niż back-office (telefon, nie biurkowy monitor), większe cele
   dotyku (przyciski, karty), mniej informacji naraz — patrz mobile.js po
   uzasadnienie, dlaczego to osobne strony, a nie "responsywna" wersja
   index.html/document.html. */

.mobile-body {
    max-width: 480px;
    margin: 0 auto;
    /* Runda 8: bottom padding clears the fixed bottom nav (mobile.html).
       mobile-document.html has no bottom nav, so .mobile-body-detail resets it.
       Runda 10: + the iOS home-indicator inset (viewport-fit=cover) so scrolled
       content clears the now-taller nav. */
    padding: 0 0 calc(5.5rem + env(safe-area-inset-bottom));
}

.mobile-body-detail {
    padding-bottom: 2rem;
}

/* Runda 17 — offline strip. In normal flow at the very top of <body>
   (offline-banner.js inserts it there), so no sticky/safe-area juggling
   with .mobile-header. Amber, not red — it's a "heads up", not an error;
   the data on screen is still usable, just possibly stale. */
.offline-banner {
    max-width: 480px;
    margin: 0 auto;
    padding: calc(0.4rem + env(safe-area-inset-top)) 1rem 0.4rem;
    background: #92400e;
    color: #fff;
    font-size: 0.8rem;
    font-weight: 600;
    text-align: center;
    box-sizing: border-box;
}

.mobile-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 0.75rem;
    /* Runda 10: top padding grows by the iOS status-bar / notch inset
       (viewport-fit=cover) — the sticky background fills the strip above the
       notch, the content stays below it. */
    padding: calc(0.9rem + env(safe-area-inset-top)) 1rem 0.9rem;
    border-bottom: 1px solid #ddd;
    margin-bottom: 1rem;
    position: sticky;
    top: 0;
    background-color: #f4f4f4;
    z-index: 5;
}

/* Runda 17: the offline banner already covers the notch inset — don't pad
   for it twice when both are on screen. */
body.offline-banner-visible .mobile-header {
    padding-top: 0.9rem;
}

/* Runda 17: network-only action buttons, dimmed while offline. Still
   tappable — the tap shows a "needs a connection" note (mobile-document.js). */
.offline-disabled {
    opacity: 0.45;
}

.mobile-header .user-info {
    font-weight: 600;
    font-size: 0.95rem;
}

/* Runda 8 — identity block: name over company, plus a driver's vehicle
   plate as a small standalone badge (CONTEXT.md pkt 2). */
.mobile-header-identity {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.mobile-header-name {
    font-weight: 600;
    font-size: 1rem;
}

.mobile-header-company {
    font-size: 0.82rem;
    color: #666;
}

.mobile-vehicle-badge {
    flex-shrink: 0;
    background-color: #fff;
    border: 1px solid #ddd;
    border-radius: var(--radius-sm, 6px);
    padding: 0.3rem 0.6rem;
    font-size: 0.85rem;
    font-weight: 600;
    white-space: nowrap;
}

.mobile-vehicle-badge-label {
    color: #8b8f98;
    font-weight: 500;
}

/* --- Bottom nav (Runda 8) --- */
.mobile-bottom-nav {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    max-width: 480px;
    margin: 0 auto;
    display: flex;
    background-color: #fff;
    border-top: 1px solid #ddd;
    /* Runda 10: raised — items sit above the iOS home indicator with a
       margin, instead of hugging the bottom edge. */
    padding: 0.5rem 0 calc(0.55rem + env(safe-area-inset-bottom));
    z-index: 20;
}

.mobile-nav-item {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.2rem;
    padding: 0.35rem 0;
    background: none;
    border: none;
    font-size: 0.72rem;
    font-family: inherit;
    color: #8b8f98;
    cursor: pointer;
}

.mobile-nav-item.active {
    color: var(--color-accent, #0a3ea3);
    font-weight: 600;
}

.mobile-nav-icon {
    line-height: 1;
}

/* Inline SVG icons (icons.js) — currentColor stroke, sized by context.
   Base: block so there's no inline-baseline gap; each wrapper sets the box. */
.icon {
    display: block;
    width: 100%;
    height: 100%;
}

.mobile-nav-icon {
    width: 22px;
    height: 22px;
}

.mobile-vehicle-badge .icon,
.action-tile-icon {
    display: inline-flex;
}

.action-tile-icon {
    width: 20px;
    height: 20px;
}

/* Two classes (.mobile-action-button.mobile-button-with-icon) — beats the
   plain .mobile-action-button { display: block } that follows later in the
   file, so the flex row (and its gap) actually applies. */
.mobile-action-button.mobile-button-with-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.55rem;
}

.mobile-button-icon {
    width: 20px;
    height: 20px;
    display: inline-flex;
    flex-shrink: 0;
}

.mobile-datetime-icon {
    width: 18px;
    height: 18px;
    color: #8b8f98;
    flex-shrink: 0;
}

.mobile-back-arrow .icon {
    width: 24px;
    height: 24px;
}

.mobile-sheet-close .icon {
    width: 20px;
    height: 20px;
}

.mobile-sheet-option .action-tile-icon {
    width: 22px;
    height: 22px;
}


/* --- Settings tab (Runda 8) --- */
.mobile-settings-card {
    background-color: #fff;
    border: 1px solid #ddd;
    border-radius: 10px;
    padding: 0.5rem 1rem;
}

.mobile-settings-row {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.6rem 0;
    font-size: 0.9rem;
    border-bottom: 1px solid #eee;
}

.mobile-settings-row:last-child {
    border-bottom: none;
}

.mobile-settings-label {
    color: #666;
}

.mobile-settings-value {
    font-weight: 500;
    text-align: right;
}

/* Runda 11 (pkt 15): language row inside the account card — globe icon +
   label on the left, the switcher <select> on the right. */
.mobile-settings-row {
    align-items: center;
}

.mobile-settings-label-icon {
    display: flex;
    align-items: center;
    gap: 0.4rem;
}

.mobile-settings-label-icon .mobile-button-icon {
    width: 16px;
    height: 16px;
}

/* The shared switcher renders its own "Język:" label — redundant here,
   the row already has one. */
#mobile-lang-slot .language-switcher-label {
    display: none;
}

#mobile-lang-slot .language-switcher-select {
    font-family: inherit;
    font-size: 0.9rem;
    padding: 0.2rem 0.3rem;
    border: 1px solid var(--color-border, #d7dce3);
    border-radius: 6px;
    background: var(--color-surface, #fff);
}

/* Runda 11 (pkt 15): logout is a rare action — a small, quiet icon
   button, not a full-width CTA. */
.mobile-logout-button {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    margin-top: 1.25rem;
    padding: 0.5rem 0.9rem;
    background: none;
    border: 1px solid var(--color-border, #d7dce3);
    border-radius: 8px;
    font-family: inherit;
    font-size: 0.85rem;
    color: var(--color-text-muted, #555);
    cursor: pointer;
}

.mobile-logout-button .mobile-button-icon {
    width: 16px;
    height: 16px;
}

.mobile-main {
    padding: 0 1rem;
}

.mobile-main h1 {
    margin-top: 0.5rem;
}

.mobile-message {
    color: #555;
    text-align: center;
    padding: 2rem 0;
}

/* Step 7 waiting screen (Scenario B) — deliberately plain per CONTEXT.md
   ("bez rozbudowanego UI statusów"), just a subtle italic to hint that
   something is quietly happening in the background (the poll in
   mobile-document.js), without a spinner or progress bar. */
.mobile-waiting {
    font-style: italic;
}

.mobile-section-title {
    font-size: 1rem;
    color: #555;
    margin: 1.5rem 0 0.5rem;
}

/* Karta = cały dokument w kilku liniach, cała klikalna (to <a>, nie tylko
   jej treść) — na telefonie łatwiej trafić w duży obszar niż w mały link. */
.mobile-card {
    display: block;
    padding: 1rem;
    margin-bottom: 0.7rem;
    background-color: var(--color-surface, #fff);
    /* Runda 11 (pkt 14): a bit more definition against the cooler bg —
       clearer border + the shared soft card shadow. */
    border: 1px solid var(--color-border, #d7dce3);
    border-radius: 10px;
    box-shadow: var(--shadow-card);
    text-decoration: none;
    color: inherit;
}

/* Runda 11 (pkt 14): the mobile view leaned on one very light grey
   (#8b8f98) for every label — too faint on the cooler background. Darken
   the section/label greys inside the mobile view only (the back office
   keeps its own). */
.mobile-body .mobile-header-company,
.mobile-body .mobile-nav-item:not(.active),
.mobile-body .route-leg-label,
.mobile-body .cargo-card-title,
.mobile-body .cargo-agg-label,
.mobile-body .cargo-line-qty,
.mobile-body .cargo-line-meta,
.mobile-body .mobile-settings-label,
.mobile-body .mobile-vehicle-badge-label {
    color: #5b6472;
}

.mobile-card-top {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 0.4rem;
}

.mobile-card-route {
    font-size: 0.95rem;
}

/* Runda 13: our internal reference under the source-platform reference on
   a document card. */
.mobile-card-ourref {
    font-size: 0.78rem;
    color: #5b6472;
    margin-bottom: 0.35rem;
}

/* Runda 13: archive search box. */
.mobile-search {
    width: 100%;
    box-sizing: border-box;
    margin: 0.25rem 0 1rem;
    padding: 0.7rem 0.9rem;
    font-size: 1rem;
    font-family: inherit;
    background-color: var(--color-surface, #fff);
    border: 1px solid var(--color-border, #d7dce3);
    border-radius: 10px;
}

.mobile-search:focus {
    outline: none;
    border-color: var(--color-accent, #0a3ea3);
}

.mobile-card-meta {
    font-size: 0.85rem;
    color: #777;
    margin-top: 0.3rem;
}

.mobile-summary-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin: 1rem 0;
}

.mobile-route {
    display: flex;
    flex-direction: column;
    gap: 0.8rem;
    background-color: white;
    border: 1px solid #ddd;
    border-radius: 10px;
    padding: 1rem;
}

.mobile-route-point .mobile-route-label {
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: #777;
}

.mobile-route-point .mobile-route-address {
    color: #555;
    font-size: 0.9rem;
}

.mobile-route-point .mobile-route-date {
    font-size: 0.85rem;
    color: #0a3ea3;
    margin-top: 0.1rem;
}

.mobile-cargo {
    margin-top: 0.8rem;
    font-size: 0.9rem;
    color: #333;
}

.mobile-ref {
    margin-top: 0.3rem;
    font-size: 0.85rem;
    color: #777;
}

/* Duży, kciukiem-przyjazny przycisk akcji — na całą szerokość, wysoki. */
.mobile-action-button {
    display: block;
    width: 100%;
    margin-top: 1.5rem;
    padding: 1rem;
    font-size: 1.05rem;
    font-weight: 600;
    background-color: #0a3ea3;
    color: white;
    border: none;
    border-radius: 10px;
    cursor: pointer;
}

.mobile-action-button:hover:not(:disabled) {
    background-color: #08306f;
}

.mobile-action-button:disabled {
    background-color: #999;
}

/* Krok 8 — przycisk skanowania na liście "Moje dokumenty", zawsze widoczny
   nad sekcjami statusów. Współdzieli wygląd z .mobile-action-button, ale
   bez jego górnego marginesu (tu stoi zaraz pod nagłówkiem, nie pod kartą). */
#scan-action {
    margin-bottom: 1.5rem;
}

#scan-action .mobile-action-button {
    margin-top: 0;
}

.mobile-card-route-line {
    font-size: 0.85rem;
    color: #555;
    margin-top: 0.15rem;
}

/* camera_qr round: full-screen camera modal (mobile.js) — fixed overlay,
   not an in-flow section, since it has to sit above the whole page
   (including the header) while the camera is active.
   :not([hidden]) — NOT just `.scan-modal { display: flex }`: a plain class
   selector setting `display` outranks the browser's own `[hidden]{display:
   none}` UA rule (both are single selectors, but the UA stylesheet is
   always lower priority than the page's own CSS), so the modal would stay
   visible even while the `hidden` attribute is set. Conditioning the
   selector on :not([hidden]) means our rule simply doesn't match at all
   while hidden, letting the UA rule apply instead — caught during manual
   testing (the modal rendered open on page load, before any click). Same
   fix applied to .scan-manual-entry below, which has the same shape. */
.scan-modal:not([hidden]) {
    position: fixed;
    inset: 0;
    background-color: rgba(0, 0, 0, 0.85);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 100;
    padding: 1rem;
}

.scan-modal-content {
    width: 100%;
    max-width: 420px;
    display: flex;
    flex-direction: column;
    gap: 0.8rem;
}

/* Positioning context for the viewfinder overlay below — the overlay is
   absolutely positioned against THIS box, not the video itself, so it
   stays correctly sized/centered regardless of the video's own intrinsic
   aspect ratio. */
.scan-video-wrapper {
    position: relative;
    line-height: 0; /* avoids a few stray px of inline-element gap under the video */
}

.scan-video {
    width: 100%;
    border-radius: 10px;
    background-color: #000;
}

/* Feedback (2026-08-25): the scanning area was the ENTIRE camera frame —
   easy to accidentally scan the wrong QR code when more than one is
   visible in shot (e.g. a phone screen with several codes listed). The
   bracketed square below is not just decoration: mobile.js crops the
   actual jsQR decode to this exact region (VIEWFINDER_FRACTION,
   in sync with the 65% width here), so a code outside the brackets
   genuinely can't be picked up by accident. Centered square via
   aspect-ratio: 1 — width alone is enough to size a square in both CSS
   and mobile.js's crop math (see that file's comment on why the video's
   uniform CSS scaling makes this correspondence exact). box-shadow with
   an oversized spread is the standard trick for a "spotlight" mask: the
   frame casts a huge shadow everywhere BUT its own box, dimming the rest
   of the video without needing a separate mask element. */
.scan-viewfinder {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 65%;
    aspect-ratio: 1;
    transform: translate(-50%, -50%);
    box-shadow: 0 0 0 999px rgba(0, 0, 0, 0.55);
    border-radius: 12px;
    pointer-events: none;
}

.scan-viewfinder-corner {
    position: absolute;
    width: 28px;
    height: 28px;
    border: 3px solid #ffffff;
}

.scan-viewfinder-corner-tl {
    top: -2px;
    left: -2px;
    border-right: none;
    border-bottom: none;
    border-top-left-radius: 10px;
}

.scan-viewfinder-corner-tr {
    top: -2px;
    right: -2px;
    border-left: none;
    border-bottom: none;
    border-top-right-radius: 10px;
}

.scan-viewfinder-corner-bl {
    bottom: -2px;
    left: -2px;
    border-right: none;
    border-top: none;
    border-bottom-left-radius: 10px;
}

.scan-viewfinder-corner-br {
    bottom: -2px;
    right: -2px;
    border-left: none;
    border-top: none;
    border-bottom-right-radius: 10px;
}

/* Scanning-line animation — purely cosmetic, signals "actively looking"
   the same way the reference mockup's red sweep did. Bounces top<->bottom
   INSIDE the viewfinder box only (0 to 100% of its own height), not the
   whole video, so it visually confirms the same bounded area the crop
   math actually reads from. */
.scan-viewfinder-line {
    position: absolute;
    left: 6%;
    right: 6%;
    height: 2px;
    background: linear-gradient(90deg, transparent, #ff4d4d, transparent);
    box-shadow: 0 0 6px 1px rgba(255, 77, 77, 0.8);
    animation: scan-line-sweep 2.2s ease-in-out infinite;
}

@keyframes scan-line-sweep {
    0% {
        top: 4%;
    }
    50% {
        top: 94%;
    }
    100% {
        top: 4%;
    }
}

.scan-status {
    color: white;
    text-align: center;
    min-height: 1.2em;
    margin: 0;
}

.scan-cancel-button {
    background-color: #555;
}

.scan-cancel-button:hover {
    background-color: #333;
}

/* Generated QR display (mobile-document.js: "Pokaż QR do odbioru" and the
   road-inspection button; test-qr-codes.js's table) — QRCode (vendor/
   qrcode.js) renders its own canvas/table inside this element, this class
   just centers and frames whatever it produces. :not([hidden]) — same
   `hidden`-vs-class-display fix as .scan-modal above; #road-inspection-qr
   toggles the `hidden` attribute on this exact class. */
.qr-display:not([hidden]) {
    display: flex;
    justify-content: center;
    padding: 1rem;
    background-color: white;
    border: 1px solid #ddd;
    border-radius: 10px;
    margin-top: 1rem;
}

.qr-display-compact {
    padding: 0.3rem;
    margin-top: 0;
    display: inline-flex;
}

#road-inspection-section {
    margin-top: 1rem;
}

.mobile-secondary-button {
    background-color: white;
    color: #0a3ea3;
    border: 1px solid #0a3ea3;
}

.mobile-secondary-button:hover:not(:disabled) {
    background-color: #eef3fc;
}

/* ============================================================
   Runda 8 — przebudowany widok szczegółu dokumentu (mobile-document)
   ============================================================ */

.mobile-doc-header {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: center;
    gap: 0.5rem 0.75rem;
    margin: 0.5rem 0 1rem;
}

/* Runda 13: reference block — source-platform transport reference on top
   (context, not a headline), our internal reference + platform name muted
   below it. */
.mobile-doc-ref {
    min-width: 0;
}

.mobile-doc-ref-value {
    font-size: 1.05rem;
    font-weight: 600;
    margin: 0;
}

.mobile-doc-ref-meta {
    font-size: 0.78rem;
    color: #5b6472;
    margin: 0.15rem 0 0;
}

/* Karta "Załadunek / Rozładunek" — obie sekcje w jednej karcie, rozdzielone
   linią (CONTEXT.md pkt 4b). */
.route-card {
    padding: 0;
    overflow: hidden;
}

.route-leg {
    padding: 0.9rem 1rem;
}

.route-leg-divider {
    border-top: 1px solid #eee;
}

.route-leg-label {
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: #8b8f98;
    margin: 0 0 0.2rem;
}

.route-leg-name {
    font-size: 0.95rem;
    font-weight: 600;
    margin: 0;
}

.route-leg-sub {
    font-size: 0.85rem;
    color: #666;
    margin: 0.1rem 0 0;
}

.route-leg-date {
    font-size: 0.82rem;
    color: var(--color-accent, #0a3ea3);
    margin: 0.2rem 0 0;
}

/* Karta "Szczegóły ładunku" — <details>: nagłówek = summary, agregacja
   zawsze widoczna, lista pozycji rozwijana (CONTEXT.md pkt 6). */
.cargo-card {
    padding: 0;
}

.cargo-summary {
    display: block;
    padding: 0;
    cursor: pointer;
    list-style: none;
}

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

/* Runda 11 (pkt 7): summary = title row + always-visible aggregate grid. */
.cargo-summary-head {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.9rem 1rem 0.5rem;
}

.cargo-summary-chevron {
    margin-left: 0.25rem;
    color: #8b8f98;
    transition: transform 0.15s ease;
}

.cargo-card[open] .cargo-summary-chevron {
    transform: rotate(180deg);
}

.cargo-card-title {
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: #8b8f98;
}

.cargo-card-count {
    font-size: 0.8rem;
    color: #666;
    margin-left: auto;
    margin-right: 0.5rem;
}

.cargo-aggregate {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    padding: 0 1rem 0.9rem;
}

.cargo-agg-item {
    text-align: center;
}

.cargo-agg-mid {
    border-left: 1px solid #eee;
    border-right: 1px solid #eee;
}

.cargo-agg-num {
    display: block;
    font-size: 1.05rem;
    font-weight: 700;
}

.cargo-agg-label {
    display: block;
    font-size: 0.7rem;
    color: #8b8f98;
    margin-top: 0.15rem;
}

.cargo-line-list {
    border-top: 1px solid #eee;
    padding: 0.75rem 1rem;
}

.cargo-line {
    border: 1px solid #eee;
    border-radius: 8px;
    padding: 0.6rem 0.7rem;
    margin-bottom: 0.5rem;
}

.cargo-line:last-child {
    margin-bottom: 0;
}

.cargo-line-top {
    display: flex;
    justify-content: space-between;
    font-size: 0.85rem;
    margin-bottom: 0.15rem;
}

.cargo-line-name {
    font-weight: 600;
}

.cargo-line-qty {
    color: #8b8f98;
}

.cargo-line-desc {
    font-size: 0.8rem;
    color: #666;
    margin-bottom: 0.25rem;
}

.cargo-line-meta {
    display: flex;
    gap: 1rem;
    font-size: 0.78rem;
    color: #8b8f98;
}

/* Runda 11 (pkt 11) / Runda 15 — sekcja "Zastrzeżenia dokumentu": osobna
   lista, żeby kierowca nie roluł rosnącej Historii. Renderowana tylko gdy
   jakieś są (mobile-document.js). Runda 15: <details> — domyślnie zwinięta,
   licznik widoczny w summary. */
.objections-card {
    padding: 0;
    border-left: 3px solid #d97706;
    /* Runda 16: nie kleić się do przycisku "Zgłoś zastrzeżenia" wyżej. */
    margin-top: 1.25rem;
}

.objections-summary {
    padding: 0.8rem 1rem;
    cursor: pointer;
    list-style: none;
    display: flex;
    justify-content: space-between;
    align-items: center;
}

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

.objections-summary::after {
    content: '▾';
    color: #8b8f98;
}

.objections-card[open] .objections-summary::after {
    content: '▴';
}

.objections-title {
    margin: 0;
    font-weight: 600;
    color: #b45309;
}

.objections-list {
    list-style: none;
    margin: 0;
    padding: 0 1rem 0.9rem;
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.objection-item + .objection-item {
    border-top: 1px solid var(--color-border, #e0e0e0);
    padding-top: 0.75rem;
}

.objection-note {
    margin-top: 0.25rem;
    font-size: 0.9rem;
}

/* Runda 14/16: grupa miniatur pod jednym wpisem (zastrzeżenie / wiersz
   historii). Jedna linia, zawijana. */
.event-photos {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin-top: 0.4rem;
}

.event-photos .event-photo-thumb {
    margin-top: 0;
    width: 72px;
    height: 72px;
    object-fit: cover;
}

/* Runda 16 — pełnoekranowa Historia zdarzeń (osobny widok). Wiersz:
   ikona + mały tekst + timestamp, potem "kto", notatka, miniatury. */
.history-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.history-entry {
    padding: 0.7rem 0;
    border-bottom: 1px solid var(--color-border, #e0e0e0);
}

.history-entry:last-child {
    border-bottom: none;
}

.history-entry-head {
    display: flex;
    align-items: center;
    gap: 0.4rem;
}

.history-entry-icon {
    display: inline-flex;
    flex-shrink: 0;
    color: #5b6472;
}

.history-entry-icon .icon {
    width: 16px;
    height: 16px;
}

.history-entry-label {
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--color-text, #1a1a1a);
}

.history-entry-head .event-timestamp {
    margin-left: auto;
    white-space: nowrap;
}

/* Runda 11 (pkt 12) — modal QR: pełny ekran, jasne białe tło + duży kod.
   Przeglądarka nie wymusi jasności ekranu — białe tło pełnoekranowe +
   wake lock (mobile-document.js) to maksimum. */
.qr-modal:not([hidden]) {
    position: fixed;
    inset: 0;
    z-index: 1000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1.5rem;
    background: rgba(20, 24, 33, 0.55);
}

.qr-modal-card {
    width: 100%;
    max-width: 340px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
    padding: 1.75rem 1.5rem calc(1.5rem + env(safe-area-inset-bottom));
    background: #ffffff;
    border-radius: 16px;
}

.qr-modal-title {
    margin: 0;
    text-align: center;
    font-size: 0.95rem;
    color: var(--color-text, #1a1a1a);
}

.qr-modal-code {
    display: flex;
    padding: 0.75rem;
    background: #ffffff;
    border: 1px solid var(--color-border, #e0e0e0);
    border-radius: 8px;
}

.qr-modal-code img,
.qr-modal-code canvas {
    display: block;
}

.qr-modal-hint {
    margin: 0;
    text-align: center;
    font-size: 0.8rem;
    color: var(--color-text-muted, #555);
}

.qr-modal-card .mobile-action-button {
    width: 100%;
}

/* Runda 11 (pkt 6) — pusta lista "Bieżące": wyśrodkuj przycisk skanowania
   + komunikat w pionie zamiast zostawiać je u góry nad pustką. */
/* :not([hidden]) — the id+class selector would otherwise outrank the UA
   [hidden] rule and keep the tab visible when another tab is active. */
#tab-current.tab-empty:not([hidden]) {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 1rem;
    min-height: 68vh;
}

/* Sekcja akcji po podpisie — siatka kafelków (CONTEXT.md pkt 5). */
.actions-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.5rem;
    margin-bottom: 0.5rem;
}

.action-tile {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.35rem;
    min-height: 66px;
    padding: 0.6rem;
    background-color: #fff;
    border: 1px solid #ddd;
    border-radius: 10px;
    font-family: inherit;
    font-size: 0.8rem;
    font-weight: 500;
    color: var(--color-text, #1a1a1a);
    cursor: pointer;
}

.action-tile:hover {
    background-color: #f6f8fc;
}

.action-tile-icon {
    font-size: 1.15rem;
    line-height: 1;
}

/* Runda 16: historia to teraz osobny pełnoekranowy widok (patrz
   .history-list / .history-entry wyżej), nie rozwijany akordeon —
   przycisk "Historia (N)" w #document-detail używa .mobile-button-with-icon. */

.event-line {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 0.5rem;
}

.event-who {
    font-size: 0.82rem;
    color: #666;
    margin-top: 0.15rem;
}

.event-note {
    margin-top: 0.3rem;
    padding: 0.4rem 0.6rem;
    background-color: #fff;
    border-left: 3px solid var(--warn-text, #92400e);
    border-radius: 4px;
    font-size: 0.85rem;
    color: #444;
}

.event-photo-thumb {
    display: block;
    margin-top: 0.4rem;
    max-width: 140px;
    max-height: 140px;
    border-radius: 8px;
    border: 1px solid #ddd;
    object-fit: cover;
    cursor: pointer; /* Runda 15: tap to open the lightbox */
}

/* Runda 15 — powiększone zdjęcie (History / Zastrzeżenia). */
.photo-lightbox:not([hidden]) {
    position: fixed;
    inset: 0;
    z-index: 1100;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    background: rgba(0, 0, 0, 0.92);
}

.photo-lightbox-image {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    border-radius: 4px;
}

.photo-lightbox-close {
    position: absolute;
    top: calc(0.6rem + env(safe-area-inset-top));
    right: 0.8rem;
    width: 40px;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    background: rgba(255, 255, 255, 0.16);
    border: none;
    border-radius: 50%;
    color: #fff;
    cursor: pointer;
}

.photo-lightbox-close .icon {
    width: 22px;
    height: 22px;
}

/* Ekrany pełnoekranowe: potwierdzenie podpisu + formularz notatki. */
.mobile-fullscreen {
    padding-bottom: 2rem;
}

.mobile-fullscreen-header {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    margin-bottom: 1.25rem;
}

.mobile-fullscreen-header h1 {
    font-size: 1.1rem;
    margin: 0;
}

.mobile-back-arrow {
    background: none;
    border: none;
    font-size: 1.4rem;
    line-height: 1;
    color: #555;
    cursor: pointer;
    padding: 0.2rem 0.4rem 0.2rem 0;
}

.mobile-field-label {
    display: block;
    font-size: 0.8rem;
    color: #666;
    margin: 0.6rem 0 0.3rem;
}

.mobile-datetime-field {
    position: relative;
    display: flex;
    align-items: center;
    border: 1px solid #ddd;
    border-radius: 10px;
    padding: 0.5rem 0.8rem;
    margin-bottom: 1rem;
    background-color: #fff;
}

.mobile-datetime-field input {
    flex: 1;
    border: none;
    font-size: 1rem;
    font-family: inherit;
    background: transparent;
}

.mobile-datetime-field input:focus {
    outline: none;
}

.mobile-datetime-icon {
    color: #8b8f98;
}

.mobile-textarea {
    width: 100%;
    box-sizing: border-box;
    border: 1px solid #ddd;
    border-radius: 10px;
    padding: 0.7rem 0.8rem;
    font-size: 1rem;
    font-family: inherit;
    resize: vertical;
}

/* Runda 11 (pkt 9) — dwa przyciski wyboru zdjęcia (aparat / plik). */
.note-photo-buttons {
    display: flex;
    gap: 0.5rem;
    margin: 0.4rem 0;
}

.note-photo-buttons .mobile-action-button {
    flex: 1;
    margin: 0;
}

/* Runda 14: grid of photo thumbnails (each with its own remove ×).
   :not([hidden]) — a bare `display: flex` would outrank the UA [hidden]
   rule and show an empty box before any photo is picked. */
.note-photo-previews:not([hidden]) {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin: 0.6rem 0;
}

.note-photo-thumb {
    position: relative;
    width: 84px;
    height: 84px;
}

.note-photo-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: 8px;
    border: 1px solid var(--color-border, #ddd);
}

.note-photo-thumb-remove {
    position: absolute;
    top: -8px;
    right: -8px;
    width: 24px;
    height: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    background: #fff;
    border: 1px solid var(--color-border, #d7dce3);
    border-radius: 50%;
    color: #b45309;
    cursor: pointer;
}

.note-photo-thumb-remove .icon {
    width: 14px;
    height: 14px;
}

/* "Kontrola drogowa" — bottom sheet (CONTEXT.md pkt 10).
   :not([hidden]) — ta sama pułapka co .scan-modal (patrz komentarz wyżej):
   zwykła reguła display: flex miałaby wyższy priorytet niż [hidden]. */
.mobile-sheet:not([hidden]) {
    position: fixed;
    inset: 0;
    z-index: 50;
    display: flex;
    align-items: flex-end;
    justify-content: center;
}

.mobile-sheet-backdrop {
    position: absolute;
    inset: 0;
    background-color: rgba(0, 0, 0, 0.4);
}

.mobile-sheet-panel {
    position: relative;
    width: 100%;
    max-width: 480px;
    background-color: #fff;
    border-radius: 16px 16px 0 0;
    /* Runda 10: bottom padding clears the iOS home indicator (the sheet is
       anchored to the bottom edge). */
    padding: 1rem 1.25rem calc(2rem + env(safe-area-inset-bottom));
}

.mobile-sheet-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 0.5rem;
}

.mobile-sheet-header h2 {
    font-size: 1.05rem;
    margin: 0;
}

.mobile-sheet-close {
    background: none;
    border: none;
    font-size: 1.1rem;
    color: #8b8f98;
    cursor: pointer;
}

.mobile-sheet-option {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    width: 100%;
    min-height: 52px;
    padding: 0 0.9rem;
    margin-top: 0.5rem;
    background-color: #fff;
    border: 1px solid #ddd;
    border-radius: 10px;
    font-family: inherit;
    font-size: 0.95rem;
    font-weight: 500;
    text-align: left;
    color: var(--color-text, #1a1a1a);
    cursor: pointer;
}

.mobile-sheet-option:hover {
    background-color: #f6f8fc;
}

/* ============================================================
   Runda 8/11 — dwuetapowe logowanie kierowcy
   (klawiatura ekranowa i przełącznik roli usunięte w Rundzie 11)
   ============================================================ */

/* Krok "telefon" pokazuje pola numeru, krok "PIN" drugie. Ten przycisk cofa
   do kroku telefonu i pokazuje wpisany numer jako kontekst. */
.login-step-back {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    align-self: flex-start;
    margin-bottom: 0.5rem;
    padding: 0.3rem 0;
    background: none;
    border: none;
    font-family: inherit;
    font-size: 0.9rem;
    color: var(--color-text-muted, #555);
    cursor: pointer;
}

.login-step-back .icon {
    width: 18px;
    height: 18px;
}
