/* Torkzt · catalog_poster.css — обложки, заглушки, скелетоны, мобильные правки.
 *
 * Подключать ПОСЛЕДНИМ из стилей каталога: часть правил ниже перебивает
 * пропорции и отступы из catalog.css и catalog_new.css.
 */

/* ═════════════════ заглушка вместо отсутствующего постера ═════════════════
 *
 * Локального постера нет — обычное дело после миграции игр и софта: обложек
 * в описаниях там не было. Пустой прямоугольник читался как ошибка загрузки.
 *
 * Оттенок приходит из PHP в --ph-h: базовый тон задаёт тип релиза, сдвиг
 * считается из id. На странице с 739 играми без единого постера одинаковые
 * плитки сливались в обои — теперь у каждой свой оттенок, и карточки видно
 * как отдельные объекты. Разброс узкий: заглушки не должны перетягивать
 * внимание с настоящих обложек по соседству.
 */

.poster-placeholder {
    position: relative;
    overflow: hidden;
    border-radius: inherit;
}

.rel-ph {
    --ph-h: 220;

    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;

    /* Два слоя: мягкое световое пятно за иконкой и общий диагональный уклон.
       Плоская заливка среди настоящих обложек читается как дырка в сетке. */
    background:
        radial-gradient(circle at 50% 42%,
            hsl(var(--ph-h) 46% 95%) 0%,
            hsl(var(--ph-h) 34% 90%) 45%,
            hsl(var(--ph-h) 26% 86%) 100%);
}

/* Диагональная штриховка — очень слабая, задаёт фактуру и снимает
   ощущение «не загрузилось». */
.rel-ph::before {
    content: "";
    position: absolute;
    inset: 0;
    background-image: repeating-linear-gradient(
        135deg,
        rgba(255, 255, 255, .5) 0 2px,
        rgba(255, 255, 255, 0) 2px 9px);
    opacity: .35;
    pointer-events: none;
}

.rel-ph-ico {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 34%;
    max-width: 68px;
    color: hsl(var(--ph-h) 32% 62%);

    /* Лёгкая тень отрывает иконку от фона: без неё она выглядит как
       водяной знак, а не как содержимое карточки. */
    filter: drop-shadow(0 2px 3px hsl(var(--ph-h) 30% 70% / .55));
}

.rel-ph-ico svg {
    width: 100%;
    height: auto;
    display: block;
}

body[data-bs-theme='dark'] .rel-ph {
    background:
        radial-gradient(circle at 50% 42%,
            hsl(var(--ph-h) 16% 22%) 0%,
            hsl(var(--ph-h) 14% 17%) 45%,
            hsl(var(--ph-h) 12% 13%) 100%);
}

body[data-bs-theme='dark'] .rel-ph::before { opacity: .06; }
body[data-bs-theme='dark'] .rel-ph-ico {
    color: hsl(var(--ph-h) 18% 42%);
    filter: none;
}

/* Нижняя строка карточки поверх заглушки.
   Тёмный градиент рассчитан на фотографию — на светлой заглушке он
   выглядит как чужеродная полоса, приклеенная снизу. */
.cat-poster:has(.poster-placeholder) .cat-footline {
    background: linear-gradient(to top,
        hsl(var(--ph-h, 220) 22% 74% / .92) 40%,
        hsl(var(--ph-h, 220) 22% 74% / 0));
}

.cat-poster:has(.poster-placeholder) .cat-footline .cat-status,
.cat-poster:has(.poster-placeholder) .cat-footline .cat-torrents {
    background: rgba(255, 255, 255, .55);
    color: #38414d;
}

/* ═════════════════ квадратная обложка ═════════════════
 *
 * Классы .cat-card-square и .cat-list-poster.is-square уже расставляет
 * catalog.php по release_type_poster_square(). Свой механизм здесь не
 * заводим — только доводим заглушку до той же пропорции.
 */

/* Квадрат нужен И рамке с картинкой, И заглушке.
   Раньше правило стояло только на .poster-placeholder: класс на карточку
   PHP вешал, но контейнеру с настоящим постером размер никто не задавал —
   квадратными становились только пустые карточки, а с обложкой оставались
   2:3. Симптом выглядел как «в музыке квадрат не работает». */

.cat-card-square .cat-poster,
.cat-card-square .poster-placeholder,
.cat-list-poster.is-square,
.cat-list-poster.is-square .poster-placeholder {
    aspect-ratio: 1 / 1;
}

/* Картинка внутри квадрата: заполняем кадр целиком.
   Нарезка сейчас приходит в 2:3, поэтому object-fit обрежет её по бокам —
   это временно, до перегенерации постеров в квадрат для музыки и софта.
   object-position по центру: у обложек альбомов значимое обычно в середине. */
.cat-card-square .cat-poster img,
.cat-list-poster.is-square img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
}

