# Дизайн-система сайта и игры «Вечерний детектив» Два направления с общим логотипом: сайт помогает выбрать дело и управлять участием, игра погружает в расследование. Визуальные правила описаны здесь; единственный источник правил реализации — [FRONTEND_CODE_STANDARD.md](FRONTEND_CODE_STANDARD.md). Рабочие страницы мигрируют постепенно; образцы не меняют их оформление. ## Области применения | Направление | Где применяется | Характер | | --------------------- | ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | | Сайт «Золотой вечер» | Главная, каталог, кабинет, страницы организатора, редакторы и обычные формы | Тёмные ровные панели, машинописный шрифт, ярко-жёлтые действия, лёгкие фактуры | | Игра «Материалы дела» | Расследование команды, улики, сюжетные документы, игровое управление и печатные материалы | Существующие бумага, кожа, металл, машинописный текст, бронзовые надписи и фактурные кнопки | Превью сюжетного документа внутри каталога или редактора использует игровой стиль; окружающие управление и формы — стиль сайта. Игровые изображения и фоны сценариев сохраняют собственное оформление. ## Живые образцы Запустить `npm run dev` и открыть `/design-system` на адресе Vite. Вкладка «Сайт» открывается первой, «Игра» показывает отдельные материалы и управление, «Компоненты» — последовательный каталог: заголовок компонента, живой пример, описание контракта и код подключения; затем следующий компонент. Страница доступна только в разработке, без входа и пункта основного меню; маршрут и компоненты образцов исключены из production-сборки. Все данные вымышлены. Форма, модальное окно и ход игры работают локально; игровой ход не вызывает API и не меняет данные игры. Сайт использует `SiteThemeProvider`, игровые образцы — собственный `NConfigProvider`: тема сайта не попадает в игровые компоненты. ## Общий бренд и логотип Использовать [существующий знак](../src/assets/images/лого.jpg): детектив в шляпе, чёрный круг, золотая окантовка. Не растягивать, не обрезать окантовку, не перерисовывать. Свободное поле — не меньше четверти диаметра; промежуток до названия — от 12 px. Размеры образцов — 48 и 144 px. Изображение рядом с названием имеет пустой `alt`, самостоятельный знак — описательный. JPEG сохраняет белый фон внутри круга, круглое размещение допускает `border-radius: 50%`. Прозрачного и векторного исходника нет; качество крупной печати и узнаваемость favicon проверяются отдельно. Основной цвет текста обоих стилей на тёмных поверхностях — светлый `#EEE`, второстепенный — `#BDB8AE`. Игровой бежевый `#BFA07D` используется точечно: в бренде, декоративных надписях и текстовыделителе. Цвета статусов сохраняют значение; текст на бумаге и жёлтых кнопках остаётся тёмным. Общий блок бренда `DesignBrand` содержит логотип 48 px, промежуток 12 px и название «Вечерний детектив» через `HeaderText`. На узком экране название может переноситься; название направления «Материалы дела» располагается отдельно. Общие правила: mobile-first, desktop от 1024 px, текущие контейнеры 700/1200 px, явные состояния ошибки и загрузки, доступность с клавиатуры. Шкала отступов: 4, 8, 12, 16, 24, 32, 48, 64 px. Цвета задавать семантическими CSS-переменными. ## Сайт «Золотой вечер» ### Палитра Токены находятся в `src/assets/base.css`. `--brand-bronze` и бумага связывают оформление с игрой; жёлтый primary относится к сайту, а не к игровым действиям. | CSS-переменная | Цвет | Назначение | | ------------------------ | --------- | -------------------------------------------------- | | `--brand-background` | `#111111` | Фон сайта; текст на золотой кнопке и бумаге | | `--brand-surface` | `#222222` | Карточки, панели, окна | | `--brand-surface-hover` | `#2E2E39` | Подсветка поверхности при наведении | | `--brand-text` | `#EEEEEE` | Основной текст | | `--brand-text-muted` | `#BDB8AE` | Пояснения, подписи, второстепенные данные | | `--brand-accent` | `#FFD43B` | Основное действие, ссылки, активный элемент, focus | | `--brand-accent-hover` | `#FFE066` | Наведение на основное действие | | `--brand-accent-pressed` | `#F5C518` | Нажатие на основное действие | | `--brand-border` | `#77737F` | Границы полей и панелей | | `--brand-success` | `#87C99D` | Успех | | `--brand-info` | `#94BFEE` | Информация | | `--brand-error` | `#F29A9A` | Ошибка и опасное действие | | `--brand-bronze` | `#BFA07D` | Бренд, текстовыделитель и декоративные надписи | | `--brand-paper` | `#F4EDE0` | Бумажные материалы | Предупреждение использует золото и явную подпись. Статусы не передавать только цветом: добавлять текст и штатную иконку. Жёлтый акцент не использовать как цвет обычного текста на бумаге или белом фоне. ## Типографика и компоновка Весь стиль сайта использует существующий `font_old_typer`: заголовки, основной текст, подписи, меню, кнопки, формы, таблицы и модальные окна. Новые шрифты не загружаются. Шрифт задаётся на контейнере и в локальной теме Naive UI, чтобы сохраняться в телепортируемых окнах. Игровая типографика остаётся прежней. | Элемент | Размер | Вес | Межстрочный интервал | | ----------------------------- | ------------------------ | ------------------------------- | -------------------- | | Главный заголовок | `clamp(32px, 4vw, 48px)` | 600 | 1.15 | | Заголовок раздела | 28 px | 600 | 1.3 | | Заголовок блока | 22 px | 600 | 1.4 | | Вступление | 18 px | 400 | 1.5 | | Основной текст | 18 px | 400 | 1.5 | | Подпись | 14 px | 400 | 1.5 | | Короткая надпись над разделом | 14 px | 400 | 1.5 | | Бумажный текст | 18 px | существующий вес `MessagePaper` | 1.5 | Шкала отступов: 4, 8, 12, 16, 24, 32, 48, 64 px. На мобильном экране внешние поля 16 px, на desktop — 24 px; между разделами 32 px на мобильном и 48 px на desktop, без сложения верхних и нижних отступов соседних секций. Базовое скругление 8 px. Панели имеют тонкую границу; выраженную тень оставить бумажному слою и существующим фактурным компонентам. Использовать текущие контейнеры `.width700` для дел и `.width1200` для списков, прокрутку `.center-block-custom` и шапку высотой 70 px. Mobile-first; desktop-порог — `@media (width >= 1024px)`. До него колонки складываются вертикально, кнопки переносятся; широкая таблица прокручивается внутри себя. Главный блок выравнивается по верхнему краю, между колонками 32 px. Внутри карточек поля 16 px на мобильном и 24 px на desktop, между элементами 16 px, перед главным действием 24 px. Отступы абзацев по умолчанию нулевые; интервалы задаются контейнерами. Не сжимать машинописный заголовок отрицательным межбуквенным интервалом. Небольшие папки каталога сохраняют подписи не меньше 14 px. ### Компоненты и материалы Использовать Naive UI. `NConfigProvider` берёт тему из CSS-токенов. Primary имеет сплошную заливку `#FFD43B`, hover `#FFE066`, pressed `#F5C518`, текст `#111`; сохранять машинописный шрифт и видимый focus. Опасное действие использует красный акцент. Disabled и loading — штатные состояния Naive UI. Главный блок, карточки, формы, таблицы и окна имеют ровные поверхности. Кожа допускается как небольшая полоса в шапке (`BeltBlock`), бумага — в документальных фрагментах превью дела (`paper.jpg`); не оформлять весь сайт стопками листов. Название с логотипом в обоих стилях использует общий `DesignBrand` и существующий `HeaderText`: бежевый `#BFA07D`, машинописный шрифт 22 px, вес 600 и разрядка 2 px. Меню и основной текст сайта используют `font_old_typer`. Ссылки жёлтые на тёмном фоне; на светлом ярлыке текст тёмный. Формы имеют подписи и ошибки у полей, таблицы — локальную прокрутку при необходимости. Модальные окна — `n-modal` + `n-card`, заголовок, role dialog и aria-modal. ### Доска расследования Без градиентов и свечения. Главный блок использует композицию из текстовых улик: записка, билет, время отправления, номера и соединительные линии приглушённого бронзового цвета. Логотип остаётся в шапке, не заменяет обложку каждого дела. Под композицией — название, параметры и жёлтое действие. На desktop фрагменты расположены асимметрично с небольшими поворотами; на мобильном — вертикально, без наложения текста. Бумага использует существующую фактуру. Машинописный шрифт допустим внутри документальных фрагментов; описания, навигация, формы и кнопки тоже используют `font_old_typer`. Документальные фрагменты декоративные, не имеют самостоятельных hover или действий. Линии не перехватывают клики. Формы и служебные панели сохраняют ровные поверхности. Большая доска использует `CaseBoard`; каталог — повторяемые папки `CaseFolder` с предметными обложками. ### Детали досье | Приём | Где и как применять | | -------------------- | --------------------------------------------------------------------------------------------------- | | Папка с ярлыком | Карточка каталога, номер на выступающем ярлыке; оставлять 32 px между карточками | | Бежевый маркер | Одно важное выражение в заголовке, тёмный текст на бежевой неровной полосе | | Улика на обороте | Явная кнопка раскрывает цитату, `aria-expanded` и `aria-controls`; без 3D-переворота | | Архивные разделители | Пунктир между разделами, номера и уголки на обложках; не дополнительные рамки вокруг каждого текста | | Предметная обложка | Билет, ключ или письмо из существующих иконок и бумажных фактур; тот же символ рядом с названием | | Заметка на полях | Короткая сюжетная подпись рядом с большой доской; на мобильном — ниже композиции | | Штамп статуса | «Новое дело», «Скоро», «Пройдено»; только при наличии соответствующего реального состояния | | Подсветка связи | Одна бронзовая линия становится жёлтой при hover или фокусе действия в карточке | | Конец досье | Номер листа, название проекта, тонкая линия и «Продолжение — в следующем деле» | Карточки поднимаются на 3 px при наведении мыши и фокусе внутри. Переходы занимают 160 ms; при `prefers-reduced-motion` подъём и переходы отключаются, раскрытие цитат продолжает работать. Touch не зависит от hover: цитата открывается кнопкой. Декоративные слои и линии не перехватывают клики. Три папки в образцах вымышлены, их штампы не обозначают реальные публикации или историю пользователя. В образце дело «Скоро» имеет отключённое основное действие через отдельный `disabled`; сам статус не управляет доступностью. На рабочем сайте привязать состояния к данным; не вычислять «новое» или «пройдено» по предположениям. Формы и таблицы сохраняют спокойный вид. ## Игра «Материалы дела» ### Эталон и палитра Эталон — текущее оформление расследования команды, а не тема сайта. Сохранить `MessagePaper`, `IntroBlock`, `GameInputForm`, `BeltBlock`, `MetalPlate` и их фактуры. Окружение тёмное `#111`, панели `#222`, основной текст `#EEE`, бумажный текст чёрный, декоративные надписи бронзовые `#BFA07D`. Существующие мятные состояния и фактурные игровые кнопки сохраняются; жёлтую тему сайта не передавать игровому provider. ### Материалы и управление | Материал | Источник | Применение | | ------------------ | ------------------------------------------------- | ------------------------------------------------------------ | | Бумага | `MessagePaper`, `paper.jpg`, `paper_white.jpg` | Вступление, точки, улики и фотографии; сохранять слои и тени | | Кожа | `BeltBlock`, `belt.png` | Полосы управления и фактурные действия | | Металл | `MetalPlate`, `metal.png`, `pin.png` | Детали панелей, без заливки всей страницы | | Игровое управление | `GameInputForm`, `input_center.png`, `button.png` | Место назначения, счётчики и фактурная кнопка | Машинописный шрифт сохраняется в документах и существующих игровых компонентах; сайт использует тот же шрифт по собственным правилам компоновки. `HeaderText` — для бронзовых игровых надписей. В образцах подписи на коже и металле используют чёрную подложку 80% для читаемости. Это локальное оформление образцов, не массовая переделка рабочих игровых компонентов. Вступление и улика используют настоящие компоненты с демонстрационными данными. Панель хода повторяет поведение игры: успешный локальный ход очищает поле и показывает результат. В образцах панель размещена в потоке страницы; в рабочей игре остаётся её существующее фиксированное положение. ### Печатные материалы Светлые внутренние страницы, тёмный текст, небольшие золотые метки. Тёмное оформление допустимо для обложек. Не печатать свечение интерфейса. Номера, подписи и статусы должны читаться в чёрно-белом виде; сюжетные изображения сохраняют собственную стилистику. ## Проверка изменённого экрана - На ширинах 375, 768 и 1280 px нет горизонтальной прокрутки всей страницы; таблица может прокручиваться локально. - Текст имеет контраст от 4.5:1; крупный текст и значимые границы управления — от 3:1. Проверять реальные пары цветов, в том числе hover и pressed. - Все действия доступны с клавиатуры; focus виден, окно закрывается и возвращает фокус на открывший его элемент. - Ошибка, успех, загрузка и пустое состояние различимы без цвета. - Логотип не деформирован; весь UI сайта использует `font_old_typer`, включая окна. - Компонентные стили локальны, глобальная тема изменяется только при осознанной миграции. Типы, ESLint и Stylelint проходят; изменения маршрутов проверены сборкой. - Переключение вкладок доступно с клавиатуры; сайт открывается первым. - Жёлтая тема сайта не меняет игровые кнопки и документы. - Игровой ход в образцах работает без сетевых запросов. ## Подключение библиотеки Компоненты находятся в `src/components`, импортируются напрямую и не зависят от dev-маршрута. Отдельного пакета и глобальной регистрации нет. Демонстрационные данные остаются в `SiteDesignPreview`, `GameDesignPreview` и `ComponentDesignCatalog`. Рабочие экраны пока не мигрируют. ```vue ``` Provider читает существующие CSS-токены при монтировании, задаёт darkTheme, цвета, машинописный шрифт и размеры Naive UI; кнопки, поля, таблицы и окна используются непосредственно из `naive-ui`. Телепортируемые окна сохраняют тему; для текста внутри `NCard` используйте машинописный шрифт на классе окна, как в каталоге. `--site-card-padding` позволяет контейнеру задавать поля карточек. Игровые компоненты размещайте вне provider сайта, под своим `NConfigProvider :theme="darkTheme" :theme-overrides="{}"`. | Компонент | Props | Slots / события | | --- | --- | --- | | `SiteThemeProvider` | Нет | default / нет | | `DesignBrand` | Нет | Нет | | `CaseFolder` | number, title, description, quote, object: ticket/key/letter, coverLabel, coverCaption; status?, disabled=false, actionLabel='Открыть дело' | Нет / open(title: string) | | `CaseBoard` | label, fragments: readonly массив { number, title, text, caption?, detail?, kind?: note/ticket/timetable }, footer? | footer / нет | | `ObjectCover` | object: ticket/key/letter, label, caption, status? | Нет | | `StatusStamp` | text? | default заменяет text / нет | | `TextHighlight` | Нет | default / нет | | `SectionHeading` | title, id?, eyebrow? | default заменяет title / нет | | `DossierFooter` | label | default / нет | | `MessagePaper` | Нет | default / нет | | `HeaderText` | Нет | default / нет | | `BeltBlock` | Нет | default / нет | | `MetalPlate` | Нет | default / нет | | `IntroBlock` | introduction: EditableIntroduction, mode: show/show-editor/edit | default в режиме edit / update:mode | | `GameInputForm` | addAction: (code: string) => Promise, allPlacesCount, newPlacesCount, gameStatus | Нет; true от addAction очищает поле | Статус папки необязателен и только показывает текст. Доступность задаёт родитель через `disabled`, подпись действия — через `actionLabel`. Событие `open` передаёт название; маршрутизация и API остаются у родителя. Каждая цитата получает уникальный Vue `useId()`, даже для повторных карточек одного дела. Вкладки переключаются стрелками по кругу, Home открывает «Сайт», End — «Компоненты». Каталог показывает disabled, loading, ошибку и успешную форму, обрабатывает open локально и не отправляет запросы к серверу.