/**
 * ArtiCart — Shanti / vesta.pp.ua
 * Единый файл стилей расширения: media карточки товара (плагин контента),
 * витрины (mod_articart_showcase) и корзины в шапке (mod_articart_cart).
 *
 * Собран из двух источников:
 *   1) assets/css/user.css — ПРИОРИТЕТНЫЙ источник (актуальный дизайн Shanti);
 *   2) правила расширения-предшественника этого магазина, которых в user.css
 *      не было (см. секцию "ДОПОЛНЕНО ИЗ ПРЕДЫДУЩЕЙ ВЕРСИИ" в конце) — оттуда
 *      же унаследованы префиксы .cart-action-*, #header-cart-root: под них уже
 *      написаны переопределения в user.css сайта, менять их означало бы
 *      править чужой файл параллельно с этим.
 *
 * Из user.css перенесены ТОЛЬКО правила, относящиеся к расширению; стили шаблона
 * сайта (шапка, меню, хлебные крошки, пагинация, карточки блога, категории и т.п.)
 * не переносились — им место в user.css шаблона.
 */

/* ==========================================================================
   1. КНОПКА ТОВАРА НА СТРАНИЦЕ СТАТЬИ (.cart-action-*)
   ========================================================================== */

/* БАЗОВЫЕ СТИЛИ (для ПК) */
.cart-action-module {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 20px;
    flex-wrap: nowrap;
    border: 1px solid rgba(214, 164, 46, 0.25);
    border-radius: 10px;
    padding: 10px 16px;
    margin: 14px 0;
    /* Вариант 3: Теплый винно-шоколадный тон + легкий внутренний свет */
    /*background: rgba(45, 12, 18, 0.5); */
    background: rgba(67, 11, 21, 0.5);
    /*background: rgba (65, 12, 18, 0.5)*/
    box-shadow: inset 0 0 15px rgba(214, 164, 46, 0.1);
}
.cart-action-info {
    flex: 1 1 auto;
    display: flex;
    align-items: baseline;
    gap: 8px;
}
.cart-action-title {
    font-size: 1.1em;
    font-weight: 700;
    color: #f5eed7;
}
.cart-action-pack {
    font-size: 0.85em;
    color: #bfa38a;
}
.cart-action-price {
    flex: 0 0 auto;
    font-size: 1em;
    white-space: nowrap;
    /* Вариант 1: Изящный вертикальный разделитель */
    border-left: 1px solid rgba(214, 164, 46, 0.3);
    padding-left: 20px;
}
.cart-action-price-label {
    color: #d6a42e;
    margin-right: 4px;
}
.cart-action-price-value {
    font-weight: 700;
    color: #ffd700;
}
.cart-action-count {
    width: 45px;
    height: 34px;
    text-align: center;
    background: #000000;
    border: 1px solid #d6a42e;
    color: #f5eed7;
    border-radius: 4px;
    font-size: 0.95em;
}
.cart-action-button {
    white-space: nowrap;
    background: #d6a42e;
    color: #000000;
    border: none;
    padding: 0 14px;
    height: 34px;
    font-weight: 700;
    border-radius: 4px;
    text-transform: uppercase;
    font-size: 0.8em;
    letter-spacing: 0.5px;
    cursor: pointer;
    transition: background 0.2s;
}
.cart-action-button:hover {
    background: #b88d22; /* Мягкое благородное золото, чуть светлее базового */
    box-shadow: 0 4px 12px rgba(214, 164, 46, 0.3); /* Объемная золотистая тень */
    transform: translateY(-1px); /* Легкий интерактивный подъем кнопки вверх */
}
.cart-action-button.ac-added {
    background-color: #ffd700 !important; /* Делаем золото чуть ярче на 2 секунды */
    color: #000000 !important;
    border-color: #ffffff !important; /* Белая или ярко-золотая рамка */
    /* Эффект дорогого неонового свечения */
    box-shadow: 0 0 20px rgba(255, 215, 0, 0.8), inset 0 0 10px rgba(255, 255, 255, 0.5) !important;
}
/* Состояние кнопки, когда товар уже в корзине */
/* Блокируем инпут количества для добавленного товара, чтобы не путать пользователя */
.cart-action-count:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}
/* АДАПТИВ Корзины  ДЛЯ МОБИЛЬНЫХ (экраны менее 768px) */

@media (max-width: 767px) {
    .cart-action-module {
        flex-wrap: wrap;
        gap: 12px;
        padding: 12px;
    }
    .cart-action-info {
        flex: 1 1 50%;
        flex-direction: column;
        gap: 2px;
    }
    .cart-action-price {
        flex: 1 1 auto;
        text-align: right;
        /* На мобильных убираем вертикальную черту, так как верстка перестраивается */
        border-left: none;
        padding-left: 0;
    }
    .cart-action-count {
        width: 55px;
        height: 38px;
    }
    .cart-action-button {
        flex: 1;
        height: 38px;
        font-size: 0.9em;
    }
}
/*
 * Компактный модуль корзины в шапке.
 */
/* ================================================================ */
/* ФИКС: модуль корзины (#header-cart-root) оказался внутри            */
/* .container-header .grid-child:nth-child(2) — блока, стилизованного   */
/* под "резиновый" центральный текст (см. раздел HEADER выше).          */
/* Правило .container-header .grid-child:nth-child(2) * даёт ВСЕМ       */
/* потомкам overflow:hidden; white-space:nowrap; text-overflow:ellipsis;*/
/* max-width:100% — специфичность этого селектора (3 класса) выше,      */
/* чем почти у всех правил .header-cart-* ниже (1-2 класса),            */
/* поэтому оно побеждало по каскаду независимо от порядка в файле —     */
/* именно так резался бейдж и обрубался текст тултипа в один ряд.       */
/* ID (#header-cart-root) по специфичности побеждает любое количество   */
/* классов — этим и нейтрализуем конфликт, не трогая исходное правило   */
/* (оно по-прежнему нужно для хлебных крошек/заголовка в этом блоке).   */
/* ================================================================ */
.container-header .grid-child:nth-child(2):has(#header-cart-root) {
    /* Сам контейнер тоже обрезал position:absolute потомков (бейдж, тултип) —
    снимаем обрезку только когда внутри реально сидит корзина. */
    overflow: visible !important;
}
#header-cart-root * {
    overflow: visible;
    white-space: normal;
    text-overflow: clip;
    max-width: none;
}
/* Возвращаем размеры шрифта, которые были заданы в наших правилах ниже,
   но проигрывали wildcard-селектору по специфичности. */
#header-cart-root .header-cart-wrapper {
    font-size: 0.95em;
}
#header-cart-root .header-cart-tooltip {
    font-size: 0.9em;
}
#header-cart-root .cart-cta {
    font-size: 0.85em;
}
#header-cart-root .cart-badge {
    font-size: 10px;
}
/* Общий контейнер модуля в шапке */
.header-cart-wrapper {
    position: relative;
    display: flex;
    align-items: center;
    gap: 10px;
    cursor: pointer;
    font-size: 0.95em;
    font-weight: 600;
    color: #ffd700; /* Фирменное золото */
    text-decoration: none;
}
/* Иконка + бейдж */
.header-cart-icon-box {
    position: relative;
    display: flex;
    align-items: center;
    /* Бейдж (.cart-badge) позиционируется с отрицательными top/right, то есть
    намеренно чуть вылезает за пределы этого блока. У .container-header выше
    по дереву стоит overflow: hidden (защита от переполнения при сжатии шапки),
    который обрезает любое содержимое, выходящее за его границы — включая
    вложенные позиционированные элементы вроде этого бейджа. Margin здесь
    создаёт немного "запаса" внутри уже существующего padding у .container-header,
    чтобы бейдж физически не доставал до обрезаемой границы.
    overflow:hidden не трогаем — он нужен для резинового сжатия шапки в других местах. */
    margin-right: 6px;
    margin-top: 4px;
}
/* На случай, если бейдж всё равно оказывается впритык к правому краю —
   уменьшенный вылет за пределы иконки (было -6px/-8px, тоже работает, но с меньшим
   запасом). Смотрите правило .cart-badge ниже: если после проверки на сайте бейдж
   всё ещё немного подрезан, замените там top:-6px;right:-8px на top:-4px;right:-4px. */
