/* =====================================================================================
   Foaia de stil a aplicatiei.

   [T+B] Biblioteca de componente aduce tema (culori, tipografie, forma controalelor); ce
         se afla aici e CADRUL — asezarea in pagina, spatierea si cele cateva elemente
         care nu sunt componente (etichete de stare, antet de pagina, adnotari).

   [TEHNIC] Nimic din ce se poate obtine dintr-un parametru al componentei nu se rescrie
            aici. Regula tine foaia mica si evita ca o actualizare de biblioteca sa strice
            aspectul.
   ===================================================================================== */

html, body {
    margin: 0;
    padding: 0;
    height: 100%;
    font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
}

:root {
    /* [TEHNIC] Accentul urmareste accentul bibliotecii, cu o valoare de rezerva daca tema
       nu-l publica in contextul curent. */
    --app-accent: #0d6efd;
    --app-accent-strong: #0b5ed7;

    /* Tenta foarte deschisa pentru hover si pentru randul de sub cursor. Fixa, nu derivata
       din accent, ca sa ramana discreta pe orice tema. */
    --app-accent-soft: #eef4ff;

    --app-surface: #ffffff;       /* carduri, antet, meniu lateral */
    --app-bg: #f6f7f9;            /* fundalul zonei de continut, din spatele cardurilor */

    --app-border: #e7e9ee;        /* linii de despartire — mai deschis decat vechiul #dee2e6 */
    --app-border-strong: #d9dce2; /* aceleasi linii, unde trebuie sa se vada */

    --app-text-muted: #6c757d;

    --app-radius: 8px;            /* controale, pastila din meniu */
    --app-radius-lg: 12px;        /* carduri, container de grila */

    /* Umbre fine: prezenta, nu greutate. */
    --app-shadow-sm: 0 1px 2px rgba(16, 24, 40, .06), 0 1px 3px rgba(16, 24, 40, .04);
    --app-shadow-card: 0 1px 2px rgba(16, 24, 40, .04), 0 4px 12px rgba(16, 24, 40, .05);
    /* Umbra dialogului: mai adinca decat a cardului (pluteste peste tot ecranul), dar
       departe de umbra grea implicita a bibliotecii. */
    --app-shadow-dialog: 0 2px 8px rgba(16, 24, 40, .08), 0 16px 48px rgba(16, 24, 40, .18);

    --app-gap: 20px;             /* distanta dintre carduri stivuite */
    /* [T+B] Marginea zonei de continut, COMPACTA: 12px sus/jos, 10px stanga/dreapta (era 28px peste tot) —
       cerinta din 2026-09-21, ca grila sa aiba cat mai multa latime. E o valoare prescurtata de
       `padding`, cu doua componente: se foloseste ca atare, nu se combina cu alte unitati. */
    --app-content-pad: 12px 10px;
}

/* ── cadrul: antet fix, meniu lateral, continut derulabil ──────────────────────────── */

.app-shell {
    display: flex;
    flex-direction: column;
    flex: 1 1 0;
    min-height: 0;
}

/* [TEHNIC] Cadrul NU mai are `height: 100vh` (2026-10-09). Banda de evaluare a bibliotecii (`<dx-license>`,
   primul copil al lui `body`, ~54px) statea DEASUPRA unui cadru inalt cat toata fereastra, deci documentul
   iesea cu inaltimea ei mai lung decat ecranul: paginatorul unei grile cat pagina (`app-fill-page`) si
   butoanele de jos cadeau sub fereastra, cu o a doua bara de derulare, a browserului. Acum `body` e coloana
   inalta cat fereastra, iar cadrul ia ce ramane sub banda; fara banda (licenta instalata) ia tot, ca inainte.
   Fara inaltime scrisa in pixeli: banda se poate rupe pe doua randuri pe o fereastra ingusta.
   Paginile de autentificare au alt `body` (`app-auth-body`) si nu sunt atinse.
   [TEHNIC] FARA `:has()` — prima forma era `body:has(> dx-license)` si a fost scoasa in aceeasi zi: vezi
   capcana de la `.app-fill-page`. */
body:not(.app-auth-body) { display: flex; flex-direction: column; height: 100vh; }

.app-header {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 20px;
    background: var(--app-surface);
    /* [TEHNIC] Umbra fina in loc de bordura dura de 1px: desparte antetul de continut fara
       o linie care taie ecranul dintr-o parte in alta. `position` + `z-index` ca umbra sa
       cada PESTE meniul si continutul de dedesubt, nu sub ele. */
    box-shadow: var(--app-shadow-sm);
    position: relative;
    z-index: 20;
    flex: 0 0 auto;

    /* [BUSINESS] Varianta translucida, DEZACTIVATA. Se activeaza mutand cele doua linii de
       mai jos peste `background` de sus. E antetul nostru, nu o componenta a bibliotecii —
       risc zero.
    background: rgba(255, 255, 255, .78);
    backdrop-filter: blur(10px);
    */
}

.app-title { margin: 0; font-size: 17px; font-weight: 600; }
.app-header-spacer { flex: 1; }

.app-body { display: flex; flex: 1; min-height: 0; }

.app-sidebar {
    width: 260px;
    flex: 0 0 260px;
    border-right: 1px solid var(--app-border);
    overflow-y: auto;
    background: var(--app-surface);
    transition: flex-basis .15s ease, width .15s ease;
    padding: 8px 0 0;

    /* [T+B] Coloana, ca semnatura produsului (`.app-brand`) sa stea jos, lipita de marginea meniului,
       oricat de scurt ar fi meniul. Vezi `SidebarBrand`. */
    display: flex;
    flex-direction: column;
}

/* ── semnatura produsului, jos in meniul lateral ───────────────────────────────────── */

/* [T+B] `sticky` + `margin-top: auto`: jos cand meniul e scurt, si lipita de marginea de jos a ferestrei cand
   meniul e mai lung decat ecranul si derulează — deci mereu vizibila. Fundal propriu, ca meniul sa nu se vada
   pe sub ea la derulare. */
.app-brand {
    position: sticky; bottom: 0; margin-top: auto;
    display: flex; align-items: center; gap: 8px;
    padding: 9px 16px 10px;
    background: var(--app-surface);
    border-top: 1px solid var(--app-border);
}
.app-brand-text { display: flex; flex-direction: column; line-height: 1.25; min-width: 0; }
.app-brand-text b { font-size: 13px; font-weight: 600; color: var(--app-accent-strong); letter-spacing: .2px; }
.app-brand-text small { font-size: 11px; color: var(--app-text-muted); white-space: nowrap; }

/* Marca (initialele) — doar cand meniul e strans, fiindca textul nu incape in 64px. */
.app-brand-mark {
    display: flex;
    font-size: 13px; font-weight: 700; letter-spacing: .5px; color: var(--app-accent-strong);
}
.app-sidebar-collapsed .app-brand { justify-content: center; padding: 10px 0; }
.app-sidebar-collapsed .app-brand-text { display: none; }
.app-sidebar-collapsed .app-brand-mark { display: inline; }

/* [TEHNIC] Colapsat = BANDA DE PICTOGRAME de 64px, nu ascundere totala (pana pe 2026-08-29
   era `width: 0`). Etichetele si chevroanele se ascund, pictogramele se centreaza, iar la
   hover apare un tooltip din `aria-label` — eticheta pe care biblioteca o pune deja
   TRADUSA pe fiecare item, deci zero chei noi in `.resx`.

   [TEHNIC] `overflow: visible` ca tooltipul sa iasa din banda. Meniul are cel mult 7 iteme
   de nivel 1, deci nu-i trebuie derulare cand e colapsat. Flyout-urile submeniurilor se
   randeaza intr-un portal la nivel de `body`, deci banda ingusta nu le atinge. */
.app-sidebar-collapsed { width: 64px; flex-basis: 64px; overflow: visible; }
/* Tooltipul benzii: eticheta itemului, la dreapta pictogramei, doar la hover. */
/* [TEHNIC] Fundal gri foarte fin sub continut, ca sa iasa cardurile albe in relief. */
.app-content { flex: 1; overflow-y: auto; padding: var(--app-content-pad); min-width: 0; background: var(--app-bg); }

/* [TEHNIC] Card maximizat (grila de linii a comenzii client): acopera doar `.app-content`, nu si meniul.
   `:has()` opreste derularea zonei de continut cat timp cardul e maximizat, altfel `inset: 0` s-ar
   deruula odata cu pagina. Grila ia inaltimea ramasa (`flex: 1; min-height: 0`) si deruleaza in
   interior; totalurile raman jos, vizibile. */
.app-content:has(.app-card--maximized) { position: relative; overflow: hidden; }
.app-card--maximized {
    position: absolute; inset: 0; z-index: 20; margin: 0;
    display: flex; flex-direction: column; overflow: hidden; border-radius: 0;
}
.app-card--maximized > .app-grid-lines { flex: 1 1 auto; min-height: 0; height: auto; }

/* [BUSINESS] Grila cat pagina (2026-10-09, cerinta utilizatorului, pe listele importului de facturi): la o
   lista lunga si lata, grila crestea cat toate randurile ei, iar bara de derulare orizontala ajungea tocmai
   la capatul paginii — ca sa vezi coloanele din dreapta coborai 150 de randuri. Acum grila ia exact
   inaltimea ramasa pe ecran: randurile deruleaza IN grila, iar titlurile coloanelor, bara orizontala si
   paginatorul raman mereu la vedere.
   [TEHNIC] Opt-in, in doua piese: pagina isi inveleste tot continutul in `<div class="app-fill-page">`, iar
   grila primeste `app-grid-fill` langa `app-grid` si ramane copil DIRECT al invelisului (`AppDataView` nu
   adauga niciun element in jur). Fratii grilei (antetul paginii, nota, butoanele de jos) isi pastreaza
   inaltimea; grila ia restul. Pe o fereastra foarte scunda grila se opreste la `min-height`, invelisul iese
   din zona de continut si deruleaza aceasta, in loc sa ramana o grila de doua randuri.
   [TEHNIC] CAPCANA, platita 2026-10-09: prima forma nu avea invelis, ci `.app-content:has(> .app-grid-fill)`.
   Cu regulile `:has()` in foaie, o lista de linii cu 150 de randuri (peste 1.200 de editoare, 12.000 de
   noduri) ingheta browserul ~83 s la incarcare, fata de ~14 s fara ele — masurat in Chrome, pe aceeasi
   factura. Regulile incetineau si paginile pe care NU se potriveau. De aceea aici nu exista niciun
   `:has()`, iar unul nou pe `body` sau pe `.app-content` (stramosi ai tuturor grilelor) se masoara pe o
   lista plina inainte sa fie acceptat. */
.app-fill-page { height: 100%; display: flex; flex-direction: column; }
.app-fill-page > * { flex: 0 0 auto; }
.app-fill-page > .app-grid-fill { flex: 1 1 0; min-height: 260px; }

/* [TEHNIC] O pagina „cat pagina" desenata intr-o FEREASTRA (factura deschisa din centralizatorul importului, 2026-10-09):
   `.app-fill-page` isi ia inaltimea de la parinte, iar corpul unei ferestre nu are una — cutia aceasta i-o da.
   Sta in corpul STANDARD al ferestrelor (`app-dialog-body`, pentru aceleasi margini ca peste tot), in varianta
   `--page`: corpul nu mai deruleaza el (pagina dinauntru isi deruleaza grila) si nu-si mai limiteaza inaltimea,
   fiindca i-o da cutia. Inaltimea lasa loc antetului, subsolului si marginilor ferestrei. Regula variantei sta mai
   jos in foaie, dupa `.app-dialog-body`, ca sa-i bata `max-height` si `overflow` (aceeasi specificitate). */
.app-embedded-page { height: calc(100vh - 300px); min-height: 360px; }

/* [BUSINESS] Legatura dintr-o celula de grila (componenta `CellLink`) — REGULA PERMANENTA din 2026-10-09: un text de
   celula care duce undeva (numarul unui document, numarul de linii) e un buton mic albastru cu pictograma, nu o
   legatura subliniata; intr-o grila plina de text, legatura simpla nu spunea destul de tare ca se apasa.
   [TEHNIC] Acelasi aspect pe `<a>` (navigare) si pe `<button>` (deschide o fereastra), de aceea se reseteaza ce
   aduce fiecare element de la browser. Inaltime fixa de 24px, ca randul grilei sa nu creasca din cauza lui. Textul
   lung se taie cu trei puncte in loc sa lateasca coloana. */
