/*
 * Страница цифровых товаров /digital.
 *
 * Почему отдельный файл, а не Tailwind. Публичные страницы вклеивают
 * public/css/2024-tailwind.css ИНЛАЙНОМ, а собирается он скриптом `npm run tail24`,
 * который написан под Tailwind v3 — при том что в package.json стоит только v4.1.17.
 * v4 проглатывает v3-конфиг молча, тему не грузит, и из сборки исчезают все утилиты
 * со шкалой: gap-y-20, px-44, font-sans, space-y-32 (550 селекторов против 450).
 * То есть добавить один класс нельзя — любая пересборка снимает отступы и шрифт
 * со ВСЕГО сайта. Пока это не починено, страница одевается своим CSS.
 *
 * ⚠ Если всё-таки надо пересобрать tailwind — только с прижатой версией:
 *     npx tailwindcss@3 -c tailwind-2024.js -i ./app/resources/2022.css \
 *         -o ./public/css/2024-tailwind.css --minify
 * Проверено: воспроизводит живой файл байт в байт.
 *
 * 🔴 Здесь px и em, НИ ОДНОГО rem. У публичного фронта html{font-size:10px}
 * (Bootstrap 3), поэтому rem тут равен 10px, а не 16: любая rem-величина съёживается
 * в 0,625 и лестница отступов переворачивается. em считается от собственного кегля
 * элемента и к этому невосприимчив.
 *
 * Файл подключается только на /digital — из @section('styles') вьюхи 2024/digital.blade.php,
 * то есть ПОСЛЕДНИМ в каскаде (порядок — в докблоке layout.blade.php). Значит при равной
 * специфичности он перебивает bootstrap, black-100 и инлайновый tailwind, и !important
 * нужен только против чужих !important (в black-100 такой висит на подчёркивании ссылок).
 */

/* ── Страница и группы ──────────────────────────────────────────────────────
 * Лестница отступов: 128 между группами > 50 между рядами карточек > 40 под шапкой
 * группы > 16 между заголовком и подзаголовком. Разрыв между группами обязан быть
 * заметно больше шва между рядами одной группы, иначе граница раздела читается как
 * поехавшая вёрстка, а не как начало другого раздела.
 */
.digital-page {
    padding-top: 50px;
}

.digital-section + .digital-section {
    margin-top: 128px;
}

.digital-section-head {
    margin-bottom: 40px;
}

/* Заголовки — div, а не h*: единственный h1 страницы печатает обвязка
 * (layout.blade.php, текст из метатегов, спрятан клипом ради SEO). */
.digital-section-title {
    font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
    font-size: 32px;
    font-weight: 700;
    line-height: 1.2;
    color: #000;
    text-align: center;
}

.digital-section-subtitle {
    margin-top: 16px;
    padding-left: 110px;
    padding-right: 110px;
    text-align: center;
}

/* ── Сетка ──────────────────────────────────────────────────────────────────
 * Всегда три в ряд, для всех цифровых товаров: и книги, и комиксы, и аудиокниги.
 * Ячейка выходит 293px = (960 контейнера − 30 полей бутстрапа − 2×25 промежутка) / 3.
 */
.digital-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    column-gap: 25px;
    row-gap: 50px;
}

/* ── Карточка: три этажа ────────────────────────────────────────────────────
 * height:100% обязателен: грид растягивает ячейку по самой высокой в ряду, и без
 * него карточка осталась бы короче ячейки, а этаж корзины не смог бы прижаться к низу.
 */
.digital-card {
    display: flex;
    flex-direction: column;
    height: 100%;
}

/*
 * Этаж обложки. Коробка фиксированная 175×260, картинка вписывается и ПРИЖАТА К НИЗУ:
 * обложки у нас трёх пропорций — книжный портрет (0,65–0,83), квадрат у аудиокниг
 * и альбомные комиксы (1,45–1,57). Общая нижняя линия ставит их на одну полку, и ряд
 * читается ровным, хотя картинки разной высоты. Весь воздух собирается сверху.
 *
 * Сделано на flex-end + max-width/max-height, а НЕ на object-fit/object-position:
 * результат тот же, а зависимости от поддержки object-fit нет.
 */
