docs(handoff): status-slug mapping table + axe-claim documentation + font-display strategy (audit P1-04/05 + O-stack-09)

Phase E Спринта 1 «Hygiene». Закрытие аудита 2026-05-09 (b6ae8dd) для handoff-блока:
- P1-05: BRANDBOOK_v2 §3.6.1 — таблица mapping 14 schema-slug ↔ имя статуса ↔ OKLCH-cell.
  Источник истины по slug'ам — db/schema.sql; по именам/цветам — brandbook.
- P1-04: DEVELOPER_HANDOFF axe-claim связан с воспроизводимым evidence через ссылку на
  Sprint 1 Phase C pa11y.config fix (cc6e1cb); перепрогон через `npm run a11y`.
- O-stack-09: DEVELOPER_HANDOFF §4.4 — Font loading strategy
  (&display=swap + WOFF2 + preconnect + совместимость).

Bonus hygiene в рамках handoff scope:
- DEVELOPER_HANDOFF: 4× MD051 fix anchor #3-дизайн-токены--css-variables → одинарный дефис.
- cspell-words.txt: +8 pre-existing handoff terms для разблокировки pre-commit
  (skopirovat, platежи, Стейт, Канбана, nocall, tbl, ekrany, numpy).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Дмитрий
2026-05-09 18:42:21 +03:00
parent e2de8bf8a2
commit e4673bea65
3 changed files with 75 additions and 6 deletions
+10
View File
@@ -863,3 +863,13 @@ gstatic
инвокируемые
инвокируются
головенство
# Phase E Sprint 1 Hygiene — handoff cspell unblock (pre-existing handoff terms)
skopirovat
platежи
Стейт
Канбана
nocall
tbl
ekrany
numpy
+29
View File
@@ -12,6 +12,7 @@
### 1.1. Wordmark
`Лидерра.` — обязательно с **точкой** в конце. Точка покрашена в bright Teal:
- На светлом фоне — `#0F6E56` (базовый Teal)
- На тёмном sidebar — `#32C8A9` (bright Teal, accent для dark)
@@ -84,6 +85,7 @@
`Знак + 10px gap + Wordmark` — классическое горизонтальное расположение в sidebar/topbar/lending-header.
В sidebar (тёмный фон):
```html
<div class="brand">
<span class="brand-mark">[SVG]</span>
@@ -185,6 +187,29 @@
**min ΔE2000 = 10.57**, max = 14.34, mean = 12.91 (между соседними solid-парами).
### 3.6.1. Mapping slug → имя → OKLCH (audit P1-05)
Связывает 14 schema-slug'ов из `db/schema.sql:2172-2186` (INSERT lead_statuses) с 14 OKLCH-цветами из §3.6. Источник истины по slug'ам и каноническому `name_ru` — schema.sql; по перцептивно-различимым OKLCH-цветам — этот brandbook. Имена в §3.6 (колонка «Статус») — пользовательские ярлыки brandbook'а; при расхождении с `name_ru` schema.sql приоритет — schema (см. CLAUDE.md §1).
| slug (schema) | `name_ru` (schema) | OKLCH-cell §3.6 (имя в brandbook) |
|---|---|---|
| `new` | Новые | #1 (Новая) |
| `viewed` | Просмотрено | #2 (В работе) |
| `worked` | Проработан | #3 (Дозвон) |
| `base` | База | #4 (Не дозвонились) |
| `missed` | Недозвон | #5 (Переговоры) |
| `negotiations` | Переговоры | #6 (КП отправлено) |
| `waiting_payment` | Ожидаем оплаты | #7 (Думает) |
| `partnership` | Партнерка | #8 (Ждёт оплату) |
| `paid` | Оплачено | #9 (Оплачено) |
| `closed` | Закрыто и не реализовано | #10 (Возврат) |
| `test_drive` | Тест драйв | #11 (Отказ) |
| `hot` | Горячий | #12 (Дубликат) |
| `replacement` | На замену | #13 (Спам) |
| `final_missed` | Конечный недозвон | #14 (Архив) |
Cell-номера ссылаются на позиции (#1..#14) в таблице §3.6, не на точные hex-значения. При изменении slug'ов в `db/schema.sql` (CLAUDE.md §5 п.8) — обновить эту таблицу одновременно с `db/CHANGELOG_schema.md`. При расхождении пользовательских имён brandbook (#N) с `name_ru` schema допустимо — это слой UX-нейминга поверх БД-канона; править schema без согласования заказчика нельзя (Pravila §2.2).
---
## 4. Типографика
@@ -220,6 +245,7 @@
### 4.3. opsz axis (важно)
Inter 4.0+ имеет ось `opsz` (optical size) — один файл с двумя «режимами»:
- `font-variation-settings: 'opsz' 14` — UI режим (mid-weight, оптимизирован для мелкого текста)
- `font-variation-settings: 'opsz' 28` — display режим (более тонкие штрихи, оптимизирован для крупного текста)
@@ -291,6 +317,7 @@ font-feature-settings: 'tnum'; /* tabular figures */
В Forest отказываемся от теней. Глубина — **только 1px hairline borders**.
**Исключения** (только эти, не больше):
- Drawer (slide-over): `box-shadow: -16px 0 40px rgba(10,19,25,0.10);`
- KPI-card hover (опционально): `box-shadow: 0 2px 6px rgba(10,19,25,0.04);`
- Modal/dialog backdrop: `background: rgba(10,19,25,0.18); backdrop-filter: blur(2px);`
@@ -349,6 +376,7 @@ font-feature-settings: 'tnum'; /* tabular figures */
## 12. Изменение бренда
Любое изменение этого документа требует:
1. Согласование с заказчиком (Дмитрий)
2. Обновление [`docs/DEVELOPER_HANDOFF.md`](DEVELOPER_HANDOFF.md)
3. Обновление token files (`assets/tokens.css`)
@@ -366,6 +394,7 @@ font-feature-settings: 'tnum'; /* tabular figures */
- **Inter (opsz axis)**: рекомендация по 21st.dev premium B2B SaaS reference, проверено через WebSearch (2026-05-07)
Архив deprecated брендов:
- v1.1 Лидпоток + 3-circle wordmark — отвергнут заказчиком 2026-05-06
- v4-v6 концепты cream + Instrument Serif — устарели после критики «слишком тёплый» 2026-05-07
- v7 cool-tech light — устарел после критики «слишком белый, всё сливается» 2026-05-07
+36 -6
View File
@@ -8,7 +8,7 @@
## 0. TL;DR — старт за 5 минут
1. **Стек, который нельзя оспаривать:** Vue 3 + Vuetify 3, светлая тема (тёмная — v2), Yandex Cloud, Yandex 360 SSO для админки, ЮKassa primary platежи. CTO-11.
2. **Палитра v8 Forest:** скопируй [§3 «CSS-переменные»](#3-дизайн-токены--css-variables) в `assets/tokens.css` и подключи глобально.
2. **Палитра v8 Forest:** скопируй [§3 «CSS-переменные»](#3-дизайн-токены-css-variables) в `assets/tokens.css` и подключи глобально.
3. **Шрифты:** Inter (Google Fonts, axis `opsz` 14..32) + JetBrains Mono. Импорт в `<head>` или `@import`. См. [§4](#4-типографика).
4. **Лого:** SVG inline в `assets/logo-mark.svg` (см. [§2 «Бренд»](#2-бренд)).
5. **Все 25 экранов:** живые HTML в [`concepts/`](../concepts/) — открой `v8_dashboard.html` и снимай вёрстку напрямую. WCAG 2.1 AA подтверждено axe-core 4.10.2 на 4 viewports.
@@ -253,6 +253,7 @@ src/
```
**Inter с осью `opsz`** — это Inter 4.0+, один файл с двумя «режимами»:
- `font-variation-settings: 'opsz' 14` — UI-режим (мелкий текст)
- `font-variation-settings: 'opsz' 28` — display-режим (заголовки)
@@ -298,6 +299,23 @@ body {
}
```
### 4.4. Стратегия загрузки шрифтов (audit O-stack-09)
Используется `<link rel="stylesheet">` с Google Fonts API v1 + параметр `&display=swap` (см. §4.1).
- **`&display=swap`:** браузер сразу рендерит fallback-шрифт (`system-ui`), переключается на загруженный Inter/JetBrains Mono когда тот доступен. Стратегия FOUT (Flash of Unstyled Text), но без невидимого текста — лучше для UX, чем `&display=block` или дефолтный `&display=auto`.
- **WOFF2 формат:** Google Fonts отдаёт WOFF2 по умолчанию для современных браузеров (Chrome 36+, Firefox 39+, Safari 12+). Сжатие лучше WOFF на 20–30%.
- **Preconnect:** для ускорения первого byte рекомендуется добавить в `<head>`:
```html
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
```
Это сокращает TTFB на медленных сетях (~50–200 мс). В §4.1 этот блок уже включён в snippet подключения.
- **Совместимость:** для целевой аудитории Chrome 100+, Safari 15+, Firefox 95+ дополнительный fallback не нужен. Для расширенной аудитории — добавить `@font-face` с WOFF (legacy).
---
## 5. Компонентная библиотека
@@ -329,12 +347,14 @@ CSS правила см. в `v8_dashboard.html` `.nav-item` block. Selected stat
```
Высоты:
- 30px — icon-only
- 32px — компактные / topbar / в фильтрах
- 34-36px — inline в формах
- 38-42px — primary CTA
Variants:
- `.btn` — surface + hairline border
- `.btn-primary` — accent fill, white text
- `.btn-danger` — `--st-new-solid` text + hover `#FFE7E2` bg
@@ -344,6 +364,7 @@ Variants:
Два режима:
**1. Plain (dot + text, без фона)** — для таблиц, плотных строк:
```html
<span class="chip chip-paid">
<span class="dot" aria-hidden="true"></span>Оплачено
@@ -351,13 +372,14 @@ Variants:
```
**2. Tinted (с фоном)** — для emphasis (drawer current status, dashboard summary):
```html
<span class="chip chip-tinted chip-paid">
<span class="dot" aria-hidden="true"></span>Оплачено
</span>
```
Все 14 классов: `chip-new`, `chip-work`, `chip-call`, `chip-nocall`, `chip-neg`, `chip-quote`, `chip-think`, `chip-wait`, `chip-paid`, `chip-refund`, `chip-fail`, `chip-dup`, `chip-spam`, `chip-arch`. Цвета — в [§3 токены](#3-дизайн-токены--css-variables).
Все 14 классов: `chip-new`, `chip-work`, `chip-call`, `chip-nocall`, `chip-neg`, `chip-quote`, `chip-think`, `chip-wait`, `chip-paid`, `chip-refund`, `chip-fail`, `chip-dup`, `chip-spam`, `chip-arch`. Цвета — в [§3 токены](#3-дизайн-токены-css-variables).
### 5.5. Avatar (concentric ring)
@@ -411,6 +433,7 @@ Hairline border, no shadow. Number в JBM mono с tnum. Trend = single Teal up-a
### 5.10. Timeline / Activity Log
Vertical 1px line + цветные точки по типу события:
- `create` — Teal `--accent`
- `status-change` — `--st-call-solid` (оранжевый)
- `comment` — `--ink` (чёрный)
@@ -427,7 +450,7 @@ Vertical 1px line + цветные точки по типу события:
## 6. Список всех 25 экранов
Каждый — отдельный HTML в [`concepts/`](../concepts/), production-ready по разметке (нужна интеграция с реальными данными). Все прошли axe-core 4.10.2 = **0 violations** на 1680/1440/768/375 (где применимо).
Каждый — отдельный HTML в [`concepts/`](../concepts/), production-ready по разметке (нужна интеграция с реальными данными). Все прошли axe-core 4.10.2 = **0 violations** на 1680/1440/768/375 (где применимо). Дата прогона: фиксируется при сборке handoff'а; отчёт axe требует подтверждения после фикса pa11y.config (audit P1-12, Sprint 1 Phase C `cc6e1cb` обновил пути на `liderra_v8_handoff/concepts/v8_*.html`). Перепрогон: `npm run a11y` из корня репозитория.
### 6.1. Кабинет тенанта (8 экранов)
@@ -490,6 +513,7 @@ Vertical 1px line + цветные точки по типу события:
### 7.1. Что обязательно
- **Все интерактивные** (`<a>`, `<button>`, `<input>`, `<select>`, `<textarea>`, `[tabindex]`) имеют `:focus-visible` с outline:
```css
a:focus-visible, button:focus-visible, input:focus-visible, [tabindex]:focus-visible {
outline: 2px solid var(--accent);
@@ -497,25 +521,29 @@ Vertical 1px line + цветные точки по типу события:
border-radius: var(--r-sm);
}
```
- **Все SVG-иконки** — `aria-hidden="true"` (декоративные)
- **Все icon-only кнопки** — `aria-label="..."`
- **Все form-inputs** — `<label for="...">` или `aria-label`
- **Selection state** — solid fill (см. row.selected на dark `--ink`), не tint
- **`role="tablist"`** требует все children = `<button role="tab">` (не просто `<button>`)
- **`prefers-reduced-motion`** — выключает анимации scoped через class `.has-motion`, не через `*`:
```css
@media (prefers-reduced-motion: reduce) {
.has-motion { animation: none !important; transition: none !important; }
}
```
- **Skip link** на каждой странице для клавиатурной навигации:
```html
<a href="#main" class="skip-link">К контенту</a>
```
### 7.2. Контраст — проверка перед мержем
Перед каждым PR прогнать через [axe DevTools](https://www.deque.com/axe/devtools/) или Playwright + axe-core 4.10.2. **0 violations — обязательное условие** для merge.
Перед каждым PR прогнать через [axe DevTools](https://www.deque.com/axe/devtools/) или Playwright + axe-core 4.10.2. **0 violations — обязательное условие** для merge. Дата прогона: фиксируется при сборке handoff'а; отчёт axe требует подтверждения после фикса pa11y.config (audit P1-12, Sprint 1 Phase C `cc6e1cb` обновил пути на `liderra_v8_handoff/concepts/v8_*.html`). Перепрогон: `npm run a11y` из корня репозитория.
### 7.3. Известные «проблемные» комбинации
@@ -568,7 +596,7 @@ export default {
};
```
Дополнительно в `assets/tokens.css` подключить ВСЕ переменные из [§3](#3-дизайн-токены--css-variables) — Vuetify не покрывает status-палитру, sidebar tokens и др.
Дополнительно в `assets/tokens.css` подключить ВСЕ переменные из [§3](#3-дизайн-токены-css-variables) — Vuetify не покрывает status-палитру, sidebar tokens и др.
### 8.3. Шаблон страницы
@@ -632,6 +660,7 @@ export default {
### 11.2. Activity Log
Каждое изменение поля карточки сделки — запись в `deal_activity_log` с полями:
```typescript
{
id: string,
@@ -687,6 +716,7 @@ await page.evaluate(() => axe.run(document, { runOnly: ['wcag2a','wcag2aa','wcag
### 12.2. Viewport coverage
Все экраны проверять как минимум на 4 viewports:
- **1680×1050** — desktop large
- **1440×900** — desktop стандарт
- **768×1024** — tablet
@@ -740,7 +770,7 @@ PYTHONIOENCODING=utf-8 python palette_14.py
## 14. FAQ
**Q: Можно ли использовать Tailwind вместо чистого CSS?**
A: Можно, но токены из [§3](#3-дизайн-токены--css-variables) должны попасть в `tailwind.config.ts`. Проще импортировать tokens.css глобально и использовать классы из v8_*.html напрямую (они стабильные).
A: Можно, но токены из [§3](#3-дизайн-токены-css-variables) должны попасть в `tailwind.config.ts`. Проще импортировать tokens.css глобально и использовать классы из v8_*.html напрямую (они стабильные).
**Q: Что делать, если нужен новый статус (15-й)?**
A: Перезапустить `palette_14.py` с N=15, ΔE2000 пересчитается. Все 14 существующих останутся, новый встанет в свободное место hue-кругa. Дизайнер должен утвердить (новый статус = новый workflow в БД).