.cart-badge {
    position: absolute;
    top: -5px; /* было -6px — чуть выше, меньше перекрывает иконку сверху */
    right: -1px; /* было -8px — чуть левее (меньше вылезает вправо), тоже меньше перекрытия */
    background: #ff3b30; /* Контрастный красный */
    color: #fff;
    font-size: 10px;
    font-weight: 700;
    border-radius: 50%;
    padding: 1px 5px;
    min-width: 10px;
    text-align: center;
    line-height: 1.3;
}
/* Текст суммы + призыв к действию (состояние "полно") */
.header-cart-data {
    display: flex;
    flex-direction: column;
    line-height: 1.25;
}
.cart-sum {
    font-weight: 700;
}
.cart-cta {
    font-size: 0.85em;
    font-weight: 500;
    opacity: 0.9;
}
/* Анимация "покачивания" при добавлении товара.
   Класс .cart-bounce вешает media/js/articart.js на .header-cart-icon-box,
   а НЕ на .header-cart-wrapper — иначе вместе с иконкой прыгали бы сумма
   и призыв к действию.

   1) Покачивание и микро-прыжок для самой иконки. */

@keyframes iconWiggle {
    0%   { transform: scale(1); }
    20%  { transform: scale(1.2) rotate(-8deg); }
    40%  { transform: scale(1.2) rotate(8deg); }
    60%  { transform: scale(1.1) rotate(-4deg); }
    80%  { transform: scale(1.1) rotate(4deg); }
    100% { transform: scale(1) rotate(0deg); }
}
/* 2) Эффект пружины ("поп-корн") для круглого бейджа с цифрой. */

