<!-- /autoplan restore point: ~/.gstack/projects/romfast-rar-autopass/docs-prd-5.16-5.17-design-tiers-autoplan-restore-20260628-212525.md -->
# PRD 5.16 — Tipografie uniforma (fonturi standard web) + bug-fix formular editare + E2E

**Stare**: draft

> Proces complet: `docs/ROADMAP.md` §5. Contract RAR (sursa de adevar): `docs/api-rar-contract.md`.
> Sistemul de design: `DESIGN.md` + `app/web/templates/base.html`. Landing: `app/web/templates/landing.html`.
> Mockup tipografie (REFERINTA VIZUALA): `docs/mockups/prd-5.16-fonturi-system-stack.html`
>   — system font stack, scala uniforma, DOT pentru RAR online, denumiri in picker, buton Renunta.
> Mockup header + login + selector tema (REFERINTA VIZUALA): `docs/mockups/prd-5.16-header-login-tema.html`
>   — antet branded "ROMFAST AUTOPASS" + nume service, pagina /login profesionala, selector tema stil landing.
> Mockup dashboard COMPLET (REFERINTA VIZUALA): `docs/mockups/prd-5.16-dashboard.html`
>   — pagina Acasa cu antet branded, selector tema landing, strip DOT, contoare SEPARATE
>     (Total/Luna/Azi/In coada/De corectat), lista slim, modal editare cu picker+denumiri+Renunta.
> Mockup dashboard MOBIL 390px (REFERINTA VIZUALA): `docs/mockups/prd-5.16-dashboard-mobil.html`
>   — Acasa + editare full-screen pe telefon: antet compact (tema doar iconita <=560px ca pe landing),
>     contoare separate (Total prominent + 2x2), strip DOT cu text pe 2 linii, butoane full-width.
> Mockup WIZARD import + editare/corectie (REFERINTA VIZUALA): `docs/mockups/prd-5.16-import-wizard.html`
>   — cei 4 pasi (1 Incarca · 2 Potriveste coloanele · 3 Verifica · 4 Confirma), import colapsat,
>     preview cu stari (Cod RAR lipsa/Date incomplete/Duplicat/Deja trimis) + editare/corectie rand
>     inline (picker cod+denumire, + adauga operatie, salveaza regula, Renunta).
> Continua si finalizeaza propagarea de design inceputa in 5.15 (`docs/prd/prd-5.15-propagare-design-dashboard-editare.md`).
> Starea trece: `draft -> aprobat -> in-executie -> verify-pass -> inchis`.

## 1. Introducere

PRD 5.15 a propagat sistemul de design al landing-ului in aplicatie (carduri-contor, lista slim,
formular slim cu chips, 7 teme). La folosire reala userul a constatat ca rezultatul NU respecta inca
claritatea exemplelor din landing: **fonturile sunt prea mici si neuniforme** intre pagini si
formulare, **cardurile au textul inghesuit**, iar in formularul de editare au ramas patru
**bug-uri functionale** care fac corectia trimiterilor frustranta sau imposibila. In plus userul vrea
**fonturi standard web** (fara fisiere de font instalate), aceleasi in aplicatie SI in landing.

5.16 finalizeaza propagarea de design pe doua planuri:
1. **Tipografie**: o singura scala uniforma, lizibila, mai mare, pe fonturi de sistem (system font
   stack) — atat in aplicatie cat si in landing — eliminand IBM Plex self-hostat.
2. **Bug-fix + ergonomie formular editare**: cele 4 probleme reale + indicatorul RAR online ca DOT.

Plus o trecere E2E in browser pe toate paginile, conforme cu `DESIGN.md` si spiritul landing-ului.

## 2. Obiective

### Obiectiv principal
Aplicatia sa para acelasi produs ca landing-ul comercial: tipografie clara, uniforma, lizibila, fara
text inghesuit; iar formularul de editare sa functioneze corect (salveaza, se inchide, permite
adaugarea de operatii cu denumiri citibile).

### Obiective secundare
- Zero fisiere de font in runtime (gateway intern) — fonturi 100% native.
- Sursa unica de adevar pentru dimensiunile de text (tokeni de scala), nu valori ad-hoc per template.
- Indicator de stare RAR online consistent cu landing-ul (dot pulsant, nu bifa).

### Metrici de succes
- Un esantion de 5 pagini (Acasa, Trimiteri, detaliu/editare, Mapari, Integrare) folosesc ACELEASI
  dimensiuni de text pentru acelasi rol (label, body, cifra) — verificabil prin tokeni.
- Cele 4 bug-uri din §3 (US-004..US-007) reproductibile inainte, ne-reproductibile dupa (teste lock).
- E2E browser: zero overflow orizontal, fonturi native incarcate (fara request la `/static/fonts/`).

## 3. User Stories

> Backend + UI pentru acelasi comportament = stories separate. `base.html` e fisier FIERBINTE
> (serializat — un singur autor pe val). Toate UI verificate pe un esantion de teme (o luminoasa +
> una intunecata) si pe 390/1280.

### US-001: Fonturi standard web (system font stack) — eliminam IBM Plex self-hostat
**Ca** operator **vreau** fonturi web standard, lizibile, fara sa instalez nimic **pentru ca** vreau
text clar si uniform, fara dependente de fisiere de font.

- **Depinde de**: —
- **Fisiere**: `app/web/templates/base.html` (`--font-ui`/`--font-mono` + `font-family` body),
  `app/web/templates/landing.html` (sterge cele 9 `@font-face` IBM Plex + `font:... 'IBM Plex Sans'`),
  `DESIGN.md` (sectiunea Tipografie rescrisa), `tests/test_tema.py` / `tests/test_web_responsive.py`
  (~4 fisiere)
- **Test intai (RED)**: `test_font_stack_system_in_base`, `test_landing_fara_font_face_ibm_plex`,
  `test_zero_referinte_static_fonts`
- **Acceptance criteria**:
  - [ ] `base.html` defineste doi tokeni sursa-de-adevar in `:root`:
        `--font-ui: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;`
        si `--font-mono: ui-monospace, "SF Mono", "Cascadia Code", "Segoe UI Mono", "Roboto Mono",
        Menlo, Consolas, monospace;`. `body` foloseste `var(--font-ui)`; codurile/VIN folosesc
        `var(--font-mono)` prin clasa existenta (`.camp-mono`/`.slim-vin` etc.).
  - [ ] `landing.html`: cele 9 reguli `@font-face` IBM Plex Sans/Mono ELIMINATE; toate aparitiile
        `font: ... 'IBM Plex Sans'` / `'IBM Plex Mono'` inlocuite cu `var(--font-ui)` / `var(--font-mono)`
        (sau un fallback explicit identic cu app-ul). Landing si app folosesc ACELASI stack.
  - [ ] **Zero referinte la `/static/fonts/`** raman in template-uri (grep negativ in test). Fisierele
        woff2 din `app/web/static/fonts/` pot ramane pe disc (curatare = follow-up optional, non-blocant),
        dar nu mai sunt referite.
  - [ ] Diacriticele romanesti (ă/â/î/ș/ț) se randeaza corect pe stack-ul nativ (acoperite de fonturile
        de sistem — verificat vizual in E2E).
  - [ ] `DESIGN.md` §Tipografie rescrisa: motiveaza system font stack (zero dependente runtime,
        nativ pe fiecare OS), documenteaza cele doua stive, noteaza tradeoff-ul (aspect usor diferit
        Windows/Mac/Linux) ca decizie acceptata de user.
- **Verificare E2E**: DevTools Network pe `/` si pe landing — niciun request catre `/static/fonts/`;
  text lizibil pe Windows (Segoe UI) verificat de operator la deploy.

### US-002: Scala tipografica uniforma (tokeni `--fs-*`) + carduri aerisite
**Ca** operator **vreau** dimensiuni de text uniforme si mai mari, fara text inghesuit **pentru ca**
azi fonturile sunt ad-hoc (10/11/13px) si difera de la pagina la pagina.

- **Depinde de**: US-001 (acelasi val, `base.html`)
- **Fisiere**: `app/web/templates/base.html` (tokeni `--fs-*` + clasele slim/contor/camp consumandu-i),
  `DESIGN.md`, `tests/test_web_responsive.py` (~3 fisiere)
- **Test intai (RED)**: `test_tokeni_scala_fs_definiti`, `test_componente_slim_folosesc_fs_tokeni`,
  `test_fara_font_size_sub_12px_in_componente_noi`
- **Acceptance criteria**:
  - [ ] `base.html` defineste o scala unica in `:root` (sursa de adevar): `--fs-xs:12px`, `--fs-sm:13.5px`,
        `--fs-base:15px`, `--fs-md:16px`, `--fs-lg:18px`, `--fs-xl:20px`, `--fs-2xl:28px`, `--fs-3xl:34px`
        (+ `--lh-tight`/`--lh-body`). Valorile finale pot fi ajustate la executie, dar DEFINITE ca tokeni.
        Referinta vizuala: `docs/mockups/prd-5.16-fonturi-system-stack.html`.
  - [ ] Componentele slim din 5.15 (`.contor-cifra`, `.contor-label`, `.contor-sub`, `.slim-vin`,
        `.slim-meta`, `.camp-slim label/input`, `.chip`, `.op-row-name`, pill-uri) sunt RECABLATE pe
        tokenii `--fs-*` (NU mai au px hardcodat sub 12px). Minim crestere fata de azi:
        label-uri 11→13.5px, sub-linii 10→12px, cifra contor 22→28px, input 13→16px.
  - [ ] **Carduri aerisite**: `.contor-card` si randurile slim cresc padding-ul (contor ~18px,
        rand slim ~14px) ca textul mai mare sa nu para inghesuit; fara overflow pe 390px.
  - [ ] **Contoare separate (NU inghesuite)**: statisticile "Trimise" se afiseaza ca **carduri
        distincte** — `Total`, `Luna asta`, `Azi` fiecare cu eticheta proprie, pe langa `In coada` si
        `De corectat` (5 in total). NU se mai inghesuie `luna`/`azi` ca sub-linie mono sub cifra "Total"
        (asa cum era in 5.15/D4). Pe **desktop**: 5 carduri pe un rand, FARA titlu/eticheta de grup
        deasupra (minimalist — userul nu vrea subtitlu de sectiune). Referinta:
        `docs/mockups/prd-5.16-dashboard.html`.
        **Nota**: REVIZUIESTE framing-ul D4/US-003 din 5.15 (cifra mare all-time + sub-linie `luna · azi`).
        Sursa de timp/bucketare RO ramane cea din 5.15/US-003 (`sent_today`/`sent_month`, timp local RO
        E7); doar PREZENTAREA se schimba.
  - [ ] **Mobil: contoare COMPACTE (doar numere)**: pe 390px contoarele NU mai sunt 5 carduri mari, ci
        o **bara compacta de statistici pe un singur rand** — cifra mare + eticheta scurta (`Total`/`Lună`/
        `Azi`/`Coadă`/`Corectat`), separatoare subtiri, inaltime mica, fara a ocupa jumatate de ecran.
        Referinta: `docs/mockups/prd-5.16-dashboard-mobil.html`.
  - [ ] **Ordine dashboard (compact, minimalist)**: pe Acasa, ordinea verticala e **(1) carduri-contor
        → (2) import colapsat → (3) tab-uri Trimiteri/Mapari → (4) lista**. Indicatorul RAR online NU mai
        ocupa o banda in corp — sta ca dot in antet (US-003). Tab-urile Trimiteri/Mapari stau imediat
        deasupra listei (nu sub antet). Atat pe desktop cat si pe mobil.
  - [ ] **Fara duplicare / fara subtitlu de sectiune**: numele service-ului apare DOAR in antet
        (US-010), NU se mai repeta intr-un meta "Service Auto … · data" deasupra listei. Se ELIMINA
        titlul de sectiune "Trimiteri RAR AUTOPASS" + linia meta de sub el (ocupau spatiu pe desktop si
        mobil) — lista incepe direct sub tab-uri/filtre.
  - [ ] `body` are `font-size:var(--fs-base)` si `line-height:var(--lh-body)` (azi implicit de browser).
  - [ ] Zero regresie vizuala pe componentele existente non-slim (`.card/.pill/.act/.tabel-trimiteri`):
        crestem unde e prea mic, fara a sparge layout-ul tabelului desktop.
  - [ ] `DESIGN.md` §Tipografie + §Componente slim actualizat cu scala in tokeni.
