# Этап B3 — Hi-fi working specification

Дата: 2026-08-07  
Статус: `owner_accepted_for_stage_c_with_production_clearance_blockers`  
Основание: этап A, Gate B1 и Gate B2 утверждены владельцем 2026-08-05; итоговый B3 визуально принят владельцем 2026-08-07  
Следующий gate: этап C — backend specification; production implementation остаётся запрещённой до утверждения A–C и закрытия перечисленных clearance gates

## 0. Статус документа и правило правды

Этот файл — рабочий контракт и gate report B3, по которому утверждённая визуальная система B1 применяется к утверждённой UX-топологии B2. Владелец принял визуальный и UX-результат для передачи на этап C 2026-08-07. Это решение не подтверждает production rights, не превращает preview-only platform marks в разрешённые assets и не отменяет оставшиеся accessibility/physical-device проверки.

| Область | Состояние на дату документа |
|---|---|
| Product/UX scope | Утверждён на этапе A |
| Visual direction | Утверждён на B1: «Тёплая тропическая утилитарность» |
| UX topology и обязательные states | Утверждены на B2 |
| Hi-fi screens и clickable prototype | Принят владельцем для передачи на этап C: 103 состояния; результаты проверки — [`gate-b3/QA.md`](gate-b3/QA.md) |
| Фото | Основное фото заменено на owner-provided scenic JPEG из logobook; исходный поток, responsive-варианты и SHA-256 записаны, production rights требуют подтверждения владельца |
| Platform marks | Используются только в review build; production provenance gate остаётся открытым |
| Production implementation | Не разрешена до утверждения A–C |

Фактические артефакты B3:

- clickable prototype: [`gate-b3/index.html`](gate-b3/index.html);
- responsive review frame: [`gate-b3/qa-responsive.html`](gate-b3/qa-responsive.html);
- QA evidence и известные ограничения: [`gate-b3/QA.md`](gate-b3/QA.md);
- asset manifest: [`gate-b3/assets/manifest.yml`](gate-b3/assets/manifest.yml).
- постраничный desktop-аудит и reference decisions: [`gate-b3/DESKTOP-DESIGN-AUDIT.md`](gate-b3/DESKTOP-DESIGN-AUDIT.md).

Планируемые результаты B3, которые можно назвать готовыми только после фактического появления и QA:

1. responsive hi-fi clickable prototype с полным каталогом B2 `surface/screen/state`;
2. component/state inventory и handoff-аннотации;
3. accessibility annotations и keyboard flows;
4. motion specification с вариантом `prefers-reduced-motion`;
5. утверждённый набор logo/photo/platform assets с заполненным provenance manifest;
6. отчёт visual, responsive и accessibility QA.

## 1. Цель и границы B3

### 1.1. Цель

Сделать интерфейс узнаваемой частью ThaiForTravel и доказать на рабочих состояниях, что он остаётся быстрым, спокойным и понятным партнёру, а owner/admin получает плотный, но читаемый инструмент расследования. B3 полирует форму, иерархию, feedback и переходы, не меняя продуктовую модель.

### 1.2. Входит в B3

- применение B1 palette, typography, spacing, shape и elevation к каждой B2-поверхности;
- окончательная композиция обязательных компонентов и их состояний;
- responsive hi-fi на access, agent и owner/admin surfaces;
- реальные фото только после подтверждения прав и provenance;
- оригинальные platform marks только после прохождения asset gate;
- accessibility annotations, focus order, live regions и data alternatives;
- restrained motion, reduced-motion behavior и interruptibility;
- clickable navigation, state selector для review и handoff notes;
- visual regression baseline и documented QA evidence.

### 1.3. Не входит в B3

- пересмотр четырёх agent-разделов, route hierarchy или responsive topology B2;
- добавление dashboard home, commission, payout, client PII или funnel analytics;
- изменение archive/disable semantics, attribution rules, auth contract, moderation policy или CRM behavior;
- проектирование API, ERD, event model, threat model и rollout этапов C–D;
- интеграция с реальными Telegram, CRM, clipboard, download или production API;
- переписывание существующего production/prototype кода до прохождения gate.

Если hi-fi выявит UX-проблему, требующую изменения B2, работа останавливается на затронутом flow: изменение документируется как отдельный запрос на пересмотр B2, а не незаметно встраивается в B3.

## 2. Direction contract