.app-cell-link {
    display: inline-flex; align-items: center; gap: 5px; box-sizing: border-box;
    max-width: 100%; height: 24px; padding: 0 8px;
    border: 1px solid var(--app-accent); border-radius: var(--app-radius);
    background-color: var(--app-accent-soft); color: var(--app-accent-strong);
    font: inherit; font-weight: 600; line-height: 1; text-decoration: none; white-space: nowrap; cursor: pointer;
    vertical-align: middle;
    transition: background-color .12s ease, color .12s ease;
}
.app-cell-link > span:last-child { overflow: hidden; text-overflow: ellipsis; }
.app-cell-link .mi { font-size: 15px; }
.app-cell-link:hover, .app-cell-link:focus-visible {
    background-color: var(--app-accent); color: #fff; text-decoration: none; outline: none;
}

/* [BUSINESS] Panoul „ce scrie pe factura" de sub grila de linii a unei facturi importate (2026-10-09), si fereastra
   cu toate randurile ei: tabel simplu cu coloanele FISIERULUI (difera de la un furnizor la altul).
   [TEHNIC] Panoul e frate al grilei in `.app-fill-page`, deci isi ia inaltimea din continut si grila pe cea ramasa.
   Are inaltime MINIMA fixa, cat un rand de tabel cu capul lui: altfel grila ar sari in sus si in jos la fiecare
   trecere de pe o linie cu rand original pe una fara. Tabelul nu se rupe pe randuri (`nowrap`) si deruleaza
   orizontal in cutia lui — un rand de CSV are si 30 de campuri. In fereastra, capul de tabel ramane lipit sus. */