- **Verificare E2E**: browser pe Acasa + Trimiteri + editare, esantion de teme + 390/1280 — text mai
  mare, uniform, fara inghesuire, fara overflow.

### US-003: RAR online — dot compact in antet (nu banda) + in meniul burger; banda DOAR cand e blocat
**Ca** operator **vreau** ca "RAR online" sa fie un dot mic in antet (cu data/ora pe hover) si in meniul
burger, NU o banda care ocupa un rand intreg **pentru ca** cand totul e ok nu vreau sa-mi fure spatiu —
dar cand e blocat trebuie sa fie imposibil de ratat.

- **Depinde de**: US-002, US-011 (antet/selector tema)
- **Fisiere**: `app/web/templates/base.html` (antet + meniu burger), `app/web/templates/_status.html`
  (banda doar pe blocat + dot), `app/web/routes.py` (context sanatate in layout, nu doar fragment),
  `DESIGN.md`, `tests/test_web_status.py`, `tests/test_web_status_fragment.py` (~6 fisiere)
- **Test intai (RED)**: `test_rar_dot_in_antet_ok`, `test_rar_in_meniu_burger`,
  `test_banda_apare_doar_cand_blocat`, `test_dot_title_datetime`, `test_blocat_text_accesibil`
- **Acceptance criteria**:
  - [ ] **Stare OK (online)**: indicatorul RAR e un **dot/pill compact in antet**, langa selectorul de
        tema (ex. dot verde + "RAR online"), stilat ca pill-ul "Live" din landing (`landing.html:117`).
        Data/ora ultimei autentificari RAR apare pe **`title`/hover** (`title="Ultima autentificare RAR:
        28.06.2026 09:41"`), NU pe un rand separat. NU mai exista banda full-width in corpul paginii in
        starea OK. Referinta: `docs/mockups/prd-5.16-dashboard.html`.
  - [ ] **Si in meniul burger**: starea RAR (dot + "RAR online" + ora ultimei autentificari) apare ca
        prima intrare in meniul de cont, pentru cazul in care antetul e ingust (mobil) — vezi
        `docs/mockups/prd-5.16-dashboard-mobil.html`.
  - [ ] **Stare BLOCAT (worker oprit / RAR inaccesibil)**: ATUNCI (si numai atunci) reapare **banda
        rosie full-width**, loud, in corp ("Blocat: RAR inaccesibil — declaratiile NU pleaca"), iar
        dot-ul din antet devine rosu. Invariant zero-silent-failures (D6/5.15) PASTRAT: blocajul e
        imposibil de ratat; doar starea OK se comprima la un dot.
  - [ ] **Accesibilitate**: sensul NU depinde de culoare — `title`/`aria-label` pe dot ("RAR online" /
        "RAR blocat") + textul explicit al benzii pe blocat poarta sensul pentru screen-reader/daltonisti.
        Se inlocuieste glifa bifa/X (`✓/✗`) cu dot + text.
  - [ ] `DESIGN.md` §Header & branding + §Componente actualizat: dot de stare in antet + banda doar pe
        blocat documentate.
- **Verificare E2E**: browser pe `/` — worker viu → dot verde in antet (+ in meniu), fara banda, ora pe
  hover; worker oprit → dot rosu + banda rosie in corp; screen-reader confirma sensul fara culoare.

### US-004: Bug — picker prestatii arata DENUMIREA, nu doar codul
**Ca** operator **vreau** sa vad denumirea operatiei/codului RAR cand aleg din picker **pentru ca**
nu imi dau seama ce e doar din cod (ex. "REV2").

- **Depinde de**: — (independent; UI-only in template chips)
- **Fisiere**: `app/web/templates/_chips_prestatii.html`, `tests/test_web_mapare_din_chip.py` SAU
  `tests/test_web_corectie_prestatii.py` (~2 fisiere)
- **Test intai (RED)**: `test_picker_flat_arata_cod_si_denumire`, `test_picker_op_arata_denumire`
- **Acceptance criteria**:
  - [ ] In **modul plat** (corectie pura, fara `op_service`), picker-ul `chips_add_cod_flat`
        (`_chips_prestatii.html:146-148`) afiseaza `{{ cod }} — {{ nume_prestatie }}` pentru fiecare
        optiune (azi arata DOAR `cod_prestatie`). Acelasi format ca modul operatii (`:101`).
  - [ ] Optiunea placeholder ramane lizibila ("+ cod RAR" sau "— alege cod RAR —"); latimea
        selectului creste cat sa incapa denumirea fara a sparge layout-ul chips.
  - [ ] Consistenta: ORICE select de cod RAR din formularul de editare (plat + per-operatie) arata
        cod + denumire. Niciun loc nu mai arata cod gol.
- **Verificare E2E**: editez o trimitere fara cod (corectie pura) → deschid picker-ul → optiunile arata
  "FRN1 — Sistem de franare", nu doar "FRN1".

### US-005: Bug — adaugare de operatii/coduri RAR suplimentare la editare
**Ca** operator **vreau** sa pot adauga ALTE operatii/coduri RAR pe o trimitere cu probleme **pentru ca**
azi, cand trimiterea are deja operatii, nu pot adauga un cod RAR in plus.

- **Depinde de**: US-004 (acelasi template)
- **Fisiere**: `app/web/templates/_chips_prestatii.html`, `app/web/routes.py` (`post_form_chips`,
  `routes.py:1867-1957` — actiune noua `add_extra`), `tests/test_web_corectie_prestatii.py` (~3 fisiere)
- **Test intai (RED)**: `test_adauga_cod_extra_in_mod_operatii`, `test_extra_cod_persistat_la_salvare`,
  `test_extra_cod_validat_nomenclator`
- **Acceptance criteria**:
  - [ ] In **modul operatii** (`_has_ops`), sub lista de operatii apare un control "**+ Adauga alta
        operatie / cod RAR**" (picker cod+denumire + buton), care adauga un chip de cod RAR liber
        (fara `op_service`) la lista — pe langa codurile per-operatie existente. Azi acest control
        exista DOAR in modul plat; il aducem si in modul operatii.
  - [ ] `post_form_chips` primeste o actiune noua (`chips_action=add_extra`) care valideaza codul fata
        de nomenclator (invariant ORA-12899) si il adauga ca item `{cod_prestatie, cod_op_service:"",
        denumire:""}`. Re-randeaza partial-ul chips.
  - [ ] Codul extra adaugat SE PERSISTA la salvare: e emis ca hidden `cod_prestatie` (paralel cu
        `chip_op_service`/`chip_denumire` goale) si cules de `post_corectie_trimitere`
        (`routes.py:1334 getlist`). Lista finala `prestatii` contine si codurile per-operatie SI
        codurile extra (dedup per-item E4 din 5.15 pastrat).
  - [ ] Stergere simetrica: chip-ul extra are `×` (reuse `remove`/`remove_flat`).
- **Verificare E2E**: editez o trimitere cu o operatie mapata → adaug un cod RAR extra → salvez →
  `prestatii` contine ambele coduri (verificat in detaliu / payload).

### US-006: Bug — salvarea codului ales pe o trimitere fara cod nu facea nimic
**Ca** operator **vreau** ca atunci cand aleg un cod RAR si salvez, sa se aplice **pentru ca** azi,
la o trimitere care nu avea cod operatie, aleg codul dar la salvare nu se intampla nimic.

- **Depinde de**: US-004, US-005
- **Fisiere**: `app/web/templates/_chips_prestatii.html`, `app/web/routes.py`
  (`post_corectie_trimitere` / `post_form_chips`), `tests/test_web_corectie_prestatii.py` (~3 fisiere)
- **Test intai (RED)**: `test_cod_ales_in_picker_se_salveaza_fara_buton_add`,
  `test_salvare_fara_chip_explicit_nu_e_no_op`
- **Acceptance criteria**:
  - [ ] **Reproducere (RED)**: o trimitere fara `cod_prestatie` (mod plat, ZERO chips). Userul alege
        un cod in picker-ul `chips_add_cod_flat` si apasa direct "Salveaza" (FARA sa apese "+" intai).
        Azi: `getlist("cod_prestatie")` e gol → submission ramane `needs_mapping` → "nu se intampla
        nimic". Cauza confirmata: selectul `chips_add_cod_flat` NU e citit de `post_corectie_trimitere`.
  - [ ] **Fix**: `post_corectie_trimitere` (si `/repune`, `/editeaza`) culeg si codul nesubmis din
        picker (`chips_add_cod_flat` + `chips_add_cod_{i}` per-operatie) ca un add implicit la salvare,
        SAU formularul promoveaza automat selectia in curs intr-un chip inainte de submit (progressive
        enhancement JS + fallback server). Rezultat: codul ales se aplica chiar fara click pe "+".
        Decizie de implementare (la executie): preferinta pe calea SERVER (citeste picker-ul la submit),
        ca sa functioneze si fara JS — aliniat cu E6 server-driven din 5.15.
  - [ ] Codul ales e validat fata de nomenclator; cod necunoscut → mesaj, nu trimitere raw.
  - [ ] Nu rupe fluxul existent "+ apoi Salveaza" (ramane valid; nu se dubleaza codul — dedup per-item).
- **Verificare E2E**: editez o trimitere needs_mapping fara cod → aleg un cod in picker → Salveaza
  (fara "+") → submission devine `queued` cu codul ales.

### US-007: Bug — butonul Renunta/Anuleaza inchide formularul
**Ca** operator **vreau** ca butonul Renunta sa inchida modalul **pentru ca** azi nu il inchide si
raman blocat in formular.

- **Depinde de**: —
- **Fisiere**: `app/web/templates/base.html` (handler `data-modal-close`, `base.html:1131-1133`),
  `tests/test_web_corectie.py` SAU un test JS/markup nou (~2 fisiere)
- **Test intai (RED)**: `test_anuleaza_are_data_modal_close`,
  `test_modal_close_pe_element_interior` (markup: butonul Anuleaza contine `<span>`/icon → tinta de
  click e copilul)