| Параметр | Контракт B3 |
|---|---|
| Mode | `Operate`: интерфейс прежде всего помогает создать, найти, проверить и обслужить рабочий материал |
| Thesis | ThaiForTravel — тёплый и надёжный партнёрский инструмент у моря, а не postcard campaign и не холодный SaaS dashboard |
| Ownable world | Тёплый светлый canvas, уверенный sea-teal для структуры, sun-yellow только для главного действия или готового результата, реальные сцены Таиланда в редких контекстных окнах |
| Product story | Доверенный вход → одна ясная форма → атомарная пара link + QR → спокойное повторное использование → честная aggregate statistics; для owner/admin — evidence-first timeline |
| Signature pattern | В Campaign detail link и QR всегда читаются как два связанных материала одной campaign, но имеют раздельные статусы; в admin главным доказательством решения остаётся append-only timeline |
| First viewport | Agent: смысл экрана и начало CampaignForm без dashboard-плиток. Admin: очередь/контекст расследования и следующий допустимый action. Access: ценность, требования и один следующий шаг |
| Form | Light-first, warm neutrals, left-aligned hierarchy, плотные task groups с generous separators; карточка используется только когда выражает самостоятельную сущность или интерактивную границу |
| Tone | Дружелюбный русский, конкретные глаголы, без внутреннего жаргона и обещаний дохода |
| Mobile principle | Самостоятельная mobile topology, а не сжатая desktop table; все ключевые действия доступны большим пальцем и без hover |

### 2.1. Неподвижные решения B1 → B3

- dominant brand color — sea-teal; sun-yellow — один функциональный accent, а не второй декоративный брендовый цвет;
- основной режим V1 — светлый; dark tokens остаются compatibility reserve без theme switch в B3;
- единственное core-семейство — Golos Text с кириллицей и tabular numerals;
- используется существующий официальный ThaiForTravel logo; новый знак, lettermark или перерисовка не создаются;
- фотографии не входят в transactional forms, lists, statistics и admin; они допустимы только в onboarding, pending/empty и редких contextual moments;
- platform mark всегда сопровождается текстовым названием; цвет или форма не являются единственным носителем смысла;
- QR — рабочий материал с quiet zone и проверяемым scan result, а не декоративная иллюстрация.

### 2.2. Отвергнутые направления

- cobalt/lime referral styleboard и deep-navy live prototype как итоговая визуальная система;
- postcard/luxury mood, полноэкранные туристические коллажи и фото на каждом экране;
- generic cold SaaS с одинаковыми KPI-карточками, giant metric hero и вложенными cards;
- purple/blue AI gradients, neon glow, decorative glassmorphism и bounce/confetti;
- icon-only navigation, буквенные `YT/VK/TG` marks и preview SVG как финальные assets;
- смешивание agent и owner/admin в одном shell;
- возврат результата создания внутрь формы вместо отдельного Campaign detail;
- hover-only actions, toast для field errors и destructive action рядом с primary без separation.

## 3. Visual foundation application

### 3.1. Light-first color roles

| Token | Значение | Применение и ограничение |
|---|---:|---|
| `canvas` | `#F4F6F2` | Фон приложения и спокойные широкие поля |
| `surface` | `#FFFEFA` | Forms, dialogs, самостоятельные рабочие surfaces |
| `surface-sea` | `#E7F2F0` | Мягкое тематическое выделение, не фон каждого блока |
| `ink` | `#263336` | Основной текст и текст на sun-yellow |
| `muted` | `#5F6D6F` | Secondary text; не используется для disabled без отдельной проверки contrast |
| `line` | `#D8E2DF` | Dividers, control boundaries и chart grid с дополнительной QA-проверкой |
| `sea` | `#006D79` | Navigation, links, focus, selected controls, основной брендовый сигнал |
| `sea-strong` | `#005761` | Active/pressed и вторая series trend при наличии label/pattern |
| `sea-soft` | `#DFF1F1` | Selected background и quiet information state |
| `sun` | `#F2C35F` | Один primary action в контексте или готовый результат |
| `sun-soft` | `#FFF4D6` | Warning/supporting highlight, не low-contrast text surface без проверки |
| `success` | `#176F52` | Success status вместе с текстом/иконкой |
| `warning` | `#8A5B00` | Warning text/icon; для QR series — dashed line + square marker |
| `danger` | `#B94424` | Destructive/error с текстом, никогда как единственный сигнал |
| `focus` | `#006D79` | Явный focus indicator на светлых поверхностях |

Базовые подтверждённые пары: `ink/surface`, `muted/surface`, `sea/surface`, `ink/sun`. Белый текст на `sun` запрещён: его контраст недостаточен. До B3 approval отдельно измеряются hover, pressed, disabled, focus, chart/grid, photo overlay и forced-colors states; цвет из таблицы не освобождает конкретную комбинацию от проверки WCAG 2.2 AA.

Dark reserve (`#0E1A1C`, `#152427`, `#1C3034`, `#F3F7F5`, `#B6C3C1`, `#33484B`, `#54C1C8`, `#F2C35F`) в B3 используется только для проверки совместимости Telegram/browser chrome, но не оформляется как пользовательский theme.

