# 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 и **посмотреть глазами** до выката.
