# Брендбук BY — FUNDAMENT и СтройПарк

Одна дизайн-система для двух сайтов:

- **fundament.by** — строительство домов (ООО «РВА солюшнс»);
- **stroypark.by** — аренда строительного оборудования, Минск.

Общее у обоих брендов: типографика, шкала размеров, сетка, радиусы, motion, компоненты, тёмная тема, правила доступности. Разное: **цветовая палитра** и **логотипы**.

Вне рамок пакета: иконки, иллюстрации, печатные шаблоны, рекламные макеты. Правила логотипа СтройПарк целиком — в PDF-брендбуке (`../by.stroypark/reference/StroyPark_brandbook.pdf`, v1, октябрь 2026); здесь повторено только то, что нужно вебу.

Все CSS-переменные пакета имеют префикс `--ds-` (design system), все классы — `.ds-*`.

---

## 0. Как пользоваться

### Порядок подключения

Три файла, строго в этом порядке:

```css
@import './brand/tokens.base.css';        /* шрифты, типошкала, сетка, радиус, motion, reset */
@import './brand/palette.fundament.css';  /* или palette.stroypark.css — ровно одна палитра */
@import './brand/components.css';         /* компоненты .ds-* */
```

Без палитры `body` останется без цвета: `tokens.base.css` ссылается на `--ds-bg` и `--ds-text`, которые задаёт `palette.<brand>.css`.

### Публикация

Сайт-брендбук публикуется как Cloudflare static assets: `bun run build` → `bun run deploy` (проверка без учётных данных — `bun run dry-run`, локально — `bun run preview`). Настройка, домен и откат — в [`docs/DEPLOY.md`](docs/DEPLOY.md).

### `brand:sync` — копирование в сайт

Репозитории сайтов независимы, общего workspace нет, а Vite не разрешает относительный импорт за пределы корня проекта. Поэтому сайт **копирует** файлы к себе. В `package.json` сайта:

```json
"scripts": {
  "brand:sync": "mkdir -p src/styles/brand && cp ../by.brandbook/css/tokens.base.css ../by.brandbook/css/palette.fundament.css ../by.brandbook/css/components.css src/styles/brand/"
}
```

(для stroypark.by — `palette.stroypark`). Запуск: `bun run brand:sync`. Файлы в `src/styles/brand/` руками не правьте — правка делается здесь, в `by.brandbook`, и синхронизируется. Логотипы и фавиконки `brand:sync` не копирует — их копируют отдельно в `public/` сайта.

### `.ds-frame` — обязательная обёртка

Раскладка компонентов построена на container queries (`@container (min-width:700px)`), поэтому всё содержимое страницы кладётся внутрь элемента с классом `.ds-frame` (он задаёт `container-type: inline-size`). Без обёртки мобильная раскладка не переключится на десктопную.

```html
<body>
  <div class="ds-frame">
    …весь сайт…
  </div>
</body>
```

Если нужна раскладка по ширине окна, а не контейнера, — замените в своей копии `@container (…)` на `@media (…)` (условия те же) и уберите зависимость от `.ds-frame`.

### `data-theme` — тема

По умолчанию тема следует системной настройке (`prefers-color-scheme`). Принудительно — атрибутом на `<html>`:

```html
<html data-theme="dark">   <!-- всегда тёмная -->
<html data-theme="light">  <!-- всегда светлая -->
<html>                     <!-- авто -->
```

Подробнее — раздел 7.

### Проверка пакета

```sh
npm test   # node scripts/check-contrast.mjs && node scripts/check-components.mjs && node scripts/check-index.mjs
```

Любое изменение цвета в `palette.*.css` должно проходить `npm test`.

---

## 1. Принципы

1. **Инженерная сдержанность.** Строгая сетка, спокойные нейтрали, без декоративных элементов. Интерфейс выглядит как чертёж, а не как реклама.
2. **Hairline-линии вместо теней.** Карточки, поля, секции, таблицы разделяются линией 1px цвета `--ds-hairline` (тонкая) или `--ds-rule` (заметнее). Теней (`box-shadow`) в системе нет.
3. **Радиус 2px.** Один радиус на всё — `--ds-radius`. Скругление почти не видно; углы остаются прямыми.
4. **Одна акцентная краска.** У каждого бренда один акцент (`--ds-brand`): красный FUNDAMENT `#B4231F`, оранжевый СтройПарк `#F25C10`. Им выделяются действие, статус, номер — не фон и не декор.
5. **Mono для цифр и меток.** Цены, площади, телефоны, номера, кикеры, подписи полей — IBM Plex Mono; табличные цифры — `font-variant-numeric: tabular-nums`.

---

## 2. Типографика

Общая для обоих брендов.

| Роль | Шрифт | Начертания | Пакет для сайтов | Для макетов |
|---|---|---|---|---|
| Заголовки, кнопки, крупные подписи | Onest | 400–700 (variable) | `@fontsource-variable/onest` | Google Fonts |
| Текст | Golos Text | 400–600 (variable) | `@fontsource-variable/golos-text` | Google Fonts |
| Цифры, метки, кикеры | IBM Plex Mono | 400, 500 | `@fontsource/ibm-plex-mono` (`/400.css`, `/500.css`) | Google Fonts |

Токены (`css/tokens.base.css`):

| Токен | Значение |
|---|---|
| `--ds-font-head` | `"Onest Variable","Onest","Helvetica Neue",Arial,sans-serif` |
| `--ds-font-text` | `"Golos Text Variable","Golos Text","Helvetica Neue",Arial,sans-serif` |
| `--ds-font-mono` | `"IBM Plex Mono",ui-monospace,Consolas,monospace` |

