

/* Start:/local/js/viva/nav/style.css?17899838003582*/
/* ------------------------------------------------------------------ */
/* E3-11: полоса перехода и плавная смена страниц                      */
/* ------------------------------------------------------------------ */

/*
 * Полоса прибита к верху окна и живёт поверх шторки меню: ссылка из
 * открытой шторки — основной путь перехода с телефона, и под её фоном
 * индикатор было бы не видно. Панель заказа флориста остаётся выше.
 */
.nav-progress {
    position: fixed;
    inset: 0 0 auto 0;
    z-index: 95;
    height: 2px;
    /* Дорожка нужна из-за чернильной полосы срока наверху страницы:
       без неё тёмный бегунок на тёмном фоне не читается */
    background: var(--paper);
}

.nav-progress__bar {
    width: 30%;
    height: 100%;
    background: var(--brand);
    animation: nav-progress 900ms linear infinite;
}

@keyframes nav-progress {
    from {
        transform: translateX(-100%);
    }
    to {
        transform: translateX(433%);
    }
}

/*
 * Общий гаситель движения выставил бы бегунку нулевую длительность, и он
 * доехал бы до конца за один кадр — индикатор молча исчез бы. Оставляем
 * неподвижную полосу: переход идёт, движения нет.
 */
@media (prefers-reduced-motion: reduce) {
    .nav-progress__bar {
        width: 100%;
        animation: none;
    }
}

/*
 * Плавная смена страниц. Правило должно стоять в обоих документах —
 * и в том, откуда уходят, и в том, куда приходят, — поэтому живёт
 * в расширении, которое подключается на каждой странице.
 */
@view-transition {
    navigation: auto;
}

/*
 * Шапка на обеих страницах одна и та же: без имени она затухала бы
 * сама в себя, и меню моргало бы на каждом переходе.
 */
.header {
    view-transition-name: viva-header;
}

/* Полоса гаснет быстрее остального: она уже сделала свою работу */
.nav-progress {
    view-transition-name: viva-progress;
}

::view-transition-old(viva-progress) {
    animation-duration: 80ms;
}

/*
 * Псевдоэлементы перехода общий гаситель не выбирает — селектор `*` до них
 * не достаёт, и затухание отработало бы свои четверть секунды.
 */
@media (prefers-reduced-motion: reduce) {
    @view-transition {
        navigation: none;
    }

    ::view-transition-old(*),
    ::view-transition-new(*) {
        animation-duration: 1ms;
    }
}

/*
 * Второй конец перетекания: кадр на странице товара. Имя достаётся только
 * первому кадру галереи — их там столько же, сколько слайдов, а имя
 * в документе обязано быть единственным.
 */
.splide__list > .splide__slide:first-child .item__shot,
.item__gallery > .item__shot {
    view-transition-name: viva-shot;
}

/* End */


/* Start:/local/templates/viva/template_styles.css?1789983800150936*/
/*
 * Дизайн-система, направление A: галерейный минимализм.
 *
 * Белая база и чернильный текст по референсу заказчика, воздух и крупные
 * фото. Единственный цветной голос — метка времени: строка срока, бейдж
 * «собран сегодня», выбранное окно доставки. Свежесть здесь доказывается
 * временем, поэтому время и покрашено.
 *
 * Шрифты лежат в шаблоне: Google Fonts из России отвечает через раз,
 * а таймаут шрифта — это секунды пустого экрана.
 */

@font-face {
    font-family: 'Golos Text';
    font-weight: 400;
    font-display: swap;
    src: url('/local/templates/viva/fonts/golos-400.woff2') format('woff2');
}

@font-face {
    font-family: 'Golos Text';
    font-weight: 500;
    font-display: swap;
    src: url('/local/templates/viva/fonts/golos-500.woff2') format('woff2');
}

@font-face {
    font-family: 'Golos Text';
    font-weight: 600;
    font-display: swap;
    src: url('/local/templates/viva/fonts/golos-600.woff2') format('woff2');
}

:root {
    --motion-fast: 160ms;
    --motion-panel: 240ms;
    --motion-ease: cubic-bezier(0.2, 0.7, 0.2, 1);
    /* Покраска начинается и заканчивается здесь */
    --ink: #16150f;
    /* Вторичный текст темнее обычного «серого»: составы букетов и подписи
       читают, а не пробегают. Контраст к белому 7:1 */
    --ink-soft: #5b574d;
    /* Третичный — приглушённые состояния: недоступный чип, номер шага,
       заглушка поля. Прежний #a5a096 давал контраст 2,6 к белому,
       то есть был не приглушённым, а нечитаемым */
    --ink-faint: #827c71;
    --paper: #ffffff;
    --surface: #faf8f4;
    /* Греж-подложка кадров товара, как у образца: фото живут на нём,
       а не на белом, и сетка карточек читается без рамок */
    --shot: #f5f4f2;
    --line: #e7e3da;

    /* Фирменный зелёный — цвет знака. Носит марку и выбранные состояния:
       чип фильтра, окно доставки, способ получения. Контраст к белому 11:1,
       поэтому годится и для мелкого кегля */
    --brand: #1b4332;
    --brand-wash: #eef2ef;

    /* Акцент — пыльная латунь. Носит только метки времени: строку срока,
       «уже собран», ближайшее окно. Кнопки остаются чернильными.
       --accent-deep — тот же цвет для мелкого кегля: сам акцент на белом
       проходит контраст 4,6:1 впритык, мелкому тексту нужен запас */
    --accent: #9a6c22;
    --accent-deep: #7c561a;
    --accent-wash: #f6efe2;
    --accent-ink: #ffffff;
    --alarm: #a33a2a;

    /* E3-10, копия FLOWERBX: один гротеск на всё, роли различает капс
       с разрядкой, а не смена гарнитуры. Токен display оставлен —
       с приходом логотипа марке может понадобиться своя гарнитура */
    --font-display: 'Golos Text', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif;
    --font-text: 'Golos Text', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif;

    /*
     * Шаг ритма. Воздух — половина этого направления, поэтому щедрый.
     *
     * Эта шкала разводит блоки. Внутренние отступы мелких элементов —
     * метки, чипа, бейджа, строки фильтра — в неё не укладываются: восемь
     * точек внутри метки в двенадцатом кегле делают её плашкой. Для них
     * своя короткая шкала: 2 / 4 / 6 / 12. Разбор 27.08 нашёл вместо неё
     * десять разных значений — 3, 5, 9, 10 вперемешку с остальными, следы
     * правок, а не решение.
     *
     * Вне обеих шкал осознанно живут: 20 у рамки марки и 14 у пункта меню
     * (выверены под ширину знака и высоту шапки), 9 и 11 у площадок под
     * палец в блоке pointer: coarse (считаны от порога 44), отрицательные
     * −11 и −16 (выравнивают полоски бургера и полноширинные блоки).
     */
    --gap: 8px;
    --gap-2: 16px;
    --gap-3: 24px;
    --gap-4: 40px;
    --gap-5: 64px;
    --gap-6: 96px;

    /* Прямые углы: на референсе заказчика скруглений нет ни у кнопок,
       ни у карточек. Токен оставлен, чтобы не искать 40 мест, если решение
       once поменяется */
    --radius: 0;
    /* Ширина контейнера по образцу: у него поля растут до 174 пикселей
       на широком экране, а не до трёхсот, как было при 1280 — иначе
       блоки в полях и блоки во всю ширину расходятся слишком далеко */
    --page: 1536px;
    /* Бегущий градиент заглушки объявлен токеном, потому что рабочие экраны
       красят свои кадры своими правилами и специфичностью перебивают общий
       класс: там фон приходится возвращать, и повторять сам градиент
       в третьем файле незачем */
    --skeleton-sweep: linear-gradient(100deg, var(--surface) 40%, var(--line) 50%, var(--surface) 60%);
}

/* Числа в интерфейсе не должны менять ширину от значения: цена, время,
   количество и телефон остаются на своей сетке и не дёргают соседний текст.
   Выборочно задаём ровные цифры только данным, а не заголовкам и названиям
   букетов, где пропорциональная гарнитура живее и легче читается. */
:is(
    .header__phone,
    .footer__phone,
    .deadline__value,
    .good__price,
    .line__price,
    .line__quantity,
    .line__sum,
    .total,
    .checkout__bill,
    .schedule,
    .slot,
    .order-card__when,
    .item__price,
    .price-field__input,
    .catalog__total,
    input[type='tel']
) {
    font-variant-numeric: tabular-nums lining-nums;
}


*,
*::before,
*::after {
    box-sizing: border-box;
}

html {
    -webkit-text-size-adjust: 100%;
}

body {
    margin: 0;
    background: var(--paper);
    color: var(--ink);
    font: 400 16px/1.65 var(--font-text);
    font-feature-settings: 'kern', 'liga';

    /* Радио и чекбоксы рисует браузер: без этого они синие и выпадают
       из палитры. Зелёный — цвет выбранного состояния, как у чипов */
    accent-color: var(--brand);
}

img {
    max-width: 100%;
    height: auto;
    display: block;
}

a {
    color: inherit;
    text-decoration: none;
}

a:hover {
    text-decoration: underline;
    text-underline-offset: 3px;
}

/* Видимый фокус для ходьбы с клавиатуры. Полям ниже оставлен свой,
   внутренний — там внешнее кольцо слипается с рамкой */
:focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: 2px;
}

::selection {
    /* Светлая подложка на тонком тексте, особенно на номере телефона,
       выглядела почти как обычный фон. Выделение должно читаться сразу. */
    background: var(--brand);
    color: var(--paper);
}

/*
 * Правило шрифтов по E3-10: копия FLOWERBX.
 *
 * Заголовки, имена товаров и навигация набраны капсом с разрядкой,
 * прежний порог капса в 14 точек отменён вместе с серифом. Капс съедает
 * читаемость на крупном кегле, поэтому кегли заголовков заметно меньше
 * серифных: h1 у образца — двадцать точек с разрядкой, не полсотни.
 */
h1, h2 {
    font-family: var(--font-display);
    font-weight: 500;
    line-height: 1.25;
    margin: 0;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

h3 {
    font-family: var(--font-text);
    font-weight: 500;
    line-height: 1.3;
    margin: 0;
}

h1 {
    font-size: clamp(22px, 3vw, 34px);
}

h2 {
    font-size: clamp(17px, 2vw, 22px);
}

h3 {
    font-size: 20px;
}

p {
    margin: 0 0 var(--gap-2);
}

/* Раскладка */

/* Фото героя вылетает за контейнер через отрицательный margin от 50vw,
   а 100vw на Windows считается со скроллбаром — без clip эти полтора
   десятка пикселей дают горизонтальную прокрутку всей странице */
main {
    overflow-x: clip;
}

.page {
    max-width: var(--page);
    margin: 0 auto;
    padding: 0 var(--gap-3);
}

@media (max-width: 600px) {
    .page {
        padding: 0 var(--gap-2);
    }
}

/*
 * Меры страницы. Блок либо во всю меру, либо в своей мере по центру —
 * прижатых влево узких блоков на витрине нет.
 *
 * Покупка — 980: 620 под вопросы или строки заказа, 320 под сводку, 40
 * между ними. Чтение и личное — 620: столько держит текстовая колонка,
 * кабинет и страница заказа. Просмотр меры не получает и остаётся в 1536:
 * у каталога и карточки сетки и фото, ширина им нужна.
 *
 * Меру несёт контейнер, а не блок внутри. Когда её задавал блок, заголовок
 * и рельсы допов оставались у левого края, и на одной странице получались
 * две левые кромки. Поля входят в число: `box-sizing` у всего border-box
 */
.page--buy {
    max-width: calc(980px + var(--gap-3) * 2);
}

.page--read {
    max-width: calc(620px + var(--gap-3) * 2);
}

.section {
    padding: var(--gap-6) 0;
}

/* У соседних секций поля складываются, поэтому берём половину шага:
   между блоками выходит ровно --gap-6, крупная ступень ритма */
.section--tight {
    padding-block: calc(var(--gap-6) / 2);
}

.section__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--gap-3);
    margin-bottom: var(--gap-4);
}

.section__more {
    color: var(--ink-soft);
    font-size: 16px;
    white-space: nowrap;
}

/* Заголовок страницы печатает шаблон, а содержимое начинается сразу за ним:
   без этого отступа первая секция оформления липла к слову «Оформление» */
main > .page > h1 {
    margin: var(--gap-3) 0 var(--gap-4);
}

/* Шапка */

.header {
    border-bottom: 1px solid var(--line);
    background: var(--paper);

    /* Шапка липкая, как у образца; полоса срока над ней уезжает
       с прокруткой. Заодно она — позиционный предок панелей меню */
    position: sticky;
    top: 0;
    z-index: 50;
}

/* Марка по центру, служебное по краям: телефон слева, кабинет и корзина
   справа. Сетка из трёх колонок держит центр точным при любой ширине
   боковых частей */
.header__bar {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: var(--gap-3);
    min-height: 96px;
}

.header__side {
    justify-self: start;
    font-size: 16px;
}

.header__mark {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    text-align: center;
}

.header__logo {
    font-family: var(--font-display);
    font-size: 22px;
    letter-spacing: 0.02em;
    white-space: nowrap;
}

/* Знака ещё нет: марка набрана шрифтом в тонкой рамке, как у образца.
   Когда придёт логотип, здесь встанет он */
/* Кегль поднят до 21: при 17 рамка выходила 43 пикселя в высоту — вровень
   с иконками рядом, и марка читалась как ещё одна кнопка, а не как имя
   магазина. Теперь она на четверть выше их и держит центр строки */
.header__logo--word {
    color: var(--brand);
    letter-spacing: 0.14em;
    text-transform: uppercase;
    font-size: 21px;
    font-weight: 500;
    border: 1px solid var(--brand);
    padding: 8px 20px;
}

/* Подстрока марки: адрес мастерской вместо городов образца. Капс здесь
   служебный и мелкий, в порог 14 точек укладывается с запасом */
.header__place {
    font-size: 12px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--ink-soft);
    white-space: nowrap;
}

/* Меню отдельной строкой под маркой, по центру. Пункты капсом с разрядкой.
   Нижний отступ живёт на самих пунктах, а не на контейнере: пункт должен
   дотягиваться до низа шапки, иначе курсор по дороге к панели теряет
   :hover и панель захлопывается */
