/* bundle.css - generowany automatycznie przez deploy_to_qnap.py (P1-03).
   NIE EDYTOWAC RECZNIE: zmiany znikna przy najblizszym deployu.
   Zrodla i kolejnosc = tablica $gfd_css w index.php. */
:root {
    /* --- Paleta --- */
    --primary-color: #006400;
    /* Baza Głębokiej Zieleni */
    --primary-gradient: linear-gradient(135deg, #006400 0%, #004d00 100%);
    --sidebar-gradient: linear-gradient(160deg, #005c00 0%, #003300 100%);
    /* F4.15 (2026-07-23): stan hover przycisków brandowych — token zamiast
       hardkodowanych #0a7a0a (light) / #22c55e (dark) w dashboard.css */
    --primary-hover: #0a7a0a;
    /* 2026-09-25: kolor tekstu/ikony NA tle --primary-color (przycisk „Log ind” strony startowej).
       Jasny motyw: biały na ciemnej zieleni; ciemny motyw: ciemny na jasnej zieleni (#4ade80). */
    --primary-contrast: #ffffff;

    --secondary-color: #f8f9fa;
    /* Miększe białe/szare tło */
    --surface-color: #ffffff;
    --bg-color: #f5f5f5;

    --text-color: #2c3e50;
    --text-muted: #6c757d;

    --accent-light: #e6ffe6;
    /* Jasnozielony odcień dla stanów aktywnych */
    --accent-border: #c3e6cb;

    /* --- Kolory kart/boxów --- */
    --card-bg: #edf7ed;
    --card-border: #e9ecef;
    --header-bg: #ffffff;
    --input-bg: #ffffff;
    --input-border: #ced4da;

    /* --- Typografia --- */
    --font-main: 'Inter', 'Segoe UI', system-ui, sans-serif;

    /* --- Układ --- */
    --sidebar-width: 260px;
    /* Nieco szerszy dla nowoczesnego odczucia */
    --header-height: 70px;
    /* Bardziej przewiewny */

    /* --- Efekty --- */
    --shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.05);
    /* Miękki cień */
    --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.08);
    /* Cień karty */
    --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.12);
    /* Cień najechania/modalu */

    --radius-sm: 8px;
    --radius-md: 16px;
    /* Nowoczesne zaokrąglone rogi */
    --radius-lg: 24px;

    --transition-fast: 0.2s ease;
    --transition-smooth: 0.3s cubic-bezier(0.4, 0, 0.2, 1);

    /* --- Skala z-index (F4.22, 2026-07-23) — jedna semantyczna drabina zamiast
       licytacji ad hoc (90/100 → 999/1000 → 9999/10000 → 20000 → 100000).
       Wartości zachowują dotychczasową kolejność warstw (bez zmian wizualnych).
       W JS inline stosować z fallbackiem: z-index:var(--z-modal, 9999) — strony
       standalone bywają renderowane bez variables.css. Dark mode nie zmienia z-index. --- */
    --z-raised: 10;            /* lokalne wypiętrzenie (etykiety, przyciski w popupie) */
    --z-sidebar: 90;          /* sidebar desktop */
    --z-header: 100;          /* nagłówek aplikacji */
    --z-overlay: 999;         /* dimmer za szufladą (mobile) */
    --z-drawer: 1000;         /* szuflada mobilna + overlay modali 1000-tier + sticky close */
    --z-modal: 9999;          /* modale bazowe / panel admina */
    --z-modal-raised: 10000;  /* modal nad modalem (popup instalacji, benchmark) */
    --z-modal-detail: 20000;  /* detale silnika (nad listą modali) */
    --z-modal-top: 100000;    /* modale najwyższe (kumulacja globalna, słupek miesiąca) */
    --z-toast: 100001;        /* F5.23: dymki komunikatów — zawsze nad modalami */

    /* --- Tokeny alertów (F4.16, 2026-07-23) — semantyczne kolory kart alarmów;
       używane w popupie alarmów (index.php) i docelowo we wszystkich kartach
       stanów. Dark mode nadpisuje niżej — inline hexy w JS zastąpione var(). --- */
    --alert-error-bg: #fee2e2;
    --alert-error-bg2: #fef2f2;
    --alert-error-border: #dc3545;
    --alert-error-ink: #991b1b;
    --alert-error-ink2: #b91c1c;
    --alert-warn-bg: #fff3cd;
    --alert-warn-border: #ffc107;
    --alert-warn-ink: #92400e;
    --alert-info-bg: #dbeafe;
    --alert-info-border: #3b82f6;
    --alert-info-ink: #1e40af;
    --alert-card-ink: #1f2937;
    --alert-card-ink2: #4b5563;
    /* F5.23: brakujący komplet „sukces" — dotąd zieleń komunikatów była
       hardkodowana (#16a34a w toaście installations.js). */
    --alert-success-bg: #dcfce7;
    --alert-success-border: #16a34a;
    --alert-success-ink: #14532d;
}

/* ============================================
   DARK MODE
   ============================================ */
[data-theme="dark"] {
    /* --- Paleta Dark --- */
    --primary-color: #4ade80;
    --primary-contrast: #06200f;
    --primary-gradient: linear-gradient(135deg, #4ade80 0%, #22c55e 100%);
    --sidebar-gradient: linear-gradient(160deg, #1a2e1a 0%, #0d1a0d 100%);
    /* F4.15: hover przycisków brandowych w dark (jaśniejsza zieleń) */
    --primary-hover: #22c55e;

    --secondary-color: #171717;
    --surface-color: #0d0d0d;
    --bg-color: #0a0a0a;

    --text-color: #f5f5f5;
    --text-muted: #a8a8a8;
    --text-dark: #e0e0e0;

    --accent-light: #1f2e1f;
    --accent-border: #2d4a2d;

    /* --- Kolory kart/boxów Dark --- */
    --card-bg: #1a1a1a;
    --card-border: #2a2a2a;
    --header-bg: #141414;
    --input-bg: #252525;
    --input-border: #3a3a3a;

    /* --- Dodatkowe kolory dla kontrastowych elementów --- */
    --table-header-bg: #222222;
    --table-row-hover: #252525;
    --button-text: #f5f5f5;
    --link-color: #4ade80;

    /* --- Efekty Dark --- */
    --shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.4);
    --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.5);
    --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.6);

    /* --- Tokeny alertów Dark (F4.16) — przyciemnione tła, rozjaśnione tusze;
       kontrast tuszu na tle ≥4.5:1 --- */
    --alert-error-bg: #3b1216;
    --alert-error-bg2: #2a0e11;
    --alert-error-border: #ef4444;
    --alert-error-ink: #fca5a5;
    --alert-error-ink2: #f87171;
    --alert-warn-bg: #3a2e0a;
    --alert-warn-border: #f59e0b;
    --alert-warn-ink: #fcd34d;
    --alert-info-bg: #16233f;
    --alert-info-border: #60a5fa;
    --alert-info-ink: #93c5fd;
    --alert-card-ink: #f3f4f6;
    --alert-card-ink2: #cbd5e1;
    /* F5.23: sukces w dark (tusz #bbf7d0 na tle #0f2e1a = kontrast 9,4:1) */
    --alert-success-bg: #0f2e1a;
    --alert-success-border: #4ade80;
    --alert-success-ink: #bbf7d0;
}

/* F4.11 (2026-07-23): USUNIĘTY blok @media (prefers-color-scheme: dark).
   Definiował DRUGĄ, konkurencyjną paletę dark (--primary #00a000, card #1e1e1e)
   o wyższej specyficzności niż [data-theme="dark"] (#4ade80, #1a1a1a) — user
   z ciemnym OS dostawał inny zielony niż z jasnym. JS w index.php ZAWSZE ustawia
   data-theme przy starcie (localStorage gf_theme albo prefers-color-scheme),
   więc [data-theme="dark"] wyżej jest JEDYNYM źródłem prawdy o palecie dark. *//* Reset i podstawowe style */
* {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

body {
    margin: 0;
    padding: 0;
    font-family: var(--font-main);
    display: flex;
    flex-direction: column;
    height: 100vh;
    background-color: var(--secondary-color);
    color: var(--text-color);
    transition: background-color 0.3s ease, color 0.3s ease;
}

canvas {
    max-width: 100%;
}

/* =============================================
   F4.24 (2026-07-23) — Widoczny focus TYLKO dla klawiatury.
   :focus-visible = nawigacja Tab (obwódka brand); klik myszą jej nie pokazuje.
   Zastępuje rozproszone „outline:none" bez zamiennika (top10.css).
   ============================================= */
:focus-visible {
    outline: 2px solid var(--primary-color);
    outline-offset: 2px;
    border-radius: 2px;
}

:focus:not(:focus-visible) {
    outline: none;
}

/* =============================================
   F4.28 (2026-07-23) — prefers-reduced-motion (globalnie).
   Skraca/wyłącza animacje (tickery 120s, pulsy, flip 3D) i przejścia dla
   użytkowników preferujących brak ruchu. weather_icons.js ma własny wariant.
   ============================================= */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }

    /* Marquee: zatrzymaj w pozycji startowej (widoczny początek) zamiast
       przewinąć treść za krawędź i ją schować */
    .inline-ticker-content,
    .ticker-content {
        animation: none !important;
        transform: none !important;
    }
}

/* =============================================
   GLOBALNE NADPISANIA DLA DARK MODE
   ============================================= */

/* Linki */
a {
    color: var(--primary-color);
    text-decoration: none;
}

a:hover {
    text-decoration: underline;
}

/* Inputy i selecty */
input,
select,
textarea {
    background-color: var(--input-bg);
    color: var(--text-color);
    border: 1px solid var(--input-border);
    border-radius: var(--radius-sm);
    padding: 8px 12px;
}

input::placeholder {
    color: var(--text-muted);
}

/* Buttony */
button {
    color: var(--text-color);
}

/* Nagłówki */
h1,
h2,
h3,
h4,
h5,
h6 {
    color: var(--text-color);
}

/* Tabele */
table {
    color: var(--text-color);
}

th {
    background-color: var(--secondary-color);
    color: var(--text-muted);
}

td {
    border-color: var(--card-border);
}

/* Modals i popupy */
.modal,
.popup,
[class*="modal"],
[class*="popup"] {
    background-color: var(--card-bg);
    color: var(--text-color);
    border-color: var(--card-border);
}

/* F4.21 (2026-07-23): USUNIĘTO martwy duplikat scrollbara — identyczny selektor
   [data-theme="dark"] ::-webkit-scrollbar* jest w dark-mode-overrides.css (ładowany
   PÓŹNIEJ → wygrywał; ten był martwy). Jedno źródło = dark-mode-overrides.css. */

/* Wykresy Chart.js - tekst osi */
[data-theme="dark"] .chart-container,
[data-theme="dark"] .chart-title {
    color: var(--text-color);
}

/* Status Tiles & Badges */
.status-bg-red {
    background-color: #fee2e2;
    color: #991b1b;
}

.status-bg-yellow {
    background-color: #fef3c7;
    color: #92400e;
}

.status-bg-green {
    background-color: #dcfce7;
    color: #166534;
}

[data-theme="dark"] .status-bg-red {
    background-color: #450a0a;
    color: #fca5a5;
    border: 1px solid #7f1d1d;
}

[data-theme="dark"] .status-bg-yellow {
    background-color: #451a03;
    color: #fdba74;
    border: 1px solid #78350f;
}

[data-theme="dark"] .status-bg-green {
    background-color: #052e16;
    color: #86efac;
    border: 1px solid #14532d;
}

/* Dark mode calendar / inputs */
[data-theme="dark"] input[type="date"] {
    color-scheme: dark;
}

/* Loader Animation */
.loader {
    border: 4px solid var(--card-border);
    border-top: 4px solid var(--primary-color);
    border-radius: 50%;
    width: 40px;
    height: 40px;
    animation: spin 1s linear infinite;
    margin: 20px auto;
}

@keyframes spin {
    0% {
        transform: rotate(0deg);
    }

    100% {
        transform: rotate(360deg);
    }
}

/* Brighten icons in dark mode */
[data-theme="dark"] #admin-gear,
[data-theme="dark"] #logout-btn,
[data-theme="dark"] #user-gear {
    filter: invert(1);
}

/* Detail Modal Styles */
.detail-modal-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.75);
    z-index: var(--z-drawer); /* F4.22 (=1000) */
    display: none;
    justify-content: center;
    align-items: center;
    padding: 20px;
    backdrop-filter: blur(4px);
}

.detail-modal-content {
    background: var(--card-bg);
    border: 1px solid var(--card-border);
    border-radius: var(--radius-md);
    width: 100%;
    max-width: 1100px;
    max-height: 90vh;
    overflow-y: auto;
    box-shadow: 0 20px 50px rgba(0, 0, 0, 0.5);
    display: flex;
    flex-direction: column;
}

.detail-modal-header {
    padding: 20px;
    border-bottom: 1px solid var(--card-border);
    display: flex;
    justify-content: space-between;
    align-items: center;
    background: var(--secondary-color);
    position: sticky;
    top: 0;
    z-index: var(--z-raised); /* F4.22 (=10) */
}

.detail-close-btn {
    background: none;
    border: none;
    font-size: 28px;
    color: var(--text-muted);
    cursor: pointer;
    line-height: 1;
}

.detail-close-btn:hover {
    color: var(--text-color);
}

.detail-body {
    padding: 20px;
}

.detail-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    gap: 20px;
}

.detail-card {
    background: var(--input-bg);
    border: 1px solid var(--input-border);
    border-radius: var(--radius-sm);
    padding: 15px;
}

.detail-card h3 {
    margin-bottom: 15px;
    font-size: 14px;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    border-bottom: 1px solid var(--card-border);
    padding-bottom: 8px;
}

.detail-row {
    display: flex;
    justify-content: space-between;
    padding: 6px 0;
    border-bottom: 1px solid rgba(128, 128, 128, 0.1);
    font-size: 13px;
}

.detail-row:last-child {
    border-bottom: none;
}

.detail-label {
    color: var(--text-muted);
}

.detail-value {
    color: var(--text-color);
    font-weight: 500;
    text-align: right;
}

/* Service progress bar */
.service-progress {
    height: 8px;
    background: var(--card-border);
    border-radius: 4px;
    overflow: hidden;
    margin-top: 5px;
}

.service-bar {
    height: 100%;
    background: var(--primary-gradient);
}

/* Clickable sparkline rows */
.sparkline-clickable {
    transition: background-color 0.2s ease;
}

.sparkline-clickable:hover {
    background-color: var(--primary-color);
    background-color: rgba(74, 222, 128, 0.1);
    border-radius: 4px;
}

.sparkline-clickable:active {
    background-color: rgba(74, 222, 128, 0.2);
}/* Układ: Nagłówek, Pasek boczny, Treść główna */

/* --- Nagłówek ---
   Padding poziomy uwzględnia safe-area-inset (iPhone z notchem w landscape),
   żeby header nie chował się pod notchem ani zaokrągleniem ekranu. */
.header {
    background-color: var(--surface-color);
    height: var(--header-height);
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding-top: 0;
    padding-bottom: 0;
    padding-left: max(25px, env(safe-area-inset-left));
    padding-right: max(25px, env(safe-area-inset-right));
    position: relative;
    box-shadow: var(--shadow-sm);
    z-index: var(--z-header); /* F4.22 (=100) */
}

.header-logo {
    display: flex;
    align-items: center;
}

.header-logo img {
    height: 48px;
    object-fit: contain;
}

/* Hover tylko na urządzeniach z prawdziwym kursorem (nie touch),
   żeby na telefonie pierwszy tap nie "zaklejał" przeskalowanego stanu */
@media (hover: hover) and (pointer: fine) {
    .header-logo img:hover {
        transform: scale(1.02);
    }
}

#language-selector {
    display: flex;
    align-items: center;
    gap: 15px;
    /* Odstępy między flagami */
}

/* Kontener dla elementów po prawej stronie, aby zapewnić jeden wiersz */
.header-right {
    display: flex;
    align-items: center;
    gap: 20px;
    /* Odstępy między grupą flag a ikonami */
}

#language-selector img {
    border-radius: 4px;
    /* Zmiękcz flagi */
    /* ... reszta css flag */
}

@media (hover: hover) and (pointer: fine) {
    #language-selector img:hover {
        opacity: 1;
    }
}

#language-selector img.active-flag {
    transform: scale(1.2);
    opacity: 1;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}

.header-icon-img {
    width: 32px;
    height: 32px;
    vertical-align: middle;
    filter: grayscale(100%) opacity(0.6);
    transition: all 0.2s;
    cursor: pointer;
}

@media (hover: hover) and (pointer: fine) {
    .header-icon-img:hover {
        filter: grayscale(0%) opacity(1);
        transform: rotate(15deg);
    }
}

/* --- Kontener Treści --- */
.content {
    display: flex;
    flex-grow: 1;
    overflow: hidden;
    height: calc(100vh - var(--header-height));
}

/* --- Pasek boczny --- */
.sidebar {
    width: var(--sidebar-width);
    min-width: var(--sidebar-width);
    flex-shrink: 0;
    /* Zapobiega ściskaniu przez main-content */
    background: var(--sidebar-gradient);
    color: white;
    display: flex;
    flex-direction: column;
    padding: 25px 15px;
    overflow-y: auto;
    overflow-x: hidden;
    overscroll-behavior: contain; /* F4.32: scroll szuflady nie „ucieka" do body */
    box-shadow: 4px 0 15px rgba(0, 0, 0, 0.05);
    /* Głębia */
    z-index: var(--z-sidebar); /* F4.22 (=90) */
}