.app-source-panel {
    margin-top: 8px; padding: 6px 8px; min-height: 92px;
    border: 1px solid var(--app-border); border-radius: var(--app-radius-lg); background: var(--app-surface);
}
.app-source-panel-head { display: flex; align-items: center; gap: 12px; margin-bottom: 4px; }
.app-source-panel-title { flex: 1; font-size: 13px; color: #6c757d; }
.app-source-scroll { overflow-x: auto; }
.app-source-scroll--all { max-height: max(200px, calc(100vh - 320px)); overflow-y: auto; }
.app-source-table { border-collapse: collapse; font-size: 13px; white-space: nowrap; }
.app-source-table th, .app-source-table td { padding: 3px 10px; border: 1px solid var(--app-border); text-align: left; }
.app-source-table th { background: #fafbfc; font-weight: 600; color: #495057; }
.app-source-scroll--all .app-source-table th { position: sticky; top: 0; }
.app-source-table tr.app-source-current td { background: var(--app-accent-soft); }
/* [BUSINESS] Celula din care vine valoarea coloanei pe care s-a dat clic in grila (2026-10-09): galben tare pentru
   sursa directa, galben pal pentru partile ei („Quant" si „QPU" la cantitate). Galben, nu albastrul accentului:
   albastrul e deja randul curent, iar aici trebuie sa sara in ochi o celula, nu un rand. Doar celula cu VALOAREA, nu si
   titlul ei de deasupra (cerinta utilizatorului): o singura pata se observa mai usor decat o coloana intreaga. */
.app-source-table td.app-source-hit { background: #ffe58a; }
.app-source-table td.app-source-hit-light { background: #fff6d1; }

/* [BUSINESS] Rand de inaltime MINIMA (`app-grid-tight`, din 2026-10-09 pe cele doua liste de linii ale importului: mai
   multe linii de factura vazute odata; opt-in, are rost doar pe grile cu editoare in celule). Refacut pe grila
   bibliotecii Syncfusion (2026-10-15, cerinta utilizatorului: „facusem pe DevExpress,
   acum randurile din facturile Olanda sunt prea mari"). Regula de DevExpress lucra prin token-ul bibliotecii vechi si
   ramasese fara efect: randul de linii iesea de 39px (editoarele de 32px de pe fiecare rand — denumire, cantitate,
   pret — plus 3px sus si jos), iar randul de lucru de 42px.
   [TEHNIC] Pe grilele de linii (`app-grid-tight`): celula fara spatiu sus si jos, editoarele bibliotecii de 28px si
   textul alegerii (`app-cell-text`) tot de 28px, ca randul obisnuit si randul de lucru sa aiba aceeasi inaltime
   (~30px). Butoanele „+" au 26px, deci incap. Restul listelor raman la 32px (`AppGrid.RowHeight`). Marginea de 2px
   pe care biblioteca o pune sus si jos pe lista de alegere se scoate: cu ea, randul de lucru iesea de 33px. */
.app-sfgrid.app-grid-tight .e-grid .e-rowcell { padding-top: 0; padding-bottom: 0; }
.app-sfgrid.app-grid-tight .e-grid .e-rowcell .e-input-group,
.app-sfgrid.app-grid-tight .e-grid .e-rowcell .e-input-group.e-control-wrapper { height: 28px; min-height: 28px; margin-top: 0; margin-bottom: 0; }
.app-sfgrid.app-grid-tight .e-grid .e-rowcell .e-input-group input.e-input,
.app-sfgrid.app-grid-tight .e-grid .e-rowcell .e-input-group.e-control-wrapper input.e-input { height: 26px; min-height: 26px; }
.app-sfgrid.app-grid-tight .app-cell-text { height: 28px; line-height: 28px; }
.app-sfgrid.app-grid-tight .app-cell-problem { margin: 0 -6px; padding: 0 6px; }

.app-menu { border: none; background: transparent; padding: 4px 0; }

/* [T+B] Grupul care CONTINE ruta curenta — pastila plina de accent, „esti aici" fara
   echivoc. Clasa `app-menu-current` o pune `NavMenu.razor` pe `AppMenuItem`, dintr-o harta
   ruta -> grup potrivita pe primul segment de cale; biblioteca de componente nu marcheaza singur ruta
   activa. Bate tenta de grup extins (un grup poate fi si curent, si deschis in acelasi
   timp). Cand meniul e banda de pictograme, pastila plina ramine cel mai bun reper. */

.app-grid,
.app-grid-lines {
    border: 1px solid var(--app-border);
    border-radius: var(--app-radius-lg);
    box-shadow: var(--app-shadow-card);
    overflow: hidden;
    background: var(--app-surface);

        /* [T+B] Rand COMPACT, in TOATE grilele (2026-09-21, proba pe /items apoi extinsa): 4px sus/jos da
       ~32px pe randurile cu text si ~41px pe cele cu butoane, fata de ~44 / ~53px la 10px. Inaltimea
       randului o decide celula cea mai inalta, deci cele cu butoane raman mai inalte. */
    /* [T+B] Spatiul stanga-dreapta din celule, MINIM — cerinta explicita (2026-09-20), coborat la
       2px pe 2026-09-21: cat mai multa latime pentru continut, in grilele cu multe coloane. Token-ul
       se aplica la antet, la celulele de date si la butoanele meniului de filtrare, deci ramane totul
       aliniat. Cel al randului de filtre (`editor-cell`) coboara odata cu el, ca editorul sa nu ramana
       decalat fata de textul de deasupra. */
}

/* [TEHNIC] Grila de linii sta DEJA intr-un `.app-card`: fara umbra proprie, altfel ar fi
   card in card. Bordura exterioara subtire ramine. */
.app-card .app-grid-lines { box-shadow: none; }

/* [T+B] Butonul de stergere apare doar la HOVER pe rand — cerinta explicita (2026-09-01),
   la fel pe toate documentele (extins la 2026-09-20, dupa proba de pe factura de vanzare). Clasa
   proprie, opt-in, NU pe `.app-grid-lines`: acela ramane comun si grilelor de
   consultare, iar o schimbare acolo ar fi mutat tacut comportamentul peste tot.
   Randurile de date n-au clasa proprie (vezi nota structurii de mai sus), deci tinta e
   orice `tr` din `tbody`. */
/* [BUSINESS] Randul evidentiat dupa ce omul salveaza un document si se intoarce la lista (2026-09-21;
   vezi AppGrid.HighlightWhen). Ramane pana la urmatorul click sau tasta — o stinge gridHighlight.js.
   [T+B] Se coloreaza CELULELE, nu `tr`: fundalul din biblioteca se pune pe `td`, cu selectoare atat de
   specifice incat un fundal pe rand n-ar fi vazut niciodata. `!important` e deliberat si ramane doar aici —
   aceeasi situatie ca in comentariul de mai sus despre variabilele bibliotecii, dar pentru o stare pe rand,
   pe care variabilele grilei nu o expun. Bara din stanga face randul gasibil chiar si pe o culoare
   estompata, cu ecran de calitate slaba. */
.app-grid tr.app-row-highlight > td {
    background-color: var(--app-accent-soft) !important;
}

.app-grid tr.app-row-highlight > td:first-child {
    box-shadow: inset 3px 0 0 var(--app-accent);
}

/* [T+B] RANDUL CURENT — cel pe care omul a dat click (`AppGrid.MarkCurrentRow`, implicit pe toate listele din
   2026-09-23, dupa proba pe articole si parteneri). DELIBERAT fara fundal: fundalul albastru e deja al evidentierii randului salvat si
   al randului de sub cursor, iar un al treilea fundal ar fi facut cele trei stari de nedeosebit. Aici: un
   contur subtire sus si jos plus bara din stanga, care raman vizibile si cand cursorul coloreaza alt rand.
   Pe `td`, ca evidentierea — randurile bibliotecii nu se stilizeaza sigur pe `tr`. */
.app-grid tr.app-row-current > td {
    box-shadow: inset 0 1px 0 var(--app-accent), inset 0 -1px 0 var(--app-accent);
}

.app-grid tr.app-row-current > td:first-child {
    box-shadow: inset 3px 0 0 var(--app-accent), inset 0 1px 0 var(--app-accent), inset 0 -1px 0 var(--app-accent);
}

.app-grid-lines--hover-actions tbody tr .app-icon-btn { opacity: 0; transition: opacity .12s ease; }
.app-grid-lines--hover-actions tbody tr:hover .app-icon-btn,
.app-grid-lines--hover-actions tbody tr:focus-within .app-icon-btn { opacity: 1; }

/* ── elementele din bara de sus ────────────────────────────────────────────────────── */

/* [BUSINESS] Firma activa e TITLUL barii (2026-09-23): `.app-title` da marimea, aici doar asezarea. */
.app-company-indicator {
    display: inline-flex; align-items: center; gap: 7px;
}
.app-company-indicator .mi { color: var(--app-accent); font-size: 20px; }

.app-lang-switcher { display: inline-flex; gap: 3px; }
.app-lang-btn { min-width: 34px !important; padding: 3px 8px !important; }

/* ── meniul utilizatorului (UserMenu): un buton pe bara, panou cu limba si iesirea ── */
.app-user-btn { max-width: 260px; }
.app-user-menu-head {
    display: flex; flex-direction: column; gap: 1px;
    padding: 2px 2px 10px; margin-bottom: 8px;
    border-bottom: 1px solid var(--app-border);
}
.app-user-menu-head span { font-size: 12px; }
/* Elementele panoului, TOATE aliniate la stanga: „Limba" (cu sub-elementele RO/EN) si Iesirea.
   [T+B] Acelasi aspect pentru `<div>`, `<button>` din limba si din formularul de iesire, ca sa para un singur meniu. */
.app-user-menu-item {
    display: flex; align-items: center; gap: 8px;
    width: 100%; padding: 6px 8px; text-align: left; cursor: pointer;
    background: none; border: 0; border-radius: 4px;
    font-size: 13px; color: #495057;
}
.app-user-menu-item:hover { background: #f1f3f5; }
.app-lang-list { display: flex; flex-direction: column; margin-bottom: 4px; }
.app-lang-item { padding-left: 20px; }
/* Bifa e mereu in loc (latimea fixa), dar se vede doar la limba curenta — textul nu sare intre elemente. */
.app-lang-check { width: 16px; font-size: 16px; visibility: hidden; }
.app-user-menu-item-current { font-weight: 600; color: var(--app-accent-strong); }
.app-user-menu-item-current .app-lang-check { visibility: visible; }
/* Latimea panoului (2026-09-23: 300px, apoi cu 30% mai ingust = 210px, la cererea utilizatorului): sta pe invelisul
   continutului, nu pe clasa ferestrei. */
.app-user-menu-content { min-width: 210px; }
/* [T+B] „Limba" cu SUBMENIU LATERAL RO/EN (cerinta din 2026-09-23): inchis pana treci cu mausul pe „Limba" (sau
   tastatura ajunge pe ea), apoi se deschide in STANGA panoului — panoul sta lipit de marginea din dreapta a
   ecranului, deci in dreapta n-ar avea loc. Zona de hover e chiar grupul; puntea `::before` acopera golul dintre
   panou si submeniu, ca mausul sa poata trece pe RO/EN fara sa-l inchida.

   [TEHNIC] Fereastra bibliotecii isi poate taia continutul la margini; de aceea containerele ei sunt puse pe
   `overflow: visible` doar pentru acest panou. Daca submeniul apare taiat, aici e locul de reglat. */
.app-user-menu-sub { position: relative; }
.app-user-menu-sub .app-lang-list {
    display: flex;
    position: absolute; top: -4px; right: calc(100% + 12px);
    min-width: 120px; margin: 0; padding: 4px;
    background: var(--app-surface); border: 1px solid var(--app-border); border-radius: 8px;
    box-shadow: var(--app-shadow-card); z-index: 60;
}
.app-user-menu-sub .app-lang-list::before {
    content: ''; position: absolute; top: 0; bottom: 0; left: 100%; width: 14px;
}
.app-user-menu-sub .app-lang-item { padding-left: 8px; }
.app-user-menu-sub-label { flex: 1; text-align: left; }
.app-user-menu-sub-chevron { font-size: 18px; color: var(--app-text-muted); }
.app-user-menu-logout { display: block; margin-top: 4px; padding-top: 6px; border-top: 1px solid var(--app-border); }

/* ── antetul unei pagini: titlu la stanga, actiuni la dreapta ──────────────────────── */

/* [T+B] Primul copil (titlul) ia tot spatiul liber, iar restul se aliniaza la dreapta, in ordinea din markup.
   Inainte era `space-between`, care la TREI copii punea al doilea la mijloc — de aceea lista comenzilor
   client avea butonul de generare pe centru. Cu `space-between` si un buton nou de coloane, fiecare lista cu
   doua butoane ar fi avut aceeasi problema. */
.app-page-header {
    display: flex; align-items: center; justify-content: flex-start;
    gap: 8px; margin-bottom: 8px; flex-wrap: wrap;
}
.app-page-header > :first-child { margin-right: auto; }
/* [T+B] Antet COMPACT (2026-09-21, proba pe /items apoi extinsa): titlu 17px, 8px pana la continut.
   Butoanele din antet sunt `SizeMode.Small`, pe fiecare in markup — inaltimea lor decide inaltimea barii. */
.app-page-header h4 { margin: 0; font-size: 17px; font-weight: 600; }
.app-page-actions { display: flex; gap: 8px; }

/* Nota explicativa de sub titlul unei pagini. */
.app-page-hint { margin: -4px 0 8px; color: #6c757d; font-size: 13px; }

/* Bara de deasupra unei liste incapsulate intr-un component (grila unui partener,
   folosita si in dialog, si ca pagina de meniu): text la stanga, buton la dreapta. */
.app-list-toolbar {
    display: flex; align-items: center; gap: 12px; margin-bottom: 12px; flex-wrap: wrap;
}
.app-list-toolbar > small { color: #6c757d; }

/* Titlu precedat de un buton (ex. sageata „inapoi"). */
.app-page-title-group { display: flex; align-items: center; gap: 8px; }

/* Bara de deasupra unei grile: filtre, cifre, actiuni pe selectie. */
.app-toolbar {
    display: flex; align-items: flex-end; gap: 16px;
    margin-bottom: 12px; flex-wrap: wrap;
}
.app-toolbar-facts { display: flex; gap: 16px; font-size: 13px; color: #495057; }

/* Un tip de document intr-o lista de bife, cu actiuni la dreapta. */
.app-type-line { display: flex; align-items: center; gap: 12px; }
.app-type-line-spacer { flex: 1; }

.app-muted { color: #6c757d; }

/* ── etichete de stare ─────────────────────────────────────────────────────────────── */

/* [TEHNIC] Marginea din stanga e implicita fiindca eticheta sta aproape mereu DUPA un text,
   in aceeasi celula („Buc  Implicita"). Cand sta singura in celula ei — coloana de sens de la
   custodie — se adauga `badge-solo`, care o anuleaza. */
.badge {
    display: inline-block; padding: 2px 10px; border-radius: 10px;
    font-size: 12px; font-weight: 600; white-space: nowrap; margin-left: 8px;
}
.badge-solo { margin-left: 0; }
.badge-success { background: #d4edda; color: #155724; }
.badge-danger  { background: #f8d7da; color: #721c24; }
.badge-warning { background: #fff3cd; color: #856404; }
.badge-info    { background: #cfe2ff; color: #084298; }
.badge-light   { background: #e9ecef; color: #495057; }

/* [BUSINESS] Textul unei alegeri pe un rand care NU e randul de lucru (liniile unei facturi importate, 2026-10-09):
   lista de alegere se deseneaza doar pe randul pe care s-a dat clic, restul arata textul ei.
   [TEHNIC] Aceeasi inaltime (32px) si acelasi inceput de text ca editorul bibliotecii, ca randul sa nu sara si textul
   sa nu se mute cand randul devine de lucru. Un text prea lung se taie cu trei puncte, ca in editor. Cursor de
   mana: clicul pe rand ii deschide editoarele. */
.app-cell-text {
    display: block; height: 32px; line-height: 32px; padding: 0 9px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; cursor: pointer;
}

.app-cell-problem {
    display: block;
    margin: -3px -4px;
    padding: 3px 4px;
    min-height: 1em;
    background: #f8d7da;
}

/* O lista de alegere intr-o celula cu problema (valoarea de completat pe linia comenzii, randul de lucru la import)
   isi pune altfel fundalul alb peste rosu, iar din rosu ramane doar o margine subtire. */
.app-cell-problem .e-input-group,
.app-cell-problem .e-input-group.e-control-wrapper,
.app-cell-problem .e-input-group input.e-input { background: #f8d7da; }

/* ── formulare si dialoguri ────────────────────────────────────────────────────────── */

.app-card {
    border: 1px solid var(--app-border);
    border-radius: var(--app-radius-lg);
    padding: 20px;
    margin-bottom: var(--app-gap);
    background: var(--app-surface);
    /* [TEHNIC] Bordura `#dee2e6` pe alb era practic invizibila — cardul nu se citea ca un
       card. Umbra fina il ridica de pe fundalul gri al continutului. */
    box-shadow: var(--app-shadow-card);
}

.app-form-row { display: flex; gap: 16px; flex-wrap: wrap; }

/* [T+B] Antetul facturii de vanzare, in TREI coloane de aceeasi latime — furnizor, date
   factura, client — cerinta explicita de simetrie vizuala (2026-09-01). `align-items: stretch`
   (implicit pe flex) le face si de aceeasi INALTIME, chiar daca panoul din mijloc are mai multe
   campuri decat celelalte doua. */
.app-header-columns { display: flex; gap: var(--app-gap); flex-wrap: wrap; }
.app-header-columns > .app-card { flex: 1 1 0; min-width: 260px; margin-bottom: 0; }

/* [T+B] Spatiere mai COMPACTA — cerinta explicita (2026-09-01), proba pe factura de vanzare, extinsa
   la toate documentele pe 2026-09-20 (`.app-page-compact` pe containerul paginii, nu pe
   `.app-card`/`.app-header-columns` global): mai putin gol intre carduri si intre campurile
   perechi, ca ecranul sa arate mai dens, fara sa schimbe tacut paginile care nu sunt documente. */
.app-page-compact .app-card { padding: 14px 16px; margin-bottom: 12px; }
.app-page-compact .app-header-columns { gap: 12px; }
.app-page-compact .app-field-pair { gap: 12px; }
.app-page-compact .app-lines-header { margin-bottom: 6px; }
.app-page-compact .app-totals { margin-top: 8px; padding-top: 8px; }

/* [T+B] Doua campuri pe ACELASI rand, indiferent cat de ingusta e coloana din jur (panoul
   "Date factura" e o treime din latimea paginii) — spre deosebire de `.app-form-grid`, care
   foloseste `auto-fit` si s-ar fi prabusit la o singura coloana sub ~450px. Aici perechea e
   ceruta explicit de layout (Data + Scadenta, Serie + Numar), nu decisa de spatiul disponibil. */
.app-field-pair { display: flex; gap: 16px; }
.app-field-pair > .app-field { flex: 1; min-width: 0; }

/* [TEHNIC] `<small>` e element INLINE — doua la rand (adresa, apoi rezidenta) s-ar fi scris pe
   acelasi rand, lipite. Restul aplicatiei scapa de asta fiindca are un singur `<small>` liber pe
   card; aici, cu doi, block-ul devine necesar. */
.app-note-block { display: block; }

/* Campurile de filtru din EntitySearchDialog, pe UN singur rand. `.app-field` de mai jos are
   `min-width: 200px` — potrivit pentru un formular de document, prea lat pentru cinci campuri de
   cautare inghesuite intr-un popup. Fiecare camp isi da propria latime prin `flex`/`min-width`
   inline (vezi PartnerCard), care castiga fata de clasa. */
.app-search-filters { display: flex; gap: 12px; flex-wrap: wrap; align-items: flex-end; margin-bottom: 12px; }

.app-search-dialog-body { flex: 1 1 auto; min-height: 0; }
.app-search-dialog-list { flex: 1 1 auto; min-height: 0; display: flex; }
.app-search-dialog-grid.app-grid { flex: 1 1 auto; height: 100%; min-height: 0; }

/* [T+B] lista ferestrei de cautare desparte FOCUSUL (sageata) de SELECTIA (albastru, Space) prin design — vezi
   comentariul de langa lista ferestrei de cautare in `EntitySearchDialog.razor`. Fara un contur vizibil pe randul
   focalizat, mutarea cu sageata ar fi invizibila (browserul poate sa nu arate niciun contur implicit
   pe un `<tr>`, sau tema biblioteca de componente il poate suprima). Un contur, nu un fundal — ca sa nu se
   confunde cu randul selectat, care ramane singurul cu fundal albastru. */
.app-field { display: flex; flex-direction: column; gap: 4px; min-width: 200px; flex: 1; }
.app-field label { font-size: 12px; font-weight: 600; color: #6c757d; }
.app-field small { color: #6c757d; font-size: 12px; }

.app-dialog-body {
    display: flex;
    flex-direction: column;
    gap: 16px;
    /* [TEHNIC] Marginea laterala se aliniaza cu antetul bibliotecii (retras 24px), ca
       marginea din stanga a campurilor sa cada exact sub titlu. Fara `scrollbar-gutter`:
       ar fi lasat un gol de ~15px in dreapta pe dialogurile SCURTE (majoritatea), o
       asimetrie mai suparatoare decat bara de derulare peste padding pe cele lungi. */
    padding: 16px 24px 8px;
    max-height: max(260px, calc(100vh - 260px));
    overflow-y: auto;
    overscroll-behavior: contain;
}

/* [BUSINESS] Refuzul serviciului ramane LA VEDERE oricat e derulata fereastra (gasit 2026-10-13, la
   infiintarea unei firme cu un cod fiscal luat). Ferestrele isi pun eroarea sus, in corpul care deruleaza, iar
   butonul Salveaza e jos: intr-o fereastra lunga, derulata pana la buton, omul apasa, nu se schimba nimic din
   ce vede si nu afla de ce. Lipita sus, banda apare peste campuri chiar in clipa refuzului.
   [TEHNIC] `sticky` pe copilul direct al corpului — corpul e chiar elementul care deruleaza (`overflow-y`), deci
   banda se lipeste de marginea lui de sus. `top` negativ cat spatiul de sus al corpului (16px), altfel deasupra
   benzii ar ramane o fasie din campurile derulate. Fundalul benzii e opac, iar umbra o desparte de campurile de
   sub ea. O singura regula pentru toate ferestrele, fara nicio schimbare in markup. */
.app-dialog-body > .app-alert-error {
    position: sticky;
    top: -16px;
    z-index: 3;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
}

/* Varianta de corp pentru o pagina intreaga desenata in fereastra — vezi `.app-embedded-page`. */
.app-dialog-body.app-dialog-body--page { max-height: none; overflow: visible; }

/* [T+B] Grila de formular: JUMATATE de latime IMPLICIT, latimea intreaga e exceptia care
   se cere prin `.app-field-full`. `auto-fit` + `minmax` aseaza doua campuri pe rand cand
   incap si unul cand nu (dialog ingust) — fara media query. Se pune ca A DOUA clasa pe
   `.app-dialog-body` si TREBUIE sa vina DUPA ea in fisier: aceeasi specificitate (0,1,0),
   deci ordinea decide cine da `display`. Opt-in per dialog — nu toate au nevoie.
   `min-width: 0` pe campuri ca un continut lung (eticheta de combo) sa nu largeasca
   coloana peste `1fr`. */
.app-form-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 16px;
    align-content: start;
}
.app-form-grid > .app-field { min-width: 0; }
.app-form-grid > .app-field-full { grid-column: 1 / -1; }
/* Alerta si `<small>`-ul liber de la finalul multor dialoguri (hint-uri gen „diacriticele se
   elimina") ocupa tot randul; alerta fara marginea proprie, ca sa nu se adune peste `gap`. */
.app-form-grid > .app-alert { grid-column: 1 / -1; margin-bottom: 0; }
.app-form-grid > small { grid-column: 1 / -1; }

/* [T+B] „Ce fel de X vrei sa creezi" — primul pas din crearea unui rand cu doua fete (azi:
   custodia data/primita), inainte de a deschide formularul propriu-zis. Fiecare card ESTE
   raspunsul, nu o previzualizare de bifat — un singur clic alege si inchide dialogul. */
.app-choice-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 16px;
}

.app-choice-card {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
    padding: 16px;
    border: 1px solid var(--app-border);
    border-radius: var(--app-radius-lg);
    background: var(--app-surface);
    text-align: left;
    cursor: pointer;
    /* [TEHNIC] E un `<button>`, nu un `<div>` cu handler de clic — trebuie sa ramana
       accesibil de la tastatura (Tab + Enter). Reseteaza doar ce mosteneste de la browser. */
    font: inherit;
    color: inherit;
}
.app-choice-card:hover,
.app-choice-card:focus-visible {
    border-color: var(--app-accent);
    background: var(--app-accent-soft);
    outline: none;
}
.app-choice-title { font-weight: 600; }
.app-choice-hint { font-size: 12px; color: var(--app-text-muted); }

.app-dialog-footer {
    display: flex; justify-content: flex-end; gap: 10px;
    margin: 0; padding: 16px 24px 20px; border-top: 1px solid var(--app-border);
}

.validation-message { color: #dc3545; font-size: 12px; }

/* ── mesaje in pagina ──────────────────────────────────────────────────────────────── */

.app-alert { padding: 10px 14px; border-radius: 6px; margin-bottom: 16px; }
.app-alert-info    { background: #d1ecf1; color: #0c5460; }
.app-alert-error   { background: #f8d7da; color: #721c24; }
.app-alert-warning { background: #fff3cd; color: #856404; }

.app-centered-message {
    display: flex; flex-direction: column; align-items: center; gap: 12px;
    margin-top: 80px; text-align: center; color: #495057;
}
.app-centered-message-icon { font-size: 48px !important; color: #adb5bd; }
.app-centered-message h5 { margin: 0; font-size: 18px; }
.app-centered-message p { margin: 0; color: #6c757d; }

/* ── ecranul de verificari ─────────────────────────────────────────────────────────────
   Lista de verificari NU e o grila: randurile au inaltimi diferite, fiindca fiecare isi
   duce cu el propriile exemple. O grila ar fi cerut randuri de detaliu, adica fix zona in
   care componentele esueaza tacut. Aici e markup simplu, care ori se vede, ori nu exista. */

.app-checks-area { margin: 20px 0 8px; font-size: 14px; font-weight: 600; color: #495057; }
.app-checks-card { padding: 0; }

.app-check-row {
    display: flex; align-items: flex-start; gap: 12px;
    padding: 12px 16px; border-bottom: 1px solid #f1f3f5;
}
.app-check-row:last-child { border-bottom: none; }

.app-check-icon { font-size: 18px !important; margin-top: 1px; }
.app-check-ok  .app-check-icon { color: #2f9e44; }
.app-check-bad .app-check-icon { color: #e8590c; }

.app-check-text { flex: 1; min-width: 0; }
.app-check-title { font-size: 14px; font-weight: 600; color: #212529; }
.app-check-hint  { font-size: 12px; color: #6c757d; margin-top: 2px; }

/* Exemplele sunt date brute — coduri, cifre, denumiri — deci font monospatiat: asa coloanele
   de numere se citesc unele sub altele, chiar daca nu sunt intr-un tabel. */
.app-check-samples {
    margin: 8px 0 0; padding-left: 18px;
    font-family: Consolas, 'Courier New', monospace; font-size: 12px; color: #495057;
}
.app-check-samples li { margin-bottom: 2px; word-break: break-word; }
.app-check-more { margin-top: 4px; font-size: 12px; color: #868e96; font-style: italic; }

.app-check-count { font-size: 13px; font-weight: 600; white-space: nowrap; }
.app-check-ok  .app-check-count { color: #2f9e44; }
.app-check-bad .app-check-count { color: #e8590c; }

/* ── totaluri de document ──────────────────────────────────────────────────────────── */

.app-totals {
    display: flex; justify-content: flex-end; gap: 24px;
    margin-top: 12px; padding-top: 12px; border-top: 1px solid #dee2e6;
}
.app-totals span { color: #6c757d; }
.app-total-final b { font-size: 16px; }

/* [T+B] Totalul final, pe fundal usor diferit — cerinta explicita (2026-09-01), pe toate
   documentele din 2026-09-20 (`.app-totals-highlight`, opt-in, nu pe `.app-totals` global). */
.app-totals-highlight .app-total-final {
    background: var(--app-accent-soft);
    padding: 4px 10px;
    border-radius: var(--app-radius);
}

.app-vat-summary { margin-top: 16px; }
.app-vat-summary table { border-collapse: collapse; margin-top: 6px; }
.app-vat-summary th, .app-vat-summary td {
    border: 1px solid #dee2e6; padding: 4px 12px; text-align: right; font-size: 13px;
}
.app-vat-summary th { background: #f1f3f5; }

/* ── iconite ───────────────────────────────────────────────────────────────────────────
   [TEHNIC] Componentele pun clasa data in `IconCssClass` pe un <span> intern. Material
            Symbols functioneaza prin LIGATURI — numele iconitei se scrie ca text — iar
            legatura dintre cele doua se face cu `content`. Fiecare iconita devine astfel o
            clasa proprie, iar adaugarea uneia noi e o singura linie. */

/* [T+B] Fontul e LOCAL, in `wwwroot/fonts` (2026-08-21). Nu se incarca de la Google: o
   aplicatie de firma n-are voie sa ramana fara iconite fiindca reteaua clientului n-are
   internet, si n-are voie sa trimita adresa IP a fiecarui utilizator catre un tert.

   [TEHNIC] E varianta COMPLETA a fontului (~3,9 MB, toate cele ~3600 de iconite), aleasa
   deliberat in locul unui subset de 7 KB cu cele 59 de iconite folosite azi. Subsetul ar fi
   cerut REGENERARE la fiecare iconita noua, iar uitarea lui esueaza prost: iconita nu apare,
   se vede numele ei ca text. Cu fontul intreg, adaugarea unei iconite ramane o singura linie
   in acest fisier. Fisierul se descarca o data si ramane in cache.

   [TEHNIC] `font-display: block` — nu `swap`. La un font de ICONITE, `swap` ar arata pentru
   o clipa numele scris cu litere („delete", „warehouse") in locul simbolului, ceea ce arata a
   pagina stricata. `block` lasa locul gol pana soseste fontul. */
@font-face {
    font-family: 'Material Symbols Outlined';
    font-style: normal;
    font-weight: 100 700;
    font-display: block;
    src: url('../fonts/material-symbols-outlined.woff2') format('woff2');
}

.mi::before {
    font-family: 'Material Symbols Outlined';
    font-weight: normal;
    font-style: normal;
    font-size: 20px;
    line-height: 1;
    letter-spacing: normal;
    text-transform: none;
    display: inline-block;
    white-space: nowrap;
    direction: ltr;
    -webkit-font-feature-settings: 'liga';
    -webkit-font-smoothing: antialiased;
}

/* actiuni */
.mi-add::before      { content: 'add'; }
.mi-playlist_add::before { content: 'playlist_add'; }
.mi-add_box::before { content: 'add_box'; }
.mi-fullscreen::before      { content: 'fullscreen'; }
.mi-fullscreen-exit::before { content: 'fullscreen_exit'; }
.mi-edit::before     { content: 'edit'; }
.mi-delete::before   { content: 'delete'; }
.mi-columns::before  { content: 'view_column'; }
.mi-reset::before    { content: 'restart_alt'; }
.mi-star::before     { content: 'star'; }
.mi-print::before    { content: 'print'; }
.mi-check::before    { content: 'check'; }
.mi-close::before    { content: 'close'; }
.mi-back::before     { content: 'arrow_back'; }
.mi-translate::before { content: 'translate'; }
.mi-menu::before     { content: 'menu'; }
.mi-search::before   { content: 'search'; }
.mi-refresh::before  { content: 'refresh'; }
.mi-warning::before  { content: 'warning'; }
.mi-upload_file::before { content: 'upload_file'; }
.mi-lock::before     { content: 'lock'; }
.mi-lock-open::before { content: 'lock_open'; }
.mi-logout::before   { content: 'logout'; }
.mi-account::before  { content: 'account_circle'; }
.mi-person-add::before { content: 'person_add'; }
.mi-key::before      { content: 'key'; }
.mi-block::before    { content: 'block'; }
.mi-check-circle::before { content: 'check_circle'; }
.mi-manage-accounts::before { content: 'manage_accounts'; }
.mi-extension::before { content: 'extension'; }
.mi-more::before     { content: 'more_horiz'; }

/* meniu */
.mi-home::before          { content: 'home'; }
.mi-admin::before         { content: 'admin_panel_settings'; }
.mi-group::before         { content: 'group'; }
.mi-badge::before         { content: 'badge'; }
.mi-rule::before          { content: 'rule'; }
.mi-settings::before      { content: 'settings'; }
.mi-domain::before        { content: 'domain'; }
.mi-apartment::before     { content: 'apartment'; }
.mi-warehouse::before     { content: 'warehouse'; }
.mi-event::before         { content: 'event_available'; }
.mi-swap::before          { content: 'swap_horiz'; }
.mi-list::before          { content: 'list_alt'; }
.mi-business::before      { content: 'business'; }
.mi-inventory::before     { content: 'inventory_2'; }
.mi-inbox::before         { content: 'inventory'; }
.mi-palette::before       { content: 'palette'; }
.mi-straighten::before    { content: 'straighten'; }
.mi-category::before      { content: 'category'; }
.mi-percent::before       { content: 'percent'; }
.mi-sell::before          { content: 'sell'; }
.mi-currency::before      { content: 'currency_exchange'; }
.mi-trending::before      { content: 'trending_up'; }
.mi-history::before       { content: 'history'; }
.mi-bank::before          { content: 'account_balance'; }
.mi-contacts::before      { content: 'contacts'; }
.mi-download::before      { content: 'cloud_download'; }
.mi-csv::before           { content: 'csv'; }
.mi-pdf::before           { content: 'picture_as_pdf'; }
.mi-description::before   { content: 'description'; }
.mi-cart::before          { content: 'shopping_cart'; }
.mi-receipt::before       { content: 'receipt_long'; }
.mi-link::before          { content: 'link'; }
.mi-truck::before         { content: 'local_shipping'; }
.mi-request-quote::before { content: 'request_quote'; }
.mi-layers::before        { content: 'layers'; }
.mi-qr::before            { content: 'qr_code_2'; }
.mi-tag::before           { content: 'tag'; }
.mi-location::before      { content: 'location_on'; }
.mi-public::before        { content: 'public'; }
.mi-map::before           { content: 'map'; }
.mi-city::before          { content: 'location_city'; }
.mi-signpost::before      { content: 'signpost'; }
.mi-output::before        { content: 'output'; }
.mi-input::before         { content: 'input'; }
.mi-numbers::before       { content: 'format_list_numbered'; }
.mi-fact-check::before    { content: 'fact_check'; }
.mi-help::before          { content: 'help_outline'; }
.mi-gavel::before         { content: 'gavel'; }
.mi-book::before          { content: 'menu_book'; }
.mi-chevron-right::before { content: 'chevron_right'; }
.mi-chevron-left::before  { content: 'chevron_left'; }

.app-icon-btn {
    min-width: 32px !important;
    padding: 4px 6px !important;
    margin-right: 4px;
    border: 1px solid transparent !important;
    border-radius: var(--app-radius) !important;
    transition: background-color .12s ease, border-color .12s ease;
}
.app-icon-btn:hover {
    background-color: var(--app-accent-soft) !important;
    border-color: var(--app-border-strong) !important;
}
.app-btn-danger { color: #dc3545 !important; }
.app-btn-danger:hover {
    background-color: #fdecec !important;
    border-color: #f1c9c9 !important;
}

.app-page-title { font-size: 24px; font-weight: 600; margin: 0 0 18px; }
.app-no-margin { margin: 0; }

/* [TEHNIC] `pre-line` pastreaza randurile noi din text: inchiderea de luna compune un mesaj cu
   lista ciornelor gasite, iar fara asta lista ar aparea lipita intr-un singur paragraf. */
.app-confirm-body { padding: 4px 6px; line-height: 1.5; white-space: pre-line; }

/* ── formularul de adresa ──────────────────────────────────────────────────────────── */

.app-address-form { display: flex; flex-direction: column; gap: 14px; }

/* Camp cu buton alaturat („+" pentru localitate si strada): lista ia tot spatiul, butonul
   ramane la dimensiunea lui. */
.app-field-with-action { display: flex; gap: 6px; align-items: center; }
.app-field-grow { flex: 1; }

/* Cardul de alegere a partenerului (PartnerCard): inlocuieste combobox-ul, se deschide pe click
   catre EntitySearchDialog. Compact, nu "app-card" de pagina (acela are padding si umbra de
   sectiune) — aici e un camp de formular, doar cu inaltime mai mare ca sa incapa doua randuri. */
.app-picker-card {
    flex: 1; min-width: 0; cursor: pointer;
    border: 1px solid var(--app-border); border-radius: var(--app-radius);
    padding: 6px 10px; background: var(--app-surface);
    transition: background-color .12s ease, border-color .12s ease;
}
.app-picker-card:hover, .app-picker-card:focus-visible {
    background-color: var(--app-accent-soft); border-color: var(--app-border-strong);
    outline: none;
}
.app-picker-card-disabled { cursor: default; opacity: .7; }
.app-picker-card-disabled:hover { background-color: var(--app-surface); border-color: var(--app-border); }
.app-picker-card-placeholder { color: var(--app-text-muted, #6c757d); }
.app-picker-card-title { font-weight: 600; }
.app-picker-card-sub { font-size: 12px; color: var(--app-text-muted, #6c757d); }

/* ── ecran impartit in doua (master-detail) ────────────────────────────────────────────
   Sub 900px coloanele se aseaza una sub alta: pe ecran ingust, doua grile alaturate ar fi
   ilizibile amandoua. */
.app-split { display: flex; gap: 20px; align-items: flex-start; flex-wrap: wrap; }
.app-split-left { flex: 1 1 380px; min-width: 0; }
.app-split-right { flex: 1 1 460px; min-width: 0; }

.app-field-narrow { flex: 0 0 140px; min-width: 140px; }

/* Valoare doar-citire in locul unui editor: articolul unui pret nu se mai poate schimba dupa
   creare, iar un editor dezactivat ar fi aratat ca un camp pe care poate il deblochezi cumva. */
.app-readonly-value { padding: 6px 0; font-weight: 500; }

/* Previzualizarea unei modificari in masa: „articol — vechi → nou", pe randuri.
   Cifrele sunt aliniate la dreapta ca sa se poata compara dintr-o privire; cea veche e
   estompata, ca ochiul sa cada pe cea noua. */
.app-preview { border-collapse: collapse; margin-top: 4px; }
.app-preview td { padding: 2px 8px 2px 0; font-size: 13px; }
.app-preview-old { text-align: right; color: #6c757d; }
.app-preview-arrow { color: #6c757d; }
.app-preview-new { text-align: right; font-weight: 600; }

/* Mentiune mica langa eticheta unui camp — „(cu TVA)" la pret. Nu e un `small` de sub camp:
   trebuie citita ODATA cu eticheta, fiindca schimba intelesul cifrei. */
.app-field-note { font-weight: 400; text-transform: none; color: #6c757d; }
.app-section { margin-top: 6px; display: flex; flex-direction: column; gap: 2px; }
.app-section small { color: #6c757d; font-size: 12px; }

/* Blocurile din dialogul de mutare a sediului social. */
.app-swap-block {
    border: 1px solid #dee2e6; border-radius: 6px; padding: 10px 12px;
    display: flex; flex-direction: column; gap: 4px;
}
.app-swap-label { font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: #6c757d; }
.app-swap-label-success { color: #198754; }

/* ── linia de atribut din dialogul de articol ──────────────────────────────────────── */
.app-attr-line {
    display: flex; align-items: center; gap: 6px;
    border: 1px solid #dee2e6; border-radius: 6px; padding: 8px 10px;
}
.app-attr-name { min-width: 130px; }
.app-attr-picker { min-width: 240px; }

.mi-up::before   { content: 'arrow_upward'; }
.mi-down::before { content: 'arrow_downward'; }

/* ── grupuri de bife in dialoguri ──────────────────────────────────────────────────────
   Folosite de editorul de rol (permisiuni pe module) si de modulele firmei. */

.app-fieldset {
    border: 1px solid #dee2e6; border-radius: 6px;
    padding: 10px 14px 12px; margin: 0;
    display: flex; flex-direction: column; gap: 4px;
}
.app-fieldset legend {
    padding: 0 6px; font-size: 12px; font-weight: 600; color: #495057;
}

/* Bifele de submeniu din CompanyMenuVisibilityDialog: usor retrase fata de bifa grupului. */
.app-menu-visibility-leaf { margin-left: 20px; }

/* [T+B] Frunzele unui SUBGRUP (al treilea nivel, „Articole"): inca o treapta de indentare. */
.app-menu-visibility-leaf--sub { margin-left: 40px; }

/* [TEHNIC] Dialogurile lungi (permisiuni, module) deruleaza CORPUL, nu pagina din spate:
   altfel butoanele de salvare ar cobori sub marginea ferestrei si ar deveni inaccesibile. */
.app-dialog-scroll { max-height: 60vh; overflow-y: auto; }

/* Un rand de controale asezate orizontal intr-un card (resetare de parola, buton de numire). */
.app-inline-form { display: flex; align-items: center; gap: 8px; margin-top: 8px; flex-wrap: wrap; }

.app-alert-success { background: #d4edda; color: #155724; }

/* Formular de pagina (nu de dialog): latime limitata, ca randurile lungi sa ramana lizibile. */
.app-form-narrow { max-width: 680px; display: flex; flex-direction: column; gap: 14px; }

.app-form-actions {
    display: flex; align-items: center; gap: 8px;
    padding-top: 12px; border-top: 1px solid #dee2e6;
}
.app-form-actions-spacer { flex: 1; }

/* ── alocarea pe loturi si alegerea bucatilor ──────────────────────────────────────────
   [TEHNIC] Randurile de alocare sunt un FORMULAR, nu o grila: patru randuri nu se sorteaza,
   nu se filtreaza si nu se pagineaza. Coloanele se aliniaza cu latimi fixe, iar antetul
   foloseste aceleasi clase ca randurile. */

.app-alloc-head, .app-alloc-row { display: flex; align-items: center; gap: 8px; }
.app-alloc-head { font-size: 12px; font-weight: 600; color: #6c757d; }
.app-alloc-lot { flex: 1; min-width: 160px; }
.app-alloc-mid { width: 170px; text-align: right; }
.app-alloc-qty { width: 140px; }
.app-alloc-del { width: 40px; text-align: center; }

.app-serial-memo { width: 100%; font-family: ui-monospace, 'Cascadia Mono', Consolas, monospace; }
.app-serial-list { max-height: 320px; overflow-y: auto; display: flex; flex-direction: column; gap: 4px; }

/* Antetul sectiunii de linii a unui document: titlu la stanga, „Adauga linie" la dreapta. */
.app-lines-header {
    display: flex; align-items: center; justify-content: space-between;
    margin-bottom: 8px;
}

/* [T+B] Antetul sectiunii de linii al unui document: titlul la stanga, apoi TOATE butoanele in dreapta (spacer
   intre ele), cu „Adauga linie" primul si albastru — regula butoanelor de adaugare din 2026-09-23. Modificatorul
   `--start` da doar spatiul dintre elemente (`.app-lines-header--start`, opt-in, nu pe `.app-lines-header` global). */
.app-lines-header--start { justify-content: flex-start; gap: 12px; }

/* Randul de date de identificare al unui document de consultare (data, partener, depozit). */
.app-facts { display: flex; gap: 32px; flex-wrap: wrap; font-size: 14px; }

/* ── ajutor ────────────────────────────────────────────────────────────────────────────
   [T+B] Fiecare articol e o LEGATURA adevarata, nu un card cu handler de clic: asa se poate
   deschide intr-o fila noua, iar adresa se vede in bara de stare inainte de clic. */

.app-help-list { display: flex; flex-direction: column; gap: 10px; }

.app-help-card {
    display: flex; align-items: center; gap: 14px;
    border: 1px solid var(--app-border); border-radius: 6px;
    padding: 14px 16px; background: #fff;
    color: inherit; text-decoration: none;
}
.app-help-card:hover { background: #f8f9fa; border-color: #adb5bd; }

.app-help-icon { color: #6c757d; }
.app-help-body { display: flex; flex-direction: column; gap: 6px; flex: 1; }
.app-help-badges { display: flex; gap: 8px; align-items: center; margin-bottom: 16px; }
.app-help-chevron { color: #adb5bd; }

/* Corpul unui articol: HTML generat din Markdown, deci fara clase proprii pe elemente. */
.help-article { max-width: 820px; line-height: 1.65; }
.help-article h2 { font-size: 20px; margin: 28px 0 8px; }
.help-article h3 { font-size: 16px; margin: 22px 0 6px; }
.help-article p { margin: 0 0 12px; }
.help-article ul, .help-article ol { margin: 0 0 12px; padding-left: 22px; }
.help-article li { margin-bottom: 4px; }
.help-article code {
    background: #f1f3f5; padding: 1px 5px; border-radius: 3px;
    font-family: ui-monospace, 'Cascadia Mono', Consolas, monospace; font-size: 13px;
}
.help-article table { border-collapse: collapse; margin: 0 0 16px; }
.help-article th, .help-article td { border: 1px solid #dee2e6; padding: 6px 12px; text-align: left; }
.help-article th { background: #f1f3f5; }
.help-article blockquote {
    margin: 0 0 12px; padding: 8px 14px;
    border-left: 3px solid #adb5bd; background: #f8f9fa; color: #495057;
}

/* Zona vizualizatorului de rapoarte: are nevoie de o inaltime CONCRETA, altfel se monteaza
   la zero pixeli si pare ca nu s-a intamplat nimic. */
.app-report-host { height: calc(100vh - 190px); min-height: 420px; }

/* ── paginile din afara aplicatiei: autentificare, alegerea firmei, eroare ──────────────
   [T+B] Sunt pagini Razor obisnuite, cu `Layout = null`, deci NU pot folosi componentele
   bibliotecii: acelea au nevoie de circuitul Blazor, care aici inca nu exista — omul nu s-a
   autentificat. De aceea au stil propriu, scris de mana. E singurul loc din aplicatie unde
   se intampla asta, si e o consecinta a securitatii, nu o scapare. */

.app-auth-body {
    margin: 0; min-height: 100vh; background: #f1f3f5;
    font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
    color: #212529;
}

.app-auth-card {
    max-width: 420px; margin: 8vh auto 0;
    background: #fff; border: 1px solid #dee2e6; border-radius: 8px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .08);
    padding: 28px 32px;
}
.app-auth-card-wide { max-width: 520px; }

.app-auth-title { margin: 0 0 4px; font-size: 20px; font-weight: 600; text-align: center; }
.app-auth-subtitle { margin: 0 0 20px; text-align: center; color: #6c757d; font-size: 13px; }

.app-auth-field { display: flex; flex-direction: column; gap: 5px; margin-bottom: 16px; }
.app-auth-field label { font-size: 12px; font-weight: 600; color: #6c757d; }
.app-auth-field input {
    padding: 8px 11px; border: 1px solid #ced4da; border-radius: 4px;
    font-size: 14px; font-family: inherit;
}
.app-auth-field input:focus { outline: none; border-color: #0d6efd; box-shadow: 0 0 0 3px rgba(13,110,253,.15); }

.app-auth-submit {
    width: 100%; padding: 9px 14px; border: none; border-radius: 4px;
    background: #0d6efd; color: #fff; font-size: 14px; font-weight: 600;
    font-family: inherit; cursor: pointer;
}
.app-auth-submit:hover { background: #0b5ed7; }
/* Aceeasi infatisare pe o legatura (ecranul „Lucrezi deja intr-o firma"): o legatura e in linie, deci fara
   display: block latimea de 100% nu s-ar aplica. */
a.app-auth-submit { display: block; box-sizing: border-box; text-align: center; text-decoration: none; }

/* Lista firmelor: fiecare rand e un formular propriu, deci un buton cat tot randul. */
.app-auth-list { display: flex; flex-direction: column; gap: -1px; }
.app-auth-list-item {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    width: 100%; padding: 12px 14px; text-align: left;
    background: #fff; border: 1px solid #dee2e6; border-radius: 4px;
    font-size: 14px; font-family: inherit; color: inherit; cursor: pointer;
    margin-bottom: 6px;
}
.app-auth-list-item:hover { background: #f8f9fa; border-color: #adb5bd; }

.app-auth-footer { text-align: center; margin-top: 18px; }

.app-auth-link {
    display: inline-block; padding: 4px 12px; margin: 0 2px;
    border: 1px solid #ced4da; border-radius: 4px;
    background: #fff; color: #495057; font-size: 13px;
    font-family: inherit; text-decoration: none; cursor: pointer;
}
.app-auth-link:hover { background: #f1f3f5; }
.app-auth-link-active { background: #495057; border-color: #495057; color: #fff; }

.app-auth-error {
    padding: 9px 13px; border-radius: 4px; margin-bottom: 16px;
    background: #f8d7da; color: #721c24; font-size: 13px;
}

.app-auth-page { max-width: 720px; margin: 8vh auto 0; padding: 0 24px; }
.app-auth-page h1 { font-size: 22px; margin: 0 0 6px; color: #b02a37; }
.app-auth-page h2 { font-size: 16px; margin: 0 0 20px; color: #b02a37; font-weight: 500; }

/* ── Sigla firmei ─────────────────────────────────────────────────────────────────────────
   Caseta de previzualizare are inaltime FIXA si fundal in carouri. Fixa, ca randul de butoane
   sa nu sara cand se incarca o sigla mai inalta; in carouri, ca transparenta unui PNG sa se
   vada — altfel o sigla alba pe fond alb pare ca lipseste, iar omul incarca alta degeaba. */
.app-logo-box {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 120px;
    margin: 0.75rem 0;
    padding: 0.5rem;
    border: 1px solid #dee2e6;
    border-radius: 4px;
    background-color: #fff;
    background-image:
        linear-gradient(45deg, #f1f3f5 25%, transparent 25%, transparent 75%, #f1f3f5 75%),
        linear-gradient(45deg, #f1f3f5 25%, transparent 25%, transparent 75%, #f1f3f5 75%);
    background-size: 16px 16px;
    background-position: 0 0, 8px 8px;
}

.app-logo-preview {
    max-height: 100%;
    max-width: 100%;
    object-fit: contain;
}

/* [TEHNIC] Eticheta E butonul, iar `input`-ul din ea se ascunde prin dimensiune zero si
   `opacity`, NU prin `display:none`: un camp cu `display:none` nu mai poate fi declansat de
   eticheta in unele browsere, iar butonul ar fi ramas inert fara nicio eroare. */
.app-file-button {
    display: inline-flex;
    align-items: center;
    padding: 0.375rem 0.75rem;
    border: 1px solid #adb5bd;
    border-radius: 4px;
    background-color: #fff;
    cursor: pointer;
    user-select: none;
}

.app-file-button:hover { background-color: #f8f9fa; }

.app-file-button input[type="file"] {
    width: 0;
    height: 0;
    opacity: 0;
    position: absolute;
}

/* [T+B] Varianta ALBASTRA a `.app-file-button` (2026-09-29, cerinta explicita: „de forma
   celor de adauga, culoare etc"). Acelasi mecanism (eticheta + input ascuns — un `AppButton`
   n-ar putea deschide singur dialogul nativ de fisiere), dar cu aspectul unui `AppButton`
   `Primary` + `SizeMode.Small`: fundal `--app-accent` (chiar tonul temei bibliotecii, prin
   variabila deja folosita in restul paginii), text alb, padding mai stramt decat implicitul
   lui `.app-file-button` (acela e marimea REGULAR a bibliotecii). */
.app-file-button-primary {
    padding: 0.25rem 0.75rem;
    gap: 0.25rem;
    border-color: var(--app-accent);
    background-color: var(--app-accent);
    color: #fff;
}

.app-file-button-primary:hover {
    border-color: var(--app-accent-strong);
    background-color: var(--app-accent-strong);
}

.app-file-button-primary .mi { font-size: 1rem; }

/* Numerele zecimale se aliniaza la DREAPTA, ca zecimalele sa cada una sub alta si doua cifre
   sa se poata compara dintr-o privire. Se aplica pe editor, deci trebuie sa ajunga la
   `input`-ul dinauntrul componentei — clasa pusa pe componenta nu-l atinge singura. */
.app-number input { text-align: right; }

/* [T+B] Editor „plain text" pe o celula de grid (2026-09-29, cerinta explicita: coloanele
   Denumire/Lungime din import-ul de facturi nu au nevoie de un editor al bibliotecii cu chenar
   si sageti — un `<input>` obisnuit, fara decor, e destul, dar ramane click-si-scrie).
   Umple celula (`width: 100%`) si preia fontul din jur, ca sa nu se vada ca e alt element
   decat restul textului din grid pana la focalizare. */
/* [TEHNIC] Titlu de coloana pe DOUA randuri (2026-10-09, „Inaltime (factura)" pe listele de linii ale
   importului): un nume lung pe o coloana ingusta de cifre. Se pune pe un `span` din `HeaderCaptionTemplate`;
   biblioteca tine titlul pe un rand si il taie cu trei puncte, de aceea `white-space` se da explicit.
   Randul de titluri creste singur cat cel mai inalt titlu. */
.app-header-wrap { display: block; white-space: normal; line-height: 1.2; }

/* Celula de grila care are voie sa treaca pe doua randuri (TenantDatabaseCell: cheia bazei + „lipseste din
   configurare"). Biblioteca tine celula pe un rand si o taie cu trei puncte, iar latimea salvata de om in browser
   poate fi mai mica decat cea din pagina — fara asta, avertizarea ar iesi taiata tocmai cand conteaza. Randul
   creste doar acolo unde chiar e nevoie. */
.app-cell-wrap { display: inline-block; white-space: normal; line-height: 1.6; }
.app-cell-wrap .badge { white-space: normal; }

.app-plain-input {
    width: 100%;
    padding: 0;
    border: none;
    background: transparent;
    font: inherit;
    color: inherit;
}

.app-plain-input:focus {
    outline: none;
    box-shadow: 0 0 0 1px var(--app-accent, #0d6efd) inset;
}

/* [TEHNIC] `.app-number` pe INPUT-ul insusi, nu pe un invelis — regula de mai sus
   (`.app-number input`) nu se aplica aici, deci coloana Lungime cere propria regula. */
.app-plain-input.app-number { text-align: right; }

/* =====================================================================================
   INDICATORUL DE INCARCARE — pana porneste circuitul Blazor

   [T+B] Exista fiindca prerandarea e oprita (vezi App.razor): serverul nu mai trimite niciun
         continut al aplicatiei, deci fara asta browserul ar arata o pagina alba pana se
         stabileste circuitul. Se sterge din JavaScript cand Blazor a pornit.

   [TEHNIC] Ocupa tot ecranul si sta DEASUPRA a tot: nu are ce sa acopere la inceput, dar daca
            ramane o clipa peste primul cadru randat, mai bine acopera decat sa se vada
            amandoua deodata.
   ===================================================================================== */
.app-loading {
    position: fixed;
    inset: 0;
    z-index: 2000;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1rem;
    background: var(--app-bg);
}

/* Cercul, FOLOSIT DE DOUA ORI: la pornirea aplicatiei (mai sus) si cat timp un ecran isi asteapta
   datele (mai jos). Doua faze diferite, acelasi semn vizual — omul n-are de ce sa invete doua. */
.app-spinner {
    width: 2.5rem;
    height: 2.5rem;
    border: 3px solid var(--app-border);
    /* Un singur sfert colorat — el da senzatia de rotatie. */
    border-top-color: var(--app-accent);
    border-radius: 50%;
    animation: app-loading-spin 0.8s linear infinite;
}

.app-loading-text {
    margin: 0;
    color: var(--app-text-muted);
}

@keyframes app-loading-spin {
    to { transform: rotate(360deg); }
}

/* [T+B] Cine a cerut sistemului mai putina miscare nu primeste rotatie — cercul ramane pe loc,
         iar textul spune oricum ce se intampla. Aceeasi regula ca la orice animatie. */
@media (prefers-reduced-motion: reduce) {
    .app-spinner { animation: none; }
}

/* Faza A DOUA: aplicatia e pornita, ecranul e desenat, dar datele n-au sosit. Sta IN pagina, nu
   peste ea — cadrul, meniul si titlul raman vizibile si folosibile. */
.app-data-loading {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1rem;
    padding: 3rem 0;
}

/* [T+B] Odata ce aplicatia a pornit, indicatorul nu mai are voie sa se vada — nici daca reapare in
         DOM. Se intampla la navigarile „imbunatatite": Blazor inlocuieste corpul paginii cu HTML-ul
         serverului, deci si cu indicatorul, dar scripturile din el NU se mai executa. Regula asta e
         plasa care a reparat pagina alba de dupa login (2026-08-29). */
html.app-started .app-loading { display: none; }

/* =====================================================================================
   <TextOperatorFilterCell> — selectorul de operator din randul de filtre (azi doar pe
   coloana „Denumire" din /partners).

   [TEHNIC] Celula de filtru e ingusta: butonul de operator sta la latime fixa, casuta ia
            restul. `min-width: 0` pe casuta ca flexbox sa o poata micsora sub latimea ei
            intrinseca, altfel randul de filtre s-ar largi.
   ===================================================================================== */
.app-op-filter {
    display: flex;
    align-items: center;
    gap: 4px;
}

.app-op-filter-value {
    flex: 1 1 auto;
    min-width: 0;
}

/* Butonul poarta eticheta operatorului („conține", „începe cu”…) — text mic, fara sa creasca
   inaltimea randului de filtre. */
.app-op-filter-op {
    flex: 0 0 auto;
    padding-block: 2px;
    font-size: .78rem;
    white-space: nowrap;
}

/* Lista de operatori din dropdown: butoane pe toata latimea, aliniate la stanga, unul sub altul. */
.app-op-filter-item {
    display: flex;
    width: 100%;
    justify-content: flex-start;
    min-width: 9rem;
}

/* =====================================================================================
   Pasii unui wizard (planificarea achizitiilor).

   [T+B] Doar un indicator de stare, nu navigare: pasii se parcurg cu butoanele „Continua" /
         „Inapoi", iar un pas viitor nu se poate deschide direct — pasul 2 depinde de ce s-a ales
         in pasul 1.
   ===================================================================================== */
.app-steps { display: flex; gap: 8px; margin-bottom: 16px; flex-wrap: wrap; }
.app-step {
    padding: 6px 14px;
    border-radius: 999px;
    border: 1px solid var(--app-border-strong);
    color: var(--app-text-muted);
    font-size: 0.9rem;
}
.app-step-active { background: var(--app-accent); border-color: var(--app-accent); color: #fff; font-weight: 600; }
.app-step-done { color: inherit; }

/* [TEHNIC] Punct de ancorare pentru fereastra „Coloane" a unei grile. Fereastra bibliotecii se aliniaza
   fata de un ELEMENT-TINTA; tinta nu poate fi chiar butonul, fiindca `Top` ar pune fereastra peste el.
   Ancora are latime si inaltime zero si sta absolut sub marginea dreapta a gazdei (`right: 0`,
   `top: 100%`), deci „marginea de sus si cea din dreapta a ferestrei = ancora" inseamna, in fapt, „fereastra
   se deschide sub buton, cu marginea dreapta la a lui". Vezi `ItemsPage.ShowColumnChooser`. */
.app-chooser-host { position: relative; display: inline-flex; gap: 4px; }
.app-chooser-anchor { position: absolute; right: 0; top: 100%; width: 0; height: 0; margin-top: 4px; pointer-events: none; }

/* Setarile unui modul, sub bifa lui in dialogul platformei (modulul de variante, 2026-09-23): indentate,
   ca sa se citeasca drept ale modulului de deasupra, nu ca un modul separat. */
/* Fereastra „Adauga mai multe linii" de pe comanda client (`AddOrderLinesDialog`): articolul singur pe
   rand, pe toata latimea (denumirea variantei se vede intreaga); sub el cantitatea si butonul, cu butonul
   aliniat la baza campului; dedesubt, ce s-a trimis deja. */
.app-add-lines-item { margin-top: 8px; }
.app-add-lines-item-row { display: flex; align-items: center; gap: 6px; }
.app-add-lines-item-row > :first-child { flex: 1 1 auto; min-width: 0; }
.app-add-lines-row {
    display: flex; align-items: flex-end; gap: 10px;
    margin-top: 8px;
}
.app-add-lines-qty  { flex: 0 0 160px; }
.app-add-lines-added {
    display: flex; flex-direction: column; gap: 2px;
    margin-top: 12px;
}
.app-add-lines-added-row {
    display: flex; justify-content: space-between; gap: 12px;
}

.app-module-options {
    display: flex; flex-direction: column; gap: 4px;
    margin: 2px 0 10px 26px;
}

/* =====================================================================================
   FISELE SESIUNILOR DE IMPORT (`InvoiceImportSessionsPage`, 2026-10-01) — o fisa pe rand.

   [BUSINESS] Cerinta utilizatorului: lista de sesiuni semana prea mult cu lista facturilor unei
              sesiuni (aceeasi grila, acelasi cos de gunoi pe rand), iar uneori stergea o SESIUNE
              crezand ca sterge o FACTURA. De aceea sesiunile au alt desen — fise, cu data mare in
              stanga — si NU au cos pe fisa: stergerea sta in meniul „⋯", sub editare.
   [TEHNIC]  Clase proprii, nu `.app-card`: acela are padding de formular (20px) si margine de
             `--app-gap`, prea mult pentru o fisa care tine locul unui rand.
   ===================================================================================== */
.app-session-toolbar { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-bottom: 10px; }
.app-session-toolbar-spacer { flex: 1 1 auto; }
.app-session-search { width: 240px; max-width: 100%; }

/* Filtrele rapide pe tip — butoane simple, nu `AppButton`: n-au nevoie de nimic din biblioteca, iar starea
   „ales" se citeste mai bine ca bordura albastra decat ca al doilea buton albastru langa „Adauga sesiune". */
.app-chip {
    font: inherit; font-size: 0.875rem;
    padding: 3px 12px;
    border: 1px solid var(--app-border-strong);
    border-radius: 999px;
    background: var(--app-surface);
    color: inherit;
    cursor: pointer;
}
.app-chip:hover { background: var(--app-accent-soft); }
.app-chip-active { border-color: var(--app-accent); color: var(--app-accent-strong); background: var(--app-accent-soft); }
.app-chip-count { color: var(--app-text-muted); margin-left: 4px; }

.app-session-card {
    display: flex;
    align-items: stretch;
    background: var(--app-surface);
    border: 1px solid var(--app-border);
    border-radius: var(--app-radius-lg);
    box-shadow: var(--app-shadow-sm);
    margin-bottom: 8px;
}
.app-session-card:hover { border-color: var(--app-border-strong); }

/* [T+B] Sesiunea din care omul tocmai s-a intors (`Recent.Take("invoice-import")`) — acelasi albastru ca
   randul salvat din grile (`.app-row-highlight`), deci aceeasi semnificatie. Clasa e chiar
   `app-row-highlight`, ca `gridHighlight.js` s-o stinga la primul click sau la prima tasta, fara script nou. */
.app-session-card.app-row-highlight {
    border-color: var(--app-accent);
    box-shadow: inset 3px 0 0 var(--app-accent), var(--app-shadow-sm);
    background: var(--app-accent-soft);
}

.app-session-date {
    flex: none;
    width: 78px;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    border-right: 1px solid var(--app-border);
    padding: 8px 0;
}
.app-session-day { font-size: 1.5rem; font-weight: 600; line-height: 1.1; }
.app-session-month { font-size: 0.8rem; color: var(--app-text-muted); }

.app-session-body { flex: 1 1 auto; min-width: 0; padding: 8px 14px; }
.app-session-title { display: flex; align-items: center; gap: 8px; min-width: 0; }
.app-session-number { color: var(--app-text-muted); font-size: 0.875rem; flex: none; }
.app-session-description {
    font-weight: 600;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.app-session-description-empty { font-weight: normal; font-style: italic; color: var(--app-text-muted); }
.app-session-meta {
    display: flex; flex-wrap: wrap; gap: 4px 16px;
    margin-top: 2px;
    font-size: 0.875rem; color: var(--app-text-muted);
}
.app-session-meta .mi::before { font-size: 16px; vertical-align: -3px; margin-right: 3px; }
.app-session-status-done { color: #146c43; }

/* Tipul sesiunii — o culoare per tip, ca doua sesiuni de tipuri diferite sa nu se confunde nici ele. */
.app-kind-badge { flex: none; font-size: 0.75rem; padding: 1px 8px; border-radius: 999px; font-weight: 600; }
.app-kind-badge-ecuador { background: #e3edff; color: #0b4fb3; }
.app-kind-badge-netherlands { background: #efe8fc; color: #5631a8; }

.app-session-actions { flex: none; display: flex; align-items: center; gap: 6px; padding: 0 12px; }

/* Perechile „Import ↔ Comenzi" (2026-10-16): doua fise de sesiune aliniate, legate printr-o pictograma, plus o fisa
   mica de actiuni in dreapta. Fisele isi pastreaza forma de pe paginile sesiunilor; aici doar impart randul egal. */
.app-pair-row { display: flex; align-items: stretch; gap: 8px; margin-bottom: 8px; }
.app-pair-row > .app-session-card { flex: 1 1 0; min-width: 0; margin-bottom: 0; }
.app-pair-link { flex: none; align-self: center; color: var(--app-text-muted); }
.app-pair-link::before { font-size: 20px; }
.app-pair-actions {
    flex: none;
    display: flex; flex-direction: column; justify-content: center; gap: 4px;
    padding: 6px 10px;
    background: var(--app-surface);
    border: 1px solid var(--app-border);
    border-radius: var(--app-radius-lg);
    box-shadow: var(--app-shadow-sm);
}
.app-pair-row.app-row-highlight > .app-session-card,
.app-pair-row.app-row-highlight > .app-pair-actions {
    border-color: var(--app-accent);
    background: var(--app-accent-soft);
}
/* Sesiunea de comenzi poarta si ea o eticheta colorata, ca fisa sa se deosebeasca dintr-o privire de cea de import. */
.app-kind-badge-orders { background: #e6f4ea; color: #146c43; }

@media (max-width: 900px) {
    .app-pair-row { flex-wrap: wrap; }
    .app-pair-row > .app-session-card { flex-basis: 100%; }
    .app-pair-link { display: none; }
    .app-pair-actions { flex-basis: 100%; flex-direction: row; justify-content: flex-end; }
}

/* Optiunea de stergere din meniul „⋯" — rosie, ca sa se vada ca e altceva decat editarea de deasupra.
   `!important` fiindca textul elementelor din lista bibliotecii vine pe un selector mai specific. */
.app-menu-danger, .app-menu-danger .mi { color: #b02a37 !important; }

.app-session-empty { padding: 24px 8px; color: var(--app-text-muted); text-align: center; }

/* Pe ecran ingust, butoanele trec sub continut, pe toata latimea fisei. */
@media (max-width: 640px) {
    .app-session-card { flex-wrap: wrap; }
    .app-session-body { flex-basis: calc(100% - 78px); }
    .app-session-actions { flex-basis: 100%; justify-content: flex-end; padding: 6px 12px 8px; border-top: 1px solid var(--app-border); }
}

/* Text lung intr-o celula de grila, pe UN rand, taiat cu „..." (2026-10-07, descrierea articolului). Textul intreg
   il da atributul `title` pus de pagina. `display: block` + `max-width` sunt cele care fac taierea sa functioneze
   intr-o celula de tabel: un `span` inline nu are latime de care sa se loveasca. */
.app-cell-ellipsis {
    display: block;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* =====================================================================================
   [BUSINESS] Filtrul unei coloane NUMERICE e o caseta in care se scrie, fara sagetile
              „mareste / micsoreaza cu 1" (cerinta utilizatorului, 2026-10-08).
   [TEHNIC] Pe listele `AppGrid` sagetile sunt oprite din cod (`PlainNumericFilter`); regula
            de aici le ascunde si pe grilele `AppGrid` din dialoguri si sub-liste, care nu
            trec pe acolo. Doar in randul de filtre: editoarele numerice din formulare si
            din liniile documentelor isi pastreaza sagetile.
   ===================================================================================== */
/* =====================================================================================
   COMPONENTELE PROPRII DE INTERFATA (2026-10-11) — AppButton, AppTextBox, AppCombo, AppGrid,
   AppPopup, AppMenu, AppDropDown, notificarile.

   [TEHNIC] Tema bibliotecii de componente (Syncfusion, clasele e-*) se incarca INAINTEA
            acestei foi; regulile de aici o aliniaza cu restul aplicatiei: densitate compacta,
            culorile si razele din token-urile --app-*. Paginile nu folosesc niciodata clase
            e-*: ele scriu app-*, iar legatura cu biblioteca sta doar aici si in
            Components/Shared.
   ===================================================================================== */

.mi-expand-more::before { content: 'expand_more'; }
.mi-error::before { content: 'error'; }
.mi-info::before { content: 'info'; }

/* ── Butoane ─────────────────────────────────────────────────────────────────────────── */
.app-btn.e-btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 5px;
    text-transform: none; font-family: inherit; font-weight: 500; letter-spacing: 0;
    border-radius: var(--app-radius); line-height: 1.2; white-space: nowrap; text-decoration: none;
}
.app-btn.e-btn .e-btn-icon { margin: 0; width: auto; font-size: 18px; line-height: 1; }
.app-btn.e-btn.e-small .e-btn-icon { font-size: 16px; }
.app-btn.e-btn.e-icon-btn { padding-left: 6px; padding-right: 6px; }
.app-btn.e-btn.e-disabled, .app-btn.e-btn:disabled { opacity: .5; pointer-events: none; }

/* ── Casete de text ──────────────────────────────────────────────────────────────────── */
input.app-input.e-input, textarea.app-input.e-input {
    width: 100%; box-sizing: border-box; height: 32px; padding: 4px 8px; margin: 0;
    border: 1px solid var(--app-border-strong); border-radius: var(--app-radius);
    background: var(--app-surface); color: inherit; font: inherit;
}
textarea.app-input.app-memo { height: auto; min-height: 64px; resize: vertical; line-height: 1.4; }
input.app-input.e-input:focus, textarea.app-input.e-input:focus {
    outline: none; border-color: var(--app-accent); box-shadow: 0 0 0 3px rgba(13,110,253,.15);
}
input.app-input.e-input:disabled, textarea.app-input.e-input:disabled,
input.app-input.e-input[readonly] { background: #f3f4f6; color: #6c757d; }
input.app-input.e-error { border-color: #dc3545; }

/* Editoarele bibliotecii (liste, date, numere) iau toata latimea campului, ca si casetele de text. */
.app-combo.e-control-wrapper, .app-date.e-control-wrapper, .app-number.e-control-wrapper,
.app-tagbox.e-control-wrapper { width: 100%; }

/* ── Bifa ────────────────────────────────────────────────────────────────────────────── */
.app-checkbox { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; user-select: none; }
.app-checkbox input { width: 16px; height: 16px; margin: 0; accent-color: var(--app-accent); cursor: pointer; }
.app-checkbox-disabled { cursor: default; color: #868e96; }
.app-checkbox-disabled input { cursor: default; }

/* ── Panou derulant (AppDropDown) si elementele lui de meniu ─────────────────────────── */
.app-dropdown { position: relative; display: inline-flex; align-items: center; }
.app-dropdown-backdrop { position: fixed; inset: 0; z-index: 1900; }
.app-dropdown-panel {
    position: absolute; top: 100%; left: 0; z-index: 1901; margin-top: 4px; min-width: 190px;
    padding: 4px; background: var(--app-surface); border: 1px solid var(--app-border);
    border-radius: var(--app-radius-lg); box-shadow: var(--app-shadow-dialog);
}
.app-dropdown-panel.app-dropdown-right { left: auto; right: 0; }
.app-menu-item {
    display: flex; align-items: center; gap: 8px; width: 100%; padding: 7px 10px;
    border: 0; border-radius: var(--app-radius); background: none; color: inherit; font: inherit;
    text-align: left; white-space: nowrap; cursor: pointer;
}
.app-menu-item:hover { background: var(--app-accent-soft); }
.app-menu-item .mi { font-size: 18px; }
.app-menu-item-current { font-weight: 600; color: var(--app-accent-strong); }
.app-menu-item-sep { margin-top: 4px; border-top: 1px solid var(--app-border); border-radius: 0 0 var(--app-radius) var(--app-radius); }

/* Buton compus: actiunea principala + sageata care deschide restul. */
.app-split .app-split-main.e-btn { border-top-right-radius: 0; border-bottom-right-radius: 0; }
.app-split .app-split-toggle.e-btn { margin-left: -1px; padding-left: 2px; padding-right: 2px; border-top-left-radius: 0; border-bottom-left-radius: 0; }

.app-user-menu-panel { padding: 8px; }

/* ── Notificari ──────────────────────────────────────────────────────────────────────── */
.app-toasts {
    position: fixed; top: 56px; right: 16px; z-index: 3000;
    display: flex; flex-direction: column; gap: 8px; pointer-events: none;
}
.app-toast {
    display: flex; align-items: flex-start; gap: 10px; min-width: 260px; max-width: 420px;
    padding: 10px 12px; border-radius: var(--app-radius-lg); background: #212529; color: #fff;
    box-shadow: var(--app-shadow-dialog); pointer-events: auto;
}
.app-toast-text { display: flex; flex-direction: column; gap: 2px; flex: 1; font-size: 13px; }
.app-toast-icon { font-size: 20px; }
.app-toast-success .app-toast-icon { color: #51cf66; }
.app-toast-danger { background: #a61e2b; }
.app-toast-warning .app-toast-icon { color: #ffd43b; }
.app-toast-close { border: 0; background: none; color: inherit; opacity: .7; cursor: pointer; padding: 0; }
.app-toast-close:hover { opacity: 1; }
.app-toast-close .mi { font-size: 18px; }

/* ── Meniul lateral (AppMenu) ────────────────────────────────────────────────────────── */
.app-sidebar { overflow: visible; }
.app-menu-list, .app-menu-flyout { list-style: none; margin: 0; padding: 0; }
.app-menu-list { padding: 0 6px; }
.app-menu-node { position: relative; }
.app-menu-link {
    display: flex; align-items: center; gap: 10px; width: 100%; height: 38px; padding: 0 10px;
    border: 0; border-radius: var(--app-radius); background: none; color: inherit; font: inherit;
    font-size: 14px; text-align: left; text-decoration: none; cursor: pointer; box-sizing: border-box;
}
.app-menu-link:hover, .app-menu-node:hover > .app-menu-link { background: var(--app-accent-soft); color: var(--app-accent-strong); }
.app-menu-icon { font-size: 20px; opacity: .8; }
.app-menu-text { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.app-menu-chevron { font-size: 18px; color: var(--app-text-muted); }
.app-menu-flyout {
    display: none; position: absolute; left: 100%; top: -4px; z-index: 1500; min-width: 240px;
    padding: 4px; background: var(--app-surface); border: 1px solid var(--app-border);
    border-radius: var(--app-radius-lg); box-shadow: var(--app-shadow-dialog);
}
.app-menu-node:hover > .app-menu-flyout, .app-menu-node:focus-within > .app-menu-flyout { display: block; }
.app-menu-closing .app-menu-flyout { display: none !important; }
.app-menu .app-menu-current > .app-menu-link { background: var(--app-accent-soft); color: var(--app-accent-strong); font-weight: 600; }
.app-menu .app-menu-current > .app-menu-link .app-menu-icon { opacity: 1; }
.app-sidebar-collapsed .app-menu-list > .app-menu-node > .app-menu-link { justify-content: center; padding: 0; }
.app-sidebar-collapsed .app-menu-list > .app-menu-node > .app-menu-link > .app-menu-text,
.app-sidebar-collapsed .app-menu-list > .app-menu-node > .app-menu-link > .app-menu-chevron { display: none; }

/* ── Tabelul simplu (liniile documentelor, sublistele, lista ferestrei de cautare) ────── */
.app-plain-grid { overflow-x: auto; }

/* [TEHNIC] Intr-o fereastra, tabelul NU se strange (2026-10-13). Corpul ferestrei e o coloana flex cu inaltime
   maxima si derulare, iar `overflow-x: auto` de mai sus ii da tabelului inaltime minima zero: cand continutul
   depaseste fereastra, coloana il strange pe el primul, pana la 2 pixeli, si randurile raman taiate — fara nicio
   eroare. Vazut la administratorii unei firme: dupa numire aparea banda de confirmare, continutul trecea de
   inaltimea ferestrei si lista ramanea goala tocmai cand trebuia sa arate omul abia numit. Doar pe copilul
   direct al corpului de fereastra: listele „cat pagina" se sprijina tocmai pe strangere. */
.app-dialog-body > .app-plain-grid { flex-shrink: 0; }
.app-table { width: 100%; border-collapse: collapse; table-layout: fixed; font-size: 13px; }
.app-table th {
    padding: 6px 6px; background: #fafbfc; color: #495057; font-weight: 600; text-align: left;
    border-bottom: 1px solid var(--app-border); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.app-table td {
    padding: 3px 4px; border-bottom: 1px solid var(--app-border); vertical-align: middle;
    overflow: hidden; text-overflow: ellipsis;
}
.app-table tbody tr:last-child td { border-bottom: 0; }
.app-table tbody tr:hover td { background: var(--app-accent-soft); }
.app-table .app-cell-right { text-align: right; }
.app-table .app-cell-center { text-align: center; }
.app-table .app-th-sort { cursor: pointer; }
.app-th-sort-icon { font-size: 14px; vertical-align: middle; }
.app-table-empty td { padding: 14px; text-align: center; color: var(--app-text-muted); }
.app-table-empty:hover td { background: none !important; }
.app-table tfoot td { background: #fafbfc; font-weight: 600; border-top: 1px solid var(--app-border); border-bottom: 0; }
.app-table tr.app-row-highlight > td { background-color: var(--app-accent-soft); }
.app-table tr.app-row-current > td { box-shadow: inset 0 1px 0 var(--app-accent), inset 0 -1px 0 var(--app-accent); }

.app-search-dialog-list { overflow: auto; border: 1px solid var(--app-border); border-radius: var(--app-radius); }
.app-list-table thead th { position: sticky; top: 0; z-index: 1; }
.app-list-row { cursor: pointer; }
.app-list-row td { padding: 6px 8px; white-space: nowrap; }
.app-table tr.app-list-row-selected > td { background: var(--app-accent); color: #fff; }

/* ── Grila bibliotecii (listele) ─────────────────────────────────────────────────────── */
.app-sfgrid .e-grid { border: 0; font-family: inherit; }
.app-sfgrid .e-grid .e-headercell, .app-sfgrid .e-grid .e-filterbarcell { padding: 0 6px; height: 34px; }
.app-sfgrid .e-grid .e-headercell { background: #fafbfc; color: #495057; font-weight: 600; }
.app-sfgrid .e-grid .e-headercelldiv { font-size: 13px; font-weight: 600; padding: 0 2px; }
.app-sfgrid .e-grid .e-rowcell { padding: 3px 6px; font-size: 13px; line-height: 1.35; }
.app-sfgrid .e-grid .e-filterbarcell input.e-input, .app-sfgrid .e-grid .e-filterbarcell .e-input-group { height: 26px; min-height: 26px; }
.app-sfgrid .e-grid .e-gridpager { padding: 2px 6px; }
.app-sfgrid .e-grid .e-summarycell { padding: 4px 6px; font-size: 13px; }
.app-sfgrid .e-grid tr.e-row:hover .e-rowcell { background-color: var(--app-accent-soft) !important; }
.app-sfgrid .e-grid tr.app-row-highlight > td.e-rowcell { background-color: var(--app-accent-soft) !important; }
.app-sfgrid .e-grid tr.app-row-highlight > td.e-rowcell:first-child { box-shadow: inset 3px 0 0 var(--app-accent); }
.app-filter-combo.e-control-wrapper { min-width: 0; }

/* Lista „cat pagina": grila umple invelisul si isi deruleaza randurile in interior. */
.app-sfgrid.app-grid-fill { display: flex; flex-direction: column; min-height: 0; }
.app-sfgrid.app-grid-fill > .e-grid { flex: 1 1 auto; min-height: 0; }

/* ── Fereastra (AppPopup) ────────────────────────────────────────────────────────────── */
.app-popup.e-dialog { border-radius: var(--app-radius-lg); box-shadow: var(--app-shadow-dialog); max-height: calc(100vh - 40px) !important; }
.app-popup.e-dialog .e-dlg-header-content { padding: 14px 24px; border-bottom: 1px solid var(--app-border); border-radius: var(--app-radius-lg) var(--app-radius-lg) 0 0; }
.app-popup.e-dialog .e-dlg-header { font-size: 16px; font-weight: 600; }
.app-popup.e-dialog .e-dlg-content { padding: 0; display: flex; flex-direction: column; min-height: 0; border-radius: 0 0 var(--app-radius-lg) var(--app-radius-lg); }
.app-popup-body { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.app-popup-body > form { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }

/* Butoanele-pictograma de pe randurile listelor: mici, ca randul sa ramana compact (~32px). */
.app-icon-btn.e-btn { height: 26px; min-height: 26px; min-width: 28px !important; padding: 2px 5px !important; margin-right: 2px; line-height: 1; }

/* Gazda nevazuta a exportului unui tabel simplu (vezi AppGrid): in afara ecranului, nu ascunsa cu display. */
.app-export-host { position: absolute; left: -10000px; top: 0; width: 1200px; height: 0; overflow: hidden; }

/* Lista ferestrei de cautare e un tabel obisnuit intr-o cutie care deruleaza. */
.app-search-dialog-list { display: block; }

/* Invelisurile editoarelor (pentru focus din cod si pentru Enter): nu participa la asezare. */
.app-number-host, .app-combo-host { display: contents; }