- **Acceptance criteria**:
  - [ ] **Cauza confirmata**: handler-ul `overlay.addEventListener('click', ...)` (`base.html:1132`)
        verifica `e.target.hasAttribute('data-modal-close')`. Butonul Anuleaza/Renunta
        (`_form_editare.html:106`) are atributul pe `<button>`, dar contine `<span class="act-tx">` +
        un SVG icon → la click pe text/icon, `e.target` e copilul fara atribut → `close()` NU se apeleaza.
        (X-ul `.modal-close` merge doar fiindca e `&times;` fara copii.)
  - [ ] **Fix**: handler-ul foloseste `e.target.closest('[data-modal-close]')` in loc de
        `hasAttribute` direct, ca un click pe orice descendent al unui element cu `data-modal-close`
        sa inchida modalul. Pastreaza inchiderea pe backdrop + Esc.
  - [ ] Butonul de Renunta e prezent in AMBELE modale unde se editeaza (detaliu + preview import):
        verifica `with_cancel` / eticheta. Daca in modalul de detaliu nu exista buton de inchidere
        in form, se adauga unul (text "Renunta"), nu doar X-ul din colt.
  - [ ] Focus-ul revine logic dupa inchidere (comportament `close()` existent pastrat).
- **Verificare E2E**: deschid editarea → apas Renunta (pe text si pe icon) → modalul se inchide,
  focus revine pe rand; Esc si backdrop inchid in continuare.

### US-008: Landing — aliniere copy si fonturi cu aplicatia (fara redesign)
**Ca** vizitator **vreau** ca landing-ul sa foloseasca aceleasi fonturi ca aplicatia **pentru ca**
userul a cerut explicit fonturi web uniforme intre cele doua.

- **Depinde de**: US-001
- **Fisiere**: `app/web/templates/landing.html`, `tests/test_web_*` (~2 fisiere)
- **Test intai (RED)**: `test_landing_foloseste_font_stack_app`
- **Acceptance criteria**:
  - [ ] Landing-ul foloseste `var(--font-ui)`/`var(--font-mono)` (sau acelasi literal de stack) —
        consecinta directa a US-001, fara redesign de layout.
  - [ ] Mockup-ul intern din landing (cardul "prestatie noua", `landing.html:155-171`) — care arata
        "Confirma Vin" ca al doilea camp VIN — ramane DOAR ilustrativ; NU il aliniem la formularul real
        (VIN unic) in acest PRD (non-goal: redesign landing). Notat ca debt vizual minor.
  - [ ] Fara alte modificari de continut in 5.16 (copy-ul de plan/limita 60 e in PRD-ul de tipuri-cont).
- **Verificare E2E**: landing in browser — fonturi identice cu app, fara request la `/static/fonts/`.

### US-010: Antet branded "ROMFAST AUTOPASS" + nume service + /login profesional
**Ca** operator **vreau** un antet profesional cu "ROMFAST AUTOPASS" si numele service-ului meu, si o
pagina /login pe masura **pentru ca** azi antetul arata generic ("Gateway RAR AUTOPASS") iar /login e
schelet — nu inspira incredere.

- **Depinde de**: US-001, US-002 (fonturi + scala)
- **Fisiere**: `app/web/templates/base.html` (header), `app/web/templates/login.html`,
  `app/web/auth_routes.py` (`_base_ctx`/`login_get` — paseaza `account_name` cand e logat),
  `app/web/routes.py` (context layout cu `account_name`), `DESIGN.md` (§Header & branding),
  `tests/test_web_responsive.py` / un test de header (~5 fisiere)
- **Test intai (RED)**: `test_titlu_romfast_autopass`, `test_header_arata_nume_service_logat`,
  `test_login_branded_nu_schelet`
- **Acceptance criteria**:
  - [ ] Titlul din antet devine **"ROMFAST AUTOPASS"** (azi "Gateway RAR AUTOPASS",
        `base.html:769`), pastrand badge-ul de mediu (test/prod) si link-ul la `/`.
  - [ ] Cand userul e autentificat, sub titlu apare **numele service-ului auto** (din `accounts.name`,
        ex. "Service auto: Service Auto Vâlcea SRL"), pasat in context (`account_name`). Pe paginile
        neautentificate (login/signup) NU apare (nu exista cont logat).
  - [ ] **Gate strict pe `is_authenticated` (NU pe /login/signup)**: dot-ul RAR online (US-003), numele
        service-ului, badge-ul de plan/tier (US-010 + 5.17) si meniul burger se randeaza DOAR cand
        `is_authenticated` e adevarat. Pe `/login` si `/signup` antetul e **minimal**: logo ROMFAST +
        titlu "ROMFAST AUTOPASS" + selectorul de tema — atat. Fara RAR, fara nume service, fara tier,
        fara meniu de cont (utilizatorul nu e logat). Referinta: `docs/mockups/prd-5.16-header-login-tema.html`
        (blocurile "LOGAT" vs "/login NEAUTENTIFICAT").
  - [ ] **/login profesional, nu schelet**: pagina capata un layout brandeit pe doua coloane (panou
        stanga cu logo ROMFAST + "ROMFAST AUTOPASS" + tagline conformitate/criptare; dreapta formularul
        de autentificare existent), folosind tokenii de fonturi/scala (US-001/002) si paleta temelor.
        Functionalitatea formularului (`POST /login`, CSRF, link signup/parola) ramane neschimbata.
        Referinta: `docs/mockups/prd-5.16-header-login-tema.html`. Degradeaza la o coloana pe mobil.
  - [ ] `<title>` actualizat coerent ("ROMFAST AUTOPASS" in loc de "Gateway RAR AUTOPASS").
  - [ ] **Tip cont (plan) in titlu**: langa titlu/badge-ul de mediu apare un **badge de plan**
        (`Gratuit`/`Standard`/`Pro`/`Premium`), citit din `accounts.tier` (model definit in PRD 5.17;
        in 5.16 e doar AFISARE — daca 5.17 nu e livrat inca, badge-ul citeste `tier` cu fallback
        `Gratuit`). Referinta: `docs/mockups/prd-5.16-dashboard.html` / `...-mobil.html`.
  - [ ] **Meniul burger — structura cu separatoare + plan + RAR**: meniul de cont primeste, in ordine:
        (a) starea RAR online (US-003) + (b) linia "Plan: <tier> [· trial N zile]", apoi intrarile de
        navigare **grupate cu separatoare (`<hr>`) intre sectiuni**: [Trimiteri · Mapari] | [Nomenclator]
        | [Cont · Integrare · Jurnal] | [Iesi din cont]. Userul a cerut explicit separatoare clare intre
        sectiuni. (Detaliile planului/trial vin din 5.17; in 5.16 = afisare.)
  - [ ] `DESIGN.md` §Header & branding actualizat (titlu nou + nume service sub titlu + badge plan;
        meniu burger cu separatoare).
- **Verificare E2E**: browser logat → antet "ROMFAST AUTOPASS" + nume service + badge plan; meniul
  burger arata RAR + plan + sectiuni separate; `/login` brandeit pe desktop + o coloana pe 390px.

### US-011: Selector de tema stil landing (icon + eticheta temei curente)
**Ca** operator **vreau** ca selectorul de teme din aplicatie sa arate ca cel din landing **pentru ca**
azi e doar o iconita (☀) fara eticheta si nu stiu pe ce tema sunt.

- **Depinde de**: US-002 (acelasi val pe `base.html`)
- **Fisiere**: `app/web/templates/base.html` (butonul `#tema-toggle` + scriptul ciclic),
  `DESIGN.md` (§Selector de tema), `tests/test_tema.py` (~3 fisiere)
- **Test intai (RED)**: `test_selector_tema_are_eticheta`, `test_eticheta_reflecta_tema_curenta`
- **Acceptance criteria**:
  - [ ] Butonul de tema devine un **pill cu icon + eticheta** (numele temei curente vizibil, ex.
        "Grafit"), ca pe landing (`landing.html:78-81`), nu doar iconita. Reuse structura `THEMES`
        existenta (DRY E2 din 5.15) pentru a deriva eticheta — fara a doua sursa de adevar.
  - [ ] Ciclarea prin toate temele (5.15) ramane; eticheta se actualizeaza la fiecare click; aria-label
        si `#tema-live` (anunt screen-reader) reflecta tema curenta.
  - [ ] Pe mobil (390px), daca spatiul e strans, eticheta se poate ascunde (ca pe landing,
        `#theme-label{display:none}` la <=560px) pastrand iconita — degradare eleganta, fara overflow.
  - [ ] Stil aliniat header-ului (US-010): bordura `--line`, hover `--accent`, fonturi system.
  - [ ] `DESIGN.md` §Selector de tema actualizat (pill icon+eticheta, nu doar iconita).
- **Verificare E2E**: browser → butonul arata "Grafit"/"Hârtie" etc.; click cicleaza si eticheta se
  schimba; pe 390px iconita ramane fara a sparge antetul.

### US-012: Landing — butonul "Autentificare" duce la /login
**Ca** vizitator **vreau** ca "Autentificare" sa ma duca la pagina reala de login **pentru ca** azi
deschide formularul de inregistrare din landing (tab login), nu pagina dedicata.

- **Depinde de**: US-010 (pagina /login brandeita e tinta)
- **Fisiere**: `app/web/templates/landing.html` (butonul `data-act="auth" data-tab="login"` +
  scriptul de auth), `tests/test_web_*` (~2 fisiere)
- **Test intai (RED)**: `test_landing_autentificare_link_login`
- **Acceptance criteria**:
  - [ ] Butonul "Autentificare" din header-ul landing (`landing.html:82`) devine un link/redirect real
        catre **`/login`** (un `<a href="/login">` stilat ca butonul actual, sau handler care face
        `location.href='/login'`), NU mai deschide modalul de auth din landing pe tab-ul login.
  - [ ] "Creează cont" ramane neschimbat (deschide modalul de register din landing SAU duce la `/signup`
        — pastram comportamentul actual; userul a cerut sa schimbam DOAR Autentificare).
  - [ ] Daca dupa scoaterea tab-ului login modalul de auth ramane doar pe register, codul mort de
        comutare login/register din landing se curata (fara a rupe register). Non-blocant daca modalul
        ramane bi-tab; minim: butonul Autentificare nu mai deschide modalul.
  - [ ] Link-ul "Autentifică-te" din interiorul modalului de register (`landing.html:370`) — decizie la
        executie: poate ramane (tab intern) sau redirect la `/login`; implicit pastrat.
- **Verificare E2E**: click pe "Autentificare" in landing → navigheaza la `/login` (pagina brandeita
  US-010), nu deschide modalul.

### US-013: Wizard import + preview/corectie aliniate la designul 5.16 (import colapsat)
**Ca** operator **vreau** ca paginile de import (cei 4 pasi + verificarea) sa arate la fel de
profesional ca restul aplicatiei **pentru ca** acolo petrec efectiv timpul, iar azi importul ocupa
spatiu pe Acasa chiar cand nu il folosesc.

- **Depinde de**: US-002 (scala/tokeni), US-004/005/006 (chips in editarea din preview)
- **Fisiere**: `app/web/templates/_stepper.html`, `app/web/templates/_upload.html`,
  `app/web/templates/_mapcoloane.html`, `app/web/templates/_preview_import.html`,
  `app/web/templates/_preview_rand.html`, `app/web/templates/_acasa.html` (import colapsat),
  `tests/test_web_import_stepper.py` / `tests/test_web_responsive.py` (~6 fisiere)