.header__nav {
    font-size: 12px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.nav {
    display: flex;
    justify-content: center;
    column-gap: var(--gap-4);
    row-gap: 0;
    flex-wrap: wrap;
    list-style: none;
    margin: 0;
    padding: 2px 0 0;
}

.nav__item > a {
    display: block;
    padding-bottom: 14px;
}

/* Панель раздела на всю ширину под шапкой — позиционный предок у неё
   сама липкая шапка. Открытие с клавиатуры даёт :focus-within.
   Прячется видимостью с задержкой: курсору, сошедшему с пункта вбок или
   наискосок, даётся треть секунды вернуться — без неё панель захлопывалась
   на полпути. Активная панель поднята над гаснущей соседней */
.nav__panel {
    visibility: hidden;
    opacity: 0;
    position: absolute;
    left: 0;
    right: 0;
    top: 100%;
    background: var(--paper);
    border-bottom: 1px solid var(--line);
    box-shadow: none;
    transition: opacity var(--motion-fast) ease 0.25s,
        visibility 0s linear 0.41s;
}

.nav__item:hover .nav__panel,
.nav__item:focus-within .nav__panel {
    visibility: visible;
    opacity: 1;
    z-index: 1;
    transition-delay: 0s;
}

.nav__panel-row {
    display: flex;
    flex-wrap: wrap;
    gap: var(--gap-2) var(--gap-4);
    padding: var(--gap-3) var(--gap-3) var(--gap-3);
    font-size: 12px;
}

.header__aside {
    justify-self: end;
    display: flex;
    align-items: center;
    gap: var(--gap-3);
    font-size: 16px;
}

.header__phone {
    white-space: nowrap;
}

/* Иконки правого края: поиск, кабинет, корзина. Рисованы вручную
   одним штрихом, библиотек нет — решение E3-10 вместо текстовых ссылок */
.header__icon {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* 44 — нижняя мерка площадки под палец. Рисунок внутри остался 22:
       растёт область нажатия, а не иконка */
    width: 44px;
    height: 44px;
    color: var(--ink);
}

.header__icon:hover {
    text-decoration: none;
    color: var(--brand);
}

/* Кабинет визуально меняется после входа: контурный силуэт остаётся гостю,
   а авторизованный покупатель видит свой «аватар» и точку активной сессии.
   Это не новый цвет интерфейса, а тот же фирменный зелёный из выбранных
   способов доставки и фильтров. */
.header__icon--account-on {
    color: var(--brand);
}

.header__icon--account-on::before {
    content: '';
    position: absolute;
    inset: 4px;
    z-index: -1;
    border-radius: 50%;
    background: var(--brand-wash);
}

.header__icon--account-on svg {
    position: relative;
    z-index: 1;
}

.header__account-status {
    position: absolute;
    right: 5px;
    bottom: 5px;
    z-index: 2;
    width: 8px;
    height: 8px;
    border: 2px solid var(--paper);
    border-radius: 50%;
    background: var(--brand);
}

.header__count {
    position: absolute;
    top: 0;
    right: -1px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    min-width: 18px;
    height: 18px;
    padding: 0;
    background: var(--accent);
    color: var(--accent-ink);
    font-size: 12px;
    font-weight: 600;
    line-height: 1;
    font-variant-numeric: tabular-nums;
    /* Круг здесь не украшение: счётчик квадратом читается как кнопка */
    border-radius: 50%;
}

/*
 * Мобильное меню. Наверху остаются кнопка меню, знак и корзина; пункты
 * каталога, кабинет и телефон живут в раскрывающейся панели. Панель
 * появляется без анимации: списка движений из брифа это касание не входит.
 *
 * display: contents у .header__aside распускает обёртку, и корзина с
 * кабинетом становятся флекс-детьми самой шапки — их можно развести
 * по строкам через order, не дублируя разметку под телефон.
 */
.header__burger {
    display: none;
}

@media (max-width: 700px) {
    .header__bar {
        display: flex;
        gap: 4px;
        min-height: 56px;

        /* Только сверху и снизу: боковые поля приходят от .page, и
           сокращённое padding их обнуляло — оттого полоски бургера липли
           к самому краю экрана, а корзина стояла в одиннадцати точках
           от него. Шапка расходилась с полями всего, что ниже */
        padding-block: var(--gap);
    }

    .header__burger {
        display: inline-flex;
        flex-direction: column;
        justify-content: center;

        /* У кнопок браузерный align-items: flex-start, а не stretch:
           без явного значения пустые полоски схлопываются в ширину ноль */
        align-items: stretch;
        gap: 4px;
        width: 44px;
        height: 44px;
        padding: 0 11px;
        margin-left: -11px;
        border: 0;
        background: transparent;
        cursor: pointer;
    }

    .header__burger i {
        display: block;
        height: 2px;
        background: var(--ink);
    }

    /* Телефон и меню живут в шторке; ссылка на последний заказ на этой ширине
       продублирована там — рядом с маркой ей не хватает места. Кабинет остаётся
       иконкой, как у образца: с телефона в него заходят чаще всего */
    .header__side,
    .header__order,
    .header__nav {
        display: none;
    }

    .header__mark {
        flex: 1;
        min-width: 0;
    }

    .header__logo--word {
        font-size: 15px;
        letter-spacing: 0.1em;
        padding: 6px 12px;
    }

    /* Адресу под маркой в тесной шапке места нет */
    .header__place {
        display: none;
    }

    .header__aside {
        justify-self: auto;
        gap: 0;
    }

    /* Площадка иконки шире рисунка на 11 точек с каждой стороны, поэтому
       корзина стоит от края дальше, чем полоски бургера слева: те уже
       выровнены отрицательным отступом. Сдвигаем правый край на столько же,
       и рисунки в обоих углах встают по полю страницы.

       Сдвигается последняя иконка, а не вся правая группа: у кабинета под
       иконкой висит меню с собственным «right», и вместе с группой оно
       уехало бы за край экрана */
    .header__aside > :last-child {
        margin-right: -11px;
    }
}

.header__count[hidden] {
    display: none;
}

/* Меню кабинета под иконкой: открывается кликом или с клавиатуры. */
.header__account {
    position: relative;
    display: flex;
}

.header__menu {
    visibility: hidden;
    opacity: 0;
    position: absolute;
    right: -14px;
    top: 100%;
    z-index: 2;
    display: grid;
    gap: var(--gap);
    min-width: 190px;
    padding: var(--gap-2);
    background: var(--paper);
    border: 1px solid var(--line);
    transition: opacity var(--motion-fast) ease;
}

/* Открывает клик по иконке, а не наведение: покупателя сначала спрашивают,
   что он хочет сделать. Состояние держит только класс — правило
   :focus-within здесь держало меню открытым, пока фокус стоял на самой
   иконке, и закрыть его с клавиатуры было нельзя: Escape возвращает
   фокус на кнопку, а та снова открывала панель */
.header__account--open .header__menu {
    visibility: visible;
    opacity: 1;
    transition-delay: 0s;
}

.header__menu a {
    font-size: 14px;
    white-space: nowrap;
}

/* Анонс над шапкой: чернильный фон, белый мелкий капс, одна мысль по центру */
.deadline {
    background: var(--ink);
    font-size: 12px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.85);
}

.deadline__row {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--gap);
    padding: 8px 0;
    flex-wrap: wrap;
}

.deadline__value {
    font-weight: 500;
    color: #ffffff;
}

/* Служебная шапка рабочего экрана: марка слева, выход справа. Ниже
   витринной, чтобы очередь начиналась выше на телефоне у стола */
.staff__bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--gap-2);
    min-height: 72px;
}

.staff__nav {
    display: flex;
    align-self: stretch;
    align-items: center;
    gap: var(--gap-3);
    margin-left: auto;
}

.staff__nav-link {
    display: inline-flex;
    align-items: center;
    align-self: stretch;
    position: relative;
    color: var(--ink-soft);
    font-size: 14px;
}

.staff__nav-link--on {
    color: var(--ink);
    font-weight: 600;
}

.staff__nav-link--on::after {
    content: '';
    position: absolute;
    right: 0;
    bottom: 0;
    left: 0;
    height: 2px;
    background: var(--brand);
}

.staff-mobile-nav {
    display: none;
}

.staff__aside a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    font-size: 14px;
}

@media (max-width: 600px) {
    .staff__bar {
        /* Поля контейнера сохраняем: сокращаем только высоту */
        padding: var(--gap) var(--gap-2);
        min-height: 0;
    }

    .staff__nav {
        display: none;
    }

    .staff-mobile-nav {
        position: fixed;
        right: 0;
        bottom: 0;
        left: 0;
        z-index: 80;
        display: grid;
        grid-template-columns: repeat(2, 1fr);
        min-height: calc(64px + env(safe-area-inset-bottom));
        padding-bottom: env(safe-area-inset-bottom);
        border-top: 1px solid var(--line);
        background: var(--paper);
    }

    .staff-mobile-nav__link {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        gap: 2px;
        min-height: 64px;
        color: var(--ink-faint);
        font-size: 12px;
        line-height: 1.2;
    }

    .staff-mobile-nav__link:hover {
        text-decoration: none;
    }

    .staff-mobile-nav__link--on {
        color: var(--brand);
        font-weight: 600;
    }

    .staff-mobile-nav svg {
        width: 22px;
        height: 22px;
        fill: none;
        stroke: currentColor;
        stroke-width: 1.6;
        stroke-linecap: round;
        stroke-linejoin: round;
    }

    .staff-shell--nav main {
        padding-bottom: calc(76px + env(safe-area-inset-bottom));
    }
}

/* Вход сотрудника: узкая колонка по центру, без соцсетей и регистрации.
   Поля и кнопка те же, что на витрине — своей формы у экрана нет */
.staff-auth {
    display: flex;
    flex-direction: column;
    gap: var(--gap-2);
    max-width: 380px;
    margin: var(--gap-4) auto var(--gap-6);
}

.staff-auth__error {
    color: var(--alarm);
}

.staff-auth__remember {
    display: flex;
    align-items: center;
    gap: var(--gap);
    font-size: 14px;
    color: var(--ink-soft);
    /* Площадка под палец: отметку жмут мокрыми руками у стола */
    min-height: 44px;
    cursor: pointer;
}

.staff-auth__remember input {
    width: 20px;
    height: 20px;
}

/* Блоки рабочего экрана: очередь адресов, сборка, вручение. Разделены
   линией и заголовком, а не тенью — поверхности на витрине живут так же */
.staff__block {
    padding-top: var(--gap-3);
    margin-top: var(--gap-3);
    border-top: 1px solid var(--line);
}

.staff__block:first-of-type {
    padding-top: 0;
    margin-top: 0;
    border-top: 0;
}

.staff__title {
    font-size: 12px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ink-soft);
    margin-bottom: var(--gap-2);
}

/* Карточка товара */

.goods {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: var(--gap-4) var(--gap-3);
}

/* Телефон: две колонки со скупой карточкой — фото, название, цена, кнопка.
   Состав в такой ширине не читается и уходит */
@media (max-width: 600px) {
    .goods {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: var(--gap-3) var(--gap-2);
    }

    .good__name {
        font-size: 16px;
    }

    .good__buy {
        min-height: 40px;
        font-size: 14px;
        padding: 0 var(--gap-2);
    }
}

/* Колонкой во всю высоту ячейки: тогда кнопки в ряду стоят на одной линии
   независимо от того, у кого название в две строки, а у кого в одну */
/*
 * Витринная карточка собрана по образцу карточки Shopify Dawn (card--card):
 * рамка вокруг всей карточки, фото с внутренними полями, под ним текстовый
 * блок с воздухом. Оттуда же выравнивание — карточка тянется на высоту
 * ячейки, поэтому ряд не пляшет при разной длине названий.
 *
 * Что не взято: скругление и тень (проект их не использует), показ второго
 * фото при наведении и кнопка быстрой покупки — движение ограничено брифом,
 * а покупка живёт на странице товара.
 */
/* E3-10: карточка без рамки и подложки — кадр на греже сам держит
   форму, как у образца */
.good {
    position: relative;
    display: flex;
    flex-direction: column;
    height: 100%;
}

.good__body {
    display: flex;
    flex-direction: column;
    flex: 1;
    gap: 6px;
    padding: var(--gap-2) 0 0;
}

/* Подчёркивание на наведении — из Dawn: карточка кликабельна целиком,
   и подчёркнутое имя показывает, куда именно ведёт нажатие */
.good:hover .good__link {
    text-decoration: underline;
    text-underline-offset: 3px;
}

/* Рейл допов: карточки мельче и фото квадратом. Ваза и коробка конфет
   в вертикальном кадре на три четверти экрана выглядят важнее букета,
   к которому их предлагают */
.goods--rail {
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
}

.goods--rail .good__shot {
    aspect-ratio: 1 / 1;
}

.goods--rail .good__name {
    font-size: 16px;
}

/* В узкой карточке допа «В корзину» ломалось на две строки */
.goods--rail .good__buy {
    white-space: nowrap;
    padding: 0 var(--gap);
}

.goods--rail .good__body {
    padding: var(--gap) 0 0;
}

/* Телефон: допы едут лентой вбок. Растянутая на весь экран ваза выглядит
   вторым главным товаром, хотя это добавка к букету */
@media (max-width: 600px) {
    .goods--rail {
        display: flex;
        overflow-x: auto;
        scrollbar-width: none;
        gap: var(--gap-2);
        margin: 0 calc(var(--gap-2) * -1);
        padding: 0 var(--gap-2) var(--gap);
    }

    .goods--rail::-webkit-scrollbar {
        display: none;
    }

    .goods--rail .good {
        flex: 0 0 45%;
    }

}

/*
 * Квадратный кадр, как на референсе заказчика: там все снимки сделаны
 * одинаково, и ряд читается витриной. У нас фотографии пока разные —
 * квадрат уравнивает их сильнее, чем вертикаль, а подложка тоном бумаги
 * держит снимки с вырезанным фоном, которые иначе висят в пустоте
 */
.good__shot {
    position: relative;
    /* Кадр чуть вытянут по вертикали, как 262×283 у образца */
    aspect-ratio: 13 / 14;
    background: var(--shot);
    overflow: hidden;
    border-radius: var(--radius);
}

.good__shot img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Плашка в правом верхнем углу кадра, как «10 COLOURS» у образца */
/* Метка держит левый угол: правый верхний отдан кнопке корзины */
.good__mark {
    position: absolute;
    left: 12px;
    top: 12px;
    background: var(--paper);
    color: var(--ink);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    padding: 6px 12px;
    border-radius: var(--radius);
}

/* Имя капсом с разрядкой, как у образца. Три строки потолок: одно
   название на восемь строк перекашивает весь ряд */
.good__name {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    overflow: hidden;
    margin: 2px 0 0;
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

/* Ссылка накрывает карточку целиком: нажатие мимо кнопки ведёт на товар.
   Кнопку из-под этого слоя поднимает её собственный position ниже */
/* Нажимается вся карточка, а не только ссылка внутри: в снимок и заголовок
   целятся чаще, чем в подпись под ними. Площадку растягивает псевдоэлемент
   самой ссылки — в разметке остаётся одна ссылка, без вложенных, и переход
   по клавиатуре работает как прежде. Приём общий для карточки товара
   и карточки в блоке о магазине */
.good__link::after,
.world .button::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: var(--radius);
}

.good__link:hover {
    text-decoration: none;
}

/* Быстрое добавление прямо из списка: иконка корзины в правом верхнем
   углу кадра — та же сумка, что в шапке. Квадрат, а не круг: скруглений
   у нас нет нигде. Поднята над слоем, которым ссылка накрывает карточку */
.good .good__buy {
    position: absolute;
    right: 12px;
    top: 12px;
    z-index: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* Ростом с метку в соседнем углу: крупнее она перевешивала кадр.
       Тонкая линия по краю — как у стрелок рельса, без неё белый
       квадрат лежал на фото заплаткой */
    width: 32px;
    height: 32px;
    padding: 0;
    border: 1px solid var(--line);
    background: var(--paper);
    color: var(--ink);
    font: inherit;
    cursor: pointer;

    /* Прячем прозрачностью, а не visibility: скрытая ею кнопка выпадает
       из обхода табом, и с клавиатуры до неё было не добраться */
    opacity: 0;
    pointer-events: none;
}

.good:hover .good__buy,
.good:focus-within .good__buy {
    opacity: 1;
    pointer-events: auto;
}

/* Под курсором темнеет только линия — так же ведут себя стрелки рельса.
   Заливка чернилами на наведении читалась как уже нажатая кнопка */
.good .good__buy:hover {
    border-color: var(--ink);
}

/* Букет уже в корзине: вместо сумки — счёт, квадрат залит чернилами
   и остаётся на кадре. Прятать его под курсор нельзя: это состояние
   карточки, а не предложение действия */
