docs: update re-design plan

This commit is contained in:
2026-08-27 18:53:42 +05:00
parent 84534b2f58
commit dfb2311e32
+298 -130
View File
@@ -1,27 +1,72 @@
# План: переезд на новый дизайн (refs) # План: переезд на новый дизайн (refs) — параллельная сборка
> Статус: план к выполнению. > Статус: план к выполнению.
> >
> Источники: `refs/` — Next/React-референс (правда по пикселям), `refs-html/` — > Источники: `refs/` — Next/React-референс (правда по пикселям и интерактиву),
> статические HTML-снимки для быстрого просмотра в браузере. > `refs-html/` — статические HTML-снимки для быстрого просмотра в браузере.
>
> **Стратегия изменена.** Вместо in-place рестайла (старый план A–F, правка
> общих компонентов на месте с алиасами токенов) — **параллельная сборка**:
> новый дизайн строится отдельно, изолируется от старого, проверяется
> целиком, затем становится основным и старый удаляется. Старое приложение
> остаётся рабочим и шippable на всём протяжении перехода.
## 1. Что происходит ## 0. Почему меняем стратегию
В `refs/` лежит новый визуальный язык проекта: «чертёжный» техно-стиль — - **Старый план (A–F):** правим `ui/*` и страницы на месте, держим старые
сетка на фоне, IBM Plex Sans/Mono, моно-микролейблы в верхнем регистре, токены как алиасы, чтобы ничего не сломалось до этапа F. Риск: общие
острые углы 4px, панели с 1px-бордером, акценты синий/циан/амбер, зелёные компоненты редактируются вживую → регресс старого UI во время работы,
статус-точки. Референс написан на Next 16 + Tailwind v4, но **переезд новый дизайн нельзя принять изолированно.
дизайновый, а не фреймворковый**: SvelteKit в `web/` остаётся, переносится - **Новый подход (5 фаз):** (1) строим новый ui-kit, (2) строим новые
только дизайн-слой (токены → примитивы → UI-kit → страницы). страницы рядом, не трогая старые, (3) проверяем новый дизайн, (4) делаем
его основным, (5) удаляем старый. Ниже фазы 1–5 — это требуемые шаги.
- **Главный технический риск и его решение.** Сейчас `web/src/app.css`
импортируется в **корневом** `web/src/routes/+layout.svelte:2` и потому
грузится на ВСЕХ маршрутах, включая новые. Решение — **не префиксовать
новый CSS (никакого `.ds2`), а разнести глобальные стили по layout'ам без
наследования**: (а) убрать `import '../app.css'` из корневого layout;
(б) старые маршруты обернуть группой `(old)/` с собственным layout,
импортирующим `app.css`; (в) новые маршруты (`preview/*`) — собственный
layout, импортирующий `design2.css`. SvelteKit делает code-splitting CSS
по маршрутам, а стили компонентов скоупятся сами — поэтому глобальные
стили каждого дизайна живут только в своей ветке, и префикс-обёртка
`.ds2` не нужна. Старые `ui/` и страницы не трогаются до фазы 5.
Чего не делаем: не тащим Tailwind и React в проект. Токены из ## 1. Источники и их оценка
`refs/app/globals.css` переносятся в наш vanilla-CSS слой почти один в один,
классы референса (`step-card`, `setting-group`, …) воспроизводятся как наши
глобальные утилиты и стили компонентов.
## 2. Токены (фундамент) ### `refs-html/` — витрина разметки
Маппинг старых токенов `web/src/app.css` → новые из референса: Покрытие достаточное:
| Файл | Что показывает | Оценка |
| ------------------------- | ----------------------------------------- | ---------------- |
| `index.html` | Главная: pipeline-воркспейс + превью | ✅ |
| `demo.html` | Зеркало `index.html` (идентичны) | ⚠️ дубликат |
| `gradient.html` | Инструмент «Градиент»: настройки + превью | ✅ (тёмная тема) |
| `background-remover.html` | Инструмент «Удаление фона»: source/result | ✅ (тёмная тема) |
| `list-tools.html` | Каталог инструментов | ✅ |
- **Статика без JS** — интерактив (тумблеры/слайдеры/перетаскивание) брать из
кода `refs/`, не из HTML. HTML — только визуальная правда по разметке/классам.
- По 4 файлам собран инвентарь классов — это и есть спецификация kit'а:
`app-shell`, `page-grid`, `eyebrow`, `brand-mark`, `topbar`, `footer`,
`panel-heading`, `setting-group`, `settings-footer`, `settings-panel`,
`segmented`, `status`, `step-card` (`step-index`/`step-heading`/`step-type`/
`step-body`/`drag`), `color-field` (`swatch`/`native-color`),
`preview-toolbar`/`checker` (`tile-canvas`/`remover-canvas`/`comparison-grid`),
`result-meta`/`meta-row`, `tool-card`/`image-card` (`tool-icon`/`tool-index`/
`tool-copy`), `code-block`, `icon-btn`, `download-btn`, `reset-btn`, `lede`,
`auto-note`, `label`, `toggle`/`toggle-group`, `direction-grid`, `gradient-bar`.
- **Дыры в refs-html:** нет состояний empty/error/loading, нет глобальных
модалок/тултипов, i18n не представлен (все лейблы — английские брендовые).
Решения — см. §9.
## 2. Токены (фундамент нового дизайна)
Живут в `src/lib/styles/design2.css` как обычный `:root { … }` (плюс
`[data-theme='dark'] { … }`). Файл грузится **только** layout'ом новой
ветки (§5), поэтому глобально не конфликтует со старым `app.css`. Маппинг
старых токенов `web/src/app.css` → новые:
| Старый | Новый | Light | Dark | | Старый | Новый | Light | Dark |
| -------------- | -------------- | --------- | ------------------------ | | -------------- | -------------- | --------- | ------------------------ |
@@ -38,135 +83,172 @@
Прочее: Прочее:
- Радиусы: вместо `--radius-s/m` один `--radius: 4px`. Скруглённая мягкость - Радиусы: один `--radius: 4px` (мягкость старой темы уходит).
старой темы уходит.
- Шрифты: `IBM Plex Sans` + `IBM Plex Mono`, self-host через `@fontsource` - Шрифты: `IBM Plex Sans` + `IBM Plex Mono`, self-host через `@fontsource`
(проект offline-first, CDN нельзя). Mono — рабочий шрифт для лейблов, (offline-first, CDN нельзя). Mono — рабочий шрифт для лейблов/метаданных/
метаданных, цифр; Sans — для заголовков и текста. цифр; Sans — заголовки и текст. Задаются на `.app-shell` (корень новой
- Фон-сетка приложения (32px blueprint-grid) и шахматка канвасов — ветки), чтобы не зависеть от старых глобальных правил `body`.
отдельные утилиты `.app-shell`, `.checker-canvas`, не токены. - Фон-сетка (32px blueprint-grid) и шахматка канвасов — утилиты `.page-grid`
- Тёмная тема остаётся на `[data-theme='dark']` (инлайн-скрипт в `app.html` и `.checker-canvas` внутри `.ds2`, не токены.
уже есть); класс `.dark-mode` из референса не переносим. - Тёмная тема — на `[data-theme='dark']` (инлайн-скрипт уже есть в
- На переходный период старые имена живут как алиасы `app.html`); класс `.dark-mode` из рефа не переносим, используем наш
(`--bg: var(--background)` …), чтобы существующие компоненты не ломались механизм. На переходный период **никаких алиасов старых токенов** (старые
до этапа D. В конце алиасы удаляются. страницы сами живут на своём `app.css`).
## 3. Базовые примитивы дизайн-системы ## 3. Базовые примитивы дизайн-системы (все — компоненты)
Повторяющиеся паттерны референса выносим в глобальные классы `app.css` Правило фазы 1: **любой повторяющийся паттерн — компонент**, даже «просто
(по одному определению, без копипасты между компонентами): div с двумя стилями». Никакой копипасты классов между страницами. Каждый
примитив ниже — отдельный `.svelte` в `src/lib/components/kit/`.
- `.mono-label` — микро-лейбл: mono 10px, uppercase, letter-spacing .1em, - `MonoLabel` — микро-лейбл: mono 10px, uppercase, letter-spacing .1em,
цвет muted; модификаторы `.mono-label--accent` (синие eyebrow/version). muted; слот-модификатор accent (синие eyebrow/version).
- `.status-dot` / `.status-line` — точка `--success` + подпись - `StatusDot` / `StatusLine` — точка `--success` + подпись
(«AUTO PIPELINE», «LIVE PREVIEW»). («AUTO PIPELINE», «LIVE PREVIEW»).
- `.panel` — панель: фон `--panel`, бордер `--line`; композиция - `Panel` / `PanelHeading` / `SettingGroup` / `SettingsFooter` — панель с
`.panel-heading` (label + strong + правый слот) / `.setting-group` / 1px-бордером, составные части с разделителями.
`.settings-footer` с разделителями. - `CheckerCanvas` рабочая поверхность превью: тёмная подложка + шахматка.
- `.checker-canvas` — рабочая поверхность превью: тёмная подложка + - `MetaRow` / `MetaList` — пары «CAPTION значение».
шахматка; размеры через контейнер. - `Segmented` — сегмент-переключатель (язык, тип градиента, пресеты).
- `.meta-row` — пары «CAPTION значение» (dimensions/format/size, - `Badge` — тег типа шага (BACKGROUND/TRANSFORM/STYLE), чип «✓ AUTO».
result-meta). - `StepCard` — нумерованная карточка этапа: индекс `01`, drag-handle,
- `.segmented` — сегмент-переключатель (общий для языка, типа градиента, Badge типа, заголовок, кнопка удаления; слот для параметров.
пресетов). - `ToolCard` — карточка каталога (icon, index, title, copy, arrow).
- `ImageCard` / `PreviewTile` — label сверху + canvas-превью.
- `AppShell` — корневой контейнер `.app-shell` + `.page-grid` (обёртка
новой ветки маршрутов); задаёт шрифты и фон нового дизайна.
- `BlueprintGrid` — фоновая сетка (используется в `AppShell`).
- `IconButton`, `Icon` (обёртка `lucide-svelte`, 1617px, muted).
## 4. Минимальный UI-kit (`src/lib/components/ui/`) ## 4. Минимальный UI-kit (`src/lib/components/kit/`)
API компонентов сохраняем, меняем внутренности. Новые компоненты — только Контролы, поверх примитивов §3. API проектируем сразу под новый дизайн
те, для которых нет аналога: (обратной совместимости со старым `ui/` не нужно — старые страницы его
продолжают использовать).
| Компонент | Статус | Что меняется | | Компонент | Назначение |
| --------------------------------------------- | --------- | ------------------------------------------------------------------------------------------------------- | | ------------------------- | ----------------------------------------------------------------- |
| `Button.svelte` | рестайл | варианты `primary` (синий solid) / `secondary` (outline) / `ghost` + `icon`-режим; busy-логика остаётся | | `Button.svelte` | `primary` (solid blue) / `secondary` (outline) / `ghost` + `icon` |
| `Field.svelte` | рестайл | обёртка в стиле `.setting-group`: mono-label + output справа | | `Field.svelte` | обёртка: `MonoLabel` + слот значения/контрола |
| `SliderField` | рестайл | range + `<output>` значения, опциональная строка подсказок («strict edges … more removal») | | `SliderField.svelte` | range + `<output>`, опц. строка подсказок |
| `ColorField` | рестайл | swatch + hex-input + нативный color-picker в одном поле | | `ColorField.svelte` | swatch + hex-input + нативный picker |
| `TextField` / `SelectField` / `CheckboxField` | рестайл | чекбокс → switch-toggle 32×18 как в рефе | | `TextField.svelte` | текстовый ввод в стиле дизайна |
| `SegmentedControl.svelte` | **новый** | RU/EN, Linear/Radial, пресеты прозрачности | | `SelectField.svelte` | селект в стиле дизайна |
| `Badge.svelte` | **новый** | тег типа шага (BACKGROUND/TRANSFORM/STYLE), чип «✓ AUTO» | | `CheckboxField.svelte` | чекбокс → switch-toggle 32×18 |
| `MetaList.svelte` | **новый** | `.meta-row` для DIMENSIONS/FORMAT/SIZE | | `Toggle.svelte` | переключатель (для toggle-group) |
| `EmptyState.svelte` | рестайл | под новый стиль панелей | | `SegmentedControl.svelte` | на базе `Segmented` — RU/EN, Linear/Radial, пресеты |
| `Badge.svelte` | на базе `Badge` |
| `MetaList.svelte` | на базе `MetaRow` |
| `EmptyState.svelte` | пустое состояние под новый стиль |
| `CodeBlock.svelte` | блок кода (gradient-art / direction-grid) |
| `DownloadButton.svelte` | кнопка скачивания (можно переиспользовать идею старой) |
Иконки: в рефе lucide-react; берём `lucide-svelte` (те же пути, MIT) Иконки: `lucide-svelte` (те же пути, MIT), 1617px, stroke, muted.
1617px, stroke, приглушённый цвет.
## 5. Шелл и страницы ## 5. Изоляция старого и нового (критично)
### 5.1 Layout (`+layout.svelte`) Без префиксов и обёрток — только за счёт того, какие layout грузят какой CSS.
- Topbar: brand-mark «EP» (синий квадрат 30px) + `easy-png-tools` + версия - **Корневой layout `src/routes/+layout.svelte`** перестаёт импортировать
суффиксом `/ v0.x`; справа — статус «LOCAL-ONLY», icon-btn темы `../app.css`. В нём остаётся только общая логика (init темы/locale) и
(Moon/Sun), сегмент RU|EN. нейтральный `<div>{children}</div>` без глобальных стилей дизайна.
- Footer: `easy-png-tools vX` · `pipeline is local-only` · © год. - **Старая ветка `src/routes/(old)/+layout.svelte`** импортирует `app.css`
- Фон-сетка на корневом контейнере `.app-shell`. и содержит текущую шапку/подвал (разметку из нынешнего корневого layout).
Все старые страницы переносятся внутрь `(old)/` (группа в скобках не
меняет URL): `(old)/+page.svelte`, `(old)/demo/...`,
`(old)/list-tools/...`, `(old)/tools/[id]/...`.
- **Новая ветка `src/routes/preview/+layout.svelte`** импортирует
`design2.css` и рендерит `<AppShell>`. Сюда же — новые страницы (§6).
- Благодаря code-splitting CSS в SvelteKit: на старых маршрутах грузится
только `app.css`, на `preview/*` — только `design2.css`. Скоуп стилей
Svelte-компонентов добавляет второй уровень изоляции. Никаких `.ds2`.
- Переключатель для ручной проверки: временный флаг `previewDesign` в
`localStorage` + кнопка в старой шапке («Preview v2»), ведущая на
`/preview`. На фазе 4 флаг убираем.
### 5.2 `/` — воркспейс > Почему не `(new)`-группа с теми же путями вместо `preview/*`: две группы
> не могут одновременно определять один и тот же URL (`(old)/+page.svelte`
> и `(new)/+page.svelte` оба → `/` = конфликт маршрутов). Поэтому новая
> ветка живёт под префиксом `preview/`, а на фазе 4 файлы переносятся на
> реальные пути и группа `(old)` удаляется.
>
> Это совпадает с рекомендованным в документации SvelteKit паттерном:
> «put your entire app inside one or more groups except the routes that
> should not inherit the common layouts» — старое целиком в `(old)`, новое
> снаружи. Синтаксис `@`-breakout (`+layout@.svelte`, `+page@.svelte`) здесь
> не требуется: «выломаться» можно лишь до корня, а нам нужно, чтобы именно
> у корня НЕ было `app.css`; если позже захотим держать новые маршруты внутри
> группы, `@` пригодится для сброса родительского layout.
Текущий hero + ToolSearch переезжает в рампу референса: eyebrow ## 6. Маршрутизация параллельных страниц
«PNG PROCESSING / WORKSPACE», крупный h1 (clamp 3664px, tracking 0.06em),
lede; поиск — строка в стиле file-chip/pipeline-head. «Открыть последний» —
кнопка secondary. Каталог `/list-tools` — сетка карточек в стиле
`image-card` (label сверху, canvas-превью).
### 5.3 `/tools/[id]` — страница инструмента Новые страницы живут в **отдельной ветке `preview/*`**, не трогая старые:
Главная перестройка. Целевая раскладка из рефа — двухпанельная:
```txt ```txt
eyebrow + tool-title (+ LIVE PREVIEW) src/routes/+layout.svelte # нейтральный, БЕЗ app.css
┌─ settings-panel ────────┐ ┌─ preview-panel ─────────┐ src/routes/(old)/+layout.svelte # импорт app.css + старая шапка/подвал
│ panel-heading │ │ preview-toolbar │ src/routes/(old)/+page.svelte # / (старое)
│ setting-group ×N │ │ checker-canvas / source │ src/routes/(old)/demo/+page.svelte # /demo
│ (Slider/Color/Toggle…) │ │ + result comparison │ src/routes/(old)/list-tools/...
│ settings-footer (reset) │ │ meta-row │ src/routes/(old)/tools/[id]/...
└─────────────────────────┘ └─────────────────────────┘ src/routes/preview/+layout.svelte # импорт design2.css, <AppShell>
src/routes/preview/+page.svelte # /preview — воркспейс (index/demo)
src/routes/preview/demo/+page.svelte # /preview/demo
src/routes/preview/list-tools/+page.svelte
src/routes/preview/tools/[id]/+page.svelte
``` ```
- `ParamsCard`/`ParamForm` → секция настроек: поля становятся - Каждая новая страница импортирует **только** `kit/*`. Старые страницы
`.setting-group` через обновлённый `ui/*`. не изменяются (только перемещены в `(old)/`).
- `SourceCard`/`ResultCard`/`Preview` → превью-панель: toolbar с именем - Фаза 4: содержимое `preview/*` переносится на реальные маршруты
файла и download-btn, canvas на шахматке, result-meta снизу. (move-файлы), группа `(old)/` удаляется, `design2.css` подключается в
- Chain-блоки (`ChainToolBlock`) — нумерованные step-cards из главной корневом `+layout.svelte` (как новый основной слой), временный флаг/кнопка
рефа: индекс `01`, drag-handle, Badge типа, заголовок, кнопка удаления; убираются.
параметры этапа — те же setting-groups внутри карточки.
- Существующий `ToolStageClassic`/inline-вариант заменяются целевой
раскладкой; stage-абстракция из plan-inline-params закрывается этим
переездом.
### 5.4 `/demo` ## 7. Фазы выполнения (1–5 по запросу)
Зеркало `refs-html/index.html` — витрина пайплайна, используется как Каждая фаза заканчивается зелёными `test`/`check`/`build` и ревью в браузере
приёмочный стенд нового стиля (делается первым среди страниц). (обе темы) против `refs-html/`.
## 6. Этапы и проверки - **Фаза 1 — Фундамент + UI-kit.** Токены §2, `design2.css` по §5, все
примитивы §3 и контролы §4 как отдельные компоненты. Критерий:
демо-страница kit'а (`/preview` или временная) показывает все состояния
(light/dark, hover/disabled, все варианты Button/Segmented/Badge);
unit-тесты форм не падают; **старые страницы визуально не изменились**
(изоляция работает).
Каждый этап заканчивается зелёными `test`/`check`/`build` и ревью в браузере - **Фаза 2 — Новые страницы.** Под `preview/*` (§6): воркспейс, demo,
(обе темы) против соответствующего HTML из `refs-html/`. list-tools, tool-page (двухпанельная раскладка из рефа: settings-panel +
preview-panel, step-cards для chain). Критерий: разметка соответствует
`refs-html/index.html`, `gradient.html`, `background-remover.html`,
`list-tools.html`; интерактив (слайдеры/тоглы/загрузка/автозапуск) работает
в новом стиле; старые маршруты продолжают работать как раньше.
- **A. Фундамент** — новые токены + алиасы старых, @fontsource IBM Plex, - **Фазa 3 — Проверка нового дизайна.** Смоук §8 (обе темы, узкий экран,
утилиты §3, тёмная тема на `[data-theme]`. Критерий: приложение выглядит 800px), скриншоты против `refs-html/`, прогон старого тест-сьюта для
по-старому (алиасы дают прежние цвета близко к новым), тесты зелёные, доказательства отсутствия регресса, RU/EN-локализация новых лейблов.
FOUC-скрипт темы работает. Критерий: визуальное совпадение с рефом, зелёные тесты, записанные
- **B. UI-kit** — компоненты §4: сначала рестайл существующих, потом новые скриншоты приняты.
(`SegmentedControl`, `Badge`, `MetaList`). Критерий: демо-страница kit'а
или `/demo` показывает все состояния; unit-тесты форм не падают.
- **C. Шелл** — topbar/footer по §5.1, переключение темы и языка в новом
виде. Критерий: i18n/theme тесты зелёные, разметка шапки соответствует
рефу.
- **D. Страница инструмента** — раскладка §5.3 на `/demo`, затем на всех
инструментах; chain-карточки. Критерий: смоук §7, скриншоты против
`refs-html/gradient.html` и `background-remover.html`.
- **E. Главная и каталог** — §5.2. Критерий: поиск/фильтры работают,
покрытие search-coverage/i18n тестов зелёное.
- **F. Чистка** — удаление алиасов старых токенов, неиспользуемых классов
`app.css` (`.tool-stage`, `.pane*`…), финальный проход по брейкпоинтам
1200/1100/800/480 из рефа. Критерий: grep по старым токенам пуст,
build без предупреждений.
Оценка объёма: A+B — фундамент (~полдня), C+D — основная работа (~1–2 дня), - **Фаза 4 — Сделать новый дизайн основным.** Перенос `preview/*`
E+F — добивка (~полдня). реальные маршруты; `design2.css` подключается в корневом `+layout.svelte`;
удаление preview-группы и временного флага/кнопки. Старые страницы теперь
не используются (мёртвый код), но физически ещё в репо.
Критерий: реальные маршруты отдают новый дизайн, тесты зелёные, билд без
предупреждений.
## 7. Смоук (после этапа D) - **Фаза 5 — Удалить старый дизайн.** Удаление старых страниц, старого
`ui/`, старого `app.css` (и его токенов), неиспользуемых классов;
переименование `kit/``ui/` (финальное имя) либо оставление `kit/` как
основного — решается на фазе 1. Финальный проход по брейкпоинтам
1200/1100/800/480. Критерий: `grep` по старым токенам/классам пуст,
build чистый, старый дизайн нигде не упоминается.
Оценка объёма: Фаза 1 — фундамент+kit (~1 день), Фаза 2 — страницы
(~1–2 дня), Фаза 3 — проверка (~полдня), Фаза 4–5 — переключение и чистка
(~полдня).
## 8. Смоук (после фазы 3, контроль на фазе 4)
1. Светлая и тёмная тема: сетка фона, панели, шахматка канвасов читаются, 1. Светлая и тёмная тема: сетка фона, панели, шахматка канвасов читаются,
контраст mono-лейблов достаточный. контраст mono-лейблов достаточный.
@@ -176,16 +258,102 @@ E+F — добивка (~полдня).
шахматке. шахматке.
4. Chain из 3+ инструментов: step-cards рендерятся, удаление/сброс работают. 4. Chain из 3+ инструментов: step-cards рендерятся, удаление/сброс работают.
5. Узкий экран 800px: настройки над превью, sticky выключается как в рефе. 5. Узкий экран 800px: настройки над превью, sticky выключается как в рефе.
6. RU/EN: новые лейблы локализованы; mono-лейблы рефа либо ключи i18n, 6. RU/EN: новые лейблы локализованы; mono-лейблы рефа либо ключи i18n,
либо осознанно английские брендовые элементы (см. §8). либо осознанно английские брендовые элементы (см. §9).
## 8. Открытые вопросы ## 9. Открытые вопросы
- Mono-лейблы рефа на английском (`PROCESSING PIPELINE`). Предложение: - **Имя финального каталога компонентов:** оставить `kit/` как основное имя
завести i18n-ключи, но для техно-эстетики допустимо оставить часть или переименовать в `ui/` на фазе 5 (удалив старое `ui/`). Рекомендую
английскими как «приборную панель». Решить на этапе A. сразу писать в `kit/`, на фазе 5 переименовать в `ui/`. Решить на фазе 1.
- Версия в топбаре/футере: брать из package.json при сборке (define) или - **Изоляция через layout:** `app.css` вынесен из корневого layout в
захардкодить? Мелочь, решить на этапе C. `(old)/+layout.svelte`; новый `design2.css` — только в `preview/+layout`.
- `refs/` оставляем в репо как источник правды; при изменении дизайна — Проверить на фазе 1, что на `/preview/*` не попадают стили старого
правки там, затем синхронизация вручную. Регенерация refs-html описана в дизайна (DevTools → вкладка Styles, нет правил из `app.css`).
его README. - **Переключатель для проверки:** рекомендую `localStorage`-флаг +
кнопка «Preview v2» в старой шапке + группа `preview/*`. Убрать на фазе 4.
- **Mono-лейблы рефа на английском** (`PROCESSING PIPELINE`): завести i18n-
ключи, но допустить часть английских брендовых («приборная панель»).
- **Версия в шапке/футере:** из `package.json` через `define` или
захардкодить — мелочь, решить при сборке topbar.
- **`refs/` и `refs-html/` — одноразовый источник, НЕ поддерживаемый.**
После внедрения нового дизайна все правки дизайна делаются сразу в
продакшен-коде (`design2.css` + `kit/`), а не в `refs/`. Механизм
синхронизации «ref → код» не нужен и не создаётся. `refs/` и `refs-html/`
можно удалить из репо на фазе 5 (по желанию), они не являются частью
рантайма.
## 10. План исполнения (мелкие коммиты)
Ветка `feat/redesign`. Каждый шаг — отдельный коммит, цель < ~500 строк.
Перед стартом: `test`/`build` зелёные на базе (якорь регрессии).
### Шаг 0. Изоляция layout (без дизайна)
- [ ] **[C1]** Сделать корневой `routes/+layout.svelte` нейтральным: убрать
`import '../app.css'`, оставить только init темы/locale и
`<div>{children}</div>`.
- [ ] **[C2]** Создать `routes/(old)/+layout.svelte` (импорт `app.css` + старая
шапка/подвал) и перенести старые страницы (`+page`, `demo`, `list-tools`,
`tools/[id]`) в `(old)/`. URL не меняются. Проверка: старый сайт идентичен.
_(файлы — move, объём строк минимален)_
### Шаг 1. Фундамент нового дизайна
- [ ] **[C3]** Добавить `@fontsource/ibm-plex-sans` + `@fontsource/ibm-plex-mono`,
подключить шрифты в `design2.css` (self-host, offline-first).
- [ ] **[C4]** Создать `src/lib/styles/design2.css`**только токены** `:root` +
`[data-theme='dark']` (таблица §2). Без утилитарных классов.
- [ ] **[C5]** Примитивы batch 1: `AppShell`, `BlueprintGrid`, `CheckerCanvas`,
`MonoLabel`, `StatusDot`/`StatusLine`.
- [ ] **[C6]** Примитивы batch 2: `Panel`, `PanelHeading`, `SettingGroup`,
`SettingsFooter`, `MetaRow`/`MetaList`, `Segmented`, `Badge`, `StepCard`,
`ToolCard`, `ImageCard`/`PreviewTile`. _(при превышении 500 строк —
разбить на C6a/C6b)_
- [ ] **[C7]** Контролы: `Icon`, `IconButton`, `Button`, `Field`, `SliderField`,
`ColorField`, `TextField`, `SelectField`, `CheckboxField`, `Toggle`,
`SegmentedControl`, `EmptyState`, `CodeBlock`, `DownloadButton`.
### Шаг 2. Витрина kit (проверка компонентов)
- [ ] **[C8]** `preview/+layout.svelte` (импорт `design2.css` + `<AppShell>`) и
временная `preview/kit` страница со всеми состояниями (light/dark,
hover/disabled, варианты Button/Segmented/Badge). Проверка: визуально
против `refs-html/`, старый сайт не затронут.
### Шаг 3. Новые страницы
- [ ] **[C9]** `/preview` — воркспейс (eyebrow, h1, lede, поиск, «открыть последний»).
- [ ] **[C10]** `/preview/list-tools` — каталог карточек.
- [ ] **[C11]** `/preview/demo` — зеркало воркспейса (приёмочный стенд).
- [ ] **[C12]** `/preview/tools/[id]` — раскладка gradient (settings-panel + preview-panel).
- [ ] **[C13]** `/preview/tools/[id]` — раскладка background-remover (comparison-grid).
- [ ] **[C14]** step-cards для chain в tool-page.
### Шаг 4. Переключатель и проверка
- [ ] **[C15]** Кнопка «Preview v2» + `localStorage`-флаг в старой шапке (ведёт на
`/preview`).
- [ ] **[C16]** Смоук §8, скриншоты против `refs-html/`, прогон старых тестов
(доказательство отсутствия регресса). Фиксы по результатам — отдельными
мелкими коммитами.
### Шаг 5. Сделать новый дизайн основным
- [ ] **[C17]** Перенести `preview/*` → реальные маршруты (move), удалить
`(old)/`, корневой `+layout.svelte` импортирует `design2.css` + новый shell.
Убрать флаг/кнопку.
- [ ] **[C18]** Правки импортов/редиректов после переноса, проверка билда.
### Шаг 6. Удаление старого
- [ ] **[C19]** Удалить старое `ui/`, прочие старые компоненты, старый `app.css`,
неиспользуемые классы. Переименовать `kit/``ui/` (если решено на C1).
- [ ] **[C20]** Финальный проход по брейкпоинтам 1200/1100/800/480; build без
предупреждений; `grep` по старым токенам/классам пуст.
- [ ] **[C21]** _(опционально)_ Удалить `refs/` и `refs-html/` из репо — они
больше не источник правды.
> Если какой-то коммит тянет за собой > 500 строк (например, C6/C7),
> разбивать на под-коммиты по 2–4 компонента. Тесты/билд прогонять после
> каждого коммита, чтобы регрессия локализовалась одним шагом назад.