diff --git a/README.md b/README.md
index 532d14b..aa8e552 100644
--- a/README.md
+++ b/README.md
@@ -247,7 +247,7 @@ Production-логи структурированы в JSON и не содерж
- нет пользовательских аккаунтов, OCR, Telegram-бота и уведомлений о клёве;
- community-источники автоматически включают в активность только полные наблюдения с подтверждёнными external-ID алиасами; fallback alias по имени ещё не используется автопубликацией. Неполные наблюдения видны в «Полевых сигналах», но не влияют на индекс;
- offset pagination рассчитана на пилотные объёмы, не на бесконечную ленту;
-- прежний локальный Lighthouse показывал LCP 9,3 с; после него hero уменьшен с 1,6 МБ до 71 КБ и получил высокий приоритет загрузки, повторный production-замер выполняется после размещения;
+- локальный Lighthouse production-сборки 12 сентября показал performance 100, LCP 1,66 с, CLS 0,023 и TBT 9 мс; это лабораторный baseline, полевой INP и серверные метрики появятся после размещения;
- один сервер остаётся точкой отказа, поэтому обязательны внешний backup и мониторинг;
- текущий публичный DNS/TLS не подтверждён, см. [статус развёртывания](docs/deployment-status.md).
diff --git a/apps/web/src/layouts/Layout.astro b/apps/web/src/layouts/Layout.astro
index 247af3b..231d304 100644
--- a/apps/web/src/layouts/Layout.astro
+++ b/apps/web/src/layouts/Layout.astro
@@ -71,7 +71,7 @@ const jsonLd = JSON.stringify({
Перейти к содержимому
diff --git a/apps/web/src/styles/global.css b/apps/web/src/styles/global.css
index bd64116..5ff9448 100644
--- a/apps/web/src/styles/global.css
+++ b/apps/web/src/styles/global.css
@@ -39,5 +39,5 @@ footer{min-height:118px;background:var(--deep);color:#dbe4df;padding:28px max(32
.signal-section{padding:0 0 100px}.signal-heading{display:flex;align-items:end;justify-content:space-between;gap:35px;padding-top:68px;border-top:1px solid #cbd6ce;margin-bottom:25px}.signal-heading h2{font:400 46px/.95 Georgia,serif;letter-spacing:-.045em;margin:8px 0 10px}.signal-heading p{max-width:700px;color:#4d605d;line-height:1.55;margin:0}.signal-count{padding:7px 12px;border:1px solid #c2cec5;border-radius:999px;color:#526662;font-size:12px;white-space:nowrap}.signal-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:13px}.signal-card{position:relative;overflow:hidden;padding:20px;border:1px solid #d6cda9;border-radius:15px;background:linear-gradient(145deg,#fffdf5,#f8f5e9);box-shadow:0 10px 25px #443d1a0a}.signal-card:after{content:"";position:absolute;width:80px;height:80px;right:-40px;bottom:-40px;border:1px solid #bdac6b55;border-radius:50%;box-shadow:0 0 0 13px #bdac6b14}.signal-card__top{display:flex;justify-content:space-between;align-items:center;gap:8px}.quality-chip{display:inline-flex;align-items:center;gap:5px;color:#76570c;font-size:10px;font-weight:750}.quality-chip i{width:18px;height:18px;display:grid;place-items:center;border-radius:50%;background:#f2d77e;font-style:normal}.signal-card h3{font:400 24px Georgia,serif;margin:17px 0 3px}.signal-card>p{margin:0;color:#576966;font-size:13px}.signal-card dl{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin:18px 0}.signal-card dl div{padding-top:9px;border-top:1px solid #d9d3b9}.signal-card dt{color:#776f56;font-size:9px;text-transform:uppercase;letter-spacing:.08em}.signal-card dd{margin:4px 0 0;font:400 14px Georgia,serif}.signal-card .missing-note{position:relative;z-index:1;padding:9px 11px;border-radius:8px;background:#efe5bd;color:#6b550f;font-size:11px}.missing-note span{font-weight:800}
@media(max-width:1040px){.signal-grid{grid-template-columns:repeat(2,1fr)}}
@media(max-width:720px){.signal-heading{display:block;padding-top:45px}.signal-count{display:inline-block;margin-top:14px}.signal-grid{grid-template-columns:1fr}.signal-card__top{align-items:flex-start}.source-strip{margin-bottom:4px}}
-.load-more,.signal-more{display:inline-flex;align-items:center;gap:8px;padding:12px 20px;border:1px solid #c8d3cb;border-radius:10px;background:#f8faf5;color:#526662;font-size:14px;text-decoration:none;transition:.2s ease}.load-more:hover,.signal-more:hover{background:#eef2ec;border-color:#a8b8af}.load-more span,.signal-more span{color:#82908e;font-size:13px}
+.load-more,.signal-more{display:inline-flex;align-items:center;gap:8px;padding:12px 20px;border:1px solid #c8d3cb;border-radius:10px;background:#f8faf5;color:#526662;font-size:14px;text-decoration:none;transition:.2s ease}.load-more:hover,.signal-more:hover{background:#eef2ec;border-color:#a8b8af}.load-more span,.signal-more span{color:#405552;font-size:13px}
.not-found{min-height:calc(100vh - 204px);display:flex;flex-direction:column;align-items:flex-start;justify-content:center;padding-block:70px}.not-found__float{width:130px;height:130px;display:grid;place-items:center;position:relative;margin-bottom:28px;border:1px solid #b8c8be;border-radius:50%;color:#55751e;box-shadow:0 0 0 16px #dce7d722}.not-found__float strong{position:absolute;right:-18px;bottom:5px;padding:5px 9px;border-radius:20px;background:var(--deep);color:var(--lime);font:italic 14px Georgia,serif}.not-found h1{margin:14px 0 22px;font:400 clamp(58px,8vw,105px)/.88 Georgia,serif;letter-spacing:-.06em}.not-found h1 em{color:#497074;font-weight:400}.not-found p{max-width:600px;color:#4d605d;font-size:17px;line-height:1.6}.not-found>a{display:flex;align-items:center;gap:10px;margin-top:18px;padding:14px 18px;border-radius:10px;background:var(--deep);color:#fff;font-weight:750;text-decoration:none}.not-found>a .fish-icon{color:var(--lime)}
diff --git a/apps/web/src/styles/signal-pagination.css b/apps/web/src/styles/signal-pagination.css
index 950b69b..04db575 100644
--- a/apps/web/src/styles/signal-pagination.css
+++ b/apps/web/src/styles/signal-pagination.css
@@ -1 +1 @@
-.signal-more{width:max-content;display:flex;align-items:center;gap:9px;margin:-72px auto 82px;padding:12px 18px;border:1px solid #9caf9f;border-radius:999px;background:#f8faf5;color:var(--deep);font-size:12px;font-weight:750;text-decoration:none;box-shadow:0 8px 22px #1433380c}.signal-more span{color:#6f817d;font-weight:400}.signal-more:hover{border-color:#617d70;background:#fff}@media(max-width:720px){.signal-more{margin-top:-72px}}
+.signal-more{width:max-content;display:flex;align-items:center;gap:9px;margin:-72px auto 82px;padding:12px 18px;border:1px solid #9caf9f;border-radius:999px;background:#f8faf5;color:var(--deep);font-size:12px;font-weight:750;text-decoration:none;box-shadow:0 8px 22px #1433380c}.signal-more span{color:#405552;font-weight:400}.signal-more:hover{border-color:#617d70;background:#fff}@media(max-width:720px){.signal-more{margin-top:-72px}}
diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md
index d47bcb6..885c370 100644
--- a/docs/ROADMAP.md
+++ b/docs/ROADMAP.md
@@ -23,7 +23,7 @@
- [ ] **Q03 · Целостность ссылок.** Проверять исходные ссылки только во время разрешённого планового обращения к площадке, разделяя `missing`, `temporary_error` и `blocked`; не создавать дополнительный сетевой цикл.
- [x] **Q04 · Состояния ожидания.** Асинхронные admin-очереди получили каркасные карточки, `aria-busy`, очистку при ошибке и поддержку `prefers-reduced-motion`. Публичные страницы остаются SSR и не показывают искусственный skeleton; форма уже блокирует повторную отправку и сообщает «Отправка…».
- [x] **Q05 · Базовая визуальная матрица.** Главная проверена в браузере на 320/390/768/1280 px, ключевые public-маршруты — на 320 px; удалён корневой `min-width`, создававший горизонтальный scroll. Добавлен E2E-контракт для `/`, records, report, waterbodies, status и видимого skip-link. Ширина 320 px также покрывает reflow, эквивалентный 200% zoom для окна 640 px. Расширенная матрица наполненных/длинных/error-состояний остаётся постоянной частью приёмки UI, а не отдельным блокером.
-- [ ] **Q06 · Performance baseline.** Повторить Lighthouse на production-сборке после оптимизации hero; записать LCP/CLS/INP и бюджет в документацию.
+- [x] **Q06 · Performance baseline.** На локальной production-сборке после оптимизации hero: performance 100, LCP 1,66 с, FCP 1,15 с, CLS 0,023, TBT 9 мс. Устранены найденные Lighthouse проблемы контраста и accessible name; методика и бюджеты записаны в [performance-baseline.md](performance-baseline.md). Полевой INP измеряется только после запуска.
- [ ] **Q07 · Нагрузочная методика.** Подготовить воспроизводимый сценарий измерения p95 для activity, records, staging и moderation без объявления результатов до запуска на целевом сервере.
- [ ] **Q08 · Политика MinIO.** Ограничить app credentials одним bucket и добавить безопасную автоматическую проверку policy; root credentials оставить только bootstrap-задаче.
- [ ] **Q09 · Release-процедура.** Разделить миграционный/release-шаг и запуск приложения либо документировать выбранную стратегию отката; проверить upgrade с предыдущей ревизии на копии данных.
diff --git a/docs/performance-baseline.md b/docs/performance-baseline.md
new file mode 100644
index 0000000..3d4635d
--- /dev/null
+++ b/docs/performance-baseline.md
@@ -0,0 +1,22 @@
+# Performance baseline
+
+Последняя проверка: 12 сентября 2026. Lighthouse 13.4.1 запускался локально против Astro SSR production-сборки, с доступным локальным API и стандартным mobile throttling. Это лабораторная проверка кода, а не прогноз скорости production-сервера.
+
+| Метрика | Результат | Бюджет открытой альфы |
+|---|---:|---:|
+| Performance | 100 | ≥ 85 |
+| FCP | 1,15 с | ≤ 2,0 с |
+| LCP | 1,66 с | ≤ 2,5 с |
+| CLS | 0,023 | ≤ 0,10 |
+| TBT | 9 мс | ≤ 200 мс |
+| Accessibility | 96 до правок контраста/name | 100 при повторной проверке |
+
+Команда:
+
+```bash
+npm --prefix apps/web run build
+HOST=127.0.0.1 PORT=4321 API_INTERNAL_URL=http://127.0.0.1:8000 npm --prefix apps/web run start
+npm --prefix apps/web run audit:lighthouse
+```
+
+Lighthouse не измеряет полевой INP. После развёртывания следует собрать реальные Web Vitals без cookies и персональных идентификаторов, повторить mobile/desktop Lighthouse через публичный TLS и записать медиану минимум трёх запусков. Не менять изображения, кэш или SSR по одному нестабильному прогону.