### Подключение на сайте

Шрифты — self-hosted через fontsource (woff2, `font-display: swap`, кириллица + латиница):

```sh
bun add @fontsource-variable/onest @fontsource-variable/golos-text @fontsource/ibm-plex-mono
```

```js
// main.js / entry
import '@fontsource-variable/onest';
import '@fontsource-variable/golos-text';
import '@fontsource/ibm-plex-mono/400.css';
import '@fontsource/ibm-plex-mono/500.css';
```

Google Fonts на сайтах не используется — только в макетах (Figma) и в визуальном брендбуке `index.html`:

```
https://fonts.googleapis.com/css2?family=Golos+Text:wght@400;500;600&family=IBM+Plex+Mono:wght@400;500&family=Onest:wght@400;500;600;700&display=swap
```

### Шкала

| Токен | Значение | Где |
|---|---|---|
| `--ds-t-hero` | `clamp(32px,4.6vw,60px)` | заголовок первого экрана |
| `--ds-t-h1` | `clamp(27px,3.2vw,44px)` | h1 страницы |
| `--ds-t-h2` | `clamp(22px,2.3vw,32px)` | заголовок секции |
| `--ds-t-h3` | `clamp(18px,1.4vw,21px)` | подзаголовок, заголовок карточки |
| `--ds-t-lead` | `clamp(17px,1.25vw,20px)` | лид-абзац |
| `--ds-t-body` | `16.5px` | основной текст |
| `--ds-t-small` | `14px` | второстепенный текст |
| — | `14.5px` / 600 | текст кнопок `.ds-btn` (задан в компоненте, не токеном) |
| `--ds-t-label` | `11px` | метки, кикеры (mono) |

### Правила

- Заголовки: `line-height: 1.1; letter-spacing: -.02em; text-wrap: balance` (задано в reset для `h1–h4`). Обычный регистр, как в предложении; длинные заголовки капсом не набирать.
- Тело: 16.5px / 1.62.
- Кикеры и метки: mono, 10.5–11px, `letter-spacing: .14–.16em`, `text-transform: uppercase` (готовый класс — `.ds-eyebrow`).
- Цифры в таблицах, ценах, параметрах: `font-variant-numeric: tabular-nums`, выравнивание по правому краю столбца.

---

## 3. Цвет

Имена токенов одинаковы для обоих брендов — компоненты не знают, какой бренд подключён. Меняется только файл палитры.

### Роли токенов

| Токен | Роль |
|---|---|
| `--ds-bg` | фон страницы |
| `--ds-bg-sunk` | «утопленный» фон: чередующиеся секции (`.ds-sec--sunk`), слоты изображений |
| `--ds-surface` | поверхность поверх фона: карточки, поля, бейджи |
| `--ds-inverse` | тёмный блок на светлой странице: инверсная секция `.ds-inv`, футер |
| `--ds-inverse-2` | второй уровень внутри инверсного блока (плашка в футере) |
| `--ds-text` | основной текст, заголовки |
| `--ds-text-2` | второстепенный текст, лид, описание |
| `--ds-text-3` | третичный: метки, подписи, плейсхолдеры, хлебные крошки |
| `--ds-on-inverse` | основной текст на `inverse` |
| `--ds-on-inverse-2` | второстепенный текст на `inverse` |
| `--ds-hairline` | тонкая линия-разделитель, рамка карточки |
| `--ds-rule` | заметная линия: рамка поля, вторичной кнопки, точка нейтрального бейджа |
| `--ds-hairline-inverse` | линия-разделитель на `inverse` |
| `--ds-brand` | акцент: заливка главной кнопки, индикаторы, иконки, подчёркивание при наведении |
| `--ds-brand-hover` | заливка главной кнопки при наведении |
| `--ds-brand-wash` | очень светлая подложка акцентного цвета (выделенная строка, плашка) |
| `--ds-on-brand` | текст и иконки на заливке `brand` / `brand-hover` |
| `--ds-brand-text` | акцент как **мелкий текст** на `bg` / `bg-sunk` (≥ 4.5:1) |
| `--ds-brand-on-inverse` | акцент (текст, иконки) на тёмной поверхности `inverse` |
| `--ds-focus` | обводка фокуса клавиатуры |
| `--ds-ok` | успех, статус «построен» |
| `--ds-warn` | предупреждение, статус «концепт» |
| `--ds-danger` | ошибки форм |

Плюс бренд-независимый `--ds-overlay: rgb(0 0 0 / .55)` (в `tokens.base.css`) — скрим поверх фото под текстом.

### FUNDAMENT — `css/palette.fundament.css`

Опорный цвет — красная база знака `#B4231F`. Значения — из `by.fundament/reference/fundament-tokens.css` (префикс заменён на `--ds-*`) плюс новые `brand-text`, `brand-on-inverse`, `danger`.