/* Взятое отмечено зелёным марки, а не чернилами: цвет здесь работает
   признаком принадлежности — этот букет уже ваш. В покое кнопка остаётся
   нейтральной и с фотографией не спорит */
.good .good__buy.is-in-cart {
    opacity: 1;
    pointer-events: auto;
    border-color: var(--brand);
    background: var(--brand);
    color: var(--paper);
}

.good .good__buy.is-in-cart svg {
    display: none;
}

.good__buy-count {
    display: none;
    font-size: 14px;
    font-weight: 600;
    letter-spacing: 0;
    font-variant-numeric: tabular-nums;
}

.good .good__buy.is-in-cart .good__buy-count {
    display: block;
}

/* Там, где курсора нет, иконке неоткуда всплыть: на телефоне она видна всегда */
@media (hover: none) {
    .good .good__buy {
        opacity: 1;
        pointer-events: auto;
    }
}

.good__price {
    /* Цену прижимаем к низу: названия бывают в одну и в две строки,
       и без этого цены в ряду стоят на разной высоте */
    margin-top: auto;
    font-size: 14px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

.good__price-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin-top: auto;
}

.good__price-row .good__price {
    margin-top: 0;
}

.good__availability {
    color: var(--brand);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    white-space: nowrap;
}

.good__availability--preorder {
    color: var(--muted);
}

/* Кнопки и поля */

/* Кнопки чернильные, а не акцентные: в галерее действие спокойное,
   цветом говорит только время */
.button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--gap);
    min-height: 48px;
    padding: 0 var(--gap-3);
    border: 1px solid var(--ink);
    border-radius: var(--radius);
    background: var(--ink);
    color: var(--paper);
    font: inherit;
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    cursor: pointer;
    transition: background-color 150ms ease, border-color 150ms ease;
}

/* Авторское `display` перебивает браузерное скрытие: без этого правила
   `button.hidden = true` не прячет кнопку. Тот же дефект уже был
   у `.stage__note`, и сообщение о занятом окне не пропадало */
.button[hidden] {
    display: none;
}

.button:hover {
    text-decoration: none;
    /* Вне палитры с 23.08, решение за заказчиком, см. docs/29-дизайн-система.md,
       «Требует решения заказчика» */
    background: #37342a; /* design-rules: pending, docs/29 */
    border-color: #37342a; /* design-rules: pending, docs/29 */
}

.button--ghost {
    background: transparent;
    color: var(--ink);
    border-color: var(--line);
}

.button--ghost:hover {
    background: transparent;
    border-color: var(--ink);
}

.button--wide {
    width: 100%;
}

/* Букет уже в корзине: кнопка перестаёт быть действием и становится
   входом в корзину. Зелёный марки здесь тот же признак принадлежности,
   что и у залитого квадрата на карточке витрины */
.button.is-in-cart {
    background: var(--brand);
    border-color: var(--brand);
}

.button.is-in-cart:hover {
    /* Тот же пробел мимо палитры, что у .button:hover выше, см. там */
    background: #143528; /* design-rules: pending, docs/29 */
    border-color: #143528; /* design-rules: pending, docs/29 */
}

/* Поле на светлой подложке, как у образца: на бумаге белое поле в тонкой
   рамке терялось, и форма читалась как набор пустот */
.field {
    width: 100%;
    min-height: 48px;
    padding: 0 var(--gap-2);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--shot);
    color: var(--ink);
    font: inherit;
}

.field:focus {
    outline: 2px solid var(--brand);
    outline-offset: -2px;
}

/*
 * Подсказки под полем ввода.
 *
 * Список накрывает то, что под ним, а не раздвигает форму: иначе секции
 * прыгали бы на каждом знаке, а кнопка оформления убегала из-под пальца.
 * Рамка цвета чернил — как у панели поиска в шапке: обе всплывают над
 * страницей, и тон рамки отличает их от обычных полей.
 */
.suggest {
    position: relative;
    display: block;
}

/* Поверх закреплённой полосы итога, но ниже липкой шапки */
.suggest__list {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    z-index: 20;
    max-height: min(264px, 40dvh);
    overflow-y: auto;
    margin: 0;
    padding: 0;
    list-style: none;
    background: var(--paper);
    border: 1px solid var(--ink);
    border-top: 0;
}

/* Высота в палец задана здесь, а не в блоке касаний: строка адреса
   и на десктопе нажимается мышью по всей длине */
.suggest__item {
    display: flex;
    align-items: center;
    min-height: 44px;
    padding: 6px var(--gap-2);
    font-size: 14px;
    cursor: pointer;
}

.suggest__item--on,
.suggest__item:hover {
    background: var(--surface);
}

/* Заглушка строки адреса нажимается впустую, поэтому не отзывается ни на
   наведение, ни на курсор: список подсказок пока пустой */
.suggest__item--ghost,
.suggest__item--ghost:hover {
    background: none;
    cursor: default;
}

/* Корзина */

.cart__alarm {
    /* Ошибка промокода вставляется прямым ребёнком сетки корзины. Без
       растяжения она занимала левую колонку и сдвигала список с итогом. */
    grid-column: 1 / -1;
    color: var(--alarm);
    margin-bottom: var(--gap-3);
}

.cart__empty {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--gap-2);
    padding: var(--gap-4) 0;
}

.cart {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 320px;
    gap: var(--gap-4);
    align-items: start;
}

.cart:has(.cart__empty) {
    display: block;
}

.line {
    display: grid;
    grid-template-columns: 96px minmax(0, 1fr) auto auto auto;
    align-items: center;
    gap: var(--gap-2);
    padding: var(--gap-2) 0;
    border-bottom: 1px solid var(--line);
}

/* Телефон: пять колонок в 373 пикселя не помещаются — грид складывался
   сам, и на имя оставалось сто двадцать, отчего «Конфеты ручной работы»
   рвались на четыре строки. Собираем строку в две колонки: кадр слева
   на всю высоту, остальное столбиком */
@media (max-width: 600px) {
    .line {
        grid-template-columns: 72px minmax(0, 1fr);
        align-items: start;
        row-gap: var(--gap);
    }

    .line__shot {
        grid-row: span 4;
    }

    .line__body,
    .line__count,
    .line__sum,
    .line__drop {
        grid-column: 2;
        justify-self: start;
    }
}

.line__shot {
    display: block;
    aspect-ratio: 3 / 4;
    background: var(--surface);
    border-radius: var(--radius);
    overflow: hidden;
}

.line__shot img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.line__name {
    font-size: 16px;
    font-weight: 500;
}

.line__price {
    color: var(--ink-soft);
    font-size: 14px;
}

.line__changed {
    color: var(--alarm);
    font-size: 14px;
    margin-top: var(--gap);
}

.line__count {
    display: inline-flex;
    align-items: center;
    border: 1px solid var(--line);
    border-radius: var(--radius);
}

.line__step {
    min-width: 44px;
    min-height: 44px;
    border: 0;
    background: transparent;
    color: var(--ink);
    font: inherit;
    font-size: 20px;
    cursor: pointer;
}

.line__step:disabled {
    color: var(--ink-faint);
    cursor: default;
}

.line__quantity {
    min-width: 32px;
    text-align: center;
}

.line__sum {
    min-width: 92px;
    text-align: right;
}

.line__drop {
    border: 0;
    background: transparent;
    color: var(--ink-soft);
    font: inherit;
    font-size: 14px;
    cursor: pointer;
    text-decoration: underline;
}

.total {
    position: sticky;
    top: calc(96px + var(--gap-2));
    display: flex;
    flex-direction: column;
    gap: var(--gap-2);
    padding: var(--gap-3);
    background: var(--surface);
    border-radius: var(--radius);
}

.total__row {
    display: flex;
    justify-content: space-between;
    gap: var(--gap-2);
    color: var(--ink-soft);
    font-variant-numeric: tabular-nums;
}

.total__row b {
    color: var(--ink);
    font-weight: 400;
}

/* Пояснение вместо суммы уходит на свою строку: в узкой панели
   «посчитаем при оформлении» ломалось пополам, и строка теряла вид */
.total__row--note {
    display: block;
}

.total__row--note b {
    display: block;
    margin-top: 2px;
    color: var(--ink-soft);
    font-size: 14px;
}

.total__row--big {
    font-size: 20px;
    color: var(--ink);
    padding-top: var(--gap-2);
    border-top: 1px solid var(--line);
}

.total__row--big b {
    font-weight: 600;
}

/*
 * Вход из корзины — подсказка после основной кнопки, а не обязательный шаг.
 * Акцентная подложка отделяет её от расчёта, но текстовая ссылка не спорит
 * по весу с «Оформить заказ».
 */
.total__account {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--gap);
    padding: var(--gap-2);
    background: var(--accent-wash);
    border-radius: var(--radius);
}

.total__account-copy {
    display: flex;
    flex-direction: column;
    gap: 3px;
}

.total__account-title {
    font-size: 14px;
    font-weight: 600;
}

.total__account-note {
    margin: 0;
    color: var(--ink-soft);
    font-size: 13px;
    line-height: 1.45;
}

.total__account-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--gap) var(--gap-2);
}

.total__account-link {
    color: var(--accent-deep);
    font-size: 14px;
    font-weight: 600;
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 3px;
}

.total__account-link--quiet {
    color: var(--ink-soft);
    font-weight: 500;
}

.cart__mobile-action {
    display: none;
}

@media (max-width: 900px) {
    .cart {
        grid-template-columns: minmax(0, 1fr);
        padding-bottom: calc(88px + env(safe-area-inset-bottom));
    }

    /* Узкий экран: фото и название сверху, количество и сумма под ними */
    .line {
        grid-template-columns: 72px minmax(0, 1fr) auto;
    }

    .line__sum,
    .line__drop {
        grid-column: 2 / -1;
        text-align: left;
    }

    .total {
        position: static;
    }

    .cart__mobile-action {
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 5;
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        align-items: center;
        gap: var(--gap-2);
        padding: var(--gap-2) var(--gap-3) calc(var(--gap-2) + env(safe-area-inset-bottom));
        background: var(--surface);
        border-top: 1px solid var(--line);
    }

    .cart__mobile-total {
        display: flex;
        flex-direction: column;
        gap: 2px;
        font-size: 12px;
        color: var(--ink-soft);
    }

    .cart__mobile-total b {
        color: var(--ink);
        font-size: 18px;
        font-variant-numeric: tabular-nums;
    }
}

/* Оформление */

/*
 * Форма и сводка. Меру страницы держит `.page--buy`: из 980 под вопросы
 * уходит 620, и поле в двух колонках выходит 298. До сужения формой был
 * весь лист, а под телефон отдавалось 504 — столько не нужно ни одному
 * значению тут.
 */
.checkout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 320px;
    grid-template-areas:
        "steps steps"
        "stages bill"
        "go bill";
    gap: var(--gap-3) var(--gap-4);
    align-items: start;
}

.checkout__bill {
    grid-area: bill;
    position: sticky;
    top: calc(var(--header-height, 160px) + var(--gap-2));
    display: flex;
    flex-direction: column;
    gap: var(--gap-2);
    padding: var(--gap-3);
    background: var(--surface);
    border-radius: var(--radius);
}

.checkout__stages {
    grid-area: stages;
}

.checkout__go {
    grid-area: go;
}

/* Шаги идут одной строкой, активный выделен чернилами, пройденные тоже
   нажимаются, будущие приглушены. Метка активного — утолщение линии:
   пиктограмм в системе нет, и заводить их ради одной стрелки не станем */
.steps {
    grid-area: steps;
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    counter-reset: step;
    border-bottom: 1px solid var(--line);
}

.steps__item {
    counter-increment: step;
    display: flex;
    align-items: center;
    gap: 8px;
    min-height: 44px;
    padding: var(--gap) 0;
    border: 0;
    border-bottom: 1px solid transparent;
    background: none;
    color: var(--ink-faint);
    font: inherit;
    font-size: 14px;
    text-align: left;
    cursor: default;
}

.steps__item::before {
    content: counter(step);
    font-variant-numeric: tabular-nums;
}

.steps__item--done {
    color: var(--ink);
    cursor: pointer;
}

.steps__item--on {
    color: var(--ink);
    border-bottom: 2px solid var(--ink);
}

.checkout__consent {
    margin: 0;
    font-size: 14px;
    color: var(--ink-soft);
}

/* Карточка заказа всегда раскрыта: это последний безопасный момент сверить
   состав до ввода адреса и оплаты. */
.checkout__bill-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--gap-2);
}

.checkout__bill-head h2 {
    margin: 0;
    font-size: 18px;
}

.checkout__bill-count {
    margin: 4px 0 0;
    color: var(--ink-soft);
    font-size: 14px;
}

.checkout__bill-edit {
    color: var(--ink-soft);
    font-size: 14px;
}

.checkout__bill-items {
    display: flex;
    flex-direction: column;
    gap: var(--gap);
    margin: 0;
    padding: 0;
    list-style: none;
    font-size: 14px;
}

.checkout__bill-item {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: var(--gap);
    align-items: center;
}

.checkout__bill-item-product {
    display: grid;
    grid-template-columns: 48px minmax(0, 1fr);
    gap: var(--gap);
    align-items: center;
    min-width: 0;
    color: inherit;
}

.checkout__bill-item-product:hover .checkout__bill-item-name {
    text-decoration: underline;
}

.checkout__bill-item-shot {
    width: 48px;
    height: 56px;
    overflow: hidden;
    background: var(--shot);
    border-radius: calc(var(--radius) - 2px);
}

.checkout__bill-item-shot img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.checkout__bill-item-body {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.checkout__bill-item-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.checkout__bill-item-quantity {
    color: var(--ink-soft);
    font-size: 12px;
}

.checkout__bill-item b,
.checkout__bill-total b {
    font-variant-numeric: tabular-nums;
}

.checkout__coupon {
    min-height: 22px;
}

.checkout__coupon-toggle,
.checkout__coupon-drop {
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--ink-soft);
    font: inherit;
    font-size: 14px;
    text-decoration: underline;
    cursor: pointer;
}

.checkout__coupon-form {
    display: flex;
    gap: var(--gap);
}

.checkout__coupon-form .field {
    min-width: 0;
}

.checkout__coupon-send {
    flex: 0 0 auto;
    border: 0;
    background: transparent;
    color: var(--ink);
    font: inherit;
    font-size: 14px;
    text-decoration: underline;
    cursor: pointer;
}

.checkout__coupon-applied {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    color: var(--ink-soft);
    font-size: 14px;
}

.checkout__coupon-applied b {
    color: var(--ink);
    font-weight: 500;
}

.checkout__coupon-note {
    margin: var(--gap) 0 0;
    color: var(--alarm);
    font-size: 13px;
}

.checkout__bill-cost {
    display: flex;
    flex-direction: column;
    gap: var(--gap);
    margin: 0;
    padding-top: var(--gap-2);
    color: var(--ink-soft);
    font-size: 14px;
}

.checkout__bill-cost > div,
.checkout__bill-total {
    display: flex;
    justify-content: space-between;
    gap: var(--gap-2);
}

.checkout__bill-cost > [hidden] {
    display: none;
}

.checkout__bill-cost dt,
.checkout__bill-cost dd {
    margin: 0;
}

.checkout__bill-total {
    align-items: baseline;
    padding-top: var(--gap-2);
    border-top: 1px solid var(--line);
    font-size: 18px;
}

.checkout__bill-total b {
    font-size: 20px;
}

.checkout__go {
    display: flex;
    flex-direction: column;
    gap: var(--gap-2);
    align-items: flex-start;
    padding-top: var(--gap-3);
}

.checkout__alarm {
    margin: 0;
    color: var(--alarm);
}