- **Test intai (RED)**: `test_import_colapsat_implicit`, `test_wizard_foloseste_scala_tokeni`,
  `test_preview_stari_pill_dot`
- **Acceptance criteria**:
  - [ ] **Import colapsat pe Acasa**: zona de upload nu mai ocupa spatiu implicit — devine o bara slim
        ("+ Importa fisier (XLSX / CSV)") care se extinde la click (`<details>` nativ, fara JS custom),
        ca lista de trimiteri sa fie primul lucru vizibil. Referinta: `docs/mockups/prd-5.16-dashboard.html`.
  - [ ] **Cei 4 pasi** (`_stepper.html`, `_upload.html`, `_mapcoloane.html`, `_preview_import.html`)
        consuma tokenii de fonturi/scala (US-001/002): stepper slim lizibil, tabel de mapare cu nume
        coloana + exemplu + select "camp RAR", preview cu pill-uri de stare folosind **dot** (consistent
        cu lista slim si stripul) — fara hex hardcodat, pe toate temele. Referinta:
        `docs/mockups/prd-5.16-import-wizard.html`.
  - [ ] **Editare/corectie rand in preview** foloseste ACELASI `_form_editare.html`/`_chips_prestatii.html`
        ca modalul de detaliu — deci mostenesc automat fix-urile US-004 (denumiri in picker), US-005
        (adaugare operatie), US-006 (salvare cod ales) si US-007 (Renunta inchide). Nu se duplica logica.
  - [ ] Pill-urile de stare din preview pastreaza maparea din `labels.py` (`STARI_PREVIEW`:
        "Cod RAR lipsa"/"Date incomplete"/"Verifica valori"/"Deja trimis"/"Duplicat in fisier") — zero
        etichete noi; doar stilul (dot + scala) se aliniaza.
  - [ ] Responsive: pe mobil stepperul ramane forma colapsata "Pasul N din 4" (5.13) si tabelele de
        mapare/preview nu produc overflow orizontal.
- **Verificare E2E**: import xlsx → pas 1..4 in design 5.16; pe Acasa importul e colapsat implicit;
  in preview, un rand needs_mapping editat cu picker (denumiri) + Renunta → comportament identic cu
  modalul de detaliu.

### US-009: E2E browser final pe toate paginile + regresie
**Ca** dezvoltator **vreau** o trecere E2E completa **pentru ca** 5.16 atinge `base.html` (fierbinte)
si formularul de editare, si nu vreau regresii.

- **Depinde de**: US-002, US-003, US-006, US-007, US-008, US-010, US-011, US-012, US-013
- **Fisiere**: `tests/test_web_responsive.py`, `tests/test_tema.py`, `tests/test_web_corectie.py`
  (~3 fisiere)
- **Test intai (RED)**: completare scenarii lipsa (scala pe toate componentele; bug-urile lock).
- **Acceptance criteria**:
  - [ ] `python3 -m pytest -q -m "not live"` verde (fara regresii fata de baseline 5.15).
  - [ ] E2E Playwright (sau headless screenshot ca fallback in sandbox) pe 390/1280, pe o tema
        intunecata (grafit) + una luminoasa (hartie): Acasa (antet "ROMFAST AUTOPASS" + nume service,
        selector tema cu eticheta, strip dot + contoare aerisite), Trimiteri (lista slim text mai mare),
        editare (denumiri in picker, adaugare operatie extra, salvare cod ales, Renunta inchide),
        wizard import (4 pasi + import colapsat pe Acasa + preview cu pill-uri dot + corectie rand),
        `/login` brandeit, Mapari, Integrare, landing (Autentificare → /login) — fara overflow orizontal,
        fonturi native (zero `/static/fonts/`), text uniform.
  - [ ] Raport VERIFY documenteaza cele 4 bug-uri ca reproduse-inainte / reparate-dupa.
- **Verificare E2E**: rulare completa documentata in Raportul VERIFY.

## 4. Cerinte functionale (rezumat)
1. [REQ-001] Toate template-urile folosesc `var(--font-ui)`/`var(--font-mono)` (system stack); zero
   `@font-face` si zero referinte `/static/fonts/`.
2. [REQ-002] Toate dimensiunile de text din componentele de design folosesc tokenii `--fs-*`.
3. [REQ-003] Indicatorul RAR online = dot colorat + text (nu bifa), accesibil fara culoare.
4. [REQ-004] Picker-ele de cod RAR arata cod + denumire peste tot.
5. [REQ-005] Se pot adauga operatii/coduri RAR suplimentare la editare, in modul operatii si plat.
6. [REQ-006] Codul ales in picker se aplica la salvare chiar si fara pasul intermediar "+".
7. [REQ-007] Butonul Renunta inchide modalul (click pe orice descendent).
8. [REQ-008] Antet branded "ROMFAST AUTOPASS" + nume service logat; `/login` profesional (nu schelet).
9. [REQ-009] Selector de tema stil landing (icon + eticheta temei curente).
10. [REQ-010] Butonul "Autentificare" din landing duce la `/login`.

## 5. Non-Goals (anti scope-creep)
- Fara redesign al layout-ului landing (doar fonturi); mockup-ul intern "Confirma Vin" ramane ilustrativ.
- Fara modificari pe backend-ul de trimitere (worker, masina de stari, idempotenta-logica `build_key`,
  reconciliere, contract RAR). US-005/006 ating DOAR handler-ele de editare/`form-chips`, nu logica de
  trimitere.
- Fara migrare de schema.
- Fara tipuri de cont / planuri / limite — sunt in PRD 5.17 (separat, la cererea userului).
- Fara stergerea fizica a fisierelor woff2 din `static/fonts/` (curatare optionala, follow-up).
- Fara a schimba cele 7 teme sau tokenii cromatici (5.15 ramane); 5.16 atinge doar tipografia.

## 6. Consideratii tehnice
- **Stack**: FastAPI + Jinja2 + HTMX, CSS pe variabile in `base.html` (fara build de CSS).
- **Patterns de urmat**: tokeni CSS sursa-unica (ca `THEMES`/`--card2`/`--line2` din 5.15);
  server-driven HTMX (E6); `e.target.closest` pentru delegare de evenimente (deja folosit la
  `data-modal-retry`, `base.html:1166`).
- **Fisier fierbinte**: `base.html` atins de US-001/002/003/007 → un singur autor pe val, serializat.
- **Riscuri**:
  - System font stack arata diferit pe Windows/Mac/Linux — acceptat de user (tradeoff "no install").
    Mitigare: scala in px (nu em-uri dependente de font) ramane uniforma indiferent de familie.
  - Diacritice RO pe fonturi de sistem — toate stack-urile tinta le acopera; verificat in E2E.
  - US-006 (save no-op) e un bug de cale dubla picker/chip — riscul e sa "reparam" doar JS-ul si sa
    ramana rupt fara JS. Mitigare: fix pe calea server (citeste picker-ul la submit).
  - `base.html` fierbinte + 7 teme = suprafata de test; recablarea pe `--fs-*` trebuie sa nu strice
    tabelul desktop. Mitigare: US-002 AC de non-regresie + test ancorat pe sentinel.

## 7. Consideratii UI/UX
- Referinta vizuala obligatorie: `docs/mockups/prd-5.16-fonturi-system-stack.html`.
- Stari: strip verde (online) / rosu (blocat); picker gol vs cu denumiri; chip extra adaugabil/stergibil;
  modal cu Renunta functional.
- Tinte 44px pe mobil pastrate; contrast AA in toate temele (text mai mare ajuta lizibilitatea).

## 8. Open Questions
- [ ] Valorile exacte ale scalei `--fs-*` (12/13.5/15/16/28…) — propuse in mockup; de validat la
      executie pe ecran real, in limita "mai mare + uniform".
- [ ] Dot-ul RAR online: puls discret (animatie) DA/NU — implicit DA (ca "Live" din landing), dezactivabil
      daca deranjeaza.
- [ ] Curatarea fizica a `static/fonts/*.woff2` — in 5.16 sau follow-up separat? (implicit: follow-up).

## 9. Valuri de executie

```
Val 1: [US-001] -> [US-002] -> [US-003] -> [US-010] -> [US-011] -> [US-007]
                                           base.html: fonturi, scala, dot, antet branded,
                                           selector tema, fix Renunta — SECVENTIAL (autor unic base.html) ||
       [US-008]                            landing fonturi (dupa US-001 fixeaza stack-ul)
Val 2: [US-004] -> [US-005] -> [US-006]    chips: denumiri, adaugare extra, save-no-op —
                                           SECVENTIAL (acelasi _chips_prestatii.html + routes)
Val 3: [US-012]                            landing Autentificare → /login (dupa US-010 livreaza /login)
Val 4: [US-009]                            E2E final + regresie (dupa toate)
```

> Regula autor-unic: `base.html` (US-001/002/003/007/010/011) + `login.html`/`auth_routes.py` (US-010)
> si `routes.py`/`_chips_prestatii.html` (US-004/005/006) sunt fisiere fierbinti — serializate, nu
> paralele. US-010 atinge si `login.html` (separat), poate merge in paralel cu chips-urile din Val 2 daca
> autorul base.html e liber.

---

> Acest PRD nu a fost inca trecut prin `/plan-ceo-review` / `/plan-eng-review`. Recomandat inainte de
> executie (atinge `base.html` fierbinte + 4 bug-uri reale in calea de editare).

---

# /autoplan — Revizuire automata (CEO -> Design -> Eng)

> Pipeline rulat non-interactiv. Fiecare AskUserQuestion intermediar a fost AUTO-DECIS prin cele 6
> principii (completitudine, boil-lakes, pragmatic, DRY, explicit>clever, bias-spre-actiune) si logat
> in Decision Audit Trail (jos). Doua porti raman pentru confirmarea umana: (1) premisele Fazei 1,
> (2) User Challenges (unde ambele modele cer schimbarea directiei userului). Acestea sunt RAPORTATE,
> nu decise.

## FAZA 1 — CEO Review (Strategie & Scop)

Mod (override autoplan): **SELECTIVE EXPANSION** — iteratie pe un sistem existent (5.15 livrat);
tin scopul ca baseline si semnalez expansiuni ca optiuni.

### 0A. Premise Challenge (de confirmat de user)

**Premisa P1 (bug-fix)** — „cele 4 bug-uri sunt reale si fac corectia frustranta/imposibila".
VERIFICAT in cod, toate 4 confirmate:
- US-007 (Renunta nu inchide): `base.html:1132` foloseste `e.target.hasAttribute('data-modal-close')`
  pe handler-ul de overlay; butonul Anuleaza (`_form_editare.html:106`) are atributul pe `<button>`
  dar contine `<span class="act-tx">`+SVG, deci click pe text/icon → `e.target` = copilul fara atribut
  → `close()` nu se apeleaza. X-ul (`base.html:822`) merge doar fiindca `&times;` nu are copii. **Cauza
  exacta a planului e corecta.**
- US-006 (save no-op): `post_corectie_trimitere` (`routes.py:1359`) citeste `form.getlist("cod_prestatie")`;
  selectul `chips_add_cod_flat` (`_chips_prestatii.html:142`) NU se numeste `cod_prestatie` si nu e citit
  → la 0 chips, lista e goala → ramane `needs_mapping`. **Confirmat.**
