diff --git a/apps/web/src/pages/spots/[id].astro b/apps/web/src/pages/spots/[id].astro
index e7ccea7..29c6d00 100644
--- a/apps/web/src/pages/spots/[id].astro
+++ b/apps/web/src/pages/spots/[id].astro
@@ -1,12 +1,12 @@
---
import Layout from "../../layouts/Layout.astro";
import AtlasBreadcrumbs from "../../components/AtlasBreadcrumbs.astro";
-import SourceBadge from "../../components/SourceBadge.astro";
import CoordinateRadar from "../../components/CoordinateRadar.astro";
import TackleGlyph from "../../components/TackleGlyph.astro";
import ActivityTimeline from "../../components/ActivityTimeline.astro";
import CatchList from "../../components/CatchList.astro";
-import { activityLevel, api, ApiError, plural, type Activity, type Catch, type PaginatedActivity, type Spot } from "../../lib/api";
+import DataPassport from "../../components/DataPassport.astro";
+import { activityLevel, api, ApiError, type Activity, type Catch, type PaginatedActivity, type Spot } from "../../lib/api";
const { id } = Astro.params;
let spot: Spot | null = null, catches: Catch[] = [], activity: Activity | null = null, unavailable = false;
let timeline: { start: string; end: string; count: number }[] = [];
@@ -44,7 +44,7 @@ const breadcrumbs = spot ? { "@context": "https://schema.org", "@type": "Breadcr
Последние уловы
{catches.length ? :
Уловов пока нет
Для этой точки нет одобренных наблюдений.
}
-
+
>}
diff --git a/apps/web/src/styles/query-context.css b/apps/web/src/styles/query-context.css
index b107bb3..6163905 100644
--- a/apps/web/src/styles/query-context.css
+++ b/apps/web/src/styles/query-context.css
@@ -4,4 +4,5 @@
.query-summary__filters{display:flex;align-items:center;justify-content:flex-end;flex-wrap:wrap;gap:8px}
.query-summary__filters span{padding:6px 10px;border:1px solid #c8d3cb;border-radius:20px;background:#f8faf5;color:#526662;font-size:12px}
.query-summary__filters a{margin-left:4px;color:#4d625e;font-size:13px;text-underline-offset:3px}
+.detail-action-heading{margin:27px 0 8px;font:400 24px Georgia,serif;color:var(--lime)}
@media(max-width:720px){.query-summary{display:block;padding:16px 14px 0;width:100%}.query-summary h2{font-size:23px}.query-summary__filters{justify-content:flex-start;flex-wrap:nowrap;overflow-x:auto;padding-top:11px;scroll-snap-type:x proximity;scrollbar-width:none}.query-summary__filters::-webkit-scrollbar{display:none}.query-summary__filters span{flex:0 0 auto;scroll-snap-align:start}.query-summary__filters a{position:sticky;right:0;flex:0 0 auto;padding:6px 10px;background:var(--paper)}}
diff --git a/apps/web/tests/spot-evidence.spec.ts b/apps/web/tests/spot-evidence.spec.ts
new file mode 100644
index 0000000..85d522f
--- /dev/null
+++ b/apps/web/tests/spot-evidence.spec.ts
@@ -0,0 +1,13 @@
+import { expect, test } from "@playwright/test";
+
+test("spot detail exposes the same evidence passport as activity cards", async ({ page }) => {
+ await page.goto("/spots/vyunok-6331x6332");
+
+ const passport = page.locator(".detail-grid aside .data-passport");
+ await expect(passport).toBeVisible();
+ await expect(passport).toContainText("Свежесть");
+ await expect(passport).toContainText("Наблюдения");
+ await expect(passport).toContainText("Игроки");
+ await expect(passport).toContainText("Координаты");
+ await expect(page.getByRole("heading", { name: "Что взять" })).toBeVisible();
+});
diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md
index 3ee649b..cebb853 100644
--- a/docs/ROADMAP.md
+++ b/docs/ROADMAP.md
@@ -94,10 +94,10 @@
- [ ] **U01 · UX-контракт и scorecard.** Зафиксировать task-based навигацию, смысловой порядок ответа, словарь статусов (`fresh`, `stale`, `insufficient_data`, `blocked`, `temporary_error`) и единый scorecard: time-to-first-useful-answer, filter-to-result steps, completion rate, overflow, axe и keyboard regression. Сверить каждый публичный маршрут с контрактом; не добавлять фичи, которые не улучшают решение игрока.
- [ ] **U02 · Главный сценарий «рыба → водоём → точка → снасть».** Главная уже сохраняет рыбу, водоём, период и сортировку в shareable URL и после поиска явно показывает контекст запроса, включая мобильный режим; empty-state предлагает вернуться к полному набору данных. Осталось показать 3–5 вариантов с понятным CTA и добавить режим map. Acceptance: первый полезный вариант виден без регистрации, back/refresh сохраняют контекст, mobile не теряет фильтры.
-- [ ] **U03 · Evidence/trust card.** Для activity-карточек добавлен первый общий evidence-контракт: freshness, confidence, число наблюдений, независимые игроки, `coordinate_precision`, source badges и явный статус `Неполные данные` при малой выборке; targeted E2E проверяет эти поля. Осталось протянуть тот же контракт на spot, waterbody и tackle, добавить период выборки, completeness, конфликт источников и правило минимальной выборки для любых рекомендаций. Нельзя показывать «лучшую точку» или AI-like рекомендацию без объяснения и минимальной выборки.
+- [ ] **U03 · Evidence/trust card.** Общий evidence-контракт теперь используется и на activity-карточках, и на detail точки: freshness, confidence, число наблюдений, независимые игроки, `coordinate_precision`, source badges и явный статус `Неполные данные` при малой выборке; targeted E2E проверяет оба пути. Осталось протянуть его на waterbody и tackle, добавить период выборки, completeness, конфликт источников и правило минимальной выборки для любых рекомендаций. Нельзя показывать «лучшую точку» или AI-like рекомендацию без объяснения и минимальной выборки.
- [ ] **U04 · List/map и progressive disclosure.** List остаётся честным базовым режимом: фильтры, сортировка, URL-состояние и evidence-карточки уже работают без имитации координатной карты. Следующий шаг — единый list/map-контракт после подтверждения геометрии; на mobile карта должна открываться отдельным действием. Вторичные raw/provenance-поля не исчезают и раскрываются по запросу.
- [ ] **U05 · Mobile-first и сохранённый план рыбалки.** Добавить лёгкий сценарий сравнения и сохранения 3–5 вариантов без обязательного аккаунта: рыба, водоём, координаты, метод, наживка, свежесть, доверие и риск. Acceptance: shareable URL/print-карточка, 320/390 px, восстановление после reload, удаление локального плана без внешнего сервиса.
-- [ ] **U06 · Контентная и визуальная иерархия.** Сократить конкурирующие цифры на карточках, привести badges/source labels к одной семантике, сделать «что делать» главным текстом, а provenance — вторичным раскрываемым слоем. Провести ручной review на 5 ключевых маршрутах и проверить, что цвет не является единственным носителем статуса.
+- [ ] **U06 · Контентная и визуальная иерархия.** Для detail точки действие «Что взять» выделено отдельным заголовком, а provenance и качество собраны в общем паспорте данных; статусы дополнительно передаются текстом, не только цветом. Осталось сократить конкурирующие цифры на карточках и провести ручной review на 5 ключевых маршрутах.
- [ ] **U07 · UX-приёмка и измерения.** Добавить Playwright-контракты для полного journey, list/map, evidence states, saved plan, stale/blocked/insufficient data и share/print. Зафиксировать baseline Lighthouse/axe/CLS/INP и time-to-first-useful-answer; закрывать U01–U06 только по evidence, screenshots и обратной связи пилота.
- [ ] **Q01 · Документы источников — реестр готов, нужны первичные подтверждения.** Создан единый production-gate с атрибуцией, общим лимитом 30 минут, хранением и процедурой отзыва для RF4DB, RF4-STAT, RF4MAP, RF4 Posts и официального RF4. До открытой публикации приложить устойчивые ссылки/копии первичных разрешений, контакты, даты и отдельно подтвердить право на изображения; пустое поле блокирует соответствующий источник.