# Proposal ## Why Сетка миниатюр часто отображает изображение крупнее, чем единственный вариант `thumb` (200px), потому что между миниатюрой 200px и превью 1200px нет промежуточного размера. При увеличении плиток (малое число колонок) и на экранах с высокой плотностью пикселей фото расплывается; обложки альбомов в обзоре и вовсе отдают только 200px. ## What Changes - Добавить четвёртый вариант `medium` — квадратный кроп 800×800, WebP — и роль `medium` в журнале объектов. `thumb` перевести на квадратный кроп 200×200; `preview` остаётся вписанным 1200×1200 для просмотрщика. - API фото SHALL отдавать `medium_url` рядом с `thumb_url`/`preview_url`; данные обложки альбома SHALL отдавать URL более крупного варианта обложки. - Сетка фото и обзор альбомов SHALL выбирать вариант под фактический размер плитки через `srcset` (200/800/1200) и `sizes`, а не всегда тянуть 200px. - Миграция расширяет ограничение роли `photo_objects` значением `medium` (Postgres и SQLite) и ставит в очередь перегенерацию вариантов для уже загруженных фото. - Из-за смены кропа у `thumb` существующие миниатюры перегенерируются (квадратными) вместе с добавлением `medium`. ## Capabilities ### New Capabilities Нет. ### Modified Capabilities - `photos`: требование «Варианты изображений» — четыре варианта, квадратный кроп grid-вариантов. - `media-objects`: требование «Журнал объектов» — роль `medium` в наборе ролей. - `albums`: требование «Отображение обложки альбома» — URL обложки крупнее миниатюры. - `ui-workspace`: новое требование — сетка и обзор альбомов подбирают вариант изображения под размер плитки. ## Impact - Backend: `photos/{pipeline,worker,objects,models,service,store,sqlite_store}.go`, `albums/{models,store,sqlite_store,service}.go`, миграции Postgres и SQLite, бэкфилл `variant_jobs`, контрактные тесты `repo/contract`. - Frontend: `PhotoGrid.svelte` и обзор альбомов (`(app)/+page.svelte`). - API: новые поля `medium_url` (фото) и URL medium-обложки (альбом); существующие клиенты продолжают работать (аддитивно). - Хранилище: +1 производный объект (800px WebP) на фото; preview у существующих фото перегенерируется впустую и удаляется сборщиком мусора по ссылкам.