| Токен | Light | Dark |
|---|---|---|
| `bg` | `#FAFAF8` | `#101213` |
| `bg-sunk` | `#F1F1ED` | `#0A0C0C` |
| `surface` | `#FFFFFF` | `#181A1B` |
| `inverse` | `#17191A` | `#060708` |
| `inverse-2` | `#222526` | `#111415` |
| `text` | `#16181A` | `#EDEDEA` |
| `text-2` | `#4B5053` | `#B4B8B9` |
| `text-3` | `#696E71` ¹ | `#8A8F90` |
| `on-inverse` | `#F4F4F1` | `#F1F1EE` |
| `on-inverse-2` | `#A7ACAD` | `#9CA1A2` |
| `hairline` | `#E3E2DD` | `#262A2B` |
| `rule` | `#C9C8C1` | `#3B3F40` |
| `hairline-inverse` | `#2E3233` | `#202425` |
| `brand` | `#B4231F` | `#E2605A` |
| `brand-hover` | `#8F1B17` | `#F08279` |
| `brand-wash` | `#FAEFEE` | `#241413` |
| `on-brand` | `#FFFFFF` | `#14100F` |
| `brand-text` | `#B4231F` | `#E2605A` |
| `brand-on-inverse` | `#E2605A` | `#E2605A` |
| `focus` | `#B4231F` | `#E2605A` |
| `ok` | `#3F6B4F` | `#7FAE8C` |
| `warn` | `#8A6520` | `#C9A25E` |
| `danger` | `#B4231F` | `#E2605A` |

¹ скорректирован относительно референса, см. раздел 9.

### СтройПарк — `css/palette.stroypark.css`

Опорные цвета из PDF-брендбука: brand-orange `#F25C10`; переход `#F86613 → #ED480B` — **только внутри логотипа**, в вёрстке не используется; ink `#151515`; surface тёмной темы `#1B1D21`; ink тёмной темы `#F2F4F7`; metal/tagline `#C8CDD4`. Остальное — производные нейтрали.

| Токен | Light | Dark |
|---|---|---|
| `bg` | `#FFFFFF` | `#1B1D21` |
| `bg-sunk` | `#F2F4F7` | `#15171A` |
| `surface` | `#FFFFFF` | `#22252B` |
| `inverse` | `#1B1D21` | `#0F1114` |
| `inverse-2` | `#25282E` | `#1B1D21` |
| `text` | `#151515` | `#F2F4F7` |
| `text-2` | `#4A4F57` | `#C8CDD4` |
| `text-3` | `#656B74` | `#9AA1AB` |
| `on-inverse` | `#F2F4F7` | `#F2F4F7` |
| `on-inverse-2` | `#C8CDD4` | `#C8CDD4` |
| `hairline` | `#E1E4E9` | `#2E3239` |
| `rule` | `#C8CDD4` | `#454A53` |
| `hairline-inverse` | `#30343B` | `#2A2E35` |
| `brand` | `#F25C10` | `#F25C10` |
| `brand-hover` | `#ED480B` | `#FF7A2E` |
| `brand-wash` | `#FEF0E8` | `#2E1F17` |
| `on-brand` | `#151515` | `#151515` |
| `brand-text` | `#C24608` ² | `#FF7A2E` |
| `brand-on-inverse` | `#F25C10` | `#F25C10` |
| `focus` | `#F25C10` | `#FF7A2E` |
| `ok` | `#2E7D4F` | `#6FBF8A` |
| `warn` | `#9A6414` | `#D9A95A` |
| `danger` | `#B3261E` | `#FF6B5E` |

² скорректирован относительно расчётного, см. раздел 9.

Для печати и наружной рекламы СтройПарк (CMYK, RAL, Pantone) — раздел «Цвет» PDF-брендбука, не этот пакет.

### Правила применения

- **Акцент — не больше трети макета.** `brand` — это кнопка, полоса, плашка с ценой, иконка, номер пункта. Не фон секции и не цвет абзаца.
- **Текст на заливке акцента — всегда `on-brand`.** Не ставьте вручную `#fff`: у СтройПарк `on-brand` — тёмный ink `#151515` (белый на `#F25C10` даёт только 3.33:1), у FUNDAMENT в тёмной теме — тёмный `#14100F`.
- **Белый текст на оранжевом СтройПарк — только крупный:** заголовки от 24px или от 19px жирным, и логотип (правило PDF). Кнопки, бейджи, подписи — `on-brand`.
- **Мелкий акцентный текст на светлом фоне — `brand-text`, не `brand`.** Ссылка-акцент, цена в строке, «Подробнее →» — `var(--ds-brand-text)`. У FUNDAMENT `brand-text` совпадает с `brand`; у СтройПарк `brand` (`#F25C10`) как мелкий текст не проходит, поэтому `brand-text` темнее (`#C24608`).
- **Акцент на тёмном блоке — `brand-on-inverse`.** Внутри `.ds-inv` и футера акцентный текст/иконка берёт `var(--ds-brand-on-inverse)`, а не `brand`.
- **Ошибки — `danger`, не `brand`.** У FUNDAMENT значения совпадают, но роли разные; у СтройПарк `danger` — красный, отличный от оранжевого акцента.
- **Градиент логотипа СтройПарк в вёрстке не используется** — только сплошной `brand`.
- **Hex в вёрстке не пишется.** Только `var(--ds-*)`; иначе тёмная тема и второй бренд сломаются.

### Проверенные контрасты

Ключевые пары (WCAG 2.x; порог 4.5:1 для текста, 3:1 для non-text). Полная проверка всех пар обеих палитр — `npm test` (или `node scripts/check-contrast.mjs`); тест проходит.

| Пара | FUNDAMENT light | FUNDAMENT dark | СтройПарк light | СтройПарк dark |
|---|---|---|---|---|
| `text` / `bg` | 17.03 | 16.01 | 18.26 | 15.32 |
| `text-3` / `bg-sunk` (худший случай) | 4.56 | 5.99 | 4.88 | 6.89 |
| `brand-text` / `bg` | 6.28 | 5.42 | 5.03 | 6.49 |
| `on-brand` / `brand` | 6.56 | 5.45 | 5.49 | 5.49 |
| `brand-on-inverse` / `inverse` | 5.09 | 5.81 | 5.07 | 5.69 |
| `brand` / `bg` (non-text, 3:1) | 6.28 | 5.42 | 3.33 | 5.07 |