.sidebar button {
    background: transparent;
    border: none;
    color: rgba(255, 255, 255, 0.85);
    /* Lekko przygaszony tekst dla nieaktywnych */
    padding: 12px 20px;
    margin-bottom: 8px;
    /* Odstępy między elementami */
    text-align: left;
    font-size: 18px;
    width: 100%;
    cursor: pointer;
    border-radius: var(--radius-sm);
    /* Zaokrąglone pigułki */
    transition: all var(--transition-fast);
    display: flex;
    /* Gotowe na ikony, jeśli zostaną dodane */
    align-items: center;
}

/* Hover sidebar tylko na hover-capable — na touch pierwszy tap "zaklejał" przesunięcie */
@media (hover: hover) and (pointer: fine) {
    .sidebar button:hover {
        background-color: rgba(255, 255, 255, 0.1);
        color: #fff;
        transform: translateX(4px);
    }
}

.sidebar button.active {
    background-color: var(--surface-color);
    /* Biała aktywna pigułka */
    color: var(--primary-color);
    font-weight: 700;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

/* Przewijanie Menu Paska Bocznego */
#menu-buttons {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: rgba(255, 255, 255, 0.2) transparent;
    padding-right: 5px;
}

#menu-buttons::-webkit-scrollbar {
    width: 6px;
}

#menu-buttons::-webkit-scrollbar-thumb {
    background-color: rgba(255, 255, 255, 0.2);
    border-radius: 8px;
}

#menu-buttons::-webkit-scrollbar-track {
    background: transparent;
}


/* --- Treść Główna ---
   padding-bottom uwzględnia safe-area-inset-bottom (home indicator iPhone),
   żeby ostatni rząd kafelków nie schował się pod paskiem gestów. */
.main-content {
    flex-grow: 1;
    min-width: 0;
    /* Zapobiega rozszerzaniu poza dostępną przestrzeń */
    overflow-y: auto;
    padding: 30px;
    padding-bottom: max(30px, env(safe-area-inset-bottom));
    /* Więcej przestrzeni */
    background-color: var(--secondary-color);
}

/* --- Układ Responsywny ---
   Sidebar w trybie drawer (<=768px) zdefiniowany w responsive.css.
   Tutaj zostawiamy tylko padding headera. */
@media (max-width: 768px) {
    .header {
        padding: 0 15px;
    }
}/* Komponenty: Przyciski, Modale, Tabele, Alerty */

/* --- Przyciski --- */
.retry-button {
    background: var(--primary-gradient);
    color: white;
    border: none;
    padding: 12px 24px;
    border-radius: 30px;
    /* Pełna pigułka */
    cursor: pointer;
    font-weight: 600;
    font-size: 14px;
    margin-top: 20px;
    box-shadow: 0 4px 10px rgba(0, 100, 0, 0.2);
    transition: transform var(--transition-fast), box-shadow var(--transition-fast);
}

.retry-button:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 15px rgba(0, 100, 0, 0.3);
}

/* --- Alerty / Status --- */
.error-message {
    color: #721c24;
    background-color: #f8d7da;
    border-left: 5px solid #f5c6cb;
    border-radius: var(--radius-sm);
    padding: 15px 20px;
    margin: 20px 0;
    font-weight: 500;
}

.loading-indicator {
    text-align: center;
    padding: 40px;
    color: var(--primary-color);
    font-weight: 600;
    font-size: 16px;
    letter-spacing: 0.5px;
}

/* --- Modale (Ogólne) --- */
.modal-overlay,
#password-modal {
    display: none;
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.4);
    backdrop-filter: blur(4px);
    /* Nowoczesny efekt szkła */
    z-index: var(--z-modal); /* F4.22 (=9999) */
    /* Dostosowany z-index dla nakładki modalu */
    align-items: center;
    /* Dla #password-modal */
    justify-content: center;
    /* Dla #password-modal */
}


/* ==================================================================
   F4.13 (2026-07-23): WSPÓLNA klasa kart modali generowanych z JS.
   Zamiast inline background:white (dark-mode-overrides łatał to kruchymi
   hackami [style*="background: white"]) — generatory dodają .gf-modal-card,
   a tokeny robią resztę w obu motywach. NOWY modal z JS: użyj tej klasy.
   ================================================================== */
.gf-modal-card {
    background: var(--card-bg);
    color: var(--text-color);
    border: 1px solid var(--card-border);
    box-shadow: var(--shadow-lg);
    overscroll-behavior: contain; /* F4.32: scroll modala nie „ucieka" do body */
}

/* Popup Instalacji (Specyficzny Modal) */
#installation-popup {
    position: absolute;
    top: 120px;
    left: 50%;
    transform: translateX(-50%);
    width: 500px;
    max-width: 90%;
    max-height: 80vh;
    overflow-y: auto;
    overscroll-behavior: contain; /* F4.32 */

    background: var(--card-bg);
    border: 1px solid var(--card-border);
    border-radius: var(--radius-md);
    padding: 30px;
    color: var(--text-color);

    box-shadow: var(--shadow-lg);
    z-index: var(--z-modal-raised); /* F4.22 (=10000) */
    display: none;
    /* F4.17: unikalna nazwa — wcześniej „fadeIn" kolidowało z @keyframes w index.php
       (translate-center-scale), przez co popup instalacji „podskakiwał" przy otwarciu */
    animation: installationPopupFadeIn 0.3s cubic-bezier(0.18, 0.89, 0.32, 1.28);
}

/* F4.8 (2026-07-23): telefon w landscape (niski ekran) — popup startował na
   top:120px z max-height:80vh i wystawał poza ekran. dvh = realna wysokość
   viewportu na iOS (pasek przeglądarki). */
@media (max-height: 500px) and (orientation: landscape) {
    #installation-popup {
        top: 10px;
        max-height: calc(100vh - 20px);
        max-height: calc(100dvh - 20px);
        padding: 16px;
    }
}

#close-popup {
    background: #ff4d4f;
    color: white;
    border: none;
    padding: 8px 12px;
    border-radius: 50%;
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: bold;
    cursor: pointer;
    position: sticky;
    /* Sticky - zawsze widoczny przy scrollu */
    top: 0;
    float: right;
    transition: transform 0.2s;
    z-index: var(--z-drawer); /* F4.22 (=1000) */
}

#close-popup:hover {
    transform: scale(1.1);
}

@keyframes installationPopupFadeIn {
    from {
        opacity: 0;
        transform: translateX(-50%) translateY(20px);
    }

    to {
        opacity: 1;
        transform: translateX(-50%) translateY(0);
    }
}

/* --- Tabele --- */
#service-table {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    margin-top: 20px;
    background: var(--card-bg);
    border-radius: var(--radius-sm);
    overflow: hidden;
    box-shadow: var(--shadow-sm);
    color: var(--text-color);
}

#service-table th {
    background-color: var(--secondary-color);
    padding: 15px 20px;
    color: var(--text-muted);
    font-weight: 600;
    text-transform: uppercase;
    font-size: 12px;
    letter-spacing: 0.5px;
    text-align: left;
    border-bottom: 1px solid var(--card-border);
}

#service-table td {
    padding: 15px 20px;
    border-bottom: 1px solid var(--card-border);
    font-size: 14px;
}

#service-table tr:last-child td {
    border-bottom: none;
}

#service-table tbody tr:hover {
    background-color: var(--accent-light);
}

#service-table td:not(:first-child),
#service-table th:not(:first-child) {
    text-align: center;
}

/* --- Spinnery Ładowania --- */
.loading-overlay {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100%;
    width: 100%;
    min-height: 200px;
    /* Zapewnij widoczność */
}

.loading-spinner {
    width: 40px;
    height: 40px;
    /* F4.15: token — tor spinnera podąża za motywem (dark = ciemny) */
    border: 4px solid var(--card-border);
    border-top: 4px solid var(--primary-color);
    border-radius: 50%;
    animation: spin 1s linear infinite;
}

.loading-spinner-large {
    width: 60px;
    height: 60px;
    border: 6px solid var(--card-border);
    border-top: 6px solid var(--primary-color);
    border-radius: 50%;
    animation: spin 1s linear infinite;
}

@keyframes spin {
    0% {
        transform: rotate(0deg);
    }

    100% {
        transform: rotate(360deg);
    }
}
/* Moduł: Pulpit nawigacyjny */

/* Napraw wzrost wykresu miesięcznego — specyficzne ID zamiast globalnego canvas */
#monthly-chart {
    max-width: 100%;
    height: 600px !important;
}

/* Wykres donut — NIE override height */
#donutCard {
    display: block;
    height: auto !important;
    width: 100% !important;
}

.chart-title {
    font-size: 22px;
    font-weight: 700;
    color: var(--text-color);
    margin-bottom: 15px;
    text-align: center;
}

.chart-subtitle {
    text-align: center;
    color: var(--text-muted);
    margin-bottom: 15px;
    font-size: 14px;
}

/* Kontenery statystyk */
.stats-container {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
    gap: 15px;
    margin-bottom: 30px;
    width: 100%;
}

.stat-box {
    background: var(--card-bg);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-md);
    padding: 15px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-height: 100px;
    transition: transform var(--transition-smooth), box-shadow var(--transition-smooth);
    border: 1px solid var(--card-border);
    color: var(--text-color);
}

@media (hover: hover) and (pointer: fine) {
    .stat-box:hover {
        transform: translateY(-3px);
        box-shadow: var(--shadow-lg);
    }
}

.stat-title {
    font-size: 18px;
    font-weight: bold;
    color: var(--text-color);
    margin-bottom: 8px;
    text-align: center;
    line-height: 1.3;
}

.stat-value {
    font-size: 20px;
    font-weight: bold;
    color: var(--primary-color);
}

.kafelek-uptime,
.kafelek-m3,
.kafelek-clickable {
    cursor: pointer;
    background-color: var(--accent-light);
    border: 1px solid var(--accent-border);
}

@media (hover: hover) and (pointer: fine) {
    .kafelek-uptime:hover,
    .kafelek-m3:hover,
    .kafelek-clickable:hover {
        background-color: var(--accent-light);
        transform: translateY(-2px);
        box-shadow: var(--shadow-lg);
    }
}

/* Mapy */
.map-container {
    /* F4.15: token zamiast jasnoszarego gradientu — dark mode podąża automatycznie
       (dawniej gradient nadpisywany osobno w dark-mode-overrides) */
    background: var(--card-bg);
    padding: 15px;
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-md);
    border: 1px solid var(--card-border);
}

#map {
    width: 100%;
    height: 600px;
    border-radius: var(--radius-sm);
}

/* Lekko stonuj jasne tile'y mapy */
#map .leaflet-tile-pane {
    filter: brightness(0.96) saturate(1.05);
}

/* Konterner wykresu */
.chart-container {
    /* F4.15: token zamiast jasnoszarego gradientu — spójne z systemem kart */
    background: var(--card-bg);
    padding: 15px;
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-md);
    border: 1px solid var(--card-border);
}

/* Wykres Produktionssteder — stała wysokość na desktop (bez niej canvas rośnie w nieskończoność) */
.production-chart-container {
    height: 936px;
}

.production-chart-container canvas {
    height: 100% !important;
}

/* Siatki */
.grid-2col,
.grid-2col-production {
    display: grid;
    grid-template-columns: 1fr 2fr;
    gap: 20px;
    margin-top: 20px;
}

/* =============================================
   RESPONSIVE - WIDOK MOBILNY
   ============================================= */
@media (max-width: 1024px) {

    .grid-2col,
    .grid-2col-production {
        grid-template-columns: 1fr 1fr;
    }

    #map {
        height: 400px;
    }
}

@media (max-width: 768px) {

    .grid-2col,
    .grid-2col-production {
        grid-template-columns: 1fr;
    }

    .stats-container {
        grid-template-columns: repeat(2, 1fr);
        gap: 10px;
    }

    .stat-box {
        padding: 12px;
        min-height: 80px;
    }

    .stat-value {
        font-size: 20px;
    }

    .stat-title {
        font-size: 11px;
    }

    #map {
        height: 300px;
    }

    /* Klamra wysokości tylko dla wykresów Chart.js, które bez tego rosłyby w nieskończoność.
       Wcześniej była tu reguła `canvas { height: 300px !important }` — globalna i destrukcyjna:
       zniekształcała donut (#donutCard) oraz #top10-chart, który ma własną dynamiczną wysokość. */
    #monthly-chart {
        height: 400px !important;
    }

    #installation-breakdown-chart,
    #kw-history-chart,
    #daily-history-chart {
        max-height: 300px !important;
    }

    .chart-title {
        font-size: 18px;
    }
}

@media (max-width: 480px) {
    .stats-container {
        grid-template-columns: 1fr 1fr;
        gap: 8px;
    }

    .stat-box {
        padding: 10px;
        min-height: 70px;
    }

    .stat-value {
        font-size: 18px;
    }

    .stat-title {
        font-size: 11px; /* F4.7: minimum czytelności (było 10px) */
    }

    #map {
        height: 250px;
    }

    /* Mniej miejsca w pionie na małym telefonie — niższe wykresy */
    #monthly-chart {
        height: 300px !important;
    }

    #installation-breakdown-chart,
    #kw-history-chart,
    #daily-history-chart {
        max-height: 240px !important;
    }
}

/* Przewijanie miesięczne (Dół pulpitu) */
/* Scrollbar pod wykresem miesięcznym */
.chart-scrollbar {
    margin-top: 10px;
    padding: 0 4px;
}

