# FiveRP — Server Design System Единый стиль для **всего** сервера: loading screen, авторизация, будущие меню (инвентарь, телефон, банк, HUD). Основан на белой «стеклянной» теме Filmorum (`fiveM_design.md`), адаптирован под CEF/NUI FiveM. > Правило номер один: **ни один компонент не хардкодит цвет, радиус или шрифт.** > Только `var(--…)` из блока токенов ниже. Смена темы = одна строка. --- ## 0. Шрифт — Unbounded **Unbounded — основной шрифт всего сервера.** Геометрический дисплейный гротеск, переменная ось веса 300–800. Никаких других сансов в интерфейсе. Файлы лежат в каждом ресурсе локально (`html/fonts/`), а НЕ грузятся с `fonts.googleapis.com`: у части игроков CEF стартует раньше сети, и веб-шрифт успевает не приехать — интерфейс мигает системным шрифтом. Локальный woff2 рисуется с первого кадра. ```css @font-face { font-family: 'Unbounded'; font-style: normal; font-weight: 300 800; /* вариативный: один файл на все веса */ font-display: block; /* block, не swap — подмены шрифта быть не должно */ src: url('fonts/unbounded-latin.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } /* + unbounded-latin-ext.woff2 и unbounded-cyrillic.woff2 теми же блоками */ ``` ```css --sans: 'Unbounded', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; --mono: ui-monospace, 'SF Mono', SFMono-Regular, Menlo, Consolas, 'Liberation Mono', 'DejaVu Sans Mono', monospace; ``` **Как набирать Unbounded.** Шрифт широкий и характерный — он требует другой типографики, чем SF Pro: | Роль | Размер | Вес | Трекинг | |---|---|---|---| | Display (лого, экран загрузки) | 44–72px | 800 | `-0.04em` | | H1 (заголовок панели) | 26–30px | 700 | `-0.035em` | | H2 (секция) | 18–20px | 600 | `-0.03em` | | Кнопка / линк | 14px | 600 | `-0.01em` | | Body / инпут | 14–15px | 400 | `-0.005em` | | Лейбл поля | 11px | 600 | `+0.09em`, `uppercase` | | Eyebrow / надзаголовок | 10px | 600 | `+0.20em`, `uppercase` | | Метаданные | 11–12px | 400 | `0` | Правила: - **Крупный кегль = минусовой трекинг.** У Unbounded широкие апроши; без `letter-spacing: -0.03em` заголовок расползается. - **Мелкий кегль = плюсовой трекинг + uppercase.** Ниже 12px строчные буквы Unbounded слипаются — все подписи только капслоком с разрядкой. - **Веса 300 и 800 — крайности**, в интерфейсе живут 400/500/600/700. - **Не набирать Unbounded длинный текст.** Абзац больше двух строк — читать тяжело. Для многострочных описаний кегль 13px/1.65 и вес 400, не больше. - **Цифры документов, ID, MRZ — только `--mono`.** Unbounded для них слишком «дизайнерский», а нужен вид машинного считывания. --- ## 1. Философия - **Air, light, frosted** — полупрозрачные стеклянные панели поверх живой игры. - **Кислород** — между карточками 12px, между секциями 40–48px. - **Один акцент** — синий `#0071e3`, дозированно: кнопка, ссылка, фокус. - **Сдержанное движение** — fade и подъём на 4px. Анимации ради анимации нет. - **Один герой на экран** — крупный объект (паспорт, лого), остальное тихое. --- ## 2. Токены ```css :root { --bg: #f5f5f7; --bg-deep: #e8e8ed; --surface: rgba(255, 255, 255, 0.72); --surface-solid:#ffffff; --panel: rgba(255, 255, 255, 0.80); --header-bg: rgba(255, 255, 255, 0.70); --field-bg: rgba(0, 0, 0, 0.04); --field-bg-focus:#ffffff; --fg: #1d1d1f; --fg-secondary: #6e6e73; --fg-tertiary: #a1a1a6; --accent: #0071e3; --accent-strong:#0077ed; --accent-soft: rgba(0, 113, 227, 0.08); --ring: rgba(0, 113, 227, 0.18); --line: rgba(0, 0, 0, 0.06); --line-strong: rgba(0, 0, 0, 0.10); --hover: rgba(0, 0, 0, 0.04); --success: #34c759; --danger: #ff3b30; --radius-lg: 1.5rem; /* 24px — крупные панели */ --radius-md: 1rem; /* 16px — карточки, инпуты */ --radius-sm: 0.7rem; /* 11px — мелочь */ --ease: cubic-bezier(0.25, 0.8, 0.25, 1); color-scheme: light; } ``` Тёмная и бежевая темы — через `data-theme` на `html`, переопределением тех же токенов (`--bg`, `--surface`, `--fg`, `--accent`, `--success`, `--danger`). --- ## 3. КРИТИЧНО: особенности CEF во FiveM Это не «хорошо бы», а условия, при нарушении которых интерфейс ломается в игре, оставаясь идеальным в браузере. 1. **`backdrop-filter` и `box-shadow` не живут на одном элементе.** Композитор CEF рисует тень такого элемента непрозрачным прямоугольником — в игре под панелью появляется чёрный квадрат. Если нужны и блюр, и тень — тень вешать на элемент-обёртку, а блюр на внутренний. По умолчанию **у стеклянных панелей тени нет вообще**: их отделяет от игры блюр и светлая граница, этого достаточно. 2. **`html, body { background: transparent }`** — иначе NUI закрашивает игру. 3. **Никаких затемняющих подложек.** Экран за панелью — это игра, её видно и она красивая. Контраст добирается блюром и белой заливкой стекла, а не `rgba(0,0,0,…)` поверх кадра. Допустим только **осветляющий** вуаль: `radial-gradient(…, rgba(255,255,255,0.28), transparent)`. 4. **Шрифты — локальные woff2.** См. раздел 0. 5. **`prefers-reduced-motion`** — обязательный блок с самого начала. 6. **Курсор и фокус** — `SetNuiFocus(true, true)` только когда панель открыта, и обязательно `SetNuiFocus(false, false)` при закрытии, иначе игрок остаётся без управления. --- ## 4. Стеклянная панель ```css .glass { background: var(--surface); backdrop-filter: saturate(180%) blur(24px); -webkit-backdrop-filter: saturate(180%) blur(24px); border: 1px solid rgba(255, 255, 255, 0.55); border-radius: var(--radius-lg); /* без box-shadow — см. раздел 3.1 */ } ``` Тень разрешена только элементам **без** `backdrop-filter` (карточки на непрозрачном фоне, экран загрузки): ```css .shadow-soft { box-shadow: 0 1px 2px rgba(0,0,0,.03), 0 12px 40px -12px rgba(0,0,0,.12); } .shadow-lift { box-shadow: 0 2px 4px rgba(0,0,0,.04), 0 24px 50px -16px rgba(0,0,0,.20); } ``` Ховер кликабельной карточки: `transform: translateY(-4px)`, 0.4s `--ease`. --- ## 5. Кнопки ```css .btn-primary { border-radius: 999px; padding: 12px 24px; font: 600 14px var(--sans); letter-spacing: -0.01em; color: #fff; background-image: linear-gradient(180deg, var(--accent-strong), var(--accent)); box-shadow: 0 1px 1px rgba(0,0,0,.10), inset 0 1px 0 rgba(255,255,255,.20); } .btn-primary:hover { filter: brightness(1.08); } .btn-primary:active { transform: scale(0.97); } .btn-primary:disabled { opacity: .5; pointer-events: none; } .btn-ghost { border-radius: 999px; padding: 10px 20px; font: 600 14px var(--sans); color: var(--accent); background: var(--accent-soft); } .btn-ghost:hover { background: rgba(0,113,227,.14); } ``` Ровно два стиля кнопок на весь сервер. Третий не заводить. --- ## 6. Поля ввода ```css .field { width: 100%; border-radius: var(--radius-md); padding: 13px 14px; font: 400 15px var(--sans); letter-spacing: -0.005em; color: var(--fg); background: var(--field-bg); border: 1px solid transparent; outline: none; transition: background-color .2s, border-color .2s, box-shadow .2s; } .field::placeholder { color: var(--fg-tertiary); } .field:focus { background: var(--field-bg-focus); border-color: var(--accent); box-shadow: 0 0 0 4px var(--ring); /* можно: у инпута нет backdrop-filter */ } .field.is-bad { border-color: var(--danger); box-shadow: 0 0 0 4px rgba(255,59,48,.14); } ``` Лейбл над полем — 11px/600/`+0.09em`/uppercase/`--fg-secondary`. --- ## 7. Компоновка - Панель по центру экрана, ширина `min(940px, 92vw)`, радиус `--radius-lg`. - Внутренние отступы панели 32–40px. - Между полями формы 16px, между группами 24px. - Двухколоночная схема «форма + герой»: `grid-template-columns: minmax(0,1fr) 420px`. - Сворачивание в одну колонку — анимацией `grid-template-columns` и `width`, 620ms `--ease`. --- ## 8. Motion ```css .fade-up { animation: fadeUp .6s cubic-bezier(.22,1,.36,1) both; } .delay-1 { animation-delay: .06s } .delay-2 { animation-delay: .12s } .delay-3 { animation-delay: .18s } .delay-4 { animation-delay: .24s } @keyframes fadeUp { from { opacity: 0; transform: translateY(18px) scale(.995); filter: blur(6px); } to { opacity: 1; transform: none; filter: blur(0); } } @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: .001ms !important; transition-duration: .001ms !important; } } ``` --- ## 9. Фокус и доступность ```css :focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 6px; } ::selection { background: var(--accent-soft); color: var(--accent-strong); } ``` Контраст текста к стеклу — не ниже 4.5:1. `--fg-tertiary` только для плейсхолдеров и декоративных подписей, никогда для смысловых. --- ## 10. Существующие интерфейсы | Ресурс | Что это | Файлы | |---|---|---| | `fiverp-loadscreen` | экран загрузки сервера | `html/index.html`, `style.css`, `app.js` | | `fiverp-auth` | регистрация и вход, паспорт США | `html/index.html`, `style.css`, `app.js` | `fiverp-auth` использует один «герой» — разворот паспорта США (страница с данными: фото, поля, MRZ). Паспорт — единственный насыщенный цветом объект на экране; форма рядом с ним остаётся полностью нейтральной. --- ## 11. Чек-лист нового интерфейса 1. Скопировать `html/fonts/` и блок `:root` из `fiverp-auth`. 2. `html, body { background: transparent }`. 3. Панель — `.glass`, **без** `box-shadow`. 4. Ни одного затемняющего слоя поверх игры. 5. Шрифт Unbounded, трекинг по таблице из раздела 0. 6. Акцент только `--accent`; кнопки только `.btn-primary` / `.btn-ghost`. 7. Подключить `prefers-reduced-motion`. 8. `SetNuiFocus(false, false)` на закрытии — проверить руками. 9. Отрендерить в headless Chrome и **посмотреть глазами** до выката.