diff --git a/.paul/STATE.md b/.paul/STATE.md index 0da641d..bea2c1a 100644 --- a/.paul/STATE.md +++ b/.paul/STATE.md @@ -1,10 +1,10 @@ # STATE — orderPRO **Tryb:** plan-first -**Ostatnia aktualizacja:** 2026-05-19 +**Ostatnia aktualizacja:** 2026-05-20 ## Aktywna praca -UNIFY zakonczony dla `.paul/plans/20260519-1730-refactor-delivery-status/`. Petla zamknieta, brak aktywnego planu. +UNIFY zakonczony dla `.paul/plans/20260520-1200-fix-login-page-and-remember-me/`. Petla zamknieta. Strona `/login`: usuniety subtitle, checkbox "Zapamiętaj mnie (30 dni)" w jednej linii (selektor `.form-field.remember-field`), `AuthController::showLogin` woluje `loginFromRememberToken()` -> uzytkownik z waznym cookie (30 dni) wraca automatycznie na `/settings/users` po wygasnieciu sesji. SUMMARY: `.paul/plans/20260520-1200-fix-login-page-and-remember-me/SUMMARY.md`. ``` PLAN ──▶ APPLY ──▶ UNIFY diff --git a/.paul/codebase/tech_changelog.md b/.paul/codebase/tech_changelog.md index 038bd48..de16d5c 100644 --- a/.paul/codebase/tech_changelog.md +++ b/.paul/codebase/tech_changelog.md @@ -2,6 +2,22 @@ Chronologiczny log zmian technicznych (co i dlaczego). Najnowsze na gorze. +## 2026-05-20 — Strona logowania: usuniecie subtitle, inline "Zapamietaj mnie (30 dni)", auto-login z cookie + +### Co +- `resources/views/auth/login.php`: usuniety element `
`.
+- `resources/lang/pl.php`: `auth.login.remember_me` -> "Zapamiętaj mnie (30 dni)".
+- `resources/scss/login.scss`: selektor `.remember-field` -> `.form-field.remember-field` (kompozytowy, specyficznosc 0,2,0 bije `.form-field { display: grid }` zdefiniowane ponizej). Compiled `public/assets/css/login.css` przebudowany przez `sass --style=compressed`.
+- `src/Modules/Auth/AuthController.php`: `showLogin` woluje `loginFromRememberToken()` przed renderem formularza.
+
+### Dlaczego
+- Bug "Zapamietaj mnie nie dziala": `AuthMiddleware` poprawnie konsumowal cookie na route'ach chronionych, ale `/login` go nie wolal -> uzytkownik z waznym cookie po wygasnieciu sesji nadal widzial formularz. Backend (`AuthService::REMEMBER_DAYS=30`, httponly, SameSite=Lax, hash SHA-256 w `users.remember_token`) byl OK.
+- Bug "label pod checkboxem": rownosc specyficznosci 0,1,0 + pozniejsza regula `.form-field { display: grid }` (linia 128) nadpisywala `.remember-field { display: flex }` (linia 104).
+
+### Wplyw
+- Brak zmian schematu DB, brak zmian kontraktow API, brak zmian w innych widokach.
+- Plan: `.paul/plans/20260520-1200-fix-login-page-and-remember-me/PLAN.md`, SUMMARY: `.paul/plans/20260520-1200-fix-login-page-and-remember-me/SUMMARY.md`.
+
## 2026-05-19 — Dekompozycja DeliveryStatus (fasada + 3 wspolpracownikow)
### Co
diff --git a/.paul/governance/governance_2026-05-20.jsonl b/.paul/governance/governance_2026-05-20.jsonl
new file mode 100644
index 0000000..8828ccd
--- /dev/null
+++ b/.paul/governance/governance_2026-05-20.jsonl
@@ -0,0 +1,7 @@
+{"ts":"2026-05-20T06:23:51Z","tool":"Bash","cmd":"mkdir -p .paul/plans/20260520-1200-fix-login-page-and-remember-me\",\"description\":\"Create plan directory\"},\"tool_response\":{\"stdout\":\"\",\"stderr\":\"\",\"interrupted\":false,\"isImage\":fals","cwd":"/c/visual-studio-code/projekty/orderPRO"}
+{"ts":"2026-05-20T06:25:19Z","tool":"Write","file":"C:\\\\visual-studio-code\\\\projekty\\\\orderPRO\\\\.paul\\\\plans\\\\20260520-1200-fix-login-page-and-remember-me\\\\PLAN.md","cwd":"/c/visual-studio-code/projekty/orderPRO"}
+{"ts":"2026-05-20T06:25:32Z","tool":"Edit","file":"C:\\\\visual-studio-code\\\\projekty\\\\orderPRO\\\\.paul\\\\STATE.md","cwd":"/c/visual-studio-code/projekty/orderPRO"}
+{"ts":"2026-05-20T06:27:34Z","tool":"Edit","file":"C:\\\\visual-studio-code\\\\projekty\\\\orderPRO\\\\resources\\\\lang\\\\pl.php","cwd":"/c/visual-studio-code/projekty/orderPRO"}
+{"ts":"2026-05-20T06:27:40Z","tool":"Edit","file":"C:\\\\visual-studio-code\\\\projekty\\\\orderPRO\\\\resources\\\\views\\\\auth\\\\login.php","cwd":"/c/visual-studio-code/projekty/orderPRO"}
+{"ts":"2026-05-20T06:27:45Z","tool":"Edit","file":"C:\\\\visual-studio-code\\\\projekty\\\\orderPRO\\\\resources\\\\scss\\\\login.scss","cwd":"/c/visual-studio-code/projekty/orderPRO"}
+{"ts":"2026-05-20T06:27:54Z","tool":"Bash","cmd":"npx --yes sass --style=compressed --no-source-map resources/scss/login.scss public/assets/css/login.css 2>&1 | tail -20\",\"description\":\"Build login CSS\"},\"tool_response\":{\"stdout\":\"\",\"stde","cwd":"/c/visual-studio-code/projekty/orderPRO"}
diff --git a/.paul/plans/20260520-1200-fix-login-page-and-remember-me/PLAN.md b/.paul/plans/20260520-1200-fix-login-page-and-remember-me/PLAN.md
new file mode 100644
index 0000000..25a8830
--- /dev/null
+++ b/.paul/plans/20260520-1200-fix-login-page-and-remember-me/PLAN.md
@@ -0,0 +1,225 @@
+---
+plan_id: 20260520-1200-fix-login-page-and-remember-me
+title: Strona logowania - usuniecie subtitle, inline checkbox "Zapamietaj mnie" (30 dni) + naprawa auto-logowania
+storage: plan-first
+legacy_phase: null
+created: 2026-05-20T12:00:00+02:00
+status: planned
+type: execute
+autonomous: true
+delegation: auto
+files_modified:
+ - resources/views/auth/login.php
+ - resources/lang/pl.php
+ - resources/scss/login.scss
+ - public/assets/css/login.css
+ - src/Modules/Auth/AuthController.php
+quality_radar: ok
+---
+
+ ...
` |
+| `resources/lang/pl.php` | `auth.login.remember_me` -> "Zapamiętaj mnie (30 dni)" |
+| `resources/scss/login.scss` | selektor `.remember-field` -> `.form-field.remember-field` (wyzsza specyficznosc bije `.form-field { display: grid }`) |
+| `public/assets/css/login.css` | rebuild `sass --style=compressed` |
+| `src/Modules/Auth/AuthController.php` | `showLogin` woluje `loginFromRememberToken()` przed renderem |
+
+## Diagnoza root cause "Zapamietaj mnie nie dziala"
+
+Backend byl poprawny:
+- `AuthService::REMEMBER_DAYS = 30`,
+- cookie `remember_token`: `httponly=true`, `samesite=Lax`, `secure` zalezne od HTTPS,
+- hash SHA-256 zapisany w `users.remember_token`,
+- `AuthMiddleware` poprawnie woluje `loginFromRememberToken()` na route'ach chronionych.
+
+Bug: **`AuthController::showLogin` nie konsumowal cookie remember**. Gdy uzytkownikowi wygasala sesja PHP (`PHPSESSID`) i wracal bezposrednio na `/login`, formularz byl renderowany pomimo waznego cookie - zaden middleware nie chronil samego `/login`. Fix: dodanie `|| $this->auth->loginFromRememberToken()` w warunku redirectu.
+
+## Diagnoza root cause "label pod checkboxem"
+
+W `login.scss` regula `.form-field { display: grid; gap: 7px; }` (linia 128) byla zdefiniowana **po** `.remember-field { display: flex; ... }` (linia 104). Element ma obie klasy (`form-field form-field--inline remember-field`), wiec przy rownej specyficznosci pojedynczej klasy wygrywa pozniejsza regula -> grid -> stack. Fix: zmiana selektora na kompozytowy `.form-field.remember-field` (specyficznosc 0,2,0 vs 0,1,0).
+
+## Weryfikacja
+
+- `php -l` na wszystkich modyfikowanych plikach PHP: clean.
+- Compiled CSS zawiera `.form-field.remember-field{display:flex;align-items:center;gap:8px}`.
+- Brak trafien na `login-subtitle` w `resources/views/auth/login.php`.
+- Sass build wykonany przez `npx sass`.
+
+## Smoke test (do wykonania recznie)
+
+1. `/login` - brak podtytulu, checkbox + "Zapamiętaj mnie (30 dni)" w jednej linii.
+2. Login z checkboxem -> wyczysc `PHPSESSID` -> wejdz `/login` -> redirect na `/settings/users`.
+
+## Deferrals
+
+- Rotacja remember tokenu po uzyciu (`loginFromRememberToken` nie odswieza tokenu). Odlozone.
+- Synchronizacja literalu "30" miedzy `AuthService::REMEMBER_DAYS` a stringiem PL pozostaje manualna - akceptowalne ryzyko.
+
+## Quality Radar - delty
+
+Brak nowych ryzyk. `auth/login.php` (47 -> 46 lin.), `AuthController.php` (89 -> 89 lin., zmiana semantyczna 1 linii), `login.scss` (selektor kompozytowy). Skala zmian: pojedyncze linie.
diff --git a/public/assets/css/login.css b/public/assets/css/login.css
index 16e87b8..2c0fea1 100644
--- a/public/assets/css/login.css
+++ b/public/assets/css/login.css
@@ -1 +1 @@
-:root{--c-primary: #6690f4;--c-primary-dark: #3164db;--c-action-primary: #0f766e;--c-action-primary-dark: #0b5f59;--c-bg: #f4f6f9;--c-surface: #ffffff;--c-text: #4e5e6a;--c-text-strong: #2d3748;--c-muted: #718096;--c-border: #b0bec5;--c-danger: #cc0000;--focus-ring: 0 0 0 3px rgba(102, 144, 244, 0.15);--focus-ring-action: 0 0 0 3px rgba(15, 118, 110, 0.18);--shadow-card: 0 1px 4px rgba(0, 0, 0, 0.06)}.btn{display:inline-flex;align-items:center;justify-content:center;min-height:34px;padding:6px 12px;border:1px solid rgba(0,0,0,0);border-radius:8px;font:inherit;font-weight:600;text-decoration:none;cursor:pointer;transition:background-color .2s ease,border-color .2s ease,color .2s ease,transform .1s ease}.btn--primary{color:#fff;background:var(--c-action-primary)}.btn--primary:hover{background:var(--c-action-primary-dark)}.btn--secondary{color:var(--c-text-strong);border-color:var(--c-border);background:var(--c-surface)}.btn--secondary:hover{border-color:#cbd5e0;background:#f8fafc}.btn--danger{color:#fff;border-color:#b91c1c;background:#dc2626}.btn--danger:hover{border-color:#991b1b;background:#b91c1c}.btn--sm{min-height:28px;padding:3px 10px;font-size:12px}.btn--block{width:100%}.btn--disabled{opacity:.3;cursor:not-allowed;pointer-events:none}.btn:active{transform:translateY(1px)}.btn:focus-visible{outline:none;box-shadow:var(--focus-ring-action);border-color:var(--c-action-primary)}.form-control{width:100%;min-height:30px;border:1px solid var(--c-border);border-radius:6px;padding:4px 8px;font:inherit;color:var(--c-text-strong);background:#fff;transition:border-color .2s ease,box-shadow .2s ease}.form-control:focus{outline:none;border-color:var(--c-primary);box-shadow:var(--focus-ring)}.input{min-height:34px;border:1px solid var(--c-border);border-radius:8px;padding:5px 10px;font:inherit;color:var(--c-text-strong);background:#fff}.input--sm{min-height:28px;padding:3px 8px;font-size:12px}.flash{padding:8px 12px;border-radius:6px;font-size:13px}.flash--success{border:1px solid #b7ebcf;background:#f0fff6;color:#0f6b39}.flash--error{border:1px solid #fed7d7;background:#fff5f5;color:var(--c-danger)}.alert{display:flex;align-items:flex-start;gap:10px;padding:12px 14px;border-radius:8px;border:1px solid rgba(0,0,0,0);font-size:13px;min-height:44px;line-height:1.4}.alert__icon{flex:0 0 18px;display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;line-height:1;color:inherit}.alert__icon svg{width:18px;height:18px;display:block}.alert__body{flex:1;min-width:0;word-break:break-word}.alert__dismiss{flex:0 0 auto;margin-left:auto;align-self:flex-start;background:rgba(0,0,0,0);border:0;padding:2px 6px;cursor:pointer;color:inherit;opacity:.55;font-size:16px;line-height:1;border-radius:4px;transition:opacity .15s ease,background-color .15s ease}.alert__dismiss:hover,.alert__dismiss:focus-visible{opacity:1;background-color:rgba(0,0,0,.06);outline:none}.alert--info{border-color:#bfdbfe;background:#eff6ff;color:#1e3a8a}.alert--danger{border-color:#fed7d7;background:#fff5f5;color:var(--c-danger)}.alert--success{border-color:#b7ebcf;background:#f0fff6;color:#0f6b39}.alert--warning{border-color:#f7dd8b;background:#fff8e8;color:#815500}.alerts-stack{display:flex;flex-direction:column;gap:8px;margin-bottom:12px}.form-field{display:grid;gap:5px}.field-label{color:var(--c-text-strong);font-size:13px;font-weight:600}.table-wrap{width:100%;overflow-x:auto}.table-wrap--visible{overflow:visible !important;overflow-x:visible !important}.table{width:100%;border-collapse:collapse;background:var(--c-surface)}.table th,.table td{padding:10px 12px;border-bottom:1px solid var(--c-border);text-align:left}.table th{color:var(--c-text-strong);font-weight:700;background:#f8fafc}.table--details th{white-space:nowrap}.table--details th:first-child,.table--details td:first-child{width:36px;text-align:center}.pagination{display:flex;align-items:center;flex-wrap:wrap;gap:8px}.pagination__item{display:inline-flex;align-items:center;justify-content:center;min-width:36px;height:36px;padding:0 10px;border-radius:8px;border:1px solid var(--c-border);color:var(--c-text-strong);background:var(--c-surface);text-decoration:none;font-weight:600}.pagination__item:hover{border-color:#cbd5e0;background:#f8fafc}.pagination__item.is-active{border-color:var(--c-primary);color:var(--c-primary);background:#edf2ff}.receipt-header{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:16px;padding-bottom:12px;border-bottom:2px solid var(--c-text-strong)}.receipt-header__seller{flex:1}.receipt-header__seller strong{font-size:14px;display:block;margin-bottom:4px}.receipt-header__title{text-align:right}.receipt-header__title h1{font-size:18px;font-weight:700;margin-bottom:4px}.receipt-print{max-width:700px;margin:0 auto}@media print{.receipt-print{max-width:100%}}.copy-name-row{display:flex;align-items:center;gap:6px}.copy-btn-inline{display:inline-flex;align-items:center;justify-content:center;background:none;border:none;padding:2px;cursor:pointer;color:var(--c-text-muted, #999);border-radius:3px;transition:color .15s;flex-shrink:0}.copy-btn-inline:hover{color:var(--c-primary)}.copy-btn-inline .check-icon{color:var(--c-action-primary)}:root{--shadow-card: 0 20px 50px rgba(22, 34, 58, 0.14)}*{box-sizing:border-box}html,body{min-height:100%}body{margin:0;font-family:"Roboto","Segoe UI",sans-serif;color:var(--c-text);background:var(--c-bg);overflow-x:hidden}.bg-orb{position:fixed;width:460px;height:460px;border-radius:999px;filter:blur(28px);z-index:0;opacity:.45;pointer-events:none}.bg-orb-left{top:-200px;left:-180px;background:radial-gradient(circle, rgba(102, 144, 244, 0.48) 0%, rgba(102, 144, 244, 0) 70%)}.bg-orb-right{right:-200px;bottom:-220px;background:radial-gradient(circle, rgba(30, 42, 58, 0.36) 0%, rgba(30, 42, 58, 0) 70%)}.login-page{min-height:100vh;display:grid;place-items:center;padding:32px 20px;position:relative;z-index:1}.login-card{width:100%;max-width:430px;background:var(--c-surface);border:1px solid var(--c-border);border-radius:12px;box-shadow:var(--shadow-card);padding:34px 30px 28px;animation:card-enter 420ms ease-out}.login-header{margin-bottom:24px}.login-badge{display:inline-block;margin:0 0 14px;padding:5px 12px;border-radius:999px;border:1px solid #d9e2ff;background:#eef2ff;color:#3f5faf;font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.06em}h1{margin:0;color:var(--c-text-strong);font-size:clamp(1.6rem,2.5vw,1.9rem);line-height:1.15;font-weight:700}.login-subtitle{margin:10px 0 0;font-size:15px;line-height:1.55;color:var(--c-muted)}.login-alert{margin-bottom:18px}.remember-field{display:flex;align-items:center;gap:8px}.remember-field input[type=checkbox]{width:16px;height:16px;accent-color:var(--c-primary, #4f6ef7);cursor:pointer}.remember-field .field-label{font-weight:400;cursor:pointer;user-select:none}.login-form{display:grid;gap:16px}.form-field{display:grid;gap:7px}.field-label{color:var(--c-text-strong);font-size:13px;font-weight:600}.login-form .form-control{min-height:46px;padding:0 14px;border-width:2px}.login-form .form-control::placeholder{color:#cbd5e0}.login-submit{margin-top:2px;font-size:15px;min-height:48px}@keyframes card-enter{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}@media(max-width: 640px){.login-page{padding:18px 14px}.login-card{padding:24px 20px 20px}h1{font-size:1.55rem}}
+:root{--c-primary: #6690f4;--c-primary-dark: #3164db;--c-action-primary: #0f766e;--c-action-primary-dark: #0b5f59;--c-bg: #f4f6f9;--c-surface: #ffffff;--c-text: #4e5e6a;--c-text-strong: #2d3748;--c-muted: #718096;--c-border: #b0bec5;--c-danger: #cc0000;--focus-ring: 0 0 0 3px rgba(102, 144, 244, 0.15);--focus-ring-action: 0 0 0 3px rgba(15, 118, 110, 0.18);--shadow-card: 0 1px 4px rgba(0, 0, 0, 0.06)}.btn{display:inline-flex;align-items:center;justify-content:center;min-height:34px;padding:6px 12px;border:1px solid rgba(0,0,0,0);border-radius:8px;font:inherit;font-weight:600;text-decoration:none;cursor:pointer;transition:background-color .2s ease,border-color .2s ease,color .2s ease,transform .1s ease}.btn--primary{color:#fff;background:var(--c-action-primary)}.btn--primary:hover{background:var(--c-action-primary-dark)}.btn--secondary{color:var(--c-text-strong);border-color:var(--c-border);background:var(--c-surface)}.btn--secondary:hover{border-color:#cbd5e0;background:#f8fafc}.btn--danger{color:#fff;border-color:#b91c1c;background:#dc2626}.btn--danger:hover{border-color:#991b1b;background:#b91c1c}.btn--sm{min-height:28px;padding:3px 10px;font-size:12px}.btn--block{width:100%}.btn--disabled{opacity:.3;cursor:not-allowed;pointer-events:none}.btn:active{transform:translateY(1px)}.btn:focus-visible{outline:none;box-shadow:var(--focus-ring-action);border-color:var(--c-action-primary)}.form-control{width:100%;min-height:30px;border:1px solid var(--c-border);border-radius:6px;padding:4px 8px;font:inherit;color:var(--c-text-strong);background:#fff;transition:border-color .2s ease,box-shadow .2s ease}.form-control:focus{outline:none;border-color:var(--c-primary);box-shadow:var(--focus-ring)}.input{min-height:34px;border:1px solid var(--c-border);border-radius:8px;padding:5px 10px;font:inherit;color:var(--c-text-strong);background:#fff}.input--sm{min-height:28px;padding:3px 8px;font-size:12px}.flash{padding:8px 12px;border-radius:6px;font-size:13px}.flash--success{border:1px solid #b7ebcf;background:#f0fff6;color:#0f6b39}.flash--error{border:1px solid #fed7d7;background:#fff5f5;color:var(--c-danger)}.alert{display:flex;align-items:flex-start;gap:10px;padding:12px 14px;border-radius:8px;border:1px solid rgba(0,0,0,0);font-size:13px;min-height:44px;line-height:1.4}.alert__icon{flex:0 0 18px;display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;line-height:1;color:inherit}.alert__icon svg{width:18px;height:18px;display:block}.alert__body{flex:1;min-width:0;word-break:break-word}.alert__dismiss{flex:0 0 auto;margin-left:auto;align-self:flex-start;background:rgba(0,0,0,0);border:0;padding:2px 6px;cursor:pointer;color:inherit;opacity:.55;font-size:16px;line-height:1;border-radius:4px;transition:opacity .15s ease,background-color .15s ease}.alert__dismiss:hover,.alert__dismiss:focus-visible{opacity:1;background-color:rgba(0,0,0,.06);outline:none}.alert--info{border-color:#bfdbfe;background:#eff6ff;color:#1e3a8a}.alert--danger{border-color:#fed7d7;background:#fff5f5;color:var(--c-danger)}.alert--success{border-color:#b7ebcf;background:#f0fff6;color:#0f6b39}.alert--warning{border-color:#f7dd8b;background:#fff8e8;color:#815500}.alerts-stack{display:flex;flex-direction:column;gap:8px;margin-bottom:12px}.form-field{display:grid;gap:5px}.field-label{color:var(--c-text-strong);font-size:13px;font-weight:600}.table-wrap{width:100%;overflow-x:auto}.table-wrap--visible{overflow:visible !important;overflow-x:visible !important}.table{width:100%;border-collapse:collapse;background:var(--c-surface)}.table th,.table td{padding:10px 12px;border-bottom:1px solid var(--c-border);text-align:left}.table th{color:var(--c-text-strong);font-weight:700;background:#f8fafc}.table--details th{white-space:nowrap}.table--details th:first-child,.table--details td:first-child{width:36px;text-align:center}.pagination{display:flex;align-items:center;flex-wrap:wrap;gap:8px}.pagination__item{display:inline-flex;align-items:center;justify-content:center;min-width:36px;height:36px;padding:0 10px;border-radius:8px;border:1px solid var(--c-border);color:var(--c-text-strong);background:var(--c-surface);text-decoration:none;font-weight:600}.pagination__item:hover{border-color:#cbd5e0;background:#f8fafc}.pagination__item.is-active{border-color:var(--c-primary);color:var(--c-primary);background:#edf2ff}.receipt-header{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:16px;padding-bottom:12px;border-bottom:2px solid var(--c-text-strong)}.receipt-header__seller{flex:1}.receipt-header__seller strong{font-size:14px;display:block;margin-bottom:4px}.receipt-header__title{text-align:right}.receipt-header__title h1{font-size:18px;font-weight:700;margin-bottom:4px}.receipt-print{max-width:700px;margin:0 auto}@media print{.receipt-print{max-width:100%}}.copy-name-row{display:flex;align-items:center;gap:6px}.copy-btn-inline{display:inline-flex;align-items:center;justify-content:center;background:none;border:none;padding:2px;cursor:pointer;color:var(--c-text-muted, #999);border-radius:3px;transition:color .15s;flex-shrink:0}.copy-btn-inline:hover{color:var(--c-primary)}.copy-btn-inline .check-icon{color:var(--c-action-primary)}:root{--shadow-card: 0 20px 50px rgba(22, 34, 58, 0.14)}*{box-sizing:border-box}html,body{min-height:100%}body{margin:0;font-family:"Roboto","Segoe UI",sans-serif;color:var(--c-text);background:var(--c-bg);overflow-x:hidden}.bg-orb{position:fixed;width:460px;height:460px;border-radius:999px;filter:blur(28px);z-index:0;opacity:.45;pointer-events:none}.bg-orb-left{top:-200px;left:-180px;background:radial-gradient(circle, rgba(102, 144, 244, 0.48) 0%, rgba(102, 144, 244, 0) 70%)}.bg-orb-right{right:-200px;bottom:-220px;background:radial-gradient(circle, rgba(30, 42, 58, 0.36) 0%, rgba(30, 42, 58, 0) 70%)}.login-page{min-height:100vh;display:grid;place-items:center;padding:32px 20px;position:relative;z-index:1}.login-card{width:100%;max-width:430px;background:var(--c-surface);border:1px solid var(--c-border);border-radius:12px;box-shadow:var(--shadow-card);padding:34px 30px 28px;animation:card-enter 420ms ease-out}.login-header{margin-bottom:24px}.login-badge{display:inline-block;margin:0 0 14px;padding:5px 12px;border-radius:999px;border:1px solid #d9e2ff;background:#eef2ff;color:#3f5faf;font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.06em}h1{margin:0;color:var(--c-text-strong);font-size:clamp(1.6rem,2.5vw,1.9rem);line-height:1.15;font-weight:700}.login-subtitle{margin:10px 0 0;font-size:15px;line-height:1.55;color:var(--c-muted)}.login-alert{margin-bottom:18px}.form-field.remember-field{display:flex;align-items:center;gap:8px}.form-field.remember-field input[type=checkbox]{width:16px;height:16px;accent-color:var(--c-primary, #4f6ef7);cursor:pointer}.form-field.remember-field .field-label{font-weight:400;cursor:pointer;user-select:none}.login-form{display:grid;gap:16px}.form-field{display:grid;gap:7px}.field-label{color:var(--c-text-strong);font-size:13px;font-weight:600}.login-form .form-control{min-height:46px;padding:0 14px;border-width:2px}.login-form .form-control::placeholder{color:#cbd5e0}.login-submit{margin-top:2px;font-size:15px;min-height:48px}@keyframes card-enter{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}@media(max-width: 640px){.login-page{padding:18px 14px}.login-card{padding:24px 20px 20px}h1{font-size:1.55rem}}
diff --git a/resources/lang/pl.php b/resources/lang/pl.php
index 606fd68..be55d38 100644
--- a/resources/lang/pl.php
+++ b/resources/lang/pl.php
@@ -99,7 +99,7 @@ return [
'title' => 'Logowanie',
'heading' => 'Panel zarządzania zamówieniami',
'subtitle' => 'Zaloguj się, aby przejść do obsługi zamówień i wysyłek.',
- 'remember_me' => 'Zapamiętaj mnie',
+ 'remember_me' => 'Zapamiętaj mnie (30 dni)',
'email_label' => 'Email',
'email_placeholder' => 'np. admin@firma.pl',
'password_label' => 'Hasło',
diff --git a/resources/scss/login.scss b/resources/scss/login.scss
index 4ad19bc..411febf 100644
--- a/resources/scss/login.scss
+++ b/resources/scss/login.scss
@@ -101,7 +101,7 @@ h1 {
margin-bottom: 18px;
}
-.remember-field {
+.form-field.remember-field {
display: flex;
align-items: center;
gap: 8px;
diff --git a/resources/views/auth/login.php b/resources/views/auth/login.php
index 0c38a7d..9719526 100644
--- a/resources/views/auth/login.php
+++ b/resources/views/auth/login.php
@@ -2,7 +2,6 @@
= $e($t('brand.name_full')) ?> = $e($t('auth.login.subtitle')) ?>= $e($t('auth.login.heading')) ?>
-