.chart-scrollbar-track {
    position: relative;
    width: 100%;
    height: 10px;
    background: var(--card-border, #e8e8e8); /* F4.14: --bg-muted nie istniało; card-border = widoczny tor w obu motywach */
    border-radius: 5px;
    cursor: pointer;
}

.chart-scrollbar-thumb {
    position: absolute;
    top: 0;
    height: 100%;
    min-width: 30px;
    background: var(--primary-color, #006400);
    border-radius: 5px;
    cursor: grab;
    opacity: 0.55;
    transition: opacity 0.15s;
}

.chart-scrollbar-thumb:hover,
.chart-scrollbar-thumb:active {
    opacity: 0.85;
    cursor: grabbing;
}

.stats-title-row {
    padding: 0 2px 4px;
}

.stats-title-row .page-title {
    font-size: 22px;
    font-weight: 800;
    color: var(--text-color);
    letter-spacing: -0.5px;
}

/* =============================================
   DONUT CARD
   ============================================= */
/* Donut card — szmaragdowy tint */
.donut-card {
    background: linear-gradient(135deg, rgba(0,100,0,0.03), rgba(34,139,34,0.05));
    border: 1px solid var(--card-border);
    border-radius: var(--radius-md);
    overflow: hidden;
    display: flex;
    flex-direction: column;
    box-shadow: 0 4px 16px rgba(0, 100, 0, 0.1), var(--shadow-sm);
}

/* Live power card — turkusowo-cyjanowy tint */
.live-power-card {
    background: linear-gradient(135deg, rgba(6,182,212,0.04), rgba(34,211,238,0.06)) !important;
    box-shadow: 0 4px 16px rgba(6, 182, 212, 0.1), var(--shadow-sm) !important;
}

.donut-card::before {
    content: '';
    display: block;
    height: 3px;
    background: linear-gradient(90deg, #006400, #228B22, #4ade80);
}

/* Header: tytuł (lewo) + trend (prawo) */
.donut-card-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 10px 20px 0;
}

.donut-card-header .donut-trend {
    margin: 0;
    padding: 2px 8px;
    font-size: 12px;
}

.donut-card-inner {
    display: flex;
    align-items: center;
    padding: 4px 12px 0;
    gap: 12px;
    flex: 1;
}

.donut-canvas-wrap {
    position: relative;
    width: 50%;
    max-width: 324px;
    min-height: 234px;
    flex-shrink: 0;
    margin: 0;
}

.donut-canvas-wrap canvas {
    filter: drop-shadow(0 8px 6px rgba(0,0,0,0.15));
}

.donut-center {
    display: none;
}

.donut-center[onclick] {
    pointer-events: auto;
}

.donut-center-val {
    font-size: 52px;
    font-weight: 800;
    letter-spacing: -2px;
    text-align: center;
    color: var(--text-color);
    width: 100%;
}

.donut-center-label {
    font-size: 14px;
    font-weight: 700;
    color: var(--text-muted);
    text-align: center;
    line-height: 1.3;
    margin-top: 2px;
}

.donut-info {
    flex: 1;
    /* Fix 2026-07-24 (zoom przeglądarki tnie treść): min-width:0 pozwala kolumnie
       tekstowej KURCZYĆ SIĘ zamiast wypychać poza kartę (overflow:hidden ucinał
       „7.170 MWh el total" i legendę przy zoomie 110–150% / wąskich oknach).
       Pionowe wyśrodkowanie przez justify-content zamiast sztywnych marginesów. */
    min-width: 0;
    align-self: stretch;
    padding-top: 0;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;
}

.donut-info-title {
    font-size: 15px;
    font-weight: 800;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 1.2px;
    margin-bottom: 0;
}

.donut-title {
    font-size: 14px;
    font-weight: 800;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.8px;
    margin-bottom: 14px;
    text-align: left;
}

.donut-legend {
    display: flex;
    flex-direction: column;
    gap: 8px;
    /* Fix 2026-07-24: sztywne margin-left:110px / margin-top:80px pozycjonowały
       legendę „na oko" przy pełnej szerokości — przy zoomie/węższej kolumnie
       wypychały ją poza kartę (overflow:hidden ucinał wartości MWh).
       Naturalny flow: legenda zaraz za donutem, wyśrodkowanie robi .donut-info. */
    margin-left: 0;
    margin-top: 14px;
    min-width: 0;
}

.donut-total {
    margin-top: 0;
    margin-bottom: 6px;
    /* Fix 2026-07-24: bez sztywnego padding-left:70px (jak wyżej — ucinało liczbę) */
    padding-left: 0;
    display: flex;
    align-items: baseline;
    gap: 6px;
    flex-wrap: wrap;
    min-width: 0;
}

.donut-total-val {
    /* Fix 2026-07-24: clamp zamiast stałych 42px — liczba skaluje się z oknem
       (42px przy pełnej szerokości, mniej przy zoomie 110–150%) */
    font-size: clamp(28px, 2.6vw, 42px);
    font-weight: 800;
    color: var(--text-color);
    letter-spacing: -1.5px;
}

.donut-total-unit {
    font-size: 15px;
    font-weight: 700;
    color: var(--text-muted);
}

.donut-trend {
    margin-top: 0;
    margin-bottom: 10px;
    padding: 4px 0;
    text-align: left;
    cursor: help;
    font-size: 12px;
}

.pie3d-tooltip {
    position: absolute;
    pointer-events: none;
    background: rgba(0,0,0,0.8);
    color: #fff;
    padding: 6px 10px;
    border-radius: 6px;
    font-size: 13px;
    font-weight: 600;
    white-space: nowrap;
    z-index: var(--z-raised); /* F4.22 (=10) */
    transition: opacity 0.15s;
}

.legend-item {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    font-size: 14px;
    gap: 10px;
}

.legend-left {
    display: flex;
    align-items: center;
    gap: 6px;
    color: var(--text-muted);
    font-weight: 500;
    font-size: 15px;
    white-space: nowrap;
}

.legend-dot {
    width: 13px;
    height: 13px;
    border-radius: 3px;
    flex-shrink: 0;
}

.legend-val {
    font-weight: 800;
    font-size: 19px;
    white-space: nowrap;
    color: var(--text-color);
}

.legend-pct {
    font-size: 14px;
    color: var(--text-muted);
    margin-left: 4px;
    font-weight: 700;
}

/* =============================================
   STAT-CARDS-ROW (3 karty: cieplo, metan, co2)
   ============================================= */
.stat-cards-row {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 12px;
}

/* Varme (ciepło) — ciepły czerwono-pomarańczowy */
.stat-card:nth-child(1) {
    background: linear-gradient(135deg, rgba(239,68,68,0.05), rgba(251,146,60,0.07));
}
/* Metan (biogaz) — fioletowo-indygo */
.stat-card:nth-child(2) {
    background: linear-gradient(135deg, rgba(139,92,246,0.05), rgba(99,102,241,0.06));
}
/* CO2e — zielony */
.stat-card:nth-child(3) {
    background: linear-gradient(135deg, rgba(0,100,0,0.04), rgba(74,222,128,0.06));
}

.stat-card {
    background: var(--card-bg);
    border: 1px solid var(--card-border);
    border-radius: var(--radius-md);
    padding: 16px 14px 12px;
    cursor: pointer;
    transition: transform 0.2s ease, box-shadow 0.2s ease;
    position: relative;
    overflow: hidden;
    box-shadow: 0 4px 16px rgba(0, 100, 0, 0.1), var(--shadow-sm);
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    min-height: 110px;
}

.stat-card::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 3px;
    background: linear-gradient(90deg, #006400, #228B22);
}

.stat-card:nth-child(2)::before {
    background: linear-gradient(90deg, #f59e0b, #fbbf24);
}

.stat-card:nth-child(3)::before {
    background: linear-gradient(90deg, #3b82f6, #60a5fa);
}

.stat-card:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-md);
    border-color: var(--accent-border);
}

.stat-top {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    margin-bottom: 8px;
}

.stat-icon {
    width: 30px;
    height: 30px;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 16px;
    background: var(--accent-light);
}

.stat-trend-badge {
    font-size: 11px;
    font-weight: 700;
    padding: 2px 6px;
    border-radius: 20px;
    background: var(--accent-light);
    color: var(--primary-color);
    display: flex;
    align-items: center;
    gap: 2px;
}

.stat-card .stat-label {
    font-size: 11px;
    font-weight: 700;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: 2px;
}

.stat-card .stat-value {
    font-size: 28px;
    font-weight: 800;
    letter-spacing: -0.5px;
    white-space: nowrap;
    line-height: 1;
    margin-bottom: 2px;
    color: var(--text-color);
}

.stat-kwh {
    font-size: 13px;
    font-weight: 600;
    color: var(--text-muted);
    margin-top: 1px;
}

.stat-sub {
    font-size: 11px;
    font-weight: 500;
    color: var(--text-muted);
    margin-top: 3px;
}

/* =============================================
   INLINE TICKERS
   ============================================= */
.inline-tickers {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.inline-ticker {
    /* F4.15: token (biały w light bez zmian; dark nadpisywany osobno) */
    background: var(--surface-color);
    border: 1px solid var(--card-border);
    border-radius: 8px;
    height: 44px;
    display: flex;
    align-items: center;
    overflow: hidden;
    position: relative;
    box-shadow: var(--shadow-sm);
}

.inline-ticker-title {
    color: white;
    font-weight: 800;
    font-size: 18px;
    padding: 0 14px;
    height: 100%;
    display: flex;
    align-items: center;
    white-space: nowrap;
    border-right: 1px solid rgba(255,255,255,0.2);
    z-index: 2;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    min-width: 90px;
}

.inline-ticker.el-ticker .inline-ticker-title {
    background: linear-gradient(135deg, #006400 0%, #228B22 100%);
}

.inline-ticker.news-ticker .inline-ticker-title {
    background: linear-gradient(135deg, #1e3a8a 0%, #3b82f6 100%);
}

.inline-ticker-content {
    flex: 1;
    overflow: hidden;
    height: 100%;
    position: relative;
    display: flex;
    align-items: center;
}

.inline-ticker-scroll {
    display: inline-flex;
    white-space: nowrap;
    animation: scrollTicker 120s linear infinite;
    align-items: center;
    padding-left: 100%;
}

.inline-ticker.news-ticker .inline-ticker-scroll {
    animation-duration: 60s;
    font-size: 21px;
}

.inline-ticker-scroll:hover {
    animation-play-state: paused;
}

@keyframes scrollTicker {
    0%   { transform: translateX(0); }
    100% { transform: translateX(-100%); }
}

.ticker-node {
    display: inline-flex;
    align-items: center;
    margin-right: 36px;
    font-size: 20px;
}

.ticker-node .node-name {
    color: var(--text-muted);
    margin-right: 6px;
    font-weight: 700;
    font-size: 18px;
}

.ticker-node .node-val {
    font-weight: 800;
    color: var(--text-color);
    font-size: 21px;
}

.inline-ticker-controls {
    padding: 0 10px;
    height: 100%;
    display: flex;
    align-items: center;
    background: rgba(0,0,0,0.03);
    border-left: 1px solid var(--card-border);
    z-index: 2;
}

.toggle-switch {
    width: 30px;
    height: 16px;
    background: var(--card-border);
    border-radius: 10px;
    position: relative;
    cursor: pointer;
    transition: 0.2s;
}

.toggle-switch::after {
    content: '';
    position: absolute;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: white;
    top: 2px;
    left: 2px;
    transition: 0.2s;
    box-shadow: 0 1px 3px rgba(0,0,0,0.2);
}

.toggle-switch.on {
    /* F4.15: token — w dark #4ade80 (widoczny), było zamrożone #006400 */
    background: var(--primary-color);
}

.toggle-switch.on::after {
    left: 16px;
}

/* =============================================
   RESPONSIVE
   F4.9 (2026-07-23): breakpointy ujednolicone do 768/1024 (były 600/900 —
   w oknie 769-900px sidebar statyczny + zawinięte kolumny dawały najciaśniejszy
   wariant; teraz zawijanie obejmuje całą strefę statycznego sidebara ≤1024).
   ============================================= */
@media (max-width: 1024px) {
    .stat-cards-row {
        grid-template-columns: repeat(3, 1fr);
    }

    .donut-canvas-wrap {
        max-width: 180px;
    }
}

/* ── Donut card — kompaktowy układ dla tabletów (TB336FU i podobnych) ──
   Wcześniej kompaktowy układ (donut nad info zamiast obok siebie) włączał się
   dopiero przy ≤600px. Na tabletach dashboard-3col trzymał donut w wąskiej
   kolumnie ~340–450px, a w `.donut-legend` był hardkodowany `margin-left: 110px`,
   `margin-top: 80px` + `.donut-total { padding-left: 70px }` i `.legend-left
   { white-space: nowrap }` — w efekcie legenda była ucinana, a pierwsza cyfra
   totalu wycinana poza kartę.
   POPRAWKA 2026-05-28: pierwotna reguła `(max-width: 1024px)` nie łapała tabletu
   z viewportem 1280–1920px (TB336FU landscape DPR=1.0–1.5). Druga gałąź
   `(hover: none) and (pointer: coarse)` łapie każdy tablet niezależnie od DPR. */
@media (max-width: 1024px),
       (max-width: 1920px) and (hover: none) and (pointer: coarse) {
    /* Układ POZIOMY (row): donut po lewej, info po prawej.
       Wcześniej był column (donut nad info) — wygenerował dużo pustego pionu
       i poziomego białego miejsca dookoła donuta wycentrowanego w 448px kolumnie.
       Row wykorzystuje całą szerokość karty, wysokość = max(donut, info) ≈ 180–200px
       zamiast 350+px. */
    .donut-card-inner {
        flex-direction: row;
        align-items: center;
        padding: 6px 14px 12px;
        gap: 12px;
    }

    .donut-canvas-wrap {
        width: 42%;
        max-width: 160px;
        min-width: 110px;
        min-height: 0;
        margin: 0;
        align-self: center;
        flex-shrink: 0;
    }

    .donut-info {
        flex: 1;
        align-self: center;
        align-items: flex-start;
        text-align: left;
        min-width: 0;
    }

    .donut-title {
        text-align: left;
        margin-bottom: 4px;
    }

    /* Wyzeruj hardkodowane offsety projektowane pod szeroką kartę desktopową */
    .donut-legend {
        margin-left: 0;
        margin-top: 0;
        align-items: stretch;
        width: 100%;
        gap: 4px;
    }

    .donut-total {
        padding-left: 0;
        margin-top: 0;
        margin-bottom: 6px;
        justify-content: flex-start;
    }

    /* Cyfra totalu — mniejsza na tablecie (była 42px desktop, 28px telefon) */
    .donut-total-val {
        font-size: 28px;
        letter-spacing: -0.5px;
    }

    .donut-total-unit {
        font-size: 12px;
    }

    /* Pozycje w legendzie — mniejsze fonty bez ucinania */
    .legend-item {
        font-size: 12px;
    }

    .legend-left {
        white-space: normal;
        font-size: 12px;
    }

    .legend-val {
        font-size: 14px;
    }

    .legend-pct {
        font-size: 11px;
    }

    .donut-card-header {
        padding: 6px 14px 0;
    }

    .donut-info-title {
        font-size: 12px;
        letter-spacing: 0.8px;
    }
}

/* F4.9: 600→768 (spójnie z breakpointem drawera) */
@media (max-width: 768px) {
    .stat-cards-row {
        grid-template-columns: 1fr;
    }

    /* ── Donut card kompakt na mobile ──
       Wcześniej: donut 50% szerokości karty + info 50%, w info hardkodowane
       margin-left: 110px / padding-left: 70px / white-space: nowrap → labele jak
       "Vedvarende energi" się ucinały, total cyfra 42px wycinała pierwszą cyfrę.
       Teraz: donut nad info (column), info zajmuje pełną szerokość. */
    .donut-card-inner {
        flex-direction: column;
        align-items: stretch;
        padding: 4px 12px 12px;
        gap: 8px;
    }

    .donut-canvas-wrap {
        width: 100%;
        max-width: 220px;
        min-height: 0;
        margin: 0 auto;
        align-self: center;
    }

    .donut-info {
        align-self: stretch;
        align-items: center;
        text-align: center;
    }

    .donut-title {
        margin-bottom: 8px;
        font-size: 12px;
        letter-spacing: 0.5px;
        text-align: center;
    }

    /* Wyzeruj hardkodowane offsety, wyśrodkuj */
    .donut-legend {
        margin-left: 0;
        margin-top: 8px;
        align-items: stretch;
        width: 100%;
    }

    .donut-total {
        padding-left: 0;
        margin-top: 12px;
        justify-content: center;
    }

    .donut-total-val {
        font-size: 28px;
        letter-spacing: -0.5px;
    }

    .donut-total-unit {
        font-size: 13px;
    }

    /* Pozwól labelom łamać się — koniec ucinania tekstu */
    .legend-left {
        white-space: normal;
        font-size: 13px;
    }

    .legend-item {
        font-size: 13px;
        justify-content: space-between;
    }

    .legend-val {
        font-size: 16px;
    }

    .legend-pct {
        font-size: 12px;
    }

    /* Header (tytuł + trend) — mniejszy padding, krótszy tytuł */
    .donut-card-header {
        padding: 8px 12px 0;
    }

    .donut-info-title {
        font-size: 13px;
        letter-spacing: 0.6px;
    }
}

/* =============================================
   DASHBOARD 3-KOLUMNOWY LAYOUT
   ============================================= */
.dashboard-3col {
    display: flex;
    gap: 16px;
    min-height: 0;
}

.dash-left {
    flex: 0 0 36%;
    min-width: 300px;
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.dash-right {
    flex: 1;
    min-width: 240px;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

/* =============================================
   LIVE POWER CARD — osobna kolumna środkowa
   ============================================= */
.live-power-card {
    flex: 0 0 150px;
    background: var(--card-bg);
    border: 1px solid var(--card-border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-sm);
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 12px 8px;
    gap: 6px;
    position: relative;
    overflow: hidden;
}

.live-power-card::before {
    content: '';
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 3px;
    background: linear-gradient(90deg, #006400, #22c55e);
}

.lpc-header {
    display: flex;
    align-items: center;
    gap: 6px;
    width: 100%;
    justify-content: center;
    padding-top: 2px;
}

.lpc-title {
    font-size: 11px;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.8px;
    color: var(--text-muted);
}

.lpc-kw {
    text-align: center;
}

.lpc-kw-val {
    font-size: 32px;
    font-weight: 900;
    color: var(--primary-color, #006400);
    line-height: 1;
    letter-spacing: -1px;
}

.lpc-kw-unit {
    font-size: 11px;
    font-weight: 700;
    color: var(--text-muted);
}

.lpc-engines {
    text-align: center;
    padding: 4px 0;
    border-top: 1px solid var(--card-border, rgba(0,0,0,0.06));
    width: 100%;
}

.lpc-eng-val {
    font-size: 16px;
    font-weight: 800;
    color: var(--text-color);
    line-height: 1.2;
}

.lpc-eng-label {
    font-size: 11px; /* F4.7: było 9px — nieczytelne, zwłaszcza uppercase */
    color: var(--text-muted);
    text-transform: uppercase;
}

.lpc-bar-section {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    width: 100%;
    min-height: 80px;
}

.lpc-bar-wrap {
    flex: 1;
    width: 50px;
    min-height: 60px;
    background: rgba(0,0,0,0.06);
    border-radius: 8px;
    position: relative;
    overflow: hidden;
    display: flex;
    align-items: flex-end;
}

.lpc-bar-fill {
    width: 100%;
    height: 0%;
    background: linear-gradient(to top, #006400, #22c55e);
    border-radius: 8px;
    transition: height 0.6s cubic-bezier(0.4, 0, 0.2, 1);
}

.lpc-pct {
    font-size: 12px;
    font-weight: 800;
    color: var(--text-color);
    margin-top: 4px;
}

.lpc-daily-section {
    text-align: center;
    cursor: pointer;
    padding: 6px 4px;
    border-top: 1px solid var(--card-border, rgba(0,0,0,0.06));
    width: 100%;
    border-radius: 6px;
    transition: background 0.2s;
}

.lpc-daily-section:hover {
    background: var(--accent-light, rgba(0,100,0,0.06));
}

.lpc-daily-val {
    font-size: 16px;
    font-weight: 800;
    color: var(--primary-color, #006400);
    line-height: 1.2;
}

.lpc-daily-label {
    font-size: 9px;
    color: var(--text-muted);
    text-transform: uppercase;
}

.lpc-max {
    font-size: 11px; /* F4.7 */
    font-weight: 700;
    color: var(--text-muted);
    text-align: center;
    white-space: nowrap;
}

.lpc-ts {
    font-size: 11px; /* F4.7: było 9px */
    color: var(--text-muted);
    opacity: 0.7;
}

/* Status dot (shared) */
.lp-status-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: #6b7280;
    display: inline-block;
    flex-shrink: 0;
}

.lp-dot-active {
    animation: lp-pulse 2s ease-in-out infinite;
}

@keyframes lp-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.4; }
}

/* Dark mode */
[data-theme="dark"] .live-power-card {
    border-color: rgba(74,222,128,0.15);
}

[data-theme="dark"] .lpc-bar-wrap {
    background: rgba(255,255,255,0.08);
}

[data-theme="dark"] .lpc-daily-section:hover {
    background: rgba(74,222,128,0.08);
}

/* Responsive: live-power-card jako pasek (nie ukrywany na mobile)
   F4.9: 900→1024 (spójnie z resztą projektu) */
@media (max-width: 1024px) {
    .dashboard-3col {
        flex-wrap: wrap;
    }

    .dash-left {
        flex: 1 1 100%;
        max-width: 100%;
    }

    .live-power-card {
        flex: 0 0 100%;
        flex-direction: row;
        gap: 16px;
        padding: 12px 16px;
    }

    .lpc-bar-section {
        flex-direction: row;
        min-height: auto;
        gap: 8px;
    }

    .lpc-bar-wrap {
        width: 100%;
        min-height: 20px;
        height: 20px;
        flex-direction: row;
        align-items: stretch;
    }

    .lpc-bar-fill {
        height: 100% !important;
        width: 0%;
        transition: width 0.6s cubic-bezier(0.4, 0, 0.2, 1);
    }

    .dash-right {
        flex: 1 1 100%;
    }
}

/* Na bardzo małych ekranach Live Power zostaje widoczny — kompaktowy pasek
   (wcześniej `display: none` ukrywał kluczową informację o aktualnej mocy).
   F4.9: 600→768 (spójnie z breakpointem drawera) */
@media (max-width: 768px) {
    .live-power-card {
        padding: 8px 12px;
        gap: 8px;
    }

    .lpc-header {
        font-size: 11px;
        gap: 4px;
        padding-top: 0;
    }

    .lpc-bar-wrap {
        min-height: 16px;
        height: 16px;
    }

    /* Sekcja dzienna — mniejsze etykiety, jeden rząd */
    .lpc-daily-section {
        padding: 4px 6px;
        font-size: 11px;
    }
}
/* ============================================================
   TV MODE — kafelek "TV wersja" w naglowku instalacji
   #TAG: TV_MODE STYLE PRODUKCJA
   ============================================================ */
.tv-mode-controls .tv-mode-btn,
.tv-mode-controls .tv-mode-copy {
    background: var(--primary-color, #006400);
    color: #fff;
    border: none;
    border-radius: 8px;
    padding: 8px 14px;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    font-family: inherit;
    transition: background 0.15s ease, transform 0.1s ease;
    display: inline-flex;
    align-items: center;
    gap: 6px;
}
.tv-mode-controls .tv-mode-copy {
    padding: 8px 10px;
    font-size: 14px;
}
.tv-mode-controls .tv-mode-btn:hover,
.tv-mode-controls .tv-mode-copy:hover {
    background: var(--primary-hover);
    transform: translateY(-1px);
}
.tv-mode-controls .tv-mode-btn:active,
.tv-mode-controls .tv-mode-copy:active {
    transform: translateY(0);
}
[data-theme="dark"] .tv-mode-controls .tv-mode-btn,
[data-theme="dark"] .tv-mode-controls .tv-mode-copy {
    background: var(--primary-color, #4ade80);
    color: #0a1a14;
}
[data-theme="dark"] .tv-mode-controls .tv-mode-btn:hover,
[data-theme="dark"] .tv-mode-controls .tv-mode-copy:hover {
    background: var(--primary-hover);
}
/* Moduł: Widok Top 10 */

.top10-grid {
    display: flex;
    gap: 8px;
    align-items: stretch;
}

/* Lewa Kolumna */
.top10-col-left {
    flex: 0 0 36%;
    display: grid;
    gap: 8px;
    grid-template-rows: repeat(3, var(--pillarH, 108px));
}

/* Prawa Kolumna */
.top10-col-right {
    flex: 1 1 auto;
    display: grid;
    gap: 8px;
    grid-template-rows: repeat(3, var(--rowH, 108px));
    grid-auto-flow: column;
    grid-auto-columns: minmax(320px, 1fr);
    height: auto;
}

/* Karty */
.top10-card {
    position: relative;
    background: var(--card-bg);
    border-radius: 10px;
    overflow: hidden;
    box-shadow: var(--shadow-sm);
    transition: transform .12s ease, box-shadow .12s ease;
    cursor: pointer;
    /* F4.24: usunięto outline:none — focus klawiatury obsługuje globalny :focus-visible */
    height: 100%;
    border: 1px solid var(--card-border);
    color: var(--text-color);
}

.top10-card:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-md);
}

/* Układ Wewnętrzny */
.tile-inner {
    display: flex;
    align-items: center;
    height: 100%;
}

.tile-text {
    flex: 1 1 auto;
    padding: 8px 12px;
    display: flex;
    flex-direction: column;
    justify-content: center;
}

.tile-photo {
    display: none !important;
}

/* Filary (Lewy) */
.pillar .tile-text {
    border-left: 5px solid var(--primary-color);
}

.pillar .tile-name {
    font-size: 16px;
    font-weight: 800;
    color: var(--primary-color);
}

/* Lista Rankingowa (Prawa) */
.rank .tile-name {
    font-size: 15px;
    font-weight: 700;
    color: var(--text-color);
}

.tile-stat {
    font-size: 13px;
    color: var(--text-muted);
}

.tile-stat .label {
    text-transform: uppercase;
    letter-spacing: .3px;
    opacity: .85;
    margin-right: 6px;
}

.tile-val {
    font-weight: 800;
    color: var(--text-color);
}

/* Dekoracje */
/* Ikona przed tytułem */
.top10-grid .tile-header {
    display: flex;
    align-items: center;
    gap: 8px;
}

.top10-grid .tile-header::before {
    content: "";
    width: 18px;
    height: 14px;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 30'><rect x='5' y='12' width='30' height='12' rx='2' fill='%23006400'/><ellipse cx='20' cy='12' rx='15' ry='8' fill='%2300a050'/><rect x='18' y='5' width='4' height='5' rx='1' fill='%23006400'/></svg>");
    background-repeat: no-repeat;
    background-size: contain;
    background-position: center;
}

/* Diament Rankingu / Odznaka */
.top10-grid .rank-diamond {
    position: relative;
    width: 34px;
    height: 26px;
    margin-right: 8px;
    flex: 0 0 auto;
}

.top10-grid .rank-diamond::before {
    content: "";
    position: absolute;
    inset: 0;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 30'><rect x='5' y='12' width='30' height='12' rx='2' fill='%23006400'/><ellipse cx='20' cy='12' rx='15' ry='8' fill='%2300a050'/><rect x='18' y='5' width='4' height='5' rx='1' fill='%23006400'/></svg>");
    background-repeat: no-repeat;
    background-size: contain;
    background-position: center;
}

.top10-grid .rank-diamond>span {
    position: absolute;
    right: -6px;
    top: -6px;
    width: 18px;
    height: 18px;
    border-radius: 9px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 800;
    font-size: 11px;
    color: #fff;
    background: var(--primary-color);
}

/* Wstążki (odznaki) — F4.12 (2026-07-23): tło z tokena (w dark mode
   #4ade80 na białym miał kontrast ~1.9:1) */
.ribbon {
    background: var(--card-bg, #fff);
    border: 2px solid var(--primary-color);
    border-radius: 12px;
    padding: 3px 7px;
    font-weight: 800;
    color: var(--primary-color);
    font-size: 12px;
}

.ribbon.gold {
    background: #DAA520;
    border-color: #DAA520;
    color: #000;
}

.ribbon.silver {
    background: #C0C0C0;
    border-color: #C0C0C0;
    color: #000;
}

.ribbon.bronze {
    background: #CD7F32;
    border-color: #CD7F32;
    color: #000;
}

.flag-badge {
    display: inline-block;
    padding: 2px 6px;
    border-radius: 10px;
    /* F4.12: token zamiast #e6ffe6 (accent-light = #e8f5e9 light / #1f2e1f dark) */
    background: var(--accent-light, #e6ffe6);
    color: var(--primary-color);
    font-weight: 700;
    font-size: 11px;
    margin-left: 4px;
}

/* Pasek Filtrów */
.filters-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    margin: 6px 0 14px 0;
}

.segmented {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 4px;
    border: 1px solid var(--accent-border);
    border-radius: 999px;
    background: var(--card-bg);
}

.segmented button {
    border: 0;
    background: transparent;
    padding: 6px 12px;
    border-radius: 999px;
    font-weight: 600;
    font-size: 13px;
    color: var(--text-color);
    cursor: pointer;
}

.segmented button.active {
    background: var(--primary-color);
    color: #fff;
}

.filters-bar select {
    height: 32px;
    padding: 4px 10px;
    border-radius: 8px;
    border: 1px solid var(--accent-border);
    background: var(--card-bg);
    color: var(--text-color);
}

/* F4.9 (2026-07-23): 980→1024 (ujednolicenie breakpointów projektu) */
@media (max-width: 1024px) {
    .top10-grid {
        flex-direction: column;
    }
}

/* Stylizacja Suwaka / Nawigatora */
.gf-nav {
    display: flex;
    align-items: center;
    gap: 8px;
    background: var(--card-bg);
    padding: 6px 14px;
    border-radius: 999px;
    border: 1px solid var(--accent-border);
    box-shadow: var(--shadow-sm);
}

.gf-btn {
    width: 28px;
    height: 28px;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--card-border);
    background: var(--card-bg);
    color: var(--primary-color);
    border-radius: 50%;
    cursor: pointer;
    font-weight: bold;
    font-size: 16px;
    line-height: 1;
    transition: all 0.2s ease;
}

.gf-btn:hover {
    background: var(--primary-color);
    color: #fff;
    border-color: var(--primary-color);
    transform: scale(1.05);
}

.gf-current {
    font-weight: 700;
    font-size: 14px;
    /* F4.15: token — dark nadpisywany osobno na #fff, teraz jedno źródło */
    color: var(--text-color);
    min-width: 75px;
    text-align: center;
    font-variant-numeric: tabular-nums;
    user-select: none;
}

.gf-range {
    width: 140px;
    cursor: pointer;
    accent-color: var(--primary-color);
    height: 4px;
    /* F4.15: token — tor suwaka podąża za motywem (dark = ciemny tor) */
    background: var(--input-border);
    border-radius: 2px;
    /* F4.24: outline:none usunięty — :focus-visible pokazuje obwódkę przy Tab */
}

/* Zapewnij prawidłowe wyrównanie pionowe w kontenerze flex */
.filters-bar .gf-nav {
    margin-left: 10px;
}/* Moduł: Panel Administratora */

#admin-panel {
    display: none;
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.6);
    z-index: var(--z-modal); /* F4.22 (=9999) */
}

/* Uwaga: admin.html ma własny CSS w bloku <style>, ponieważ był samodzielnym plikiem.
   Jeśli unifikujemy, powinniśmy to również wyodrębnić. 
   Obecnie admin.html jest kopiowany TAK JAK JEST. 
   Więc ten plik może obsługiwać 'ukrytą' logikę admina w index.html */

.admin-dialog {
    /* F4.10 (2026-07-23): tokeny zamiast białego — w dark mode panel był
       biały tekst na białym tle (nieczytelny) */
    background: var(--card-bg, #fff);
    color: var(--text-color, #333);
    width: 90%;
    height: 90%;
    margin: 2% auto;
    padding: 20px;
    border-radius: 8px;
    display: flex;
    flex-direction: column;
}

.admin-dialog-header {
    display: flex;
    justify-content: space-between;
    margin-bottom: 20px;
}/* Style Widoku Serwisu */

.service-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 20px;
    padding: 20px 0;
}

.service-card {
    background: var(--card-bg);
    border-radius: 16px;
    box-shadow: var(--shadow-md);
    padding: 15px;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    transition: transform 0.2s, box-shadow 0.2s;
    border: 1px solid var(--card-border);
    position: relative;
    overflow: hidden;
    color: var(--text-color);
}

.service-card:hover {
    transform: translateY(-4px);
    box-shadow: var(--shadow-lg);
}

.service-header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    margin-bottom: 10px;
}

.service-site-name {
    font-size: 15px;
    font-weight: 700;
    color: var(--text-color);
    line-height: 1.3;
}

.service-unit-id {
    background: var(--secondary-color);
    padding: 3px 6px;
    border-radius: 6px;
    font-size: 11px;
    font-weight: 600;
    color: var(--text-muted);
    white-space: nowrap;
    border: 1px solid var(--card-border);
}

.service-body {
    margin-bottom: 15px;
    text-align: center;
}

.service-timer-val {
    font-size: 28px;
    font-weight: 800;
    margin-bottom: 5px;
    display: block;
    color: var(--text-color);
}

.service-timer-label {
    font-size: 11px;
    text-transform: uppercase;
    color: var(--text-muted);
    letter-spacing: 1px;
    font-weight: 600;
    margin-bottom: 8px;
}

/* Kontener paska postępu */
.service-progress-track {
    width: 100%;
    height: 6px;
    background: var(--secondary-color);
    border-radius: 4px;
    overflow: hidden;
    margin-top: 8px;
}

.service-progress-fill {
    height: 100%;
    border-radius: 4px;
    transition: width 0.6s ease-out;
}

.service-footer {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding-top: 10px;
    border-top: 1px solid var(--card-border);
    font-size: 12px;
    color: var(--text-muted);
}

.service-meta-item {
    display: flex;
    align-items: center;
    gap: 6px;
}

.service-meta-icon {
    font-size: 14px;
    opacity: 0.7;
}

.service-days-left {
    font-weight: 600;
    color: var(--text-color);
}

/* =============================================
   Tabele serwisowe — horyzontalny scroll na mobile
   Wrapper renderowany przez service.js wokół każdej tabeli (overdue / urgent / upcoming).
   Przy `table-layout: fixed` i 5–6 kolumnach z procentowymi szerokościami,
   kolumny "Servicedato" i "Dage til service" wąskie się zwężały na <480px
   tak, że tekst (np. "2026-04-29") nakładał się na sąsiednią kolumnę.
   Teraz tabela ma min-width na mobile i scroll-x w wrapperze. */
.service-table-wrap {
    width: 100%;
    /* Ledwie widoczny pasek scrolla zamiast przezroczystego — żeby było wiadomo, że można przesunąć */
    scrollbar-width: thin;
}

.service-table-wrap::-webkit-scrollbar {
    height: 6px;
}

.service-table-wrap::-webkit-scrollbar-thumb {
    background: rgba(0, 100, 0, 0.25);
    border-radius: 3px;
}

@media (max-width: 768px) {
    /* 2026-09-16: poziomy scroll TYLKO tu, gdzie tabela ma min-width. Na desktopie `overflow-x`
       robił z opakowania kontener przewijania i przyklejony nagłówek przewijał się razem ze stroną. */
    .service-table-wrap {
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }

    .service-table-wrap > table {
        min-width: 640px;
    }
}

@media (max-width: 480px) {
    .service-table-wrap > table {
        min-width: 560px;
    }

    /* Mniejszy padding w komórkach, żeby tabela była użyteczna po przewinięciu */
    .service-table-wrap > table th,
    .service-table-wrap > table td {
        padding: 8px 8px !important;
        font-size: 12px !important;
    }
}/* benchmark.css — kompaktowy kafelek + modal porownania efektywnosci vs modelfarmy.
   Wstrzykiwany przez installations.js do .stats-container.
   #TAG: BENCHMARK CSS PoC */

/* === Wspolny styl podpisow w kafelkach panelu instalacji === */

/* Okres pod liczba — "fra start", "sidste 2 mdr.", "12 mdr." itp. */
.stat-box .stat-period {
  font-size: 0.7em;
  color: #888;
  margin-top: 4px;
  font-style: italic;
  text-align: center;
  line-height: 1.2;
}

/* Wskazowka ze kafelek jest klikalny (pojawia sie tylko gdy stat-click-hint dodane) */
.stat-box .stat-click-hint {
  font-size: 0.68em;
  color: var(--primary-color, #006400);
  margin-top: 6px;
  text-align: center;
  font-weight: 500;
  opacity: 0.75;
}

/* Klikalne kafelki — wzmocnij wizualnie (cursor + lekki hover lift).
   Dodajemy lekka zielona linia na dole jako sygnal interaktywnosci. */
.stat-box.kafelek-clickable,
.stat-box.kafelek-m3,
.stat-box.kafelek-uptime,
.stat-box.stat-box-benchmark {
  cursor: pointer;
  border-bottom: 3px solid var(--primary-color, #006400);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.stat-box.kafelek-clickable:hover,
.stat-box.kafelek-m3:hover,
.stat-box.kafelek-uptime:hover,
.stat-box.stat-box-benchmark:hover {
  transform: translateY(-2px);
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.12);
}

.stat-box.kafelek-clickable:hover .stat-click-hint,
.stat-box.kafelek-m3:hover .stat-click-hint,
.stat-box.kafelek-uptime:hover .stat-click-hint {
  opacity: 1;
}

/* Dark mode */
[data-theme="dark"] .stat-box .stat-period {
  color: var(--text-muted, #aaa); /* F4.14: --text-secondary nie istniało (działał tylko fallback) */
}
[data-theme="dark"] .stat-box .stat-click-hint {
  color: #4ade80;
}


.stat-box-benchmark {
  position: relative;
  cursor: pointer;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.stat-box-benchmark:hover {
  transform: translateY(-2px);
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.12);
}

.stat-box-benchmark .bm-tile-subline {
  font-size: 0.85em;
  color: #444;
  text-align: center;
  margin-top: 2px;
  font-variant-numeric: tabular-nums;
}

.stat-box-benchmark .bm-tile-meta {
  font-size: 0.78em;
  color: #666;
  text-align: center;
  margin-top: 2px;
}

.stat-box-benchmark .bm-tile-hint {
  font-size: 0.7em;
  color: #888;
  text-align: center;
  margin-top: 6px;
  font-style: italic;
}

/* Dark mode */
[data-theme="dark"] .stat-box-benchmark {
  background-blend-mode: multiply !important;
  background-color: var(--card-bg, #1e1e1e) !important; /* F4.14: --bg-card → --card-bg (istniejący token) */
}

[data-theme="dark"] .stat-box-benchmark .bm-tile-subline,
[data-theme="dark"] .stat-box-benchmark .bm-tile-meta,
[data-theme="dark"] .stat-box-benchmark .bm-tile-hint {
  color: var(--text-muted, #aaa) !important; /* F4.14 */
}

/* Modal — domyslne style w JS sa inline (zgodnie z konwencja innych modali w projekcie),
   ale dodajmy hover na wierszach tabeli i responsywnosc. */
#benchmark-modal table tbody tr:hover {
  filter: brightness(0.97);
}

@media (max-width: 768px) {
  #benchmark-modal table {
    font-size: 11px !important;
  }
  #benchmark-modal table th,
  #benchmark-modal table td {
    padding: 6px 4px !important;
  }
}
/* ==================================================================
   toast.css — dymki i modale komunikatów (F5.23, 2026-08-27)
   Para do `public/js/gf_ui.js`. Zastępuje natywne alert/confirm/prompt.

   ⚠️ Plik musi działać TAKŻE bez `variables.css` — strony standalone
   (admin.html, status_standalone.html, login.html) mają własne, inaczej
   nazwane tokeny w <style>. Stąd łańcuchy fallbacków:
       var(--card-bg, var(--card, #ffffff))
         ^ dashboard      ^ admin   ^ ostateczność
   Dark mode na tych stronach działa, bo `--card`/`--text` są tam
   nadpisywane pod [data-theme="dark"] — łańcuch przelicza się sam.
   ================================================================== */

:root {
    --gfu-info-bd: var(--alert-info-border, #3b82f6);
    --gfu-info-bg: var(--alert-info-bg, #dbeafe);
    --gfu-info-ink: var(--alert-info-ink, #1e40af);
    --gfu-warn-bd: var(--alert-warn-border, #ffc107);
    --gfu-warn-bg: var(--alert-warn-bg, #fff3cd);
    --gfu-warn-ink: var(--alert-warn-ink, #92400e);
    --gfu-err-bd: var(--alert-error-border, #dc3545);
    --gfu-err-bg: var(--alert-error-bg, #fee2e2);
    --gfu-err-ink: var(--alert-error-ink, #991b1b);
    --gfu-ok-bd: var(--alert-success-border, #16a34a);
    --gfu-ok-bg: var(--alert-success-bg, #dcfce7);
    --gfu-ok-ink: var(--alert-success-ink, #14532d);
}

/* Wartości zapasowe dla ciemnego motywu na stronach BEZ variables.css.
   Tam, gdzie variables.css jest — pierwszy człon var() i tak wygrywa. */
:root[data-theme="dark"] {
    --gfu-info-bd: var(--alert-info-border, #60a5fa);
    --gfu-info-bg: var(--alert-info-bg, #16233f);
    --gfu-info-ink: var(--alert-info-ink, #93c5fd);
    --gfu-warn-bd: var(--alert-warn-border, #f59e0b);
    --gfu-warn-bg: var(--alert-warn-bg, #3a2e0a);
    --gfu-warn-ink: var(--alert-warn-ink, #fcd34d);
    --gfu-err-bd: var(--alert-error-border, #ef4444);
    --gfu-err-bg: var(--alert-error-bg, #3b1216);
    --gfu-err-ink: var(--alert-error-ink, #fca5a5);
    --gfu-ok-bd: var(--alert-success-border, #4ade80);
    --gfu-ok-bg: var(--alert-success-bg, #0f2e1a);
    --gfu-ok-ink: var(--alert-success-ink, #bbf7d0);
}

/* ---------------- Dymki (toasty) ---------------- */

.gf-toast-host {
    position: fixed;
    top: calc(var(--header-height, 70px) + 12px);
    right: 16px;
    z-index: var(--z-toast, 100001);
    /* nad modalami (--z-modal-top 100000) — dymek może polecieć znad modala */
    display: flex;
    flex-direction: column;
    gap: 10px;
    width: min(380px, calc(100vw - 32px));
    pointer-events: none;
    /* host nie łapie kliknięć — tylko same dymki */
}

.gf-toast {
    pointer-events: auto;
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 12px 14px;
    border-radius: var(--radius-md, 16px);
    border: 1px solid var(--card-border, var(--border, #e9ecef));
    border-left: 4px solid var(--gfu-info-bd);
    background: var(--card-bg, var(--card, #ffffff));
    color: var(--text-color, var(--text, #2c3e50));
    box-shadow: var(--shadow-lg, 0 8px 24px rgba(0, 0, 0, 0.2));
    font-family: var(--font-main, 'Inter', 'Segoe UI', system-ui, sans-serif);
    font-size: 14px;
    line-height: 1.45;
    animation: gfToastIn 0.22s cubic-bezier(0.18, 0.89, 0.32, 1.28);
}

.gf-toast--info {
    border-left-color: var(--gfu-info-bd);
}

.gf-toast--success {
    border-left-color: var(--gfu-ok-bd);
}

.gf-toast--warning {
    border-left-color: var(--gfu-warn-bd);
}

.gf-toast--error {
    border-left-color: var(--gfu-err-bd);
}

.gf-toast__icon {
    flex: 0 0 auto;
    font-size: 16px;
    line-height: 1.3;
}

.gf-toast__body {
    flex: 1 1 auto;
    min-width: 0;
}

.gf-toast__title {
    font-weight: 700;
    margin-bottom: 2px;
}

.gf-toast__msg {
    white-space: pre-line;
    /* `\n` z komunikatów zachowane, bez innerHTML */
    overflow-wrap: anywhere;
    /* długie URL-e/ID nie rozpychają dymka */
}

.gf-toast--error .gf-toast__title {
    color: var(--gfu-err-ink);
}

.gf-toast--warning .gf-toast__title {
    color: var(--gfu-warn-ink);
}

.gf-toast--success .gf-toast__title {
    color: var(--gfu-ok-ink);
}

.gf-toast__close {
    flex: 0 0 auto;
    background: none;
    border: 0;
    cursor: pointer;
    color: var(--text-muted, var(--muted, #6c757d));
    font-size: 14px;
    line-height: 1;
    padding: 2px 4px;
    border-radius: 6px;
}

.gf-toast__close:hover {
    color: var(--text-color, var(--text, #2c3e50));
    background: var(--gfu-info-bg);
}

.gf-toast.is-leaving {
    animation: gfToastOut 0.18s ease-in forwards;
}

@keyframes gfToastIn {
    from {
        opacity: 0;
        transform: translateX(24px);
    }

    to {
        opacity: 1;
        transform: translateX(0);
    }
}

@keyframes gfToastOut {
    from {
        opacity: 1;
        transform: translateX(0);
    }

    to {
        opacity: 0;
        transform: translateX(24px);
    }
}

/* ---------------- Modale (alert / confirm / prompt) ---------------- */

.gf-dialog-overlay {
    position: fixed;
    inset: 0;
    /* O JEDEN NIŻEJ niż dymki (--z-toast). Przy równym z-index overlay wygrywał
       kolejnością w DOM i przyciemniał dymki wyświetlone znad modala. */
    z-index: var(--z-modal-top, 100000);
    background: rgba(0, 0, 0, 0.5);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
    animation: gfDialogFade 0.15s ease-out;
}

.gf-dialog {
    width: min(460px, 100%);
    max-height: 80vh;
    max-height: 80dvh;
    /* iOS: realna wysokość viewportu (F4.9) */
    overflow-y: auto;
    overscroll-behavior: contain;
    /* F4.32 */
    padding: 22px 24px 18px;
    border-radius: var(--radius-md, 16px);
    /* .gf-modal-card (components.css) daje tło/kolor tam, gdzie jest wczytany;
       poniżej to samo dla stron standalone bez tego arkusza */
    background: var(--card-bg, var(--card, #ffffff));
    color: var(--text-color, var(--text, #2c3e50));
    border: 1px solid var(--card-border, var(--border, #e9ecef));
    box-shadow: var(--shadow-lg, 0 8px 24px rgba(0, 0, 0, 0.3));
    font-family: var(--font-main, 'Inter', 'Segoe UI', system-ui, sans-serif);
}

.gf-dialog__title {
    font-size: 17px;
    font-weight: 700;
    margin-bottom: 10px;
}

.gf-dialog--danger .gf-dialog__title {
    color: var(--gfu-err-ink);
}

.gf-dialog__msg {
    font-size: 14px;
    line-height: 1.5;
    white-space: pre-line;
    overflow-wrap: anywhere;
}

.gf-dialog__input {
    width: 100%;
    /* 2026-09-25: bez tego pole (100% + padding + ramka) wystawało o 24 px poza kartę
       na stronach bez globalnego box-sizing (panel admina) → poziomy pasek w oknie */
    box-sizing: border-box;
    margin-top: 14px;
    padding: 9px 11px;
    font-size: 14px;
    font-family: inherit;
    color: var(--text-color, var(--text, #2c3e50));
    background: var(--input-bg, var(--card, #ffffff));
    border: 1px solid var(--input-border, var(--border, #ced4da));
    border-radius: var(--radius-sm, 8px);
}

.gf-dialog__actions {
    display: flex;
    justify-content: flex-end;
    gap: 10px;
    margin-top: 20px;
    flex-wrap: wrap;
}

.gf-btn {
    padding: 9px 18px;
    font-size: 14px;
    font-family: inherit;
    font-weight: 600;
    border-radius: var(--radius-sm, 8px);
    border: 1px solid transparent;
    cursor: pointer;
}

.gf-btn--primary {
    background: var(--primary-color, var(--primary, #006400));
    color: #ffffff;
}

.gf-btn--primary:hover {
    background: var(--primary-hover, #0a7a0a);
}

.gf-btn--danger {
    background: var(--gfu-err-bd);
    color: #ffffff;
}

.gf-btn--danger:hover {
    filter: brightness(1.1);
}

.gf-btn--ghost {
    background: transparent;
    color: var(--text-color, var(--text, #2c3e50));
    border-color: var(--card-border, var(--border, #ced4da));
}

.gf-btn--ghost:hover {
    background: var(--bg-color, var(--bg2, rgba(0, 0, 0, 0.05)));
}

@keyframes gfDialogFade {
    from {
        opacity: 0;
    }

    to {
        opacity: 1;
    }
}

/* ---------------- Mobile / dotyk / a11y ---------------- */

/* Dymek na telefonie: z góry-prawej na dół ekranu (kciuk sięga zamknięcia) */
@media (max-width: 480px) {
    .gf-toast-host {
        top: auto;
        /* --bottom-nav-h istnieje tylko w wersji mobilnej (m/) — tam dymek musi
           siedzieć NAD dolną nawigacją; na desktopie fallback 0px */
        bottom: calc(var(--bottom-nav-h, 0px) + 16px);
        left: 12px;
        right: 12px;
        width: auto;
    }
}

/* Telefon w landscape — niski ekran (F4.8) */
@media (max-height: 500px) and (orientation: landscape) {
    .gf-dialog {
        max-height: 92vh;
        padding: 14px 16px 12px;
    }
}

/* F4.3: cele dotykowe ≥44px */
@media (pointer: coarse) {

    .gf-btn,
    .gf-toast__close {
        min-height: 44px;
        min-width: 44px;
    }
}

/* F4.28: bez animacji, gdy użytkownik tak ustawił system */
@media (prefers-reduced-motion: reduce) {

    .gf-toast,
    .gf-toast.is-leaving,
    .gf-dialog-overlay {
        animation: none;
    }
}
/* ============================================
   RESPONSIVE CSS - Responsywność dla różnych rozdzielczości
   Breakpoints:
   - xs: < 480px (telefony pionowo)
   - sm: 480-768px (telefony poziomo, małe tablety)
   - md: 768-1024px (tablety)
   - lg: 1024-1440px (laptopy)
   - xl: > 1440px (monitory)
   ============================================ */

/* ============================================
   EXTRA LARGE (1440px+) - Monitory
   ============================================ */
@media (min-width: 1440px) {
    .main-content {
        padding: 40px 60px;
    }

    .detail-modal-content {
        max-width: 1300px;
    }

    .detail-grid {
        grid-template-columns: repeat(3, 1fr);
    }

    .comparison-container,
    .status-history-container {
        max-width: 1600px;
        margin: 0 auto;
    }
}

/* ============================================
   LARGE (1024-1440px) - Laptopy
   ============================================ */
@media (max-width: 1440px) {
    .main-content {
        padding: 25px;
    }

    .detail-grid {
        grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    }
}

/* ============================================
   MEDIUM (768-1024px) - Tablety
   ============================================ */
@media (max-width: 1024px) {
    .main-content {
        padding: 20px;
    }

    .sidebar {
        width: 180px;
        padding: 15px 10px;
    }

    .sidebar button {
        font-size: 14px;
        padding: 10px 12px;
    }

    .detail-modal-content {
        max-width: 95%;
    }

    .detail-grid {
        grid-template-columns: repeat(2, 1fr);
        gap: 15px;
    }

    /* Comparison - zmniejsz selektory */
    .compare-select {
        min-width: 160px !important;
    }

    /* Status History */
    .status-controls {
        flex-direction: column;
    }

    /* Header */
    .header-right {
        gap: 10px;
    }

    #language-selector {
        gap: 8px;
    }

    #language-selector img {
        width: 24px;
        height: 18px;
    }
}

/* ============================================
   SMALL (480-768px) - Telefony poziomo, małe tablety
   ============================================ */
@media (max-width: 768px) {

    /* Sidebar — tryb drawer (zsuwany z lewej) zamiast skompresowanego 60px paska.
       Wcześniej w przedziale 481–768px sidebar miał 60px szerokości i tekst 10px,
       co czyniło go nieczytelnym, a hamburgera nie było (pojawiał się dopiero <=480px).
       Teraz drawer + hamburger aktywne w całym zakresie <=768px. */
    .sidebar {
        position: fixed;
        left: 0;
        top: 0;
        height: 100vh;
        height: 100dvh; /* F4.29: iOS — pasek przeglądarki nie zasłania dołu menu */
        width: 240px;
        transform: translateX(-100%);
        display: flex;
        flex-direction: column;
        background: var(--sidebar-gradient);
        z-index: var(--z-drawer); /* F4.22 (=1000) */
        transition: transform 0.3s ease;
        box-shadow: 2px 0 10px rgba(0, 0, 0, 0.5);
        padding: 20px 12px;
        padding-left: max(12px, env(safe-area-inset-left)); /* F4.6: notch w landscape */
    }

    .sidebar.open {
        transform: translateX(0);
    }

    .sidebar button {
        width: 100%;
        justify-content: flex-start;
        text-align: left;
        font-size: 16px;
        padding: 12px 18px;
    }

    .sidebar button span {
        display: flex !important;
    }

    /* Overlay tła pod drawerem */
    #sidebar-overlay {
        display: none;
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background: rgba(0, 0, 0, 0.5);
        z-index: var(--z-overlay); /* F4.22 (=999) */
    }

    #sidebar-overlay.active {
        display: block;
    }

    /* Treść główna zajmuje całą szerokość — sidebar wisi nad nią jako overlay */
    .content {
        margin-left: 0;
        width: 100%;
    }

    /* Header */
    /* F4.30 (2026-07-23): zmienna podąża za realną wysokością headera —
       .content liczy się z var(--header-height), rozjazd 70 vs 56 dawał lukę */
    :root {
        --header-height: 56px;
    }

    .header {
        padding: 0 10px;
        height: var(--header-height);
    }

    .header-logo img {
        height: 36px;
    }

    .header-icon-img {
        width: 24px;
        height: 24px;
    }

    #language-selector img {
        width: 20px;
        height: 15px;
    }

    /* Zaciśnij odstępy w prawej grupie ikon — nadpisz inline `margin-left/right`
       z `index.html`/`index.php`, bo nakładają się na flex `gap` i robi się ciasno */
    #language-selector {
        gap: 6px;
    }

    .header-right {
        gap: 10px;
    }

    #language-selector > span,
    #theme-toggle,
    #docs-btn,
    #admin-gear,
    #logout-btn,
    #user-gear {
        margin-left: 0 !important;
    }

    /* Alerts (admin) — inline `margin-right:20px` jest za duży na mobile */
    #alerts-btn {
        margin-right: 6px !important;
    }

    /* Aktywna flaga: mniejsze powiększenie, żeby nie zachodziła na sąsiada */
    #language-selector img.active-flag {
        transform: scale(1.08);
    }

    /* Theme toggle / docs glyph — zmniejsz znaki emoji */
    #theme-toggle {
        font-size: 18px !important;
    }

    #docs-btn > span,
    #alerts-btn > span:first-child {
        font-size: 20px !important;
    }

    /* Main Content */
    .main-content {
        padding: 15px;
    }

    /* Detail Modal */
    .detail-modal-overlay {
        padding: 10px;
    }

    .detail-modal-content {
        max-width: 100%;
        max-height: 95vh;
        border-radius: var(--radius-sm);
    }

    .detail-modal-header {
        padding: 12px 15px;
        flex-wrap: wrap;
        gap: 10px;
    }

    .detail-modal-header h2 {
        font-size: 14px;
    }

    #detail-icon {
        font-size: 18px !important;
    }

    /* Copy/Print buttons */
    #copy-detail-btn,
    #print-detail-btn {
        padding: 4px 8px !important;
        font-size: 11px !important;
    }

    .detail-body {
        padding: 12px;
    }

    .detail-grid {
        grid-template-columns: 1fr;
        gap: 12px;
    }

    .detail-card {
        padding: 12px;
    }

    .detail-card h3 {
        font-size: 12px;
    }

    .detail-row {
        font-size: 12px;
        padding: 5px 0;
    }

    /* Comparison */
    .comparison-container {
        padding: 10px !important;
    }

    .comparison-controls {
        padding: 15px !important;
    }

    #comparison-selectors {
        flex-direction: column;
    }

    .compare-select {
        width: 100% !important;
        min-width: auto !important;
    }

    #period-panel>div:last-child {
        flex-direction: column;
    }

    .segmented {
        flex-wrap: wrap;
    }

    .segmented button {
        font-size: 11px;
        padding: 6px 10px;
    }

    /* Status History */
    .status-history-container {
        padding: 10px !important;
    }

    .status-controls {
        padding: 12px !important;
    }

    /* Tabele */
    #service-table th,
    #service-table td {
        padding: 8px 10px;
        font-size: 12px;
    }

    /* Charts & Maps responsive height */
    .chart-container,
    .map-container {
        height: 220px !important;
        min-height: 0 !important;
    }

    /* Wyjątek - wykres produkcji może rosnąć */
    .production-chart-container,
    .installation-chart-container {
        height: auto !important;
        min-height: 400px !important;
        max-height: 800px !important;
        overflow-y: auto !important;
    }

    .production-chart-container canvas,
    .installation-chart-container canvas {
        max-height: 100% !important;
    }

    #map {
        height: 100% !important;
    }

    /* Top 10 Compact Stack */
    .top10-col-left,
    .top10-col-right {
        display: flex;
        flex-direction: column;
        gap: 8px;
    }

    .top10-card {
        height: auto !important;
        min-height: 60px;
    }

}

/* ============================================
   TABLET (TB336FU i podobne) — drawer + hamburger
   Aktywne dla:
   • Każde urządzenie 769–1024px szerokości (portrait tablet, wąskie okna)
   • Każde urządzenie czysto-dotykowe (hover: none + pointer: coarse) do 1920px
     — łapie tablet TB336FU niezależnie od DPR (CSS viewport może być 1280×800,
     1536×960 lub 1920×1200 w landscape).
   Mouse-only desktopy i laptopy z hoverem zachowują statyczny sidebar.
   POPRAWKA 2026-05-28 wieczór: pierwotna reguła `max-width: 1366px AND
   max-height: 900px` nie łapała tabletu z viewportem 1536+ px szerokości lub
   1200+ px wysokości w portrait. Rozluźnione do detekcji typu input (hover/pointer).
   ============================================ */
@media (min-width: 769px) and (max-width: 1024px),
       (min-width: 769px) and (max-width: 1920px) and (hover: none) and (pointer: coarse) {

    .sidebar {
        position: fixed;
        left: 0;
        top: 0;
        height: 100vh;
        height: 100dvh; /* F4.29 */
        width: 260px;
        min-width: 260px;
        transform: translateX(-100%);
        display: flex;
        flex-direction: column;
        background: var(--sidebar-gradient);
        z-index: var(--z-drawer); /* F4.22 (=1000) */
        transition: transform 0.3s ease;
        box-shadow: 2px 0 10px rgba(0, 0, 0, 0.5);
        padding: 20px 12px;
        padding-left: max(12px, env(safe-area-inset-left)); /* F4.6 */
    }

    .sidebar.open {
        transform: translateX(0);
    }

    .sidebar button {
        width: 100%;
        justify-content: flex-start;
        text-align: left;
        font-size: 16px;
        padding: 12px 18px;
    }

    .sidebar button span {
        display: flex !important;
    }

    #sidebar-overlay,
    .sidebar-overlay {
        display: none;
        position: fixed;
        top: 0; left: 0; right: 0; bottom: 0;
        background: rgba(0, 0, 0, 0.5);
        z-index: var(--z-overlay); /* F4.22 (=999) */
    }

    #sidebar-overlay.active,
    .sidebar-overlay.active {
        display: block;
    }

    .content {
        margin-left: 0;
        width: 100%;
    }

    /* !important bo dalej w pliku jest bazowa reguła `.hamburger-btn { display: none }`
       (linia ~860), która ma taką samą specyficzność klasy i wygrywa przez source-order.
       Bez !important sidebar by się chował (transform), ale hamburger nie pojawiał się
       — co dawało efekt "menu zniknęło ale nie ma przycisku do otwarcia". */
    .hamburger-btn {
        display: block !important;
    }

    .main-content {
        padding: 18px;
    }

    /* ── Wysokości wykresów / mapy na tablecie ──
       Domyślnie `#monthly-chart { height: 600px }` + map/chart-container często 400–500px.
       Na tablecie landscape 800px wysokości viewportu (header 70 + padding 36 = ~694px na
       dashboard) takie wysokości powodują pionowy scroll. Skalujemy do wartości które
       mieszczą cały dashboard w jednym ekranie tabletu landscape, ale są wystarczająco
       duże w portrait (1280 wys.) żeby wykres był czytelny. */
    #monthly-chart {
        height: 360px !important;
    }

    .chart-container {
        height: 280px !important;
        min-height: 0 !important;
    }

    /* Mapa — niższa niż chart-container; donut+mapa muszą się zmieścić w lewej
       kolumnie dash-left. Iteracja na fizycznym tablecie: 280 → 210 → 180 (z bugiem
       #map height: 600px = mapa wystawała poza kontener) → po naprawie #map height: 100%
       container 180px wyglądał maluteńko → 270 → 380 → 440px. dash-left ~ donut(200)+
       gap(16)+mapa(440) = 656px, dash-right ~640px, w landscape 694px ~40px slack. */
    .map-container {
        height: 440px !important;
        min-height: 0 !important;
    }

    /* KLUCZOWE — bez tego mapa wystaje poza .map-container.
       `dashboard.css` ma `#map { height: 600px }` hardkodowane w base style
       (linia 113), poza media query. Ograniczenie samego .map-container do 180px
       nie pomaga, bo #map w środku ma swoje 600px i overflow:visible. Reszta
       breakpointów (np. <=1024px linia 349) dodaje `#map { height: 100% }` —
       mój blok tabletowy też musi. */
    #map {
        height: 100% !important;
        min-height: 0 !important;
    }

    /* Wykresy w modalach instalacji — mogą rosnąć, ale niżej niż na desktopie */
    .production-chart-container,
    .installation-chart-container {
        height: auto !important;
        min-height: 380px !important;
        max-height: 700px !important;
        overflow-y: auto !important;
    }

    /* Live power card w środkowej kolumnie — daj jej minimum, niech nie ściska zawartości */
    .live-power-card {
        min-height: 360px;
    }

    /* ── Stats-container na widoku INSTALACJI ──
       Widok instalacji wstrzykuje do 10 kafelków (electrical, thermal, CO2e, m³, runtime,
       uptime, last2months, biomass eff, capacity factor + weather; 2026-09-16 usunięte
       gas, methane, reactor yield, Performance faktor i starts). Z domyślnym `minmax(130px, 1fr)` i `min-height: 100px`
       na tablecie 1244px szerokości daje ~8 kolumn × ~140px wysokie = 2 rzędy × ~300px =
       same kafelki zajmują pół ekranu. Tutaj kompaktujemy: mniejszy próg minmax (90px
       zamiast 130), niższe kafelki (70 zamiast 100), mniejsze fonty i paddingi.
       Wszystkie kafelki zmieszczą się w 1 rzędzie (~10×90 = 900, slack na gap). */
    .stats-container {
        grid-template-columns: repeat(auto-fit, minmax(90px, 1fr));
        gap: 8px;
        margin-bottom: 14px;
    }

    .stat-box {
        padding: 8px 6px;
        min-height: 70px;
    }

    .stat-title {
        font-size: 11px;
        margin-bottom: 4px;
        line-height: 1.2;
    }

    .stat-value {
        font-size: 17px;
    }

    .stat-period,
    .stat-click-hint {
        font-size: 9px;
    }

}

/* ============================================
   EXTRA SMALL (< 480px) - Telefony pionowo
   ============================================ */
@media (max-width: 480px) {

    /* Drawer + overlay zdefiniowane w bloku <=768px wyżej — tutaj tylko drobne korekty
       wymuszone niższym headerem (50px) na bardzo małych ekranach. */
    .content {
        height: calc(100vh - 50px) !important;
        height: calc(100dvh - 50px) !important;
    }

    /* Header */
    :root {
        --header-height: 50px; /* F4.30 */
    }

    .header {
        padding: 0 8px;
        height: var(--header-height);
        justify-content: space-between;
    }

    .header-logo img {
        height: 28px;
    }

    .header-right {
        gap: 6px;
    }

    .header-icon-img {
        width: 20px;
        height: 20px;
    }

    #language-selector {
        gap: 3px;
    }

    #language-selector img {
        width: 16px;
        height: 12px;
    }

    /* Aktywna flaga — minimalne powiększenie na bardzo małym ekranie */
    #language-selector img.active-flag {
        transform: scale(1.05);
    }

    /* Theme/docs/alerts — mniejsze emoji */
    #theme-toggle {
        font-size: 16px !important;
    }

    #docs-btn > span,
    #alerts-btn > span:first-child {
        font-size: 18px !important;
    }

    /* Hamburger nieco mniejszy, żeby nie zjadał headera */
    .hamburger-btn {
        font-size: 22px;
        padding: 4px 6px;
    }

    /* Main Content */
    .main-content {
        padding: 8px;
        height: 100% !important;
    }

    /* Stats Grid 2col on portrait small phone */
    .stats-container {
        grid-template-columns: repeat(2, 1fr) !important;
        gap: 8px !important;
    }

    .stat-box {
        padding: 8px !important;
        min-height: 70px !important;
    }

    .stat-value {
        font-size: 16px !important;
    }

    /* Modal */
    .detail-modal-header {
        padding: 8px 10px;
    }

    .detail-modal-content {
        max-height: 90vh;
        /* Zostaw miejsce na paski przeglądarki */
    }

    .detail-modal-header>div:first-child {
        flex-direction: column;
        align-items: flex-start;
        gap: 2px;
    }

    #detail-title {
        font-size: 14px !important;
        margin: 0 !important;
    }

    #detail-subtitle {
        font-size: 10px !important;
        margin: 0 !important;
    }

    .detail-close-btn {
        font-size: 24px;
        padding: 0 5px;
    }

    .detail-card h3 {
        font-size: 11px;
        margin-bottom: 6px;
    }

    .detail-row {
        flex-direction: row !important;
        /* Wróć do row, żeby oszczędzić pion */
        justify-content: space-between;
        align-items: center;
        gap: 10px;
        padding: 3px 0;
        font-size: 11px !important;
    }

    .detail-value {
        text-align: right;
    }

    /* Wykresy jeszcze niższe */
    /* Wykresy jeszcze niższe */
    .chart-container,
    .map-container {
        height: 180px !important;
    }

    #comparison-chart {
        height: auto !important;
        min-height: 400px !important;
    }

    /* Wyjątek - wykres produkcji może rosnąć */
    .production-chart-container,
    .installation-chart-container {
        height: auto !important;
        min-height: 400px !important;
        max-height: 800px !important;
        overflow-y: auto !important;
    }

    .production-chart-container canvas,
    .installation-chart-container canvas {
        max-height: 100% !important;
    }

    /* Comparison */
    .comparison-container h2,
    .status-history-container h2 {
        font-size: 16px !important;
    }

    /* Service Table compact — F4.7: min 12px (tabela i tak ma scroll-x) */
    #service-table th,
    #service-table td {
        padding: 4px 6px !important;
        font-size: 12px !important;
    }


    #comp-mode button,
    #comp-scope button {
        font-size: 12px; /* F4.7: było 10px */
        padding: 5px 8px;
    }

    #period-panel h4 {
        font-size: 12px !important;
    }

    #period-panel input[type="month"] {
        width: 100%;
        font-size: 12px;
    }

    #run-comparison-btn {
        width: 100%;
        padding: 10px 16px !important;
    }

    /* Stats boxes */
    .stat-box {
        padding: 10px !important;
    }

    .stat-box>div:first-child {
        font-size: 11px !important;
    }

    .stat-box>div:last-child {
        font-size: 18px !important;
    }

    /* Navigation */
    .gf-nav {
        padding: 4px 8px !important;
        gap: 4px !important;
    }

    .gf-btn {
        width: 24px !important;
        height: 24px !important;
        font-size: 14px;
    }

    .gf-range {
        width: 80px !important;
    }

    /* Charts */
    #comparison-chart {
        height: auto !important;
        min-height: 400px !important;
    }
}

/* ============================================
   LANDSCAPE MODE (TELEFONY POZIOMO)
   ============================================ */
@media (max-height: 500px) and (orientation: landscape) {

    body {
        padding-bottom: 0 !important;
    }

    /* 1. SIDEBAR - ukryty domyślnie (hamburger), jak w pionie */
    .sidebar {
        position: fixed;
        left: 0;
        transform: translateX(-100%);
        top: 0;
        height: 100vh;
        height: 100dvh; /* F4.29 */
        width: 240px !important;
        display: flex;
        flex-direction: column;
        /* F4.15 (2026-07-23): było hardcodowane #1a1a2e — sidebar robił się
           GRANATOWY po obróceniu telefonu; token = spójny z resztą motywu */
        background: var(--sidebar-gradient);
        z-index: var(--z-drawer); /* F4.22 (=1000) */
        transition: transform 0.3s ease;
        box-shadow: 2px 0 10px rgba(0, 0, 0, 0.5);
        padding: 10px !important;
        padding-left: max(10px, env(safe-area-inset-left)) !important; /* F4.6: notch */
    }

    .sidebar.open {
        transform: translateX(0);
    }

    .sidebar button {
        justify-content: flex-start !important;
        padding-left: 20px !important;
        height: auto !important;
    }

    .sidebar button span {
        display: inline !important;
        /* Pokaż tekst w otwartym menu */
    }

    /* Przesuń content na 100% szerokości */
    .content {
        margin-left: 0 !important;
        width: 100%;
        height: calc(100vh - 40px) !important;
        height: calc(100dvh - 40px) !important;
    }

    /* Pokaż hamburgera */
    .hamburger-btn {
        display: block !important;
    }

    /* 2. HEADER - kompaktowy */
    :root {
        --header-height: 40px; /* F4.30 */
    }

    .header {
        height: var(--header-height) !important;
        padding: 0 10px !important;
    }

    .header-logo img {
        height: 25px !important;
        /* Mniejsze logo */
    }

    /* Języki */
    #language-selector img {
        width: 16px !important;
        height: 11px !important;
    }

    .header-icon-img {
        width: 18px !important;
        height: 18px !important;
    }

    /* 3. MAIN CONTENT - paddingi */
    .main-content {
        padding: 5px !important;
        height: 100% !important;
    }

    /* 4. STATYSTYKI (Te niebieskie kafelki) */
    .stats-container {
        display: grid;
        grid-template-columns: repeat(4, 1fr) !important;
        /* Wszystkie w 1 rzędzie */
        gap: 5px !important;
        margin-bottom: 5px !important;
    }

    .stat-box {
        min-height: 0 !important;
        padding: 5px !important;
        height: auto !important;
    }

    .stat-title {
        font-size: 11px !important; /* F4.7: było 9px */
        margin-bottom: 2px !important;
    }

    .stat-value {
        font-size: 14px !important;
    }

    .stat-change {
        font-size: 11px !important; /* F4.7: było 8px */
    }

    /* Mapy i Wykresy */
    .grid-2col {
        grid-template-columns: 1fr 1fr !important;
        /* Obok siebie */
        gap: 5px !important;
    }

    .chart-container,
    .map-container {
        height: 180px !important;
        /* Mniejsze wykresy */
        min-height: 0 !important;
    }

    /* Wyjątki dla wykresów produkcji i porównania */
    .production-chart-container,
    .installation-chart-container,
    #comparison-chart-container,
    #comparison-chart {
        height: auto !important;
        min-height: 400px !important;
    }

    .production-chart-container canvas,
    .installation-chart-container canvas,
    #comparison-chart {
        min-height: 400px !important;
    }

    #map {
        height: 100% !important;
        min-height: 0 !important;
    }
}

/* ============================================
   MOBILE-FIRST ENHANCEMENTS - Dodatkowe style dla telefonów
   ============================================ */

/* Tabele responsywne - poziomy scroll */
@media (max-width: 768px) {
    /* Ukryj mniej ważne kolumny na małych ekranach */
    .hide-on-mobile {
        display: none !important;
    }

    /* Większe obszary dotykowe — TYLKO główne CTA (klasa `.btn`).
       Wcześniej reguła obejmowała też goły `button`, co rozjeżdżało drobne
       inline-buttony w modalach (close ×, kebab itp.) wymuszając min 44×44. */
    .btn {
        min-height: 44px;
        min-width: 44px;
    }

    /* Hamburger ma własną wysokość poniżej 44px — daj mu touch-friendly target */
    .hamburger-btn {
        min-height: 40px;
        min-width: 40px;
    }

    /* Lepsze inputy na mobile */
    input,
    select,
    textarea {
        font-size: 16px !important;
        /* Zapobiega zoomowi na iOS */
    }
}

/* Touch-friendly improvements */
@media (hover: none) and (pointer: coarse) {

    /* Urządzenia dotykowe */
    .btn:active,
    button:active {
        transform: scale(0.98);
    }

    /* Większe cele dotykowe */
    .sidebar button {
        min-height: 48px;
    }

    /* Usuń hover effects na touch */
    .admin-tile:hover,
    .tile:hover {
        transform: none !important;
    }
}

/* ============================================
   UTILITIES - Klasy pomocnicze do ukrywania
   ============================================ */
.hide-xs {
    display: none !important;
}

@media (min-width: 480px) {
    .hide-xs {
        display: initial !important;
    }

    .show-xs {
        display: none !important;
    }
}

.hide-sm {
    display: none !important;
}

@media (min-width: 768px) {
    .hide-sm {
        display: initial !important;
    }

    .show-sm {
        display: none !important;
    }
}

.hide-md {
    display: none !important;
}

@media (min-width: 1024px) {
    .hide-md {
        display: initial !important;
    }

    .show-md {
        display: none !important;
    }
}

/* ============================================
   HAMBURGER MENU BUTTON (dla bardzo małych ekranów)
   ============================================ */
.hamburger-btn {
    display: none;
    background: none;
    border: none;
    font-size: 24px;
    cursor: pointer;
    padding: 5px;
    color: var(--text-color);
}

/* Hamburger widoczny od 768px (rozszerzone z 480px — patrz drawer wyżej) */
@media (max-width: 768px) {
    .hamburger-btn {
        display: block;
    }
}

/* Overlay dla menu mobilnego */
.sidebar-overlay {
    display: none;
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.5);
    z-index: var(--z-overlay); /* F4.22 (=999) */
}

.sidebar-overlay.active {
    display: block;
}

/* ============================================
   LANDSCAPE ORIENTATION (telefony poziomo) — uzupełnienia
   Główny blok landscape jest wyżej (drawer 240px). Tutaj tylko nadpisania
   modala/grida specyficzne dla niskiej wysokości — sidebar 50px / button 9px
   były martwe (nie mogły wygrać z !important w głównym bloku) i zostały usunięte.
   ============================================ */
@media (max-height: 500px) and (orientation: landscape) {
    .main-content {
        padding: 10px;
    }

    .detail-modal-content {
        max-height: 98vh;
    }

    .detail-grid {
        grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    }
}

/* ============================================
   PRINT STYLES
   ============================================ */
@media print {

    .sidebar,
    .header,
    .hamburger-btn,
    #copy-detail-btn,
    #print-detail-btn,
    .detail-close-btn {
        display: none !important;
    }

    .main-content {
        padding: 0;
        overflow: visible;
    }

    .detail-modal-overlay {
        position: static;
        background: none;
        padding: 0;
    }

    .detail-modal-content {
        max-width: 100%;
        max-height: none;
        box-shadow: none;
        border: none;
    }

    .detail-grid {
        grid-template-columns: repeat(2, 1fr);
    }
}
/* ============================================
   F4.3 (2026-07-23) — TOUCH TARGETS >=44px na urzadzeniach dotykowych.
   Grafika/emoji zostaja male; rosnie wylacznie klikalna powierzchnia
   (padding/min-wymiary), wiec wyglad na desktopie (pointer:fine) bez zmian.
   ============================================ */
@media (pointer: coarse) {

    /* Flagi jezyka: span-rodzic dostaje padding -> hitbox ~44px
       (dziala tez przy pomniejszonych flagach 20x15/16x12 z breakpointow) */
    #language-selector > span {
        padding: 12px 6px;
        display: inline-flex;
        align-items: center;
    }

    /* Ikony headera (alarmy, benchmark, TV, motyw, dokumenty, kolo zebate,
       wylogowanie): min 44x44. Uwaga: JS pokazuje czesc z nich przez inline
       display, dlatego bez wymuszania display tutaj — min-wymiary wystarcza. */
    #alerts-btn,
    #benchmark-btn,
    #tv-rotation-btn,
    #theme-toggle,
    #docs-btn,
    #admin-gear,
    #logout-btn {
        min-width: 44px;
        min-height: 44px;
        text-align: center;
        vertical-align: middle;
    }

    /* Strzalki nawigacji Top10/Sammenligning: hitbox 40x40
       (nadpisuje 24px z breakpointu 480px — stad !important) */
    .gf-btn {
        width: 40px !important;
        height: 40px !important;
    }

    /* Zamkniecie popupow (instalacja 32px, alarmy/benchmark ✖ 32px) —
       wieksze pole dotyku; !important nadpisuje inline width/height */
    #close-popup,
    .popup-close-btn {
        width: 44px !important;
        height: 44px !important;
    }

    /* Hamburger: pewny hitbox */
    .hamburger-btn {
        min-width: 44px;
        min-height: 44px;
    }
}
/* =============================================
   DARK MODE - NADPISANIA DLA WSZYSTKICH ELEMENTOW
   ============================================= */

/* Panel alertów - ciemniejsze tło */
[data-theme="dark"] #alerts-panel,
[data-theme="dark"] .alerts-panel {
    background: linear-gradient(135deg, #2d1f1f 0%, #3d2525 100%) !important;
    border-color: #5c3535 !important;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.4) !important;
}

[data-theme="dark"] #alerts-panel h3,
[data-theme="dark"] .alerts-panel h3 {
    color: #ff8a8a !important;
}

[data-theme="dark"] #toggle-alerts {
    color: #ff8a8a !important;
}

[data-theme="dark"] .alert-item {
    background: #3d2525 !important;
    border-color: #5c3535 !important;
    color: #f5f5f5 !important;
}

[data-theme="dark"] .alert-item div {
    color: #e0e0e0 !important;
}

/* Wykresy - ciemne tło */
[data-theme="dark"] .chart-container,
[data-theme="dark"] .chart-scroll,
[data-theme="dark"] .chart-inner,
[data-theme="dark"] #monthly-scroll,
[data-theme="dark"] #monthly-inner {
    background: var(--card-bg) !important;
    color: var(--text-color) !important;
}

/* Mapa - ciemniejszy filtr */
[data-theme="dark"] #map {
    filter: brightness(0.8) contrast(1.1) saturate(0.9);
}

[data-theme="dark"] .map-container {
    background: var(--card-bg) !important;
}

[data-theme="dark"] .leaflet-container {
    background-color: #1a1a1a !important;
}

[data-theme="dark"] .leaflet-control-zoom a {
    background-color: var(--card-bg) !important;
    color: var(--text-color) !important;
    border-color: var(--card-border) !important;
}

[data-theme="dark"] .leaflet-control-attribution {
    background-color: rgba(26, 26, 26, 0.8) !important;
    color: var(--text-muted) !important;
}

/* Gas Quality - dawne reguly dla .gq-controls / .gq-params / .gq-chart-container / #gq-controls /
   #gq-params / .controls-panel USUNIETE 2026-09-16 (wsad F4.20 z 17.08): markup uzywa wylacznie
   gq-hover / gq-overlay / gq-btn / gq-btn-h (grep po gas_quality.js i gas_quality_standalone.html),
   wiec te selektory nigdy nic nie stylowaly. Kopia: archive/f420_martwe_selektory_20260916/ */

/* Strony instalacji - ciemne tło wykresów */
[data-theme="dark"] .installation-chart-container,
[data-theme="dark"] .installation-stats,
[data-theme="dark"] .inst-chart-wrapper {
    background-color: var(--card-bg) !important;
    color: var(--text-color) !important;
    border-color: var(--card-border) !important;
}

/* Stat boxy na stronach instalacji */
[data-theme="dark"] .stat-box {
    background-color: var(--card-bg) !important;
    border-color: var(--card-border) !important;
}

[data-theme="dark"] .stat-title {
    color: var(--text-muted) !important;
}

[data-theme="dark"] .stat-value {
    color: var(--primary-color) !important;
    -webkit-text-fill-color: var(--primary-color) !important;
    background: none !important;
}

/* Legendy wykresów */
[data-theme="dark"] .legend-item {
    color: var(--text-color) !important;
}

/* Tabele danych */
[data-theme="dark"] table,
[data-theme="dark"] tbody,
[data-theme="dark"] thead {
    background-color: var(--card-bg) !important;
    color: var(--text-color) !important;
}

[data-theme="dark"] th {
    background-color: var(--secondary-color) !important;
    color: var(--text-muted) !important;
    border-color: var(--card-border) !important;
}

[data-theme="dark"] td {
    border-color: var(--card-border) !important;
    color: var(--text-color) !important;
}

/* Hover wierszy w dark (fix 2026-07-23, zgłoszenie usera): NIE podmieniamy tła —
   !important nadpisywał pastelowe tła tabel serwisu, a wewnętrzny ciemny tekst
   (inline na spanach) zostawał → wiersz pod kursorem nieczytelny.
   brightness() przyciemnia DOWOLNE tło (pastel/karta) zachowując kontrast
   tekstu — wzorzec z benchmark.css:110. */
[data-theme="dark"] tr:hover {
    filter: brightness(0.9);
}

/* Scrollbary */
[data-theme="dark"] ::-webkit-scrollbar {
    width: 10px;
    height: 10px;
}

[data-theme="dark"] ::-webkit-scrollbar-track {
    background: var(--secondary-color);
}

[data-theme="dark"] ::-webkit-scrollbar-thumb {
    background: #444;
    border-radius: 5px;
}

[data-theme="dark"] ::-webkit-scrollbar-thumb:hover {
    background: #555;
}

/* Popup instalacji */
[data-theme="dark"] #installation-popup,
[data-theme="dark"] .installation-popup {
    background-color: var(--card-bg) !important;
    border-color: var(--card-border) !important;
    color: var(--text-color) !important;
}

[data-theme="dark"] #popup-content {
    color: var(--text-color) !important;
}

/* Modalne okna */
[data-theme="dark"] #chart-modal>div,
[data-theme="dark"] .modal-content {
    background-color: var(--card-bg) !important;
    color: var(--text-color) !important;
}

[data-theme="dark"] #chart-modal-title {
    color: var(--primary-color) !important;
}

/* Przycisk zamknij */
[data-theme="dark"] #close-popup,
[data-theme="dark"] #close-chart-modal {
    background: #dc3545 !important;
    color: white !important;
}

/* Header */
[data-theme="dark"] .header {
    background-color: var(--header-bg) !important;
    border-bottom: 1px solid var(--card-border);
}

/* Checkboxy i radio w Gas Quality */
[data-theme="dark"] input[type="checkbox"],
[data-theme="dark"] input[type="radio"] {
    accent-color: var(--primary-color);
}

/* Etykiety */
[data-theme="dark"] label {
    color: var(--text-color);
}

/* Spany z tekstem */
[data-theme="dark"] span {
    color: inherit;
}

/* PARAMETRY panel (dla Gas Quality) */
[data-theme="dark"] [class*="param"],
[data-theme="dark"] [id*="param"] {
    color: var(--text-color) !important;
}

/* F4.21 (2026-07-23): blok „wszystkie divs z białym tłem" USUNIĘTY — w pełni pokryty
   przez skonsolidowany blok „POPUPY Z INLINE STYLES" niżej (te same warianty white/#fff). */

/* =============================================
   POPUP WYKRESÓW (produktionssteder)
   ============================================= */
[data-theme="dark"] .popup,
[data-theme="dark"] .chart-popup,
[data-theme="dark"] [class*="popup"],
[data-theme="dark"] div[style*="position: fixed"][style*="background"],
[data-theme="dark"] div[style*="position:fixed"][style*="background"] {
    background-color: var(--card-bg) !important;
    color: var(--text-color) !important;
}

/* F4.21: blok „popup z białym tłem inline" USUNIĘTY — pokryty przez skonsolidowany
   blok „POPUPY Z INLINE STYLES" niżej (#ffffff łapie się przez wariant background:#fff). */

/* Nagłówki i teksty w popup */
[data-theme="dark"] .popup h3,
[data-theme="dark"] .popup h2,
[data-theme="dark"] .popup p,
[data-theme="dark"] .popup span,
[data-theme="dark"] .popup div {
    color: var(--text-color) !important;
}

/* Popup tła z użyciem rgba */
[data-theme="dark"] div[style*="background-color: rgba(0,0,0"] {
    background-color: rgba(0, 0, 0, 0.7) !important;
}

/* =============================================
   GAS QUALITY - LISTA PARAMETRÓW (CZYTELNOŚĆ)
   ============================================= */

/* Panel parametrów - cały kontener */
[data-theme="dark"] .gq-left,
[data-theme="dark"] .gq-params-container,
[data-theme="dark"] .params-list,
[data-theme="dark"] #params-container,
[data-theme="dark"] [class*="params-"] {
    background-color: var(--card-bg) !important;
    color: #f5f5f5 !important;
}

/* Elementy listy parametrów - tekst ZAWSZE widoczny */
[data-theme="dark"] .gq-param-item,
[data-theme="dark"] .param-item,
[data-theme="dark"] .param-row,
[data-theme="dark"] [class*="param-item"],
[data-theme="dark"] [class*="param-row"] {
    color: #e8e8e8 !important;
}

/* Label przy checkboxach */
[data-theme="dark"] .gq-param-item label,
[data-theme="dark"] .param-item label,
[data-theme="dark"] .param-row label,
[data-theme="dark"] input[type="checkbox"]+label,
[data-theme="dark"] input[type="checkbox"]~span,
[data-theme="dark"] input[type="checkbox"]~label {
    color: #e8e8e8 !important;
    opacity: 1 !important;
}

/* Span z nazwą parametru */
[data-theme="dark"] .gq-left span,
[data-theme="dark"] .gq-params span,
[data-theme="dark"] .param-name,
[data-theme="dark"] [class*="param"] span {
    color: #e8e8e8 !important;
}

/* Hover na parametrach - jaśniejszy */
[data-theme="dark"] .gq-param-item:hover,
[data-theme="dark"] .param-item:hover,
[data-theme="dark"] .param-row:hover {
    background-color: var(--accent-light) !important;
    color: #ffffff !important;
}

/* Przyciski Alle/Ingen */
[data-theme="dark"] .gq-left button,
[data-theme="dark"] .params-buttons button,
[data-theme="dark"] button[onclick*="selectAll"],
[data-theme="dark"] button[onclick*="selectNone"] {
    background-color: var(--secondary-color) !important;
    color: var(--text-color) !important;
    border-color: var(--card-border) !important;
}

/* Kontener wykresu Gas Quality */
[data-theme="dark"] .gq-right,
[data-theme="dark"] .gq-chart,
[data-theme="dark"] #gq-chart-container {
    background-color: var(--card-bg) !important;
}

/* Tytuł w Gas Quality */
[data-theme="dark"] .gq-title,
[data-theme="dark"] #gq-title {
    color: var(--text-color) !important;
}

/* Wszystkie inputy i selecty w Gas Quality */
[data-theme="dark"] .main-content select,
[data-theme="dark"] .main-content input[type="text"],
[data-theme="dark"] .main-content input[type="number"] {
    background-color: var(--input-bg) !important;
    color: var(--text-color) !important;
    border-color: var(--input-border) !important;
}

/* =============================================
   INSTALACJE - POPUP WYKRESU
   ============================================= */

/* Popup instalacji z inline styles */
[data-theme="dark"] div[style*="position: relative"][style*="background-color: white"],
[data-theme="dark"] div[style*="position:relative"][style*="background-color:white"],
[data-theme="dark"] div[style*="background-color: white"][style*="border-radius"] {
    /* F4.21: tokenizowane (było #1a1a1a/#f5f5f5) */
    background-color: var(--card-bg) !important;
    color: var(--text-color) !important;
}

/* Canvas na ciemnym tle ma ciemny tekst - napraw */
[data-theme="dark"] canvas {
    color-scheme: dark;
}

/* Inputs w popup */
[data-theme="dark"] .popup input,
[data-theme="dark"] .popup select {
    background-color: var(--input-bg) !important;
    color: var(--text-color) !important;
    border-color: var(--input-border) !important;
}

/* =============================================
   SERVICE TABLE - LEPSZE KOLORY
   ============================================= */
[data-theme="dark"] .service-table,
[data-theme="dark"] #service-container table {
    background-color: #1e1e1e !important;
}

[data-theme="dark"] .service-table td,
[data-theme="dark"] .service-table th,
[data-theme="dark"] #service-container td,
[data-theme="dark"] #service-container th {
    color: #e8e8e8 !important;
    border-color: #444 !important;
}

[data-theme="dark"] .service-table tr,
[data-theme="dark"] #service-container tr {
    background-color: #252525 !important;
}

[data-theme="dark"] .service-table tr:nth-child(even),
[data-theme="dark"] #service-container tr:nth-child(even) {
    background-color: #2d2d2d !important;
}

/* (usunięte 2026-07-23, fix hovera) — podmiana tła na hover niszczyła kontrast
   z inline-kolorami tekstu; globalny [data-theme="dark"] tr:hover wyżej robi
   teraz brightness() zamiast podmiany tła. */

/* =============================================
   TOP 10 - PRZYCISKI I KONTROLNIKI
   ============================================= */
/* =============================================
   MONTH SELECTOR - STRZAŁKI I SLIDER
   ============================================= */
/* 2026-09-16: .month-nav / .month-prev / .month-next usuniete (martwe od F4.20, brak w markupie) */
[data-theme="dark"] [class*="month-selector"] {
    background-color: #1e1e1e !important;
    border-color: #444 !important;
}

/* Slider (legacy) */
[data-theme="dark"] input[type="range"] {
    background-color: #2d2d2d !important;
}

[data-theme="dark"] input[type="range"]::-webkit-slider-track {
    background: #3a3a3a !important;
}

[data-theme="dark"] input[type="range"]::-webkit-slider-thumb {
    background: #4CAF50 !important;
}

/* Chart scrollbar (dark) */
[data-theme="dark"] .chart-scrollbar-track {
    background: #2d2d2d;
}

[data-theme="dark"] .chart-scrollbar-thumb {
    background: #4CAF50;
}

/* =============================================
   STATUS HISTORY - WIĘKSZA CZCIONKA
   ============================================= */
[data-theme="dark"] .status-history-modal,
[data-theme="dark"] #status-history-modal,
[data-theme="dark"] [id*="history-modal"] {
    background-color: #1e1e1e !important;
}

[data-theme="dark"] .status-history-modal table,
[data-theme="dark"] #status-history-modal table {
    font-size: 14px !important;
}

[data-theme="dark"] .status-history-modal td,
[data-theme="dark"] .status-history-modal th,
[data-theme="dark"] #status-history-modal td,
[data-theme="dark"] #status-history-modal th {
    padding: 10px 15px !important;
    color: #e8e8e8 !important;
}

/* =============================================
   INSTALLATION PAGE - TOP BAR I WYKRES
   ============================================= */
[data-theme="dark"] .top-bar,
[data-theme="dark"] .page-title,
[data-theme="dark"] .installation-header {
    background-color: #1a1a1a !important;
    color: #e8e8e8 !important;
}

/* Legenda wykresu (2026-09-16: martwy .legend-label usuniety; .legend-item jest ZYWY - nie ruszac) */
[data-theme="dark"] [class*="legend"] span {
    color: #d0d0d0 !important;
}

/* =============================================
   KAFELEK POGODY - CIEMNIEJSZY
   ============================================= */
[data-theme="dark"] .stat-box[onclick*="Weather"],
[data-theme="dark"] .stat-box[onclick*="weather"],
[data-theme="dark"] .stat-box[onclick*="Forecast"],
[data-theme="dark"] [onclick*="showWeatherForecast"] {
    background: linear-gradient(135deg, #1e3a3a 0%, #1a2a2a 100%) !important;
    border-color: #2a4a4a !important;
}

[data-theme="dark"] .stat-box[onclick*="showWeatherForecast"] .stat-value {
    color: #70c0c0 !important;
    -webkit-text-fill-color: #70c0c0 !important;
}

[data-theme="dark"] .stat-box[onclick*="showWeatherForecast"] .stat-trend {
    color: #60b0b0 !important;
}

/* =============================================
   POPUPY Z INLINE STYLES - CIEMNE TŁO
   ============================================= */
[data-theme="dark"] div[style*="background-color:white"],
[data-theme="dark"] div[style*="background: white"],
[data-theme="dark"] div[style*="background:#fff"],
[data-theme="dark"] div[style*="background-color: #fff"],
[data-theme="dark"] div[style*="background-color:#ffffff"],
[data-theme="dark"] div[style*="background-color: #ffffff"] {
    /* F4.21: JEDYNY blok inline-white po konsolidacji (3→1) + tokenizowany
       (było #1e1e1e/#e8e8e8). Łapie m.in. 4 statyczne modale index.php
       (hasło/alerty/benchmark/dokumenty) do czasu ich konwersji na .gf-modal-card. */
    background-color: var(--card-bg) !important;
    color: var(--text-color) !important;
}

/* Popup pogody */
[data-theme="dark"] #weather-modal,
[data-theme="dark"] #weather-modal>div {
    background-color: #1e1e1e !important;
    color: #e8e8e8 !important;
}

[data-theme="dark"] #weather-modal .ticker-title,
[data-theme="dark"] #weather-modal [style*="background: #e0f7fa"],
[data-theme="dark"] #weather-modal [style*="background:#e0f7fa"] {
    background: linear-gradient(135deg, #1e3a3a 0%, #2a4a4a 100%) !important;
    color: #70c0c0 !important;
}

[data-theme="dark"] #weather-modal thead,
[data-theme="dark"] #weather-modal [style*="background: #b2ebf2"] {
    background: #1e3a3a !important;
    color: #70c0c0 !important;
}

[data-theme="dark"] #weather-modal tbody tr {
    background-color: #252525 !important;
}

[data-theme="dark"] #weather-modal tbody tr:nth-child(even) {
    background-color: #2d2d2d !important;
}

/* =============================================
   SUBSTRATE HISTORY MODAL
   ============================================= */
[data-theme="dark"] #substrate-history-modal,
[data-theme="dark"] #substrate-history-modal>div {
    background-color: #1e1e1e !important;
    color: #e8e8e8 !important;
}

[data-theme="dark"] #substrate-history-modal table {
    background-color: #252525 !important;
}

[data-theme="dark"] #substrate-history-modal thead {
    background-color: #2c5530 !important;
}

[data-theme="dark"] #substrate-history-modal th {
    color: #90d090 !important;
}

[data-theme="dark"] #substrate-history-modal td {
    color: #e8e8e8 !important;
    border-color: #444 !important;
}