@keyframes badgePop {
    0%   { transform: scale(1); }
    40%  { transform: scale(1.6); background-color: #ffcc00; }
    70%  { transform: scale(0.9); }
    100% { transform: scale(1); }
}
/* 3) Покачивание — только для иконки внутри .cart-bounce. */
.header-cart-icon-box.cart-bounce .cart-icon-full {
    animation: iconWiggle 0.5s ease-in-out;
    transform-origin: bottom center;
}
/* 4) Взрывной эффект — только для бейджа с количеством. */
.header-cart-icon-box.cart-bounce .cart-badge {
    animation: badgePop 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
/* Мобильная адаптация — см. @media в самом конце файла (она должна идти
   ПОСЛЕ базового .header-cart-tooltip, иначе перебивается им по каскаду). */
/*================================
================================
================================*/
/* ------------------------------------------------------------------ */
/* ТУЛТИП КОРЗИНЫ — ПРЕМИУМ ВЕРСИЯ (Shanti Dark Luxury)              */
/* ------------------------------------------------------------------ */
.header-cart-tooltip {
    --tt-x: 0px;
    --tt-y: 0px;
    position: absolute;
    top: 130%;
    right: 0;
    width: 320px; /* чуть шире для комфортного размещения мессенджеров */
    background: #230a0f;
    border: 1.5px solid rgba(214, 164, 46, 0.5);
    border-radius: 8px; /* чуть более скругленные углы — премиум */
    padding: 16px 18px 18px;
    color: #fff;
    font-size: 0.9em;
    line-height: 1.5;
    box-shadow:
    0 8px 40px rgba(0, 0, 0, 0.7),
    inset 0 1px 0 rgba(214, 164, 46, 0.15); /* тонкий внутренний свечение */
    z-index: 999;
    opacity: 0;
    visibility: hidden;
    transform: translate(var(--tt-x), var(--tt-y)) scale(0.96);
    transform-origin: top right;
    transition: opacity 0.25s ease, transform 0.25s ease, visibility 0.25s;
    backdrop-filter: blur(2px); /* легкое размытие фона */
}
.header-cart-tooltip.is-active {
    opacity: 1;
    visibility: visible;
    transform: translate(var(--tt-x), var(--tt-y)) scale(1);
}
.header-cart-tooltip.no-anim {
    transition: none !important;
}
/* ------------------------------------------------------------------ */
/* ЗАГОЛОВОК БЛОКА "Бажаєте щось купити?" — ПРЕМИУМ                 */
/* ------------------------------------------------------------------ */
.header-cart-tooltip-text {
    margin: 0 0 12px 0;
    position: relative;
}
/* Декоративный золотой акцент сверху */
.header-cart-tooltip-text::before {
    content: '';
    display: block;
    width: 40px;
    height: 2px;
    background: linear-gradient(90deg, rgba(214, 164, 46, 0.8), rgba(214, 164, 46, 0.2));
    margin-bottom: 10px;
    border-radius: 2px;
}
.header-cart-tooltip-intro {
    display: block;
    font-size: 1.1em;
    font-weight: 600;
    color: #fff;
    margin-bottom: 4px;
    letter-spacing: 0.3px;
}
.header-cart-tooltip-connector {
    display: block;
    color: rgba(255, 255, 255, 0.7);
    font-size: 0.88em;
    margin-bottom: 2px;
}
.header-cart-tooltip-outro {
    display: block;
    color: rgba(255, 255, 255, 0.65);
    font-size: 0.85em;
    font-weight: 300;
    font-style: italic;
    height: auto;
    padding-bottom: 5px;
}
/* Золотая ссылка внутри текста */
.header-cart-tooltip-link {
    color: #e6b94a;
    text-decoration: none;
    font-weight: 600;
    border-bottom: 2px solid rgba(214, 164, 46, 0.3);
    transition: border-color 0.2s ease, color 0.2s ease;
}
.header-cart-tooltip-link:hover {
    color: #ffd700;
    border-bottom-color: rgba(214, 164, 46, 0.8);
}
/* ------------------------------------------------------------------ */
/* МЕССЕНДЖЕРЫ — ПРЕМИУМ: цветные кружки с белыми логотипами        */
/* ------------------------------------------------------------------ */
.header-cart-tooltip-messengers {
    display: flex;
    justify-content: flex-start;
    gap: 14px;
    align-items: center;
    padding-top: 14px;
    margin-top: 4px;
    border-top: 1px solid rgba(214, 164, 46, 0.2);
    position: relative;
}
/* Декоративная золотая точка-разделитель */
.header-cart-tooltip-messengers::before {
    content: '✦';
    position: absolute;
    top: -10px;
    left: 50%;
    transform: translateX(-50%);
    color: rgba(214, 164, 46, 0.3);
    font-size: 10px;
    background: #230a0f;
    padding: 0 8px;
}
/* Кожна іконка месенджера — овальна золотиста підсвітка навколо (не кольоровий
   бейдж під бренд — той прибрано, лишається тільки м'яке золоте сяйво). */
.header-cart-messenger-link {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    justify-content: center;
    text-decoration: none;
    color: rgba(255, 255, 255, 0.8);
    flex-shrink: 0;
    padding: 4px 12px 4px 4px;
    border-radius: 30px;
    background: rgba(255, 255, 255, 0.04);
    /*background: rgba(214, 164, 46, 0.1);*/
    border: 1px solid transparent;
    box-shadow: 0 0 14px rgba(214, 164, 46, 0.2);
    transition: box-shadow 0.25s ease, background 0.25s ease;
}
.header-cart-messenger-link:hover {
    background: rgba(255, 255, 255, 0.08);
    /*background: rgba(214, 164, 46, 0.16);*/
    border-color: rgba(214, 164, 46, 0.2);
    color: #fff;
    text-decoration: none;
    transform: translateY(-1px);
    /*box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);*/
    box-shadow: 0 0 20px rgba(214, 164, 46, 0.32);
}
/* Просто зона іконки 44×44 (мінімальний розмір для зручного натискання на телефоні) —
   без кружка-підложки й без фону: сам силует і є іконкою. */
.header-cart-messenger-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    flex-shrink: 0;
    transition: transform 0.25s ease;
}
.header-cart-messenger-link:hover .header-cart-messenger-icon {
    transform: scale(1.08);
}
/* SVG заповнює всю область іконки (44×44), а не маленький значок посередині. */
.header-cart-messenger-icon svg {
    width: 44px;
    height: 44px;
    display: block;
}
/* Колір за замовчуванням — стандартний колір тексту тултипа (не бренд-кольори, без фону).
   `svg *` потрібен окремо: у Viber fill стоїть на вкладеному <g>, на рівень глибше, ніж у
   Telegram/WhatsApp (де fill прямо на <svg>) — правило на самому <svg> туди не докотиться. */
.header-cart-messenger-icon svg,
.header-cart-messenger-icon svg * {
    fill: #dde426;
    transition: fill 0.25s ease;
}
/* При наведенні — м'яка пастельна заливка силуету під кожен месенджер. */
.header-cart-messenger-link.messenger-whatsapp:hover .header-cart-messenger-icon svg,
.header-cart-messenger-link.messenger-whatsapp:hover .header-cart-messenger-icon svg * {
    fill: #B5E6C3;
}
.header-cart-messenger-link.messenger-viber:hover .header-cart-messenger-icon svg,
.header-cart-messenger-link.messenger-viber:hover .header-cart-messenger-icon svg * {
    fill: #D4C9F0;
}
.header-cart-messenger-link.messenger-telegram:hover .header-cart-messenger-icon svg,
.header-cart-messenger-link.messenger-telegram:hover .header-cart-messenger-icon svg * {
    fill: #C2E0F4;
}
/*  появился эффект рамки вокруг свечения*/
a.header-cart-messenger-link.messenger-whatsapp:hover {
    color: #B5E6C3 !important;
}
a.header-cart-messenger-link.messenger-viber:hover {
    color: #D4C9F0 !important;
}
a.header-cart-messenger-link.messenger-telegram:hover {
    color: #C2E0F4 !important;
}
/* Текст рядом с иконкой */
/* ------------------------------------------------------------------ */
/* АНИМАЦИЯ НАЖАТИЯ (оставляем вашу, но слегка улучшаем)             */
/* ------------------------------------------------------------------ */

@keyframes messengerPop {
    0%   { transform: scale(1); }
    35%  { transform: scale(1.3); }
    65%  { transform: scale(0.92); }
    100% { transform: scale(1); }
}
.header-cart-messenger-link.messenger-pop .header-cart-messenger-icon {
    animation: messengerPop 0.45s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
/* ------------------------------------------------------------------ */
/* СТИЛИ ДЛЯ ТОВАРОВ В КОРЗИНЕ (если есть) — ПРЕМИУМ                */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* ИТОГО И КНОПКА ОФОРМЛЕНИЯ — ПРЕМИУМ                               */
/* ------------------------------------------------------------------ */
/* Кнопка "пустая корзина" — оформить красиво */
/* ------------------------------------------------------------------ */
/* МОБИЛЬНАЯ АДАПТАЦИЯ                                                */
/* ------------------------------------------------------------------ */

@media (max-width: 480px) {
    .header-cart-tooltip {
        width: 270px;
        right: -10px;
        padding: 14px 14px 16px;
    }
    .header-cart-messenger-link {
        padding: 5px 10px;
    }
    .header-cart-messenger-icon {
        width: 44px;
        height: 44px;
    }
    .header-cart-messenger-icon svg {
        width: 44px;
        height: 44px;
    }
    .header-cart-tooltip-intro {
        font-size: 1em;
    }
    .header-cart-tooltip-messengers {
        gap: 8px;
        flex-wrap: wrap;
    }
    /* Убираем декоративную звездочку на мобильных */
    .header-cart-tooltip-messengers::before {
        display: none;
    }
}
/*=================================
==================================
=================================*/
/*
 * Адаптивные карточки товаров на странице оформления заказа (#cart-from-storage).
 * Заменяют жёсткую таблицу, которая на узких экранах вылезала за пределы блока
 * при длинных названиях товаров.
 */
.ac-cart-items {
    display: flex;
    flex-direction: column;
    gap: 12px;
    margin-bottom: 16px;
}
.ac-cart-item {
    border: 1px solid rgba(214, 164, 46, 0.35);
    border-radius: 6px;
    padding: 10px 14px;
    background: rgba(255, 255, 255, 0.03);
}
.ac-cart-item-row {
    display: flex;
    align-items: center;
    gap: 10px;
}
/* Строка 1: название + бренд слева, кнопка удаления справа */
.ac-cart-item-row-main {
    justify-content: space-between;
}
.ac-cart-item-title {
    flex: 1 1 auto;
    min-width: 0; /* критично: без этого длинное название растягивает карточку вместо переноса */
}
.ac-cart-item-name {
    font-weight: 700;
    text-decoration: none;
    color: inherit;
    word-break: break-word;
}
.ac-cart-item-brand {
    font-weight: 400;
    opacity: 0.75;
    font-size: 0.9em;
    margin-left: 4px;
}
/* Кнопка-иконка удаления вместо текста "Удалить" — корзина/мусорка однозначно
   читается как "удалить товар", отдельный текст был избыточен. */
.ac-cart-item-remove {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    color: inherit;
    opacity: 0.7;
    transition: opacity 0.15s ease, background-color 0.15s ease;
}
.ac-cart-item-remove:hover {
    opacity: 1;
    background: rgba(255, 59, 48, 0.12);
}
/* Строка 2: характеристики (pack) — мелким приглушённым текстом */
.ac-cart-item-row-pack {
    margin-top: 2px;
}
.ac-cart-item-pack {
    font-size: 0.82em;
    opacity: 0.65;
}
/* Строка 3: количество / цена за единицу / сумма */
.ac-cart-item-row-finance {
    margin-top: 8px;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: 6px 0;
}
.ac-cart-item-qty {
    width: 60px;
    padding: 4px;
    text-align: center;
    flex: 0 0 auto;
}
.ac-cart-item-unit-price {
    font-size: 0.88em;
    opacity: 0.75;
    flex: 1 1 auto;
    text-align: left;
    padding-left: 1em
}
.ac-cart-item-sum {
    flex: auto;
    order: 3;
    font-weight: 700;
    flex: 0 0 auto;
    text-align: right;
}
/* Итоговая сумма заказа под списком карточек */
.ac-cart-total {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 12px 4px;
    border-top: 2px solid rgba(214, 164, 46, 0.4);
    font-size: 1.1em;
    font-weight: 700;
}
/* На самых узких экранах: цена за единицу переносится на отдельную строку,
   чтобы количество и сумма не сжимались друг к другу */

@media (max-width: 420px) {
    .ac-cart-item-unit-price {
        flex: 0 0 auto;
        order: 2;
        text-align: right;
        margin-top: 4px;
    }
    .ac-cart-item-sum {
        flex: auto !important;
    }
}
/* ------------------------------------------------------------------ */
/* ФОРМА ОФОРМЛЕННЯ — розбита на 2 візуальні блоки, щоб не виглядала  */
/* переобтяженою полями (Контактні дані / Доставка + примітка)       */
/* ------------------------------------------------------------------ */
.ac-form-block {
    margin-top: 22px;
    padding-top: 18px;
    border-top: 1px solid rgba(214, 164, 46, 0.2);
}
.ac-form-block:first-child {
    margin-top: 0;
    padding-top: 0;
    border-top: none;
}
/* Єдина ширина полів в обох блоках форми — щоб поля доставки не
   розтягувались на весь екран, а виглядали так само, як Ім'я/email/телефон.
   Трохи більші за замовчуванням: вище і довше, щоб не відчувалось затиснутості. */
.ac-form-block input[type="text"],
.ac-form-block input[type="email"],
.ac-form-block input[type="tel"],
.ac-form-block select,
.ac-form-block textarea {
    width: 100%;
    max-width: 340px;
    min-height: 46px;
    padding: 12px 14px;
    font-size: 1em;
    box-sizing: border-box;
    display: block;
    margin-left: auto;
    margin-right: auto;
    background: #000000;
    border: 1px solid #d6a42e;
    color: #f5eed7;
    border-radius: 4px;
}
.ac-form-block textarea {
    min-height: 90px;
    resize: vertical;
}
/* Обёртки полей (простые <div> в cart.php) и текст меток — центрируем,
   иначе label/paragraph остаются прижаты к левому краю, даже когда
   сам input уже центрирован через margin:auto выше. */
.ac-form-block > div {
    text-align: center;
}
.ac-delivery-fixed-label {
    font-size: 0.9em;
    margin: 4px 0 10px;
    text-align: center;
    color: #f5eed7;
}
.ac-delivery-group {
    margin-top: 8px;
    display: grid;
    justify-items: center;
    gap: 8px;
}
/* ------------------------------------------------------------------ */
/* Кнопки "назад/у каталог" одразу після суми замовлення (перед       */
/* полями форми), а нижче — заклик "Готові оформити замовлення?"      */
/* Все по центру. DOM-порядок лишається title → subtitle → кнопки     */
/* (так природньо читає скрінрідер і клавіатурна навігація), а         */
/* видима черговість "кнопки, потім фрази" задана через flex order.   */
/* ------------------------------------------------------------------ */
.ac-order-intro {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    margin: 14px 0 22px;
    padding-top: 14px;
    border-top: 1px solid rgba(214, 164, 46, 0.2);
}
.ac-order-intro-title {
    order: 2;
    font-size: 1.25em;
    font-weight: 700;
    color: #f5eed7;
    margin: 14px 0 4px;
}
/* Всі кнопки форми оформлення (і ці дві, і кнопка "Оформити замовлення" нижче)
   в одному стилі з кнопкою "Купити" у статті — золота пігулка. */
.ac-form-block .ac-button,
.ac-form-block input[type="submit"].ac-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    white-space: nowrap;
    min-height: 44px;
    padding: 0 18px;
    background: #d6a42e !important;
    color: #000000 !important;
    border: none !important;
    border-radius: 4px;
    font-weight: 700;
    text-transform: uppercase;
    font-size: 0.8em;
    letter-spacing: 0.5px;
    text-decoration: none;
    cursor: pointer;
    transition: background 0.2s, box-shadow 0.2s, transform 0.2s;
}
.ac-order-intro .ac-button:hover,
.ac-form-block .ac-button:hover,
.ac-form-block input[type="submit"].ac-button:hover {
    background: #b88d22 !important;
    box-shadow: 0 4px 12px rgba(214, 164, 46, 0.3);
    transform: translateY(-1px);
    text-decoration: none;
}

/* ------------------------------------------------------------------ */
/* АВТОЗАПОВНЕННЯ У БРАУЗЕРАХ НА ОСНОВІ CHROMIUM                       */
/*                                                                     */
/* Chrome, Edge та Opera застосовують до автозаповнених полів власне   */
/* правило input:-webkit-autofill зі світлим фоном. Перебити його      */
/* через background-color неможливо: браузер малює цей фон окремим     */
/* шаром поверх власного тла елемента.                                 */
/*                                                                     */
/* Робочий прийом — внутрішня тінь на всю площу поля: вона лягає ВИЩЕ  */
/* службового фону і повністю його перекриває. Колір тексту задається  */
/* через -webkit-text-fill-color, бо звичайний color на автозаповнених */
/* полях так само ігнорується.                                         */
/*                                                                     */
/* transition на background-color з великою затримкою — страховка на   */
/* випадок, якщо тінь не спрацює: браузер просто не встигне показати   */
/* свій фон. Firefox таких стилів не нав'язує, тому правило йому не    */
/* шкодить: він ігнорує -webkit-* властивості.                         */
/* ------------------------------------------------------------------ */
.ac-form-block input:-webkit-autofill,
.ac-form-block input:-webkit-autofill:hover,
.ac-form-block input:-webkit-autofill:focus,
.ac-form-block input:-webkit-autofill:active,
.ac-form-block textarea:-webkit-autofill,
.ac-form-block textarea:-webkit-autofill:hover,
.ac-form-block textarea:-webkit-autofill:focus,
.ac-form-block select:-webkit-autofill,
.ac-form-block select:-webkit-autofill:hover,
.ac-form-block select:-webkit-autofill:focus {
    -webkit-box-shadow: inset 0 0 0 1000px #000000 !important;
    box-shadow: inset 0 0 0 1000px #000000 !important;
    -webkit-text-fill-color: #f5eed7 !important;
    caret-color: #f5eed7;
    border: 1px solid #d6a42e !important;
    -webkit-transition: background-color 100000s ease-in-out 0s;
    transition: background-color 100000s ease-in-out 0s;
}

/* Підказка автозаповнення у полі (значення, яке браузер пропонує,
   але користувач ще не підтвердив) — той самий колір тексту. */
.ac-form-block input:-webkit-autofill::first-line {
    color: #f5eed7;
    font-size: 1em;
}

@media (max-width: 480px) {
    .ac-order-intro .ac-button,
    .ac-form-block .ac-button {
        width: 100%;
    }
    .ac-form-block input[type="text"],
    .ac-form-block input[type="email"],
    .ac-form-block input[type="tel"],
    .ac-form-block select,
    .ac-form-block textarea {
        max-width: 100%;
    }
}
/* ------------------------------------------------------------------ */
/* ПЛАШКА "ЗАМОВЛЕННЯ ПРИЙНЯТО" — стандартне повідомлення Joomla      */
/* (enqueueMessage) перефарбоване під стиль сайту замість дефолтного  */
/* bootstrap-алерту. Якщо шаблон сайту виводить повідомлення іншою    */
/* розміткою — уточніть реальний селектор через інспектор браузера,   */
/* тут покриті обидва поширені варіанти (Joomla 4 і Joomla 5).        */
/* ------------------------------------------------------------------ */
#system-message-container .alert-success,
joomla-alert[type="success"] {
    background: linear-gradient(135deg, #3a1f1f, #2a1414);
    border: 1px solid rgba(214, 164, 46, 0.4);
    color: #f5ece0;
    border-radius: 8px;
    padding: 14px 18px;
}
#system-message-container .alert-success .alert-heading,
joomla-alert[type="success"] strong {
    color: #d6a42e;
}
#system-message-container .alert-error,
#system-message-container .alert-danger,
joomla-alert[type="danger"] {
    background: linear-gradient(135deg, #3a1f1f, #2a1414);
    border: 1px solid rgba(214, 60, 46, 0.5);
    color: #f5ece0;
    border-radius: 8px;
    padding: 14px 18px;
}
/* ===== Continue shopping / back to catalog — text links (not buttons) =====
   Задача: дать пользователю возможность вернуться к покупкам, но НЕ создавать
   визуальную конкуренцию с основным действием "Оформити замовлення".
   Поэтому: маленький шрифт, приглушённый (не акцентный) золотой, без фона/рамки,
   подчёркивание только на hover — стандартный визуальный код "второстепенное действие". */
.ac-continue-shopping-links {
    display: flex;
    justify-content: flex-end; /* прижаты к правому краю, под шапкой блока корзины */
    gap: 24px;
    margin: 4px 0 16px;
    flex-wrap: wrap;
}
.ac-link {
    /* сброс нативных стилей <button>, чтобы он выглядел как <a> */
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: none;
    border: none;
    padding: 2px 0;
    margin: 0;
    cursor: pointer;
    font-family: inherit;
    font-size: 13px;
    line-height: 1.4;
    letter-spacing: 0.02em;
    text-decoration: none;
    white-space: nowrap;
    /* приглушённый золотой — заметно тише, чем яркий акцент кнопки заказа */
    color: rgba(212, 175, 100, 0.72);
    transition: color 0.15s ease, opacity 0.15s ease;
}
.ac-link:hover,
.ac-link:focus-visible {
    color: rgb(212, 175, 100); /* полный акцентный золотой только при взаимодействии */
    text-decoration: underline;
    text-underline-offset: 3px;
}
.ac-link:focus-visible {
    outline: 1px dashed rgba(212, 175, 100, 0.6);
    outline-offset: 3px;
}
.ac-link-arrow {
    font-size: 14px;
    transform: translateY(-0.5px);
}
.ac-textarea {
    margin: 0 auto;
}
.ac-form-block.order-button {
    width: 50%;
    margin: auto;
    text-align: center;
}
.ac-form-block.order-button input[type="submit"] {
    width: 100%
}
/* На мобильном — ссылки друг под другом, тоже прижаты вправо */

@media (max-width: 480px) {
    .ac-continue-shopping-links {
        gap: 6px;
        flex-direction: column;
        align-items: flex-end;
    }
}

/* ==========================================================================
   ДОБАВЛЕНО ИЗ РАСШИРЕНИЯ-ПРЕДШЕСТВЕННИКА — правила, которых нет в user.css
   ========================================================================== */

/* Заголовки блоков формы оформления заказа. */
.ac-title-data {
    text-align: center;
}

/* Блок контактных данных. */
.ac-block-data {
    text-align: center;
}

/* Кнопка "Купити" для нативного состояния disabled (например, будущей
   блокировки на время сетевого запроса). */
.articart-add-to-cart:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

/* Сообщение о пустой корзине на странице оформления заказа. */
#cart-empty-message {
    text-align: center;
    padding: 40px 20px;
    color: #666;
    font-size: 1.1em;
    background-color: #f9f9f9;
    border: 1px dashed #d7d7d7;
    border-radius: 4px;
    margin: 20px 0;
}

/* ============================================================
   ДОПОЛНЕНИЯ ArtiCart (складской учёт, бейджи, витрина, позиции «под заказ»)
   ============================================================ */

/* --- Бейджи и акционная цена в плашке товара --- */
.cart-action-marks { display: flex; flex-wrap: wrap; gap: .3rem; margin-top: .2rem; }
.cart-action-marks:empty { display: none; }

.articart-badge {
    --h: 0;
    --s: 100%;
    --l: 33%;

    display: inline-flex;
    align-items: center;
    padding: .12rem .5rem;
    font-size: .75rem;
    font-weight: 600;
    line-height: 1.5;
    border-radius: 1rem;
    background: hsl(var(--h), var(--s), var(--l));
    /* Окантовка приходит посчитанной из PHP (BadgeColor::edge): «на 12% темнее»
       уходило в минус у тёмных пресетов и давало чёрный ободок — ровно та же
       грабля, что была у ножек ленты. Запасное значение оставлено прежним:
       разметка, отданная старой версией плагина, не должна остаться без рамки. */
    border: 1px solid hsl(
        var(--edge-h, var(--h)),
        var(--edge-s, var(--s)),
        var(--edge-dark-l, calc(var(--l) - 12%)));
    /* Тот же готовый цвет, что и у ленты: на золотом «Топ» он тёмный,
       на бордовой «Акции» — золотисто-бежевый. Считается в PHP по
       относительной яркости (см. BadgeColor::textColor). */
    color: var(--fg, #ffeaa7);
}


/* --- Сигналы под блоком цен: «свіжа партія» и «залишилось» (1.9.28) ---

   Оба выровнены по левому краю наравне с ценой и идут один под другим:
   сначала повод купить (партия свежая), потом повод поторопиться (мало).
   Обратный порядок читается как давление.

   ЦВЕТ БЕРЁТСЯ ИЗ ТЕХ ЖЕ ПЕРЕМЕННЫХ, ЧТО У ЛЕНТЫ (--h/--s/--l приходят
   инлайном из BadgeColor), но светлота поднимается до читаемой: плашка стоит
   на тёмном фоне шаблона, а «свіже» задано тёмно-зелёным — на своём фоне он
   верен, поверх тёмного превращается в нечитаемое пятно. max() поднимает
   только то, что ниже порога, и не трогает и без того светлые пресеты. */
.cart-action-fresh,
.cart-action-last {
    --h: 0;
    --s: 0%;
    --l: 50%;

    display: flex;
    align-items: center;
    gap: .35rem;
    margin-top: .25rem;
    font-size: .85rem;
    line-height: 1.35;
    color: hsl(var(--h), var(--s), max(52%, var(--l)));
}

.cart-action-fresh__date { font-weight: 600; }

/* Значок стоит в своём элементе, а не в тексте: так его можно увеличить или
   заменить, не трогая подпись, и он не попадает в озвучку скринридера. */
.cart-action-last__icon {
    /* inline-block обязателен: к строчному элементу transform не применяется,
       и вся анимация ниже молча не работала бы. Внутри flex-строки элемент и
       так становится flex-item, но маркер выводится не только там. */
    display: inline-block;
    font-size: 1.05em;
    line-height: 1;
    /* Точка опоры внизу: огонь растёт от основания, а не раздувается из
       середины — сверху вниз пламя не горит. */
    transform-origin: 50% 90%;
}

/* --- Анимация значков дефицита (1.9.30) ---

   ДВА УРОВНЯ — ДВА РАЗНЫХ ДВИЖЕНИЯ, И РАЗНИЦА СМЫСЛОВАЯ.
   Огонёк «розбирають» ГОРИТ: непрерывное мягкое колебание, к которому глаз
   привыкает и перестаёт замечать, — товар ещё есть, торопить незачем.
   Молния «закінчується» ВСПЫХИВАЕТ: почти всё время ровный значок и короткий
   двойной разряд раз в пару секунд. Пауза и делает вспышку заметной; будь
   молния в постоянном движении, она сравнялась бы с огоньком и уровень
   перестал бы читаться.

   ДВИЖЕТСЯ ТОЛЬКО ЗНАЧОК, НЕ СТРОКА. Анимируются transform, opacity и
   filter — свойства, которые браузер считает на композиторе, не трогая
   раскладку. Меняй тут размер шрифта или margin — и строка прыгала бы по
   высоте, а вместе с ней и вся плашка: остаток пересчитывается на глазах
   покупателя, пока он складывает товар в корзину.

   Свечение задано в цветах пламени и молнии, а не переменными --h/--s/--l
   бейджа: подпись рядом красится цветом типа (её можно перенастроить), а
   огонь оранжевый, а не «цвета маркера» — иначе жёлтый пресет дал бы
   зеленоватое пламя. */
.cart-action-last--moderate .cart-action-last__icon {
    animation: articart-flame 1.9s ease-in-out infinite;
}

@keyframes articart-flame {
    0%, 100% {
        transform: scale(1) rotate(0deg);
        opacity: 1;
        filter: drop-shadow(0 0 .18em rgba(255, 138, 0, .55));
    }
    25% {
        transform: scale(1.1) rotate(-3deg);
        opacity: .92;
        filter: drop-shadow(0 0 .34em rgba(255, 106, 0, .75));
    }
    50% {
        transform: scale(.96) rotate(2deg);
        opacity: 1;
        filter: drop-shadow(0 0 .14em rgba(255, 160, 0, .5));
    }
    75% {
        transform: scale(1.07) rotate(3deg);
        opacity: .95;
        filter: drop-shadow(0 0 .3em rgba(255, 120, 0, .7));
    }
}

.cart-action-last--critical .cart-action-last__icon,
.cart-action-last--single .cart-action-last__icon {
    animation: articart-spark 2.6s ease-out infinite;
}

/* Разряд занимает первые 18% цикла — две вспышки подряд, — остальное время
   значок стоит ровно. Проценты подобраны так, чтобы вторая вспышка была
   слабее первой: разряд затухает, а не мигает лампочкой. */
@keyframes articart-spark {
    0% {
        transform: scale(1);
        opacity: .85;
        filter: drop-shadow(0 0 0 rgba(255, 224, 130, 0));
    }
    4% {
        transform: scale(1.28);
        opacity: 1;
        filter: drop-shadow(0 0 .45em rgba(255, 233, 150, .95));
    }
    9% {
        transform: scale(1);
        opacity: .8;
        filter: drop-shadow(0 0 .05em rgba(255, 224, 130, .2));
    }
    13% {
        transform: scale(1.16);
        opacity: 1;
        filter: drop-shadow(0 0 .3em rgba(255, 233, 150, .8));
    }
    18%, 100% {
        transform: scale(1);
        opacity: .9;
        filter: drop-shadow(0 0 0 rgba(255, 224, 130, 0));
    }
}

/* Критический уровень и последняя единица говорят громче умеренного —
   но именно насыщенностью, а не размером: строка не должна прыгать по высоте,
   когда покупатель кладёт товар в корзину и уровень меняется на глазах. */
.cart-action-last--critical,
.cart-action-last--single { font-weight: 600; }

/* Скрытие через атрибут hidden: маркер прячется, когда покупатель забрал в
   корзину весь остаток, и возвращается, когда он его уменьшил. display у
   .cart-action-last задан flex, а flex сильнее hidden — без этого правила
   скрытие бы не сработало. */
.cart-action-last[hidden] { display: none; }

/* Мигающий маячок перед «свіжа партія». Точка своего цвета не имеет — берёт
   тот же оттенок, что и подпись рядом. */
.pulse-dot {
    flex: 0 0 auto;
    width: .5rem;
    height: .5rem;
    border-radius: 50%;
    background: currentColor;
    animation: articart-pulse 1.6s ease-in-out infinite;
}

@keyframes articart-pulse {
    0%, 100% { opacity: 1;  transform: scale(1); }
    50%      { opacity: .35; transform: scale(.75); }
}

/* Мигание — акцент, а не необходимость: для тех, кому анимация мешает,
   точка просто остаётся на месте. Тем же правилом гасятся огонёк и молния:
   сами значки при этом остаются, теряется только движение — смысл маркера
   держится на подписи и числе, а не на анимации. */
@media (prefers-reduced-motion: reduce) {
    .pulse-dot,
    .cart-action-last__icon { animation: none; }

    /* Обнуление явное — это страховка, а не необходимость: сам по себе
       animation: none возвращает базовые значения. Но стоит однажды добавить
       значку animation-fill-mode: forwards или выставить свечение инлайном —
       и кадр останется висеть, причём только у тех, кто просил меньше
       движения, то есть у тех, кто об этом не сообщит. */
    .cart-action-last__icon { filter: none; opacity: 1; transform: none; }
}

.cart-action-price-old {
    margin-right: .4rem;
    font-size: .85em;
    text-decoration: line-through;
    opacity: .65;
}

.cart-action-unavailable {
    padding: .3rem .7rem;
    border-radius: .35rem;
    background: rgba(128, 128, 128, .18);
    font-size: .9rem;
}

/* --- Витрина (mod_articart_showcase) --- */
.articart-showcase {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
    gap: 1rem;
}

.articart-showcase--carousel {
    display: flex;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    gap: 1rem;
    padding-bottom: .5rem;
}

.articart-showcase--carousel .articart-showcase__item {
    flex: 0 0 min(220px, 70vw);
    scroll-snap-align: start;
}

.articart-showcase__item {
    display: flex;
    flex-direction: column;
    gap: .35rem;
    padding: .75rem;
    border: 1px solid rgba(128, 128, 128, .3);
    border-radius: .5rem;
}

.articart-showcase__link { text-decoration: none; }
.articart-showcase__image img { width: 100%; height: auto; border-radius: .35rem; }
/* Картинка витрины стоит в ячейке сетки и должна занимать её целиком.
   Общее правило обёртки ленты делает её inline-block (это нужно, чтобы в
   статье лента прижималась к картинке, а не к краю текста) — здесь возвращаем
   блочное поведение, иначе плитки витрины съедут по ширине. */
.articart-showcase__image.articart-ribbon-host { display: block; }
.articart-showcase__name { display: block; font-weight: 600; margin-top: .35rem; }
.articart-showcase__brand,
.articart-showcase__note { font-size: .85rem; opacity: .8; }
.articart-showcase__price { margin-top: auto; font-size: 1.05rem; }
.articart-price--old { text-decoration: line-through; opacity: .65; margin-right: .4rem; font-size: .85em; }

/* --- Страница корзины --- */
.articart-cart table { width: 100%; }
.articart-cart__total { font-size: 1.2rem; font-weight: 700; }
.articart-cart__row--unavailable { opacity: .55; }

/* --- Остаток и позиции «под заказ» (1.9.3) ---
   Цвета заданы через currentColor и прозрачности, а не жёсткими значениями:
   плашка живёт внутри шаблона сайта, где фон задаёт user.css, и любой
   фиксированный цвет пришлось бы там же переопределять. */
.cart-action-stock {
    font-size: .85rem;
    opacity: .8;
    white-space: nowrap;
}

.cart-action-stock--empty {
    font-weight: 600;
    opacity: 1;
}

/* Предупреждение занимает всю ширину плашки: она выстроена в строку, и
   сообщение должно вставать под неё, а не сжимать кнопку. */
.cart-action-notice {
    flex-basis: 100%;
    width: 100%;
    margin-top: .35rem;
    padding: .3rem .6rem;
    border-radius: .35rem;
    background: rgba(190, 130, 0, .15);
    font-size: .85rem;
    line-height: 1.35;
}

.cart-action-notice[hidden] { display: none; }

.ac-cart-item-backorder {
    margin-top: .25rem;
    font-size: .85rem;
    opacity: .85;
}

.ac-cart-item-backorder:empty { display: none; }


/* ==========================================================================
   ТОВАР КАК ЕДИНЫЙ БЛОК + ЛЕНТЫ И МАРКЕРЫ
   ========================================================================== */

/* Рамка отбивает границу между соседними товарами в одной статье. Цвет через
   currentColor: плашка живёт внутри шаблона сайта, и жёстко заданный цвет
   пришлось бы переопределять в user.css. */
.articart-product {
    position: relative;
    isolation: isolate;
    border: 1px solid currentColor;
    border-radius: .6rem;
    padding: 1rem;
    margin: 1.5rem 0;
}

.articart-product .cart-action-module { margin-bottom: 0; }

/* Обёртка первой картинки описания: лента позиционируется относительно неё.
   inline-block, а не block — иначе обёртка растянулась бы на всю ширину
   текста, и лента ушла бы от картинки в пустое поле слева. */
.articart-ribbon-host {
    position: relative;
    display: inline-block;
    max-width: 100%;

    /*
     * ЗДЕСЬ НЕЛЬЗЯ СТАВИТЬ container-type.
     *
     * Соблазн понятен: обёртка облегает картинку, и контейнерные единицы
     * дали бы размер ленты в долях от неё. Но container-type: inline-size
     * включает СДЕРЖИВАНИЕ ПО ШИРИНЕ — браузер обязан вычислить ширину
     * элемента, не заглядывая в содержимое. Своей ширины у обёртки нет, она
     * как раз облегает картинку, поэтому ширина становится нулевой, а
     * max-width: 100% у картинки превращается в ноль — изображение исчезает
     * со страницы целиком.
     *
     * Поэтому контейнером сделана сама лента (см. ниже), а её размер задан
     * процентом от этой обёртки: проценты сдерживания не требуют.
     */

    /*
     * СВОЙ СЛОЙ.
     * Без изоляции z-index ленты соперничает с элементами всей страницы, и
     * лента всплывала поверх логотипа сайта. isolation создаёт собственный
     * контекст наложения: внутри него лента по-прежнему выше картинки, но
     * наружу её слой больше не выходит.
     */
    isolation: isolate;
}

/* --------------------------------------------------------------------------
   ЛЕНТА.

   ЦВЕТ выводится из ОДНОГО базового оттенка (--h/--s/--l/--fg), который
   приходит инлайном из PHP (BadgeColor::cssVars) — и у ленты в статье, и у
   ленты в витрине, поэтому пара «лента вверху / маркер внизу» всегда одного
   тона.

   ГЕОМЕТРИЯ замкнута на одну величину — сторону квадрата (--ribbon-size).
   Всё остальное задано в процентах ОТ НЕЁ, а сама она — процент от обёртки,
   то есть от картинки. Цепочка пропорций замкнута, поэтому при любом размере
   картинки и при любом зуме браузера (в том числе 280%) лента масштабируется
   целиком, а не по частям.

   От чего считается каждый процент — это разное у разных величин:

     --ribbon-size     ширина ленты (сторона квадрата)  — от обёртки = от картинки
     --ribbon-band     padding полосы                    — от ширины квадрата
     --ribbon-pos      left/top полосы                   — от ширины/высоты квадрата
     --ribbon-length   ширина полосы                     — от ширины квадрата
     --ribbon-offset   вынос ленты за угол картинки И размер ножек — АБСОЛЮТНАЯ
                       величина в px, НЕ процент (объяснение ниже)

   ПОЧЕМУ НОЖКИ — ЕДИНСТВЕННАЯ ВЕЛИЧИНА, КОТОРАЯ НЕ ПРОЦЕНТ ОТ КВАДРАТА.
   Ножки не украшение: они закрывают ровно тот вынос, на который лента сдвинута
   за угол картинки (top/left: -offset). Их задача — дотянуться от угла квадрата
   до края изображения, а это расстояние равно ВЫНОСУ и ничему больше. Вынос
   задан в px и от размера квадрата не зависит — значит, и ножка от него
   зависеть не должна.

   До 1.9.28 ножка задавалась процентом от стороны квадрата, и на глаз это
   работало ровно до тех пор, пока сторона была пропорциональна картинке.
   Но --ribbon-size — это clamp(): на широкой картинке он упирается в потолок
   (260px), при зуме браузера картинка в CSS-пикселях сжимается, квадрат уходит
   из потолка вниз, а вынос остаётся теми же 6px. Одна и та же доля даёт разную
   длину ножки: 2.3% держались до 200%, а на 300% требовалось уже 4.1%. Оба
   значения — это одни и те же ~6px, просто от разных квадратов.
   Поэтому ножка = вынос, а не доля.

   ГЛАВНОЕ ПРАВИЛО, которое нельзя нарушать. Полоса достаёт торцами до углов
   квадрата (там, где стоят ножки) только если её полутолщина не меньше
   расстояния от угла до её оси. При --ribbon-pos: 40.5% это 0.135 × сторона,
   а полутолщина складывается как --ribbon-band + --ribbon-font / 2. Значения
   9% + 9cqw/2 дают ровно 0.135 — равенство. Поэтому менять --ribbon-band в
   одиночку НЕЛЬЗЯ: придётся пересчитывать и --ribbon-pos по формуле
   pos = (1 - 1.414 × (band + доля_шрифта / 2)) / 2. Безопасно меняется только
   --ribbon-size: остальное подстроится само.

   Значения по умолчанию в этом блоке — для витрины (мелкая картинка).
   Для статьи они переопределены ниже, в .articart-product .articart-ribbon.
   -------------------------------------------------------------------------- */
.articart-ribbon {
    position: absolute;

    /* Вынос за угол картинки и длина ножек — ОДНА величина, см. объяснение
       выше. Разъехаться они не могут: обе стороны считаются отсюда. */
    top:  calc(-1 * var(--ribbon-offset));
    left: calc(-1 * var(--ribbon-offset));
    z-index: 2;

    /* Значения цвета по умолчанию — на случай, если переменные не пришли. */
    --h: 0;
    --s: 100%;
    --l: 33%;

    /* --- Геометрия (витрина) --- */
    --ribbon-size:   clamp(56px, 40%, 150px);
    --ribbon-band:   5.9%;
    --ribbon-font:   clamp(8px, 9cqw, 40px);
    --ribbon-track:  .08em;
    --ribbon-length: 155%;
    --ribbon-pos:    40.5%;
    --ribbon-offset: 6px;

    /*
     * РАЗМЕР — ПРОЦЕНТОМ ОТ ОБЁРТКИ, НЕ В cqw ОТ НЕЁ ЖЕ.
     * Проценты не требуют сдерживания, а контейнерные единицы требуют —
     * и обёртка, которая облегает картинку, схлопнулась бы в ноль.
     * Границы clamp() держат ленту в разумных пределах: на миниатюре она не
     * станет микроскопической, на широком баннере не разрастётся.
     */
    width: var(--ribbon-size);
    height: var(--ribbon-size);

    /*
     * Контейнер объявлен на самой ленте: внутри неё 1cqw = 1% её ширины, и
     * кегль надписи масштабируется вместе с лентой. Сдерживание здесь
     * безвредно — ширина ленты задана явно и от содержимого не зависит.
     */
    container-type: inline-size;

    /*
     * Торцы полосы уходят за квадрат и подрезаются — именно это создаёт
     * впечатление, что лента продолжается под изображением.
     */
    overflow: hidden;
    pointer-events: none;

    /*
     * ТЕНЬ ЖИВЁТ ЗДЕСЬ, А НЕ НА ПОЛОСЕ. Это не вкусовщина, а единственный
     * способ не потерять её при подрезке.
     *
     * box-shadow на самой полосе рисуется ВНУТРИ квадрата, и overflow: hidden
     * срезает её вместе с торцами — по нижней и правой сторонам квадрата
     * появлялись отчётливые серые полосы с резким краем.
     *
     * filter применяется к элементу ПОСЛЕ обрезки: браузер сначала вырезает
     * форму, а тень отбрасывает уже вырезанный силуэт — и она свободно
     * выходит за границы квадрата.
     *
     * Побочный эффект, о котором стоит помнить: filter создаёт новый контекст
     * наложения. Внутренний z-index: 1 у полосы (чтобы ножки уходили под неё)
     * продолжает работать, но вывести что-либо из ленты НАРУЖУ поверх страницы
     * этим z-index больше нельзя.
     */
    filter: drop-shadow(0 4px 8px rgba(0, 0, 0, .4));

    /* Края градиента, блик по центру и цвет загнутых «ножек». */
    --ribbon-dark:  hsl(var(--h), var(--s), calc(var(--l) - 12%));
    --ribbon-light: hsl(var(--h), var(--s), calc(var(--l) + 12%));

    /*
     * ЦВЕТ НОЖЕК — УМНОЖЕНИЕМ ЯРКОСТИ, НЕ ВЫЧИТАНИЕМ.
     * Прежняя формула вычитала 22% яркости. У зелёного пресета яркость всего
     * 21% — результат уходил в минус, зажимался в ноль, и загиб получался
     * чёрным. Умножение сохраняет пропорцию на любом пресете, а max() держит
     * нижнюю границу, чтобы у совсем тёмных цветов ножки не сливались в пятно.
     */
    --ribbon-leg-color: hsl(var(--h), calc(var(--s) - 10%), max(12%, calc(var(--l) * .55)));

    /*
     * ЦВЕТ НАДПИСИ ПРИХОДИТ ГОТОВЫМ (--fg), А НЕ СЧИТАЕТСЯ ЗДЕСЬ.
     *
     * Прежняя версия переключала текст по яркости L с порогом 55% — и на
     * золотом (L=48%) выбирала светлую надпись, которая сливалась с фоном.
     * Дело не в пороге: L из HSL не отражает воспринимаемую яркость, жёлтый
     * и синий с одинаковой L выглядят по-разному. Правильная величина —
     * относительная яркость по WCAG, а её в CSS не вычислить: нужна
     * гамма-коррекция каналов. Поэтому цвет считает PHP (BadgeColor) и
     * передаёт готовым вместе с остальными переменными.
     */
}

/* Квадрат: высота повторяет ширину. Отдельным правилом, потому что явная
   height выше нужна старым браузерам как запасная — при поддержке
   aspect-ratio она снимается. */
@supports (aspect-ratio: 1) {
    .articart-ribbon {
        height: auto;
        aspect-ratio: 1;
    }
}

/* --------------------------------------------------------------------------
   ПОЛОСА С НАДПИСЬЮ.

   Положение вычисляется ОТ ТОЛЩИНЫ, а не фиксированным отступом сверху.
   Раньше стояло top: 25%, а толщина полосы с тех пор выросла втрое: отступ
   задаёт верхний край, а середина отстоит от него на половину толщины — и
   чем толще полоса, тем сильнее её ось уезжает с диагонали. Торцы переставали
   доставать до углов, и ножки повисали отдельными квадратиками рядом с лентой.
   Теперь из точки пересечения с диагональю вычитается половина полосы, ось
   остаётся на диагонали при любой толщине.

   Центрировать через transform: translate(-50%, -50%) нельзя: торцы выходят
   за углы и обрезаются не там, где нужно. Только left/top от --ribbon-pos.
   -------------------------------------------------------------------------- */
.articart-ribbon span {
    position: absolute;
    display: block;

    /* Полоса длиннее стороны квадрата: она идёт по диагонали (141.4%) и
       должна уходить за оба края, иначе на концах видны ровные срезы.
       Ниже 142% торцы показываются. */
    width: var(--ribbon-length);
    left: calc(var(--ribbon-pos) - var(--ribbon-length) / 2);
    top:  calc(var(--ribbon-pos) - (var(--ribbon-band) + var(--ribbon-font) / 2));

    /*
     * ТОЛЩИНА — В ПРОЦЕНТАХ ОТ КВАДРАТА, НЕ В em ОТ ШРИФТА.
     * В em пропорция ломается ровно в тот момент, когда кегль упирается в
     * потолок clamp и перестаёт расти: полоса замирает, а квадрат продолжает
     * увеличиваться. Отсюда «плывёт при 250%».
     */
    padding: var(--ribbon-band) 0;

    text-align: center;
    text-transform: uppercase;
    font-size: var(--ribbon-font);
    font-weight: 700;
    letter-spacing: var(--ribbon-track);
    line-height: 1.4;
    transform: rotate(-45deg);

    /*
     * Слой полосы. ::after рисуется ПОСЛЕ содержимого, поэтому верхняя ножка
     * ложилась поверх ленты. Поднимаем полосу — обе ножки уходят под неё.
     * z-index: -1 у самих ножек не годится: лента — свой контекст наложения,
     * и отрицательный слой прячет их вовсе.
     */
    z-index: 1;

    /*
     * Тени здесь НЕТ намеренно — она перенесена на .articart-ribbon выше,
     * иначе overflow: hidden срезает её по нижней и правой сторонам квадрата.
     */

    background: linear-gradient(135deg,
        var(--ribbon-dark) 0%,
        var(--ribbon-light) 50%,
        var(--ribbon-dark) 100%);
    color: var(--fg, #ffeaa7);

    /*
     * ОКАНТОВКА ПОЛОСЫ — ДВЕ ЛИНИИ, ОБЕ ПОСЧИТАНЫ В PHP ОТ БАЗОВОГО ЦВЕТА.
     *
     * Светлая внутри (--edge-*) читается как отблеск металла на кромке,
     * тёмная снаружи (--edge-dark-l) отделяет ленту от картинки, какой бы
     * светлой картинка ни была. Обе — box-shadow, а не border: border вошёл бы
     * в размеры полосы и сбил бы равенство, на котором держатся её торцы и
     * ножки (см. «главное правило» выше). Тень геометрии не меняет.
     *
     * ЗАЧЕМ СЧИТАТЬ ЭТО В PHP, А НЕ ЗДЕСЬ. Оттенок канта — не «базовый плюс
     * столько-то»: он подтягивается к тёплому якорю по кратчайшей дуге, а
     * светлота уходит от заливки в ту сторону, где остаётся контраст. Ни
     * условия «если заливка тёмная», ни арифметики по кратчайшей дуге в CSS
     * нет — ровно та же причина, по которой в PHP считается и --fg.
     * Формула и её обоснование — BadgeColor::edge().
     */
    box-shadow:
        inset 0 0 0 1px hsl(var(--edge-h, var(--h)), var(--edge-s, var(--s)), var(--edge-l, 60%)),
        0 0 0 1px hsl(var(--edge-h, var(--h)), var(--edge-s, var(--s)), var(--edge-dark-l, 15%));
}

/* --------------------------------------------------------------------------
   НОЖКИ (загиб ленты). Квадраты, а не треугольные клинья: загиб так читается
   лучше, а стык с краем картинки получается ровным.

   РАЗМЕР РАВЕН ВЫНОСУ ЛЕНТЫ (--ribbon-offset), и это не совпадение, а
   определение: ножка перекрывает ровно тот зазор, на который лента сдвинута
   за угол картинки. Ни em (привязка к кеглю, который упирается в clamp), ни
   проценты от квадрата (сам квадрат упирается в clamp) этому не отвечают —
   обе величины перестают меняться там, где зазор меняться не перестаёт.

   ИМЕНИ --ribbon-leg БОЛЬШЕ НЕТ, И ВОЗВРАЩАТЬ ЕГО НЕЛЬЗЯ. Оно уже дважды
   меняло смысл (до 1.9.27 — цвет ножек, в 1.9.27 — их размер), и в user.css
   сайта могло остаться старое значение-ЦВЕТ. Подставься такой var() в width —
   свойство стало бы недопустимым на этапе вычисления, ножки схлопнулись бы, и
   искать причину пришлось бы в чужом файле. Незнакомая переменная просто
   игнорируется, поэтому размер ножек взят из --ribbon-offset напрямую, без
   запасного var(--ribbon-leg, …). Нужен другой размер — меняется вынос.
   -------------------------------------------------------------------------- */
.articart-ribbon::before,
.articart-ribbon::after {
    content: "";
    position: absolute;
    width:  var(--ribbon-offset);
    height: var(--ribbon-offset);
    background: var(--ribbon-leg-color);
    /* z-index не задавать: под полосу они уходят за счёт z-index: 1 у неё. */
}

.articart-ribbon::before { bottom: 0; left: 0; }
.articart-ribbon::after  { top: 0; right: 0; }

/* --------------------------------------------------------------------------
   ЛЕНТА В СТАТЬЕ. Картинка крупная, поэтому и квадрат крупнее, и разрядка
   букв шире. Вынос (и, значит, ножки) остаётся общим — 6px: он привязан к
   стыку с краем картинки, а край одинаков и в статье, и в витрине.
   Правило покрывает оба случая: и ленту поверх первой картинки описания, и
   запасную ленту в углу рамки товара, когда картинки в описании нет.
   -------------------------------------------------------------------------- */
.articart-product .articart-ribbon {
    --ribbon-size:  clamp(96px, 45%, 260px);
    --ribbon-font:  clamp(9px, 9cqw, 40px);
    --ribbon-track: .14em;
}

/* Лента без картинки живёт в углу самой рамки товара: там стык не с картинкой,
   а с рамкой, и вынос на пиксель меньше. Отдельного правила top/left больше
   нет — достаточно поменять вынос, ножки подстроятся сами. */
.articart-product > .articart-ribbon { --ribbon-offset: 5px; }

/* --------------------------------------------------------------------------
   МАРКЕРЫ НА ПЛАШКЕ. Тот же базовый оттенок, что у парной ленты, — поэтому
   «Акція» внизу и лента «SALE» вверху читаются как одно целое.
   -------------------------------------------------------------------------- */

/* Отдельного правила для телефонов больше нет: лента меряется от картинки,
   а картинка на узком экране и так меньше — размер подстроится сам. */

/* ============================================================
   ДОБАВЛЕНО В 1.9.32
   ============================================================ */

/* --- Примерная дата поставки на плашке недоступного товара ---

   «Очікуємо поставку» и «20 серпня 2026» — это утверждение и его уточнение,
   поэтому дата стоит рядом, а не строкой ниже: перенос превратил бы её в
   отдельное сообщение, и взгляд читал бы её как второй, независимый факт.
   Точка-разделитель нарисована псевдоэлементом, а не набрана в PHP: в тексте
   её не выделить, а выделять надо — она относится к оформлению, а не к фразе,
   и переводчику в ней делать нечего. */
.cart-action-unavailable__eta {
    white-space: nowrap;
    opacity: .85;
}

.cart-action-unavailable__eta::before {
    content: "\00b7";
    margin: 0 .4em;
    opacity: .6;
}

/* --- Угловая медаль ---

   Правил формы здесь НЕТ намеренно, и это не забывчивость.

   Оформление углового штампа (.cart-action-corner-seal*) живёт в user.css
   сайта, а не в компоненте: так сложилось исторически и так и оставлено —
   переопределения там уже написаны и подключаются ПОСЛЕ наших стилей, то есть
   всё равно выигрывают. Поэтому медаль выводится с классом --hit (форму берёт
   у бестселлера) плюс своим --medal, а здесь задан только цвет: он приходит
   инлайном из PHP и должен перебить пресет хита, унаследованный вместе с
   формой.

   Как только в user.css появятся собственные правила для --medal, они
   победят и это правило — по тому же порядку подключения. */
.cart-action-corner-seal--medal {
    background: hsl(var(--h), var(--s), var(--l));
    color: var(--fg, #ffeaa7);
    border-color: hsl(var(--edge-h, var(--h)), var(--edge-s, var(--s)), var(--edge-l, 60%));
}


/* ============================================================
   ТОВАРА НЕТ И НЕ БУДЕТ: ПРИГЛУШЁННАЯ ЦЕНА (1.9.33)

   Цена не убирается совсем — она остаётся ответом на вопрос «сколько это
   стоило» и нужна тому, кто вернулся сравнить. Но она перестаёт быть
   ПРЕДЛОЖЕНИЕМ: рядом нет кнопки, и золотая цифра во всю яркость рядом с
   фразой «немає в наявності» читается как ошибка вёрстки — «купить можно,
   а кнопки почему-то нет».

   Гасится через filter: grayscale + opacity, а не подменой цвета. Причина
   та же, по которой затемнение в этом проекте всегда умножение: цвет цены
   приходит и из user.css сайта, и из инлайновых переменных бейджа, и
   перечислить все места, где его надо переопределить, невозможно. Фильтр
   действует на то, что получилось, каким бы оно ни было.

   Класс висит на .cart-action-price, а не на теле плашки: фраза о
   недоступности ниже гаснуть не должна — она здесь главная. */
.cart-action-price--muted {
    filter: grayscale(1);
    opacity: .55;
}

/* ============================================================
   ОЧЕРЕДЬ ОЖИДАНИЯ: «повідомити про наявність» (1.9.33)

   Раскрывашка на <details>, без единой строки JS. Кнопкой её делает вот это
   правило: у <summary> свой маркер-треугольник, и он здесь лишний — кнопка с
   треугольником читается как «раскрыть список», а не как «оставить адрес».
   Убирается он ДВУМЯ способами сразу: ::-webkit-details-marker для старых
   WebKit и list-style для всех остальных. Одного не хватает. */
.cart-action-waitlist {
    margin-top: .5rem;
}
.cart-action-waitlist > summary {
    display: inline-flex;
    align-items: center;
    /* height у .cart-action-button задан для <button>; у summary своя
       природа, поэтому строчная высота задаётся здесь. */
    line-height: 34px;
    list-style: none;
    user-select: none;
}
.cart-action-waitlist > summary::-webkit-details-marker {
    display: none;
}

.cart-action-waitlist__form {
    margin-top: .6rem;
    padding: .7rem .8rem;
    border: 1px solid rgba(214, 164, 46, .35);
    border-radius: .35rem;
    background: rgba(128, 128, 128, .12);
}

.cart-action-waitlist__lead {
    margin: 0 0 .6rem 0;
    font-size: .85em;
    opacity: .85;
}

.cart-action-waitlist__label {
    display: block;
    margin-bottom: .5rem;
    font-size: .85em;
}
.cart-action-waitlist__label span {
    display: block;
    margin-bottom: .15rem;
}
/* Ширина ограничена сверху: поле почты во всю ширину плашки на широком
   мониторе выглядит как поле для текста письма, а не для адреса. */
.cart-action-waitlist__label input {
    width: 100%;
    max-width: 22rem;
    height: 34px;
    padding: 0 .5rem;
    border: 1px solid #d6a42e;
    border-radius: 4px;
    background: #000000;
    color: #f5eed7;
}