- US-004 (picker fara denumire): modul plat (`_chips_prestatii.html:147`) afiseaza doar `{{ n.cod_prestatie }}`;
  modul operatii (`:101`) afiseaza `cod — nume`. **Confirmat asimetria.**
- US-005 (fara adaugare extra in mod operatii): controlul „+ cod nou" exista doar in ramura `else`
  (mod plat, `:139-161`); `post_form_chips` (`routes.py:1925`) trateaza add/add_flat/remove/remove_flat,
  fara `add_extra`. **Confirmat lipsa.**
P1 = ACCEPTATA (verificata in cod). Premisa solida; jumatatea de bug-fix e clar problema corecta.

**Premisa P2 (tipografie) — CONTESTATA partial.** Planul afirma „vreau fonturi standard web (fara
fisiere de font instalate)" si „zero dependente runtime". Dar IBM Plex e DEJA self-hostat ca woff2
local cu subset latin-ext (`base.html:42-103`, `landing.html:10-18`) — fara CDN, fara dependenta de
retea la runtime, fara „instalare" de catre operator (serverul serveste woff2 din acelasi origine).
Deci „dependenta" eliminata = ~8-10 fisiere statice deja in repo (~200-400KB), nu o dependenta reala.
In plus, obiectivul declarat e UNIFORMITATEA, dar system-ui se randeaza DIFERIT pe Windows/Mac/Linux
(planul insusi listeaza asta ca risc acceptat) — IBM Plex self-hostat e MAI uniform cross-OS decat
system-ui. `DESIGN.md` a ales explicit IBM Plex pentru identitatea „software serios". Premisa P2 e deci
fragila: castigul real al userului („fonturi prea mici si neuniforme") se obtine din US-002 (scala in
tokeni) FARA a scoate familia. **Vezi User Challenge #1.** P2 acceptata ca sa avansez, dar marcata
pentru confirmare umana.

**Premisa P3 (badge plan citit din `accounts.tier`)** — US-010 afiseaza un badge de plan din 5.17.
In 5.16 e doar afisare cu fallback `Gratuit`. ACCEPTATA, dar creeaza un cuplaj soft 5.16->5.17 (vezi
Sec 1).

### 0B. Existing Code Leverage (ce exista deja)
- **Scala/tokeni**: `base.html` are deja `--card2`/`--line2` (5.15) ca model de „token sursa-unica" —
  US-002 extinde acelasi pattern cu `--fs-*`. Reuse, nu reinventare. OK.
- **Selector tema**: landing are deja `THEMES`/`#theme-label` (`landing.html:78-82`); US-011 deriva
  eticheta din structura `THEMES` existenta (E2 DRY din 5.15). Reuse confirmat.
- **Pill „Live"**: `landing.html:117` exista deja ca model pentru dot-ul RAR (US-003). Reuse.
- **`e.target.closest`**: deja folosit la `data-modal-retry` (`base.html:1166`) — US-007 reuse exact
  acelasi pattern. DRY, explicit.
- **Chips server-driven** (`_chips_prestatii.html` + `post_form_chips`): US-004/005/006 extind handler-ul
  existent, nu construiesc un al doilea. Modalul de editare partajat (`_form_editare.html`) e refolosit
  in preview import (US-013) → fix-urile bug se propaga automat. Reuse arhitectural confirmat.
- **Strip sanatate** (`_status.html:22-41`): US-003 il muta din corp in antet ca dot; pastreaza
  invariantul D6 (banda doar pe blocat). Refolosire, nu rescriere.

### 0C. Dream State
```
  CURENT (5.15)                    ACEST PLAN (5.16)               IDEAL 12 luni
  Dashboard propagat, dar      ->  Tipografie uniforma + 4 bug  -> Produs care „pare ca landing-ul":
  fonturi mici/ad-hoc,             reparate, antet branded,        identitate ROMFAST consecventa,
  corectie rupta (save no-op,      /login profesional, dot RAR,    corectie fluida fara frustrare,
  Renunta blocat), antet generic   wizard aliniat                  tipuri cont (5.17), self-serve
```
Delta: planul muta produsul clar spre ideal pe axa „incredere/corectie". Pe axa „identitate vizuala",
trecerea la system-ui e o miscare LATERALA/inapoi (pierde caracter tipografic) — vezi User Challenge #1.