/* =============================================
   OGÓLNE MODALNE OKNA Z BIAŁYM TŁEM INLINE
   ============================================= */
[data-theme="dark"] [style*="position: fixed"][style*="background"][style*="rgba(0,0,0"],
[data-theme="dark"] [style*="position:fixed"][style*="background"][style*="rgba(0,0,0"] {
    background-color: rgba(0, 0, 0, 0.7) !important;
}

/* Wewnętrzne boxy modali */
[data-theme="dark"] [style*="position: fixed"]>div[style*="background"],
[data-theme="dark"] [style*="position:fixed"]>div[style*="background"] {
    /* F4.21: tokenizowane (było #1e1e1e/#e8e8e8) */
    background-color: var(--card-bg) !important;
    color: var(--text-color) !important;
}

/* Nagłówki w modalach */
[data-theme="dark"] [style*="position: fixed"] h2,
[data-theme="dark"] [style*="position: fixed"] h3,
[data-theme="dark"] [style*="position:fixed"] h2,
[data-theme="dark"] [style*="position:fixed"] h3 {
    color: #4CAF50 !important;
}

/* Tabele w modalach */
[data-theme="dark"] [style*="position: fixed"] table,
[data-theme="dark"] [style*="position:fixed"] table {
    background-color: #252525 !important;
}

