feat(setari): pagina Setari compacta — 3 sub-taburi, plan clarificat, copy scurt

- Date firma mutat in sub-tabul Cont (date firma + plan + parola); 3 taburi in loc de 4
- Plan afisat o singura data (tier bold + consum) cu bara de progres; fara dublarea 'Plan curent'/'Plan:'
- Copy Credentiale RAR redus la un rand; confirmare Productie scurtata; parola setata are placeholder distinct
- Formulare compacte pe 2 coloane (setari-fgrid), titluri de sectiune uppercase mici, microcopy langa butoane
- activ_subtab implicit 'firma' -> 'cont'; 'firma' vechi mapat defensiv la 'cont'

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Claude Agent
2026-07-06 16:53:05 +00:00
parent e2627c1aa4
commit d7adeaf382
3 changed files with 157 additions and 131 deletions

View File

@@ -464,7 +464,7 @@ def _render_panel_cont(request: Request, conn, account_id: int) -> str:
"account_meta": account_meta,
"date_firma_mesaj": None,
"date_firma_eroare": None,
"activ_subtab": "firma",
"activ_subtab": "cont",
"parola_mesaj": None,
"parola_eroare": None,
"creds_test_mesaj": None,
@@ -4507,9 +4507,9 @@ def _render_cont(
date_firma_mesaj: str | None = None,
date_firma_eroare: str | None = None,
are_cheie: bool = False,
# Sub-tab activ dupa re-randare: 'firma' | 'rar' | 'api' | 'cont'.
# Fiecare handler POST intoarce sub-tabul propriu, ca swap-ul HTMX sa nu resete la firma.
activ_subtab: str = "firma",
# Sub-tab activ dupa re-randare: 'cont' | 'rar' | 'api'.
# Fiecare handler POST intoarce sub-tabul propriu, ca swap-ul HTMX sa nu resete la primul.
activ_subtab: str = "cont",
# Schimbare parola de acces (sub-tab Cont).
parola_mesaj: str | None = None,
parola_eroare: str | None = None,
@@ -4985,7 +4985,7 @@ async def cont_rar_medii(request: Request) -> HTMLResponse:
if prod_enabled_form and not was_prod_enabled and not prod_confirmare:
creds_prod_eroare = (
"Bifati confirmarea de mai jos pentru a activa mediul Productie: "
"\"Inteleg ca trimiterile pe Productie sunt declaratii reale (L.142)\"."
"\"Confirm: trimiterile pe Productie sunt declaratii reale (L.142)\"."
)
account_meta = _fetch_account_meta(conn, acct)
env_ctx = _fetch_cont_env_state(conn, acct)

View File

@@ -1,80 +1,138 @@
{# Pagina Setari: sub-taburi interne — Date firma / Credentiale RAR / Cheie API /
Cont (plan + parola). `activ_subtab` (server) alege panoul activ dupa fiecare
{# Pagina Setari: sub-taburi interne — Cont (date firma + plan + parola) /
Credentiale RAR / Cheie API. `activ_subtab` (server) alege panoul activ dupa fiecare
swap HTMX, ca re-randarea sa nu resete la primul tab. Comutarea intre taburi
fara server = JS delegat in base.html (#card-cont). #}
{% set _firma_ok = account_meta.name and account_meta.email and account_meta.cui %}
{% set _rar_ok = medii_disponibile and medii_disponibile|length > 0 %}
<div class="card" id="card-cont" data-activ-subtab="{{ activ_subtab|default('firma') }}">
<div class="setari-head">
{% set _subtab = activ_subtab|default('cont') %}
{% if _subtab == 'firma' %}{% set _subtab = 'cont' %}{% endif %}
<div class="card" id="card-cont" data-activ-subtab="{{ _subtab }}">
<h2 class="setari-title">
<svg class="ic" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="3"/><path d="M12 2v3M12 19v3M2 12h3M19 12h3M4.6 4.6l2.1 2.1M17.3 17.3l2.1 2.1M4.6 19.4l2.1-2.1M17.3 6.7l2.1-2.1"/></svg>
Setari
</h2>
<p class="setari-sub">Datele firmei, credentialele RAR, cheia API si contul tau.</p>
</div>
<div class="setari-subtabs" role="tablist" aria-label="Sectiuni setari">
<button type="button" class="setari-subtab{{ ' is-active' if activ_subtab|default('firma') == 'firma' else '' }}" role="tab" data-subtab="firma"
aria-selected="{{ 'true' if activ_subtab|default('firma') == 'firma' else 'false' }}">
<span class="st-dot {{ 'ok' if _firma_ok else 'warn' }}" aria-hidden="true"></span>Date firma</button>
<button type="button" class="setari-subtab{{ ' is-active' if activ_subtab|default('firma') == 'rar' else '' }}" role="tab" data-subtab="rar"
aria-selected="{{ 'true' if activ_subtab|default('firma') == 'rar' else 'false' }}">
<button type="button" class="setari-subtab{{ ' is-active' if _subtab == 'cont' else '' }}" role="tab" data-subtab="cont"
aria-selected="{{ 'true' if _subtab == 'cont' else 'false' }}">
<span class="st-dot {{ 'ok' if _firma_ok else 'warn' }}" aria-hidden="true"></span>Cont</button>
<button type="button" class="setari-subtab{{ ' is-active' if _subtab == 'rar' else '' }}" role="tab" data-subtab="rar"
aria-selected="{{ 'true' if _subtab == 'rar' else 'false' }}">
<span class="st-dot {{ 'ok' if _rar_ok else 'warn' }}" aria-hidden="true"></span>Credentiale RAR</button>
<button type="button" class="setari-subtab{{ ' is-active' if activ_subtab|default('firma') == 'api' else '' }}" role="tab" data-subtab="api"
aria-selected="{{ 'true' if activ_subtab|default('firma') == 'api' else 'false' }}">
<button type="button" class="setari-subtab{{ ' is-active' if _subtab == 'api' else '' }}" role="tab" data-subtab="api"
aria-selected="{{ 'true' if _subtab == 'api' else 'false' }}">
<span class="st-dot {{ 'ok' if are_cheie else 'warn' }}" aria-hidden="true"></span>Cheie API</button>
<button type="button" class="setari-subtab{{ ' is-active' if activ_subtab|default('firma') == 'cont' else '' }}" role="tab" data-subtab="cont"
aria-selected="{{ 'true' if activ_subtab|default('firma') == 'cont' else 'false' }}">
<span class="st-dot info" aria-hidden="true"></span>Cont</button>
</div>
{# ============================ Sub-tab: Date firma ============================ #}
<div class="setari-pane" data-subpane="firma" role="tabpanel"
{% if activ_subtab|default('firma') != 'firma' %}hidden{% endif %}>
{# ================= Sub-tab: Cont (date firma + plan + parola) ================ #}
<div class="setari-pane" data-subpane="cont" role="tabpanel"
{% if _subtab != 'cont' %}hidden{% endif %}>
{# --- Date firma --- #}
<div class="setari-zone-title">
<svg class="ic" viewBox="0 0 24 24" aria-hidden="true"><path d="M4 21V4a1 1 0 0 1 1-1h9a1 1 0 0 1 1 1v17"/><path d="M15 9h4a1 1 0 0 1 1 1v11"/><path d="M2 21h20"/><path d="M8 7h3M8 11h3M8 15h3"/></svg>
Date firma
<span class="setari-badge {{ 'sb-ok' if _firma_ok else 'sb-warn' }}">{{ 'complet' if _firma_ok else 'incomplet' }}</span>
</div>
<p class="setari-zone-desc">Apar pe declaratiile catre RAR si pe facturile de plan.</p>
{% if date_firma_mesaj %}<div class="flash" style="margin-bottom:12px;">{{ date_firma_mesaj }}</div>{% endif %}
{% if date_firma_eroare %}<div class="banner" style="margin-bottom:12px; padding:8px 12px;">{{ date_firma_eroare }}</div>{% endif %}
<form hx-post="/cont/date-firma" hx-target="#card-cont" hx-swap="outerHTML">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<p style="margin:0 0 8px;">
<label style="font-size:13px; color:var(--muted);">Companie</label><br>
<input type="text" name="companie" required value="{{ account_meta.name or '' }}"
style="width:100%; max-width:340px;" placeholder="Numele firmei (ex. Service Auto SRL)">
</p>
<p style="margin:0 0 8px;">
<label style="font-size:13px; color:var(--muted);">Email contact</label><br>
<input type="email" name="email" required value="{{ account_meta.email or '' }}"
style="width:100%; max-width:340px;" placeholder="contact@firma.ro">
</p>
<p style="margin:0 0 12px;">
<label style="font-size:13px; color:var(--muted);">CUI (cod unic de identificare)</label><br>
<input type="text" name="cui" required value="{{ account_meta.cui or '' }}"
style="width:100%; max-width:340px;" placeholder="RO12345678">
</p>
<button type="submit">Salveaza datele firmei</button>
<div class="setari-fgrid">
<div>
<label for="df-companie">Companie</label>
<input id="df-companie" type="text" name="companie" required value="{{ account_meta.name or '' }}"
placeholder="Numele firmei (ex. Service Auto SRL)">
</div>
<div>
<label for="df-cui">CUI</label>
<input id="df-cui" type="text" name="cui" required value="{{ account_meta.cui or '' }}"
placeholder="RO12345678">
</div>
<div class="fg-full">
<label for="df-email">Email contact</label>
<input id="df-email" type="email" name="email" required value="{{ account_meta.email or '' }}"
placeholder="contact@firma.ro">
</div>
</div>
<div class="setari-btn-row">
<button type="submit">Salveaza</button>
<span class="setari-micro">Apar pe declaratiile RAR si pe facturi.</span>
</div>
</form>
{# --- Plan --- #}
{% if plan_linie is defined %}
<hr class="setari-subzone-sep">
<div id="sectiune-plan" class="setari-zone-title">
<svg class="ic" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3 3 8l9 5 9-5z"/><path d="M3 13l9 5 9-5"/></svg>
Plan
</div>
{# plan_linie vine ca "Plan: <tier> · <detaliu>"; aici tier-ul apare O data, bold. #}
{% set _plan_text = plan_linie|replace('Plan: ', '', 1) %}
{% set _plan_parts = _plan_text.split(' · ', 1) %}
<div class="plan-row">
<span class="plan-tier">{{ _plan_parts[0] }}</span>
{% if _plan_parts|length > 1 %}
<span class="plan-usage" style="{% if plan_limita_atinsa|default(false) %}color:var(--err); font-weight:600;{% elif plan_warn|default(false) %}color:var(--warn); font-weight:600;{% endif %}">{{ _plan_parts[1] }}</span>
{% endif %}
</div>
{% if monthly_limit_val|default(none) and usage_lunar is defined %}
{% set _pct = (usage_lunar / monthly_limit_val * 100)|round|int %}
<div class="plan-meter" role="progressbar" aria-valuenow="{{ usage_lunar }}" aria-valuemin="0"
aria-valuemax="{{ monthly_limit_val }}" aria-label="Consum plan luna curenta">
<span style="width:{{ [_pct, 100]|min }}%;{% if plan_limita_atinsa|default(false) %} background:var(--err);{% elif plan_warn|default(false) %} background:var(--warn);{% endif %}"></span>
</div>
{% endif %}
{% if plan_limita_atinsa|default(false) %}
<p class="setari-micro" style="color:var(--err); margin:0 0 6px;">Limita lunara atinsa — trimiterile noi sunt blocate pana luna viitoare.</p>
{% endif %}
<p class="setari-micro" style="margin:0;">Pentru mai mult volum sau acces API, <a href="mailto:contact@romfast.ro">contacteaza-ne</a>.</p>
{% endif %}
{# --- Parola de acces --- #}
<hr class="setari-subzone-sep">
<div class="setari-zone-title">
<svg class="ic" viewBox="0 0 24 24" aria-hidden="true"><rect x="4" y="10" width="16" height="11" rx="2"/><path d="M8 10V7a4 4 0 0 1 8 0v3"/><circle cx="12" cy="15.5" r="1.2"/></svg>
Parola de acces
</div>
<p class="setari-zone-desc">Parola dashboard-ului — separata de credentialele RAR. Minim 10 caractere.</p>
{% if parola_mesaj %}<div class="flash" style="margin-bottom:12px;">{{ parola_mesaj }}</div>{% endif %}
{% if parola_eroare %}<div class="banner" style="margin-bottom:12px; padding:8px 12px;">{{ parola_eroare }}</div>{% endif %}
<form hx-post="/cont/schimba-parola" hx-target="#card-cont" hx-swap="outerHTML">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<div class="setari-fgrid">
<div class="fg-full" style="max-width:273px;">
<label for="pw-actuala">Parola actuala</label>
<input id="pw-actuala" type="password" name="parola_actuala" autocomplete="current-password">
</div>
<div>
<label for="pw-noua">Parola noua</label>
<input id="pw-noua" type="password" name="parola_noua" autocomplete="new-password">
</div>
<div>
<label for="pw-confirma">Confirma parola noua</label>
<input id="pw-confirma" type="password" name="parola_confirma" autocomplete="new-password">
</div>
</div>
<button type="submit">Schimba parola</button>
</form>
</div>
{# ========================= Sub-tab: Credentiale RAR ========================= #}
<div class="setari-pane" data-subpane="rar" role="tabpanel"
{% if activ_subtab|default('firma') != 'rar' %}hidden{% endif %}>
{% if _subtab != 'rar' %}hidden{% endif %}>
<div class="setari-zone-title">
<svg class="ic" viewBox="0 0 24 24" aria-hidden="true"><path d="M5 11l1.5-4A2 2 0 0 1 8.4 5.6h7.2A2 2 0 0 1 17.5 7L19 11"/><path d="M4 11h16v6H4z"/><path d="M6 17v2M18 17v2"/><circle cx="7.5" cy="14" r="1"/><circle cx="16.5" cy="14" r="1"/></svg>
Credentiale RAR (portal AUTOPASS)
Credentiale RAR
<span class="setari-badge {{ 'sb-ok' if _rar_ok else 'sb-warn' }}">{{ 'configurat' if _rar_ok else 'neconfigurat' }}</span>
</div>
<p class="setari-zone-desc">
Configureaza mediile RAR — Testare si/sau Productie — fiecare cu credentialele lui,
validate separat la salvare pe sistemul RAR corespunzator. Un mediu devine activ cand e
bifat si are credentiale; abia atunci importul web poate trimite pe el. (Canalul API ramane
pe mediul global al instantei, {{ mediu_instanta() }}, pentru ca isi cara singur credentialele.)
Fiecare mediu are propriile credentiale, verificate la salvare. Trimiterile merg doar pe mediile active.
</p>
{% if creds_mesaj %}<div class="flash" style="margin-bottom:12px;">{{ creds_mesaj }}</div>{% endif %}
@@ -93,10 +151,11 @@
<input type="checkbox" name="test_enabled" value="1" {% if test_enabled %}checked{% endif %}>
Activare Testare
</label>
<label class="env-lbl">Email RAR Testare</label>
<input type="email" name="test_email" placeholder="email@service.ro">
<label class="env-lbl">Parola RAR Testare</label>
<input type="password" name="test_parola" autocomplete="new-password">
<label class="env-lbl" for="rar-test-email">Email RAR Testare</label>
<input id="rar-test-email" type="email" name="test_email" placeholder="email@service.ro">
<label class="env-lbl" for="rar-test-parola">Parola RAR Testare</label>
<input id="rar-test-parola" type="password" name="test_parola" autocomplete="new-password"
{% if test_disponibil %}placeholder="&bull;&bull;&bull;&bull;&bull;&bull;&bull;&bull; (setata)"{% endif %}>
{% if creds_test_mesaj %}<div class="flash" style="margin-top:6px;">{{ creds_test_mesaj }}</div>{% endif %}
{% if creds_test_eroare %}<div class="banner" style="margin-top:6px; padding:8px 12px;">{{ creds_test_eroare }}</div>{% endif %}
</div>
@@ -110,13 +169,14 @@
<input type="checkbox" name="prod_enabled" value="1" {% if prod_enabled %}checked{% endif %}>
Activare Productie
</label>
<label class="env-lbl">Email RAR Productie</label>
<input type="email" name="prod_email" placeholder="email@service.ro">
<label class="env-lbl">Parola RAR Productie</label>
<input type="password" name="prod_parola" autocomplete="new-password">
<label class="env-lbl" for="rar-prod-email">Email RAR Productie</label>
<input id="rar-prod-email" type="email" name="prod_email" placeholder="email@service.ro">
<label class="env-lbl" for="rar-prod-parola">Parola RAR Productie</label>
<input id="rar-prod-parola" type="password" name="prod_parola" autocomplete="new-password"
{% if prod_disponibil %}placeholder="&bull;&bull;&bull;&bull;&bull;&bull;&bull;&bull; (setata)"{% endif %}>
<label class="env-confirm">
<input type="checkbox" name="prod_confirmare" value="1">
<span>Inteleg ca trimiterile pe Productie sunt declaratii reale (L.142), finale si fara anulare.</span>
<span>Confirm: trimiterile pe Productie sunt declaratii reale (L.142), finale si fara anulare.</span>
</label>
{% if creds_prod_mesaj %}<div class="flash" style="margin-top:6px;">{{ creds_prod_mesaj }}</div>{% endif %}
{% if creds_prod_eroare %}<div class="banner" style="margin-top:6px; padding:8px 12px;">{{ creds_prod_eroare }}</div>{% endif %}
@@ -124,9 +184,9 @@
</div>
<div class="default-env">
<label style="font-size:13px; color:var(--muted);">Mediu implicit pentru trimiteri</label>
<label for="rar-env-default" style="font-size:13px; color:var(--muted);">Mediu implicit pentru trimiteri</label>
{% if medii_disponibile %}
<select name="rar_env_default">
<select id="rar-env-default" name="rar_env_default">
{% for env in medii_disponibile %}
<option value="{{ env }}"{% if env == rar_env_default %} selected{% endif %}>{{ "Testare" if env == "test" else "Productie" }}</option>
{% endfor %}
@@ -138,22 +198,23 @@
{% if creds_default_eroare %}<div class="banner" style="margin-top:6px; padding:8px 12px; flex-basis:100%;">{{ creds_default_eroare }}</div>{% endif %}
</div>
<button type="submit">Salveaza mediile RAR</button>
<span style="font-size:12px; color:var(--muted); margin-left:8px;">Parolele stocate criptat, niciodata in clar.</span>
<div class="setari-btn-row">
<button type="submit">Salveaza</button>
<span class="setari-micro">Parolele se stocheaza criptat.</span>
</div>
</form>
</div>
{# ============================ Sub-tab: Cheie API ============================ #}
<div class="setari-pane" data-subpane="api" role="tabpanel"
{% if activ_subtab|default('firma') != 'api' %}hidden{% endif %}>
{% if _subtab != 'api' %}hidden{% endif %}>
<div class="setari-zone-title">
<svg class="ic" viewBox="0 0 24 24" aria-hidden="true"><circle cx="8" cy="15" r="4"/><path d="M11 12l9-9"/><path d="M17 6l2.5 2.5M14 9l2.5 2.5"/></svg>
Cheie API
<span class="setari-badge {{ 'sb-ok' if are_cheie else 'sb-warn' }}">{{ 'activa' if are_cheie else 'lipsa' }}</span>
</div>
<p class="setari-zone-desc">
O foloseste softul propriu / ROAAUTO ca sa trimita prezentari prin API. Se vede integral o
singura data, la creare sau rotire.
Pentru trimiteri din softul propriu / ROAAUTO. Se afiseaza integral o singura data.
</p>
{% if api_key %}
@@ -164,9 +225,6 @@
onclick="navigator.clipboard.writeText(this.dataset.key).then(()=>this.textContent='Copiat!')">
Copiaza cheia
</button>
<p style="font-size:13px; color:var(--warn); margin:10px 0 0;">
Atentie: la urmatoarea vizita aceasta cheie dispare. Daca o pierzi, roteste din nou.
</p>
{% endif %}
{% if rot_eroare %}<div class="banner" style="margin:12px 0; padding:8px 12px;">{{ rot_eroare }}</div>{% endif %}
@@ -174,62 +232,10 @@
<form hx-post="/cont/roteste-cheie" hx-target="#card-cont" hx-swap="outerHTML"
style="margin-top:{% if api_key %}14px{% else %}0{% endif %};">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<div class="setari-btn-row">
<button type="submit" class="btn-warn">{{ 'Roteste cheia API' if are_cheie else 'Genereaza cheia API' }}</button>
<span style="font-size:12px; color:var(--muted); margin-left:8px;">Cheia veche se revoca imediat.</span>
</form>
<span class="setari-micro">Rotirea revoca imediat cheia veche.</span>
</div>
{# ========================= Sub-tab: Cont (plan + parola) ==================== #}
<div class="setari-pane" data-subpane="cont" role="tabpanel"
{% if activ_subtab|default('firma') != 'cont' %}hidden{% endif %}>
{# --- Plan curent --- #}
{% if plan_linie is defined %}
<div class="setari-zone-title">
<svg class="ic" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3 3 8l9 5 9-5z"/><path d="M3 13l9 5 9-5"/></svg>
Plan curent
<span class="setari-badge sb-info">{{ tier_label|default('Gratuit') }}</span>
</div>
<div style="font-size:var(--fs-md); font-weight:600; margin-bottom:6px;
color:{% if plan_limita_atinsa|default(false) %}var(--err){% elif plan_warn|default(false) %}var(--warn){% else %}var(--ink){% endif %};">
{{ plan_linie }}
</div>
{% if plan_limita_atinsa|default(false) %}
<p class="setari-zone-desc" style="color:var(--err);">Limita lunara a fost atinsa — trimiterile noi sunt blocate pana la inceputul lunii urmatoare.</p>
{% elif plan_warn|default(false) %}
<p class="setari-zone-desc" style="color:var(--warn);">Te apropii de limita lunara.</p>
{% endif %}
<p class="setari-zone-desc">
Pentru mai mult volum sau import prin API, <a href="mailto:contact@romfast.ro">contacteaza-ne</a> — alocarea planurilor se face manual.
</p>
<hr class="setari-subzone-sep">
{% endif %}
{# --- Parola de acces --- #}
<div class="setari-zone-title">
<svg class="ic" viewBox="0 0 24 24" aria-hidden="true"><rect x="4" y="10" width="16" height="11" rx="2"/><path d="M8 10V7a4 4 0 0 1 8 0v3"/><circle cx="12" cy="15.5" r="1.2"/></svg>
Parola de acces
</div>
<p class="setari-zone-desc">Parola cu care te autentifici in dashboard (separata de credentialele RAR). Minim 10 caractere.</p>
{% if parola_mesaj %}<div class="flash" style="margin-bottom:12px;">{{ parola_mesaj }}</div>{% endif %}
{% if parola_eroare %}<div class="banner" style="margin-bottom:12px; padding:8px 12px;">{{ parola_eroare }}</div>{% endif %}
<form hx-post="/cont/schimba-parola" hx-target="#card-cont" hx-swap="outerHTML">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<p style="margin:0 0 8px;">
<label style="font-size:13px; color:var(--muted);">Parola actuala</label><br>
<input type="password" name="parola_actuala" autocomplete="current-password" style="width:100%; max-width:340px;">
</p>
<p style="margin:0 0 8px;">
<label style="font-size:13px; color:var(--muted);">Parola noua</label><br>
<input type="password" name="parola_noua" autocomplete="new-password" style="width:100%; max-width:340px;">
</p>
<p style="margin:0 0 12px;">
<label style="font-size:13px; color:var(--muted);">Confirma parola noua</label><br>
<input type="password" name="parola_confirma" autocomplete="new-password" style="width:100%; max-width:340px;">
</p>
<button type="submit">Schimba parola</button>
</form>
</div>
</div>

View File

@@ -857,10 +857,30 @@
.st-dot.warn { background:var(--warn); }
.st-dot.info { background:var(--muted); }
.setari-pane[hidden] { display:none; }
.setari-zone-title { font-size:var(--fs-md); font-weight:600; margin:0 0 4px; display:flex;
align-items:center; gap:10px; flex-wrap:wrap; }
.setari-zone-title .ic { opacity:.7; }
.setari-zone-desc { color:var(--muted); font-size:var(--fs-sm); margin:0 0 16px; max-width:64ch; line-height:1.5; }
/* Titlu de sectiune compact (uppercase mic) — ierarhie sub titlul paginii, nu concurenta cu el. */
.setari-zone-title { font-size:var(--fs-xs); font-weight:600; text-transform:uppercase;
letter-spacing:.07em; color:var(--muted); margin:0 0 10px; display:flex;
align-items:center; gap:8px; flex-wrap:wrap; }
.setari-zone-title .ic { opacity:.7; width:15px; height:15px; }
.setari-zone-title .setari-badge { text-transform:none; letter-spacing:0; }
.setari-zone-desc { color:var(--muted); font-size:var(--fs-sm); margin:0 0 12px; max-width:60ch; line-height:1.5; }
/* Formulare compacte pe 2 coloane in Setari. */
.setari-fgrid { display:grid; grid-template-columns:1fr 1fr; gap:10px 14px; max-width:560px; margin:0 0 12px; }
.setari-fgrid .fg-full { grid-column:1 / -1; }
.setari-fgrid label { display:block; font-size:var(--fs-xs); color:var(--muted); margin-bottom:3px; }
.setari-fgrid input { width:100%; box-sizing:border-box; font:inherit; font-size:14px;
background:var(--bg); color:var(--ink); border:1px solid var(--line);
border-radius:6px; padding:7px 10px; }
@media (max-width:560px) { .setari-fgrid { grid-template-columns:1fr; } }
.setari-btn-row { display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
.setari-micro { font-size:var(--fs-xs); color:var(--muted); }
/* Plan: tier + consum pe un rand, bara de progres sub ele. */
.plan-row { display:flex; align-items:baseline; gap:10px; flex-wrap:wrap; margin:0 0 8px; }
.plan-tier { font-size:var(--fs-md); font-weight:600; color:var(--ink); }
.plan-usage { font-size:var(--fs-sm); color:var(--muted); font-variant-numeric:tabular-nums; }
.plan-meter { height:6px; border-radius:99px; background:var(--line2); max-width:340px;
overflow:hidden; margin:0 0 8px; }
.plan-meter > span { display:block; height:100%; border-radius:99px; background:var(--accent); }
.setari-badge { font-size:11px; font-weight:700; padding:2px 9px; border-radius:99px;
text-transform:uppercase; letter-spacing:.03em; border:1px solid transparent; }
.setari-badge.sb-ok { color:var(--ok); background:color-mix(in srgb,var(--ok) 12%,transparent);
@@ -869,7 +889,7 @@
border-color:color-mix(in srgb,var(--warn) 40%,transparent); }
.setari-badge.sb-info { color:var(--muted); background:color-mix(in srgb,var(--muted) 12%,transparent);
border-color:color-mix(in srgb,var(--muted) 35%,transparent); }
.setari-subzone-sep { border:none; border-top:1px solid var(--line); margin:26px 0 22px; }
.setari-subzone-sep { border:none; border-top:1px solid var(--line); margin:20px 0 18px; }
/* Cheie API afisata o singura data. */
.keybox { font-family:var(--font-mono); font-size:14px; background:var(--card2);
border:1px solid var(--line); border-radius:8px; padding:12px 14px; word-break:break-all;