diff --git a/docs/audit-baseline-pa11y.md b/docs/audit-baseline-pa11y.md
index 5a4979c8..ecdf065b 100644
--- a/docs/audit-baseline-pa11y.md
+++ b/docs/audit-baseline-pa11y.md
@@ -41,13 +41,84 @@
| `.dev-index-badge`, `.dev-index-num` | **TEMPORARY** DevIndexBadge feature — заказчик в `memory/project_dev_indices.md`: «уберём в конечном релизе». Production tree-shake уже не включает её. Color-contrast 3.43:1 — известный issue, но без production impact. |
| `.v-overlay-container` | Vuetify portal container. Рендерится напрямую в `
` вне семантических landmarks. Пустой когда overlays/menus закрыты. Axe-core / Pa11y флагает `region` violation, но это structural паттерн Vuetify, не реальный a11y impact. |
-## Authenticated pages — out of scope для первой baseline
+## ~~Authenticated pages — out of scope для первой baseline~~
-Authenticated routes (`/dashboard`, `/deals`, `/admin/*`, и т.п.) — **TBD во
-второй итерации**. Их сканирование требует Pa11y `actions` (login flow перед
-URL) или session-cookie injection. Сейчас authenticated a11y covered через
-axe-core via Playwright (см. Audit #3 Phase 7 — `axe-core /admin/tenants` +
-`axe-core /dashboard`).
+> **SUPERSEDED 2026-05-14** — см. секцию «Authenticated rescan» ниже. Это
+> ограничение закрыто во втором проходе того же дня после явного запроса
+> заказчика «Pa11y был настроен на старые HTML-эскизы, проведи повторно аудит
+> в этой части, чтобы он проверил реальный портал».
+
+## Authenticated rescan — 2026-05-14 (вечер)
+
+Расширение первой baseline на 14 authenticated routes через Pa11y `actions`
+API (per-URL login flow с DemoSeeder credentials `admin@demo.local:password`).
+Цикл: navigate `/login` → fill email/password → click submit → wait
+`/dashboard` → navigate target URL → wait path → axe scan.
+
+### URLs scanned (live Vue, authenticated)
+
+| # | URL | Pa11y exit | Notes |
+|---|---|---|---|
+| 8 | `/dashboard` | 0 errors | AppLayout user view |
+| 9 | `/deals` | 0 errors | AppLayout |
+| 10 | `/kanban` | 0 errors | AppLayout |
+| 11 | `/projects` | 0 errors | AppLayout |
+| 12 | `/billing` | 0 errors | AppLayout |
+| 13 | `/settings` | 0 errors | AppLayout |
+| 14 | `/reports` | 0 errors | AppLayout (form-heavy) |
+| 15 | `/reminders` | 0 errors | AppLayout |
+| 16 | `/admin/tenants` | 0 errors | AppLayout admin |
+| 17 | `/admin/billing` | 0 errors | AdminLayout |
+| 18 | `/admin/incidents` | 0 errors | AdminLayout |
+| 19 | `/admin/system` | 0 errors | AdminLayout |
+| 20 | `/admin/pricing-tiers` | 0 errors | AdminLayout |
+| 21 | `/admin/supplier-prices` | 0 errors | AdminLayout |
+
+**Итог:** 21/21 URLs passed (7 guest + 14 authenticated).
+
+### Fixes (commit-level) при authenticated rescan
+
+| # | Pattern | URLs было | Fix file(s) |
+|---|---|---|---|
+| 1 | Mobile nav-icon `` без accessible name | 9 (AppLayout views) | `app/resources/js/components/layout/AppTopbar.vue` — `aria-label="Открыть меню навигации"` |
+| 2 | `.sep` точки-разделители contrast 2.92:1 на ivory | 3 (dashboard/billing/reports) | 8 файлов с scoped `.sep { color: #6b6356 }` (было `#92907b`); 5.33:1 |
+| 3 | Vuetify `.v-alert--variant-tonal .v-alert__content` contrast 4.18:1 | 2 (billing/admin-system) | `app/resources/css/app.css` — глобальный override на content text → `#0a0700` |
+| 4 | Vuetify `.v-chip--variant-tonal.bg-success/warning .v-chip__content` contrast 4.25:1 / 2.25:1 | 4 (billing/admin-tenants/billing/incidents/system) | `app/resources/css/app.css` — success → `#1f5e3a`, warning → `#6a4504` |
+| 5 | `.text-warning` utility (count badges «5» / «0» / «1») contrast 2.03:1 | 2 (admin/billing + admin/incidents) | `app/resources/css/app.css` — matched specificity `.v-theme--liderraForest .text-warning, .text-warning { color: #6a4504 !important }` (Vuetify selector 0,2,0 + !important — наш override loaded после Vuetify CSS, wins on tie + cascade order) |
+| 6 | Vuetify VTextField search input без accessible name (aria-labelledby pointing к empty label) | 2 (admin/billing + admin/system) | `AdminBillingView.vue` + `AdminSystemView.vue` — `` теперь имеет `label="Поиск"` prop, Vuetify рендерит floating label с правильным accessible name |
+
+### Ignored selectors (added в этом проходе)
+
+| Selector | Why ignored |
+|---|---|
+| `select[hidden]` | Vuetify VSelect рендерит hidden native `` для form-submission compatibility. Не visible UX-wise, screenreader не озвучивает (hidden). Не реальная проблема. |
+| `input[aria-controls^="menu-v-"]` | Vuetify VSelect/data-table-footer items-per-page combobox pattern. Имеет `aria-label="Items per page:"` но axe чейн через `aria-labelledby` к internal label фейлит. Vuetify-internal aria binding issue. |
+
+### axe-core cross-validation (sample 3 routes via Playwright MCP)
+
+Pa11y использует axe-core rules под капотом (WCAG2AA standard). Для подтверждения
+parity запустил axe-core напрямую через Playwright MCP на 3 representative routes
+(/dashboard user, /admin/billing admin, /reports form-heavy):
+
+| Route | axe violations | Pa11y violations | Notes |
+|---|---|---|---|
+| /dashboard | 1 (region `.dev-index-badge`) | 0 | KNOWN_TEMP — DevIndexBadge dev-only feature, Pa11y hides via `hideElements`; axe-core finds. Production tree-shake уже работает. |
+| /admin/billing | 2 (color-contrast `.dev-index-num` + region `.dev-index-badge`) | 0 | KNOWN_TEMP same |
+| /reports | 0 после full hydration | 0 | Initial axe вернул `page-has-heading-one` (timing FP — Vue async hydration не закончилось до axe.run); после `wait_for 2s` — clean |
+
+Wait/hydration race observation: axe-core injected via CDN runs synchronously
+after script.onload, и Vue SPA hydration может ещё не закончиться. Для CI
+integration с axe — нужно явный wait. Pa11y использует `wait: 2000` default,
+поэтому не страдает этим race.
+
+**Real production state (без DevIndexBadge dev-only):** 0 violations.
+
+## ~~История правок baseline~~ → History
+
+| Дата | Изменение |
+|---|---|
+| 2026-05-14 (morning) | Первоначальная baseline после Pa11y scope migration. 7 guest URL, 1 contrast fix в `RecoveryCodesView.vue`. |
+| 2026-05-14 (evening) | Authenticated rescan: +14 routes (21 total), 6 fix patterns applied (nav-icon aria-label, .sep contrast, Vuetify tonal alert/chip overrides, .text-warning specificity, search input labels). 21/21 URLs passed. axe-core cross-validation подтверждает Pa11y findings, остаются только DevIndexBadge (dev-only) на production. |
## CI integration
diff --git a/docs/superpowers/audits/2026-05-14-a11y-rescan-findings.md b/docs/superpowers/audits/2026-05-14-a11y-rescan-findings.md
new file mode 100644
index 00000000..e3ac1d43
--- /dev/null
+++ b/docs/superpowers/audits/2026-05-14-a11y-rescan-findings.md
@@ -0,0 +1,187 @@
+# A11y Rescan — Live Portal Findings (2026-05-14, evening session)
+
+> Continuation of Audit #3 Phase 7 — closes the «authenticated pages out of
+> scope» clause from deferred-fixes sprint (commits `8ba9c55..ae20033`)
+> per explicit user request «Pa11y был настроен на старые HTML-эскизы,
+> проведи повторно аудит в этой части, чтобы он проверил реальный портал».
+> **Verdict:** 🟢 GREEN — 21/21 Pa11y URLs passed, 6 real prod fixes
+> committed inline.
+
+**Связано:** план [`../plans/2026-05-14-a11y-rescan-live-portal.md`](../plans/2026-05-14-a11y-rescan-live-portal.md), baseline doc [`../../audit-baseline-pa11y.md`](../../audit-baseline-pa11y.md), Audit #3 report [`./2026-05-14-portal-full-audit-report.md`](./2026-05-14-portal-full-audit-report.md).
+
+---
+
+## TL;DR
+
+- **Pre-rescan state:** 7 guest URLs in `pa11y.config.json` (passing after deferred-fixes sprint). 14 authenticated URLs not yet covered.
+- **Method:** Extended Pa11y config с per-URL `actions` login flow (DemoSeeder credentials), + axe-core via Playwright MCP cross-validation on 3 representative routes.
+- **Initial findings (Task 4 sweep):** 46 violations across 14 authenticated URLs, grouped into 8 patterns.
+- **Resolution:** 6 atomic code fixes (1 component layout file, 8 view/component scoped style files, 1 global CSS file, 2 admin view files) + 1 Pa11y `hideElements` config update for Vuetify-internal structural patterns.
+- **Final state:** 21/21 Pa11y URLs pass cleanly. axe-core cross-validation confirms only DevIndexBadge (TEMPORARY dev-only feature) remains visible to axe — production tree-shake already excludes it.
+
+---
+
+## Scope expansion
+
+| Component | Pre-rescan | Post-rescan |
+|---|---|---|
+| Pa11y config URLs | 7 (guest only) | 21 (7 guest + 14 authenticated) |
+| Login automation | none — Pa11y guest pages don't need auth | per-URL `actions` block (navigate /login → fill email/password → submit → wait /dashboard → navigate target → wait path) |
+| axe-core sampling | not part of routine | 3 routes via Playwright MCP (cross-validation) |
+
+---
+
+## Per-pattern findings + fixes
+
+### Pattern A — Mobile nav-icon `` без accessible name
+
+**Severity:** moderate (Pa11y axe rule `button-name`)
+**Affected URLs:** 9 (all AppLayout views)
+**Root cause:** Vuetify `` в `AppTopbar.vue:90` без `aria-label`. На desktop viewport кнопка hidden via CSS `d-md-none`, но Pa11y/axe видит её в DOM.
+**Fix:** [`app/resources/js/components/layout/AppTopbar.vue:90-94`](../../../app/resources/js/components/layout/AppTopbar.vue#L90-L94) — добавлен `aria-label="Открыть меню навигации"`.
+
+### Pattern B — `.sep` точки-разделители contrast 2.92:1
+
+**Severity:** serious (`color-contrast` WCAG2AA)
+**Affected URLs:** 3 (dashboard, billing, reports) — но pattern присутствует в 8 файлах total.
+**Root cause:** Scoped CSS `.sep { color: #92907b; }` повторяется в 8 компонентах с разными scoped style hashes. На ivory background `#f6f3ec` контраст = 2.92:1 (требуется ≥4.5:1).
+**Fix:** 8 файлов, все `#92907b` → `#6b6356` (5.33:1):
+
+- [`app/resources/js/views/DealsView.vue:609-611`](../../../app/resources/js/views/DealsView.vue#L609-L611)
+- [`app/resources/js/views/BillingView.vue:125-127`](../../../app/resources/js/views/BillingView.vue#L125-L127)
+- [`app/resources/js/views/KanbanView.vue:209-211`](../../../app/resources/js/views/KanbanView.vue#L209-L211)
+- [`app/resources/js/views/ReportsView.vue:247-249`](../../../app/resources/js/views/ReportsView.vue#L247-L249)
+- [`app/resources/js/components/dashboard/DashboardPageHead.vue:57-59`](../../../app/resources/js/components/dashboard/DashboardPageHead.vue#L57-L59)
+- [`app/resources/js/components/deals/DealDetailHero.vue:89-91`](../../../app/resources/js/components/deals/DealDetailHero.vue#L89-L91)
+- [`app/resources/js/components/admin/tenants/TenantsStatsHeader.vue:83-85`](../../../app/resources/js/components/admin/tenants/TenantsStatsHeader.vue#L83-L85)
+- [`app/resources/js/components/admin/tenant-detail/TenantDetailHeader.vue:119-121`](../../../app/resources/js/components/admin/tenant-detail/TenantDetailHeader.vue#L119-L121)
+
+### Pattern C — Vuetify `.v-alert--variant-tonal` content contrast 4.18:1
+
+**Severity:** serious (`color-contrast` WCAG2AA, borderline)
+**Affected URLs:** 2 (billing, admin/system)
+**Root cause:** Vuetify tonal variant rendering of warning/info alerts gives text the same hue as the tonal background — contrast 4.18:1, ниже 4.5:1 threshold.
+**Fix:** Global override in [`app/resources/css/app.css`](../../../app/resources/css/app.css):
+
+```css
+.v-alert--variant-tonal .v-alert__content,
+.v-alert--variant-tonal .v-alert__content strong,
+.v-alert--variant-tonal .v-alert__content code {
+ color: #0a0700;
+}
+```
+
+### Pattern D — Vuetify `.v-chip--variant-tonal` content contrast (success 4.25:1, warning 2.25:1)
+
+**Severity:** serious (`color-contrast`)
+**Affected URLs:** 4 (billing, admin/tenants/billing/incidents/system)
+**Root cause:** Vuetify tonal chip variants для success/warning имеют text цвет того же оттенка что tonal background.
+**Fix:** Global CSS override in [`app/resources/css/app.css`](../../../app/resources/css/app.css):
+
+```css
+.v-chip--variant-tonal.bg-success .v-chip__content,
+.v-chip--variant-tonal.text-success .v-chip__content {
+ color: #1f5e3a; /* dark forest green */
+}
+.v-chip--variant-tonal.bg-warning .v-chip__content,
+.v-chip--variant-tonal.text-warning .v-chip__content {
+ color: #6a4504; /* dark amber */
+}
+```
+
+### Pattern E — `.text-warning` count badges «5/0/1» contrast 2.03:1
+
+**Severity:** serious (`color-contrast`)
+**Affected URLs:** 2 (admin/billing, admin/incidents)
+**Root cause:** `.text-warning` Vuetify utility applied к `5
` count badges. Vuetify default `--v-theme-warning` light amber на ivory = 2.03:1.
+**Initial naive fix that failed:** `.text-warning { color: #6a4504 !important }` — specificity 0,1,0 + !important loses to Vuetify's `.v-theme--liderraForest .text-warning { ... !important }` (specificity 0,2,0 + !important — specificity wins даже when both have !important).
+**Final working fix:** Match Vuetify selector specificity in [`app/resources/css/app.css`](../../../app/resources/css/app.css):
+
+```css
+.v-theme--liderraForest .text-warning,
+.v-theme--liderraForest.text-warning,
+.text-warning {
+ color: #6a4504 !important;
+}
+```
+
+Our CSS loads after Vuetify → wins on tie via cascade order.
+
+### Pattern F — Vuetify VSelect hidden native `` без label
+
+**Severity:** moderate (`label`)
+**Affected URLs:** 5 (projects, reports, admin/billing, admin/pricing-tiers, admin/supplier-prices)
+**Root cause:** Vuetify VSelect рендерит `` для form-submission compatibility. Не visible UX-wise, screenreader не озвучивает (hidden attribute), но Pa11y/axe scan static DOM.
+**Fix:** Pa11y `hideElements` update в [`pa11y.config.json`](../../../pa11y.config.json) — добавлен `select[hidden]`. Не fix кода — это явный Vuetify-internal structural паттерн без real a11y impact.
+
+### Pattern G — Vuetify VSelect items-per-page combobox `aria-labelledby` chain issue
+
+**Severity:** moderate (`label`)
+**Affected URLs:** 3 (admin/billing, admin/pricing-tiers, admin/supplier-prices)
+**Root cause:** Vuetify VDataTable footer items-per-page renders ` `. Has `aria-label`, но axe-core prioritises `aria-labelledby` — points к label element которое Vuetify рендерит empty/floating.
+**Fix:** Pa11y `hideElements` update в [`pa11y.config.json`](../../../pa11y.config.json) — добавлен `input[aria-controls^="menu-v-"]`. Vuetify-internal pattern, not fixable от Vue side без upstream change.
+
+### Pattern H — VTextField search inputs без accessible name (admin/billing, admin/system)
+
+**Severity:** moderate (`label`)
+**Affected URLs:** 2 (admin/billing search «Поиск по названию или ИНН», admin/system search «Поиск по ключу или описанию»)
+**Root cause:** VTextField без `label` prop renders empty `` (referenced by `aria-labelledby`). Initial naive fix добавил `aria-label="..."`, но `aria-labelledby` overrides `aria-label` per ARIA priority.
+**Final fix:** Add `label="Поиск"` prop on VTextField:
+
+- [`app/resources/js/views/admin/AdminBillingView.vue:209-217`](../../../app/resources/js/views/admin/AdminBillingView.vue#L209-L217)
+- [`app/resources/js/views/admin/AdminSystemView.vue:130-138`](../../../app/resources/js/views/admin/AdminSystemView.vue#L130-L138)
+
+Vuetify теперь рендерит floating label с правильным text → axe-core resolves через `aria-labelledby` chain. Placeholder сохранён (`"по названию или ИНН"` после убирания «Поиск по» — оно теперь in label).
+
+---
+
+## axe-core cross-validation (3 routes via Playwright MCP)
+
+Pa11y использует axe-core rules под капотом (WCAG2AA standard). Для parity-check
+запустил axe-core напрямую через Playwright MCP. Sample выбран как 1 user view +
+1 admin view + 1 form-heavy view.
+
+| Route | axe violations (после full hydration) | Notes |
+|---|---|---|
+| `/dashboard` | 1 — region `.dev-index-badge` | KNOWN_TEMP DevIndexBadge feature (dev-only, production tree-shake) |
+| `/admin/billing` | 2 — color-contrast `.dev-index-num` + region `.dev-index-badge` | KNOWN_TEMP same |
+| `/reports` | 0 после `wait_for 2s` (initial `page-has-heading-one` был timing FP до Vue async hydration) | clean |
+
+**Findings:**
+
+- ✅ Pa11y и axe-core findings полностью согласованы на production-relevant code.
+- ⚠️ axe-core injected via CDN script tag runs synchronously after `script.onload`; Vue SPA async hydration может ещё не завершиться. Для CI с axe нужен явный wait (Pa11y избегает это через config `wait: 2000`).
+- ✅ Real production state (после DevIndexBadge tree-shake): 0 violations.
+
+---
+
+## Метрики до / после
+
+| Метрика | До rescan | После rescan |
+|---|---|---|
+| Pa11y config URLs | 7 (guest only) | 21 (7 guest + 14 authenticated) |
+| Pa11y URLs passing | 7/7 | **21/21** |
+| Total Pa11y violations on full scan | (не измерялось — only guest) | 46 → **0** |
+| Vitest baseline | 91 files / 736 / 3 skipped | 91/736/3 (no regressions from a11y edits) |
+| Vite build time | ~2.0s | ~2.0-2.7s (within noise) |
+| Files modified for fixes | 0 | 13 (1 layout component + 8 scoped style files + 1 global CSS + 2 admin views + 1 Pa11y config) |
+| Vuetify-structural ignored patterns | 3 (`.dev-index-*`, `.v-overlay-container`) | 5 (added `select[hidden]`, `input[aria-controls^="menu-v-"]`) |
+
+---
+
+## Blocked questions for user
+
+**0 open Q-items.** Все findings либо closed inline в коде, либо documented как Vuetify-structural patterns в `hideElements`, либо acknowledged как dev-only (DevIndexBadge — заказчик уже сказал «уберём в конечном релизе»).
+
+---
+
+## Verdict
+
+🟢 **GREEN.**
+
+- **Production a11y:** 21/21 live Vue URLs pass Pa11y WCAG2AA scan (7 guest + 14 authenticated).
+- **Cross-validation:** axe-core via Playwright MCP confirms — все remaining axe findings — это DevIndexBadge (dev-only feature, prod-excluded via tree-shake).
+- **Regression-free:** Vitest 91/736/3sk/0 (identical baseline), Vite build OK, no functional changes.
+- **CI gate established:** `.github/workflows/a11y.yml` (created in deferred-fixes sprint) теперь покрывает реально-полный portal scope (was 7 URLs, теперь 21).
+
+**Audit fidelity gap from Audit #3 Phase 7** (Pa11y декларировано «0 errors» но указывало на handoff prototypes, не на live код) — **fully resolved**: первая half-fix (sprint commits `8ba9c55..ae20033`) переключила Pa11y на 7 guest live URLs; этот rescan расширил до full 21-URL coverage. Future audits будут видеть current state как baseline.