### 3.2. Typography

- Golos Text: body/UI `400–500`, labels/actions `500–600`, headings/metrics `600–700`;
- onboarding display: `clamp(2rem, 5vw, 3.5rem)`;
- page title: `clamp(1.5rem, 2.4vw, 2rem)`;
- section title: `clamp(1.125rem, 1.5vw, 1.375rem)`;
- body/control: `clamp(.9375rem, 1vw, 1rem)` / `1rem`;
- meta text: не меньше `13px`; не используется для критичной инструкции;
- dominant metric: `clamp(2rem, 4vw, 3.25rem)` только там, где total действительно главный;
- counts, dates и chart axes используют tabular numerals;
- self-hosted WOFF2 загружается с `font-display: swap`; preload разрешён только критичному Cyrillic face, fallback — системный sans-serif.

Нельзя добавлять display accent font в core cabinet. Переносы, truncation и рост строк проверяются на реальных русских строках, при text zoom 200% и system font fallback.

### 3.3. Spacing, shape, elevation

- spacing scale: `4, 8, 12, 16, 24, 32, 48, 64px`;
- control radius: `12–14px`; item: `16px`; major panel: `20–24px`;
- full pill разрешён только status, filter chip и compact segmented control;
- minimum interactive target: `44×44px`, независимо от видимого размера glyph;
- tonal separation и dividers первичны; shadow разрешён только floating bottom nav, dialog/sheet и sticky overlap;
- border/shadow не дублируются без функциональной причины;
- между task groups больше пространства, чем между label и связанным control.

### 3.4. Layout and hierarchy

- на странице один `h1`, один dominant action в текущем task context и один явный reading start;
- рабочие группы собираются divider/spacing, а не карточкой вокруг каждого абзаца;
- primary action не повторяется одновременно в header, body и sticky footer;
- destructive action вынесен в отдельную danger zone или protected confirmation;
- длинные формы сохраняют введённые данные при recoverable error и возвращают focus к summary/первому invalid field;
- loading reserves final geometry; skeleton не появляется короткой вспышкой и не меняет структуру после ответа;
- local actions (`copy`, `download`) дают feedback рядом с trigger; `Toast` оставлен только для фонового/global результата.

### 3.5. Photo, QR and data-visual style

- фото использует natural warm sun, teal sea и реальные сцены работы агента/блогера/публикации в конкретном месте Таиланда;
- обязательны responsive crop, focal point, AVIF/WebP с fallback, `srcset`, explicit dimensions и lazy loading ниже fold;
- текст не кладётся на сложный crop без проверенного однотонного scrim и contrast annotation;
- QR выводится на чистом светлом поле с quiet zone; download preview и фактический файл проверяются минимум двумя независимыми сканерами/устройствами;
- trend total: solid sea line + circle marker; link: sea-strong solid line + label; QR: warning/sun-dark dashed line + square marker;
- chart area имеет стабильную высоту, доступное textual summary и data table; tooltip не является единственным способом прочитать значение;
- декоративные карты, псевдоданные без маркировки и 3D/chart gradients запрещены.

## 4. Hi-fi application by surface

### 4.1. Access / onboarding

- `AccessShell` существует до product shell и не показывает agent navigation;
- welcome может использовать одно подтверждённое фото как context window, но смысл и CTA остаются читаемыми без него;
- application — одна readable column; identity summary, required fields, optional channels и consent разделены spacing/dividers;
- pending/rejected/approved/suspended используют status icon + heading + plain-language consequence; status не кодируется цветом;
- desktop auth явно показывает browser/device context, одноразовость и TTL; waiting, confirmed, expired и consumed визуально различимы;
- session-expired обещает только подтверждённую сохранность формы и возвращает пользователя в безопасную точку flow.

### 4.2. Agent cabinet

- navigation содержит ровно `Создать`, `Мои ссылки`, `Статистика`, `Профиль`; `Создать` — start route approved agent;
- Create first viewport содержит intro и начало `CampaignForm`, без KPI, preview dashboard и декоративного hero;
- successful submit всегда открывает отдельный Campaign detail; форма и результат не показываются как split-screen даже на desktop;
- Campaign detail начинает с campaign identity/status, затем показывает связанную пару link + QR и раздельную availability каждого материала;
- Library на mobile — tappable items без quick actions; на desktop — rows с явными text-labeled actions;
- Statistics начинает с definition/freshness, затем показывает один total, link/QR split, trend + table и campaign breakdown;
- Profile остаётся одной содержательной колонкой; support и logout вторичны по отношению к сохранению профиля;
- archive использует protected confirmation и прямо говорит, что материалы продолжат работать; `disabled_by_owner` не маскируется под archive.