[data-theme="dark"] [style*="position: fixed"] th,
[data-theme="dark"] [style*="position:fixed"] th {
    background-color: #1e3a1e !important;
    color: #90d090 !important;
}

[data-theme="dark"] [style*="position: fixed"] td,
[data-theme="dark"] [style*="position:fixed"] td {
    color: #e0e0e0 !important;
    background-color: #2a2a2a !important;
}

/* =============================================
   SERVICE TABLE - WIERSZE Z INLINE COLORS
   Zachowaj jasne tło, użyj ciemnego tekstu
   Inline style: style="background:rgb(...)"
   ============================================= */
/* Wszystkie td wewnątrz tr z inline background - ciemny tekst */
[data-theme="dark"] tr[style*="background:rgb"] td,
[data-theme="dark"] tr[style*="background: rgb"] td,
[data-theme="dark"] tr[style*="background:#"] td {
    color: #1a1a1a !important;
}

/* Także span/div wewnątrz tych komórek */
[data-theme="dark"] tr[style*="background:rgb"] td span,
[data-theme="dark"] tr[style*="background:rgb"] td div,
[data-theme="dark"] tr[style*="background: rgb"] td span,
[data-theme="dark"] tr[style*="background: rgb"] td div {
    color: #1a1a1a !important;
}