.digital-cover {
    --cover-height: 260px;

    width: 100%;
    height: var(--cover-height, 260px);
    display: flex;
    align-items: flex-end;
    justify-content: center;
}

/*
 * 🔴 Потолок высоты — ПЕРЕМЕННОЙ, а не процентом. `max-height: 100%` здесь не работает
 * вовсе: браузер не клампит им картинку (замер — 269 px в коробке 260), и от флекса это
 * не зависит, в блочной раскладке то же самое. Дефект жил незаметно, пока коробка была
 * 175 px шириной: при ней картинка упиралась в max-width и до потолка высоты не доходила.
 * Стоило раздать коробке всю ширину ячейки — и портреты полезли на название.
 *
 * Поэтому высота названа один раз в --cover-height и оттуда же берётся обоими правилами:
 * разъехаться им теперь нечем.
 */
.digital-cover img {
    max-width: 100%;
    max-height: 260px;
    max-height: var(--cover-height, 260px);
}

/*
 * Этаж названия. Высота — ровно три строки (4,05em при line-height 1,35), текст по
 * центру по вертикали, собственных вертикальных отступов НЕТ: воздух над названием и
 * под ним даёт третья, свободная строка.
 *
 * 🔴 Поэтому этаж идёт во всю ширину ячейки, а не в ширину обложки. Замер по всем
 * 30 названиям: при 293px ни одно не доходит до третьей строки (максимум два ряда),
 * при 175px пяти названиям нужна четвёртая — и запас, из которого берётся воздух,
 * исчезает ровно у них («Кодекс чести русского офицера (Советы молодому офицеру)»,
 * «Записки террориста (в хорошем смысле слова)», «Значение Романовского периода
 * в Русской Истории» и оба комикса).
 *
 * Кегль задан явно, а не унаследован: от него считается min-height, и молчаливая
 * смена наследуемого размера разъехалась бы с высотой коробки.
 */
.digital-title {
    min-height: 4.05em;
    font-size: 18px;
    line-height: 1.35;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
}

.digital-title a,
.digital-title a:hover,
.digital-title a:focus {
    color: #000;
}

.digital-title a:hover {
    /* против `a:hover{text-decoration:none !important}` из black-100.css */
    text-decoration: underline !important;
}

/*
 * Этаж корзины. margin-top:auto — это и есть то, что держит флажки на одной линии:
 * ячейка тянется по самой высокой карточке ряда, а этаж прижат к её низу. Без него
 * одно длинное название подняло бы соседние флажки, и ряд потерял бы строй.
 *
 * min-height задан, чтобы «Уже приобретена» занимала столько же, сколько флажок,
 * и ряд не дёргался от того, куплена книга или нет.
 *
 * Кегль 20px здесь не косметика: флажок (2024/goods/good-price.blade.php) весь свёрстан
 * в em, и его размер задаётся кеглем родителя.
 */
.digital-buy {
    margin-top: auto;
    min-height: 36px;
    font-size: 20px;
    display: flex;
    align-items: center;
    justify-content: center;
}

.digital-owned {
    font-size: 15px;
    color: #666666;
}