.checkout__prompt {
    margin: 0;
    color: var(--ink-soft);
    font-size: 14px;
}

.checkout__prompt[hidden] {
    display: none;
}

.checkout__note {
    margin: 0;
    font-size: 14px;
    color: var(--ink-soft);
}

/* Не `step`: этим классом на главной размечен блок «как это работает»,
   и его нумерация досталась бы секциям оформления по случайности */
.checkout__stages {
    display: flex;
    flex-direction: column;
    gap: var(--gap-2);
}

/* Мастер показывает ровно один шаг. Отдельная линия у секции дублировала
   нижнюю границу навигации на шагах 2–4. */
.stage {
    display: flex;
    flex-direction: column;
    gap: var(--gap-2);
    scroll-margin-top: calc(var(--header-height, 72px) + var(--gap-2));
}

.stage[hidden] {
    display: none;
}

/* Подзаголовок внутри шага: он нужен там, где в один шаг сошлись два
   прежних вопроса. Сам шаг заголовка не несёт, его называет строка сверху */
.stage__sub {
    margin: 0;
    font-size: 16px;
    font-weight: 500;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--ink-soft);
}

/* Часть шага, которую можно погасить целиком: получатель уходит
   при самовывозе, а открытка в том же шаге остаётся */
.stage__part {
    display: flex;
    flex-direction: column;
    gap: var(--gap-2);
}

.stage__part[hidden] {
    display: none;
}

.stage__sub:not(:first-child) {
    margin-top: var(--gap-3);
}

/*
 * Занятое окно: секция коротко подсвечивается — это из списка движений
 * брифа. Ошибка приходит с сервера в момент отправки, когда взгляд уже
 * на кнопке внизу, и без вспышки покупатель не понимает, куда смотреть
 */
.stage--flash {
    animation: stage-flash 400ms ease;
}

@keyframes stage-flash {
    from {
        background: var(--brand-wash);
    }
}

/*
 * Поля в две колонки от 700 точек. В одну форма растягивалась на два
 * с лишним экрана, а поле телефона занимало восемьсот пятьдесят точек
 * ширины — столько не нужно ни одному значению в этой форме.
 *
 * Строку целиком занимают адрес, «что сказать курьеру» и почта: у первых
 * двух значения длинные, у почты подсказка в две строки.
 */
.stage__fields {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--gap-2) var(--gap-3);
    align-items: start;
}

.address-fields {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--gap-2) var(--gap-3);
}

.address-fields__main {
    grid-column: 1 / -1;
}

.address-fields[hidden] {
    display: none;
}

/* Адрес прошлого заказа: строка-подсказка и кнопка рядом, не поле */
.address-fields__last {
    grid-column: 1 / -1;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--gap);
    margin: 0;
}

.address-fields__last[hidden] {
    display: none;
}

.field-row--wide,
.stage__fields > .check {
    grid-column: 1 / -1;
}

@media (max-width: 700px) {
    /* Столбец из четырёх названий занимает четверть экрана телефона.
       Вместо него строка: пройденные и будущие сжаты до номеров,
       развёрнуто только название текущего шага */
    .checkout {
        grid-template-columns: minmax(0, 1fr);
        grid-template-areas:
            "bill"
            "steps"
            "stages"
            "go";
    }

    .checkout__bill {
        position: static;
    }

    .steps {
        display: flex;
        flex-direction: row;
        align-items: stretch;
        gap: 2px;
        border-bottom: 0;
    }

    /* Сжатый до номера шаг — всё ещё кнопка: ширина под палец задана
       явно, иначе выходит 40 точек при пороге 44 */
    .steps__item {
        flex: 0 0 auto;
        justify-content: center;
        min-width: 44px;
        padding: var(--gap);
        border-left: 0;
        border-bottom: 1px solid var(--line);
    }

    .steps__item--on {
        flex: 1 1 auto;
        justify-content: flex-start;
        padding: var(--gap) var(--gap-2);
        border-left: 0;
        border-bottom: 2px solid var(--ink);
    }

    /* Название видно только у текущего: четыре не помещаются даже на 414 */
    .steps__item:not(.steps__item--on) span {
        display: none;
    }

    .stage__fields {
        grid-template-columns: minmax(0, 1fr);
    }

    .address-fields {
        grid-template-columns: minmax(0, 1fr);
    }

    .address-fields__main {
        grid-column: auto;
    }
}

.stage__fields[hidden] {
    display: none;
}

.stage__alarm {
    color: var(--alarm);
    margin: 0;
}

.stage__note {
    display: flex;
    flex-direction: column;
    gap: var(--gap);
    align-items: flex-start;
    color: var(--alarm);
    margin: 0;
}

/* Авторское `display` перебивает браузерное скрытие: без этого правила
   `note.hidden = true` не работал, и сообщение о занятом окне оставалось
   на экране после выбора другого */
.stage__note[hidden] {
    display: none;
}

/* Свободные окна внутри сообщения: не перечисление, а кнопки выбора */
.stage__offer {
    display: flex;
    align-items: center;
    gap: var(--gap);
    flex-wrap: wrap;
    color: var(--ink-soft);
    font-size: 16px;
}

.field-row {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

/* Своё display перебивает штатное скрытие: поле, спрятанное из скрипта,
   осталось бы на экране. То же и у отметки ниже */
.field-row[hidden],
.check[hidden] {
    display: none;
}

.field-row__label {
    font-size: 14px;
    color: var(--ink-soft);
}

.field-row__label small {
    font-size: 12px;
}

.field-row__hint {
    font-size: 14px;
    color: var(--ink-soft);
}

.field--area {
    min-height: 76px;
    padding: var(--gap) var(--gap-2);
    line-height: 1.5;
    resize: vertical;
}

.check {
    display: inline-flex;
    align-items: center;
    gap: var(--gap);
    cursor: pointer;
}

/*
 * Выбор одного из вариантов: способ получения, точка, оплата.
 *
 * В ряд, а не столбцом: двух-трёх вариантов по строке каждый хватало,
 * чтобы секция «как получить» стала самой высокой в форме. Сетка сама
 * сворачивается в одну колонку, когда вариантам тесно.
 */
.choice {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: var(--gap);
}

.choice[hidden] {
    display: none;
}

/* Заглушка «сначала выберите способ получения» — элемент сетки, и нижнее
   поле от глобального `p` добавляло секции лишние шестнадцать точек */
.choice p {
    margin: 0;
}

.choice__item {
    display: flex;
    align-items: center;
    gap: var(--gap-2);
    padding: 12px var(--gap-2);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    cursor: pointer;
}

/* Выбранное отвечает тем же голосом, что выбранный чип фильтра
   и выбранное окно доставки: знак и бледная заливка */
.choice__item:has(input:checked) {
    border-color: var(--brand);
    background: var(--brand-wash);
}

.choice__item:hover {
    border-color: var(--ink-faint);
}

.choice__item--disabled,
.choice__item--disabled:hover {
    border-color: var(--line);
    background: var(--surface);
    color: var(--ink-soft);
    cursor: not-allowed;
}

.choice__item--disabled .choice__note {
    color: var(--brand);
    font-weight: 600;
}

.choice__body {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.choice__note {
    color: var(--ink-soft);
    font-size: 14px;
}

/*
 * Даты и окна доставки. Своё имя, а не общий `.chip`: окно показывает две
 * строки (время и сколько осталось мест) и обязано быть высотой в палец,
 * а чип фильтра в каталоге — короткая круглая метка в одну строку.
 *
 * На широком экране даты собраны сеткой и видны сразу. На телефоне те же
 * две недели превращаются в одну компактную горизонтальную ленту.
 */
.chips {
    display: flex;
    flex-wrap: wrap;
    gap: var(--gap);
}

/* Количество дат в строке зависит от ширины колонки, а не всего экрана:
   рядом с итогом на планшете четыре даты не помещаются. */
.chips--rail {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 112px), 1fr));
}

.chips--rail .slot {
    min-width: 0;
    width: 100%;
}

/* Пустой ряд не должен занимать место: до выбора даты `[data-slots]` стоит
   без детей и всё равно берёт свою долю промежутка секции. Пробел внутри
   тега считается содержимым — тег в разметке закрыт вплотную */
.chips:empty {
    display: none;
}

.schedule {
    display: flex;
    flex-direction: column;
    gap: var(--gap-3);
}

.schedule__part {
    display: flex;
    flex-direction: column;
    gap: var(--gap);
}

.schedule__title {
    margin: 0;
    font-size: 14px;
    font-weight: 600;
}

.chips--times {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
}

.slot {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 1px;
    min-height: 48px;
    padding: 6px 12px;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--paper);
    color: var(--ink);
    font: inherit;
    font-size: 16px;
    font-variant-numeric: tabular-nums;
    cursor: pointer;
    /* Заливка выбранного окна из списка движений брифа */
    transition: background-color 150ms ease, border-color 150ms ease, color 150ms ease;
}

.slot--on {
    border-color: var(--brand);
    background: var(--brand-wash);
    color: var(--brand);
}

/* Пока окно выбрано, соседние отступают на полшага назад — тоже бриф */
.chips:has(.slot--on) .slot:not(.slot--on):not(:disabled) {
    color: var(--ink-soft);
}

.slot:disabled {
    color: var(--ink-faint);
    background: var(--surface);
    cursor: default;
}

.slot__note {
    font-size: 12px;
}

.slot__marker {
    position: absolute;
    top: 50%;
    right: 14px;
    width: 18px;
    height: 18px;
    border: 1px solid var(--ink-faint);
    border-radius: 50%;
    transform: translateY(-50%);
}

.slot--on .slot__marker {
    border: 5px solid var(--brand);
    background: var(--paper);
}

.slot--date {
    min-width: 112px;
}

.slot--date .slot__label {
    font-size: 14px;
    line-height: 1.25;
    text-align: left;
    white-space: normal;
}

.slot--date .slot__note {
    max-width: 100%;
    white-space: normal;
    overflow-wrap: anywhere;
    text-align: left;
}

.slot--time {
    position: relative;
    width: 100%;
    min-height: 44px;
    align-items: center;
    justify-content: center;
    gap: var(--gap);
    padding: 10px 42px 10px 12px;
}

/* Срочный самовывоз — отдельный режим, а не ещё одно часовое окно. Он идёт
   первым и занимает всю строку, чтобы пояснение не зажималось в полкарточки. */
.slot--asap {
    position: relative;
    grid-column: 1 / -1;
    width: 100%;
    min-height: 72px;
    justify-content: center;
    padding: 12px 44px 12px 14px;
    text-align: left;
}

.slot--asap .slot__label {
    font-weight: 600;
}

.slot--asap .slot__note {
    max-width: 58ch;
    line-height: 1.35;
}

.schedule__selection {
    margin: 0;
    color: var(--brand);
    font-size: 14px;
    font-weight: 600;
}

.schedule__selection[hidden] {
    display: none;
}

.total__items {
    display: flex;
    flex-direction: column;
    gap: var(--gap);
    margin: 0 0 var(--gap);
    padding: 0 0 var(--gap-2);
    border-bottom: 1px solid var(--line);
    list-style: none;
    font-size: 14px;
}

.total__item {
    display: flex;
    justify-content: space-between;
    gap: var(--gap-2);
    color: var(--ink-soft);
}

.total__item b {
    color: var(--ink);
    font-weight: 400;
    white-space: nowrap;
}

/* Промокод */

.promo {
    display: flex;
    gap: var(--gap);
    align-items: center;
    flex-wrap: wrap;
}

.promo__field {
    min-height: 44px;
    flex: 1 1 auto;
    min-width: 0;
}

.promo__send {
    min-height: 44px;
    white-space: nowrap;
}

.promo__alarm {
    flex: 0 0 100%;
    margin: 0;
    color: var(--alarm);
    font-size: 14px;
}

.promo__applied {
    display: flex;
    align-items: center;
    gap: var(--gap);
    flex-wrap: wrap;
}

.promo__code {
    padding: 4px 12px;
    border: 1px dashed var(--line);
    border-radius: var(--radius);
    font-size: 14px;
    letter-spacing: 0.04em;
}

.promo__drop {
    border: 0;
    background: transparent;
    color: var(--ink-soft);
    font: inherit;
    font-size: 14px;
    cursor: pointer;
    text-decoration: underline;
}

.total__row[hidden] {
    display: none;
}

.total__alarm {
    margin: 0;
    color: var(--alarm);
}

/*
 * Телефон: итог превращается в закреплённую полосу внизу экрана —
 * бриф просит мобильный чекаут одним экраном с кнопкой на виду.
 * До правки кнопка лежала в конце формы, и до неё надо было домотать
 * шесть секций, чтобы узнать сумму.
 *
 * В полосе остаются итог, ошибка и кнопка. Состав заказа покупатель
 * только что видел в корзине, и на пятидесяти точках высоты он лишний.
 */
@media (max-width: 900px) {
    .checkout {
        padding-bottom: calc(132px + env(safe-area-inset-bottom));
    }

    /* Кнопка прибита к низу экрана: форма длиннее экрана, и покупатель
       не должен искать её прокруткой */
    .checkout__go {
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 5;
        gap: var(--gap);
        padding: var(--gap-2) var(--gap-2) calc(var(--gap-2) + env(safe-area-inset-bottom));
        background: var(--surface);
        border-top: 1px solid var(--line);
    }

    .checkout__go .button {
        width: 100%;
    }

    .checkout__note {
        display: none;
    }

    /* Длинный отказ вроде «адрес вне зоны» раздувал полосу до 59%
       альбомного экрана, поэтому текст живёт в окне с прокруткой */
    .checkout__alarm {
        max-height: 4.2em;
        overflow-y: auto;
        font-size: 14px;
        line-height: 1.4;
    }

    /* Две недели не должны выталкивать время за нижнюю границу телефона.
       Даты идут одной лентой с видимым краем следующей карточки, а окна
       появляются сразу под ней. */
    .chips--rail {
        display: flex;
        flex-wrap: nowrap;
        max-width: 100%;
        overflow-x: auto;
        padding-bottom: 4px;
        scroll-snap-type: x proximity;
        scrollbar-width: thin;
    }

    .chips--rail .slot--date {
        flex: 0 0 132px;
        width: 132px;
        scroll-snap-align: start;
    }
}

@media (max-width: 480px) {
    .chips--times {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .slot--time {
        min-height: 48px;
        padding-inline: 10px 38px;
        font-size: 14px;
    }
}

/* Кабинет */

.account,
.account__enter {
    display: flex;
    flex-direction: column;
    gap: var(--gap-2);
    padding-bottom: var(--gap-5);
}

/* Вход и регистрация собраны как у образца: заголовок капсом по центру,
   под ним строка о том, зачем кабинет, и форма посреди страницы.
   У регистрации полей втрое больше, поэтому панель шире и поля идут
   в две колонки — в одну они растягивали страницу на два экрана */
.account__enter {
    text-align: center;
}

.account__email {
    overflow-wrap: anywhere;
}

/* Ширина у входа и регистрации одна: при переключении панель прыгала
   с одной на другую. Разное здесь только число полей, поэтому у
   регистрации они идут сеткой, а у входа остаются столбиком */
.account__enter--wide .account__form {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: var(--gap-2) var(--gap-3);
    text-align: left;
}

/* Полей нечётное число, и последнее оставляло рядом с собой пустую клетку.
   Пароль занимает строку целиком — заодно ему видно всю подсказку */
.account__enter--wide .account__form .field-row:last-of-type,
.account__enter--wide .account__form .button {
    grid-column: 1 / -1;
}

.account__enter .account__form {
    text-align: left;
}

/* Второстепенные действия отделяем от формы свободным пространством. */
.account__enter .account__switch {
    justify-content: center;
    gap: var(--gap-4);
    margin-top: var(--gap);
    padding-top: var(--gap-3);
}

/* Части панели — заголовок с лидом, вход через сервисы, форма,
   переключатели — разведены крупнее, чем строки внутри них. Общий шаг
   в 16 точек выстраивал их одной лестницей, и группы не читались */
.account__enter .account__social {
    margin-top: var(--gap-3);
}

.account__enter .account__or {
    margin-block: var(--gap);
}

/* В кабинете заголовок печатает островок, а не шаблон: он меняется
   по состоянию — «Вход в кабинет», «Ваши заказы». Отступ сверху тогда
   нужен здесь, иначе заголовок липнет к полосе срока. На странице пароля
   заголовок шаблонный, и свой отступ у него уже есть */
[data-account] > .account {
    padding-top: var(--gap-4);
}

/* Вход занимает пол-экрана, и при отступе истории заголовок липнул
   к полосе срока, оставляя весь воздух под собой */
[data-account] > .account__enter {
    padding-top: var(--gap-5);
}


.account__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--gap-2);
}