/* =============================================
   TOP 10 - NAWIGATOR MIESIĘCY (.gf-nav .gf-current)
   HTML: <div class="gf-current" id="m-cur">2024-12</div>
   ============================================= */
[data-theme="dark"] .gf-current,
[data-theme="dark"] #m-cur,
[data-theme="dark"] #y-cur {
    color: #ffffff !important;
}

/* Przyciski w nawigatorze */
[data-theme="dark"] .gf-nav .gf-btn,
[data-theme="dark"] .gf-nav button {
    color: #e0e0e0 !important;
    background-color: #333 !important;
    border-color: #555 !important;
}

/* =============================================
   CHART LEGEND - #legend-fixed (renderFixedLegend)
   HTML: <ul><li><span [color box]></span><span>[text]</span></li>...</ul>
   ============================================= */
/* Ciemny tekst na jasnym/białym pasku legendy */
[data-theme="dark"] #legend-fixed li>span:last-child,
[data-theme="dark"] #legend-fixed span:not([style*="background"]) {
    color: #1a1a1a !important;
}

/* Caly kontener legendy - zachowaj jasne tlo, ciemny tekst */
[data-theme="dark"] #legend-fixed {
    color: #1a1a1a !important;
}

[data-theme="dark"] #legend-fixed li {
    color: #1a1a1a !important;
}