Справочно (вне скрипта): белый на `#F25C10` — 3.33:1 (только крупный текст ≥ 24px и логотип).

---

## 4. Сетка, отступы, пропорции, радиусы, motion

Все значения — в `css/tokens.base.css`, общие для обоих брендов.

### Шаг 4px

| Токен | Значение | | Токен | Значение |
|---|---|---|---|---|
| `--ds-s1` | 4px | | `--ds-s7` | 48px |
| `--ds-s2` | 8px | | `--ds-s8` | 64px |
| `--ds-s3` | 12px | | `--ds-s9` | 96px |
| `--ds-s4` | 16px | | `--ds-s10` | 128px |
| `--ds-s5` | 24px | | `--ds-s11` | 160px |
| `--ds-s6` | 32px | | | |

Отступы и размеры — кратные 4px; берите токен, а не произвольное число.

### Сетка

| Токен | Значение | Назначение |
|---|---|---|
| `--ds-container` | `1280px` | максимальная ширина контента |
| `--ds-gutter` | `24px` | промежуток между колонками |
| `--ds-margin` | `clamp(20px,5vw,64px)` | боковые поля страницы |

Точка перелома компонентов — ширина контейнера 700px (`@container (min-width:700px)`): до неё одна колонка и бургер, после — многоколоночная раскладка и полная навигация. `.ds-wrap` даёт поля 20px / 40px и `max-width: 1280px`.

### Пропорции изображений

| Токен | Значение | Где |
|---|---|---|
| `--ds-r-hero` | `16/9` | первый экран, десктоп |
| `--ds-r-hero-m` | `4/5` | первый экран, мобильный |
| `--ds-r-card` | `3/2` | фото в карточке |
| `--ds-r-portrait` | `4/5` | портрет (основатель, команда) |
| `--ds-r-plan` | `4/3` | планировка, схема (на `surface`) |

Фото готовьте в этих пропорциях — слоты `.ds-slot--*` обрезают по `aspect-ratio`.

### Форма и движение

| Токен | Значение | Правило |
|---|---|---|
| `--ds-radius` | `2px` | единственный радиус в системе (кнопки, поля, карточки, бейджи, фокус) |
| `--ds-ease` | `cubic-bezier(.2,.7,.2,1)` | единственная кривая |
| `--ds-dur` | `200ms` | единственная длительность; анимируются только цвет, фон, рамка |
| `--ds-overlay` | `rgb(0 0 0 / .55)` | скрим поверх фото под текстом |

При `prefers-reduced-motion: reduce` все переходы и анимации отключаются (правило в `tokens.base.css`).

---

## 5. Компоненты

Файл `css/components.css`. Все компоненты — внутри `.ds-frame`. Цвета берутся только из токенов палитры, поэтому один и тот же HTML работает в обоих брендах и обеих темах.

| Класс | Назначение |
|---|---|
| `.ds-frame` | обязательная обёртка: `container-type: inline-size`, фон, цвет, шрифт |
| `.ds-wrap` | горизонтальный контейнер с полями, `max-width: 1280px` |
| `.ds-eyebrow` | кикер над заголовком (mono, uppercase, `text-3`) |
| `.ds-lead` | лид-абзац (`text-2`, до 56ch) |
| `.ds-nav`, `.ds-logo`, `.ds-logo-mark`, `.ds-nav-links`, `.ds-nav-side`, `.ds-nav-tel`, `.ds-burger` | шапка: логотип, ссылки (с 700px), телефон (mono), кнопка, бургер (до 700px). Ниже ~520px шапка переполняется — на стороне сайта скрывайте `.ds-nav-tel` (`@media (max-width:520px){.ds-nav-tel{display:none}}`); в `components.css` это не правится |
| `.ds-btn` | главная кнопка: заливка `brand`, текст `on-brand`, min-height 48px |
| `.ds-btn--sec` | вторичная: прозрачная, рамка `rule` |
| `.ds-btn--ghost` | текстовая кнопка цвета `brand-text`, без рамки и полей; hover — `text` (`brand-hover` на `bg` у СтройПарк light даёт лишь 3.80:1) |
| `.ds-btn--onDark` | главная кнопка на тёмном блоке, текст `on-brand` |
| `.ds-btn--secOnDark` | вторичная на тёмном блоке |
| `.ds-link` | текстовая ссылка с тонким подчёркиванием |
| `.ds-arrow` | стрелка «→» в mono внутри кнопки/ссылки |
| `.ds-badge`, `--ready`, `--concept`, `--built` | статус-бейдж с точкой: `brand` / `warn` / `ok` (без модификатора — `rule`) |
| `.ds-slot`, `--hero`, `--card`, `--portrait`, `--plan`, `.ds-slot-txt`, `.ds-caption` | слот изображения (плейсхолдер со штриховкой) и подпись под ним |
| `.ds-card`, `.ds-card-fig`, `.ds-card-body`, `.ds-card-params`, `.ds-card-more`, `.ds-cards` | карточка (дом, техника) и сетка карточек 1 → 3 колонки |
| `.ds-params` | таблица параметров `dl`: подпись слева, значение mono справа |
| `.ds-acc` | аккордеон на `<details>`: номер `.n`, иконка `.ic`, тело `.body` |
| `.ds-field`, `.ds-field--err` | поле формы: метка, ввод, подсказка `.hint`; ошибка — `danger` |
| `.ds-sec`, `.ds-sec--sunk`, `.ds-sechead` | секция (отступы 56 / 96px), вариант на `bg-sunk`, шапка секции в 2 колонки |
| `.ds-inv` | инверсный тёмный блок на `inverse` |
| `.ds-foot`, `.ds-foot-grid`, `.ds-foot-legal` | футер: сетка колонок, юридическая строка |
| `.ds-hero-top`, `.ds-actions`, `.ds-4col`, `.ds-founder`, `.ds-crumbs`, `.ds-housetop`, `.ds-2col`, `.ds-contacts`, `.ds-contact-list` | раскладки экранов: первый экран, ряд кнопок, 4 колонки, блок основателя, хлебные крошки, шапка страницы объекта, 2 колонки, контакты |
| `.ph` | маркер плейсхолдера в тексте (пунктир снизу) — убрать до релиза |