/* Заголовок кабинета набран как заголовки витрины: капс с разрядкой.
   Своя манера здесь выглядела страницей из другого магазина */
.account__title {
    margin: 0;
    font-family: var(--font-display);
    font-size: clamp(22px, 3vw, 34px);
    font-weight: 500;
    line-height: 1.25;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.account__tools {
    display: flex;
    gap: var(--gap-2);
    flex-wrap: wrap;
}

/* На телефоне «Сменить пароль» и «Выйти» зажимали заголовок в две строки */
@media (max-width: 600px) {
    .account__head {
        flex-direction: column;
        align-items: flex-start;
        gap: var(--gap);
    }
}

.account__link {
    border: 0;
    background: transparent;
    padding: 0;
    color: var(--ink-soft);
    font: inherit;
    font-size: 14px;
    cursor: pointer;
    text-decoration: underline;
}

.account__link:hover {
    color: var(--ink);
}

.account__form {
    display: flex;
    flex-direction: column;
    gap: var(--gap-2);
    margin: 0;
}

/* Кнопка отделена от последнего поля: вплотную она читается его частью */
.account__form .button {
    margin-top: var(--gap);
}

.account__form .field {
    width: 100%;
}

/* Кнопки соцсетей: их рисует ядро по списку настроенных провайдеров,
   поэтому блока может не быть вовсе */
/* Кнопки сервисов стоят под заголовком и идут в ряд: в конце страницы
   о них узнавали последними — на телефоне блок был за экраном прокрутки,
   на широком лежал ниже сгиба. Рядом они занимают одну строку вместо двух */
.account__social {
    display: flex;
    flex-direction: column;
    gap: var(--gap);
    margin: 0;
    text-align: left;
}

/* Названы кнопки по сервисам, и без подписи ряд читался парой кнопок
   неясного назначения. Набор тот же, что у разделителя «или» ниже:
   две подписи одной манеры показывают, что способов входа два */
.account__social-label {
    color: var(--ink-soft);
    font-size: 12px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
}

.account__social-row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: var(--gap);
}

/* Разделитель между сервисами и формой: слово в разрыве линии говорит,
   что ниже второй способ входа */
.account__or {
    display: flex;
    align-items: center;
    gap: var(--gap-2);
    color: var(--ink-soft);
    font-size: 12px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
}

.account__or::before,
.account__or::after {
    content: '';
    flex: 1;
    height: 1px;
    background: var(--line);
}

.account__social[hidden] {
    display: none;
}

.account__switch {
    display: flex;
    gap: var(--gap-2);
    flex-wrap: wrap;
    padding-top: var(--gap);
}

/* Подпись формы одинакова в кабинете и на «Заказ принят»: правило общее,
   имена классов разные, потому что блоки разные */
.account__status,
.done__status {
    margin: 0;
    color: var(--ink-soft);
    font-size: 14px;
}

.account__status--bad,
.done__status--bad {
    color: var(--alarm);
}

/* A guest order is deliberately not merged into a social profile just because
   both happen to name the same email.  This compact block explains the extra
   proof without turning an empty history into a dead end. */
.account__claim {
    display: flex;
    align-items: flex-start;
    flex-wrap: wrap;
    gap: var(--gap);
    margin: var(--gap-3) 0 0;
    padding: var(--gap-2);
    border: 1px solid var(--line);
}

.account__claim-note {
    flex: 1 1 280px;
    margin: 0;
    color: var(--ink-soft);
    font-size: 14px;
    line-height: 1.45;
}

.account__claim .account__status {
    flex-basis: 100%;
}

.order-card {
    display: flex;
    flex-direction: column;
    gap: var(--gap-2);
    padding: var(--gap-3) 0;
    border-bottom: 1px solid var(--line);
    /* Плашка в шапке ведёт на карточку якорем: без отступа она встаёт под
       липкую шапку, и покупатель попадает на середину чужого заказа */
    scroll-margin-top: calc(var(--header-height, 72px) + var(--gap-2));
}

.order-card__main {
    display: grid;
    grid-template-columns: 104px minmax(0, 1fr);
    gap: var(--gap-2);
    align-items: start;
}

.order-card__main--plain {
    grid-template-columns: minmax(0, 1fr);
}

.order-card__shot {
    display: block;
    aspect-ratio: 1;
    overflow: hidden;
    background: var(--shot);
}

.order-card__shot img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.order-card__body {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
}

.order-card__head {
    display: flex;
    align-items: center;
    gap: var(--gap);
    flex-wrap: wrap;
}

/* Номер заказа — то, чем покупатель называет заказ в разговоре с магазином */
.order-card__number {
    color: var(--ink-soft);
    font-size: 13px;
    font-weight: 600;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    font-variant-numeric: tabular-nums;
}

.order-card__title {
    overflow: hidden;
    color: var(--ink);
    font-size: 17px;
    font-weight: 500;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.order-card__title:hover {
    color: var(--brand);
    text-decoration: none;
}

.order-card__quantity {
    color: var(--ink-soft);
    font-size: 13px;
}

.badge {
    padding: 4px 12px;
    border: 1px solid var(--line);
    font-size: 12px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--ink-soft);
}

.badge--off {
    color: var(--alarm);
    border-color: var(--alarm);
}

.order-card__when {
    color: var(--ink-soft);
    font-size: 14px;
}

.order-card__sum {
    font-size: 15px;
    font-weight: 500;
    font-variant-numeric: tabular-nums;
}

.order-card__actions {
    display: flex;
    gap: var(--gap);
    flex-wrap: wrap;
}

.order-card__actions .button {
    min-height: 44px;
    font-size: 14px;
}

.order-card__cancel,
.order-view__cancel {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--gap);
    width: 100%;
}

.order-card__cancel .field,
.order-view__cancel .field {
    width: 100%;
}

.button--danger {
    color: var(--alarm);
    border-color: var(--alarm);
}

.order-card__details {
    display: flex;
    flex-direction: column;
    gap: var(--gap);
    padding: var(--gap-2);
    background: var(--surface);
    border-radius: var(--radius);
}

/* Подписи внутри — части одного блока, а не отдельные абзацы:
   собственные отступы рвали ритм списка */
.order-card__details p {
    margin: 0;
}

.order-card__details[hidden] {
    display: none;
}

.order-card__items {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin: 0;
    padding: 0;
    list-style: none;
    font-size: 14px;
}

.order-card__items li {
    display: flex;
    justify-content: space-between;
    gap: var(--gap-2);
}

.order-card__items b {
    font-weight: 400;
    white-space: nowrap;
}

.order-card__photo {
    max-width: 200px;
    border-radius: var(--radius);
}

@media (max-width: 520px) {
    .order-card__main {
        grid-template-columns: 84px minmax(0, 1fr);
    }
}

/* Заказ принят */

.done__invite {
    display: flex;
    flex-direction: column;
    gap: var(--gap);
    margin-top: var(--gap-3);
    padding-top: var(--gap-3);
    width: 100%;
}

.done__invite-title {
    margin: 0;
    font-size: 16px;
    font-weight: 500;
}

.done__form {
    display: flex;
    gap: var(--gap);
    flex-wrap: wrap;
    margin: 0;
    max-width: 480px;
}

.done__form .field {
    flex: 1 1 220px;
    min-width: 0;
}

.done {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--gap-2);
    padding: var(--gap-4) 0 var(--gap-6);
}

/* Заголовок с номером печатает островок: номер лежит в памяти браузера,
   сервер при отрисовке страницы его не знает */
.done__title {
    margin: 0;
    font-family: var(--font-display);
    font-size: clamp(28px, 4vw, 40px);
    font-weight: 400;
    line-height: 1.12;
}

.done__more {
    font-size: 14px;
    color: var(--ink-soft);
}

.header__order[hidden] {
    display: none;
}

/* Подвал */

.footer {
    margin-top: var(--gap-6);
    background: var(--surface);
    padding: var(--gap-5) 0 var(--gap-3);
    font-size: 16px;
    color: var(--ink-soft);
}

.footer__intro {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: end;
    gap: var(--gap-4);
    padding-bottom: var(--gap-4);
}

.footer__kicker,
.footer__title {
    color: var(--ink);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.footer__kicker {
    margin-bottom: var(--gap-2);
}

.footer__heading {
    max-width: 20ch;
    color: var(--ink);
    font-family: var(--font-display);
    font-size: clamp(26px, 3vw, 38px);
    font-weight: 400;
    line-height: 1.08;
}

.footer__lead {
    max-width: 56ch;
    margin: var(--gap-2) 0 0;
}

.footer__contact {
    display: grid;
    gap: 6px;
    min-width: 270px;
    padding: var(--gap-3);
    background: var(--paper);
    color: var(--ink-soft);
    font-size: 14px;
}

.footer__phone {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    color: var(--ink);
    font-size: 20px;
    font-weight: 600;
    letter-spacing: 0.02em;
}

.footer__cols {
    display: grid;
    grid-template-columns: minmax(220px, 1.35fr) minmax(180px, 1fr) minmax(260px, 1.2fr);
    gap: var(--gap-4);
    padding-top: var(--gap-4);
}

.footer__title {
    margin-bottom: var(--gap-2);
}

.footer__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: var(--gap);
}

.footer__list--caps {
    font-size: 12px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ink);
}

.footer__brand {
    color: var(--brand);
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.footer__bottom {
    margin-top: var(--gap-4);
    padding-top: var(--gap-3);
    display: flex;
    justify-content: space-between;
    gap: var(--gap-3);
    flex-wrap: wrap;
    font-size: 14px;
    color: var(--ink-soft);
}

@media (max-width: 800px) {
    .footer {
        margin-top: var(--gap-5);
        padding-top: var(--gap-4);
    }

    .footer__intro {
        grid-template-columns: 1fr;
        gap: var(--gap-3);
        padding-bottom: var(--gap-3);
    }

    .footer__contact {
        min-width: 0;
        padding: var(--gap-2);
    }

    .footer__cols {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: var(--gap-3) var(--gap-2);
        padding-top: var(--gap-3);
    }

    .footer__col--order {
        grid-column: 1 / -1;
        padding-top: var(--gap-3);
    }

    .footer__bottom {
        margin-top: var(--gap-3);
        padding-top: var(--gap-2);
        font-size: 12px;
    }
}

/* Служебное */

.muted {
    color: var(--ink-soft);
}

.empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--gap-2);
    padding: var(--gap-5) 0;
    text-align: center;
    color: var(--ink-soft);
}

/* У .empty есть собственный display, поэтому штатный hidden без этого
   правила не работал: загрузочный экран оставался под готовой формой. */
.empty[hidden] {
    display: none;
}

.empty__title {
    margin: 0;
    color: var(--ink);
}

.empty__note {
    margin: 0;
    max-width: 48ch;
}

.empty__actions {
    display: flex;
    gap: var(--gap);
    flex-wrap: wrap;
    justify-content: center;
}

.skip {
    position: absolute;
    left: -9999px;
}

.skip:focus {
    left: var(--gap-3);
    top: var(--gap);
    z-index: 10;
    background: var(--paper);
    padding: var(--gap) var(--gap-2);
    border: 1px solid var(--ink);
}

/* Фильтры и сортировка */

.chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 12px;
    /* Прозрачная рамка держит размер: выбранный чип не толкает соседей */
    border: 1px solid transparent;
    font-size: 14px;
    color: var(--ink-soft);
    background: var(--paper);
}

.chip:hover {
    color: var(--ink);
    text-decoration: underline;
    text-underline-offset: 4px;
}

.chip--on {
    border-color: var(--brand);
    color: var(--brand);
    background: var(--brand-wash);
}

/*
 * Телефон: сортировка каталога остаётся короткой горизонтальной лентой,
 * а дни доставки переходят в обычную двухколоночную сетку без бокового
 * скролла.
 */
