Flow chrome

Shell-ul pentru flow-uri secvențiale (onboarding, wizards, declarații, semnare). Două variante, una per platformă: .flow-chrome pe mobile (overlay-uri peste conținut scrollabil, tratament veil + blur) și .app-shell = .app-top + .app-footer pe desktop / multi-page (header fix cu stepper aliniat stânga, close și bandă de progres; footer fix cu back + CTA și text help revealed pe scroll). Aceleași semnale (înainte / înapoi / ieșire), două layout-uri.

Markup canonic · components/flow-chrome.json

sursa = JSON · generat de scripts/build-catalog.py
Documente

Tranziția la 1024px — cine devine ce

Un singur prag în DS: --bp-desktop: 1024px. Sub el, tot fluxul trăiește în .flow-chrome (bare-overlay peste conținut scrollabil). De la 1024px în sus, shell-ul se schimbă complet: pagina devine .app-shell + .layout-12, iar chrome-ul fluxului devine .app-top sus (stepper aliniat stânga + close + bandă de progres) și .app-footer jos (back + CTA la mărimea default). Consumatorul face swap între cele două — nu le suprapune niciodată.

… se citește lățimea ferestrei…

Redimensionează fereastra peste / sub 1024px — indicatorul arată shell-ul pe care l-ar folosi acest viewport.

< 1024px · mobile.flow-chrome

Trei zone sus (back · titlu pas · meniu), un singur CTA jos, ambele ca overlay-uri cu veil + blur peste conținutul scrollabil. Pașii se văd tapând titlul (steps sheet).

PASUL 2 DIN 3

Ce documente încarci?

≥ 1024px · desktop.app-shell

Sidebar-ul (opțional) reapare ca rail. Sus, .app-top: stepper-ul procesului aliniat stânga, close-ul dreapta, bandă de progres jos — fără back și fără logo. Jos, .app-footer cu back + CTA la mărimea default. Header și footer își aliniază conținutul pe aceeași coloană (.app-top-in = .app-footer-in). Fără veil, fără sheets.

Ce documente încarci?

Corespondența semnalelor. Fiecare semnal al fluxului există pe ambele platforme — se mută, nu dispare. Eticheta e aceeași în ambele locuri (copy = single source of truth).

SemnalMobile · <1024pxDesktop · ≥1024px
Înapoi .btn.secondary.icon-only stânga sus · aria-disabled (opacity 0.4) pe primul pas .btn.outline (md) în .app-foot-nav · .invisible pe primul pas (rezervă spațiul). Niciodată în header.
Înainte un singur .btn.primary.lg, full width, în .flow-footer .btn.primary (md) în dreapta rândului de navigare, lângă back
Pasul curent .flow-step-title centru, cu chevron .stepper-step.active — în .app-top-center, stepper aliniat stânga, vizibil permanent
Lista pașilor .sheet.attached + .stepper.vertical, deschis DOAR din titlu toți pașii sunt deja pe ecran în .stepper-ul din .app-top — nu există listă separată
Titlul lung al pasului .t-h1 în conținut .t-h1 în conținut — identic
Progres poziția în foaia pașilor (.sheet.attached) .app-progress — bandă de 3px jos în header, (step + 1) / total; absentă pe ecranele fără pași
Ajutor rând „Ajutor și suport" în foaia meniului (.sheet.attached) .app-foot-help — text sub butoane, revealed pe .is-scrolled
Ultimul pas CTA devine „Trimite" + check identic — aceeași etichetă, același icon
Ieșire din flux .list-row simplu, singur în al doilea grup al foii meniului .btn.outline.icon-only — singura acțiune de chrome din header. Deschide modalul de confirmare (salvează / ieși), niciodată ieșire silențioasă.
Tratament voal bej-0 @ 85% + blur(7px), mască spre conținut --c-white solid + border-bottom / border-top, fără blur
Swap, nu suprapunere

La trecerea pragului consumatorul schimbă shell-ul: randează .flow-chrome SAU .app-footer, niciodată ambele. Un .flow-* rămas într-o pagină desktop e violare, nu detaliu.

Banda mobile include tabletele

Între ~600px și 1024px shell-ul rămâne o singură coloană: conținutul și barele se capează la --flow-max (560px) și se centrează, voalul face bleed pe toată lățimea. Nu devine layout desktop pe tabletă.

Aceeași etichetă în ambele locuri

.flow-step-title (mobil) și .stepper-step.active (desktop) afișează textul identic. Nu „Activitate" pe desktop și „Despre activitatea ta" pe mobil.

Un CTA, pe ambele

O singură cale înainte per ecran. Pe mobil CTA-ul e singur și full width; pe desktop stă lângă back, dar rămâne unicul primary din viewport.

Mobile · .flow-chrome