/* =============================================
   MAP POPUP - LAYOUT (LISTA)
   Wymuszenie układu listy dla statystyk w popupie
   ============================================= */
#popup-content .stats-container {
    display: flex !important;
    flex-direction: column !important;
    gap: 8px !important;
    margin-bottom: 20px !important;
}

#popup-content .stat-box {
    width: 100% !important;
    min-height: auto !important;
    flex-direction: row !important;
    justify-content: space-between !important;
    align-items: center !important;
    padding: 10px 15px !important;
    text-align: left !important;
}

#popup-content .stat-title {
    margin-bottom: 0 !important;
    text-align: left !important;
    font-size: 14px !important;
}

#popup-content .stat-value {
    text-align: right !important;
    font-size: 16px !important;
}

/* =============================================
   MAP POPUP - SEKCJA ENGINE-STATUSES (status.js)
   Jasne tło z ciemnym tekstem (zachowujemy z poprzedniej zmiany)
   ============================================= */
[data-theme="dark"] .engine-statuses {
    background: #e8e8e8 !important;
    color: #1a1a1a !important;
}

[data-theme="dark"] .engine-statuses h3 {
    color: #006400 !important;
}

[data-theme="dark"] .engine-statuses span,
[data-theme="dark"] .engine-status-row span {
    color: #1a1a1a !important;
}