@media (max-width: 700px) {
    .catalog__sort {
        flex-wrap: nowrap;
        overflow-x: auto;
        scrollbar-width: none;
        margin-left: calc(var(--gap-2) * -1);
        margin-right: calc(var(--gap-2) * -1);
        padding: 0 var(--gap-2) var(--gap);
    }

    .catalog__sort::-webkit-scrollbar {
        display: none;
    }

    .catalog__sort .chip {
        flex: 0 0 auto;
    }

    .chips--rail {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    main > .page > h1 {
        margin: var(--gap-2) 0 var(--gap-3);
    }
}

/* Каталог листается кнопкой «Показать ещё»: список страниц-чипов ушёл
   вместе с ней 26.08. При полутора сотнях позиций прыгать на седьмую
   страницу некуда, а дописывать товары к уже просмотренным привычнее */
.catalog__more {
    display: flex;
    justify-content: center;
    margin-top: var(--gap-5);
}

/* Заглушка карточки на время подгрузки: держит место в сетке, чтобы
   кнопка не прыгала вверх под курсором */
.good--ghost .good__shot {
    aspect-ratio: 13 / 14;
}

/* Карточка товара */

.item {
    display: grid;
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
    gap: var(--gap-5);
    align-items: start;
    padding-top: var(--gap-4);
}

@media (max-width: 900px) {
    .item {
        grid-template-columns: 1fr;
        gap: var(--gap-3);
    }
}

/* Кадр товара стоит на греже и повторяет пропорцию карточки витрины:
   одна и та же фотография не должна менять кадрирование между списком
   и страницей */
.item__shot {
    background: var(--shot);
    border-radius: var(--radius);
    overflow: hidden;
    aspect-ratio: 13 / 14;
}

.item__shot img,
.item__shot video {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Ролик снят квадратом, кадр карточки выше: чёрные поля по бокам
   выглядели бы браком, поэтому обрезаем так же, как фотографии */
.item__shot video {
    display: block;
    background: var(--shot);
}

.item__body {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--gap-2);
}

.item__body h1 {
    font-size: clamp(22px, 3vw, 34px);
}

.item__price {
    font-family: var(--font-display);
    /* Вровень с именем букета цена спорила с ним за внимание, поэтому
       кегль опущен. Вес держит её заметной, как у образца и как у цены
       в карточке витрины */
    font-size: 22px;
    font-weight: 500;
    font-variant-numeric: tabular-nums;
}

/* Статус стоит в одной строке с ценой: он отвечает на вопрос «можно ли
   заказать», не споря с названием букета и главной кнопкой. */
.item__price-row {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
}

.item__availability {
    padding: 4px 8px;
    border-radius: var(--radius);
    background: var(--brand-wash);
    color: var(--brand);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.04em;
    line-height: 1.2;
    text-transform: uppercase;
}

.item__availability--preorder {
    background: var(--shot);
    color: var(--muted);
}

.item__preorder-note {
    margin: 0;
    color: var(--muted);
    font-size: 14px;
}

.line__unavailable {
    margin-top: 6px;
    color: var(--accent-deep);
    font-size: 13px;
    line-height: 1.35;
}

.button:disabled {
    cursor: not-allowed;
    opacity: 0.48;
}

/* В правой колонке разделителем служит воздух. Раньше каждая смысловая
   группа получала свою линию, а вместе с подчёркнутым именем и табами это
   превращало карточку в таблицу и спорило с фотографией букета. */
.item__band {
    width: 100%;
    display: grid;
    gap: var(--gap);
    padding-top: var(--gap);
}

.item__band > p {
    margin: 0;
}

/* Как получить: окно доставки и самовывоз, без цифр — цена доставки
   ещё не решена заказчиком, а выдуманное «от 350 ₽» хуже её отсутствия */
.item__get {
    font-size: 16px;
}

.item__composition {
    font-size: 16px;
}

/* Кнопка и обещания под ней — последняя полоса колонки */
.item__buy {
    gap: var(--gap-2);
}

.item__mobile-buy {
    display: none;
}

@media (max-width: 900px) {
    .item {
        padding-bottom: calc(88px + env(safe-area-inset-bottom));
    }

    .item__mobile-buy {
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 5;
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        align-items: center;
        gap: var(--gap-2);
        padding: var(--gap-2) var(--gap-3) calc(var(--gap-2) + env(safe-area-inset-bottom));
        background: var(--surface);
        border-top: 1px solid var(--line);
        font-size: 18px;
        font-weight: 600;
        font-variant-numeric: tabular-nums;
    }
}

.specs {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: var(--gap) var(--gap-3);
    margin: var(--gap-3) 0;
    font-size: 16px;
}

.specs dt {
    color: var(--ink-soft);
}

.specs dd {
    margin: 0;
}

/*
 * Заказ по ссылке.
 *
 * Самая посещаемая страница после каталога: сюда приходят из письма
 * смотреть фото букета. До 24.08 у неё не было ни одного правила в этом
 * файле — оформление задавалось из скрипта через element.style.
 */

.order-view {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: var(--gap-3) 0 var(--gap-6);
    /* Цифры срока не должны менять ширину каждую секунду */
    font-variant-numeric: tabular-nums;
}

/* Колонка выравнена по левому краю, и без этого дети получают ширину
   по содержимому: длинный адрес уезжал за экран, а прокрутку гасит
   родитель, так что текст просто пропадал */
.order-view > * {
    max-width: 100%;
}

.order-view__line,
.order-view__facts,
.order-view__items li {
    overflow-wrap: anywhere;
}

.order-view__head {
    display: flex;
    align-items: center;
    gap: var(--gap-2);
    flex-wrap: wrap;
}

.order-view__head h1 {
    margin: 0;
}

.order-view__status,
.order-view__section {
    width: 100%;
    padding: var(--gap-3) 0;
}

.order-view__status {
    display: flex;
    flex-direction: column;
    gap: var(--gap-2);
    padding-top: 0;
}

.order-view__section-title {
    margin: 0 0 var(--gap-2);
    font-family: var(--font-display);
    font-size: 20px;
    font-weight: 400;
}

.order-view__section--payment > .button {
    margin-top: var(--gap-2);
}

/*
 * Путь заказа: пять шагов в строку. Пройденные и текущий подчёркнуты
 * чернилами, будущие — линией. Без галочек и значков: шаг читается
 * по тону черты и весу подписи.
 */
/* Ссылка на страницу отслеживания службы и телефон магазина: обе строки
   появились 07.09, чтобы человеку с вопросом было куда нажать.
   Подчёркивание обязательно: по умолчанию ссылки на витрине его не имеют,
   и обе читались обычным текстом */
.order-view__track,
.order-view__call a {
    text-decoration: underline;
    text-underline-offset: 3px;
}

.order-view__track {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    margin: var(--gap) 0;
}

.order-view__call {
    margin-top: var(--gap);
    color: var(--ink-soft);
}

.order-view__call a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    color: var(--ink);
}

.order-steps {
    display: flex;
    width: 100%;
    margin: var(--gap) 0 0;
    padding: 0;
    list-style: none;
}

.order-steps__item {
    flex: 1 1 0;
    padding-top: 8px;
    border-top: 2px solid var(--line);
    font-size: 11px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--ink-faint);
}

/* На узком экране разрядка съедает место, и «Ждёт вас» ломается пополам:
   пять подписей должны стоять в строку и на трёхстах двадцати точках */
@media (max-width: 375px) {
    .order-steps__item {
        letter-spacing: 0;
        font-size: 10px;
    }
}

.order-steps__item + .order-steps__item {
    margin-left: 4px;
}

.order-steps__item.is-done {
    border-top-color: var(--ink);
    color: var(--ink-soft);
}

.order-steps__item.is-now {
    border-top-color: var(--ink);
    color: var(--ink);
    font-weight: 600;
}

.order-view__title {
    margin: var(--gap-3) 0 var(--gap);
    font-family: var(--font-display);
    font-size: 20px;
    font-weight: 400;
}

.order-view__line {
    margin: 0;
    line-height: 1.55;
}

/* Постоянное место под MM:SS сохраняет переносы текста при каждом тике. */
.order-view__countdown {
    display: inline-block;
    width: 5ch;
    white-space: nowrap;
    text-align: center;
    font-variant-numeric: tabular-nums lining-nums;
}

.order-view__items {
    margin: 0;
    padding: 0;
    list-style: none;
}

.order-view__items li {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--gap-2);
    padding: 10px 0;
}

.order-view__items li + li {
    border-top: 1px solid var(--line);
}

.order-view__item-meta {
    flex: 0 0 auto;
    color: var(--ink-soft);
    font-size: 14px;
}

/* Название букета возвращает в его карточку: подчёркивание не даёт принять
   ссылку за обычную строку состава заказа. */
.order-view__item-link {
    color: var(--ink);
    text-decoration: underline;
    text-underline-offset: 3px;
}

.order-view__facts {
    display: grid;
    grid-template-columns: minmax(96px, 120px) minmax(0, 1fr);
    gap: 10px var(--gap-3);
    width: 100%;
    margin: 0;
}

.order-view__fact {
    display: contents;
}

.order-view__fact dt {
    color: var(--ink-soft);
}

.order-view__fact dd {
    margin: 0;
    overflow-wrap: anywhere;
}

.order-view__total {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--gap-2);
    margin-top: var(--gap);
    padding-top: var(--gap-2);
    border-top: 1px solid var(--line);
    font-size: 18px;
}

.order-view__total strong {
    font-size: 20px;
}

.order-view__delivery-price {
    margin: 4px 0 0;
    color: var(--ink-soft);
    font-size: 13px;
    text-align: right;
}

.order-view__telegram {
    margin-top: var(--gap-3);
    padding: var(--gap-3);
    border: 0;
    background: var(--brand-wash);
}

.order-view__telegram .order-view__section-title {
    margin-bottom: var(--gap);
}

.order-view__telegram-copy,
.order-view__telegram-state,
.order-view__telegram-legal {
    margin: 0;
}

.order-view__telegram-copy {
    max-width: 560px;
    line-height: 1.5;
}

.order-view__telegram-state {
    margin-bottom: 4px;
    color: var(--brand);
    font-weight: 600;
}

.order-view__telegram .button {
    margin-top: var(--gap-2);
}

.order-view__telegram-legal {
    margin-top: var(--gap);
    color: var(--ink-soft);
    font-size: 12px;
    line-height: 1.5;
}

.order-view__support {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
}

.order-view__support .order-view__call {
    margin: 0 0 var(--gap-2);
}

@media (max-width: 600px) {
    .order-view__facts {
        grid-template-columns: minmax(0, 1fr);
        gap: 4px;
    }

    .order-view__fact {
        display: grid;
        gap: 2px;
        padding: 6px 0;
    }

    .order-view__items li {
        align-items: flex-start;
        flex-direction: column;
        gap: 4px;
    }

    .order-view__telegram {
        margin-inline: calc(-1 * var(--gap-2));
        padding-inline: var(--gap-2);
    }
}

/*
 * Фото букета — то, ради чего страницу открывают.
 *
 * Снимки лежат рядом, а не башней: после переделки их становится два,
 * и второй уводил кнопки решения за нижний край. Кадр вписан в рамку
 * постоянных пропорций, поля добираются грежем: снимки приходят с телефона
 * флориста и бывают любой стороной, а страница от этого прыгать не должна.
 * Обрезать букет нельзя, поэтому вписываем целиком.
 */
.order-view__tracking {
    width: 100%;
    min-width: 0;
    margin: 0 0 var(--gap-2);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    overflow: hidden;
    background: var(--shot);
}

.order-view__tracking-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 8px 16px;
    padding: 20px 20px 8px;
}

.order-view__tracking-head h2 {
    margin: 0;
    font-size: 22px;
    font-weight: 500;
    letter-spacing: 0;
}

.order-view__tracking-link {
    font-size: 13px;
    text-underline-offset: 4px;
}

.order-view__tracking-copy,
.order-view__tracking-hint {
    margin: 0;
    padding: 0 20px 16px;
    color: var(--ink-soft);
    font-size: 13px;
    line-height: 1.5;
}

.order-view__tracking-hint {
    padding-top: 12px;
    padding-bottom: 12px;
}

.order-view__tracking-frame {
    display: block;
    width: 100%;
    height: clamp(480px, 68vh, 720px);
    border: 0;
    background: #fff;
}

.order-view__photo-details {
    margin-bottom: var(--gap-2);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    padding: 0 20px;
}

.order-view__photo-details summary {
    padding: 18px 0;
    cursor: pointer;
    font-weight: 500;
}

.order-view__photo-details summary:focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: 4px;
}

.order-view__photo-details .order-view__shots {
    margin-bottom: 16px;
}

.order-view__photo-details .order-view__shot {
    max-height: 360px;
}

@media (max-width: 600px) {
    .order-view__tracking-head { padding: 16px 16px 8px; }
    .order-view__tracking-copy,
    .order-view__tracking-hint { padding-inline: 16px; }
    .order-view__tracking-frame { height: 560px; }
    .order-view__photo-details { padding-inline: 16px; }
}

.order-view__shots {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: var(--gap-2);
    width: 100%;
}

.order-view__shot {
    aspect-ratio: 3 / 4;
    max-height: 60vh;
    background: var(--shot);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    overflow: hidden;
}

.order-view__shot img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: contain;
}

.order-view__decide {
    display: flex;
    flex-direction: column;
    gap: var(--gap-2);
    width: 100%;
    max-width: 480px;
    margin-top: var(--gap-2);
}

.order-view__actions {
    display: flex;
    gap: var(--gap);
    flex-wrap: wrap;
}

/* Решение принимают в одно касание: кнопки делят строку поровну,
   на телефоне каждая занимает её целиком */
.order-view__actions .button {
    flex: 1 1 200px;
}

/* Просьба о переделке — отдельное состояние: поле ведёт прямо к главному
   действию, а возврат к выбору не выглядит третьей конкурирующей кнопкой. */
.order-view__change-form {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: var(--gap);
    width: 100%;
    padding: var(--gap-2);
    background: var(--surface);
}

.order-view__change-title {
    margin: 0;
    font-family: var(--font-display);
    font-size: 20px;
    font-weight: 400;
}

.order-view__change-hint,
.order-view__change-error {
    margin: 0;
    font-size: 14px;
    line-height: 1.5;
}

.order-view__change-hint,
.order-view__change-count {
    color: var(--ink-soft);
}

.order-view__change-label {
    margin-top: 4px;
    font-size: 14px;
    font-weight: 600;
}

.order-view__change-comment {
    width: 100%;
    min-height: 128px;
}

.order-view__change-meta {
    display: flex;
    justify-content: flex-end;
    min-height: 18px;
    font-size: 12px;
}

.order-view__change-error {
    color: var(--alarm);
}

.order-view__change-error:empty {
    display: none;
}

.order-view__change-cancel {
    align-self: flex-start;
    min-height: 44px;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--ink-soft);
    font: inherit;
    font-size: 14px;
    text-decoration: underline;
    text-underline-offset: 3px;
    cursor: pointer;
}

/* После решения каталог снова доступен, но остаётся обычной ссылкой:
   это продолжение просмотра, а не действие над текущим заказом. */
.order-view__catalog {
    margin-top: var(--gap-2);
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    color: var(--ink-soft);
    text-decoration: underline;
    text-underline-offset: 3px;
}

/* Главная, E3-10: герой-слайдер — кадр во всю ширину полосы, белое поле
   с капс-заголовком и подчёркнутым «Смотреть» лежит поверх кадра.
   Ссылка — весь слайд целиком */

/* Вылет за контейнер до краёв экрана. Половину полосы прокрутки вычитаем:
   100vw считается вместе с ней, и без поправки блок уезжал влево
   на десяток пикселей относительно полей страницы */
.full-bleed {
    margin-inline: calc(50% - 50vw + var(--sbw, 0px) / 2);
}

.hero-slider {
    position: relative;
    background: var(--shot);
}

.hero-slide {
    position: relative;
    display: block;
    min-height: clamp(440px, 46vw, 720px);
    color: inherit;
}

/* Глобальный a:hover подчеркнул бы весь текст слайда разом */
.hero-slide:hover {
    text-decoration: none;
}

.hero-slide__shot {
    position: absolute;
    inset: 0;
    display: block;
    overflow: hidden;
    background: var(--shot);
}

.hero-slide__shot img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.hero-slide__text {
    position: absolute;
    /* Ровно по заголовку рельса ниже: край контейнера плюс его поле.
       Иначе панель стоит на своей вертикали, ни с чем не совпадая */
    left: calc(max(0px, (100% - var(--page)) / 2) + var(--gap-3));
    top: 50%;
    transform: translateY(-50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--gap-2);
    padding: var(--gap-4);
    max-width: min(460px, calc(100% - 32px));
    background: var(--paper);
    text-align: center;
}

.hero-slide__title {
    font-family: var(--font-display);
    font-weight: 500;
    line-height: 1.3;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    font-size: clamp(20px, 2.6vw, 34px);
    margin: 0;
}

.hero-slide__note {
    margin: 0;
    font-size: 14px;
    color: var(--ink-soft);
}

.hero-slide__cta {
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    text-decoration: underline;
    text-underline-offset: 6px;
}

/* Телефон: белого поля нет, текст ложится прямо на кадр, как у образца,
   а точки уходят под фотографию на бумагу */
@media (max-width: 700px) {
    .hero-slider {
        background: var(--paper);
    }

    .hero-slide {
        min-height: clamp(420px, 110vw, 560px);
    }

    /* Вуаль ровным тоном, без градиента: белые буквы должны читаться
       и на светлом снимке — у нас кадры разного тона, не студийные */
    .hero-slide__shot::after {
        content: '';
        position: absolute;
        inset: 0;
        background: rgba(22, 21, 15, 0.32);
    }

    .hero-slide__text {
        left: var(--gap-2);
        right: var(--gap-2);
        top: auto;
        bottom: var(--gap-4);
        transform: none;
        max-width: none;
        padding: 0;
        background: none;
        color: var(--paper);
    }

    .hero-slide__note {
        color: var(--paper);
    }
}

/* Стрелки Splide по краям ленты — у героя и галереи товара. Ядро рисует
   стрелку одним path, красим её текущим цветом; левую зеркалим */