/* ── Орган корзины: флажок-кнопка ───────────────────────────────────────────
 * Флажок И есть кнопка: отдельного «Беру!» рядом с ценником больше нет.
 * Нарисован с нуля и НЕ переиспользует 2024/goods/good-price.blade.php — тот включён
 * в одиннадцати вьюхах (/books, /merch, косоворотки, наборы, чекаут), и любая правка
 * там расходится по всему сайту. Форма тоже другая: у good-price хвост только правый,
 * у органа концы с обеих сторон.
 *
 * Анатомия: сама кнопка — только место под кант, лента с подписью лежит внутри спаном
 * (.digital-flag__body), рыжий кант — псевдоэлементы кнопки ПОД лентой. Всё внутри
 * кнопки, поэтому кликается весь силуэт.
 *
 * 🔴 Лента — ОДИН элемент, обрезанный clip-path, а не тело + два бордер-треугольника.
 * Склеенный из трёх фигур силуэт на дробных координатах (зум, DPI 125/150 %, да и на
 * 100 % — от 4,05em названия всё ниже съезжает на доли пикселя) давал шов: каждая
 * фигура сглаживала общий край сама, и сквозь стык просвечивал фон. Вдобавок ширина
 * бордера округляется до целых device-пикселей, а край фона — нет, и тело выходило
 * на пиксель ниже хвостов. У одного контура внутренних стыков нет вовсе, а высота
 * хвоста равна высоте ленты по определению (проценты в полигоне), что бы ни делал
 * line-height. Замеры — сессия 2026-10-12, DPR 1 / 1.1 / 1.25 / 1.5.
 *
 * Два цвета вынесены в переменные --flag-ink (лента) и --flag-edge (кант): состояния
 * меняют только их. Через opacity на контейнере то же сделать нельзя — лента и кант
 * должны гаснуть ПОРОЗНЬ. Перед каждым var() стоит обычное значение-дублёр: браузер
 * без переменных нарисует чёрный флажок без рыжего, а не невидимую кнопку.
 *
 * Глубина выреза .7em — ОДНО число на всё: им обрезаны лента и оба канта. Разойдутся —
 * полоса канта станет клином.
 *
 * 🔴 font: inherit в сбросе обязателен. Базовое button{border:none;background-color:
 * transparent} в собранном tailwind уже есть, но шрифта не касается: без inherit кнопка
 * возьмёт системные ~13px вместо 20px от .digital-buy, и вся em-геометрия сложится вдвое.
 *
 * Рыжий #FF6B01 — не новый цвет, а цвет бейджа «Новинка» из шапки этой же страницы
 * (2024/header/goods-menu.blade.php). Поэтому кант не выглядит деталью из чужой системы.
 */
.digital-flag {
    --flag-ink: #000;
    --flag-edge: transparent;
    --kant-out: .75em;          /* кант спрятан; состояния ниже выдвигают его */

    position: relative;
    display: inline-block;
    padding: 0 .75em;           /* место под выехавший кант с каждой стороны */
    border: none;
    background: none;
    font: inherit;
    line-height: 1.4;
    white-space: nowrap;
    cursor: pointer;
}

/*
 * Лента. Горизонтальный падинг = .6em воздуха у подписи + .7em под вырез.
 *
 * Обрезано тело, а НЕ кнопка: clip-path на кнопке срезал бы и фокус-кольцо, и кант.
 *
 * Концы — ВЫРЕЗ внутрь (V-образный хвост ленты), а не остриё наружу: точки полигона
 * на середине высоты стоят на .7em ВНУТРИ от краёв.
 *
 * z-index держит ленту поверх канта независимо от порядка в дереве (::after кнопки
 * идёт после тела и иначе лёг бы сверху).
 */
.digital-flag__body {
    position: relative;
    z-index: 1;
    display: block;
    padding: .15em 1.3em;
    color: #fff;
    background-color: #000;
    background-color: var(--flag-ink, #000);
    -webkit-clip-path: polygon(0 0, 100% 0, calc(100% - .7em) 50%, 100% 100%, 0 100%, .7em 50%);
    clip-path: polygon(0 0, 100% 0, calc(100% - .7em) 50%, 100% 100%, 0 100%, .7em 50%);
}

/*
 * Рыжий кант — ПОЛОСА СНАРУЖИ чёрной ленты, повторяющая её контур.
 *
 * 🔴 Кант НЕ перекрашивает хвосты: чёрная лента остаётся целиком чёрной, рыжее лежит
 * ЗА её краем. Промер макета Group301.png: рыжее — полоса постоянной толщины вдоль
 * шеврона, сверху и снизу ленты рыжего нет.
 *
 * Как получается полоса. Каждый кант — сплошной прямоугольник с ТЕМ ЖЕ вырезом .7em
 * на внешнем конце, стоящий ровно под концом ленты. Сдвиг наружу на S оставляет
 * видимой полосу ширины S вдоль шеврона, остальное закрыто лентой. Ширина 1.5em =
 * .7em выреза + .8em сплошного, который целиком прячется под лентой и не даёт полосе
 * сойти на нет у середины.
 *
 * В выключенном состоянии кант ПРОЗРАЧЕН и задвинут, но место под него зарезервировано
 * падингом кнопки — поэтому при переключении лента не прыгает по горизонтали.
 */
.digital-flag::before,
.digital-flag::after {
    content: '';
    position: absolute;
    top: 0;
    bottom: 0;
    width: 1.5em;
    background-color: transparent;
    background-color: var(--flag-edge, transparent);
}

.digital-flag::before {
    left: 0;
    -webkit-clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%, .7em 50%);
    clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%, .7em 50%);
    transform: translateX(var(--kant-out));
}