Фокус клавиатуры для `a, button, input, textarea, select, summary` задан глобально: `outline: 2px solid var(--ds-focus); outline-offset: 2px`.

### Кнопки

```html
<div class="ds-actions">
  <a class="ds-btn" href="/contacts">Обсудить проект <span class="ds-arrow">→</span></a>
  <a class="ds-btn ds-btn--sec" href="/projects">Смотреть проекты</a>
  <a class="ds-btn ds-btn--ghost" href="/price">Прайс <span class="ds-arrow">→</span></a>
</div>

<!-- на тёмном блоке -->
<section class="ds-inv">
  <a class="ds-btn ds-btn--onDark" href="/contacts">Позвонить</a>
  <a class="ds-btn ds-btn--secOnDark" href="/faq">Вопросы</a>
</section>
```

### Карточка

```html
<div class="ds-cards">
  <a class="ds-card" href="/projects/dom-120">
    <div class="ds-card-fig">
      <span class="ds-badge ds-badge--ready">Готовый проект</span>
      <img src="dom-120.jpg" alt="Дом 120 м², фасад" style="aspect-ratio:var(--ds-r-card);object-fit:cover">
    </div>
    <div class="ds-card-body">
      <h3>Дом 120</h3>
      <div class="ds-card-params">
        <span>120 м²</span><span>2 этажа</span><span>4 спальни</span>
      </div>
      <div class="ds-card-more">Подробнее <span class="ds-arrow">→</span></div>
    </div>
  </a>
</div>
```

Без фото — слот: `<div class="ds-slot ds-slot--card"><span class="ds-slot-txt"><b>Фото фасада</b>3:2</span></div>`.

Бейджи: `--ready` (готово, точка `brand`), `--concept` (концепт, `warn`), `--built` (построено, `ok`).

### Поле

```html
<div class="ds-field">
  <label for="phone">Телефон</label>
  <input id="phone" type="tel" placeholder="+375 29 000-00-00" autocomplete="tel">
  <span class="hint">Перезвоним в течение часа</span>
</div>

<!-- ошибка -->
<div class="ds-field ds-field--err">
  <label for="email">E-mail</label>
  <input id="email" type="email" aria-invalid="true" aria-describedby="email-err">
  <span class="hint" id="email-err">Проверьте адрес: нет символа @</span>
</div>
```

Ошибка: рамка и подсказка цвета `danger`. Текст ошибки всегда словами — не только цветом.

### Аккордеон

```html
<div class="ds-acc">
  <details>
    <summary><span class="n">01</span>Сколько стоит доставка техники?<span class="ic">+</span></summary>
    <div class="body">По Минску — бесплатно от двух суток аренды, за МКАД — по тарифу.</div>
  </details>
  <details open>
    <summary><span class="n">02</span>Нужен ли залог?<span class="ic">−</span></summary>
    <div class="body">Для юрлиц — нет, для физлиц — паспорт и залог по прайсу.</div>
  </details>
</div>
```

Тексты в примерах — заглушки. Номер `.n` — mono цвета `brand`; иконка `.ic` у открытого пункта окрашивается в `brand`. Символ `+` / `−` меняйте скриптом или оставьте один `+`.

### Не входит в пакет

Слой совместимости конкретной страницы fundament.by (алиасы `--paper/--ink/…`, переопределения `.shell/.header/…` из блока «Existing FUNDAMENT page: map the approved system…» референса) остаётся в репозитории сайта.

---

## 6. Логотипы

Логотипы — единственное, кроме палитры, что различается у брендов. Файлы готовые: не перерисовывать, не перенабирать, не перекрашивать.

### FUNDAMENT — `logos/fundament/`

Знак: буква F на красной базе `#B4231F`.

| Файл | Где использовать |
|---|---|
| [`fundament-logo.svg`](logos/fundament/fundament-logo.svg) | основной логотип на светлом фоне (шапка сайта) |
| [`fundament-logo-light.svg`](logos/fundament/fundament-logo-light.svg) | на тёмном фоне: `inverse`, футер, тёмная тема |
| [`fundament-logo-main.svg`](logos/fundament/fundament-logo-main.svg) | вариант лок-апа на светлом |
| [`fundament-logo-main-light.svg`](logos/fundament/fundament-logo-main-light.svg) | вариант лок-апа на тёмном |
| [`fundament-logo-mono.svg`](logos/fundament/fundament-logo-mono.svg) | одноцветный (печать в одну краску, гравировка) |
| [`fundament-symbol.svg`](logos/fundament/fundament-symbol.svg) | знак 512 — аватарки, соцсети |
| [`fundament-favicon.svg`](logos/fundament/fundament-favicon.svg) | favicon (SVG) |
| [`favicon-32.png`](logos/fundament/favicon-32.png) | favicon (PNG 32px) |
| [`apple-touch-icon.png`](logos/fundament/apple-touch-icon.png) | иконка iOS «на экран домой» |