Header (back · titlu pas + dropdown · meniu) și footer (CTA primar) ca overlay-uri peste conținut scrollabil. Voal bej-0 la 85% cu backdrop-filter: blur(7px) care se estompează spre conținut. Plus două bottom-sheets: meniul general și lista de pași.

Chrome peste un ecran de wizard: header (back · titlu pas + dropdown · meniu) + footer cu CTA primar. Conținutul nu depășește zona vizibilă, deci voalul rămâne discret.

SITUAȚIE FISCALĂ

Mai ești angajat și altundeva?

Conținut lung pre-derulat ca să se vadă cum textul intră gradual sub voal și cum cele 15% transparență fac blur-ul vizibil peste litere.

POVESTE · CAPITOLUL I

Croitorașul cel viteaz

Într-o dimineață cu soare, un croitoraș tânăr și sărman ședea cu picioarele încrucișate pe masa de lucru, lângă fereastra atelierului. Și-a întins pe genunchi o vestă, a luat acul subțire în mână și s-a apucat de treabă.

Atunci a auzit o femeie strigând în piață: „Dulceață bună, dulceață ieftină." Croitorașul a ieșit la geam și a chemat-o sus.

Cum lucra mai departe la vestă, șapte muște au coborât din tavan. Croitorașul a privit o clipă, a luat o bucată de pânză, a învârtit-o repede și a izbit cu putere — dintr-o singură lovitură, toate cele șapte muște au rămas pe pâine.

„Eu am făcut asta?" a spus el. „Trebuie să afle tot orașul." A luat o fâșie de pânză roșie și a brodat pe ea, cu litere mari: șapte dintr-o singură lovitură.

Meniul fluxului deschis peste scrim: o .sheet.attached peste .sheet-scrim (contract sheet.json), cu un .btn.sm.icon-only (X) în dreapta sus și rânduri .list-row în .list-group.sm. .flow-sheet / .flow-menu-row sunt aliasuri deprecate din 2026-09-16. Meniul e doar acțiuni — nicio navigare. Pașii nu se accesează de aici (doar din titlul pasului). Rândul „Ieși din flux" e un .list-row simplu, ca celelalte — ieșirea nu e distructivă —, singur în al doilea grup.

SITUAȚIE FISCALĂ

Mai ești angajat și altundeva?

Foaia cu lista pașilor — aceeași .sheet.attached ca meniul (fost .flow-sheet.steps, alias deprecat), accesibilă doar din titlul pasului (nu din meniu). Lista dinăuntru e un .stepper.vertical — exact aceleași clase și stări ca stepperul din .app-top, doar pe rânduri: .done (chip tonal, tint verde cu check verde), .active (chip pink solid — singurul plin din listă — label pink-deep, fără fundal pe rând), pas viitor (chip alb cu ring, label fog).

SITUAȚIE FISCALĂ

Mai ești angajat și altundeva?

Desktop · .app-shell = .app-top + .app-footer

Perechea desktop a lui .flow-chrome. Header fix cu stepper aliniat stânga, close în dreapta și o bandă de progres de 3px jos în header; footer fix cu back outline + CTA primar și textul de ajutor revealed pe scroll. Ambele bare se aliniază pe --app-foot-w (default 640px), deci close-ul cade flush cu CTA-ul. Suprafață albă cu rule-soft pe ambele, fixe la scroll. .app-footer singur rămâne valid — paginile existente merg nemodificate.

Structura

<div class="app-shell">
  <header class="app-top">
    <div class="app-top-in">
      <div class="app-top-center">
        <nav class="stepper">…</nav>                 <!-- omis pe ecrane fără pași -->
      </div>
      <div class="app-top-right">
        <button class="btn outline icon-only" aria-label="Închide">×</button>
      </div>
    </div>
    <div class="app-progress"><div class="app-progress-bar" style="--app-progress:40%"></div></div>
  </header>

  <!-- conținutul paginii -->

  <footer class="app-footer" id="appFooter">
    <div class="app-footer-in">
      <div class="app-foot-nav">
        <button class="btn outline">Înapoi</button>
        <button class="btn primary">Continuă</button>
      </div>
      <p class="app-foot-help">…</p>
    </div>
  </footer>
</div>

Pas intermediar — stepper + progress 40%

SITUAȚIE FISCALĂ

Mai ești angajat și altundeva?

Ultimul pas — progress 100%, CTA „Trimite"

CONFIRMARE

Verifică datele înainte de trimitere

CUI
RO 42 118 903
Județ
Cluj

Ecran fără pași — header doar cu close

Single-page flow (emitere factură, editare setare, upload). Fără pași nu există nici context de pus în header: titlul trăiește ca h1 în pagină, iar banda de progres lipsește complet — nu o pui la 0% sau 100%. Headerul rămâne doar cu close-ul.

Factură nouă

Footerul desktop în detaliu · .app-footer

Ipostazele barei de jos, izolate. Rândul de navigare (back outline + primary CTA) plus textul de ajutor care apare doar la scroll.