/* =============================================
   MAP POPUP - STATS-CONTAINER i STAT-BOX (map.js)
   Jasne tło z ciemnym tekstem dla widoczności
   ============================================= */
[data-theme="dark"] #popup-content .stats-container,
[data-theme="dark"] #popup-content .stat-box {
    background: #f0f0f0 !important;
    color: #1a1a1a !important;
}

[data-theme="dark"] #popup-content .stat-title,
[data-theme="dark"] #popup-content .stat-value {
    color: #1a1a1a !important;
}

[data-theme="dark"] #popup-content p {
    color: var(--text-color) !important;
}

/* =============================================
   CHART DETAIL POPUP / MODAL (top10 klik w wykres)
   ============================================= */
[data-theme="dark"] .chart-detail-popup,
[data-theme="dark"] .chart-detail-modal,
[data-theme="dark"] #chart-detail-popup {
    background-color: var(--card-bg) !important;
    color: var(--text-color) !important;
}

/* Tabela w popupie szczegółów wykresu */
[data-theme="dark"] .chart-detail-popup table,
[data-theme="dark"] .chart-detail-modal table,
[data-theme="dark"] #chart-detail-popup table {
    background-color: var(--card-bg) !important;
    color: var(--text-color) !important;
}

[data-theme="dark"] .chart-detail-popup td,
[data-theme="dark"] .chart-detail-popup th,
[data-theme="dark"] .chart-detail-modal td,
[data-theme="dark"] .chart-detail-modal th {
    background-color: var(--card-bg) !important;
    color: var(--text-color) !important;
    border-color: var(--card-border) !important;
}

/* =============================================
   FIX 2026-03-26: Dark mode — 6 poprawek
   ============================================= */

/* 1. Pasek pogodowy/tickery — bialy bg na ciemny */
[data-theme="dark"] .inline-ticker {
    background: var(--card-bg) !important;
    border-color: var(--card-border) !important;
}

[data-theme="dark"] .ticker-node .node-name {
    color: #b0b0b0 !important;
}

[data-theme="dark"] .ticker-node .node-val {
    color: #e0e0e0 !important;
}

/* 2. Ramka mapy — ciemniejsza (background nie background-color!) */
[data-theme="dark"] .map-container,
[data-theme="dark"] .map-card {
    background: var(--card-bg) !important;
    border: 1px solid var(--card-border) !important;
}

/* 3. Ramka wykresu miesięcznego — ciemniejsza */
[data-theme="dark"] .chart-card,
[data-theme="dark"] .monthly-chart-card,
[data-theme="dark"] #monthly-chart-container,
[data-theme="dark"] .dash-right .chart-container {
    background: var(--card-bg) !important;
    border: 1px solid var(--card-border) !important;
}

/* 4. Top10 popup — tekst kWh na stacked bar */
[data-theme="dark"] #chart-modal .stacked-total,
[data-theme="dark"] #chart-modal td,
[data-theme="dark"] #chart-modal th,
[data-theme="dark"] #chart-modal span {
    color: var(--text-color) !important;
}

[data-theme="dark"] #chart-modal table {
    background-color: var(--card-bg) !important;
}

[data-theme="dark"] #chart-modal tr:nth-child(even) {
    background-color: #252525 !important;
}

/* 5. Produktionssteder — tlo wykresu */
[data-theme="dark"] #prod-sites-container,
[data-theme="dark"] .prod-chart-container,
[data-theme="dark"] #comparison-chart-container,
[data-theme="dark"] [id*="prod-sites"] {
    background: var(--card-bg) !important;
    border: 1px solid var(--card-border) !important;
}

/* 6. Instalacja — tlo wykresu */
[data-theme="dark"] .installation-view,
[data-theme="dark"] .installation-chart-wrapper,
[data-theme="dark"] .inst-monthly-chart,
[data-theme="dark"] [id*="inst-chart"] {
    background: var(--card-bg) !important;
    border: 1px solid var(--card-border) !important;
}/* =====================================================================
   STRONA STARTOWA — widok dla niezalogowanych (2026-09-25)
   Klasa `strona-startowa` na <body> ustawia index.php, gdy serwer odpowie
   na `me` 401 (gość bez sesji). Do 2026-09-25 te same reguły miało konto
   `demo` (plik `demo.css`, klasa `role-demo`) — konto wycofane.
   Plan: PLAN_PUBLICZNY_DASHBOARD.md.
   ⚠️ Te reguły to wygląd, NIE ochrona: danych pilnuje api.php (gość dostaje
      wyłącznie zbiór publiczny z `data/public/`).
   ===================================================================== */

/* Bez nawigacji i ustawień — ze strony startowej jedyna droga dalej to „Log ind". */
.strona-startowa .sidebar,
.strona-startowa #sidebar,
.strona-startowa #hamburger-btn,
.strona-startowa .sidebar-overlay,
.strona-startowa #admin-gear,
.strona-startowa #menu-buttons {
    display: none !important;
}

.strona-startowa .content {
    grid-template-columns: 1fr !important;
}

.strona-startowa .main-content {
    width: 100% !important;
    padding: 20px;
}

/* Przycisk „Log ind” — JEDYNE wyjście ze strony startowej, więc ma być widoczny od razu
   (prośba usera 2026-09-25: „bardziej widoczna, większa i w kolorze”). Wcześniej była tu
   ikona 32×32 z `assets/login.png` — a to w rzeczywistości ilustracja całej biogazowni,
   do tego szara (`.header-icon-img`) i odwracana w trybie ciemnym (`base.css`), czyli
   nieczytelna plama. Treść przycisku (ikona SVG + napis `logIn`) wstawia index.php. */
.strona-startowa #logout-btn.przycisk-log-ind {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin-left: 14px !important;
    padding: 9px 18px 9px 14px;
    min-height: 42px;
    box-sizing: border-box;
    background: var(--primary-color);
    color: var(--primary-contrast);
    border-radius: 999px;
    font-size: 15px;
    font-weight: 700;
    line-height: 1;
    white-space: nowrap;
    box-shadow: var(--shadow-md);
    /* base.css odwraca kolory #logout-btn w trybie ciemnym (dla ikon PNG) — tu nie wolno */
    filter: none !important;
    transition: background 0.2s, transform 0.2s, box-shadow 0.2s;
}

.strona-startowa #logout-btn.przycisk-log-ind svg {
    width: 20px;
    height: 20px;
    flex-shrink: 0;
}

.strona-startowa #logout-btn.przycisk-log-ind:hover {
    background: var(--primary-hover);
    box-shadow: var(--shadow-lg);
    transform: translateY(-1px);
}

.strona-startowa #logout-btn.przycisk-log-ind:focus-visible {
    outline: 3px solid var(--accent-border);
    outline-offset: 2px;
}

@media (max-width: 480px) {
    .strona-startowa #logout-btn.przycisk-log-ind {
        padding: 8px 12px 8px 10px;
        font-size: 14px;
        gap: 6px;
    }
}

/* Bez interakcji: kafelki, mapa i wykresy są tylko do oglądania */
.strona-startowa .kafelek-clickable {
    pointer-events: none !important;
    cursor: default !important;
}

.strona-startowa .leaflet-interactive {
    pointer-events: none !important;
}

.strona-startowa canvas {
    pointer-events: none !important;
}

.strona-startowa .chart-subtitle {
    display: none !important;
}

/* Ikona dokumentów (książka) — gość nie ma czego tam oglądać. Ukrycie tutaj jest
   zabezpieczeniem fail-closed: działa nawet gdy main.js się nie doładuje.
   Prawdziwa blokada siedzi w api.php (`case 'documents'` → 401 bez sesji). */
.strona-startowa #docs-btn {
    display: none !important;
}

/* Mapa jako gotowy obrazek zamiast Leafleta — dzięki temu do przeglądarki
   nie idą ŻADNE współrzędne instalacji (pomysł usera 2026-09-04).
   Obrazek generuje `scripts/build_public_map.py` na QNAP. */
.strona-startowa #map {
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    background: var(--card-bg);
}

.strona-startowa #map img.mapa-publiczna {
    width: 100%;
    height: 100%;
    /* `contain`, nie `cover`: obrazek ma proporcje kontenera na desktopie (880x1000
       vs ~530x600 px), ale na wąskim ekranie kontener robi się szeroki i niski —
       `cover` obcinałby wtedy górę i dół, czyli północną Norwegię i Danię. */
    object-fit: contain;
    border-radius: var(--radius-sm);
    /* Mapa jest ilustracją, nie kontrolką — żadnego kursora ani przeciągania */
    pointer-events: none;
    user-select: none;
}