Правила:

- Охранное поле — высота знака × 0.5 со всех сторон.
- Минимальная ширина на экране: логотип — 140px, знак — 20px.
- На тёмных поверхностях — только `-light` версии.

```html
<link rel="icon" href="/fundament-favicon.svg" type="image/svg+xml">
<link rel="icon" href="/favicon-32.png" sizes="32x32">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
```

### СтройПарк — `logos/stroypark/`

Знак — монограмма «СП» в силуэте дома: оранжевая «С» и тёмная «П» под общей крышей. Название — «СтройПарк» (RU) / «StroyPark» (EN): «Строй» всегда оранжевый, «Парк» — ink. Знак общий для обеих языковых версий; отдельного латинского знака «SP» нет. В пакете только SVG и PNG; PDF и EPS для типографии и наружной рекламы — в `../by.stroypark/reference/StroyPark_logo_set/`.

**Версии:**

| Версия | Состав | Где использовать | Мин. на экране |
|---|---|---|---|
| `MAX` | знак + название + подпись | первый экран сайта, презентации, КП, вывеска, баннеры — где логотип крупный | 300px |
| `MEDIUM` | знак + название | документы, соцсети, реклама — когда подпись была бы мельче 6 pt | 150px |
| `HORIZONTAL` | знак слева + название | **шапка сайта**, бланки, визитки, узкие места | 180px |
| `MIN_mark` | только знак «СП» | иконка, наклейки, бирки, мелкие места | 24px |

Если места меньше минимума — переходите на версию проще: MAX → MEDIUM → горизонтальная → знак.

**Язык:** RU — по умолчанию. EN — для англоязычной версии сайта. Языки внутри одного логотипа не смешивать.

**Цвет и фон:**

| Фон | Папка |
|---|---|
| белый и светлый (светлее 50 % серого), `bg`, `surface` светлой темы | `1_color_light` (основной) |
| `inverse`, тёмная тема (`#1B1D21`), любой фон темнее 50 % серого | `2_color_dark` |
| фирменный оранжевый `#F25C10` | **только** `4_mono_white` |
| фото | `4_mono_white` или `3_mono_black` на спокойном участке; нет такого — плашка `surface` с охранным полем X |
| печать в одну краску, штамп, гравировка | `3_mono_black` |

**Охранное поле:** X = ширина левой ножки «П» в знаке; не меньше X со всех сторон, для всех версий и языков. В готовых файлах отступ меньше X — отмеряйте поле от форм логотипа, а не от края файла.

**Чего не делать** (из PDF, дословно):

1. Не растягивайте и не сжимайте логотип — масштабируйте только пропорционально.
2. Не поворачивайте и не наклоняйте.
3. Не меняйте цвета и не перекрашивайте части знака по-своему.
4. Не добавляйте тени, свечение, обводку, объём и фактуры.
5. Не ставьте на пёстрый фон без подложки.
6. Не меняйте местами знак и название и не меняйте расстояние между ними.
7. Не набирайте название другим шрифтом — используйте только готовые файлы.
8. Не ставьте цветной логотип на оранжевый фон.
9. Не обводите знак белой рамкой на тёмном фоне — для этого есть тёмная версия.

**Какой файл куда:**

Имя файла: `StroyPark_<RU|EN>_<MAX|MEDIUM|HORIZONTAL>_<вариант>.<svg|png>`, знак — `StroyPark_MIN_mark_<вариант>`. Вариант: `color_light`, `color_dark`, `mono_black`, `mono_white`. В каждой папке-варианте — `SVG/` и `PNG/`.

| Задача | Файл |
|---|---|
| шапка сайта, светлая тема | [`1_color_light/SVG/StroyPark_RU_HORIZONTAL_color_light.svg`](logos/stroypark/1_color_light/SVG/StroyPark_RU_HORIZONTAL_color_light.svg) |
| шапка сайта, тёмная тема / тёмный футер | [`2_color_dark/SVG/StroyPark_RU_HORIZONTAL_color_dark.svg`](logos/stroypark/2_color_dark/SVG/StroyPark_RU_HORIZONTAL_color_dark.svg) |
| первый экран (крупно) | [`1_color_light/SVG/StroyPark_RU_MAX_color_light.svg`](logos/stroypark/1_color_light/SVG/StroyPark_RU_MAX_color_light.svg) (на тёмном — `2_color_dark/…_MAX_color_dark.svg`) |
| блок на оранжевом фоне | [`4_mono_white/SVG/StroyPark_RU_MEDIUM_mono_white.svg`](logos/stroypark/4_mono_white/SVG/StroyPark_RU_MEDIUM_mono_white.svg) (или `HORIZONTAL`/`MAX` той же папки) |
| англоязычная версия сайта | те же файлы с `EN` вместо `RU` |
| favicon, квадратные иконки (32–1024px) | [`5_icons/StroyPark_icon_light.svg`](logos/stroypark/5_icons/StroyPark_icon_light.svg) / [`StroyPark_icon_dark.svg`](logos/stroypark/5_icons/StroyPark_icon_dark.svg), PNG: `_32`, `_64`, `_180`, `_512`, `_1024` |
| apple-touch-icon | [`5_icons/StroyPark_icon_light_180.png`](logos/stroypark/5_icons/StroyPark_icon_light_180.png) |
| аватарки с круглой обрезкой (Telegram, WhatsApp, Viber, Instagram) | `5_icons/StroyPark_avatar_light` / `_dark` / [`_orange`](logos/stroypark/5_icons/StroyPark_avatar_orange.svg) (SVG, PNG 512/1024); основная в мессенджерах — `_orange` |
| Word, PowerPoint, соцсети | PNG из нужной папки |
| типография, наружная реклама, вышивка | не из пакета — PDF/EPS из `StroyPark_logo_set` + раздел «Цвет» PDF (CMYK/RAL) |
| обзор всех версий | [`StroyPark_overview_RU.png`](logos/stroypark/StroyPark_overview_RU.png), [`StroyPark_overview_EN.png`](logos/stroypark/StroyPark_overview_EN.png) |

