## MODIFIED Requirements

### Requirement: Страницы веб-UI

Веб-UI SHALL предоставлять страницы: список загрузок с единым окном
добавления, **серверными фильтром по группе состояний, поиском и постраничной
выдачей (пагинацией)** (`/`), экран ревью одной загрузки (`/review/{id}`)
и страницу просмотра одной загрузки (`/download/{id}`) с распознаванием,
файлами→раскладкой, историей, блоком информации о торренте и — для сидирующих
задач — секцией живой статистики раздачи. Карточки активных (downloading)
загрузок в списке SHALL содержать индикатор прогресса. Фильтр, поиск и номер
страницы SHALL передаваться GET-параметрами запроса (например `f`, `q`, `page`)
и SHALL работать без клиентского JavaScript. Состояние `deleted` SHALL быть
скрыто в списке по умолчанию (с переключателем «показать всё»). Механика живого
обновления прогресса и наполнение секции раздачи определяются capability
`live-status`.

#### Scenario: Просмотр одной загрузки

- **WHEN** клиент открывает `GET /download/{id}` существующей загрузки
- **THEN** отрисовывается страница с её распознаванием, файлами, раскладкой и
  историей

#### Scenario: Прогресс активной загрузки в списке

- **WHEN** в списке есть загрузка в состоянии `downloading`
- **THEN** её карточка содержит индикатор прогресса (прогресс-бар со скоростью
  и ETA)

#### Scenario: Удалённые скрыты по умолчанию

- **WHEN** в списке есть загрузки в состоянии `deleted` и фильтр «показать
  всё» не включён
- **THEN** они не отображаются, но доступны при включённом переключателе

#### Scenario: Пагинация списка

- **WHEN** загрузок под текущим фильтром больше, чем помещается на одну
  страницу, и клиент запрашивает `GET /?page=N`
- **THEN** возвращается N-я страница результатов и элементы навигации по
  страницам, сохраняющие текущие фильтр и поисковый запрос

#### Scenario: Серверный фильтр и поиск

- **WHEN** клиент запрашивает список с параметрами фильтра по состоянию и/или
  строкой поиска (`GET /?f=review&q=дюна`)
- **THEN** сервер возвращает только подходящие загрузки (по группе состояний и
  совпадению строки в названии/infohash/контексте), отфильтрованные на стороне
  БД, а не на клиенте

## ADDED Requirements

### Requirement: Порядок списка загрузок

Список загрузок SHALL сортироваться по времени добавления торрента в источник
(qBittorrent `added_on`), от новых к старым. Если время добавления в источник
неизвестно, для сортировки SHALL использоваться время создания загрузки в
jellybit (`created_at`). Порядок MUST быть согласован между страницами
пагинации.

#### Scenario: Сортировка по времени добавления в источник

- **WHEN** отрисовывается список загрузок, у которых известно время добавления
  в qBittorrent
- **THEN** загрузки идут от недавно добавленных к более старым по этому времени

#### Scenario: Фолбек порядка без времени источника

- **WHEN** у загрузки нет сохранённого времени добавления в источник
- **THEN** для её позиции в списке используется время создания загрузки в
  jellybit

### Requirement: Заголовок загрузки из имени раздачи

Веб-UI SHALL показывать заголовком загрузки (в карточке списка и в шапке
страницы `/download/{id}`) сохранённое отображаемое имя раздачи (`display_name`,
переданное в qBittorrent при приёме). Если имя пусто, заголовок SHALL брать
распознанное название из плана; если и его нет — сырой источник (`source_ref`),
усечённый до одной строки как обычный заголовок. Заголовок MUST NOT занимать
несколько строк сырым magnet.

#### Scenario: Заголовок из имени раздачи

- **WHEN** у загрузки сохранено отображаемое имя раздачи
- **THEN** карточка и страница показывают это имя заголовком

#### Scenario: Фолбек до распознавания и без имени

- **WHEN** отображаемого имени нет, но есть распознанное название
- **THEN** заголовком служит распознанное название
- **AND** если нет ни того, ни другого — заголовком служит усечённый до одной
  строки сырой источник, а не многострочный magnet

### Requirement: Матч с записью метабазы ссылкой

Веб-UI SHALL показывать подтверждённый матч с записью метабазы (TMDB/TVDB/IMDb)
как ссылку на эту запись — на странице просмотра `/download/{id}` (блок
распознавания) и в блоке «Источник совпадения» экрана ревью. Ссылка SHALL
открываться в новой вкладке с `rel="noopener"`. Рядом со ссылкой SHALL быть
видны провайдер, идентификатор записи и (при наличии) год.

#### Scenario: Матч виден ссылкой на странице просмотра

- **WHEN** у загрузки подтверждён матч с записью метабазы и известен URL записи
- **THEN** в блоке распознавания на `/download/{id}` матч показан ссылкой на
  запись с провайдером и id

#### Scenario: URL записи неизвестен

- **WHEN** матч подтверждён (например, id задан вручную), но канонический URL
  записи построить нельзя
- **THEN** матч показывается текстом (провайдер и id) без ссылки, страница не
  ломается

### Requirement: Блок информации о торренте

Страница `/download/{id}` SHALL содержать блок «Информация о торренте» с полным
исходным источником (magnet/URL/`.torrent`-ссылка) и infohash с кнопкой
копирования. Сырой источник MUST выноситься в этот блок, а не в заголовок.

#### Scenario: Полный источник в отдельном блоке

- **WHEN** клиент открывает `GET /download/{id}`
- **THEN** полный источник (magnet) и infohash показаны в блоке «Информация о
  торренте», а заголовок страницы остаётся человекочитаемым именем
