/* ============================================================================
   CentPerCent — design system.

   Every colour a component paints with comes from these tokens. Components
   used to hardcode #fff and #f8fbff, so switching to the dark theme left
   white cards on a dark page. One source of truth means dark mode follows
   for free, and the palette can be retuned in one place.

   Structure:
     1. Tokens (light + dark)
     1b. Registered properties (@property) — the tokens that need to MOVE
     2. Base: body, aurora backdrop, typography, scrollbars
     3. App shell: sidebar, topbar, content
     4. Core controls: buttons, forms, dropdowns, modals, toasts, badges
     5. Components: page-head, stat cards, table cards, empty states, chips,
        timeline, auth pages, command palette
     6. Feature surfaces kept from before: task board, chat (tm-*), deadlines,
        today's meetings, client panel — restyled, same class names
     7. Print
     8. Motion + accessibility
     9. Shtresa e përbashkët: tabela e të dhënave, çifti etiketë→vlerë, shiriti
        i filtrave, gjendjet bosh, pamja e pritjes, koka e pasuruar, kartela e
        detajit, rrjeta e faqes, kartelat në një vijë (subgrid), hyrja me
        rrëshqitje — format që faqet i rindërtonin secila vetë
   ========================================================================= */

/* Kaskada, e thënë një herë dhe me emra.

   Deri tani Bootstrap-i hynte me `<link>` te base.html dhe kjo fletë vinte pas
   tij — pra e mundte vetëm me specifikë, dhe aty ku s'e mundte dot, me
   `!important`. Ai ishte çmimi i të qenit mbi një framework pa shtresa: jo
   neglizhencë, por mungesë e një mjeti.

   Shtresat e zëvendësojnë atë mjet. Çdo gjë te `vendor` humbet nga çdo gjë te
   shtresat pas saj, pavarësisht specifikës — pra një `.btn` i yni e mund
   `.btn.btn-primary` të Bootstrap-it pa asnjë fjalë të fortë.

   Radha këtu është SAKTËSISHT radha e këtij skedari: tokena, bazë, komponentë,
   dhe në fund kontrasti i lartë. Kjo nuk është rastësi dhe as zbukurim — nëse
   shtresat rreshtohen ndryshe nga burimi, kaskada e brendshme ndryshon bashkë
   me to dhe rregulla që sot humbin fillojnë të fitojnë. E provuar: seksioni 8
   (lëvizja dhe qasshmëria) i vendosur te një shtresë mbi seksionin 9 do t'i
   fitonte atij, gjë që sot nuk ndodh.

   `@import` duhet të rrijë para çdo rregulli, dhe deklarimi i shtresave para
   tij — vetëm komentet lejohen më lart. Bootstrap-i lexohet ende nga e njëjta
   rrugë, pra `sw.js` (rreshti 65) e gjen aty ku e ka pritur gjithnjë.

   --- Ç'u bë me `!important`-et -------------------------------------------
   Ishin 93 deklarata të forta te rregulla; mbetën 84. U hoqën nëntë, dhe vetëm
   nëntë, sepse shtresat ndihmojnë shumë më pak se sa duket. Arsyeja është një
   rregull i vetëm i kaskadës: një deklaratë e FORTË e përmbys radhën e
   shtresave. Bootstrap-i ka 1.715 sish — i tërë niveli i utility-ve të tij.
   Pra `!important`-i i `vendor`-it e mund ende rregullin tonë normal, dhe e
   mund vetëm një `!important` i yni.

   Mbeten katër familje, dhe asnjëra nuk pret shtresë:

     53  shtypi mbi ekranin. Blloqet `@media print` rrinë të shpërndara në
         tetë vende të skedarit, pranë rregullave që mbivendosin. Do të hiqeshin
         vetëm duke i mbledhur të tetët në një shtresë të fundit — shpërngulje
         e vërtetë, jo mbështjellje, prandaj rri si punë më vete.
     19  detyrime të vetëdijshme ndaj vetes: `.panel-off` (njeriu e fiku me
         dorë), `[hidden]`, `prefers-reduced-motion` mbi `*`. Këto DUHET të
         jenë të forta; s'janë borxh.
      9  ndaj utility-ve të Bootstrap-it (`.text-muted`, `.bg-primary`,
         `.d-none`…). Ai i shkruan me `!important`, pra vetëm `!important` i
         përgjigjet. Shtresa këtu nuk bën asgjë.
      3  të shpjeguara aty ku rrinë: dy sepse Popper-i shkruan `position` te
         atributi `style` — asnjë shtresë s'e prek një stil inline — dhe një
         sepse kundërshtari është një rregull i këtij skedari, jo i Bootstrap-it.

   Të nëntat e hequra u provuan me piksela, jo me arsyetim: e njëjta faqe
   tabelash para e pas, në dy gjerësi — zero ndryshim. */
@layer vendor, tokens, base, components, utilities;
@import url('../vendor/bootstrap/bootstrap.min.css') layer(vendor);

@layer tokens {

:root {
  color-scheme: light;

  /* Surfaces, from the page backwards to the topmost card. */
  --bg: #f2f4fb;
  --surface: #ffffff;
  --surface-muted: #f5f7fc;   /* inputs, table stripes, quiet panels */
  --surface-sunken: #edf0f8;  /* wells the page sits behind */
  --surface-hover: rgba(30,41,59,.045);

  /* Translucent shells for the sidebar / topbar glass. */
  --glass: rgba(255,255,255,.78);
  --glass-strong: rgba(255,255,255,.92);
  --glass-blur: 18px;
  /* Sipërfaqja që hapet MBI një kartelë: menyja rënëse, paleta e komandave,
     shiriti i veprimit me shumicë.

     `--glass-strong` u shkrua për shiritin e sipërm dhe për shiritin e telefonit
     — gjëra që rrinë mbi vetë FAQEN. Të ripërdorura për diçka që hapet mbi një
     kartelë, ato e përmbysin ngritjen te tema e errët, sepse aty ngritja shkon
     nga e errëta te e ndritura: faqja ndriçon 0,34, kartela 0,94, dhe menyja
     mbi të binte te 0,68 — pra dukej si e futur nën kartelën që e mbante, dhe
     hija s'kishte ku të shihej. Këtu ajo del te 1,77.

     Në temën e ndritshme vlera është fjalë për fjalë ajo e mëparshme: aty
     ngritja shkon nga e ndritura te e bardha, dhe s'kishte asgjë të prishur. */
  --surface-raised: rgba(255,255,255,.92);
  /* Xhami i sheshuar: pikërisht `--glass` i piktuar mbi `--bg`, vetëm pa alfa.
     I duhet çdo gjëje që rri NGJITUR brenda guaskës prej xhami — një titull
     seksioni me sfond të tejdukshëm i lë lidhjet të rrëshqasin nën vete, dhe një
     `backdrop-filter` i dytë brenda një të pari është një shtresë kompozimi më
     shumë pikërisht te Chromium-i i inkorporuar që na ka dhënë hallin njëherë. */
  --glass-solid: #fcfdfe;

  --border: rgba(30,41,59,.10);
  --border-strong: rgba(30,41,59,.16);
  --surface-border: var(--border);

  --text: #101728;
  --muted: #5a6a85;
  /* Checked against the page background — placeholders and empty states are
     exactly the text people struggle with, so contrast is measured, not
     eyeballed.

     E matur ishte, por vetëm te tema e errët: atje një provë e mban prej kohësh
     mbi 4,5:1 për të tria sipërfaqet, kurse këtu asgjë nuk e ruante. `#75839b`
     jepte 3,83:1 mbi kartelë dhe 3,36:1 mbi `--surface-sunken` — nën kufirin AA
     te 112 përdorime, ku hyjnë placeholder-i i çdo fushe, `.form-text`,
     `.stat-note` dhe orët te timeline-i. Pra pikërisht teksti që koment i
     mësipërm premton se u mat.

     `#606d84` e njëjta familje, vetëm më e ngopur: 5,23:1 mbi kartelë dhe 4,58:1
     mbi më të errëtën e katër sipërfaqeve. Roja tani është provë, jo koment —
     shih `test_faint_text_clears_the_aa_line_on_every_light_surface`. */
  --faint: #606d84;

  /* Indigo core with a violet ramp: the gradient the brand, primary buttons
     and active nav all share, so the accent reads as one voice everywhere. */
  --primary: #4f46e5;
  --primary-dark: #4338ca;
  --primary-2: #7c3aed;
  --primary-contrast: #ffffff;
  /* Familja e aksentit derivohet nga `--primary`, nuk rishkruhet.
     Deri tani secila nga këto ishte një `rgba()` e shkruar me dorë me të njëjtat
     tri shifra — pra ngjyra primare ishte shkruar gjashtë herë në këtë skedar,
     dhe një retuning i saj do të linte pesë prej tyre pas. `color-mix` e kthen
     në atë që gjithnjë ka qenë: e njëjta ngjyrë me opacitet tjetër. Përqindjet
     janë saktësisht ato të vlerave të vjetra, pra faqja nuk ndryshon asnjë piksel
     sot — ndryshon vetëm ç'kushton retuning-u nesër. */
  --primary-soft: color-mix(in srgb, var(--primary) 10%, transparent);
  /* Roli, jo hija: ngjyra primare kur eshte TEKST. Ne temen e ndritshme kjo
     eshte pikerisht --primary-dark, prandaj asgje nuk ndryshon ketu; ne te
     erreten duhet e kunderta, dhe pa nje token te vetin cdo perdorim e
     gjente vete rrugen e gabuar. */
  --primary-text: #4338ca;
  --primary-line: color-mix(in srgb, var(--primary) 24%, transparent);
  /* Dy skajet e gradientit, veç nga gradienti vetë.
     Një `linear-gradient(...)` i mbaruar është një vlerë që nuk hapet dot më:
     kush do vetëm këndin, ose vetëm ngjyrën e parë, duhet ta rishkruajë të tërin
     — dhe atëherë ka dy gradientë që duhen mbajtur në hap. Skajet të veçuara e
     lejojnë butonin ta rrotullojë këndin nën mi pa e prekur ngjyrën, dhe ngjyra
     mbetet e shkruar një herë. */
  --grad-from: #4f46e5;
  --grad-to: #7c3aed;
  --grad-from-hover: #4338ca;
  --grad-to-hover: #6d28d9;
  --grad-primary: linear-gradient(135deg, #4f46e5, #7c3aed);
  --grad-primary-hover: linear-gradient(135deg, #4338ca, #6d28d9);
  /* I njejti gradient kur perdoret si TEKST (background-clip). Ne temen e
     ndritshme eshte identik me mbushjen — teksti rri mbi te bardhe, pra
     duhet po aq i erret. Ne te erreten duhet e kunderta, prandaj token. */
  --grad-primary-text: var(--grad-primary);

  /* A cool second accent for highlights that should not read as "primary". */
  --accent: #0891b2;
  --accent-soft: color-mix(in srgb, var(--accent) 10%, transparent);

  --success: #0e7a4a;
  --success-soft: rgba(16,185,129,.13);
  --warning: #9a5b08;
  --warning-soft: rgba(245,158,11,.15);
  --danger: #c02626;
  --danger-soft: rgba(220,38,38,.10);
  --info: #0369a1;
  --info-soft: rgba(14,165,233,.12);

  /* I njëjti status, por si SIPËRFAQE.
     Ato më sipër janë ngjyra e statusit kur ai është tekst — të errëta, të
     matura kundër së bardhës. Një pikë kalendari, mbushja e një shiriti ose një
     shtyllë grafiku duan të kundërtën, dhe pikërisht sepse s'kishin token,
     secila e zgjidhte vetë: brenda këtij skedari rrinin katër jeshile
     (#10b981, #059669, #22c55e, #16a34a), dy të kuqe dhe dy të verdha, dhe
     grafikët te Analitika mbanin nga tri të tjera të shkruara me dorë. Pra e
     njëjta «e kryer» dilte me një jeshile te tabela dhe me një tjetër te
     grafiku pranë saj — e njëjta faqe, dy të vërteta.

     Dy hapa për secilin, sepse gradientët e ikonave duan një çift: `-strong`
     është fundi i errët, ai pa prapashtesë është fundi i ndritshëm. Larja e
     zbehtë pas tyre e ka tashmë tokenin e vet — `--success-soft` e të tjerat. */
  --success-fill: #10b981;
  --success-fill-strong: #059669;
  --warning-fill: #f59e0b;
  --warning-fill-strong: #d97706;
  /* Hapi i katërt i shkallës së vjetërsimit të borxhit: mes «po vonohet» dhe
     «vonuar». Ekziston vetëm aty, prandaj mban emrin e vet. */
  --warning-fill-deep: #f97316;
  /* «Urgjent»: tri ditë a më pak deri te afati. As e verdhë («po vjen») as e
     kuqe («kaloi») — një gjendje e katërt që faqja e deklarimeve e ndan nga të
     dyja. E kishte këtë hex të shkruar me dorë në pesë vende, pra e njëjta
     portokalli ishte pesë ngjyra që rastësisht përputheshin. */
  --urgent: #ea580c;
  --urgent-soft: rgba(234, 88, 12, .04);
  --danger-fill: #ef4444;
  --danger-fill-strong: #dc2626;
  /* Aksenti e kishte çiftin e vet të shkruar me dorë brenda ikonës së një
     kartele — `linear-gradient(135deg,#0891b2,#06b6d4)` — pra e vetmja ngjyrë e
     programit që s'e prekte dot as tema, as një retuning. Këtu është si të
     tjerat: `-strong` fundi i errët, pa prapashtesë fundi i ndritshëm. */
  --accent-fill: #06b6d4;
  --accent-fill-strong: #0891b2;
  /* «Gjallë»: pika që pulson kur diçka është në linjë tani. Është një hap më e
     ndritshme se `--success-fill`, sepse nuk e lexon kush si tekst — dhe rri e
     njëjtë në të dyja temat, si çdo mbushje. E kishte këtë emerald të shkruar
     shtatë herë me tri shifra, brenda dy pikave dhe dy grupeve kuadrosh. */
  --live: #34d399;
  /* Jeshilja e Excel-it. Nuk është `--success` dhe nuk duhet të bëhet: është
     ngjyra e një programi tjetër, e vënë mbi butonin që nxjerr skedarin e tij.
     Rrinte si dy hex-e brenda një gradienti e një `rgba()` brenda një hijeje —
     pra e vetmja ngjyrë e huaj e programit, e shkruar tri herë. */
  --excel: #16a765;
  --excel-strong: #0f9d58;

  /* Çifti «të ardhura / shpenzime» te grafikët e Analitikës, i zgjedhur me
     validatorin e paletës e jo me sy: në dritë #4f46e5/#0891b2 kalojnë çdo
     kontroll. Rrinin te një `if (dark)` brenda faqes; këtu tema i vendos vetë,
     si çdo ngjyrë tjetër e programit. */
  --chart-revenue: #4f46e5;
  --chart-expense: #0891b2;

  /* Paleta e serive te Analitika — ngjyrat e paracaktuara të Power BI Desktop.
     Nuk janë zgjedhur për t'i shkuar markës: janë zgjedhur sepse ajo faqe është
     një raport BI dhe kush lexon raporte e njeh këtë renditje pa e menduar —
     blu për serinë e parë, portokalli për të dytën, pastaj navy. Aksenti indigo
     i programit mbetet i paprekur kudo tjetër; këtu ngjyra i takon të dhënave,
     jo markës.

     Rrinë te `:root` e jo brenda `.bi-report`, sepse ato i lexon JavaScript-i i
     grafikëve nga `getComputedStyle(document.body)` — i njëjti burim si çdo
     ngjyrë tjetër e programit, pra tema i ndërron edhe këto. */
  --bi-cat-1: #118dff;
  --bi-cat-2: #e66c37;
  --bi-cat-3: #12239e;
  --bi-cat-4: #6b007b;
  --bi-cat-5: #e044a7;
  --bi-cat-6: #744ec2;
  --bi-cat-7: #d9b300;
  --bi-cat-8: #d64550;
  /* Statuset e raportit, në të njëjtën gjuhë: jeshilja, e verdha dhe e kuqja e
     Power BI-t, jo ato të pjesës tjetër të programit. Brenda një kanavace ku
     çdo ngjyrë tjetër është e tija, dy jeshile të ndryshme lexohen si dy gjëra
     të ndryshme. */
  --bi-good: #1aab40;
  --bi-warn: #d9b300;
  --bi-bad: #d64550;

  /* Chrome-i i dritares së raportit — gri-të e Power BI-t. Rrinë këtu e jo
     brenda `.bi-report` që të lexohen si çdo token tjetër i programit: nga
     JavaScript-i, dhe nga kontrollet e kontrastit që i kërkojnë tokenat te
     blloku i temës. Kush i përdor është vetëm Analitika. */
  --bi-canvas: #f1f1f1;        /* kanavaca nën vizualet */
  --bi-visual: #ffffff;        /* kutia e një vizuali */
  --bi-line: #e1dfdd;          /* vija e floku rreth saj */
  --bi-line-soft: #edebe9;
  --bi-ink: #252423;           /* teksti kryesor i raportit */
  --bi-ink-2: #605e5c;         /* tituj boshtesh, etiketa, gjithçka dytësore */
  --bi-chrome: #f3f2f1;        /* koka, paneli i filtrave, shiriti i faqeve */
  --bi-chrome-hover: #edebe9;
  --bi-accent: #0078d4;        /* blu-ja e chrome-it, jo e të dhënave */
  --bi-accent-dark: #106ebe;
  /* Fonti i raportit. Segoe UI-ja është shkrimi i Power BI-t dhe e ka çdo
     Windows — pra asnjë skedar nuk shkarkohet dhe asnjë host i jashtëm nuk
     preket. Kudo tjetër bie te fonti i programit, që kanavaca të mos mbetet pa
     shkrim aty ku Segoe-ja nuk ekziston. */
  --bi-font: 'Segoe UI', 'Segoe UI Variable Text', system-ui, -apple-system,
             'Inter Variable', Inter, sans-serif;
  --bi-radius: 4px;
  --bi-shadow: 0 1.6px 3.6px rgba(0,0,0,.09), 0 .3px .9px rgba(0,0,0,.06);
  --bi-shadow-hover: 0 3.2px 7.2px rgba(0,0,0,.11), 0 .6px 1.8px rgba(0,0,0,.08);
  /* Thellësia e tretë e së njëjtës familje: kartela që ka marrë fokusin te
     raporti. Rrinte e shkruar te vetë rregulli, pra ishte e vetmja hije e
     raportit që s'e ndërronte temën bashkë me dy motrat e saj. */
  --bi-shadow-focus: 0 25.6px 57.6px rgba(0,0,0,.22), 0 4.8px 14.4px rgba(0,0,0,.18);

  /* Elevation: a short, deliberate scale rather than one enormous shadow. */
  --shadow-sm: 0 1px 2px rgba(23,25,60,.05), 0 1px 3px rgba(23,25,60,.05);
  --shadow-md: 0 2px 4px rgba(23,25,60,.04), 0 10px 24px rgba(23,25,60,.07);
  --shadow-lg: 0 14px 34px rgba(23,25,60,.12), 0 3px 8px rgba(23,25,60,.06);
  /* Drita e faqes bie nga lart, pra çdo hije bie poshtë — përveç njërës.
     Shiriti i poshtëm i telefonit rri MBI faqen që shkon nën të, dhe hija e tij
     ngjitet përpjetë. Ishte i vetmi vend ku ajo hije shkruhej me dorë, dhe
     pikërisht prandaj ishte i vetmi që s'e ndërronte kurrë temën. */
  --shadow-up: 0 -2px 14px rgba(23,25,60,.06);
  --shadow-glow: 0 6px 20px color-mix(in srgb, var(--primary) 28%, transparent);
  /* Po ai shkëlqim, kur butoni është nën mi. Rrinte i shkruar me dorë te
     `.btn-primary:hover`, me tri shifrat e indigos së ndritshme — pra në temën
     e errët butoni ndriçonte me ngjyrën e temës tjetër, sepse asnjë token s'e
     prekte atë rresht. */
  --shadow-glow-strong: 0 8px 24px color-mix(in srgb, var(--primary) 34%, transparent);
  --card-shadow: var(--shadow-md);

  /* I njëjti shkëlqim kur sendi nën të nuk është primar.
     Ishin pesë rreshta të shkruar me dorë — `0 8px 20px`, `0 6px 18px`,
     `0 4px 14px` — me tri shifrat e ngjyrës brenda: pra as ndërronin temë, as
     binin mbi njëri-tjetrin, dhe ikona e afatit ndriçonte ndryshe nga shiriti
     që tregonte të njëjtin alarm. Gjeometria është e `--shadow-glow`-t; nga
     tokeni vjen vetëm ngjyra, dhe ajo është ngjyra e MBUSHJES, jo e tekstit —
     një shkëlqim merr ngjyrën e sendit që ndriçon. */
  --glow-accent: 0 6px 20px color-mix(in srgb, var(--accent-fill-strong) 26%, transparent);
  --glow-success: 0 6px 20px color-mix(in srgb, var(--success-fill) 32%, transparent);
  --glow-warning: 0 6px 20px color-mix(in srgb, var(--warning-fill) 32%, transparent);
  --glow-danger: 0 6px 20px color-mix(in srgb, var(--danger-fill-strong) 32%, transparent);

  /* Rrezja: pesë hapa dhe dy forma.
     Poshtë katër hapave rrinin dyzet vlera të tjera — `2px`, `.2rem`, `3px`,
     `.25rem`, `.3rem`, `4px`, `.35rem`, `5px`, `6px`, `.4rem`, `7px`, `.45rem`,
     `8px`, `.5rem` — pra çdo komponent e zgjidhte vetë sa i rrumbullakët të
     ishte, dhe dy çipa fqinjë nuk binin kurrë mbi njëri-tjetrin. Hapat e vjetër
     nuk lëvizën asnjë piksel: u shtua vetëm hapi që mungonte poshtë tyre, aty
     ku ishte grumbulluar gjysma e atyre vlerave.
     `--radius-pill` dhe `--radius-round` nuk janë hapa por FORMA: e para thotë
     «skajet janë gjysmërrathë», e dyta «kjo është rreth». Ishin shkruar `999px`,
     `99px`, `800px` dhe `50%` — katër mënyra për dy gjëra. */
  --radius-xs: .25rem;   /*  4px — shirita, mini-bare, kutiza, pika */
  --radius-sm: .55rem;   /* 8.8px — çipa, butona, fusha */
  --radius: .8rem;       /* 12.8px — kutia e zakonshme */
  --radius-lg: 1.1rem;   /* 17.6px — kartela */
  --radius-xl: 1.5rem;   /* 24px — sipërfaqja që mban kartela të tjera */
  --radius-pill: 999px;
  --radius-round: 50%;

  /* Dhe e njëjta shkallë te ç'vizaton Bootstrap-i.
     Katër rrezet e tij lexohen 106 herë brenda fletës së vendor-it — faqet e
     numëruara, akordeoni, kutiza, `input-group`, `list-group`, `progress`,
     `offcanvas` — pra çdo komponent që s'e kemi prekur me dorë e mban ende
     shkallën e vet: 4px, 6px, 8px, 16px, 32px dhe një «pill» prej 800px. Kjo
     është arsyeja pse ekrani nxori njëzet e shtatë rreze aty ku shkalla ka
     pesë: gjysma e bishtit nuk ishte e jona fare. Një bllok i vetëm e lidh atë
     shkallë me këtë — dhe ata komponentë e marrin pa i rishkruar një nga një.
     Rreshtat vlejnë vetëm pse shtresa `tokens` vjen pas `vendor`-it. */
  --bs-border-radius-sm: var(--radius-xs);
  --bs-border-radius: var(--radius-sm);
  --bs-border-radius-lg: var(--radius);
  --bs-border-radius-xl: var(--radius-lg);
  --bs-border-radius-xxl: var(--radius-xl);
  --bs-border-radius-pill: var(--radius-pill);

  /* E njëjta rrugë për trupin e faqes. Kjo është e vetmja madhësi e vendor-it që
     rri vërtet te `:root`-i i tij; të tjerat janë deklaruar brenda rregullit të
     vet komponentit, pra atyre u përgjigjet seksioni 9b dhe jo ky rresht.
     Vlera nuk lëviz asnjë piksel — `1rem` ËSHTË `--text-base`. Ajo që ndryshon
     është kush e zotëron: hapi tjetër i shkallës e merr me vete edhe trupin. */
  --bs-body-font-size: var(--text-base);

  /* Gjerësitë e katër formave që NUK janë elevacion.
     `box-shadow` i vizaton të katërta, prandaj rrinin të përziera me hijet dhe
     secila kishte marrë gjerësinë e vet sipas seksionit: rripi i majtë ishte
     `3px` diku, `2px` diku tjetër dhe `.2rem` në një vend të tretë — i njëjti
     rrip, tri trashësi. Emri e mban njëfarësh. */
  --rail: 3px;           /* rripi i majtë që shënon gjendjen e një rreshti */
  --hairline: 1px;       /* vija e brendshme që zëvendëson një kufi */
  --ring-w: 2px;         /* unaza e zgjedhjes rreth një sendi */
  --ring-w-lg: 3px;      /* unaza e fokusit, që duhet parë nga larg */

  --ring: 0 0 0 var(--ring-w-lg) color-mix(in srgb, var(--primary) 32%, transparent);
  /* Prerja: dy piksele të sipërfaqes rreth një pike, që pika të mos ngjitet me
     çfarëdo rreshti kalon nën të. Sipërfaqja vjen nga tokeni, pra prerja e
     ndërron temën bashkë me faqen. */
  --ring-cut: 0 0 0 var(--ring-w) var(--surface);

  /* Buza e sipërme e një sipërfaqeje të ngritur.
     Një kartelë e vërtetë nuk ka vetëm hije poshtë: ka edhe një vijë drite
     lart, aty ku sipërfaqja kthehet nga drita. Pa të, hija poshtë lexohet si
     njollë e pikturuar; me të, kutia lexohet si material. Kushton një `inset`
     të vetëm dhe rri te i njëjti `box-shadow` ku rri hija — pra as një element
     i vetëm i ri.
     Në dritë është e bardha e vetë sipërfaqes; në errësirë s'mund të jetë e
     bardhë (do të bëhej vijë neoni), prandaj tema e vet e ul në një pëshpërimë. */
  --edge-light: inset 0 1px 0 rgba(255,255,255,.65);
  --edge-light-soft: inset 0 1px 0 rgba(255,255,255,.4);

  /* Lëvizja: dy kthesa dhe tri kohëzgjatje, nga një burim i vetëm.
     Ngjyra, hapësira, shkronjat dhe hijet e kishin secila burimin e vet që në
     ditën e parë; lëvizja jo. Prandaj brenda këtij skedari rrinin `.15s ease`,
     `.18s ease`, `.12s ease` dhe `.2s ease` mbi gjëra që preken bashkë — dy
     butona fqinjë që i përgjigjen miut me dy shpejtësi të ndryshme, dhe askush
     s'e sheh pse faqja duket «e palidhur».

     `--ease-out` është kthesa që kishte tashmë gjysma e skedarit, e emërtuar;
     `--ease-spring` është e vetmja e re: mbaron pak përtej caqes dhe kthehet —
     pikërisht ç'bën një send që ngrihet nën dorë. Aty ku mungon `linear()`,
     mbetet një `cubic-bezier` me të njëjtin tejkalim, pra sjellja s'humbet.

     Si te hapësira, e vjetra nuk u rishkrua e tëra: këto janë standardi tutje,
     dhe janë vënë sot te sipërfaqet që preken më shpesh — butonat, kartelat,
     rreshtat e menysë. */
  --dur-1: .12s;   /* përgjigje e menjëhershme: ngjyrë, kufi */
  --dur-2: .18s;   /* lëvizja e zakonshme: ngritja e një kartele */
  --dur-3: .32s;   /* diçka që hyn ose del nga faqja */
  --dur-4: .7s;    /* diçka që tregon një sasi: shiriti që rritet drejt shifrës */
  --ease-out: cubic-bezier(.22,.61,.36,1);
  --ease-in-out: cubic-bezier(.65,0,.35,1);
  --ease-spring: cubic-bezier(.34,1.4,.64,1);

  /* Ritmet — lëvizja që përsëritet, e cila NUK është e njëjta gjë me atë më lart.
     `--dur-*` mat sa zgjat një përgjigje: dikush preku diçka, dhe ajo mbaron.
     Një ritëm nuk mbaron — ai rreh sa kohë gjendja qëndron, dhe koha e tij nuk
     është shpejtësi por puls. Prandaj kishin mbetur jashtë orës: një rrotullues
     me `--dur-3` do të dukej i çmendur, dhe një pikë që pulson me `--dur-1` do të
     dukej e prishur.

     Të katërt këto numra ekzistonin tashmë, të shkruar me dorë nëpër njëmbëdhjetë
     `animation:` — `1.4s` te tri vende të ndryshme, `.6s` te njëri rrotullues dhe
     `.65s` te tjetri, `1.5s` te një i tretë që donte të ishte i njëjti. Dy pika që
     pulsojnë me dy pulse janë e njëjta gjë si dy butona me dy shpejtësi. */
  --spin: .65s;        /* një rrotullues: rrotullimi i plotë */
  --beat-fast: 1.1s;   /* pikat e shkrimit — një bisedë pret shpejt */
  --beat: 1.4s;        /* shenja që kërkon sy: mikrofoni, rreshti që ndryshoi */
  --beat-slow: 2s;     /* pika e gjallë te një listë — rri aty, nuk ngutet */

  /* Deriva — lëvizja që nuk i përgjigjet askujt.
     `--dur-*` mat një përgjigje: dikush preku diçka, dhe ajo mbaron. `--beat-*`
     mat një puls: diçka pret, dhe rreh sa kohë pret. Kjo e treta nuk mat as
     njërën as tjetrën. Është një shtresë dekorative që lëviz gjithë ditën pa e
     nisur kush dhe pa e parë kush drejtpërdrejt — ajri i faqes, jo një përgjigje
     e saj. Koha e saj matet me dhjetëra sekonda, dhe pikërisht kjo e nxjerr nga
     të dyja familjet sipër: `--dur-4` te një aurorë do të ishte një dridhje,
     `--beat-slow` një kërcim.

     Që të tria kohët e para ekzistonin tashmë, të shkruara me dorë, dhe rrinin
     jashtë orës me emër te provat — jo sepse ishin të pamatura, por sepse ora
     s'kishte njësi për to. Përjashtimi me emër ishte plagë, jo rregull.

     Janë të ndryshme me qëllim e jo nga pakujdesia: tri shtresa me të njëjtën
     kohë bien në hap brenda ciklit të parë, dhe atëherë sfondi pulson si një
     send i vetëm — pikërisht ajo që një aurorë nuk duhet të bëjë. Përveç
     njëshit s'kanë pjesëtues të përbashkët, pra cikli ku do të takoheshin të
     tria është më i gjatë se çdo vizitë te faqja. */
  --drift-a: 19s;      /* shtresa e parë e një aurore */
  --drift-b: 25s;      /* e dyta, që s'bie kurrë në hap me të parën */
  --drift-c: 31s;      /* e treta */
  --drift-slow: 52s;   /* skena nën gjithë faqen: aq ngadalë sa s'zihet syri */
  --drift-tick: 37s;   /* shiriti i ngjarjeve: një kalim i plotë i listës */

  /* Hapësira: dhjetë hapa, hap bazë 4px.
     Ngjyrat, hijet dhe radiuset e kishin nga një burim të vetëm që në ditën e
     parë; hapësira jo. Prandaj brenda këtij skedari rrinin përkrah `.38rem`,
     `.34rem`, `.35rem` dhe `.3rem` — katër vlera që synonin të njëjtën gjë dhe
     s'binin kurrë saktësisht mbi njëra-tjetrën. Dy komponentë që duhet të duken
     njësoj, nuk duken kurrë njësoj kur secili e zgjedh vetë hapësirën e vet.

     Këtu rrinte një fjali që e shtynte punën: «nuk u rishkrua gjithçka prapa».
     Tani u rishkrua. Ishin **1.055 deklarata** hapësire me vlerë të ngurtë në
     778 rreshta, dhe **50 vlera të dallueshme** aty ku shkalla kishte shtatë:
     `.35` pranë `.34`, `.38` e `.4`; `.05`, `.1`, `.12`, `.15` e `.18` për të
     njëjtin hap prej dy pikselash. Të gjitha u palosën mbi këta dhjetë hapa me
     skript, dhe harta rri te vetë skripti.

     Tre vendime që i lexon diff-i por nuk i shpjegon:

     Dy gjysmë-hapa u shtuan sepse matja i kërkoi, jo simetria: `--space-1-5`
     (6px) mbulonte 224 deklarata — grumbulli më i madh i tërë skedarit — dhe
     `--space-6-5` (40px) mban mbushjet e mëdha të faqeve të hyrjes, që përndryshe
     do të lëviznin 6px secila. Asnjë gjeometri nuk zhvendoset më shumë se 1,6px.

     Barazimet zgjidhen POSHTË: 20px shkon te 16px, jo te 24px. Hapësira anash
     është gjëja e pakët e këtij programi — faqja e mesazheve dhe regjistri i
     faturave u luftuan pikërisht për të.

     Jashtë shkallës mbeten tetë numra, dhe të tetët janë e njëjta gjë: VEND I
     LËNË për një kontroll që rri absolute sipër — syri i fjalëkalimit, ikona
     brenda fushës, tre butonat te kutia e asistentit. Ai numër është i lidhur me
     gjerësinë e butonit, jo me ritmin e faqes; po e palose mbi shkallë, teksti
     fut kokën nën buton. Brenda një `calc()` paloset vetëm termi i parë, sepse
     çdo term pas tij është ndreqje (`+1px` për kufirin), jo hap.

     Utility-t e Bootstrap-it (`mb-3`, `me-1` — 1.509 përdorime te shabllonet)
     NUK arrihen nga këtu: `--bs-spacer` nuk ekziston fare te fleta e tij dhe
     `.mb-3{margin-bottom:1rem!important}` është vlerë e kompiluar. Ajo anë
     mbyllet vetëm duke i hequr nga shabllonet, dhe kjo është punë më vete. */
  --space-0: .125rem;   /*  2px — mes ikonës dhe shkronjës së saj, brenda një çipi */
  --space-1: .25rem;    /*  4px — brenda një çipi, mes ikonës dhe fjalës */
  --space-1-5: .375rem; /*  6px — mbushja e një kontrolli të vogël; hapi më i ngarkuar */
  --space-2: .5rem;     /*  8px — hapi i zakonshëm mes elementeve fqinjë */
  --space-3: .75rem;    /* 12px — mbushja e një kontrolli */
  --space-4: 1rem;      /* 16px — mbushja e një kartele, hap mes blloqeve */
  --space-5: 1.5rem;    /* 24px — hapësira e faqes */
  --space-6: 2rem;      /* 32px — mes seksioneve */
  --space-6-5: 2.5rem;  /* 40px — mbushja e kartelës së hyrjes, gjendja bosh */
  --space-7: 3rem;      /* 48px — mes pjesëve të mëdha të faqes */

  /* Shkronjat: nëntë shkallë, dhe të gjitha në `rem`.
     Këtu rrinin `12.5px` pranë `.82rem` — pra një vlerë që nuk e dëgjon fare
     shfletuesin kur dikush e rrit shkrimin, pranë një tjetre që e dëgjon. Ajo
     fjali qëndronte si paralajmërim ndërsa 59 madhësi në `px` jetonin poshtë
     saj; tani s'ka më asnjë, dhe roja `test_no_size_is_written_outside_the_scale`
     e mban ashtu. Të 311 deklaratat e papërpunuara u palosën mbi
     këto nëntë; ç'mbetet jashtë është `em` (relative ndaj prindit me qëllim),
     `0` (shiriti i ngushtuar e fsheh etiketën me madhësinë) dhe `pt` brenda
     `@media print`, ku pikat janë njësia e letrës.

     Dy shkallë hynë sepse pa to kishte hendek, jo për simetri: brezi .86–.97rem
     mbante 22 përdorime pa token, dhe brezi 1.2–1.4rem mbante 10. Maja u
     rirendit njëkohësisht — `--text-2xl` ishte i deklaruar dhe s'përdorej
     askund, `--text-xl` kishte tri përdorime, pra lëvizja kushtoi tri rreshta.
     Kufiri i poshtëm nuk zbret nën `--text-2xs`: `.6rem` bie në 9,6px, dhe atë
     s'e lexon dot kush. Aty ku barazlargësia e linte pyetjen hapur, vlera u
     ngjit lart — drejt lexueshmërisë, kurrë poshtë saj. */
  --text-2xs: .66rem;   /* numra mbi ikona, etiketat e shiritit të poshtëm */
  --text-xs: .74rem;    /* tituj seksionesh, tekst ndihmës */
  --text-sm: .84rem;    /* rreshtat e menysë, tabelat e ngjeshura */
  --text-md: .92rem;    /* rreshtat e bisedës, emrat te listat e dendura */
  --text-base: 1rem;
  --text-lg: 1.15rem;   /* ikona brenda një kontrolli, tituj kartelash */
  --text-xl: 1.32rem;   /* shifra që lexohet nga larg: `.detail-figure` e shokët */
  --text-2xl: 1.6rem;   /* e njëjta shifër kur kartela është e gjithë faqja */
  --text-3xl: 2rem;     /* ikona e madhe e një faqeje bosh */

  /* Shkronjat e mëdha: tri hapa që rrjedhin me gjerësinë.
     Shkalla lart është për tekstin e ndërfaqes, dhe ai NUK duhet të rrjedhë —
     një etiketë tabele që ndryshon madhësi me dritaren është një etiketë që nuk
     bie kurrë në të njëjtin vend, dhe nën `--text-sm` çdo rrjedhje e çon nën
     kufirin e lexueshmërisë. Titujt e kanë të kundërtën: `1.45rem` fiks te një
     ekran 1600px është një titull që humbet mes hapësirës, dhe te 360px një
     titull që del në tri rreshta.
     Kufijtë janë gjithnjë në `rem`: kur dikush e rrit shkrimin e shfletuesit,
     rriten bashkë me të — një `clamp()` me kufij në `px` do ta shpërfillte
     pikërisht atë njeri.
     Dy nga këto vlera nuk janë të reja: heroi i hyrjes dhe numri i faqes së
     gabimit i mbanin të shkruara brenda vetes. Aty ku janë tani, shkalla e
     madhe ka një vend të vetëm, si ajo e vogël mbi të. */
  --display-sm: clamp(1.35rem, 1.22rem + .5vw, 1.72rem);   /* titulli i faqes */
  --display-md: clamp(1.9rem, 3.2vw, 2.7rem);              /* heroi i hyrjes */
  --display-lg: clamp(3.5rem, 12vw, 5.5rem);               /* 403 / 404 / 500 */

  /* Shell geometry. */
  --sidebar-w: 268px;
  --topbar-h: 62px;

  /* Skena e faqes së hyrjes: tavolina e kontabilitetit — libri kryesor, raporti,
     makina e llogaritjes. E përdorin dy vende (paneli i heroit dhe sfondi i
     faqes), pra rruga e asetit shkruhet këtu një herë e vetme dhe askund tjetër.
     Një `url()` brenda një vetie të personalizuar nuk kërkohet nga rrjeti derisa
     dikush ta përdorë vërtet — çdo faqe tjetër e trashëgon vargun dhe s'ngarkon
     asgjë. */
  --login-scene: url('../img/kontabiliteti.svg');

  /* Sfondi i faqeve të brendshme: e njëjta tavolinë, një shkallë më poshtë.
     Ky skedar nuk hyn si figurë por si MASKË — prej tij merret vetëm forma e
     vijave, kurse ngjyra e mbetet e markës (shih `body::after`). Prandaj është
     një aset i vetëm për të dyja temat: një fotografi do të kërkonte dy.
     Rri pranë skenës së hyrjes e jo te blloku i vet, që të dyja rrugët të
     lexohen bashkë — janë e njëjta gjë e përdorur në dy vende. */
  --app-scene: url('../img/tavolina.svg');

  /* Tri pamjet e kryefaqes publike: libri me faturën, raportet e muajit, dosja
     me rojen mbi të. Rrinë pranë dy skenave sipër sepse janë e njëjta lloj gjëje
     — një figurë që e njeh vetëm fleta e stilit — dhe sepse tri rrugë të
     shpërndara nëpër skedar janë tri gjëra që nuk e dinë njëra-tjetrën.
     Ndryshe nga dy sipër, këto janë PËRMBAJTJE e jo dekor: secila ka legjendën
     e vet te faqja, dhe pikërisht ajo është ç'i thuhet lexuesit të ekranit.
     Prandaj kutia e figurës rri `aria-hidden` — përndryshe e njëjta gjë do të
     lexohej dy herë. */
  --land-shot-1: url('../img/kryefaqja-libri.svg');
  --land-shot-2: url('../img/kryefaqja-raportet.svg');
  --land-shot-3: url('../img/kryefaqja-dosjet.svg');

  /* The chat keeps its own violet accent, so a conversation reads as a
     different kind of surface from the ledgers. */
  --tm-accent: #6264a7;
  --tm-accent-soft: rgba(98,100,167,.14);
  --tm-accent-faint: rgba(98,100,167,.06);
  --tm-accent-line: rgba(98,100,167,.30);
  /* Gradienti i avatarit, i shkruar një herë e me ngjyrë boje të vetën.
     Ishte `linear-gradient(135deg, var(--tm-accent), #7c7fd4)` me `color: #fff`
     te trupi i rregullit: dy hex jashtë bllokut të tokenave, dhe shkronjat mbi
     skajin e dytë binin te 3,59:1 edhe këtu — kurse në temën e errët, ku
     `--tm-accent` ngrihet me qëllim te një lavande e ndritur, te 2,50:1.
     Boja është rol, jo hije, pikërisht si `--primary-contrast`: e bardhë mbi
     indigon e ditës, e thellë mbi lavanden e natës. */
  --grad-tm-from: #6264a7;
  --grad-tm-to: #6668bb;
  --grad-tm: linear-gradient(135deg, var(--grad-tm-from), var(--grad-tm-to));
  --tm-contrast: #ffffff;
}

body.theme-dark {
  color-scheme: dark;

  --bg: #070b15;
  --surface: #10182b;
  --surface-muted: #16203a;
  --surface-sunken: #0a101f;
  --surface-hover: rgba(255,255,255,.05);

  --glass: rgba(13,19,35,.72);
  --glass-strong: rgba(13,19,35,.92);
  --glass-solid: #0b111f;
  /* Mbi kartelën, jo nën të: më e ndritur se `--surface`, sepse në errësirë
     ngritja matet me dritë. */
  --surface-raised: rgba(26,36,64,.94);

  --border: rgba(148,163,184,.15);
  --border-strong: rgba(148,163,184,.26);
  --surface-border: var(--border);

  --text: #e7ecf7;
  --muted: #9aa9c4;
  /* Lifted from #71809c: measured against the lightest dark surface
     (--surface-muted #16203a) the old value came out at 4.05:1, under the 4.5
     AA line, and this is the colour placeholders and empty states use — exactly
     the text people already struggle with. Now 4.63:1 there, 5.65:1 on the page. */
  --faint: #7b8aa6;

  --primary: #818cf8;
  --primary-dark: #6366f1;
  --primary-2: #a78bfa;
  --primary-contrast: #0a0f22;
  --primary-soft: color-mix(in srgb, var(--primary) 14%, transparent);
  /* E matur kunder cdo siperfaqeje te erret: 9.87:1 mbi faqen, 8.87:1 mbi
     karte, 7.22:1 mbi nje chip me --primary-soft. --primary-dark ishte 3.22
     mbi chip — nen kufirin AA, dhe pikerisht ajo qe dukej e padukshme. */
  --primary-text: #a5b4fc;
  --primary-line: color-mix(in srgb, var(--primary) 32%, transparent);
  /* Ulur nga #6366f1/#8b5cf6: teksti i bardhe mbi to jepte 4.47..4.23:1,
     nen kufirin AA. Keto jane vlerat e temes se ndritshme, ku bardha jep
     6.29..5.70:1 — mbushja mbetet qartesisht primare, teksti lexohet. */
  --grad-from: #4f46e5;
  --grad-to: #7c3aed;
  --grad-from-hover: #7376f5;
  --grad-to-hover: #9d70fa;
  --grad-primary: linear-gradient(135deg, #4f46e5, #7c3aed);
  --grad-primary-hover: linear-gradient(135deg, #7376f5, #9d70fa);
  /* 8.87..9.58:1 mbi karte. Mbushja e mesipërme do te jepte 2.81..3.10 —
     nen kufirin edhe per tekst te madh. */
  --grad-primary-text: linear-gradient(135deg, #a5b4fc, #c4b5fd);

  --accent: #22d3ee;
  --accent-soft: color-mix(in srgb, var(--accent) 12%, transparent);

  --success: #34d399;
  --success-soft: rgba(52,211,153,.14);
  --warning: #fbbf24;
  --warning-soft: rgba(251,191,36,.14);
  --danger: #f87171;
  --danger-soft: rgba(248,113,113,.14);
  --info: #38bdf8;
  --info-soft: rgba(56,189,248,.14);

  /* Sipërfaqet e statusit nuk ndryshojnë me temën: #10b981 e #ef4444 janë
     ndërtuar për të mbajtur të bardhën sipër, dhe mbi një faqe të errët ato
     rrinë po aq mirë. Shkruhen prapë këtu me qëllim — tema e errët duhet ta
     thotë vetë çdo ngjyrë që përdor, edhe kur përgjigjja është «po ajo». Kështu
     kush e rregullon njërën temë, e sheh menjëherë a e prek tjetrën. */
  --success-fill: #10b981;
  --success-fill-strong: #059669;
  --warning-fill: #f59e0b;
  --warning-fill-strong: #d97706;
  --warning-fill-deep: #f97316;
  --urgent: #ea580c;
  /* Larja mbi sipërfaqe të errët duhet pak më e dendur se mbi të bardhë: 4% mbi
     një sfond të errët nuk shihet fare. */
  --urgent-soft: rgba(234, 88, 12, .10);
  --danger-fill: #ef4444;
  --danger-fill-strong: #dc2626;
  --accent-fill: #06b6d4;
  --accent-fill-strong: #0891b2;
  /* Mbushjet nuk e ndërrojnë temën — rrinë këtu vetëm që tema të mos kërkojë
     asgjë te blloku i mësipërm, si të tjerat mbi to. */
  --live: #34d399;
  --excel: #16a765;
  --excel-strong: #0f9d58;

  /* Buza e dritës mbi një sipërfaqe të errët nuk mund të jetë e bardhë: mbi
     #10182b një `rgba(255,255,255,.65)` s'është buzë, është vijë neoni. Këtu
     është aq sa mjafton që kutia të ndahet nga faqja pas saj — dhe pikërisht
     kjo është arsyeja pse tokeni ekziston e nuk u shkrua drejt te kartela. */
  --edge-light: inset 0 1px 0 rgba(255,255,255,.07);
  --edge-light-soft: inset 0 1px 0 rgba(255,255,255,.045);

  /* Çifti i grafikëve, përkundrazi, e do ndryshimin: #06b6d4 dilte jashtë brezit
     të ndriçimit në errësirë (L 0.715 kundrejt kufirit 0.67), prandaj aty është
     #0aa2c0 — ndarja deutan ΔE 15.1, tritan 10.8. */
  --chart-revenue: #6366f1;
  --chart-expense: #0aa2c0;

  /* Po ato seri mbi kanavacën e errët — pikërisht ç'bën edhe vetë Power BI-ja
     kur raporti kalon në temën e errët. Navy #12239e mbi një sfond #1b1a19 nuk
     lexohet fare si ngjyrë, prandaj ndriçohet; blu-ja dhe portokallia mbeten aty
     ku ishin, sepse ato dyja janë çifti i matur (shih --bi-cat-2 më poshtë) dhe
     nuk luhet me to pa e rimatur. */
  --bi-cat-1: #118dff;
  /* #e66c37 rrinte te L 0.669, pra një grimë mbi brezin e ndriçimit që kjo temë
     u vë serive (0.67). Ulja në L 0.660 nuk e prek ndarjen: dyshja #118dff /
     #e36934 mbetet ΔE 34.8 normal, 28.5 protan, 25.8 deutan, 34.7 tritan. */
  --bi-cat-2: #e36934;
  --bi-cat-3: #4168e4;
  --bi-cat-4: #b45cc4;
  --bi-cat-5: #e85fb5;
  --bi-cat-6: #8f6ad6;
  --bi-cat-7: #d9b300;
  --bi-cat-8: #e05561;
  --bi-good: #22c55e;
  --bi-warn: #d9b300;
  --bi-bad: #e05561;

  /* Chrome-i i raportit në errësirë — gri-të e temës së errët të Power BI-t. */
  --bi-canvas: #1b1a19;
  --bi-visual: #252423;
  --bi-line: #3b3a39;
  --bi-line-soft: #323130;
  --bi-ink: #f3f2f1;
  --bi-ink-2: #c8c6c4;
  --bi-chrome: #201f1e;
  --bi-chrome-hover: #323130;
  --bi-accent: #2899f5;
  --bi-accent-dark: #4aacf7;
  --bi-shadow: 0 1.6px 3.6px rgba(0,0,0,.4), 0 .3px .9px rgba(0,0,0,.3);
  --bi-shadow-hover: 0 3.2px 7.2px rgba(0,0,0,.5), 0 .6px 1.8px rgba(0,0,0,.35);
  --bi-shadow-focus: 0 25.6px 57.6px rgba(0,0,0,.55), 0 4.8px 14.4px rgba(0,0,0,.4);

  --shadow-sm: 0 1px 2px rgba(0,0,0,.4);
  --shadow-md: 0 2px 6px rgba(0,0,0,.36), 0 10px 26px rgba(0,0,0,.32);
  --shadow-lg: 0 18px 44px rgba(0,0,0,.5), 0 3px 10px rgba(0,0,0,.36);
  --shadow-up: 0 -2px 14px rgba(0,0,0,.36);
  --shadow-glow: 0 6px 22px color-mix(in srgb, var(--primary-dark) 35%, transparent);

  --ring: 0 0 0 var(--ring-w-lg) color-mix(in srgb, var(--primary) 40%, transparent);

  /* Lifted: the Teams violet is a mid-tone that turns to mud on a dark page. */
  --tm-accent: #9a9cf0;
  --tm-accent-soft: rgba(154,156,240,.18);
  --tm-accent-faint: rgba(154,156,240,.09);
  --tm-accent-line: rgba(154,156,240,.34);
  /* E njëjta lavande, dhe boja kthehet: 7,60:1 dhe 9,94:1 në vend të 2,50:1.
     Gradienti rishkruhet edhe pse formula s'ndryshon — pikërisht si
     `--grad-primary` një bllok më lart. Skajet i mjaftojnë shfletuesit, sepse
     `var()` zgjidhet në çastin e përdorimit; por roja e kontrastit e lexon
     bllokun e errët si listë të sheshtë, dhe një token që s'e gjen aty e merr
     për të zi. */
  --grad-tm-from: #9a9cf0;
  --grad-tm-to: #b4b6f7;
  --grad-tm: linear-gradient(135deg, var(--grad-tm-from), var(--grad-tm-to));
  --tm-contrast: #0a0f22;
}

/* --- Bootstrap's own palette, pulled onto ours ------------------------------
   base.html now sets data-bs-theme, so Bootstrap switches to its dark values
   instead of leaving every --bs-* variable on the light ones. That alone fixes
   the dark-on-dark text, but it brings Bootstrap's neutral grey (#212529) into
   a page built on navy. So its core tokens are re-pointed at ours: anything
   Bootstrap paints and site.css never touches now lands in the same palette as
   everything around it, instead of looking like a patch from another app.

   Only the roots are mapped. Nearly every component variable in Bootstrap
   derives from these, so the whole set follows from a dozen lines. */
body.theme-dark {
  --bs-body-bg: var(--bg);
  --bs-body-bg-rgb: 7, 11, 21;
  --bs-body-color: var(--text);
  --bs-body-color-rgb: 231, 236, 247;

  --bs-emphasis-color: #ffffff;
  --bs-emphasis-color-rgb: 255, 255, 255;
  --bs-secondary-color: var(--muted);
  --bs-secondary-bg: var(--surface-muted);
  --bs-tertiary-color: var(--faint);   /* 4.63:1 at worst — see --faint above */
  --bs-tertiary-bg: var(--surface-sunken);

  --bs-border-color: var(--border);
  --bs-border-color-translucent: var(--border);
  --bs-heading-color: var(--text);

  --bs-link-color: var(--primary);
  --bs-link-color-rgb: 129, 140, 248;
  --bs-link-hover-color: var(--primary-2);
  --bs-code-color: #f0abfc;
  --bs-highlight-bg: rgba(251, 191, 36, .25);

  /* The semantic colours too. Bootstrap keeps its light greens and reds even in
     its dark block, and #198754 on this navy is roughly 2.5:1 — a `.text-success`
     nobody can read. These are the lifted values the rest of the page uses. */
  --bs-primary-rgb: 129, 140, 248;
  --bs-success-rgb: 52, 211, 153;
  --bs-danger-rgb: 248, 113, 113;
  --bs-warning-rgb: 251, 191, 36;
  --bs-info-rgb: 56, 189, 248;
}

/* ============================================================================
   1b. Vetitë e regjistruara (@property)

   Një ndryshore e zakonshme CSS është tekst: shfletuesi nuk di ç'është `135deg`
   dhe nuk di as si të shkojë prej saj te `100deg` — pra çdo ndryshim i saj
   ndodh menjëherë, me një kërcim. Prandaj deri tani asnjë gradient i këtij
   programi nuk lëvizte dot: mund të ndërrohej, jo të kalonte.

   `@property` i thotë shfletuesit ç'lloj është vlera. Që nga ai çast ajo bëhet
   e animueshme si çdo veti tjetër, dhe një gradient mund ta rrotullojë këndin
   nën mi. `initial-value` është ajo që përdoret kur askush s'e ka vendosur, pra
   çdo element që s'e prek e ka pikërisht pamjen e djeshme.

   `initial-value` është ajo që përdoret kur askush s'e ka vendosur, pra çdo
   element që s'e prek e ka pikërisht pamjen e djeshme.
   ========================================================================= */

/* Këndi i gradientit të butonit. `inherits: false` sepse butoni e pikturon vetë
   sfondin e vet: askush poshtë tij s'ka pse ta dijë se sa i pjerrët është, dhe
   një kënd i trashëguar do të ishte një vlerë që udhëton nëpër gjysmën e faqes
   pa e lexuar askush. */
@property --grad-angle {
  syntax: '<angle>';
  inherits: false;
  initial-value: 135deg;
}

/* Ku rri miu mbi një kartelë, dhe sa fort ndriçon. site.js i vendos të parat
   dyja; e treta është thjesht «a është miu këtu», që drita të vijë e të ikë
   butë e jo si çelës.

   `inherits: true` te të trija, dhe kjo nuk është hollësi: dritën e vizaton
   `.stat-card::before`, ndërsa numrat i vë JavaScript-i te vetë kartela. Një
   pseudo-element i merr vlerat e prindit vetëm përmes trashëgimisë — me
   `inherits: false` ai do të mbetej përgjithmonë te `initial-value`, pra te
   opaciteti 0. Pikërisht ashtu ishte shkruar në fillim, dhe pikërisht ashtu
   nuk ndizej kurrë drita: `--spot-o` te kartela ishte 1 dhe te `::before` 0,
   në të njëjtin çast. Matja e gjeti; kaskada nuk e thotë me sy. */
@property --spot-x {
  syntax: '<length-percentage>';
  inherits: true;
  initial-value: 50%;
}
@property --spot-y {
  syntax: '<length-percentage>';
  inherits: true;
  initial-value: 0%;
}
@property --spot-o {
  syntax: '<number>';
  inherits: true;
  initial-value: 0;
}

/* Sustë e vërtetë aty ku shfletuesi e mban.
   `cubic-bezier` ka vetëm dy pika kontrolli, pra e bën tejkalimin njëherë dhe
   mbaron; një send i vërtetë që ngrihet e kalon caqen, kthehet pak më pak, dhe
   qetësohet. `linear()` e shkruan atë kurbë me pika — dhe kur mungon, mbetet
   `cubic-bezier`-i i deklaruar te tokenat, me të njëjtin tejkalim. Pra kjo nuk
   është kusht për të punuar: është hollësia mbi të. */
@supports (transition-timing-function: linear(0, 1)) {
  :root {
    --ease-spring: linear(
      0, 0.218 5%, 0.68 12%, 0.898 17%, 1.02 22%, 1.075 27%,
      1.073 33%, 1.03 40%, 0.994 50%, 0.986 60%, 1.002 78%, 1
    );
  }
}

}  /* @layer tokens */

/* ============================================================================
   2. Base
   ========================================================================= */

@layer base {

body {
  /* 'Inter Variable' is the file base.html loads; plain Inter catches a copy
     installed on the machine; then the system font. */
  font-family: 'Inter Variable', Inter, system-ui, -apple-system, 'Segoe UI',
               Roboto, 'Helvetica Neue', Arial, sans-serif;
  background: var(--bg);
  color: var(--text);
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
  /* Kutitë e zgjedhjes, radio-t, shiritat e progresit dhe rrëshqitësit i
     vizaton sistemi, jo ky skedar — dhe deri tani i vizatonte me blunë e vet të
     Windows-it. Një faqe indigo me tridhjetë kutizime blu sistemi është një
     faqe që duket e montuar nga dy programe. Një rresht i vetëm ia jep markës
     edhe atë që s'e prekim dot ndryshe. */
  accent-color: var(--primary);
  /* Po ajo arsye për vijën që pulson brenda një fushe. */
  caret-color: var(--primary);
  /* Inter dhe Sora janë shkronja të ndryshueshme me bosht optik: e njëjta
     shkronjë duhet të jetë pak më e trashë e më e hapur kur është e vogël, dhe
     më e ngushtë kur është titull. Shfletuesi e bën vetë — po t'i thuhet. */
  font-optical-sizing: auto;
}

/* The aurora sits on a fixed pseudo-element instead of the body background:
   `background-attachment: fixed` repaints the whole gradient on every scroll
   frame, and this is a page people scroll tables on all day. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  /* Tri dritat e aurorës janë tri tokenat e aksentit, jo tri ngjyra që rastis
     t'i ngjajnë atij. Kështu një retuning i markës e merr me vete edhe sfondin —
     përndryshe faqja do të mbetej e ndriçuar nga indigoja e vjetër, dhe askush
     s'do ta kërkonte shkakun në një gradient 9%.

     Shtresa e katërt, ajo e fundit, është e vetmja që nuk është dritë: një
     shtrat i pjerrët 155° indigo→vjollcë, pikërisht këndi dhe pikërisht rendi i
     `.auth-hero`. Pa të, tri dritat rrinë secila te cepi i vet dhe mes tyre
     mbetet faqja e zhveshur — kjo i lidh në një ngjyrë të vetme që kalon nëpër
     ekran, dhe kjo është ajo që e bën hyrjen të duket e pjekur.

     4% është kufi i matur, jo shije. Ky është i vetmi rresht i aurorës që bie
     nën kolonën e përmbajtjes — tri dritat rrinë te buzët, mbi xhamin e menysë
     dhe të kokës. Mbi `--bg` të zhveshur `--muted` jep 4.98:1; me këtë shtresë
     4.70:1; te 7% do të binte në 4.51 dhe te 10% në 4.33. Pra çdo hap më lart
     do t'ia hiqte një faqeje me tabela pikërisht atë që s'e ka me tepri.
     Shuhet te 74%, që çereku i poshtëm i faqes të mbetet krejt i pastër. */
  background:
    radial-gradient(900px 480px at 8% -10%, color-mix(in srgb, var(--primary) 10%, transparent), transparent 62%),
    radial-gradient(760px 420px at 96% -6%, color-mix(in srgb, var(--primary-2) 9%, transparent), transparent 60%),
    radial-gradient(680px 460px at 78% 108%, color-mix(in srgb, var(--accent) 8%, transparent), transparent 62%),
    linear-gradient(155deg,
                    color-mix(in srgb, var(--primary) 4%, transparent) 0%,
                    color-mix(in srgb, var(--primary-2) 3%, transparent) 46%,
                    transparent 74%);
}
/* Vjollca këtu ishte #8b5cf6, një ngjyrë pa token; tani vjen nga `--primary-2`
   (#a78bfa). Në 18%..10% opacitet, e turbulluar pas gjithë përmbajtjes, ndarja
   s'shihet — dhe aurora e errët e ndjek aksentin si ajo e ndritshmja.

   Shtrati i pjerrët i mban 7% këtu e 4% te drita, sepse mbi një faqe të errët ai
   shton dritë e nuk heq: `--muted` bie nga 8.29:1 te 7.88 — pra një e treta e
   asaj që kushton në temën tjetër, dhe pikërisht aq ngjyrë sa një sfond i errët
   ta tregojë fare. */
body.theme-dark::before {
  background:
    radial-gradient(900px 500px at 10% -12%, color-mix(in srgb, var(--primary-dark) 18%, transparent), transparent 62%),
    radial-gradient(760px 440px at 96% -8%, color-mix(in srgb, var(--primary-2) 14%, transparent), transparent 60%),
    radial-gradient(700px 480px at 80% 110%, color-mix(in srgb, var(--accent) 10%, transparent), transparent 62%),
    linear-gradient(155deg,
                    color-mix(in srgb, var(--primary-dark) 7%, transparent) 0%,
                    color-mix(in srgb, var(--primary-2) 5%, transparent) 46%,
                    transparent 74%);
}

/* --- Sfondi i faqeve të brendshme -------------------------------------------
   Hyrja e ka një skenë; sapo dikush kalon prej saj, programi mbetej me tri
   gradientë dhe asgjë tjetër. Kjo shtresë e shtrin të njëjtin mendim te çdo
   faqe — dhe tani, si te hyrja, në gjithë zonën: kutia nuk është më një cep
   560px, është vetë pamja.

   Rritja u kërkua, dhe u dha ashtu si e duron një faqe pune. Një fotografi e
   plotë nën tabela mbetet e pamundur, dhe numrat e thonë pse: skena e hyrjes,
   e vendosur si figurë nën temën e çelët, e ul `.page-sub` (`--muted`, jashtë
   çdo karte) nën 4.5:1 që te 5% — pra e vetmja fotografi e mundur atje do të
   ishte një fantazmë më e zbehtë se ky vizatim. Vija e mban atë që pamja nuk e
   mban dot: një gdhendje e prek faqen vetëm aty ku kalon vija, kurse një
   fotografi e mbulon të tërën.

   Prandaj: e njëjta skenë, e njëjta gjuhë ngjyrash, e njëjta shtrirje — po
   vizatuar, jo fotografuar.

   Katër vendime e mbajnë të padëmshme:

   1. Vizatimi hyn si MASKË, jo si figurë. Ngjyra vjen nga familja e markës —
      `--primary`, `--primary-2`, `--accent` — pra shtresa e ndjek atë dhe i
      shërben të dyja temave me një aset të vetëm: një fotografi do të kërkonte
      dy, dhe e dyta do të harrohej.
   2. Ngjyrat piktohen nga gradientë që shuhen drejt qendrës së faqes. Pra
      pjesa e vizatimit që i afrohet kolonës së përmbajtjes nuk zbehet: ajo nuk
      piktohet fare. Buza e figurës nuk ekziston, prandaj s'ka çfarë të presë.
   3. Vizatimi shtrihet në gjithë faqen, po ngjyra jo. Tri dritat rrinë të
      lidhura te e treta e poshtme-djathtë: e para prek faqen nga 31% e
      gjerësisë e 35% e lartësisë e tutje. Pra shiriti i sipërm — aty ku çdo
      faqe pune e vë `.page-head` me titullin dhe `.page-sub` jashtë çdo karte —
      mbetet letër e bardhë. Kjo është e vetmja gjë që e mban numrin e lartë:
      forca nuk kufizohet nga kontrasti, sepse ngjyra nuk shkon atje ku është
      teksti.
   4. `position: fixed` me `z-index: -1` — jashtë rrjedhës, poshtë çdo karte,
      dhe pa u rivizatuar me rrëshqitjen. E njëjta arsye si te aurora mbi të.

   Forca është një numër i vetëm, `opacity`. Ngjyra rri e plotë te gradienti me
   qëllim: dy vlera që shumëzohen mes tyre janë dy vende ku duhet menduar sa
   herë preket njëra.

   `@supports` nuk është kujdes i tepërt. Pa maskë, gradienti mbetet një njollë
   e ngjyrosur në cep — pra e gjithë shtresa varet nga e vetmja veti që e bën
   vizatim, dhe kur ajo mungon s'duhet të mbetet gjysma e saj. */
@supports ((-webkit-mask-image: url('')) or (mask-image: url(''))) {
  body::after {
    content: "";
    position: fixed;
    /* Ishte një kuti `min(44vw, 560px)` e varur te cepi. Tani është faqja.
       `contain` mbi këtë kuti do të thotë: vizatimi merr gjithë lartësinë e
       dritares dhe rri në mes — pra te një ekran zyre 1600×900 ai është 900px,
       jo 560. E njëjta skenë sa te hyrja, në të njëjtën shkallë. */
    inset: 0;
    z-index: -1;
    pointer-events: none;
    /* Nën maskë nuk rri më një ngjyrë e vetme, por e njëjta udhë ngjyrash që e
       ka paneli i hyrjes: indigo në trupin e skenës, vjollcë te ijë e djathtë,
       ciano poshtë te buza. Aty ishte `linear-gradient(155deg, indigo →
       vjollcë)` me një ndriçim ciano mbi të; këtu e njëjta gjë e thënë me tri
       drita, sepse forma që i mban nuk është një drejtkëndësh por një gdhendje.
       Secila është e plotë te qendra e vet dhe e shuar te buza, prandaj kalimi
       nga njëra te tjetra ndodh brenda vizatimit e jo mbi një kufi — asnjë vijë
       ndarëse nuk lind, dhe pikërisht vija do të ishte e vetmja gjë që do të
       tregonte se këtu ka tri shtresa e jo një.
       Përqindjet lexohen ndaj dritares tani, jo ndaj një kutie 560px, dhe janë
       zgjedhur që të tria bashkë ta lënë të paprekur shiritin e sipërm dhe
       kolonën e majtë: indigoja niset te 31%/35%, vjollca te 67%/29%, ciano te
       47%/79%. Mbi to nuk rri asnjë rresht teksti pa kartë.
       Tokena dhe asgjë tjetër: maska mbetet një aset për të dyja temat, dhe një
       retuning i markës e merr me vete edhe këtë skenë. */
    background:
      radial-gradient(46% 46% at 74% 106%, var(--accent) 0%, transparent 58%),
      radial-gradient(62% 62% at 104% 66%, var(--primary-2) 0%, transparent 60%),
      radial-gradient(86% 86% at 88% 92%, var(--primary) 0%, transparent 66%);
    -webkit-mask: var(--app-scene) center / contain no-repeat;
    mask: var(--app-scene) center / contain no-repeat;
    /* Numri matet si më parë — ndryshimi më i madh për kanal te pikseli më i
       fortë i vizatimit, jo te mesatarja — po tani llogaritur drejtpërdrejt nga
       tokenat mbi `--bg`, sepse ngjyrat janë tri dhe secila lëviz kanal tjetër:
       indigoja 174 njësi te e gjelbra, vjollca 186 po aty, ciano 234 te e kuqja.
       Pra e njëjta `opacity` jep tri prani të ndryshme, dhe .14 e vjetër u mat
       kur poshtë kishte vetëm një ngjyrë e sipër një kuti 560px:
         .14 → Δ24 indigo · Δ26 vjollcë · Δ33 ciano
         .22 → Δ38 indigo · Δ41 vjollcë · Δ52 ciano
       Ngjitja nga .14 te .22 nuk e ha kontrastin e askujt, dhe arsyeja është
       vendimi 3 më lart e jo vetë numri: po të binte një rresht `--muted` mbi
       ngjyrën e plotë, ai do të lexohej 3.6:1 — poshtë pragut. Prandaj ngjyra
       ndalet para se të arrijë te shiriti ku rri teksti pa kartë. Kush e ngre
       këtë numër duhet ta lëvizë bashkë me vendimin 3, jo veç: të dyja së
       bashku e mbajnë premtimin, asnjëra vetëm.

       Këtu qëndronte edhe një gabim që s'dukej te skedari: komentit më lart i
       mungonte shenja e hapjes, pra shfletuesi e lexonte tekstin e tij si
       deklaratë të prishur, dhe rimëkëmbja gëlltiste gjithçka deri te
       pikëpresja e parë — që ishte pikërisht e këtij rreshti. Pra skena
       piktohej me `opacity: 1`, jo me numrin e matur.
       Provat s'e kapnin dot: i heqin komentet me regex, dhe teksti i mbetur
       ende përmbante fjalën `opacity:`. */
    opacity: .22;
    /* Skena merr frymë. Gjysmë minute për një hark të vetëm — pra brenda kohës
       sa dikush lexon një tabelë, vizatimi poshtë saj ka lëvizur aq sa ta
       ndjesh se faqja nuk është letër e shtypur, dhe aq pak sa të mos e kapësh
       duke lëvizur. Kjo është e gjithë matja: mbi këtë kohë bëhet dekor që
       kërkon vëmendje, nën të bëhet e padukshme.

       Vetëm `transform`, dhe pikërisht sepse kjo shtresë është sa gjithë
       dritarja: një `background-position` që lëviz do të thoshte ripikturim i
       një maske me tri gradientë në çdo kuadër, pesëdhjetë e dy sekonda pa
       pushim, te makina të zyrës që s'e kanë atë për të dhënë. Një `transform`
       nuk pikturon asgjë — vetëm zhvendos atë që u pikturua një herë.

       Pa `will-change`: një animacion i pafund `transform` e ngre vetë shtresën
       te kompozitori sa kohë luan, pra fjala do të shtonte vetëm një premtim që
       shfletuesi e ka dhënë tashmë — dhe do ta mbante të ngritur edhe atë
       shtresë sa ekrani që dikush e ka fikur me `prefers-reduced-motion`. */
    animation: sceneDrift var(--drift-slow) var(--ease-in-out) infinite alternate;
  }
  /* Mbi faqen e errët e njëjta vijë ka më pak nga çfarë ta ndajë nga sfondi,
     por edhe sfondi vetë nuk e mbyt: te .16 të tria dritat bien mes Δ35 e Δ37 —
     pra pak më poshtë se numri i temës së çelët, e ndjeshme njësoj. Kjo është
     arsyeja e vetme pse ky numër ekziston veç: nuk kërkohet ngjyrë tjetër,
     kërkohet e njëjta prani. */
  body.theme-dark::after { opacity: .16; }
}
/* Harku është i shkurtër me qëllim: gjashtë të mijtat e gjerësisë majtas e
   djathtas, dhe tri e gjysmë për qind rritje. Mbi një ekran zyre kjo bie rreth
   dhjetë piksele — pra syri nuk e ndjek dot, po truri e regjistron. Skena rri
   `center / contain` me hapësirë bosh në të dyja anët, pra zhvendosja nuk zbulon
   kurrë një buzë: s'ka buzë për të zbuluar. */
@keyframes sceneDrift {
  from { transform: translate3d(-.6%, -.4%, 0) scale(1); }
  to   { transform: translate3d(.6%, .4%, 0) scale(1.035); }
}

/* Hyrja e mban vetë gjithë zonën me skenën e vet, pra këtu do të ishte vizatim
   i dytë poshtë të parit. Sfondi opak i `.app-content` e mbulon tashmë — ky
   rresht nuk ndreq diçka që duket, ndal diçka që do të dukej po t'i ulet atij
   opakësia një ditë. */
body:has(.auth-hero)::after { display: none; }

/* Në telefon s'ka cep të lirë: përmbajtja shkon buzë më buzë dhe poshtë rri
   navigimi. Një vizatim atje bie nën gishta, jo pranë tyre. */
@media (max-width: 900px) {
  body::after { display: none; }
}
/* Kush kërkon më shumë kontrast nuk kërkon më shumë sipërfaqe të pikturuar. */
@media (prefers-contrast: more) {
  body::after { display: none; }
}

/* Inter's contextual alternates give a cleaner 'a' and 'g' at UI sizes. */
@supports (font-variation-settings: normal) {
  body { font-feature-settings: 'cv02','cv03','cv04','cv11'; }
}

h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 {
  font-family: 'Sora Variable', 'Inter Variable', Inter, system-ui, sans-serif;
  letter-spacing: -.02em;
  font-weight: 700;
  /* Titulli që kalon në dy rreshta i ndan fjalët në mes, jo katër fjalë lart e
     një poshtë. Shfletuesi që s'e njeh e shpërfill rreshtin — pra kostoja e
     kësaj është zero kudo ku s'punon. */
  text-wrap: balance;
}

/* Teksti i rrjedhshëm: pa fjalë të vetmuar në rreshtin e fundit. `pretty`
   ndryshe nga `balance` nuk e prek gjithë bllokun — vetëm fundin — prandaj rri
   te paragrafët e gjatë, ku `balance` do ta ngadalësonte faqen pa dukuri.

   `.text-muted` DOLI nga kjo listë, dhe arsyeja vlen për çdo utility ngjyre që
   dikush do të tundohej ta shtojë këtu. `text-wrap` është shkurtore: `pretty`
   vendos edhe `text-wrap-style: pretty` edhe `text-wrap-mode: wrap`. Pra një
   `<span class="text-muted">` brenda një kutie me `white-space: nowrap` e
   rikthente mbështjelljen për vetveten — dhe rreshti i bisedës, që duhej të
   ishte një rresht me tri pika, mbante dy: shtatëmbëdhjetë piksela të humbur në
   çdo rresht liste, pra tri biseda më pak në ekran. Ngjyra s'ka pse të vendosë
   për mbështjelljen. */
p, .page-sub, .empty-text, .stat-note, .form-text {
  text-wrap: pretty;
}

::selection { background: var(--primary-soft); color: inherit; }

/* Thin, theme-aware scrollbars everywhere. */
* { scrollbar-width: thin; scrollbar-color: var(--border-strong) transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-thumb {
  background: var(--border-strong);
  border-radius: var(--radius-pill);
  border: 3px solid transparent;
  background-clip: padding-box;
}
*::-webkit-scrollbar-track { background: transparent; }

/* Figures line up in columns. In an accounting office a column of numbers that
   does not align is a column nobody can scan. */
.table td, .table th,
.money, .task-col-count, .badge, .chip,
input[type="number"],
.stat-value {
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
}

/* Links inside content: underline on hover only, so tables stay quiet. */
/* Vetem `a`, pa mbishkrim per temen e erret: --primary-text e mban vete
   rolin ne te dyja temat. Nje rregull `body.theme-dark a` do te kishte
   specifikitet (0,1,2) dhe do te fitonte mbi `.btn-primary` (0,1,0) —
   pra cdo <a class="btn"> do te merrte ngjyren e lidhjes mbi mbushjen e
   vet. Pikerisht ashtu u zhduken Bordi, Lista, Muaj dhe Klient i ri. */
a { color: var(--primary-text); text-underline-offset: .18em; }
a:hover { color: var(--primary); }

hr { border-color: var(--border); opacity: 1; }

code, kbd, pre, samp {
  font-family: 'JetBrains Mono Variable', 'JetBrains Mono', ui-monospace,
               SFMono-Regular, Menlo, Consolas, monospace;
}
code { color: var(--primary-text); background: var(--primary-soft);
       padding: var(--space-0) var(--space-1-5); border-radius: var(--radius-xs); font-size: .875em; }

kbd, .kbd {
  display: inline-flex;
  align-items: center;
  gap: var(--space-0);
  background: var(--surface-muted);
  color: var(--muted);
  border: 1px solid var(--border-strong);
  border-bottom-width: 2px;
  border-radius: var(--radius-xs);
  padding: var(--space-0) var(--space-1-5);
  font-size: var(--text-xs);
  font-weight: 600;
  line-height: 1.5;
}

/* Headline accent: paints text with the brand gradient. Falls back to plain
   text colour where background-clip:text is missing. */
.text-gradient {
  background: var(--grad-primary-text);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: var(--primary-text);
}

.text-muted { color: var(--muted) !important; }

}  /* @layer base */

/* ============================================================================
   3. App shell
   ========================================================================= */

@layer components {

.app-shell { display: flex; min-height: 100vh; }

/* --- Sidebar --------------------------------------------------------------- */
/* Above lg the responsive offcanvas renders as a plain element and these rules
   make it a fixed rail; below lg Bootstrap turns it into a slide-in drawer. */
.app-sidebar {
  width: var(--sidebar-w);
  flex-shrink: 0;
  background: var(--glass);
  backdrop-filter: blur(var(--glass-blur)) saturate(1.3);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(1.3);
  border-right: 1px solid var(--border);
}
@media (min-width: 992px) {
  .app-sidebar {
    position: sticky;
    top: 0;
    height: 100vh;
    display: flex;
    flex-direction: column;
    overflow: hidden;
  }
}
/* As a drawer the shell is Bootstrap's; only the paint is ours. */
.app-sidebar.offcanvas, .app-sidebar.offcanvas-lg {
  --bs-offcanvas-width: var(--sidebar-w);
  --bs-offcanvas-bg: var(--glass-strong);
  --bs-offcanvas-color: var(--text);
}

.sidebar-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  padding: var(--space-4);
  min-height: var(--topbar-h);
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}

.sidebar-body {
  flex: 1;
  overflow-y: auto;
  padding: var(--space-4) var(--space-3);
  overscroll-behavior: contain;
}

/* Titulli i seksionit rri ngjitur në krye sa kohë seksioni i tij është në ekran.
   Menyja e adminit mban njëzet e shtatë lidhje në gjashtë seksione: rrëshqite pak
   dhe «Financat» ikën lart, kurse ti lexon ende listën e saj — pra ke shtatë emra
   përpara dhe asnjë fjalë që të thotë se cilës i përkasin.

   Të gjithë ngjiten te e njëjta `top: 0` dhe nuk mbivendosen kurrë: janë vëllezër
   në të njëjtin bllok-përmbajtës, pra titulli që vjen pas e mbulon plotësisht atë
   përpara sapo e arrin — dhe meqë sfondi është i patejdukshëm, ajo duket si një
   kokë e vetme që ndërron emrin. Prandaj sfondi NUK mund të jetë `--glass`. */
.sidebar-section-title {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--glass-solid);
  font-size: var(--text-2xs);
  text-transform: uppercase;
  letter-spacing: .09em;
  color: var(--faint);
  font-weight: 700;
  padding: var(--space-3) var(--space-2) var(--space-1-5);
  user-select: none;
}
/* Hapësira mbi një titull seksioni e ndan atë nga seksioni i mësipërm; te i pari
   nuk ka çfarë të ndajë, pra bie. Deri tani mjaftonte `:first-child`, sepse i
   pari ishte vërtet një titull. Tani fëmija i parë është gjithnjë «Të mitë» —
   i dukshëm kur ka faqe të fiksuara, `d-none` kur s'ka — dhe rregulli duhet t'i
   mbulojë të dyja gjendjet e tij, përndryshe menyja hapet me një hapësirë boshe
   që nuk e kërkoi askush. */
.sidebar-body > .sidebar-section-title:first-child,
.sidebar-body > .sidebar-fav .sidebar-section-title,
.sidebar-body > .sidebar-fav.d-none + .sidebar-section-title { padding-top: var(--space-0); }

/* Titulli i seksionit është buton: shtypja e palos listën poshtë tij. Duket si
   më parë derisa e prek — një menu që ndryshon pamje pa u prekur do të kërkonte
   të mësohej nga e para.

   Sfondi përsëritet këtu dhe nuk bëhet `none`: ky përzgjedhës është më specifik
   se `.sidebar-section-title`, pra një `background: none` këtu ia heq sfondin e
   patejdukshëm çdo titulli të palosshëm — dhe atëherë gjashtë tituj që ngjiten
   te e njëjta `top: 0` lexohen njëri mbi tjetrin në vend që ta mbulojnë njëri
   tjetrin. Shih arsyetimin te rregulli bazë më lart. */
button.sidebar-section-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  background: var(--glass-solid);
  border: 0;
  text-align: left;
  cursor: pointer;
}
button.sidebar-section-title i {
  font-size: var(--text-xs);
  opacity: .55;
  transition: transform var(--dur-2) var(--ease-out);
}
button.sidebar-section-title.collapsed i { transform: rotate(-90deg); }
button.sidebar-section-title:hover { color: var(--text); }

/* Ylli i fiksimit: i heshtur derisa e kërkon miu, i ndezur kur faqja është te
   «Të mitë». Nuk zë vend kur menuja është shirit ikonash. */
.app-sidebar .fav-star {
  margin-left: auto;
  background: none;
  border: 0;
  padding: 0 var(--space-0);
  line-height: 1;
  color: var(--faint);
  opacity: 0;
  transition: opacity var(--dur-2) var(--ease-out), color var(--dur-2) var(--ease-out);
}
.app-sidebar .nav-link:hover .fav-star,
.app-sidebar .fav-star:focus-visible { opacity: 1; }
.app-sidebar .fav-star.on { opacity: 1; color: var(--warning-fill); }
.app-sidebar .fav-star:hover { color: var(--warning-fill); }
body.sidebar-mini .app-sidebar .fav-star { display: none; }

/* Në telefon ylli nuk vizatohet fare.
   Gishti s'ka hover, kështu që shfletuesi e shpik: prekja e parë mbi një rresht
   që fsheh diçka nën `:hover` shpenzohet për ta zbuluar atë diçka, dhe lidhja
   hapet vetëm me të dytën. Pra çdo faqe e menysë kërkonte dy prekje, për shkak
   të një butoni që në telefon s'e shihte kush. Fiksimi te «Të mitë» mbetet punë
   e miut; lista e fiksuar lexohet njësoj në të dyja. Po nga kjo arsye edhe hover-i
   i vetë rreshtit rri nën `hover: hover` — një ikonë që lëviz nën gisht është
   pikërisht ajo që e bën shfletuesin ta mbajë prekjen e parë për vete. */
@media (hover: none) {
  .app-sidebar .fav-star { display: none; }
}

.sidebar-fav .nav-link .sidebar-badge { display: none; }   /* numri rri te origjinali */

.sidebar .nav-link,
.app-sidebar .nav-link {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  color: var(--muted);
  border-radius: var(--radius);
  padding: var(--space-2);
  margin-bottom: var(--space-0);
  font-size: var(--text-sm);
  font-weight: 500;
  transition: color var(--dur-1) var(--ease-out),
              background var(--dur-1) var(--ease-out),
              transform var(--dur-2) var(--ease-spring);
}
.app-sidebar .nav-link i {
  font-size: var(--text-base);
  width: 1.35rem;
  text-align: center;
  color: var(--faint);
  transition: color var(--dur-2) var(--ease-out), transform var(--dur-2) var(--ease-out);
  flex-shrink: 0;
}
@media (hover: hover) {
  .app-sidebar .nav-link:hover {
    color: var(--text);
    background: var(--surface-hover);
  }
  .app-sidebar .nav-link:hover i { color: var(--primary); transform: translateX(1px); }
  /* Shina e zbehtë nën kursor: e njëjta formë si te rreshti aktiv, por më e
     shkurtër dhe pa gradient — një premtim, jo një pohim. Vetëm te rreshtat që
     nuk janë aktivë; mbi atë aktiv do të ishte shina e dytë mbi të parën. */
  .app-sidebar .nav-link:not(.active):hover::before {
    content: "";
    position: absolute;
    left: -.3rem;
    top: 38%;
    bottom: 38%;
    width: 3px;
    border-radius: var(--radius-xs);
    background: var(--primary-line);
    transform-origin: center;
    animation: railIn var(--dur-2) var(--ease-spring) both;
  }
}
/* Përgjigjja për gishtin: rreshti ndriçon sa mban prekjen, pa pretenduar hover. */
.app-sidebar .nav-link:active {
  color: var(--text);
  background: var(--surface-hover);
}
.app-sidebar .nav-link.active {
  color: var(--primary-text);
  background: var(--primary-soft);
  font-weight: 600;
}
.app-sidebar .nav-link.active i { color: inherit; }
/* A rail on the active item, so the eye finds "where am I" without reading. */
.app-sidebar .nav-link.active::before {
  content: "";
  position: absolute;
  left: -.3rem;
  top: 22%;
  bottom: 22%;
  width: 3px;
  border-radius: var(--radius-xs);
  background: var(--grad-primary);
  /* Shina hapet nga mesi kur faqja mbërrin. `--ease-spring` mbaron pak përtej
     caqes e kthehet — pra shina e kalon gjatësinë e vet për një çast dhe ulet
     në të, si diçka që zë vend e jo si diçka që vizatohet. Kjo është e vetmja
     lëvizje e menysë që thotë «ja ku je», dhe e thotë një herë. */
  transform-origin: center;
  animation: railIn var(--dur-3) var(--ease-spring) both;
}
@keyframes railIn {
  from { transform: scaleY(0); opacity: 0; }
  to   { transform: none; opacity: 1; }
}

.sidebar-badge {
  margin-left: auto;
  background: var(--grad-primary);
  color: #fff;
  font-size: var(--text-2xs);
  font-weight: 700;
  padding: var(--space-0) var(--space-1-5);
  border-radius: var(--radius-pill);
  min-width: 1.25rem;
  text-align: center;
}

/* Card pinned to the sidebar foot: who am I, one glance. */
.sidebar-foot {
  flex-shrink: 0;
  padding: var(--space-3);
  border-top: 1px solid var(--border);
}
.sidebar-user {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2);
  border-radius: var(--radius);
  text-decoration: none;
  color: inherit;
  transition: background var(--dur-2) var(--ease-out);
}
.sidebar-user:hover { background: var(--surface-hover); color: inherit; }
.sidebar-user-name {
  font-size: var(--text-sm);
  font-weight: 600;
  line-height: 1.2;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sidebar-user-role { font-size: var(--text-xs); color: var(--faint); text-transform: capitalize; }

/* --- Main column ----------------------------------------------------------- */
.app-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.app-topbar {
  position: sticky;
  top: 0;
  z-index: 1030;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--topbar-h);
  padding: var(--space-2) var(--space-4);
  background: var(--glass);
  backdrop-filter: blur(var(--glass-blur)) saturate(1.3);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(1.3);
  border-bottom: 1px solid var(--border);
}

/* Koka që e ndien rrëshqitjen.
   Në krye të faqes ajo s'ka pse të ndahet nga asgjë — nën të rri fillimi i
   përmbajtjes, dhe një hije aty është një hije pa shkak. Sapo faqja niset, ajo
   kokë fillon të mbulojë tekst: atëherë duhet të thotë se rri MBI të, përndryshe
   rreshtat duket sikur hyjnë brenda saj.

   Deri tani kjo bëhej gjithnjë me JavaScript — një dëgjues `scroll` që vë e heq
   një klasë, pra një funksion i yni që ekzekutohet për çdo kuadër ndërsa dikush
   rrëshqet një tabelë me pesëqind rreshta. Këtu s'ka dëgjues fare: `scroll()` e
   lidh animacionin drejtpërdrejt me pozicionin e rrëshqitjes, dhe atë e llogarit
   vetë shfletuesi, jashtë fillit kryesor. Kush s'e njeh, e ka kokën pikërisht
   siç e kishte dje.

   Longhand dhe jo shkurtorja `animation:` — ajo e rivendos `animation-timeline`
   te `auto`, pra do ta shkëpuste vetë lidhjen që po vendoset këtu. */
@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
    .app-topbar {
      animation-name: topbarLift;
      animation-fill-mode: both;
      animation-timing-function: linear;
      animation-timeline: scroll(root block);
      animation-range: 0 96px;
    }
  }
}
@keyframes topbarLift {
  from {
    background-color: var(--glass);
    box-shadow: 0 0 0 rgba(0,0,0,0);
  }
  to {
    background-color: var(--glass-strong);
    box-shadow: var(--shadow-md);
  }
}

/* Sa larg ke shkuar te kjo faqe.
   Faqet e kësaj zyre janë të gjata — një matricë me dymbëdhjetë muaj, një listë
   me pesëqind rreshta, një raport me tridhjetë vizuale — dhe rrëshqitësi i
   shfletuesit është e vetmja gjë që e thotë sa mbetet. Te një dritare e
   inkorporuar ai është tre piksele gri që s'i sheh kush.

   Vija rri te buza e poshtme e kokës sepse aty është kufiri që e ndan atë që ke
   lexuar nga ajo që po lexon, dhe sepse koka është e vetmja gjë e ngulur në
   ekran. Pa element të ri te asnjë shabllon: `::after` i kokës ishte i lirë.

   E njëjta lidhje si te `topbarLift` mbi të — vetë shfletuesi e llogarit, jashtë
   fillit kryesor, pa asnjë dëgjues `scroll` timonin e të cilit do ta mbanim ne.
   Dhe e njëjta kujdesje: longhand, sepse shkurtorja `animation:` do ta rivendoste
   `animation-timeline` te `auto` dhe do ta shkëpuste pikërisht atë që lidhet.

   `scaleX` e jo `width`: e dyta rillogarit shtratin e faqes në çdo kuadër të një
   rrëshqitjeje, e para lëviz një shtresë të gatshme. Dhe `linear` sepse kjo nuk
   është shije — vija duhet të thotë saktësisht sa është rrëshqitur, jo diçka që
   ngadalësohet drejt fundit.

   Kur faqja nuk ka çfarë të rrëshqasë, afati mbetet joaktiv: vija rri te
   `scaleX(0)` e deklaruar këtu, pra thjesht nuk ekziston. */
@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
    .app-topbar::after {
      content: "";
      position: absolute;
      left: 0;
      right: 0;
      bottom: -1px;
      height: 2px;
      background: var(--grad-primary);
      transform: scaleX(0);
      transform-origin: left center;
      pointer-events: none;
      animation-name: readProgress;
      animation-fill-mode: both;
      animation-timing-function: linear;
      animation-timeline: scroll(root block);
    }
  }
}
@keyframes readProgress {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

.app-content {
  flex: 1;
  padding: var(--space-5) var(--space-5) var(--space-6-5);
  /* Opacity-only, `backwards` fill — NEVER a transform and never `both`: an
     animated transform on this element makes it the containing block and
     stacking context for every position:fixed descendant, and page modals
     live inside it. That bug shipped once: the group "Menaxho" modal landed
     UNDER the body-level backdrop — a dark veil nobody could click through.
     The slide-up motion lives on the children (.stagger, .reveal) instead. */
  animation: pageFade var(--dur-3) var(--ease-out) backwards;
}
@keyframes pageFade {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@media (max-width: 576px) {
  .app-content { padding: var(--space-4) var(--space-3) var(--space-6); }
  .app-topbar { padding: var(--space-2) var(--space-3); }
}
@keyframes pageIn {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}

/* --- Shiriti i poshtëm (telefon) --------------------------------------------
   Katër dyert e ditës plus «Më shumë», atje ku e arrin gishti i madh. Shfaqet
   vetëm nën `lg`, pikërisht ku menyja anësore bëhet sirtar — shih base.html.

   Lartësia rri te një token, dhe kjo është pjesa që nuk duhet harruar: shiriti
   është `fixed`, pra ai NUK e shtyn faqen — pa këtë token çdo faqe do të mbaronte
   nën të, dhe rreshti i fundit i çdo tabele do të ishte i palexueshëm. Mbi `lg`
   tokeni është `0px`, pra të gjitha llogaritjet që e përmendin mbeten ashtu siç
   ishin, pa asnjë kusht të dytë. `env(safe-area-inset-bottom)` është shiriti i
   iPhone-it: pa të, «Mesazhet» do të binte nën vijën e bardhë të sistemit. */
:root { --bottomnav-h: 0px; }
@media (max-width: 991.98px) {
  :root { --bottomnav-h: calc(3.55rem + env(safe-area-inset-bottom)); }
  .app-content { padding-bottom: calc(var(--space-5) + var(--bottomnav-h)); }
}

.bottom-nav {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 1035;             /* mbi faqen, nën modalet (1055) dhe njoftimet (1090) */
  display: flex;
  height: var(--bottomnav-h);
  padding-bottom: env(safe-area-inset-bottom);
  background: var(--glass-strong);
  backdrop-filter: blur(var(--glass-blur));
  -webkit-backdrop-filter: blur(var(--glass-blur));
  border-top: 1px solid var(--border);
  box-shadow: var(--shadow-up);
}
.bottom-nav-item {
  position: relative;
  flex: 1 1 0;
  min-width: 0;              /* pesë tituj s'e zgjerojnë dot shiritin jashtë ekranit */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-1);
  padding: var(--space-1) var(--space-1);
  border: 0;
  background: transparent;
  color: var(--faint);
  text-decoration: none;
  font-weight: 600;
  transition: color var(--dur-2) var(--ease-out);
}
/* Shiriti i poshtëm preket vetëm me gisht, pra hover-i i tij vlen vetëm aty ku
   ka mi; përndryshe shfletuesi e lexon si «diçka ndryshon kur e prek» dhe e
   mban prekjen e parë për vete. `:active` e jep të njëjtën përgjigje pa këtë
   çmim — dhe pa e vonuar hapjen as edhe një prekje. */
@media (hover: hover) {
  .bottom-nav-item:hover { color: var(--primary-text); }
}
.bottom-nav-item:focus-visible, .bottom-nav-item:active { color: var(--primary-text); }
.bottom-nav-icon { position: relative; display: block; font-size: var(--text-lg); line-height: 1; }
.bottom-nav-label {
  font-size: var(--text-2xs);
  letter-spacing: .01em;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Faqja ku je: ngjyra e plotë dhe një vijë e shkurtër lart. Vija rri mbi buzë,
   jo poshtë tekstit — poshtë do të përplasej me shiritin e sistemit. */
.bottom-nav-item.active { color: var(--primary-text); }
.bottom-nav-item.active::before {
  content: "";
  position: absolute;
  top: 0;
  width: 1.7rem;
  height: 3px;
  border-radius: 0 0 var(--radius-xs) var(--radius-xs);
  background: var(--grad-primary);
}
/* Numri mbi ikonën, jo pranë saj: pesë rubrika s'lënë gjerësi për të dyja. */
.bottom-nav-dot {
  position: absolute;
  top: -.35rem;
  left: 60%;
  min-width: 1.05rem;
  padding: var(--space-0) var(--space-1);
  background: var(--grad-primary);
  color: #fff;
  font-size: var(--text-2xs);
  font-weight: 700;
  line-height: 1.3;
  border-radius: var(--radius-pill);
  text-align: center;
  box-shadow: var(--ring-cut);
}

/* Round, quiet controls that live on the topbar. */
.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--muted);
  transition: color var(--dur-1) var(--ease-out),
              border-color var(--dur-1) var(--ease-out),
              background var(--dur-1) var(--ease-out),
              transform var(--dur-2) var(--ease-spring),
              box-shadow var(--dur-2) var(--ease-out);
}
.icon-btn:hover {
  color: var(--primary);
  border-color: var(--primary-line);
  background: var(--primary-soft);
  transform: translateY(-1px);
}
.icon-btn:active { transform: none; }

/* Prapa: e njëjta kuti e qetë si të tjerat te koka. E vetmja shtesë është
   shigjeta që rrëshqet majtas nën gisht — drejtimi thuhet nga lëvizja, jo vetëm
   nga forma e ikonës, dhe kjo e ndan atë nga zilja e nga menyja pranë. */
.topbar-back i {
  display: block;
  transition: transform var(--dur-2) var(--ease-spring);
}
.topbar-back:hover i { transform: translateX(-2px); }

/* Topbar search doubles as the command-palette trigger. */
.topbar-search {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: min(340px, 34vw);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--faint);
  font-size: var(--text-sm);
  cursor: pointer;
  transition: border-color var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease-out), color var(--dur-2) var(--ease-out);
}
.topbar-search:hover { border-color: var(--primary-line); color: var(--muted); }
.topbar-search .kbd { margin-left: auto; }
/* Në ekran të vogël mbetet vetëm ikona: koka atje ka vend për tri gjëra, jo pesë. */
@media (max-width: 575.98px) {
  .topbar-search { width: auto; padding: var(--space-2); }
}

/* --- Gjuha ------------------------------------------------------------------
   Dy fjalë, njëra e ndezur. Pa menu që hapet: zgjedhja duket pa u klikuar, dhe
   ndërrohet me një klik të vetëm. */
.lang-switch {
  display: inline-flex;
  align-items: center;
  padding: var(--space-0);
  gap: var(--space-0);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-muted);
}
.lang-opt {
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: .04em;
  color: var(--faint);
  text-decoration: none;
  transition: background var(--dur-2) var(--ease-out), color var(--dur-2) var(--ease-out);
}
.lang-opt:hover { color: var(--text); }
.lang-opt.active {
  background: var(--surface);
  color: var(--primary-text);
  box-shadow: var(--shadow-sm);
}

/* --- «Pamja» ----------------------------------------------------------------
   Gjuha, tema dhe densiteti nën një ikonë. Të treja i bashkon e njëjta gjë: nuk
   janë punë, janë «si duket faqja për mua, në këtë makinë». Të shpërndara nëpër
   kokë ato zinin tri vende të përhershme për zgjedhje që bëhen një herë e
   harrohen — dhe në telefon i shtynin nga shiriti pikërisht ato që preken çdo
   ditë, zilen dhe kërkimin. */
.view-menu { min-width: 12.5rem; padding-bottom: var(--space-2); }
.view-menu .dropdown-header {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--faint);
  padding-bottom: var(--space-0);
}
.view-menu-row { padding: var(--space-1) var(--space-3) var(--space-1); }
.view-opt {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  padding: var(--space-2) var(--space-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-muted);
  color: var(--text);
  font-size: var(--text-sm);
  font-weight: 600;
  text-align: left;
  transition: background var(--dur-2) var(--ease-out), border-color var(--dur-2) var(--ease-out), color var(--dur-2) var(--ease-out);
}
.view-opt:hover {
  background: var(--surface-hover);
  border-color: var(--primary);
  color: var(--primary-text);
}
.view-opt i { font-size: var(--text-base); color: var(--faint); }
.view-opt:hover i { color: var(--primary); }
/* Brenda menysë ndërruesi i gjuhës zë gjithë gjerësinë, që të tria rreshtat të
   nisin nga e njëjta vijë dhe menyja të mos duket e ngrënë nga njëra anë. */
.view-menu .lang-switch { display: flex; width: 100%; }
.view-menu .lang-opt { flex: 1; text-align: center; padding: var(--space-1) var(--space-2); }

/* --- «Sot» ------------------------------------------------------------------
   Blloku i punës që pret. Rreshtat janë lidhje me numrin para tekstit: numri
   thotë sa, teksti thotë çfarë, dhe e gjithë shiriti është klikim — një gjë për
   të bërë, jo një shifër për t'u parë. */
.worklist { display: flex; flex-direction: column; }
.worklist-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  color: var(--text);
  text-decoration: none;
  border-top: 1px solid var(--border);
  transition: background var(--dur-2) var(--ease-out);
}
.worklist-row:first-child { border-top: 0; }
.worklist-row:hover { background: var(--surface-hover); }
.worklist-icon {
  display: grid;
  place-items: center;
  width: 2rem;
  height: 2rem;
  border-radius: var(--radius-sm);
  font-size: var(--text-md);
}
.worklist-count {
  font-family: 'Sora Variable', 'Inter Variable', Inter, sans-serif;
  font-size: var(--text-lg);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  min-width: 2ch;
}
.worklist-text { color: var(--muted); font-size: var(--text-sm); }
.worklist-go { margin-left: auto; color: var(--faint); font-size: var(--text-sm); }
.worklist-danger .worklist-icon { background: var(--danger-soft); color: var(--danger); }
.worklist-danger .worklist-count { color: var(--danger); }
.worklist-warning .worklist-icon { background: var(--warning-soft); color: var(--warning); }
.worklist-warning .worklist-count { color: var(--warning); }
.worklist-info .worklist-icon { background: var(--info-soft); color: var(--info); }

/* --- Radha e ditës te «Puna ime» --------------------------------------------
   Te zyra rreshti thotë sa; te puntori thotë cili. Ai ka vetëm punën e vet,
   prandaj këtu rrinë vetë task-et, jo numrat e tyre — dhe secili rresht është
   një derë. Ora rri e para se pyetja e mëngjesit është «kur», jo «çfarë». */
.wq { display: flex; flex-direction: column; }
.wq-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-4);
  color: var(--text);
  text-decoration: none;
  border-top: 1px solid var(--border);
  border-left: 3px solid transparent;
  transition: background var(--dur-2) var(--ease-out);
}
.wq-row:first-child { border-top: 0; }
.wq-row:hover { background: var(--surface-hover); }
.wq-when {
  display: flex;
  flex-direction: column;
  align-items: center;
  min-width: 3.4rem;
  font-variant-numeric: tabular-nums;
}
.wq-date { font-weight: 700; font-size: var(--text-md); }
.wq-time { font-size: var(--text-2xs); color: var(--muted); }
.wq-main { flex: 1; min-width: 0; }
.wq-title {
  display: block;
  font-weight: 600;
  font-size: var(--text-sm);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.wq-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-1) var(--space-2);
  margin-top: var(--space-0);
  font-size: var(--text-2xs);
  color: var(--muted);
}
.wq-tag {
  flex-shrink: 0;
  font-size: var(--text-2xs);
  font-weight: 600;
  color: var(--muted);
  text-align: right;
}
/* Vonesa merr të vetmen ngjyrë të fortë në këtë listë: gjithçka tjetër është
   ende në kohë, dhe një faqe ku çdo rresht bërtet nuk thotë asgjë. */
.wq-late { border-left-color: var(--danger); }
.wq-late .wq-date, .wq-late .wq-tag { color: var(--danger); }
.wq-today { border-left-color: var(--warning); }
.wq-today .wq-tag { color: var(--warning); }

.wq-sub {
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--faint);
  text-transform: uppercase;
  letter-spacing: .04em;
}

/* Java ime: katër numra që e thonë ngarkesën pa e hapur bordin. */
.wq-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr));
  gap: var(--space-3);
  text-align: center;
}
.wq-stat-value {
  font-family: 'Sora Variable', 'Inter Variable', Inter, sans-serif;
  font-size: var(--text-xl);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}
.wq-stat-label { font-size: var(--text-2xs); color: var(--muted); margin-top: var(--space-0); }

/* --- Tabelat e gjata --------------------------------------------------------
   Puna e vërtetë e zyrës rri te tabelat, dhe ato janë të gjata: pa kokë të
   ngjitur, pas njëzet rreshtash nuk dihet më ç'kolonë po lexon, dhe pa kolonën e
   parë të ngjitur nuk dihet as për cilin klient. `.table-sticky` te një
   .table-responsive i mban të dyja. */
.table-responsive.table-sticky { max-height: min(70vh, 720px); overflow: auto; }
.table-sticky thead th {
  position: sticky;
  top: 0;
  z-index: 3;
  background: var(--surface);
  box-shadow: inset 0 -1px 0 var(--border-strong);
}
.table-sticky tbody th:first-child,
.table-sticky td.sticky-col,
.table-sticky th.sticky-col {
  position: sticky;
  left: 0;
  z-index: 2;
  background: var(--surface);
}
.table-sticky thead th.sticky-col { z-index: 4; }

/* Densiteti: i njëjti ekran, më shumë rreshta. Prek vetëm hapësirën — asnjë
   madhësi shkronje, që tabela të mos bëhet e palexueshme kur ngjishet. */
body.density-compact .table > :not(caption) > * > * { padding-top: var(--space-1); padding-bottom: var(--space-1); }
body.density-compact .card-body { padding: var(--space-3) var(--space-4); }
body.density-compact .stat-card { padding: var(--space-3); }

/* --- Brand -----------------------------------------------------------------
   Logoja (templates/_brand.html) i sjell të gjitha ngjyrat e veta: pllakën
   indigo→vjollcë→fuksia, dritën lart-majtas dhe vijën e artë që ngrihet. Vendi
   ku ulet i jep vetëm përmasën. Kështu marka është e njëjta gjë mbi sfond të
   errët, mbi gradient dhe mbi të bardhë — dhe s'ka faqe ku zbehet. */
.ka-logo {
  width: 100%;
  height: 100%;
  display: block;
  /* Vetë vizatimi e mban hapësirën e vet brenda viewBox-it, prandaj kutia
     mbushet plot dhe frymëmarrja nuk varet nga padding-u i çdo vendi. */
}

.navbar-brand, .brand {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  text-decoration: none;
  font-weight: 700;
  letter-spacing: .04em;
}
/* Vetëm një kuti me madhësi dhe një shkëlqim poshtë. Pllaka, drita dhe vija e
   artë vijnë brenda vetë logos — më parë sfondi ishte këtu, që do të thoshte se
   marka dukej ndryshe në çdo vend ku ulej. */
.brand-mark-lg {
  display: inline-flex;
  width: 36px;
  height: 36px;
  border-radius: var(--radius);
  box-shadow: var(--shadow-glow);
}
.brand-word {
  font-family: 'Sora Variable', 'Inter Variable', Inter, sans-serif;
  font-weight: 700;
  font-size: var(--text-base);
  /* Ulur edhe një herë, nga .1em: emri tani është «CentPerCent» — njëmbëdhjetë
     shkronja me të vogla mes tyre, jo tetë të mëdha. Hapësira që i rrinte mirë
     një shkurtese e shpërndan një fjalë të tërë, dhe në atë gjatësi e shtynte
     emrin drejt butonit të mbledhjes. */
  letter-spacing: .04em;
  white-space: nowrap;
  color: var(--text);
}

/* --- Legacy shell names ----------------------------------------------------
   Old templates and page scripts still reference these; keep them painting
   with tokens until every page has moved to the new shell classes. */
.navbar { position: relative; z-index: 2000; backdrop-filter: blur(14px);
          border-bottom: 1px solid var(--border); }
.navbar, .sidebar { background: var(--glass); color: var(--text); }
/* Këto dy mbeten të forta, dhe jo nga Bootstrap-i: Popper-i e pozicionon menunë
   e hapur duke i shkruar `position` te atributi `style` i elementit. Një stil
   inline nuk e prek asnjë shtresë — e mund vetëm një deklaratë e fortë. */
.navbar .dropdown-menu { position: absolute !important; z-index: 3000 !important; }
.sidebar { min-height: 100vh; border-right: 1px solid var(--border); }
.sidebar .nav-link.active { color: var(--primary-text); background: var(--primary-soft); font-weight: 600; }
.main-panel { padding-top: var(--space-4); }

/* ============================================================================
   4. Core controls
   ========================================================================= */

.btn {
  border-radius: var(--radius-sm);
  font-weight: 500;
  /* `--grad-angle` rri te lista e çdo butoni e jo vetëm te ai primar: vetëm
     primari e ndryshon, dhe një veti që nuk lëviz kurrë nuk kushton asgjë —
     ndërsa një `transition` e dytë e shkruar veç te `.btn-primary` do të duhej
     ta përsëriste të tërën, dhe atëherë ka dy lista që duhen mbajtur në hap. */
  transition: background var(--dur-1) var(--ease-out),
              border-color var(--dur-1) var(--ease-out),
              color var(--dur-1) var(--ease-out),
              box-shadow var(--dur-2) var(--ease-out),
              transform var(--dur-2) var(--ease-spring),
              filter var(--dur-1) var(--ease-out),
              --grad-angle var(--dur-3) var(--ease-out);
}
.btn:active { transform: translateY(1px); }

/* --- Butoni që po punon ------------------------------------------------------
   Vendoset nga site.js sapo niset një formë, dhe hiqet kur faqja ndërrohet ose
   kur diçka e ndaloi nisjen. Rrotulluesi vjen si pseudo-element, jo si markup:
   asnjë nga 152 format e programit s'ka pse ta mbajë atë të shkruar brenda, dhe
   përmbajtja e butonit mbetet e paprekur — pra rikthimi është vetëm heqja e një
   klase. `currentColor` do të thotë se ai merr ngjyrën e butonit ku rri: i bardhë
   mbi «primary», i errët mbi një buton të zbrazët. */
.btn.is-busy, .icon-btn.is-busy {
  pointer-events: none;   /* klikimi i dytë s'ka ku të bjerë */
  opacity: .78;
}
.is-busy::before {
  content: "";
  display: inline-block;
  width: 1em;
  height: 1em;
  vertical-align: -.125em;
  margin-inline-end: .45em;
  border: 2px solid currentColor;
  border-inline-end-color: transparent;
  border-radius: var(--radius-round);
  animation: ka-spin var(--spin) linear infinite;
}
/* Butoni pa fjalë: ikona e tij fshihet dhe rrotulluesi zë saktësisht vendin e
   saj, pra butoni nuk ndërron gjerësi nën gisht. */
.is-busy-bare::before { margin-inline-end: 0; }
.is-busy > i.bi, .is-busy > svg { display: none; }
@keyframes ka-spin { to { transform: rotate(360deg); } }

/* Primary carries the brand gradient and a soft glow — one obvious action per
   screen, and this is what it looks like. */
.btn-primary {
  /* Gradienti shkruhet këtu me skajet e tij e jo si `var(--grad-primary)`, që
     këndi të mbetet i prekshëm: nën mi ai rrotullohet nga 135° në 100°, dhe
     drita rrëshqet nëpër buton në vend që të ndërrohet me një kërcim. Ngjyrat
     mbeten tokenat e temës — vetëm këndi është i yni këtu. */
  background: linear-gradient(var(--grad-angle), var(--grad-from), var(--grad-to));
  border: 0;
  color: #fff;
  box-shadow: var(--shadow-glow);
  padding-top: calc(var(--space-1-5) + 1px);
  padding-bottom: calc(var(--space-1-5) + 1px);
}
.btn-primary:hover, .btn-primary:focus {
  --grad-from: var(--grad-from-hover);
  --grad-to: var(--grad-to-hover);
  --grad-angle: 100deg;
  color: #fff;
  transform: translateY(-1px);
  box-shadow: var(--shadow-glow-strong);
}
.btn-primary:active { transform: none; }
.btn-primary.btn-sm { padding-top: calc(var(--space-1) + 1px); padding-bottom: calc(var(--space-1) + 1px); }

/* Every outline variant is driven through Bootstrap's own --bs-btn-* variables
   rather than by setting `color` directly.

   Setting the colour looked equivalent and was not. Bootstrap paints the
   pressed state with `.btn.active` — specificity (0,2,0) — while the theme
   override `body.theme-dark .btn-outline-primary` scores (0,2,1) and won. So a
   selected button kept its resting indigo text while Bootstrap filled the
   background with its own #0d6efd underneath: 1.51:1, which is no text at all.
   That is what the «Këtë javë / Këtë muaj» toggle was doing.

   Variables have no such fight. One declaration feeds rest, hover, active and
   disabled together, and the active fill becomes ours instead of Bootstrap's
   stock blue. */
.btn-outline-primary {
  --bs-btn-color: var(--primary-text);
  --bs-btn-border-color: var(--primary-line);
  --bs-btn-hover-color: var(--primary-contrast);
  --bs-btn-hover-bg: var(--primary);
  --bs-btn-hover-border-color: var(--primary);
  --bs-btn-active-color: var(--primary-contrast);
  --bs-btn-active-bg: var(--primary);
  --bs-btn-active-border-color: var(--primary);
  --bs-btn-disabled-color: var(--faint);
  --bs-btn-disabled-border-color: var(--border);
}

.btn-secondary {
  background: var(--surface-muted);
  color: var(--text);
  border-color: var(--border-strong);
}
.btn-secondary:hover { background: var(--surface-hover); color: var(--text); border-color: var(--border-strong); }
/* The same treatment for the rest: each had the identical latent bug, only
   nobody had pressed them yet. The active fill is the variant's own colour with
   contrast ink on top, not Bootstrap's stock palette. */
.btn-outline-secondary {
  --bs-btn-color: var(--text);
  --bs-btn-border-color: var(--border-strong);
  --bs-btn-hover-color: var(--text);
  --bs-btn-hover-bg: var(--surface-hover);
  --bs-btn-hover-border-color: var(--border-strong);
  --bs-btn-active-color: var(--text);
  --bs-btn-active-bg: var(--surface-muted);
  --bs-btn-active-border-color: var(--border-strong);
  --bs-btn-disabled-color: var(--faint);
  --bs-btn-disabled-border-color: var(--border);
}
.btn-outline-success {
  --bs-btn-color: var(--success);
  --bs-btn-border-color: var(--success);
  --bs-btn-hover-color: var(--success);
  --bs-btn-hover-bg: var(--success-soft);
  --bs-btn-hover-border-color: var(--success);
  --bs-btn-active-color: var(--success);
  --bs-btn-active-bg: var(--success-soft);
  --bs-btn-active-border-color: var(--success);
}
.btn-outline-danger {
  --bs-btn-color: var(--danger);
  --bs-btn-border-color: var(--danger);
  --bs-btn-hover-color: var(--danger);
  --bs-btn-hover-bg: var(--danger-soft);
  --bs-btn-hover-border-color: var(--danger);
  --bs-btn-active-color: var(--danger);
  --bs-btn-active-bg: var(--danger-soft);
  --bs-btn-active-border-color: var(--danger);
}

.form-control, .form-select {
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-strong);
  color: var(--text);
  /* background-color, NEVER the `background` shorthand. A select carries its
     chevron as a background-image, and the shorthand resets image, position,
     repeat and size along with the colour. That wiped the chevron in the light
     theme, and in the dark theme — where the image was painted back — it
     returned with repeat and 0 0, tiling arrows across the text. */
  background-color: var(--surface-muted);
  transition: border-color var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease-out), background-color var(--dur-2) var(--ease-out);
}
.form-control::placeholder { color: var(--faint); }
.form-control:focus, .form-select:focus {
  background-color: var(--surface);
  border-color: var(--primary);
  box-shadow: var(--ring);
  color: var(--text);
}
/* Fusha e gabuar thotë menjëherë, jo pas dërgimit.
   `:user-invalid` dhe jo `:invalid`: e dyta është e vërtetë që në çastin e parë,
   pra çdo formë e sapohapur do të hapej e tëra e kuqe — një faqe që të qorton
   para se t'i kesh prekur. E para pret derisa njeriu ta ketë shkruar dhe lënë
   fushën. Kufiri, jo mbushja: `.is-invalid` e Bootstrap-it, që e vë serveri pas
   dërgimit, mbetet zëri i fortë; ky është kujtesa e qetë përpara tij. */
.form-control:user-invalid, .form-select:user-invalid {
  border-color: var(--danger);
}
.form-control:user-invalid:focus, .form-select:user-invalid:focus {
  box-shadow: 0 0 0 var(--ring-w-lg) color-mix(in srgb, var(--danger) 28%, transparent);
}
/* Kartela që mban një fushë të gabuar shënohet e tëra — te një formë e gjatë
   fusha e kuqe rri jashtë ekranit, dhe njeriu shtyp «Ruaj» pa e parë kurrë. */
.card:has(.form-control:user-invalid, .form-select:user-invalid) {
  border-color: color-mix(in srgb, var(--danger) 45%, var(--border));
}
/* Bootstrap paints the calendar and select arrows near-black; in dark mode they
   vanish against a dark field. The chevron is swapped through Bootstrap's own
   variable rather than by setting background-image: Bootstrap layers
   `var(--bs-form-select-bg-img), var(--bs-form-select-bg-icon, none)` and
   overwriting background-image would drop the validation-icon layer. */
body.theme-dark .form-control::-webkit-calendar-picker-indicator { filter: invert(1) opacity(.7); }
body.theme-dark .form-select {
  --bs-form-select-bg-img: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%239aa9c0' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
}

/* Kutia e tekstit që rritet me atë që shkruhet brenda.
   Një `<textarea rows="2">` mban dy rreshta dhe pastaj rrëshqet brenda vetes:
   kush shkruan arsyen e një ndryshimi te regjistri e sheh fillimin e fjalisë të
   ikë sapo mbush rreshtin e tretë, dhe s'e rilexon dot pa u kthyer me shigjeta.
   Deri tani kjo zgjidhej me JavaScript — një dëgjues `input` që mat
   `scrollHeight` dhe vë lartësinë — te secila faqe veç. `field-sizing: content`
   e bën vetë shfletuesi.

   `rows` nuk dëgjohet më sapo kjo ndizet, prandaj lartësia e nisjes rikthehet
   nga vetë ai atribut: `1lh` është saktësisht lartësia e një rreshti të kësaj
   fushe, plus mbushja e Bootstrap-it (.375rem lart e poshtë) dhe dy kufijtë.
   Pra fusha hapet ashtu siç hapej dje, dhe prej andej rritet.

   Të dyja pyetjet te i njëjti `@supports`: pa `lh` lartësia e nisjes s'ka si
   llogaritet, dhe një fushë që hapet me një rresht atje ku shabllonet presin
   tre është më keq se ajo e djeshmja. */
@supports (field-sizing: content) and (height: 1lh) {
  textarea.form-control {
    field-sizing: content;
    /* Një letër e tërë e ngjitur brenda s'duhet ta bëjë faqen sa tre ekrane:
       deri këtu rritet, pastaj rrëshqet si më parë. */
    max-height: 40vh;
  }
  textarea.form-control[rows="1"] { min-height: calc(1lh + .75rem + 2px); }
  textarea.form-control[rows="2"] { min-height: calc(2lh + .75rem + 2px); }
  textarea.form-control[rows="3"] { min-height: calc(3lh + .75rem + 2px); }
  textarea.form-control[rows="4"] { min-height: calc(4lh + .75rem + 2px); }
  textarea.form-control[rows="5"] { min-height: calc(5lh + .75rem + 2px); }
  textarea.form-control[rows="6"] { min-height: calc(6lh + .75rem + 2px); }
}

.form-label { font-weight: 500; font-size: var(--text-sm); color: var(--muted); }
.form-text { color: var(--faint); }
/* Dy komponentë të Bootstrap-it që rrezen s'e lexojnë nga ndryshoret e tij, pra
   lidhja te tokenat nuk i prek dot: kutiza e zgjedhjes e ka `.25em` — domethënë
   një rreze tjetër për çdo madhësi shkronje ku ndodhet, dhe matja i nxori tri
   (2,96px, 3,36px, 3,5px) — dhe butoni i mbylljes e ka `.375rem` të ngurtë.
   Rreshti i dytë kthen çelësin te forma e vet: `.form-switch` e ka rrezen te një
   rregull i tijin, dhe pa të çelësi do të dilte kuti. */
.form-check-input[type="checkbox"] { border-radius: var(--radius-xs); }
.form-switch .form-check-input { border-radius: var(--radius-pill); }
.btn-close { border-radius: var(--radius-sm); }
.input-group-text {
  background: var(--surface-muted);
  border-color: var(--border-strong);
  color: var(--muted);
}

.dropdown-menu {
  background-color: var(--surface-raised);
  backdrop-filter: blur(var(--glass-blur));
  -webkit-backdrop-filter: blur(var(--glass-blur));
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  padding: var(--space-1-5);
}
.dropdown-item {
  color: var(--text);
  border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-sm);
}
.dropdown-item:hover, .dropdown-item:focus {
  background-color: var(--surface-hover);
  color: var(--text);
}
.dropdown-divider { border-color: var(--border); }
.dropdown-header { color: var(--faint); font-size: var(--text-xs); text-transform: uppercase; letter-spacing: .07em; }

.modal-content {
  background-color: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}
.modal-header, .modal-footer { border-color: var(--border); }
.modal-backdrop { --bs-backdrop-opacity: .6; }

.offcanvas { background-color: var(--surface); color: var(--text); border-color: var(--border); }
.list-group-item { background-color: transparent; color: var(--text); border-color: var(--border); }
.list-group-item-action:hover, .list-group-item-action:focus {
  background-color: var(--surface-hover);
  color: var(--text);
}

.toast {
  border-radius: var(--radius);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-lg);
  backdrop-filter: blur(10px);
}
.toast.text-bg-primary {
  background: var(--grad-primary) !important;
  border: 0;
}
.toast.text-bg-success, .toast.text-bg-danger, .toast.text-bg-warning { border: 0; }

/* Kolona e njoftimeve.
   Vendin e mbanin klasat e Bootstrap-it te vetë markup-i — `position-fixed
   top-0 end-0 p-3` — dhe pikërisht ato e bënin të parregullueshme: `.top-0` te
   Bootstrap-i shkruhet me `!important`, pra asnjë media query e jona s'e zhvendos
   dot. Prandaj pozicioni erdhi këtu, dhe markup-i mban vetëm emrin. */
.toast-stack {
  position: fixed;
  top: 0;
  right: 0;
  z-index: 1090;             /* mbi modalet e Bootstrap-it (1055), si toast-container-i i tij */
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-4);
  max-width: min(26rem, calc(100vw - 2rem));
  pointer-events: none;      /* zona bosh nën to mos e bllokojë faqen */
}
.toast-stack > * { pointer-events: auto; }

/* Në telefon njoftimi rri poshtë.
   Lart-djathtas ai binte saktësisht mbi zilen, temën dhe avatarin — pra mbulonte
   kontrollet në çastin kur faqja sapo kishte vepruar, dhe gishti i madh është
   gjithsesi më afër fundit të ekranit se majës. */
@media (max-width: 576px) {
  .toast-stack {
    top: auto;
    /* Mbi shiritin e poshtëm, jo mbi të. Njoftimi që mbulon «Mesazhet» dhe «Më
       shumë» e bllokon navigimin pikërisht në çastin kur faqja sapo veproi. */
    bottom: var(--bottomnav-h);
    left: 0;
    right: 0;
    max-width: none;
    padding: var(--space-3);
    flex-direction: column-reverse;   /* i fundit mbërritur, më afër gishtit */
  }
}

/* Ikona e mesazhit: e njëjta madhësi si teksti, pak më e ndritshme se ai, dhe
   kurrë e ngjeshur kur fjalia shkon në dy rreshta. */
.ka-toast-icon {
  flex: 0 0 auto;
  font-size: var(--text-lg);
  line-height: 1.35;
  opacity: .92;
}
.ka-toast .toast-body { line-height: 1.35; }
/* Dera e kthimit brenda njoftimit. Një zvarritje e gabuar është një çast; pa
   këtë buton rregullimi i saj janë pesë klikime nëpër tri kolona. Rri e bardhë
   mbi njoftimin me ngjyrë, që të lexohet si veprim e jo si pjesë e fjalisë. */
.toast-undo {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-0) var(--space-2);
  font-size: var(--text-xs);
  font-weight: 600;
  white-space: nowrap;
}
/* Lidhja te përsëritja që sapo u hap: e bardhë si teksti rreth saj, e nënvizuar
   sepse pa nënvizim mbi një sfond me ngjyrë s'do të dukej fare si lidhje.
   Bardhë, jo `--primary-contrast`: ai është i errët në temën e errët, kurse
   njoftimi e mban të njëjtin sfond të ngopur në të dyja — pikërisht arsyeja e
   shkruar te `.avatar-initial`. */
.toast-link {
  color: #fff;
  text-decoration: underline;
  font-size: var(--text-xs);
  font-weight: 600;
}
.toast-link:hover, .toast-link:focus-visible { color: #fff; }

.badge { font-weight: 600; letter-spacing: .01em; border-radius: var(--radius-sm); }
.badge.bg-primary, .badge.text-bg-primary { background: var(--grad-primary) !important; color: #fff !important; }

/* Soft, readable status chips — preferred over solid badges in tables.

   Ndarja që ndjek gjithë aplikacioni: një etiketë që thotë *çfarë është* diçka —
   statusi, përparësia, kategoria — është `chip`; `badge` mbetet vetëm te numëruesit
   e Bootstrap-it (sa fatura, sa mesazhe të palexuara). Prandaj `.badge-priority-*`
   u hoq bashkë me rregullat e veta: asnjë shabllon nuk e përdorte më. */
.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-0) var(--space-2);
  border-radius: var(--radius-pill);
  font-size: var(--text-xs);
  font-weight: 600;
  line-height: 1.4;
  background: var(--surface-muted);
  color: var(--muted);
  border: 1px solid var(--border);
  white-space: nowrap;
}
.chip i { font-size: .8em; }
.chip-primary { background: var(--primary-soft); color: var(--primary-text); border-color: var(--primary-line); }
body.theme-dark .chip-primary { color: var(--primary); }
.chip-success { background: var(--success-soft); color: var(--success); border-color: transparent; }
.chip-warning { background: var(--warning-soft); color: var(--warning); border-color: transparent; }
.chip-danger  { background: var(--danger-soft);  color: var(--danger);  border-color: transparent; }
.chip-info    { background: var(--info-soft);    color: var(--info);    border-color: transparent; }

/* Live dot for online/ongoing states. */
.pulse-dot {
  display: inline-block;
  width: .55rem;
  height: .55rem;
  border-radius: var(--radius-round);
  background: var(--success);
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--live) 50%, transparent);
  animation: pulseDot var(--beat-slow) var(--ease-in-out) infinite;
}
@keyframes pulseDot {
  0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--live) 45%, transparent); }
  70% { box-shadow: 0 0 0 .45rem transparent; }
  100% { box-shadow: 0 0 0 0 transparent; }
}

/* ============================================================================
   5. Components
   ========================================================================= */

/* --- Cards ------------------------------------------------------------------ */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  /* Buza e dritës para hijes: e para është brenda kutisë, e dyta poshtë saj —
     bashkë ato thonë «kjo sipërfaqe rri mbi faqen», ndërsa hija e vetme thotë
     vetëm «dikush ka pikturuar gri poshtë». */
  box-shadow: var(--edge-light-soft), var(--shadow-sm);
  color: var(--text);
}
.card-header {
  background: transparent;
  border-bottom: 1px solid var(--border);
  font-weight: 600;
  letter-spacing: -.01em;
  font-size: var(--text-md);
  color: var(--text);
}
.card-footer { background: transparent; border-top: 1px solid var(--border); }

/* Card that lifts on hover — for anything clickable. */
.card-lift {
  transition: transform var(--dur-2) var(--ease-spring),
              box-shadow var(--dur-2) var(--ease-out),
              border-color var(--dur-2) var(--ease-out);
}
.card-lift:hover {
  transform: translateY(-2px);
  box-shadow: var(--edge-light), var(--shadow-md);
  border-color: var(--primary-line);
}

.glass-card {
  background: var(--glass);
  backdrop-filter: blur(var(--glass-blur)) saturate(1.2);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(1.2);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--edge-light), var(--shadow-md);
}

/* --- Page header ------------------------------------------------------------ */
.page-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-3) var(--space-4);
  margin-bottom: var(--space-4);
}
.page-head-main { min-width: 0; }
.page-eyebrow {
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .1em;
  color: var(--primary);
  margin-bottom: var(--space-1);
}
.page-title {
  font-size: var(--display-sm);
  font-weight: 700;
  letter-spacing: -.02em;
  margin-bottom: var(--space-0);
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
.page-title .page-title-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  flex-shrink: 0;
  border-radius: var(--radius);
  background: var(--primary-soft);
  color: var(--primary);
  font-size: var(--text-lg);
  box-shadow: inset 0 0 0 var(--hairline) var(--primary-line);
}
.page-sub { color: var(--muted); font-size: var(--text-md); margin-bottom: 0; }
.page-actions { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-2); }

/* --- Paneli: blloqet rrjedhin në shtylla kur ka vend -------------------------
   Dymbëdhjetë blloqe rrinin njëri mbi tjetrin, dhe katër prej tyre shtriheshin
   1.124px për të mbajtur një grafik me gjashtë shtylla, një tabelë me tre
   rreshta dhe një rrip 86px të lartë. Te një laptop 1280×720 faqja dilte 4,2
   ekrane e gjatë dhe tregonte dy blloqe nga dymbëdhjetë — pra paneli që hapet
   në tetë e gjysmë dhe rri hapur deri në darkë duhej lëvizur katër herë për t'u
   lexuar një herë.

   `auto-fit` dhe jo një pikë ndarjeje e shkruar me dorë: shtylla e dytë hyn kur
   për të ka vend, jo në një gjerësi të zgjedhur nga unë — dhe te një ekran shumë
   i gjerë hyn e treta pa u shkruar asgjë më. 26rem është kufiri nën të cilin
   blloqet e këtij paneli nisin të gëlltiten; tabela nën grafikun e shitjeve
   kërkon 416px të vetat.

   Rendi i leximit nuk ndryshon. Blloqet rrinë në radhën e burimit, pra «Sot»
   mbetet e para — arsyeja pse rri aty është shkruar te vetë shablloni, dhe
   pamja nuk është vend për ta rimenduar atë.

   Kjo ishte rrjetë dhe nuk është më, dhe arsyeja e ndërrimit është një e vetme:
   te një rrjetë lartësia e rreshtit është sa kartela më e lartë e tij. Kartela
   e shkurtër mbaron aty ku mbaron, dhe poshtë saj mbetet bardhësi deri te
   rreshti tjetër — jo hapësirë e zgjedhur, por mbetje e një rreshti. Te paneli
   kjo dukej më së forti aty ku «Njoftim i ri», me formularin e palosur e pra sa
   koka e vet, binte pranë kartës së shitjeve me grafik e tabelë.

   Në një shtyllë teksti nuk ka rreshta: blloku i dytë nis aty ku mbaroi i pari,
   pa e pyetur fqinjën se sa e gjatë ishte. Pra fundi i papjekur nuk mbyllet —
   nuk lind. Dhe vendimi i vjetër që kartela e shkurtër nuk shtrihet për të
   mbushur rreshtin nuk hiqet: këtu ai bëhet i vetvetishëm, se s'ka rresht që ta
   kërkojë shtrirjen.

   Çmimi paguhet te renditja: shtyllat lexohen nga lart-poshtë, jo majtas-djathtas
   — kartela e dytë e shabllonit mund të dalë poshtë të parës në të njëjtën
   shtyllë. Për trembëdhjetë kuti të pavarura, secila me kokën dhe kufirin e vet,
   ky është shkëmbim i mirë; do të ishte i keq për një listë, ku rreshti i dytë e
   vazhdon të parin. Tastiera dhe lexuesi i ekranit e ndjekin gjithsesi burimin.

   `column-width` dhe jo `column-count`: shtylla e dytë hyn kur për të ka vend,
   jo në një pikë ndarjeje të zgjedhur me dorë — si `auto-fit` më parë. */
.dash-grid {
  /* `min(26rem, 100%)` dhe jo `26rem`: 26rem është kufiri nën të cilin blloqet
     e këtij paneli nisin të gëlltiten — tabela nën grafikun e shitjeve kërkon
     416px të vetat — po një kërkesë 416px mbi një ekran 390px është një shtyllë
     që del jashtë faqes duke marrë me vete gjithçka brenda. Në telefon kjo nxori
     dikur 89 elemente jashtë kufirit. `min()` e lë kërkesën të tërhiqet te
     gjerësia që ka vërtet. */
  column-width: min(26rem, 100%);
  column-gap: var(--space-4);
}
/* Ritmin e mbante `gap` i rrjetës. Mes dy blloqeve të një shtylle `gap` nuk
   ekziston — aty flet marzhi — pra ritmi zbret këtu, po mbetet një vendim i
   vetëm në një vend të vetëm, si më parë. Aty rrinin tri hapësira të ndryshme
   mes kartelash fqinje — 16px (`mb-3`), 8px (`mb-2`) dhe 20px (`.stat-grid`) —
   dhe asnjëra s'ishte vendim, ishin tri klasa të shkruara në tri ditë të
   ndryshme.

   `break-inside: avoid` është kushti pa të cilin gjithë kjo nuk lexohet:
   shfletuesi, po s'i thuhet, e pret kartelën në fund të shtyllës dhe e vazhdon
   te tjetra — koka lart majtas, tabela poshtë djathtas, dhe një kuti e vetme e
   lexuar si dy. */
.dash-grid > * {
  break-inside: avoid;
  margin-bottom: var(--space-4);
}
/* `.stat-grid` e mban hapësirën e vet (`--space-5`) te çdo faqe tjetër, dhe ajo
   rri më poshtë te skedari — pra pa këtë rresht ajo do ta fitonte mbi ritmin e
   panelit thjesht se vjen pas. Këtu nuk hiqet, barazohet. */
.dash-grid .stat-grid { margin-bottom: var(--space-4); }

/* Rreshti i pllakave e ka kuptimin te gjerësia: tri shifra krah për krah
   lexohen si një rresht, dhe të njëjtat tri të palosura në dy rreshta lexohen
   si dy gjëra të ndryshme. Prandaj marrin gjithë gjerësinë, sa shtylla të ketë
   paneli — `all` nuk e pyet se sa janë, si `1 / -1` para tij te rrjeta.
   Blloku që shtrihet i ndërpret shtyllat: ç'vjen para tij mbaron mbi të, dhe
   shtyllat rinisin poshtë. Pra ai është edhe e vetmja prerje horizontale e
   panelit — dhe pikërisht prandaj janë dy, njëra pas tjetrës, e jo të shpërndara
   mes kartelave. */
.dash-wide { column-span: all; }

/* Pllakat e njerëzve dhe tri listat që hapen nën to janë një bllok i vetëm për
   rrjetën. Ndryshe lista do të ishte qeliza pasardhëse: klikoje pllakën, dhe
   përgjigjja hapet në shtyllën tjetër — pikërisht ajo që u ndreq kur këto lista
   u ngjitën nga fundi i faqes këtu. */
.dash-people {
  display: grid;
  gap: var(--space-3);
  align-content: start;
}

/* --- Stat cards ------------------------------------------------------------- */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13.5rem, 1fr));
  gap: var(--space-3);
  margin-bottom: var(--space-5);
}
.stat-card {
  position: relative;
  overflow: hidden;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space-4);
  box-shadow: var(--edge-light-soft), var(--shadow-sm);
  transition: transform var(--dur-2) var(--ease-spring),
              box-shadow var(--dur-2) var(--ease-out),
              border-color var(--dur-2) var(--ease-out);
  /* Kutia bëhet kontejner: shih pyetjen @container më poshtë. */
  container-type: inline-size;
  container-name: stat;
  /* Kontekst i vetin i shtresimit, që dy zbukurimet poshtë (`::before` dhe
     `::after`) të rrinë me `z-index: -1` MBI sfondin e kartelës e NËN tekstin e
     saj. Pa këtë, `-1` do t'i çonte prapa vetë sfondit, pra do të zhdukeshin.
     Kartela e ka tashmë `overflow: hidden` — pra asgjë brenda saj nuk kishte
     ku të dilte gjithsesi, dhe konteksti i ri nuk mbyll asnjë derë. */
  isolation: isolate;
}
.stat-card:hover {
  transform: translateY(-2px);
  box-shadow: var(--edge-light), var(--shadow-md);
  border-color: var(--primary-line);
}
/* Toni i pllakës: një vijë 3px lart, dhe jo më një njollë në qoshe.
   Njolla ishte një rreth 120px i tërhequr te qoshja e sipërme e djathtë — pra
   pikërisht poshtë ikonës, të cilën e mjegullonte, dhe me një buzë të rrumbullakët
   që lexohej nën tekstin e etiketës si një hije e panjohur. Ajo mbante të njëjtën
   informatë që mban kjo vijë — jeshile do të thotë para, e kuqe borxh me vonesë —
   por e mbante të shpërndarë mbi një të katërtën e kartelës.

   Vija rri e prerë te buza nga `overflow: hidden` i kartelës, pra nuk kërkon
   rrezet e vet: qoshet e rrumbullakuara i vijnë nga kutia. Dhe mbetet me
   `z-index: -1` si njolla, sepse arsyeja pse ishte aty s'ka ndryshuar — një
   element i pozicionuar rri mbi tekstin fqinjë derisa t'i thuhet të mos rrijë. */
.stat-card::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: var(--grad-primary);
  pointer-events: none;
  z-index: -1;
}

/* Drita që ndjek miun.
   Një kartelë e sheh miun mbi vete: site.js i vë `--spot-x/--spot-y` (ku rri) e
   `--spot-o` (a është këtu), dhe pjesa tjetër është CSS. Kjo është arsyeja pse
   të tria u regjistruan si veti më lart — të paregjistruara, ndriçimi do të
   ndizej e fikej si çelës, dhe pozicioni do të kërcente nga fusha në fushë.

   Vetëm te kartelat e shifrave, dhe vetëm ku ka mi. Është rreshti i parë i çdo
   paneli — pikërisht aty ku syri bie i pari — dhe një efekt që ndjek miun mbi
   çdo kuti të programit do të ishte zhurmë, jo material. */
@media (hover: hover) {
  .stat-card::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: inherit;
    pointer-events: none;
    opacity: var(--spot-o);
    transition: opacity var(--dur-3) var(--ease-out);
    background: radial-gradient(circle 16rem at var(--spot-x) var(--spot-y),
                color-mix(in srgb, var(--primary) 16%, transparent), transparent 70%);
  }
}

/* Vija e mban ngjyrën e mbushjes, jo të butën: tri piksele me 13% tejdukshmëri
   janë një vijë që nuk shihet, dhe një vijë që nuk shihet është e njëjta gjë me
   asnjë vijë — vetëm më e vështirë për t'u fshirë nesër. */
.stat-card.stat-success::after {
  background: linear-gradient(90deg, var(--success-fill-strong), var(--success-fill));
}
.stat-card.stat-warning::after {
  background: linear-gradient(90deg, var(--warning-fill-strong), var(--warning-fill));
}
.stat-card.stat-danger::after {
  background: linear-gradient(90deg, var(--danger-fill-strong), var(--danger-fill));
}
.stat-card.stat-accent::after {
  background: linear-gradient(90deg, var(--accent-fill-strong), var(--accent-fill));
}

.stat-top { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); }
/* Ikona e pllakës flet të njëjtën gjuhë me ikonën e titullit të faqes: sfond i
   butë, glif me ngjyrë, një unazë 1px brenda. Deri tani ishte e kundërta —
   katror me gradient dhe `--shadow-glow` poshtë, pra e njëjta ikonë mbante dy
   gramatika brenda njëzet centimetrave: e sheshtë te kryeja e faqes, e shndritshme
   te rreshti i pllakave pak më poshtë. Gradienti dhe shkëlqimi mbeten aty ku kanë
   punë — butonat kryesorë — dhe pllakat, që në panel janë trembëdhjetë, kthehen
   te sipërfaqja e qetë. */
.stat-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  border-radius: var(--radius);
  background: var(--primary-soft);
  color: var(--primary);
  font-size: var(--text-lg);
  box-shadow: inset 0 0 0 var(--hairline) var(--primary-line);
  flex-shrink: 0;
}
/* Unaza e ikonës derivohet nga vetë ngjyra e tonit, si `--primary-line` nga
   `--primary`. Rrinte e shkruar me dorë — `rgba(16,185,129,.3)` përbri
   `var(--success-fill)`, pra e njëjta jeshile dy herë, njëherë si token e
   njëherë si tri shifra. Kush e ndërron tokenin nesër, e lë hijen te jeshilja e
   sotme dhe s'ka ku ta kërkojë. */
.stat-card.stat-success .stat-icon {
  background: var(--success-soft);
  color: var(--success);
  box-shadow: inset 0 0 0 var(--hairline) color-mix(in srgb, var(--success) 24%, transparent);
}
.stat-card.stat-warning .stat-icon {
  background: var(--warning-soft);
  color: var(--warning);
  box-shadow: inset 0 0 0 var(--hairline) color-mix(in srgb, var(--warning) 24%, transparent);
}
.stat-card.stat-danger .stat-icon {
  background: var(--danger-soft);
  color: var(--danger);
  box-shadow: inset 0 0 0 var(--hairline) color-mix(in srgb, var(--danger) 24%, transparent);
}
.stat-card.stat-accent .stat-icon {
  background: var(--accent-soft);
  color: var(--accent);
  box-shadow: inset 0 0 0 var(--hairline) color-mix(in srgb, var(--accent) 24%, transparent);
}

/* Stat cards that filter the table below. The active one wears a ring so it is
   obvious what the table is currently showing. */
.stat-card-filter { cursor: pointer; user-select: none; }
.stat-card-filter:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
.stat-card-filter.is-active {
  border-color: var(--primary);
  box-shadow: inset 0 0 0 var(--ring-w) var(--primary), var(--shadow-md);
}
/* Hidden by the card filter. Forced so it wins over the text quick-filter's
   inline display, giving the two filters AND semantics: a row shows only when
   it passes both. */
tr.u-filter-hidden { display: none !important; }

.stat-label {
  font-size: var(--text-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--muted);
  margin-bottom: var(--space-0);
}
.stat-value {
  font-family: 'Sora Variable', 'Inter Variable', Inter, sans-serif;
  font-size: var(--text-2xl);
  font-weight: 700;
  letter-spacing: -.02em;
  line-height: 1.15;
}
/* Kartela e ngushtë pyet veten, jo dritaren.
   E njëjta kartelë rri në një rresht me katër te paneli dhe në një shtyllë të
   ngushtë te faqja e klientit. Një `@media` mat dritaren — pra te faqja e
   klientit ajo sheh një ekran 1600px dhe e lë kartelën me shkronjat e panelit,
   brenda një shtylle 220px ku shifra del jashtë. `@container` mat kutinë vetë:
   e njëjta klasë, e njëjta HTML, dhe secila kopje vendos për vete.

   Brenda bllokut rrinë vetëm PËRMBAJTËSIT e kartelës, kurrë kartela vetë: një
   kontejner s'e pyet dot veten — pyetja i drejtohet gjithnjë kontejnerit mbi
   elementin që stilohet, pra një `.stat-card {…}` këtu s'do të zbatohej kurrë.

   DHE rri POSHTË tyre, jo mbi. `@container` nuk shton asnjë pikë specifikiteti:
   `.stat-icon` brenda tij dhe `.stat-icon` jashtë peshojnë njësoj, pra fiton ai
   që vjen i fundit. I shkruar mbi to — ashtu si ishte fillimisht — blloku ishte
   i saktë, i vlefshëm, i lexueshëm, dhe nuk bënte asgjë: kartela ngushtohej deri
   në 190px dhe ikona mbetej 42px. Matja e gjeti; leximi jo. */
@container stat (max-width: 13rem) {
  .stat-icon { width: 34px; height: 34px; border-radius: var(--radius); font-size: var(--text-md); }
  .stat-value { font-size: var(--text-xl); }
  .stat-label { font-size: var(--text-2xs); letter-spacing: .05em; }
}

.stat-note { font-size: var(--text-xs); color: var(--faint); margin-top: var(--space-0); }

/* Njësia nuk është shifër. «12,400.00 €» me euron në të njëjtën peshë e lartësi
   me shifrën jep pesë karaktere të mëdha që njeriu i lexon të parat dhe nuk i
   duhen: ai e di se zyra punon me euro. Shenja rri, se pa të nuk dihet se numri
   është para, por rri një hap prapa — më e vogël, më e zbehtë, pa `tabular-nums`
   (një simbol i vetëm nuk ka kolonë me kë të radhitet, dhe gjerësia e tabelës do
   t'i lëshonte një bosh të kotë përpara). */
.stat-value .stat-unit {
  font-size: .62em;
  font-weight: 600;
  color: var(--muted);
  margin-left: .18em;
  letter-spacing: 0;
  font-variant-numeric: normal;
}

/* Rreshti i fundit i një pllake: ku shpie, jo një buton.
   Aty rrinin gjashtë `btn btn-outline-primary w-100` brenda gjashtë pllakave, dhe
   secila pllakë ishte tashmë vetë lidhje — pra kartela premtonte dy klikime kur
   kishte një, dhe rreshti i shifrave lexohej si një shirit butonash blu ku syri
   nuk e gjente më shifrën. Tani është një prag i qetë: vija, etiketa, shigjeta;
   ngjyrën e merr kur miu bie mbi kartelë, pra kur premtimi vlen. */
.stat-go {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  width: 100%;
  margin-top: var(--space-3);
  padding: var(--space-2) 0 0;
  border: 0;
  border-top: 1px solid var(--border);
  background: none;
  font: inherit;
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--muted);
  text-align: left;
  cursor: pointer;
  transition: color var(--dur-2) var(--ease-out);
}
.stat-go .stat-go-icon { font-size: 1.05em; transition: transform var(--dur-2) var(--ease-spring); }
/* Te pllakat e njerëzve ky rresht është `<button>`, pra e merr fokusin i vetëm:
   ngjyra e vetme është shumë pak për të thënë «ky është elementi i fokusuar», dhe
   te një kartelë që ndriçon nën mi ajo ngjyrë lexohet si hover, jo si fokus. */
.stat-go:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}
.stat-card:hover .stat-go,
.stat-card:focus-visible .stat-go,
.stat-go:hover,
.stat-go:focus-visible { color: var(--primary); }
.stat-card:hover .stat-go .stat-go-icon { transform: translateX(3px); }
/* Butoni që hap listën nën pllakën: shigjeta e tij tregon poshtë dhe kthehet kur
   lista është hapur, pra kandili e thotë gjendjen dhe teksti s'ka nevojë ta thotë
   dy herë. Nuk shtyhet anash në hover — ai nuk shpie gjëkundi, hap. */
.stat-go[aria-expanded] .stat-go-icon { transform: none; }
.stat-card:hover .stat-go[aria-expanded] .stat-go-icon { transform: none; }
.stat-go[aria-expanded="true"] { color: var(--primary); }
.stat-go[aria-expanded="true"] .stat-go-icon,
.stat-card:hover .stat-go[aria-expanded="true"] .stat-go-icon { transform: rotate(180deg); }

.stat-delta { font-size: var(--text-xs); font-weight: 700; display: inline-flex; align-items: center; gap: var(--space-1); }
.stat-delta.up { color: var(--success); }
.stat-delta.down { color: var(--danger); }

/* Tiny inline sparkline (hand-rolled SVG, no chart library — the CSP allows
   nothing new, and nothing new is needed). */
.stat-spark { display: block; width: 100%; height: 34px; margin-top: var(--space-2); }
.stat-spark polyline { fill: none; stroke: var(--primary); stroke-width: 2; }
.stat-spark .spark-fill { fill: var(--primary-soft); stroke: none; }

/* Live invoice calculator strip: net + VAT = gross, recomputed as you type. */
.invoice-calc {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  gap: var(--space-2) var(--space-4);
  padding: var(--space-3) var(--space-4);
  border: 1px dashed var(--primary-line);
  border-radius: var(--radius-lg);
  background: var(--primary-soft);
}
.invoice-calc .calc-item { display: flex; flex-direction: column; gap: var(--space-0); min-width: 6.5rem; }
.invoice-calc .calc-label {
  font-size: var(--text-xs); font-weight: 600; text-transform: uppercase;
  letter-spacing: .06em; color: var(--muted);
}
.invoice-calc .calc-num {
  font-family: 'Sora Variable', 'Inter Variable', Inter, sans-serif;
  font-size: var(--text-lg); font-weight: 700; letter-spacing: -.01em;
}
.invoice-calc .calc-op { display: flex; align-items: center; font-size: var(--text-lg); font-weight: 700; color: var(--muted); }
.invoice-calc .calc-total .calc-num { color: var(--primary); }

/* `.summary-card` iku bashkë me kutinë e vetme që e mbante — «Team pulse», e cila
   u bë shirit dhe merr tani `.card` si dymbëdhjetë vëllezërit e vet. Katër rregulla
   pa asnjë element: një `.icon` me gradient që s'e vinte kush, dhe një hover që
   ngrinte një kuti që s'ekziston. `.collapse-card` mbetet — pllakat e njerëzve e
   mbajnë. */
.collapse-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); }
.collapse-card:focus-visible { outline: none; box-shadow: var(--ring); }

.action-card { background: var(--surface); border: 1px solid var(--primary-line); }
.action-card .list-group-item {
  border-radius: var(--radius);
  margin-bottom: var(--space-2);
  background: transparent;
  color: var(--text);
  border-color: var(--border);
}
.action-card .list-group-item:last-child { margin-bottom: 0; }
.action-card .list-group-item-action { transition: background var(--dur-2) var(--ease-out), color var(--dur-2) var(--ease-out), transform var(--dur-2) var(--ease-out); }
.action-card .list-group-item-action:hover {
  background: var(--primary-soft);
  color: var(--text);
  transform: translateX(2px);
}

/* --- Tables ----------------------------------------------------------------- */
.table { color: var(--text); --bs-table-bg: transparent; --bs-table-color: var(--text); }
.table > :not(caption) > * > * {
  background-color: transparent;
  border-bottom-color: var(--border);
  color: inherit;
}
.table thead th {
  color: var(--muted);
  font-weight: 600;
  font-size: var(--text-xs);
  letter-spacing: .05em;
  text-transform: uppercase;
  border-bottom: 1px solid var(--border-strong);
  white-space: nowrap;
}
.table-sm th, .table-sm td { padding: var(--space-3); }
.table-hover tbody tr { transition: background var(--dur-1) var(--ease-out); }
.table-hover tbody tr:hover > * { background-color: var(--surface-hover); }
.table-striped > tbody > tr:nth-of-type(odd) > * {
  --bs-table-accent-bg: var(--surface-muted);
  color: inherit;
}
/* Sfondi e hoqi `!important`-in: aty kundërshtari ishte Bootstrap-i
   (`.table > :not(caption) > * > *`, specifikë më e lartë se kjo), dhe shtresa
   e zgjidh atë tani.

   Ngjyra e tekstit jo, dhe arsyeja s'ka të bëjë fare me Bootstrap-in: `.table
   thead th` pak më lart është (0,1,2) kurse `.table-light th` është (0,1,1) —
   pra koka e kësaj tabele do të zbehej te `--muted` bashkë me çdo kokë tjetër.
   E provuar duke e hequr: teksti kaloi nga #101728 te #5a6a85. Kjo është luftë
   me veten, dhe asnjë shtresë nuk e zgjidh luftën e një skedari me vetveten. */
.table-light th, .table-light td, thead.table-light tr {
  background-color: var(--surface-muted);
  color: var(--text) !important;
}
.table-bordered th, .table-bordered td { border-color: var(--border); }

/* Contextual row highlights (e.g. a client with no documents gets .table-warning).
   Bootstrap sets a light bg + near-black text; the `.table > * > * { background:
   transparent; color: inherit }` rule above strips the bg but the text keeps
   inheriting Bootstrap's black — black-on-dark, unreadable in dark mode. Retint
   with the theme tokens so the row reads in both light and dark. */
.table > tbody > tr.table-warning > * { background-color: var(--warning-soft); color: var(--text); }
.table > tbody > tr.table-success > * { background-color: var(--success-soft); color: var(--text); }
.table > tbody > tr.table-danger  > * { background-color: var(--danger-soft);  color: var(--text); }

/* Rreshti i zgjedhur duket i zgjedhur. Te importi i bankës njeriu shënon dhjetë
   transaksione nga tridhjetë e pastaj shtyp «Importo» — deri tani e vetmja shenjë
   se cilat po shkonin ishte një kutizë 14px në buzë të majtë.
   Vetëm kutiza e qelizës së parë, ajo e zgjedhjes: matrica e lejeve te Qasjet ka
   një kutizë për çdo modul, dhe një rregull i përgjithshëm do ta linte të gjithë
   tabelën të ndezur sapo të lejohej diçka. */
.table > tbody > tr:has(> td:first-child input[type="checkbox"]:checked) > * {
  background-color: var(--primary-soft);
}

/* Card shell for a table: header with title + toolbar, body edge-to-edge. */
.table-card { overflow: hidden; }
.table-card .table { margin-bottom: 0; }
.table-card .table > :not(caption) > * > *:first-child { padding-left: var(--space-4); }
.table-card .table > :not(caption) > * > *:last-child { padding-right: var(--space-4); }
.table-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-3);
}

/* --- Tabela si kartela (telefon) --------------------------------------------
   Puna e zyrës rri te tabelat, dhe tabelat kanë tetë-dhjetë shtylla. Deri tani
   telefoni i jepte një dritare 360px dhe `.table-responsive` e zgjidhte të
   vetmen mënyrë që dinte: rrëshqitje anash. Pra për të parë borxhin e një
   klienti duhej tërhequr faqja djathtas, dhe emri i klientit — shtylla e parë —
   dilte nga ekrani pikërisht atëherë. Njeriu mbante me gisht rreshtin.

   Nën `md` çdo rresht bëhet kartelë: qeliza e parë është titulli, çdo qelizë
   tjetër është një çift «etiketë → vlerë», dhe koka e tabelës fshihet sepse
   tashmë e mban çdo qelizë me vete. Asnjë shabllon nuk u prek — etiketat i vë
   site.js duke lexuar `<thead>`, prandaj një tabelë e re nesër e ka këtë pa
   bërë asgjë. Klasa `.table-cards` vjen po nga ai skript, dhe vetëm te tabelat
   ku transformimi ka kuptim: pa kokë, me `colspan`, ose me shtylla që s'përputhen
   me kokën, rreshti nuk është një regjistrim dhe mbetet ashtu siç ishte.

   `767.98px` dhe jo një container query: një `container-type` do ta bënte kutinë
   bllok-përmbajtës për çdo pasardhës `position: fixed`, dhe nëpër qeliza rrinë
   modale. Pikërisht ai defekt ka qenë njëherë në prodhim (shih .app-content). */
@media (max-width: 767.98px) {
  .table-cards > thead { display: none; }
  .table-cards, .table-cards > tbody, .table-cards > tbody > tr,
  .table-cards > tbody > tr > td, .table-cards > tbody > tr > th { display: block; }
  .table-cards { width: 100%; }

  .table-cards > tbody > tr {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
    padding: var(--space-1) 0;
    margin-bottom: var(--space-2);
  }
  /* Rreshtat me ngjyrë statusi e mbajnë atë si buzë të majtë: një kartelë e
     tërë e larë me të verdhë është zhurmë, një vijë 3px është e njëjta gjë e
     thënë me zë të ulët. */
  .table-cards > tbody > tr.table-warning { border-left: 3px solid var(--warning); }
  .table-cards > tbody > tr.table-success { border-left: 3px solid var(--success); }
  .table-cards > tbody > tr.table-danger  { border-left: 3px solid var(--danger); }
  .table-cards > tbody > tr.table-warning > *,
  .table-cards > tbody > tr.table-success > *,
  .table-cards > tbody > tr.table-danger > *,
  .table-striped.table-cards > tbody > tr:nth-of-type(odd) > * {
    background-color: transparent;
  }

  .table-cards > tbody > tr > td {
    display: grid;
    grid-template-columns: minmax(5.5rem, 34%) 1fr;
    gap: var(--space-3);
    align-items: baseline;
    border: 0;
    padding: var(--space-1) var(--space-3);
    white-space: normal;
  }
  .table-cards > tbody > tr > td::before {
    content: attr(data-label);
    color: var(--faint);
    font-size: var(--text-2xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .05em;
    line-height: 1.5;
  }
  /* Qeliza pa etiketë — shtylla e veprimeve, ajo që te koka rri bosh — s'ka
     çfarë të prezantojë: zë gjithë gjerësinë dhe rri poshtë si fundi i kartelës. */
  .table-cards > tbody > tr > td:not([data-label]) {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
  }
  /* Qeliza e parë është titulli i kartelës, jo një fushë si të tjerat. */
  .table-cards > tbody > tr > td:first-child {
    display: block;
    font-weight: 600;
    font-size: var(--text-base);
    padding: var(--space-2) var(--space-3) var(--space-1);
  }
  .table-cards > tbody > tr > td:first-child::before { content: none; }
  .table-cards > tbody > tr > td:last-child { padding-bottom: var(--space-2); }

  /* …veç kur qeliza e parë mban vetëm një kutizë zgjedhjeje.
     Koka e asaj shtylle rri me qëllim pa tekst — pra site.js s'i vë `data-label`
     — dhe rregulli më lart e bënte titullin e kartelës një katror 14px, ndërsa
     emri i klientit binte poshtë si fushë e etiketuar si çdo tjetër. Tri tabela
     e bëjnë këtë: klientët, task-et, afatet.

     `:has()` e jo emrat e klasave: sot janë dy emra për të njëjtën gjë
     (`.tbl-pick`, `.dek-pick`) dhe një tabelë e katërt nesër do të sillte një të
     tretë. Rolin e përcakton përmbajtja — një kutizë dhe asgjë tjetër — pikërisht
     si etiketat, që lexohen nga `<thead>` e nuk shkruhen te shablloni.

     Kutiza shkon te qoshja, jo në rresht të vetin: në kartelë ajo është veprim
     mbi të tërën, jo fushë e saj. */
  .table-cards > tbody > tr:has(> td:first-child input[type="checkbox"]) {
    position: relative;
  }
  .table-cards > tbody > tr > td:first-child:has(input[type="checkbox"]) {
    position: absolute;
    inset-block-start: var(--space-2);
    inset-inline-end: var(--space-3);
    width: auto;
    padding: 0;
  }
  /* Titulli është qeliza pas saj. Të njëjtat vlera si `td:first-child` më lart,
     plus vendi i kutizës djathtas që një emër i gjatë të mos hyjë nën të. */
  .table-cards > tbody > tr > td:first-child:has(input[type="checkbox"]) + td {
    display: block;
    font-weight: 600;
    font-size: var(--text-base);
    padding: var(--space-2) calc(var(--space-3) + 1.75rem) var(--space-1) var(--space-3);
  }
  .table-cards > tbody > tr > td:first-child:has(input[type="checkbox"]) + td::before {
    content: none;
  }
  /* Rreshti bosh ose përmbledhës (colspan) s'është regjistrim — pa kuti, pa etiketa. */
  .table-cards > tbody > tr:has(> td[colspan]) {
    background: none;
    border: 0;
    box-shadow: none;
    padding: 0;
  }
  .table-cards > tbody > tr > td[colspan] { display: block; text-align: center; }
  .table-cards > tbody > tr > td[colspan]::before { content: none; }

  /* Te kartelat s'ka kokë për të ngjitur dhe as shtyllë të parë për të mbajtur
     në vend; dritarja me lartësi të kufizuar do të bënte një rrëshqitje brenda
     një rrëshqitjeje. */
  .table-responsive:has(> .table-cards) { overflow: visible; }
  .table-responsive.table-sticky:has(> .table-cards) { max-height: none; overflow: visible; }
  .table-cards > tbody > tr > td.sticky-col,
  .table-cards > tbody > tr > th.sticky-col { position: static; }
  /* Mbushja e kartelës e vendos vetë hapësirën anësore. */
  .table-card .table-cards > :not(caption) > * > *:first-child { padding-left: var(--space-3); }
  .table-card .table-cards > :not(caption) > * > *:last-child { padding-right: var(--space-3); }
}

/* --- Empty states ----------------------------------------------------------- */
.empty-state {
  text-align: center;
  padding: var(--space-6-5) var(--space-4);
  color: var(--muted);
}
.empty-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 62px;
  height: 62px;
  border-radius: var(--radius-lg);
  background: var(--primary-soft);
  color: var(--primary);
  font-size: var(--text-2xl);
  margin-bottom: var(--space-3);
  box-shadow: inset 0 0 0 var(--hairline) var(--primary-line);
}
.empty-title { font-weight: 600; color: var(--text); margin-bottom: var(--space-0); }
.empty-text { font-size: var(--text-sm); margin-bottom: var(--space-3); }

/* Hapi tjetër, jo vetëm lajmi.
   Kutia bosh ishte gjysma e mesazhit: «Nuk ka fatura për këtë filtër», «Ende
   nuk ka klientë. Krijo të parin me butonin lart». Faqja e dinte se çfarë
   duhej bërë dhe e tregonte me gisht drejt një butoni tjetër — në një telefon,
   shpesh jashtë ekranit. Vendi ku njeriu po shikon ËSHTË vendi ku duhet të rrijë
   veprimi.

   Dy butona më së shumti, dhe i pari është ai që e nis punën. Kutia bosh nuk
   është panel komandimi — është një pyetje me një përgjigje. */
.empty-action {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-2);
  margin-top: var(--space-1);
}

/* --- Activity timeline ------------------------------------------------------- */
.timeline { position: relative; padding-left: var(--space-5); }
.timeline::before {
  content: "";
  position: absolute;
  left: .35rem;
  top: .4rem;
  bottom: .4rem;
  width: 2px;
  border-radius: var(--radius-xs);
  background: linear-gradient(to bottom, var(--primary-line), transparent);
}
.timeline-item { position: relative; padding: var(--space-1-5) 0 var(--space-2); }
.timeline-item::before {
  content: "";
  position: absolute;
  left: -1.35rem;
  top: .62rem;
  width: .6rem;
  height: .6rem;
  border-radius: var(--radius-round);
  background: var(--surface);
  border: 2px solid var(--primary);
}
.timeline-time { font-size: var(--text-xs); color: var(--faint); }

/* --- Avatars ----------------------------------------------------------------- */
.avatar { width: 42px; height: 42px; border-radius: var(--radius-round); }
.avatar-initial {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: var(--radius);
  background: var(--grad-primary);
  color: #fff;
  font-weight: 700;
  font-size: var(--text-md);
  flex-shrink: 0;
}
/* Iniciali sa një çip: te karta e bordit emri i punëtorit duhet të njihet para
   se të lexohet, por 36px do të hanin gjysmën e kartës. */
.avatar-xs {
  width: 1.35rem;
  height: 1.35rem;
  border-radius: var(--radius-sm);
  font-size: var(--text-2xs);
}
.avatar-large {
  width: 72px;
  height: 72px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-lg);
  font-size: var(--text-2xl);
  font-weight: 700;
}
.bg-primary-soft { background: var(--primary-soft); }

.debt-paid { color: var(--success) !important; font-weight: 600; }
.debt-unpaid { color: var(--danger) !important; font-weight: 600; }
.file-input-hidden { display: none; }

/* --- Skeleton shimmer (for anything a page script fills in later) ----------- */
.skeleton {
  position: relative;
  overflow: hidden;
  background: var(--surface-muted);
  border-radius: var(--radius-sm);
  min-height: 1em;
}
.skeleton::after {
  content: "";
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, var(--surface-hover), transparent);
  animation: shimmer var(--beat) linear infinite;
}
@keyframes shimmer { to { transform: translateX(100%); } }

/* --- Auth pages (login / register / forced password change) ----------------- */
.auth-wrap {
  min-height: calc(100vh - var(--topbar-h) - 4rem);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-5) 0;
}
.auth-card {
  width: 100%;
  max-width: 960px;
  display: grid;
  grid-template-columns: 1.05fr 1fr;
  border-radius: var(--radius-xl);
  overflow: hidden;
  border: 1px solid var(--border);
  background: var(--surface);
  box-shadow: var(--shadow-lg);
}
.auth-visual {
  position: relative;
  padding: var(--space-6-5);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--space-4);
  color: #fff;
  background:
    radial-gradient(120% 90% at 85% 10%, rgba(34,211,238,.35), transparent 55%),
    linear-gradient(140deg, #4338ca 0%, #6d28d9 55%, #4f46e5 100%);
  overflow: hidden;
}
.auth-visual::after {
  /* Faint grid so the gradient has texture without an image request. */
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(255,255,255,.06) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.06) 1px, transparent 1px);
  background-size: 34px 34px;
  mask-image: radial-gradient(90% 80% at 50% 40%, #000 30%, transparent 100%);
  -webkit-mask-image: radial-gradient(90% 80% at 50% 40%, #000 30%, transparent 100%);
  pointer-events: none;
}
.auth-visual > * { position: relative; z-index: 1; }
.auth-visual h2 { color: #fff; }
.auth-visual p { color: rgba(255,255,255,.82); }
.auth-feature {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-size: var(--text-md);
  color: rgba(255,255,255,.9);
}
.auth-feature i {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: var(--radius-sm);
  background: rgba(255,255,255,.14);
  flex-shrink: 0;
}
.auth-form { padding: var(--space-6-5); }
/* Hapësira nën kokën e formës rri këtu e jo si `mb-4` te shablloni, që telefoni
   ta shkurtojë me një rregull të vetëm — pa luftuar një utility me !important. */
.auth-form-head { margin-bottom: var(--space-5); }

/* --- Fusha e hyrjes ---------------------------------------------------------
   Ikona brenda fushës e jo pranë etiketës. Dallimi nuk është zbukurim: etiketa
   lexohet një herë, kurse fusha shihet sa herë syri kthehet te forma — dhe një
   formë me dy fusha të njëjta pa asgjë brenda tyre është pikërisht ajo që të
   detyron ta rilexosh etiketën për të ditur ku po shkruan.

   RRJETË dhe jo pozicion absolut, dhe kjo është e vetmja hollësi që ka rëndësi
   këtu. `site.js` fut vetë poshtë çdo fushe fjalëkalimi rreshtin «Caps Lock
   është ndezur», brenda kësaj kutie. Me `position: absolute` dhe `top: 50%`,
   ikona qendërzohet mbi lartësinë e KUTISË — pra do të zbriste gjysmën e atij
   rreshti sapo ai të ndizej, dhe do të dilte nga fusha. Në rrjetë ikona dhe
   fusha ndajnë qelinë 1/1, paralajmërimi zë rreshtin e dytë, dhe ikona s'e di
   kurrë që ai ekziston.

   Qelia e fushës emërohet dy herë sepse `site.js` e mbështjell fjalëkalimin te
   `.pw-wrap` sapo faqja ngarkohet: para tij fëmija i drejtpërdrejtë është vetë
   fusha, pas tij mbështjellësi. Të dyja rrugët duhet të bien te e njëjta qeli,
   përndryshe fjalëkalimi kërcen një rresht poshtë në çastin që JS-ja mbërrin. */
.auth-input {
  display: grid;
  transition: transform var(--dur-2) var(--ease-out);
}
.auth-input > .form-control,
.auth-input > .pw-wrap { grid-area: 1 / 1; }
.auth-input > .caps-hint { grid-area: 2 / 1; }
.auth-input > .bi {
  grid-area: 1 / 1;
  align-self: center;
  justify-self: start;
  /* Mbi fushën, sepse në rrjetë piktohet i pari kush vjen i pari te dokumenti —
     dhe pa këtë rresht ikona do të rrinte poshtë sfondit të vet të fushës.
     `pointer-events: none` që klikimi mbi të ta zërë prapëseprapë fushën. */
  z-index: 1;
  pointer-events: none;
  margin-inline-start: var(--space-4);
  font-size: var(--text-lg);
  line-height: 1;
  color: var(--faint);
  transition: color var(--dur-1) var(--ease-out);
}
/* Vendi i ikonës, i shtuar te mbushja e fushës. Syri i fjalëkalimit e mban të
   vetin nga ana tjetër (`.pw-wrap > input`), dhe të dy nuk takohen. */
.auth-input .form-control {
  padding-inline-start: 2.75rem;
  border-radius: var(--radius);
}
/* Fokusi thotë tri gjëra njëherësh — unaza rreth fushës (nga `.form-control`),
   ikona dhe etiketa. Ngjyra e tekstit merret nga `--primary-text` e jo nga
   `--primary`: e para është roli «ngjyrë e markës kur je SHKRONJË», dhe vetëm
   ajo ndërron kah në temën e errët. */
.auth-field .form-label {
  font-weight: 600;
  transition: color var(--dur-1) var(--ease-out);
}
.auth-field:focus-within .form-label,
.auth-field:focus-within .auth-input > .bi { color: var(--primary-text); }
.auth-field:focus-within .auth-input { transform: translateY(-1px); }

/* --- Butoni i hyrjes --------------------------------------------------------
   Një valë drite që kalon nga e majta në të djathtë kur miu ndalon mbi të. Nuk
   është dritë e re mbi faqe: rri brenda vetë butonit (`overflow: hidden`), pra
   asgjë përreth nuk ndriçon dhe asnjë kontrast i matur nuk lëviz.

   `inline-flex` që rrotulluesi i `.is-busy` — një `::before` — të zërë vendin e
   vet si çdo fëmijë tjetër dhe të mos e shtyjë tekstin jashtë qendrës. */
.auth-submit {
  position: relative;
  overflow: hidden;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
}
.auth-submit > .bi { transition: transform var(--dur-2) var(--ease-out); }
.auth-submit:hover > .bi { transform: translateX(3px); }
.auth-submit::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(100deg, transparent 38%, rgba(255,255,255,.28) 50%,
                              transparent 62%);
  transform: translateX(-110%);
  transition: transform var(--dur-3) var(--ease-out);
}
.auth-submit:hover::after,
.auth-submit:focus-visible::after { transform: translateX(110%); }
@media (max-width: 900px) {
  .auth-card { grid-template-columns: 1fr; max-width: 460px; }
  .auth-visual { display: none; }
  .auth-form { padding: var(--space-6) var(--space-5); }
}

/* `.btn-outline-dark` and `.btn-outline-light` name a colour instead of a role,
   so they invert exactly wrong: the dark one is near-black text and border on a
   dark card, the light one is near-white on a white one. Bootstrap's own dark
   block does not lift them either — it keeps #212529.

   Eight pages use the dark one for buttons like «Dosja», «TVSH», «Pasqyra ime»,
   and every one of them means "a quiet neutral button", not "black". So that is
   what both now are, in whichever theme is on. Driven through Bootstrap's own
   --bs-btn-* variables, so hover, focus and active keep their behaviour. */
.btn-outline-dark,
.btn-outline-light {
  --bs-btn-color: var(--text);
  --bs-btn-border-color: var(--border-strong);
  --bs-btn-hover-color: var(--primary-contrast);
  --bs-btn-hover-bg: var(--text);
  --bs-btn-hover-border-color: var(--text);
  --bs-btn-active-color: var(--primary-contrast);
  --bs-btn-active-bg: var(--text);
  --bs-btn-active-border-color: var(--text);
  --bs-btn-disabled-color: var(--faint);
  --bs-btn-disabled-border-color: var(--border);
}

/* --- Qasjet e puntorëve: matrica e lejeve ---------------------------------- */

/* Hyrja/dalja e fundit, lart te faqja e Hyrjeve. Ora është ajo që lexohet e
   para, prandaj i jepet pesha e një shifre, jo e një etikete. */
.last-io-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  flex-shrink: 0;
  border-radius: var(--radius);
  font-size: var(--text-lg);
  /* Bardhë, jo --primary-contrast: ai është i errët në temën e errët, dhe të dy
     mbushjet këtu janë të ngopura e mesatarisht të errëta në të dyja temat —
     bojë e errët mbi to del 1.08:1. Kontrasti e kapi këtë sapo u shkrua. */
  color: #fff;
  background: var(--grad-primary);
}
/* Jeshilja ulur një hap nën `--success-fill`: e bardha mbi të jepte ~2.1:1, nën
   kufirin edhe për një glif të madh. Kështu qëndron mbi 3:1 në të dy skajet —
   prandaj kjo ikonë e vetme nis nga #047857, jo nga tokeni. */
.last-io-icon.in { background: linear-gradient(135deg, #047857, var(--success-fill-strong)); }
.last-io-time {
  font-family: 'Sora Variable', 'Inter Variable', Inter, sans-serif;
  font-weight: 800;
  font-size: var(--text-2xl);
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}

/* Hyrja dhe dalja e të njëjtit sesion, në një qelizë të vetme. Shigjeta majtas
   e mban rreshtin e dytë të lexueshëm si «dhe pastaj doli», jo si një orë e dytë
   pa lidhje; numrat rreshtohen sepse ora është ajo që krahasohet. */
.io-line {
  display: flex;
  align-items: center;
  gap: var(--space-1-5);
  font-variant-numeric: tabular-nums;
}
.io-line + .io-line { margin-top: var(--space-0); }
.io-line .io-in { color: var(--bs-success, var(--success-fill-strong)); }
.io-line .io-out { color: var(--muted, #6b7280); }
.io-line .io-check { color: var(--muted); }

/* Verifikimi i portës së dytë rri në të njëjtën listë — kush provon një
   kredencial ia vlen të shihet — por një hap më prapa, që të mos numërohet me sy
   si edhe një hyrje e të njëjtit njeri. Vetëm peshë, jo ngjyrë: një rresht i
   kuq apo i verdhë do të thoshte «diçka shkoi keq», dhe zakonisht s'ka shkuar. */
.io-check-row > td { opacity: .72; }
.io-check-row > td:first-child { box-shadow: inset var(--rail) 0 0 var(--border); }

/* --- Hyrjet: pyetja, sesioni i hapur, aktiviteti ---------------------------
   Faqja pyetet me adresën e vet (?q=, ?only=, ?user=, ?ip=), pra çdo ngushtim
   është një lidhje. Këto rregulla i bëjnë atë lidhje të dukshme si gjendje: çka
   është në fuqi, dhe si hiqet. */
.io-line .io-now { color: var(--success); }
.last-io-icon.now { background: linear-gradient(135deg, var(--primary), #7c3aed); }

.io-applied {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-1-5);
  min-height: 2rem;
}
.io-applied-label {
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--muted);
}
/* Shenja e filtrit është edhe butoni që e heq: iksi rri brenda saj, sepse
   «hiqe këtë» i takon pikërisht atij fjale, jo një butoni tjetër larg tij. */
.io-chip-clear { text-decoration: none; gap: var(--space-1); }
.io-chip-clear .bi-x-lg { font-size: var(--text-2xs); opacity: .7; }
.io-chip-clear:hover .bi-x-lg { opacity: 1; }

/* Kush është brenda tani: emrat si shenja, ora e hyrjes pas emrit. */
.io-inside { display: flex; flex-wrap: wrap; gap: var(--space-1); margin-top: var(--space-1); }
.io-inside .chip { text-decoration: none; }
.io-inside-since { font-variant-numeric: tabular-nums; opacity: .75; }

/* Aktiviteti: një shtyllë për orë ose për ditë, hyrjet poshtë dhe të refuzuarat
   mbi ato. E njëjta zgjedhje si te histogrami i historikut — pa bibliotekë
   grafiku për tridhjetë numra — por me dy tone, sepse pyetja e kësaj faqeje nuk
   është «sa ishin gjithsej», po «kur u refuzuan më shumë sesa hynë». */
.io-chart {
  display: flex;
  align-items: flex-end;
  gap: var(--space-0);
  height: 96px;
}
.io-chart-col {
  flex: 1 1 0;
  min-width: 0;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  border-radius: var(--radius-xs);
  transition: background var(--dur-2) var(--ease-out);
}
.io-chart-col:hover { background: var(--surface-muted); }
.io-chart-bar { display: block; width: 100%; border-radius: var(--radius-xs); }
/* Vetëm shtylla me përmbajtje merr lartësi minimale: një kovë bosh që dukej si
   një pikë do të thoshte «pati diçka» pikërisht kur nuk pati asgjë. */
.io-chart-bar.has { min-height: 3px; }
.io-bar-ok { background: var(--grad-primary); }
.io-bar-bad {
  background: linear-gradient(180deg, var(--danger-fill), var(--danger-fill-strong));
  border-radius: var(--radius-xs) var(--radius-xs) 0 0;
}
.io-chart-axis {
  display: flex;
  justify-content: space-between;
  gap: var(--space-2);
  margin-top: var(--space-2);
  font-size: var(--text-xs);
  color: var(--faint);
}
.io-legend { display: inline-flex; align-items: center; gap: var(--space-3); font-size: var(--text-xs); color: var(--muted); }
.io-legend-item { display: inline-flex; align-items: center; gap: var(--space-1); font-weight: 600; }
.io-dot { width: .6rem; height: .6rem; border-radius: var(--radius-xs); display: inline-block; }
.io-dot-ok { background: var(--grad-primary); }
.io-dot-bad { background: linear-gradient(180deg, var(--danger-fill), var(--danger-fill-strong)); }

/* Sinjalet e kësaj faqeje (`.io-signal*`, `.io-evidence*`) janë i njëjti
   komponent me «Ç'bie në sy» të historikut privat, prandaj deklaratat e tyre
   rrinë te ai bllok i vetëm dhe jo këtu. Këto poshtë janë vetëm ato që kjo faqe
   i ka të vetat. */

/* Kur asnjë sinjal nuk ka zë, faqja e thotë me fjalë. Një kuti e zbrazët nën
   katër zerot lexohet si «ende s'u llogarit». */
.io-signal-quiet {
  margin: var(--space-3) 0 0;
  font-size: var(--text-sm);
  color: var(--success);
  font-weight: 600;
}
.io-evidence-more {
  margin: var(--space-1-5) 0 0;
  font-size: var(--text-xs);
  color: var(--faint);
}

/* Ritmi i javës: shtatë rreshta ditësh mbi njëzet e katër shtylla orësh. Rrjetë
   e vetme, jo shtatë rreshta të veçantë — vetëm kështu shtylla e orës 09 rri
   mbi atë të së martës edhe kur emrat e ditëve kanë gjatësi të ndryshme. */
.io-heat-wrap { overflow-x: auto; padding-bottom: var(--space-1); }
.io-heat {
  display: grid;
  grid-template-columns: max-content repeat(24, minmax(13px, 1fr));
  gap: var(--space-0);
  align-items: center;
  /* Nën këtë gjerësi qelizat bëhen vija: në telefon rrjeta rrëshqet, nuk ngjishet. */
  min-width: 34rem;
}
.io-heat-hour {
  font-size: var(--text-2xs);
  color: var(--faint);
  font-variant-numeric: tabular-nums;
  line-height: 1;
  text-align: center;
}
.io-heat-day {
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--muted);
  padding-right: var(--space-2);
  text-align: right;
  white-space: nowrap;
}
/* Qeliza bosh mbetet e dukshme si vend, jo si mungesë: pa sfondin e qetë poshtë,
   një javë e lirë do të dukej sikur rrjeta s'u vizatua fare. */
.io-heat-cell {
  position: relative;
  height: 15px;
  border-radius: var(--radius-xs);
  background: var(--surface-muted);
  overflow: hidden;
}
.io-heat-cell::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--grad-primary);
  opacity: var(--io-heat, 0);
}
/* Aty ku dështimet marrin dorën nuk është zyra që punon — është dikush që s'po
   hyn dot, dhe ajo qelizë s'guxon ta ketë ngjyrën e punës. */
.io-heat-cell.is-sour::after {
  background: linear-gradient(180deg, var(--danger-fill), var(--danger-fill-strong));
}
.io-heat-scale { display: inline-flex; align-items: center; gap: var(--space-0); }
.io-legend .io-heat-cell { width: 12px; height: 12px; --io-heat: .8; }

/* Profili i një personi: tri kolona që bien njëra nën tjetrën vetë, pa pyetur
   dritaren — kutia mund të rrijë edhe brenda një rrjete më të ngushtë nesër. */
.io-profile {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: var(--space-4);
  align-items: start;
}
.io-profile .list-kv + .list-kv { border-top: 1px solid var(--border); }
.io-profile-title {
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--muted);
  margin-bottom: var(--space-1-5);
}
/* Njëzet e katër orët e vetë personit. Pa lartësi minimale: një orë ku ai nuk ka
   hyrë kurrë duhet të mbetet bosh, përndryshe ora tre e natës do të kishte
   gjithmonë një pikë nën vete. */
.io-hours {
  display: flex;
  align-items: flex-end;
  gap: var(--space-0);
  height: 54px;
}
.io-hours-col {
  flex: 1 1 0;
  min-width: 0;
  height: 100%;
  display: flex;
  align-items: flex-end;
  border-radius: var(--radius-xs);
  transition: background var(--dur-2) var(--ease-out);
}
.io-hours-col:hover { background: var(--surface-muted); }
.io-hours-bar {
  display: block;
  width: 100%;
  border-radius: var(--radius-xs);
  background: var(--grad-primary);
}
.io-hours-col.is-peak .io-hours-bar {
  background: linear-gradient(180deg, var(--warning-fill), var(--warning-fill-strong));
}

/* Krahasimi me periudhën paraardhëse. Aty ku drejtimi s'ka vlerë — hyrjet janë
   hyrje, as mirë as keq — shifra mbetet e qetë: një ngjyrë pa kuptim është
   zhurmë, dhe pas dhjetë të tillave ngjyra që ka kuptim nuk lexohet më. */
.stat-delta.flat { color: var(--muted); font-weight: 600; }

/* Kartela që është vetë filtri: te Hyrjet ajo është lidhje, sepse ngushtimi
   ndodh te serveri. Ngjyra e tekstit mbetet e kartelës — një kartelë e tërë e
   blertë dhe e nënvijuar do të lexohej si fjalë, jo si numër. */
a.stat-card { color: inherit; text-decoration: none; display: block; }
a.stat-card:hover { border-color: var(--primary-line); box-shadow: var(--shadow-md); }

/* Fjalëkalimi rri lart dhe mbetet aty. Faqja është e gjatë — një kartë për çdo
   puntor — dhe një buton ruajtjeje që humbet nga ekrani sapo nis puna është
   buton që kërkohet me lëvizje. Nën topbar-in (1030), kurrë mbi të. */
.acc-confirm {
  position: sticky;
  top: calc(var(--topbar-h) + .5rem);
  z-index: 15;
  border-color: var(--primary-line);
  box-shadow: var(--shadow-md);
}

.acc-card .acc-matrix th { font-size: var(--text-xs); color: var(--muted); font-weight: 600; }
.acc-card .acc-matrix td { padding-top: var(--space-1-5); padding-bottom: var(--space-1-5); }
/* Folja që nuk zbatohet për këtë modul: e dukshme si mungesë e qëllimshme, jo
   si kuti e harruar. */
.acc-na { color: var(--faint); user-select: none; }

.acc-sub-title {
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--faint);
  margin-bottom: var(--space-2);
}

.acc-days { display: flex; flex-wrap: wrap; gap: var(--space-1); }
.acc-day { margin: 0; cursor: pointer; }
.acc-day input { position: absolute; opacity: 0; width: 0; height: 0; }
.acc-day span {
  display: inline-block;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-pill);
  font-size: var(--text-xs);
  border: 1px solid var(--border-strong);
  color: var(--muted);
  transition: background var(--dur-2) var(--ease-out), color var(--dur-2) var(--ease-out), border-color var(--dur-2) var(--ease-out);
}
.acc-day input:checked + span {
  background: var(--primary);
  border-color: var(--primary);
  color: var(--primary-contrast);
}
.acc-day input:focus-visible + span { box-shadow: var(--ring); }

.acc-clients {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr));
  gap: var(--space-1) var(--space-3);
  max-height: 11rem;
  overflow-y: auto;
  padding: var(--space-1-5) var(--space-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-muted);
}
.acc-client {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
  font-size: var(--text-sm);
  cursor: pointer;
}
.acc-client small { display: block; font-size: var(--text-xs); }

/* Checkbox-et «zgjidh të gjitha»: kryesori te koka, njëri për rresht (modul)
   dhe njëri për kolonë (folje). Rri në një rresht me etiketën; te kolonat e
   ngushta kutia shkon mbi tekst. */
.acc-headcheck {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1-5);
  margin: 0;
  cursor: pointer;
}
.acc-headcheck-col { flex-direction: column; gap: var(--space-0); }
.acc-headcheck .form-check-input { margin: 0; float: none; flex-shrink: 0; }

/* Kartë me ndryshime të paruajtura: kufi i verdhë që paralajmëron pa bërtitur,
   që admini ta dijë se kjo pjesë pret ende fjalëkalimin për t'u ruajtur. */
.acc-card.acc-dirty {
  border-color: var(--warning);
  box-shadow: 0 0 0 var(--hairline) var(--warning), var(--shadow-md);
}
.acc-card.acc-dirty > .card-header { background: var(--warning-soft); }

/* Shiriti i sipërm: kërkimi, numëruesit dhe dy filtrat që e ngushtojnë faqen.
   Rri në të njëjtën kartë me fjalëkalimin, sepse të dyja janë «para se të
   nisësh»: gjeje njeriun, pastaj vuloseje ndryshimin. */
.acc-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-3);
  padding-bottom: var(--space-3);
  margin-bottom: var(--space-1);
  border-bottom: 1px solid var(--border);
}
.acc-bar-find {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex: 1 1 14rem;
  max-width: 22rem;
  color: var(--muted);
}
.acc-bar-chips { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-1-5); }

/* Kërkimi u nda nga forma e ruajtjes, që shfletuesi të mos e lexojë çiftin
   «tekst + fjalëkalim» si ekran hyrjeje dhe t'i mbushë vetë. Si kartë e vetja
   ai nuk ka më pse të mbajë vijën që e ndante nga fjalëkalimi poshtë. */
.acc-find .acc-bar { padding-bottom: 0; margin-bottom: 0; border-bottom: 0; }

/* Në telefon i njëjti shirit bie në katër rreshta, dhe i ngjitur ai do të hante
   gjysmën e ekranit — pra do të mbronte butonin e ruajtjes duke fshehur
   pikërisht kutizat që po ruhen. Atje rri me faqen. */
@media (max-width: 767.98px) {
  .acc-confirm { position: static; }
}

/* Chip që klikohet: e njëjta formë si shenjat pranë saj, sepse bën të njëjtën
   punë — thotë një numër — vetëm se ky numër e filtron faqen. */
.chip-button {
  cursor: pointer;
  font: inherit;
  font-size: var(--text-xs);
  transition: background var(--dur-2) var(--ease-out), color var(--dur-2) var(--ease-out);
}
.chip-button[aria-pressed="true"] { box-shadow: var(--ring); }

/* Numri mbi butonin e ruajtjes: sa karta do të shkojnë me këtë klikim. */
.acc-save-count {
  display: inline-block;
  min-width: 1.25rem;
  padding: 0 var(--space-1-5);
  margin-left: var(--space-1-5);
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, .25);
  font-size: var(--text-xs);
  font-weight: 700;
}

/* «Çka do të ruhet»: ndryshimi i mbledhur nga vetë kutizat, para se të niset. */
.acc-plan > summary {
  cursor: pointer;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--warning);
}
.acc-plan-body {
  margin-top: var(--space-2);
  max-height: 16rem;
  overflow-y: auto;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
  gap: var(--space-2);
}
.acc-plan-worker {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: var(--space-1-5) var(--space-2);
  background: var(--surface-muted);
}
.acc-plan-name {
  display: block;
  font-weight: 600;
  font-size: var(--text-sm);
  text-decoration: none;
  margin-bottom: var(--space-1);
}

/* Rreshtat e ndryshimit: shtimi, heqja dhe ajo që thjesht u zhvendos. Ngjyra
   vjen nga tokenat e statusit — e njëjta jeshile/kuqe si kudo tjetër. */
.acc-diff { display: grid; gap: var(--space-0); }
.acc-diff-line {
  font-size: var(--text-xs);
  padding-left: var(--space-4);
  position: relative;
  line-height: 1.5;
}
.acc-diff-line::before { position: absolute; left: 0; font-weight: 700; }
.acc-diff-up { color: var(--success); }
.acc-diff-up::before { content: '+'; }
.acc-diff-down { color: var(--danger); }
.acc-diff-down::before { content: '−'; }
.acc-diff-flat { color: var(--muted); }
.acc-diff-flat::before { content: '~'; }

/* Përmbledhja: një rresht për puntor, dhe emri që hap kartën e vet. */
.acc-overview .acc-ov-name { font-weight: 600; text-decoration: none; }
.acc-overview .acc-ov-sub { font-size: var(--text-2xs); }
.acc-ov-row.acc-dirty > td { background: var(--warning-soft); }
.acc-ov-row[data-tone="warning"] > td:first-child {
  box-shadow: inset var(--rail) 0 0 var(--warning);
}

/* Çka hap moduli, nën emrin e tij. Fjalia rri e heshtur derisa të kërkohet:
   e njëjta madhësi si te kutia bosh, jo si te teksti i rreshtit. */
.acc-hint {
  font-size: var(--text-2xs);
  color: var(--faint);
  max-width: 22rem;
  margin-top: var(--space-0);
  font-weight: 400;
}

.acc-client-tools {
  display: flex;
  align-items: center;
  gap: var(--space-1-5);
  margin-bottom: var(--space-1-5);
}
.acc-client-tools input { max-width: 14rem; }

/* Bizneset zgjidhen nga një listë që hapet, jo nga një kolonë e hapur
   përgjithmonë: me dhjetëra klientë ajo bëhej pjesa më e gjatë e kartës dhe
   shtynte matricën e lejeve jashtë ekranit. E mbyllur, kartela thotë sa janë
   zgjedhur; poshtë saj rrinë emrat, që zgjedhja të lexohet pa e hapur. */
.acc-picker-head { position: relative; }
.acc-picker-toggle {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  padding: var(--space-1-5) var(--space-3);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  font-size: var(--text-sm);
  text-align: left;
  cursor: pointer;
  list-style: none;                    /* trekëndëshi i `details` — e thotë shigjeta */
  transition: border-color var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease-out);
}
.acc-picker-toggle::-webkit-details-marker { display: none; }
.acc-picker-toggle:hover { border-color: var(--primary); }
.acc-picker-toggle:focus-visible { outline: none; box-shadow: var(--ring); }
.acc-picker-head[open] > .acc-picker-toggle { border-color: var(--primary); box-shadow: var(--ring); }
.acc-picker-text { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.acc-picker-caret { color: var(--muted); transition: transform var(--dur-2) var(--ease-out); }
.acc-picker-head[open] .acc-picker-caret { transform: rotate(180deg); }

.acc-picker-menu {
  position: absolute;
  z-index: 30;
  top: calc(100% + .3rem);
  left: 0;
  right: 0;
  padding: var(--space-2);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  box-shadow: var(--shadow-lg);
}
/* Brenda listës së hapur bizneset rrinë njëri nën tjetrin: dy kolona të ngushta
   do t'i ndanin emrat në mes, dhe emri është e vetmja gjë që kërkohet këtu. */
.acc-picker-menu .acc-clients {
  grid-template-columns: 1fr;
  max-height: 14rem;
  padding: var(--space-0);
  border: 0;
  background: transparent;
}
.acc-picker-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  margin-top: var(--space-1-5);
  padding-top: var(--space-1-5);
  border-top: 1px solid var(--border);
}

.acc-chosen {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
  margin-top: var(--space-2);
  max-height: 8rem;
  overflow-y: auto;
}
.acc-chosen-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-0) var(--space-2);
  border-radius: var(--radius-pill);
  border: 1px solid var(--border-strong);
  background: var(--surface-muted);
  color: var(--text);
  font-size: var(--text-xs);
  cursor: pointer;
  transition: border-color var(--dur-2) var(--ease-out), color var(--dur-2) var(--ease-out);
}
.acc-chosen-chip:hover { border-color: var(--danger); color: var(--danger); }
.acc-chosen-chip:focus-visible { outline: none; box-shadow: var(--ring); }
.acc-chosen-chip i { font-size: .9em; opacity: .7; }

/* Karta e palosur: mbetet koka me numrat, dhe asgjë tjetër. Kutizat brenda
   vazhdojnë të ekzistojnë — palosja fsheh nga sytë, s'heq nga forma. */
.acc-fold {
  border: 0;
  background: none;
  color: var(--muted);
  padding: 0 var(--space-1-5) 0 0;
  line-height: 1;
}
.acc-fold i { transition: transform var(--dur-2) var(--ease-out); display: inline-block; }
.acc-card.acc-folded .acc-body { display: none; }
.acc-card.acc-folded .acc-fold i { transform: rotate(-90deg); }
.acc-card.acc-folded > .card-footer { display: none; }

/* Historiku i shkurtër i kartës: pesë ndryshimet e fundit, të palosura. */
.acc-trail > summary { cursor: pointer; color: var(--muted); }
.acc-trail-list { list-style: none; padding-left: 0; margin: var(--space-1-5) 0 0; }
.acc-trail-list > li { padding: var(--space-0) 0; border-top: 1px dashed var(--border); }
.acc-trail-lines { color: var(--muted); font-size: var(--text-2xs); }

/* --- Analitika: eksport i personalizuar, drill-i i muajit, margjina --------- */

.export-sections {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  padding: var(--space-1-5) var(--space-3);
  border-radius: var(--radius);
  background: var(--surface-muted);
  border: 1px solid var(--border);
}
.export-sections-label {
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--faint);
}
.export-chk {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1-5);
  font-size: var(--text-sm);
  color: var(--text);
  cursor: pointer;
  margin: 0;
}
.export-chk i { color: var(--muted); margin-right: var(--space-1); }
.export-chk input:checked ~ span i { color: var(--primary-text); }

/* Muaji te matrica është lidhje: e dukshme si e tillë, me hinkën që thotë çka
   bën përpara se ta klikosh. */
.drill-month {
  color: var(--primary-text);
  text-decoration: none;
  font-weight: 600;
}
.drill-month:hover { text-decoration: underline; }
.drill-month i { font-size: .7em; opacity: .6; }

.drill-bar {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-lg);
  border: 1px solid var(--primary-line);
  background: var(--primary-soft);
}
.drill-bar-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: var(--radius-sm);
  flex-shrink: 0;
  color: var(--primary-contrast);
  background: var(--primary);
}
.drill-bar-main { display: flex; flex-direction: column; line-height: 1.35; }
.drill-bar-main span { font-size: var(--text-sm); }
.drill-bar .btn { margin-left: auto; }

/* Margjina: një rresht etiketash nën grafik, jo një bosht i dytë. */
.margin-strip {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(4.2rem, 1fr));
  gap: var(--space-1-5);
  margin-top: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px solid var(--border);
}
.margin-cell {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-0);
  text-align: center;
}
.margin-month { font-size: var(--text-xs); color: var(--faint); }
.margin-pct {
  font-size: var(--text-sm);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  display: inline-flex;
  align-items: center;
  gap: var(--space-0);
}
.margin-pct i { font-size: .7em; }
.margin-pct.pos  { color: var(--success); }
.margin-pct.neg  { color: var(--danger); }
.margin-pct.none { color: var(--faint); font-weight: 500; }

/* Printimi respekton kutizat: seksionet e pazgjedhura nuk dalin në PDF, por
   mbeten në ekran. Klasat vendosen mbi <body> nga skripti i faqes. */
@media print {
  body.hide-print-financat  [data-bipage="financat"],
  body.hide-print-arketimet [data-bipage="arketimet"],
  body.hide-print-puna      [data-bipage="puna"] { display: none !important; }
}

/* --- Dashboard: dokumentet e muajit dhe task-et e ekipit --------------------
   Mbushja e shtyllave nuk merret nga --primary. E kaluam nëpër validatorin e
   paletës kundër të dyja sipërfaqeve: #4f46e5 kalon çdo kontroll mbi të bardhën,
   kurse mbi karten e errët (#10182b) e vetmja nga tri kandidatet brenda brezit
   të ndriçimit (L 0.48–0.67) është #6366f1 — --primary i errët (0.68) dhe
   --primary-text (0.785) dalin të dyja jashtë. Prandaj token i vetin: mbushja e
   një shenje dhe ngjyra e një teksti kanë kërkesa të ndryshme, dhe pikërisht
   ngatërrimi i tyre është ajo që e bëri tekstin të padukshëm më parë. */
:root { --chart-bar: #4f46e5; }
body.theme-dark { --chart-bar: #6366f1; }

.chase-hero,
.tt-hero {
  font-family: 'Sora Variable', 'Inter Variable', Inter, sans-serif;
  font-weight: 800;
  font-size: var(--text-3xl);
  line-height: 1;
  letter-spacing: -.02em;
  color: var(--text);          /* teksti mban token teksti, kurrë ngjyrën e serisë */
}

/* Një shirit i vetëm, i ndarë sipas gjendjes. Boshllëku 2px mes pjesëve i mban
   të dallueshme edhe kur njëra është vetëm disa piksela e gjerë. */
.chase-bar {
  display: flex;
  gap: var(--space-0);
  height: 10px;
  margin: var(--space-3) 0;
  border-radius: var(--radius-pill);
  overflow: hidden;
  background: var(--surface-sunken);
}
.chase-bar > span { display: block; min-width: 3px; }
.chase-bar .is-sent    { background: var(--success); }
.chase-bar .is-late    { background: var(--danger); }
.chase-bar .is-chase   { background: var(--warning); }
.chase-bar .is-waiting { background: var(--border-strong); }

/* Gjendjet janë ngjyra statusi, prandaj shkojnë gjithnjë me ikonë dhe fjalë —
   kurrë vetëm me ngjyrë. */
.chase-key {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1-5) var(--space-4);
  font-size: var(--text-sm);
  color: var(--muted);
}
.chase-key span { display: inline-flex; align-items: center; gap: var(--space-1); }
.chase-key i { font-size: var(--text-sm); color: var(--success); }
.chase-key .is-late i    { color: var(--danger); }
.chase-key .is-chase i   { color: var(--warning); }
.chase-key .is-waiting i { color: var(--faint); }

/* --- Kurba e vogël nën një shifër ------------------------------------------
   SVG i shkruar te shablloni, jo bibliotekë: gjashtë pika s'kërkojnë njëqind
   kilobajt, dhe kështu kurba del edhe me JavaScript-in e fikur edhe te PDF-ja e
   printuar. Kutia shtrihet pa ruajtur përpjesëtimin, prandaj vija mban
   `non-scaling-stroke` — përndryshe do të dilte e trashë horizontalisht dhe e
   hollë vertikalisht. */
.spark {
  display: block;
  height: 2.1rem;
  margin: var(--space-1-5) 0 var(--space-2);
}
.spark svg {
  width: 100%;
  height: 100%;
  display: block;
  overflow: visible;      /* pika e muajit të fundit rri buzë kutisë */
}
.spark-line {
  fill: none;
  stroke: var(--primary);
  stroke-width: 1.75;
  stroke-linejoin: round;
  stroke-linecap: round;
}
.spark-area { fill: var(--primary); opacity: .12; stroke: none; }
.spark-dot {
  stroke: var(--primary);
  stroke-width: 4.5;
  stroke-linecap: round;
}
.spark-success .spark-line, .spark-success .spark-dot { stroke: var(--success-fill); }
.spark-success .spark-area { fill: var(--success-fill); }
.spark-accent .spark-line, .spark-accent .spark-dot { stroke: var(--accent, var(--primary-2)); }
.spark-accent .spark-area { fill: var(--accent, var(--primary-2)); }

/* --- Vjetërsia e borxhit: një shirit i ndarë në katër grupmosha -------------
   Pllaka e borxheve nuk merr kurbë gjashtëmujore sepse baza s'mban fotografi
   historike të borxhit të hapur. Kjo është e vërteta e sotme, dhe thotë atë që
   kurba do të donte të thoshte: a po plaket ky borxh. */
.age-strip {
  display: flex;
  gap: var(--space-0);
  height: 8px;
  margin: var(--space-2) 0 var(--space-1-5);
  border-radius: var(--radius-pill);
  overflow: hidden;
  background: var(--surface-sunken);
}
.age-strip > span { display: block; min-width: 3px; }
.age-key {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-2);
  font-size: var(--text-xs);
  color: var(--muted);
  margin-bottom: var(--space-2);
}
.age-key-item { display: inline-flex; align-items: center; gap: var(--space-1); }
.age-key-item b { font-variant-numeric: tabular-nums; color: var(--text); font-weight: 600; }
.age-dot {
  width: .5rem;
  height: .5rem;
  border-radius: var(--radius-xs);
  display: inline-block;
}
/* Sa më i vjetër borxhi, aq më i nxehtë grupi — rendi i ngjyrave është vetë
   leximi: i freskët, po plaket, vonuar, i rrezikuar. */
.age-1 { background: var(--success-fill); }
.age-2 { background: var(--primary); }
.age-3 { background: var(--warning-fill); }
.age-4 { background: var(--danger-fill); }

/* Blloqet e fikura nga vetë njeriu para ekranit. */
.panel-off { display: none !important; }
.panel-prefs-menu { min-width: 15rem; }
.panel-prefs-item {
  display: flex;
  align-items: center;
  cursor: pointer;
  font-size: var(--text-sm);
}
.panel-prefs-item:active { color: inherit; }
.panel-prefs-count {
  display: inline-block;
  margin-left: var(--space-1-5);
  padding: 0 var(--space-1-5);
  border-radius: var(--radius-pill);
  background: var(--primary-soft);
  color: var(--primary-text);
  font-size: var(--text-xs);
  font-weight: 700;
}

.tt-total { display: flex; align-items: baseline; gap: var(--space-2); }

.tt-chart { display: flex; flex-direction: column; gap: var(--space-2); }
.tt-row {
  display: grid;
  grid-template-columns: minmax(5.5rem, 8rem) 1fr 2.2rem;
  align-items: center;
  gap: var(--space-2);
}
.tt-name {
  font-size: var(--text-sm);
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tt-track {
  position: relative;
  height: 10px;                /* shenjë e hollë: të dhënat, jo dekori */
  border-radius: var(--radius-pill);
  background: var(--surface-sunken);
  overflow: hidden;
}
.tt-fill {
  display: block;
  height: 100%;
  min-width: 2px;              /* një vlerë jo-zero nuk zhduket kurrë */
  background: var(--chart-bar);
  /* Fundi i të dhënave rrumbullakoset; fundi i ankoruar te boshti mbetet i
     drejtë, që syri ta lexojë ku nis matja. */
  border-radius: 0 var(--radius-xs) var(--radius-xs) 0;
  transition: width var(--dur-3) var(--ease-out);
}
.tt-value {
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  font-size: var(--text-sm);
  text-align: right;
  color: var(--text);
}

@media (max-width: 480px) {
  .tt-row { grid-template-columns: minmax(4.5rem, 6rem) 1fr 2rem; }
}

/* Faqja e gabimit (403 / 404 / 500). Numri është i madh dhe me gradientin e
   markës, që faqja të mos duket si një defekt i shfletuesit por si pjesë e
   sistemit — dikush që e sheh duhet ta kuptojë se është pritur, jo shpërthyer. */
.error-code {
  font-family: 'Sora Variable', 'Inter Variable', Inter, sans-serif;
  font-weight: 800;
  font-size: var(--display-lg);
  line-height: 1;
  letter-spacing: -.04em;
  background: var(--grad-primary-text);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* Edge draws its own reveal eye inside every password field. site.js already
   hangs our own eye on every one of them, so the native control is always a
   second eye next to ours — off everywhere, not per field. */
input[type="password"]::-ms-reveal,
input[type="password"]::-ms-clear { display: none; width: 0; height: 0; }

/* --- Login hero -------------------------------------------------------------
   The login screen is the one page every single person sees — client, worker,
   manager, admin — so it carries a richer version of the auth panel: a drifting
   aurora, the brand block, what the office actually runs here, and the security
   promise. The other auth pages (register, reset, 2FA) keep the plain
   .auth-visual, so this is opt-in via .auth-hero and changes nothing there.

   Ky panel u pikturua dikur krejt me gradientë, pa asnjë kërkesë figure. Tani
   poshtë tyre rri një skenë — tavolina e kontabilitetit — dhe ajo është e vetmja
   figurë e kësaj faqeje: një SVG i vetëm nga `/static/img/`, pa host të jashtëm
   dhe pa raster, që shkallëzohet njësoj te një telefon dhe te një ekran 4K. */
/* Skena nuk mbetet brenda panelit: e njëjta fotografi mban gjithë zonën e
   hyrjes, dhe kartela noton mbi të.

   Rri si sfond i vetë `.app-content` e jo si shtresë e pozicionuar mbi faqe, dhe
   arsyeja është një gabim që kjo rrugë e shmang: sfondi i një elementi bie
   vetvetiu nën ÇDO fëmijë të tij — edhe nën flash-in «Fjalëkalimi është gabim»,
   që rrjedh pa pozicion pak mbi kartelë. Një `::before` me `position: fixed`
   brenda `.auth-wrap` do t'i kishte mbuluar pikërisht ato njoftime, sepse bllokut
   në rrjedhë i vjen radha para çdo pasardhësi të pozicionuar.

   `:has(.auth-hero)` e mban këtë te e vetmja faqe që e kërkoi. Regjistrimi,
   rikthimi i fjalëkalimit dhe hapi i dytë i hyrjes ndajnë të njëjtin `.auth-wrap`
   por jo heroin — dhe ato mbeten saktësisht siç ishin.

   Mbi skenën rrinë dy shtresa errësimi: një gradient vertikal që e ul dritën nën
   kokë dhe e mbyll fundin, dhe një rreth që errësohet nga qendra drejt buzëve —
   pra pikërisht atje ku bien anët e kartelës, sfondi është më i errët dhe kufiri
   i saj lexohet pa pasur nevojë për vijë. Hija e brendshme lart është ajo që koka
   `sticky` hedh mbi skenën: pa të, shiriti i çelët dhe fotografia takoheshin me
   një prerje. */
.app-content:has(.auth-hero) {
  background:
    radial-gradient(118% 86% at 50% 44%, transparent 26%, rgba(4,6,22,.52) 100%),
    linear-gradient(180deg, rgba(4,6,22,.52) 0%, rgba(4,6,22,.14) 22%,
                    rgba(4,6,22,.12) 58%, rgba(4,6,22,.44) 100%),
    var(--login-scene) center / cover no-repeat,
    #0b0d26;
  box-shadow: inset 0 16px 30px -16px rgba(2,3,12,.9);
}
/* Në temën e errët faqja rreth kartelës është tashmë e errët dhe kartela vetë
   është e errët: skenës nuk i duhet më errësim, i duhet pak më shumë dritë, që
   `.auth-card` të mos zhytet brenda saj. */
body.theme-dark .app-content:has(.auth-hero) {
  background:
    radial-gradient(118% 86% at 50% 44%, transparent 24%, rgba(2,4,16,.74) 100%),
    linear-gradient(180deg, rgba(2,4,16,.56) 0%, rgba(2,4,16,.20) 20%,
                    rgba(2,4,16,.18) 58%, rgba(2,4,16,.56) 100%),
    var(--login-scene) center / cover no-repeat,
    #070a1e;
}
/* Mbi një skenë të errët hija është e vetmja gjë që e ngre kartelën nga sfondi,
   dhe ajo e paracaktuar (`--shadow-lg`) u mat për një faqe të çelët. Rri këtu e
   jo te një selektor me `:has()`, që blloku i 900px-it dhe ai i 576px-it — të
   dy me të njëjtën specifikë dhe më poshtë në skedar — ta mbivendosin me një
   deklaratë të vetme, siç bëjnë tashmë. */
.auth-card-hero {
  max-width: 1120px;
  grid-template-columns: 1.18fr 1fr;
  box-shadow: 0 46px 92px -30px rgba(2,3,12,.82), 0 10px 28px -14px rgba(2,3,12,.6);
  /* Vetëm që unaza e mëposhtme të ketë ku të kapet. Kartela mbetet rrjetë me dy
     shtylla; `relative` nuk lëviz asnjë piksel të saj. */
  position: relative;
}

/* Buza që kap dritën.
   Një kuti e madhe me kufi të njëtrajtshëm lexohet e sheshtë sado hije t'i vësh
   poshtë, sepse asgjë mbi buzë nuk ndryshon: e njëjta vijë, i njëjti ton, gjithë
   rrugës. Sende të vërteta nuk sillen ashtu — buza e tyre e ndez dritën aty ku
   ajo bie dhe e humb ku s'bie.

   Prandaj mbi kufirin e vjetër vjen një unazë prej një floku, e pikturuar me një
   gradient konik: një hark i ndritur dhe pjesa tjetër e tejdukshme. `--sheen`
   është këndi i atij harku, dhe e shkruan JavaScript-i i faqes nga pozicioni i
   miut. Pa të — pa mi, pa JS, pa lëvizje — mbetet `200deg`: shkëlqimi rri lart
   majtas, aty ku e presin sytë dritën në çdo ndërfaqe të kësaj bote.

   Ngjyrat janë të markës e jo të bardha me qëllim: kjo unazë kalon mbi TË DY
   panelet — të errëtin e heroit dhe të çeltin e formës — dhe e bardha do të
   zhdukej fare mbi të dytin.

   Maska është truku i vetëm këtu: dy shtresa të plota, njëra e prerë te kutia e
   përmbajtjes, dhe `exclude` lë vetëm unazën mes tyre. Pa të, gradienti do të
   mbulonte kartelën e tërë — prandaj i tërë blloku rri brenda një `@supports`.
   Një shfletues që s'e njeh, s'e vizaton fare; kufiri poshtë saj mbetet ai që
   ishte, dhe askush s'e vëren mungesën. */
@supports ((-webkit-mask-composite: xor) or (mask-composite: exclude)) {
  .auth-card-hero::after {
    content: "";
    position: absolute;
    inset: 0;
    /* Mbi të dy panelet: `.auth-visual > *` i ngre fëmijët e heroit te 1. */
    z-index: 2;
    border-radius: inherit;
    padding: var(--hairline);
    pointer-events: none;
    background: conic-gradient(from var(--sheen, 200deg),
                transparent 0deg,
                color-mix(in srgb, var(--primary) 62%, transparent) 46deg,
                color-mix(in srgb, var(--accent-fill) 58%, transparent) 92deg,
                transparent 170deg,
                transparent 360deg);
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    mask-composite: exclude;
  }
}

/* Qepja mes dy paneleve.
   Aty ku heroi i errët takon formën e çelët ka sot një prerje të thatë: dy
   sipërfaqe të ndryshme që fillojnë e mbarojnë te i njëjti piksel. Një hije e
   brendshme në buzën e majtë të formës e kthen atë prerje në një takim — paneli
   i errët duket sikur rri PARA saj dhe e hedh hijen mbi të, gjë që është
   pikërisht ajo çka syri pret nga dy sipërfaqe me kaq dritë të ndryshme.

   Ngjyra nga `color-mix` e jo si `rgba()` e shkruar me dorë: e njëjta rojë si
   kudo tjetër (`test_no_shadow_invents_a_colour_or_a_width`) — një hije nuk
   sjell ngjyrë të vetën, e merr nga tokeni dhe ndërron me temën bashkë me të.

   Larja në krye është e njëjta ngjyrë, dy shkallë më e zbehtë: paneli i formës
   është e vetmja sipërfaqe krejt e bardhë e kësaj faqeje, dhe një e bardhë e
   plotë pranë asaj skene lexohet si letër e prerë e ngjitur sipër. */
.auth-card-hero .auth-form {
  background-image: radial-gradient(120% 84% at 100% 0%, var(--primary-soft), transparent 62%);
  box-shadow: inset 16px 0 30px -30px color-mix(in srgb, var(--primary) 62%, transparent);
}
.auth-hero {
  padding: var(--space-6-5);
  gap: var(--space-4);
  justify-content: space-between;
  /* Poshtë rri fotografia e tavolinës; mbi të, i njëjti gradient marke si më
     parë — por tani gjysmë i tejdukshëm. Pra ai s'është më sfond: është shtresë
     ngjyrimi mbi një skenë, dhe kjo është e vetmja mënyrë që një fotografi të
     hyjë nën tekst pa e humbur panelin ngjyrën e vet.

     Ngjyrimi ndahet me qëllim në dy shtresa e jo në një. Errësimi (rreshti i
     tretë) e ul fotografinë; ngjyra e markës (i dyti) e ngjyros. Të bashkuara në
     një gradient të vetëm, çdo lëvizje e ngjyrës do të lëvizte edhe ndriçimin —
     dhe pikërisht ndriçimi është ai që mban ose thyen pragun e tekstit.

     Pozicioni `62%` nuk është shije: paneli është më i gjatë se i gjerë, pra
     `cover` e pret skenën majtas e djathtas (lartësia hyn e plotë, gjerësia jo),
     dhe pikërisht te 62% brenda kuadrit mbeten të tria gjërat që e thonë punën —
     kolonat e librit, vula dhe buza e makinës së llogaritjes. Te qendra, makina
     del jashtë.

     Matur mbi faqen e vërtetë me tekstin e fshehur — pra vetëm sipërfaqja, jo
     vetë shkronjat — dhe gjithnjë te piksela e 99-të nga 100, jo te mesatarja.
     Majtas gradienti i vjetër, djathtas skena me gjithçka mbi të njëherësh —
     fotografia, errësimi, ngjyra e markës, aurora te .55 dhe rozeta te .08:

       .hero-pill      .92   5.11 → 6.44
       .hero-word small .74  3.42 → 4.95    (te .68 dilte 4.45 — prandaj .74)

     Katër rreshta të tjerë u matën bashkë me këta dhe s'janë më: titulli, hyrja,
     pllakat dhe fundi i panelit dolën nga faqja kur ato fjalë kaluan te
     kryefaqja publike. Numrat e tyre rrinë te historia e git-it; matja mbetet e
     vlefshme për të dy rreshtat sipër, sepse shtresat poshtë tyre s'u prekën.
     Të katërt ishin nën 4.5 para se skena të hynte fare. Nuk u kërkua kjo,
     por as nuk u lanë ashtu: fotografia bëhej e mundur vetëm duke ulur aurorën,
     dhe pikërisht ajo ulje ua ktheu kontrastin. Prandaj asnjë nga këta numra nuk
     guxon të lëvizë pa u matur sërish — tri shtresa këtu ndikojnë njëra-tjetrën
     dhe asnjëra s'lexohet dot veç. */
  background:
    radial-gradient(120% 90% at 82% -5%, rgba(34,211,238,.15), transparent 55%),
    linear-gradient(155deg, rgba(49,46,129,.62) 0%, rgba(67,56,202,.50) 38%,
                    rgba(109,40,217,.44) 72%, rgba(124,58,237,.46) 100%),
    /* Errësimi u bë i peshuar nga lart kur fjalët dolën nga paneli. Ai ishte i
       njëtrajtshëm sepse tekst kishte kudo: titulli në mes, pllakat poshtë tij,
       fundi te buza. Sot mbi këtë sipërfaqe rrinë vetëm dy rreshta — emri i
       zyrës dhe ora — dhe të dy brenda 12% të parë të lartësisë. Vetëm aty ka
       çfarë të mbrohet; poshtë tyre errësimi hapet dhe tavolina del më në fund
       ashtu siç është vizatuar.
       Matur mbi faqen e vërtetë, si të gjitha shifrat e këtij paneli: brezi ku
       bien ata dy rreshta rri te L=.0983 para dhe L=.0984 pas — pra ndryshimi
       për tekstin është zero, dhe gjithë hapja bie aty ku s'ka fjalë. Mesi i
       panelit shkon .1162 → .1632, fundi .0697 → .0812. */
    linear-gradient(180deg, rgba(6,8,28,.70) 0%, rgba(6,8,28,.62) 22%,
                    rgba(6,8,28,.36) 60%, rgba(6,8,28,.44) 100%),
    var(--login-scene) 62% center / cover no-repeat,
    #241f5e;
}

/* Mbi skenën, poshtë aurorës: një rozetë guilloche — gdhendja e imët e shtypit
   të vlerës, ajo e pasaportës dhe e çekut. Rri gjysma jashtë buzës së djathtë,
   dhe maska e shuan para se të arrijë te teksti.

   Detyra e saj ndryshoi. Kur poshtë kishte vetëm një gradient, kjo ishte e vetmja
   formë e pavizatuar prej tij dhe mbi të mbahej gjithë thellësia e panelit —
   prandaj rrinte te .16, dhe prandaj komenti i vjetër këtu numëronte rresht për
   rresht sa kontrast i hiqte çdo teksti. Tani poshtë rri një fotografi, dhe
   thellësinë e jep ajo. Mbi një fotografi një rrjetë vijash të bardha te .16 nuk
   lexohet më si gdhendje: lexohet si gërvishtje mbi pamje, dhe ndriçon pikërisht
   ballin e panelit ku bie `.hero-word small`.

   .08 e lë modelin të dukshëm aty ku e kap drita dhe e heq nga rruga kudo tjetër.
   Matjet që qeverisin tani nuk janë këtu — janë te `.auth-hero` më lart, ku të
   gjashtë rreshtat e panelit u matën bashkë, me tekstin e fshehur dhe me këtë
   shtresë në vend. Kjo është arsyeja pse ato numra janë të vetmit: një shtresë e
   matur veç nuk thotë asgjë kur mbi të njëjtin piksel bien katër.

   Aurora sipër mban `filter: blur()`, pra grupi i saj i përzierjes është i
   izoluar: `mix-blend-mode: screen` i blob-eve nuk e ndriçon dot këtë shtresë.

   Pa animacion me qëllim — një gdhendje nuk lëviz. Prandaj `prefers-reduced-motion`
   s'ka çfarë të heqë këtu, dhe s'i shkruhet asnjë degë. */
.hero-guilloche {
  position: absolute;
  top: 50%;
  right: -34%;
  width: 108%;
  aspect-ratio: 1;
  transform: translateY(-50%);
  z-index: 0;               /* si .hero-aurora — .auth-visual > * i ngre te 1 */
  background: url('../img/guilloche.svg') center / contain no-repeat;
  opacity: .08;
  pointer-events: none;
  -webkit-mask-image: radial-gradient(64% 64% at 88% 34%, black 24%, transparent 76%);
  mask-image: radial-gradient(64% 64% at 88% 34%, black 24%, transparent 76%);
}
/* Në kontrastin e lartë të Windows-it sfondi bëhet `Canvas` dhe teksti
   `CanvasText`: gradienti nën këtë shtresë zhduket, dhe mbi një sipërfaqe të
   sheshtë një rrjetë vijash të bardha nuk është më dekor, është zhurmë mbi
   fjalë. Dekori dekorativ bie i pari në atë regjim. */
@media (forced-colors: active) {
  .hero-guilloche { display: none; }
  /* `forced-colors` i zëvendëson ngjyrat, por NUK i heq figurat e sfondit: pa
     këto dy rreshta skena do të mbetej e paprekur nën tekstin e sistemit, dhe
     mbi të askush s'e ka premtuar dot kontrastin — pikërisht ata njerëz e kanë
     ndezur këtë regjim që të mos varen nga një sipërfaqe e pikturuar. */
  .auth-hero { background-image: none; }
  .app-content:has(.auth-hero) { background: none; box-shadow: none; }
  /* Të tria për të njëjtën arsye si skena: janë figura sfondi, dhe regjimi i lë
     të paprekura. Unaza e kartelës do të mbetej e vetmja vijë me ngjyrë në një
     faqe që sapo i mori të gjitha ngjyrat nga sistemi; larja mbi formë dhe vala
     e butonit do të ishin dy njolla mbi tekstin e tij. */
  .auth-card-hero::after,
  .auth-submit::after { display: none; }
  .auth-card-hero .auth-form { background-image: none; box-shadow: none; }
}

/* Three blurred colour fields drifting behind the text. Blur + screen blending
   is what turns three flat circles into one moving light. */
.hero-aurora {
  position: absolute;
  inset: -25%;
  z-index: 0;               /* .auth-visual > * lifts children to 1 — sit under */
  filter: blur(52px);
  /* Ishte .8 kur poshtë saj rrinte vetëm një gradient dhe e gjithë thellësia e
     panelit varej prej saj. Tani poshtë rri një skenë e vërtetë, dhe aurora ka
     vetëm një punë: të lëvizë. Ulja nuk është zbukurim — `mix-blend-mode: screen`
     e blobit ciano është ndriçuesi më i fortë i ballit të panelit, dhe pikërisht
     aty bie `.hero-word small`. Matur me tekstin e fshehur, .8 e
     çonte sipërfaqen poshtë tyre te L=.166; .55 e ul te L=.135, pra i kthen ato
     dy rreshta mbi pragun 4.5:1 — të cilin gradienti i vjetër nuk e arrinte. */
  opacity: .55;
  pointer-events: none;
}
.hero-aurora span {
  position: absolute;
  display: block;
  border-radius: var(--radius-round);
  mix-blend-mode: screen;
  will-change: transform;
}
.hero-blob-1 {
  width: 58%; height: 58%; left: -8%; top: 4%;
  background: radial-gradient(circle, rgba(34,211,238,.80), transparent 66%);
  animation: heroDrift var(--drift-a) var(--ease-in-out) infinite;
}
.hero-blob-2 {
  width: 52%; height: 52%; right: -10%; top: 22%;
  background: radial-gradient(circle, rgba(168,85,247,.85), transparent 66%);
  animation: heroDrift var(--drift-b) var(--ease-in-out) infinite reverse;
}
.hero-blob-3 {
  width: 46%; height: 46%; left: 26%; bottom: -12%;
  background: radial-gradient(circle, rgba(56,189,248,.55), transparent 68%);
  animation: heroDrift var(--drift-c) var(--ease-in-out) infinite;
}
@keyframes heroDrift {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
  33%      { transform: translate3d(12%, -8%, 0) scale(1.12); }
  66%      { transform: translate3d(-9%, 9%, 0) scale(.92); }
}

/* Drita që e ndjek miun.
   Vetëm aurora, dhe pikërisht sepse ajo tashmë lëviz: `heroDrift` e zhvendos
   12% të një kutie që del 25% jashtë panelit në çdo anë, pra njëzet piksele
   pas kursorit janë brenda asaj që kjo sipërfaqe bën gjithë ditën. Gdhendja
   dhe skena rrinë të ngulura — arsyet te blloqet e tyre dhe te skripti i faqes.

   `transition` e bën lëvizjen të ngelet pas dorës: JavaScript-i shkruan
   pozicionin e ri në çdo kuadër, dhe kalimi e sjell panelin drejt tij me
   vonesën e vet. Pa të, aurora do të ngjitej pas kursorit si e ngjitur me
   ngjitës — dhe pikërisht ajo vonesë e vogël është ç'e bën një shtresë të duket
   e largët.

   `(hover: hover)` sepse te gishti nuk ka «ku rri kursori»; atje kjo shtresë
   mbetet saktësisht ajo që ishte. Kush ka kërkuar më pak lëvizje s'e merr as ai
   — skripti nuk niset fare, pra `--sway-*` s'ekziston dhe rezerva 0px vlen. */
@media (hover: hover) {
  .hero-aurora {
    transform: translate3d(var(--sway-x, 0px), var(--sway-y, 0px), 0);
    transition: transform var(--dur-3) var(--ease-out);
  }
}

.hero-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
}
.hero-brand { display: flex; align-items: center; gap: var(--space-3); }
/* Mbi gradientin e panelit, logoja mban ngjyrat e veta — pa pllakë xhami mbi të,
   që të mos dalin dy kuti njëra brenda tjetrës. Vetëm hija e mban të ngritur nga
   sfondi, dhe një unazë e hollë e bardhë e ndan nga vjollca poshtë saj. */
.auth-visual-brand { display: flex; align-items: center; gap: var(--space-3); margin-bottom: var(--space-1); }
.hero-mark, .auth-visual-mark {
  display: inline-flex;
  width: 46px;
  height: 46px;
  border-radius: var(--radius);
  box-shadow: 0 0 0 var(--hairline) rgba(255,255,255,.22), 0 10px 24px rgba(9,10,40,.34);
}
/* Pak më e madhe se te heroi: aty logon e shoqëron një kolonë e tërë përmbajtjeje,
   këtu ajo dhe emri janë e gjithë koka e panelit. */
.auth-visual-mark { width: 54px; height: 54px; border-radius: var(--radius-lg); flex-shrink: 0; }
.hero-word {
  display: flex;
  flex-direction: column;
  line-height: 1.15;
  color: #fff;
}
.hero-word strong { font-weight: 800; letter-spacing: .16em; font-size: var(--text-md); }
/* .74 e jo .68: ky është teksti më i vogël i panelit dhe rri pikërisht ku bie
   blobi ciano i aurorës — matur me tekstin e fshehur, te .68 ai dilte 4.45:1,
   pra pesë të qindtat e fundit nën pragun. Zgjidhja u mor te teksti e jo te
   skena: ngritja e shkronjës kushton asgjë, errësimi i mëtejshëm i sfondit do
   të kishte kushtuar pikërisht fotografinë. */
.hero-word small { color: rgba(255,255,255,.74); font-size: var(--text-xs); letter-spacing: .04em; }

.hero-pill {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-pill);
  font-size: var(--text-xs);
  font-weight: 600;
  color: rgba(255,255,255,.92);
  background: rgba(255,255,255,.12);
  border: 1px solid rgba(255,255,255,.22);
  white-space: nowrap;
}
.hero-dot {
  width: 7px;
  height: 7px;
  border-radius: var(--radius-round);
  background: #34d399;
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--live) 70%, transparent);
  animation: heroPulse var(--beat-slow) var(--ease-out) infinite;
}
@keyframes heroPulse {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--live) 65%, transparent); }
  70%  { box-shadow: 0 0 0 7px transparent; }
  100% { box-shadow: 0 0 0 0 transparent; }
}

/* Çasti, te fundi i panelit.
   `justify-content: space-between` te `.auth-hero` kishte vetëm një fëmijë prej
   kur fjalët e prezantimit shkuan te kryefaqja — pra «mes dy skajeve» nuk
   ndante asgjë, dhe dy të tretat e poshtme të panelit ishin skenë e zhveshur.
   Ky është skaji i dytë.

   Vendi nuk është shije, është ai i vetmi që e mban matjen e panelit në këmbë.
   Errësimi mbi skenë është i peshuar nga lart (shih `.auth-hero`), dhe numrat e
   matur atje thonë se sipërfaqja bie te L=.1632 në mes, te L=.0812 në fund —
   pra brezi ku ulen këta dy rreshta është më i ERRËTI i gjithë panelit, jo më i
   ndriçuari. Mbi të e bardha e plotë jep 8:1 dhe ajo e datës, te .88, rreth
   5.4:1; të dyja mbi pragun 4.5, dhe të dyja më lart se `.hero-word small`, që
   kaloi te .74 mbi një brez më të ndritshëm (L=.0983). Prandaj këtu nuk u mat
   asgjë e re: u zgjodh brezi që matja e kishte tashmë të mbuluar, dhe një bojë
   më e çelët se ajo që kaloi atje.

   `text-wrap: balance` sepse në anglisht «Good afternoon» thyhet në dy rreshta
   te ekranet e mesme, dhe një fjalë e vetme e varur poshtë një tjetre është
   pikërisht ajo që e bën një titull të duket i pakujdesur. */
.hero-say { max-width: 22ch; }
/* `.auth-visual p` (0,1,1) i jep çdo paragrafi të panelit `rgba(255,255,255,.82)`.
   Të dy këta janë paragrafë, pra emri i prindit duhet edhe këtu — një selektor
   me një klasë të vetme do të humbte pa u vënë re. */
.hero-say .hero-greet {
  margin: 0;
  font-size: var(--display-md);
  font-weight: 800;
  line-height: 1.04;
  letter-spacing: -.02em;
  color: #fff;
  text-wrap: balance;
}
.hero-say .hero-date {
  margin: var(--space-1-5) 0 0;
  font-size: var(--text-md);
  font-weight: 500;
  color: rgba(255,255,255,.88);
  font-variant-numeric: tabular-nums;
}

/* Below 900px the plain .auth-visual hides itself. The hero does not: a phone
   user should still land on a branded welcome — now just the brand block and the
   clock, which is all the panel carries since the words moved to the landing. */
@media (max-width: 900px) {
  /* Një shtyllë, dhe kjo duhet thënë pikërisht këtu. `.auth-card` e ka rregullin
     e vet të njëjtë te blloku 900px shumë më lart, por `.auth-card-hero` në
     rreshtin 1861 vjen PAS tij me të njëjtën specifikë — pra dy shtyllat e tij
     fitonin në çdo gjerësi, edhe në 375px. Rezultati ishte një hero 188px pranë
     një forme 160px: dy shirita ku çdo fjalë thyhej. */
  /* Hija e rëndë u mat kundër skenës së errët; këtu skena nuk është më aty, dhe
     mbi një faqe të çelët ajo do të dukej njollë nën kartelë. */
  .auth-card-hero { max-width: 460px; grid-template-columns: 1fr; box-shadow: var(--shadow-lg); }
  .auth-hero {
    display: flex;
    padding: var(--space-5);
    gap: var(--space-3);
  }
  /* Heroi këtu mblidhet në një shirit: marka dhe ora — dhe asgjë tjetër.
     Një rozetë sa dy herë gjerësia e tij nuk ka ku të rrijë pa hyrë nën fjalë,
     dhe maska që e mbante larg tekstit u ndërtua mbi një panel të gjatë, jo mbi
     këtë. Hiqet fare: më mirë pa gdhendje sesa me gdhendje mbi tekst. */
  .hero-guilloche { display: none; }
  /* Përshëndetja bie, data mbetet — dhe kjo është pikërisht ndarja që bën
     matja e palës më poshtë. Një fjalë e vetme te `--display-md` kushton mbi
     pesëdhjetë piksele lartësi te një ekran ku butoni «Hyr» mezi arrihet, dhe
     ajo nuk mban asnjë informacion: e thotë vetëm më ngrohtë atë që faqja e
     thotë tashmë. Data mban një — sa është ora — dhe kushton një rresht.
     Ajo rrinte këtu edhe dje, brenda pilulës; thjesht ndërroi vend. */
  .hero-greet { display: none; }
  .hero-say { max-width: none; }
  .hero-say .hero-date { font-size: var(--text-sm); }
  /* Në një shtyllë s'ka më buzë të majtë ku dy panelet të takohen: heroi rri
     MBI formën, dhe një hije anësore aty do të ishte një vijë pa shkak. */
  .auth-card-hero .auth-form { box-shadow: none; }
  /* Sfondi i faqes bie këtu, dhe jo për shije: nën 576px `.auth-card` bëhet e
     tejdukshme që koka të shkojë buzë më buzë (shih bllokun pasues), pra skena
     do të dilte pikërisht prapa fushës së fjalëkalimit. E ndalur një herë, te
     kufiri ku kartela ndërron sjellje. */
  .app-content:has(.auth-hero) { background: none; box-shadow: none; }
}

/* Telefoni. Kjo faqe hapet më shpesh se çdo tjetër dhe pikërisht nga pajisja ku
   shtypja është më e vështirë — prandaj matja që ka rëndësi nuk është sa e bukur
   duket lart, por a arrihet butoni «Hyr» pa u rrëshqitur. Në 375×667 stiva dilte
   rreth 990px: fjalëkalimi dhe butoni binin poshtë palës.

   Vendimi është të hiqen përsëritjet, jo përmbajtja. Në atë ekran shenja e KA
   GROUP-it shfaqej tri herë — te koka, te heroi, te forma. Mbetet nga një.
   Nënkryeja e formës bie po ashtu: kush e ka hapur faqen e hyrjes nuk ka nevojë
   t'i thuhet të vendosë kredencialet. (Premtimi i sigurisë dilte dikur dy herë,
   te fundi i panelit dhe te rreshti «Çdo hyrje regjistrohet»; i pari s'ekziston
   më — ato fjalë i thotë kryefaqja.) */
@media (max-width: 576px) {
  /* Kartela hiqet fare. Një kuti me buzë, cepa dhe hije që zë gjithë gjatësinë e
     ekranit lexohet si shirit — dhe sa më e gjatë të bëhet, aq më e ngushtë
     duket, sepse buzët anësore i japin syrit dy vija paralele përgjatë gjithë
     rrugës. Ekranet e hyrjes në telefon nuk janë kuti: koka shkon buzë më buzë
     dhe forma ulet drejt mbi faqen. */
  .auth-wrap { min-height: auto; padding: 0; display: block; }
  .auth-card-hero, .auth-card {
    max-width: none;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    background: transparent;
    /* Dalje nga hapësira anësore e `.app-content` (rreshti 565: 1rem .85rem 2rem),
       që heroi të prekë të dyja buzët e ekranit. `width: auto` është pjesa që
       s'duhet harruar: `.auth-card` mban `width: 100%`, dhe një gjerësi e ngulur
       nuk zgjerohet nga margjina negative — kartela thjesht zhvendosej majtas
       dhe linte 27px bosh vetëm në të djathtë. */
    width: auto;
    margin-inline: calc(var(--space-3) * -1);
  }
  /* Bashkë me kufirin bie edhe unaza që e ndriçonte: ajo ndjek `border-radius`-in
     e kartelës, dhe kur ai bëhet zero ajo s'është më buzë sendi — është një
     drejtkëndësh i ngjyrosur rreth gjysmës së ekranit. */
  .auth-card-hero::after { display: none; }
  /* Ngjitja te koka bëhet vetëm kur s'ka asgjë para: alarmi i certifikatës rri
     në rrjedhë pikërisht mbi këtë bllok, dhe një tërheqje prej 1rem do t'i hipte
     sipër. Kur ai është aty, hendeku prej 1rem mbetet — dhe kështu duhet. */
  .app-content > .auth-wrap:first-child .auth-card { margin-top: calc(var(--space-4) * -1); }

  /* Hapësira e poshtme e `.app-content` (2rem) bie këtu: pas kartelës nuk vjen
     asgjë, dhe ajo ishte e vetmja arsye pse ekrani më i vogël rrëshqiste. */
  .auth-wrap { margin-bottom: calc(var(--space-6) * -1); }

  .auth-hero { padding: var(--space-4); gap: var(--space-1-5); border-radius: 0; }
  .hero-word small { display: block; }
  /* Tri fusha ngjyrash të turbullta janë ripikturim i vazhdueshëm; në sipërfaqe
     kaq të vogël 38px duken njësoj si 52px dhe kushtojnë më pak baterie. */
  .hero-aurora { filter: blur(38px); }

  .auth-form { padding: var(--space-5) var(--space-4) var(--space-4); }
  .auth-form-head { margin-bottom: var(--space-4); }
  /* 1.75rem është madhësi kryeje për ekran të gjerë; në 375px ajo zë dy rreshta
     pa i shtuar asgjë kuptimit. */
  .auth-form-head h3 { font-size: var(--text-xl); }
  .auth-form-mark, .auth-form-sub { display: none; }
  .auth-form hr { margin: var(--space-3) 0; }

  /* Një lidhje teksti është caku më i vogël në faqe; në gisht duhet të jetë sa
     një buton, edhe kur shkronjat mbeten të vogla. */
  .auth-form a.small {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 0 var(--space-2);
  }
}

/* Legacy login classes so the old markup keeps working until it is migrated. */
.login-page { min-height: calc(100vh - 200px); }
.login-visual {
  background:
    radial-gradient(120% 90% at 85% 10%, rgba(34,211,238,.35), transparent 55%),
    linear-gradient(140deg, #4338ca, #6d28d9);
  border-top-left-radius: 1.5rem;
  border-bottom-left-radius: 1.5rem;
}
.login-visual h2, .login-visual p, .login-visual .badge { color: #fff; }
.login-card { border-radius: var(--radius-xl); overflow: hidden; background: var(--surface) !important; }

/* --- Hero (landing page) ----------------------------------------------------- */
.hero-section {
  position: relative;
  overflow: hidden;
  border: 1px solid var(--border);
  background:
    radial-gradient(90% 120% at 90% -10%, rgba(124,58,237,.14), transparent 60%),
    radial-gradient(80% 100% at 0% 110%, rgba(8,145,178,.10), transparent 55%),
    var(--surface);
}
body.theme-dark .hero-section {
  background:
    radial-gradient(90% 120% at 90% -10%, rgba(139,92,246,.2), transparent 60%),
    radial-gradient(80% 100% at 0% 110%, rgba(34,211,238,.12), transparent 55%),
    var(--surface);
}

/* ============================================================================
   Command palette (Ctrl/⌘+K)
   ========================================================================= */
.cmdk-backdrop {
  position: fixed;
  inset: 0;
  z-index: 4000;
  display: none;
  align-items: flex-start;
  justify-content: center;
  padding: 12vh var(--space-4) var(--space-4);
  background: rgba(5,8,18,.45);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}
.cmdk-backdrop.open { display: flex; }
.cmdk {
  width: 100%;
  /* 620 e jo 560: rreshti mban tani dy rreshta — emrin dhe atë që e dallon, NUI
     ose pronarin e dokumentit — dhe te 560 emrat e gjatë të bizneseve priteshin
     me tri pika pikërisht aty ku dallohen nga njëri-tjetri. */
  max-width: 620px;
  background: var(--surface-raised);
  backdrop-filter: blur(var(--glass-blur));
  -webkit-backdrop-filter: blur(var(--glass-blur));
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  animation: cmdkIn var(--dur-2) var(--ease-out) both;
}
@keyframes cmdkIn {
  from { opacity: 0; transform: translateY(-8px) scale(.985); }
  to   { opacity: 1; transform: none; }
}
.cmdk-input-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border);
  color: var(--muted);
}
.cmdk-input {
  flex: 1;
  border: 0;
  outline: none;
  background: transparent;
  color: var(--text);
  font-size: var(--text-base);
}
.cmdk-input::placeholder { color: var(--faint); }
/* Lupa dhe rrotulluesi e ndajnë të njëjtin vend: kur pyetja shkon te serveri
   ndërron ikona, jo rreshti — pra asgjë nuk lëviz nën gishtin që po shkruan. */
.cmdk-spinner { display: none; }
.cmdk-backdrop.is-searching .cmdk-glass { display: none; }
.cmdk-backdrop.is-searching .cmdk-spinner {
  display: inline-block;
  width: 1rem;
  height: 1rem;
  border: 2px solid var(--primary-line);
  border-top-color: var(--primary);
  border-radius: var(--radius-round);
  animation: cmdkSpin var(--spin) linear infinite;
}
@keyframes cmdkSpin { to { transform: rotate(360deg); } }

.cmdk-list { max-height: 52vh; overflow-y: auto; padding: var(--space-2); }
/* Titulli i grupit. Pa të, klientët, dokumentet, faqet dhe veprimet vinin si një
   listë e vetme ku asgjë s'thoshte ç'lloj gjëje ishte rreshti — dhe një emër
   klienti dhe një emër faqeje duken njësoj derisa dikush e hap të gabuarin. */
.cmdk-group {
  padding: var(--space-2) var(--space-3) var(--space-1);
  font-size: var(--text-2xs);
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--faint);
}
.cmdk-group:first-child { padding-top: var(--space-1); }
.cmdk-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  text-align: left;
  border: 0;
  background: transparent;
  color: var(--text);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius);
  font-size: var(--text-md);
  cursor: pointer;
  text-decoration: none;
}
.cmdk-item i { color: var(--faint); width: 1.3rem; text-align: center; flex-shrink: 0; }
.cmdk-item.active, .cmdk-item:hover {
  background: var(--primary-soft);
  color: var(--primary-text);
}
.cmdk-item.active i, .cmdk-item:hover i { color: inherit; }
/* Dy rreshta brenda një rreshti: emri, dhe poshtë tij ajo që e dallon njërin
   klient nga tjetri me të njëjtin emër — NUI-ja, qyteti, pronari i dokumentit. */
.cmdk-item-body { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.cmdk-item-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cmdk-item-sub {
  font-size: var(--text-xs);
  color: var(--faint);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cmdk-item.active .cmdk-item-sub, .cmdk-item:hover .cmdk-item-sub {
  color: color-mix(in srgb, var(--primary-text) 70%, transparent);
}
/* Shkronjat e gjetura. `<mark>` vjen me të verdhën e shfletuesit, e cila mbi një
   rresht të zgjedhur violet është e palexueshme — dhe në temën e errët është
   thjesht një bllok drite. */
.cmdk-item mark {
  background: transparent;
  color: var(--primary-text);
  font-weight: 700;
  padding: 0;
}
.cmdk-item.active mark, .cmdk-item:hover mark { color: inherit; text-decoration: underline; }
.cmdk-item-tag {
  flex-shrink: 0;
  font-size: var(--text-2xs);
  color: var(--faint);
  text-transform: uppercase;
  letter-spacing: .05em;
}
.cmdk-empty { padding: var(--space-5); text-align: center; color: var(--faint); font-size: var(--text-md); }
.cmdk-hint {
  display: flex;
  gap: var(--space-4);
  padding: var(--space-2) var(--space-4);
  border-top: 1px solid var(--border);
  color: var(--faint);
  font-size: var(--text-xs);
}

/* ============================================================================
   Fleta (sheet): një dialog i vetin, për përmbajtje që lexohet e mbyllet.
   Ndryshe nga një modal Bootstrap-i, ky nuk mban formë dhe nuk dërgon asgjë —
   prandaj s'ka nevojë as për JavaScript-in e tij, veç hapjes dhe mbylljes.
   ========================================================================= */
.sheet-backdrop {
  position: fixed;
  inset: 0;
  z-index: 4000;
  display: none;
  align-items: center;
  justify-content: center;
  padding: var(--space-4);
  background: rgba(5,8,18,.45);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}
.sheet-backdrop.open { display: flex; }
.sheet {
  width: 100%;
  max-width: 34rem;
  max-height: min(80vh, 42rem);
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  animation: cmdkIn var(--dur-2) var(--ease-out) both;
}
.sheet-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-4);
  border-bottom: 1px solid var(--border);
}
.sheet-title {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
  font-size: var(--text-lg);
  font-weight: 700;
}
.sheet-title i { color: var(--primary); }
.sheet-body { padding: var(--space-4); overflow-y: auto; }

.keys-group + .keys-group { margin-top: var(--space-5); }
.keys-group-title {
  font-size: var(--text-2xs);
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--faint);
  margin-bottom: var(--space-2);
}
/* Rrjet me dy shtylla: tastet djathtas-rreshtuar te e para, shpjegimi te e dyta.
   Me `dt`/`dd` në rrjedhë të lirë, çdo shkurtore do të fillonte në një vend
   tjetër horizontal — dhe një listë tastesh që s'rreshtohen nuk skanohet dot me
   sy, që është e vetmja gjë për të cilën ekziston kjo fletë. */
.keys-list {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-2) var(--space-4);
  align-items: baseline;
  margin: 0;
}
.keys-list dt { display: flex; gap: var(--space-1); align-items: center; justify-content: flex-end; }
.keys-list dd { margin: 0; color: var(--muted); font-size: var(--text-sm); }
.keys-foot {
  margin: var(--space-5) 0 0;
  padding-top: var(--space-3);
  border-top: 1px solid var(--border);
  color: var(--faint);
  font-size: var(--text-xs);
}
@media (max-width: 575.98px) {
  /* Në një ekran 360px dy shtylla e lënë shpjegimin në katër rreshta të ngushtë.
     Tasti kalon sipër fjalës, si te çdo listë tjetër e telefonit. */
  .keys-list { grid-template-columns: 1fr; gap: 0; }
  .keys-list dt { justify-content: flex-start; margin-top: var(--space-3); }
  .keys-list dd { margin-bottom: 0; }
}

/* --- Numrat e Alt-it te menyja ---------------------------------------------
   Dalin vetëm sa mbahet Alt-i shtypur. Një meny me nëntë numra të ndezur gjithë
   ditën është zhurmë për këdo që s'i përdor kurrë; e njëjta meny me numrat që
   shfaqen pikërisht kur i kërkon dora është një hartë. */
.nav-key {
  display: none;
  margin-left: auto;
  padding: 0 var(--space-1);
  min-width: 1.1rem;
  text-align: center;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-xs);
  background: var(--surface-muted);
  color: var(--muted);
  font-size: var(--text-2xs);
  font-weight: 700;
  line-height: 1.45;
}
body.alt-keys .app-sidebar .nav-link .nav-key { display: inline-block; }
/* Ylli i «Të mitë» rri po te fundi i rreshtit dhe del vetëm në hover; kur numrat
   janë ndezur, ata e kanë vendin. */
body.alt-keys .app-sidebar .nav-link .fav-star { display: none; }
/* Te shiriti i ngushtë mbetet vetëm ikona: një numër aty do të mbulonte atë. */
body.sidebar-mini .nav-key { display: none !important; }

/* --- Lidhja që bie ----------------------------------------------------------
   Poshtë-majtas: lart rrinë njoftimet e veprimeve, dhe kjo s'është përgjigje e
   asnjë veprimi — është gjendja e makinës. Mbi shiritin e poshtëm në telefon,
   që të mos e mbulojë asnjë nga katër dyert. */
.net-chip {
  position: fixed;
  left: var(--space-4);
  bottom: calc(var(--space-4) + var(--bottomnav-h));
  z-index: 3500;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-pill);
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-lg);
  color: var(--text);
  font-size: var(--text-sm);
  font-weight: 600;
  opacity: 0;
  transform: translateY(.5rem);
  pointer-events: none;
  transition: opacity var(--dur-2) var(--ease-out), transform var(--dur-2) var(--ease-out);
}
.net-chip.show { opacity: 1; transform: none; }
.net-chip.net-off { border-color: var(--danger); color: var(--danger); }
.net-chip.net-off i { color: var(--danger); }
.net-chip.net-on { border-color: var(--success); color: var(--success); }

/* Butoni i shkarkimit rri te shiriti i tabelës, pranë filtrit; ikona e tij nuk
   duhet të rritet me tekstin e butonit. */
.table-export { display: inline-flex; align-items: center; gap: var(--space-1); flex-shrink: 0; }

/* ============================================================================
   6. Feature surfaces (existing class names, restyled)
   ========================================================================= */

/* --- Task board ----------------------------------------------------------- */
.task-board {
  display: grid;
  /* auto-fit so the fourth column folds onto its own row instead of squeezing */
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  gap: var(--space-3);
  align-items: start;
}
/* Pesë kolona gri me pesë fjalë gri: «E re» dhe «E anuluar» dukeshin saktësisht
   njësoj, dhe gjendjen e mbante vetëm fjala. Vija sipër i jep secilës ngjyrën e
   çipit të vet — të njëjtën që mban rreshti te lista dhe koka te detaji — pra
   kolona njihet para se të lexohet. */
.task-col {
  --col-tone: var(--border-strong);
  background: var(--surface-sunken);
  border: 1px solid var(--border);
  border-top: 3px solid var(--col-tone);
  border-radius: var(--radius);
  padding: var(--space-3);
}
.task-col[data-status="created"] { --col-tone: var(--border-strong); }
.task-col[data-status="accepted"] { --col-tone: var(--primary); }
.task-col[data-status="completed"],
.task-col[data-status="finalized"] { --col-tone: var(--success); }
.task-col[data-status="cancelled"] { --col-tone: var(--faint); }
.task-col-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: var(--space-2);
  padding: 0 var(--space-0);
}
.task-col-title {
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--muted);
}
.task-col-count {
  background: var(--surface-hover);
  color: var(--muted);
  border-radius: var(--radius-pill);
  padding: var(--space-0) var(--space-2);
  font-size: var(--text-2xs);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
/* Numri i kolonës merr të njëjtin çift ngjyrash si çipi i asaj gjendjeje — jo
   vetë tonin e vijës: `--col-tone` është ngjyrë vije, dhe një vijë e lexueshme
   mbi sfond nuk është domosdo tekst i lexueshëm mbi të. Gjendjet pa çift
   (e re, e anuluar) mbeten të heshtura, siç janë. */
.task-col[data-status="accepted"] .task-col-count {
  background: var(--primary-soft);
  color: var(--primary-text);
}
body.theme-dark .task-col[data-status="accepted"] .task-col-count { color: var(--primary); }
.task-col[data-status="completed"] .task-col-count,
.task-col[data-status="finalized"] .task-col-count {
  background: var(--success-soft);
  color: var(--success);
}
/* Ora e planifikuar dhe vonesa e kolonës, poshtë titullit të saj: pesë task nga
   dy orë dhe pesë nga tetë e mbajnë të njëjtin numër te koka. */
.task-col-meta {
  display: flex;
  gap: var(--space-3);
  padding: 0 var(--space-0) var(--space-2);
  margin-top: calc(var(--space-1-5) * -1);
  font-size: var(--text-xs);
  color: var(--muted);
}
/* Butoni që e palos kolonën. Rri para titullit, i heshtur, dhe rrotullohet
   bashkë me gjendjen — shigjeta poshtë do të thotë e hapur. */
.task-col-fold {
  background: none;
  border: 0;
  padding: 0 var(--space-1) 0 0;
  line-height: 1;
  color: var(--faint);
  cursor: pointer;
}
.task-col-fold:hover { color: var(--text); }
.task-col-fold i { display: inline-block; transition: transform var(--dur-2) var(--ease-out); }
.task-col-head { gap: var(--space-1); }
.task-col-head .task-col-title { margin-right: auto; }
.task-col.is-folded { padding-bottom: var(--space-1-5); }
.task-col.is-folded .task-col-body,
.task-col.is-folded .task-col-meta { display: none; }
.task-col.is-folded .task-col-head { margin-bottom: 0; }
.task-col.is-folded .task-col-fold i { transform: rotate(-90deg); }

/* Pesë task-e dhe një derë. Kutia e zgjedhjes bën punën e butonit — pra hapja
   bëhet pa JS — dhe rri e padukshme, por e fokusueshme: `display:none` do ta
   hiqte nga rrjeshti i tastierës dhe «Shiko më shumë» do të mbetej vetëm për
   miun. Kartelat e fshehura fshihen vërtet, prandaj s'i lexon as lexuesi i
   ekranit; numri i plotë qëndron te koka e kolonës. */
.task-col-toggle {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  opacity: 0;
}
.task-col-toggle:not(:checked) ~ .task-col-body > .task-card.is-extra { display: none; }
.task-col-more {
  display: block;
  margin-top: var(--space-1-5);
  padding: var(--space-1) var(--space-2);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-sm);
  color: var(--muted);
  font-size: var(--text-xs);
  font-weight: 700;
  text-align: center;
  cursor: pointer;
}
.task-col-more:hover {
  color: var(--primary-text);
  border-color: var(--primary);
  background: var(--primary-soft);
}
.task-col-toggle:focus-visible ~ .task-col-more {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}
.task-col-toggle:not(:checked) ~ .task-col-more .more-close,
.task-col-toggle:checked ~ .task-col-more .more-open { display: none; }
/* Kolona e paluar i fsheh edhe kartelat edhe derën e tyre. */
.task-col.is-folded .task-col-more { display: none; }

/* Keep a short column droppable — otherwise an empty one has no target. */
/* Kolona e hapur skrollon brenda vetes, nuk e shtrin bordin. Pa këtë, një
   kolonë me tridhjetë task-e i shtynte katër kolonat e tjera aq poshtë sa nuk
   krahasoheshin më — dhe krahasimi është arsyeja pse bordi ka kolona. Kufiri
   prek vetëm atë që është hapur me «Shiko më shumë»: pesë karta s'e arrijnë. */
.task-col-body {
  min-height: 5rem;
  max-height: min(68vh, 44rem);
  overflow-y: auto;
  overscroll-behavior: contain;
  border-radius: var(--radius-sm);
  transition: background var(--dur-2) var(--ease-out);
  scrollbar-width: thin;
}
.task-col-body.drop-target {
  background: var(--primary-soft);
  outline: 2px dashed var(--primary);
  outline-offset: -2px;
}
/* Sapo nis tërheqja, të gjitha kolonat thonë se e presin — jo vetëm ajo mbi të
   cilën ndodhi të kalojë miu. `.drop-target` e vë JS-i te `dragover`, pra
   përgjigjja vjen pasi njeriu e ka gjetur vetë vendin; kjo e tregon vendin që në
   çastin e parë. Pyetja «a po tërhiqet diçka?» i bëhet vetë pemës, prandaj s'ka
   nevojë as për klasë të re te bordi, as për një dëgjues `dragstart` që ta heqë
   patjetër më vonë — një gjendje më pak që mund të mbetet e ngecur. */
.task-board:has(.task-card.dragging) .task-col-body {
  outline: 1px dashed var(--border-strong);
  outline-offset: -2px;
  border-radius: var(--radius-sm);
}
/* Kolona bosh është një vend ku bie punë, jo një gabim. Teksti gri i pjerrët
   lexohej si «këtu mungon diçka»; vija e ndërprerë thotë «këtu ka vend», dhe
   ndriçohet bashkë me të tjerat sapo një kartë ngrihet. */
.task-col-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);
  margin: 0;
  padding: var(--space-4) var(--space-1-5);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-sm);
  text-align: center;
  font-size: var(--text-xs);
  color: var(--faint);
}
.task-col-empty i { font-size: var(--text-lg); opacity: .55; }
.task-board:has(.task-card.dragging) .task-col-empty {
  border-color: var(--primary-line);
  color: var(--primary-text);
}

.task-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--border-strong);
  border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-3);
  margin-bottom: var(--space-2);
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--dur-2) var(--ease-out), transform var(--dur-2) var(--ease-out), opacity var(--dur-2) var(--ease-out), border-color var(--dur-2) var(--ease-out);
}
/* Only a card that can actually move offers to be grabbed. The worker's board
   is read-only, and a grab cursor there would promise something that is not
   on offer. */
.task-card[draggable="true"] { cursor: grab; }
.task-card[draggable="true"]:active { cursor: grabbing; }
.task-card:hover {
  box-shadow: var(--shadow-md);
  transform: translateY(-1px);
  border-color: var(--border-strong);
}
.task-card.dragging { opacity: .45; transform: rotate(1.5deg); }
.task-card.prio-high { border-left-color: var(--danger); }
.task-card.prio-medium { border-left-color: var(--warning); }
.task-card.prio-low { border-left-color: var(--primary); }
/* Past its deadline and not done: a clear red border, in both themes. */
.task-card.is-overdue {
  background: var(--danger-soft);
  border: 1px solid var(--danger);
  border-left: 3px solid var(--danger);
}
/* E finalizuar: kufi i gjelbër rreth e rrotull. Prioriteti e humb kuptimin pasi
   puna është mbyllur nga admini — prandaj merret edhe buza e majtë, ajo që deri
   këtu mbante ngjyrën e prioritetit.
   Dy selektorë sepse dy bordet e shkruajnë statusin në dy vende: te admini JS-ja
   e rifreskon `data-status` të vetë kartelës pas tërheqjes (pra ngjyra vjen pa
   ngarkuar faqen), kurse bordi i puntorit s'e ka fare atributin te kartela — aty
   statusin e di vetëm kolona. */
.task-card[data-status="finalized"],
.task-col[data-status="finalized"] .task-card {
  border: 1px solid var(--success);
  border-left: 3px solid var(--success);
}

.task-card.prio-cancelled,
.task-col[data-status="cancelled"] .task-card { opacity: .7; border-left-color: var(--faint); }
.task-col[data-status="cancelled"] .task-card-title {
  text-decoration: line-through;
  text-decoration-color: var(--faint);
}

.task-card-title {
  display: block;
  font-weight: 600;
  font-size: var(--text-sm);
  color: inherit;
  text-decoration: none;
  margin-bottom: var(--space-1-5);
}
.task-card-title:hover { color: var(--primary); text-decoration: underline; }

.task-card-meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-2);
  align-items: center;
  font-size: var(--text-xs);
  color: var(--muted);
}

/* --- Karta e bordit: tri nivele ----------------------------------------------
   Deri dje karta ishte një re prej tetë copëzash meta — punëtori, klienti,
   subjekti, institucioni, afati, orët, përsëritja, shënimet — të gjitha me të
   njëjtën peshë, madhësi dhe ngjyrë. Asgjë nuk dilte përpara, prandaj asgjë nuk
   lexohej me një sy, dhe pesë kolona bëheshin një mur teksti gri.

   Tani: titulli; kush e bën; dhe poshtë, kur bie. Afati është i vetmi element që
   merr ngjyrë — dhe vetëm kur ka kaluar. */
.task-card-who {
  display: flex;
  align-items: center;
  gap: var(--space-1-5);
  margin-bottom: var(--space-1);
  min-width: 0;
}
/* Te bordi i puntorit vendin e inicialit e zë klienti: një ikonë, jo një kuti
   me shkronjë — kutia do të premtonte një njeri. */
.task-card-who-icon { color: var(--muted); font-size: var(--text-xs); }
.task-card-name {
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Klienti rri pas punëtorit dhe një hap më poshtë në zë: kush e bën punën është
   pyetja e bordit, për kë e bën është konteksti. */
.task-card-client {
  font-size: var(--text-xs);
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
.task-card-client::before { content: "· "; }
.task-card-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-1) var(--space-2);
  font-size: var(--text-2xs);
  color: var(--muted);
}
.task-card-tag {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  min-width: 0;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Afati: numri me shifra tabelore, që dy karta njëra mbi tjetrën ta kenë datën
   në të njëjtën gjerësi. I kuq vetëm kur ka kaluar — një afat i ardhshëm nuk
   është lajm. */
.task-due {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-weight: 600;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.task-due.is-late {
  color: var(--danger);
  font-weight: 700;
}
/* Kualifikimet — subjekti, institucioni, përsëritja, shënimet — si shenja të
   heshtura në skaj. Emri i plotë rri te `title` dhe te teksti për lexuesin e
   ekranit: kush e do e merr, kush s'e do nuk e lexon katër herë për kartë. */
.task-card-flags {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  margin-left: auto;
  color: var(--faint);
}
.task-card-flag {
  display: inline-flex;
  align-items: center;
  gap: var(--space-0);
}
/* Zhvendosjet e një task-u: një grup, tri vende — karta e bordit, rreshti i
   tabelës dhe koka e faqes së detajit. Deri dje ishin tri blloqe të kopjuara te
   shabllonet, secili me tonin e vet të butonave. Markup-i rri te
   `templates/_task_bits.html`; këtu rri vetëm forma. */
.task-moves {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
}
.task-moves .btn { font-size: var(--text-2xs); padding: var(--space-0) var(--space-1-5); }
/* Te karta: një vijë e ndan punën nga veprimi mbi të. */
.task-moves-card {
  margin-top: var(--space-2);
  padding-top: var(--space-2);
  border-top: 1px dashed var(--border);
}
/* Te tabela: vetëm shenjat, në një rresht të vetëm djathtas. Pesë butona me
   tekst herë tridhjetë rreshta e kthenin shtyllën e fundit në mur, dhe muri e
   shtynte titullin — arsyen pse hapet faqja — jashtë ekranit. */
.task-moves-tight {
  flex-wrap: nowrap;
  justify-content: flex-end;
  gap: var(--space-1);
}
.task-moves-tight .btn { padding: var(--space-0) var(--space-1-5); line-height: 1; }
.task-moves-tight .btn i { font-size: var(--text-xs); }
/* Te karta shenjat nisin nga e majta, si gjithçka tjetër te ajo kuti, dhe rrinë
   të zbehta derisa karta merret nën mi ose me tastierë: janë veprim mbi punën,
   jo pjesë e saj, dhe pesë shenja me kontrast të plotë mbi çdo kartë e bëjnë
   bordin të duket si panel butonash. Pa mi — telefoni — rrinë gjithnjë të
   plota, sepse atje s'ka gjendje «nën mi». */
.task-moves-card {
  justify-content: flex-start;
  opacity: .5;
  transition: opacity var(--dur-2) var(--ease-out);
}
.task-card:hover .task-moves-card,
.task-card:focus-within .task-moves-card { opacity: 1; }
@media (hover: none) {
  .task-moves-card { opacity: 1; }
}

/* Minimalist checklist progress on the card. */
.task-progress {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-2);
}
.task-progress-track {
  flex: 1;
  height: 7px;
  background: var(--surface-muted);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  overflow: hidden;
}
.task-progress-fill {
  height: 100%;
  background: var(--grad-primary);
  border-radius: var(--radius-pill);
  transition: width var(--dur-3) var(--ease-out);
}
.task-progress-fill.done { background: linear-gradient(90deg,var(--success-fill-strong),var(--success-fill)); }
.task-progress-label {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--text-2xs);
  font-weight: 700;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.task-progress-label i { font-size: var(--text-xs); }
.task-progress.is-done .task-progress-label { color: var(--success); }
/* Brenda një qelize tabele shiriti nuk ka nevojë për hapësirën e kartës, dhe
   duhet një gjerësi të cilës t'i besojë syri: pa të, shtylla e përparimit do të
   ishte aq e gjerë sa e lë tabela atë rresht. */
.task-progress-cell {
  margin-top: 0;
  margin-bottom: var(--space-1);
  min-width: 5rem;
  max-width: 9rem;
}
/* Rrethanat e rreshtit — shënimet, skedarët — si shenja, si te karta. Aty rrinë
   djathtas me `margin-left: auto`; këtu janë vetë përmbajtja e qelizës. */
.task-row-flags { margin-left: 0; }

/* Checklist rows on the task detail. */
.task-check-box {
  border: 0;
  background: transparent;
  color: var(--muted);
  padding: 0;
  font-size: var(--text-base);
  line-height: 1;
  cursor: pointer;
  display: inline-flex;
}
.task-check-box:hover { color: var(--primary); }
.task-check.is-done .task-check-box { color: var(--success); }
.task-check.is-done .task-check-text {
  text-decoration: line-through;
  color: var(--faint);
}

/* System entries in the process timeline read as events, not as someone talking. */
.task-event {
  background: var(--surface-hover);
  border-left: 2px solid var(--border-strong);
  font-size: var(--text-xs);
  color: var(--muted);
}

/* Shigjeta e një paneli që paloset ndjek gjendjen e vet: e mbyllur do të thotë
   shigjetë poshtë. Bootstrap-i e vë `.collapsed` te butoni, prandaj s'duhet asnjë
   rresht JS për ta kthyer. */
.panel-fold i { display: inline-block; transition: transform var(--dur-2) var(--ease-out); }
.panel-fold.collapsed i { transform: rotate(180deg); }

/* --- Formulari i task-ut të ri ---------------------------------------------
   Tri pyetjet e tij — çfarë, kush·kur, ku — rrinin njëra poshtë tjetrës brenda
   një kolone të ngushtë: njëmbëdhjetë fusha, një gjarpër i gjatë që kërkonte
   skrollim para se të shtypej butoni. Në ekran të gjerë ato ndahen: «çfarë»
   majtas mbi dy rreshta (aty rri përshkrimi dhe zëri, pjesa më e lartë),
   «kush·kur» e «ku» djathtas, hapat poshtë të gjithëve.

   Nën 992px rrjeti shpërbëhet vetvetiu në një kolonë — pikërisht ajo që ishte. */
.task-form-grid { display: grid; gap: 0; }
.task-form-sec + .task-form-sec { margin-top: var(--space-4); }
.task-form-actions { margin-top: var(--space-4); }

@media (min-width: 992px) {
  .task-form-grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-areas:
      "what who"
      "what where"
      "steps steps";
    column-gap: var(--space-4);
    row-gap: var(--space-4);
    align-items: start;
  }
  .task-form-what { grid-area: what; }
  .task-form-who { grid-area: who; }
  .task-form-where { grid-area: where; }
  .task-form-steps { grid-area: steps; }
  /* Hapësirën mes seksioneve e mban rrjeti; margjina do ta numëronte dy herë. */
  .task-form-sec + .task-form-sec { margin-top: 0; }
}

/* --- Ngarkesa e punëtorëve ------------------------------------------------
   Kush sa mban, dhe sa prej tyre kanë kaluar afatin — para se dikush të caktojë
   të tridhjetin te i njëjti njeri. Vija krahason me më të ngarkuarin e ditës, jo
   me një numër të shpikur: «plot» do të thotë «aq sa mban sot më i ngarkuari i
   zyrës».

   Ishte një kartë e plotë me kokë, buton palosjeje dhe rrjet kutish prej 11rem —
   nëntë rreshta lartësi mes kokës së faqes dhe punës, të hapura në të tria
   pamjet. Tani është një shirit copëzash: e njëjta përgjigje, tre rreshta. Ç'u
   shkruante me fjalë (orët, vonesa, cikli) rri te `title` dhe te teksti i
   fshehur — një kuti që i thotë të gjitha njëherësh nuk lexohet nga askush. */
.load-rail {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-3);
}
.load-rail-label {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--muted);
}
.load-rail-cycle {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  margin-left: var(--space-0);
  padding: var(--space-0) var(--space-1-5);
  border-radius: var(--radius-pill);
  background: var(--surface-muted);
  font-variant-numeric: tabular-nums;
}
.load-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1-5);
  min-width: 8.5rem;
  max-width: 13rem;
  padding: var(--space-1) var(--space-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: var(--surface);
  color: inherit;
  text-decoration: none;
  transition: border-color var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease-out), transform var(--dur-2) var(--ease-out);
}
.load-chip:hover {
  border-color: var(--primary-line);
  box-shadow: var(--shadow-sm);
  transform: translateY(-1px);
  color: inherit;
}
.load-chip.is-active {
  border-color: var(--primary);
  background: var(--primary-soft);
}
.load-chip-main {
  display: flex;
  flex-direction: column;
  gap: var(--space-0);
  min-width: 0;
  flex: 1 1 auto;
}
.load-chip-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2);
  min-width: 0;
}
.load-chip-name {
  font-size: var(--text-xs);
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.load-chip-count {
  font-size: var(--text-xs);
  font-weight: 700;
  color: var(--primary-text);
  font-variant-numeric: tabular-nums;
}
body.theme-dark .load-chip-count { color: var(--primary); }
/* Vonesa nuk bëhet fjalë e dytë brenda copëzës — bëhet ngjyra e vijës dhe një
   pikë në skaj. Fjala e plotë rri te `title` dhe te teksti i fshehur. */
.load-chip.is-late .load-chip-count { color: var(--danger); }
.load-chip-track {
  height: .25rem;
  border-radius: var(--radius-pill);
  background: var(--surface-hover);
  overflow: hidden;
}
.load-chip-fill {
  display: block;
  height: 100%;
  border-radius: var(--radius-pill);
  background: linear-gradient(90deg, var(--primary), var(--primary-2));
}
.load-chip-fill.is-late { background: linear-gradient(90deg, var(--danger-fill-strong), var(--danger-fill)); }
/* Ora e vogël në skaj: e mban punën më gjatë se mesatarja e zyrës. Vetëm
   përjashtimi e merr — nëse do ta mbante çdo copëz, s'do të thoshte asgjë. */
.load-chip-slow { color: var(--warning); font-size: var(--text-xs); }

/* --- Kalendari i ngarkesës: punëtorë × ditë --------------------------------
   Një rrjet i gjerë me kolonën e emrit të ngjitur majtas: pa të, skrollimi
   horizontal e nxjerr punëtorin nga ekrani dhe rreshti bëhet një varg qelizash
   pa pronar. Qeliza mban intensitetin te `--heat` (0–1), të vendosur nga
   serveri kundrejt ditës më të ngarkuar të vetë pamjes — jo kundrejt një numri
   të shpikur. */
.tl-scroll { overflow-x: auto; }
.tl-table {
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--text-xs);
}
.tl-table th, .tl-table td {
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}
.tl-who {
  position: sticky;
  left: 0;
  z-index: 2;
  min-width: 8.5rem;
  max-width: 11rem;
  background: var(--surface);
  border-right: 1px solid var(--border);
  text-align: left;
  font-weight: 600;
}
.tl-table thead .tl-who { z-index: 3; }
.tl-who-name {
  display: block;
  color: inherit;
  text-decoration: none;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tl-who-name:hover { color: var(--primary-text); }
.tl-who-note {
  display: block;
  font-size: var(--text-xs);
  font-weight: 400;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.tl-head-day, .tl-head-late {
  min-width: 6.5rem;
  text-align: center;
  line-height: 1.2;
  padding: var(--space-1) var(--space-1);
}
.tl-day-name { display: block; font-size: var(--text-xs); color: var(--muted); }
.tl-day-num { display: block; font-weight: 700; font-variant-numeric: tabular-nums; }
.tl-day-load {
  display: inline-block;
  margin-top: var(--space-0);
  padding: 0 var(--space-1);
  border-radius: var(--radius-pill);
  background: var(--surface-hover);
  color: var(--muted);
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
}
.tl-head-day.is-weekend { background: var(--surface-muted); }
.tl-head-day.is-today, .tl-head-late { background: var(--primary-soft); }
.tl-head-late .tl-day-num { color: var(--danger); }

.tl-cell {
  position: relative;
  min-width: 6.5rem;
  padding: var(--space-1);
}
/* Intensiteti si `opacity` mbi një shtresë të vetme me ngjyrën e temës, si te
   harta e sezonalitetit — jo si katërmbëdhjetë ngjyra të shkruara me dorë:
   kështu rrjeti e ndjek paletën edhe në errësirë, dhe çipat rrinë mbi mbushjen,
   jo brenda saj. */
.tl-cell::before {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--primary);
  opacity: calc(var(--heat, 0) * .18);
  pointer-events: none;
}
.tl-cell.is-late::before { background: var(--danger-fill); opacity: calc(var(--heat, 0) * .22); }
.tl-cell.is-weekend { background-color: var(--surface-muted); }
.tl-cell.is-today { box-shadow: inset var(--rail) 0 0 var(--primary); }
.tl-cell.is-muted { background-color: var(--surface-muted); }

.tl-chip {
  position: relative;
  z-index: 1;
  display: block;
  margin-bottom: var(--space-1);
  padding: var(--space-1) var(--space-1-5);
  border-radius: var(--radius-sm);
  border-left: 3px solid var(--border);
  background: var(--surface);
  color: inherit;
  text-decoration: none;
  box-shadow: var(--shadow-sm);
}
.tl-chip:last-child { margin-bottom: 0; }
.tl-chip:hover { color: inherit; border-color: var(--primary-line); background: var(--surface-hover); }
.tl-chip.prio-high { border-left-color: var(--danger); }
.tl-chip.prio-medium { border-left-color: var(--warning); }
.tl-chip.prio-low { border-left-color: var(--primary); }
.tl-chip-title {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 600;
}
.tl-chip-h { color: var(--muted); font-variant-numeric: tabular-nums; }
.tl-legend { display: flex; flex-wrap: wrap; gap: var(--space-1-5); }
.tl-legend-item {
  font-size: var(--text-xs);
  color: var(--muted);
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
}
.tl-legend-item.is-late { color: var(--danger); font-weight: 600; }

/* --- Veprimi me shumicë ----------------------------------------------------
   Shiriti rri ngjitur poshtë derisa ka diçka të zgjedhur: zgjedhja bëhet lart
   te rreshtat, dhe veprimi duhet të mbetet aty ku janë sytë, jo dyqind rreshta
   më poshtë. Mbi shiritin e telefonit, jo nën të. */
.bulk-bar {
  position: sticky;
  bottom: calc(var(--space-3) + var(--bottomnav-h));
  z-index: 15;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  margin-bottom: var(--space-3);
  border: 1px solid var(--primary-line);
  border-radius: var(--radius);
  background: var(--surface-raised);
  backdrop-filter: blur(var(--glass-blur));
  box-shadow: var(--shadow-lg);
}
.bulk-count {
  font-size: var(--text-sm);
  color: var(--muted);
  white-space: nowrap;
}
.bulk-count strong {
  color: var(--primary-text);
  font-variant-numeric: tabular-nums;
}
.bulk-field { width: auto; flex: 0 1 13rem; }
/* Shtylla e kutive rri e ngushtë: është një zgjedhje, jo një e dhënë. */
.tbl-pick { width: 2.4rem; }
tr.is-picked > td { background: var(--primary-soft); }

@media (max-width: 900px) {
  .task-board { grid-template-columns: 1fr; }
  /* Kolonat rrinë njëra nën tjetrën, pra s'ka çfarë të shtyhet poshtë ekranit —
     dhe një kuti që skrollon brenda faqes që skrollon është dy skrollime për një
     gisht. Kufiri i lartësisë vlen vetëm kur kolonat janë vërtet kolona. */
  .task-col-body { min-height: 3rem; max-height: none; overflow-y: visible; }
  /* Dragging between stacked columns is awkward, so lean on the buttons. */
  .task-card { cursor: default; }
  .bulk-field { flex: 1 1 100%; }
}

/* --- Groups: sidebar list -------------------------------------------------- */
.group-nav-title {
  font-size: var(--text-2xs);
  text-transform: uppercase;
  letter-spacing: .09em;
  color: var(--faint);
  font-weight: 700;
  padding: var(--space-2) var(--space-2) var(--space-1);
}
.group-empty {
  display: block;
  padding: var(--space-1) var(--space-2);
  font-size: var(--text-xs);
  color: var(--faint);
  font-style: italic;
}

/* «Grup i ri» — veprimi që rri në fund të një seksioni, jo një plus i vogël
   ngjitur me titullin. Në kokë ai e pengonte seksionin të mblidhej fare, sepse
   koka duhej të ishte buton më vete; këtu është rresht si të tjerët dhe lexohet
   me fjalë, jo me ikonë. */
.sidebar-add {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  padding: var(--space-1-5) var(--space-2);
  border: 1px dashed var(--border);
  border-radius: var(--radius);
  background: transparent;
  color: var(--faint);
  font-size: var(--text-xs);
  font-weight: 600;
  transition: color var(--dur-2) var(--ease-out), border-color var(--dur-2) var(--ease-out), background var(--dur-2) var(--ease-out);
}
.sidebar-add:hover {
  color: var(--primary-text);
  border-color: var(--primary);
  background: var(--surface-hover);
}
.sidebar-add i { font-size: var(--text-sm); }
.group-link {
  display: flex;
  align-items: center;
  gap: var(--space-1-5);
  padding: var(--space-1-5) var(--space-2) !important;
  font-size: var(--text-sm);
  border-radius: var(--radius-sm);
}
.group-link.active { background: var(--tm-accent-soft); font-weight: 600; }
.group-hash { opacity: .5; }
.group-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; }
.group-unread {
  background: var(--tm-accent);
  color: var(--primary-contrast);
  font-size: var(--text-2xs);
  font-weight: 700;
  padding: var(--space-0) var(--space-1-5);
  border-radius: var(--radius-pill);
  min-width: 1.15rem;
  text-align: center;
}

/* --- Teams-style chat ------------------------------------------------------
   Purple accent, avatars on the left, actions revealed on hover, threads
   indented under their parent. */
.tm-chat {
  display: flex;
  flex-direction: column;
  height: calc(100vh - var(--topbar-h) - var(--bottomnav-h) - 5.5rem);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
}

.tm-header {
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-4);
  flex-shrink: 0;
  background: var(--surface-muted);
}

/* Client info card under the chat header: debt, overdue filings, this
   month's papers, and quick jumps into the modules. */
.tm-clientcard {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-5);
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border);
  background: var(--surface);
  flex-shrink: 0;
}
.tm-clientcard-item { display: flex; flex-direction: column; line-height: 1.2; }
.tm-clientcard-label {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--muted);
  font-weight: 600;
}
.tm-clientcard-value {
  font-weight: 700;
  font-size: var(--text-base);
  font-variant-numeric: tabular-nums;
}
.tm-clientcard-sub { font-size: var(--text-xs); color: var(--faint); }
.tm-clientcard-links { margin-left: auto; display: flex; gap: var(--space-1-5); flex-wrap: wrap; }
@media (max-width: 640px) {
  .tm-clientcard { gap: var(--space-4); }
  .tm-clientcard-links { margin-left: 0; width: 100%; }
}

/* Quick-message templates above the composer. */
.tm-templates { display: flex; flex-wrap: wrap; gap: var(--space-1-5); }
.tm-template-chip {
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  border-radius: var(--radius-pill);
  padding: var(--space-1) var(--space-3);
  font-size: var(--text-sm);
  font-weight: 600;
  cursor: pointer;
  transition: background var(--dur-2) var(--ease-out), border-color var(--dur-2) var(--ease-out), color var(--dur-2) var(--ease-out);
}
.tm-template-chip:hover {
  background: var(--primary-soft);
  border-color: var(--primary-line);
  color: var(--primary);
}

/* Quick filters over the conversation list. */
.tm-filters { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-bottom: var(--space-4); }
.tm-filter {
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--muted);
  border-radius: var(--radius-pill);
  padding: var(--space-1-5) var(--space-3);
  font-size: var(--text-sm);
  font-weight: 600;
  text-decoration: none;
  transition: background var(--dur-2) var(--ease-out), border-color var(--dur-2) var(--ease-out), color var(--dur-2) var(--ease-out);
}
.tm-filter:hover { color: var(--primary); border-color: var(--primary-line); }
.tm-filter.active {
  background: var(--primary);
  border-color: var(--primary);
  color: var(--primary-contrast);
}
.tm-filter-count {
  margin-left: var(--space-2);
  font-size: var(--text-xs);
  background: var(--surface-muted);
  color: var(--muted);
  border-radius: var(--radius-pill);
  padding: var(--space-0) var(--space-2);
  font-weight: 700;
}
.tm-filter.active .tm-filter-count { background: rgba(255,255,255,.25); color: var(--primary-contrast); }
.tm-read { font-size: .9em; margin-right: var(--space-0); }

.tm-avatar {
  width: 34px; height: 34px;
  border-radius: var(--radius-round);
  background: var(--grad-tm);
  color: var(--tm-contrast);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: var(--text-sm);
  flex-shrink: 0;
}
.tm-avatar.sm { width: 26px; height: 26px; font-size: var(--text-2xs); }

.tm-facepile { display: flex; align-items: center; }
.tm-facepile .tm-avatar { margin-left: -6px; border: 2px solid var(--surface); }
.tm-facepile .tm-avatar:first-child { margin-left: 0; }
.tm-facepile-more { font-size: var(--text-2xs); color: var(--muted); margin-left: var(--space-1-5); }

.tm-messages { flex: 1; overflow-y: auto; padding: var(--space-3) var(--space-4); }

.tm-day { text-align: center; margin: var(--space-4) 0 var(--space-3); border-top: 1px solid var(--border); }
.tm-day span {
  position: relative;
  top: -.65rem;
  background: var(--surface);
  padding: 0 var(--space-3);
  font-size: var(--text-2xs);
  color: var(--muted);
  font-weight: 600;
}

.tm-msg {
  position: relative;
  display: flex;
  gap: var(--space-3);
  padding: var(--space-2);
  border-radius: var(--radius-sm);
}
.tm-msg-main {
  min-width: 0;
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}
.tm-msg-head { display: flex; align-items: baseline; gap: var(--space-2); }
.tm-msg-author { font-weight: 600; font-size: var(--text-sm); }
.tm-msg-time { font-size: var(--text-2xs); color: var(--muted); }
.tm-msg-edited { font-size: var(--text-2xs); color: var(--faint); font-style: italic; }
.tm-msg-text { white-space: pre-wrap; word-break: break-word; line-height: 1.45; }

/* --- Flluska --------------------------------------------------------------
   Brenda saj rri i gjithë mesazhi — koka, teksti, bashkëngjitja, reagimet —
   dhe jashtë vetëm fija e përgjigjeve te grupi: një degë e tërë nuk hyn dot në
   një kuti 78% të gjerë, dhe pikërisht aty dështonte çdo provë e mëparshme për
   ta kthyer bisedën në dy anë.

   Kufiri nuk është zbukurim: kur mesazhi është një foto e vetme, sfondi nuk
   shihet fare dhe pa të flluska pushon së ekzistuari. Cepi i prerë është bishti
   — vetëm i pari i një vargu e mban, sepse pesë bishta radhazi s'tregojnë më
   nga vjen zëri. */
.tm-bubble {
  min-width: 0;
  max-width: min(78%, 38rem);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  border-top-left-radius: var(--radius-xs);
  background: var(--surface-muted);
  transition: border-color var(--dur-1) var(--ease-out);
}
.tm-msg-cont > .tm-msg-main > .tm-bubble { border-top-left-radius: var(--radius); }
.tm-msg:hover > .tm-msg-main > .tm-bubble { border-color: var(--border-strong); }

/* --- Vazhdimi: i njëjti folës, pa e thënë tri herë ------------------------
   Rreshtat mblidhen te njëri-tjetri, sepse hapësira mes dy fjalive të një
   njeriu s'ka çfarë të ndajë; ajo mes dy folësve e ka, dhe atë e mban `.tm-msg`
   e zakonshme më lart. */
.tm-msg-cont { padding-top: var(--space-0); padding-bottom: var(--space-0); }

/* Vendi i avatarit nuk zbrazet: aty zbret ora, e heshtur derisa syri shkon atje.
   Gjerësia është saktësisht ajo e `.tm-avatar` (34px), përndryshe teksti i
   vazhdimit do të hynte pak më majtas se ai i mesazhit që e hapi vargun — dhe
   një kolonë që dridhet lexohet më keq se një kolonë e gabuar.

   `opacity` e jo `visibility`: ora është e dhënë e mesazhit dhe duhet të mbetet
   e lexueshme nga një lexues ekrani edhe kur syri s'e sheh. */
.tm-msg-when {
  width: 34px;
  flex-shrink: 0;
  text-align: right;
  font-size: var(--text-2xs);
  color: var(--faint);
  line-height: 1.5;
  font-variant-numeric: tabular-nums;
  opacity: 0;
  transition: opacity var(--dur-1) var(--ease-out);
}
.tm-msg:hover > .tm-msg-when,
.tm-msg:focus-within > .tm-msg-when { opacity: 1; }
@media (hover: none) {
  .tm-msg-when { opacity: 1; }
}

.mention {
  background: var(--tm-accent-soft);
  color: var(--tm-accent);
  font-weight: 600;
  padding: 0 var(--space-1);
  border-radius: var(--radius-xs);
}

/* Hover toolbar, floating over the top-right of the message. */
/* Shiriti i veprimeve mbi një mesazh. `display: none` → `flex` e sillte atë në
   ekzistencë nga asgjëja: pa gjendje të ndërmjetme, pa mundësi për të kaluar
   butë, dhe — meqë miu duhet ta kalojë mesazhin për ta arritur — me një dridhje
   sa herë kufiri prekej. `opacity` e mban kutinë gjithnjë aty dhe ndërron vetëm
   dukshmërinë, pikërisht si `.ai-msg-acts` te asistenti.

   `:focus-within` bashkë me `:hover`: pa të, shiriti nuk arrihej kurrë me
   tastierë — dilte vetëm nën mi. */
.tm-msg-actions {
  position: absolute;
  top: -.55rem;
  right: .5rem;
  display: flex;
  align-items: center;
  gap: var(--space-0);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  padding: var(--space-0);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-1) var(--ease-out);
}
.tm-msg:hover > .tm-msg-actions,
.tm-msg:focus-within > .tm-msg-actions { opacity: 1; pointer-events: auto; }
@media (hover: none) {
  .tm-msg-actions { opacity: 1; pointer-events: auto; }
}
.tm-action {
  border: 0;
  background: transparent;
  color: var(--text);
  padding: var(--space-0) var(--space-1);
  border-radius: var(--radius-xs);
  cursor: pointer;
  font-size: var(--text-sm);
  line-height: 1;
}
.tm-action:hover { background: var(--primary-soft); }
.tm-action-danger:hover { background: var(--danger-soft); color: var(--danger); }

.tm-reactions { display: flex; flex-wrap: wrap; gap: var(--space-1); margin-top: var(--space-1); }
.tm-reaction {
  border: 1px solid var(--border-strong);
  background: var(--surface);
  color: var(--text);
  border-radius: var(--radius-pill);
  padding: var(--space-0) var(--space-1-5);
  font-size: var(--text-xs);
  cursor: pointer;
  line-height: 1.5;
}
.tm-reaction:hover { border-color: var(--tm-accent); }
.tm-reaction.mine { background: var(--tm-accent-soft); border-color: var(--tm-accent); font-weight: 700; }

.tm-reply-btn, .tm-thread-toggle {
  border: 0;
  background: transparent;
  color: var(--tm-accent);
  font-size: var(--text-xs);
  font-weight: 600;
  padding: var(--space-0) 0;
  margin-top: var(--space-1);
  cursor: pointer;
}
.tm-reply-btn:hover, .tm-thread-toggle:hover { text-decoration: underline; }

/* A thread reads as a branch of its parent, not as a new conversation. */
.tm-thread {
  border-left: 2px solid var(--tm-accent-line);
  margin: var(--space-1-5) 0 var(--space-1);
  padding-left: var(--space-2);
}
.tm-reply { padding: var(--space-1) var(--space-1-5); }
.tm-reply .tm-msg-author { font-size: var(--text-xs); }
.tm-reply .tm-msg-text { font-size: var(--text-sm); }

.tm-edit-form { margin-top: var(--space-1); }
.tm-edit-actions { display: flex; gap: var(--space-1-5); margin-top: var(--space-1); }

/* «X po shkruan» plus tri pikat që kërcejnë. Pikat nuk rishkruhen këtu: janë
   `.ai-typing`, e shkruar për asistentin, dhe një bisedë që pret një fjalë është
   e njëjta gjë si një model që pret një fjalë. Lartësia mbetet e fiksuar që
   shfaqja e tyre të mos e shtyjë listën e mesazheve lart. */
.tm-typing {
  height: 1.15rem;
  padding: 0 var(--space-4);
  font-size: var(--text-xs);
  color: var(--muted);
  display: flex;
  align-items: center;
  gap: var(--space-1-5);
}

.tm-composer {
  position: relative;
  padding: var(--space-3) var(--space-4) var(--space-4);
  border-top: 1px solid var(--border);
  flex-shrink: 0;
}
.tm-composer-row { display: flex; gap: var(--space-2); }
.tm-composer input[type="text"] { border-radius: var(--radius-sm); }
.tm-composer input[type="text"]:focus {
  border-color: var(--tm-accent);
  box-shadow: 0 0 0 var(--ring-w-lg) var(--tm-accent-line);
}

.tm-reply-context {
  display: flex;
  align-items: center;
  gap: var(--space-1-5);
  background: var(--tm-accent-soft);
  border-left: 3px solid var(--tm-accent);
  border-radius: var(--radius-xs);
  padding: var(--space-1) var(--space-2);
  margin-bottom: var(--space-1-5);
  font-size: var(--text-xs);
  color: var(--muted);
}
.tm-reply-context .btn-close { margin-left: auto; font-size: var(--text-2xs); }

.tm-mention-box {
  position: absolute;
  bottom: 100%;
  left: 1.25rem;
  right: 1.25rem;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  z-index: 20;
}
.tm-mention-item {
  display: block;
  width: 100%;
  text-align: left;
  border: 0;
  background: transparent;
  color: var(--text);
  padding: var(--space-1-5) var(--space-2);
  font-size: var(--text-sm);
  cursor: pointer;
}
.tm-mention-item:hover { background: var(--primary-soft); }

/* File row under the composer: quiet until a file is picked. */
.group-attach-form {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: 0 var(--space-4) var(--space-3);
  flex-shrink: 0;
}
.group-attach-form .icon-btn { width: 34px; height: 34px; cursor: pointer; }
.chat-link { word-break: break-all; }

/* --- Channel header search ------------------------------------------------- */
.tm-search {
  display: flex;
  align-items: center;
  gap: var(--space-1-5);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-pill);
  padding: var(--space-1) var(--space-3);
  color: var(--muted);
  transition: border-color var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease-out);
}
.tm-search:focus-within {
  border-color: var(--tm-accent);
  box-shadow: 0 0 0 var(--ring-w-lg) var(--tm-accent-line);
}
.tm-search .bi-search { font-size: var(--text-sm); }
.tm-search input {
  border: 0;
  background: transparent;
  outline: none;
  color: var(--text);
  font-size: var(--text-sm);
  width: 11rem;
  max-width: 40vw;
}
.tm-search input::placeholder { color: var(--faint); }
/* E njëjta shenjë pastrimi shërben si lidhje (grupet, ku pastrimi është një
   adresë) dhe si buton (shiriti i bisedave, ku s'ka ku të shkohet). Prandaj
   sfondi e korniza hiqen këtu: një <button> i vjen me të dyja nga shfletuesi. */
.tm-search-clear {
  text-decoration: none;
  color: var(--muted);
  font-size: var(--text-lg);
  line-height: 1;
  padding: 0 var(--space-0);
  background: none;
  border: 0;
  cursor: pointer;
}
.tm-search-clear[hidden] { display: none; }
.tm-search-clear:hover { color: var(--danger); }

/* --- Pinned messages banner ------------------------------------------------ */
.tm-pinned {
  flex-shrink: 0;
  border-bottom: 1px solid var(--border);
  background: var(--warning-soft);
  padding: var(--space-2) var(--space-4);
  max-height: 8.5rem;
  overflow-y: auto;
}
.tm-pinned-head {
  display: flex;
  align-items: center;
  gap: var(--space-1-5);
  font-size: var(--text-2xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--warning);
  margin-bottom: var(--space-1-5);
}
.tm-pinned-list { display: flex; flex-direction: column; gap: var(--space-1); }
.tm-pinned-item {
  display: flex;
  align-items: center;
  gap: var(--space-1-5);
  border-radius: var(--radius-sm);
  padding: var(--space-0) var(--space-0) var(--space-0) var(--space-1);
}
.tm-pinned-item:hover { background: var(--surface); }
.tm-pinned-jump {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: baseline;
  gap: var(--space-1-5);
  border: 0;
  background: transparent;
  text-align: left;
  cursor: pointer;
  color: var(--text);
  font-size: var(--text-sm);
  padding: var(--space-0) 0;
}
.tm-pinned-author { font-weight: 700; flex-shrink: 0; }
.tm-pinned-text {
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.tm-pinned-unpin {
  border: 0;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  padding: var(--space-0) var(--space-1-5);
  border-radius: var(--radius-sm);
  font-size: var(--text-xs);
  flex-shrink: 0;
}
.tm-pinned-unpin:hover { background: var(--danger-soft); color: var(--danger); }

/* Pin marks on the message itself. */
.tm-pin-tag { color: var(--warning); font-size: var(--text-sm); }
.tm-action-on { color: var(--warning); }
/* Rripi rri te flluska e jo te rreshti: te një mesazh i yti rreshti shkon deri
   në skajin e majtë, ku s'ka mbetur asgjë për të shënuar. */
.tm-msg.is-pinned > .tm-msg-main > .tm-bubble { box-shadow: inset var(--rail) 0 0 var(--warning); }
.tm-flash { animation: tm-flash var(--beat) var(--ease-out); }
@keyframes tm-flash {
  0%, 40% { background: var(--tm-accent-soft); }
  100% { background: transparent; }
}

/* --- In-channel search results --------------------------------------------- */
.tm-search-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
  padding: var(--space-1-5) var(--space-1) var(--space-3);
  border-bottom: 1px solid var(--border);
  margin-bottom: var(--space-2);
  color: var(--muted);
  font-size: var(--text-sm);
}
.tm-search-hit {
  display: flex;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-1-5);
  border-radius: var(--radius-sm);
  text-decoration: none;
  color: inherit;
}
.tm-search-hit:hover { background: var(--surface-muted); }
.tm-search-hit-main { min-width: 0; flex: 1; }
.tm-search-hit-head {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-0);
}
.tm-search-file {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--text-xs);
  color: var(--tm-accent);
  margin-top: var(--space-1);
}

/* --- Composer attachment preview bar --------------------------------------- */
.tm-attach-trigger { width: 38px; flex-shrink: 0; }
.tm-attach-preview {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  background: var(--surface-muted);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: var(--space-1-5) var(--space-2);
}
.tm-attach-icon { color: var(--tm-accent); flex-shrink: 0; }
.tm-attach-name {
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--text);
  max-width: 12rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  flex-shrink: 0;
}
.tm-attach-preview .form-control { flex: 1; min-width: 6rem; }

/* Role dropdown in the manage-group modal. */
.tm-role-form { display: inline-flex; }
.tm-role-select { width: auto; min-width: 8rem; }

.tm-mention-toast {
  position: fixed;
  bottom: 1.25rem;
  right: 1.25rem;
  background: var(--tm-accent);
  color: var(--primary-contrast);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg);
  font-size: var(--text-sm);
  z-index: 1080;
}

@media (max-width: 768px) {
  .tm-chat { height: calc(100vh - var(--bottomnav-h) - 12rem); }
  .tm-msg-actions { position: static; margin-top: var(--space-1); opacity: 1; pointer-events: auto; }
  /* Te telefoni ana lihet e ngushtë sa për t'u parë: 78% e një ekrani 360px
     nuk mban dot as një fjali të tërë pa u thyer tri herë. */
  .tm-bubble { max-width: 88%; }
}

/* --- Dy anët: e jotja djathtas, e tjetrit majtas ---------------------------
   Këtu rrinte e kundërta: mesazhi yt mbetej majtas mbi një sfond të lehtë,
   «sepse një pamje me dy anë prishet sapo hyjnë avatarët dhe reagimet». Ajo që
   prish nuk është ana — është kur ana mban gjithçka. Prandaj avatari yt hiqet
   (vendi e ka thënë tashmë kush foli) dhe fija e përgjigjeve del jashtë
   flluskës e shtrihet sa rreshti.

   Ngjyra e anës sate është e njëjta familje aksenti si kudo tjetër, jo një e
   gjelbër e huazuar: e vetmja gjë që duhet të thotë është «kjo është e imja». */
.tm-msg.mine > .tm-msg-main { align-items: flex-end; }
.tm-msg.mine > .tm-msg-main > .tm-bubble {
  background: var(--tm-accent-soft);
  border-color: var(--tm-accent-line);
  border-top-left-radius: var(--radius);
  border-top-right-radius: var(--radius-xs);
}
.tm-msg.mine.tm-msg-cont > .tm-msg-main > .tm-bubble { border-top-right-radius: var(--radius); }
.tm-msg.mine:hover > .tm-msg-main > .tm-bubble { border-color: var(--tm-accent); }
.tm-msg.mine > .tm-msg-main > .tm-bubble > .tm-reactions { justify-content: flex-end; }
/* Vazhdimi yt e mban vetëm orën te koka — pa emër ajo do të dukej etiketë e
   mbetur; te skaji i djathtë ajo lexohet si ora e vetë flluskës. */
.tm-msg.mine.tm-msg-cont > .tm-msg-main > .tm-bubble > .tm-msg-head { justify-content: flex-end; }

/* Shiriti i veprimeve kalon në anën e lirë: mbi mesazhin tënd ai do të binte
   pikërisht mbi cepin e flluskës. */
.tm-msg.mine > .tm-msg-actions { right: auto; left: .5rem; }

/* Dega mbetet degë: një fill përgjigjesh nuk rreshtohet djathtas vetëm se
   prindi i tij ke qenë ti. */
.tm-msg-main > .collapse { align-self: stretch; }

.tm-seen {
  font-size: var(--text-2xs);
  color: var(--muted);
  margin-top: var(--space-1);
  text-align: right;
}

.tm-attachment {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: var(--space-2);
  margin: var(--space-1) 0;
  background: var(--surface-muted);
  max-width: 26rem;
}
.tm-attachment-head { margin-bottom: var(--space-1); font-size: var(--text-xs); }
.tm-attachment-img {
  max-width: 100%;
  max-height: 16rem;
  border-radius: var(--radius-xs);
  display: block;
}

.tm-presence { font-variant-numeric: tabular-nums; }

/* --- Two-pane messenger shell ---------------------------------------------
   A fixed-height row: a scrolling conversation list on the left, the open
   thread (or a "pick one" placeholder) on the right. On a phone the two become
   separate screens — see the responsive block at the end. */
.tm-shell {
  display: flex;
  gap: var(--space-4);
  height: calc(100vh - var(--topbar-h) - var(--bottomnav-h) - 4.5rem);
  min-height: 24rem;
}

.tm-sidebar {
  width: 340px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}
.tm-sidebar-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border);
  background: var(--surface-muted);
  flex-shrink: 0;
}
.tm-sidebar-title { display: flex; align-items: center; gap: var(--space-2); font-weight: 700; font-size: var(--text-base); }
.tm-sidebar-search {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: var(--space-3) var(--space-3) var(--space-1-5);
  padding: var(--space-1-5) var(--space-3);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-pill);
  color: var(--muted);
  background: var(--surface);
  flex-shrink: 0;
  transition: border-color var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease-out);
}
.tm-sidebar-search:focus-within {
  border-color: var(--tm-accent);
  box-shadow: 0 0 0 var(--ring-w-lg) var(--tm-accent-line);
}
.tm-sidebar-search input {
  border: 0; background: transparent; outline: none;
  color: var(--text); font-size: var(--text-sm); width: 100%;
}
.tm-sidebar-search input::placeholder { color: var(--faint); }
.tm-sidebar-filters { margin: var(--space-0) var(--space-3) var(--space-2); gap: var(--space-1-5); flex-shrink: 0; }
.tm-sidebar-filters .tm-filter { padding: var(--space-1) var(--space-2); font-size: var(--text-xs); }
/* Shenjat dalin nga skedat e listës. Te një shirit 340px ato janë tetëdhjetë
   piksela dekor që e shtyjnë skedën e fundit në rreshtin e dytë — dhe rreshti i
   dytë kushton njëzet e gjashtë piksela liste, çdo herë që hapet faqja. Fjala e
   mban vetë kuptimin; shenja ishte veç shoqërim. */
.tm-sidebar-filters .tm-filter > .bi { display: none; }
.tm-sidebar-list { flex: 1; overflow-y: auto; }

.tm-main { flex: 1; min-width: 0; display: flex; }
.tm-main > .tm-chat, .tm-main > .tm-empty-main, .tm-main > .tm-overview {
  flex: 1;
  width: 100%;
  /* `min-width: 0` sepse një fëmijë flex e ka minimumin te përmbajtja: një
     rresht i gjatë brenda përmbledhjes do ta zgjeronte panelin dhe do ta shtynte
     listën e bisedave jashtë, në vend që të shkurtohej me pika. */
  min-width: 0;
}
/* Inside the shell the thread fills the pane; the standalone height (used by
   group chat) is left untouched for pages that are not two-pane. */
.tm-shell .tm-chat { height: 100%; }

/* Right-pane placeholder shown while no thread is open. */
.tm-empty-main {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: var(--space-1-5);
  padding: var(--space-6);
  background: var(--surface);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-lg);
  color: var(--muted);
}
.tm-empty-main-icon { font-size: var(--text-3xl); color: var(--tm-accent); opacity: .55; }
.tm-empty-main-title { font-weight: 700; font-size: var(--text-base); color: var(--text); }
.tm-empty-main-text { font-size: var(--text-sm); max-width: 22rem; }

/* Back-to-list arrow in the chat header — phone only. */
.tm-back {
  display: none;
  align-items: center;
  justify-content: center;
  width: 34px; height: 34px;
  border-radius: var(--radius-sm);
  color: var(--text);
  text-decoration: none;
  flex-shrink: 0;
}
.tm-back:hover { background: var(--surface-hover); color: var(--text); }

/* --- People list ----------------------------------------------------------- */
.tm-people { display: flex; flex-direction: column; }

/* The row is a flex container; the link is the clickable part and the
   three-dot menu sits beside it, never inside the <a>. */
.tm-person {
  position: relative;
  display: flex;
  align-items: stretch;
  border-bottom: 1px solid var(--border);
  transition: background var(--dur-1) var(--ease-out);
}
.tm-person:last-child { border-bottom: 0; }
.tm-person:hover { background: var(--surface-hover); }
/* The accent bar makes an unread row findable without reading it. */
.tm-person.has-unread { background: var(--tm-accent-faint); box-shadow: inset var(--rail) 0 0 var(--tm-accent); }
/* The open conversation, marked so the list reads as "you are here". */
.tm-person.active { background: var(--tm-accent-soft); box-shadow: inset var(--rail) 0 0 var(--tm-accent); }
.tm-person.active:hover { background: var(--tm-accent-soft); }

/* Biseda që pret fjalën tënde. Ndryshe nga e palexuara: një bisedë e lexuar dhe
   e lënë pa përgjigje s'ka asnjë shenjë tjetër, dhe pikërisht ajo harrohet. Këtu
   shenja rri te shiriti i djathtë, jo si sfond — sfondi është tashmë i zënë nga
   e palexuara, dhe dy sfonde mbi një rresht do të fshinin njëri-tjetrin. */
.tm-await-ic { color: var(--tm-accent); font-size: var(--text-xs); }
.tm-await-ic.is-warm { color: var(--warning); }
.tm-await-ic.is-old  { color: var(--danger); }

.tm-person-link {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex: 1;
  min-width: 0;
  /* .6rem → .45rem: gjashtëdhjetë e tre piksela për rresht do të thoshin nëntë
     biseda në një ekran 900px dhe gjashtë në një 720px, pra pjesa më e madhe e
     listës rrinte nën palosje sa herë hapej faqja. */
  padding: var(--space-2) var(--space-1) var(--space-2) var(--space-4);
  text-decoration: none;
  color: inherit;
}
.tm-person-link:hover { color: inherit; }

.tm-person-avatar { position: relative; flex-shrink: 0; }
.tm-dot {
  position: absolute;
  right: -1px;
  bottom: -1px;
  width: 10px;
  height: 10px;
  border-radius: var(--radius-round);
  background: var(--faint);
  border: 2px solid var(--surface);
}
.tm-dot.on { background: var(--success-fill); }

.tm-person-main { flex: 1; min-width: 0; }
.tm-person-top {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-2);
}
.tm-person-name {
  font-weight: 600; font-size: var(--text-sm);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  min-width: 0;
}
/* Margjina automatike e thith gjithë hapësirën e lirë PARA se `space-between` ta
   ndajë, pra çipi i rolit rri ngjitur me emrin dhe ora mbetet në skaj. Pa të,
   rreshti me tri copa do t'i ndante të treja njësoj larg njëra-tjetrës. */
.tm-person-role { margin-right: auto; }
.tm-person.has-unread .tm-person-name { font-weight: 700; }
.tm-pin-ic { color: var(--tm-accent); font-size: var(--text-2xs); margin-right: var(--space-0); }
/* Roli i kolegut, aq i qetë sa të lexohet vetëm kur kërkohet. Emri e ka rendin e
   parë; kjo rri pas tij dhe s'e shtyn kurrë orën jashtë rreshtit. */
.tm-person-role {
  font-size: var(--text-2xs);
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--muted);
  background: var(--surface-muted);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  padding: 0 var(--space-1-5);
  white-space: nowrap;
  flex-shrink: 0;
}
.tm-person-time { font-size: var(--text-2xs); color: var(--faint); white-space: nowrap; flex-shrink: 0; }

.tm-person-bottom {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-0);
}
.tm-person-preview {
  font-size: var(--text-xs);
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 1;
}
.tm-person.has-unread .tm-person-preview { color: var(--text); font-weight: 500; }
.tm-person-badges { display: flex; align-items: center; gap: var(--space-1); flex-shrink: 0; }
.tm-muted-ic { color: var(--faint); font-size: var(--text-xs); }
.tm-person-unread {
  background: var(--tm-accent);
  color: var(--primary-contrast);
  font-size: var(--text-2xs);
  font-weight: 700;
  padding: var(--space-0) var(--space-1-5);
  border-radius: var(--radius-pill);
  min-width: 1.2rem;
  text-align: center;
}

/* --- Per-row three-dot menu (pin / mute / delete) -------------------------- */
.tm-menu { display: flex; align-items: center; flex-shrink: 0; padding-right: var(--space-1); }
.tm-menu-btn {
  border: 0;
  background: transparent;
  color: var(--muted);
  width: 28px; height: 28px;
  border-radius: var(--radius-sm);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  font-size: var(--text-md);
  line-height: 1;
}
.tm-menu-btn:hover,
.tm-menu-btn[aria-expanded="true"] { background: var(--surface-hover); color: var(--text); }
/* Fixed + moved to <body> on open, so no scroll container or animated
   ancestor can clip it (see _conversation_sidebar.html). */
.tm-menu-pop {
  position: fixed;
  z-index: 1090;
  min-width: 196px;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg);
  padding: var(--space-1);
}
.tm-menu-pop[hidden] { display: none; }
.tm-menu-form { margin: 0; }
.tm-menu-item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  border: 0;
  background: transparent;
  color: var(--text);
  padding: var(--space-2);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  font-weight: 500;
  text-align: left;
  cursor: pointer;
}
.tm-menu-item i { font-size: var(--text-sm); width: 1rem; text-align: center; color: var(--muted); }
.tm-menu-item:hover { background: var(--surface-hover); }
.tm-menu-item.danger { color: var(--danger); }
.tm-menu-item.danger i { color: var(--danger); }
.tm-menu-item.danger:hover { background: var(--danger-soft); }
.tm-menu-sep { height: 1px; background: var(--border); margin: var(--space-1); }

.tm-people-empty { padding: var(--space-5) var(--space-4); text-align: center; color: var(--muted); font-size: var(--text-sm); }

/* --- Kërkimi brenda mesazheve --------------------------------------------
   Rezultatet e serverit rrinë mbi listën e emrave, brenda të njëjtit rrëshqitës:
   një njeri që kërkon një fjalë e ka atë fjalë të parën para syve, dhe emrat që
   përputhen mbeten poshtë saj pa u zhdukur. */
.tm-sidebar-search .tm-search-clear { font-size: var(--text-sm); padding: 0; }
/* Një `input[type="search"]` e sjell vetë kryqin e vet te Chromium-i, dhe pranë
   tonit ishin dy kryqe njëri pas tjetrit. Mbahet i yni: ai pastron edhe listën e
   emrave edhe rezultatet e serverit, kurse i shfletuesit di vetëm fushën. */
.tm-sidebar-search input::-webkit-search-cancel-button,
.tm-sidebar-search input::-webkit-search-decoration { -webkit-appearance: none; appearance: none; }
.tm-hits { border-bottom: 1px solid var(--border); background: var(--surface-muted); }
.tm-hits[hidden] { display: none; }
.tm-hits-head {
  padding: var(--space-2) var(--space-3) var(--space-1-5);
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--muted);
}
.tm-hit-group { padding: 0 0 var(--space-1-5); }
.tm-hit-who {
  display: flex;
  align-items: center;
  gap: var(--space-1-5);
  padding: var(--space-1) var(--space-3);
}
.tm-hit-name { font-size: var(--text-xs); font-weight: 700; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tm-hit-count {
  margin-left: auto;
  font-size: var(--text-2xs);
  color: var(--muted);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  padding: 0 var(--space-1-5);
  flex-shrink: 0;
}
.tm-hit {
  display: block;
  padding: var(--space-1) var(--space-3) var(--space-1-5) var(--space-5);
  color: var(--text);
  text-decoration: none;
  border-left: 2px solid transparent;
}
.tm-hit:hover { background: var(--surface-hover); border-left-color: var(--tm-accent); color: var(--text); }
.tm-hit-text {
  font-size: var(--text-xs);
  line-height: 1.35;
  /* Dy rreshta: një copë teksti pa fund do ta shtynte listën jashtë ekranit. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.tm-hit-mine { color: var(--muted); }
.tm-hit-mark {
  background: var(--warning-soft);
  color: inherit;
  padding: 0 var(--space-0);
  border-radius: var(--radius-xs);
}
.tm-hit-time { font-size: var(--text-2xs); color: var(--faint); margin-top: var(--space-0); }
.tm-hit-more { padding: var(--space-0) var(--space-3) var(--space-1) var(--space-5); font-size: var(--text-2xs); color: var(--faint); font-style: italic; }

/* --- E djathta e faqes së mesazheve: e gjithë kutia postare e lexuar njëherësh
   ------------------------------------------------------------------------- */
.tm-overview {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  overflow-y: auto;
  padding: var(--space-0) var(--space-0) var(--space-4);
}
/* Njoftimi se përmbledhja s'është më e freskët. Rri i qetë dhe nuk lëviz asgjë:
   kush po lexon, lexon; kush do numrat e rinj, klikon. */
.tm-stale {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1-5) var(--space-3);
  border: 1px solid var(--tm-accent-line);
  background: var(--tm-accent-soft);
  border-radius: var(--radius-sm);
  color: var(--tm-accent);
  font-size: var(--text-xs);
  font-weight: 600;
  text-decoration: none;
}
.tm-stale[hidden] { display: none; }
/* Te hover-i sfondi forcohet, prandaj teksti duhet të ndërrojë me të: aksenti mbi
   `--tm-accent-line` bie te 3,67:1 në temën e errët — nën kufirin AA, dhe roja e
   temës së errët e kap. */
.tm-stale:hover { background: var(--tm-accent-line); color: var(--text); }

.tm-ov-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
}
.tm-ov-title {
  font-family: 'Sora Variable', 'Inter Variable', Inter, sans-serif;
  font-size: var(--text-xl);
  font-weight: 700;
  letter-spacing: -.02em;
  margin: 0;
}
.tm-ov-sub { margin: var(--space-0) 0 0; font-size: var(--text-sm); color: var(--muted); }
.tm-ov-actions { display: flex; gap: var(--space-1-5); flex-wrap: wrap; }
/* Kartelat e shifrave rrinë në një gjysmë ekrani, jo në një faqe të tërë.
   `11rem` i mbante katër vetëm mbi ekrane të gjera: te 1280 gjysma e djathtë del
   rreth 620px, pra tri kartela hynin e e katërta zbriste vetme në një rresht të
   ri — një vrimë sa një kartelë, pikërisht nën kokën e faqes. Me `8.5rem` të katërta
   rrinë bashkë deri poshtë, dhe në telefon bien në dysh. */
.tm-ov-stats { grid-template-columns: repeat(auto-fit, minmax(min(8.5rem, 100%), 1fr)); gap: var(--space-2); margin-bottom: 0; }
.tm-ov-stats .stat-card { padding: var(--space-3) var(--space-4); }
/* Në një kartelë 9rem shenja e madhe ha gjerësinë që i duhet fjalës. */
.tm-ov-stats .stat-icon { align-self: flex-start; }

.tm-ov-pair { display: flex; gap: var(--space-3); }
.tm-ov-pair i { opacity: .75; }

/* Dy kartat rrinë njësoj të larta edhe kur njëra ka tre rreshta e tjetra
   tetë: e shkurtra e mbyllur në mes të faqes lë poshtë vetes një zbrazëti që
   duket si diçka që s'u ngarkua. */
/* `19rem` i mbante të dyja krah për krah vetëm mbi ekrane të gjera: te 1280 e
   djathta del 608px, dhe dy shtylla 304px me një hapësirë 13,6px kërkojnë 621,6
   — gjashtëmbëdhjetë piksela më shumë se ç'ka. Pra dy kartat ziheshin njëra mbi
   tjetrën dhe përmbledhja dyfishohej në lartësi pikërisht te gjerësia më e
   zakonshme e një laptopi. `17rem` i mban bashkë deri poshtë. */
.tm-ov-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(17rem, 100%), 1fr));
  gap: var(--space-3);
  align-items: stretch;
}
.tm-ov-grid > .card { display: flex; flex-direction: column; }
.tm-ov-grid > .card > .card-body { flex: 1; }
.tm-ov-card { margin-bottom: 0; }

/* Dikur secila kartë mbante një dritare 21rem dhe rrëshqiste brenda vetes, që
   një listë e gjatë të mos e shtynte grafikun jashtë faqes. Kjo e zgjidhte
   lartësinë duke shtuar një rrëshqitje të tretë: faqja, përmbledhja, dhe pastaj
   karta — tri rrota miu mbi të njëjtin piksel, secila me fundin e vet të fshehur.
   Tani listat priten te serveri (AWAIT_ROWS / FEED_ROWS) dhe prerja shkruhet me
   fjalë poshtë tyre; e djathta ka një rrëshqitje të vetme, atë të përmbledhjes. */
.tm-ov-more {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-1-5);
  padding: var(--space-2);
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--tm-accent);
  text-decoration: none;
  border-top: 1px solid var(--border);
}
.tm-ov-more:hover { background: var(--surface-hover); color: var(--tm-accent); }

/* Bisedat që presin përgjigje. Sa më e vjetër fjala e tyre, aq më e ngrohtë
   shenja majtas — kjo është e vetmja renditje që ka rëndësi këtu. */
.tm-await { display: flex; flex-direction: column; }
.tm-await-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  border-bottom: 1px solid var(--border);
  color: inherit;
  text-decoration: none;
  box-shadow: inset var(--rail) 0 0 transparent;
  transition: background var(--dur-1) var(--ease-out);
}
.tm-await-row:last-child { border-bottom: 0; }
.tm-await-row:hover { background: var(--surface-hover); color: inherit; }
.tm-await-row.is-warm { box-shadow: inset var(--rail) 0 0 var(--warning); }
.tm-await-row.is-old { box-shadow: inset var(--rail) 0 0 var(--danger); }
.tm-await-main { flex: 1; min-width: 0; }
.tm-await-top { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-2); }
.tm-await-name { font-weight: 600; font-size: var(--text-sm); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tm-await-wait {
  font-size: var(--text-2xs);
  font-variant-numeric: tabular-nums;
  color: var(--muted);
  flex-shrink: 0;
}
.tm-await-row.is-warm .tm-await-wait { color: var(--warning); font-weight: 700; }
.tm-await-row.is-old .tm-await-wait { color: var(--danger); font-weight: 700; }
.tm-await-text {
  font-size: var(--text-xs);
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tm-await-badges { display: flex; align-items: center; gap: var(--space-1); flex-shrink: 0; }

/* Rrjedha e fundit e kutisë — pa ndarje sipas njerëzve, vetëm rendi i orës. */
.tm-feed { display: flex; flex-direction: column; }
.tm-feed-row {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  border-bottom: 1px solid var(--border);
  color: inherit;
  text-decoration: none;
}
.tm-feed-row:last-child { border-bottom: 0; }
.tm-feed-row:hover { background: var(--surface-hover); color: inherit; }
.tm-feed-dir {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px; height: 24px;
  border-radius: var(--radius-round);
  font-size: var(--text-xs);
  flex-shrink: 0;
  margin-top: var(--space-0);
}
.tm-feed-dir.is-in { background: var(--tm-accent-soft); color: var(--tm-accent); }
.tm-feed-dir.is-out { background: var(--surface-hover); color: var(--muted); }
.tm-feed-main { flex: 1; min-width: 0; }
.tm-feed-top { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-2); }
.tm-feed-name { font-weight: 600; font-size: var(--text-sm); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tm-feed-time { font-size: var(--text-2xs); color: var(--faint); flex-shrink: 0; }
.tm-feed-more { font-size: var(--text-2xs); color: var(--faint); font-style: italic; margin-top: var(--space-0); }
.tm-feed-text {
  font-size: var(--text-xs);
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Dy javët: i njëjti grafik i vogël si te paneli, me çiftin e vet të ngjyrave —
   e ardhur dhe e nisur, jo shitje dhe blerje.

   Masat shkruhen me dy klasa (`.tm-overview .mini-chart`), jo me një. Rregullat
   bazë të `.mini-chart` rrinë MË POSHTË në këtë skedar; me peshë të barabartë
   fiton gjithnjë ai që vjen i fundit, pra një `.tm-ov-chart {…}` i vetëm do të
   ishte i saktë, i lexueshëm dhe pa asnjë efekt. */
.tm-overview .mini-chart { height: 108px; gap: var(--space-1); }
.mini-bar.is-in { background: var(--tm-accent); }
.mini-bar.is-out { background: color-mix(in srgb, var(--tm-accent) 34%, transparent); }
.tm-ov-legend { display: flex; align-items: center; gap: var(--space-2); font-size: var(--text-xs); color: var(--muted); }
.tm-legend-key { display: inline-flex; align-items: center; gap: var(--space-1); }
.tm-legend-dot { width: .55rem; height: .55rem; border-radius: var(--radius-round); display: inline-block; }
.tm-legend-dot.is-in { background: var(--tm-accent); }
.tm-legend-dot.is-out { background: color-mix(in srgb, var(--tm-accent) 34%, transparent); }

/* --- Brenda bisedës: ku e le, dhe ku ra syri ------------------------------ */
.tm-newmark {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: var(--space-4) 0 var(--space-2);
  color: var(--danger);
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .07em;
}
.tm-newmark::before, .tm-newmark::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--danger-soft);
}
/* Mesazhi që solli kërkimi: ndizet, pastaj shuhet vetë. Klasa hiqet nga JS-ja
   pas disa sekondash, prandaj kalimi shkruhet mbi vetë rreshtin. */
.tm-msg { transition: background var(--dur-3) var(--ease-out), box-shadow var(--dur-3) var(--ease-out); }
.tm-msg.is-target {
  background: var(--warning-soft);
  box-shadow: inset var(--rail) 0 0 var(--warning);
}

/* --- Messenger responsive: one pane at a time on a phone ------------------- */
@media (max-width: 768px) {
  .tm-shell {
    gap: 0;
    height: calc(100vh - var(--topbar-h) - var(--bottomnav-h) - 2.5rem);
  }
  .tm-sidebar { width: 100%; }
  /* The URL decides which pane is on screen: an open chat shows the chat alone.
     Te faqja e listës, përmbledhja nuk fshihet më — ajo zbret nën listën e
     bisedave dhe faqja rrëshqet si çdo faqe tjetër. Dy kuti me rrëshqitës të
     vetin, njëra brenda tjetrës, janë e vetmja gjë më e keqe se një faqe e gjatë. */
  .tm-shell[data-view="list"] {
    height: auto;
    min-height: 0;
    flex-direction: column;
    gap: var(--space-3);
  }
  .tm-shell[data-view="list"] .tm-sidebar-list,
  .tm-shell[data-view="list"] .tm-overview { overflow-y: visible; max-height: none; }

  /* Kush e hap këtë faqe në telefon e hap për një pyetje: kush pret. Përgjigjja
     rrinte nën një mijë e pesëqind piksela listë — pra e fundit, pas gjithçkaje.
     Por as lista s'mund të zbresë e tëra poshtë: kutia e kërkimit dhe skedat
     rrinë te koka e saj, dhe ato janë vegla e faqes.
     `display: contents` i bën fëmijët e së djathtës motra të listës, pra rendi
     shkruhet mbi ta një nga një: koka dhe kartelat sipër, lista në mes, listat e
     gjata e grafiku poshtë. Asnjë kopje, asnjë shabllon i dytë. */
  .tm-shell[data-view="list"] .tm-main,
  .tm-shell[data-view="list"] .tm-overview { display: contents; }
  .tm-shell[data-view="list"] .tm-stale     { order: -4; }
  .tm-shell[data-view="list"] .tm-ov-head   { order: -3; }
  .tm-shell[data-view="list"] .tm-ov-stats  { order: -2; }
  .tm-shell[data-view="list"] .tm-sidebar   { order: -1; }
  .tm-shell[data-view="list"] .tm-ov-grid,
  .tm-shell[data-view="list"] .tm-overview > .card { order: 0; }
  /* Pa këtë koka e faqes do të ngjitej te kartelat: hapësirën e mbante `gap`-i i
     përmbledhjes, dhe ajo sapo pushoi së qeni kuti. */
  .tm-shell[data-view="list"] .tm-empty-main { order: -1; }

  .tm-shell[data-view="chat"] .tm-sidebar { display: none; }
  .tm-back { display: inline-flex; }
}

@media (max-width: 575.98px) {
  /* Katër kartela njëra mbi tjetrën zinin 423px para se të fillonte puna e
     faqes; dy me dy i lexon syri njësoj dhe e nis listën gjysmë ekrani më lart. */
  .tm-ov-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .tm-ov-head { gap: var(--space-2); }

  /* Grafiku i përgjithshëm rrëshqet anash në telefon, sepse poshtë tij rrinë
     emra muajsh dhe gjashtë sosh s'hyjnë. Këtu poshtë rrinë dy shifra: të
     katërmbëdhjetat hyjnë njëherësh, dhe një grafik që shihet i tëri thotë më
     shumë se një që duhet shtyrë me gisht. */
  .tm-overview .mini-col { min-width: 0; }
  .tm-overview .mini-bars { gap: var(--space-0); }
  .tm-overview .mini-bar { max-width: 10px; }
  .tm-overview .mini-label { font-size: var(--text-2xs); padding-top: var(--space-1); }
  .tm-overview .mini-chart { gap: var(--space-0); }
}

/* --- Today's meetings on the dashboard ------------------------------------ */
.today-card { border-color: var(--primary-line); }
.today-card .card-header {
  background: var(--primary-soft);
  border-bottom-color: var(--primary-line);
}

.today-row {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-4);
}
.today-time {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  font-size: var(--text-md);
  min-width: 3.2rem;
  flex-shrink: 0;
}
.today-main { flex: 1; min-width: 0; }
.today-title { font-weight: 600; }
.today-badge { flex-shrink: 0; }

/* A meeting that already happened should not compete with one still to come. */
/* state-past no longer reaches the dashboard — a finished meeting is dropped
   rather than greyed out — but the calendar still renders rows with it. */
.today-row.state-past { opacity: .5; }
.today-row.state-past .today-title { text-decoration: line-through; }
.today-row.state-soon { background: var(--warning-soft); }
/* Being held right now: the one row on the panel you might have to walk into. */
.today-row.state-ongoing {
  background: var(--success-soft);
  box-shadow: inset var(--rail) 0 0 var(--success);
}
.today-row.state-now {
  background: var(--danger-soft);
  box-shadow: inset var(--rail) 0 0 var(--danger);
}

@media (max-width: 576px) {
  .today-row { flex-wrap: wrap; gap: var(--space-1-5); }
  .today-time { min-width: auto; }
}

/* --- Client file beside the chat ------------------------------------------ */
.tm-layout { display: block; }
.tm-layout.has-panel {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 19rem;
  gap: var(--space-3);
  align-items: stretch;
}

.tm-panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  display: flex;
  flex-direction: column;
  height: calc(100vh - var(--topbar-h) - var(--bottomnav-h) - 5.5rem);
  overflow: hidden;
}
.tm-panel-head {
  padding: var(--space-3);
  border-bottom: 1px solid var(--border);
  background: var(--surface-muted);
  flex-shrink: 0;
}
.tm-panel-head .min-w-0 { min-width: 0; }
.tm-panel-body { flex: 1; overflow-y: auto; padding: var(--space-3); }

.tm-stat {
  border: 1px solid var(--border);
  border-left: 3px solid var(--border-strong);
  border-radius: var(--radius-sm);
  padding: var(--space-2);
  margin-bottom: var(--space-2);
}
.tm-stat.danger { border-left-color: var(--danger); background: var(--danger-soft); }
.tm-stat.warn { border-left-color: var(--warning); background: var(--warning-soft); }
.tm-stat.ok { border-left-color: var(--success); }
.tm-stat-label {
  font-size: var(--text-2xs);
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--muted);
  font-weight: 700;
}
.tm-stat-value { font-size: var(--text-xl); font-weight: 700; line-height: 1.2; }
.tm-stat.danger .tm-stat-value { color: var(--danger); }
.tm-stat-note { font-size: var(--text-2xs); color: var(--muted); }

.tm-panel-section {
  border-top: 1px solid var(--border);
  padding-top: var(--space-2);
  margin-top: var(--space-2);
}
.tm-panel-title {
  font-size: var(--text-2xs);
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--muted);
  font-weight: 700;
  margin-bottom: var(--space-1-5);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-1-5);
}
.tm-panel-row {
  display: flex;
  justify-content: space-between;
  gap: var(--space-2);
  padding: var(--space-1) 0;
  font-size: var(--text-xs);
  color: inherit;
  text-decoration: none;
}
a.tm-panel-row:hover { color: var(--tm-accent); }
.tm-panel-row-main { min-width: 0; flex: 1; }
.tm-panel-row-side { flex-shrink: 0; font-variant-numeric: tabular-nums; }
.tm-panel-kv { font-size: var(--text-xs); word-break: break-word; }

/* Internal notes look different on purpose: the client is in this very group,
   and someone may be sharing their screen. */
.tm-panel-private {
  background: var(--warning-soft);
  border-radius: var(--radius-sm);
  padding: var(--space-2);
  border-top: 0;
  margin-top: var(--space-2);
}

.tm-panel-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
  margin-top: var(--space-3);
  padding-top: var(--space-2);
  border-top: 1px solid var(--border);
}
.tm-panel-actions .btn { font-size: var(--text-2xs); padding: var(--space-1) var(--space-2); }

/* Below a laptop the panel would squeeze the chat, so it moves underneath. */
@media (max-width: 1100px) {
  .tm-layout.has-panel { grid-template-columns: 1fr; }
  .tm-panel { height: auto; max-height: 26rem; }
}

/* --- Tax deadlines --------------------------------------------------------- */
.deadline-card { border-color: rgba(220, 38, 38, .25); }
.deadline-card .card-header {
  background: var(--danger-soft);
  border-bottom-color: rgba(220, 38, 38, .15);
}

.deadline-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}
.deadline-when {
  min-width: 3.4rem;
  flex-shrink: 0;
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.deadline-main { flex: 1; min-width: 0; }

/* Urgency reads at a glance: the bar is the signal, colour alone is not. */
tr.deadline-row { display: table-row; }
.deadline-row.state-late { box-shadow: inset var(--rail) 0 0 var(--danger-fill-strong); background: rgba(220, 38, 38, .05); }
.deadline-row.state-urgent { box-shadow: inset var(--rail) 0 0 var(--urgent); background: var(--urgent-soft); }
.deadline-row.state-soon { box-shadow: inset var(--rail) 0 0 var(--warning-fill-strong); }
.deadline-row.state-done { opacity: .55; }

tr.deadline-row.state-late > td:first-child { border-left: 3px solid var(--danger-fill-strong); }
tr.deadline-row.state-urgent > td:first-child { border-left: 3px solid var(--urgent); }
tr.deadline-row.state-soon > td:first-child { border-left: 3px solid var(--warning-fill-strong); }
tr.deadline-row.state-late { background: rgba(220, 38, 38, .04); }

@media (max-width: 576px) {
  .deadline-row { flex-wrap: wrap; }
}

/* --- Visual tax calendar: a month grid with status dots ------------------- */
.view-toggle .btn { font-weight: 600; }

.cal-nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  margin-bottom: var(--space-4);
}
.cal-title {
  font-family: 'Sora Variable', 'Inter Variable', Inter, sans-serif;
  font-weight: 700;
  font-size: var(--text-lg);
  min-width: 11rem;
  text-align: center;
}

.tax-calendar {
  width: 100%;
  min-width: 44rem;
  border-collapse: separate;
  border-spacing: 0;
  table-layout: fixed;
}
.tax-calendar th {
  padding: var(--space-2);
  text-align: center;
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--muted);
  font-weight: 600;
}
.tax-cal-cell {
  vertical-align: top;
  height: 6.5rem;
  width: 14.28%;
  border: 1px solid var(--border);
  padding: var(--space-1-5);
  background: var(--surface);
}
.tax-cal-cell.out { background: var(--surface-muted); }
.tax-cal-cell.out .tax-cal-daynum { opacity: .4; }
.tax-cal-cell.today {
  outline: 2px solid var(--primary);
  outline-offset: -2px;
  background: var(--primary-soft);
}
.tax-cal-daynum { font-size: var(--text-sm); font-weight: 600; color: var(--muted); }
.tax-cal-cell.today .tax-cal-daynum { color: var(--primary); }
.tax-cal-item {
  display: flex;
  align-items: center;
  gap: var(--space-1-5);
  margin-top: var(--space-1);
  font-size: var(--text-xs);
  line-height: 1.2;
}
.tax-cal-item:hover .tax-cal-item-text { color: var(--primary); }
.tax-cal-item-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tax-cal-more { font-size: var(--text-2xs); color: var(--faint); margin-top: var(--space-1); }

.tax-dot {
  width: .6rem;
  height: .6rem;
  border-radius: var(--radius-round);
  flex-shrink: 0;
  display: inline-block;
}
.tax-dot.state-late   { background: var(--danger-fill-strong); }
.tax-dot.state-urgent { background: var(--urgent); }
.tax-dot.state-soon   { background: var(--warning-fill-strong); }
.tax-dot.state-ahead  { background: var(--success-fill-strong); }
.tax-dot.state-done   { background: var(--primary); }

.cal-legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: 1px solid var(--border);
  font-size: var(--text-xs);
  color: var(--muted);
}
.cal-legend span { display: inline-flex; align-items: center; gap: var(--space-1-5); }
.cal-legend .cal-legend-sep { margin-left: var(--space-2); padding-left: var(--space-4); border-left: 1px solid var(--border); }

/* --- Ku ka mbetur periudha --------------------------------------------------
   Një rresht për detyrim: emri, periudha mbi të cilën po punohet, shiriti i
   mbylljes, dhe sa mungojnë. Rrjeta ka gjerësi të emëruara e jo `auto`, që dy
   rreshta të njëpasnjëshëm t'i kenë shiritat të nisur nga i njëjti vend —
   përndryshe syri krahason gjatësi që nisin në kolona të ndryshme. */
.dek-cover { display: grid; gap: var(--space-2); }
.dek-cover-row {
  display: grid;
  grid-template-columns: minmax(6rem, 1.4fr) auto minmax(4rem, 1fr) auto;
  grid-template-areas: 'name period bar num' 'note note note note';
  align-items: center;
  gap: var(--space-1-5) var(--space-3);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  color: inherit;
  text-decoration: none;
  transition: border-color var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease-out);
}
.dek-cover-row:hover { border-color: var(--primary-line); box-shadow: var(--shadow-sm); }
.dek-cover-row:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }
.dek-cover-name {
  grid-area: name;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dek-cover-period {
  grid-area: period;
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
  color: var(--muted);
}
.dek-cover-bar {
  grid-area: bar;
  height: .5rem;
  border-radius: var(--radius-pill);
  background: var(--surface-muted);
  box-shadow: inset 0 0 0 var(--hairline) var(--border);
  overflow: hidden;
  position: relative;
}
/* `--bar` është e vetmja gjë që e di serveri: sa përqind e periudhës u mbyll. */
.dek-cover-bar::before {
  content: '';
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--bar, 0%);
  border-radius: inherit;
  background: var(--primary);
}
.dek-cover-num {
  grid-area: num;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  font-size: var(--text-sm);
}
.dek-cover-note { grid-area: note; font-size: var(--text-xs); color: var(--faint); }
/* Ngjyra e shiritit thotë sa larg është afati, jo sa u mbyll — një periudhë
   gjysmë e mbyllur me afat nesër dhe një me afat pas njëzet ditësh janë dy
   gjendje krejt të ndryshme, dhe shifra 50% e njëjtë te të dyja. */
.dek-cover-row.state-late .dek-cover-bar::before { background: var(--danger-fill-strong); }
.dek-cover-row.state-urgent .dek-cover-bar::before { background: var(--urgent); }
.dek-cover-row.state-soon .dek-cover-bar::before { background: var(--warning-fill-strong); }
.dek-cover-row.state-done .dek-cover-bar::before { background: var(--success-fill-strong); }
.dek-cover-row.state-late { border-color: var(--danger-fill); }
.dek-cover-row.state-done { opacity: .7; }

/* --- Tridhjetë ditët që vijnë ----------------------------------------------
   Kalendari mban një muaj dhe kërkon rrëshqitje; ky rrip hyn në një rresht.
   Qelizat kanë `align-items: end`, pra shtyllat rriten nga poshtë lart — një
   histogram i lexohet vetëm kur të gjitha nisin nga e njëjta vijë. */
.dek-load {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  align-items: end;
  gap: var(--space-0);
  /* Rreshti shkruhet, nuk lihet `auto` me një `height` mbi kontejnerin: lartësia
     e qelizës është përqindje, dhe një përqindje mbi një gjurmë të papërcaktuar
     lejohet të lexohet si `auto` — pra i tërë rripi do të shtypej në dy piksela
     pa e thënë asnjë provë. Me gjurmë të shkruar, ajo është e përcaktuar. */
  grid-template-rows: 3.25rem;
}
.dek-load-cell {
  display: block;
  height: max(2px, var(--bar, 0%));
  min-height: 2px;
  border-radius: var(--radius-xs) var(--radius-xs) 0 0;
  background: var(--success-fill-strong);
  transition: filter var(--dur-1) var(--ease-out);
}
.dek-load-cell:hover { filter: brightness(1.15); }
.dek-load-cell:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }
.dek-load-cell.state-urgent { background: var(--urgent); }
.dek-load-cell.state-soon { background: var(--warning-fill-strong); }
/* Dita bosh mbetet e dukshme si vijë: një rrip me boshllëqe duket i grisur, dhe
   një ditë pa afate është vetë e dhëna që kërkohet. */
.dek-load-cell.is-empty { background: var(--border); }
.dek-load-foot {
  display: flex;
  justify-content: space-between;
  margin-top: var(--space-1-5);
  font-size: var(--text-xs);
  color: var(--faint);
  font-variant-numeric: tabular-nums;
}

/* --- Ç'bie në sy te deklarimet ----------------------------------------------
   I njëjti komponent si te Hyrjet dhe te historiku privat: `.dek-signal*` rrinë
   te po ata selektorë (shih `.hist-signal`, seksioni më poshtë) e nuk i kopjojnë
   deklaratat. Këtu ndryshon vetëm gjerësia e kolonës, sepse ky është shirit
   anësor e jo faqe e plotë — dhe ngushtimi shkruhet me dy klasa me qëllim:
   rregulli i përbashkët rri NËN këtë vend te skedari, pra një `.dek-signals` i
   thjeshtë do të ishte i saktë dhe nuk do të bënte asgjë. */
.page-aside .dek-signals { grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr)); }

/* --- Zgjedhja dhe veprimi në grup ------------------------------------------
   Shiriti rri i fshehur derisa zgjidhet diçka, dhe atëherë ngjitet në fund të
   ekranit: zyra shënon njëzet rreshta duke rrëshqitur listën, dhe një shirit që
   ikën lart me rrëshqitjen do të kërkonte kthim çdo herë. */
.dek-pick { width: 2.25rem; text-align: center; }
.dek-pick .form-check-input { margin: 0; vertical-align: middle; }
.dek-bulk-bar {
  position: sticky;
  bottom: var(--space-3);
  z-index: 3;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-3);
  padding: var(--space-3);
  border: 1px solid var(--primary-line);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow-md);
}
.dek-bulk-bar[hidden] { display: none; }
.dek-bulk-count { font-size: var(--text-sm); color: var(--muted); }
.dek-bulk-count strong { font-variant-numeric: tabular-nums; color: var(--text); }
.dek-bulk-ref { max-width: 12rem; }
/* Numri i protokollit: shifra që e ndan «e dorëzuar» nga «thonë se e dorëzuan». */
.dek-ref {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

@media (max-width: 575.98px) {
  /* Te telefoni tabela bëhet kartelë, dhe shiriti i ngjitur do të mbulonte
     rreshtin e fundit; aty ai rri thjesht në fund të listës. */
  .dek-bulk-bar { position: static; }
  .dek-cover-row { grid-template-columns: 1fr auto; grid-template-areas: 'name num' 'period num' 'bar bar' 'note note'; }
}

/* --- Appointments on the month grid: a filled pill, coloured by status ---- */
.cal-event {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  margin-top: var(--space-1);
  padding: var(--space-0) var(--space-1-5);
  border-radius: var(--radius-sm);
  font-size: var(--text-xs);
  line-height: 1.25;
  background: var(--surface-muted);
  border-left: 3px solid var(--faint);
  overflow: hidden;
}
.cal-event-time { font-weight: 700; flex-shrink: 0; font-variant-numeric: tabular-nums; }
.cal-event-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.cal-event.state-now      { border-left-color: var(--danger-fill-strong); background: rgba(220, 38, 38, .10); }
.cal-event.state-today    { border-left-color: var(--primary); background: var(--primary-soft); }
.cal-event.state-soon     { border-left-color: var(--warning-fill-strong); background: rgba(217, 119, 6, .10); }
.cal-event.state-upcoming { border-left-color: var(--success-fill-strong); background: var(--success-soft); }
.cal-event.state-past     { border-left-color: var(--faint); opacity: .6; }

/* Tax deadlines ride the same grid but read as a lighter, dashed overlay so
   they never look like a meeting the office booked. */
.cal-event.is-afat {
  background: transparent;
  border-left-style: dashed;
  border-left-color: var(--border);
}
.cal-event.is-afat:hover .cal-event-text { color: var(--primary); }

/* The legend's little colour chips, one per appointment state. */
.cal-swatch {
  width: .7rem;
  height: .7rem;
  border-radius: var(--radius-xs);
  flex-shrink: 0;
  display: inline-block;
  background: var(--faint);
}
.cal-swatch.state-now      { background: var(--danger-fill-strong); }
.cal-swatch.state-today    { background: var(--primary); }
.cal-swatch.state-soon     { background: var(--warning-fill-strong); }
.cal-swatch.state-upcoming { background: var(--success-fill-strong); }
.cal-swatch.state-past     { background: var(--faint); }

/* ============================================================================
   6b. Bootstrap surfaces the tokens cannot reach by inheritance — retinted
   here once, so pages built on stock utility classes still speak the brand.
   ========================================================================= */

.alert { border-radius: var(--radius); border: 1px solid transparent; }
.alert-danger  { background: var(--danger-soft);  color: var(--danger);  border-color: rgba(220,38,38,.22); }
.alert-warning { background: var(--warning-soft); color: var(--warning); border-color: rgba(245,158,11,.25); }
.alert-success { background: var(--success-soft); color: var(--success); border-color: rgba(16,185,129,.25); }
.alert-info    { background: var(--info-soft);    color: var(--info);    border-color: rgba(14,165,233,.25); }
.alert-secondary { background: var(--surface-muted); color: var(--muted); border-color: var(--border); }
.alert .alert-link { color: inherit; font-weight: 700; }
.alert-heading { color: inherit; }

/* Deadline reminder: a warning-toned banner with a boxed alert icon, used at
   the top of the VAT page. Same amber gradient as the .stat-warning icon. */
.deadline-banner {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-4);
  border-radius: var(--radius-lg);
  background: var(--warning-soft);
  border: 1px solid rgba(245,158,11,.28);
  color: var(--text);
}
.deadline-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  flex-shrink: 0;
  border-radius: var(--radius);
  background: linear-gradient(135deg,var(--warning-fill-strong),var(--warning-fill));
  color: #fff;
  font-size: var(--text-lg);
  box-shadow: var(--glow-warning);
}
.deadline-title { font-weight: 700; line-height: 1.35; }
.deadline-text { font-size: var(--text-sm); color: var(--muted); margin-top: var(--space-0); }
/* Kutia e mban të verdhën e kujtesës derisa afati të afrohet vërtet; atëherë e
   thotë me ngjyrë, jo vetëm me numër. */
.deadline-copy { flex: 1; min-width: 0; }
.deadline-banner-soon { border-color: var(--warning-fill-strong); }
.deadline-banner-late {
  background: var(--danger-soft);
  border-color: var(--danger-fill);
}
.deadline-banner-late .deadline-icon {
  background: linear-gradient(135deg,var(--danger-fill-strong),var(--danger-fill));
  box-shadow: var(--glow-danger);
}

/* --- Kontrolli para deklarimit (Pasqyra e TVSH-së) ------------------------
   Secili rresht është një lidhje drejt faturave që e shkaktuan — një listë që
   thotë «tri fatura pa NUI» dhe s'të çon dot tek ato është një listë që duhet
   punuar dy herë. */
.check-card { border-top: 3px solid var(--border); }
.check-card-critical { border-top-color: var(--danger-fill); }
.check-card-warning { border-top-color: var(--warning-fill); }
.check-card-clear { border-top-color: var(--success-fill); }
.check-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: var(--space-2);
}
.check-item {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-3);
  border-radius: var(--radius-sm);
  background: var(--surface-hover);
  border-left: 3px solid var(--border);
  text-decoration: none;
  color: inherit;
  transition: background var(--dur-2) var(--ease-out), transform var(--dur-2) var(--ease-out);
}
.check-item:hover { background: var(--surface-muted); color: inherit; transform: translateX(2px); }
.check-critical { border-left-color: var(--danger-fill); }
.check-warning { border-left-color: var(--warning-fill); }
.check-info { border-left-color: var(--primary); }
.check-icon {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 1.9rem;
  height: 1.9rem;
  border-radius: var(--radius-sm);
  background: var(--surface);
  font-size: var(--text-md);
}
.check-critical .check-icon { color: var(--danger); }
.check-warning .check-icon { color: var(--warning); }
.check-info .check-icon { color: var(--primary-text); }
.check-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: var(--space-0); }
.check-title { font-weight: 600; font-size: var(--text-md); }
.check-count {
  display: inline-block;
  min-width: 1.4rem;
  padding: 0 var(--space-1-5);
  margin-left: var(--space-1);
  border-radius: var(--radius-pill);
  background: var(--surface);
  border: 1px solid var(--border);
  font-size: var(--text-xs);
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.check-text { font-size: var(--text-sm); color: var(--muted); line-height: 1.35; }
.check-sample {
  font-size: var(--text-xs);
  color: var(--faint);
  font-variant-numeric: tabular-nums;
}
.check-go { color: var(--faint); align-self: center; font-size: var(--text-sm); }
/* Shenja e zbatuar. Një kartelë që ka ngushtuar listën poshtë duhet ta thotë ku
   rri, përndryshe njeriu e klikon të dytën dhe beson se e para nuk punoi. */
.check-item.check-on {
  background: var(--surface-muted);
  box-shadow: inset 0 0 0 var(--hairline) var(--primary);
}
.check-item.check-on .check-go { color: var(--primary-text); }

/* --- Afati dhe deklarimi, në një bllok ------------------------------------
   Dy gjysma të së njëjtës pyetje — «deri kur» dhe «a u bë» — që deri sot i
   ndante gjithë faqja: e para lart, e dyta 1.458px poshtë, mes dy tabelash.
   `min(…, 100%)` te minimumi është i detyrueshëm: pa të një shtyllë 24rem e
   mban gjerësinë e vet edhe në ekran 390px dhe rrjeta del jashtë faqes. */
.vat-now {
  display: grid;
  grid-template-columns: minmax(min(24rem, 100%), 1.3fr) minmax(min(19rem, 100%), 1fr);
  gap: var(--space-4);
  align-items: stretch;
  margin-bottom: var(--space-4);
}
@media (max-width: 62rem) {
  .vat-now { grid-template-columns: 1fr; }
}
/* Hapësira e bllokut e mban rrjeta; kujtesa nuk shton të sajën mbi të. */
.vat-now > .deadline-banner { margin-bottom: 0; }
.vat-file { margin-bottom: 0; }
.vat-file > .card-body { display: flex; flex-direction: column; justify-content: center; }
/* Pilulat e periudhës rrinë nën formularin që i shpjegon, pa hapësirën e vet
   poshtë: karta e mbyll bllokun. */
.filter-quick.vat-quick { margin-bottom: 0; margin-top: var(--space-3); }

/* --- Kutitë e formularit TV -----------------------------------------------
   Pasqyra jepte tri shifra dhe ndarja e tyre nëpër gjashtëdhjetë kutitë e
   formularit bëhej me dorë, mbi një ekran të dytë. Rreshti është kuti–emër–vlerë,
   dhe kur letra e deklaratës rri në dosje shtohen dy shtylla: sa u dorëzua dhe
   sa ndryshon. Rrjetë e jo tabelë, sepse në telefon një tabelë me pesë shtylla
   bëhet dymbëdhjetë kartela njëra mbi tjetrën. */
.vat-boxes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(22rem, 100%), 1fr));
  gap: var(--space-4);
  align-items: start;
}
.vat-box-group { min-width: 0; }
.vat-box {
  display: grid;
  grid-template-columns: 2.6rem minmax(0, 1fr) auto;
  align-items: baseline;
  column-gap: var(--space-2);
  padding: var(--space-1-5) 0;
  border-bottom: 1px solid var(--border);
}
.vat-box:last-child { border-bottom: 0; }
.vat-box-no {
  font-size: var(--text-xs);
  font-weight: 700;
  color: var(--faint);
  font-variant-numeric: tabular-nums;
}
.vat-box-label {
  font-size: var(--text-sm);
  color: var(--muted);
  line-height: 1.3;
  min-width: 0;
}
/* Sa fatura e mbushën këtë kuti. Pa të, një bazë e vetme dhe njëqind fatura të
   mbledhura duken njësoj — dhe vetëm njëra nga të dyja pyetet te kontrolli. */
.vat-box-count {
  display: block;
  font-size: var(--text-xs);
  color: var(--faint);
  font-variant-numeric: tabular-nums;
}
.vat-box-value { font-size: var(--text-sm); }
.vat-box-total {
  border-bottom: 0;
  border-top: 1px solid var(--border);
  margin-top: var(--space-1);
  padding-top: var(--space-2);
}
.vat-box-total .vat-box-label { color: var(--text); font-weight: 600; }
.vat-box-total .vat-box-value { font-size: var(--text-md); font-weight: 700; }
/* Me deklaratën përballë rreshti bëhet pesë-shtyllësh. Numri i shtyllave rri te
   kjo klasë e jo te vetë rreshti, që një kuti pa deklaratë të mos lërë dy boshe. */
.vat-box:has(.vat-box-filed) {
  grid-template-columns: 2.6rem minmax(0, 1fr) auto auto 3.2rem;
}
.vat-box-filed { font-size: var(--text-sm); text-align: right; min-width: 4.5rem; }
.vat-box-delta { font-size: var(--text-sm); text-align: right; }
/* Kutia që s'përputhet me atë që u dorëzua. Ngjyra rri te shifra, jo te tërë
   rreshti: rreshti është ende i saktë, vetëm ndryshimi është ai që pyetet. */
.vat-box-diff .vat-box-no { color: var(--danger); }

/* Ç'mbetet për dorën e njeriut, me arsyen përbri. Një listë «plotësoji vetë»
   pa arsye lexohet si mungesë e programit; me arsyen lexohet si kufi i librit. */
.vat-manual { display: grid; gap: var(--space-2); }
.vat-manual-row {
  display: grid;
  grid-template-columns: minmax(0, 11rem) minmax(0, 1fr);
  column-gap: var(--space-3);
  align-items: baseline;
}
@media (max-width: 48rem) {
  .vat-manual-row { grid-template-columns: 1fr; }
}
.vat-manual-boxes {
  font-size: var(--text-xs);
  font-weight: 700;
  color: var(--primary-text);
  font-variant-numeric: tabular-nums;
}
.vat-manual-body { min-width: 0; }
.vat-manual-title { display: block; font-size: var(--text-sm); font-weight: 600; }
.vat-manual-why {
  display: block;
  font-size: var(--text-xs);
  color: var(--muted);
  line-height: 1.4;
}

.text-primary { color: var(--primary) !important; }
.border-primary { border-color: var(--primary) !important; }
.btn-link { color: var(--primary-text); }
.btn-link:hover { color: var(--primary); }

.progress { background-color: var(--surface-muted); border-radius: var(--radius-pill); }
.progress-bar { background-color: var(--primary); background-image: var(--grad-primary); }

.nav-pills .nav-link { color: var(--muted); }
.nav-pills .nav-link.active {
  background: var(--grad-primary);
  color: #fff;
}
.nav-tabs { border-bottom-color: var(--border); }
.nav-tabs .nav-link { color: var(--muted); }
.nav-tabs .nav-link:hover { border-color: var(--border) var(--border) transparent; }
.nav-tabs .nav-link.active {
  color: var(--primary-text);
  background-color: transparent;
  border-color: var(--border) var(--border) var(--surface);
}

/* Dosjet sipas kategorive — te arkivi i nje klienti, cdo kategori eshte nje
   dosje qe hapet me nje klik. Gjithnje te dukshme, edhe bosh, qe stafi te shohe
   cdo sirtar para se ta mbushe. */
.folder-tab {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1-5);
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--muted);
  border-radius: var(--radius) var(--radius) var(--radius-sm) var(--radius-sm);
  font-weight: 600;
  transition: color var(--dur-2) var(--ease-out), border-color var(--dur-2) var(--ease-out), background var(--dur-2) var(--ease-out);
}
.folder-tab:hover {
  color: var(--text);
  border-color: var(--accent);
}
.folder-tab.active {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
}
.folder-tab .chip { border-color: transparent; }
.folder-tab.empty { opacity: .6; }
.folder-tab.empty:hover { opacity: 1; }

/* Kartat e KPI-ve te ndjekja e dokumenteve punojne edhe si filter i shpejte. */
.kpi-card { cursor: pointer; }
.kpi-card.kpi-active {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Historiku privat: krahasimi vizual i vleres se vjeter me te ren. */
.history-diff { font-size: var(--text-sm); }
.history-diff td, .history-diff th { vertical-align: top; word-break: break-word; }
.history-diff-changed { background: var(--warning-soft); }
.history-diff-changed .history-old {
  color: var(--danger);
  text-decoration: line-through;
  text-decoration-color: rgba(220, 38, 38, .4);
}
.history-diff-changed .history-new { color: var(--success); font-weight: 600; }

/* Vetem fushat qe levizen. Nje rekord me tridhjete fusha qe ndryshoi njeren e
   fsheh ndryshimin brenda vetes; ky celes e le vetem ate. */
.hist-only-changed .history-diff-same { display: none; }

/* Muaji i fundit, dite per dite. Nje shirit shtyllash i bere me dore: pa
   biblioteke grafiku per tridhjete numra, dhe secila shtylle eshte nje lidhje
   qe e kufizon faqen te ajo dite. */
.hist-spark {
  display: flex;
  align-items: flex-end;
  gap: var(--space-0);
  height: 68px;
}
.hist-spark-col {
  flex: 1 1 0;
  display: flex;
  align-items: flex-end;
  height: 100%;
  min-width: 0;
  border-radius: var(--radius-xs);
  transition: background var(--dur-2) var(--ease-out);
}
.hist-spark-col:hover { background: var(--surface-muted); }
.hist-spark-col:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
.hist-spark-bar {
  display: block;
  width: 100%;
  min-height: 3px;
  border-radius: var(--radius-xs) var(--radius-xs) 0 0;
  background: var(--border);
}
.hist-spark-col.has-hits .hist-spark-bar { background: var(--grad-primary); }
.hist-spark-axis {
  display: flex;
  justify-content: space-between;
  gap: var(--space-2);
  margin-top: var(--space-2);
  font-size: var(--text-xs);
  color: var(--faint);
}

/* Ç'bie në sy: katër shifra që lexohen para listës, dhe dy lista dëshmish nën
   to. Rrinë si kuti të veçanta e jo si kartat lart, sepse ato thonë sa ka gjurma
   — këto thonë çfarë duhet hapur i pari.

   Dy faqe e bëjnë tani të njëjtën pyetje mbi dy gjurmë të ndryshme — historiku
   privat dhe hyrjet — prandaj emrat e të dytës rrinë te po këta selektorë e nuk
   i kopjojnë deklaratat. `.hist-*` mbeti si emër sepse aty u shkrua i pari dhe
   shabllonet e provat e njohin me atë emër; `.io-*` është i njëjti komponent te
   faqja e Hyrjeve. */
.hist-signals,
.io-signals,
.dek-signals,
.cl-signals,
.inv-signals {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: var(--space-3);
}
.hist-signal,
.io-signal,
.dek-signal,
.cl-signal,
.inv-signal {
  padding: var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
}
/* I ngrohtë kur ka diçka për t'u parë, i nxehtë kur ajo s'kthehet mbrapsht.
   Një kuti me zero mbetet e qetë: alarmi që bie gjithmonë nuk dëgjohet kurrë. */
.hist-signal.is-warm,
.io-signal.is-warm,
.dek-signal.is-warm,
.cl-signal.is-warm,
.inv-signal.is-warm { border-color: var(--warning-fill); }
.hist-signal.is-hot,
.io-signal.is-hot,
.dek-signal.is-hot,
.cl-signal.is-hot,
.inv-signal.is-hot { border-color: var(--danger-fill); }
.hist-signal-top,
.io-signal-top,
.dek-signal-top,
.cl-signal-top,
.inv-signal-top {
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--muted);
  display: flex;
  align-items: center;
  gap: var(--space-1-5);
}
.hist-signal-value,
.io-signal-value,
.dek-signal-value,
.cl-signal-value,
.inv-signal-value {
  font-family: 'Sora Variable', 'Inter Variable', Inter, sans-serif;
  font-size: var(--text-2xl);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
  margin-top: var(--space-1);
}
.hist-signal-value a,
.cl-signal-note a { color: inherit; text-decoration: none; }
.hist-signal-value a:hover,
.cl-signal-note a:hover { text-decoration: underline; }
.hist-signal-delta { font-size: var(--text-sm); font-weight: 600; color: var(--muted); }
.hist-signal-delta.up { color: var(--warning-fill); }
.hist-signal-delta.down { color: var(--success-fill); }
.hist-signal-note,
.io-signal-note,
.dek-signal-note,
.cl-signal-note,
.inv-signal-note {
  font-size: var(--text-xs);
  color: var(--faint);
  margin-top: var(--space-1);
}
.hist-signal-list,
.io-evidence,
.dek-evidence,
.cl-evidence { margin-top: var(--space-3); }
.hist-signal-list-title,
.io-evidence-title,
.dek-evidence-title,
.cl-evidence-title {
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--muted);
}

/* Ora e ditës: njëzet e katër shtylla nën atë të ditëve. Orët e mbylljes kanë
   ngjyrën e tyre — një shtyllë e lartë aty është vetë sinjali. */
.hist-hours { border-top: 1px solid var(--border); padding-top: var(--space-3); }
.hist-hours-title { font-size: var(--text-xs); font-weight: 600; margin-bottom: var(--space-2); }
.hist-hours-grid {
  display: flex;
  align-items: flex-end;
  gap: var(--space-0);
  height: 46px;
}
.hist-hour {
  flex: 1 1 0;
  display: flex;
  align-items: flex-end;
  height: 100%;
  min-width: 0;
}
.hist-hour-bar {
  display: block;
  width: 100%;
  min-height: 2px;
  border-radius: var(--radius-xs) var(--radius-xs) 0 0;
  background: var(--grad-primary);
}
.hist-hour.is-night .hist-hour-bar {
  background: linear-gradient(180deg, var(--warning-fill-strong), var(--warning-fill));
}
.hist-hours-axis {
  display: flex;
  justify-content: space-between;
  margin-top: var(--space-1-5);
  font-size: var(--text-xs);
  color: var(--faint);
}

/* Kush çfarë bën. Numrat lexohen kolonë më kolonë, prandaj janë me gjerësi të
   njëjtë shifrash — përndryshe syri i krahason gjatësitë, jo vlerat. */
.hist-matrix td, .hist-matrix th { font-size: var(--text-sm); }
.hist-matrix td.text-end { font-variant-numeric: tabular-nums; }
.hist-matrix a { text-decoration: none; }
.hist-matrix a:hover { text-decoration: underline; }

/* Fjala e gjetur brenda rreshtit. E verdha e shfletuesit mbi një sfond të errët
   është një bllok drite; këtu mbetet teksti, vetëm i ndezur. */
.hist-entry mark {
  background: color-mix(in srgb, var(--primary) 22%, transparent);
  color: inherit;
  border-radius: var(--radius-xs);
  padding: 0 .1em;
}

/* Rreshtat e facetave nen kerkimin: periudha, veprimi, lloji. */
.hist-facet-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-1-5);
}
.hist-facet-label {
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--muted);
  min-width: 5.5rem;
}
.hist-facet-count {
  margin-left: var(--space-1-5);
  padding: 0 var(--space-1);
  border-radius: var(--radius-pill);
  background: var(--surface-muted);
  font-size: var(--text-2xs);
  font-weight: 700;
}
.chip-primary .hist-facet-count { background: rgba(255, 255, 255, .35); }

/* Tab-et e vjetra rrine te palosura: sot puna behet me facetat lart. */
.hist-quick-summary {
  cursor: pointer;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--muted);
  list-style: none;
}
.hist-quick-summary::-webkit-details-marker { display: none; }
.hist-quick-summary::before {
  content: "\f285";
  font-family: "bootstrap-icons";
  margin-right: var(--space-1-5);
  font-size: .7em;
  display: inline-block;
  transition: transform var(--dur-2) var(--ease-out);
}
.hist-quick[open] .hist-quick-summary::before { transform: rotate(90deg); }

.hist-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-1-5);
}

/* Titulli i dites. Regjistri lexohet si ditar, jo si nje shtylle e vetme pa
   fund — dhe titulli rri ngjitur lart derisa dita te mbarojë. */
.hist-day {
  position: sticky;
  top: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: var(--space-4) 0 var(--space-2);
  padding: var(--space-1) 0;
  background: var(--surface);
}
.hist-day:first-child { margin-top: 0; }
.hist-day-label {
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--muted);
}
.hist-day-count {
  font-size: var(--text-xs);
  font-weight: 700;
  color: var(--faint);
  padding: var(--space-0) var(--space-1-5);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
}
.hist-day::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--border);
}

/* Pika e ngjarjes e merr ngjyren nga veprimi: fshirja duket e kuqe qe nga skaji
   i majte, pa u lexuar asnje fjale. */
.hist-tone-danger::before  { border-color: var(--danger); }
.hist-tone-success::before { border-color: var(--success); }
.hist-tone-warning::before { border-color: var(--warning); }
.hist-tone-info::before    { border-color: var(--info); }
.hist-entry-main { min-width: 0; }
.hist-entry-side { flex-shrink: 0; }
.hist-entry-links {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
}
.hist-link {
  font-size: var(--text-xs);
  color: var(--muted);
  text-decoration: none;
  border-bottom: 1px dashed var(--border);
}
.hist-link:hover { color: var(--primary); border-bottom-color: var(--primary-line); }

.hist-pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  margin-top: var(--space-4);
}
.hist-pager-mid { font-size: var(--text-sm); font-weight: 600; color: var(--muted); }
.hist-pagesize {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-1-5);
  margin-top: var(--space-2);
}

/* Dropdown pop: Bootstrap only flips display, so the animation rides .show. */
.dropdown-menu.show { animation: dropIn var(--dur-2) var(--ease-out); }
@keyframes dropIn {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: none; }
}

/* ============================================================================
   6c. Shell extras: collapsible mini sidebar, navigation progress bar,
       cross-document transitions.
   ========================================================================= */

/* Mini rail: the same sidebar at icon width. The nav labels are bare text
   nodes after the icon, so font-size carries the hiding — a wrapper span for
   every label would mean touching all the templates again. Desktop only; the
   phone drawer keeps its full width. */
@media (min-width: 992px) {
  body.sidebar-mini .app-sidebar { width: 84px; }
  body.sidebar-mini .app-sidebar .brand-word,
  body.sidebar-mini .app-sidebar .sidebar-section-title,
  body.sidebar-mini .app-sidebar .group-nav-title,
  body.sidebar-mini .app-sidebar .group-empty,
  body.sidebar-mini .app-sidebar .group-name,
  body.sidebar-mini .app-sidebar .group-unread,
  body.sidebar-mini .app-sidebar .sidebar-badge,
  body.sidebar-mini .app-sidebar .sidebar-user-name,
  body.sidebar-mini .app-sidebar .sidebar-user-role { display: none; }
  body.sidebar-mini .app-sidebar .nav-link {
    font-size: 0;
    justify-content: center;
    gap: 0;
    padding: var(--space-2) var(--space-1-5);
  }
  body.sidebar-mini .app-sidebar .nav-link i { font-size: var(--text-lg); }
  body.sidebar-mini .app-sidebar .group-link { font-size: 0; }
  body.sidebar-mini .app-sidebar .group-hash { font-size: var(--text-base); opacity: .7; }
  /* «Grup i ri» mbetet, por vetëm si plus: teksti do ta shtrinte shiritin. */
  body.sidebar-mini .app-sidebar .sidebar-add {
    font-size: 0;
    justify-content: center;
    gap: 0;
  }
  body.sidebar-mini .app-sidebar .sidebar-add i { font-size: var(--text-base); }
  body.sidebar-mini .sidebar-head { flex-direction: column; gap: var(--space-2); padding: var(--space-3) var(--space-2); }
  body.sidebar-mini .sidebar-user { justify-content: center; padding: var(--space-2) var(--space-1); }
  body.sidebar-mini .sidebar-user > .icon-btn { display: none; }
  body.sidebar-mini #sidebar-collapse-btn i { transform: rotate(180deg); }
}
#sidebar-collapse-btn i { transition: transform var(--dur-2) var(--ease-out); }

/* --- Dashboard bar chart (pure CSS, data heights inline from Jinja) -------- */
.chart {
  display: flex;
  align-items: flex-end;
  gap: var(--space-2);
  height: 200px;
  padding-top: var(--space-2);
}
.chart-col {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  height: 100%;
}
.chart-bars {
  flex: 1;
  width: 100%;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: var(--space-1);
}
.chart-bar {
  width: clamp(14px, 40%, 30px);
  min-height: 3px;
  border-radius: var(--radius-xs) var(--radius-xs) 0 0;
  transition: filter var(--dur-2) var(--ease-out), transform var(--dur-2) var(--ease-out);
  animation: barGrow var(--dur-4) var(--ease-out) both;
  transform-origin: bottom;
}
.chart-bar:hover { filter: brightness(1.12); }
@keyframes barGrow { from { transform: scaleY(0); } to { transform: scaleY(1); } }
.chart-col:nth-child(2) .chart-bar { animation-delay: .06s; }
.chart-col:nth-child(3) .chart-bar { animation-delay: .12s; }
.chart-col:nth-child(4) .chart-bar { animation-delay: .18s; }
.chart-col:nth-child(5) .chart-bar { animation-delay: .24s; }
.chart-col:nth-child(6) .chart-bar { animation-delay: .3s; }
.chart-bar-sale { background: var(--grad-primary); box-shadow: var(--shadow-glow); }
.chart-bar-purchase { background: linear-gradient(180deg, #22d3ee, #0891b2); box-shadow: var(--glow-accent); }
.chart-label {
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: .04em;
}
.chart-legend { display: inline-flex; align-items: center; gap: var(--space-3); font-size: var(--text-xs); color: var(--muted); }
.chart-legend-item { display: inline-flex; align-items: center; gap: var(--space-1-5); font-weight: 600; }
.chart-dot { width: .6rem; height: .6rem; border-radius: var(--radius-xs); display: inline-block; }
.chart-dot-sale { background: var(--grad-primary); }
.chart-dot-purchase { background: linear-gradient(180deg, #22d3ee, #0891b2); }

/* --- BI canvas (Analitika): a Power-BI-style report grid ------------------- */
.bi-grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: var(--space-3);
  /* Rrjeti pyetet për veten, jo për dritaren.
     Këto shtylla ishin të vetmet në program që i binin ndesh gjerësisë reale:
     `auto-fit`/`minmax` gjetiu e zgjidh vetë sa hyjnë, kurse këtu span-et janë
     të shkruara me dorë, dhe pikat e thyerjes lexonin `@media` — pra dritaren,
     jo hapësirën që ka mbetur pas menysë anësore. Në 1210px me menynë hapur
     mbeteshin ~880px përmbajtje dhe grafiku vazhdonte të ndahej në tri shtylla
     prej 280px; me menynë e mbyllur, i njëjti ekran jepte tri shtylla krejt të
     tjera. Tani numrat më poshtë janë gjerësi e vetë rrjetit — një kartë e ngushtë
     është e ngushtë edhe kur ekrani është i gjerë. */
  container: bi-grid / inline-size;
}
.bi-card { min-width: 0; }
.bi-span-4 { grid-column: span 4; }
.bi-span-5 { grid-column: span 5; }
.bi-span-6 { grid-column: span 6; }
.bi-span-7 { grid-column: span 7; }
.bi-span-8 { grid-column: span 8; }
.bi-span-12 { grid-column: span 12; }
/* Pragjet janë gjerësi kanavace, pra më të vogla se pikat e vjetra të dritares:
   1200px dritare me menynë hapur ishin ~880px këtu. */
@container bi-grid (max-width: 880px) {
  .bi-span-4 { grid-column: span 6; }
  /* 5 dhe 7 janë çifti i vetëm asimetrik i kanavacës (ura e klientëve dhe
     tabela pranë saj). Nën këtë gjerësi asimetria nuk lexohet më, prandaj
     bëhen gjysma — jo secili në rreshtin e vet, sepse ato dy karta janë një
     pyetje e vetme e ndarë në grafik dhe emra. */
  .bi-span-5, .bi-span-7 { grid-column: span 6; }
  .bi-span-8 { grid-column: span 12; }
}
@container bi-grid (max-width: 660px) {
  .bi-span-4, .bi-span-5, .bi-span-6,
  .bi-span-7, .bi-span-8 { grid-column: span 12; }
}

/* Chart.js needs a sized, positioned box when aspect ratio is off.
   Lartësia rrjedh me gjerësinë e rrjetit (`cqi` = 1% e gjerësisë së kontejnerit,
   jo e dritares): në një monitor të gjerë grafiku ishte një shirit 280px i shtypur
   përgjatë 1400px, dhe në një kanavacë të ngushtë po aq i lartë sa i gjerë.
   Kufijtë mbeten në px sepse këtu masa është hapësirë vizatimi, jo shkrim. */
.chart-box { position: relative; height: clamp(240px, 20cqi, 380px); }
.bi-span-4 .chart-box { height: clamp(200px, 15cqi, 280px); }
/* Jashtë kanavacës BI nuk ka kontejner për t'u pyetur, dhe `cqi` do të binte te
   dritarja — pra te një gjerësi që s'e njeh menynë anësore. Grafiku i vetmuar te
   Pasqyra e TVSH-së e thotë vetë lartësinë e vet. */
.card:not(.bi-card) > .card-body > .chart-box { height: clamp(240px, 32vh, 360px); }


/* KPI sparkline: a whisper of trend under the number. The wrapper's fixed
   height is what Chart.js measures against — a bare responsive canvas inside
   the card reads the card itself and inflates it frame by frame. */
.kpi-spark {
  position: relative;
  width: 100%;
  height: 40px;
  margin-top: var(--space-2);
  overflow: hidden;
  /* Kurba vizatohet majtas→djathtas ndërsa shifra mbi të numërohet. Të dyja
     tregojnë të njëjtën gjë nga dy anë — sa është, dhe si u arrit aty — pra
     lëvizin bashkë: `--dur-4` është po ajo kohë që mban «diçka që tregon një
     sasi», dhe numëruesi te site.js ka 700ms.

     Fshirja rri këtu e jo te Chart.js me qëllim. Një vonesë për pikë mbi një
     vijë e bën atë të hyjë copë-copë, dhe kjo lexohet e prishur — arsyeja rri e
     shkruar te `make()` te shablloni, dhe ky rresht nuk vjen ta thyejë. Një
     fshirje mbi kutinë s'e copëton kurbën: ajo vizatohet e tëra, thjesht
     zbulohet me radhë. */
  animation: wipeIn var(--dur-4) var(--ease-out) both;
}

/* Pika e gjallë te skaji i një kurbe: «këtu jemi tani». Kurba tregon rrugën e
   bërë, dhe pa këtë pikë asgjë nuk thotë se skaji i djathtë është muaji që ende
   po shkruhet e jo një muaj i mbyllur si të tjerët.

   Ndarja e punës rri e shkruar te vetë vetitë: `--px` dhe `--py` i vë grafiku
   pas çdo vizatimi, sepse vendin e di vetëm ai; rrahjen e jep kjo fletë, sepse
   kohën e di vetëm ajo. Pasoja që vlen: një rimasë e dritares e zhvendos pikën
   pa e nisur rrahjen nga e para — po ta bënte JavaScript-i të tërën, çdo
   zgjerim dritareje do ta kthente pulsimin te fillimi. */
.live-point {
  position: absolute;
  left: 0;
  top: 0;
  width: var(--space-1-5);
  height: var(--space-1-5);
  margin: calc(var(--space-1-5) / -2) 0 0 calc(var(--space-1-5) / -2);
  /* `transform` e jo vetia `translate`: kjo fletë punon edhe te Chromium-i i
     inkorporuar i zyrës, dhe atje vetia e veçuar është më e re se programi. */
  transform: translate(var(--px, 0), var(--py, 0));
  border-radius: var(--radius-round);
  background: var(--live);
  animation: livePulse var(--beat-slow) var(--ease-in-out) infinite;
  pointer-events: none;
}
@keyframes livePulse {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--live) 55%, transparent); }
  70%  { box-shadow: 0 0 0 var(--space-2) transparent; }
  100% { box-shadow: 0 0 0 0 transparent; }
}

/* Shiriti i faqeve të raportit — poshtë kanavacës, si te Power BI Desktop.
 *
 * Ishte një pilulë xhami që notonte në mes të ekranit me tabin aktiv të ndezur
 * me gradient. Te Power BI-ja ky shirit nuk është dekor: është shtresa e
 * poshtme e dritares së raportit, e ngjitur buzë më buzë me kanavacën, dhe faqja
 * aktive dallohet me një vijë të hollë poshtë emrit — jo me ngjyrë sfondi.
 * Prandaj rri `sticky` te fundi pa hapësirë, mban të njëjtën ngjyrë chrome si
 * paneli i filtrave, dhe në të djathtë lë vend për orën e rifreskimit, ashtu si
 * shiriti i gjendjes atje. */
.bi-tabs {
  position: sticky;
  bottom: 0;
  z-index: 900;
  display: flex;
  align-items: stretch;
  gap: 0;
  max-width: 100%;
  overflow-x: auto;
  margin: 0;
  padding: 0 var(--space-1-5);
  background: var(--bi-chrome);
  border: 1px solid var(--bi-line);
  border-top: 0;
  border-radius: 0 0 var(--bi-radius) var(--bi-radius);
}
.bi-tab {
  border: 0;
  border-bottom: 2px solid transparent;
  background: transparent;
  color: var(--bi-ink-2);
  font-size: var(--text-sm);
  font-weight: 400;
  padding: var(--space-2) var(--space-3);
  white-space: nowrap;
  cursor: pointer;
  transition: background var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}
.bi-tab:hover { color: var(--bi-ink); background: var(--bi-visual); }
.bi-tab.active {
  background: var(--bi-visual);
  color: var(--bi-ink);
  font-weight: 600;
  border-bottom-color: var(--bi-accent);
}
/* Ora e rifreskimit, e shtyrë në skaj: shiriti i gjendjes së raportit. */
.bi-status {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: var(--space-1-5);
  padding: 0 var(--space-2);
  font-size: var(--text-xs);
  color: var(--bi-ink-2);
  white-space: nowrap;
}

/* Focus mode: one visual, the whole screen. The card is position:fixed, so it
   must never sit under an ancestor with a transform — .bi-grid has none. */
.bi-focus-backdrop {
  position: fixed;
  inset: 0;
  z-index: 1900;
  display: none;
  background: rgba(5,8,18,.55);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}
body.bi-focus-open .bi-focus-backdrop { display: block; }
.bi-card.bi-focused {
  position: fixed;
  inset: 4vh 4vw;
  z-index: 1950;
  display: flex;
  flex-direction: column;
  box-shadow: var(--shadow-lg);
}
.bi-card.bi-focused .card-body { flex: 1; min-height: 0; }
.bi-card.bi-focused .chart-box { height: 100%; }

/* Data bars in matrix cells, Power-BI style: the value paints its own scale.
   The gradient stops at --bar, set inline per cell from the server. */
.cell-bar {
  background-image: linear-gradient(90deg, var(--primary-soft) var(--bar, 0%), transparent var(--bar, 0%));
  background-repeat: no-repeat;
}
.cell-bar-accent {
  background-image: linear-gradient(90deg, var(--accent-soft) var(--bar, 0%), transparent var(--bar, 0%));
}

/* --- Përqendrimi i të ardhurave: tri shifra dhe leximi i tyre -------------- */
.conc-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-2);
  margin-bottom: var(--space-4);
}
.conc-item {
  text-align: center;
  padding: var(--space-2) var(--space-1-5);
  border-radius: var(--radius-sm);
  background: var(--surface-hover);
}
.conc-value {
  font-size: var(--text-xl);
  font-weight: 800;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.conc-label { font-size: var(--text-xs); color: var(--muted); margin-top: var(--space-0); line-height: 1.25; }
.conc-hhi {
  padding: var(--space-3);
  border-radius: var(--radius-sm);
  border-left: 3px solid var(--border);
  background: var(--surface-hover);
}
.conc-hhi-num { font-weight: 800; font-variant-numeric: tabular-nums; }
.conc-hhi-low { border-left-color: var(--success-fill); }
.conc-hhi-mid { border-left-color: var(--warning-fill); }
.conc-hhi-high { border-left-color: var(--danger-fill); }

/* --- Ura e klientëve: nga vjen ndryshimi i xhiros --------------------------
   Çelësi nën grafik nuk është legjendë zbukuruese: ai është i vetmi vend ku
   katër shifrat lexohen kur Chart.js nuk niset, dhe i vetmi që del në PDF-në e
   printuar. Prandaj mban vlerën, jo vetëm ngjyrën. */
.movers-key {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1-5);
  margin-top: var(--space-3);
}
.movers-key-item {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1-5);
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  background: var(--surface-hover);
  border-left: 3px solid var(--border);
  font-size: var(--text-xs);
  color: var(--muted);
}
.movers-key-item b {
  font-variant-numeric: tabular-nums;
  color: var(--text);
}
.movers-key-item.is-new,
.movers-key-item.is-up { border-left-color: var(--success-fill); }
.movers-key-item.is-down,
.movers-key-item.is-lost { border-left-color: var(--danger-fill); }

.movers-table { font-size: var(--text-sm); }
.movers-table td, .movers-table th { padding: var(--space-1-5) var(--space-2); }
.movers-table td { font-variant-numeric: tabular-nums; }
/* Lloji i lëvizjes lexohet edhe pa ngjyrë te shifra: shiriti buzë rreshtit e
   thotë me pozicion, jo vetëm me ton. */
.movers-table tbody tr { border-left: 3px solid transparent; }
.movers-table tbody tr.mover-new,
.movers-table tbody tr.mover-up { border-left-color: var(--success-fill); }
.movers-table tbody tr.mover-down,
.movers-table tbody tr.mover-lost { border-left-color: var(--danger-fill); }


/* --- Puna e vetë zyrës ------------------------------------------------------
   Pesë kartat që matin dorët e zyrës e jo dosjet e klientëve. Ato ndajnë një
   parim me pjesën tjetër të kanavacës: shifra shkruhet, grafiku vetëm e
   vizaton. Prandaj çdo gjë këtu ka trajtë teksti — kartat lexohen edhe te
   PDF-ja e printuar, ku asnjë skript nuk ka xhiruar. */

/* Norma e afatit: një shifër e madhe, një shirit nën të, dy numra pranë. Banda
   e ngjyros vetëm kufirin dhe shifrën, jo sfondin — një kuti e tërë e kuqe në
   mes të kanavacës do të bërtiste më fort se alarmet, të cilat kanë të drejtë
   ta bëjnë atë. */
.sla-box {
  border-left: 3px solid var(--border);
  padding: var(--space-0) 0 var(--space-0) var(--space-3);
}
/* E njëjta masë si te `.stat-value`: kjo është një shifër KPI-je, dhe dy
   madhësi të ndryshme për të njëjtin rol do të lexoheshin si dy rëndësi. */
.sla-rate {
  font-size: var(--text-2xl);
  font-weight: 800;
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}
.sla-label {
  font-size: var(--text-xs);
  color: var(--muted);
}
.sla-good { border-left-color: var(--bi-good); }
.sla-good .sla-rate { color: var(--bi-good); }
.sla-warn { border-left-color: var(--bi-warn); }
.sla-warn .sla-rate { color: var(--bi-warn); }
.sla-bad { border-left-color: var(--bi-bad); }
.sla-bad .sla-rate { color: var(--bi-bad); }

.sla-track {
  position: relative;
  height: .375rem;
  margin-top: var(--space-3);
  border-radius: var(--radius-xs);
  background: var(--surface-hover);
  overflow: hidden;
}
/* Gjerësia vjen si `--bar` nga serveri: përqindja është e dhënë, jo dekor. */
.sla-fill {
  display: block;
  height: 100%;
  width: var(--bar, 0%);
  border-radius: var(--radius-xs);
  background: var(--bi-good);
}
.sla-warn .sla-fill { background: var(--bi-warn); }
.sla-bad .sla-fill { background: var(--bi-bad); }

.sla-legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1-5);
  margin-top: var(--space-2);
}
.sla-leg {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  background: var(--surface-hover);
  border-left: 3px solid var(--border);
  font-size: var(--text-xs);
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.sla-leg.is-on { border-left-color: var(--success-fill); }
.sla-leg.is-late { border-left-color: var(--danger-fill); }

/* Katër shifrat e ciklit. Rrjet me `auto-fit` e jo katër shtylla fikse: karta
   është e gjerë tetë njësi në ekran të plotë dhe e plotë dymbëdhjetë në fokus,
   dhe katër kolona të ngurta do të shtypeshin te e para. */
.cyc-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(7.5rem, 1fr));
  gap: var(--space-2);
  margin-bottom: var(--space-4);
}
.cyc-item {
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  background: var(--surface-hover);
  border-left: 3px solid var(--border);
}
/* Mesorja është përgjigjja; tri të tjerat janë konteksti i saj. */
.cyc-item-lead { border-left-color: var(--primary); }
.cyc-val {
  display: block;
  font-size: var(--text-lg);
  font-weight: 700;
  line-height: 1.15;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}
.cyc-lab {
  display: block;
  font-size: var(--text-xs);
  color: var(--muted);
}

/* Dy tabelat e punës ndjekin matricën: shifra e rreshtuar, shkrim i vogël, dhe
   asnjë kthim në karta te ekrani i ngushtë — një tabelë katër-kolonëshe me
   emra punëtorësh lexohet ende, dhe kartat do ta bënin tri herë më të gjatë. */
.load-table, .workclients-table { font-size: var(--text-sm); }
.load-table td, .load-table th,
.workclients-table td, .workclients-table th { padding: var(--space-1-5) var(--space-2); }
.load-table td, .workclients-table td { font-variant-numeric: tabular-nums; }


/* --- Koka e vizualit, si te Power BI ---------------------------------------
   Aty ikonat e një vizuali nuk rrinë në ekran: dalin kur miu hyn mbi të. Këtu
   njëzet e ca karta i mbanin gjithnjë të gjitha — fokus, CSV, rivendos — dhe
   rezultati ishte një kanavacë ku çdo kartë kërkonte vëmendje njësoj sa
   shifrat brenda saj.

   Fshihet vetëm VEPRIMI. Çelësat e matjes (`seg`) dhe çipat janë gjendje e
   raportit, jo veprime: një lexues duhet ta shohë se cila matje është aktive
   pa e kërkuar me miun.

   Vetëm aty ku ka vërtet hover. Te prekja nuk ka gjendje mbi-qëndrimi, dhe një
   ikonë që del vetëm me hover atje s'del kurrë. */
@media (hover: hover) {
  .bi-report .bi-card .card-header .icon-btn {
    opacity: 0;
    transition: opacity var(--dur-2) var(--ease-out);
  }
  /* `:focus-within` mban tastierën brenda lojës: ikona e padukshme mbetet e
     fokusueshme, dhe pa këtë rresht kush ecën me Tab do të bënte fokus mbi një
     buton që s'e sheh dot. */
  .bi-report .bi-card:hover .card-header .icon-btn,
  .bi-report .bi-card:focus-within .card-header .icon-btn,
  .bi-report .bi-card.bi-focused .card-header .icon-btn { opacity: 1; }
}

/* Ngritja e kartës nën mi. `bi-focused` rri jashtë me qëllim: ajo kartë është
   `position: fixed`, dhe një `transform` mbi të do t'i prishte shtrirjen. */
@media (hover: hover) {
  .bi-report .bi-card:not(.bi-focused) {
    transition: transform var(--dur-2) var(--ease-out),
                box-shadow var(--dur-2) var(--ease-out);
  }
  .bi-report .bi-card:not(.bi-focused):hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-lg);
  }
}

/* Kush e ndjek kontekstin. Theks i hollë në krye të kartës — pozitiv, jo
   zbehje e të tjerave: një kartë e zbehur lexohet si «e nxjerrë jashtë
   filtrit», kurse e vërteta është që ajo s'e njeh fare atë bosht. */
body.bi-xf-on .bi-report .bi-card[data-xf="live"] {
  box-shadow: inset 0 2px 0 0 var(--primary);
}
@media (hover: hover) {
  body.bi-xf-on .bi-report .bi-card[data-xf="live"]:not(.bi-focused):hover {
    box-shadow: inset 0 2px 0 0 var(--primary), var(--shadow-lg);
  }
}
.xf-follow {
  font-size: var(--text-xs);
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* --- Sfondi i gjallë i kokës së raportit ------------------------------------
   Pa foto: CSP-ja lejon vetëm `'self'`, dhe një raport i brendshëm nuk ka pse
   të varet nga një skedar i rëndë për të dukur i gjallë. Tri njolla drite nga
   po ata tokena të paletës, të vëna në lëvizje si një i tërë.

   Lëviz `transform`, jo pozicioni i gradientit: e para e bën karta grafike, e
   dyta e ripikturon shtresën në çdo kornizë — dhe kjo faqe ka njëzet e pesë
   grafikë që e duan atë kohë për vete. */
.bi-report .bi-hero {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}
.bi-report .bi-hero::before {
  content: '';
  position: absolute;
  inset: -45%;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(38% 46% at 18% 32%, color-mix(in oklab, var(--primary) 26%, transparent), transparent 68%),
    radial-gradient(34% 42% at 80% 22%, color-mix(in oklab, var(--bi-cat-2) 22%, transparent), transparent 68%),
    radial-gradient(30% 38% at 56% 84%, color-mix(in oklab, var(--bi-cat-3) 20%, transparent), transparent 68%);
  animation: bi-aurora var(--drift-c) var(--ease-in-out) infinite alternate;
  will-change: transform;
}
@keyframes bi-aurora {
  from { transform: translate3d(-2.5%, -1.5%, 0) scale(1.04) rotate(0deg); }
  to   { transform: translate3d(2.5%, 1.5%, 0) scale(1.12) rotate(5deg); }
}

/* Shiriti i kohës te prezantimi: sa mbetet nga qëndrimi te kjo faqe. Gjerësia
   e plotë e shiritit, lart, që të lexohet anash pa e lënë ekranin. */
.present-progress {
  position: absolute;
  left: .6rem;
  top: .3rem;
  width: calc(100% - 1.2rem);
  height: 2px;
  /* `scaleX` e jo `width`: shiriti është brenda një kutie me cepa gjysmërrethorë
     dhe pa `overflow: hidden` — të cilin s'e duam, sepse do të priste unazat e
     fokusit të butonave nën të. Njëkohësisht ky është edhe i vetmi variant që
     nuk e detyron shfletuesin të rirregullojë faqen për çdo kornizë. */
  transform: scaleX(0);
  transform-origin: left center;
  background: var(--primary);
  border-radius: var(--radius-xs);
}
.present-progress.is-running {
  /* 12s = `PRESENT_DWELL` te shablloni. Numri rri i shkruar te të dyja anët
     sepse alternativa — një `--var` e vënë nga JS-ja — do të hapte një vend të
     tretë ku jeton e njëjta kohë. */
  animation: bi-present-sweep 12s linear forwards;
}
@keyframes bi-present-sweep {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

/* Çfiket lëvizja te blloku i vetëm `prefers-reduced-motion` më poshtë, jo këtu.
   Një bllok i dytë do të ishte vend i dytë ku dikush duhet të kujtohet të
   shikojë — dhe pikërisht atë njësi ruan
   `test_the_spinner_keeps_turning_for_reduced_motion`. */

/* --- Harta e sezonalitetit: muaj × vit -------------------------------------
   Intensiteti vjen si `opacity` mbi një shtresë të vetme me ngjyrën e temës, jo
   si dyzet ngjyra të shkruara me dorë: kështu harta e ndjek paletën kudo ku ajo
   ndryshon, dhe teksti rri gjithnjë mbi mbushjen, jo brenda saj. */
.heat-table { font-size: var(--text-xs); }
.heat-table th { font-weight: 600; }
.heat-cell {
  position: relative;
  min-width: 3.1rem;
  font-variant-numeric: tabular-nums;
  isolation: isolate;
}
.heat-fill {
  position: absolute;
  inset: 1px;
  border-radius: var(--radius-xs);
  background: var(--primary);
  z-index: -1;
}
.heat-val { position: relative; }
.heat-cell.is-hot .heat-val { color: #fff; font-weight: 700; }
.heat-cell.is-future { color: var(--faint); }

/* --- Vizualet e raportit vizatohen ndërsa u afrohesh -----------------------
   Kartat e kësaj faqeje nuk rrëshqasin, dhe vendimi rri i shkruar poshtë te
   `.bi-report .reveal`: dhjetë kuti që ngrihen një nga një lexohen si ngarkim i
   papërfunduar. Ky bllok nuk e prek atë. Kutia mbetet aty ku ishte, e plotë, që
   nga kuadri i parë — lëviz vetëm ajo që kutia mban.

   Dallimi nuk është hollësi shijeje. Një kuti që hyn thotë «faqja ende po vjen»;
   një shirit që rritet drejt gjatësisë së vet thotë «kjo është sa është», dhe e
   thotë duke e treguar rrugën. E dyta është ç'bën një grafik kur e vizaton
   dikush me dorë, dhe pikërisht atë bëjnë tashmë grafikët e Chart.js-së këtu me
   650ms-shin e tyre. Ç'mbetej jashtë ishin katër vizuale që i vizatojmë vetë me
   SVG — dhe ato dilnin të gatshme, sikur t'i kishte pasur faqja në xhep.

   Afati është `view()` dhe jo koha: pra vizuali nuk vizatohet kur ngarkohet
   faqja — ai vizatohet kur i afrohesh. Kjo zgjidh njëkohësisht dy gjëra. E para:
   një raport me tridhjetë vizuale do të nisje tridhjetë animacione në të njëjtin
   çast, mbi po atë fill që po ndërton nëntëmbëdhjetë kanavaca Chart.js. E dyta:
   këto SVG rindërtohen sa herë ndryshon filtri ose gjerësia e dritares, dhe një
   animacion me kohë do të rikthehej nga e para me çdo rindërtim — një vizual që
   rivizatohet vetvetiu sa herë zgjeron dritaren. Afati i rrëshqitjes s'e ka atë
   sjellje: ai lexon pozicionin, jo çastin, pra një rindërtim mbi vend e gjen
   animacionin pikërisht aty ku ishte.

   Asnjë nga këto s'e prek shabllonin: emrat e klasave i shkruan tashmë vetë
   JavaScript-i që i ndërton këto SVG. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {

    /* Sezonaliteti: njëqind e ca qeliza që ndizen. Vetëm `opacity`, dhe kuadri i
       parë është i vetmi i shkruar — i dyti nënkuptohet, pra secila qelizë ndalet
       te forca e VET, ajo që serveri i llogariti nga pesha e muajit. Një `to` i
       shkruar këtu do t'i barazonte të gjitha te një forcë dhe do të fshinte
       pikërisht atë që harta tregon. */
    .heat-table .heat-fill {
      animation-name: heatIgnite;
      animation-fill-mode: both;
      animation-timing-function: var(--ease-out);
      animation-timeline: view();
      animation-range: entry 0% entry 200px;
    }
    /* Katër korsi me katër gjatësi: qelizat fqinje s'ndizen kurrë bashkë, dhe
       rreshti kalon si valë e jo si çelës drite. */
    .heat-table td:nth-child(4n+2) .heat-fill { animation-range: entry 0% entry 260px; }
    .heat-table td:nth-child(4n+3) .heat-fill { animation-range: entry 0% entry 320px; }
    .heat-table td:nth-child(4n) .heat-fill { animation-range: entry 0% entry 380px; }

    /* Muri i klientëve: kurba vizatohet si me laps.
       `stroke-dasharray` më e gjatë se vetë shtegu do të thotë një vizë e vetme
       pa ndërprerje — pra `stroke-dashoffset` nuk pikturon pika, ai zbulon vijën
       nga e majta në të djathtë. 320 njësi mbi një `viewBox` 100×30: edhe kurba
       më e dhëmbëzuar e mundshme këtu mbetet nën gjysmën e asaj gjatësie.
       Rri brenda `@supports` bashkë me animacionin sepse pa të do të ishte një
       dasharray e varur pa kush që e vizaton. */
    .mult-spark path:nth-of-type(2) {
      stroke-dasharray: 320;
      animation-name: sparkDraw;
      animation-fill-mode: both;
      animation-timing-function: var(--ease-out);
      animation-timeline: view();
      animation-range: entry 0% entry 220px;
    }
    /* Sipërfaqja poshtë kurbës dhe pika e fundit nuk vizatohen — ato mbushen pas
       saj. Njësoj: pa `to`, që pika ta ruajë forcën e vet. */
    .mult-spark path:nth-of-type(1),
    .mult-spark circle {
      animation-name: heatIgnite;
      animation-fill-mode: both;
      animation-timing-function: var(--ease-out);
      animation-timeline: view();
      animation-range: entry 60px entry 260px;
    }

    /* Shiriti i renditjes dhe ritmi i ditëve: një fshirje e vetme majtas→djathtas.
       Këtu nuk animohet asnjë nga qindra format brenda — animohet kutia që i
       mban, pra një element dhe jo treqind e gjashtëdhjetë e pesë. Të dyja janë
       vizuale ku boshti i kohës shkon majtas→djathtas, pra fshirja ndjek
       pikërisht drejtimin që lexuesi do të ndjekë.
       `inset(0 0 0 0)` te fundi nuk pret asgjë që s'ishte prerë tashmë: një `svg`
       i jashtëm e pret vetë atë që del jashtë `viewBox`-it të vet. */
    .ribbon-svg,
    .cal-svg {
      animation-name: wipeIn;
      animation-fill-mode: both;
      animation-timing-function: var(--ease-out);
      animation-timeline: view();
      animation-range: entry 0% entry 260px;
    }
  }
}
@keyframes heatIgnite { from { opacity: 0; } }
@keyframes sparkDraw { from { stroke-dashoffset: 320; } }
@keyframes wipeIn {
  from { clip-path: inset(0 100% 0 0); }
  to   { clip-path: inset(0 0 0 0); }
}

/* Matrica e deklaratave të TVSH-së — subjekti × vit × dymbëdhjetë muaj.
   Kolona e subjektit rri e ngjitur majtas: pa të, rrëshqitja horizontale mbi
   dymbëdhjetë muaj e lë lexuesin pa e ditur se kujt i përkasin shifrat. */
.vat-matrix { font-size: var(--text-xs); }
.vat-matrix th { font-weight: 600; white-space: nowrap; }
.vat-owner-col, .vat-owner {
  position: sticky;
  left: 0;
  z-index: 2;
  background: var(--surface);
  min-width: 12rem;
}
.vat-owner { border-right: 1px solid var(--border); vertical-align: top; padding-top: var(--space-2); }
.vat-owner-name { display: block; font-weight: 700; line-height: 1.2; }
.vat-owner-nf, .vat-owner-count {
  display: block;
  font-size: var(--text-2xs);
  color: var(--faint);
  font-variant-numeric: tabular-nums;
}
.vat-year-col { min-width: 3.4rem; }
.vat-year { font-weight: 700; color: var(--muted); font-variant-numeric: tabular-nums; }
.vat-owner-first > .vat-year, .vat-owner-first > .vat-cell, .vat-owner-first > .vat-total {
  border-top: 2px solid var(--border);
}
.vat-cell { padding: var(--space-0); }
.vat-dash { color: var(--faint); }
.vat-total { font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Qelia është buton sepse është veprim: hap deklaratën. Ngjyra e sfondit mban
   peshën kundrejt muajit më të fortë të tabelës (--heat, 0..1). */
.vat-chip {
  position: relative;
  display: block;
  width: 100%;
  min-width: 3.6rem;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  padding: var(--space-1);
  background: color-mix(in srgb, var(--primary) calc(var(--heat, 0) * 70%), var(--surface-muted));
  color: inherit;
  font: inherit;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  transition: transform var(--dur-1) var(--ease-out), box-shadow var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out);
}
.vat-chip:hover { transform: translateY(-1px); box-shadow: var(--shadow-sm); }
.vat-chip:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }
.vat-chip.is-active { border-color: var(--primary); box-shadow: 0 0 0 var(--ring-w) var(--primary-soft); }
/* Deklarata vjetore rri te kolona e vitit, jo te një muaj — dhe duket ndryshe
   pikërisht që të mos lexohet si muaj. */
.vat-chip-year { margin-top: var(--space-1); font-size: var(--text-xs); border-style: dashed; border-color: var(--border); }
.vat-chip-dup {
  position: absolute;
  top: -.3rem;
  right: -.3rem;
  min-width: 1rem;
  border-radius: var(--radius-lg);
  /* Sfondi i paralajmërimit ndryshon shumë mes temave — i errët në dritë, i
     ndritshëm në errësirë — pra teksti mbi të nuk mund të jetë i bardhë te të
     dyja. Shenja e kundërt e temës është ajo që qëndron mbi të dyja. */
  background: var(--warning);
  color: var(--primary-contrast);
  font-size: var(--text-2xs);
  line-height: 1rem;
  font-weight: 700;
}

/* «Çfarë mungon»: e kundërta e matricës. Atje një qeli me ngjyrë do të thotë
   një deklaratë e dorëzuar; këtu çdo shenjë është një periudhë që s'u dorëzua,
   dhe secila është njëkohësisht butoni që e kthen atë mungesë në task. Prandaj
   duken si etiketa dhe sillen si butona — sepse janë të dyja. */
.gap-chip {
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  padding: var(--space-1) var(--space-2);
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  cursor: pointer;
  transition: transform var(--dur-1) var(--ease-out), box-shadow var(--dur-1) var(--ease-out);
}
.gap-chip:hover { transform: translateY(-1px); box-shadow: var(--shadow-sm); }
.gap-chip:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }
/* Kaluar afati dhe «afati po vjen» nuk ngjyrosen njësoj me qëllim: e para
   kërkon veprim sot, e dyta vetëm sy. */
.gap-chip-late {
  background: color-mix(in srgb, var(--danger) 14%, var(--surface));
  border-color: color-mix(in srgb, var(--danger) 45%, transparent);
  color: var(--danger);
}
.gap-chip-soon {
  background: color-mix(in srgb, var(--warning) 14%, var(--surface));
  border-color: color-mix(in srgb, var(--warning) 40%, transparent);
  color: var(--warning);
}
/* Kush ka ndaluar fare merr një vijë në të majtë: rreshti lexohet si i tillë
   edhe pa u lexuar shenjat një nga një. */
.gap-table tr.gap-stopped > td:first-child {
  box-shadow: inset var(--rail) 0 0 var(--danger);
}

/* Shenja që tashmë është kthyer në punë nuk është më buton: është derë drejt
   task-ut. Jeshile e qetë, jo e kuqe — kjo periudhë s'ka mbetur pa u prekur, e
   ka dikush në dorë, dhe ngjyra e alarmit mbi të do të kërkonte një veprim që
   është bërë. */
.gap-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  text-decoration: none;
}
.gap-chip-held {
  background: color-mix(in srgb, var(--success) 12%, var(--surface));
  border-color: color-mix(in srgb, var(--success) 40%, transparent);
  color: var(--success);
}
.gap-chip-held .bi { font-size: var(--text-xs); }

/* Vargu i pritur si rrip: e mbushura, vrimat, dhe ajo që po vjen. Lista e
   shenjave djathtas thotë ÇFARË mungon; ky rrip thotë SI duket mungesa — një
   vrimë e vetme mes dymbëdhjetë të mbushurave nuk lexohet njësoj si gjysma e
   vitit e heshtur, dhe pa të të dyja janë «tri shenja të kuqe». */
.gap-strip {
  display: flex;
  gap: var(--space-0);
  margin-top: var(--space-1);
}
.gap-strip-cell {
  width: 9px;
  height: 12px;
  border-radius: var(--radius-xs);
  background: var(--surface-muted);
}
/* E dorëzuara mbetet e qetë me qëllim: ajo është sfondi mbi të cilin lexohet
   vrima, jo lajmi. */
.gap-strip-cell.is-filed { background: color-mix(in srgb, var(--success) 45%, transparent); }
.gap-strip-cell.is-late { background: var(--danger); }
.gap-strip-cell.is-soon { background: var(--warning); }
/* Nën dritaren e shikimit: mungon vërtet, por s'numërohet një nga një. Gri e
   dukshme, sepse një kuti bosh do të thoshte «u dorëzua». */
.gap-strip-cell.is-old { background: var(--border-strong); }

/* Kush e ka barrën: numrat lart thonë sa mungesa ka zyra, ky rresht thotë te
   kush rrinë. Secila kartelë është vetë filtri, si te Hyrjet. */
.gap-owners {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}
.gap-owner {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: var(--space-0) var(--space-2);
  min-width: 12rem;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: inherit;
  text-decoration: none;
  transition: border-color var(--dur-1) var(--ease-out), box-shadow var(--dur-1) var(--ease-out);
}
.gap-owner:hover { border-color: var(--primary-line); box-shadow: var(--shadow-sm); }
.gap-owner.is-active { border-color: var(--primary); box-shadow: var(--shadow-sm); }
/* Puna pa zot nuk është një njeri që kërkohet — është një punë që s'ia ka dhënë
   askush askujt, dhe rri e shkruar ndryshe që të mos numërohet si person. */
.gap-owner.is-orphan { border-style: dashed; }
.gap-owner-name {
  font-weight: 600;
  font-size: var(--text-sm);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.gap-owner-count {
  grid-row: 1 / span 2;
  grid-column: 2;
  font-family: 'Sora Variable', 'Inter Variable', Inter, sans-serif;
  font-size: var(--text-xl);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
}
.gap-owner-count.is-late { color: var(--danger); }
.gap-owner-note { font-size: var(--text-xs); color: var(--faint); }

/* Deklarata e hapur: kutitë 9–14 sipër, pastaj formulari i plotë me grupet e
   veta. Rri poshtë matricës e jo në modal — një raport që printohet duhet ta
   mbajë të hapurën brenda faqes. */
.vat-detail {
  margin-top: var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface-muted);
  padding: var(--space-4);
}
.vat-detail-empty {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  color: var(--faint);
  font-size: var(--text-sm);
}
.vat-detail-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
  flex-wrap: wrap;
  margin-bottom: var(--space-3);
}
.vat-detail-name { font-weight: 700; font-size: var(--text-base); }
.vat-detail-sub { color: var(--faint); font-size: var(--text-sm); }
.vat-highlights {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: var(--space-2);
  margin-bottom: var(--space-4);
}
.vat-hl {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  padding: var(--space-2);
}
.vat-hl.is-zero { opacity: .55; }
/* Shuma e pesë kutive rri si e gjashta, por e shquar: është ajo që tregon
   matrica kur matja është «Qarkullimi». */
.vat-hl-total { border-color: var(--primary-line); background: var(--primary-soft); }
.vat-hl-total.is-zero { opacity: 1; }
.vat-hl-no { font-size: var(--text-2xs); font-weight: 700; color: var(--primary-text); }
.vat-hl-label { display: block; font-size: var(--text-2xs); color: var(--faint); line-height: 1.25; }
.vat-hl-val {
  display: block;
  margin-top: var(--space-1);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.vat-measure-form { display: flex; align-items: center; gap: var(--space-1-5); }
.vat-measure-form .form-select { min-width: 14rem; }

/* Ndërrimi i formës ose i vitit e rishkruan vetëm këtë kartë, në vend. Sa zgjat
   marrja, karta zbehet pak dhe s'pranon klikime — aq sa të thotë «po vjen», pa
   e lëvizur asnjë pikë të faqes nën lexuesin. */
#vat-card.is-swapping .card-body { opacity: .45; pointer-events: none; }

/* Smart narrative — the numbers read back as sentences, Power BI's insight box.
   A tinted rail on the left signals "this is generated, not typed." */
.narrative-card { border-top: 2px solid transparent; border-image: var(--grad-primary) 1; }
.narrative-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: var(--space-2) var(--space-4);
}
.insight {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  background: var(--surface-hover);
  font-size: var(--text-sm);
  line-height: 1.35;
}
.insight-icon {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 1.7rem;
  height: 1.7rem;
  border-radius: var(--radius-pill);
  font-size: var(--text-md);
  color: #fff;
  background: var(--grad-primary);
}
.insight-text { color: var(--text); padding-top: var(--space-0); }
.insight-good .insight-icon { background: linear-gradient(135deg,var(--success-fill-strong),var(--success-fill)); }
.insight-bad  .insight-icon { background: linear-gradient(135deg,var(--danger-fill-strong),var(--danger-fill)); }
.insight-neutral .insight-icon { background: linear-gradient(135deg,#0891b2,#06b6d4); }

/* Cross-filter context bar — the chip that shows which month the whole report
   is currently highlighting. Sits above the grid; drill lives on the chip. */
.xf-bar {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
  margin-bottom: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius);
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--primary);
  box-shadow: var(--shadow-sm);
  animation: xf-in var(--dur-2) var(--ease-out);
}
@keyframes xf-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
.xf-label {
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--primary);
}
.xf-drill {
  font-size: var(--text-sm);
  font-weight: 600;
  text-decoration: none;
  color: var(--primary);
}
.xf-drill:hover { text-decoration: underline; }
/* Një nga çelësat e shiritit nuk hap faqe por një kartë poshtë — pra buton, jo
   lidhje. Duket njësoj; vetëm veshja e butonit hiqet. */
button.xf-drill {
  padding: 0;
  border: 0;
  background: transparent;
  font-family: inherit;
  font-size: var(--text-sm);
  font-weight: 600;
  cursor: pointer;
}
.xf-clear {
  margin-left: auto;
  border: 0;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  padding: var(--space-0) var(--space-1-5);
  border-radius: var(--radius-sm);
  line-height: 1;
}
.xf-clear:hover { color: var(--danger); background: var(--surface-hover); }

/* The month picked in the report glows in the matrix — cross-highlight. */
tr.xf-row > td {
  background: var(--primary-soft) !important;
  box-shadow: inset var(--rail) 0 0 var(--primary);
}

/* ============================================================================
   Analitika — dritarja e raportit, në gjuhën vizuale të Power BI-t.

   Ç'ndryshoi dhe pse: kjo faqe ishte veshur si pjesa tjetër e programit, vetëm
   me dorë më të rëndë — pllakë gradienti te koka, kanavacë me pika e me larje
   indigo, karta që ngriheshin nën kursor, tab-e që ndriçonin. E bukur si faqe,
   por e gabuar si raport: në një raport çdo ngjyrë dhe çdo hije që nuk vjen nga
   të dhënat është zhurmë mbi to. Power BI-ja e zgjidh me kursim — sfond gri i
   sheshtë, kuti të bardha me një vijë floku, tituj të vegjël gri, dhe ngjyrë
   vetëm brenda vizualeve.

   Prandaj gjithçka këtu është e sheshtë me qëllim: pa gradientë, pa xham, pa
   ngritje nën kursor, rreze 4px, dhe një hije aq e hollë sa vetëm ta ndajë
   kutinë nga kanavaca.

   Struktura është ajo e dritares së raportit atje, dhe rri e ngjitur si një
   trup i vetëm — kokë, trup, shirit faqesh:

       .bi-frame
         .bi-hero        koka e raportit
         .bi-body        trupi: kanavaca + paneli i filtrave
           .bi-surface   kanavaca ku rrinë vizualet
           .bi-pane      paneli i filtrave, në të djathtë, i palosshëm
         .bi-tabs        faqet e raportit + ora e rifreskimit

   Tokenat më poshtë janë të vetmet ngjyra të shkruara me dorë. Gjithçka tjetër
   brenda `.bi-report` — kartat, tabelat, butonat, formularët — i lexon këto
   përmes tokenave të programit (`--surface`, `--border`, `--text`…), të cilat
   rishkruhen një herë te blloku pas tyre. Kjo është arsyeja pse asnjë rregull
   ekzistues i `.card`-it ose i `.table`-s nuk u prek: brenda kësaj faqeje ata
   marrin vlera të tjera, jashtë saj mbeten ata që ishin.
   ========================================================================== */
.bi-report {
  /* Këtu chrome-i i Power BI-t bëhet gjuha e gjithë faqes. Vlerat rrinë te
     `:root` bashkë me çdo token tjetër; ky bllok vetëm i lidh me emrat që
     përdor programi, një herë, që çdo komponent brenda kësaj kanavace të vishet
     vetë si vizual raporti — pa asnjë rregull të dytë të shkruar për të.
     Pikërisht kjo është arsyeja pse asnjë rregull ekzistues i `.card`-it ose i
     `.table`-s nuk u prek: brenda kësaj faqeje marrin vlera të tjera, jashtë saj
     mbeten ata që ishin. */
  --surface: var(--bi-visual);
  --surface-muted: var(--bi-chrome);
  --surface-sunken: var(--bi-chrome-hover);
  --surface-hover: rgba(0,0,0,.035);
  --border: var(--bi-line);
  --border-strong: var(--bi-line);
  --surface-border: var(--bi-line);
  --text: var(--bi-ink);
  --muted: var(--bi-ink-2);
  --faint: var(--bi-ink-2);
  --primary: var(--bi-accent);
  --primary-dark: var(--bi-accent-dark);
  --primary-2: var(--bi-accent);
  --primary-text: var(--bi-accent-dark);
  --grad-primary: var(--bi-accent);
  --grad-primary-hover: var(--bi-accent-dark);
  --grad-primary-text: var(--bi-accent);
  --success: #0e6b28;
  --warning: #7a6100;
  --danger: #a4262c;
  --radius-xs: 2px;
  --radius-sm: 2px;
  --radius: var(--bi-radius);
  --radius-lg: var(--bi-radius);
  --radius-xl: var(--bi-radius);
  --shadow-sm: var(--bi-shadow);
  --shadow-md: var(--bi-shadow-hover);
  --shadow-glow: none;
  --card-shadow: var(--bi-shadow);
}
/* Në errësirë ndryshojnë vetëm ato që lidhja më sipër nuk i mbulon dot: ngjyrat
   e statusit si TEKST, ku kanavaca e errët do të kundërtën e asaj që do e bardha.
   Chrome-i vjen vetvetiu — tokenat `--bi-*` i ka ndërruar tashmë `body.theme-dark`. */
body.theme-dark .bi-report {
  --surface-hover: rgba(255,255,255,.06);
  --success: #5ad07f;
  --warning: #e3c53a;
  --danger: #f1707a;
}

/* --- Dritarja: kokë, trup, shirit faqesh, pa fugë mes tyre ----------------- */
.bi-frame {
  border-radius: var(--bi-radius);
  /* Shiriti i faqeve rri `sticky`, pra korniza duhet ta lërë të dalë. */
  overflow: visible;
}
.bi-body {
  display: flex;
  align-items: stretch;
  background: var(--bi-canvas);
  border-left: 1px solid var(--bi-line);
  border-right: 1px solid var(--bi-line);
}
.bi-surface {
  flex: 1 1 auto;
  min-width: 0;
  padding: var(--space-2);
}

/* Koka: një shirit chrome me titullin dhe kontekstin, jo një pllakë e pikturuar.
   `page-head` e jashtme e mban ende renditjen; këtu i hiqet vetëm veshja. */
.bi-hero {
  position: relative;
  overflow: hidden;
  padding: var(--space-3);
  border: 1px solid var(--bi-line);
  border-radius: var(--bi-radius) var(--bi-radius) 0 0;
  background: var(--bi-chrome);
  box-shadow: none;
  align-items: center;
  gap: var(--space-3);
}
.bi-hero::after { display: none; }   /* orbi i dritës — s'ka vend në një raport */
.bi-hero .page-eyebrow { font-size: var(--text-2xs); letter-spacing: .06em; color: var(--bi-ink-2); }
.bi-hero .page-title {
  font-size: var(--text-lg);
  font-weight: 600;
  letter-spacing: 0;
  margin: 0;
  gap: var(--space-2);
}
.bi-hero .page-title-icon {
  width: 1.6rem;
  height: 1.6rem;
  border-radius: var(--radius-xs);
  background: var(--bi-accent);
  box-shadow: none;
  font-size: var(--text-sm);
}
.bi-hero .page-sub { font-size: var(--text-xs); margin: var(--space-0) 0 0; color: var(--bi-ink-2); }

/* --- Shiriti i ngjarjeve ----------------------------------------------------
   E vetmja gjë e kësaj faqeje që lëviz pa e nisur kush dhe pa u ndalur kurrë.
   Ka të drejtë ta bëjë sepse përmbajtja e tij nuk është listë për t'u lexuar nga
   fillimi: janë letrat që sapo hynë, puna që sapo u mbyll dhe afatet e sotme, dhe
   cilido rresht vlen po aq sa tjetri. Një listë ku rreshti i parë vlen më shumë
   nuk rrjedh kurrë — ajo rri.

   Ngjitur nën kokë dhe brenda së njëjtës kornizë: raporti është një trup i
   vetëm, dhe një shirit që noton mbi kanavacë do të ishte gjëja e dytë që tërheq
   syrin para vetë raportit.

   Kufiri i sipërm i shpejtësisë e vendos vetë përmbajtja: gjatësia e listës
   ndryshon me ditën, koha jo. Prandaj një ditë e ngarkuar rrjedh më shpejt se
   një e qetë — dhe kjo është e drejtë, sepse atë ditë ka më shumë për të parë. */
.bi-tick {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1-5) var(--space-2);
  border: 1px solid var(--bi-line);
  border-top: 0;
  background: var(--bi-chrome);
  overflow: hidden;
}
/* `hidden` duhet ta mbysë `display: flex` më sipër: shiriti niset i fshehur dhe
   zbulohet vetëm kur mbërrin pulsi i parë, pra pa këtë rresht do të dukej i
   zbrazët për një sekondë e gjysmë në çdo hapje. */
.bi-tick[hidden] { display: none; }

.bi-tick-lead {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  flex: 0 0 auto;
  padding-right: var(--space-2);
  border-right: 1px solid var(--bi-line);
  font-size: var(--text-2xs);
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--bi-accent);
}

/* Dritarja pret, shina lëviz. Ndarja rri sepse `overflow: hidden` mbi vetë atë
   që animohet do të priste gjysmën e vet. */
.bi-tick-window {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  /* Të dy skajet shuhen në sfond, që rreshtat të mos priten me thikë mu në mes
     të një fjale. Maska rri mbi dritaren e jo mbi shinën: një maskë mbi diçka që
     lëviz lëviz bashkë me të, dhe atëherë s'fsheh më skajin por një copë teksti. */
  mask-image: linear-gradient(to right, transparent, #000 var(--space-4),
                              #000 calc(100% - var(--space-4)), transparent);
}
.bi-tick-track {
  display: flex;
  width: max-content;
  animation: biTick var(--drift-tick) linear infinite;
}
/* Ndalet nën gisht dhe nën fokus. Një shirit që ikën sapo e ndjek syri është
   shirit që s'e lexon askush — dhe një lidhje që ikën nën shigjetën e miut është
   lidhje që s'hapet dot. Fokusi rri bashkë me hover-in sepse rreshtat janë
   lidhje: kush kalon me tastierë duhet ta ndalë njësoj. */
.bi-tick:hover .bi-tick-track,
.bi-tick:focus-within .bi-tick-track { animation-play-state: paused; }

@keyframes biTick {
  /* Gjysma, jo e tëra: shina mban dy kopje të listës, pra kur e para del nga
     ekrani e dyta ndodhet pikërisht aty ku nisi e para — dhe kthimi te zeroja
     nuk shihet fare. */
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-50%, 0, 0); }
}

.bi-tick-run { display: flex; flex: 0 0 auto; }
.bi-tick-item {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1-5);
  padding: 0 var(--space-3);
  border-right: 1px solid var(--bi-line);
  font-size: var(--text-xs);
  white-space: nowrap;
  text-decoration: none;
  color: var(--bi-ink);
  transition: color var(--dur-1) var(--ease-out);
}
.bi-tick-item:hover { color: var(--bi-accent); text-decoration: underline; }
.bi-tick-item .bi { font-size: var(--text-sm); }
/* Nga cila familje është ngjarja, e lexueshme para se të lexohet teksti: letrat
   janë të zakonshme, puna e mbyllur është lajm i mirë, afati i sotëm është i
   vetmi që kërkon diçka sot. */
.bi-tick-invoice .bi { color: var(--bi-cat-1); }
.bi-tick-task    .bi { color: var(--bi-good); }
.bi-tick-due     .bi { color: var(--bi-bad); }
.bi-tick-time {
  font-size: var(--text-2xs);
  font-variant-numeric: tabular-nums;
  color: var(--bi-ink-2);
}

/* Një raport nuk hyn duke u rrëshqitur. Kartat e kësaj faqeje mbanin `reveal`
   dhe `stagger` si çdo faqe tjetër e programit — të mira aty ku faqja tregon
   diçka, të gabuara këtu, ku dhjetë vizuale që ngrihen një nga një lexohen si
   ngarkim i papërfunduar. Vlerat vendosen me `!important` sepse `.js-reveal
   .reveal` i mban në opacity 0 derisa t'i shohë vëzhguesi; pa këtë, një vizual
   që s'del kurrë në ekran do të mbetej i padukshëm përgjithmonë. */
.bi-report .reveal,
.bi-report .stagger > * {
  opacity: 1 !important;
  transform: none !important;
  animation: none !important;
}

/* --- Kanavaca: vizualet notojnë mbi gri, pa kornizë të dytë rreth tyre ------ */
.bi-report .bi-grid {
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  box-shadow: none;
  gap: var(--space-2);
}

/* Kutia e një vizuali: e bardhë, një vijë floku, rreze 4px, hije sa për ta
   ndarë nga gri-ja. Nën kursor nuk ngrihet — vetëm hija forcohet, sepse një
   kartë që lëviz e zhvendos edhe grafikun brenda saj. */
.bi-report .bi-card {
  background: var(--bi-visual);
  border: 1px solid var(--bi-line);
  border-radius: var(--bi-radius);
  box-shadow: var(--bi-shadow);
  transition: box-shadow var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out);
}
.bi-report .bi-card:hover {
  transform: none;
  box-shadow: var(--bi-shadow-hover);
  border-color: var(--bi-ink-2);
}
.bi-report .bi-card.bi-focused:hover { box-shadow: var(--bi-shadow-hover); }
/* Titulli i vizualit: i vogël, gri i errët, pa vijë poshtë — te Power BI-ja ai
   rri thjesht sipër vizatimit, si etiketë, jo si kokë tabele. */
.bi-report .bi-card > .card-header {
  background: transparent;
  border-bottom: 0;
  padding: var(--space-2) var(--space-3) var(--space-0);
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: 0;
  color: var(--bi-ink);
  min-height: 0;
}
.bi-report .bi-card > .card-body { padding: var(--space-1-5) var(--space-3) var(--space-3); }
/* Tabela brenda një vizuali është matricë: rreshta të ngushtë, kokë e qetë. */
.bi-report .table > :not(caption) > * > * { padding: var(--space-1-5) var(--space-2); }
.bi-report .table thead th {
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--bi-ink-2);
  text-transform: none;
  letter-spacing: 0;
}

/* --- Kartat KPI = vizuali «Card» i Power BI-t ------------------------------
   Aty një KPI është shifra dhe emri i saj, mbi të bardhë. Asgjë tjetër: pa
   shirit ngjyre lart, pa rreth aksenti në qoshe, pa ikonë në kuti me hije.

   Ikona qëndroi këtu një herë, e zbehtë, me arsyen se një rresht me tetë karta
   lexohet më shpejt me të. Ra kur u kërkua ngjashmëri maksimale me origjinalin:
   te «Card» nuk ka ikonë fare, dhe tetë glife gri janë tetë gjëra që lëvizin
   syrin pa i thënë asgjë. Bashkë me të ndërroi edhe radha — shifra sipër,
   emri i saj poshtë — sepse ashtu rri atje, dhe sepse numri është vetë karta. */
.bi-report .stat-grid {
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}
.bi-report .stat-card {
  background: var(--bi-visual);
  border: 1px solid var(--bi-line);
  border-radius: var(--bi-radius);
  box-shadow: var(--bi-shadow);
  padding: var(--space-3);
  transition: box-shadow var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out);
}
.bi-report .stat-card:hover {
  transform: none;
  box-shadow: var(--bi-shadow-hover);
  border-color: var(--bi-ink-2);
}
.bi-report .stat-card::after { display: none; }
/* Radha: shifra, emri, pastaj shënimi. Markupi i kartës mbetet ai i panelit —
   ku etiketa vjen e para — dhe rirenditja bëhet këtu, brenda kanavacës. */
.bi-report .stat-top > div:first-child { display: flex; flex-direction: column; min-width: 0; }
.bi-report .stat-label {
  order: 2;
  margin: var(--space-0) 0 0;
  font-size: var(--text-xs);
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
  color: var(--bi-ink-2);
}
.bi-report .stat-value {
  order: 1;
  font-family: inherit;
  font-size: var(--text-2xl);
  font-weight: 600;
  letter-spacing: -.02em;
  color: var(--bi-ink);
}
.bi-report .stat-note { order: 3; font-size: var(--text-xs); color: var(--bi-ink-2); }
.bi-report .stat-delta { font-weight: 600; }
.bi-report .stat-delta.up { color: var(--bi-good); }
.bi-report .stat-delta.down { color: var(--bi-bad); }
.bi-report .stat-icon { display: none; }
.bi-report .kpi-spark { height: 34px; margin-top: var(--space-1-5); }

/* --- Paneli i filtrave, në të djathtë -------------------------------------
   Elementi më i njohshëm i Power BI-t, dhe i vetmi që kjo faqe nuk e kishte:
   slicer-at rrinin si shirit horizontal mbi raport, pra hanin lartësi nga
   kanavaca dhe nuk thoshin kurrë "ky është filtri", vetëm "këto janë butona".
   Këtu janë aty ku i pret dora — buzë e djathtë, të palosshme deri në një kurriz
   të hollë me emrin e kthyer, si atje. */
.bi-pane {
  flex: 0 0 15.5rem;
  width: 15.5rem;
  display: flex;
  flex-direction: column;
  background: var(--bi-chrome);
  border-left: 1px solid var(--bi-line);
  transition: flex-basis var(--dur-2) var(--ease-out), width var(--dur-2) var(--ease-out);
}
.bi-pane-head {
  display: flex;
  align-items: center;
  gap: var(--space-1-5);
  padding: var(--space-2);
  border-bottom: 1px solid var(--bi-line);
}
.bi-pane-title {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--bi-ink);
  flex: 1;
  white-space: nowrap;
}
.bi-pane-icon { color: var(--bi-ink-2); font-size: var(--text-sm); }
.bi-pane-toggle {
  border: 0;
  background: transparent;
  color: var(--bi-ink-2);
  padding: var(--space-1) var(--space-1-5);
  border-radius: var(--radius-xs);
  cursor: pointer;
  line-height: 1;
}
.bi-pane-toggle:hover { background: var(--bi-chrome-hover); color: var(--bi-ink); }
.bi-pane-body {
  padding: var(--space-2);
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
/* Një filtër = një kartë, si te Power BI: emri i fushës lart, kontrolli poshtë. */
.bi-filter {
  background: var(--bi-visual);
  border: 1px solid var(--bi-line);
  border-radius: var(--bi-radius);
  padding: var(--space-2);
}
.bi-filter-name {
  display: block;
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--bi-ink-2);
  margin-bottom: var(--space-1-5);
}
.bi-filter .form-select { font-size: var(--text-sm); }
.bi-pane-foot {
  margin-top: auto;
  padding: var(--space-2);
  border-top: 1px solid var(--bi-line);
  display: flex;
  align-items: center;
  gap: var(--space-1-5);
  flex-wrap: wrap;
}
/* I palosur: mbetet vetëm kurrizi, me emrin e kthyer 90° — pikërisht sjellja e
   panelit atje, dhe e vetmja mënyrë për t'i dhënë kanavacës gjithë gjerësinë pa
   e humbur nga sytë se filtrat ekzistojnë. */
.bi-report.pane-collapsed .bi-pane { flex-basis: 2.4rem; width: 2.4rem; }
.bi-report.pane-collapsed .bi-pane-body,
.bi-report.pane-collapsed .bi-pane-foot { display: none; }
/* Kurrizi është buton i tërë (shih skriptin te faqja), pra duhet ta thotë. */
.bi-report.pane-collapsed .bi-pane-head { cursor: pointer; }
.bi-report.pane-collapsed .bi-pane-head:hover { background: var(--bi-chrome-hover); }
.bi-report.pane-collapsed .bi-pane-head {
  flex-direction: column-reverse;
  justify-content: flex-start;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-1);
  border-bottom: 0;
  /* `flex: 1`, jo `height: 100%`: kurrizi është vetë një artikull flex brenda
     panelit, dhe një përqindje lartësie mbi një artikull të tillë nuk ka kundrejt
     çfarë të matet — emri i kthyer do të rrinte i ngjeshur lart. */
  flex: 1 1 auto;
  align-items: center;
}
.bi-report.pane-collapsed .bi-pane-title {
  writing-mode: vertical-rl;
  flex: 0 0 auto;
  font-size: var(--text-xs);
}
/* Numri i filtrave aktivë te kurrizi: e vetmja gjë që një panel i mbyllur duhet
   ende ta thotë. */
.bi-pane-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.1rem;
  height: 1.1rem;
  padding: 0 var(--space-1);
  border-radius: var(--radius-pill);
  background: var(--bi-accent);
  color: #fff;
  font-size: var(--text-2xs);
  font-weight: 700;
}
/* Blu-ja e chrome-it ndriçohet në temën e errët — dhe e bardha mbi të bie te
   3.0:1, nën vijën AA. Aty teksti kthehet i errët; ngjyra e pastilës mbetet
   po ajo, sepse ajo është sinjali. */
body.theme-dark .bi-pane-count { color: #10222e; }
.bi-pane-count:empty { display: none; }

/* Slicer-i i periudhës: butona të sheshtë në një kuti, jo pilula me shkëlqim. */
.seg {
  display: inline-flex;
  gap: 0;
  padding: 0;
  border-radius: var(--bi-radius);
  background: var(--surface);
  border: 1px solid var(--border);
  overflow: hidden;
}
.seg-btn {
  border: 0;
  border-right: 1px solid var(--border);
  background: transparent;
  color: var(--muted);
  font-size: var(--text-xs);
  font-weight: 400;
  letter-spacing: 0;
  padding: var(--space-1) var(--space-2);
  border-radius: 0;
  line-height: 1.35;
  cursor: pointer;
  transition: color var(--dur-1) var(--ease-out), background var(--dur-1) var(--ease-out);
}
.seg-btn:last-child { border-right: 0; }
.seg-btn:hover { color: var(--text); background: var(--surface-hover); }
.seg-btn.active {
  background: var(--bi-accent, var(--primary));
  color: #fff;
  font-weight: 600;
  box-shadow: none;
}
.bi-pane .seg { width: 100%; }
.bi-pane .seg-btn { flex: 1; text-align: center; }
/* «Periudha paraprake» dhe «Viti i kaluar» nuk hyjnë kurrë krah për krah në një
   panel 15rem. Kur etiketat janë fjalë e jo shkurtesa, slicer-i rri vertikal —
   po ashtu si te Power BI, ku një slicer listë është kolonë. */
.seg-stack { flex-direction: column; }
.seg-stack .seg-btn { border-right: 0; border-bottom: 1px solid var(--border); text-align: left; }
.seg-stack .seg-btn:last-child { border-bottom: 0; }

/* --- Shiriti i eksportit dhe alarmet: pjesë e kanavacës, jo panele më vete -- */
.bi-report .export-bar,
.bi-report .alarm-panel,
.bi-report .drill-bar,
.bi-report .xf-bar {
  border-radius: var(--bi-radius);
  box-shadow: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
.bi-report .export-bar { background: var(--bi-visual); border: 1px solid var(--bi-line); }

/* Ikonat e alarmeve dhe të leximeve mbanin gradientë 135°. Të mira te një panel
   njoftimesh; të huaja mbi një kanavacë ku asnjë sipërfaqe tjetër nuk ka dy
   ngjyra. Këtu bëhen njëngjyrëshe — dhe pikërisht me fundin e errët të atij
   gradienti, jo me një ngjyrë të re: kështu glifi i bardhë sipër tyre nuk humb
   asnjë pikë kontrasti nga ç'kishte. */
.bi-report .insight-good .insight-icon,
.bi-report .alarm-panel-clear .alarm-head-icon { background: var(--success-fill-strong); }
.bi-report .insight-bad .insight-icon,
.bi-report .alarm-panel-critical .alarm-head-icon,
.bi-report .alarm-critical .alarm-item-icon { background: var(--danger-fill-strong); }
.bi-report .alarm-panel-warning .alarm-head-icon,
.bi-report .alarm-warning .alarm-item-icon { background: var(--warning-fill-strong); }
.bi-report .insight-neutral .insight-icon,
.bi-report .alarm-info .alarm-item-icon { background: var(--bi-cat-1); }
.bi-report .whatif-bar-fill.up { background: var(--success-fill-strong); }
.bi-report .whatif-bar-fill.down { background: var(--danger-fill-strong); }

/* ============================================================================
   Veshja: tipografia dhe kutia e vizualit

   Ngjyrat, rrezja dhe hijet e këtij ekrani ishin tashmë vlerat e Power BI-t.
   Ajo që e tradhtonte ishte chrome-i RRETH vizualeve: shkrimi i programit,
   tituj me ikona blu, veprime gjithnjë në dukje dhe pllaka KPI me ikona sa një
   pullë poste. Asnjëra prej tyre nuk ekziston atje.

   Rregulli që ndoqi gjithë blloku: një vizual i Power BI-t është një kuti e
   bardhë ku e vetmja gjë me ngjyrë janë të dhënat. Titulli është gri i errët
   dhe i vogël, veprimet dalin vetëm kur dora afrohet, dhe numri i një karte
   është vetë karta — jo një rresht pranë një ikone.
   ========================================================================== */

/* Shkrimi. Rri i lidhur me `--bi-font` që të ndërrohet nga një vend i vetëm,
   dhe prek edhe titujt: `.page-title` dhe `.stat-value` e kanë Sora-n të
   shkruar me emër, dhe pa këtë rresht kanavaca do të kishte dy shkrime. */
.bi-report,
.bi-report .page-title,
.bi-report .card-header,
.bi-report .stat-value,
.bi-report h1, .bi-report h2, .bi-report h3,
.bi-report h4, .bi-report h5, .bi-report h6 {
  font-family: var(--bi-font);
  letter-spacing: 0;
}

/* Nëntitulli gri pranë emrit të vizualit — te Power BI ai është një rresht më i
   vogël se titulli, jo i njëjti tekst me ngjyrë tjetër. */
.bi-report .bi-card > .card-header .small,
.bi-report .bi-card > .card-header .text-muted { font-size: var(--text-2xs); }

/* Shiriti i eksportit bëhet command bar: një rresht i hollë veprimesh me
   tekst 11px, jo një kartë me titull e me nëntitull. Ndarësi para kutizave
   është po ai që Power BI-ja vë mes grupeve të veprimeve. */
.bi-report .export-bar {
  padding: var(--space-1) var(--space-2);
  gap: var(--space-2);
  border-left-width: 1px;
  border-left-color: var(--bi-line);
}
.bi-report .export-bar-icon { display: none; }
.bi-report .export-bar-title { font-size: var(--text-xs); font-weight: 600; }
.bi-report .export-bar-sub { font-size: var(--text-2xs); }
.bi-report .export-sections {
  padding-left: var(--space-2);
  border-left: 1px solid var(--bi-line);
}
.bi-report .export-sections-label,
.bi-report .export-chk { font-size: var(--text-2xs); }
.bi-report .export-bar .btn {
  padding: var(--space-0) var(--space-2);
  font-size: var(--text-xs);
  font-weight: 400;
}

/* Fletët e faqeve: pak më të vogla dhe pa trashje kur janë aktive — te Desktop-i
   dallimin e bën e bardha dhe vija blu, jo pesha e shkronjës. */
.bi-report .bi-tab { font-size: var(--text-xs); padding: var(--space-2) var(--space-3); }
.bi-report .bi-tab.active { font-weight: 600; }

/* --- Modaliteti fokus ------------------------------------------------------ */
.bi-report .bi-card.bi-focused {
  border-radius: var(--bi-radius);
  box-shadow: var(--bi-shadow-focus);
}

/* --- Ekrane të ngushta ----------------------------------------------------
   Nën 900px paneli nuk rri më buzë: bëhet një shirit mbi kanavacë, i palosur
   që në fillim. Një panel 15rem përballë një kanavace 320px do të thoshte dy
   shtylla ku s'ka vend për një. */
@media (max-width: 900px) {
  .bi-body { flex-direction: column; }
  .bi-pane {
    flex: 0 0 auto;
    width: auto;
    order: -1;
    border-left: 0;
    border-bottom: 1px solid var(--bi-line);
  }
  .bi-report.pane-collapsed .bi-pane { flex-basis: auto; width: auto; }
  .bi-report.pane-collapsed .bi-pane-head {
    flex-direction: row;
    height: auto;
    padding: var(--space-2);
  }
  .bi-report.pane-collapsed .bi-pane-title { writing-mode: horizontal-tb; flex: 1; }
  .bi-surface { padding: var(--space-2); }
}

/* Në letër dritarja e raportit zhduket: mbeten vizualet, siç ndodh kur një
   raport eksportohet në PDF. Paneli dhe shiriti i faqeve s'kanë ç'të thonë aty
   — filtrat e zbatuar shkruhen tashmë te koka dhe te shiriti i drill-it. */
@media print {
  .bi-frame, .bi-body { border: 0; background: none; }
  .bi-hero { background: none; border: 0; padding: 0; }
  .bi-surface { padding: 0; }
  .bi-pane, .bi-tabs { display: none !important; }
  .bi-report .bi-card { box-shadow: none; }
}

/* Butonat e kokës së vizualit dalin nën kursor, si te Power BI — dhe rrinë
   gjithnjë të dukshëm aty ku kursor s'ka (prekje). */
@media (hover: hover) {
  .bi-card .card-header .icon-btn { opacity: 0; transition: opacity var(--dur-1) var(--ease-out); }
  .bi-card:hover .card-header .icon-btn,
  /* Fokusi brenda kartës i sjell po ashtu: kush ecën me tastierë mund të jetë
     te një çelës i kokës kur i duhet fokusi ose CSV-ja pranë tij, dhe një buton
     i padukshëm nën kursorin e tastierës është një buton që nuk ekziston. */
  .bi-card:focus-within .card-header .icon-btn,
  .bi-card.bi-focused .card-header .icon-btn,
  .bi-card .card-header .icon-btn:focus-visible { opacity: 1; }
}

/* --- Menuja e vizualit -----------------------------------------------------
   Rri te <body>, jo brenda kartës: një menu brenda një kutie me `overflow` do
   të pritej pikërisht atje ku fillon të jetë e nevojshme. Prandaj ngjyrat i
   lexon nga tokenat `--bi-*` drejtpërdrejt — jashtë `.bi-report` rilidhja e
   emrave nuk vlen. Dy numrat e pozicionit vijnë nga JS-ja si variabla; rregullat
   mbeten këtu. */
.bi-menu {
  position: absolute;
  left: var(--menu-x, 0);
  top: var(--menu-y, 0);
  z-index: 1080;
  min-width: 12rem;
  padding: var(--space-1);
  background: var(--bi-visual);
  border: 1px solid var(--bi-line);
  border-radius: var(--bi-radius);
  box-shadow: var(--bi-shadow-hover);
}
.bi-menu[hidden] { display: none; }
.bi-menu-sep {
  padding: var(--space-1-5) var(--space-2) var(--space-0);
  font-size: var(--text-2xs);
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--bi-ink-2);
}
.bi-menu-item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  padding: var(--space-1-5) var(--space-2);
  border: 0;
  border-radius: var(--radius-xs);
  background: transparent;
  color: var(--bi-ink);
  font-size: var(--text-xs);
  text-align: left;
  cursor: pointer;
}
.bi-menu-item:hover { background: var(--bi-chrome-hover); }
.bi-menu-item .bi { color: var(--bi-ink-2); }
.bi-menu-item.is-on { font-weight: 600; color: var(--bi-accent); }
.bi-menu-item.is-on .bi { color: var(--bi-accent); }

/* --- Tooltip-i si faqe raporti --------------------------------------------- */
.bi-tip {
  position: absolute;
  left: var(--tip-x, 0);
  top: var(--tip-y, 0);
  transform: translate(-50%, -100%) translateY(-.6rem);
  z-index: 1080;
  min-width: 11rem;
  padding: var(--space-2);
  pointer-events: none;
  background: var(--bi-visual);
  border: 1px solid var(--bi-line);
  border-radius: var(--bi-radius);
  box-shadow: var(--bi-shadow-hover);
}
.bi-tip[hidden] { display: none; }
.bi-tip-head { font-size: var(--text-sm); font-weight: 600; color: var(--bi-ink); }
.bi-tip-sub { font-size: var(--text-2xs); color: var(--bi-ink-2); margin-bottom: var(--space-1); }
.bi-tip-row { display: flex; justify-content: space-between; gap: var(--space-4); font-size: var(--text-xs); }
.bi-tip-key { color: var(--bi-ink-2); display: inline-flex; align-items: center; gap: var(--space-1-5); }
/* Pika e serisë, si te tooltip-i i Power BI-t: ngjyrën e vë JS-ja, sepse ajo
   është ngjyra e vizatimit dhe jo e faqes. */
.bi-tip-dot {
  width: .5rem;
  height: .5rem;
  border-radius: var(--radius-round);
  flex: 0 0 auto;
  background: var(--dot, currentColor);
}
.bi-tip-val { font-weight: 600; color: var(--bi-ink); font-variant-numeric: tabular-nums; }
.bi-tip-val.is-good { color: var(--bi-good); }
.bi-tip-val.is-bad { color: var(--bi-bad); }
.bi-tip-foot {
  margin-top: var(--space-1);
  padding-top: var(--space-1);
  border-top: 1px solid var(--bi-line);
  font-size: var(--text-2xs);
  color: var(--bi-ink-2);
}

/* --- Spotlight: gjithçka tjetër hesht, pa u zhdukur ------------------------
   Ndryshe nga fokusi, asgjë nuk lëviz dhe asgjë nuk mbulohet: kush tregon një
   vizual gjatë një bisede e ka ende rrethin e tij në ekran, vetëm i heshtur. */
body.bi-spot-on .bi-report .bi-card:not(.bi-spot),
body.bi-spot-on .bi-report .stat-card,
body.bi-spot-on .bi-report .export-bar,
body.bi-spot-on .bi-report .alarm-panel {
  opacity: .28;
  filter: saturate(.45);
}
.bi-report .bi-card,
.bi-report .stat-card,
.bi-report .export-bar,
.bi-report .alarm-panel { transition: opacity var(--dur-2) var(--ease-out), filter var(--dur-2) var(--ease-out), box-shadow var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out); }
.bi-report .bi-card.bi-spot { border-color: var(--bi-accent); box-shadow: var(--bi-shadow-hover); }

/* --- «Shfaq si tabelë»: shifrat e vizualit, aty ku rrinte vizuali ---------- */
.bi-card.bi-as-table .chart-box,
.bi-card.bi-as-table .bi-canvas { display: none; }
.bi-datagrid { max-height: 22rem; overflow: auto; }
.bi-datagrid .table { font-variant-numeric: tabular-nums; }

/* --- Shigjetat e hierarkisë së kohës --------------------------------------- */
.bi-drill {
  display: inline-flex;
  align-items: center;
  gap: var(--space-0);
  padding: var(--space-0);
  border: 1px solid var(--border);
  border-radius: var(--bi-radius);
}
.bi-drill-btn {
  border: 0;
  padding: var(--space-0) var(--space-1);
  border-radius: var(--radius-xs);
  background: transparent;
  color: var(--muted);
  font-size: var(--text-xs);
  line-height: 1;
  cursor: pointer;
}
.bi-drill-btn:hover:not(:disabled) { background: var(--surface-hover); color: var(--text); }
.bi-drill-btn:disabled { opacity: .35; cursor: default; }
.bi-drill-level {
  padding: 0 var(--space-1);
  font-size: var(--text-2xs);
  color: var(--muted);
  white-space: nowrap;
}
.seg-sm .seg-btn { padding: var(--space-1) var(--space-2); font-size: var(--text-2xs); }

/* --- Pema e zbërthimit -----------------------------------------------------
   Kolona pas kolone, secila një nivel: emri i fushës sipër, degët poshtë, dhe
   pjesa e secilës prej prindit si shirit brenda vetë butonit. Shiriti është
   `::before` me gjerësi `--bar` — i vetmi numër që e di JS-ja, si te qelizat e
   tjera me shirit në këtë fletë. */
.decomp {
  display: flex;
  gap: var(--space-2);
  align-items: flex-start;
  overflow-x: auto;
  padding-bottom: var(--space-1);
}
.decomp-col {
  position: relative;
  flex: 0 0 13.5rem;
  min-width: 13.5rem;
  padding: var(--space-1-5);
  border: 1px solid var(--border);
  border-radius: var(--bi-radius);
  background: var(--surface);
}
.decomp-col-head {
  margin-bottom: var(--space-1);
  font-size: var(--text-2xs);
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--muted);
}
.decomp-nodes { display: flex; flex-direction: column; gap: var(--space-1); max-height: 17rem; overflow-y: auto; }
.decomp-node {
  position: relative;
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0 var(--space-1-5);
  width: 100%;
  padding: var(--space-1) var(--space-1-5);
  border: 1px solid transparent;
  border-radius: var(--radius-xs);
  background: var(--surface-muted);
  color: var(--text);
  text-align: left;
  cursor: pointer;
  overflow: hidden;
}
.decomp-node::before {
  content: '';
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--bar, 0%);
  background: var(--bi-cat-1);
  opacity: .14;
}
.decomp-node > * { position: relative; }
.decomp-node:hover { border-color: var(--bi-ink-2); }
.decomp-node.is-on { border-color: var(--bi-accent); background: var(--surface); }
.decomp-node.is-on::before { opacity: .24; }
.decomp-node-name {
  font-size: var(--text-xs);
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.decomp-node-val { font-size: var(--text-xs); font-weight: 600; font-variant-numeric: tabular-nums; }
.decomp-node-val.is-bad { color: var(--bi-bad); }
.decomp-node-share { grid-column: 1 / -1; font-size: var(--text-2xs); color: var(--muted); }
.decomp-drop {
  position: absolute;
  top: .25rem;
  right: .3rem;
  padding: 0 var(--space-1);
  border: 0;
  background: transparent;
  color: var(--muted);
  font-size: var(--text-2xs);
  line-height: 1;
  cursor: pointer;
}
.decomp-drop:hover { color: var(--bi-bad); }
.decomp-col-add {
  flex-basis: 10.5rem;
  min-width: 10.5rem;
  background: transparent;
  border-style: dashed;
}
.decomp-add-btn {
  display: flex;
  align-items: center;
  gap: var(--space-1-5);
  width: 100%;
  margin-top: var(--space-1);
  padding: var(--space-1) var(--space-1-5);
  border: 1px solid var(--border);
  border-radius: var(--radius-xs);
  background: var(--surface);
  color: var(--text);
  font-size: var(--text-xs);
  cursor: pointer;
}
.decomp-add-btn:hover { border-color: var(--bi-accent); color: var(--bi-accent); }
.decomp-add-auto .bi { color: var(--bi-accent); }

/* --- «Pse ndryshoi»: kontributet rreth një boshti zero ---------------------
   Shiriti nuk nis nga e majta si te pema, sepse këtu shenja është gjysma e
   kuptimit: një rënie e madhe dhe një rritje e madhe janë e njëjta gjatësi, dhe
   vetëm ana e vijës së mesit i ndan. Prandaj mbushja del nga qendra — majtas
   kur bie, djathtas kur ngjitet — dhe gjerësia matet kundrejt lëvizjes më të
   madhe të kartës, jo kundrejt totalit: kontributet janë të vogla përballë
   xhiros, dhe të gjitha do të ishin vija flokësh. */
/* `.card` e Bootstrap-it është `display: flex`, dhe një rregull autori e mund
   `[hidden]`-in e shfletuesit: pa këtë rresht karta do të rrinte hapur gjithnjë,
   bosh, sepse fshehja e saj është atributi. Specifika mjafton — pa `!important`. */
.explain-card[hidden] { display: none; }
.explain { display: flex; flex-direction: column; gap: var(--space-2); }
.explain-head { display: flex; align-items: baseline; flex-wrap: wrap; gap: var(--space-2); }
.explain-delta {
  font-size: var(--text-xl);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.explain-delta.is-up { color: var(--bi-good); }
.explain-delta.is-down { color: var(--bi-bad); }
.explain-say { font-size: var(--text-sm); color: var(--muted); }
.explain-rows { display: flex; flex-direction: column; gap: var(--space-1); }
.explain-row {
  display: grid;
  grid-template-columns: minmax(7rem, 15rem) 1fr auto;
  align-items: center;
  gap: 0 var(--space-2);
  width: 100%;
  padding: var(--space-1) var(--space-2);
  border: 1px solid transparent;
  border-radius: var(--radius-xs);
  background: var(--surface-muted);
  color: var(--text);
  text-align: left;
  font-family: inherit;
}
button.explain-row { cursor: pointer; }
button.explain-row:hover { border-color: var(--bi-ink-2); }
.explain-row.is-on { border-color: var(--bi-accent); background: var(--surface); }
.explain-row.is-rest .explain-row-name { color: var(--muted); }
.explain-row-name {
  font-size: var(--text-xs);
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.explain-row-val { font-size: var(--text-xs); font-weight: 700; font-variant-numeric: tabular-nums; }
.explain-row.is-up .explain-row-val { color: var(--bi-good); }
.explain-row.is-down .explain-row-val { color: var(--bi-bad); }
.explain-row-sub {
  grid-column: 1 / -1;
  font-size: var(--text-2xs);
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.explain-bar { position: relative; height: .5rem; }
.explain-bar::before {
  content: '';
  position: absolute;
  left: 50%;
  top: -.1rem;
  bottom: -.1rem;
  width: 1px;
  background: var(--border);
}
.explain-bar-fill {
  position: absolute;
  top: 0;
  bottom: 0;
  /* --bar është pesha kundrejt lëvizjes më të madhe; gjysma e pistës i takon
     secilës anë, prandaj përgjysmohet këtu e jo te JS-ja. */
  width: calc(var(--bar, 0%) / 2);
  border-radius: var(--radius-xs);
}
.explain-row.is-up .explain-bar-fill { left: 50%; background: var(--bi-good); }
.explain-row.is-down .explain-bar-fill { right: 50%; background: var(--bi-bad); }
.explain-foot { font-size: var(--text-2xs); color: var(--muted); }

/* --- Shiriti i renditjes ---------------------------------------------------
   Ngjyrat e shiritave vijnë nga JS-ja (paleta kategorike, një ngjyrë për klient),
   sepse ato varen nga të dhënat e jo nga faqja. Këtu rri vetëm sjellja: kush
   zbehet kur syri ndjek dikë, dhe sa i shpejtë është ai zbehje. */
.ribbon { width: 100%; }
.ribbon-svg { display: block; width: 100%; }
.ribbon-band, .ribbon-link, .ribbon-name {
  transition: opacity var(--dur-1) var(--ease-out);
}
.ribbon-band { cursor: pointer; }
.ribbon-band.is-dim, .ribbon-link.is-dim, .ribbon-name.is-dim { opacity: .16; }
.ribbon-band.is-on { stroke: var(--bi-ink); stroke-width: 1; }
.ribbon-link.is-on { opacity: 1; }
.ribbon-name { font-size: var(--text-2xs); font-weight: 600; }
.ribbon-name.is-on { font-weight: 700; }
.ribbon-axis { font-size: var(--text-2xs); }

/* --- Muri i klientëve (small multiples) ------------------------------------
   Kutitë janë të gjitha njësoj të mëdha me qëllim: kur shkalla është e
   përbashkët, forma e kurbës është e vetmja gjë që ndryshon, dhe ajo lexohet
   pa asnjë shifër. */
.multiples {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
  gap: var(--space-2);
}
.mult {
  display: flex;
  flex-direction: column;
  gap: var(--space-0);
  padding: var(--space-2) var(--space-2) var(--space-1);
  border: 1px solid var(--border);
  border-radius: var(--bi-radius);
  background: var(--surface);
  color: var(--text);
  text-align: left;
  font-family: inherit;
  transition: opacity var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out);
}
button.mult { cursor: pointer; }
button.mult:hover { border-color: var(--bi-ink-2); }
.mult.is-on { border-color: var(--bi-accent); }
.mult.is-dim { opacity: .35; }
.mult.is-group { background: var(--surface-muted); }
.mult-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-1-5); }
.mult-name {
  font-size: var(--text-xs);
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.mult-delta { font-size: var(--text-2xs); font-weight: 700; font-variant-numeric: tabular-nums; }
.mult-delta.is-up { color: var(--bi-good); }
.mult-delta.is-down { color: var(--bi-bad); }
.mult-val { font-size: var(--text-sm); font-weight: 700; font-variant-numeric: tabular-nums; }
.mult-spark { width: 100%; height: 2.4rem; display: block; }
/* Në fokus karta merr ekranin: shiriti e ndjek lartësinë, muri e mban rrjetin
   e vet dhe vetëm rrjedh me shumë kolona. */
.bi-focused .ribbon { height: 100%; }
.bi-focused .multiples { align-content: start; }

/* --- Boshti që luan --------------------------------------------------------
   Shiriti nën grafik është transporti i kohës: buton, vizore, muaji me shkronja
   dhe shpejtësia. Vizorja është `input[type=range]`, e veshur me tokenat e
   raportit që të mos jetë e vetmja kontrollë me ngjyrat e sistemit. */
.play-bar {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-2);
  padding-top: var(--space-2);
  border-top: 1px solid var(--border);
}
.play-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  flex: 0 0 auto;
  border: 1px solid var(--border);
  border-radius: var(--radius-round);
  background: var(--surface);
  color: var(--bi-accent);
  font-size: var(--text-base);
  line-height: 1;
  cursor: pointer;
}
.play-btn:hover { border-color: var(--bi-accent); }
.play-range { flex: 1 1 auto; min-width: 6rem; accent-color: var(--bi-accent); }
.play-label {
  min-width: 4.5rem;
  font-size: var(--text-sm);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* --- Ritmi i ditëve --------------------------------------------------------
   Katrorët e ditëve e marrin ngjyrën nga JS-ja (intensiteti është të dhëna);
   këtu rrinë vetëm ato që nuk varen nga shifra: dita bosh, rrëshqitja anash kur
   dymbëdhjetë muaj nuk hyjnë në gjerësi, dhe legjenda. */
.cal-scroll { overflow-x: auto; padding-bottom: var(--space-1); }
.cal-svg { display: block; }
.cal-day { cursor: pointer; }
.cal-day:hover { stroke: var(--bi-ink); stroke-width: 1; }
.cal-wd, .cal-month { font-size: var(--text-2xs); }
.cal-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-1-5);
  font-size: var(--text-2xs);
  color: var(--muted);
}
.cal-legend { display: inline-flex; align-items: center; gap: var(--space-1); }
.cal-legend-box {
  width: .7rem;
  height: .7rem;
  border-radius: var(--radius-xs);
  background: var(--bi-cat-1);
  opacity: var(--lvl, 1);
}

/* --- Modaliteti i prezantimit ----------------------------------------------
   Raporti merr ekranin dhe gjithçka që s'është vizual hesht: menyja, koka e
   programit, shiriti i eksportit, paneli i filtrave, tab-et. Mbetet një shirit
   i vetëm poshtë — faqja, numri i saj dhe dalja. Ekrani i plotë kërkohet nga
   JS-ja, por nuk mbahet si kusht: pa të, kjo shtresë e mbulon vetë faqen. */
body.bi-present .app-sidebar,
body.bi-present .app-topbar,
body.bi-present .bi-tabs,
body.bi-present .export-bar,
body.bi-present .bi-pane,
body.bi-present .page-head,
body.bi-present .app-content > :not(.bi-report) { display: none !important; }
body.bi-present { overflow: hidden; }
body.bi-present .app-content { padding: 0; }
body.bi-present .bi-report {
  position: fixed;
  inset: 0;
  z-index: 1900;
  overflow: auto;
  /* Fundi është vend i lënë, jo ritëm: raporti rri `fixed` mbi tërë ekranin dhe
     butonat e prezantimit notojnë poshtë tij. Anët i mban shkalla. */
  padding: var(--space-4) var(--space-4) 4rem;
  background: var(--bi-canvas);
}
body.bi-present .bi-frame { border: 0; box-shadow: none; }
body.bi-present .bi-card { break-inside: avoid; }
.bi-present-bar {
  position: fixed;
  left: 50%;
  bottom: 1rem;
  transform: translateX(-50%);
  z-index: 1960;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1-5) var(--space-2);
  border: 1px solid var(--bi-line);
  border-radius: var(--radius-pill);
  background: var(--bi-visual);
  box-shadow: var(--bi-shadow-hover);
}
.bi-present-bar[hidden] { display: none; }
.present-nav, .present-exit {
  border: 0;
  background: transparent;
  color: var(--bi-ink);
  font-size: var(--text-sm);
  cursor: pointer;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
}
.present-nav:hover, .present-exit:hover { background: var(--surface-hover); }
.present-title { font-size: var(--text-sm); font-weight: 700; color: var(--bi-ink); }
.present-count { font-size: var(--text-2xs); color: var(--bi-ink-2); font-variant-numeric: tabular-nums; }
.present-exit kbd {
  font-size: var(--text-2xs);
  padding: 0 var(--space-1);
  border: 1px solid var(--bi-line);
  border-radius: var(--radius-xs);
}
@media (max-width: 640px) {
  .explain-row { grid-template-columns: 1fr auto; }
  .explain-bar { display: none; }
}

/* --- Export bar: the whole report as PDF or Excel ------------------------- */
.export-bar {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  flex-wrap: wrap;
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-lg);
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  box-shadow: var(--shadow-sm);
}
.export-bar-lead { display: flex; align-items: center; gap: var(--space-3); }
.export-bar-icon {
  display: grid; place-items: center;
  width: 2.2rem; height: 2.2rem; flex: 0 0 auto;
  border-radius: var(--radius);
  background: var(--accent-soft); color: var(--accent);
  font-size: var(--text-lg);
}
.export-bar-title { font-weight: 700; font-size: var(--text-md); letter-spacing: -.01em; }
.export-bar-sub { font-size: var(--text-xs); color: var(--muted); }
.export-bar-actions { display: flex; gap: var(--space-2); margin-left: auto; flex-wrap: wrap; }
.btn-export {
  display: inline-flex; align-items: center; gap: var(--space-2);
  font-weight: 600; font-size: var(--text-sm);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius);
  border: 1px solid var(--border-strong);
  background: var(--surface); color: var(--text);
  transition: transform var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease-out), background var(--dur-2) var(--ease-out);
}
.btn-export:hover { transform: translateY(-1px); box-shadow: var(--shadow-md); }
.btn-export-pdf { border-color: rgba(220,38,38,.35); color: var(--danger); }
.btn-export-pdf:hover { background: var(--danger-soft); }
.btn-export-excel { border: 0; background: linear-gradient(135deg, var(--excel-strong), var(--excel)); color: #fff; }
.btn-export-excel:hover { color: #fff; box-shadow: var(--glow-success); }

/* --- Alarme & anomali financiare ----------------------------------------- */
.alarm-panel {
  border-radius: var(--radius-lg);
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}
.alarm-panel-critical { border-left: 4px solid var(--danger); }
.alarm-panel-warning  { border-left: 4px solid var(--warning); }
.alarm-panel-clear    { border-left: 4px solid var(--success); }
.alarm-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-3); flex-wrap: wrap;
  padding: var(--space-3) var(--space-4);
}
.alarm-panel:not(.alarm-panel-clear) .alarm-head { border-bottom: 1px solid var(--border); }
.alarm-head-title { display: flex; align-items: center; gap: var(--space-3); }
.alarm-head-icon {
  display: grid; place-items: center;
  width: 2.3rem; height: 2.3rem; flex: 0 0 auto;
  border-radius: var(--radius);
  font-size: var(--text-lg); color: #fff;
}
.alarm-panel-critical .alarm-head-icon { background: linear-gradient(135deg,var(--danger-fill-strong),var(--danger-fill)); }
.alarm-panel-warning  .alarm-head-icon { background: linear-gradient(135deg,var(--warning-fill-strong),var(--warning-fill)); }
.alarm-panel-clear    .alarm-head-icon { background: linear-gradient(135deg,var(--success-fill-strong),var(--success-fill)); }
.alarm-head-name { font-weight: 700; font-size: var(--text-base); letter-spacing: -.01em; }
.alarm-head-sub { font-size: var(--text-xs); color: var(--muted); }
.alarm-head-counts { display: flex; gap: var(--space-1-5); flex-wrap: wrap; }
.alarm-badge {
  font-size: var(--text-xs); font-weight: 700; padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-pill); white-space: nowrap;
}
.alarm-badge-critical { background: var(--danger-soft); color: var(--danger); }
.alarm-badge-warning  { background: var(--warning-soft); color: var(--warning); }
.alarm-badge-clear    { background: var(--success-soft); color: var(--success); }
.alarm-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(310px, 1fr));
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
}
.alarm-item {
  display: flex; align-items: flex-start; gap: var(--space-3);
  padding: var(--space-3);
  border-radius: var(--radius);
  background: var(--surface-hover);
  border: 1px solid transparent;
  text-decoration: none; color: inherit;
  transition: transform var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease-out), border-color var(--dur-2) var(--ease-out);
}
a.alarm-item:hover { transform: translateY(-1px); box-shadow: var(--shadow-sm); border-color: var(--border-strong); }
.alarm-item-icon {
  flex: 0 0 auto; display: grid; place-items: center;
  width: 1.9rem; height: 1.9rem; border-radius: var(--radius-pill);
  font-size: var(--text-md); color: #fff;
}
.alarm-critical { border-left: 3px solid var(--danger); }
.alarm-warning  { border-left: 3px solid var(--warning); }
.alarm-critical .alarm-item-icon { background: linear-gradient(135deg,var(--danger-fill-strong),var(--danger-fill)); }
.alarm-warning  .alarm-item-icon { background: linear-gradient(135deg,var(--warning-fill-strong),var(--warning-fill)); }
.alarm-info     .alarm-item-icon { background: linear-gradient(135deg,#0891b2,#06b6d4); }
.alarm-item-body { display: flex; flex-direction: column; gap: var(--space-0); min-width: 0; }
.alarm-item-title { font-weight: 700; font-size: var(--text-sm); }
.alarm-item-text { font-size: var(--text-sm); color: var(--muted); line-height: 1.35; }
.alarm-item-go { margin-left: auto; align-self: center; color: var(--muted); font-size: var(--text-sm); }
.alarm-empty {
  display: flex; align-items: center; gap: var(--space-2);
  padding: var(--space-1-5) var(--space-4) var(--space-4); color: var(--success); font-weight: 600; font-size: var(--text-md);
}
.alarm-empty .bi { font-size: var(--text-lg); }

/* --- Year-over-year toggle switch ----------------------------------------- */
.yoy-toggle {
  display: inline-flex; align-items: center; gap: var(--space-1-5);
  cursor: pointer; user-select: none; margin: 0;
  font-size: var(--text-xs); font-weight: 600; color: var(--muted);
  white-space: nowrap;
}
.yoy-toggle input { position: absolute; opacity: 0; width: 0; height: 0; }
.yoy-track {
  position: relative; width: 34px; height: 18px; flex: 0 0 auto;
  border-radius: var(--radius-pill); background: rgba(120,131,155,.45);
  transition: background var(--dur-2) var(--ease-out);
}
.yoy-thumb {
  position: absolute; top: 2px; left: 2px;
  width: 14px; height: 14px; border-radius: var(--radius-round);
  background: #fff; box-shadow: var(--shadow-sm);
  transition: transform var(--dur-2) var(--ease-out);
}
.yoy-toggle input:checked + .yoy-track { background: var(--warning); }
.yoy-toggle input:checked + .yoy-track .yoy-thumb { transform: translateX(16px); }
.yoy-toggle input:focus-visible + .yoy-track { box-shadow: 0 0 0 var(--ring-w-lg) var(--warning-soft); }
.yoy-toggle input:checked ~ .yoy-text { color: var(--warning); }
.yoy-toggle-off { opacity: .5; cursor: not-allowed; }

/* --- Cash flow forecast --------------------------------------------------- */
.chart-box-sm { height: 210px; }
.forecast-foot { display: flex; gap: var(--space-2); flex-wrap: wrap; margin-bottom: var(--space-3); }
.forecast-kpi {
  flex: 1 1 0; min-width: 92px;
  display: flex; flex-direction: column; gap: var(--space-0);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius);
  background: var(--surface-hover);
}
.forecast-kpi-label { font-size: var(--text-xs); color: var(--muted); font-weight: 600; }
.forecast-kpi-val { font-size: var(--text-lg); font-weight: 800; letter-spacing: -.01em; }
.forecast-kpi-val.up { color: var(--success); }
.forecast-kpi-val.down { color: var(--danger); }
.forecast-table { font-size: var(--text-sm); }
.forecast-table thead th {
  font-size: var(--text-xs); text-transform: uppercase; letter-spacing: .04em; color: var(--muted);
}

/* --- What-if scenario widget ---------------------------------------------- */
.whatif-margin-box {
  text-align: center; padding: var(--space-3);
  border-radius: var(--radius-lg);
  background: var(--surface-hover);
  margin-bottom: var(--space-3);
}
.whatif-margin { font-size: var(--text-3xl); font-weight: 800; line-height: 1; color: var(--primary); transition: color var(--dur-2) var(--ease-out); }
.whatif-margin.pos { color: var(--success); }
.whatif-margin.warn { color: var(--warning); }
.whatif-margin.neg { color: var(--danger); }
.whatif-margin-label { font-size: var(--text-xs); color: var(--muted); margin-top: var(--space-1); }
.whatif-baseline { font-size: var(--text-xs); font-weight: 600; margin-top: var(--space-1); color: var(--muted); }
.whatif-baseline.pos { color: var(--success); }
.whatif-baseline.neg { color: var(--danger); }
.whatif-controls { display: flex; flex-direction: column; gap: var(--space-3); margin-bottom: var(--space-4); }
.whatif-row > label { display: flex; justify-content: space-between; align-items: center; font-size: var(--text-sm); font-weight: 600; margin-bottom: var(--space-1); }
.whatif-delta { font-weight: 800; font-variant-numeric: tabular-nums; }
.whatif-delta.up { color: var(--success); }
.whatif-delta.down { color: var(--danger); }
.whatif-range { width: 100%; cursor: pointer; accent-color: var(--primary); }
.whatif-range-up { accent-color: var(--success); }
.whatif-range-down { accent-color: var(--danger); }
.whatif-bars { display: flex; flex-direction: column; gap: var(--space-2); }
.whatif-bar { display: grid; grid-template-columns: 3.4rem 1fr auto; align-items: center; gap: var(--space-2); font-size: var(--text-sm); }
.whatif-bar-name { color: var(--muted); font-weight: 600; }
.whatif-bar-track { height: .55rem; border-radius: var(--radius-pill); background: var(--surface-hover); overflow: hidden; }
.whatif-bar-fill { height: 100%; border-radius: var(--radius-pill); width: 0; transition: width var(--dur-3) var(--ease-out); }
.whatif-bar-fill.up { background: linear-gradient(90deg,var(--success-fill-strong),var(--success-fill)); }
.whatif-bar-fill.down { background: linear-gradient(90deg,var(--danger-fill-strong),var(--danger-fill)); }
.whatif-bar-fill.neu { background: var(--grad-primary); }
.whatif-bar-val { font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }

/* The report prints as a clean one-column deck; canvases print as images. */
@media print {
  .bi-pane, .bi-tabs, .bi-focus-backdrop, .bi-focus-btn, .export-bar { display: none !important; }
  .bi-grid { display: block; }
  .bi-card { break-inside: avoid; margin-bottom: var(--space-3); page-break-inside: avoid; }
  .chart-box { height: 260px !important; }
  .kpi-spark { display: none; }
  .alarm-panel { break-inside: avoid; }
}

/* --- Outside-access grant: the admin picks a duration from a small grid ---- */
.outside-access-menu { min-width: 12.5rem; }
.outside-access-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-1-5);
}
.outside-access-grid .btn { padding: var(--space-1); font-weight: 600; }

/* --- Sortable tables + quick filter (wired up by site.js) ------------------ */
th.sortable { cursor: pointer; user-select: none; white-space: nowrap; }
th.sortable:hover { color: var(--primary); }
th.sortable::after {
  content: "↕";
  opacity: .32;
  margin-left: var(--space-1);
  font-size: .85em;
}
th.sortable.sorted-asc::after { content: "↑"; opacity: 1; color: var(--primary); }
th.sortable.sorted-desc::after { content: "↓"; opacity: 1; color: var(--primary); }
th.sortable:focus-visible {
  outline: none;
  box-shadow: var(--ring);
  border-radius: var(--radius-sm);
}
.table-filter {
  min-width: 150px;
  max-width: 220px;
  font-size: var(--text-sm);
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-pill);
}
/* Numri pranë kutisë: sa rreshta i mbetën filtrit, nga sa ishin. Tabular që
   shifrat të mos kërcejnë majtas-djathtas ndërsa njeriu shkruan. */
.table-count { font-variant-numeric: tabular-nums; }

/* Të pesta veglat — filtri, numri, «Shtyllat», kopjimi, «Shkarko» — janë një
   grup i vetëm, jo pesë fëmijë të shpërndarë nga `space-between` nëpër tërë
   gjerësinë e shiritit. */
.table-tools {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-1-5);
  margin-left: auto;
}
/* Shiriti që s'ekzistonte te shablloni dhe e ndërtoi vetë skripti: pa titull,
   pra pa asgjë majtas — veglat rrinë djathtas dhe koka nuk mban rresht bosh. */
.table-toolbar-auto { justify-content: flex-end; }

/* Rreshti që hap dosjen e vet nga kudo. Shenja është kursori dhe një ndriçim i
   lehtë — po ashtu si te çdo listë ku rreshti është një gjë, jo tetë qeliza. */
.row-linked { cursor: pointer; }
.row-linked:hover { background: var(--surface-hover); }
/* Qelizat ku klikimi NUK hap asgjë e thonë vetë: aty rri një buton, një formë
   ose një fushë, dhe kursori i dorës do të premtonte diçka që s'ndodh. */
.row-linked td:has(> form),
.row-linked td:has(.btn),
.row-linked td:has(input),
.row-linked td:has(select) { cursor: default; }

/* Shtylla e nxjerrë jashtë nga «Shtyllat». `!important` sepse në telefon i
   njëjti rresht bëhet kartelë dhe qelizat marrin `display: block` — pa të,
   shtylla e fshehur do të rikthehej pikërisht atje ku ekrani është më i vogël. */
.tbl-col-off { display: none !important; }
.table-cols-menu {
  min-width: 12rem;
  padding: var(--space-1-5);
  max-height: min(60vh, 22rem);
  overflow: auto;
}
.table-col-opt {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1-5) var(--space-2);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  cursor: pointer;
  user-select: none;
}
.table-col-opt:hover { background: var(--surface-hover); }
.table-col-opt input { flex: none; margin: 0; cursor: pointer; }
.table-cols-reset {
  width: 100%;
  text-align: left;
  font-size: var(--text-sm);
  padding: var(--space-1-5) var(--space-2);
  text-decoration: none;
}

/* Rreshti i shumave. Rri ngjitur poshtë kur tabela rrëshqet brenda vetes, si
   koka lart: totali që humbet nga ekrani sapo shtyhet lista është një total që
   duhet kërkuar prapë. */
.table-sum > td {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  background: var(--surface-muted);
  border-top: 2px solid var(--border-strong);
  color: var(--text);
}
.table-sticky tfoot .table-sum > td {
  position: sticky;
  bottom: 0;
  z-index: 3;
}

@media (max-width: 767.98px) {
  /* Në telefon rreshti bëhet kartelë; totali s'është kartelë, është një rresht
     i vetëm — pra rri si shirit poshtë listës, jo si një kuti e nëntë pa emër. */
  .table-cards > tfoot { display: block; }
  .table-cards > tfoot > tr { display: flex; flex-wrap: wrap; gap: var(--space-1-5) var(--space-4); }
  .table-cards > tfoot > tr > td {
    display: inline-block;
    border: 0;
    padding: var(--space-1) 0;
  }
  .table-cards > tfoot > tr > td:empty { display: none; }
  .table-sum > td { background: transparent; }
  .table-cards > tfoot > tr { border-top: 2px solid var(--border-strong); padding-top: var(--space-2); }
}

@media print {
  /* Në letër mbeten të dhënat: kutia e filtrit, «Shtyllat», kopjimi dhe
     shkarkimi janë vegla ekrani dhe dalin bosh ose si drejtkëndësha të zbrazët. */
  .table-filter, .table-cols, .table-copy, .table-export { display: none !important; }
  th.sortable::after { content: none; }
  .table-sum > td { background: transparent; }
}

/* --- Password fields: visibility toggle + caps-lock hint (site.js) --------- */
.pw-wrap { position: relative; display: block; }
.pw-wrap > input { padding-right: 2.7rem; }
.pw-toggle {
  position: absolute;
  top: 50%;
  right: .45rem;
  transform: translateY(-50%);
  border: 0;
  background: transparent;
  color: var(--faint);
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  cursor: pointer;
  line-height: 1;
}
.pw-toggle:hover { color: var(--primary); background: var(--primary-soft); }
.caps-hint {
  display: none;
  margin-top: var(--space-1);
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--warning);
}
.caps-hint.on { display: block; }

/* Slim gradient bar under the topbar while the next page loads. site.js sets
   .loading on click/submit; a full reload resets it naturally. */
.page-progress {
  position: fixed;
  top: 0;
  left: 0;
  height: 3px;
  width: 0;
  z-index: 5000;
  background: var(--grad-primary);
  box-shadow: 0 0 8px color-mix(in srgb, var(--primary-2) 55%, transparent);
  opacity: 0;
  transition: width 4s var(--ease-out), opacity var(--dur-2) var(--ease-out);
  pointer-events: none;
}
.page-progress.loading { width: 82%; opacity: 1; }

/* Cross-document view transitions were tried here and pulled out again: with
   `@view-transition { navigation: auto }` the inbound page's rendering is
   paused until the snapshot handshake finishes, and in embedded/webview
   Chromium that handshake can stall for tens of seconds — frozen frames,
   IntersectionObserver callbacks never delivered. pageIn covers the entrance
   without touching the navigation pipeline. */

/* ============================================================================
   6b. Ato që rrinin te `style="…"` nëpër shabllone
   ----------------------------------------------------------------------------
   Nëpër 52 shabllone rrinin 77 atribute `style`. Dhjetë prej tyre janë të
   ligjshme: mbajnë një numër që e di vetëm serveri — gjerësia e një shiriti
   progresi, `--bar` i një qelize. Ato mbeten aty ku janë, sepse aty e kanë
   vendin: vlera vjen nga të dhënat, jo nga dizajni.

   Të tjerat ishin dizajn i shkruar jashtë sistemit: nëntë gjerësi kolonash që
   nisnin nga 130px e shkonin në 210px me hap dhjetë; gjashtë `cursor:pointer`;
   dy fusha kodi me të njëjtat dy rregulla të kopjuara. Asnjëra s'e dinte se
   tjetra ekzistonte, dhe asnjëra s'ndryshohej dot nga një vend i vetëm.

   Bashkë me to erdhën këtu edhe katër blloqe `<style>` nga vetë faqet — mes tyre
   `.edi-pass.is-masked`, i njëjti rregull i shkruar dy herë në dy skedarë. Kjo
   e afron edhe atë hapin që CSP-ja e ka të shënuar prej kohësh: pa stile brenda
   faqes, `style-src` s'ka më nevojë për 'unsafe-inline'.
   ========================================================================= */

/* Rreshti që hapet me klikim. Kursori ishte i vetmi që e thoshte, dhe e thoshte
   gjashtë herë, veç e veç. */
.is-clickable { cursor: pointer; }

/* Gjerësia e kolonës, katër hapa në vend të nëntë numrave. Është `min-width`,
   pra tabela vazhdon të zgjerohet kur ka vend — ky është vetëm kufiri nën të
   cilin teksti nis të thyhet shëmtuar. */
.tcol-sm { min-width: 8rem; }
.tcol-md { min-width: 10rem; }
.tcol-lg { min-width: 12rem; }
.tcol-xl { min-width: 14rem; }
/* Dy kolonat që s'mbajnë tekst por numër rreshti dhe butona: aty gjerësia është
   e ngulur, jo minimale — përndryshe ato hanë hapësirën e emrave. */
.tcol-tiny { width: 2.5rem; }
.tcol-num { width: 3.5rem; }
.tcol-act { width: 6rem; }
/* Tabela e ndryshimeve te historiku: kolona e emrit të fushës mban një pjesë të
   caktuar, që vlerat e vjetra dhe të reja të bien nën njëra-tjetrën në çdo hyrje. */
.history-diff thead th:first-child { width: 26%; }
.history-diff-fields td:first-child { width: 35%; }

/* Fusha që s'duhet të shtrihet sa gjerësia e faqes: kërkimi, një filtër, një
   formular i shkurtër. Emrat thonë rolin — sa e gjatë është përgjigjja që pret. */
.field-xs { max-width: 8rem; }    /* një datë, një shumë */
.field-sm { max-width: 12rem; }
.field-md { max-width: 15rem; }   /* kërkimi mbi një tabelë */
.field-lg { max-width: 22rem; }
.field-xl { max-width: 30rem; }   /* një formular i tërë i ngushtë */
/* Zgjedhësi që merr gjerësinë e vet nga teksti brenda, por jo nën një kufi —
   përndryshe rreshtat e tabelës kërcejnë sa herë ndryshon roli i zgjedhur. */
.select-auto { width: auto; min-width: 8.25rem; }
/* Paneli i një menyje rënëse që mban një formular, jo një listë. */
.dropdown-panel { min-width: 16rem; }
/* Faqja që përmban vetëm një kartë në mes: gabimi, porta e dytë, «Pa lidhje». */
.panel-narrow { width: 100%; max-width: 32rem; }

/* Shiriti i progresit, i hollë. Bootstrap-i s'ka masë për të, prandaj lartësia
   shkruhej me dorë çdo herë — dhe tri herë me tri vlera të ndryshme. */
.progress-xs { height: .3rem; }
.progress-sm { height: .5rem; }
.progress-inline { min-width: 9rem; }

/* Një etiketë e vogël me shkronja të mëdha do frymë mes shkronjave, përndryshe
   lexohet si një fjalë e vetme e ngjeshur. */
.tracking-wide { letter-spacing: .12em; }

/* Bllok teksti i gjatë brenda faqes: rrjedh vetë, ruan rreshtat ashtu siç janë. */
.pre-scroll { max-height: 22rem; white-space: pre-wrap; }

/* Faqja «Pa lidhje». Ajo nuk e trashëgon base.html — është një faqe e vetme që
   shërbehet nga service worker-i kur serveri s'kapet — prandaj gjithçka që i
   duhet rri e shkruar këtu, jo brenda saj. */
.offline-main { max-width: 34rem; margin: var(--space-7) auto; text-align: center; }
.offline-logo { border-radius: var(--radius-lg); }
.offline-title { justify-content: center; margin-top: var(--space-5); }
/* Rruga e daljes nga rrethi i certifikatës — e qetë, por gjithnjë aty. */
.offline-hint {
  margin-top: var(--space-5);
  font-size: var(--text-sm);
  color: var(--muted);
}

/* Kodi 6-shifror i verifikimit. Shkronjat rrinë larg njëra-tjetrës që numri të
   lexohet si numër, jo si fjalë — dhe që syri ta krahasojë me telefonin pa i
   humbur radhën. */
/* Kjo është e vetmja që nuk ndoqi shkallën poshtë kur maja u rirendit. `--text-xl`
   u bë shifra e kartelës (1,32rem), dhe kodi që dikush po e lexon nga ekrani i
   telefonit s'guxon të zvogëlohet — prandaj ngjitet një shkallë, jo bie. */
.otp-input {
  letter-spacing: .4em;
  font-size: var(--text-2xl);
}

/* Fjalëkalimi i EDI-t te lista e subjekteve: i dukshëm si fushë, i mbuluar si
   përmbajtje derisa ta kërkojë dikush. `-webkit-text-security` është e vetmja
   rrugë për ta bërë këtë pa e kthyer fushën në `type="password"` — që do të
   thoshte se shfletuesi do ta ofronte për ruajtje si fjalëkalim të vetin.
   Rrinte e shkruar dy herë, te dy shabllone. */
.edi-pass.is-masked {
  -webkit-text-security: disc;
  text-security: disc;
}

/* Zgjedhësi i subjekteve te rregullat e deklarimeve dhe te qasjet. */
.subj-menu { max-height: 17rem; overflow-y: auto; min-width: 20rem; }
.subj-menu .form-check-input { flex: 0 0 auto; }
.subj-dd .subj-toggle { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Rreshti nuk mban .d-flex: utility-t e Bootstrap-it vijnë pas reboot-it, dhe
   `display:flex !important` e mundte `[hidden]{display:none!important}` — pra
   kërkimi i fshihte rreshtat vetëm në letër dhe biznesi i kërkuar s'dukej. */
.subj-row { display: flex; align-items: flex-start; gap: var(--space-2); }
.subj-row[hidden] { display: none !important; }
/* Karta e rregullit ndodhet në një grid; pa këtë, menyja e hapur pikturohej
   nën kartën pasuese. Kolona ngrihet vetëm sa është menyja hapur. */
.rule-col.dd-open { position: relative; z-index: 1080; }
.rule-col.dd-open .card { overflow: visible; }
.subj-dd .dropdown-menu { z-index: 1085; }

.access-menu { max-height: 15rem; overflow-y: auto; min-width: 14rem; }
.access-menu .form-check-input { flex: 0 0 auto; }
.access-dd .access-toggle { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* QR-i i 2FA-së vjen si SVG nga serveri, pa përmasa të vetat. */
.qr-box svg { width: 220px; height: 220px; max-width: 100%; display: block; }

/* ============================================================================
   7. Print — turns the VAT statement page into a clean sheet for Save as PDF.
   ========================================================================= */
@media print {
  nav.navbar,
  aside.sidebar,
  .app-sidebar,
  .app-topbar,
  .no-print,
  .toast-container,
  .toast-stack,
  .bottom-nav {
    display: none !important;
  }

  body { background: #fff !important; color: #000 !important; }
  body::before { display: none !important; }
  /* Aurora dhe cepi me tavolinën: të dyja janë bojë mbi letër që s'e ka kërkuar
     askush. E dyta është maskë, pra `background: #fff` mbi trupin s'e prek. */
  body::after { display: none !important; }

  main, .app-content {
    width: 100% !important;
    max-width: 100% !important;
    flex: 0 0 100% !important;
    padding: 0 !important;
    animation: none !important;
  }

  .statement-sheet { border: 0 !important; box-shadow: none !important; }
  .statement-sheet .card-body { padding: 0 !important; }

  .table { font-size: 11pt; }

  /* Keep Bootstrap's light table headers visible on paper. */
  .table-light th,
  .table-light td,
  thead.table-light tr {
    background-color: #f1f1f1 !important;
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }

  .table-bordered th, .table-bordered td { border-color: #999 !important; }

  /* Don't split a table row or a summary block across two pages. */
  tr, .row { page-break-inside: avoid; }
  h5 { page-break-after: avoid; }

  a { text-decoration: none !important; color: #000 !important; }

  @page { margin: 1.5cm; }
}

/* ============================================================================
   8. Motion + accessibility
   ========================================================================= */

/* One focus ring, on every interactive thing, and only for keyboard users —
   :focus alone put a ring on every mouse click, so the old code fought it with
   outline:none in places and lost the ring for keyboards too. */
/* Unaza vizatohet me `outline`, jo me `box-shadow`.
   Dukeshin e njëjta gjë dhe nuk ishin: hija është pjesë e pikturës së elementit,
   pra çdo prind me `overflow: hidden` ia pret. Dhe prindër të tillë ka kudo —
   `.table-card`, `.stat-card`, kokat e kartelave. Pra pikërisht atje ku njeriu
   që lëviz me tastierë kishte më shumë nevojë ta dinte ku ndodhet, unaza ishte
   e prerë ose e padukshme fare. `outline` vizatohet jashtë pikturës dhe s'e pret
   asnjë prind.
   Bashkë me të ikën edhe `border-radius` që rrinte këtu: ai i JEPTE elementit të
   fokusuar një formë tjetër nga e vetja — një ikonë e rrumbullakët 12px bëhej
   8.8px sapo e prekte tastiera. `outline` e ndjek vetë formën e elementit. */
:where(a, button, .btn, .form-control, .form-select, .form-check-input,
       [tabindex]:not([tabindex="-1"])):focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}

/* Skip straight past the sidebar to the content. Invisible until tabbed to. */
.skip-link {
  position: absolute;
  left: .5rem;
  top: -3rem;
  z-index: 4000;
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-sm);
  background: var(--primary);
  color: var(--primary-contrast);
  font-weight: 600;
  transition: top var(--dur-2) var(--ease-out);
}
.skip-link:focus { top: .5rem; color: #fff; }

/* Scroll-reveal: elements start hidden and slide in when they enter the
   viewport (site.js flips .in). Without JS nothing is hidden — the class only
   animates once the observer exists. */
.reveal { opacity: 1; transform: none; }
.js-reveal .reveal {
  opacity: 0;
  /* Shkalla është .985 dhe jo më poshtë: mjafton sa kartela të duket se vjen
     nga pak më larg, dhe aq pak sa teksti brenda saj të mos lexohet i turbullt
     në asnjë kuadër. Kuadri i fundit mbetet `none` — jo `scale(1)` — që asnjë
     kartelë të mos mbetet me kontekst stakimi mbi menytë e veta. */
  transform: translateY(12px) scale(.985);
  transition: opacity var(--dur-3) var(--ease-out), transform var(--dur-3) var(--ease-out);
  transition-delay: var(--reveal-delay, 0ms);
}
.js-reveal .reveal.in { opacity: 1; transform: none; }

/* Kaskada e rrugës së vjetër. `--reveal-delay` rrinte i deklaruar këtu që nga
   dita e parë dhe s'e vinte kurrë askush — pra çdo kartelë e ekranit të parë
   ulej në të njëjtin çast, sepse site.js ua vë `.in` të gjithave bashkë te
   kuadri i parë. Aty ku shfletuesi e njeh `view()`, kaskadën e bën vetë
   gjeometria; këtu e bën radha, dhe pas së katërtës ndalet — nëntë kartela me
   nga pesëdhjetë milisekonda do të ishin gjysmë sekonde pritje për të fundit. */
.js-reveal .reveal:nth-child(2) { --reveal-delay: 50ms; }
.js-reveal .reveal:nth-child(3) { --reveal-delay: 100ms; }
.js-reveal .reveal:nth-child(n+4) { --reveal-delay: 140ms; }

/* Stagger helper: each direct child fades up slightly after the previous. */
.stagger > * { animation: pageIn var(--dur-3) var(--ease-out) both; }
.stagger > *:nth-child(1) { animation-delay: .02s; }
.stagger > *:nth-child(2) { animation-delay: .07s; }
.stagger > *:nth-child(3) { animation-delay: .12s; }
.stagger > *:nth-child(4) { animation-delay: .17s; }
.stagger > *:nth-child(5) { animation-delay: .22s; }
.stagger > *:nth-child(6) { animation-delay: .27s; }
.stagger > *:nth-child(n+7) { animation-delay: .3s; }

/* Koka e faqes hyn me radhë, jo si një bllok i vetëm.
   Çdo faqe pune e nis njësoj: mbiemri i vogël, titulli, nënshkrimi, dhe djathtas
   butonat. Deri tani të katërta zbardheshin bashkë me `pageFade` — pra e vetmja
   gjë që lëvizte te ekrani i parë ishin kartelat me `.stagger`, dhe koka mbi to
   rrinte e ngrirë. Radha këtu është radha e leximit, dhe hapi është më i shkurtër
   se te `.stagger` (50ms kundrejt 50–70): koka është një fjali, jo një rresht
   kartelash, dhe një fjali që hyn fjalë-për-fjalë ngadalë lexohet si defekt.

   Raporti përjashtohet me emër. `.bi-hero` është koka e Analitikës, dhe atje
   vendimi është i shkruar dhjetë mijë rreshta më poshtë: një raport nuk hyn duke
   u rrëshqitur. */
.app-content .page-head:not(.bi-hero) .page-head-main > *,
.app-content .page-head:not(.bi-hero) > .page-actions {
  animation: pageIn var(--dur-3) var(--ease-out) both;
}
.app-content .page-head:not(.bi-hero) .page-head-main > *:nth-child(2) { animation-delay: .05s; }
.app-content .page-head:not(.bi-hero) .page-head-main > *:nth-child(n+3) { animation-delay: .1s; }
.app-content .page-head:not(.bi-hero) > .page-actions { animation-delay: .14s; }

/* Bootstrap draws these two from baked-in light assumptions that no token can
   reach: an unchecked box is filled white, and the close X is a near-black SVG.
   Both disappear on a dark page. */
body.theme-dark .form-check-input {
  background-color: var(--surface-muted);
  border-color: var(--border-strong);
}
body.theme-dark .form-check-input:checked {
  /* The tick inside is a white SVG baked into Bootstrap, so the fill has to
     stay dark enough to carry it. */
  background-color: var(--primary-dark);
  border-color: var(--primary-dark);
}
/* .btn-close-white is already light — inverting it would turn it black. */
body.theme-dark .btn-close:not(.btn-close-white) {
  filter: invert(1) grayscale(100%) brightness(200%);
}

/* Bootstrap's colour utilities bake a literal white in and set it !important,
   so no token reaches them. On a dark page the box stayed white while the text
   on it followed the theme and turned light — white on white, and the words
   disappeared. bg-opacity is excluded on purpose: `bg-white bg-opacity-10` on
   the login panel is a deliberate 10% white wash over a gradient, not a bug. */
body.theme-dark .bg-white:not([class*="bg-opacity"]),
body.theme-dark .bg-body-tertiary,
body.theme-dark .bg-body-secondary {
  background-color: var(--surface) !important;
}
/* text-bg-light carries its own `color:#000`, and bg-light is often paired with
   .text-dark — both would leave black text on a now-dark chip, so the colour
   moves with the background. */
body.theme-dark .bg-light:not([class*="bg-opacity"]),
body.theme-dark .text-bg-light {
  background-color: var(--surface-muted) !important;
  color: var(--text) !important;
}

/* Somebody who has asked their system to stop animating gets no animation —
   including the hover lifts and reveals scattered through the components. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  .collapse-card:hover,
  .stat-card:hover,
  .card-lift:hover,
  .task-card:hover,
  .btn-primary:hover,
  .icon-btn:hover,
  .topbar-back:hover i,
  /* Ngritja e kartës së raportit: kalimi hiqet lart, zhvendosja jo. */
  .bi-report .bi-card:not(.bi-focused):hover,
  .btn:active {
    transform: none;
  }
  .js-reveal .reveal { opacity: 1; transform: none; }
  /* Pa animacion ky shirit do të ngelej bosh; i plotë thotë të vërtetën. */
  .present-progress.is-running { transform: scaleX(1); }
  /* Përjashtim i vetëm: rrotulluesi i butonit. Ai s'është zbukurim — është e
     vetmja gjë që thotë se puna ende po bëhet, dhe i ngrirë ai gënjen. Rregulli
     i mësipërm do ta ndalte pas një rrotullimi, prandaj rikthehet këtu, vetëm
     më i qetë. */
  .is-busy::before,
  /* Për të njëjtën arsye: rrotulluesi i paletës thotë «pyetja shkoi te serveri,
     përgjigja s'ka ardhur ende». I ngrirë pas një rrotullimi ai do të thoshte se
     s'ka më asgjë për të pritur — pikërisht atëherë kur ka. */
  .cmdk-backdrop.is-searching .cmdk-spinner {
    animation-duration: var(--beat) !important;
    animation-iteration-count: infinite !important;
  }

  /* Ç'vijon rri PAS rregullit të rrotulluesit me qëllim dhe jo nga rastësia:
     dy prova e maten këtë bllok nga fillimi i tij me dritare të fiksuara, dhe
     çdo rresht i futur para tyre e shtyn jashtë asaj dritareje pikërisht atë që
     ato kërkojnë. Shtesat vijnë në fund; kush shton, shton këtu.

     Skena e sfondit: rregulli `*` më lart nuk e heq lëvizjen, ai e shkurton —
     pra animacioni mbërrin te kuadri i fundit dhe ngec aty. Për një derivë
     kuadri i fundit ËSHTË zhvendosja, pra pa këtë rresht faqja do të hapej me
     vizatimin e shtyrë dhjetë piksele dhe tre përqind më të madh. Kjo s'do të
     lexohej si lëvizje e ndalur; do të lexohej si vendosje e gabuar. */
  body::after { animation: none; }

  /* Vonesat e kaskadës. `both` do të thotë se para se t'i vijë radha, elementi
     mban kuadrin e parë — dhe kuadri i parë është `opacity: 0`. Rregulli `*` e
     vret kohëzgjatjen, po jo vonesën: kush e ka fikur lëvizjen do të priste tri
     të dhjetat e sekondës para një titulli që s'ka fare për të lëvizur. Pra
     s'është hiq lëvizje më pak — është vetëm faqja që vjen vonë. */
  .stagger > *,
  .app-content .page-head .page-head-main > *,
  .app-content .page-head > .page-actions {
    animation-delay: 0s !important;
  }

  /* Shiriti i ngjarjeve, për të njëjtën arsye si skena: rregulli `*` nuk e ndal
     rrjedhjen, e shkurton — dhe kuadri i fundit i saj është `-50%`, pra shiriti
     do të hapej i zhvendosur mu te kopja e dytë, ajo që mban `aria-hidden`.
     Lexuesi i ekranit do të dëgjonte një listë të zbrazët mbi një shirit që
     tregon rreshta. Pra ndalet te fillimi, dhe lista arrihet me rrëshqitje: kush
     e ka fikur lëvizjen nuk humb asnjë ngjarje, thjesht i shkon vetë. */
  .bi-tick-track { animation: none; }
  /* Lista arrihet me rrëshqitje, dhe maska bie: ajo shuan skajet që teksti të mos
     pritet me thikë ndërsa kalon, po mbi një shirit që rri ajo vetëm zbeh
     rreshtin e parë dhe të fundit pa asnjë arsye. */
  .bi-tick-window { overflow-x: auto; mask-image: none; }
  /* Kopja e dytë ekziston vetëm që rrjedhja të mbyllet pa zbrazëti. Pa rrjedhje
     ajo është e njëjta listë e shkruar dy herë. */
  .bi-tick-run[aria-hidden="true"] { display: none; }
}

/* --- Zgjedhësi i subjekteve te ngarkimi i dokumenteve -----------------------
   Një listë rënëse me kuti zgjedhjeje. Paneli rri i pozicionuar absolut mbi
   fushat poshtë tij, jo mbi to duke i shtyrë: një listë që zgjatet e shkurton
   formularin sa herë hapet e bën faqen të kërcejë nën dorë. */
.owner-picker { position: relative; }
.owner-picker .js-owner-toggle {
  /* Duket si çdo fushë tjetër e formularit — është pikërisht ajo që zëvendëson —
     por shigjeta e form-select-it këtu do të thoshte «zgjedhje e vetme». */
  cursor: pointer;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.owner-picker.has-selection .js-owner-toggle {
  border-color: var(--primary);
  box-shadow: 0 0 0 var(--ring-w) var(--primary-soft);
}
.owner-menu {
  position: absolute;
  z-index: 20;
  left: 0;
  right: 0;
  margin-top: var(--space-1);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}
.owner-menu-head {
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--border);
  background: var(--surface-muted);
}
.owner-menu-actions {
  display: flex;
  align-items: center;
  gap: var(--space-1-5);
  margin-top: var(--space-2);
  flex-wrap: wrap;
}
.owner-menu-list { max-height: 15rem; overflow-y: auto; }
.owner-option {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1-5) var(--space-3);
  margin: 0;
  cursor: pointer;
  font-size: var(--text-sm);
}
.owner-option:hover { background: var(--surface-muted); }
.owner-option input { flex-shrink: 0; margin: 0; }
.owner-option-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Një formular i dërguar pa asnjë subjekt kthehet me listën e hapur dhe një
   rrahje të kuqe — mjaft për të treguar ku, pa një dritare tjetër mbi të. */
.owner-picker.is-invalid-picker .js-owner-toggle {
  border-color: var(--danger);
  animation: ownerNudge var(--dur-3) var(--ease-in-out) 2;
}
@keyframes ownerNudge {
  0%, 100% { transform: translateX(0); }
  25%      { transform: translateX(-4px); }
  75%      { transform: translateX(4px); }
}

/* --- Indeksi i arkivit: ç'ka brenda çdo dosje, dhe çfarë mbërriti sot -------
   «Dhjetë dokumente» dhe «dhjetë fatura shitjeje e asgjë tjetër» janë dy
   gjendje të ndryshme, dhe numri i vetëm i thotë të dyja njësoj. Përzierja rri
   nën emrin e dosjes, e vogël sa të lexohet pa e tërhequr syrin nga numri. */
.doc-mix {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
  margin-top: var(--space-0);
}
.doc-mix-chip {
  font-size: var(--text-2xs);
  font-weight: 500;
  line-height: 1.5;
  padding: 0 var(--space-1-5);
  border-radius: var(--radius-pill);
  background: var(--surface-hover);
  color: var(--muted);
  white-space: nowrap;
}
.doc-mix-chip.is-more { background: var(--primary-soft); color: var(--primary-text); }

/* Mbërritjet e fundit: emri i letrës është derë, pjesa tjetër është konteksti
   që e bën atë derë të kuptueshme — e kujt, e çfarë lloji, e cilës periudhë. */
.doc-recent-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding-top: var(--space-2);
  padding-bottom: var(--space-2);
}
.doc-recent-icon { color: var(--muted); flex-shrink: 0; }
.doc-recent-main { min-width: 0; flex: 1; }
.doc-recent-name {
  display: block;
  font-weight: 600;
  font-size: var(--text-sm);
  text-decoration: none;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.doc-recent-meta {
  display: block;
  font-size: var(--text-xs);
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.doc-recent-when {
  flex-shrink: 0;
  font-size: var(--text-xs);
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* --- Arkivi i një subjekti: dosje brenda dosjes ----------------------------
   Deri tani dosja hapej te një tabelë e sheshtë me disa butona filtri sipër.
   Ajo është një listë, jo një dosje: nuk të thotë ku ta vësh diçka, dhe s'ka
   ku të hysh. Këtu llojet janë dosje që hapen, dhe brenda tyre periudhat janë
   dosje të tjera. */
.doc-crumbs {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-1-5);
  font-size: var(--text-md);
}
.doc-crumbs a {
  color: var(--muted);
  text-decoration: none;
  padding: var(--space-0) var(--space-2);
  border-radius: var(--radius-sm);
}
.doc-crumbs a:hover { color: var(--primary); background: var(--primary-soft); }
.doc-crumbs .bi-chevron-right { font-size: var(--text-xs); color: var(--muted); opacity: .6; }
.doc-crumbs .current { font-weight: 600; color: var(--text); padding: var(--space-0) var(--space-2); }

.folder-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  gap: var(--space-3);
}
.folder-grid-sm { grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr)); }

.folder-card {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  text-decoration: none;
  color: var(--text);
  transition: transform var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease-out), border-color var(--dur-2) var(--ease-out);
}
.folder-card:hover {
  transform: translateY(-2px);
  border-color: var(--primary);
  box-shadow: var(--shadow-md);
  color: var(--text);
}
.folder-card-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  flex-shrink: 0;
  border-radius: var(--radius);
  font-size: var(--text-lg);
  color: #fff;
  background: var(--grad-primary);
}
.folder-card-body { display: flex; flex-direction: column; min-width: 0; }
.folder-card-name {
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.folder-card-meta { font-size: var(--text-xs); color: var(--muted); }
.folder-card-go { margin-left: auto; color: var(--muted); opacity: .5; font-size: var(--text-sm); }
/* Një dosje bosh mbetet e hapshme — aty ngarkohet gjëja e parë — por nuk kërkon
   vëmendje sa një që ka diçka brenda. */
.folder-card.is-empty .folder-card-icon { background: var(--surface-muted); color: var(--muted); }
.folder-card.is-empty .folder-card-name { color: var(--muted); font-weight: 500; }

/* ── Zëri i task-ut ──────────────────────────────────────────────────────────
   Nën përshkrimin, jo te bashkëngjitjet: një incizim është shpjegim pune, dhe
   shpjegimi rri aty ku lexohet detyra. Butoni i vetëm ndërron kuptim me
   gjendjen — mikrofon kur hesht, katror i kuq kur incizon — sepse dy butona,
   njëri gjithnjë i pafuqishëm, e bënin shiritin të duket i prishur. */
.voice-note {
  margin: var(--space-3) 0 0;
  padding: var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface-muted);
}
.voice-bar { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.voice-mic {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  flex-shrink: 0;
  border: 0;
  border-radius: var(--radius-round);
  color: #fff;
  font-size: var(--text-base);
  background: var(--grad-primary);
  box-shadow: var(--shadow-sm);
  transition: transform var(--dur-1) var(--ease-out), box-shadow var(--dur-2) var(--ease-out), background var(--dur-2) var(--ease-out);
}
.voice-mic:hover { transform: translateY(-1px); box-shadow: var(--shadow-glow); }
.voice-mic:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
/* Kur incizon, butoni duhet parë nga cepi i syrit: e kuqe që rreh, se ndryshe
   mikrofoni mbetet ndezur pa e vënë re askush. */
.voice-note.is-recording .voice-mic {
  background: var(--danger);
  animation: voice-pulse var(--beat) var(--ease-in-out) infinite;
}
@keyframes voice-pulse {
  0%, 100% { box-shadow: 0 0 0 0 var(--danger-soft); }
  50% { box-shadow: 0 0 0 .55rem transparent; }
}
@media (prefers-reduced-motion: reduce) {
  .voice-note.is-recording .voice-mic { animation: none; }
}
.voice-text { font-size: var(--text-sm); color: var(--muted); flex: 1 1 12rem; min-width: 0; }
.voice-text-ok { color: var(--success); }
.voice-text-bad { color: var(--danger); }
.voice-timer {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: var(--danger);
}

/* Hapësira vjen nga rreshti i parë, jo nga lista: një listë bosh (Jinja lë
   gjithnjë pak bardhësi brenda saj) nuk duhet të hapë vend për asgjë. */
.voice-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-2); }
.voice-item:first-child { margin-top: var(--space-3); }
.voice-item {
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
}
.voice-item-head {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-sm);
  color: var(--muted);
  margin-bottom: var(--space-1-5);
}
.voice-item-who { color: var(--text); }
.voice-item-when { margin-left: auto; }
.voice-item audio { width: 100%; height: 34px; display: block; }
.voice-del {
  border: 0;
  background: none;
  padding: 0 var(--space-0);
  color: var(--muted);
  line-height: 1;
}
.voice-del:hover { color: var(--danger); }
.voice-empty { margin-top: var(--space-2); }

/* I njëjti incizues te forma e task-ut të ri, por i qetë: aty është shtesë e
   përshkrimit, jo një pjesë më vete e faqes. Vija me pika e thotë se ende s'ka
   asgjë brenda — dhe se ajo që bie brenda niset me formularin. */
.voice-note-inline {
  margin-top: var(--space-2);
  padding: var(--space-2);
  background: transparent;
  border-style: dashed;
}
.voice-note-inline .voice-mic { width: 34px; height: 34px; font-size: var(--text-md); }

/* Te biseda incizuesi s'ka kornizë fare: kompozuesi e ka tashmë të vetën, dhe
   një kuti brenda një kutie e ngushton rreshtin e shkrimit pa i dhënë asgjë. */
.voice-note-chat { margin: 0; padding: 0; border: 0; background: none; }
.voice-bar-chat { min-height: 0; margin-bottom: 0; }
.voice-bar-chat:not(:empty) .voice-text:not(:empty) { margin-bottom: var(--space-1-5); }
/* Mikrofoni rri si të tjerët në rresht — rrethi me gradient i faqes së task-ut
   do t'i bënte konkurrencë butonit «Dërgo» dhe do të lexohej si veprimi kryesor,
   që nuk është. E kuqja e incizimit vjen nga rregulli i përbashkët më sipër. */
.tm-composer .voice-mic {
  width: auto;
  height: auto;
  border-radius: var(--radius-sm);
  background: none;
  color: inherit;
  box-shadow: none;
}
.tm-composer .voice-mic:hover { transform: none; box-shadow: none; }
.voice-note-chat.is-recording .voice-mic { color: #fff; border-color: var(--danger); }
.voice-bar-chat .voice-text { flex: 1 1 auto; }

/* Zëri brenda flluskës së mesazhit. */
.tm-voice { display: flex; align-items: center; gap: var(--space-2); margin: var(--space-0) 0; }
.tm-voice-icon { color: var(--tm-accent); flex-shrink: 0; }
.tm-voice audio { height: 34px; max-width: 15rem; flex: 1 1 auto; min-width: 0; }
.tm-voice-len {
  font-size: var(--text-xs);
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Thirrja e mbaruar brenda fillit. E qetë me qëllim — ajo është shënim i asaj
   që ndodhi, jo mesazh për t'u lexuar — përveç asaj që humbi: një thirrje pa
   përgjigje është pikërisht gjëja që syri duhet ta kapë duke rrëshqitur. */
.tm-call {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-pill);
  background: var(--surface-muted);
  border: 1px solid var(--border);
  color: var(--muted);
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
}
.tm-call.is-missed {
  background: var(--danger-soft);
  border-color: color-mix(in srgb, var(--danger) 25%, transparent);
  color: var(--danger);
}

/* --- Zilja e njoftimeve -------------------------------------------------------
   Numri rri mbi ikonën, jo pranë saj: koka e faqes është e ngushtë në telefon,
   dhe një shenjë e vogël mbi zile lexohet edhe kur fjalët nuk nxënë. */
.note-dot {
  position: absolute;
  top: -2px;
  right: -2px;
  min-width: 1.05rem;
  padding: var(--space-0) var(--space-1);
  background: var(--grad-primary);
  color: #fff;
  font-size: var(--text-2xs);
  font-weight: 700;
  line-height: 1.25;
  border-radius: var(--radius-pill);
  text-align: center;
  box-shadow: var(--ring-cut);
}
.note-menu { width: min(22rem, calc(100vw - 1.5rem)); padding-bottom: var(--space-1); }
/* Tetë njoftime nxënë; të tjerat rrjedhin brenda menusë, që ajo të mos dalë
   jashtë ekranit dhe të marrë me vete edhe lidhjen «Të gjitha». */
.note-menu-body { max-height: 22rem; overflow-y: auto; }
.note-menu .dropdown-item { white-space: normal; }
.note-unread { background: var(--primary-soft); }
.note-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 34px;
  height: 34px;
  border-radius: var(--radius);
  background: var(--primary-soft);
  color: var(--primary);
  box-shadow: inset 0 0 0 var(--hairline) var(--primary-line);
}

/* ============================================================================
   LETRA
   ----------------------------------------------------------------------------
   Kjo zyrë printon. Deri tani printimi i një liste nxirrte mbi të gjithë faqen
   e parë menynë me njëzet e dy lidhje, shiritin e sipërm, kutinë e kërkimit dhe
   butonat «Klient i ri / Eksporto Excel» — dhe pastaj, diku poshtë tyre,
   tabelën për të cilën njeriu shtypi Ctrl P. Nën temën e errët dilte edhe e
   zezë faqe më faqe. Ky bllok e bën letrën letër: mbeten të dhënat, koka e
   tabelës përsëritet në çdo fletë, dhe lart shkruhet çfarë është kjo fletë, kur
   u shtyp dhe nga kush — sepse një fletë pa këto tri gjëra, e gjetur mbi tavolinë
   pas dy javësh, s'i përgjigjet dot asnjë pyetjeje.

   Faqja shtypet gjithnjë e bardhë me shkronja të zeza, pavarësisht temës në
   ekran: tema është një zgjedhje për sytë, jo për bojën e printerit.
   ========================================================================== */
.print-head { display: none; }

@media print {
  @page { margin: 14mm 12mm; }

  /* Vegla ekrani. Asnjëra prej tyre s'ka kuptim mbi letër, dhe secila zë vend. */
  .app-sidebar, .app-topbar, .bottom-nav, .toast-stack, .skip-link,
  .cmdk-backdrop, .sheet-backdrop, .offcanvas-backdrop, .modal, .modal-backdrop,
  .page-actions, .net-chip, .btn-close, .dropdown-menu,
  .tbl-col-actions { display: none !important; }

  /* Ngjyra e temës nuk shkon te bojë. */
  html, body {
    background: #fff !important;
    color: #000 !important;
  }
  body.theme-dark { --text: #000; --muted: #333; --border: rgba(0,0,0,.25); }

  .app-shell, .app-main, .app-content {
    display: block !important;
    margin: 0 !important;
    padding: 0 !important;
    max-width: none !important;
    width: auto !important;
    height: auto !important;
    overflow: visible !important;
  }

  /* Koka e fletës: çfarë, kur, nga kush. Mbushet nga site.js pak para se të
     nisë shtypja, që të mos rrijë një datë e ngrirë nga çasti i hapjes. */
  .print-head {
    display: flex !important;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-4);
    padding-bottom: var(--space-1-5);
    margin-bottom: var(--space-3);
    border-bottom: 2px solid #000;
  }
  .print-brand { font-weight: 800; font-size: var(--text-base); letter-spacing: -.01em; }
  .print-title { font-weight: 700; }
  .print-meta { font-size: var(--text-xs); text-align: right; line-height: 1.35; }

  /* Kartelat bëhen blloqe të thjeshta: hija dhe qelqi janë gjuhë ekrani. */
  .card, .table-card, .stat-card, .bi-card {
    box-shadow: none !important;
    border: 1px solid #999 !important;
    background: #fff !important;
    backdrop-filter: none !important;
    break-inside: avoid;
    page-break-inside: avoid;
  }
  .stat-grid { display: grid !important; grid-template-columns: repeat(4, 1fr); gap: var(--space-2); }
  .stat-value { font-size: var(--text-lg) !important; }
  /* Rreshti i fundit i një pllake është premtim klikimi — «Arkëtimet →» ose «Shfaq
     punëtorët ⌄». Mbi letër premtimi nuk vlen, dhe listat që ai hap dalin
     gjithsesi të hapura (shih `.collapse:not(.show)` më poshtë). Deri tani ai
     rresht ishte një `btn` dhe printohej si drejtkëndësh bosh me tekst blu. */
  .stat-go { display: none !important; }

  /* Kufiri i tabelës nuk pritet në mes të fletës, dhe koka e saj përsëritet
     lart në secilën: një tabelë tridhjetërreshtëshe zë dy fletë, dhe e dyta pa
     kokë është një kolonë numrash pa emër. */
  .table-responsive, .table-sticky {
    max-height: none !important;
    overflow: visible !important;
  }
  table.table thead { display: table-header-group; }
  table.table tfoot { display: table-footer-group; }
  table.table tr { break-inside: avoid; page-break-inside: avoid; }
  table.table { font-size: var(--text-xs); width: 100% !important; }
  table.table th, table.table td { padding: var(--space-1) var(--space-1-5) !important; }
  .table-hover > tbody > tr:hover > * { background: transparent !important; }

  /* Çipat e statusit humbin sfondin, jo kuptimin: mbeten fjalë me një vijë
     rreth, që lexohen edhe në një printer bardhezi. */
  .chip {
    background: transparent !important;
    color: #000 !important;
    border: 1px solid #666 !important;
  }

  /* Ajo që rri e mbledhur në ekran hapet në letër: një `collapse` i mbyllur
     mbi letër është thjesht një pjesë e raportit që mungon pa e ditur askush. */
  .collapse:not(.show) { display: block !important; }

  h1, h2, h3, h4, .page-title { break-after: avoid; page-break-after: avoid; }
  a { text-decoration: none !important; color: #000 !important; }
}

/* ============================================================================
   PANELI
   ----------------------------------------------------------------------------
   Ekrani i parë i mëngjesit, që rri hapur deri në darkë. Prandaj tri gjëra këtu
   kanë rregull të vetin: numri thotë sa i vjetër është, numri thotë kundrejt
   çfarë, dhe rreshti i aktivitetit është derë e jo lajm.
   ========================================================================== */

/* --- Shenja e freskisë ---------------------------------------------------- */
.pulse-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1-5);
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-pill);
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--success);
  background: var(--success-soft);
  white-space: nowrap;
}
/* Pesë minuta pa përgjigje nga serveri: shenja s'gënjen më se është e gjallë.
   Bie edhe rrahja e pikës — një pikë që pulson mbi një numër të vjetër është
   pikërisht gënjeshtra që kjo shenjë ekziston për ta ndaluar. */
.pulse-chip.is-stale { color: var(--muted); background: var(--surface-sunken); }
.pulse-chip.is-stale .pulse-dot { background: var(--faint); animation: none; box-shadow: none; }

/* Numri që ndërroi nën sytë e njeriut. Pa këtë ai ndërrohet pa u parë. */
@keyframes pulseChanged {
  0%   { background: var(--primary-soft); }
  100% { background: transparent; }
}
.pulse-changed {
  animation: pulseChanged var(--beat) var(--ease-out);
  border-radius: var(--radius-xs);
}
@media (prefers-reduced-motion: reduce) {
  .pulse-changed { animation: none; }
}

/* --- Krahasimi te kartela ------------------------------------------------- */
.kpi-delta {
  display: inline-flex;
  align-items: center;
  font-weight: 700;
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
}
.kpi-delta.is-up { color: var(--success); }
.kpi-delta.is-down { color: var(--danger); }
/* «I pari»: s'ka bazë krahasimi, dhe kjo nuk është as lajm i mirë as i keq. */
.kpi-delta.is-none { color: var(--faint); font-weight: 600; }
.kpi-delta i { font-size: 1.1em; margin-left: calc(var(--space-0) * -1); }

/* --- Gjashtë muajt: shitje kundrejt blerjeve ------------------------------ */
.mini-chart {
  display: flex;
  align-items: flex-end;
  gap: var(--space-2);
  height: 132px;
}
.mini-col { flex: 1; display: flex; flex-direction: column; height: 100%; min-width: 0; }
.mini-bars {
  flex: 1;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: var(--space-0);
}
.mini-bar {
  display: block;
  width: 46%;
  max-width: 22px;
  /* Një muaj me zero fatura duhet të mbetet i dukshëm si zero, jo të zhduket:
     mungesa e shtyllës dhe mungesa e muajit duken njësoj. */
  min-height: 2px;
  border-radius: var(--radius-xs) var(--radius-xs) 0 0;
  transition: height var(--dur-3) var(--ease-out);
}
.mini-bar.is-sale { background: var(--chart-revenue); }
.mini-bar.is-purchase { background: var(--chart-expense); }
.mini-label {
  text-align: center;
  font-size: var(--text-xs);
  color: var(--muted);
  padding-top: var(--space-1-5);
  border-top: 1px solid var(--border);
  margin-top: var(--space-1);
  white-space: nowrap;
}
/* Muaji i çastit është i pambaruar; pa këtë shenjë një gjysmë muaji pranë pesë
   të plotave lexohet si rënie. */
.mini-col.is-now .mini-label { color: var(--text); font-weight: 700; }
.mini-now {
  font-size: var(--text-2xs);
  font-weight: 700;
  color: var(--primary-text);
  background: var(--primary-soft);
  border-radius: var(--radius-pill);
  padding: 0 var(--space-1-5);
}
body.theme-dark .mini-now { color: var(--primary); }
.mini-legend { display: inline-flex; gap: var(--space-4); font-size: var(--text-xs); color: var(--muted); }
.mini-legend span { display: inline-flex; align-items: center; gap: var(--space-1-5); }
.mini-dot {
  display: inline-block;
  width: .6rem;
  height: .6rem;
  border-radius: var(--radius-xs);
  margin-right: var(--space-1-5);
  vertical-align: -1px;
}
.mini-dot.is-sale { background: var(--chart-revenue); }
.mini-dot.is-purchase { background: var(--chart-expense); }
.mini-table { font-size: var(--text-xs); }
.mini-table td, .mini-table th { font-variant-numeric: tabular-nums; }

/* Te regjistri i faturave i njëjti shirit është edhe filtër: çdo muaj është një
   lidhje që e ngushton listën poshtë. Prandaj i duhet një sipërfaqe që reagon —
   dhe një shenjë për muajin që rri i zgjedhur, ndryshe nga «tani». */
.mini-col-link {
  text-decoration: none;
  color: inherit;
  border-radius: var(--radius-sm);
  padding: var(--space-1) var(--space-0) 0;
  transition: background var(--dur-2) var(--ease-out);
}
.mini-col-link:hover { background: var(--surface-hover); color: inherit; }
.mini-col-link:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
.mini-col.is-picked { background: var(--primary-soft); }
.mini-col.is-picked .mini-label { color: var(--primary-text); font-weight: 700; }
body.theme-dark .mini-col.is-picked .mini-label { color: var(--primary); }

@media (max-width: 575.98px) {
  /* Në telefon gjashtë muaj në 360px do të thoshin shtylla 8-pikselëshe me
     etiketa mbi njëra-tjetrën. Grafiku rrëshqet; tabela poshtë e mban tërë të
     vërtetën për atë që s'e rrëshqet dot. */
  .mini-chart { overflow-x: auto; }
  .mini-col { min-width: 46px; }
}

/* --- Dublikatat e mundshme te regjistri i faturave ------------------------
   Një paralajmërim, jo një ndalesë: rreshtat rrinë të hapshëm që njeriu të
   shkojë te letra e dyshimtë me një klikim dhe të vendosë vetë. */
.dup-group + .dup-group { margin-top: var(--space-4); }
.dup-head {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
  font-size: var(--text-md);
  margin-bottom: var(--space-1-5);
}
.dup-head > i { color: var(--warning); }
.dup-rows {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
}
.dup-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-sm);
  text-decoration: none;
  color: inherit;
  background: var(--warning-soft);
}
.dup-row + .dup-row { border-top: 1px solid var(--border); }
.dup-row:hover { background: var(--surface-hover); color: inherit; }

/* --- Ç'bie në sy te regjistri: shenja që është edhe filtër -----------------
   Gjeometrinë e mban komponenti i përbashkët (`.inv-signal` rri te po ata
   selektorë si `.cl-signal`, më lart te ky skedar). Këtu shtohet vetëm ajo që
   e dallon: kutia është lidhje, pra i duhet toni i tekstit dhe një gjendje «kjo
   po lexohet» — po ajo unazë si te kartat-filtër, që dy komponentë të mos e
   thonë të njëjtën gjë me dy zëra. */
.inv-signal { text-decoration: none; color: inherit; display: block; }
.inv-signal:hover { background: var(--surface-hover); color: inherit; }
.inv-signal:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
.inv-signal.is-picked {
  border-color: var(--primary);
  box-shadow: 0 0 0 var(--ring-w-lg) var(--primary-soft);
}
.inv-signal.is-picked .inv-signal-top { color: var(--primary-text); }

/* Numrat që mungojnë, jo vetëm sa janë: pyetja e radhës është gjithnjë «cilët». */
.inv-gaps {
  margin-top: var(--space-3);
  display: flex;
  flex-direction: column;
  gap: var(--space-1-5);
}
.inv-gap {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--space-2);
  font-size: var(--text-sm);
}
.inv-gap-name { font-weight: 600; text-decoration: none; }
.inv-gap-nums { display: flex; flex-wrap: wrap; gap: var(--space-1); }
.inv-gap-num {
  font-variant-numeric: tabular-nums;
  font-size: var(--text-xs);
  padding: var(--space-0) var(--space-1-5);
  border: 1px dashed var(--danger-fill);
  border-radius: var(--radius-sm);
  color: var(--danger);
  background: var(--danger-soft);
}

/* --- Rreshti i regjistrit -------------------------------------------------
   Përshkrimi dhe NUI-ja rrinë nën qelizën që i mban, jo te dy shtylla të tyret:
   një rresht që e thotë vetë se çfarë ishte malli lexohet më shpejt se një
   tabelë që të kërkon të numërosh shtyllat. */
.inv-sub {
  display: block;
  font-size: var(--text-xs);
  font-weight: 400;
  color: var(--faint);
  line-height: 1.35;
  /* Përshkrimi mund të jetë një fjali e tërë; shtylla nuk zgjatet për të. Kufiri
     u mat: pa të, «Nr.» dilte 204px dhe tabela tepronte 98px jashtë kutisë së vet
     te një ekran 1280px. Teksti i plotë rri te `title`. */
  max-width: 9rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.inv-num { font-variant-numeric: tabular-nums; }
/* Norma pranë TVSH-së që e shpjegon. Shifra e vërtetë e qelizës rri te
   `data-sort`, prandaj kjo etiketë s'hyn kurrë te shuma poshtë tabelës. */
.inv-rate {
  display: inline-block;
  margin-left: var(--space-1-5);
  padding: 0 var(--space-1);
  border-radius: var(--radius-sm);
  background: var(--surface-muted);
  color: var(--faint);
  font-size: var(--text-2xs);
  font-variant-numeric: tabular-nums;
  vertical-align: .05em;
}
/* Fshirja dhe dryni janë të njëjtat ikona të qeta si të tjerat te `.row-act` —
   ndryshon vetëm ngjyra që marrin kur i prek dora. */
.row-act-btn.is-danger:hover,
.row-act-btn.is-danger:focus-visible {
  color: var(--danger);
  background: var(--danger-soft);
  border-color: var(--danger-fill);
}
.row-act-btn.is-locked { color: var(--warning); cursor: help; }

/* --- Aktiviteti: rreshti është derë --------------------------------------- */
.timeline-item { display: flex; gap: var(--space-2); align-items: flex-start; }
/* Pika e vjetër zëvendësohet nga ikona e llojit: dy shenja për të njëjtin vend
   do të thoshin dy rrathë njëri mbi tjetrin. */
.timeline-item:has(.timeline-icon)::before { content: none; }
.timeline-icon {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.6rem;
  height: 1.6rem;
  margin-left: -1.75rem;
  border-radius: var(--radius-round);
  font-size: var(--text-xs);
  background: var(--surface);
  color: var(--primary);
  box-shadow: inset 0 0 0 var(--ring-w) var(--primary-line);
}
.timeline-body { min-width: 0; }
.timeline-task .timeline-icon { color: var(--primary); }
.timeline-reminder .timeline-icon { color: var(--warning); box-shadow: inset 0 0 0 var(--ring-w) var(--warning-soft); }
.timeline-announcement .timeline-icon { color: var(--accent); box-shadow: inset 0 0 0 var(--ring-w) var(--accent-soft); }
.timeline-meeting .timeline-icon { color: var(--info); box-shadow: inset 0 0 0 var(--ring-w) var(--info-soft); }
a.timeline-item.is-linked {
  text-decoration: none;
  color: inherit;
  border-radius: var(--radius-sm);
  padding-right: var(--space-1-5);
}
a.timeline-item.is-linked:hover { background: var(--surface-hover); }
a.timeline-item.is-linked:hover .small { color: var(--primary-text); }
body.theme-dark a.timeline-item.is-linked:hover .small { color: var(--primary); }

@media print {
  /* Shenja e freskisë dhe ftesa për rifreskim janë vegla ekrani. */
  .pulse-chip, #pulseNew { display: none !important; }
  /* Afatet e mbledhura hapen: një raport i shtypur me gjysmën e listës të
     fshehur nuk e thotë askund se është i gjysmuar. */
  .deadline-extra.d-none { display: flex !important; }
}

/* ============================================================================
   KLIENTËT
   ----------------------------------------------------------------------------
   Lista e klientëve nuk lexohet si listë emrash, lexohet si listë punësh: kush
   ka mbetur pa paguar, kujt i ka kaluar afati, kush s'ka lëvizur prej muajsh.
   Prandaj karta lart është edhe filtër, dhe rreshti mban një panel që e thotë
   dosjen pa e hapur atë.
   ========================================================================== */

/* Karta-filtër është lidhje, jo buton: pa JavaScript ajo prapë e hap listën e
   vet. Ngjyra e lidhjes hiqet këtu, që kutia të mbetet kuti. */
a.stat-card-filter { color: inherit; text-decoration: none; }
a.stat-card-filter:hover .stat-label { color: var(--primary-text); }
body.theme-dark a.stat-card-filter:hover .stat-label { color: var(--primary); }

/* --- Ku rri paraja e hapur -------------------------------------------------
   Tri kovat e moshës si një shirit i vetëm. Kartela lart i mban të njëjtat tri
   shifra si tekst, dhe atje tetëdhjetë mijë të shpërndara lexohen njësoj si
   tetëdhjetë mijë të grumbulluara mbi gjashtëdhjetë ditë — kurse në zyrë ato
   janë dy gjendje krejt të ndryshme. Gjerësinë e çdo cope e di vetëm serveri,
   prandaj vjen si `--seg`; ngjyrat janë po ato të statusit, jo të reja. */
.cl-aging {
  display: flex;
  height: .7rem;
  border-radius: var(--radius-pill);
  overflow: hidden;
  background: var(--surface-muted);
  box-shadow: inset 0 0 0 var(--hairline) var(--border);
}
.cl-aging-seg { width: var(--seg, 0%); min-width: 2px; }
.cl-aging-seg.is-now { background: var(--success-fill); }
.cl-aging-seg.is-mid { background: var(--warning-fill); }
.cl-aging-seg.is-old { background: var(--danger-fill); }
.cl-aging-keys {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-top: var(--space-2);
  font-size: var(--text-xs);
  color: var(--muted);
}
/* Pika e ngjyrës para fjalës: pa të, legjenda është tri fjalë që s'i përkasin
   asnjë cope të shiritit. */
.cl-aging-key::before {
  content: '';
  display: inline-block;
  width: .55rem;
  height: .55rem;
  margin-inline-end: var(--space-1-5);
  border-radius: var(--radius-round);
  vertical-align: baseline;
}
.cl-aging-key.is-now::before { background: var(--success-fill); }
.cl-aging-key.is-mid::before { background: var(--warning-fill); }
.cl-aging-key.is-old::before { background: var(--danger-fill); }
.cl-aging-pct { color: var(--faint); font-variant-numeric: tabular-nums; }

/* Numri brenda çipit të filtrit: përgjigjja rri pranë pyetjes, që «sa janë të
   fjetur» të lexohet pa u klikuar asgjë. */
.chip-count {
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  opacity: .7;
}

/* --- Rreshti: kush është ---------------------------------------------------
   Dosja njihet para se të lexohet. Njëqind emra biznesesh me të njëjtën peshë
   janë njëqind rreshta ku syri e humb vendin sa herë ngrihet nga tabela; një
   shkronjë me ngjyrë e mban atë vend, dhe rreshti i dytë thotë ato tri gjëra që
   e vendosin klientin — llogaria, qyteti, sa kushton në muaj. */
.cl-ident { display: flex; align-items: center; gap: var(--space-2); min-width: 0; }
.cl-ident-main { min-width: 0; }
.cl-ident-name { font-weight: 600; color: inherit; text-decoration: none; }
.cl-ident-name:hover { color: var(--primary-text); text-decoration: underline; }
.cl-ident-meta {
  font-size: var(--text-xs);
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* NUI-ja dhe numri i TVSH-së zbritën nga shtylla e tyre te ky rresht. Shifrat
   njëgjerësishe që dy numra njëri mbi tjetrin të krahasohen si numra — me
   gjerësi të ndryshme, syri krahason gjatësi dhe lexon dy numra të njëjtë si të
   ndryshëm. */
.cl-ident-num { font-variant-numeric: tabular-nums; }
/* Kontakti është veprim, jo tekst — por ngjyra e lidhjes vjen vetëm kur preket:
   dyqind adresa blu do ta ktheheshin shtyllën në mur. */
.cl-contact { color: inherit; text-decoration: none; }
.cl-contact:hover { color: var(--primary-text); text-decoration: underline; }

/* Dosja pa asgjë të hapur s'ka nevojë për çip: kur nëntë rreshta nga dhjetë
   mbajnë një çip të gjelbër «Aktiv», ai çip nuk thotë më asgjë. Në vend të tij
   një shenjë e vetme e qetë, dhe pas saj — vetëm kur ka arsye — dy shenja të
   vogla që e shtojnë atë arsye pa e përsëritur alarmin. */
.cl-ok { color: var(--success); }
.cl-flags { display: inline-flex; gap: var(--space-1); margin-inline-start: var(--space-1); }
.cl-flag { color: var(--faint); font-size: var(--text-sm); }

/* --- Rreshti: çfarë bëhet me të --------------------------------------------
   Tetë butona me kufi për rresht janë tetëqind kuti të vizatuara te një listë me
   njëqind klientë, dhe shtylla që dilte prej tyre lexohej si mur, jo si zgjedhje.
   Mbeten tri: shiko, bisedo, hap. Të tjerat i mban paneli që hapet me të parin.

   Dy të parat rrinë si ikona të QETA — pa kufi derisa t'i prekësh — por kurrë të
   fshehura: një veprim që del vetëm nën miun nuk ekziston as për gishtin, as për
   tastierën. Ndryshon toni, kurrë prania. */
.row-act { display: inline-flex; align-items: center; justify-content: flex-end; gap: var(--space-1); }
.row-act-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.85rem;
  height: 1.85rem;
  padding: 0;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--muted);
  font-size: var(--text-md);
  line-height: 1;
  text-decoration: none;
}
/* Rreshti nën miun i afron: aty ku po lexon dikush, veprimet dalin nga heshtja
   pa e humbur qetësinë e tërë shtyllës. */
tr:hover > td .row-act-btn { color: var(--text); }
.row-act-btn:hover,
.row-act-btn:focus-visible {
  color: var(--primary-text);
  background: var(--primary-soft);
  border-color: var(--primary-line);
}

/* --- Paneli i shpejtë ----------------------------------------------------- */
/* Gjashtë shifra lart, katër lista poshtë: pikërisht ato që i duhen dikujt para
   se të vendosë nëse ia vlen të hapë dosjen e plotë. */
.peek-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr));
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}
.peek-fig {
  padding: var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-muted);
}
.peek-label {
  font-size: var(--text-2xs);
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--faint);
}
.peek-value {
  font-size: var(--text-lg);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.peek-fig-good .peek-value { color: var(--success); }
.peek-fig-warn .peek-value { color: var(--warning); }
.peek-fig-bad  .peek-value { color: var(--danger); }

.peek-gaps { margin-bottom: var(--space-4); }

.peek-block + .peek-block { margin-top: var(--space-4); }
.peek-block-title {
  font-size: var(--text-2xs);
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--faint);
  margin-bottom: var(--space-2);
}
.peek-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-1-5) 0;
  border-bottom: 1px solid var(--border);
  font-size: var(--text-sm);
}
.peek-row:last-child { border-bottom: 0; }
.peek-row-main { min-width: 0; overflow-wrap: anywhere; }
.peek-row-side {
  flex-shrink: 0;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
/* Afati i shkelur nuk është një rresht si të tjerët, dhe as ngjyra e tij nuk
   është dekor: ai është arsyeja pse paneli u hap. */
.peek-row-late .peek-row-side { color: var(--danger); font-weight: 700; }
.peek-empty {
  font-size: var(--text-sm);
  color: var(--faint);
  padding: var(--space-1-5) 0;
}
/* Veprimet e klientit, të mbledhura këtu nga rreshti. Rrinë POSHTË shifrave
   sepse paneli hapet me një pyetje dhe mbyllet me një vendim: së pari «ç'ka ky»,
   pastaj «ç'bëj me të». Vija sipër tyre e thotë atë ndarje. */
.peek-actions {
  margin-top: var(--space-4);
  padding-top: var(--space-3);
  border-top: 1px solid var(--border);
}
.peek-actions-row { display: flex; flex-wrap: wrap; gap: var(--space-2); }

/* --- Asistenti ------------------------------------------------------------
   Një bisedë, jo një tabelë. Kutia rri e lartë me qëllim: përgjigjja e modelit
   është tekst i lirë, dhe një kuti që rritet me të e zhvendos butonin e pyetjes
   poshtë ekranit — pikërisht atje ku njeriu do të shkruante të dytën. */
.ai-thread {
  /* Ishte `min(58vh, 620px)`, dhe me të kutia e pyetjes binte NËN palosje te të
     tria gjerësitë e matura: 833px te 1440×900, 795px te 1280×720, 1012px te
     telefoni. Veprimi kryesor i faqes nuk duhet kërkuar me rrëshqitje — dhe
     biseda rrëshqet vetë, pra ajo që hiqet këtu nuk humbet. */
  max-height: min(52vh, 560px);
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.ai-msg { max-width: 46rem; }
/* Pyetja e njeriut rri djathtas, përgjigjja majtas — e njëjta gramatikë si te
   çdo bisedë tjetër e programit, që syri ta lexojë pa e menduar. */
.ai-msg-user { align-self: flex-end; }
.ai-msg-assistant { align-self: flex-start; }
.ai-msg-who {
  display: flex;
  align-items: center;
  gap: var(--space-1-5);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--faint);
  margin-bottom: var(--space-1);
}
.ai-msg-user .ai-msg-who { justify-content: flex-end; }
.ai-msg-time { font-weight: 500; text-transform: none; letter-spacing: 0; }
.ai-msg-body {
  /* Teksti vjen ashtu si e shkroi modeli: rreshtat dhe listat e tij janë
     kuptim, jo formatim, prandaj ruhen — dhe kurrë nuk interpretohet si HTML. */
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  padding: var(--space-3);
  border-radius: var(--radius);
  border: 1px solid var(--border);
  line-height: 1.55;
}
.ai-msg-user .ai-msg-body {
  background: var(--accent-soft);
  border-color: color-mix(in srgb, var(--accent) 35%, transparent);
}
.ai-msg-assistant .ai-msg-body { background: var(--surface, transparent); }
.ai-examples { display: flex; flex-wrap: wrap; gap: var(--space-2); justify-content: center; }

/* Përgjigjja që nuk erdhi. E kuqe e butë, jo alarm: modeli lokal që fle është
   gjendje e zakonshme, dhe rreshti duhet lexuar, jo pësuar. */
.ai-msg-failed { border-color: var(--danger); color: var(--danger); }

/* Tri pikat derisa vjen fjala e parë. Pa to, kutia e përgjigjes rri bosh dhe
   bosh lexohet si «nuk ndodhi asgjë» — pikërisht gjatë sekondave kur modeli
   lokal po lexon faktet. */
.ai-typing { display: inline-flex; gap: var(--space-1); align-items: center; padding: var(--space-0) 0; }
.ai-typing i {
  width: .45rem; height: .45rem; border-radius: var(--radius-round);
  background: var(--faint);
  animation: ai-typing-dot var(--beat-fast) infinite var(--ease-in-out);
}
.ai-typing i:nth-child(2) { animation-delay: .15s; }
.ai-typing i:nth-child(3) { animation-delay: .3s; }
@keyframes ai-typing-dot {
  0%, 60%, 100% { opacity: .25; transform: translateY(0); }
  30% { opacity: 1; transform: translateY(-.15rem); }
}
@media (prefers-reduced-motion: reduce) {
  .ai-typing i { animation: none; opacity: .5; }
}

/* --- Kutia e pyetjes: letra dhe zëri --------------------------------------
   Të tri butonat rrinë brenda kutisë, poshtë djathtas, që në telefon të jenë aty
   ku është gishti — jo në një rresht të dytë që kërkon lëvizje. */
.ai-box { position: relative; }
.ai-box textarea { padding-bottom: 2.75rem; }
.ai-tools {
  position: absolute;
  right: .5rem;
  bottom: .5rem;
  display: flex;
  gap: var(--space-1);
}
.ai-tool {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* 2.5rem = 40px: sa gishti, jo sa shigjeta e miut. Nën këtë, çdo klikim në
     telefon bëhet lojë saktësie. */
  width: 2.5rem;
  height: 2.5rem;
  border-radius: var(--radius-round);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--muted);
  cursor: pointer;
  transition: background var(--dur-2) var(--ease-out), color var(--dur-2) var(--ease-out), border-color var(--dur-2) var(--ease-out);
}
.ai-tool:hover, .ai-tool:focus-visible { color: var(--primary-text); border-color: var(--primary-line); }
/* Incizimi i ndezur: e njëjta çift ngjyrash si te `chip-danger` — e kuqja mbi të
   kuqen e butë. Bardha mbi të kuqen del nën kufirin AA te tema e errët, ku
   `--danger` është vetë e çelët. */
.ai-tool.is-on {
  background: var(--danger-soft);
  border-color: var(--danger);
  color: var(--danger);
  animation: ai-mic-pulse var(--beat) infinite var(--ease-in-out);
}
@keyframes ai-mic-pulse {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--danger) 45%, transparent); }
  50% { box-shadow: 0 0 0 .45rem transparent; }
}
@media (prefers-reduced-motion: reduce) { .ai-tool.is-on { animation: none; } }
.ai-file-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1-5);
  margin-top: var(--space-2);
  padding: var(--space-1) var(--space-2);
  font-size: var(--text-sm);
  border-radius: var(--radius-pill);
  background: var(--accent-soft);
  border: 1px solid var(--border);
  max-width: 100%;
  overflow-wrap: anywhere;
}

/* --- Letrat e kthyera nga asistenti ---------------------------------------
   Foto sa të lexohet, jo miniaturë: kjo zëvendëson hapjen e arkivit, pra duhet
   të mjaftojë pa e hapur atë. */
.ai-docs {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  padding: var(--space-3);
}
.ai-docs-head {
  font-size: var(--text-sm);
  font-weight: 700;
  color: var(--muted);
  margin-bottom: var(--space-2);
}
.ai-docs-grid {
  display: grid;
  /* Një kolonë te telefoni, dy-tri te ekrani — pa asnjë pyetje medie. */
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 13rem), 1fr));
  gap: var(--space-3);
}
.ai-doc { margin: 0; }
.ai-doc-shot {
  position: relative;
  display: block;
  border-radius: var(--radius-sm);
  overflow: hidden;
  border: 1px solid var(--border);
  background: var(--surface-2, var(--surface));
  aspect-ratio: 4 / 3;
}
.ai-doc-shot img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Skanimet janë të bardha: pa këtë, letra humbet te sfondi i errët. */
  background: #fff;
}
.ai-doc-icon {
  display: none;
  position: absolute;
  inset: 0;
  align-items: center;
  justify-content: center;
  font-size: var(--text-3xl);
  color: var(--faint);
}
/* PDF me tekst — pa foto brenda. Ikona zë vendin e saj. */
.ai-doc-flat .ai-doc-shot img { display: none; }
.ai-doc-flat .ai-doc-icon { display: flex; }
.ai-doc figcaption { display: flex; flex-direction: column; margin-top: var(--space-1-5); }
.ai-doc-title { font-size: var(--text-sm); font-weight: 600; overflow-wrap: anywhere; }
.ai-doc-meta { font-size: var(--text-xs); color: var(--faint); }

/* Rreshti i gjetur brenda letrës. Rri si citim — me vijë anash dhe me shkronja
   të pjerrëta — që të lexohet si fjalë e letrës, jo si përshkrim i programit.
   Dy rreshta mjaftojnë: kush do më shumë, e hap letrën. */
.ai-doc-snippet {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  margin-top: var(--space-1);
  padding-left: var(--space-2);
  border-left: 2px solid var(--border);
  font-size: var(--text-xs);
  font-style: italic;
  color: var(--muted, var(--faint));
}

/* --- Karta e konfirmimit --------------------------------------------------
   Ajo që ndan një asistent që përgjigjet nga një që dërgon: kjo kartë. Prandaj
   nuk duket si mesazh — ka kufi të vetin, ngjyrën e paralajmërimit dhe listën e
   marrësve të hapur. Njeriu duhet ta ndalë syrin këtu. */
.ai-plan {
  border: 1px solid var(--warning);
  border-radius: var(--radius);
  background: var(--warning-soft);
  padding: var(--space-3);
}
.ai-plan-head { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.ai-plan-note { font-size: var(--text-sm); color: var(--muted); margin: var(--space-2) 0 var(--space-3); }
.ai-plan-hint { font-size: var(--text-xs); color: var(--faint); margin: var(--space-1-5) 0 var(--space-3); }
.ai-plan-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-1-5);
  /* Dyzet emra nuk duhet ta shtyjnë butonin jashtë ekranit — por as të fshihen:
     lista rrëshqet brenda vetes dhe mbetet e tëra e lexueshme. */
  max-height: 15rem;
  overflow-y: auto;
  padding: var(--space-2);
  border-radius: var(--radius-sm);
  background: var(--surface);
  border: 1px solid var(--border);
}
.ai-plan-row { display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-2); align-items: baseline; }
.ai-plan-who { font-weight: 600; }
.ai-plan-why { font-size: var(--text-sm); color: var(--muted); }
.ai-plan-text { font-size: var(--text-sm); color: var(--faint); flex-basis: 100%; }
.ai-plan-actions { display: flex; gap: var(--space-2); flex-wrap: wrap; margin-top: var(--space-3); }
/* Ç'i mungoi fjalisë — kur dhe me cilin. Dy fusha krah për krah, dhe njëra nën
   tjetrën sapo karta ngushtohet; `min(14rem, 100%)` dhe jo `14rem`, që minimumi
   të mos e nxjerrë rrjetën jashtë kartës te telefoni. */
.ai-job-fields {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(14rem, 100%), 1fr));
  gap: var(--space-2) var(--space-3);
  margin-top: var(--space-2);
}
.ai-job-field { min-width: 0; }

/* --- Ç'duhet parë sot -----------------------------------------------------
   Kutitë rrinë mbi bisedën sepse nuk janë përgjigje e askujt: janë ajo që
   programi do të thoshte i pari po të fliste vetë. Ngjyra mban vetëm një kuptim
   — sa afër është ajo gjë me të qenit vonë. */
/* Pa `margin-bottom`: përmbledhja rri tani si kartë brenda shtyllës anësore, dhe
   ritmin e mban rrjeta. Titullin e saj e shkruan `.section-title`, si te çdo
   kartë tjetër e programit — `.ai-brief-head` ishte e njëjta gjë, e shkruar veç.

   Te telefoni shtylla anësore zbret nën kutinë e pyetjes, dhe atje rendi i saj
   ka rëndësi: «Ç'duhet parë sot» janë numrat e ditës, kurse gjendja e modeli e
   biblioteka janë material referimi që lexohet një herë. Pra përmbledhja ngjitet
   e para. Mbi 992px rrjeta e faqes e merr vetë rendin dhe kjo nuk vlen. */
@media (max-width: 991.98px) {
  .page-aside > .ai-brief { order: -1; }
}
.ai-brief-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 10rem), 1fr));
  gap: var(--space-2);
}
.ai-tile {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-rows: auto auto;
  gap: var(--space-0) var(--space-2);
  align-items: center;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border);
  border-left-width: 3px;
  border-radius: var(--radius);
  background: var(--surface);
  text-decoration: none;
  color: inherit;
}
a.ai-tile:hover { border-color: var(--primary, #4c6ef5); }
.ai-tile-icon { grid-row: span 2; font-size: var(--text-xl); color: var(--faint); }
.ai-tile-value { font-size: var(--text-lg); font-weight: 700; line-height: 1.1; }
.ai-tile-label { font-size: var(--text-xs); color: var(--muted); }
.ai-tile-danger { border-left-color: var(--danger, #e03131); }
.ai-tile-danger .ai-tile-icon { color: var(--danger, #e03131); }
.ai-tile-warn { border-left-color: var(--warning, #f08c00); }
.ai-tile-warn .ai-tile-icon { color: var(--warning, #f08c00); }
.ai-tile-info { border-left-color: var(--primary, #4c6ef5); }

/* --- Tabela e llogaritur --------------------------------------------------
   Numrat këtu nuk i shkroi modeli — i mblodhi programi. Karta e thotë atë me
   pamje: kufi i qetë, shifra të drejtuara djathtas, dhe një rresht poshtë që
   thotë nga dolën. Një përgjigje me fjalë mund të lexohet me dyshim; një tabelë
   që duket si tabelë e zyrës duhet ta meritojë atë që kërkon. */
.ai-table {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  padding: var(--space-3);
}
.ai-table-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2);
  flex-wrap: wrap;
  margin-bottom: var(--space-2);
}
.ai-table-title { font-size: var(--text-sm); font-weight: 700; }
.ai-table-link { font-size: var(--text-xs); white-space: nowrap; }
/* Pesë kolona nuk hyjnë te një telefon — dhe as duhet të shtypen aq sa të mos
   lexohen. Tabela rrëshqet brenda vetes, faqja jo. */
.ai-table-scroll { overflow-x: auto; }
.ai-table-grid {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
}
.ai-table-grid th,
.ai-table-grid td {
  padding: var(--space-1-5) var(--space-2);
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
.ai-table-grid th {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: .03em;
  color: var(--faint);
  font-weight: 700;
}
.ai-table-grid tbody tr:last-child td { border-bottom: 0; }
.ai-table-grid .num { text-align: right; }
/* Kolona e parë mban emrat; ajo e vetmja lejohet të thyhet në dy rreshta. */
.ai-table-grid td:first-child { white-space: normal; overflow-wrap: anywhere; }
.ai-bars { display: flex; flex-direction: column; gap: var(--space-1); margin-top: var(--space-3); }
.ai-bar { display: grid; grid-template-columns: minmax(3.5rem, 8rem) 1fr; gap: var(--space-2); align-items: center; }
.ai-bar-label { font-size: var(--text-xs); color: var(--muted); overflow-wrap: anywhere; }
.ai-bar-track {
  display: block;
  height: .5rem;
  border-radius: var(--radius-pill);
  background: var(--surface-2, rgba(127, 127, 127, .16));
  overflow: hidden;
}
.ai-bar-track i {
  display: block;
  height: 100%;
  border-radius: var(--radius-pill);
  background: var(--primary, #4c6ef5);
}
.ai-table-empty { font-size: var(--text-sm); color: var(--muted); margin: var(--space-1) 0; }

/* «Sa janë?» — përgjigjja që është e tëra një shifër. Ajo shifër lexohet nga
   larg, sepse pikërisht kaq donte të dinte ai që pyeti; fjala pranë saj thotë
   çfarë numërohet, që numri të mos rrijë vetëm dhe pa kuptim. */
.ai-count { display: flex; align-items: baseline; gap: var(--space-2); flex-wrap: wrap; }
.ai-count-n {
  /* Ishte një `clamp()` i vetin, gati fjalë për fjalë `--display-md`
     (1,9–2,7rem kundrejt 2–2,75rem). Dy kufij që s'i ndan dot syri por që
     vjetrohen veç e veç — pra shifra e madhe merr tani atë të shkallës. */
  font-size: var(--display-md);
  font-weight: 800;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--primary, #4c6ef5);
}
.ai-count-label { font-size: var(--text-sm); color: var(--muted); }
.ai-table-foot {
  font-size: var(--text-xs);
  color: var(--faint);
  margin: var(--space-2) 0 0;
}

/* --- Koka e bisedës: sa radhë, dhe ku është ajo shifra --------------------
   Dyzet radhë janë më shumë se sa lexohen me sy. Pa një kuti kërkimi, «ku e
   thashë atë numër» ishte rrëshqitje nga fundi drejt fillimit — dhe fundi është
   pikërisht vendi ku faqja hapet. */
.ai-thread-count {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--muted);
  white-space: nowrap;
}
.ai-find {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  color: var(--faint);
  margin: 0;
  min-width: 0;
}
.ai-find input { width: 12rem; max-width: 100%; }
.ai-find-empty {
  font-size: var(--text-sm);
  color: var(--muted);
  text-align: center;
  margin: var(--space-3) 0;
}

/* Ndarësja e ditës. Biseda mbahet dyzet radhë, pra shpesh shtrihet mbi disa
   ditë — dhe pyetja e së martës nuk duhet lexuar si vazhdim i së hënës, atje ku
   numrat kanë ndërruar ndërkohë. Vija shkon anash tekstit, jo nën të: e para
   ndan, e dyta do të ishte edhe një titull më shumë në një faqe që i ka. */
.ai-day {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-size: var(--text-2xs);
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--faint);
}
.ai-day::before,
.ai-day::after {
  content: '';
  flex: 1;
  height: var(--hairline);
  background: var(--border);
}

/* Nënshkrimi dhe veprimet e një radhe. Rreshti rri i qetë derisa miu (ose
   tastiera) hyn te radha: një bisedë ku çdo fluskë mban dy butona të ndezur
   lexohet si panel kontrolli, jo si përgjigje. Por kurrë e fshehur me
   `display` — një veprim që nuk ekziston para hover-it nuk ekziston fare për
   gishtin, prandaj te ekranet me prekje mbetet gjithnjë i dukshëm. */
.ai-msg-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2) var(--space-3);
  flex-wrap: wrap;
  margin-top: var(--space-1);
  min-height: 1.35rem;
}
.ai-msg-user .ai-msg-foot { flex-direction: row-reverse; }
.ai-sign {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
  font-size: var(--text-2xs);
  color: var(--faint);
  min-width: 0;
}
.ai-sign-bit { display: inline-flex; align-items: center; gap: var(--space-1); }
.ai-sign-bit i { font-size: var(--text-xs); }
.ai-msg-acts {
  display: flex;
  gap: var(--space-0);
  opacity: 0;
  transition: opacity var(--dur-1) var(--ease-out);
}
.ai-msg:hover .ai-msg-acts,
.ai-msg:focus-within .ai-msg-acts { opacity: 1; }
@media (hover: none) {
  .ai-msg-acts { opacity: 1; }
}
.ai-act {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.6rem;
  height: 1.6rem;
  padding: 0;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--faint);
  font-size: var(--text-xs);
  line-height: 1;
  cursor: pointer;
}
.ai-act:hover,
.ai-act:focus-visible { background: var(--surface-hover); color: var(--primary-text); }
.ai-act.is-done { color: var(--success); }
.ai-act.is-done .bi-clipboard::before { content: '\f26b'; }   /* clipboard-check */

/* Përgjigjja që e ndaloi vetë njeriu. As e kuqe as e plotë: ajo që u shkrua
   deri aty mbetet e lexueshme, dhe vija anash e thotë pse mbaron aty. */
.ai-msg-stopped {
  border-left: var(--rail) solid var(--warning);
  color: var(--muted);
}

/* Kutia e pyetjes: rreshti i fundit, dhe letra e hedhur mbi të. */
.ai-ask-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2) var(--space-3);
  flex-wrap: wrap;
  margin-top: var(--space-2);
}
.ai-hint {
  font-size: var(--text-xs);
  color: var(--muted);
  flex: 1 1 16rem;
  min-width: 0;
}
.ai-ask-send {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
}
.ai-chars {
  font-size: var(--text-xs);
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.ai-ask.is-drop {
  border-color: var(--primary);
  box-shadow: var(--glow-accent);
}
.ai-empty-more { font-size: var(--text-xs); color: var(--faint); margin: var(--space-3) 0 0; }
/* Kutia nga e cila kopjohet teksti kur shfletuesi s'ka `navigator.clipboard`
   (çdo lidhje pa HTTPS). Duhet e zgjedhshme, pra jo `display: none` — vetëm
   jashtë syrit. */
.copy-sink { position: fixed; opacity: 0; pointer-events: none; }

/* --- Ku shkon pyetja -------------------------------------------------------
   Njeriu që pret gjysmë minute para një kutie boshe ka të drejtë të dijë kush
   po shkruan, a doli fjalia e tij nga rrjeti i zyrës, dhe sa pyetje i kanë
   mbetur. Të treja lexohen nga konfigurimi dhe nga baza — pra kjo kuti flet
   edhe kur modeli hesht. */
.ai-state {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
  margin-bottom: var(--space-2);
}
.ai-state-mark {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1-5);
  padding: var(--space-1) var(--space-2);
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  font-size: var(--text-2xs);
  font-weight: 700;
}
.ai-state-safe {
  background: var(--success-soft);
  border-color: color-mix(in srgb, var(--success) 30%, transparent);
  color: var(--success);
}
.ai-state-out {
  background: var(--warning-soft);
  border-color: color-mix(in srgb, var(--warning) 30%, transparent);
  color: var(--warning);
}
.ai-state-model {
  font-family: var(--bi-font, monospace);
  font-size: var(--text-xs);
  color: var(--muted);
  overflow-wrap: anywhere;
}
.ai-state-list { margin: 0; }
.ai-state-list .list-kv + .list-kv { border-top: var(--hairline) solid var(--border); }
.ai-state-n {
  font-size: var(--text-xs);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* Kuota si shirit. Gjerësinë e di vetëm serveri — prandaj `--bar` vjen si
   atribut, dhe ky është i vetmi numër që faqja e merr të shkruar. */
.ai-quota {
  display: block;
  height: .3rem;
  border-radius: var(--radius-pill);
  background: var(--surface-sunken);
  overflow: hidden;
  margin-top: var(--space-2);
}
.ai-quota::before {
  content: '';
  display: block;
  width: var(--bar, 0%);
  height: 100%;
  border-radius: inherit;
  background: var(--accent-fill);
}
.ai-quota-note { font-size: var(--text-2xs); color: var(--faint); margin: var(--space-1-5) 0 0; }

/* Për kë flet biseda. Çipat e bëjnë të dukshëm subjektin që fjalia e shkurtër
   e trashëgon në heshtje. */
.ai-subjects { display: flex; flex-wrap: wrap; gap: var(--space-2); }

/* --- Biblioteka e pyetjeve -------------------------------------------------
   Deri sot këta shembuj zhdukeshin përgjithmonë sapo bëhej pyetja e parë, dhe
   bashkë me ta e vetmja gjë që tregonte se kutia pranon edhe një kërkesë letre
   a një urdhër. Të ndara sipas rrugës që merr fjalia brenda programit, sepse
   ato rrugë sillen ndryshe dhe njeriu duhet ta dijë cilën po hap. */
.ai-lib-head {
  display: flex;
  align-items: center;
  gap: var(--space-1-5);
  font-size: var(--text-2xs);
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--faint);
  margin: var(--space-3) 0 var(--space-2);
}
.ai-lib-head:first-of-type { margin-top: 0; }
.ai-lib-list { display: grid; gap: var(--space-1); }
.ai-lib-item {
  text-align: left;
  padding: var(--space-1-5) var(--space-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: inherit;
  font-size: var(--text-xs);
  line-height: 1.4;
  cursor: pointer;
  transition: border-color var(--dur-1) var(--ease-out),
              background-color var(--dur-1) var(--ease-out);
}
.ai-lib-item:hover,
.ai-lib-item:focus-visible {
  border-color: var(--primary-line);
  background: var(--primary-soft);
  color: var(--primary-text);
}

/* ============================================================================
   9. SHTRESA E PËRBASHKËT
   ----------------------------------------------------------------------------
   Gjithçka poshtë kësaj vije ekziston sepse e njëjta punë ishte zgjidhur shumë
   herë. Jo ide të reja: forma që faqet i ndërtonin çdo herë vetë, me utilitete
   Bootstrap-i, dhe pra kurrë dy herë njësoj.

   Numrat janë të numëruar, jo të vlerësuar me sy:
     · shiriti i filtrave — 17 faqe, secila me hapin e vet (g-2 kundrejt g-3) dhe
       me ndarjen e vet të kolonave, pra dy faqe fqinje me katër fusha të njëjta
       nuk bien kurrë në të njëjtën vijë;
     · rreshti etiketë→vlerë — gjashtë klasa vendore plus një `dl` i papërpunuar,
       me GJASHTË madhësi etikete (var(--text-xs), 10.5px, var(--text-2xs),
       .68rem, .72rem, .74rem) dhe tri ngjyra, pra e njëjta «Borxhi i papaguar»
       lexohet ndryshe te dosja e klientit, te paneli i bisedës dhe te paneli i
       shpejtë;
     · qeliza e një shume — 271 `text-end` të shkruara me dorë, dhe pikërisht
       ngjyra e negatives ndryshon nga tabela në tabelë;
     · titulli i një seksioni brenda kartës — katër klasa vendore dhe 15 vende
       ku ndërtohet me tre-katër utilitete.

   Kjo shtresë nuk zëvendëson asgjë me forcë. Çdo klasë këtu HIPËN mbi atë që
   ekziston: `.data-table` shkon mbi `.table` e Bootstrap-it (përndryshe motori i
   tabelave te site.js — renditja, «Shtyllat», shumat, kartelat e telefonit —
   s'do ta njihte më tabelën), `.card-bar` mbi `.card-header`, `.detail-card` mbi
   `.card`. Kush s'e vë klasën e re, e ka faqen pikërisht siç e kishte dje.

   Një rregull i vetëm ngjyre për të gjithë bllokun: çdo tekst i ri i vogël merr
   `--muted`, kurrë `--faint`. E dyta është e matur vetëm kundër temës së errët
   (5.08:1 mbi kartë) dhe në atë të ndritshmen bie te 3.83:1 — nën vijën AA. Aty
   ku etiketa është e vogël, e shkruar me shkronja të mëdha dhe e ngjeshur, ajo
   është pikërisht teksti që njeriu e lexon me vështirësi. `--muted` jep 5.48:1
   në dritë dhe 7.45:1 në errësirë.
   ========================================================================== */

/* --- 9.1 Tabela e të dhënave ------------------------------------------------
   `.table` e Bootstrap-it di të vizatojë rreshta; nuk di çfarë është një rresht.
   Prandaj çdo tabelë e programit e shkruante vetë atë që dinte: shumën djathtas
   me `text-end`, vonesën me `table-warning`, totalin me `tfoot.table-active`.
   Tri gjuhë për tri gjëra që janë e njëjta gjë — një regjistrim me gjendje dhe
   me numra.

   `.data-table` shtohet PRANË `.table`, nuk e zëvendëson:
       <table class="table table-hover data-table">
   Kështu motori te site.js e njeh ende (renditja, filtri, «Shtyllat», `data-sum`,
   kartelat nën 768px) dhe kjo shtresë i shton vetëm atë që i mungonte. */
.data-table {
  /* Dy masat e tabelës, të shkruara një herë: lartësia e kokës së ngjitur dhe
     mbushja anësore e `.table-card`. E para e bën `scroll-margin` të saktë, e
     dyta e lejon vijën e gjendjes ta hajë mbushjen e vet pa e lëvizur tekstin. */
  --data-head-h: 2.6rem;
  --data-pad-x: 1.1rem;
}

/* Koka me lartësi të matur, jo me mbushje të trashëguar. Një kokë e ngjitur që
   ndryshon lartësi nga tabela në tabelë e detyron çdo llogaritje tjetër —
   `scroll-margin`, fundi i dritares — të hamendësojë. */
.data-table > thead > tr > th,
.data-table > thead > tr > td {
  height: var(--data-head-h);
  padding-top: 0;
  padding-bottom: 0;
  vertical-align: middle;
  background: var(--surface);
}

/* Ndarësi hairline: një vijë e vetme mes rreshtave, dhe asnjë poshtë të fundit.
   Brenda një `.table-card` ajo e fundit binte pikërisht mbi kufirin e kartelës —
   dy vija 1px me një hap piksel mes tyre, që në ekran lexohen si një vijë e
   trashë e pabarabartë. */
.data-table > tbody > tr > td,
.data-table > tbody > tr > th {
  border-bottom-color: var(--border);
}
.data-table > tbody > tr:last-child > td,
.data-table > tbody > tr:last-child > th {
  border-bottom-width: 0;
}

/* Rreshti si spirancë: kur dikush vjen te një rresht nga një lidhje `#…`, koka e
   ngjitur dhe shiriti i sipërm e mbulojnë pikërisht atë. Kjo është arsyeja pse
   dy masat rrinë te ndryshore. */
.data-table > tbody > tr {
  scroll-margin-top: calc(var(--data-head-h) + var(--topbar-h) + var(--space-2));
}

/* --- Gjendja e një rreshti --------------------------------------------------
   Një vijë 3px në buzë të majtë, jo një kartelë e larë me ngjyrë. `.table-warning`
   e Bootstrap-it e lyen tërë rreshtin, dhe kur në një listë ka njëzet rreshta me
   vonesë, tabela bëhet një fushë e verdhë ku asgjë nuk shquhet më. Vija e thotë
   të njëjtën gjë me zë të ulët, dhe lejon që dy gjendje të lexohen krah për krah.

   Ngjyra vjen nga një ndryshore e vetme, që klasa e rreshtit e vendos: kështu
   rregulli i vizatimit shkruhet një herë, dhe një gjendje e re nesër është një
   rresht i vetëm. */
.data-table > tbody > tr.row-new    { --row-flag: var(--primary); }
.data-table > tbody > tr.row-soon   { --row-flag: var(--warning); }
.data-table > tbody > tr.row-late   { --row-flag: var(--danger); }
.data-table > tbody > tr.row-done   { --row-flag: var(--success); }

.data-table > tbody > tr.row-new > *:first-child,
.data-table > tbody > tr.row-soon > *:first-child,
.data-table > tbody > tr.row-late > *:first-child,
.data-table > tbody > tr.row-done > *:first-child {
  border-left: 3px solid var(--row-flag, var(--border-strong));
  /* Vija e ha mbushjen e vet, nuk e shtyn tekstin: përndryshe rreshtat e shënuar
     do të nisnin 3px më djathtas se ata të pashënuarit, dhe shtylla e parë do të
     dhëmbëzohej lart e poshtë. */
  padding-left: calc(var(--data-pad-x) - 3px);
}

/* Rreshti i qetësuar: i arkivuar, i mbyllur, jashtë periudhës. Ngjyra e tekstit,
   jo `opacity` — e dyta e zbeh edhe kufirin, edhe çipin, edhe lidhjen brenda tij,
   dhe një lidhje e zbehur nën 4.5:1 nuk është më lidhje. */
.data-table > tbody > tr.row-quiet > td,
.data-table > tbody > tr.row-quiet > th { color: var(--muted); }

/* --- Numrat -----------------------------------------------------------------
   `.money` përmendej te rregulli i shifrave tabelore që në ditën e parë dhe
   s'kishte kurrë trup: pra ekzistonte një emër për «kjo qelizë është një shumë»
   dhe asnjë sjellje pas tij. Prandaj rreshtimi djathtas, pesha dhe ngjyra e
   negatives shkruheshin me dorë në çdo tabelë — 271 herë — dhe pikërisht ngjyra
   ndryshonte: diku e kuqe vetëm nën zero, diku edhe mbi kufij të tjerë.

   `.num` është motra e saj pa monedhë: sasi, ditë, numër faturash. */
.num,
th.num,
td.num,
.money,
th.money,
td.money {
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
}
.money { white-space: nowrap; font-weight: 600; }
/* Data nuk rreshtohet djathtas si një shumë, por shifrat e saj duhet të kenë të
   njëjtën gjerësi: përndryshe `11/08` dhe `01/12` nisin nga dy vija dhe shtylla
   duket sikur dridhet ndërsa syri zbret. */
.date-cell { font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Toni i shumës thuhet nga shablloni, jo nga një kusht i rishkruar për çdo faqe. */
.money-pos { color: var(--success); }
.money-neg { color: var(--danger); }
/* Zeroja nuk është lajm. Ajo rri e qetë që syri të ndalet te shifrat që janë. */
.money-nil { color: var(--muted); font-weight: 500; }

/* --- Rreshti i shumave ------------------------------------------------------
   `.table-sum` e krijon site.js kur një `<th>` kërkon `data-sum`. Kur totalin e
   llogarit serveri dhe e shkruan vetë te `<tfoot>`, ai deri tani dilte si
   `table-active` — pra si rresht i zgjedhur, jo si total. Njëjtë me `.table-sum`,
   me emrin që e thotë ç'është. */
tr.row-sum > td,
tr.row-sum > th {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  background: var(--surface-muted);
  border-top: 2px solid var(--border-strong);
  border-bottom: 0;
  color: var(--text);
}
/* Kur tabela rrëshqet brenda dritares së vet, totali që humbet nga ekrani sapo
   shtyhet lista është një total që duhet kërkuar prapë. */
.table-sticky tfoot tr.row-sum > td,
.table-sticky tfoot tr.row-sum > th {
  position: sticky;
  bottom: 0;
  z-index: 3;
}

@media (max-width: 767.98px) {
  /* Te kartelat vija e gjendjes i takon kartelës, jo qelizës së parë: qeliza atje
     është titulli i kartelës dhe një kufi mbi të do të ishte një vijë në mes. */
  .table-cards > tbody > tr.row-new,
  .table-cards > tbody > tr.row-soon,
  .table-cards > tbody > tr.row-late,
  .table-cards > tbody > tr.row-done {
    border-left: 3px solid var(--row-flag, var(--border-strong));
  }
  .table-cards > tbody > tr.row-new > *:first-child,
  .table-cards > tbody > tr.row-soon > *:first-child,
  .table-cards > tbody > tr.row-late > *:first-child,
  .table-cards > tbody > tr.row-done > *:first-child {
    border-left: 0;
    padding-left: var(--space-3);
  }
  /* Te kartela vlera rri pranë etiketës së vet. Një shumë e shtyrë krejt djathtas
     ndahet nga fjala që e emërton me gjysmë ekrani bosh — rreshtimi djathtas ka
     kuptim vetëm kur mbi të rri një shumë tjetër. */
  .table-cards > tbody > tr > td.num,
  .table-cards > tbody > tr > td.money { text-align: left; }
}

/* --- 9.2 Rreshti etiketë→vlerë ----------------------------------------------
   Një emër i qetë dhe një vlerë e theksuar. Gjashtë klasa vendore e bënin këtë
   (.tm-clientcard-item, .tm-panel-row, .peek-row, .vat-hl, .forecast-kpi,
   .conc-item) plus `dl.row` i papërpunuar te dosja e klientit — dhe secila me
   madhësinë e vet të etiketës.

       <dl class="kv">
         <div class="kv-row">
           <dt class="kv-label">NUI</dt>
           <dd class="kv-value">810123456</dd>
         </div>
       </dl>

   Shtylla e etiketave matet nga etiketa më e gjatë e bllokut, jo nga një përqindje
   e hamendësuar: me `fit-content(45%)` një bllok me fjalë të shkurtra nuk lë një
   të tretën e kartës bosh, dhe një me fjalë të gjata nuk i thyen ato në dy rreshta
   ndërsa vlera 4 shkronjash rri e vetme djathtas. `subgrid` është ajo që i lejon
   TË GJITHË rreshtat ta ndajnë atë masë të vetme; pa të, secili rresht do ta
   matte veten, pra dy rreshta fqinjë do të nisnin nga dy vija. */
.kv {
  display: grid;
  grid-template-columns: fit-content(45%) minmax(0, 1fr);
  column-gap: var(--space-3);
  margin: 0;
}
.kv-row {
  display: grid;
  grid-template-columns: fit-content(45%) minmax(0, 1fr);
  column-gap: var(--space-3);
  align-items: baseline;
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--border);
  min-width: 0;
}
.kv-row:last-child { border-bottom: 0; }
.kv-row:first-child { padding-top: 0; }
.kv-label {
  font-size: var(--text-sm);
  color: var(--muted);
  margin: 0;
  font-weight: 500;
  min-width: 0;
  overflow-wrap: anywhere;
}
.kv-value {
  font-size: var(--text-sm);
  color: var(--text);
  font-weight: 600;
  margin: 0;
  min-width: 0;
  overflow-wrap: anywhere;
}
/* Vlera që mungon nuk shkruhet me vizë të papërkthyer nëpër shabllone. */
.kv-value:empty::before { content: "—"; color: var(--muted); font-weight: 400; }

@supports (grid-template-columns: subgrid) {
  .kv-row {
    grid-column: 1 / -1;
    grid-template-columns: subgrid;
  }
}

/* Dy çifte për rresht kur karta është e gjerë: katërmbëdhjetë çifte njëri poshtë
   tjetrit janë një shtyllë e vetme e hollë me gjysmën e kartës bosh djathtas. */
@media (min-width: 768px) {
  .kv-2col { grid-template-columns: fit-content(22%) minmax(0, 1fr) fit-content(22%) minmax(0, 1fr); }
  .kv-2col > .kv-row { grid-column: span 2; }
}

/* Paneli i ngushtë (shiriti anësor, kartela e telefonit): etiketa mbi vlerë.
   Nën ~14rem një ndarje në dy shtylla i lë të dyja të pathyeshme. */
.kv-stack,
.kv-stack > .kv-row { display: block; }
.kv-stack .kv-label { display: block; font-size: var(--text-xs); }

/* Pa vija ndarëse: brenda një kutie tashmë të vogël ato e bëjnë atë të duket
   listë e gjatë. */
.kv-flush > .kv-row { border-bottom: 0; padding: var(--space-1) 0; }

/* --- 9.3 Shiriti i filtrave -------------------------------------------------
   «Ngushtoje faqen te kjo periudhë» ishte e shkruar 17 herë me `row g-2|g-3` dhe
   `col-12 col-md-N`, dhe secila faqe zgjidhte vetë hapin dhe ndarjen — prandaj dy
   faqe fqinje me të njëjtat katër fusha nuk binin kurrë në të njëjtën vijë, dhe
   butoni «Filtro» herë rrinte brenda rreshtit e herë poshtë tij.

       <form method="get" class="filter-bar">
         <div class="filter-field filter-field-lg">
           <label class="filter-label" for="q">Kërko</label>
           <input class="form-control" id="q" name="q">
         </div>
         <div class="filter-field filter-field-sm">…</div>
         <div class="filter-actions">
           <button class="btn btn-primary">Filtro</button>
           <a class="btn btn-outline-secondary" href="…">Pastro</a>
         </div>
       </form>

   Flex, jo rrjet 12-shtyllësh: një fushë datë s'ka nevojë për të njëjtën gjerësi
   si një kërkim, dhe një rrjet e detyron secilën ta thotë me numër kolonash. Këtu
   fusha e thotë gjerësinë që i duhet përgjigjjes që pret, dhe rreshti mbështillet
   vetë kur ato s'hyjnë më. */
.filter-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--edge-light-soft), var(--shadow-sm);
  margin-bottom: var(--space-4);
}
/* I njëjti shirit kur rri tashmë brenda një kartele — te `.card-header`, mbi një
   tabelë. Aty kutia e ka kartelën e vet dhe një e dytë brenda saj është kuti mbi
   kuti. */
.filter-bar-plain {
  background: none;
  border: 0;
  box-shadow: none;
  padding: 0;
  margin-bottom: 0;
}
.filter-field {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  flex: 1 1 var(--filter-w, 11rem);
  min-width: 0;
}
/* Tri gjerësi, sipas gjatësisë së përgjigjes: një datë, një zgjedhës, një kërkim.
   `flex-grow: 0` te e vogla — një fushë muaji s'ka pse të zgjatet sa gjysma e
   shiritit vetëm sepse ka mbetur vend. */
.filter-field-sm { --filter-w: 7.5rem; flex-grow: 0; }
/* Përjashtimi: një `input[type=date]` nuk është një fushë muaji. Shfletuesi i
   vë brenda edhe ikonën e kalendarit, dhe te 7,5rem viti pritet — «07/01/202».
   E mata te pasqyra e TVSH-së, ku dy data rrinë krah për krah në krye të faqes;
   e njëjta prerje ishte e heshtur te faturat, afatet, taskët dhe gjurma. */
.filter-field-sm:has(input[type="date"]) { --filter-w: 9.25rem; }
.filter-field-lg { --filter-w: 16rem; }
.filter-field-grow { flex-grow: 3; }
/* Etiketa kompakte: `form-label small fw-semibold mb-1` ishte shkruar 17 herë, dhe
   gjashtë nga ato e harronin `mb-1` — pra kontrollet nën to nuk nisnin nga e njëjta
   vijë. Këtu hapësira poshtë është pjesë e shiritit, jo e etiketës. */
.filter-label {
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--muted);
  line-height: 1.4;
  margin: 0;
}
.filter-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin-left: auto;
}

/* --- Shiriti i gjendjeve -----------------------------------------------------
   Gjashtë numra që janë njëkohësisht përgjigje dhe derë: sa janë, dhe një klikim
   për t'i parë. Te faqja e task-eve ata rrinin tri herë — pesë `stat-card`, koka
   e faqes, dhe pilulat e gjendjes — pra zinin gjithë ekranin e parë pa bërë
   asgjë. Forma është ajo e skedave: numri i madh, fjala nën të, dhe vija poshtë
   që thotë ku je. */
.status-rail {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
  margin-bottom: var(--space-3);
  border-bottom: 1px solid var(--border);
}
.status-rail-item {
  display: flex;
  align-items: baseline;
  gap: var(--space-1-5);
  padding: var(--space-1-5) var(--space-3);
  border-bottom: 2px solid transparent;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  color: var(--muted);
  text-decoration: none;
  transition: background var(--dur-2) var(--ease-out), color var(--dur-2) var(--ease-out), border-color var(--dur-2) var(--ease-out);
}
.status-rail-item:hover,
.status-rail-item:focus-visible { background: var(--surface-hover); color: var(--text); }
.status-rail-num {
  font-size: var(--text-lg);
  font-weight: 700;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.status-rail-label { font-size: var(--text-xs); font-weight: 600; }
/* Secila gjendje mban ngjyrën e çipit të vet — përndryshe shiriti do të ishte
   gjashtë numra të njëjtë dhe fjala do të mbante gjithë punën. */
.status-rail-item.is-accepted .status-rail-num { color: var(--primary-text); }
.status-rail-item.is-completed .status-rail-num,
.status-rail-item.is-finalized .status-rail-num { color: var(--success); }
.status-rail-item.is-cancelled .status-rail-num { color: var(--muted); }
/* Zeroja nuk është lajm: rri e qetë që syri të ndalet te numrat që janë. */
.status-rail-item.is-zero .status-rail-num { color: var(--muted); font-weight: 600; }
.status-rail-item.is-active {
  color: var(--text);
  background: var(--surface-hover);
  border-bottom-color: var(--primary);
}
.status-rail-item.is-active.is-completed,
.status-rail-item.is-active.is-finalized { border-bottom-color: var(--success); }
.status-rail-item.is-active.is-cancelled { border-bottom-color: var(--muted); }

/* Një kuti për gjithë ngushtimin: kërkimi dhe zgjedhësit lart, afati dhe ç'është
   në fuqi poshtë një vije. Ishin tri kuti të stivosura njëra mbi tjetrën për një
   pyetje të vetme — «çfarë po shoh» — dhe të tria hapësirë para punës. */
.filter-panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--edge-light-soft), var(--shadow-sm);
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-4);
}
/* Rreshti i dytë ndahet me vijë, jo me hapësirë: hapësira brenda një kutie
   lexohet si e rastësishme. */
.filter-panel > .filter-quick,
.filter-panel > .filter-applied {
  margin: 0;
  padding-top: var(--space-3);
  margin-top: var(--space-3);
  border-top: 1px solid var(--border);
}
/* Kur të dy rreshtat janë aty, mes tyre mjafton hapësira — dy vija brenda një
   kutie do të bënin tri kate. */
.filter-panel > .filter-quick + .filter-applied {
  border-top: 0;
  padding-top: 0;
  margin-top: var(--space-2);
}

/* Filtrat e shpejtë: një rresht pilulash që e ngushtojnë faqen me një klikim.
   E njëjta punë kishte katër pamje — `.tm-filter` te bisedat, `.seg` te Analitika,
   `.chip-button` te Qasjet, dhe butona Bootstrap te shtatë faqe të tjera. Kutia
   është kjo; pilula brenda saj mbetet `.chip-button`, që tashmë mban `aria-pressed`
   dhe unazën e vet. */
.filter-quick {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-3);
}
.filter-quick-label {
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--muted);
}

/* Ç'është në fuqi tani. Një numër («4 aktivë») thotë sa, kurrë çfarë — dhe një
   filtër që nuk shihet është një filtër që njeriu e harron dhe pastaj beson se
   lista është bosh. Secili hiqet veç, nga aty ku shihet. */
.filter-applied {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-3);
}
.filter-applied-label {
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--muted);
}
/* Derë drejt kontrolleve kur ato nuk rrinë ngjitur me këtë rresht. Rri në fund,
   pas çipave: fakti lexohet i pari, mjeti pas tij. */
.filter-applied-edit {
  margin-left: auto;
  font-size: var(--text-xs);
  font-weight: 600;
  text-decoration: none;
  color: var(--primary-text);
}
.filter-applied-edit:hover { text-decoration: underline; }
/* Iksi brenda një çipi — heqja rri aty ku rri fakti, jo te një buton «Pastro» në
   fund të shiritit që i heq të gjitha bashkë. */
.chip-x {
  display: inline-flex;
  align-items: center;
  border: 0;
  padding: 0;
  margin-left: var(--space-0);
  background: none;
  color: inherit;
  line-height: 1;
  opacity: .7;
  transition: opacity var(--dur-1) var(--ease-out);
}
.chip-x:hover,
.chip-x:focus-visible { opacity: 1; }

@media (max-width: 575.98px) {
  /* Te telefoni çdo fushë merr rreshtin e vet: dy kontrolle krah për krah nën
     360px janë dy kontrolle që s'lexohen as njëra as tjetra. */
  .filter-bar { padding: var(--space-3); gap: var(--space-2); }
  .filter-field,
  .filter-field-sm,
  .filter-field-lg { flex-basis: 100%; flex-grow: 1; }
  .filter-actions { margin-left: 0; width: 100%; }
  .filter-actions > .btn { flex: 1 1 auto; }
}

/* --- 9.4 Gjendjet bosh ------------------------------------------------------
   `.empty-state` ekziston dhe përdoret; ç'i mungonte ishte dallimi mes dy bosheve
   që s'janë i njëjti lajm. «Ende s'ka asnjë faturë» është ftesë — e ka ikonën
   primare, dhe hapi tjetër është ta shkruash të parën. «Asgjë s'u gjet për këtë
   kërkim» është rrugë pa krye — nuk ka çfarë të krijohet, ka çfarë të hiqet, dhe
   një ikonë e ndritshme primare aty premton diçka që s'ekziston.

       <div class="empty-state empty-search">
         <div class="empty-icon"><i class="bi bi-search"></i></div>
         <p class="empty-title">Asgjë s'u gjet</p>
         <p class="empty-text">Provo pa filtrin e periudhës.</p>
         <div class="empty-action"><a class="btn btn-sm btn-outline-secondary">Pastro filtrat</a></div>
       </div> */
.empty-search .empty-icon {
  background: var(--surface-muted);
  color: var(--muted);
  box-shadow: inset 0 0 0 var(--hairline) var(--border);
}

/* Bosh brenda një kutie të vogël — një kolonë bordi, gjysma e një kartele. Kutia
   e plotë 62px me 2.4rem mbushje aty është më e madhe se vetë kutia që e mban. */
.empty-state-sm { padding: var(--space-5) var(--space-3); }
.empty-state-sm .empty-icon {
  width: 42px;
  height: 42px;
  border-radius: var(--radius);
  font-size: var(--text-lg);
  margin-bottom: var(--space-2);
}
.empty-state-sm .empty-title { font-size: var(--text-sm); }
.empty-state-sm .empty-text { font-size: var(--text-xs); }

/* Rreshti i fundit: pse është bosh, kur përgjigjja s'është e dukshme. «Puntori
   s'ka të drejtë incizimi», «Kjo listë mbushet pas dorëzimit të parë» — pa të,
   boshi lexohet si defekt. */
.empty-hint {
  font-size: var(--text-xs);
  color: var(--muted);
  margin: var(--space-3) 0 0;
}

/* Kutia bosh brenda një tabele rri te `<td colspan>`, pra brenda kornizës së saj:
   pa këtë, mbushja e qelizës i shtohet asaj të kutisë dhe boshi bëhet më i lartë
   se dhjetë rreshta me të dhëna. */
.table > tbody > tr > td > .empty-state { padding-block: var(--space-5); }

/* --- 9.5 Pamja e pritjes ----------------------------------------------------
   `.skeleton` ekzistonte si vezullim mbi një kuti; ç'mungonte ishte forma e asaj
   që pritet. Një kuti gri 200px e lartë nuk thotë «po vjen një listë» — thotë
   vetëm «diçka mungon». Këtu pritja ka formën e përgjigjes: rreshta të gjatësive
   të pabarabarta, sepse asnjë listë e vërtetë s'ka rreshta të barabartë.

       <div class="skeleton-list" aria-hidden="true">
         <div class="skeleton-row">
           <span class="skeleton skeleton-circle"></span>
           <span class="skeleton-text">
             <span class="skeleton skeleton-line skeleton-line-title"></span>
             <span class="skeleton skeleton-line"></span>
           </span>
           <span class="skeleton skeleton-line"></span>
         </div>
       </div> */
.skeleton-line {
  display: block;
  height: .72rem;
  width: 100%;
  border-radius: var(--radius-pill);
}
.skeleton-line-title { height: 1rem; }
.skeleton-circle {
  flex: none;
  width: 2.4rem;
  height: 2.4rem;
  border-radius: var(--radius-round);
}
.skeleton-block { min-height: 4.5rem; border-radius: var(--radius); }
.skeleton-text { display: grid; gap: var(--space-1-5); min-width: 0; }
/* Rreshti i dytë e i tretë janë më të shkurtër, si çdo paragraf i vërtetë. */
.skeleton-text > .skeleton-line:nth-child(2) { width: 86%; }
.skeleton-text > .skeleton-line:nth-child(3) { width: 62%; }
.skeleton-list { display: grid; gap: 0; }
.skeleton-row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) 5rem;
  gap: var(--space-3);
  align-items: center;
  padding: var(--space-3) 0;
  border-bottom: 1px solid var(--border);
}
.skeleton-row:last-child { border-bottom: 0; }
/* Rreshtat nuk nisen të gjithë njëherësh: një valë e njëtrajtshme lexohet si
   defekt vizatimi, një valë e shkallëzuar lexohet si punë në rrjedhë. */
.skeleton-row:nth-child(2) .skeleton::after { animation-delay: .12s; }
.skeleton-row:nth-child(3) .skeleton::after { animation-delay: .24s; }
.skeleton-row:nth-child(n+4) .skeleton::after { animation-delay: .36s; }

/* Kartela që pret: e njëjta gjeometri si ajo që do të vijë, që faqja të mos
   kërcejë sapo të dhënat mbërrijnë. */
.skeleton-card {
  display: grid;
  gap: var(--space-3);
  padding: var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
}

@media (prefers-reduced-motion: reduce) {
  /* Blloku i përgjithshëm më lart e ndal çdo animacion pas një rrotullimi, dhe
     `translateX(-100%)` e lë shkëlqimin të ngrirë jashtë kutisë — pra një shirit
     drite i ndaluar në buzë. Këtu hiqet fare: mbetet vetëm sipërfaqja e qetë, që
     është saktësisht ç'do të thotë «po pritet» pa lëvizje. */
  .skeleton::after { display: none; }
}

/* --- 9.6 Koka e faqes, e pasuruar -------------------------------------------
   `.page-head` di titullin dhe veprimet. Ç'i mungonte janë tri gjëra që faqet i
   shkruanin poshtë tij me utilitete: ku ndodhem (shtegu), sa janë (shifrat), dhe
   cili nga gjashtë butonat është ai kryesori. */

/* Shtegu. Te një dosje klienti a një detaj task-i, shiriti i sipërm mban vetëm
   markën dhe kërkimin — pra njeriu s'e di ku është pa e lexuar trupin e faqes. */
.page-crumbs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-0) var(--space-1-5);
  font-size: var(--text-xs);
  margin-bottom: var(--space-1);
  min-width: 0;
}
.page-crumbs a { color: var(--muted); text-decoration: none; }
.page-crumbs a:hover { color: var(--primary-text); text-decoration: underline; }
.page-crumb-sep { color: var(--muted); }
.page-crumbs [aria-current="page"] { color: var(--text); font-weight: 600; }

/* Shifrat ndihmëse. «{n} subjekte» rrinte herë si `.chip` te veprimet, herë si
   `small text-muted` te koka e një kartele, herë fare — dhe një çip i vënë te
   vendi i veprimeve është një numër që pretendon se klikohet. */
.page-figs {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2) var(--space-4);
  margin-top: var(--space-2);
  min-width: 0;
}
.page-fig { display: flex; align-items: baseline; gap: var(--space-1-5); min-width: 0; }
.page-fig-value {
  font-weight: 700;
  font-size: var(--text-lg);
  line-height: 1.1;
  letter-spacing: -.01em;
  font-variant-numeric: tabular-nums;
}
.page-fig-label { font-size: var(--text-xs); color: var(--muted); }
.page-fig-danger .page-fig-value { color: var(--danger); }
.page-fig-warning .page-fig-value { color: var(--warning); }
.page-fig-success .page-fig-value { color: var(--success); }

/* Veprimet: kryesori veç dytësorëve. Shtatë kontrolle në një rresht (Regjistri,
   Afatet) lexohen si shtatë zgjedhje njësoj të rëndësishme; ndarësi thotë se
   djathtas tij rri ajo për të cilën u hap faqja. */
.page-actions-group {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}
.page-actions-sep {
  flex: 0 0 1px;
  align-self: stretch;
  min-height: 1.4rem;
  background: var(--border-strong);
  margin-inline: var(--space-0);
}
@media (max-width: 575.98px) {
  /* Kur rreshti është mbështjellë gjithsesi, ndarësi vertikal ndan dy gjëra që
     s'janë më krah për krah. */
  .page-actions-sep { display: none; }
}

/* Koka që mbetet në ekran. Vetëm për faqet e gjata ku veprimi kryesor rri lart
   dhe lista poshtë ka treqind rreshta.
   `z-index: 5` dhe jo më shumë: shkalla e programit e nis chrome-in te 1030
   (.app-topbar), dhe një kokë faqeje që i kalon ata numra do të kalonte edhe mbi
   shiritin e sipërm. Sfond i plotë e jo `backdrop-filter` — ky i fundit do ta
   bënte kokën kontekst stakimi dhe do t'i burgoste brenda saj menytë rënëse që
   mban `.page-actions` (shih `.bi-pane` më lart, ku kjo grackë është paguar). */
.page-head-sticky {
  position: sticky;
  top: calc(var(--topbar-h) - 1px);
  z-index: 5;
  background: var(--bg);
  margin: calc(var(--space-5) * -1) calc(var(--space-5) * -1) var(--space-4);
  padding: var(--space-5) var(--space-5) var(--space-3);
  border-bottom: 1px solid var(--border);
}
@media (max-width: 576px) {
  /* Mbushja e `.app-content` bie te .85rem këtu; koka duhet ta ndjekë, përndryshe
     ajo del 0.65rem jashtë faqes në të dyja anët. */
  .page-head-sticky {
    margin-inline: calc(var(--space-3) * -1);
    padding-inline: var(--space-3);
    padding-top: var(--space-4);
  }
}

/* --- 9.7 Kartela e detajit, shiriti i kartës, titulli i seksionit -----------
   «Detaji i një regjistrimi» — titull e nëntitull majtas, status ose shumë
   djathtas, vijë poshtë — ishte ndërtuar 11 herë me `d-flex justify-content-between
   align-items-start` dhe me hapësirë poshtë herë `mb-3`, herë `pb-3 mb-4`, herë
   asgjë; vija ndarëse dilte vetëm te dy nga gjashtë faqet. `.page-head` s'mund ta
   bënte: ai ka `align-items: flex-end` dhe hapësirën e vet, pra brenda një kartele
   e shtyn gjithçka poshtë.

       <div class="card card-body detail-card">
         <div class="detail-head">
           <div class="detail-head-main">
             <h2 class="detail-title">Fatura 2026-114</h2>
             <p class="detail-sub">Klienti · 14/07/2026</p>
           </div>
           <div class="detail-side">
             <span class="detail-figure money">1 240,00 €</span>
             <span class="chip chip-warning">Pa paguar</span>
           </div>
         </div>
         <div class="detail-body">…</div>
         <div class="detail-foot">…</div>
       </div> */

/* Vetë kutia bën pak, dhe kjo është me qëllim: ajo nuk zbukuron, e SHËNON kutinë
   si «një regjistrim i vetëm». Ajo shenjë e mban letrën të mos e ndajë kartelën
   në dy fletë (shih 9.15), dhe `min-width: 0` e ndalon një numër llogarie a një
   emër skedari pa hapësira ta zgjerojë shtyllën përtej rrjetit që e mban. */
.detail-card { min-width: 0; }

.detail-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  padding-bottom: var(--space-3);
  margin-bottom: var(--space-4);
  border-bottom: 1px solid var(--border);
}
.detail-head-main { min-width: 0; flex: 1 1 14rem; }
.detail-title {
  font-size: var(--text-lg);
  font-weight: 700;
  letter-spacing: -.01em;
  margin: 0 0 var(--space-0);
  overflow-wrap: anywhere;
}
.detail-sub { font-size: var(--text-sm); color: var(--muted); margin: 0; }
.detail-side {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--space-1);
  text-align: right;
  flex: 0 0 auto;
}
.detail-figure {
  font-size: var(--text-xl);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
}
.detail-body { display: grid; gap: var(--space-4); min-width: 0; }
.detail-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  padding-top: var(--space-3);
  margin-top: var(--space-4);
  border-top: 1px solid var(--border);
}
/* Veprimet e fundit shtyhen djathtas, ku i pret dora pasi ka lexuar. */
.detail-foot-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin-left: auto;
}

/* Shiriti i një kartele: titull majtas, vegla djathtas. `.table-toolbar` e ka
   pikërisht këtë trup dhe përdoret 71 herë — por emri i saj thotë «tabelë»,
   prandaj çdo kokë që mban një buton mbi një listë, një formular ose një grafik e
   rishkruante me katër utilitete, dhe tetë nga trembëdhjetë e harronin
   `flex-wrap gap-2`: pra në telefon titulli dhe butoni ngjiteshin.
   Emri i vjetër nuk u zgjerua sepse site.js e ndërton atë shirit me atë emër —
   `.card-bar` është i njëjti trup me emrin që s'premton tabelë. */
.card-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-3);
}
/* Kur nuk ka titull: veglat shkojnë krejt djathtas, pa një bosh në mes. */
.card-bar-end { justify-content: flex-end; }

/* Titulli i një seksioni brenda një karte. Katër klasa vendore e bënin këtë
   (.acc-sub-title, .peek-block-title, .keys-group-title, .tm-panel-title) dhe 15
   vende të tjera e thurnin me tre-katër utilitete — ku hapësira mes shkronjave
   dilte herë nga `tracking-wide` (.12em), herë nga asgjë. */
.section-title {
  display: flex;
  align-items: center;
  gap: var(--space-1-5);
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--muted);
  margin: 0 0 var(--space-2);
}
/* Me vijë deri në buzë — kur seksioni ndan dy blloqe brenda së njëjtës kartë. */
.section-title-rule::after {
  content: "";
  flex: 1 1 auto;
  height: 1px;
  background: var(--border);
}

/* --- 9.8 Rrjeta e faqes -----------------------------------------------------
   Shtylla kryesore plus ajo anësore. Sot çdo faqe e shkruan me `row` dhe
   `col-lg-8` / `col-lg-4`, pra ndarja vendoset faqe për faqe: 8/4 te njëra, 7/5
   te tjetra, dhe shiriti anësor rrjedh me përmbajtjen edhe kur është vetëm një
   listë e shkurtër.

   `@media` dhe jo `@container`: një `container-type` sjell me vete `contain:
   layout`, dhe ajo e bën kutinë bllok-përmbajtës për ÇDO `position: fixed` brenda
   saj — pra çdo modal i faqes do të hapej brenda shtyllës, nën velin e vet. Ai
   defekt ka qenë njëherë në prodhim (shih `.app-content`), dhe pikërisht kjo
   rrjetë është vendi ku modalet rrinë më shpesh. Kontejnerët e programit mbeten
   dy, dhe të dy e mbajnë provën me vete.

       <div class="page-grid page-grid-wide">
         <div class="page-main">…</div>
         <aside class="page-aside page-aside-sticky">…</aside>
       </div> */
.page-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-4);
  align-items: start;
}
.page-main,
.page-aside {
  display: grid;
  gap: var(--space-4);
  align-content: start;
  min-width: 0;
}
@media (min-width: 992px) {
  .page-grid {
    grid-template-columns: minmax(0, 1fr) var(--aside-w, 20rem);
    gap: var(--space-5);
  }
  .page-grid-wide { --aside-w: 24rem; }
  .page-grid-narrow { --aside-w: 16rem; }
  /* Shiriti anësor majtas — për faqet ku ai është navigim, jo shtojcë. */
  .page-grid-left { grid-template-columns: var(--aside-w, 20rem) minmax(0, 1fr); }
  .page-grid-left > .page-aside { order: -1; }
  /* Ndjek rrëshqitjen, dhe VETËM aty ku i thuhet: një panel i ngjitur më i lartë
     se ekrani është një panel ku fundi s'arrihet kurrë, sepse ai ngjitet sapo
     kryet e tij prek kufirin dhe bishti mbetet jashtë. Pra kjo klasë i takon një
     paneli që hyn në ekran — një kartë e vetme, jo një listë që rritet.

     Pa `max-height` dhe pa `overflow`, edhe pse ato do ta zgjidhnin lartësinë:
     një kuti me `overflow` e pret çdo meny rënëse që hapet brenda saj, dhe
     paneli anësor është pikërisht vendi ku rrinë menytë me tri pika. Ai çmim
     është paguar njëherë te `.bi-pane`. */
  .page-aside-sticky {
    position: sticky;
    top: calc(var(--topbar-h) + var(--space-4));
  }
}

/* Ritmi vertikal i një faqeje. Sot hapësira mes seksioneve vjen nga `mb-3`,
   `mb-4` ose `mt-4` të zgjedhura veç e veç, pra dy faqe të njëjta marrin frymë
   ndryshe. Këtu hapësirën e mban ena, jo secili fëmijë. */
.page-stack { display: grid; gap: var(--space-5); align-content: start; }
.page-stack-sm { gap: var(--space-3); }
.page-stack-lg { gap: var(--space-6); }

/* --- 9.9 Kartelat që bien në të njëjtat vija (subgrid) ----------------------
   Kur tri karta rrinë krah për krah, titujt e tyre nisin në tri lartësi të
   ndryshme sapo njëra prej tyre ka titull dy-rreshtash, dhe butoni i fundit i
   secilës rri aty ku e la teksti i saj. Syri e lexon këtë si tri kuti të
   pakujdesshme, edhe kur nuk di ta emërtojë.

   `subgrid` e zgjidh me tri rreshta: kartat marrin rreshtat e rrjetit prind, pra
   koka, trupi dhe fundi i secilës bien mbi të njëjtat vija — pa asnjë lartësi të
   shkruar me dorë dhe pa asnjë matje nga JavaScript-i.

       <div class="card-rail">
         <div class="card card-slot">
           <div class="card-header">…</div>
           <div class="card-body">…</div>
           <div class="card-footer">…</div>
         </div>
       </div>

   Saktësisht tri pjesë për kartë — as më pak, as më shumë: `span 3` s'e mban një
   të katërtin, dhe një kartë me dy pjesë e lë rreshtin e tretë bosh. Nëse fundi
   s'ka çfarë të mbajë, lëre `<div class="card-footer"></div>` bosh: atëherë
   fundet e motrave të saj rrinë ende në një vijë.

   Pjesët brenda nuk kërkojnë emra të vetëtë: `.card-header`, `.card-body` dhe
   `.card-footer` e Bootstrap-it janë tashmë tri fëmijët, dhe subgrid-i i vendos
   sipas radhës. Rruga pa subgrid nuk shkruhet fare — pa të, `.card` e Bootstrap-it
   është një flex-kolonë me `.card-body { flex: 1 1 auto }`, pra fundet bien bashkë
   ashtu siç binin dje. Ç'shton subgrid-i është vija e dytë: koka.

   Pse jo `.stat-card`: ajo është kontejner (`container-type: inline-size`), dhe
   kontenimi i shtresës e ndalon subgrid-in — një rrjet me `contain: layout` nuk
   mund të jetë nëngrid i prindit të vet. Kartat e shifrave mbeten siç janë. */
.card-rail {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(var(--rail-min, 17rem), 1fr));
  gap: var(--space-4);
}
.card-rail-wide { --rail-min: 22rem; }
.card-slot { min-width: 0; }

@supports (grid-template-rows: subgrid) {
  .card-slot {
    display: grid;
    grid-row: span 3;
    grid-template-rows: subgrid;
    row-gap: 0;
  }
}

/* --- 9.10 Hyrja e rreshtave, e lidhur me rrëshqitjen ------------------------
   `.reveal` e bën këtë sot me një `IntersectionObserver` te site.js: një dëgjues
   i yni që zgjohet për çdo element që hyn në ekran, dhe një klasë që vihet nga
   filli kryesor. Aty ku shfletuesi e mban, e njëjta gjë bëhet pa asnjë rresht
   JavaScript-i — `view()` e lidh animacionin drejtpërdrejt me pozicionin e
   elementit brenda ekranit, dhe atë e llogarit vetë shfletuesi.

   Rruga e vjetër nuk u prek: `.js-reveal .reveal` dhe `.in` rrinë ashtu siç ishin,
   dhe janë e vetmja rrugë për shfletuesin që s'e njeh `view()`. Kur ai e njeh,
   animacioni fiton mbi vlerat e deklaruara dhe klasa `.in` thjesht s'ka më punë.

   Longhand dhe jo shkurtorja `animation:` — ajo e rivendos `animation-timeline`
   te `auto`, pra do ta shkëpuste vetë lidhjen që po vendoset këtu.

   Fundi i intervalit matet në pikselë e jo në përqindje, dhe kjo është e vetmja
   gjë delikate: një `entry 40%` mbi një kartelë më të lartë se ekrani do të thotë
   se ajo mbaron së shfaquri vetëm pasi buza e saj e poshtme ka kaluar fundin e
   ekranit — pra njeriu do ta lexonte gjysmën e saj të tejdukshme. 240 pikselë
   është 240 pikselë për çdo kuti, sado e lartë.

   E njëjta siguri si te `.stagger`: kuadri i fundit i `revealUp` është
   `transform: none`, dhe `both` e mban aty — pra asnjë kartelë nuk mbetet me një
   kontekst stakimi që do t'ia burgoste menytë rënëse brenda vetes. */
@keyframes revealUp {
  from { opacity: 0; transform: translateY(12px) scale(.985); }
  to   { opacity: 1; transform: none; }
}
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .js-reveal .reveal {
      opacity: 1;
      transform: none;
      transition: none;
      animation-name: revealUp;
      animation-timing-function: var(--ease-out);
      animation-fill-mode: both;
      animation-timeline: view();
      animation-range: entry 0% entry 240px;
    }
  }
}

/* --- 9.11 Rreshti i veprimeve -----------------------------------------------
   Fundi i një formulari: «Ruaj» dhe «Anulo», herë-herë një fshirje krejt djathtas.
   `.page-actions` e ka pikërisht këtë trup — flex, wrap, gap .5rem — por emri e
   lidh me kokën e faqes, prandaj asnjë fund formulari s'e përdorte. Në vend të
   saj kishte pesë vargje utilitetesh me tri hapësira të ndryshme (`gap-1`,
   `gap-2`, `gap-3`), dhe disa pa `flex-wrap`: pra në telefon butoni i dytë dilte
   jashtë ekranit.

       <div class="form-actions">
         <button class="btn btn-primary">Ruaj</button>
         <a class="btn btn-outline-secondary" href="…">Anulo</a>
         <button class="btn btn-outline-danger form-actions-end">Fshi</button>
       </div>

   Hapësira është `--space-2`, e njëjta që ndan çdo dy kontrolle fqinje në këtë
   shtresë — jo një e treta e zgjedhur nga faqja. */
.form-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2);
}
/* Ç'është e pakthyeshme shtyhet larg dorës që klikon e para. */
.form-actions > .form-actions-end { margin-left: auto; }
/* Kur formulari është i gjatë, fundi duhet të thotë edhe se këtu mbaron. */
.form-actions-rule {
  margin-top: var(--space-4);
  padding-top: var(--space-3);
  border-top: 1px solid var(--border);
}
/* Nën 576px dy butona krah për krah bëhen dy butona të ngushtë, secili me
   tekstin e vet të thyer në dy rreshta. Më mirë njëri poshtë tjetrit, i tërë
   gjerësia, sa gishti ta gjejë pa e kërkuar. */
@media (max-width: 575.98px) {
  .form-actions-stack { flex-direction: column; align-items: stretch; }
  .form-actions-stack > .form-actions-end { margin-left: 0; }
}

/* --- 9.12 Kutia e qetë brenda kartës ----------------------------------------
   Tetë kuti të shkruara si `border rounded p-3`, `border rounded-3 p-3`,
   `border rounded p-2` ose `bg-body-tertiary border rounded p-3`. Rrezja e
   Bootstrap-it (`rounded` = .375rem, `rounded-3` = .5rem) nuk përputhet me asnjë
   nga tokenat e programit (`--radius-sm` = .55rem, `--radius` = .8rem), pra ato
   ishin të vetmet sipërfaqe këtu me cepa që sistemi s'i njeh — dhe mbushja
   ndryshonte nga p-2 te p-3 pa asnjë arsye.

       <div class="inset">
         <div class="section-title">TVSH e mbledhur</div>
         <div class="inset-figure money">1 240,00 €</div>
       </div> */
.inset {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-muted);
  padding: var(--space-3);
  min-width: 0;
}
/* Pa sfond: kur kutia rri mbi një sipërfaqe tashmë të zbehtë dhe do vetëm vijën. */
.inset-plain { background: transparent; }
.inset-lg { padding: var(--space-4); border-radius: var(--radius); }
/* Shifra që kutia mban. E njëjta peshë dhe e njëjta gjerësi shifrash si te
   `.detail-figure` — dy kuti fqinje me numra të ndryshëm rrinë në një vijë. */
.inset-figure {
  font-size: var(--text-xl);
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
}

/* --- 9.13 Njoftimi me ikonë -------------------------------------------------
   Shtatë alarme me tri gjeometri: `d-flex gap-3 align-items-start`,
   `d-flex align-items-center gap-2`, `d-flex align-items-center gap-2
   flex-wrap`. Pra secila faqe zgjidhte vetë a rreshtohet ikona me qendrën apo me
   kryet e tekstit, dhe a është hapësira .5rem apo 1rem. `.deadline-banner` e
   zgjidh pikërisht këtë punë — por vetëm për afatet.

   Ngjyra mbetet e Bootstrap-it (`alert-danger`, `alert-success`…): këtu shkruhet
   vetëm gjeometria, pra `.notice` hipën mbi `.alert` pa e zëvendësuar.

       <div class="alert alert-danger notice">
         <i class="bi bi-exclamation-triangle notice-icon"></i>
         <div class="notice-body">
           <p class="notice-title">Deklarata s'u dorëzua</p>
           <p class="mb-0">Afati ishte më 20/07.</p>
         </div>
         <a class="btn btn-sm btn-outline-danger notice-actions" href="…">Hape</a>
       </div>

   `flex-start` dhe jo `center`: një njoftim me dy rreshta tekst e lë ikonën në
   mes të tyre, pra ajo tregon hapësirën mes rreshtave në vend të fjalisë. */
.notice {
  display: flex;
  align-items: flex-start;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-3);
}
.notice-icon {
  flex: 0 0 auto;
  font-size: var(--text-lg);
  /* Në një vijë me rreshtin e parë të tekstit, jo me kryet e kutisë. */
  line-height: 1.5;
}
.notice-body { flex: 1 1 14rem; min-width: 0; }
.notice-body > :last-child { margin-bottom: 0; }
.notice-title { font-weight: 700; margin: 0 0 var(--space-0); }
/* Veprimi shkon djathtas, dhe në telefon bie poshtë tekstit i tëri. */
.notice-actions { margin-left: auto; flex: 0 0 auto; }

/* --- 9.14 Rreshti i listës me një vlerë djathtas ----------------------------
   `list-group-item d-flex justify-content-between align-items-center` × 12, ku
   katër e shkruanin `py-2` dhe tetë e linin hapësirën e paracaktuar të
   Bootstrap-it: pra dy lista në të njëjtën faqe kishin rreshta me lartësi të
   ndryshme.

       <li class="list-group-item list-kv">
         <span>Faturat e muajit</span>
         <span class="list-kv-value">24</span>
       </li> */
.list-kv {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding-top: var(--space-2);
  padding-bottom: var(--space-2);
  min-width: 0;
}
.list-kv-value {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  flex: 0 0 auto;
}

/* --- 9.15 Llogaria te lista e përdoruesve -----------------------------------
   Një rresht i vetëm mban tri gjëra që lexohen bashkë — kush është, si quhet te
   hyrja, si kapet — dhe një të katërt që lexohet vetëm kur pyetet: kartela e
   plotë, e hapur nën po atë rresht. */
.user-cell {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
}
.user-cell-main {
  display: flex;
  flex-direction: column;
  min-width: 0;
  line-height: 1.25;
}
/* Kokë shigjete, jo buton me tekst: përsëritet në çdo rresht dhe një fjalë e
   përsëritur njëzet herë e bën shtyllën e emrit të palexueshme. */
.user-more-toggle {
  --bs-btn-padding-x: var(--space-1-5);
  --bs-btn-padding-y: var(--space-0);
  line-height: 1;
  flex: 0 0 auto;
}
.user-more-toggle i { transition: transform var(--dur-2) var(--ease-out); }
.user-more-toggle.is-open i { transform: rotate(90deg); }

/* Pak më e errët se rreshti mbi të, që kartela të lexohet si vazhdim i tij e jo
   si rresht i ri i tabelës. --surface-2 s'ekziston si token: rrjedh me fallback,
   si te vendet e tjera që e përdorin. */
.user-more > td { background: var(--surface-2, rgba(127, 127, 127, .07)); }
.user-more-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: var(--space-3);
  padding: var(--space-2) var(--space-1);
}
.user-more-title {
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--muted);
  margin-bottom: var(--space-2);
}
/* Çift emër–vlerë në dy shtylla: emri i zbehtë majtas, vlera e plotë djathtas,
   që syri të zbresë nëpër vlera pa i lexuar etiketat dy herë. */
.user-more-kv {
  display: grid;
  grid-template-columns: minmax(6.5rem, auto) 1fr;
  gap: var(--space-0) var(--space-2);
  margin: 0;
  font-size: var(--text-sm);
}
.user-more-kv dt { font-weight: 500; color: var(--muted); }
.user-more-kv dd { margin: 0; overflow-wrap: anywhere; }
.user-more-links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-2);
}

/* --- 9.16 Letra -------------------------------------------------------------
   Ç'është kontroll në ekran nuk është asgjë mbi letër, dhe ç'është pritje nuk ka
   mbërritur ende sa për t'u shtypur. */
@media print {
  .filter-bar,
  .filter-quick,
  .filter-applied,
  .page-crumbs,
  .skeleton-text,
  .skeleton-list,
  .skeleton-card { display: none !important; }

  /* Dy shtyllat bëhen një: mbi A4 një shirit anësor 20rem e ngushton tabelën aq
     sa asnjë shtyllë numrash nuk hyn më. */
  .page-grid,
  .card-rail { display: block !important; }
  .page-aside-sticky { position: static; }
  .card-slot { display: block; }

  /* Një regjistrim nuk ndahet në dy fletë. */
  .detail-card,
  .card-slot,
  .kv-row,
  .data-table > tbody > tr { break-inside: avoid; }

  /* Koka e ngjitur s'ka ku të ngjitet mbi letër, dhe hapësira negative e saj do
     ta nxirrte jashtë kufirit të fletës. */
  .page-head-sticky {
    position: static;
    margin: 0 0 var(--space-4);
    padding: 0 0 var(--space-3);
  }
}

/* --- 9.17 Kryefaqja publike --------------------------------------------------
   Deri tani rrënja e programit ishte një ridrejtim: kush e hapte adresën pa
   llogari shkonte drejt e te forma e hyrjes, dhe zyra s'kishte asnjë faqe që të
   thoshte se ç'është ky vend. Kjo është ajo faqe — një hyrje e shkurtër: kush
   jemi, çfarë punohet brenda, dhe dera.

   Një rregull e mban të ndarë nga programi: KËTU NUK KA TË DHËNA. Asnjë numër i
   vërtetë, asnjë emër subjekti, asnjë total — faqja e sheh çdo vizitor pa e
   njohur, pra çdo shifër që do të hynte këtu do të ishte e dikujt. Edhe tri
   figurat janë vizatime: fletët mbi to mbajnë forma rreshtash, jo shifra.

   Pamja: paneli i heroit është i errët në të dyja temat, si ai i hyrjes — një
   markë nuk e ndërron ngjyrën me temën e shfletuesit. Pjesa tjetër e faqes rri
   te sipërfaqet e zakonshme, që kalimi nga kjo faqe te paneli pas hyrjes të mos
   jetë kalim në një program tjetër. */
.land {
  display: grid;
  gap: var(--space-7);
  padding-bottom: var(--space-7);
}

/* Heroi: fjalët majtas, libri djathtas. Raporti 1.04/0.96 sepse kolona e majtë
   mban një titull që rrjedh — po t'i jepje gjysmën e saktë, titulli do të
   thyhej në tri rreshta pikërisht atje ku figura ka ende hapësirë bosh. */
.land-hero {
  position: relative;
  overflow: hidden;
  display: grid;
  grid-template-columns: minmax(0, 1.04fr) minmax(0, .96fr);
  align-items: center;
  gap: clamp(var(--space-5), 3vw, var(--space-7));
  padding: clamp(var(--space-5), 3.4vw, var(--space-7));
  border-radius: var(--radius-xl);
  color: rgba(255,255,255,.96);
  /* E njëjta familje si paneli i hyrjes: cyan lart-djathtas, indigo→vjollcë
     tejpërtej, dhe një bazë e errët poshtë tyre që asnjë shtresë e tejdukshme
     të mos e lërë tekstin mbi të bardhë. */
  background:
    radial-gradient(120% 92% at 86% -10%, rgba(34,211,238,.18), transparent 56%),
    linear-gradient(152deg, rgba(49,46,129,.97) 0%, rgba(67,56,202,.94) 36%,
                    rgba(109,40,217,.92) 72%, rgba(124,58,237,.95) 100%),
    rgba(20,18,58,1);
  box-shadow: var(--shadow-lg);
}
.land-hero-copy { display: grid; gap: var(--space-4); justify-items: start; }

.land-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-pill);
  background: rgba(255,255,255,.14);
  border: 1px solid rgba(255,255,255,.22);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
}
.land-title {
  margin: 0;
  font-size: var(--display-md);
  font-weight: 800;
  line-height: 1.1;
  letter-spacing: -.02em;
}
/* Emri i zyrës mbahet i bardhë dhe nënvizohet me arin e markës. Një gradient
   mbi tekst do të kërkonte `background-clip: text`, dhe atë e ka tashmë njëra
   faqe: te `forced-colors` ai tekst zhduket krejt e duhet kthyer me dorë. Një
   vijë poshtë fjalës e thotë të njëjtën gjë pa e vënë emrin në atë rrezik. */
.land-title b {
  font-weight: 800;
  box-shadow: inset 0 -.22em 0 color-mix(in srgb, var(--warning-fill) 62%, transparent);
}
.land-lead {
  margin: 0;
  max-width: 34rem;
  font-size: var(--text-lg);
  line-height: 1.62;
  color: rgba(255,255,255,.86);
}
.land-cta { display: flex; flex-wrap: wrap; gap: var(--space-3); }
/* Dera kryesore mbi një panel që është i errët në të dyja temat, pra as ajo nuk
   guxon ta pyesë temën. `btn-light` i Bootstrap-it e merr ngjyrën e tekstit nga
   tema: te e errëta ai dilte gri i zbehtë mbi të bardhë — një buton pothuaj i
   palexueshëm pikërisht aty ku faqja kërkon një klikim. */
.land-cta .btn-land-solid {
  background: rgba(255,255,255,.96);
  border: 1px solid rgba(255,255,255,.96);
  color: rgba(49,46,129,1);
  font-weight: 600;
}
.land-cta .btn-land-solid:hover,
.land-cta .btn-land-solid:focus-visible {
  background: rgba(255,255,255,1);
  border-color: rgba(255,255,255,1);
  color: rgba(49,46,129,1);
}
/* Butoni i dytë mbi një panel të errët: `btn-outline-primary` do të merrte
   indigon e temës së çelët dhe do të zhdukej brenda saj. */
.land-cta .btn-land-ghost {
  color: rgba(255,255,255,.94);
  border: 1px solid rgba(255,255,255,.34);
  background: rgba(255,255,255,.08);
}
.land-cta .btn-land-ghost:hover,
.land-cta .btn-land-ghost:focus-visible {
  color: rgba(255,255,255,1);
  background: rgba(255,255,255,.16);
  border-color: rgba(255,255,255,.5);
}
.land-facts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--text-sm);
  color: rgba(255,255,255,.8);
}
.land-facts li { display: inline-flex; align-items: center; gap: var(--space-2); }
.land-facts i { color: var(--warning-fill); }

/* Kutia e figurës. Raporti 3/2 është saktësisht ai i vizatimeve, pra `cover`
   nuk pret asgjë — dhe pikërisht poshtë majtas te secila rri marka, e cila me
   një kuti tjetër do të dilte jashtë kuadrit. Ngjyra nën figurë është e errët
   me qëllim: derisa SVG-ja mbërrin, kutia rri e mbushur e jo e bardhë. */
.land-shot {
  aspect-ratio: 3 / 2;
  border-radius: var(--radius-lg);
  border: 1px solid rgba(255,255,255,.12);
  background: rgba(11,13,38,1) center / cover no-repeat;
  box-shadow: var(--shadow-lg);
}
.land-shot-1 { background-image: var(--land-shot-1); }
.land-shot-2 { background-image: var(--land-shot-2); }
.land-shot-3 { background-image: var(--land-shot-3); }

/* Koka e një seksioni: fjala e vogël sipër, titulli, dhe një rresht që e thotë
   punën. Të tria në një rrjetë, që hapësira mes tyre të mos varet nga `<br>`. */
.land-head { display: grid; gap: var(--space-2); margin-bottom: var(--space-5); max-width: 46rem; }
.land-kicker {
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--primary-text);
}
.land-h2 {
  margin: 0;
  font-size: var(--display-sm);
  font-weight: 700;
  letter-spacing: -.01em;
}
.land-sub { margin: 0; color: var(--muted); font-size: var(--text-lg); line-height: 1.6; }

.land-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
  gap: var(--space-4);
}
/* Gjashtë kartela dhe një ekran i gjerë: `auto-fit` i vë pesë në rreshtin e parë
   e një të vetme poshtë, dhe ajo e fundit lexohet si e harruar. Tri për rresht
   është e vetmja ndarje që i bie barabar. */
@media (min-width: 1100px) {
  .land-grid { grid-template-columns: repeat(3, 1fr); }
}
.land-card {
  display: grid;
  gap: var(--space-2);
  padding: var(--space-5);
  border-radius: var(--radius-lg);
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-sm);
  transition: transform var(--dur-2) var(--ease-out),
              box-shadow var(--dur-2) var(--ease-out),
              border-color var(--dur-2) var(--ease-out);
}
.land-card:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
  border-color: var(--primary-line);
}
.land-card i {
  width: 2.6rem;
  height: 2.6rem;
  display: grid;
  place-items: center;
  border-radius: var(--radius);
  background: var(--primary-soft);
  color: var(--primary-text);
  font-size: var(--text-lg);
  margin-bottom: var(--space-2);
}
.land-card b { font-size: var(--text-base); }
.land-card span { color: var(--muted); font-size: var(--text-sm); line-height: 1.55; }

/* Dy pamjet e mëdha: figura sipër, fjala poshtë. Legjenda është ajo që e thotë
   figurën — kutia mbi të rri `aria-hidden`, pra këtu nuk ka gjë të thuhet dy
   herë. */
.land-pair { display: grid; grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr)); gap: var(--space-5); }
.land-figure {
  display: grid;
  gap: var(--space-4);
  margin: 0;
  padding: var(--space-4);
  border-radius: var(--radius-xl);
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-sm);
}
.land-figure figcaption { display: grid; gap: var(--space-1-5); padding: 0 var(--space-2) var(--space-2); }
.land-figure b { font-size: var(--text-lg); }
.land-figure p { margin: 0; color: var(--muted); line-height: 1.6; }

/* Shiriti i besimit: i errët në të dyja temat, si heroi — ai që lexon këtu
   është duke pyetur nëse letrat e veta janë të sigurta, dhe kjo pyetje nuk
   ndërron pamje me temën. */
.land-trust {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: var(--space-5);
  padding: clamp(var(--space-5), 2.6vw, var(--space-6-5));
  border-radius: var(--radius-xl);
  color: rgba(255,255,255,.92);
  background:
    radial-gradient(110% 140% at 0% 0%, rgba(34,211,238,.14), transparent 58%),
    linear-gradient(140deg, rgba(23,26,72,1) 0%, rgba(16,18,52,1) 60%, rgba(11,13,38,1) 100%);
  box-shadow: var(--shadow-lg);
}
.land-trust-item { display: grid; gap: var(--space-1); align-content: start; }
.land-trust-item i {
  font-size: var(--text-xl);
  color: var(--warning-fill);
  margin-bottom: var(--space-2);
}
.land-trust-item b { font-size: var(--text-base); }
.land-trust-item span { color: rgba(255,255,255,.72); font-size: var(--text-sm); line-height: 1.55; }

/* Dera, edhe një herë. Kush zbriti deri poshtë e ka lexuar faqen — dhe do të
   ishte e çuditshme t'i kërkohej të ngjitej prapë lart për të hyrë. */
.land-close {
  display: grid;
  justify-items: center;
  gap: var(--space-3);
  padding: clamp(var(--space-5), 3vw, var(--space-6-5));
  border-radius: var(--radius-xl);
  text-align: center;
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-sm);
}
.land-close p { margin: 0; color: var(--muted); max-width: 34rem; }
.land-foot {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-2) var(--space-4);
  color: var(--faint);
  font-size: var(--text-sm);
}

@media (max-width: 900px) {
  /* Një shtyllë, dhe figura zbret poshtë fjalëve: në një ekran të ngushtë ajo
     do të shtypej në një shirit ku as libri as marka nuk lexohen më. */
  .land-hero { grid-template-columns: 1fr; }
  .land-lead { font-size: var(--text-base); }
  .land-sub { font-size: var(--text-base); }
}

@media (max-width: 576px) {
  .land { gap: var(--space-5); }
  .land-cta { width: 100%; }
  .land-cta .btn { flex: 1 1 12rem; }
}

/* --- 9.18 Dera para programit ------------------------------------------------
   Kush shkruan adresën e zyrës mbërrin këtu i pari: një ekran, një buton, dhe
   asgjë tjetër. As meny, as gjuhë, as «Regjistrohu» — ato i mban kryefaqja pas
   kësaj dere, dhe një derë me katër doreza s'është derë.

   Prandaj bie edhe shiriti i sipërm. Nuk bie dot nga shablloni: `base.html` e
   vendos kokën para bllokut `content`, njësoj për çdo faqe, pra faqja që hapet
   brenda tij s'ka si ta heqë. `:has()` e njeh faqen nga ajo që mban — i njëjti
   mjet si te hyrja, `.app-content:has(.auth-hero)` më lart — dhe vendimi mbetet
   këtu, ku rrinë gjithë vendimet e pamjes.

   Ngjyra është familja e heroit të kryefaqes: indigo → vjollcë mbi një bazë të
   errët, e njëjtë në të dyja temat, sepse një markë nuk e ndërron ngjyrën me
   temën e shfletuesit. Kush e shtyp butonin nuk duhet të ndiejë se kaloi në një
   program tjetër — dera dhe shtëpia janë e njëjta shtëpi. */
.app-main:has(.door) .app-topbar { display: none; }
.app-content:has(.door) {
  /* Ankera e butonit lart-djathtas. `relative` e jo `transform`: një transform i
     animuar këtu do ta bënte këtë kuti bllokun mbajtës të çdo `position: fixed`
     brenda saj — gabimi te rreshti 1578. Kjo faqe s'mban asnjë modal, dhe kaq
     mban: një lidhje të vetme në cep. */
  position: relative;
  display: grid;
  place-items: center;
  padding: var(--space-5) var(--space-4);
  background:
    radial-gradient(120% 92% at 84% -12%, rgba(34,211,238,.18), transparent 56%),
    linear-gradient(152deg, rgba(49,46,129,.97) 0%, rgba(67,56,202,.94) 36%,
                    rgba(109,40,217,.92) 72%, rgba(124,58,237,.95) 100%),
    rgba(20,18,58,1);
}
.door { color: rgba(255,255,255,.96); text-align: center; }
.door-panel {
  display: grid;
  justify-items: center;
  gap: var(--space-2);
  max-width: 30rem;
}
/* Marka e madhe: këtu s'është shenjë në një cep, është vetë faqja. */
.door-mark {
  display: inline-flex;
  width: 5.5rem;
  height: 5.5rem;
  margin-bottom: var(--space-3);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}
/* Përshëndetja rri mbi emrin dhe e lë atë të flasë: e vogël, e qetë, sa një
   zë që të hap derën. Po t'i jepje të njëjtën peshë, faqja do të kishte dy
   tituj dhe asnjë emër. */
.door-hi {
  margin: 0;
  font-size: var(--text-lg);
  font-weight: 500;
  letter-spacing: .04em;
  color: rgba(255,255,255,.76);
}
.door-name {
  margin: 0;
  font-size: var(--display-md);
  font-weight: 800;
  letter-spacing: .02em;
}
.door-line {
  margin: 0;
  margin-top: var(--space-2);
  font-size: var(--text-lg);
  color: rgba(255,255,255,.78);
}
/* Kalimi tutje, i vogël dhe në cep. Xhami i lehtë mbi ngjyrën e faqes e jo një
   pllakë e bardhë: në mes rri marka, dhe një buton i bardhë atje lart do të
   ishte gjëja e parë që sheh syri — pra dera do të kërkonte prapë një klikim
   para se të thoshte ku ke mbërritur. Bëhet i bardhë kur e prek, që përgjigjja
   të mos lihet me hamendje. */
.door-go {
  position: absolute;
  top: var(--space-4);
  right: var(--space-4);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-pill);
  background: rgba(255,255,255,.14);
  border: 1px solid rgba(255,255,255,.38);
  color: rgba(255,255,255,.96);
  font-size: var(--text-sm);
  font-weight: 600;
  backdrop-filter: blur(6px);
}
.door-go:hover,
.door-go:focus-visible {
  background: rgba(255,255,255,.96);
  border-color: rgba(255,255,255,.96);
  color: rgba(49,46,129,1);
}

@media (max-width: 576px) {
  .door-panel { max-width: 22rem; }
  /* Në telefon cepi është më i ngushtë, dhe butoni s'ka pse ta prekë skajin. */
  .door-go {
    top: var(--space-3);
    right: var(--space-3);
  }
}

/* ============================================================================
   Thirrja me zë
   ----------------------------------------------------------------------------
   Një kartë e vetme me tri fytyra, sepse thirrja është një gjë e vetme me tri
   çaste: po të thërret, po thërret, po flisni. `data-state` te vetë kutia
   vendos cila fjalë dhe cili buton duket — pa u prekur asnjë klasë nga
   JavaScript-i përveç asaj një atributi.

   Zilja e merr ekranin. Kjo është e vetmja gjë në program që e bën, dhe e bën
   me qëllim: një zile që pret radhën pas asaj që po lexoje nuk është zile. Te
   çdo gjendje tjetër karta zbret poshtë-djathtas dhe të lë të punosh — biseda
   vazhdon ndërsa sytë janë diku tjetër.

   z-index 5000: mbi paletën e komandave (4500), mbi sirtarët (4000), mbi
   modalet e Bootstrap-it (1055). Asgjë s'ka të drejtë të rrijë mbi një telefon
   që bie. */

.ka-call {
  position: fixed;
  z-index: 5000;
  inset: auto var(--space-4) var(--space-4) auto;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Zona bosh rreth kartës nuk e bllokon faqen poshtë — vetëm vetë karta merr
     klikime. Pa këtë, gjysma e ekranit do të vdiste sa herë dikush thërret. */
  pointer-events: none;
}
.ka-call[data-state="idle"] { display: none; }

.ka-call-card {
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-lg);
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-lg);
  max-width: min(24rem, calc(100vw - 2rem));
}

/* --- zilja: gjithë ekrani ------------------------------------------------- */
.ka-call[data-state="ringing"] {
  inset: 0;
  background: color-mix(in srgb, var(--text) 55%, transparent);
}
.ka-call[data-state="ringing"] .ka-call-card {
  flex-direction: column;
  text-align: center;
  gap: var(--space-4);
  padding: var(--space-6) var(--space-5);
  min-width: min(21rem, calc(100vw - 2rem));
}

.ka-call-avatar {
  flex: none;
  width: 2.9rem;
  height: 2.9rem;
  border-radius: var(--radius-round);
  display: grid;
  place-items: center;
  background: var(--grad-primary);
  color: var(--primary-contrast);
  font-weight: 700;
  font-size: var(--text-lg);
}
.ka-call[data-state="ringing"] .ka-call-avatar {
  width: 5.5rem;
  height: 5.5rem;
  font-size: var(--text-3xl);
  /* Unaza që zgjerohet është e njëjta gjuhë si e një telefoni që dridhet: sytë
     e kapin nga cepi i ekranit pa e lexuar fjalën. */
  animation: kaCallPulse var(--beat) var(--ease-out) infinite;
}
@keyframes kaCallPulse {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--primary) 55%, transparent); }
  /* Fundi shkruhet `transparent` i thatë, jo një përzierje me 0%: unaza këtu nuk
     është gjerësi e zgjedhur por kuadro animacioni, dhe vetëm një ngjyrë krejt e
     tejdukshme e thotë atë — për syrin njësoj, për rregullin e hijeve qartë. */
  100% { box-shadow: 0 0 0 1.5rem transparent; }
}

.ka-call-who { min-width: 0; flex: 1 1 auto; }
.ka-call-name {
  font-weight: 600;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ka-call[data-state="ringing"] .ka-call-name { font-size: var(--text-xl); }
.ka-call-state { font-size: var(--text-sm); color: var(--muted); }
/* Vetëm fjala e çastit. Të treja rrinë te shablloni që t'i shkruajë `tr()`, jo
   JavaScript-i — përndryshe do të ishin tri vargje më shumë për t'u dërguar. */
.ka-call-state > span { display: none; }
.ka-call[data-state="ringing"] .ka-call-in,
.ka-call[data-state="calling"] .ka-call-out,
.ka-call[data-state="live"] .ka-call-on { display: inline; }
.ka-call-on {
  /* Ora s'ka pse të kërcejë sa herë ndryshon një shifër. */
  font-variant-numeric: tabular-nums;
  color: var(--success);
  font-weight: 600;
}
.ka-call-note {
  font-size: var(--text-sm);
  color: var(--muted);
}
.ka-call-note:empty { display: none; }

.ka-call-actions { display: flex; gap: var(--space-3); flex: none; }
.ka-call-btn {
  width: 2.9rem;
  height: 2.9rem;
  border-radius: var(--radius-round);
  border: 0;
  padding: 0;
  display: none;                      /* secili del vetëm te gjendja e vet */
  place-items: center;
  font-size: var(--text-lg);
  cursor: pointer;
}
.ka-call[data-state="ringing"] .ka-call-btn { width: 3.6rem; height: 3.6rem; }
.ka-call[data-state="ringing"] .ka-call-yes,
.ka-call[data-state="live"] .ka-call-mute,
.ka-call[data-state="ringing"] .ka-call-no,
.ka-call[data-state="calling"] .ka-call-no,
.ka-call[data-state="live"] .ka-call-no { display: grid; }

/* Ngjyra e shenjës rri te i njëjti rregull me mbushjen poshtë saj, jo te kutia
   e përbashkët mbi to. Ndarë, asnjë kontroll — as syri, as prova e temës së
   errët — nuk e sheh dot çiftin që në fakt del në ekran; bashkuar, ai lexohet:
   bojë e errët mbi një mbushje të ndezur, tetë e pesë me një. */
.ka-call-yes {
  background: var(--success-fill);
  color: var(--primary-contrast);
  box-shadow: var(--glow-success);
}
.ka-call-no {
  background: var(--danger-fill);
  color: var(--primary-contrast);
  box-shadow: var(--glow-danger);
}
.ka-call-mute {
  background: var(--surface-muted);
  color: var(--text);
  border: 1px solid var(--border);
}
.ka-call-mute.is-off { background: var(--warning-soft); color: var(--warning); }

@media (max-width: 576px) {
  /* Në telefon karta zë gjithë gjerësinë dhe rri mbi shiritin e poshtëm — jo
     mbi të: një thirrje s'ka pse ta bllokojë daljen prej saj. */
  .ka-call { inset: auto 0 var(--bottomnav-h) 0; }
  .ka-call-card {
    max-width: none;
    width: 100%;
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  }
  .ka-call[data-state="ringing"] { inset: 0; }
  .ka-call[data-state="ringing"] .ka-call-card {
    width: auto;
    border-radius: var(--radius-lg);
  }
}

@media (prefers-reduced-motion: reduce) {
  .ka-call[data-state="ringing"] .ka-call-avatar { animation: none; }
}

}  /* @layer components */

/* ============================================================================
   9b. Zëri i vendor-it
   ----------------------------------------------------------------------------
   Numri është `9b` dhe jo `11` sepse fjala e fundit e këtij skedari i takon
   seksionit 10: `test_the_high_contrast_work_never_touches_the_ordinary_page` e
   mat atë si «nga blloku i fundit `forced-colors` deri në fund të skedarit», pra
   çdo rregull i shkruar pas tij lexohet si i tiji — dhe roja bie mbi kod krejt
   të saktë.

   Deri sot shkalla dhe ora sundonin vetëm brenda këtij skedari. Ekrani dëgjonte
   dy zëra, dhe i dyti nuk ishte i askujt.

   U mat, jo u mendua: 14 faqe × 2 tema × 2 gjerësi, `getComputedStyle` mbi çdo
   element që mban VETË tekst — 56 matje. Dolën **15 madhësi të ndryshme** aty ku
   shkalla ka nëntë hapa, dhe të tepërtat vinin të gjitha nga jashtë saj:

     14,00px te 1.632 elemente — `.btn-sm` (`--bs-btn-font-size: .875rem`) dhe
                                 `.small` (`.875em` mbi një trup 16px);
     12,88px te 40            — po ai `.small`, tani mbi `--text-md`. `.875em`
                                 nuk është madhësi, është shumëzim: ai prodhon
                                 një numër që nuk i takon asnjë hapi, dhe që
                                 ndryshon sipas kutisë ku ndodh të bjerë;
     20,00px te 4             — `h5` i Bootstrap-it.

   Roja `test_no_size_is_written_outside_the_scale` nuk i kap dot, dhe nuk ka faj:
   ato nuk janë deklarata `font-size` te ky skedar. Janë ndryshore `--bs-*` dhe
   rregulla te një skedar që ne s'e shkruajmë. Ky seksion është përgjigjja —
   çdo vlerë e vendor-it lidhet me hapin tonë më të afërt.

   Aty ku vlera e tij rrinte tashmë mbi një hap (`1rem` = `--text-base`) lidhja
   nuk lëviz asnjë piksel; ajo vetëm i vë emrin, që hapi tjetër i shkallës t'i
   marrë me vete edhe ata. Aty ku nuk rrinte, lëvizja është nën 1,6px — sepse
   shkalla u ndërtua pikërisht pranë numrave që Bootstrap-i përdor.

   E njëjta gjë me orën. `transition` e kishte rojën e vet që nga gushti, por
   `animation` jo — dhe ajo është motra e saj, jo diçka tjetër. Në ekran matëm
   **dhjetë kohëzgjatje**: tri tonat, `4s` e shiritit të ngarkimit (e shpjeguar
   aty ku rri), dhe pastaj `.45s`, `.3s`, `.15s`, `.6s` — katër numra që s'i
   kishte zgjedhur askush për asnjë arsye.

   PSE @layer E BËN TË MUNDUR TË GJITHË KËTË: Bootstrap-i hyn me `layer(vendor)`,
   pra çdo rregull këtu fiton mbi të pa i dashur `!important` dhe pa i dashur një
   selektor më i gjatë — një klasë e vetme mjafton kundër `.btn-group-sm > .btn`.
   Përjashtimi i vetëm janë utility-t e tij (`.fs-*`), të cilat i ka shkruar vetë
   me `!important`, dhe `!important`-it i përgjigjet vetëm `!important`.
   ========================================================================= */

@layer base {

/* Titujt: gjashtë nivele mbi gjashtë hapa të njëpasnjëshëm, nga maja poshtë.
   Bootstrap-i i mban `h1`–`h4` si `calc(1.375rem + 1.5vw)` — domethënë ata
   rrjedhin me gjerësinë e dritares, dhe dy njerëz para dy ekraneve nuk e shohin
   kurrë të njëjtin titull. Kjo është pikërisht ajo që një shkallë e ndalon me
   qëllim: një hap që e ndryshon vetë lartësinë nuk është hap.

   `--display-sm` mbetet i vetmi titull që rrjedh, dhe rrjedh me `clamp()` mes dy
   kufijsh që i dimë — ai është titulli i faqes, jo çdo `h2` që gjendet aty. */
h1, .h1 { font-size: var(--text-3xl); }
h2, .h2 { font-size: var(--text-2xl); }
h3, .h3 { font-size: var(--text-xl); }
h4, .h4 { font-size: var(--text-lg); }
h5, .h5 { font-size: var(--text-base); }
h6, .h6 { font-size: var(--text-md); }

/* `.small` dhe `<small>`: nga shumëzim, në hap.
   `.875em` do të thotë «pak më e vogël se ajo ku ndodhesh», dhe pikërisht kjo e
   bën të pamatshme: e njëjta klasë jep 14px te një kartelë, 12,88px te një rresht
   bisede dhe 11,76px brenda një tabele të ngjeshur. Tri madhësi nga një emër i
   vetëm, dhe asnjëra prej tyre nuk është hap i shkallës.

   `--text-sm` është hapi që ata tre numra rrethonin. Kush do një hap më poshtë e
   ka `--text-xs`; kush do dy, `--text-2xs`. Ajo zgjedhje tani shihet te rregulli
   dhe jo te vendi ku bie klasa. */
.small, small { font-size: var(--text-sm); }
.lead { font-size: var(--text-lg); }

}  /* @layer base */

@layer components {

/* --- Madhësitë që vendor-i i mban te ndryshoret e veta ----------------------
   Të gjitha janë deklaruar brenda vetë rregullit të komponentit
   (`.btn-sm { --bs-btn-font-size: .875rem }`), jo te `:root` — pra një lidhje e
   shkruar te `:root` nuk do të arrinte kurrë deri aty. Kjo është e vetmja arsye
   pse ky bllok është listë selektorësh dhe jo gjashtë rreshta te tokenat. */
.btn                           { --bs-btn-font-size: var(--text-base); }
.btn-sm, .btn-group-sm > .btn  { --bs-btn-font-size: var(--text-sm); }
.btn-lg, .btn-group-lg > .btn  { --bs-btn-font-size: var(--text-lg); }
.dropdown-menu                 { --bs-dropdown-font-size: var(--text-base); }
.tooltip                       { --bs-tooltip-font-size: var(--text-sm); }
.toast                         { --bs-toast-font-size: var(--text-sm); }
.popover {
  --bs-popover-font-size: var(--text-sm);
  --bs-popover-header-font-size: var(--text-base);
}
.progress, .progress-stacked   { --bs-progress-font-size: var(--text-2xs); }

/* `.badge` e ka `.75em`, pra e njëjta kurth si `.small`: një shenjë numri brenda
   një titulli rritej me titullin, dhe brenda një butoni të vogël zbriste te
   10,08px. Çipat tanë rrinë te `--text-xs`; shenja e Bootstrap-it tani rri me ta. */
.badge                         { --bs-badge-font-size: var(--text-xs); }

/* --- Fushat: ato që s'kanë ndryshore, dhe s'i sheh matja ---------------------
   `.form-control-sm` e `.form-select-sm` e shkruajnë `.875rem` si deklaratë, jo
   si ndryshore — pra kërkojnë rregull, jo lidhje. Dhe ato nuk dalin te matja e
   madhësive: vlera e një `<input>` nuk është nyje teksti, pra as njëra nga 122
   fushat e vogla të programit nuk u numërua kurrë. Ato rrinin te 14px pa u parë.

   `.form-text` është `.875em` — po ai shumëzim si `.small`: fjalia nën një fushë
   ndryshonte madhësi sipas kutisë ku binte fusha. */
.form-control, .form-select    { font-size: var(--text-base); }
.form-control-sm, .form-select-sm,
.input-group-sm > .btn, .input-group-sm > .form-control,
.input-group-sm > .form-select, .input-group-sm > .input-group-text {
  font-size: var(--text-sm);
}
.form-control-lg, .form-select-lg,
.input-group-lg > .btn, .input-group-lg > .form-control,
.input-group-lg > .form-select, .input-group-lg > .input-group-text {
  font-size: var(--text-lg);
}
.form-text                     { font-size: var(--text-sm); }

/* --- Ora, te komponentët e vendor-it që programi i përdor vërtet -------------
   Longhand-et `transition-duration` / `transition-timing-function` e lënë të
   paprekur listën e vetive që ai kalon, dhe ndërrojnë vetëm orën. Po ta
   rishkruaje `transition`-in e plotë, do të duhej të mbaje në hap edhe listën e
   tij — dhe ajo listë ndryshon me çdo version të tij, jo me tonin. */
.form-control, .form-select, .form-check-input,
.btn-close, .nav-link, .fade {
  transition-duration: var(--dur-1);
  transition-timing-function: var(--ease-out);
}

/* Ç'hyn e del nga faqja e ka kohën e vet: modali, fleta anësore, palosja. */
.modal.fade .modal-dialog, .collapsing {
  transition-duration: var(--dur-3);
  transition-timing-function: var(--ease-out);
}
/* Menyja e telefonit është `.offcanvas-lg` dhe jo `.offcanvas` — pra një lidhje
   e shkruar vetëm mbi të dytën nuk e prek kurrë atë që hapet vërtet. Ishte i
   vetmi `0.3s` që mbeti në ekran pas raundit të parë, një element për faqe, dhe
   vetëm te telefoni: e gjeti matja, jo leximi. */
.offcanvas, .offcanvas-sm, .offcanvas-md,
.offcanvas-lg, .offcanvas-xl, .offcanvas-xxl {
  --bs-offcanvas-transition: transform var(--dur-3) var(--ease-in-out);
}

/* Shiriti që rritet drejt një shifre nuk është përgjigje ndaj një prekjeje —
   është një sasi që tregohet. `--dur-4` u shtua për të, dhe `barGrow` e grafikëve
   tanë lexon të njëjtin numër. */
.progress, .progress-stacked { --bs-progress-bar-transition: width var(--dur-4) var(--ease-out); }

/* Rrotulluesi është ritëm, jo përgjigje: ai rreh sa kohë prita. */
.spinner-border, .spinner-grow { --bs-spinner-animation-speed: var(--spin); }

}  /* @layer components */

@layer utilities {

/* `.fs-*` janë të vetmet që kërkojnë `!important`, dhe e kërkojnë sepse vetë i
   kanë. Katër të parat janë `calc(rem + vw)` si titujt; të gjashtat ndjekin të
   njëjtat gjashtë hapa, që `fs-4` te një shabllon të jetë saktësisht `h4`. */
.fs-1 { font-size: var(--text-3xl) !important; }
.fs-2 { font-size: var(--text-2xl) !important; }
.fs-3 { font-size: var(--text-xl) !important; }
.fs-4 { font-size: var(--text-lg) !important; }
.fs-5 { font-size: var(--text-base) !important; }
.fs-6 { font-size: var(--text-md) !important; }

}  /* @layer utilities */

/* ============================================================================
   10. Kontrasti i lartë
   ----------------------------------------------------------------------------
   Zyra punon në Windows, dhe kur dikush e ndez High Contrast-in shfletuesi ia
   merr faqes pikërisht ato me të cilat kjo faqe është ndërtuar: gradientët
   bëhen `none`, hijet bëhen `none`, dhe çdo ngjyrë kalon me detyrim te katër
   fjalët e temës së sistemit. Ç'mbetet nuk është faqja pa zbukurime — është
   faqja pa disa nga sipërfaqet mbi të cilat rri teksti.

   Dy gjëra u gjetën duke e shkruar këtë bllok, dhe të dyja ishin defekte të
   heshtura, jo çështje shijeje:

     1. Tetë rregulla fokusi e vizatojnë shenjën me `box-shadow`, jo me
        `outline` — katër mbi vetveten (`.collapse-card`, `.acc-picker-toggle`,
        `.acc-chosen-chip`, `th.sortable`), dy mbi elementin motër që është
        pjesa e dukshme e kontrollit (`.acc-day`, `.yoy-toggle`), dhe dy mbi
        kutinë rreth një fushe që e ka hequr unazën nga vetja (`.tm-search`,
        `.tm-sidebar-search`). Hija hiqet nga regjimi. Pra në kontrast të lartë
        të tetë mbeteshin krejt pa shenjë fokusi — dhe pikërisht ai regjim
        ndizet nga kush lëviz me tastierë.
     2. Tre vende e pikturojnë tekstin me `background-clip: text` mbi tekst të
        tejdukshëm: `.text-gradient` dhe `.error-code`. Kur
        gradienti bëhet `none`, nuk mbetet tekst i zbehtë — nuk mbetet tekst
        fare. I fundit është numri i madh i faqes së gabimit, pra në kontrast
        të lartë faqja «404» do të hapej pa 404-ën e vet.

   Të dyja ndreqen poshtë. Asgjë këtu nuk prek pamjen e zakonshme: të dy blloqet
   ndizen vetëm nga një zgjedhje e sistemit. Rrinë te `utilities`, shtresa e
   fundit — pra fitojnë mbi çdo komponent pa asnjë `!important`, dhe do të
   fitonin edhe sikur dikush t'i zhvendoste më lart te skedari.
   ========================================================================= */

@layer utilities {

@media (forced-colors: active) {

  /* --- Tokenat -------------------------------------------------------------
     Xhami dhe kufiri janë të dy me alfa. Regjimi ia detyron ngjyrën çdo
     `border-color`, por një `rgba()` që shërben si SIPËRFAQE mbetet sipërfaqe:
     `backdrop-filter` nuk hiqet, thjesht turbullon një `Canvas` bosh dhe
     kushton pa dhënë. Të dyja tokenat kthehen te fjalët e sistemit, dhe
     gjithçka që i lexon e merr ndreqjen pa u prekur.

     `body.theme-dark` duhet emëruar bashkë me `:root`: e deklaron vetë
     `--border`-in te trupi, pra një zëvendësim vetëm te `:root` s'do ta arrinte
     kurrë asgjë brenda tij. */
  :root,
  body.theme-dark {
    --glass: Canvas;
    --border: CanvasText;
    --border-strong: CanvasText;
  }

  /* --- Sipërfaqet me xham ----------------------------------------------- */
  .app-sidebar, .app-topbar, .bottom-nav, .navbar,
  .dropdown-menu, .toast, .glass-card, .cmdk, .bulk-bar,
  .bi-report .export-bar, .bi-report .alarm-panel,
  .bi-report .drill-bar, .bi-report .xf-bar {
    background: Canvas;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }

  /* Kutitë që rrinë MBI faqen kërkojnë buzë. Pa gradient dhe pa hije, një menu
     mbi një tabelë s'ka ku të fillojë e ku të mbarojë. Shellet e ngjitura
     (shiriti, ana, navigimi) nuk e marrin: ato kanë tashmë nga një buzë të
     vetme anësore, dhe një kornizë e plotë do t'ua zhvendoste përmbajtjen. */
  .dropdown-menu, .toast, .glass-card, .cmdk, .bulk-bar,
  .bi-report .export-bar, .bi-report .alarm-panel,
  .bi-report .drill-bar, .bi-report .xf-bar {
    border: 1px solid CanvasText;
  }

  /* Perdet: një perde që s'errëson dot duhet të mbulojë. Përndryshe dialogu
     lexohet si pjesë e faqes poshtë tij. */
  .cmdk-backdrop, .sheet-backdrop, .bi-focus-backdrop {
    background: Canvas;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }

  /* --- Dekori -------------------------------------------------------------
     Aurora dhe rrjeta e heroit janë gradientë: regjimi i zbraz vetë, por i
     lëmë kutitë bosh pa punë. `.hero-guilloche` është `url()`, dhe URL-të NUK
     i prek regjimi — ajo do të mbetej vijë e bardhë mbi sipërfaqe të sheshtë,
     prandaj fshihet te blloku i vet, aty ku rri edhe arsyeja. */
  .hero-aurora,
  .auth-visual::after { display: none; }

  /* Cepi me tavolinën te faqet e brendshme rri me të njëjtin kusht si rozeta,
     dhe për të njëjtën arsye të kundërt: regjimi i zëvendëson NGJYRAT, kurse
     figurat e sfondit — një gradient brenda një maske është pikërisht kjo — i
     lë të paprekura. Pra ai vizatim do të mbetej, dhe mbi një sipërfaqe të
     sheshtë do të lexohej si vija nën fjalë, jo si dekor. */
  body::after { display: none; }

  /* Tri pamjet e kryefaqes bien për të njëjtën arsye si dy skenat: `url()` nuk
     e prek regjimi, pra vizatimet do të mbeteshin ashtu siç janë, të vetmet
     sipërfaqe të pikturuara në një faqe që sapo i mori të gjitha ngjyrat e veta
     nga sistemi. Kutia mbetet — legjenda poshtë saj e thotë figurën me fjalë,
     dhe pikërisht ajo është ç'i mbetet dikujt që nuk e sheh dot. */
  .land-shot { background-image: none; }

  /* Dera. E njëjta arsye si te hyrja (`.app-content:has(.auth-hero)` më lart):
     ngjyra e faqes janë dy gradientë, dhe gradienti është figurë sfondi — pra
     regjimi nuk e prek. Do të mbetej ashtu, dhe mbi të teksti do të merrte
     ngjyrën e sistemit: e bardhë mbi indigo ose e zezë mbi indigo, të dyja të
     zgjedhura nga askush.

     Butoni i cepit është xham: pa `Canvas` poshtë tij, `backdrop-filter` do të
     turbullonte një sipërfaqe bosh dhe do ta linte pa buzë — një fjalë që noton
     mbi faqe, pikërisht e vetmja që duhet gjetur këtu. */
  .app-content:has(.door) { background: none; }
  .door-go {
    background: Canvas;
    border: 1px solid CanvasText;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }

  /* Teksti i pikturuar me gradient. Shih pikën 2 lart: pa këtë rregull këto
     fjalë nuk zbehen — ikin. `-webkit-text-fill-color` duhet i emëruar veç,
     sepse te `.text-gradient` është ai që e mban tejdukshmërinë, jo `color`. */
  .text-gradient,
  .error-code {
    background: none;
    -webkit-text-fill-color: CanvasText;
    color: CanvasText;
    animation: none;
  }

  /* --- Fokusi -------------------------------------------------------------
     `Highlight` është ngjyra që vetë njeriu e ka zgjedhur për «këtu jam». */
  :where(a, button, .btn, .form-control, .form-select, .form-check-input,
         [tabindex]:not([tabindex="-1"])):focus-visible {
    outline: 2px solid Highlight;
    outline-offset: 2px;
  }

  /* Të tetë ata të pikës 1. `outline` nuk hiqet nga regjimi, dhe këtu vijnë pas
     tyre te skedari me të njëjtën specifikë — pra fitojnë pa `!important`.

     Radha e tyre nuk është e njëjtë: katër e mbajnë shenjën mbi vetveten, dy ia
     japin elementit motër që është pjesa e dukshme e kontrollit, dhe dy e ngrenë
     te kutia rreth fushës — sepse vetë fusha e ka hequr unazën me `outline: none`
     dhe emri i saj e kalon `:where()`-in me zero specifikë. Përgjigjja duhet të
     zërë pikërisht atë element që e mbante hijen, jo një më lart a më poshtë. */
  .collapse-card:focus-visible,
  .acc-picker-toggle:focus-visible,
  .acc-chosen-chip:focus-visible,
  th.sortable:focus-visible,
  .acc-day input:focus-visible + span,
  .yoy-toggle input:focus-visible + .yoy-track,
  .tm-search:focus-within,
  .tm-sidebar-search:focus-within {
    outline: 2px solid Highlight;
    outline-offset: 2px;
  }

  /* --- Statuset -----------------------------------------------------------
     Këtu ngjyra hiqet, pra pesë gjendje bëhen pesë pika njësoj. Dallimi kalon
     te forma: i mbushur, me vija, me pika, i zbrazët. Pika rritet nga .6rem në
     .85rem sepse një kufi 2px me vija nën atë madhësi lexohet si njollë.

     Preken vetëm bartësit ku ngjyra është I TËRË mesazhi. Aty ku pranë rri
     ikona dhe fjala — banderolat e afateve, `.check-card-*` — ngjyra ishte
     përsëritje edhe më parë, dhe s'ka çfarë t'i shtohet. */
  .tax-dot, .cal-swatch {
    width: .85rem;
    height: .85rem;
    background: Canvas;
    border: 2px solid CanvasText;
  }
  .tax-dot.state-late,   .cal-swatch.state-now      { background: CanvasText; }
  .tax-dot.state-soon,   .cal-swatch.state-soon     { border-style: dashed; }
  .tax-dot.state-ahead,  .cal-swatch.state-upcoming { border-style: dotted; }
  .tax-dot.state-done,   .cal-swatch.state-today    { background: Highlight; }
  .cal-swatch.state-past { background: GrayText; }
  /* «Urgjent» rri mes «vonuar» dhe «së shpejti»: i mbushur si i pari, por me
     buzë të dyfishtë, që të mos jenë të dy e njëjta pikë e plotë. */
  .tax-dot.state-urgent { background: CanvasText; border-style: double; }

  /* Mosha e borxhit është shkallë, jo grup — sa më i vjetër, aq më e rëndë
     buza. Kufiri shkruhet te vetë shkalla e jo te `.age-dot`, sepse të njëjtat
     klasa i vë JS-i edhe mbi segmentet e shiritit, që s'e kanë atë bazë. */
  .age-1 { background: Canvas;     border: 2px dotted CanvasText; }
  .age-2 { background: Canvas;     border: 2px dashed CanvasText; }
  .age-3 { background: Canvas;     border: 2px solid  CanvasText; }
  .age-4 { background: CanvasText; border: 2px solid  CanvasText; }

  /* Prania te ekipi ka dy gjendje, pra mjafton mbushur kundrejt zbrazët. */
  .tm-dot    { background: Canvas; border: 2px solid CanvasText; }
  .tm-dot.on { background: Highlight; }
}

@media (prefers-contrast: more) {
  /* Këtu ngjyrat mbeten tonat: kërkohet vetëm më shumë ndarje mes tyre. Zero
     hex i ri — çdo vlerë vjen nga një token që ekziston tashmë në të dyja temat.

     `--faint` është toni më i zbehtë i sistemit dhe pikërisht ai bie i pari; e
     zë `--muted`, një shkallë më tutje nga sfondi në të dyja temat (i errët në
     të ndritshmen, i çelët në të errëtën). Kufiri kalon te `--border-strong`:
     .10 → .16 alfa në temën e ndritshme, .15 → .26 në të errëtën. */
  :root,
  body.theme-dark {
    --faint: var(--muted);
    --border: var(--border-strong);
    --glass: var(--surface);
  }

  /* Përkthyeshmëria bie. Një sipërfaqe që e lë faqen të duket nëpër të është
     pikërisht ajo që ia ul kontrastin tekstit mbi të — dhe këtu është kërkuar
     e kundërta. */
  .app-sidebar, .app-topbar, .bottom-nav, .navbar,
  .dropdown-menu, .toast, .glass-card, .cmdk, .bulk-bar,
  .bi-report .export-bar, .bi-report .alarm-panel,
  .bi-report .drill-bar, .bi-report .xf-bar {
    background: var(--surface);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }

  /* Një buzë 1px me alfa lexohet si hije, jo si kufi. Dyfishohet aty ku ndan
     përmbajtje nga përmbajtje. */
  .card, .table-card, .stat-card, .bi-card,
  .form-control, .form-select, .dropdown-menu, .toast {
    border-width: 2px;
  }
}

}  /* @layer utilities */