### 4.3. Owner/admin

- `AdminShell` физически и визуально отделён от agent shell; photography не используется;
- визуальная плотность выше agent surface, но row height, focus order и action labels остаются доступными;
- queue/detail master-detail допускается только с `1180px`, иначе detail — отдельный route/view;
- application moderation показывает current revision и `ModerationTimeline` до protected decision actions;
- attribution decision строится вокруг correlated append-only timeline, reason/rule и evidence references;
- status campaign и availability link/QR показаны раздельно;
- suspend, material disable, retry и reconciliation имеют consequence, reason, permission state, conflict state и idempotent submitting state;
- destructive/protected action никогда не доступен только через hover или без текстовой подписи.

## 5. Component inventory

Названия ниже — handoff vocabulary B3, а не утверждённый frontend API. Компонент считается готовым только после покрытия перечисленных states, responsive behavior и соответствующих accessibility annotations.

### 5.1. Shell, navigation and feedback

| Component | Обязательные variants/states | B3 contract |
|---|---|---|
| `AccessShell` | normal, offline, fatal | Centered readable flow без product navigation; один `main` и `h1` |
| `AgentShell` / `AppShell` | mobile, tablet, desktop, loading route | Bottom nav до `767px`, side nav с `768px`; safe-area и route focus |
| `AdminShell` | compact, tablet, desktop, permission denied | Отдельная navigation model; master-detail только `≥1180px` |
| `BottomNav` | default, current, focus-visible, safe-area | Ровно четыре icon + text items, `aria-current="page"`, targets `44×44px` |
| `SideNav` | default, current, collapsed where specified | Text labels всегда видимы; current state не только цветом |
| `PageHeader` | title, title + metadata, title + action | Один `h1`; action не дублирует текущий body primary |
| `Button` | primary, secondary, quiet, danger; hover, pressed, focus, disabled, submitting | Sun primary с ink text; pointer-down feedback; disabled не выглядит active |
| `StatusBadge` | neutral, info, success, warning, danger | Text + icon/pattern; pill разрешён, но не заменяет полное объяснение |
| `Skeleton` | row, form, chart, detail | Повторяет final geometry; объявляется как busy, внутренние shapes скрыты от AT |
| `InlineError` | field, section, recoverable page | Связан через `aria-describedby`; содержит причину и действие восстановления |
| `EmptyState` | first-use, filtered-empty, no-data | Причина различима; CTA только когда следующий шаг действительно доступен |
| `FatalState` | retry, retry unavailable | Correlation ID копируется локально; не обещает автоматическое восстановление |
| `Toast` | background success/error | Только global/background event; polite live region, не field validation |
| `ConfirmationDialog` | archive, reject, suspend, disable, retry/reconcile | Initial focus, trap, `Escape`, return focus; consequence до action |
| `TelegramAuthState` | waiting, confirmed, expired, consumed, denied | TTL и device context текстом; status message не зависит от animation |

### 5.2. Agent task components

| Component | Обязательные variants/states | B3 contract |
|---|---|---|
| `CampaignForm` | initial, validation, submitting, recoverable, fatal, offline | Один primary submit; данные сохраняются; double submit заблокирован idempotent state |
| `PlatformPicker` | none, selected, keyboard focus, invalid, disabled option | Official mark + text; native buttons/listbox semantics по реализации; полный keyboard path |
| `CampaignListItem` / `CampaignRow` | active, archived, mixed material state, loading | Mobile item целиком открывает detail; desktop row допускает labeled quick actions |
| `CampaignDetail` / `CampaignCreatedState` | active, archived, disabled_by_owner, mixed | Link и QR как связанная пара с раздельными status/action groups |
| `LinkField` | ready, copied, copy error, disabled | URL selectable; feedback рядом с copy trigger и в подходящем live region |
| `QRPreview` | generating, ready, download success/error, disabled | Quiet zone, accessible name, synthetic demo payload, scan QA; не декоративная картинка |
| `MaterialActions` | ready, busy, disabled, permission denied | Copy/download feedback локальный; action labels сохраняются на touch |
| `SearchField` / `FilterGroup` | default, active, no results, reset | Query/filter сериализуются в URL; count и active filters объявлены текстом |
| `DateRangePicker` | default, open, invalid, max-range error, disabled | Locale/date format явны; timezone `Asia/Bangkok`; не требует pointer |
| `PeriodSegmentedControl` | default, selected, focus, disabled | Native buttons + `aria-pressed`; selection не только цветом |
| `MetricSummary` | loaded, zero, stale, error | Definition и freshness рядом; не превращается в набор одинаковых KPI cards |
| `TrendChart` | loading, loaded, zero, stale, error, reduced motion | Label/marker/pattern coding, textual summary и связанная table alternative |
| `DataTable` | loaded, empty, sorted where applicable | Semantic table на доступной ширине; mobile получает отдельное readable представление |
| `ProfileForm` | default, editing, saving, saved, validation/error | Одна колонка; saved feedback не сбрасывает focus или entered data |

