1. Источник — [design/handoff/project/](../design/handoff/project/), экспорт Claude Design. Прототипы на HTML: разметка внутри `<x-dc>`, логика в `<script data-dc-script>`, стили — inline плюс CSS-переменные в `<style>`. `support.js` — среда выполнения прототипа, в продукт не переносится.
2. Задача — воспроизвести внешний вид точно, читая код макетов: отступы, размеры, цвета, состояния. Внутреннюю структуру прототипа не копируем.
3. Тексты макетов — на русском, английские версии — в `i18n.js` (словарь «русская строка → английская»).
4. Бриф дизайна — `design/handoff/project/uploads/` (файл «Дизайн VEILIX.md»). Где бриф расходится с прототипами или с [01-product.md](01-product.md), верны прототипы и 01-product.
| `/r/[код]` | реферальная ссылка: ставит cookie и ведёт на сайт бренда |
Навигация по макету: на широком экране — боковая панель, на узком — плавающая панель вкладок «Главная, Ключи, Купить, Ещё».
## 4. Темы и токены
1. Tailwind v4: токены макета — CSS-переменные, подключённые в `@theme`. Бренд задаёт атрибут `data-site="dedicated|mass"` на `<html>`, тему — `data-theme="light|dark"`. Режим «Как в системе» следует `prefers-color-scheme`.
2. Переключатель темы — 3 режима, как в макете. Выбор хранится в localStorage (ключ `vx_theme`), тема применяется скриптом в `<head>` до отрисовки. Новый посетитель видит «Как в системе». localStorage у каждого хоста свой: тема, выбранная на сайте, не переходит в кабинет.
В коде токены — `src/styles/tokens.css`, утилиты Tailwind называются так же (`bg-surface`, `text-ink-2`, `bg-sel`); стандартная палитра Tailwind отключена. У Вейликса `--sel` равен `--accent-soft`. Цвета карт Вейликса: глобус в hero — значения `Main` (они светлее), плоская карта — значения `Locations` (решено на этапе 1b).
1. Commissioner 300–600 — весь текст; Unbounded 600 — только надпись логотипа. Подключение через `next/font`: файлы скачиваются при сборке и отдаются с нашего домена, без запросов к Google Fonts. Предзагружаются только latin и cyrillic у Commissioner; остальные наборы (latin-ext с «₽») и Unbounded браузер скачивает по `unicode-range`, когда встречает их символы.
2. Иконки, флаги и логотип в макете нарисованы CSS-фигурами. Переносим их React-компонентами, сохраняя вид.
3. Логотип — вариант «Слои». Фавиконы — `favicon.svg` и `favicon-mass.svg` из макета.
## 6. Карта мира
1. В макете карта строится в браузере через d3 и topojson с загрузкой данных с CDN. В продукте SVG-карта рендерится на сервере при сборке: d3-geo, проекция Natural Earth, данные `world-atlas` (countries-110m) из npm.
2. В браузере — только интерактив: подсветка, всплывающая карточка, синхронизация с сеткой локаций.
3. На узком экране карта прокручивается горизонтально, как в макете.
3. Поля номера карты из макета `Order` не делаем: карта вводится в виджете провайдера (этап 4b). В фазе 1 — демо-оплата ([D-027](decisions/D-027-demo-payments.md)).
4. Mass: в кабинете «Список ключей», без «текущей/запасной локации» и без экрана смены страны. Внутри ключа — ссылка Xray и WG-конфиги по странам.
5. Статус локации показываем везде одинаково: в списках, карточках и на карте.
6. Кнопка «Получить VPN» на главной ведёт к блоку цен на этой же странице, на остальных страницах — на `/pricing`.
7. FAQ — одна коллекция с местами показа: главная, цены, поддержка (3 раздела), кабинет, MiniApp.
8. Контакты поддержки берутся из настроек сайта, Telegram — ссылка на бота поддержки.
9. Плашки способов оплаты в подвале — по активным платёжным системам сайта.
10. Добавляем то, чего нет в макете: переключатель валюты, `<title>` и мета-описания, H1 на каждой странице, поддержку `prefers-reduced-motion` для анимаций.
12. Переключатели при 5 языках и с валютой (в макете только RU/EN, валюты нет). В шапке — выпадающие списки языка и валюты. В подвале, мобильном меню и кабинете — сегменты с кодами языков (EN RU DE FR ES) и символами валют (₽ $). В оболочке кабинета валюты нет: она появится в настройках (1f).
13. В подвале четыре документа: добавлена «Политика cookies». Плашек способов оплаты нет, пока нет видимых пользователю платёжных систем (пункт 9).
14. Кабинет mass: подписи навигации те же, что у dedicated («Список ключей», «Купить ключ», «Ключи»). Подписи макета MassApp («Подключения», «Выбрать страну», «Подписка») не используем (пункт 4).
15. Ширина надписи логотипа — по содержимому: в макете она подогнана под русское название.
a. `notFound()` в Next 16 отдаёт пустую оболочку (`<html id="__next_error__">`) и рисует 404 в браузере: клиентская граница при серверной отрисовке не срабатывает. Поэтому proxy ведёт неизвестные адреса сайта на внутреннюю статичную страницу `page-not-found` со статусом 404 (`NextResponse.rewrite`с`status`, `decide.ts`). Она отрисована на сервере, в шапке и подвале бренда, на языке из адреса;
b. `notFound()` остаётся для внутренних путей и удалённых в админке страниц — там 404 по-прежнему рисуется в браузере;
c. 500: `error.tsx` сайта (шапка и подвал на месте, кнопка «Обновить страницу») и `global-error.tsx` на случай, когда не отрисовался корневой layout (бренд — по домену, язык — по префиксу адреса). Ошибки Next по устройству рисует в браузере.
17. Реферальная программа (1h): бонус — дни срока ключа, а не деньги ([D-025](decisions/D-025-referral-days.md)). Текст под ссылкой «Месяц начисляется вам и другу… и применяется к ближайшему списанию» заменяем на условия в днях. В истории платежей строка «Реферальный бонус» показывает «+30 дней» вместо «+2 499 ₽». Счётчик «Месяцев начислено» и статусы приглашённых остаются.
18. Тексты описывают работающий продукт, а не ограничения текущего этапа: «сразу после оплаты», оплата картой, автопродление, смена страны — как в макетах ([D-026](decisions/D-026-stage-order.md)).
19. Тексты страниц — в Payload, страницы собираются из блоков ([D-029](decisions/D-029-pages-blocks.md)).
20. Вейликс — «индивидуальный IP»: выделенный адрес на общем сервере. Формулировки «персональный сервер», «без соседей по серверу», «персональные VPN-серверы» не используем.
21. ВейликсВПН: RU-адрес входит в ключ, но страной не считается ([D-031](decisions/D-031-mass-ru-address.md)); число стран — из данных, только «Включено»; протоколы — Xray и WireGuard.
22. Поддержка: сроки ответа не обещаем, часы — «с 10 до 20 по московскому времени в рабочие дни». Telegram — `@veilix_support` у обоих брендов, пока нет ботов поддержки (этап 3e).
23. Контраст: `--ink-3` подобран до 4,5:1 (WCAG AA) на всех фонах темы, включая выделенные карточки; в макетах было 3,5–4,3:1 (таблица в разделе 4).
24. Карта локаций: точки расположены как в макете, клик выбирает ближайшую точку (в Европе точки перекрываются); выбор синхронизирован с сеткой карточек и отмечен кольцом на карте; всплывающая карточка — HTML поверх карты, со статусом. Контуры стран и глобуса — внешний SVG `/svc/geo/…` с версией в адресе: в HTML они попали бы дважды (разметка и данные React).
25. Межстрочный интервал в секциях страниц — `normal`, как в макетах (там он нигде не задан); у текстов с заданным интервалом — их значения. Шапка и подвал из 1a не менялись.
26. Текущий раздел в шапке выделен цветом текста, как в макетах: CSS по атрибуту `data-page` страницы, без JavaScript.
27. Под формами — строка о согласии с политикой конфиденциальности со ссылкой; формы до этапов 3d и 3e только проверяют поля и показывают «отправлено».
5. Заголовки Client Hints темы (`Accept-CH`, `Critical-CH`, `Vary`), которые `withPayload` ставит на все адреса, оставлены только админке (`next.config.ts`): на сайте `Critical-CH` заставлял Chrome повторять первый запрос страницы, Lighthouse оценивал это в 0,7 с.