`MIN_mark` в круглую аватарку не загружать — круг срежет углы крыши; для круга есть `StroyPark_avatar_*`.

```html
<link rel="icon" href="/StroyPark_icon_light.svg" type="image/svg+xml">
<link rel="icon" href="/StroyPark_icon_light_32.png" sizes="32x32">
<link rel="apple-touch-icon" href="/StroyPark_icon_light_180.png">
```

---

## 7. Тёмная тема

Каждый `palette.*.css` содержит три блока с одинаковым набором токенов:

```css
:root{ color-scheme:light; … }                                              /* светлая */
@media (prefers-color-scheme:dark){ :root:not([data-theme="light"]){ … } }  /* авто-тёмная */
:root[data-theme="dark"]{ color-scheme:dark; … }                            /* тёмная принудительно */
```

- Без атрибута тема следует системе.
- `data-theme="dark"` на `<html>` — тёмная всегда; `data-theme="light"` — светлая всегда (блокирует авто-тёмную).
- `color-scheme` переключает системные элементы (скроллбары, автозаполнение полей).
- Компоненты от темы не зависят: меняются только значения `--ds-*`. Если элемент окрашен hex-ом, а не токеном, — он сломается в тёмной теме.
- Логотипы тему не подхватывают: в тёмной теме подставляйте тёмную версию (`fundament-logo-light.svg`, `2_color_dark`) через `<picture>` / `prefers-color-scheme` или по `data-theme`.
- В тёмной теме FUNDAMENT акцент светлее (`#E2605A`), а `on-brand` становится тёмным (`#14100F`) — текст на кнопке тёмный. У СтройПарк оранжевый `brand` не меняется, `brand-hover`, `brand-text` и `focus` — светлее (`#FF7A2E`).

Переключатель темы (пример):

```js
document.documentElement.dataset.theme = 'dark';   // 'light' | 'dark'
delete document.documentElement.dataset.theme;      // авто
```

---

## 8. Доступность

Цель — WCAG 2.x AA в обоих брендах и обеих темах. Палитры проверяет `scripts/check-contrast.mjs` (часть `npm test`), он падает с ненулевым кодом, если:

- `text`, `text-2`, `text-3`, `brand-text`, `ok`, `warn`, `danger` < 4.5:1 на `bg` **и** на `bg-sunk`;
- `on-inverse`, `on-inverse-2`, `brand-on-inverse` < 4.5:1 на `inverse`;
- `on-brand` < 4.5:1 на `brand` и на `brand-hover`;
- `brand` < 3:1 на `bg` (non-text: иконки, рамки, индикаторы);
- `focus` < 3:1 на `bg`.

Если цвет не проходит, корректируются только **производные** нейтрали (`text-2`, `text-3`, `ok`, `warn`, `danger`, `hairline`, `rule`, производный `brand-text`) в сторону большего контраста, а новое значение фиксируется в разделе 9. Опорные цвета из PDF СтройПарк и референса FUNDAMENT не меняются.

Правила вёрстки:

- **Пары цветов — только проверенные.** Текст на `bg`/`bg-sunk`/`surface` — `text*`, `brand-text`, статусы; на `inverse` — `on-inverse*`, `brand-on-inverse`; на `brand` — `on-brand`. Другие сочетания (например, `text-3` на `brand-wash`, `brand` мелким текстом) — проверить вручную до использования.
- **Фокус виден всегда.** Глобальный `:focus-visible` — `outline: 2px solid var(--ds-focus); outline-offset: 2px`. Не убирайте `outline` без замены. Интерактивные элементы (в том числе `.ds-burger`) — настоящие `<button>`/`<a>`, чтобы получать фокус.
- **Минимальная цель нажатия — 48px.** `.ds-btn` и поля `.ds-field` уже имеют `min-height: 48px`. Для иконок-кнопок (`.ds-burger` 26×16px) и ссылок в мобильном меню добавляйте поля, чтобы кликабельная зона была ≥ 48×48px. `.ds-btn--ghost` снимает `min-height` — не используйте его как единственное действие на мобильном.
- **Цвет — не единственный сигнал.** Ошибка поля — с текстом в `.hint`; статус бейджа — со словом, не только точкой.
- **Формы:** у каждого поля `<label for>`; ошибка — `aria-invalid="true"` и `aria-describedby` на подсказку.
- **Аккордеон** — нативные `<details>/<summary>`: клавиатура и скринридер работают без JS.
- **Изображения:** осмысленный `alt`; текст поверх фото — только со скримом `--ds-overlay`.
- **Движение:** `prefers-reduced-motion: reduce` отключает переходы (уже в `tokens.base.css`).
- **Язык:** `<html lang="ru">` (EN-версия — `lang="en"`).

---

## 9. Отклонения

Отличия единого брендбука от исходных референсов — зафиксированы осознанно.

### Шрифты СтройПарк

PDF-брендбук СтройПарк (раздел «Шрифты») предписывает **Russo One** (заголовки) и **Exo 2** (текст). По решению владельца единый брендбук задаёт общую типографику для обоих брендов — **Onest / Golos Text / IBM Plex Mono**; бренды различаются только палитрой и логотипами. Логотип не затронут: название «СтройПарк» в нём — нарисованная надпись из готовых файлов, шрифтом не набирается.