### 5.3. Owner/admin task components

| Component | Обязательные variants/states | B3 contract |
|---|---|---|
| `AdminDataList` / `AdminRow` | loading, empty, stale, error, selected | Row remains readable without hover; mobile/compact view is not a squeezed table |
| `ReviewCaseSummary` | unassigned, assigned, overdue/SLA placeholder, conflict | Owner, age и SLA clearly labeled; B3 не придумывает C-stage contract |
| `ModerationTimeline` | submitted, revised, approved, rejected | Semantic ordered list; actor/time/action readable without connector line |
| `AttributionTimeline` | assigned, rejected, pending, flagged | Correlated click → start → identity → decision → CRM evidence, append-only visual grammar |
| `CorrelationBlock` | complete, partial, unavailable | IDs copy locally; missing evidence explicitly marked, not visually omitted |
| `MaterialStatusGroup` | both active, archived campaign, one/both disabled | Campaign lifecycle and material availability shown as separate axes |
| `DeliveryAttemptList` | delivered, retrying, failed, dead letter, provider down | Attempts ordered; freshness and last result explicit |
| `ProtectedActionPanel` | ready, permission denied, submitting, success, conflict | Consequence + reason + actor context; destructive button spatially separated |
| `AdminAuditLog` | loading, loaded, empty, error, exported | Semantic event list/table with time, actor, action, resource; immutable appearance |

## 6. State and interaction contract

Каждая применимая поверхность должна иметь не только happy path, но и state из утверждённого B2 catalog. В B3 state selector может быть review-only и не входит в product shell.

| State class | Визуальное и поведенческое правило |
|---|---|
| Loading | Reserved geometry; `aria-busy`; duplicate submit/action недоступен |
| Empty | Различать first-use, no-data и filtered-empty; показывать релевантный reset/next step |
| Validation | Inline у поля + summary для нескольких ошибок; focus идёт к summary/первой ошибке |
| Recoverable error | Введённые данные и safe local state сохраняются; есть конкретный retry |
| Fatal error | Plain explanation, correlation ID и честная доступность retry |
| Offline/stale | Явные timestamp/freshness и ограничение действий; stale не выглядит current |
| Permission denied/suspended | Причина и доступный support path; запрещённое action отсутствует или объяснённо disabled |
| Conflict | Не перезаписывать чужое решение; показать current server state и безопасное обновление |
| Success | Короткое локальное подтверждение без confetti; дальнейший следующий шаг остаётся очевидным |

Правила interaction polish:

- pointer-down feedback начинается немедленно и не блокирует ввод;
- optimistic update разрешён только при безопасном rollback; protected/admin decisions ждут подтверждения server contract;
- copy/download feedback привязан к конкретному материалу;
- sheet/dialog можно прервать; отсутствие drag gesture не блокирует закрытие;
- browser back/forward восстанавливает сериализованные screen, period, search и filters;
- после обычной route navigation focus переходит на `h1`; при browser back восстанавливается логический предыдущий focus;
- неактивная или unavailable action не прячется без объяснения, если пользователю важно понять её существование.

## 7. Responsive rules

Breakpoints означают смену topology по содержимому, а не названия устройств:

| Диапазон / trigger | Правило |
|---|---|
| `320–767px` | Single-column mobile; agent bottom nav; самостоятельные list items; actions не зависят от hover |
| `360px`, `390px` | Основные mobile QA widths для access, agent и compact admin |
| `≥768px` | Agent bottom nav меняется на side nav; layout не обязан становиться двухколоночным |
| `≥980px` | Разрешены две task columns только когда порядок чтения и focus остаются однозначными |
| `≥1180px` | Admin queue/detail может стать master-detail; detail сохраняет отдельный route/state |
| `1280px`, `1440px` | Desktop QA widths; content получает max-width, а строки не растягиваются до нечитаемой длины |

Поверхностные правила:

- Create: форма → submitting → отдельная Campaign detail при любой ширине;
- Library: mobile tappable item без quick actions; desktop horizontal row `identity → status → unique clicks → actions`;
- Statistics: `summary → split → chart → table → campaigns`; на узкой ширине сохраняется этот reading order;
- Profile: одна содержательная колонка при любой ширине;
- Onboarding: полноэкранный step; на desktop centered column `640–720px`, не dashboard shell;
- Admin: compact sections и stacked rows на узкой ширине; persistent side nav и optional master-detail только с `1180px`;
- Dialog: bottom-sheet geometry на mobile, но с dialog semantics и явной close button; centered dialog на tablet/desktop;
- sticky bottom controls и navigation учитывают `env(safe-area-inset-bottom)` и не перекрывают last focusable item;
- используется dynamic viewport unit с fallback; mobile keyboard не скрывает focused input и submit/recovery action;
- page-level horizontal scroll запрещён при `320px`, 200% zoom и длинных русских labels; локальный scroll допустим только для обоснованной data table с доступной альтернативой;
- touch target остаётся `44×44px`, spacing не уменьшается ради помещения лишней quick action.