.digital-flag::after {
    right: 0;
    -webkit-clip-path: polygon(0 0, 100% 0, calc(100% - .7em) 50%, 100% 100%, 0 100%);
    clip-path: polygon(0 0, 100% 0, calc(100% - .7em) 50%, 100% 100%, 0 100%);
    transform: translateX(calc(-1 * var(--kant-out)));
}

/* ── Выезд канта ────────────────────────────────────────────────────────────
 * Кант не появляется из ниоткуда — он ВЫЕЗЖАЕТ ИЗ-ПОД ленты. Одна величина
 * --kant-out задаёт, насколько он задвинут внутрь:
 *
 *     .75em — спрятан целиком (значение по умолчанию у .digital-flag)
 *     .45em — выглядывает намёком под курсором: видно .3em полосы, это 6 px
 *     0     — выехал на 100 %: видно всю полосу .75em, это 15 px (взят)
 *
 * 🔴 Почему сдвиг, а не scale. При scaleX вместе с элементом масштабируются и бордеры,
 * то есть МЕНЯЕТСЯ НАКЛОН шеврона: полоса перестаёт быть параллельной краю ленты
 * и её толщина плывёт (посчитано: .53em у торца против .63em у середины). Сдвиг — движение
 * жёсткое, наклон сохраняется, полоса всюду одной ширины. По той же причине не нужен и
 * transform-origin: у переноса его нет.
 *
 * 🔴 Прячется кант ровно на .75em и ни на сколько иначе: при этом сдвиге его шеврон
 * ложится точно на шеврон чёрного хвоста (у них одинаковая глубина .7em — тот самый
 * инвариант, что и выше), и кант скрывается целиком, без выглядывающей кромки.
 *
 * Длительности разные по НАПРАВЛЕНИЮ: наружу — 150 мс, внутрь — мгновенно (0). То есть
 * кант выезжает плавно, а убирается без анимации. Поэтому базовое правило несёт «возврат»
 * (0s), а состояния, в которых кант идёт наружу, переопределяют длительность на 150 мс.
 * Порядок правил = приоритет: у `:hover` и `.is-in-cart` специфичность одинаковая,
 * и спасает только порядок.
 */
.digital-flag::before,
.digital-flag::after {
    transition: transform 0s ease, background-color 0s ease;
}

/* взят, курсор ушёл: кант доезжает до 100 % — движение наружу, с анимацией */
.digital-flag.is-in-cart::before,
.digital-flag.is-in-cart::after {
    --kant-out: 0em;
    transition-duration: 150ms;
}

/*
 * Ховер на невзятом: кант выглядывает из-под ленты узкой полосой — .3em против .75em
 * у взятого, то есть 6 px против 15. Это намёк, а не состояние, и спутать их нельзя.
 *
 * 🔴 Высоту канта здесь НЕ трогаем. Пробовали scaleY(.8): он масштабирует и бордеры,
 * наклон шеврона расходится с краем ленты, и полоса из ровной превращается в линзу —
 * замер давал 10 px у середины против 1 px с краёв. Размер намёка задаётся ТОЛЬКО
 * глубиной выезда, одним числом ниже.
 */
.digital-flag:hover::before,
.digital-flag:hover::after {
    --kant-out: .45em;
    transition-duration: 150ms;
}