Comportament — scroll reveal + match width + progres

Trei hook-uri JS: toggle-ul .is-scrolled pe scroll (reveal text de help), măsurarea lățimii conținutului pentru aliniere flush pe ambele bare, și progresul derivat din indexul pasului.

// 1. Scroll reveal pentru .app-foot-help
function syncFooterScroll() {
  document.getElementById('appFooter')
    .classList.toggle('is-scrolled', window.scrollY > 4);
}
window.addEventListener('scroll', syncFooterScroll, { passive: true });
syncFooterScroll();

// 2. Match content width — pe ecranele cu conținut wider, footer-ul
//    citește lățimea reală a containerului și se aliniază cu el.
function syncFooterWidth() {
  const footer = document.getElementById('appFooter');
  const top    = document.getElementById('appTop');
  const wide   = document.querySelector('.screen.active .signer-layout');
  if (wide) {
    document.documentElement.style.setProperty(
      '--app-foot-w', wide.getBoundingClientRect().width + 'px');
    footer.classList.add('matches-content');
    if (top) top.classList.add('matches-content');
  } else {
    document.documentElement.style.removeProperty('--app-foot-w');
    footer.classList.remove('matches-content');
    if (top) top.classList.remove('matches-content');
  }
}
window.addEventListener('resize', syncFooterWidth);

// 3. Progres — derivat din indexul pasului, nu setat manual per ecran.
function syncProgress(step, total) {
  document.querySelector('.app-progress-bar')
    .style.setProperty('--app-progress', ((step + 1) / total * 100) + '%');
}

Reguli ferme

Mobile vs desktop

.flow-chrome pe mobile, .app-shell (.app-top + .app-footer) pe desktop / multi-page. Nu le combina pe același ecran. La schimbarea breakpoint-ului, consumatorul face swap între cele două.

Două shell-uri pe mobil

.flow-chrome e doar pentru fluxuri (un singur „înainte", fără navigare globală). Ecranele de produs — acasă, liste, setări, detalii — stau în .app-mobile cu .tabbar și .app-mobile-top (Shell & layout, App navigation). Nu .tabbar într-un flux, nu .flow-bar pe un ecran de produs.

Foile sunt .sheet

Meniul și lista pașilor sunt .sheet.attached peste .sheet-scrim, cu rânduri .list-row în .list-group.sm (Sheet). .flow-sheet* și .flow-menu-* sunt aliasuri deprecate — nu în cod nou.

Headerul desktop nu are back

Înainte / înapoi trăiesc doar în footer. Headerul poartă context (stepperul) și o singură acțiune: .btn.outline.icon-only. Nu duplica back-ul sus și nu pune logo, avatar, limbă sau meniu — nu e navigație globală.

Progress line = doar wizards

.app-progress apare numai când există pași. Pe single-page flow o omiți complet — nu o lași la 0% sau 100%. Procentul se derivă din index, (step + 1) / total, nu se scrie per ecran.

Aliniere sus = jos

Ambele bare citesc --app-foot-w. Când conținutul e wider (signer 1096px), pui .matches-content pe ambele — altfel close-ul nu mai cade flush cu CTA-ul.

Close se confirmă

Close-ul din header (.btn.outline.icon-only) nu abandonează silențios flow-ul: deschide modalul de confirmare (salvează / ieși), echivalentul rândului „Ieși din flux" din meniul mobil.

Butoanele din footer sunt md

.btn.outline + .btn.primary la mărimea default. .lg rămâne doar pe mobil, în .flow-footer. Footerul nu poartă mesaje de validare — eroarea stă inline pe câmp.

Tratament canonic (mobile)

Veil + blur e singura variantă în DS. Voal bej-0 @ 85% + backdrop-filter: blur(7px), mascat să se estompeze spre conținut. Butoanele chrome rămân solide (bej-1) ca să nu pară transparente. Fallback automat când backdrop-filter nu e suportat.

Heights mobile

Header ≈88px, footer ≈78px. Scroll layer are padding-top:128px; padding-bottom:108px + mask fade — conținutul intră gradual sub bară, nu se taie net.

Back consistent

Pe ambele surface-uri, back e mereu vizibil (mobile: disabled opacity 0.4 pe primul pas; desktop: .invisible rezervă spațiu). Nu îl ascunzi prin display:none.

Titlu pas = dropdown (mobile)

.flow-step-title deschide steps sheet. Chevron decorativ — funcționalitatea e pe tap pe tot butonul.

O etichetă per pas

.flow-step-title (mobil) și .stepper-step.active (desktop) folosesc același string. Titlul lung descriptiv trăiește separat, ca h1 în conținut, pe ambele platforme.

CTA pe ultimul pas

Pe ultimul pas eticheta CTA devine „Trimite" + icon check în loc de „Continuă" + arrowR. Valabil pentru ambele surface-uri.