## 8. Accessibility annotations

B3 prototype и handoff используют следующие annotation IDs. На каждом screen отмечаются только применимые ID, но полный набор проверяется в QA.

| ID | Annotation / acceptance rule |
|---|---|
| `A11Y-01` | Один `main`, один `h1`; landmark names уникальны; document title соответствует screen |
| `A11Y-02` | Skip link на повторяющейся shell; route focus на `h1`, browser-back focus восстановлен логично |
| `A11Y-03` | Focus-visible имеет непрерывный indicator, не обрезается overflow/sticky layers и проходит contrast |
| `A11Y-04` | Полный flow доступен Tab/Shift+Tab/Enter/Space/Escape/arrow keys там, где паттерн это требует |
| `A11Y-05` | Field имеет programmatic label, required/optional text, instruction и связанный `aria-describedby` error |
| `A11Y-06` | Loading, copy/download, submit и background result объявляются ровно один раз подходящим polite/assertive live region |
| `A11Y-07` | Dialog/sheet получает initial focus, удерживает Tab, закрывается Escape/close и возвращает focus trigger |
| `A11Y-08` | Status, series и selection имеют text/icon/pattern; цвет никогда не единственный сигнал |
| `A11Y-09` | Trend имеет text summary и semantic data table; tooltip доступен keyboard/touch, но не обязателен для чтения данных |
| `A11Y-10` | Informative image имеет точный русский alt; decorative crop — empty alt; platform mark имеет visible text label |
| `A11Y-11` | Minimum target `44×44px`; layout reflows at `320px` and 200% zoom без потери content/action |
| `A11Y-12` | Text/background, non-text controls, focus, disabled affordance, chart/grid и overlays проверены по WCAG 2.2 AA |
| `A11Y-13` | `prefers-reduced-motion` убирает transforms, parallax, chart morph и smooth scroll; content появляется без задержки |
| `A11Y-14` | `forced-colors` сохраняет boundaries, focus, status и selected state; custom icons не исчезают |
| `A11Y-15` | Язык документа `ru`; даты/время имеют читаемый format и timezone; TTL не сообщается только визуальным countdown |
| `A11Y-16` | Screen reader reading order совпадает с visual order; CSS reordering не меняет смысловой sequence |

Для каждой protected action annotation дополнительно фиксирует accessible name, consequence description, initial focus, cancel path и return-focus target. Для каждого photo crop фиксируются alt/empty-alt, focal point и проверенная contrast pair, если поверх фото есть текст.

## 9. Motion specification

Базовая easing: `cubic-bezier(.2, .8, .2, 1)`. Свойство `transition: all` запрещено; анимируются только перечисленные свойства. Motion не задерживает network state, focus или возможность повторить действие.

| Interaction | Duration / properties | Reduced motion |
|---|---|---|
| Button/control press | `100ms`, `transform: scale(.98)` | Transform removed; immediate color/border feedback |
| Hover/focus/selected color | `160ms`, explicit color/background/border | `0–80ms` color change допустим |
| Popover/date picker | `180ms`, opacity + small transform from trigger | Opacity only, без spatial travel |
| Dialog/sheet enter/exit | `260ms`, opacity + translate, critically damped, без bounce | Opacity `≤120ms`; no translate |
| Created/local result | `220ms`, opacity + `translateY(4–8px)` | Immediate/short opacity; focus не ждёт animation |
| List insert/remove | `180–220ms`, opacity + reserved spatial change | Immediate update, без collapse animation |
| Chart first reveal | `220ms` maximum, restrained opacity/line reveal | Static final chart immediately |
| Chart period/filter change | `160–180ms` crossfade with stable axes/height; no misleading path morph | Immediate data replacement + updated text summary |
| Skeleton → content | `160ms` opacity after anti-flash delay | Immediate replacement |
| Toast/global message | `180ms` enter, no auto-dismiss before readable minimum | Immediate appearance; dismissal behavior unchanged |

Additional rules:

- success is restrained: no confetti, particles, parallax or celebratory loop;
- sheet is interruptible during enter/exit and always has explicit close/cancel;
- animation never becomes the only indication of status or relationship;
- focus ring and error announcement are not delayed until transition end;
- looped decorative motion is absent from core product;
- motion QA covers rapid repeat click, double submit, route interruption and reduced-motion OS setting.

