# План: аудит верности `preview/*` против `refs-html` (DOM → CSS) > Статус: к выполнению. Ветка `feat/redesign`. > Источник правды по пикселям: `refs-html/*.html` (статический экспорт рефа). > Актуальный рабочий аудит сейчас — `pnpm refs-audit` (`scripts/audit.mjs`), но он > **сломан** (см. «Почему текущий аудит не работает») и подлежит замене. ## Почему текущий аудит не работает `scripts/audit.mjs` сопоставляет элементы **только по тексту** и берёт в сравнение **только листовые узлы** (у которых нет детей). Контейнеры/карточки/ панели, несущие `border-radius`, отступы и позиционирование, в сравнение **вообще не попадают** (`byText` кладёт в мапу только элементы с непустым `text`). Следствия: - разница радиусов у карточек невидима (карточка — родитель без своего текста); - позиция кнопки (`Download result`) не ловится — это структурная разница; - `onlyOurs / onlyRef` — это просто счётчик текстовых строк на одной стороне, **не метрика верности**. Плюс он не делает пиксельного сравнения, то есть принципиально не может сказать «выглядит по-другому». Это текстовый дифф стилей листовых текстов — и всё. ## Решения (подтверждены автором) 1. **Копирайт превью — через i18n `t()` с EN-базой.** Сейчас RU-литералы хардкодом только в `preview/+page.svelte:26-27` и `preview/list-tools/+page.svelte:31` (эти страницы не используют i18n, в отличие от `(old)/` и компонентов `DownloadButton`/`ChainToolBlock`/…). Заводим их через `t()` — совпадёт с рефом (EN). 2. **Имена классов НЕ сводим к рефу.** Матчинг делаем по **структурному пути**, а не по классу. Компоненты `kit/` остаются идиоматичными, Stage 0 не откатываем. Требуется только эквивалентность *структуры* (теги, вложенность, порядок сиблингов, наличие узлов, текст). 3. **Пиксельный дифф (Playwright + pixelmatch) пока НЕ делаем.** DOM+CSS-аудита достаточно; добавим как сеть позже, если стили что-то упустят. 4. **Порядок прогона маршрутов:** `demo` → `list-tools` → затем 2 инструмента (`tools/linear-gradient-png` ↔ `gradient.html`, `tools/remove-background-png` ↔ `background-remover.html`). ## Принципы - Никаких правок старого дизайна `(old)/` и старого `ui/`. - Коммиты атомарные (< ~500 строк), по 1–2 компонента/скрипта; после каждого — `lint` + `svelte-check` + `build` + соответствующий аудит (diff не должен расти без причины). - Коммиты делает автор (агент не коммитит). - Шрифты уже совпадают: `design2.css:1-6` грузит IBM Plex Sans/Mono через `@fontsource`, токены `:34-35` — `"IBM Plex Sans"/"IBM Plex Mono"` (как в рефе `demo.html:67-68`). Пиксельный шум от шрифтов не предвидится. ## Подход: две фазы Корень проблемы — нет **стабильного ключа сопоставления**. Разбиваем на две фазы: сначала доводим DOM до структурного равенства с рефом (фаза A), затем на стабильном DOM сравниваем стили по тому же пути (фаза B). Фаза A сама по себе ловит именно то, из-за чего возникли претензии (кнопка не в том родителе, лишние/недостающие обёртки, перепутанный порядок) — и без эстетических решений. --- ## Фаза A — DOM/структурный аудит (`scripts/audit-dom.mjs`) **Цель:** Svelte рендерит структуру, идентичную `refs-html` (дерево тегов, вложенность, порядок сиблингов, наличие узлов, текст). Имена классов могут отличаться. ### Нормализация узла (ключ сравнения) Для каждого элемента (пропускаем `SCRIPT`/`STYLE`/`NOSCRIPT` и скрытые поддеревья, игнорируем служебное): - **тег** (`tagName` в lower-case); - **классы** — как отсортированный набор (для инфо, не для матчинга); - **нормализованный текст** — `trim`, `collapse-whitespace`, без SVG-иконок внутри (текст иконок игнорируем); - **порядок детей** — позиция среди сиблингов (`nth-child`). Матчинг — по **структурному пути** от корня сравнения: `tag:nth-child(i) > tag:nth-child(j) …`. Не по классу и не по тексту. ### Полное соответствие, без IGNORE Оболочка (наш `TopBar`/`AppShell`/`preview-footer` vs рефовый `.topbar`/`.footer`/`.language`) тоже сводим к рефу — **IGNORE-список не заводим**. Сравниваем всё дерево от `` (без пропуска служебного, кроме Svelte-атрибутов и комментов гидрации), чтобы получить полное структурное соответствие, а не только контента. Шапка/футер/переключатель языка — часть верности; позже, после полного фикса дизайна, всё равно планируется рефакторинг компонентов, где оболочку приведём в порядок и унифицируем. Аудит на этом этапе просто показывает все расхождения, включая оболочечные. ### Дифф Для каждого маршрута — набор дельт: - `added` — у нас, нет в рефе; - `removed` — в рефе, нет у нас; - `moved` — тот же текст/тег, другой путь (перепутанный порядок/родитель); - `textMismatch` — нормализованный текст различается (в т.ч. RU vs EN). Класс-мисматч — **только информационно**, не блокирует (классы свои по решению №2). Счётчики: `added / removed / moved / textMismatch`. ### Рендеринг - **наше:** dev-сервер на `5179` (как сейчас в `audit.mjs`). - **реф:** `pathToFileURL` к `refs-html/.html` (`file://`). Реф — самодостаточный (инлайн `