/* ═════════════════ поиск: иконка не наезжает на текст ═════════════════
 *
 * Лупа лежит поверх поля абсолютом. Отступ у input задавался в общем
 * правиле для всех .cat-input и лупу не учитывал — длинное значение
 * («Найти жанр» с введённым текстом, название с кириллицей) наползало
 * на значок и читалось как каша.
 *
 * Ширина отступа считается от размера иконки, а не подобрана на глаз,
 * поэтому при смене размера лупы ничего не разъедется.
 */

.cat-search {
    --cat-ico: 16px;
    --cat-ico-left: 12px;
    position: relative;
    display: flex;
    align-items: center;
}

.cat-search > svg,
.cat-search > .cat-search-ico {
    position: absolute;
    left: var(--cat-ico-left);
    top: 50%;
    transform: translateY(-50%);
    /* Размер задаётся и здесь, и атрибутами width/height в разметке.
       Без атрибутов SVG схлопывался в ноль ширины и торчал тонкой чёрточкой
       поверх плейсхолдера — стили каталога его размер не задавали вовсе. */
    width: var(--cat-ico);
    height: var(--cat-ico);
    flex: 0 0 auto;
    color: #98a2ac;
    pointer-events: none;
    z-index: 1;
}

.cat-search > input {
    width: 100%;
    /* иконка + её левый отступ + зазор */
    padding-left: calc(var(--cat-ico) + var(--cat-ico-left) + 10px);
    /* 16px обязательны: при меньшем Safari на iOS зумит страницу при
       фокусе, и вся раскладка фильтров съезжает */
    font-size: 16px;
}

.cat-search-sm { --cat-ico: 14px; --cat-ico-left: 10px; }

.cat-search:focus-within > svg { color: #00b874; }

/* ═════════════════ название и жанры под карточкой ═════════════════ */

.cat-card .cat-title {
    /* Две строки максимум и многоточие: раньше длинные названия
       разъезжались на три-четыре строки и ломали ровные ряды сетки. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    word-break: break-word;
    line-height: 1.3;
}

.cat-card .cat-meta {
    display: -webkit-box;
    -webkit-line-clamp: 1;
    -webkit-box-orient: vertical;
    overflow: hidden;
    word-break: break-word;
}

/* ═════════════════ скелетоны загрузки ═════════════════
 *
 * Каталог — обычные ссылки с перезагрузкой. На телефоне между нажатием и
 * отрисовкой проходит секунда-другая, экран выглядит замершим, и человек
 * жмёт второй раз. Скелетоны дают мгновенный отклик; настоящая страница
 * всё равно придёт и заменит их целиком.
 */

.cat-grid.is-loading { pointer-events: none; }

.cat-skel {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.cat-skel-poster {
    aspect-ratio: 2 / 3;
    border-radius: 12px;
}

.cat-skel-line {
    height: 12px;
    border-radius: 6px;
}

.cat-skel-line.is-short { width: 55%; }

.cat-skel-poster,
.cat-skel-line {
    background: linear-gradient(100deg, #eceff3 30%, #f6f8fa 50%, #eceff3 70%);
    background-size: 300% 100%;
    animation: catShimmer 1.2s ease-in-out infinite;
}

body[data-bs-theme='dark'] .cat-skel-poster,
body[data-bs-theme='dark'] .cat-skel-line {
    background: linear-gradient(100deg, #24272c 30%, #2d3138 50%, #24272c 70%);
    background-size: 300% 100%;
}

@keyframes catShimmer {
    from { background-position: 150% 0; }
    to   { background-position: -150% 0; }
}

@media (prefers-reduced-motion: reduce) {
    .cat-skel-poster,
    .cat-skel-line { animation: none; }
}

/* ═════════════════ телефон ═════════════════ */

@media (max-width: 767px) {
    /* Поля фильтра: 16px против автозума Safari — то же правило, что и
       в .cat-search, но эти инпуты лупы не имеют и живут отдельно. */
    .cat-input,
    .cat-sheet select,
    .cat-sheet input[type="text"],
    .cat-sheet input[type="number"] {
        font-size: 16px;
    }

    /* Кнопки и таблетки — не меньше 40px по высоте: ниже начинаются
       промахи пальцем, особенно у края экрана. */
    .cat-pill { min-height: 40px; display: inline-flex; align-items: center; }
    .cat-btn,
    .cat-sheet-foot button,
    .cat-sheet-foot a { min-height: 44px; }

    /* Кнопка действий на карточке: цель нажатия расширена без изменения
       видимого размера — иначе она конфликтует с нажатием по постеру. */
    .cat-act::after {
        content: "";
        position: absolute;
        inset: -8px;
    }

    .rel-ph-ico { width: 42%; max-width: 56px; }
}

@media (max-width: 400px) {
    .cat-skel { gap: 6px; }
    .cat-skel-line { height: 10px; }
}