## 10. Asset and license gates

[`platform-asset-provenance.md`](platform-asset-provenance.md) — authoritative ledger для platform marks. Существующие файлы в `web/styleboard/assets` имеют статус preview/reference only: они не считаются approved или production-ready. Фото access/welcome хранится отдельно, имеет source/hash/provenance record в [`gate-b3/assets/manifest.yml`](gate-b3/assets/manifest.yml); production rights и финальное визуальное утверждение владельцем остаются открытыми gates.

### 10.1. Universal acceptance record

Asset допускается в approval-ready hi-fi и handoff только когда manifest содержит:

- original/official `source_url` и отдельный `terms_url`;
- author/owner, license/permission basis и retrieval/download date;
- original filename, immutable file hash и retained source package;
- usage/surface, allowed backgrounds/colors, minimum size и clear space, если применимо;
- crop variants, focal point и `alt_ru` для фотографии;
- `reviewed_by`, review date и `approval_status: approved`.

Отсутствие запрета не считается разрешением. Геометрия platform mark не редактируется, brand color не «подгоняется» под palette, а screenshot/поисковая выдача не являются источником лицензии.

### 10.2. Gate matrix

| Asset class | Working prototype rule | Условие снятия блокировки |
|---|---|---|
| ThaiForTravel logo | Только owner-confirmed original; при отсутствии подтверждённого файла — подписанный logo placeholder, без нового знака | Source/original/hash/usage подтверждены владельцем |
| Golos Text | Допустим после сохранения self-hosted WOFF2 и SIL OFL record; system fallback обязателен | Font files, version/hash, OFL text и Cyrillic subset проверены |
| YouTube mark | Preview не финальный; нельзя заявлять blanket license | Official package + terms review + product/legal review recorded |
| VK mark | Preview не финальный | Повторная загрузка из official brand source + manifest review |
| RUTUBE mark | Preview не финальный | Повторная загрузка из official brand source + manifest review |
| Telegram mark | Preview не финальный | Official source + текущие terms/use review recorded |
| Instagram mark | Заблокирован; text label + neutral placeholder | Явное permission/terms basis и approval в ledger |
| TikTok mark | Заблокирован; text label + neutral placeholder | Явное permission/terms basis и approval в ledger |
| Site / other | Нейтральные globe/link/ellipsis только как proposed own-system icons | Design-system approval + source/license record для icon set |
| Thailand photography | Reference image не переносится автоматически; до approval — aspect-ratio placeholder с intended scene/alt/focal-point note | Source, author, license, download/hash, usage, crop/alt и owner approval complete |
| QR demo image | Только synthetic, non-production payload; никаких действующих токенов или client data | Scan QA, quiet zone, export dimensions и payload label documented |
| General UI icons | Не брать случайные glyphs из web | Один approved icon set с license/version/hash и consistent stroke rules |

Генеративное изображение реального места, экскурсии или партнёра не подменяет licensed photography и не используется без отдельного owner approval. До закрытия обязательного photo/icon gate B3 остаётся `in_progress`, даже если layout visually complete.

## 11. QA and approval checklist

### 11.1. Completeness and truthfulness

- [ ] Каждый утверждённый B2 `surface/screen/state` представлен в hi-fi; baseline — 103 review routes, включая 51 owner/admin states.
- [ ] Review-only bar/state selector визуально и семантически отделён от product shell.
- [ ] Demo names, counts, URLs, timestamps, QR payloads и correlation IDs явно помечены как illustrative.
- [ ] Prototype не создаёт впечатление реальной Telegram/CRM/API/clipboard/download integration.
- [ ] Нет незадокументированных изменений B2 navigation, route order, labels или business semantics.
- [ ] Все будущие/blocked элементы обозначены честно; placeholder не выдан за final asset.

### 11.2. Visual and responsive QA

- [ ] Warm tropical utility узнаваема на access и agent surfaces без избыточной декорации; admin остаётся связанным с системой, но evidence-first.
- [ ] Sea — dominant brand color; sun используется как ограниченный functional accent и никогда с белым текстом.
- [ ] Один clear primary action на task context; destructive actions spatially separated.
- [ ] Typography, line length, Cyrillic wrapping и tabular numerals проверены с Golos, fallback и 200% text zoom.
- [ ] Все screens проверены на `320`, `360`, `390`, `768`, `1280`, `1440px`; behavior triggers `980` и `1180px` проверены отдельно.
- [ ] Нет page-level horizontal overflow, clipped focus, sticky overlap или keyboard-obscured field/action.
- [ ] Agent links дополнительно сверены на B2 widths `768`, `900`, `1120`, `1280`, `1440px`; admin — минимум `900` и `1280px`.
- [ ] Loading/empty/error/stale/conflict states не вызывают layout jump и не похожи на success/current state.
- [ ] Visual regression baselines сохранены для ключевых happy, loading, empty, error, disabled и protected-action screens.

