## 1. Статика и встраивание

- [x] 1.1 Создать структуру `web/static/{css,js,vendor}/`; `web/static/vendor/` в gitignore
- [x] 1.2 Шрифты IBM Plex Sans + IBM Plex Mono (cyrillic+latin, нужные начертания) — в манифест, фетч в `web/static/vendor/fonts/`
- [x] 1.3 Перенести `jellybit.css` из `tmp/design/` в `web/static/css/`, добавить `@font-face` на `../vendor/fonts/` (убрать ссылки на Google Fonts)
- [x] 1.4 Манифест `web/assets.manifest` (путь/URL/sha256) + идемпотентный `task assets` (нет файла или хеш не сошёлся → качаем, иначе с диска); `task build`/`run` зависят от `assets`
- [x] 1.5 Вынести `copyHash` в `web/static/js/app.js` (vanilla)
- [x] 1.6 Расширить `go:embed` в `web/web.go` на `static/*`
- [x] 1.7 Добавить роут `/static/*` (`http.FileServer` + `StripPrefix`) с `Cache-Control`; решить cache-busting CSS (хеш при старте)

## 2. Общие партиалы

- [x] 2.1 Партиал `web/templates/partials/header.html` (`.app-header`)
- [x] 2.2 Партиал `partials/status_badge.html` — карта `state→class/подпись` для всех 14 состояний (один источник)
- [x] 2.3 Партиал `partials/layout_widget.html` — виджет «файл источника → раскладка» (общий для review и download)
- [x] 2.4 Перенастроить `template.ParseFS` в `httpapi` на загрузку партиалов; сохранить/дополнить FuncMap

## 3. Страница списка (index)

- [x] 3.1 Перенести вёрстку `index.html` из `tmp/design/` в `web/templates/index.html` (карточки `range`, единое окно добавления, фильтр/поиск)
- [x] 3.2 Подключить `jellybit.css` и htmx; убрать `<meta http-equiv="refresh">` и инлайн-`<style>`
- [x] 3.3 Бейдж статуса через партиал; блок `.card-acts` — условия по `state` (соответствие `downloadView`)
- [x] 3.4 `deleted` скрыт по умолчанию + переключатель «показать всё»
- [x] 3.5 Проставить `name` полей форм действий под существующие хендлеры; сверить каждое действие по состоянию

## 4. Страница ревью (review)

- [x] 4.1 Перенести вёрстку `review.html` (догадка, кандидаты `range`, причины, уточнение, действия)
- [x] 4.2 Строка «нейронка» (`.nn-cand`) — обычный кандидат, не особый режим
- [x] 4.3 Превью путей через серверное поле `reviewView.Preview` (единая `internal/layout`)
- [x] 4.4 Сверить поля форм (`apply`/`refine`/`rerecognize`/`type`/`candidate`/`provider`/`nobase`/`defer`) с хендлерами

## 5. Страница просмотра (download)

- [x] 5.1 View-структура `downloadDetailView` (распознавание, файлы, раскладка, раздача, история)
- [x] 5.2 Хендлер `GET /download/{id}` + роут; 404 на отсутствующую загрузку
- [x] 5.3 Шаблон `web/templates/download.html` (переиспользует партиал виджета и бейдж)
- [x] 5.4 Таймлайн истории (`.timeline`) и действия по состоянию

## 6. Проверка и завершение

- [x] 6.1 `task lint` и `task test` зелёные
- [x] 6.2 Ручная проверка: все действия по каждому состоянию срабатывают, превью на ревью = реальная раскладка
- [x] 6.3 Проверить отсутствие внешних сетевых запросов (шрифты/стили только с `/static/`)
- [x] 6.4 `openspec validate --strict web-ui-design-port`
- [x] 6.5 Ревью кода (до archive) — пройдено; находки MEDIUM-1/2, LOW-2/3 исправлены