.splide__arrow {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border: 0;
    background: transparent;
    color: var(--ink);
    cursor: pointer;
}

.splide__arrow svg {
    width: 20px;
    height: 20px;
    fill: currentColor;
    transition: translate var(--motion-fast) var(--motion-ease);
}

.splide__arrow--prev {
    left: 6px;
}

.splide__arrow--prev svg {
    transform: scaleX(-1);
}

.splide__arrow--next {
    right: 6px;
}

.hero-slider .splide__pagination {
    position: absolute;
    bottom: 12px;
    left: 0;
    right: 0;
    display: flex;
    justify-content: center;
    gap: 8px;
    list-style: none;
    margin: 0;
    padding: 0;
}

.hero-slider .splide__pagination__page {
    width: 8px;
    height: 8px;
    padding: 0;
    border: 1px solid var(--ink);
    border-radius: 50%;
    background: var(--paper);
    cursor: pointer;
    transition: background-color var(--motion-fast) ease,
        border-color var(--motion-fast) ease;
}

.hero-slider .splide__pagination__page.is-active {
    background: var(--ink);
}

/* Телефон: точки встают под кадр, а стрелки получают светлый кружок —
   на фотографии чернильная стрелка теряется. Блок идёт после правил
   выше намеренно: он их перекрывает */
@media (max-width: 700px) {
    .hero-slider .splide__pagination {
        position: static;
        padding-top: var(--gap-2);
    }

    .hero-slider .splide__arrow {
        width: 34px;
        height: 34px;
        border-radius: 50%;
        background: rgba(250, 248, 244, 0.62);
    }
}

/* Рельс с перелистыванием: заголовок слева, круглые стрелки справа.
   Заголовок строчкой, как у образца, а не кеглем раздела */

.rail__head {
    display: flex;
    align-items: center;
    gap: var(--gap-3);
    margin-bottom: var(--gap-4);
}

.rail__head h2 {
    font-size: 16px;
    font-weight: 600;
    letter-spacing: 0.1em;
    margin: 0;
}

.rail__nav {
    margin-left: auto;
    display: flex;
    gap: var(--gap);
}

.rail__arrow {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border: 1px solid var(--line);
    border-radius: 50%;
    background: var(--paper);
    color: var(--ink);
    cursor: pointer;
}

.rail__arrow:hover {
    border-color: var(--ink);
}

/* Лента короче ряда — листать нечего, и стрелок нет. Класс is-overflow
   Splide ставит сам после монтажа и снимает при смене ширины окна */
.rail:has(.splide:not(.is-overflow)) .rail__nav {
    display: none;
}

/* До монтажа лента рельса стоит рядом из пяти, как смонтированная:
   иначе страница прыгает, когда карусель разложит слайды */
.rail .splide:not(.is-active) .splide__list {
    display: flex;
    gap: 20px;
}

.rail .splide:not(.is-active) .splide__slide {
    flex: 0 0 calc(20% - 16px);
}

@media (max-width: 700px) {
    .rail .splide:not(.is-active) .splide__slide {
        flex-basis: calc(50% - 10px);
    }

    /* На телефоне лента уходит под правый край, как у образца: срезанная
       карточка занимает место, которое на узком экране нечем занять */
    .rail .splide {
        margin-right: calc(50% - 50vw);
    }
}

/* Splide двигает ленту дробным translateX. Без собственного стабильного
   композитного слоя масштабирование фото внутри неё на старте hover может
   пересобраться со сдвигом в пару пикселей. Подсказка не меняет геометрию
   и оставляет inline transform под полным управлением Splide. */
.rail .splide__list {
    will-change: transform;
}

/* Ритм главной: содержимое всех блоков стоит на одной вертикали — полях
   страницы, а во всю ширину идёт только полоса заявления. Разные левые
   края у соседних блоков читались как небрежность, а не как замысел */
.band {
    margin-inline: calc(50% - 50vw + var(--sbw, 0px) / 2);
    padding-inline: clamp(var(--gap-3), calc((100vw - var(--page)) / 2), 60px);
    background: var(--shot);
}

/* Центрированное заявление между рельсом и плитками */

.statement {
    text-align: center;
}

.statement > * {
    max-width: 56ch;
    margin-inline: auto;
}

.statement p {
    margin: var(--gap-2) auto 0;
    color: var(--ink-soft);
    font-size: 16px;
}

/* Тройка страниц о магазине */

.worlds__title {
    text-align: center;
    margin-bottom: var(--gap-4);
}

.worlds__row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: var(--gap-4);
}

.world__shot {
    display: block;
    aspect-ratio: 4 / 3;
    background: var(--shot);
    overflow: hidden;
    margin-bottom: var(--gap-2);
}

.world__shot img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.world {
    display: flex;
    flex-direction: column;
    position: relative;
}


.world__name {
    margin-bottom: var(--gap);
}

.world p {
    color: var(--ink-soft);
}

/* Кнопки тройки на одной линии, сколько бы ни было текста над ними */
.world .button {
    margin-top: auto;
    align-self: flex-start;
}

.tiles {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: var(--gap-4) var(--gap-3);
}

/* Плитка раздела, как коллекция у образца: кадр, капс-имя по центру
   и подчёркнутый вход «Смотреть» */
.tile {
    display: block;
    text-align: center;
}

.tile:hover {
    text-decoration: none;
}

.tile:hover .tile__more {
    color: var(--brand);
}

/* Снимок в плитке повода — по образцу фотоплиток Flower Dose (номинант
   Awwwards среди цветочных): повод выбирают по букету, а не по подписи.
   Кадр квадратный, на той же подложке, что карточки витрины */
.tile__shot {
    display: block;
    aspect-ratio: 1;
    background: var(--surface);
    overflow: hidden;
    margin-bottom: var(--gap-2);
}

.tile__shot img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.tile__name {
    display: block;
    font-size: 14px;
    font-weight: 500;
    letter-spacing: 0.1em;
    text-transform: uppercase;
}

.tile__more {
    display: inline-block;
    margin-top: 6px;
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    text-decoration: underline;
    text-underline-offset: 5px;
}

/* Телефон: плитки идут в два столбца, как товары. В один столбец
   навигация занимала четыре экрана прокрутки и весила больше витрины */
@media (max-width: 600px) {
    .tiles {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: var(--gap-3) var(--gap-2);
    }

    .tile__name {
        font-size: 16px;
    }
}


/* Текстовые страницы */

/* Мера в 60 знаков: при 68 строка тянулась под девяносто символов,
   и глаз терял начало следующей */
.prose {
    max-width: 60ch;
    padding-bottom: var(--gap-6);
}

.prose__figure {
    margin: 0 0 var(--gap-4);
}

.prose__figure img {
    display: block;
    width: 100%;
    height: auto;
}

.prose__figure--workshop {
    max-width: 480px;
}

.prose__figure figcaption {
    margin-top: var(--gap);
    color: var(--ink-soft);
    font-size: 14px;
}

/* Кегль у заголовка общий с витриной: своя шкала осталась от прежнего
   курса, и один и тот же по смыслу заголовок был то 22, то 30 пикселей */
.prose h2 {
    margin: var(--gap-4) 0 var(--gap-2);
}

.prose h2:first-child {
    margin-top: 0;
}

.prose a {
    text-decoration: underline;
    text-underline-offset: 3px;
}

/* Список ссылок в тексте: у него свой отступ снизу, иначе следующий
   абзац прилипает к последнему пункту */
.prose ul {
    margin: 0 0 var(--gap-3);
}

.prose form {
    margin-bottom: var(--gap-4);
}

/*
 * Черновой текст видно и покупателю, и тому, кто открыл страницу перед
 * запуском. Иначе заглушка про доставку однажды уедет в бой молча:
 * выглядит она как обычный абзац
 */
.draft {
    border: 1px solid var(--line);
    border-left: 3px solid var(--alarm);
    background: var(--surface);
    color: var(--ink-soft);
    padding: var(--gap-2) var(--gap-3);
    margin-bottom: var(--gap-4);
    max-width: 68ch;
    font-size: 16px;
}

.draft--inline {
    margin: var(--gap-2) 0 var(--gap-3);
}

/* Плашка-уведомление о хранении в браузере: липнет снизу поверх страницы,
   z-index выше шапки (50), чтобы не уходить под неё при прокрутке к верху */
.cookie-note {
    position: fixed;
    inset: auto 0 0 0;
    z-index: 60;
    display: flex;
    align-items: center;
    gap: var(--gap-3);
    padding: var(--gap-2) var(--gap-3) calc(var(--gap-2) + env(safe-area-inset-bottom));
    background: var(--surface);
    border-top: 1px solid var(--line);
}

.cookie-note[hidden] {
    display: none;
}

.cookie-note__text {
    margin: 0;
    font-size: 14px;
    color: var(--ink-soft);
}

@media (max-width: 600px) {
    .cookie-note {
        flex-direction: column;
        align-items: stretch;
        gap: var(--gap-2);
    }
}

/* Строка поиска в тексте страницы — у четырёхсотой */
.inline-search {
    display: flex;
    gap: var(--gap);
    max-width: 480px;
}

.inline-search .field {
    flex: 1;
}

/* Панель фильтров: форма бюджета и сброс — остальное живёт
   в сайдбаре каталога (E3-10) */

.filters__price {
    display: grid;
    gap: 10px;
}

.filters__price-fields {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 14px minmax(0, 1fr);
    align-items: center;
    gap: 6px;
}

.price-field {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    gap: 6px;
    min-height: 48px;
    padding: 0 12px;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: #fff;
    transition: border-color 150ms ease, box-shadow 150ms ease;
}

.price-field:focus-within {
    border-color: var(--ink);
    outline: 2px solid var(--brand);
    outline-offset: -2px;
}

.price-field__label,
.price-field__currency,
.filters__price-separator {
    color: var(--ink-soft);
}

.price-field__label {
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.price-field__currency {
    font-size: 13px;
}

.price-field__input {
    min-width: 0;
    width: 100%;
    padding: 0;
    border: 0;
    outline: 0;
    background: transparent;
    color: var(--ink);
    font: inherit;
    font-size: 14px;
    font-variant-numeric: tabular-nums;
    text-align: right;
}

.price-field__input::-webkit-inner-spin-button,
.price-field__input::-webkit-outer-spin-button {
    margin: 0;
    appearance: none;
}

.filters__price-separator {
    text-align: center;
}

.filters__price-submit {
    width: 100%;
    min-height: 44px;
    justify-content: space-between;
}

.filters__drop {
    text-decoration: underline;
    text-underline-offset: 3px;
}

/*
 * Метка времени — фирменный ход: срок набран одним цветом везде, где
 * появляется. Сейчас это ближайшее получение на странице товара.
 */
/* Окно доставки не разрывается посередине: «с 09:00 до 11:00» ломалось
   на телефоне между «до» и часом, и время читалось как два разных */
.when {
    color: var(--accent-deep);
    font-weight: 500;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* Короткий отклик на действие, без изменения размеров и позиции кнопок. */
.button,
.good .good__buy,
.rail__arrow,
.slot,
.tabs__name,
.choice__item,
.steps__item,
.suggest__item {
    transition: background-color var(--motion-fast) ease,
        border-color var(--motion-fast) ease,
        color var(--motion-fast) ease,
        opacity var(--motion-fast) ease;
}

.field,
.price-field {
    transition: border-color var(--motion-fast) ease,
        box-shadow var(--motion-fast) ease;
}

.header a,
.footer a,
.account__link,
.ftree__link {
    transition: color var(--motion-fast) ease;
}

@media (prefers-reduced-motion: no-preference) {
    /* Только пользовательское раскрытие: polling заказа не запускает
       анимацию всей страницы заново. Вспышка занятого окна остаётся своей. */
    .stage:not([hidden]):not(.stage--flash),
    .account__form,
    .header__search:not([hidden]),
    .order-card__details:not([hidden]),
    .tabs__panel:not([hidden]),
    .cookie-note:not([hidden]) {
        animation: surface-in var(--motion-panel) var(--motion-ease);
    }

    details.fgroup[open] > :not(summary),
    .drawer__group[open] > :not(summary) {
        animation: content-in 180ms ease;
    }
}

@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
    .splide__arrow--prev:not(:disabled):hover svg {
        translate: -2px 0;
    }

    .splide__arrow--next:not(:disabled):hover svg {
        translate: 2px 0;
    }
}

@keyframes surface-in {
    from {
        opacity: 0;
        transform: translateY(6px);
    }
    to {
        opacity: 1;
        transform: none;
    }
}

@keyframes content-in {
    from { opacity: 0; }
    to { opacity: 1; }
}

/* Проявление фото при загрузке: только прозрачность, без смещения кадра. */
.good__shot img,
.item__shot img,
.hero-slide__shot img,
.line__shot img {
    animation: photo-in 300ms ease both;
}

@keyframes photo-in {
    from {
        opacity: 0;
    }
}

/* Счётчик в шапке коротко пульсирует, когда в корзину что-то легло */
.header__count--pulse {
    animation: count-pulse 200ms ease;
}

@keyframes count-pulse {
    50% {
        transform: scale(1.15);
    }
}

/* Скелетон вместо спиннера: остров рисует форму будущего содержимого */
.skeleton {
    color: transparent;
    background: var(--skeleton-sweep);
    background-size: 200% 100%;
    border-radius: var(--radius);
    animation: skeleton 1200ms linear infinite;
    pointer-events: none;
    -webkit-user-select: none;
    user-select: none;
}

@keyframes skeleton {
    to {
        background-position: -100% 0;
    }
}

/* Заглушки под даты и окна доставки: их размер известен заранее,
   поэтому список не прыгает, когда придёт ответ */
.skeleton--slot {
    width: 120px;
    height: 48px;
}

.skeleton--choice {
    width: 100%;
    height: 72px;
}

.skeleton--line {
    height: 96px;
    width: 100%;
}

/* Строка текста в заглушке. Габариты карточек и плиток заглушка берёт
   у самих компонентов — своих чисел здесь только два, и оба про текст,
   которого у компонента заранее нет */
.skeleton--text {
    display: block;
    height: 12px;
}

.skeleton--half {
    width: 60%;
}

.ghost-lines {
    display: flex;
    flex-direction: column;
    gap: 8px;
    align-self: center;
}

/* Просьба системы двигать поменьше важнее всего списка движений */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        transition-delay: 0s !important;
    }
}

/* ------------------------------------------------------------------ */
/* E3-10, копия FLOWERBX: строка поиска в шапке                        */
/* ------------------------------------------------------------------ */

.header__search {
    display: flex;
    gap: var(--gap);
    padding: 0 var(--gap-3) var(--gap-2);
}

.header__search[hidden] {
    display: none;
}

.header__search .field {
    flex: 1;
}

/* ------------------------------------------------------------------ */
/* E3-10, копия FLOWERBX: мобильная шторка меню                        */
/* ------------------------------------------------------------------ */

.drawer {
    position: fixed;
    inset: 0;
    z-index: 90;
    visibility: hidden;
    pointer-events: none;
    transition: visibility 0s linear var(--motion-panel);
}

.drawer--open {
    visibility: visible;
    pointer-events: auto;
    transition-delay: 0s;
}

.drawer__backdrop {
    position: absolute;
    inset: 0;
    background: rgba(22, 21, 15, 0.4);
    opacity: 0;
    transition: opacity var(--motion-fast) ease;
}

.drawer--open .drawer__backdrop {
    opacity: 1;
}

.drawer__panel {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    width: min(320px, 86vw);
    display: flex;
    flex-direction: column;
    gap: var(--gap-3);
    padding: var(--gap-2) var(--gap-3) var(--gap-3);
    background: var(--paper);
    overflow-y: auto;
    transform: translateX(-100%);
    transition: transform var(--motion-panel) var(--motion-ease);
}