### 11.3. Accessibility QA

- [ ] Automated audit не показывает blocking WCAG 2.2 AA issues; manual test дополняет, а не заменяется автоматикой.
- [ ] Полные access, create, copy/download, archive, statistics, profile, moderation и admin protected flows пройдены только клавиатурой.
- [ ] Screen reader smoke test подтверждает landmarks, headings, labels, errors, live regions, dialog и chart/table alternative.
- [ ] Contrast измерен для default/hover/pressed/disabled/focus/status/chart/grid/photo-overlay combinations.
- [ ] Status, selected state и chart series понятны в grayscale и forced-colors.
- [ ] Targets `44×44px`, focus order, focus return и route-focus behavior подтверждены на touch и desktop.
- [ ] `prefers-reduced-motion` и reduced-transparency/forced-colors сценарии не теряют content, feedback или controls.

### 11.4. Interaction and motion QA

- [ ] Campaign submit устойчив к double click и показывает idempotent submitting state.
- [ ] Recoverable errors сохраняют form data; conflict не перезаписывает current server state в демонстрируемой модели.
- [ ] Copy/download feedback локальный; toast не используется для field error.
- [ ] Dialog/sheet имеет cancel, `Escape`, trap и return focus; mobile flow не требует drag.
- [ ] Back/forward и direct review URL восстанавливают screen/state/filters/period.
- [ ] Motion соответствует таблице, не использует `transition: all`, прерывается безопасно и не блокирует input/focus.
- [ ] Trend filter update сохраняет dimensions и не изображает ложную непрерывность между разными данными.

### 11.5. Asset, performance and handoff QA

- [ ] В approval-ready prototype нет asset со статусом `preview-only`, `blocked`, неизвестной лицензией или неполным manifest.
- [ ] Logo, font, каждый platform mark, UI icon set и каждое фото имеют source/license/hash/reviewer record.
- [ ] Фото имеют responsive formats, dimensions, `srcset`, focal point, alt decision и lazy-loading rule.
- [ ] QR exports сохраняют quiet zone и сканируются на representative mobile devices; payload synthetic и подписан.
- [ ] Загружается только critical Cyrillic font face; below-fold media lazy; image dimensions предотвращают layout shift.
- [ ] Handoff фиксирует token names, component variants, responsive switches, accessibility annotation IDs и motion/reduced-motion values.
- [ ] QA report перечисляет известные ограничения и не называет preview artifact production-ready.

### 11.6. Owner approval

B3 может получить `approved_by_owner` только после одновременного выполнения условий:

1. владелец просмотрел clickable prototype на mobile и desktop и подтвердил соответствие direction contract;
2. все обязательные B2 states представлены, а отклонения либо устранены, либо отдельно утверждены;
3. accessibility, responsive, visual regression и motion QA приложены и не имеют blocking defects;
4. каждый использованный final asset прошёл provenance/license gate; unresolved preview assets отсутствуют в approval-ready build;
5. component inventory и handoff annotations соответствуют фактическому prototype;
6. в gate report перечислены: что предложено, почему, что отвергнуто, что требует отдельного решения и где лежат результаты.

### 11.7. Decision record 2026-08-07

Владелец принял итоговый clickable prototype и разрешил продолжить работу. Решение фиксируется как `owner_accepted_for_stage_c_with_production_clearance_blockers`: визуальный/UX gate закрыт для начала этапа C, но не является заявлением о production readiness. До production отдельно остаются обязательными asset provenance/rights, финальный accessibility clearance, scan QA реального QR и перечисленные в [`gate-b3/QA.md`](gate-b3/QA.md) проверки на физических устройствах.

## 12. Решения, которые выносятся на B3 review

1. Соответствует ли итоговая визуальная иерархия контракту «Тёплая тропическая утилитарность» на всех трёх surfaces.
2. Достаточно ли редкое и контекстное использование фотографии; не мешает ли оно рабочей задаче.
3. Ясно ли Campaign detail объясняет одну campaign и два материала с независимой availability.
4. Сохраняет ли mobile самостоятельную topology, а desktop — полезную плотность без dashboard/carded slop.
5. Понятны ли status, freshness, conflict и protected-action consequences без цвета, hover и animation.
6. Закрыты ли права и provenance каждого asset, реально попавшего в approval-ready prototype.
7. Готовы ли component, responsive, accessibility и motion contracts к передаче на этапы C–D без скрытого расширения product scope.