### 0C-bis. Implementation Alternatives (tipografie — punctul de decizie cheie)
```
APPROACH A: Pastreaza IBM Plex self-hostat, repara DOAR scala (US-002 tokeni)   [minimal viable]
  Effort: S (human ~0.5 zi / CC ~20min)   Risk: Low
  Pros: rezolva durerea reala (marime/uniformitate); pastreaza identitatea DESIGN.md; uniform cross-OS;
        zero risc de diacritice; respecta regula de design „no default font stacks".
  Cons: pastreaza ~10 woff2 in repo (cost real ~zero, deja servite local).
  Reuses: tot stack-ul de fonturi existent + pattern token --card2/--line2.

APPROACH B: System font stack, elimina IBM Plex (alegerea planului)             [planul curent]
  Effort: M (human ~1 zi / CC ~30min)   Risk: Med
  Pros: zero fisiere font; nimic de incarcat.
  Cons: pierde identitatea tipografica (DESIGN.md a ales IBM Plex intentionat); randare DIFERITA per OS
        (contrazice obiectivul „uniform"); incalca regula de design slop #11 (system-ui ca font primar);
        ~40+ literale `'IBM Plex Sans'` fara fallback in landing.html ar cadea pe serif default daca sunt
        ratate; testul propus grep-uie doar `/static/fonts/`, nu literalele de familie.

APPROACH C: Hibrid — pastreaza IBM Plex, dar adauga stack system explicit ca fallback peste tot
  Effort: S-M   Risk: Low
  Pros: degradare eleganta pe masini fara font; pastreaza identitatea cand fontul e prezent.
  Cons: nu satisface cererea literala „fara fisiere de font".
```
**RECOMANDARE (principiul P5 explicit + P1 completitudine + regula design „real typeface"):** APPROACH A.
Livreaza durerea reala a userului (uniformitate) cu cel mai mic risc si pastreaza identitatea. DAR userul
a cerut EXPLICIT system fonts — deci aceasta e **User Challenge #1**, nu o auto-decizie. Daca userul
confirma B, planul e tehnic fezabil; vezi gap-urile de test din Faza 3.

### 0E. Temporal Interrogation
- HOUR 1 (fundatii): valorile exacte `--fs-*` (Open Question din plan) — propuse in mockup, de validat
  pe ecran. Decizie: porneste din mockup, ajusteaza la executie. (auto-decis)
- HOUR 2-3 (US-006 server path): implementatorul va ezita JS-vs-server. Planul deja fixeaza „server"
  (citeste picker-ul la submit). Bun — fara ambiguitate.
- HOUR 4-5 (US-001 integrare): ratarea unui literal `'IBM Plex Sans'` fara fallback in landing → text
  pe serif default. Trebuie un test grep pe literale (vezi Faza 3, gap test).
- HOUR 6+ (polish): diacritice RO pe system stack — de verificat in E2E (planul o cere).

### 0F. Mode confirmation
SELECTIVE EXPANSION confirmat. Nicio expansiune noua adaugata in scop (planul e deja complet pentru
durerea declarata); o singura expansiune marcata: **test grep pe literale de font** (P2 boil-lakes,
in blast radius, <1 zi) — recomandata sa intre in US-001 (vezi Faza 3 T-uri).

### CLAUDE SUBAGENT (CEO — independenta strategica)
[Vocea mea independenta, formata inainte de a citi Codex]
1. **Problema corecta?** Jumatatea bug-fix: DA, fara echivoc — corectia e rupta pe cazul cel mai
   frecvent (rand needs_mapping cu 0 coduri: US-006 face save = no-op, US-007 te blocheaza in modal).
   Pentru un produs de conformitate legala unde corectiile TREBUIE sa plece, un formular de corectie rupt
   e risc direct de conformitate. Valoare mare, efort mic. Aceasta jumatate ar trebui sa fie PRIORITARA
   (hotfix), separat de tipografie.
2. **Tipografia** e jumatatea discutabila. Contradictie interna: obiectivul e „uniform", dar system-ui
   randeaza diferit per OS; IBM Plex self-hostat e mai uniform. Premisa „fara dependente" e deja
   satisfacuta (woff2 local, zero CDN). Castigul real (marime/uniformitate) vine din US-002, nu din
   stergerea familiei. Risc de regret la 6 luni: app-ul isi pierde identitatea si arata „ca orice admin
   AI-generat" (chiar regula de slop #11 din canonul de design semnaleaza system-ui ca font primar).
3. **Risc competitiv:** minim — gateway intern, useri captivi (obligatie legala). Identitatea conteaza
   pentru INCREDERE, nu pentru competitie.
4. **Calibrare scop:** 12 stories, 6 ating `base.html` fierbinte serializat. Mare pentru un PRD „de
   polish", dar valurile separa corect bug-fix (Val 2, independent) de tipografie (Val 1). Recomand
   livrarea Val 2 intai.
Verdict CEO independent: bug-fix = aproba si prioritizeaza; tipografie = contesteaza directia
(pastreaza IBM Plex, repara doar scala) → User Challenge #1.

### Error & Rescue Registry (Faza 1 — relevanta limitata, PRD UI)
| Codepath | Ce poate esua | Tratat? | User vede |
|---|---|---|---|
| `post_form_chips` add/add_extra | cod necunoscut in nomenclator | DA — `SELECT 1 FROM nomenclator_rar`, ignora daca lipseste | chip nu apare (silent) ← vezi GAP-1 |
| `post_corectie_trimitere` cod nevalid | cod necunoscut | DA — re-randeaza `_trimitere_detaliu` cu mesaj | „Cod RAR necunoscut: X" |
| US-006 citire picker la submit | picker gol + 0 chips | trebuie sa ramana needs_mapping cu mesaj | „Lipseste inca un cod RAR" |
GAP-1: `post_form_chips` la cod invalid/neselectat IGNORA silentios (nu re-randeaza un mesaj). Pentru
add_extra (US-005) ar trebui macar un semnal vizual daca selectul e gol. Minor (P3). Logat.

### Failure Modes Registry (Faza 1)
| Codepath | Failure mode | Tratat? | Test? | User vede | Logat? |
|---|---|---|---|---|---|
| modal close (US-007) | click pe copil fara atribut | NU (azi) → DA dupa fix `closest` | test lock propus | ramane blocat → inchide | n/a |
| save cod ales (US-006) | picker necitit la submit | NU (azi) → DA dupa fix server | test lock propus | no-op → queued | n/a |
| literal font ratat (US-001) | `'IBM Plex Sans'` fara fallback | risc dupa stergere @font-face | grep doar /static/fonts ← GAP | text pe serif | nu |
Niciun CRITICAL GAP cu impact tacut+silentios+netestabil pe backend (PRD nu atinge worker/trimitere).
GAP de test pe literale font = important, mutat in Faza 3.

### Sectiuni 1-11 (CEO) — sinteza
- **Sec 1 Arhitectura:** cuplaj nou 5.16->5.17 (badge `accounts.tier`). Mitigat de fallback `Gratuit`.
  `base.html` fierbinte: regula autor-unic respectata in plan. Fara SPOF nou. OK.
- **Sec 2 Erori:** vezi registrul; GAP-1 (silent pe add_extra cod invalid) logat P3.
- **Sec 3 Securitate:** US-005 `add_extra` valideaza fata de nomenclator (invariant ORA-12899 pastrat) —
  bine, NU trimite cod raw. CSRF mostenit din `post_form_chips`/`post_corectie` existente. Scope pe cont
  pastrat. Niciun vector nou. Examinat: input cod (validat), niciun endpoint nou nedeprotejat.
- **Sec 4 Data/UX edge:** dublu-click pe „+", navigare in timpul editarii — modalul cu focus-trap exista;
  US-006 server-path acopera „salveaza fara +". Edge: lista chips foarte lunga (overflow picker) — minor.
- **Sec 5 Calitate:** DRY bun (reuse `_form_editare`/`closest`/THEMES). Risc: ~40+ literale font in
  landing → recablare manuala mare (vezi Faza 3).
- **Sec 6 Teste:** 4 teste-lock cerute (bug-uri reproduse inainte/reparate dupa) — corect. Lipseste grep
  pe literale font. E2E cerut.
- **Sec 7 Perf:** stergerea woff2 reduce ~10 request-uri statice (neglijabil, acelasi origine). Fara N+1
  (PRD UI). OK.
- **Sec 8 Observabilitate:** US-003 pastreaza vizibilitatea blocaj (banda rosie pe blocat). OK.
- **Sec 9 Deploy:** fara migrare schema (non-goal). woff2 raman pe disc (non-goal stergere). Reversibil
  prin git revert. Risc redus.
- **Sec 10 Trajectorie:** Reversibilitate 5/5 (UI/template). Datorie: daca system-ui se dovedeste prost,
  re-adaugarea IBM Plex e usoara (woff2 raman pe disc). Path 5.17 (tier) pregatit de badge.
- **Sec 11 Design:** vezi Faza 2.

### NOT in scope (CEO)
- Backend trimitere (worker/masina stari/idempotenta/contract RAR) — non-goal explicit, corect.
- Stergerea fizica woff2 — follow-up, corect (reduce riscul de revert).
- Tipuri cont/planuri — 5.17 separat.
- Redesign layout landing — doar fonturi.

### Dream-state delta
Planul livreaza ~90% din axa „incredere/corectie" (bug-fix + antet + login). Pe axa „identitate
vizuala", User Challenge #1 determina daca planul avanseaza (pastreaza IBM Plex) sau lateral (system-ui).

### CEO Completion Summary
```
| Mod                  | SELECTIVE EXPANSION                          |
| Sec 1 Arch           | 1 (cuplaj soft 5.16->5.17, mitigat)         |
| Sec 2 Erori          | 1 GAP minor (silent add_extra) P3           |
| Sec 3 Securitate     | 0 (validare nomenclator pastrata)           |
| Sec 4 Data/UX        | 0 critice (edge minore)                     |
| Sec 5 Calitate       | 1 (recablare literale font landing)         |
| Sec 6 Teste          | 1 GAP (grep literale font)                  |
| Sec 7-10             | 0 critice                                   |
| Sec 11 Design        | -> Faza 2                                    |
| User Challenges      | 1 (system-ui vs IBM Plex)                   |
| Reversibilitate      | 5/5                                          |
```

### CODEX SAYS (CEO) — [codex-unavailable: usage limit, reset 2026-07-18]
Codex CLI e autentificat dar a atins plafonul de utilizare (eroare „usage limit" la toate apelurile).
Degradare per matricea autoplan -> **[subagent-only]** pe toate fazele. Consensul de mai jos foloseste
DOAR vocea Claude independenta; semnalele single-voice nu se ridica la „cross-model consensus".

### CEO DUAL VOICES — CONSENSUS TABLE
```
  Dimensiune                          Claude   Codex   Consensus
  ─────────────────────────────────── ──────── ─────── ──────────
  1. Premise valide?                  PARTIAL  N/A     N/A (P2 fragila — single-voice flag)
  2. Problema corecta?                DA(bug)  N/A     N/A (bug-fix solid; tipografie contestata)
  3. Calibrare scop corecta?          DA       N/A     N/A (valuri separa corect)
  4. Alternative explorate suficient? NU       N/A     N/A (A vs B nedeliberat in plan)
  5. Riscuri competitive acoperite?   DA       N/A     N/A (intern, useri captivi)
  6. Traiectorie 6-luni sanatoasa?    PARTIAL  N/A     N/A (risc identitate tipografica)
```
CONFIRMED=ambele de acord. Cu Codex indisponibil, niciun rand nu e CONFIRMED; semnalele raman
single-voice. Finding critic single-voice ridicat oricum: **User Challenge #1 (system-ui vs IBM Plex)**.

> **FAZA 1 COMPLETA.** Codex: indisponibil (usage limit). Claude subagent: 1 User Challenge + 4 gap-uri
> minore (1 test, 1 cuplaj soft, 1 silent add_extra, 1 recablare literale). Trec la Faza 2 (Design).

## FAZA 2 — Design Review (7 passes)

UI scope = DA (clar). DESIGN.md exista (calibrez fata de el). 5 mockup-uri HTML exista deja in
`docs/mockups/prd-5.16-*.html` ca referinta vizuala — folosite in locul generarii de mockup-uri noi.
Rating initial design completeness: **7/10** (interactiuni bune + mockup-uri + tokeni; lipsesc cateva
stari de eroare ale picker-ului si exista un conflict de canon tipografic).

### Pass 1 — Information Architecture: 8/10
Planul defineste explicit ce vede userul intai/al doilea/al treilea: ordine verticala Acasa
(1 contoare → 2 import colapsat → 3 tab-uri → 4 lista), dot RAR in antet, banda doar pe blocat. Mockup
confirma. Constraint worship aplicat (import colapsat ca lista sa fie primul lucru). Minor: 5 contoare
pe desktop fara titlu de grup — risc de a parea „mosaic de carduri" (regula App UI „avoid dashboard-card
mosaics"); mitigat de bara compacta pe mobil. **Fara issue blocant.**

### Pass 2 — Interaction State Coverage: 6/10
| Feature | LOADING | EMPTY | ERROR | SUCCESS | PARTIAL |
|---|---|---|---|---|---|
| Dot RAR | n/a | n/a | banda rosie (blocat) | dot verde + ora | n/a |
| Picker cod (US-004/006) | (HTMX submit?) | **GAP** | „cod necunoscut" | chip adaugat | needs_mapping ramane |
| Add operatie extra (US-005) | — | **GAP-1** (silent daca select gol) | cod invalid silent | chip nou | — |
| Modal corectie (US-007) | — | — | „nu s-a putut incarca" (exista) | inchide + focus | — |
**GAP (design):** in mod plat picker-ul e randat doar `{% if nomenclator_rar %}` (`_chips_prestatii.html:140`).
Daca nomenclatorul e gol/neincarcat, un rand `needs_mapping` NU mai are NICIO cale de a adauga cod —
„No items found" tacut. Trebuie o stare empty cu mesaj+actiune (ex. „Nomenclator indisponibil — reincarca").
**GAP-1:** add_extra cu select gol nu da feedback (vezi Faza 1). Recomandare: mesaj inline scurt.

### Pass 3 — User Journey & Emotional Arc: 8/10
Arc clar: frustrare (corectie rupta, text inghesuit) → usurare (Salveaza merge, Renunta inchide, text
lizibil). US-007/006 ataca direct momentele de frustrare maxima. 5-sec visceral (antet branded inspira
incredere), 5-min behavioral (corectie fluida), 5-an (identitate ROMFAST). Bun.

### Pass 4 — AI Slop Risk: 4/10  ← DIMENSIUNEA CRITICA
**[HARD CONFLICT cu canonul de design]** Regula de slop #11: „system-ui sau -apple-system ca font PRIMAR
de display/body — semnalul «am renuntat la tipografie». Alege o familie reala." Regula universala: „No
default font stacks (Inter, Roboto, Arial, system)." US-001 face EXACT asta: inlocuieste o familie reala
(IBM Plex, aleasa intentionat in DESIGN.md pentru caracter ingineresc) cu `system-ui, -apple-system, ...`.
Acesta e cel mai puternic argument de design pentru **User Challenge #1**: pentru un „software serios
pentru o obligatie legala serioasa" (citat DESIGN.md), trecerea la system stack e o pierdere de
identitate, nu un castig. Restul UI-ului NU e slop (fara grid 3-coloane, fara gradient violet, pill-uri
cu un singur accent — bun). Singurul issue major de slop e fontul. **Ridicat ca prim item.**

### Pass 5 — Design System Alignment: 7/10
US-001 rescrie `DESIGN.md §Tipografie` (care azi mandateaza IBM Plex „self-host woff2"). Asta REZOLVA
inconsistenta interna (planul nu lasa DESIGN.md sa contrazica codul) — bine ca e in scop. DAR noua
directie contrazice rationamentul de brand din acelasi DESIGN.md („caracter ingineresc, software serios").
Tokenii `--fs-*` + `--card2`/`--line2` se aliniaza la vocabularul existent (DRY). Mockup intern landing
„Confirma Vin" ramane debt vizual — corect flagat ca non-goal. Pill-uri/dot consistente cu landing.

### Pass 6 — Responsive & Accessibility: 8/10
Solid: 390/1280 specificate per componenta; tinte 44px pastrate; dot RAR poarta sensul prin
`title`/`aria-label` (NU doar culoare — daltonisti), banda blocat cu text explicit pentru screen-reader;
contrast AA in toate temele. Bara compacta pe mobil bine gandita. Minor: pe bara compacta mobil,
„De corectat" (azi link `<a>` catre lista in `_status.html:64`) — de pastrat afordanta de tap; spec
nu confirma ca raman tap-abile. Recomandare: pastreaza tinta tap pe contorul „De corectat" si pe mobil.

### Pass 7 — Unresolved Design Decisions
| Decizie | Daca amanata |
|---|---|
| Valori exacte `--fs-*` | implementatorul ghiceste; mockup da punct de pornire — OK |
| Dot RAR puls DA/NU | implicit DA (ca „Live"); dezactivabil — OK |
| Empty-state picker fara nomenclator | „No items found" tacut → rand needs_mapping nereparabil ← de rezolvat |
| System-ui vs IBM Plex | **User Challenge #1 — neauto-decis** |
Toate (mai putin empty-state picker) sunt deja in §8 Open Questions al planului. Empty-state picker =
adaugat ca finding nou.

### CODEX SAYS (design) — [codex-unavailable: usage limit]
### CLAUDE SUBAGENT (design — independent) — incorporat in pasele de mai sus.

### DESIGN OUTSIDE VOICES — LITMUS SCORECARD
```
  Check                                    Claude  Codex  Consensus
  ─────────────────────────────────────── ─────── ─────── ─────────
  1. Brand unmistakable in first screen?   YES(antet ROMFAST) N/A  single-voice
  2. One strong visual anchor?             YES     N/A    single-voice
  3. Scannable by headlines only?          YES     N/A    single-voice
  4. Each section has one job?             YES     N/A    single-voice
  5. Cards actually necessary?             MOSTLY (5 contoare = risc mosaic) N/A single-voice
  6. Motion improves hierarchy?            YES (dot puls discret) N/A single-voice
  7. Premium without decorative shadows?   PARTIAL (system-ui slabeste premium) N/A single-voice
  Hard rejections triggered:               1 (slop #11: system-ui font primar)  N/A
```

### Design NOT in scope
- Redesign layout landing (doar fonturi) — corect.
- Mockup intern „Confirma Vin" — debt vizual acceptat.

### Design — What already exists (reuse)
DESIGN.md (sistem 7 teme + tokeni), `landing.html` pill „Live"/selector tema, componente slim 5.15,
`_form_editare`/`_chips_prestatii` partajate. Planul reutilizeaza corect.

### DESIGN Completion Summary
```
  Pass 1 (Info Arch)   8/10
  Pass 2 (States)      6/10  (2 GAP: empty-state picker, silent add_extra)
  Pass 3 (Journey)     8/10
  Pass 4 (AI Slop)     4/10  ← font system-ui = hard conflict (User Challenge #1)
  Pass 5 (Design Sys)  7/10
  Pass 6 (Responsive)  8/10  (minor: tap „De corectat" pe mobil)
  Pass 7 (Decisions)   3 in Open Questions + 1 nou (empty-state picker)
  Overall design       7/10 -> 7/10 (deciziile cheie raman la user: font + empty-state)
```

> **FAZA 2 COMPLETA.** Codex: indisponibil. Claude subagent: 1 hard-conflict de font (intareste User
> Challenge #1) + 2 GAP de stare (empty-state picker, silent add_extra) + 1 minor (tap mobil). Trec la
> Faza 3 (Eng).

## FAZA 3 — Eng Review (Arhitectura, Calitate, Teste, Performanta)

### Step 0 — Scope Challenge
PRD UI/template: atinge `base.html` (fierbinte, 6 stories), `_chips_prestatii.html` + `routes.py`
(handlere editare), `landing.html`, `login.html`, `auth_routes.py`, `DESIGN.md`, teste. 12 stories,
dar majoritatea sunt CSS/markup; logica reala doar in US-005/006 (handlere). Complexity check: >8 fisiere,
DAR fara clase/servicii noi, fara infra, fara migrare — e in mod natural „polish + bugfix", nu
overbuild. Scop acceptat ca-i (FULL_REVIEW). Reuse confirmat (Faza 1 0B). Backend trimitere NEATINS.

### Arhitectura — diagrama dependente (componente noi vs existente)
```
                         base.html (FIERBINTE — autor unic, serializat)
   ┌──────────────────────────┬───────────────────┬────────────────────────┐
   │ :root --font-ui/--font-mono│ :root --fs-* scala │ header branded + dot RAR│
   │  (US-001)                 │  (US-002)          │  (US-003/010/011)       │
   └──────────┬────────────────┴─────────┬─────────┴───────────┬────────────┘
              │ consumat de                │ consumat de         │ context din
   ┌──────────▼─────────┐      ┌───────────▼──────────┐  ┌───────▼──────────┐
   │ landing.html       │      │ componente slim 5.15 │  │ routes.py/_status │
   │ (@font-face sterse,│      │ (.contor/.slim/.chip)│  │ (sanatate in layout│
   │  literale->var)    │      │                      │  │  US-003; account_name│
   └────────────────────┘      └──────────────────────┘  │  US-010)+auth_routes│
                                                          └──────────────────┘

   Val 2 (INDEPENDENT de base.html — poate paraleliza):
   _chips_prestatii.html ──> post_form_chips (add_extra, US-005)
            │                       │
            └──> post_corectie_trimitere (citeste picker la submit, US-006; by-index align)
   _form_editare.html ──(mostenit de)──> _preview_import.html (US-013, fix-uri propagate gratis)
```
Cuplaj nou: doar soft 5.16->5.17 (badge `accounts.tier`, fallback `Gratuit`). Fara SPOF, fara endpoint
nou nedeprotejat. Rollback: git revert (UI). Reversibilitate 5/5.

### CLAUDE SUBAGENT (eng — independent) + CODEX SAYS (eng) [codex-unavailable: usage limit]

**E1 (P1) — Test gap: literale de font fara fallback.** US-001 testeaza `grep negativ pe /static/fonts/`.
Dar dupa stergerea `@font-face`, raman ~40+ literale `'IBM Plex Sans'`/`'IBM Plex Mono'` in template-uri
(in special `landing.html`: ex. `:94 font:700 50px/1.06 'IBM Plex Sans'` FARA fallback). Cu `@font-face`
sters, `'IBM Plex Sans'` nematchat + fara fallback → font default browser (frecvent serif/Times), NU
stack-ul de sistem dorit. Testul `/static/fonts/` NU prinde asta. **Fix:** adauga test grep care esueaza
la orice literal `'IBM Plex Sans'`/`'IBM Plex Mono'` ramas FARA `var(--font-*)` sau fara fallback de
sistem in coada. (conf: 9/10 — verificat in `landing.html`.)

**E2 (P2) — US-001 nu enumera stergerea `@font-face` din `base.html`.** AC numeste cele 9 `@font-face`
din `landing.html`, dar `base.html:42-103` are ~8 reguli `@font-face` proprii care refera `/static/fonts/`.
AC „zero /static/fonts/ in template-uri" le CERE sterse, dar proza nu le enumera. **Fix:** US-001 sa
enumere explicit si `base.html` `@font-face` la stergere. (conf: 10/10 — citit `base.html:42-103`.)

**E3 (P2) — US-006 risc de aliniere by-index la merge picker->prestatii.** `post_corectie_trimitere`
(`routes.py:1388`) aliniaza codurile cu itemele `prestatii` PE INDEX. Pickerele per-operatie se numesc
`chips_add_cod_{op_idx}` (index de OPERATIE), nu pozitie de `cod_prestatie`. Cand US-006 citeste pickerul
la submit, serverul trebuie sa mapeze corect op-index→pozitie item, altfel codul ales se ataseaza la
operatia GRESITA. Bucla existenta suporta append corect pentru mod plat (0 chips → item nou), dar modul
operatii cu mai multe pozitii nemapate e riscant. **Fix + test:** alege cod in pickerul operatiei #2,
Salveaza fara „+", asserteaza ca aterizeaza pe op #2, nu pe #1. (conf: 7/10 — citit handler-ul.)

**E4 (P3) — `add_extra` silent la cod invalid/gol** (cross-ref Faza 1 GAP-1, Faza 2 GAP-1). `post_form_chips`
ignora silentios cand selectul e gol sau codul nu e in nomenclator. Pentru `add_extra` adauga un semnal
inline. (conf: 8/10.)

**E5 (P3) — empty-state picker fara nomenclator** (cross-ref Faza 2 GAP). `{% if nomenclator_rar %}`
ascunde pickerul cand nomenclatorul e gol → rand `needs_mapping` nereparabil tacut. Adauga mesaj+actiune.
(conf: 8/10 — citit `_chips_prestatii.html:140`.)

### ENG DUAL VOICES — CONSENSUS TABLE
```
  Dimensiune                          Claude   Codex   Consensus
  ─────────────────────────────────── ──────── ─────── ──────────
  1. Arhitectura sound?               DA       N/A     single-voice (cuplaj soft OK)
  2. Acoperire teste suficienta?      NU       N/A     single-voice (E1 gap font, E3 gap by-index)
  3. Riscuri perf adresate?           DA       N/A     single-voice (UI; -10 req woff2 = pozitiv)
  4. Amenintari securitate acoperite? DA       N/A     single-voice (validare nomenclator pastrata)
  5. Cai de eroare tratate?           PARTIAL  N/A     single-voice (E4/E5 silent states)
  6. Risc deploy gestionabil?         DA       N/A     single-voice (git revert, fara migrare)
```
Codex indisponibil (usage limit) → niciun rand CONFIRMED; toate single-voice.

### Sectiunea 3 (Test Review) — diagrama de acoperire
```
NEW/CHANGED CODEPATHS                                  COVERAGE
[~] base.html fonturi/scala (US-001/002)
  ├── token --font-ui/--font-mono pe body             [GAP→add] test_font_stack_system_in_base
  ├── @font-face sterse (base.html + landing)         [GAP→add] test_zero_referinte_static_fonts
  └── literale 'IBM Plex *' fara fallback              [GAP→E1] test grep literale (LIPSESTE in plan)
[~] base.html modal close (US-007)
  └── closest('[data-modal-close]')                   [GAP→add] test_anuleaza_are_data_modal_close +
                                                                test_modal_close_pe_element_interior (LOCK)
[~] _chips_prestatii.html picker (US-004)
  ├── flat: cod — denumire                            [GAP→add] test_picker_flat_arata_cod_si_denumire
  └── op: cod — denumire (exista deja :101)           [★★ are]
[~] post_form_chips add_extra (US-005)
  ├── add_extra valideaza nomenclator                 [GAP→add] test_extra_cod_validat_nomenclator
  ├── persista la salvare                             [GAP→add] test_extra_cod_persistat_la_salvare
  └── cod invalid/gol → semnal                        [GAP→E4] (lipsa in plan)
[~] post_corectie_trimitere citeste picker (US-006)
  ├── flat 0 chips: cod ales se aplica fara „+"        [GAP→add] test_cod_ales_in_picker_se_salveaza_fara_buton_add
  └── op-mode: cod aterizeaza pe operatia CORECTA      [GAP→E3] (lipsa in plan — RISC by-index)
[~] empty-state picker fara nomenclator                [GAP→E5] (lipsa in plan)
[~] header branded / dot RAR / selector tema           [GAP→add] test_titlu_romfast_autopass,
   (US-003/010/011)                                              test_rar_dot_in_antet_ok, test_selector_tema_are_eticheta
[~] landing Autentificare->/login (US-012)              [GAP→add] test_landing_autentificare_link_login
[~] E2E final (US-009)                                  [→E2E] Playwright/headless 390+1280, 2 teme

COVERAGE: planul cere ~18 teste noi + 4 lock-uri de bug. LIPSESC: E1 (grep literale), E3 (by-index op),
E4/E5 (empty/silent states). Regresie ceruta: `pytest -q -m "not live"` verde (baseline 5.15: 1256 passed).
```
**REGRESSION RULE:** cele 4 teste-lock (US-004..007 reproduse-inainte/reparate-dupa) sunt P1 obligatorii.

### Performance Review
PRD UI: fara N+1 (handlerele citesc nomenclatorul o data, deja cache-uit pe request). Stergerea woff2
elimina ~8-10 request-uri statice (pozitiv marginal). `load_nomenclator` in `post_form_chips` per add —
deja existent, nu nou. **0 issue perf.**

### Eng NOT in scope
Backend trimitere, migrare schema, stergere woff2 fizica, redesign landing, tipuri cont (5.17). Corect.

### Eng — What already exists
`post_form_chips`/`post_corectie_trimitere`/`_form_editare`/`_chips_prestatii`/`closest`-pattern/THEMES/
tokeni `--card2`/`--line2`. Planul extinde, nu rescrie.

### Failure Modes Registry (Eng) — CRITICAL GAP scan
| Codepath | Failure | Rescued? | Test? | User vede | Logat? | Verdict |
|---|---|---|---|---|---|---|
| literal font fara fallback | serif default | n/a (CSS) | NU (E1) | text urat | nu | gap test (nu critical-silent) |
| US-006 by-index op | cod pe op gresita | partial | NU (E3) | cod pe alta operatie | nu | **gap — adauga test** |
| add_extra cod invalid | ignorat | DA (validare) | partial | nimic (silent) | nu | E4 minor |
Niciun CRITICAL GAP (silent+netestat+netratat) pe trimiterea reala — PRD nu atinge worker. E3 e cel mai
serios (corectitudine), recomandat test inainte de ship.

### Worktree parallelization
- Lane A: US-001→002→003→010→011→007 (base.html, SECVENTIAL — autor unic) + US-008/012 (landing) la coada.
- Lane B: US-004→005→006 (`_chips_prestatii.html`+`routes.py`, INDEPENDENT de base.html) — paralelizabil.
- Lane C: US-013 (wizard) dupa US-002 (tokeni) + US-004/5/6 (chips). US-009 (E2E) dupa tot.
Conflict: niciunul intre Lane A si B (fisiere disjuncte). **Recomandare: livreaza Lane B (bug-fix) intai
ca hotfix — e durerea reala si nu depinde de tipografie.**

### Eng Completion Summary
```
  Step 0 Scope         FULL_REVIEW (scope acceptat ca-i)
  Arhitectura          0 issue (cuplaj soft mitigat)
  Code Quality         1 (E2: base.html @font-face neenumerat)
  Test Review          diagrama produsa, 4 gap-uri (E1,E3,E4,E5)
  Performance          0 issue
  NOT in scope         scris
  What already exists  scris
  Failure modes        0 CRITICAL GAP (E3 = gap de corectitudine, recomandat test)
  Parallelization      3 lanes (B independent — hotfix intai)
```

> **FAZA 3 COMPLETA.** Codex: indisponibil. Claude subagent: 5 findings (E1 P1 test font, E2/E3 P2,
> E4/E5 P3). Faza 3.5 (DX) SKIP — fara scop developer-facing (UI operator; API/integratori neatins).

## Cross-Phase Themes
- **Tema 1 — Tipografia system-ui (CEO Pass + Design Pass 4):** semnalata independent in Faza 1 (premisa
  P2 fragila, contradictie „uniform" vs per-OS) SI Faza 2 (hard-conflict slop #11 + identitate DESIGN.md).
  Doua faze, acelasi semnal → **User Challenge #1**, semnal puternic (chiar single-model, Codex indisponibil).
- **Tema 2 — Stari tacute in picker/chips (Design GAP + Eng E4/E5):** add_extra silent + empty-state picker
  fara nomenclator apar atat in design (Pass 2) cat si in eng (E4/E5). Convergenta → de rezolvat la executie.
- **Tema 3 — Acoperire de test sub obiectiv (Eng E1/E3):** „grep doar /static/fonts" + „by-index op
  netestat" — planul are 4 lock-uri bune dar lasa 2 gap-uri reale de test.

## Deferred to TODOS.md
- Stergerea fizica `static/fonts/*.woff2` — follow-up (deja non-goal in plan; pastreaza usurinta revert).
- Aliniere mockup intern landing „Confirma Vin" la VIN unic — debt vizual, non-goal 5.16.
(Niciun TODO nou critic; ambele deja in plan.)

## Implementation Tasks (aggregated across phases)
> Nota: T-C1 (CEO) si T-E4 (Eng) sunt acelasi finding (semnal add_extra) surprins din doua unghiuri —
> trateaza-le ca o singura sarcina la executie.

- [ ] **T-UC1 (P1, human: ~1h / CC: ~10min) — tipografie** — DECIZIE USER: pastreaza IBM Plex self-hostat + repara doar scala (Approach A) SAU confirma trecerea la system-ui (Approach B)
  - Surfaced by: ceo-review — User Challenge #1 (system-ui contrazice obiectivul uniform + DESIGN.md identity)
  - Files: docs/prd/prd-5.16-..., DESIGN.md, app/web/templates/base.html
- [ ] **T-D1 (P1, human: ~30min / CC: ~10min) — picker** — Empty-state picker cand nomenclatorul lipseste (rand needs_mapping nereparabil)
  - Surfaced by: design-review — Pass 2 GAP + Pass 7 · Files: app/web/templates/_chips_prestatii.html
- [ ] **T-E1 (P1, human: ~30min / CC: ~10min) — tipografie** — Test grep care esueaza la orice literal 'IBM Plex Sans'/'IBM Plex Mono' fara fallback dupa stergerea @font-face
  - Surfaced by: eng-review — E1 · Files: tests/test_web_responsive.py, landing.html, base.html
- [ ] **T-E2 (P2, human: ~10min / CC: ~5min) — tipografie** — US-001 sa enumere explicit stergerea @font-face din base.html (nu doar landing.html)
  - Surfaced by: eng-review — E2 (base.html:42-103) · Files: PRD, base.html
- [ ] **T-E3 (P2, human: ~45min / CC: ~15min) — chips** — Test US-006 mod operatii: cod ales pe pickerul op#2 aterizeaza pe op#2 nu #1 (aliniere by-index)
  - Surfaced by: eng-review — E3 · Files: app/web/routes.py, tests/test_web_corectie_prestatii.py
- [ ] **T-C1/T-E4 (P3, human: ~20min / CC: ~5min) — chips** — Semnal vizibil cand add_extra are select gol / cod invalid
  - Surfaced by: ceo + eng · Files: app/web/routes.py, _chips_prestatii.html
- [ ] **T-D2 (P3, human: ~15min / CC: ~5min) — contoare** — Pastreaza afordanta de tap pe „De corectat" in bara compacta mobil
  - Surfaced by: design-review — Pass 6 · Files: _status.html, base.html
- [ ] **T-E5 (P3, human: ~20min / CC: ~5min) — picker** — Empty-state picker fara nomenclator
  - Surfaced by: eng-review — E5 · Files: _chips_prestatii.html

## Decision Audit Trail

| # | Faza | Decizie | Clasificare | Principiu | Rationament | Respins |
|---|------|---------|-------------|-----------|-------------|---------|
| 1 | Setup | Ruleaza Codex toate fazele | Mecanica | P6 | Dual-voice standard | — |
| 2 | Setup | Codex usage-limit → degradare [subagent-only] | Mecanica | P6 | Plafon hard pana 2026-07-18; nu blocheaza | astept reset |
| 3 | CEO | Mod = SELECTIVE EXPANSION | Mecanica | P2 | Iteratie pe sistem 5.15 livrat | EXPANSION/HOLD |
| 4 | CEO | Premisa P1 (4 bug-uri) ACCEPTATA | Mecanica | — | Toate 4 verificate in cod | — |
| 5 | CEO | Premisa P2 (system fonts) → User Challenge | User Challenge | — | Contrazice „uniform"+DESIGN.md; NU auto-decis | — |
| 6 | CEO | Alternative font A/B/C documentate, recomand A | Taste | P5+P1 | A livreaza durerea reala cu risc minim | B (plan) |
| 7 | CEO | Nu adaug expansiuni noi in scop | Mecanica | P3 | Plan deja complet pt durerea declarata | — |
| 8 | CEO | GAP-1 add_extra silent → P3 TODO/task | Mecanica | P1 | Edge minor, nu blocheaza | — |
| 9 | Design | Fara generare mockup-uri noi | Mecanica | P3 | 5 mockup-uri HTML exista deja ca referinta | — |
| 10 | Design | Pass 4 hard-conflict font = intareste UC#1 | Taste→UC | P5 | Regula slop #11 (system-ui font primar) | — |
| 11 | Design | Empty-state picker = finding nou P1 | Mecanica | P1 | „No items found" tacut = rand nereparabil | — |
| 12 | Eng | DX scope = NU → Faza 3.5 SKIP | Mecanica | — | UI operator; API/CLI/integratori neatins | — |
| 13 | Eng | Scope = FULL_REVIEW (fara reducere) | Mecanica | P2 | >8 fisiere dar fara clase/infra noi | REDUCTION |
| 14 | Eng | E1 (grep literale font) = P1 | Mecanica | P1 | Testul curent nu prinde literalele fara fallback | — |
| 15 | Eng | E3 (by-index op) = P2 + test | Mecanica | P1 | Risc cod pe operatia gresita | — |
| 16 | Eng | Recomand livrare Lane B (bug-fix) intai | Taste | P6 | Durerea reala, independent de base.html | un singur val |
| 17 | Gate | **User Challenge #1 REZOLVAT = system-ui** (decizia userului) | User Challenge — rezolvat | — | Userul RESPINGE challenge-ul; directia originala (system fonts) prevaleaza. Risc AI-Slop #11 (system-ui ca font primar) = ACCEPTAT CONSTIENT. E1/E3 raman pre-ship. | Approach A (IBM Plex) |

## GSTACK REVIEW REPORT

| Review | Trigger | Why | Runs | Status | Findings |
|--------|---------|-----|------|--------|----------|
| CEO Review | `/plan-ceo-review` | Scope & strategy | 1 | issues_open | mode SELECTIVE_EXPANSION, 1 User Challenge, 0 critical gaps |
| Codex Review | `/codex review` | Independent 2nd opinion | 0 | — (usage limit) | indisponibil pana 2026-07-18 |
| Eng Review | `/plan-eng-review` | Architecture & tests (required) | 1 | issues_open | 5 issues, 0 critical gaps |
| Design Review | `/plan-design-review` | UI/UX gaps | 1 | issues_open | score 7/10 → 7/10, 2 GAP-uri de stare |
| DX Review | `/plan-devex-review` | Developer experience gaps | 0 | skipped | fara scop developer-facing |

- **CROSS-MODEL:** indisponibil — Codex la plafon de utilizare (reset 2026-07-18); toate vocile sunt
  single-voice (Claude). Semnalele nu se ridica la „cross-model consensus", dar Tema 1 (font) apare in 2 faze.
- **DECIZIE USER (User Challenge #1):** REZOLVAT = **system-ui** (userul a respins challenge-ul; directia
  lui originala prevaleaza). Trecerea de la IBM Plex la system font stack ramane in scop. Riscul de design
  AI-Slop #11 (system-ui ca font primar, identitate tipografica mai slaba, randare per-OS) = **risc acceptat
  constient** de catre user, nu o omisiune. Approach A (pastreaza IBM Plex) respins.
- **VERDICT:** Plan SOLID pe jumatatea bug-fix (toate 4 cauze verificate in cod, fezabile, reuse curat) si
  pe tipografie (directie confirmata de user). Inainte de ship raman ACTIONABILE (nu blocante de decizie,
  ci sarcini de implementare/test): **E1** (test grep literale `'IBM Plex Sans'`/`'IBM Plex Mono'` fara
  fallback dupa stergerea @font-face) — P1; **E3** (test US-006 mod operatii, aliniere by-index op corecta)
  — P2; **E2** (US-001 sa enumere stergerea @font-face si din `base.html`). Cele 4 teste-lock de bug
  (US-004..007) raman P1. ENG `issues_open` doar pe aceste sarcini de test, niciun critical gap, nicio
  decizie de produs deschisa.

NO UNRESOLVED DECISIONS