/*
 * 🔴 Ховер на ВЗЯТОМ кант не трогает вовсе: ни выезда, ни сжатия, ни перехода — он стабилен.
 * Значения здесь равны значениям состояния «взят», поэтому при наведении не меняется ничего;
 * transition: none стоит для надёжности — чтобы и смена цвета не анимировалась, и чтобы клик
 * по невзятому товару под курсором доводил кант до полного вида сразу, а не докатывал.
 * Сам ховер в этом состоянии выражен прозрачностью всего органа (см. .is-in-cart:hover ниже).
 */
.digital-flag.is-in-cart:hover::before,
.digital-flag.is-in-cart:hover::after {
    --kant-out: 0em;
    transition: none;
}

/*
 * 🔴 Селекторы здесь ПОВТОРЯЮТ состояния, и это не копипаста. Медиазапрос специфичности
 * не добавляет: одного `.digital-flag::before` (0,1,1) не хватает, чтобы перебить
 * `.digital-flag:hover::before` (0,2,1) с его 150 мс — то есть «без анимации» просто
 * не срабатывало там, где анимация и живёт. При равной специфичности спасает порядок,
 * поэтому блок стоит после всех правил выезда.
 */
@media (prefers-reduced-motion: reduce) {
    .digital-flag::before,
    .digital-flag::after,
    .digital-flag:hover::before,
    .digital-flag:hover::after,
    .digital-flag.is-in-cart::before,
    .digital-flag.is-in-cart::after {
        transition: none;
    }
}

/*
 * Состояния. Порядок правил — это приоритет: `.is-in-cart:hover` обязан стоять ПОСЛЕ
 * простого `:hover`, у них одинаковая специфичность.
 *
 * Чёрный на ховере НЕВЗЯТОГО гасится до 93 %, а не до половины: rgba(0,0,0,.93) над белым
 * даёт #121212 и контраст с белым текстом 18,7:1, тогда как «очевидные» 50 % дали бы
 * #808080 и 3,95:1 — ниже порога AA для 20px некрупного текста. У ВЗЯТОГО ховер устроен
 * иначе — прозрачностью всего органа, и чёрный там сплошной.
 *
 * Рыжий ОДИН И ТОТ ЖЕ во всех состояниях, где кант вообще виден. Пробовали приглушать его
 * на ховере (сперва .45, потом .93): .45 над белым выцветает в лососевый и читается другим
 * цветом, а .93 от полного неотличимо на глаз — то есть оттенок не нёс ничего. «Можно взять»
 * от «взято» отличают РАЗМЕР полосы (6 px против 15) и подпись, и этого достаточно.
 */
.digital-flag:hover,
.digital-flag.is-in-cart {
    --flag-edge: #FF6B01;
}

.digital-flag:hover {
    --flag-ink: rgba(0, 0, 0, .93);
}

/*
 * Ховер на ВЗЯТОМ — один эффект на весь орган: прозрачность 85 %. Ни лента, ни кант
 * по отдельности не трогаются, поэтому чёрный здесь возвращён к сплошному: иначе .93
 * у тела перемножился бы с .85 у элемента и дал бы 0,79, то есть другой эффект, чем
 * у невзятого товара.
 *
 * Прозрачность на КНОПКЕ, а не на частях: группа сначала собирается, потом гасится
 * целиком, поэтому спрятанный под лентой кант не просвечивает сквозь неё.
 * Перехода нет намеренно — это состояние решено держать стабильным.
 */
.digital-flag.is-in-cart:hover {
    --flag-ink: #000;
    opacity: .85;
}

/*
 * Идёт запрос — идиома good-cart: гасим целиком и запрещаем повторный клик.
 * ⚠ Второй селектор не лишний: у `.is-in-cart:hover` специфичность выше, и без него
 * взятый товар под курсором во время запроса остался бы на .85 вместо .5.
 */
.digital-flag.is-loading,
.digital-flag.is-loading:hover {
    opacity: .5;
    pointer-events: none;
}

/* Зачёркнутая старая цена. У good-price это абсолютно позиционированная красная
 * полоса поверх цифр; здесь хватает line-through — одна строка вместо отдельного слоя. */
.digital-flag__promo {
    margin-right: .3em;
    text-decoration: line-through;
    text-decoration-color: #b91c1c;
}
