/* Layout mobilny koncepcji A: pasek górny (minimalny) + obszar widgetu + kciukowy pasek akcji
   + wysuwany od dołu panel asystenta. Zmienne kolorów bierzemy z motywu Radzen, żeby layout
   podążał za skórką (jasna/ciemna) zamiast mieć wpisane kolory na sztywno. */

/* Arkusz jest linkowany w każdej aplikacji (Defaults.Links), więc reguły globalne muszą aktywować się
   TYLKO gdy powłoka kompaktowa jest na stronie - inaczej zmieniłyby zachowanie desktopu. */
html:has(.m-shell),
body:has(.m-shell) {
    height: 100%;
    margin: 0;
    overscroll-behavior: none; /* bez "gumowego" przewijania całej strony na iOS */
}

/* position: fixed, a nie zwykły przepływ: MainLayout renderuje przed powłoką hosty dialogów
   (RadzenComponents, MudThemeProvider/DialogProvider/SnackbarProvider). Każdy piksel ich wysokości
   zsuwałby powłokę w dół i ucinał dolny pasek akcji poza ekranem. */
.m-shell {
    position: fixed;
    inset: 0;
    display: flex;
    flex-direction: column;
    height: 100dvh; /* dvh, nie vh - pasek adresu Safari zmienia wysokość widoku */
    background: var(--rz-base-background-color, #f5f5f5);
    color: var(--rz-text-color, #1a1a1a);

    /* Wysokość uchwytu szuflady w JEDNYM miejscu: wchodzi i w sam uchwyt, i w wyliczenie wysokości
       zadokowanego panelu, więc rozjazd tych dwóch wartości ucinałby sekcję minimalną. */
    --m-grip-h: 2rem;

    /* Wysokość pola wpisywania w zadokowanym panelu - i zarazem podglądu rozmowy, który go zastępuje
       na czas odpowiedzi. Jedna wartość dla obu, więc podmiana nie rusza wysokości doku. */
    --m-peek-h: 5rem;

    /* Wysokość zadokowanego panelu: sekcja minimalna (mierzona w JS), uchwyt i bezpieczny margines
       dolny - w tym trybie to panel jest przy krawędzi ekranu, bo pasek akcji znika. Ta sama wartość
       steruje wysokością szuflady i rozpórką skracającą okno główne. */
    --m-dock-h: calc(var(--m-minimal-h, 0px) + var(--m-grip-h) + env(safe-area-inset-bottom));
}

/* ---------- pasek górny ---------- */

.m-topbar {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .5rem;
    padding: max(env(safe-area-inset-top), .25rem) .75rem .25rem .75rem;
    /* Zmienne NAGŁÓWKA motywu, nie primary: komponenty wstawiane w pasek (np. menu użytkownika)
       malują się kolorem nagłówka, więc przy własnym tle zostawał na nim obcy prostokąt. */
    background: var(--rz-header-background-color, var(--rz-primary, #3f51b5));
    color: var(--rz-header-color, #fff);
    min-height: 3rem;
}

.m-topbar-title {
    font-size: 1.05rem;
    font-weight: 600;
    letter-spacing: .02em;
}

.m-topbar-actions {
    display: flex;
    align-items: center;
    gap: .25rem;
}

/* Menu użytkownika: na wąskim pasku wystarczy sam login, awatar tylko zabiera miejsce. */
.m-topbar .rz-gravatar {
    display: none !important;
}

/* ---------- obszar treści (widget) ---------- */

.m-body {
    flex: 1 1 auto;
    min-height: 0;          /* bez tego flex-dziecko nie chce się skracać i scroll ucieka na body */
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    padding: .5rem;
}

/* ---------- zachęta do instalacji na ekranie głównym ---------- */

/* Karta, nie ikona w pasku: instalacja to czynność jednorazowa, która potrzebuje nazwy i krótkiego
   uzasadnienia. Kolor akcentu bierzemy z motywu, więc karta podąża za skórką. */
.m-install-card {
    display: flex;
    align-items: center;
    gap: .75rem;
    margin: .75rem 0;
    padding: .75rem;
    border: 1px solid var(--rz-primary, #3f51b5);
    border-radius: .5rem;
    /* Delikatne wyróżnienie tła bez zgadywania odcienia skórki - półprzezroczysty akcent działa
       tak samo na jasnej i ciemnej. */
    background: color-mix(in srgb, var(--rz-primary, #3f51b5) 8%, transparent);
}

/* Przycisk nie kurczy się poniżej swojej etykiety - inaczej napis był ucinany. */
.m-install-card .rz-button {
    flex-shrink: 0;
}

.m-install-text {
    display: flex;
    flex-direction: column;
    /* Minimalna szerokość 0 pozwala tekstowi zawijać się zamiast wypychać przycisk poza ekran. */
    min-width: 0;
    flex: 1 1 auto;
}

.m-install-title {
    font-weight: 600;
}

.m-install-hint {
    font-size: .8rem;
    opacity: .75;
}

/* Zamknięcie zachęty. Wyciszone i mniejsze od przycisku instalacji, bo to akcja drugiego planu -
   karta ma nakłaniać do instalacji, a nie stawiać obie odpowiedzi na równi. Pole dotyku zostaje
   pełnowymiarowe, mimo małej ikony. */
.m-install-dismiss {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 2rem;
    height: 2rem;
    padding: 0;
    border: 0;
    background: transparent;
    color: inherit;
    opacity: .6;
    cursor: pointer;
}

.m-install-dismiss:active {
    opacity: .3;
}

.m-install-dismiss .rz-icon,
.m-install-dismiss .notranslate {
    font-size: 1.125rem;
}

/* ---------- rozpórka pod zadokowaną sekcję minimalną ---------- */

/* Szuflada jest position: fixed, więc nie zabiera miejsca w układzie. Rozpórka rezerwuje dokładnie
   tyle, ile zajmuje zadokowana sekcja minimalna - dzięki temu okno główne KURCZY się zamiast chować
   swój dół pod panelem. Zmienia się razem z panelem (ta sama krzywa i czas), więc widget i panel
   ruszają się jak jeden element. */
.m-dock-spacer {
    flex: 0 0 0px;
    transition: flex-basis .22s ease;
}

.m-shell--docked .m-dock-spacer {
    flex-basis: var(--m-dock-h);
}

/* ---------- dolny pasek akcji ---------- */

/* Pasek akcji celowo NIE korzysta z odcieni palety (base-100/200/300): ich jasność zmienia się
   między skórkami i przy ciemnej pasek zlewał się z tłem, a przyciski przyjmowały jego kolor.
   Bierzemy tylko dwie pewne wartości - tło i kolor tekstu strony - a stany rozróżniamy
   przezroczystością i kolorem primary. */
.m-actionbar {
    flex: 0 0 auto;
    display: flex;
    justify-content: space-around;
    align-items: stretch;
    gap: .25rem;
    padding: .25rem .5rem max(env(safe-area-inset-bottom), .25rem) .5rem;
    background: var(--rz-base-background-color, #fff);
    color: var(--rz-text-color, #1a1a1a);
    /* Rozdzielenie od treści bez zgadywania odcienia ramki - półprzezroczysty szary
       jest widoczny i na jasnym, i na ciemnym tle. */
    border-top: 1px solid rgba(128, 128, 128, .25);
}

.m-action {
    flex: 1 1 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: .1rem;
    min-height: 3.25rem;    /* kciukowy cel dotykowy (>=44 px) */
    padding: .35rem .25rem;
    border: 0;
    border-radius: .5rem;
    background: transparent;
    color: inherit;         /* kolor tekstu strony - czytelny w każdej skórce */
    opacity: .65;           /* stan nieaktywny sygnalizujemy przygaszeniem, nie innym kolorem */
    cursor: pointer;
}

.m-action:active {
    opacity: .4;
}

.m-action--active {
    color: var(--rz-primary, #3f51b5);
    opacity: 1;
    /* Wskaźnik zamiast wypełnienia tłem - nie wymaga odcienia pasującego do skórki. */
    box-shadow: inset 0 2px 0 var(--rz-primary, #3f51b5);
}

/* Kafel maluje się kolorem wyliczonym przez deskryptor panelu (IconStyleResolver) - tym samym,
   którym powłoka desktopowa maluje przycisk w nagłówku: czerwień gdy mikrofon nagrywa, pomarańcz
   gdy sesja jest wyciszona. Konkretny odcień wchodzi zmienną --m-action-accent ustawianą na kaflu,
   więc tutaj nie ma listy stanów do utrzymywania. Ma pierwszeństwo przed stanem otwarcia -
   informacja o pracującym mikrofonie jest ważniejsza niż to, który panel jest na wierzchu.
   Stan niesie sam kolor ikony i podpisu; kreska nad kaflem odpada, bo przy mikrofonie tylko
   zaśmiecała pasek. */
.m-action--accent,
.m-action--active.m-action--accent {
    color: var(--m-action-accent);
    opacity: 1;
    box-shadow: none;
}

.m-action .rz-icon,
.m-action .rzi {
    font-size: 1.5rem;
}

.m-action-label {
    font-size: .7rem;
    line-height: 1;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ---------- wysuwany panel (bottom sheet) ---------- */

/* Panel ma trzy stany: pełny ekran, sekcja minimalna zadokowana nad paskiem akcji i schowany.
   Przy pełnym ekranie tło nie jest widoczne, więc nie ma przesłony do klikania. */
.m-sheet {
    position: fixed;
    left: 0;
    right: 0;
    /* Kotwica ZAWSZE przy dolnej krawędzi. Z ustawionym `top` układ jest nadokreślony, przeglądarka
       ignoruje `bottom` i panel przy zmianie rozmiaru rósłby od GÓRNEJ krawędzi ekranu zamiast zwijać
       się do dołu. */
    top: auto;
    bottom: 0;
    z-index: 2000;
    display: flex;
    flex-direction: column;
    height: 100dvh;
    background: var(--rz-base-background-color, #fff);
    animation: m-sheet-in .18s ease-out;
    transition: height .22s ease, bottom .22s ease;
}

/* Sekcja minimalna: panel zwija się do własnego paska sterowania i dokuje przy dolnej krawędzi.
   Pasek akcji na ten czas znika - dwa paski jeden nad drugim zabierały miejsce oknu głównemu, a wybór
   panelu i tak nie jest wtedy potrzebny (sterowanie ma się pod ręką, a gest wraca do pełnego panelu
   albo chowa go razem z przywróceniem paska). */
.m-sheet--minimal {
    height: var(--m-dock-h);
}

.m-shell--docked .m-actionbar {
    display: none;
}

/* Poza sekcją minimalną panel w tym trybie nie pokazuje nic - o tym, co znika, decyduje sam panel
   klasą m-panel-collapsed. */
.m-sheet--minimal .m-panel-collapsed {
    display: none !important;
}

/* Sekcja minimalna nie może się kurczyć: wysokość szuflady jest liczona z JEJ wysokości, więc
   ściśnięcie zapętliłoby pomiar (mniejsza sekcja → niższa szuflada → jeszcze mniejsza sekcja). */
.m-sheet--minimal .m-panel-minimal {
    flex: 0 0 auto;
}

/* Pole wpisywania i zastępujący je podgląd rozmowy dostają tę samą wysokość, więc podmiana odbywa
   się w miejscu, bez ruszania wysokości doku. Margines nosi kontener, a nie sama kontrolka -
   inaczej wysokości nie zgadzałyby się o ten margines. */
.m-sheet--minimal .m-minimal-input,
.m-sheet--minimal .m-minimal-peek {
    height: var(--m-peek-h);
    margin-bottom: 0.5rem;
}

.m-sheet--minimal .m-minimal-input .rz-textarea {
    height: 100%;
    margin-bottom: 0 !important;
}

.m-sheet--minimal .m-minimal-peek {
    overflow-y: auto;
    /* Poziomy pasek przewijania w pasku o wysokości 5rem zabierałby jedną trzecią widocznego tekstu -
       szersze elementy rozmowy przycinamy. */
    overflow-x: hidden;
    padding: 0 0.25rem;
    font-size: .85rem;
}

/* Zadokowany panel ma wysokość dobraną co do piksela pod swoją treść - pasek przewijania mógłby się
   pojawić już przy błędzie zaokrąglenia. */
.m-sheet--minimal .m-sheet-content {
    overflow: hidden;
}

/* Ruch jest tu informacją (panel zwija się DO paska sterowania), ale nie kosztem osób, które
   animacji nie chcą - zostaje sama zmiana stanu. */
@media (prefers-reduced-motion: reduce) {
    .m-sheet,
    .m-dock-spacer {
        transition: none;
    }

    .m-sheet {
        animation: none;
    }
}

@keyframes m-sheet-in {
    from { transform: translateY(100%); }
    to   { transform: translateY(0); }
}

/* Uchwyt gestu: cały pasek jest celem dotykowym (kreska w środku to tylko sygnał wizualny).
   touch-action: none jest KONIECZNE - bez tego przeglądarka przechwytuje ruch w pionie
   jako przewijanie i gest nigdy nie dociera do obsługi. */
.m-sheet-grip {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    height: var(--m-grip-h);
    touch-action: none;
    cursor: grab;
    /* Delikatne wyodrębnienie paska uchwytu od treści panelu. Półprzezroczysta szarość zamiast
       odcienia z palety - działa tak samo na jasnych i ciemnych skórkach, bez zgadywania odcieni. */
    background: rgba(128, 128, 128, .10);
    border-bottom: 1px solid rgba(128, 128, 128, .18);
    /* Kotwica dla przedłużenia obszaru dotyku poniżej (patrz ::after). z-index jest tu ISTOTNY:
       treść panelu leży w drzewie PO uchwycie i zawiera własne elementy pozycjonowane (kontrolki
       Radzena), które inaczej przykrywają przedłużenie i przechwytują dotknięcie. */
    position: relative;
    z-index: 2;
}

/* Obszar łapiący gest sięga NIŻEJ, niż widać uchwyt. W zainstalowanej aplikacji nad stroną nie ma paska
   przeglądarki, więc górne kilkadziesiąt pikseli ekranu należy do systemu (przeciągnięcie w dół rozwija
   powiadomienia) - palec startujący na samej kresce bywa przechwycony, zanim strona cokolwiek zobaczy.
   Niewidoczne przedłużenie sprawia, że ruch zaczęty NIŻEJ i tak trafia w uchwyt, a wygląd panelu zostaje
   bez zmian. Zdarzenia wskaźnika z pseudoelementu i tak mają za cel sam uchwyt, więc obsługa gestu
   nie wymaga żadnej zmiany.
   Wysokość to KOMPROMIS, nie zapas: przedłużenie zasłania to, co jest pod nim, a tuż pod uchwytem stoją
   nagłówki paneli z kontrolkami (wybór wątku, wybór profilu głosu). Przy pełnej wysokości uchwytu
   zabierało im górną połowę i trzeba było celować w dolną część kontrolki; połowa tyle wystarcza, by
   ruch zaczęty poniżej pasa systemowego trafił w uchwyt, a kontrolkom zabiera dwa piksele (zmierzone:
   przyciski nagłówka zaczynają się na 46 px).
   Tryb pełny WYŁĄCZNIE: zadokowana sekcja minimalna stoi przy dolnej krawędzi ekranu, z dala od pasa
   systemowego, a przedłużenie zasłaniałoby jej sterowanie. */
.m-sheet:not(.m-sheet--minimal) .m-sheet-grip::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 100%;
    height: calc(var(--m-grip-h) / 2);
    touch-action: none;
}

.m-sheet-grip:active {
    cursor: grabbing;
}

/* Kolor akcentu motywu, nie odcień szarości: przy ciemnych skórkach uchwyt zlewał się z tłem
   i nie było widać, że szufladę da się przeciągnąć. */
.m-sheet-grip-bar {
    width: 2.5rem;
    height: .25rem;
    border-radius: 999px;
    background: var(--rz-primary, #3f51b5);
}

/* Kontener treści MUSI być flexem w pionie: sloty paneli rozciągają się przez flex-grow, a bez tego
   są zwykłymi blokami o wysokości treści - panel czatu nie wypełniał wtedy szuflady, więc pole
   wpisywania i przyciski lądowały w połowie ekranu zamiast przy dolnej krawędzi. */
.m-sheet-content {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    -webkit-overflow-scrolling: touch;
}

/* Szuflada schowana: znika z ekranu, ale ZOSTAJE w drzewie - komponenty paneli mają przeżyć
   zamknięcie razem z trwającą sesją (np. rozmową głosową). */
.m-sheet--hidden {
    display: none;
}

/* Sloty paneli: wszystkie zamontowane, widoczny tylko slot otwartego panelu. Bezpieczny margines
   dolny trzyma pole wpisywania i przyciski nad krawędzią ekranu, także gdy klawiatura telefonu
   zmieni wysokość widoku. */
.m-panel-slot {
    display: none;
    width: 100%;
    padding-bottom: env(safe-area-inset-bottom);
}

.m-panel-slot--active {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
}

/* Panele były pisane pod prawy sidebar o stałej szerokości - na mobile mają wypełnić sheet
   na całą szerokość. */
.m-panel-slot > * {
    width: 100%;
}

/* Pełna wysokość TYLKO dla panelu o jednym elemencie głównym (np. asystent, który sam układa
   sobie wnętrze). Panel ustawień ma dwa elementy - pasek tytułu i treść - i wymuszenie 100%
   na każdym z nich spychało treść o cały ekran w dół, przez co panel wyglądał na pusty. */
.m-panel-slot > :only-child {
    height: 100%;
}

/* Elementy flex domyślnie nie kurczą się poniżej swojej treści (min-width: auto), więc paski
   narzędzi panelu wystawały poza wąski ekran. Zerowe min-width pozwala im się zmieścić,
   a poziomy scroll zostaje odcięty. */
.m-sheet-content,
.m-sheet-content * {
    min-width: 0;
    max-width: 100%;
}


/* Przycisk pełnego ekranu wewnątrz panelu jest w powłoce kompaktowej zbędny (i nie mieści się
   w rzędzie): tę rolę przejmuje gest przeciągnięcia uchwytu w górę. */
.m-sheet-content .hydra-fullscreen-toggle {
    display: none !important;
}

/* ─── Grid i widgety na małym ekranie ────────────────────────────────────────
   Chrom grida (picker kolumn, sumaryka, selektor rozmiaru strony) wycinamy w kodzie
   — HydraDataGrid.ApplyMobileChrome i GridComponent. Tutaj zostaje wyłącznie to,
   czego nie da się wyrazić parametrem: gęstość ramek i marginesów. */

/* Karta widgetu oddaje wewnętrzny margines na dane — na telefonie 1rem z każdej strony
   to ok. 15% szerokości ekranu. */
.m-shell .rz-card {
    --rz-card-padding: 0.5rem;
}

/* Komórki grida: Density.Compact zmniejsza wysokość wiersza, ale nie odstępy poziome. */
.m-shell .rz-data-grid {
    --rz-grid-cell-padding: 0.25rem 0.5rem;
    --rz-pager-gap: 0.125rem;
}

/* Pasek narzędzi grida ma jeden rząd: po ukryciu pickera kolumn ⋮ i lupa mieszczą się obok
   siebie, a zawijanie zostawiało je w dwóch wierszach nawet gdy było na to miejsce. */
.m-shell .sente-grid-header {
    flex-wrap: nowrap;
}

/* Menu widgetu (⋮) otwiera popup już kliknięciem głównego przycisku (AlwaysOpenPopup),
   więc segment ze strzałką jest na dotyku wyłącznie zajętym miejscem. */
.m-shell .rz-splitbutton-menubutton {
    display: none;
}

/* ---------- „wstecz" w pasku ---------- */

/* Chevron stoi przed nazwą aplikacji, więc oba elementy muszą tworzyć jedną grupę — inaczej
   justify-content: space-between paska rozrzuciłoby je po przeciwnych stronach. */
.m-topbar-brand {
    display: flex;
    align-items: center;
    gap: .125rem;
    min-width: 0;
}

/* Pole dotyku ~40 px: mniejsze trudno trafić kciukiem, większe zabiera miejsce nazwie aplikacji. */
.m-topbar-back {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    margin-left: -.5rem;   /* wyrównanie ikony do krawędzi paska, mimo pola dotyku */
    padding: 0;
    border: 0;
    background: transparent;
    color: inherit;        /* kolor nagłówka motywu, jak pozostałe elementy paska */
    cursor: pointer;
}

.m-topbar-back:active {
    opacity: .6;
}

.m-topbar-back .rz-icon,
.m-topbar-back .notranslate {
    font-size: 1.5rem;
}