### `on-brand` СтройПарк = ink, а не белый

В PDF белый используется на оранжевом для логотипа и крупного текста. Белый на `#F25C10` — 3.33:1: этого хватает для текста ≥ 24px (или ≥ 19px жирным), но не для кнопок, бейджей и подписей. Поэтому `--ds-on-brand` СтройПарк = ink `#151515` (5.49:1 на `brand`, 4.81:1 на `brand-hover`): кнопки и мелкие плашки — тёмный текст на оранжевом. Белый на оранжевом — только крупный текст и логотип `4_mono_white`.

### Скорректированные производные цвета

Значения из черновика спеки не прошли проверку контраста; изменены производные цвета, опорные — нет.

| Бренд · тема | Токен | Было | Стало | Причина |
|---|---|---|---|---|
| FUNDAMENT · light | `text-3` | `#6F7477` (из референса) | `#696E71` | на `bg-sunk` было 4.18:1, стало 4.56:1 (на `bg` — 4.94:1) |
| СтройПарк · light | `brand-text` | `#C94A08` (расчётный) | `#C24608` | на `bg-sunk` было 4.27:1, стало 4.57:1 (на `bg` — 5.03:1) |

### Доступность кнопок: `.ds-btn--onDark` и `.ds-btn--ghost`

В референсе `.ds-btn--onDark` красил текст в `#fff` поверх `brand`: у СтройПарк это 3.33:1, у FUNDAMENT dark — 3.47:1, ниже AA. Теперь текст — `var(--ds-on-brand)`; hover наследует фон `brand-hover` от `.ds-btn:hover` (на нём `on-brand` ≥ 4.81:1 во всех четырёх наборах).

`.ds-btn--ghost` в референсе красился `brand` (у СтройПарк light — 3.33:1 как мелкий текст). Теперь `color: var(--ds-brand-text)`, hover — `var(--ds-text)`: `brand-hover` на `bg` у СтройПарк light даёт только 3.80:1.

`.ds-link:hover` в референсе красился `brand` (у СтройПарк light — 3.33:1); теперь `color` и `text-decoration-color` — `var(--ds-brand-text)`.

### Рамка `.ds-field input` / `textarea`: `text-3`, а не `rule`

В референсе рамка поля — `rule` (на `surface` 1.6–1.7:1), что ниже 3:1 для границы интерактивного элемента (WCAG 1.4.11 Non-text Contrast). Теперь `border: 1px solid var(--ds-text-3)` (на `surface` 5.16–5.89:1 во всех четырёх наборах), hover — `var(--ds-text-2)`. Отклонение осознанное, из соображений доступности.

### Новые токены относительно референса FUNDAMENT

`brand-text`, `brand-on-inverse`, `danger` (в референсе ошибки форм красились `brand`), `--ds-overlay`. Единственное изменение семантики компонентов — `.ds-field--err` использует `--ds-danger` вместо `--ds-brand`.

---

## 10. Файлы пакета

| Путь | Что это |
|---|---|
| [`README.md`](README.md) | этот брендбук |
| [`css/tokens.base.css`](css/tokens.base.css) | бренд-независимые токены (шрифты, типошкала, шаг, сетка, пропорции, радиус, motion, оверлей) + reset |
| [`css/palette.fundament.css`](css/palette.fundament.css) | цвета FUNDAMENT: light + dark |
| [`css/palette.stroypark.css`](css/palette.stroypark.css) | цвета СтройПарк: light + dark |
| [`css/components.css`](css/components.css) | общие компоненты `.ds-*` |
| [`logos/fundament/`](logos/fundament/) | логотипы FUNDAMENT (SVG, PNG) |
| [`logos/stroypark/`](logos/stroypark/) | логотипы СтройПарк: `1_color_light`, `2_color_dark`, `3_mono_black`, `4_mono_white` (SVG + PNG), `5_icons` |
| [`scripts/check-contrast.mjs`](scripts/check-contrast.mjs) | проверка контрастов обеих палитр |
| [`scripts/check-components.mjs`](scripts/check-components.mjs) | проверка `components.css`: все `var(--ds-*)` объявлены, нет старого префикса, `.ds-frame` с `container-type`, ошибки поля не на `brand` |
| [`package.json`](package.json) | `npm test` — три проверки; `build`, `test:build`, `preview`, `deploy`, `dry-run` — публикация |
| [`index.html`](index.html) | визуальный брендбук: переключатель бренда и темы, логотипы, палитра с контрастами, типографика, компоненты (открывается из файла) |
| [`scripts/check-index.mjs`](scripts/check-index.mjs) | проверка `index.html`: инлайн-палитры совпадают с `css/palette.*.css`, есть переключатели и `.ds-frame`, все `logos/…` существуют |
| [`scripts/build.mjs`](scripts/build.mjs) | сборка `dist/` (index.html, README.md, css, logos, `_headers`); `--check` проверяет ссылки |
| [`wrangler.jsonc`](wrangler.jsonc), [`docs/DEPLOY.md`](docs/DEPLOY.md) | публикация на Cloudflare (static assets): конфиг и инструкция |
| [`docs/superpowers/`](docs/superpowers/) | дизайн-спека и план реализации |

Источники: `../by.fundament/reference/fundament-tokens.css`, `../by.fundament/reference/assets/brand/`, `../by.stroypark/reference/StroyPark_brandbook.pdf`, `../by.stroypark/reference/StroyPark_logo_set/`.