.drawer--open .drawer__panel {
    transform: none;
}

.drawer__close {
    align-self: flex-end;
    width: 44px;
    height: 44px;
    margin: 0 -12px 0 0;
    border: 0;
    background: transparent;
    color: var(--ink);
    font-size: 28px;
    line-height: 1;
    cursor: pointer;
}

.drawer__nav {
    display: flex;
    flex-direction: column;
    gap: var(--gap-2);
    font-size: 16px;
}

.drawer__group summary {
    cursor: pointer;
    padding: 2px 0;
}

.drawer__group a {
    display: block;
    padding: 6px 0 6px var(--gap-2);
    color: var(--ink-soft);
}

.drawer__link {
    display: block;
    padding: 2px 0;
}

.drawer__foot {
    display: flex;
    flex-direction: column;
    gap: var(--gap);
    margin-top: auto;
    padding-top: var(--gap-2);
    border-top: 1px solid var(--line);
    color: var(--ink-soft);
}

/* Пока шторка открыта, страница под ней не крутится */
body.drawer-locked {
    overflow: hidden;
}

/* ------------------------------------------------------------------ */
/* E3-10, копия FLOWERBX: карусели — вид до монтажа                    */
/* ------------------------------------------------------------------ */

/* До того как Splide разложит ленту, в потоке остаётся только первый
   слайд: без этого страница мигает списком всех кадров и прыгает */
.splide:not(.is-active) .splide__slide:nth-child(n+2) {
    display: none;
}

/* ------------------------------------------------------------------ */
/* E3-10, копия FLOWERBX: листинг с сайдбаром                          */
/* ------------------------------------------------------------------ */

.crumbs {
    margin: var(--gap-3) 0 var(--gap-2);
    font-size: 12px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--ink-soft);
}

.crumbs__sep {
    margin: 0 6px;
    color: var(--ink-faint);
}

/* Строка описания под заголовком раздела */
.catalog-lead {
    max-width: 64ch;
    margin: var(--gap-2) 0 0;
    color: var(--ink-soft);
}

.catalog {
    display: grid;
    grid-template-columns: 250px minmax(0, 1fr);
    gap: var(--gap-5);
    align-items: start;
    margin-top: var(--gap-4);
    padding-bottom: var(--gap-5);
}

.catalog__bar {
    display: flex;
    align-items: baseline;
    gap: var(--gap-3);
    flex-wrap: wrap;
    margin-bottom: var(--gap-3);
}

.catalog__total {
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.catalog__sort {
    margin-left: auto;
    display: flex;
    gap: 2px;
}

/* Группа фильтра в сайдбаре: открытая, с заголовком капсом */
.fgroup {
    padding: var(--gap-3) 0;
}

.fgroup:first-child {
    padding-top: 0;
}

.fgroup__title {
    margin-bottom: var(--gap-2);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

/* Свёрнутая группа: вместо браузерного треугольника — знак в наборе
   страницы. Плюс закрыт, минус открыт; иконок мы не заводим */
summary.fgroup__title {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--gap-2);
    cursor: pointer;
    list-style: none;

    /* У свёрнутой группы под заголовком нет содержимого, и отступ висел
       пустой полосой до разделительной линии */
    margin-bottom: 0;
}

summary.fgroup__title::-webkit-details-marker {
    display: none;
}

summary.fgroup__title::after {
    content: '+';
    font-size: 16px;
    font-weight: 400;
    line-height: 1;
    color: var(--ink-soft);
}

details[open] > summary.fgroup__title::after {
    content: '\2212';
}

details.fgroup[open] > summary.fgroup__title {
    margin-bottom: var(--gap-2);
}

/* Дерево категорий: ссылки в столбец, подразделы с отступом */
.ftree {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.ftree__link {
    display: flex;
    align-items: baseline;
    gap: 6px;
    font-size: 14px;
}

.ftree__link--sub {
    padding-left: var(--gap-2);
    color: var(--ink-soft);
}

.ftree__link--on {
    font-weight: 600;
}

/* Фильтр-чекбокс: та же ссылка с пересборкой адреса, вид — квадрат
   с отметкой у выбранных, как чекбоксы цвета у образца */
.fcheck {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 0;
    font-size: 14px;
}

.fcheck:hover {
    text-decoration: none;
    color: var(--brand);
}

.fcheck__box {
    flex: 0 0 auto;
    width: 15px;
    height: 15px;
    border: 1px solid var(--ink-faint);
    background: var(--paper);
}

.fcheck--on .fcheck__box {
    border-color: var(--brand);
    background:
        linear-gradient(var(--brand), var(--brand)) content-box;
    padding: 4px;
}

.fcheck__dot {
    flex: 0 0 auto;
    width: 12px;
    height: 12px;
    border: 1px solid var(--line);
    border-radius: 50%;
}

.fcheck__n {
    margin-left: auto;
    font-size: 12px;
    color: var(--ink-soft);
    font-variant-numeric: tabular-nums;
}

.fcheck--out {
    color: var(--ink-faint);
}

/* ------------------------------------------------------------------ */
/* E3-10, копия FLOWERBX: карточка товара                              */
/* ------------------------------------------------------------------ */

/* Крошки в колонке товара стоят над именем, без верхнего поля страницы */
.item__body .crumbs {
    margin: 0 0 var(--gap-2);
}

/* Имени хватает собственного начертания: подчёркивание вместе с линиями
   смысловых блоков делало карточку слишком полосатой. */
.item__name {
    align-self: start;
}

/* Факты мелким капсом — буллеты образца */
.item__facts {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: 6px;
    font-size: 12px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--ink-soft);
}

.item__facts li::before {
    content: '•';
    margin-right: 8px;
    color: var(--ink-faint);
}

/* Лента превью под главным кадром */
.item__thumbs {
    margin-top: var(--gap);
}

.item__thumbs img {
    width: 100%;
    aspect-ratio: 1 / 1;
    object-fit: cover;
    background: var(--shot);
    cursor: pointer;
    outline: 1px solid transparent;
    outline-offset: -1px;
    transition: outline-color var(--motion-fast) ease, opacity var(--motion-fast) ease;
}

.item__thumbs .splide__slide.is-active img {
    outline: 1px solid var(--ink);
    outline-offset: -1px;
}

/* Кадр с роликом подписан словом, а не значком: пиктограмм в наборе
   всего три, и все живут в шапке */
.item__thumbs .splide__slide {
    position: relative;
}

/* Та же плашка, что метит «Хит» на кадре товара, только прижата к краю:
   превью вчетверо меньше карточки, и отступы карточки съели бы его */
.good__mark--thumb {
    top: 4px;
    left: 4px;
    padding: 1px 5px;
    letter-spacing: 0.06em;
    line-height: 1.2;
    pointer-events: none;
}

/* Табы: подчёркнутое имя активного, панели под строкой имён */
/* Единственный таб печатается заголовком, а не кнопкой: переключать
   нечего. Набран он так же, как имя таба, — без подчёркивания, потому
   что подчёркивание здесь означало бы выбор из нескольких */
.tabs__solo {
    margin: 0 0 var(--gap-2);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.tabs {
    margin-top: var(--gap-3);
}

.tabs__row {
    display: flex;
    gap: var(--gap-3);
    flex-wrap: wrap;
}

.tabs__name {
    position: relative;
    border: 0;
    background: transparent;
    padding: 4px 0;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ink-soft);
    cursor: pointer;
}

.tabs__name--on {
    color: var(--ink);
}

.tabs__name::after {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 1px;
    background: currentColor;
    transform: scaleX(0);
    transform-origin: left;
    transition: transform var(--motion-fast) var(--motion-ease);
}

.tabs__name--on::after {
    transform: scaleX(1);
}

.tabs__panel {
    padding-top: var(--gap-2);
    font-size: 16px;
    color: var(--ink-soft);
}

.tabs__panel a {
    text-decoration: underline;
    text-underline-offset: 3px;
}

/* Кнопка «Фильтр» нужна только телефону */
.catalog .filters__toggle {
    display: none;
}

.filters__backdrop,
.filters__head,
.filters__close {
    display: none;
}

.filters__backdrop[hidden] {
    display: none;
}

/* Закрытие не ждёт ни кадра движения при системном reduced motion. */
@media (prefers-reduced-motion: reduce) {
    .drawer,
    .drawer__panel,
    .drawer__backdrop,
    .filters .catalog__filter-box,
    .filters__backdrop:not([hidden]) {
        transition-property: none !important;
    }
}

body.filters-locked {
    overflow: hidden;
}

@media (max-width: 900px) {
    .catalog {
        grid-template-columns: 1fr;
        gap: var(--gap-3);
    }

    .catalog .filters__toggle {
        display: inline-flex;
    }

    .filters__backdrop:not([hidden]) {
        position: fixed;
        inset: 0;
        z-index: 89;
        display: block;
        background: rgba(22, 21, 15, 0.4);
        opacity: 0;
        visibility: hidden;
        pointer-events: none;
        transition: opacity 180ms ease, visibility 0s linear 220ms;
    }

    .filters__backdrop.filters__backdrop--open {
        opacity: 1;
        visibility: visible;
        pointer-events: auto;
        transition-delay: 0s;
    }

    /* Сайдбар за кнопкой, той же шторкой, что меню */
    .catalog__filter-box {
        display: block;
        position: fixed;
        inset: 0 auto 0 0;
        z-index: 90;
        width: min(320px, 86vw);
        padding: 0 var(--gap-3) calc(var(--gap-3) + env(safe-area-inset-bottom));
        background: var(--paper);
        overflow-y: auto;
        box-shadow: none;
        border-right: 1px solid var(--line);
        opacity: 0;
        transform: translateY(6px);
        visibility: hidden;
        pointer-events: none;
        transition: opacity 180ms ease, transform 220ms var(--motion-ease),
            visibility 0s linear 220ms;
    }

    .filters--open .catalog__filter-box {
        opacity: 1;
        transform: none;
        visibility: visible;
        pointer-events: auto;
        transition-delay: 0s;
    }

    .filters__head {
        position: sticky;
        top: 0;
        z-index: 1;
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: var(--gap-2);
        min-height: 64px;
        margin: 0 calc(-1 * var(--gap-3)) var(--gap);
        padding: env(safe-area-inset-top) var(--gap-3) 0;
        background: var(--paper);
        border-bottom: 1px solid var(--line);
    }

    .filters__title {
        font-size: 14px;
        font-weight: 600;
        letter-spacing: 0.08em;
        text-transform: uppercase;
    }

    .filters__close {
        display: grid;
        width: 44px;
        height: 44px;
        place-items: center;
        padding: 0;
        border: 0;
        background: transparent;
        color: var(--ink);
        font: inherit;
        font-size: 28px;
        line-height: 1;
        cursor: pointer;
    }
}

/* ------------------------------------------------------------------ */

/*
 * Площадка под палец.
 *
 * Прогон `node tools/mobile/run.js` нашёл три десятка мест, где нажимаемое
 * оказалось ниже сорока четырёх точек. Мышью это незаметно, пальцем —
 * промах через раз, и хуже всего пришлось спискам фильтров и шторке меню,
 * где строки шли в двадцать с небольшим точек одна под другой.
 *
 * Правила живут под `pointer: coarse`: на десктопе лишний воздух в списках
 * только растягивает страницу, а мышь попадает и в двадцать точек.
 *
 * Отступ задаётся через `padding-block`, а не `padding`: сокращённое
 * свойство обнуляет боковые, и первая редакция сбила вложенность
 * подразделов в дереве фильтров — мерка этого не видит, видно глазом.
 *
 * Там, где размер сам по себе часть облика — стрелки каруселей, марка
 * в рамке, иконка покупки на кадре, — растёт не элемент, а невидимая
 * площадка вокруг него. Вид остаётся прежним, палец попадает.
 */

@media (pointer: coarse) {
    .checkout__bill-edit,
    .checkout__coupon-toggle,
    .checkout__coupon-drop {
        position: relative;
    }

    .checkout__bill-edit::after,
    .checkout__coupon-toggle::after,
    .checkout__coupon-drop::after {
        content: '';
        position: absolute;
        inset: -11px 0;
    }

    a.order-card__title {
        min-height: 44px;
        padding-block: 8px;
    }

    /* Сайдбар фильтров: строки стояли по 20–29 точек вплотную друг к другу */
    .fcheck {
        min-height: 44px;
    }

    .ftree__link {
        padding-block: 11px;
    }

    .fgroup__title {
        padding-block: 12px;
    }

    /* Шторка меню: разделы, подразделы и служебные ссылки внизу */
    .drawer__link,
    .drawer__group > summary {
        padding-block: 9px;
    }

    .drawer__group > a {
        padding-block: 9px;
    }

    /* Меню строкой под маркой доживает до планшета: там уже палец.
       Мерка по ширине нужна коротким пунктам вроде «Шары»: в сорок две
       точки слово укладывается, площадка — нет */
    .nav__item > a {
        padding-top: 10px;
        padding-bottom: 20px;
        min-width: 44px;
        text-align: center;
    }

    /* Подпись с чекбоксом нажимается целиком, поэтому мерка на ней,
       а не на квадратике внутри */
    .check,
    .choice__item {
        min-height: 44px;
    }

    .drawer__foot > a {
        padding: 9px 0;
    }

    /* Корзина и кабинет: текстовые кнопки без рамки */
    .line__drop {
        padding: 11px 8px;
    }

    .account__link {
        padding-block: 11px;
    }

    /* Меню под иконкой кабинета: две ссылки в двадцать три точки */
    .header__menu a {
        padding-block: 11px;
    }

    .chip {
        min-height: 44px;
    }

    /* Имена вкладок в карточке. Мерка по обеим сторонам: короткое слово
       «Уход» не добирает по ширине, а двенадцатый кегль с отступами —
       по высоте, и отступ здесь не помогает, он считается от строки */
    .tabs__name {
        min-width: 44px;
        min-height: 44px;
    }

    /* Иконка покупки на кадре остаётся квадратом в 32 точки: крупнее она
       перевешивает фото. Растёт только площадка вокруг неё */
    .good .good__buy::after {
        content: '';
        position: absolute;
        inset: -6px;
    }

    .rail__arrow::after,
    .header__logo--word::after {
        content: '';
        position: absolute;
        inset: -4px;
    }

    .rail__arrow,
    .header__logo--word {
        position: relative;
    }

    .hero-slider .splide__arrow::after {
        content: '';
        position: absolute;
        inset: -5px;
    }

    /* Точки слайдера стоят в шестнадцати точках друг от друга: развести их
       на полную мерку значит растащить пагинацию через полкадра. Высота
       берётся полная, ширина — сколько есть между соседями. Слайдер и так
       листается пальцем поперёк, точки тут показывают место в ряду */
    .hero-slider .splide__pagination {
        gap: 16px;
    }

    .hero-slider .splide__pagination__page {
        position: relative;
    }

    .hero-slider .splide__pagination__page::after {
        content: '';
        position: absolute;
        left: -8px;
        right: -8px;
        top: -18px;
        bottom: -18px;
    }
}

.visually-hidden {
    position: absolute !important;
    width: 1px !important;
    height: 1px !important;
    padding: 0 !important;
    margin: -1px !important;
    overflow: hidden !important;
    clip: rect(0, 0, 0, 0) !important;
    white-space: nowrap !important;
    border: 0 !important;
}

/* End */
/* /local/js/viva/nav/style.css?17899838003582 */
/* /local/templates/viva/template_styles.css?1789983800150936 */
