# PRD 5.3 — Light/Dark mode (comutator tema persistat) **Stare**: inchis > Proces complet: `docs/ROADMAP.md` §5. Contract RAR (sursa de adevar): `docs/api-rar-contract.md`. > Starea trece: `draft → aprobat → in-executie → verify-pass → inchis` (actualizata de lead). ## 1. Obiectiv Dashboard-ul web e azi **doar dark** (paleta fixa in `:root`). Adaugam o tema **light** si un **comutator in header** care persista alegerea utilizatorului. Service-urile care vin din Visual FoxPro / soft propriu lucreaza des in birouri luminoase si pe monitoare unde dark-mode obositor sau greu de citit la videoproiector — un toggle light/dark e o cerinta de ergonomie de baza (Etapa 5). CSS-ul **e deja pe variabile** (`--bg`, `--card`, `--ink`, `--muted`, `--line`, `--ok`, `--warn`, `--err`, `--accent` in `base.html`). Tema light = un bloc `[data-theme="light"]` care **suprascrie aceleasi variabile** cu o paleta deschisa. Efort mic, zero logica de domeniu, zero backend. **Invariant de design (motivul cheie):** comutarea nu trebuie sa **palpaie** (FOUC — flash of unstyled / wrong-theme content). Tema se aplica **inainte de primul paint** printr-un script inline mic in `
`, care citeste preferinta din `localStorage` si seteaza `data-theme` pe `` sincron, inainte ca `` sa randeze. Fara asta, fiecare incarcare de pagina ar clipi dark→light. ## 2. Non-Goals (anti scope-creep) - **NU backend / cookie / ruta noua.** Persistenta = `localStorage` pur client-side (roadmap zice "cookie/localStorage" — alegem localStorage: zero suprafata server + anti-FOUC prin scriptul din ``). Nu se atinge `routes.py`, `auth.py`, sesiunea, baza de date. - **NU redesign de paleta dark.** Tema dark ramane **identica la octet** cu cea de azi (default pastrat); adaugam doar varianta light + un toggle. Nicio culoare dark existenta nu se schimba. - **NU teme multiple / personalizate / culoare de accent reglabila.** Doar doua: `dark` (default) si `light`. - **NU atinge worker, masina de stari, idempotenta, mapping, schema, validation.py, API.** Strict `app/web/templates/base.html` (+ eventual un test de template). - **NU restilizeaza fragmentele HTMX.** Toate fragmentele (`_*.html`) mostenesc variabilele din `base.html` — comuta automat cu tema. (Conditie: zero culori hardcodate care sa nu adapteze — vezi US-001 pentru suprafetele care azi au fundal hardcodat.) ## 3. Stories atomice > Ambele stories ating **acelasi fisier** (`base.html`) → **secventiale**, un singur worker (sau > lead direct, livrabila mica — ROADMAP §5.5). NU se paralelizeaza (regula fisier-comun §5.5). ### US-001: Tema light (paleta + suprafete theme-aware) **Ca** utilizator al dashboard-ului **vreau** o paleta light corecta si lizibila **pentru ca** sa pot folosi gateway-ul confortabil in birou luminos / la videoproiector, fara contrast slab sau zone care raman intunecate. - **Depinde de**: — - **Fisiere**: `app/web/templates/base.html` (bloc CSS `[data-theme="light"]` + conversia suprafetelor cu fundal hardcodat la variabile), `tests/test_tema.py` (~2 fisiere) - **Test intai (RED)**: `tests/test_tema.py` — - `test_paleta_light_definita` — HTML-ul `GET /login` (sau dashboard) contine un selector `[data-theme="light"]` care redefineste `--bg`, `--card`, `--ink`, `--muted`, `--line`. - `test_dark_ramane_default` — `:root` contine inca paleta dark exacta (`--bg:#0f1115`, `--card:#181b22`, `--ink:#e6e9ef`) → default neschimbat. - `test_suprafete_fara_fundal_hardcodat` — fundalurile de stare (banner eroare/warn, flash) NU mai folosesc literal hex dark fix (`#241a1a`, `#201c0f`, `#16241c`) ci variabile/`color-mix` ce adapteaza la tema (asertie pe absenta literalilor in `