/* color-scheme. Значение light dark в :root обязательно и должно стоять именно
   здесь, а не только в правилах по data-theme: атрибут выставляет JS, а до его
   запуска (первый кадр) :root не объявлял бы поддержку тем вовсе. Android WebView
   в этот момент считал страницу не умеющей тёмную тему, включал принудительное
   затемнение (force dark) и уже не отключал его — «Светлая» выглядела тёмной.
   Дальше значение уточняется под выбранную тему. */
/* --ok — успешный исход заказа («Готов», «Доставлен»). Отдельная переменная рядом
   с --danger, потому что зелёный в тёмной теме нужен заметно светлее: на тёмной
   подложке тёмно-зелёный текст не читался бы. */
:root { --pf-blue: #FFE9DE; --pf-lilac: #FFF1E8; --pf-mint: #E6F6ED; --edge: #E9E6E0; --accent: #F45116; --on-accent: #fff; --danger: #e03a3a; --ok: #219653; --fav: #F45116; --bg: #F7F5F0; --surface: #FFFFFF; --fg: #242321; --hint: #89857F; --card: #F2EFE9; color-scheme: light dark; }
:root[data-theme="dark"] { --pf-blue: #33231A; --pf-lilac: #2E2620; --pf-mint: #1E3328; --edge: #363733; --accent: #F45116; --on-accent: #fff; --bg: #171816; --surface: #222321; --fg: #F7F5F0; --hint: #AAA8A1; --card: #2B2C29; --elev: #2B2C29; --ok: #34C77B; color-scheme: dark; }
/* Отступы под системный интерфейс: Telegram в полноэкранном режиме рисует свои
   кнопки поверх страницы, и контент под ними нужно опустить. contentSafeAreaInset
   отвечает именно за интерфейс Telegram, safeAreaInset — за «чёлку» и статус-бар
   устройства. max() берёт больший из двух: они могут отличаться.
   В обычном браузере оба значения равны 0 — макет остаётся прежним.

   env(safe-area-inset-top) вынесен в --tg-safe-top, а не вписан прямо в max().
   Смысл: у MAX шапка мессенджера нарисована над WebView, окно и так начинается ниже
   неё, но env() в MAX всё равно возвращает ненулевой «статус-бар» — и он добавлял
   сверху пустую полосу, которую нельзя было убрать из JS: env() читает только
   браузер, из скрипта он не меняется. Через переменную её обнуляет applyTgInsets
   в main.js. В Telegram и браузере переменная остаётся равной env() — там отступ
   действительно нужен. */
:root { --tg-safe-top: env(safe-area-inset-top, 0px); --tg-safe-bottom: env(safe-area-inset-bottom, 0px); }
:root { --tg-inset-top: max(var(--tg-safe-top, 0px), var(--tg-content-safe-area-inset-top, 0px), var(--tg-app-top, 0px)); --tg-inset-bottom: max(var(--tg-safe-bottom, 0px), var(--tg-content-safe-area-inset-bottom, 0px), var(--tg-app-bottom, 0px)); }
* { box-sizing: border-box; margin: 0; -webkit-tap-highlight-color: transparent; }
/* Иконки из набора: наследуют цвет текста и не сжимаются во flex-контейнерах.
   inline-block + middle — чтобы значок стоял по центру строки рядом с подписью. */
svg.ico { display: inline-block; vertical-align: middle; flex: none; stroke: currentColor; fill: none; stroke-linecap: round; stroke-linejoin: round; }
body { font: 16px/1.45 "Inter", system-ui, -apple-system, "Segoe UI", sans-serif; background: var(--bg); color: var(--fg); padding-bottom: calc(96px + var(--tg-inset-bottom)); letter-spacing: -0.005em; }
/* Пока открыто модальное окно, страница под ним не скроллится. body уходит в position:fixed
   с поднятым top (его ставит lockScroll), иначе на iOS скролл всё равно продолжается.
   width:100% обязателен — без него fixed-элемент схлопывается по горизонтали. */
body.scroll-locked { position: fixed; width: 100%; overflow: hidden; }
/* padding-top вместо фиксированного: кнопки Telegram могут быть любой высоты,
   а отступ сверху нужен на всех экранах, а не только на каталоге. */
/* Боковые поля 12px, а не 16px: на 320–390 px каждый пиксель уходит контенту —
   плитки КБЖУ и кнопка «Добавить» умещаются в строку без переноса. */
main { max-width: 640px; margin: 0 auto; padding: calc(12px + var(--tg-inset-top)) 16px 12px; }
h2 { font-size: 28px; font-weight: 800; letter-spacing: -0.02em; margin: 4px 0 12px; }
/* select здесь обязателен вместе с input и textarea. Раньше он в списке не стоял
   и не наследовал --fg, а рисовался системными цветами WebView: в тёмном режиме
   текст в списках получался белым, и на светлой теме «Район доставки» и «Время
   доставки» становились нечитаемыми. У полей формы фон свой (--bg), а не
   системный, поэтому белый текст на нём и не читался. */
button, input, textarea, select { font: inherit; color: inherit; }
/* Список вариантов открывается поверх страницы системным окном, где --bg может не
   совпасть с подложкой. Красим и его — иначе в выпавшем списке текст пропадёт. */
select option { background: var(--surface); color: var(--fg); }
button { border: 0; background: none; cursor: pointer; }
button:focus-visible, input:focus-visible, textarea:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Отступ сверху 2px: над рубриками стоит карусель баннеров, и раньше между ними
   набиралось 8px пустоты — блок выглядел разорванным. Класс используется только в каталоге. */
/* Рубрики: обычная горизонтальная лента, которая прокручивается вместе с меню.
   Раньше здесь стоял position: sticky, и в полноэкранном режиме Telegram лента
   либо уезжала вместе с контентом (sticky не работает — Telegram скроллит не
   окно, а свой контейнер), либо прилипала и перекрывала товары. Оба варианта
   раздражали, поэтому липкости здесь нет: строка ведёт себя как любой блок. */
.chips { display: flex; gap: 20px; overflow-x: auto; padding: 4px 2px 10px; scrollbar-width: none; border-bottom: 1px solid var(--edge); margin-bottom: 14px; }
.chip { padding: 8px 2px; border-radius: 0; background: none; white-space: nowrap; color: var(--hint); font-size: 15px; font-weight: 600; border-bottom: 2px solid transparent; margin-bottom: -11px; }
.chip.on { background: none; color: var(--fg); border-color: transparent; border-bottom: 2px solid var(--accent); border-radius: 0; }
/* Рубрика ведёт на страницу категории: стрелка и подложка делают переход очевидным */
.chev { font-style: normal; margin-left: 4px; opacity: .55; font-size: 15px; line-height: 1; }
.cat-chip { display: flex; align-items: center; font-weight: 600; border: 1px solid var(--edge); }
.cat-chip:active { background: var(--card); }
.addr-chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.addr-chips .chip { background: var(--bg); padding: 6px 12px; font-size: 14px; }

.items { list-style: none; padding: 0 14px; background: var(--surface); border-radius: 20px; }
/* Карусель: карточки категории прокручиваются в одну строку по горизонтали */
.catalog-items { display: flex; gap: 10px; padding: 2px 0 6px; background: transparent; border-radius: 0; overflow-x: auto; scroll-snap-type: x proximity; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
.catalog-items::-webkit-scrollbar { display: none; }
.item { display: flex; gap: 12px; align-items: center; padding: 12px 0; border-bottom: 1px solid var(--bg); }
.item:last-child { border-bottom: 0; }
.pic { font-size: 36px; width: 64px; height: 64px; display: grid; place-items: center; background: var(--card); border-radius: 16px; flex: none; }
.info { flex: 1; min-width: 0; }
.info p { font-size: 13px; color: var(--hint); margin: 2px 0 4px; }
.price { font-weight: 600; }
.add, .primary { background: var(--accent); color: var(--on-accent); }
.add { padding: 8px 14px; border-radius: 12px; }
.step { display: flex; align-items: center; background: var(--card); border-radius: 12px; }
.step button { width: 36px; height: 36px; font-size: 20px; }
.step span { min-width: 22px; text-align: center; font-weight: 600; }

.tabs { position: fixed; left: 16px; right: 16px; bottom: calc(12px + var(--tg-inset-bottom)); max-width: 612px; margin: 0 auto; display: flex; gap: 4px; padding: 8px; background: var(--surface); border: 1px solid var(--edge); border-radius: 24px; box-shadow: 0 8px 28px rgba(36, 35, 33, .12); z-index: 5; }
.tabs button { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 3px; padding: 8px 0 6px; border-radius: 16px; font-size: 12px; font-weight: 600; color: var(--hint); min-height: 52px; transition: color .14s ease; }
.tabs button.on { background: none; color: var(--accent); font-weight: 700; }
.ic { position: relative; font-size: 22px; line-height: 1.1; display: inline-flex; align-items: center; justify-content: center; }
#badge { position: absolute; top: -4px; right: -10px; min-width: 17px; height: 17px; padding: 0 4px; border-radius: 9px; font: 700 11px/17px system-ui, -apple-system, sans-serif; font-style: normal; text-align: center; background: var(--accent); color: #fff; box-shadow: 0 0 0 2px var(--surface); box-sizing: border-box; }

.box { background: var(--surface); border: 1px solid var(--edge); border-radius: 16px; padding: 12px 14px; margin: 8px 0; box-shadow: 0 1px 3px rgba(20, 30, 60, .05); }
.row { display: flex; justify-content: space-between; gap: 8px; padding: 3px 0; }
.row.total { font-weight: 700; font-size: 18px; padding-top: 8px; }
/* Итоговая сумма — единственный красный ценник в корзине: построчные суммы
   (.line-sum) остаются цветом текста, иначе красным было бы всё и акцент
   на итоге терялся бы. Жирность 800 против 700 строки — сумма ещё и весом. */
.row.total span:last-child { color: var(--accent); font-weight: 800; }
.hint { color: var(--hint); font-size: 14px; }
.field { display: block; margin: 8px 0; }
.field span { display: block; font-size: 12.5px; color: var(--hint); margin-bottom: 3px; }
.field input, .field textarea { width: 100%; padding: 9px 11px; border: 1px solid transparent; border-radius: 10px; background: var(--bg); font-size: 14.5px; }
/* Комментарий к заказу не растягивается мышью: на телефоне поле и так растёт под текст. */
.field textarea { resize: none; overflow: hidden; }
.check { display: flex; gap: 8px; align-items: center; margin: 8px 0 4px; }
.pay { display: flex; gap: 8px; }
.pay label { position: relative; display: flex; align-items: center; gap: 10px; text-align: left; padding: 10px 44px 10px 10px; border-radius: 12px; background: var(--bg); cursor: pointer; font-size: 14px; }
.pay input { display: none; }
.pay input:checked + label { background: var(--accent); color: var(--on-accent); }
/* Строки способов оплаты как в макете: иконка слева, кружок-чек справа у
   выбранного. Разметку payHtml не меняем — чек рисует ::after поверх label,
   иконку кладёт .pay-ico из существующего набора. */
.pay-ico { flex: none; width: 36px; height: 36px; display: grid; place-items: center; border-radius: 12px; background: color-mix(in srgb, var(--accent) 12%, transparent); color: var(--accent); }
.pay input:checked + label .pay-ico { background: color-mix(in srgb, var(--on-accent) 22%, transparent); color: var(--on-accent); }
.pay input:checked + label::after { content: '✓'; position: absolute; right: 10px; top: 50%; transform: translateY(-50%); width: 22px; height: 22px; border-radius: 50%; background: var(--surface); color: var(--accent); font-size: 14px; font-weight: 800; line-height: 22px; text-align: center; }
/* Способы оплаты — столбиком во всю ширину (как в макете), а не пилюлями в ряд:
   с иконкой и чеком строка стала широкой и в ряд не влезает. Скоуп #f — .pay
   живёт только в форме оформления. */
#f .pay { flex-direction: column; }
#f .pay label { flex: none; width: 100%; }
/* Строка адреса на шаге 2: пин, адрес/«Самовывоз», стрелка. Тап уводит на шаг 1
   к полю адреса — та же карточка-строка, что суммарий. */
/* Оформление: чек внутри формы перед кнопкой — итог виден у подтверждения. */
#f #sum { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--edge); }
#f #giftItems { margin-top: 12px; }
.ck-addr { display: flex; align-items: center; gap: 10px; width: 100%; padding: 12px 14px; margin-bottom: 10px; border-radius: 14px; background: var(--bg); font-size: 15px; font-weight: 600; text-align: left; }
.ck-addr .chev { margin-left: auto; }
.primary { width: 100%; padding: 14px; border-radius: 14px; font-weight: 600; margin-top: 8px; }
.primary:disabled { opacity: .5; }
.ghost { width: 100%; padding: 13px; border-radius: 14px; background: var(--surface); margin-top: 8px; }
.danger { color: var(--danger); }
.empty { text-align: center; color: var(--hint); padding: 40px 0; }
.back { display: inline-flex; align-items: center; gap: 4px; color: var(--accent); padding: 4px 0 8px; font-weight: 500; }

.steps { display: flex; gap: 4px; margin: 12px 0; }
.steps i { flex: 1; height: 6px; border-radius: 3px; background: var(--card); }
.steps i.done { background: var(--accent); }
/* Ошибка поля (пустой телефон): красная рамка вместо тоста в одиночку —
   тост исчезает, рамка остаётся пока не исправят. */
.field.err input, .field.err textarea, .field.err select { border-color: var(--danger); }
/* Карточка заказа в списке. Три самостоятельные строки вместо общего .row:
   раньше всё шло единой лентой влево, и правый нижний угол оставался пустым. */
.o-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
/* Статус не должен сжиматься и переноситься — иначе он ломает строку заголовка. */
.o-head .badge-status { flex: none; }
/* Состав — главное, ради чего заказ и открывают, поэтому он темнее и крупнее
   подсказки. Много позиций обрезаем многоточием: карточка не должна расти. */
.o-items { margin: 8px 0 0; font-size: 15px; color: var(--fg); opacity: .82; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.o-foot { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-top: 10px; }
.o-date { font-size: 13px; color: var(--hint); }
/* Сумма — крупная и акцентная: это второй по важности элемент после состава. */
.o-sum { font-size: 18px; color: var(--accent); white-space: nowrap; }

/* Статусы: серый тег читался как неактивная кнопка. Цвет несёт смысл —
   заказ в работе, заказ успешно завершён, заказ отменён. Оттенки взяты через
   color-mix от --accent, --ok и --danger, поэтому следуют за темой оформления. */
.badge-status { display: inline-block; padding: 3px 10px; border-radius: 10px; font-size: 13px; font-weight: 600; }
/* Принят и Подтверждён — работа идёт, заказ ещё можно ждать: синий. */
.badge-status.new { background: color-mix(in srgb, var(--accent) 14%, var(--surface)); color: color-mix(in srgb, var(--accent) 78%, var(--fg)); }
.badge-status.confirmed { background: color-mix(in srgb, var(--accent) 14%, var(--surface)); color: color-mix(in srgb, var(--accent) 78%, var(--fg)); }
/* В пути — курьер везёт, заказ ещё в работе, поэтому остаётся синим:
   зелёный здесь означал бы, что всё уже закончилось. */
.badge-status.delivering { background: color-mix(in srgb, var(--accent) 22%, var(--surface)); color: color-mix(in srgb, var(--accent) 92%, var(--fg)); }
/* Готов и Доставлен — успешный исход, зелёный. */
.badge-status.ready,
.badge-status.delivered { background: color-mix(in srgb, var(--ok) 16%, var(--surface)); color: color-mix(in srgb, var(--ok) 88%, var(--fg)); }
/* Отмена — единственный статус, где нужен красный: о нём человек должен узнать сразу. */
.badge-status.cancelled { background: color-mix(in srgb, var(--danger) 16%, var(--surface)); color: var(--danger); }
.order-link { display: block; width: 100%; text-align: left; }

.who { display: flex; gap: 14px; align-items: center; }
.avatar { width: 56px; height: 56px; border-radius: 50%; background: var(--accent); color: var(--on-accent); display: grid; place-items: center; font-size: 24px; font-weight: 700; flex: none; }
.menu { padding: 0; overflow: hidden; }
.mi { display: flex; align-items: center; gap: 12px; width: 100%; padding: 15px 16px; text-align: left; border-bottom: 1px solid var(--bg); }
.mi:last-child { border-bottom: 0; }
.mi em { margin-left: auto; color: var(--hint); font-style: normal; font-size: 20px; }
.addr { display: flex; justify-content: space-between; gap: 8px; padding: 8px 0; border-bottom: 1px solid var(--bg); }
.addr:last-child { border-bottom: 0; }
.acts { display: flex; flex: none; }
.acts button { padding: 6px; font-size: 18px; }
.seg { display: flex; gap: 4px; margin-top: 10px; padding: 3px; background: var(--card); border-radius: 14px; }
.seg button { flex: 1; padding: 8px; border-radius: 11px; }
.seg .on { background: var(--accent); color: var(--on-accent); }
.sw { display: flex; gap: 14px; margin-top: 12px; }
.sw button { width: 38px; height: 38px; border-radius: 50%; }
.sw .on { outline: 2px solid var(--fg); outline-offset: 3px; }
.howto { padding-left: 18px; margin-top: 10px; font-size: 14px; }
.howto li { margin: 8px 0; }

#toast { position: fixed; left: 50%; bottom: calc(96px + var(--tg-inset-bottom)); transform: translateX(-50%) translateY(20px); background: var(--fg); color: var(--bg); padding: 10px 16px; border-radius: 12px; opacity: 0; pointer-events: none; transition: .25s; max-width: 90%; text-align: center; z-index: 6; }
#toast.show { opacity: 1; transform: translateX(-50%); }
@media (prefers-reduced-motion: reduce) { #toast { transition: none; } }

[hidden] { display: none !important; }
.pic { overflow: hidden; }
.pic img { width: 100%; height: 100%; object-fit: cover; }
.field select { width: 100%; padding: 9px 11px; border: 1px solid transparent; border-radius: 10px; background: var(--bg); margin-top: 6px; font-size: 14.5px; }
.field > span + select { margin-top: 0; }
.pay { flex-wrap: wrap; }
.pay label { flex: 1 1 30%; }
.cart-promo-box { padding: 14px 16px; border: 1px solid var(--edge); }
.promo-row { display: flex; align-items: stretch; gap: 8px; }
.promo-row input { flex: 1; min-width: 0; height: 46px; padding: 0 14px; border: 1.5px solid var(--edge); border-radius: 14px; background: var(--bg); color: var(--fg); font-size: 15px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; transition: border-color .15s ease; }
.promo-row input:focus { outline: none; border-color: var(--accent); }
.promo-row input::placeholder { text-transform: none; font-weight: 400; letter-spacing: normal; color: var(--hint); }
.promo-row .chip, .promo-btn { flex: none; height: 46px; padding: 0 18px; margin: 0; border: 0; border-radius: 14px; background: var(--accent); color: var(--on-accent); font-size: 14px; font-weight: 700; display: inline-flex; align-items: center; justify-content: center; cursor: pointer; transition: filter .12s, transform .12s; }
.promo-row .chip:active, .promo-btn:active { filter: brightness(.92); transform: scale(.98); }
#cartPromoMsg { margin: 8px 2px 0; font-size: 13px; line-height: 1.35; }
#cartPromoMsg:empty { display: none; }
.luck-box { text-align: center; overflow: hidden; position: relative; border: 2px dashed color-mix(in srgb, var(--accent) 45%, transparent); }
.luck-box h3 { margin: 0 0 12px; }
.luck-help { position: absolute; top: 10px; right: 10px; width: 30px; height: 30px; border-radius: 50%; font-weight: 700; color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent); }
.luck-list-pop { position: absolute; top: 46px; right: 10px; left: 10px; z-index: 4; padding: 12px 16px; text-align: left; background: var(--surface); border-radius: 14px; box-shadow: 0 8px 26px rgba(120, 70, 30, .25); }
.luck-list-pop b { display: block; margin-bottom: 6px; }
.luck-list-pop ul { margin: 0; padding-left: 18px; color: var(--hint); font-size: 13px; line-height: 1.6; }
/* Большое тёплое колесо: 300px вместо 250 — приз видно издалека, секторов
   обычно 4–6 и места хватает всем. Арифметика радиусов та же, что и была
   (--r-out/--r-in), поэтому подписи из wheelDisk ложатся как раньше. */
.luck-wheel { --wheel-size: min(300px, 78vw); --r-out: calc(var(--wheel-size) / 2 - 18px); --r-in: calc(var(--wheel-size) / 2 * 0.30); width: var(--wheel-size); aspect-ratio: 1; position: relative; margin: 0 auto 14px; }
/* Пунктирное кольцо крутится вместе с диском (оно круглое, видно только пунктир)
   + тёплое свечение акцента вместо холодной тени. */
.luck-wheel-disk { position: absolute; inset: 10px; border: 6px solid var(--surface); border-radius: 50%; outline: 3px dashed color-mix(in srgb, var(--accent) 55%, transparent); outline-offset: 5px; box-shadow: 0 8px 32px rgba(224, 49, 43, .22), 0 4px 18px #0002; }
.luck-wheel-disk.spin { animation: luck-spin var(--wheel-duration, 4600ms) cubic-bezier(.12,.72,.08,1) both; }
/* Названия секторов: каждая подпись лежит вдоль своего радиуса — текст идёт к центру/от центра, не переворачиваясь */
.luck-seg { position: absolute; left: 50%; top: 50%; width: calc(var(--r-out) - var(--r-in) - 6px); transform-origin: 0 0; font-style: normal; font-weight: 600; line-height: 1.1; color: #fff; text-align: right; text-shadow: 0 1px 2px rgba(0, 0, 0, .55); overflow: hidden; }
/* Название приза — одной строкой вдоль радиуса, обрезается многоточием; модификаторы — отдельной строкой мельче */
.luck-seg b { display: block; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.luck-seg span { display: block; font-size: .78em; font-weight: 500; white-space: normal; overflow-wrap: anywhere; }
/* Левая половина: якорь у края, текст идёт к центру — выравниваем по краю, чтобы подписи смотрелись одинаково */
.luck-seg.flip { text-align: left; }
.luck-wheel-hub { position: absolute; inset: 50% auto auto 50%; width: 48px; aspect-ratio: 1; display: grid; place-items: center; font-size: 24px; transform: translate(-50%, -50%); border-radius: 50%; background: var(--surface); border: 3px solid var(--accent); box-shadow: 0 2px 8px #0003; }
.luck-wheel-pointer { position: absolute; z-index: 1; top: -6px; left: 50%; transform: translateX(-50%); border: 14px solid transparent; border-top: 28px solid var(--accent); border-bottom: 0; filter: drop-shadow(0 2px 2px rgba(0, 0, 0, .25)); }
/* Выигрыш — акцентом и крупнее: это главная строка блока после остановки. */
.luck-win { font-weight: 800; font-size: 18px; color: var(--accent); }
/* Кнопка копирования промокода — сплошной акцент: единственное действие в блоке. */
.luck-cast .chip { background: var(--accent); color: var(--on-accent); }
/* Выигрыш появляется только после остановки колеса: скрыт, пока идёт вращение, затем проявляется. */
.luck-cast-wait { opacity: 0; animation: luck-reveal .4s ease var(--wheel-duration, 4600ms) both; }
@keyframes luck-spin { to { transform: rotate(var(--wheel-turn)); } }
@keyframes luck-reveal { from { opacity: 0; } to { opacity: 1; } }
.ok { color: #1f9d63; font-size: 14px; }
.err { color: var(--danger); font-size: 14px; }

/* Избранное, секции каталога, оплата, отмена по таймеру, вход по телефону */
.item { position: relative; }
.fav { font-size: 20px; color: var(--hint); flex: none; padding: 4px; }
.fav.on { color: var(--fav); }
/* Между категориями только отступ — разделяющая полоса убрана по просьбе */
.catalog-section + .catalog-section { margin-top: 30px; }
/* Заголовок категории без синей плашки: на плашке терялась разница между названием
   и кнопкой «Все». Акцент перенесён на полоску слева и на саму кнопку. */
.category-heading { display: flex; align-items: center; gap: 10px; margin: 0 0 14px; padding: 2px 0; }
/* Кнопка «Все» открывает страницу категории — она должна выглядеть как ссылка, а не как текст */
.cat-all { margin-left: auto; flex: none; display: flex; align-items: center; padding: 6px 12px; border: 1px solid var(--edge); border-radius: 20px; background: var(--card); color: var(--accent); font-size: 13px; font-weight: 600; }
.cat-all:active { background: color-mix(in srgb, var(--accent) 16%, var(--card)); }
/* На тёмной подложке (--card) акцентный текст читается плохо — в тёмной теме делаем белым */
:root[data-theme="dark"] .cat-all { color: #fff; }
.cat-all .chev { opacity: .9; }
.category-heading::before { content: ''; width: 4px; height: 22px; flex: none; border-radius: 2px; background: var(--accent); }

.sec-title { font-size: 20px; line-height: 1.25; color: var(--fg); font-weight: 700; margin: 0; }
.time-row { display: flex; gap: 8px; margin-top: 8px; }
.time-row select { flex: 1; padding: 10px; border-radius: 10px; border: 1px solid transparent; background: var(--bg); }
.copy-row { display: flex; justify-content: space-between; align-items: center; gap: 8px; padding: 6px 0; font-weight: 600; }
.copy-row .chip { background: var(--bg); }
/* Реквизиты перевода: номер стоит над кнопкой во всю ширину. Раньше он делил
   строку с кнопкой «Скопировать номер», и длинный номер переносился посередине —
   его было не разобрать, куда вводить. Нужен и моноширинный шрифт: в нём все
   цифры одной ширины, поэтому переноса внутри номера не происходит вовсе. */
.pay-number { padding: 12px 0 10px; text-align: center; }
.pay-phone { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 20px; font-weight: 700; letter-spacing: .5px; word-break: keep-all; }
/* Миниатюра позиции в корзине и в заказе. Без фото показываем эмодзи товара,
   поэтому строка заказа никогда не остаётся «пустой» слева от названия. */
.mini { flex: none; width: 56px; height: 56px; display: grid; place-items: center; overflow: hidden; border-radius: 12px; background: var(--card); font-size: 28px; line-height: 1; }
.mini img { width: 100%; height: 100%; object-fit: cover; }
.mini i { font-style: normal; }
/* Сборная пицца: одна миниатюра, разрезанная пополам. Обе половины накладываются
   на один квадрат, и каждая обрезается по своей стороне — размер получается ровно
   как у обычной позиции, и текст в строке больше не сжимается.
   Правило используется и в корзине, и в заказе: разница только в размере, который
   приходит из .cart-line .mini (72px) либо из базового .mini (56px). */
.mini.dual { position: relative; background: var(--card); }
.mini.dual img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.mini.dual .dual-l { clip-path: inset(0 50% 0 0); }
.mini.dual .dual-r { clip-path: inset(0 0 0 50%); }
/* Тонкий шов между половинами: без него снимки сливаются в один, и не видно,
   что пицца сборная из двух разных. */
.mini.dual::after { content: ''; position: absolute; top: 0; bottom: 0; left: 50%; width: 1px; background: var(--surface); }
/* Название и модификаторы занимают всю оставшуюся ширину строки позиции.
   flex: 1 здесь не нужен: он забирал всё свободное место, и сумма вставала
   сразу после текста вместо правого края — space-between не мог сработать.
   Теперь текст только сжимается при нехватке места, а сумму прижимает
   .o-sum. min-width: 0 обязателен, иначе длинное название распирает строку. */
.o-text { min-width: 0; }
/* Сумма позиции: всегда у правого края строки, своей колонкой. */
.o-sum { margin-left: auto; text-align: right; white-space: nowrap; }
.o-item { align-items: flex-start; }

.order-actions { display: flex; flex-direction: column; gap: 8px; margin: 12px 0; }
.badge-status.paid { background: color-mix(in srgb, #1f9d63 16%, var(--card)); color: #1f9d63; margin-left: 6px; }

/* Детали заказа: строки «значок · подпись · значение». Подпись и значение на разных строках,
   иначе на телефоне «Адрес доставки» и сам адрес сливаются в одну нечитаемую строку. */
.order-card h3 { font-size: 15px; font-weight: 700; margin: 0 0 4px; }
.order-card .order-row { display: flex; gap: 12px; align-items: flex-start; padding: 10px 0; border-bottom: 1px solid var(--bg); }
.order-card .order-row:last-of-type { border-bottom: 0; }
.order-card .ico { flex: none; width: 30px; height: 30px; display: grid; place-items: center; font-size: 16px; background: var(--card); border-radius: 10px; }
.order-card .order-fields { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
/* Подпись мелкая и серая: главное в строке — значение, а не заголовок пункта. */
.order-card .order-label { font-size: 12px; color: var(--hint); text-transform: uppercase; letter-spacing: .03em; }
.order-card .order-value { font-size: 15px; overflow-wrap: anywhere; }
.order-card .order-sub { font-size: 13px; color: var(--hint); }
.order-card .dim { color: var(--hint); }
/* Телефон получателя кликабельный: в заказ часто звонят и курьеру. */
.order-card .tel { color: var(--accent); text-decoration: none; font-weight: 600; }
.order-card .detail-help { margin: 10px 0 0; padding-top: 10px; border-top: 1px solid var(--bg); }

/* Подтверждение без window.confirm(), комментарий к блюду в корзине */
.confirm-overlay { position: fixed; inset: 0; background: rgba(10,14,26,.45); display: flex; align-items: center; justify-content: center; z-index: 50; padding: 20px; }
.confirm-box { background: var(--surface); border-radius: 16px; padding: 18px; max-width: 320px; width: 100%; }
.confirm-box p { margin-bottom: 14px; }
.confirm-acts { display: flex; gap: 8px; }
.confirm-acts button { flex: 1; padding: 11px; border-radius: 12px; background: var(--card); }
/* .primary глобально задаёт margin-top и ширину 100% — внутри диалога это сдвигает
   кнопку «Да» вниз на 8px, и кнопки выглядят разной высоты. Сбрасываем оба свойства. */
.confirm-acts .primary { margin-top: 0; width: auto; padding: 11px; background: var(--accent); color: var(--on-accent); }

/* Карточка товара: общая для карусели меню и сетки страницы категории. Раскладку задаёт контейнер. */
.pcard { position: relative; display: flex; flex-direction: column; align-items: stretch; gap: 6px; padding: 8px; background: var(--surface); border: 1px solid var(--bg); border-radius: 18px; box-shadow: 0 6px 20px rgba(120, 70, 30, .10); }
/* .item:last-child обнуляет border-bottom — правило нужно для строк списка, где
   разделитель между позициями. У карточки рамка со всех сторон, иначе последняя
   карточка карусели и сетки осталась бы снизу без границы. Специфичность
   .item:last-child (0,2,0) выше, чем у .pcard, поэтому дублируем border-bottom
   здесь — правило ниже по файлу и при равной специфичности выигрывает. */
.pcard:last-child { border-bottom: 1px solid var(--bg); }
.catalog-items li.item { flex: 0 0 168px; scroll-snap-align: start; }
/* Страница категории: две равные колонки на всю ширину экрана. В трёх колонках
   плитка была 110 px и цена с кнопкой «+» не помещалась в одну строку —
   символ рубля уезжал вниз. В двух колонках карточка просторнее, а снимок
   и название от ширины ничего не теряют.
   Зазор 8px, а не 10: лишний пиксель уходит контенту плитки. */
.cat-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; padding: 8px; }
/* Ниже 360px остаются те же две колонки: правило для симметрии с базовым,
   чтобы узкий экран гарантированно не получил три. */
@media (max-width: 359px) { .cat-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* Ужимание плитки. На 390 px на карточку остаётся ~179 px: цена с кнопкой «+»
   в одну строку помещаются свободно. Перенос цены запрещён ниже — вместе
   кнопка и цена как раз укладываются. */
.cat-grid .pcard { padding: 8px; }
.cat-grid .pcard .price { font-size: 14px; white-space: nowrap; }
.cat-grid .pcard .card-foot { gap: 8px; }
.cat-grid .pcard .add-plus { width: 34px; height: 34px; border-radius: 12px; font-size: 17px; }
.cat-grid .pcard .step button { width: 32px; height: 34px; font-size: 18px; }
/* Бейдж оценки и сердце чуть меньше, чем в карусели каталога: поверх снимка
   они не должны спорить с блюдом. Плитка теперь просторная (~179 px), поэтому
   ужимание минимальное. */
.cat-grid .pcard .rate-badge { top: 6px; left: 6px; padding: 2px 6px; font-size: 10px; border-radius: 7px; }
.cat-grid .pcard .rate-badge b { font-size: 9px; }
.cat-grid .pcard .fav { top: 6px; right: 6px; padding: 3px; }
.cat-grid .pcard .fav svg { width: 13px; height: 13px; }
/* position: relative обязателен: значок «Нет в наличии» позиционируется от .pic, а не от карточки */
/* 3 / 2 — пропорции самих снимков (1417×932). Меньше обрезки не будет, больше — теряем
   пиццу по краям, поэтому рамку держим ровно по исходнику. */
.pcard .pic { position: relative; width: 100%; height: auto; aspect-ratio: 3 / 2; border-radius: 10px; font-size: 30px; }
/* Название переносится, а не обрезается многоточием: обрезанное блюдо не узнать.
   Ограничение в 2 строки (line-clamp) удерживает карточку от роста на длинных
   названиях — иначе она задавала бы высоту всей строке карусели.
   overflow-wrap: anywhere нужен для слитных слов и названий вроде «40см». */
.pcard .name { font-size: 14px; line-height: 1.25; overflow-wrap: anywhere; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; }
.pcard .card-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: auto; }
.pcard .price { font-size: 14px; font-weight: 600; }
/* Карточка с описанием открывает состав по тапу: курсор и реакция на нажатие.
   Вложенные кнопки (.fav, .add-plus, .step) остаются интерактивными — они перехватывают тап раньше. */
.pcard.has-info { cursor: pointer; }
.pcard.has-info:active { background: var(--card); }
/* Знак «+» рисуется иконкой icon('add'), а не символом шрифта: у глифа «+» высота
   строки задана базовой линией, поэтому в квадратной кнопке он заметно уезжал
   вверх, а по горизонтали плавал вместе с шириной глифа. Иконка рисуется в
   viewBox с центром 12,12, и сетка place-items ставит её точно по центру по
   обеим осям. Обводка идёт через currentColor, поэтому приглушённый вид товара
   из стоп-листа сохраняется. */
.pcard .add-plus { flex: none; width: 34px; height: 34px; display: grid; place-items: center; border-radius: 12px; background: var(--accent); color: var(--on-accent); line-height: 1; }
/* Конструктор пиццы из двух половинок */
/* Высота шага с половинами фиксирована: при выборе пиццы список сменяется крупной
   карточкой, и без этого окно то подрастает, то садится — а переход должен быть
   спокойным, а не прыгать. Размер от вьюпорта, чтобы одинаково было на всех телефонах.
   Колонка скроллится на случай добавок: шапка не уезжает, низ прокручивается. */
.bld-box { display: flex; flex-direction: column; height: min(78vh, 660px); overflow: hidden; }
.bld-col { overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }
/* Шаг выбора размера: кнопки в ряд. Их всего две-три, поэтому в столбик окно
   занимало целиком и выбор размера выглядел отдельной страницей. В ряд шаг
   занимает одну строку и остаётся компактным перед длинным списком половин. */
.bld-sizes { display: flex; gap: 8px; }
.bld-size { flex: 1; display: flex; align-items: center; justify-content: center; padding: 14px; border-radius: 14px; background: var(--bg); font-size: 17px; }
.bld-size:active { background: color-mix(in srgb, var(--accent) 12%, var(--bg)); }
/* Две колонки прокручиваются независимо: список длинный, и общая прокрутка
   уводила бы список второй половины при выборе первой. */
.bld-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; flex: 1; min-height: 0; }
.bld-col { display: flex; flex-direction: column; min-height: 0; }
.bld-coltitle { font-size: 13px; font-weight: 600; color: var(--hint); margin-bottom: 6px; text-align: center; }
.bld-list { flex: 1; min-height: 120px; overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }
.bld-empty { color: var(--hint); font-size: 14px; text-align: center; padding: 20px 8px; }
/* Карточка половины. Кнопка на всю карточку: попадать пальцем по товару удобнее,
   чем по узкой кнопке, а ⓘ вынесен рядом, чтобы не перехватывал тап. */
.bld-card { position: relative; border: 2px solid transparent; border-radius: 14px; background: var(--bg); margin-bottom: 8px; padding: 4px; }
.bld-card.on { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, var(--bg)); }
.bld-pick { width: 100%; display: flex; flex-direction: column; gap: 2px; padding: 6px; border-radius: 10px; text-align: left; }
/* 3 / 2 — те же пропорции, что и у .pcard .pic, чтобы карточка в списке половин
   совпадала по высоте с карточкой в каталоге. */
.bld-pic { width: 100%; aspect-ratio: 3 / 2; border-radius: 10px; overflow: hidden; background: var(--surface); font-size: 28px; display: grid; place-items: center; }
.bld-pic img { width: 100%; height: 100%; object-fit: cover; }
.bld-name { font-size: 13px; line-height: 1.2; }
.bld-price { font-size: 13px; font-weight: 600; }
.bld-info { position: absolute; top: 10px; right: 10px; width: 26px; height: 26px; display: grid; place-items: center; border-radius: 50%; background: rgba(255, 255, 255, .92); color: var(--hint); font-size: 14px; line-height: 1; box-shadow: 0 1px 4px rgba(15, 23, 42, .18); }
/* Размер и добавки — мелкими кнопками под карточкой выбранной половины. */
.bld-opts { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 4px; padding: 0 4px 4px; }
.bld-opt { display: flex; align-items: center; gap: 5px; padding: 6px 9px; border-radius: 9px; background: var(--surface); font-size: 12px; }
.bld-opt.on { background: var(--accent); color: var(--on-accent); }
.bld-opt .delta { opacity: .7; font-weight: 400; }
/* Выбранная половина занимает всю колонку: список на её месте закрылся.
   Картинка показывает ту же половину снимка, что и миниатюра в корзине —
   левая колонка левую, правая правую, поэтому рядом они дают целую пиццу.
   Обрезка ровно та же (clip-path), иначе получились бы две одинаковые картинки. */
/* Когда выбраны обе половины, картинки смыкаются: между колонками не остаётся
   зазора, а карточка теряет рамку и внутренние отступы. Иначе между половинами
   появляется пустое поле шириной с отступы и рамку — пицца разваливается на две. */
/* Когда выбраны обе половины, зазор сокращаем, но не убираем совсем: подложки
   должны читаться как два блока, а при нуле скруглённые внешние углы сливались бы
   в сплошную полосу. 4px — плотно, но стык половины остаётся видимым. */
.bld-cols.joined { gap: 4px; }
/* Селектор с .bld-card.on: без него правило выбора перебивало бы сброс рамки —
   у .bld-card.on специфичность выше, чем у одиночного класса, и рамка оставалась.
   Фон оставляем: с прозрачным карточка выглядит прорехой в диалоге. А вот боковые
   отступы и рамку убираем — из-за них половины снова разъезжаются. Поэтому текст,
   добавки и кнопка возврата получают отступы сами, см. ниже. */
/* Фон блока — как у обычных карточек списка (--bg), а НЕ как у выбранной карточки.
   Зеленоватый оттенок был у .bld-card.on, но он означает «нажато», и в блоке это
   сбивает с толку: половина занимает всю колонку и выглядит подсвеченной. Обычная
   подложка списка — то, что и читается как карточка товара. Скругление снимается
   только с внутренней стороны — той, что смотрит на вторую половину. */
.bld-card.on.bld-chosen { margin-bottom: 0; padding: 0 0 10px; border: 0; background: var(--bg); }
.bld-chosen.side-l { border-radius: 14px 0 0 14px; }
.bld-chosen.side-r { border-radius: 0 14px 14px 0; }
.bld-chosen.side-l .bld-hero { border-radius: 14px 0 0 14px; }
.bld-chosen.side-r .bld-hero { border-radius: 0 14px 14px 0; }
/* Половина пиццы занимает полную ширину колонки, но вдвое выше неё: два блока
   рядом складываются в квадратную целую пиццу, и каждая половина остаётся
   непрокрученной по пропорциям. Обрезка штатная для object-fit, поэтому снимок
   не растягивается — clip-path тут рвал бы геометрию. */
.bld-hero { position: relative; display: block; width: 100%; aspect-ratio: 1 / 2; max-height: min(42vh, 340px); overflow: hidden; border-radius: 0; background: var(--surface); }
.bld-hero img { position: absolute; top: 0; height: 100%; width: 200%; object-fit: cover; }
/* Снимок растянут ровно вдвое ширины блока и обрезан по своей середине — так разрез
   всегда приходится на середину фотографии, а не «примерно туда». Через
   object-position это не сделать: при фото не квадратного (например 4:3) блок
   1:2 обрезал бы кадр иначе, и половинки пиццы разъезжались бы. Левая колонка
   берёт левую половину, правая — правую, и рядом они дают целую пиццу. */
.bld-hero.dual-l img { left: 0; clip-path: inset(0 50% 0 0); }
.bld-hero.dual-r img { left: -100%; clip-path: inset(0 0 0 50%); }
/* Скругление снято и здесь: у фотографии и подложки должны быть прямые углы,
   иначе на стыке половин остаются маленькие светлые вырезы и пицца распадается. */
/* Без фото половину не разрезать — показываем значок товара, как в списке. */
.bld-hero.plain { display: grid; place-items: center; background: var(--surface); font-size: 34px; }
.bld-hero.plain i { font-style: normal; }
.bld-herotext { display: flex; flex-direction: column; gap: 2px; padding: 8px 10px 0; }
.bld-chosen .bld-name { font-size: 15px; font-weight: 600; }
/* Боковые отступы карточки обнулены, иначе половины разъедутся, — поэтому нижним
   элементам задаём их здесь. Иначе кнопка возврата прижималась бы к краю карточки. */
.bld-chosen .bld-opts { padding: 0 10px 4px; }
.bld-chosen .bld-change { width: auto; margin: 8px 10px 0; }
/* Сердечко в избранное на карточке и на блоке половины. Встаёт рядом со значком ⓘ:
   ⓘ отвечает за состав блюда, сердце — за избранное, спутать их нельзя. Вид тот же,
   что у сердечка на карточках меню, только в кружке — на фото без подложки оно терялось. */
.bld-fav { position: absolute; top: 10px; right: 44px; width: 26px; height: 26px; display: grid; place-items: center; padding: 0; border-radius: 50%; background: rgba(255, 255, 255, .92); color: var(--hint); box-shadow: 0 1px 4px rgba(15, 23, 42, .18); }
.bld-fav svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; display: block; }
.bld-fav:active { color: var(--fav); }
.bld-fav.on { color: var(--fav); }
.bld-fav.on svg { fill: currentColor; }
/* ⓘ на блоке половины: всегда во внешний угол, чтобы не наезжал на стык двух половин.
   У левой половины внешний угол — слева, у правой — справа. Сердце встаёт рядом с ним. */
.bld-chosen.side-l .bld-info { left: 10px; right: auto; }
.bld-chosen.side-l .bld-fav { left: 44px; right: auto; }
/* Возврат списка — заметное действие: без него нельзя поменять выбор, поэтому
   кнопка выделена акцентом. Заливка светлая, а не сплошная: рядом с ней зелёная
   кнопка добавления, и два одинаково ярких действия спорили бы друг с другом. */
.bld-change { display: block; width: 100%; margin-top: 8px; padding: 9px; border-radius: 10px; background: color-mix(in srgb, var(--accent) 12%, transparent); color: var(--accent); font-size: 13px; font-weight: 600; }
.bld-change:active { background: color-mix(in srgb, var(--accent) 22%, transparent); }
.bld-warn { color: var(--danger); font-weight: 400; }
/* Баннеры в начале меню: карусель в одну строку. В столбик два баннера занимали почти
   весь первый экран, а в две колонки картинка была ~160px и надпись не читалась.
   Теперь виден почти весь баннер, а край соседнего подсказывает, что ленту можно
   листать. Имена классов не пересекаются с .promo-row — это строка промокода. */
/* Отступ сверху и снизу: лента не липнет к шапке и отделена от чипов категорий. */
.banners { margin: 2px 0 12px; }
/* Прокручивается трек, а не секция: иначе секция со своими отступами тянула бы
   и первый, и последний баннер от краёв экрана. Скругление и зазор — на треке:
   так каждый баннер отделён от соседа, а лента прокручивается до конца и последний
   баннер встаёт вровень с правым краем контента. Лишнего padding-right здесь нет:
   он не входит в базу flex-basis и сдвинул бы баннеры на его ширину. */
.banners-track { display: flex; gap: 10px; overflow-x: auto; scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch; scrollbar-width: none; overscroll-behavior-x: contain; }
.banners-track::-webkit-scrollbar { display: none; }
/* 86% — следующий баннер выглядывает справа: это и подсказка листать, и признак карусели.
   snap по левому краю, а не по центру: иначе после свайпа баннер вставал по центру
   и слева появлялось пустое поле — лента должна начинаться у края, как весь контент. */
/* aspect-ratio у баннера и object-fit: cover у картинки — заполнение гарантировано
   при любом размере кнопки. Пропорции взяты из самих картинок (1440×810, ровно 16:9),
   поэтому обрезки не будет. */
/* overflow: hidden обязателен: скругление задаёт CSS, а не сама картинка, — иначе
   углы картинки вылезали бы за скруглённую рамку баннера. */
.banner { position: relative; flex: 0 0 86%; scroll-snap-align: start; overflow: hidden; padding: 0; aspect-ratio: 16 / 9; border-radius: 18px; background: none; display: grid; place-items: stretch; box-shadow: 0 6px 20px rgba(120, 70, 30, .10); }
.banner img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Затемняем саму картинку, а не кнопку: у кнопки есть свои фоновые края, и при нажатии
   вокруг картинки появлялась тёмная полоса шире, чем сама картинка. */
.banner:active img { filter: brightness(.9); }
/* Сборная пицца в названии позиции: «Гавайская + Пеперони». Обе половины идут
   одной строкой, размер — отдельной строкой под названием, поэтому отдельная
   разметка для этой позиции не нужна: тот же .hint, что у остальных добавок. */
/* Товар в стоп-листе: виден в меню, но помечен и не добавляется в корзину */
.pcard.stopped { opacity: .72; }
.pcard.stopped .pic { filter: grayscale(1); }
/* Половинка в стоп-листе: видна в списке, но гасится и не выбирается — собирать
   пиццу из закончившегося товара нельзя. Плашка с названием повторяет приём из
   меню, чтобы «нет в наличии» читалось одинаково в обоих списках. */
.bld-card.stopped { opacity: .6; }
.bld-card.stopped .bld-pick { cursor: default; }
.bld-stopbadge { position: absolute; left: 50%; top: 46%; transform: translate(-50%, -50%); background: rgba(20, 24, 33, .82); color: #fff; font-size: 10px; font-weight: 600; padding: 3px 6px; border-radius: 7px; white-space: nowrap; pointer-events: none; }
/* Позиция корзины, товар которой ушёл в стоп-лист. Строка остаётся видимой и
   называет, что закончилось: удалять должен человек, а не приложение молча.
   Красный --danger читается как «с этим нельзя оформить», --ok здесь не подошёл бы:
   зелёный в этой схеме означает удачный исход, а позиция не заказана. */
.cart-line.stopped .mini, .checkout-line.stopped .mini { filter: grayscale(1); opacity: .6; }
.cart-line.stopped .name, .cart-line.stopped b, .checkout-line.stopped b { color: var(--hint); }
.stop-note { color: var(--danger); font-size: 13px; line-height: 1.25; margin-top: 2px; }
.stop-badge { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); background: rgba(20, 24, 33, .82); color: #fff; font-size: 11px; font-weight: 600; padding: 4px 8px; border-radius: 8px; white-space: nowrap; }
/* Товар в стоп-листе: «+» остаётся на месте, но гасится и не нажимается.
   Так карточка не «прыгает» при остановке товара — цена и набор кнопок прежние. */
.pcard .add-plus:disabled { background: var(--card); color: var(--hint); opacity: .6; cursor: default; }
/* Адрес-ссылка на Яндекс Карты: в приложении и в админке */
.addr-link { color: var(--accent); text-decoration: none; border-bottom: 1px dashed currentColor; }
.addr-link:hover { text-decoration: none; border-bottom-style: solid; }
/* Ссылки на ботов в «О приложении»: рядом на телефоне, в столбец на узком */
.bot-links { display: grid; gap: 8px; margin-top: 10px; }
@media (min-width: 460px) { .bot-links { grid-template-columns: 1fr 1fr; } }
/* Блок «Добавить к заказу» в корзине: заголовок и карусель как в меню */
.addon-block { margin-top: 22px; }
.addon-block .category-heading { margin-bottom: 8px; }
.addon-items { padding: 2px 14px 6px; }
/* Кружок под сердечком всегда белый: в тёмной теме --surface тёмный, и подложка
   сливалась с фото товара. */
.pcard .fav { position: absolute; top: 14px; right: 14px; display: grid; place-items: center; padding: 4px; border-radius: 50%; background: var(--surface); color: var(--hint); line-height: 0; box-shadow: 0 1px 4px rgba(15, 23, 42, .18); }
.pcard .fav:active { color: var(--fav); }
.pcard .fav.on { color: var(--fav); }
.pcard .fav svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.pcard .fav.on svg { fill: currentColor; }
.pcard .step { flex: none; }
.pcard .step button { width: 30px; height: 34px; display: grid; place-items: center; line-height: 1; }
.pcard .step span { min-width: 16px; }
/* Позиция в корзине: фото слева, текст и управление по центру, сумма справа.
   Сетка из трёх колонок — сумма всегда на одной высоте с фото, а не «прыгает»,
   когда у позиции появляется комментарий или длинное название. */
/* Корзина: каждая позиция — компактная белая карточка с уменьшенными отступами. */
ul.cart-items { background: none; border: 0; padding: 0; }
.cart-items li.cart-line { position: relative; display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 6px 10px; padding: 8px 30px 8px 10px; margin-bottom: 6px; background: var(--surface); border: 1px solid var(--edge); border-radius: 14px; }
.cart-items li.gift-line { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 8px 10px; padding: 8px 10px; margin-bottom: 6px; background: var(--surface); border: 1px solid var(--edge); border-radius: 14px; }
.line-x { position: absolute; top: 4px; right: 4px; width: 26px; height: 26px; display: grid; place-items: center; border-radius: 50%; color: var(--hint); font-size: 13px; }
.line-x:active { color: var(--danger); background: var(--card); }
/* Пожелание к позиции в корзине: плашка с текстом и форма ввода */
.cart-line-cmt {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  max-width: 100%;
  margin: 3px 0 2px;
}
.cart-line-cmt-badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 8px;
  border-radius: 8px;
  background: color-mix(in srgb, var(--accent) 12%, var(--surface));
  color: var(--fg);
  font-size: 12px;
  line-height: 1.3;
  cursor: pointer;
  max-width: 100%;
  word-break: break-word;
  border: 1px solid color-mix(in srgb, var(--accent) 26%, transparent);
  transition: background .14s, border-color .14s;
}
.cart-line-cmt-badge:hover {
  background: color-mix(in srgb, var(--accent) 18%, var(--surface));
  border-color: color-mix(in srgb, var(--accent) 40%, transparent);
}
.cart-line-cmt-ico {
  color: var(--accent);
  display: inline-flex;
  align-items: center;
  flex: none;
}
.cart-line-cmt-val {
  font-weight: 500;
}
.cart-line-cmt-del {
  width: 20px;
  height: 20px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--card);
  color: var(--hint);
  font-size: 11px;
  border: 0;
  cursor: pointer;
  padding: 0;
  flex: none;
  transition: color .12s, background .12s;
}
.cart-line-cmt-del:hover, .cart-line-cmt-del:active {
  color: var(--danger);
  background: color-mix(in srgb, var(--danger) 15%, transparent);
}
.cart-line-cmt-form {
  grid-column: 1 / -1;
  width: calc(100% + 20px);
  margin-right: -20px;
  padding-top: 8px;
  margin-top: 4px;
  border-top: 1px dashed var(--edge);
}
.cmt-field-wrap {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
}
.cmt-input {
  flex: 1;
  min-width: 0;
  height: 34px;
  padding: 0 10px;
  border-radius: 10px;
  border: 1.5px solid var(--edge);
  background: var(--bg);
  color: var(--fg);
  font-size: 13px;
  outline: none;
  transition: border-color .15s, background .15s, box-shadow .15s;
}
.cmt-input:focus {
  border-color: var(--accent);
  background: var(--surface);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 15%, transparent);
}
.cmt-btn {
  flex: none;
  height: 34px;
  padding: 0;
  border-radius: 10px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  border: 0;
  transition: opacity .12s, transform .1s;
}
.cmt-btn:active {
  transform: scale(0.96);
}
.cmt-btn-save {
  width: 36px;
  background: var(--accent);
  color: #fff;
}
.cmt-btn-save:hover {
  opacity: .9;
}
.cmt-btn-cancel {
  width: 32px;
  background: var(--card);
  color: var(--hint);
  border: 1px solid var(--edge);
}
.cmt-btn-cancel:hover {
  color: var(--fg);
}
.ck-item-cmt {
  margin-top: 2px;
  color: var(--accent);
  font-size: 12px;
  line-height: 1.3;
}
/* ============================================================================
   ОФОРМЛЕНИЕ ЗАКАЗА (CHECKOUT)
   ============================================================================ */

.ck-page-title {
  margin: 2px 0 10px;
  font-size: 22px;
  font-weight: 800;
  letter-spacing: -.02em;
  color: var(--fg);
}

/* Переключатель способа получения (Доставка / Самовывоз) */
.ck-mode-tabs {
  display: flex;
  gap: 6px;
  padding: 3px;
  background: var(--bg);
  border: 1px solid var(--edge);
  border-radius: 12px;
  margin-bottom: 10px;
}
.ck-mode-tab {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 8px 10px;
  border-radius: 9px;
  font-size: 13px;
  font-weight: 600;
  color: var(--hint);
  background: transparent;
  border: 0;
  cursor: pointer;
  transition: all .14s ease;
  user-select: none;
}
.ck-mode-tab-ico {
  font-size: 15px;
  line-height: 1;
  flex: none;
}
.ck-mode-tab-title {
  font-size: 13px;
  font-weight: 600;
}
.ck-mode-tab.on {
  background: var(--surface);
  color: var(--fg);
  box-shadow: 0 1px 4px rgba(15, 23, 42, .08);
}
.ck-mode-tab.on .ck-mode-tab-title {
  font-weight: 700;
  color: var(--fg);
}
.ck-mode-tab.on .ck-mode-tab-ico {
  color: var(--accent);
}
.ck-mode-tab:disabled {
  opacity: .45;
  cursor: default;
}

/* Карточки секций оформления */
.ck-form {
  display: flex;
  flex-direction: column;
  gap: 9px;
}
.ck-card {
  background: var(--surface);
  border: 1px solid var(--edge);
  border-radius: 16px;
  padding: 11px 13px;
  box-shadow: 0 1px 4px rgba(15, 23, 42, .04);
}
.ck-card-head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
}
.ck-card-badge {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--accent) 12%, var(--surface));
  color: var(--accent);
  font-size: 12px;
  font-weight: 700;
  display: grid;
  place-items: center;
  flex: none;
}
.ck-card-title {
  font-size: 15px;
  font-weight: 700;
  color: var(--fg);
  flex: 1;
}

/* Поля ввода внутри карточек оформления: убираем лишние отступы между полями */
.ck-card .field {
  margin: 0;
}
.ck-card .field span {
  font-size: 12px;
  margin-bottom: 2px;
}
.ck-card .field input,
.ck-card .field select,
.ck-card .field textarea {
  padding: 9px 11px;
  font-size: 14px;
  border-radius: 10px;
}
#ckDeliveryPane {
  display: flex;
  flex-direction: column;
  gap: 7px;
}

/* Сохранённые адреса */
.ck-saved-addrs {
  margin-bottom: 8px;
}
.ck-sublabel {
  display: block;
  font-size: 12px;
  font-weight: 500;
  color: var(--hint);
  margin-bottom: 4px;
}
.ck-saved-addrs .addr-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

/* Сетка полей подробного адреса */
.ck-addr-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 6px;
  margin-top: 0;
}
@media (max-width: 480px) {
  .ck-addr-grid {
    grid-template-columns: repeat(2, 1fr);
    gap: 6px;
  }
}

/* Карточка пункта самовывоза */
.ck-pickup-card {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  background: var(--bg);
  border-radius: 12px;
  border: 1px dashed var(--edge);
}
.ck-pickup-ico {
  font-size: 24px;
  line-height: 1;
  flex: none;
  display: grid;
  place-items: center;
  color: var(--accent);
}
.ck-pickup-text {
  flex: 1;
  min-width: 0;
}
.ck-pickup-text b {
  display: block;
  font-size: 14.5px;
  font-weight: 700;
  color: var(--fg);
  margin-bottom: 2px;
}
.ck-pickup-addr {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--fg);
  margin: 2px 0 4px;
  line-height: 1.35;
}
.ck-pickup-text .hint {
  margin: 0;
  font-size: 12.5px;
}

/* Сетка получателя */
.ck-recipient-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 7px;
}
@media (max-width: 480px) {
  .ck-recipient-grid {
    grid-template-columns: 1fr;
    gap: 7px;
  }
}

/* Выбор времени */
.ck-time-notice {
  padding: 8px 12px;
  border-radius: 10px;
  margin-bottom: 8px;
  font-size: 13px;
  line-height: 1.35;
}
.ck-time-tabs {
  display: flex;
  gap: 6px;
  padding: 3px;
  background: var(--bg);
  border-radius: 12px;
  margin-bottom: 8px;
}
.ck-time-tab {
  flex: 1;
  padding: 8px 10px;
  border-radius: 9px;
  font-size: 13px;
  font-weight: 600;
  color: var(--hint);
  background: transparent;
  cursor: pointer;
  transition: all .14s ease;
  text-align: center;
}
.ck-time-tab.on {
  background: var(--surface);
  color: var(--fg);
  box-shadow: 0 1px 4px rgba(15, 23, 42, .08);
}
.ck-time-tab:disabled {
  opacity: .45;
  cursor: default;
}
.ck-time-hint {
  padding: 4px 2px;
}
.ck-time-picker {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 7px;
  margin-top: 4px;
}
@media (max-width: 440px) {
  .ck-time-picker:has(#dateSel) {
    grid-template-columns: 1fr;
    gap: 7px;
  }
}

/* Способы оплаты */
.ck-taxi-badge {
  padding: 8px 12px;
  border-radius: 10px;
  background: color-mix(in srgb, var(--accent) 12%, var(--surface));
  color: var(--fg);
  font-size: 13px;
  line-height: 1.35;
  margin-bottom: 8px;
  font-weight: 500;
}
.ck-pay-grid {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.ck-pay-card {
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  background: var(--bg);
  border: 1.5px solid transparent;
  border-radius: 12px;
  cursor: pointer;
  transition: all .15s ease;
}
.ck-pay-card input {
  display: none;
}
.ck-pay-card.selected {
  background: color-mix(in srgb, var(--accent) 8%, var(--surface));
  border-color: var(--accent);
}
.ck-pay-ico {
  font-size: 20px;
  width: 28px;
  display: grid;
  place-items: center;
  flex: none;
  color: var(--fg);
  transition: color .15s ease;
}
.ck-pay-card.selected .ck-pay-ico {
  color: var(--accent);
}
.ck-pay-info {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.ck-pay-info b {
  font-size: 14px;
  font-weight: 600;
  color: var(--fg);
}
.ck-pay-info small {
  font-size: 12px;
  color: var(--hint);
}
.ck-pay-check {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 2px solid var(--edge);
  flex: none;
  transition: all .14s ease;
}
.ck-pay-card.selected .ck-pay-check {
  border-color: var(--accent);
  background: var(--accent);
  box-shadow: inset 0 0 0 3px var(--surface);
}

/* Блок сдачи с наличных */
.ck-change-box {
  margin-top: 8px;
  padding: 10px;
  background: var(--bg);
  border-radius: 12px;
}
.ck-change-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 6px;
}

/* Единый блок состава заказа на экране оформления */
.checkout-items-box {
  padding: 11px 13px;
  background: var(--surface);
  border: 1px solid var(--edge);
  border-radius: 16px;
  box-shadow: 0 1px 3px rgba(20, 30, 60, .05);
}
.checkout-items-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--edge);
  margin-bottom: 2px;
}
.checkout-items-title {
  display: flex;
  align-items: baseline;
  gap: 6px;
  flex: 1;
}
.checkout-items-title b {
  font-size: 15px;
  font-weight: 700;
  color: var(--fg);
}
.checkout-items-count {
  font-size: 12px;
  color: var(--hint);
  font-weight: 500;
}
.checkout-edit-btn {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  border-radius: 8px;
  padding: 4px 10px;
  transition: background .12s, transform .12s;
  cursor: pointer;
}
.checkout-edit-btn:active {
  background: color-mix(in srgb, var(--accent) 18%, transparent);
  transform: scale(.97);
}
.checkout-items-list {
  list-style: none;
  padding: 0;
  margin: 0;
}
.checkout-item-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  padding: 8px 0;
  border-bottom: 1px solid var(--bg);
}
.checkout-item-row:last-child {
  border-bottom: 0;
  padding-bottom: 0;
}
.checkout-item-info {
  flex: 1;
  min-width: 0;
}
.checkout-item-name b {
  font-size: 14.5px;
  font-weight: 600;
  line-height: 1.25;
  color: var(--fg);
}
.checkout-item-info .hint {
  font-size: 12.5px;
  color: var(--hint);
  margin: 2px 0 0;
  line-height: 1.3;
}
.checkout-item-meta {
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 1px;
  text-align: right;
}
.checkout-item-calc {
  font-size: 11.5px;
  color: var(--hint);
  font-weight: 500;
}
.checkout-item-sum {
  font-size: 14.5px;
  font-weight: 700;
  color: var(--fg);
  white-space: nowrap;
}

/* Кнопка отправки */
.ck-submit-btn {
  height: 48px;
  border-radius: 14px;
  font-size: 15px;
  font-weight: 700;
  margin-top: 10px;
  box-shadow: 0 3px 12px color-mix(in srgb, var(--accent) 30%, transparent);
}
.ck-submit-btn:disabled {
  box-shadow: none;
}
.cart-items li.cart-line.checkout-line { grid-template-columns: minmax(0, 1fr) auto; align-items: baseline; }
.cart-line .mini { width: 56px; height: 56px; border-radius: 12px; font-size: 26px; }
.cart-line .info { display: flex; flex-direction: column; gap: 2px; }
.cart-line .info b { font-size: 14.5px; line-height: 1.25; }
.cart-line .info .hint { font-size: 12px; margin: 0; line-height: 1.3; }
/* Сумма позиции — аккуратная и контрастная */
.line-sum { font-size: 15px; font-weight: 700; white-space: nowrap; }
/* Подвал позиции: компактный счётчик и комментарий */
.line-foot { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 3px; }
.line-foot .step { border-radius: 10px; }
.line-foot .step button { width: 28px; height: 28px; font-size: 15px; }
.line-foot .step span { min-width: 28px; font-size: 13px; font-weight: 600; }
.line-foot .step button[data-inc] { display: grid; place-items: center; }
.cart-items .cmt-toggle {
  position: static;
  grid-column: auto;
  flex: none;
  width: 28px;
  height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border-radius: 9px;
  background: var(--card);
  color: var(--hint);
  border: 1px solid var(--edge);
  transition: all .14s ease;
  cursor: pointer;
  line-height: 1;
}
.cart-items .cmt-toggle:hover {
  color: var(--fg);
  border-color: var(--accent);
}
.cart-items .cmt-toggle.on {
  color: #fff;
  background: var(--accent);
  border-color: var(--accent);
}
.cart-items .cmt-toggle .ico {
  display: block;
}

/* Диалог модификаторов */
.mod-overlay { position: fixed; inset: 0; background: rgba(10,14,26,.5); display: flex; align-items: flex-end; justify-content: center; z-index: 40; }
/* Окно информации к опции открывается поверх окна выбора модификаторов */
.info-sheet { z-index: 45; }
.mod-box { background: var(--surface); border-radius: 24px 24px 0 0; padding: 16px 16px calc(16px + var(--tg-inset-bottom)); width: 100%; max-width: 640px; max-height: 85vh; overflow-y: auto; }
.mod-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px; }
.mod-close { width: 32px; height: 32px; display: grid; place-items: center; border-radius: 50%; color: var(--hint); padding: 0; background: transparent; border: 0; }
.mod-close:active { background: var(--bg); color: var(--fg); }
.mod-label { font-size: 13px; color: var(--hint); margin: 10px 0 6px; text-transform: uppercase; letter-spacing: .03em; }
.mod-label .req { color: var(--danger); }
.mod-opts { display: flex; flex-wrap: wrap; gap: 8px; }
.mod-box .mod-opts.list { flex-direction: column; gap: 10px; }
.mod-box .mod-opts.horizontal { flex-direction: row; flex-wrap: nowrap; gap: 8px; overflow-x: auto; padding-bottom: 6px; scrollbar-width: thin; }
.mod-opt { padding: 9px 14px; border-radius: 14px; background: var(--bg); border: 1.5px solid var(--edge); font-size: 14px; transition: border-color .14s, background .14s; }
/* Опция и её значок ⓘ лежат в одной строке: в горизонтальной раскладке строка не сжимается */
.mod-opt-row { display: flex; align-items: stretch; gap: 6px; }
.mod-box .mod-opts.list .mod-opt-row { width: 100%; }
.mod-box .mod-opts.horizontal .mod-opt-row { flex: 0 0 auto; max-width: 88%; }
/* В горизонтальной раскладке ограничение по ширине задано на строке, а не на самой опции */
.mod-box .mod-opts.horizontal .mod-opt-row .mod-opt { max-width: none; }
.mod-box .mod-opt-row .mod-opt { flex: 1 1 auto; min-width: 0; }
/* Значок информации: отдельная кнопка, чтобы не вкладывать кнопку в кнопку */
.mod-info { flex: none; align-self: center; width: 30px; height: 30px; display: grid; place-items: center; border-radius: 50%; background: var(--bg); color: var(--hint); font-size: 14px; line-height: 1; }
.mod-info:active { color: var(--accent); }
.mod-box .mod-opt { width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 16px; text-align: left; }
.mod-box .mod-opts.horizontal .mod-opt { width: auto; max-width: 88%; flex: 0 0 auto; }
.mod-box .mod-name { min-width: 0; }
.mod-opt.on { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, var(--surface)); color: var(--accent); font-weight: 600; }
.mod-opt .delta { color: var(--hint); font-size: 13px; font-weight: 600; white-space: nowrap; }
/* Окно состава: пояснение абзацем, ингредиенты списком */
.comp-intro { margin: 0 0 4px; color: var(--hint); font-size: 14px; line-height: 1.5; }
.comp-list { margin: 0; padding: 0; list-style: none; display: grid; gap: 6px; }
.comp-list li { position: relative; padding: 8px 12px 8px 28px; border-radius: 10px; background: var(--bg); font-size: 14px; }
.comp-list li::before { content: ''; position: absolute; left: 12px; top: 15px; width: 6px; height: 6px; border-radius: 50%; background: var(--accent); }

/* Строки, которых не было в базовом составе, — их принесла выбранная опция.
   Подложка тонируется акцентом, а точка увеличивается: иначе строка не отличилась
   бы от соседней, а разница между двумя вариантами как раз и ищется на глаз.
   Тон слабый намеренно — это подсказка, а не второй заголовок блока. */
/* Базовое оформление выделенной строки — на случай, если она встретится вне
   блока .comp-changed: плитка тонируется и становится заметно плотнее. */
.comp-list li.is-added { background: color-mix(in srgb, var(--accent) 9%, var(--bg)); font-weight: 600; }
/* Пояснение к выделению — только когда выделено что-то, иначе под заголовком
   «Ингредиенты» была бы пустая строка. */
.comp-legend { margin: 0 0 6px; font-size: 12px; line-height: 1.3; color: var(--hint); }
.mod-add { margin-top: 14px; }

/* Рейтинг и звёзды */
.stars { display: flex; gap: 6px; }
.star { background: none; border: 0; color: var(--hint); font-size: 28px; opacity: .55; padding: 2px; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; }
.star svg { fill: none; stroke: currentColor; }
/* Подсветка только у активных звёзд: disabled всё равно ловит :hover,
   и без :not() неактивная звезда выглядела бы кликабельной. */
.star:not(:disabled):hover, .star.on { color: #e3a008; opacity: 1; }
.star:not(:disabled):hover svg, .star.on svg { fill: currentColor; }
.star:disabled { cursor: default; }
.rate-star { display: inline-flex; align-items: center; justify-content: center; color: #e3a008; vertical-align: -1px; }
.rate-star svg { fill: currentColor; }
/* Оценка внутри позиции заказа: компактнее обычного блока, чтобы не спорить с суммой справа */
.stars-sm { margin-top: 4px; gap: 2px; }
.stars-sm .star { font-size: 20px; line-height: 1; }
/* Позиция с оценкой отделяется от соседней, чтобы блок читался как список отзывов */
.o-item + .o-item { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--bg); }
/* Бейдж средней оценки на карточке товара */
/* Подложка бейджа и обода колеса задаётся через --surface, а не жёстким #fff:
   иначе в тёмной теме оставалось белое пятно, а MAX (где нет colorScheme у моста)
   приходилось особенно часто. */
.rate-badge { position: absolute; top: 14px; left: 14px; padding: 3px 8px; border-radius: 10px; background: var(--surface); color: var(--hint); font-size: 12px; line-height: 1.4; box-shadow: 0 1px 4px rgba(15, 23, 42, .18); }
.rate-badge b { color: #e3a008; font-weight: 400; }

/* Модификаторы в админке */
.mod-opts { display: flex; flex-direction: column; gap: 6px; }
.mod-opts .item { display: flex; justify-content: space-between; align-items: center; padding: 8px 10px; background: var(--bg); border-radius: 10px; font-size: 14px; }

/* ============================================================================
   СТРАНИЦА ТОВАРА

   Порядок блоков повторяет референс: снимок на голом фоне, отдельным блоком
   цена, тонкая линия, название с размером серым, оценка, рубрика категории,
   карточка КБЖУ с кнопкой «Состав», варианты и добавление.
   Оформление — плоские карточки со скруглением 24px без рамок, крупные
   заголовки, спокойные отступы. Цвета не свои: страница берёт те же --surface,
   --fg, --hint, --accent, --card и --edge, что и весь интерфейс, — иначе
   выбранный в профиле акцент или тёмная тема работали бы здесь мимо.

   Фон страницы и вид нижних вкладок задаются через :has() по наличию
   .product-page внутри main: на этом экране вкладки плоские, как в референсе.
   В WebView без :has() правила не применятся — страница останется обычной.
   ============================================================================ */

/* --- Фон страницы и нижняя навигация -------------------------------------- */
/* Фон не задаём: он и так общий для всего приложения. А вот вкладки на этом
   экране плоские — белой полосой во всю ширину с верхним разделителем, как в
   референсе. Цвета те же, что у плавающей пилюли: та же тема, тот же акцент,
   просто без скругления и тени. На каталоге, корзине и профиле пилюля
   остаётся — правила срабатывают только при открытом товаре. */
main:has(.product-page) + .tabs {
  left: 0;
  right: 0;
  bottom: 0;
  max-width: none;
  margin: 0;
  padding: 8px 8px calc(8px + var(--tg-inset-bottom));
  border-top: 1px solid var(--edge);
  border-radius: 0;
  box-shadow: none;
  background: var(--surface);
}
main:has(.product-page) + .tabs button.on { background: none; color: var(--accent); }

/* --- Экран ---------------------------------------------------------------- */
.product-page {
  /* Тень не в теме: у темы нет переменной для неё, а на тёмном фоне
     светлая тень не нужна. Значение то же, что у карточек профиля. */
  --pg-shadow: 0 2px 10px rgba(20, 30, 60, .07);
  /* Золото звёздочки — локально: в теме нет переменной для оценок, а на
     тёмном фоне тёмное золото не читалось бы. То же значение, что у .rate-badge. */
  --pg-star: #e3a008;
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding-bottom: 0;
  color: var(--fg);
}
/* Заголовок карточки раздела: тот же кегль на «Ингредиентах» и названии группы
   выбора — иерархия держится на весе и размере, а не на капризных заглавных
   буквах. Заголовком КБЖУ («На 320 г») этот класс не мешает никому: он задаёт
   кегль, а не текст. */
.product-section-title {
  margin: 0 0 10px;
  font-size: 17px;
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: -.01em;
  color: var(--fg);
}

/* --- Фотография ----------------------------------------------------------- */
/* Снимок лежит прямо на фоне страницы, без белой карточки-рамки: в референсе
   он тоже ни на чём не стоит, и рамка делала его отдельной плиткой в плитке.
   position остаётся — избранному над снимком самое место. */
.product-media {
  position: relative;
  display: grid;
}
.product-media-wrap {
  /* Оговорка лежит поверх снимка (position: absolute внутри), поэтому блок
     должен быть точкой отсчёта. */
  position: relative;
  display: grid;
  place-items: center;
  width: 100%;
  font-size: 64px;
  line-height: 1;
}
/* object-fit: contain — снимок виден целиком и никогда не растягивается.
   Высота адаптивная: у обычной почти квадратной фотографии она берётся из
   пропорций файла, а у слишком высокой ограничивается max-height, и снимок
   не съедает весь экран.
   Скругление 24px — крупнее, чем у карточек товара (18px): снимок идёт от края
   до края и задаёт весь экран, ему положен больший радиус. Обрезать
   им нечего — object-fit: contain вписывает снимок целиком, скругление
   срезает только углы фона. */
.product-media-wrap img {
  display: block;
  width: 100%;
  height: auto;
  max-height: 40vh;
  object-fit: contain;
  border-radius: 24px;
}

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

   Подложка — полупрозрачный --surface с тенью, то же решение, что у кнопки
   избранного поверх снимка: в светлой теме это светлая плашка, в тёмной —
   тёмная, и на любой фотографии читается. Сплошной белый не годился бы:
   на светлом снимке текст в нём пропал бы.

   Мелкая и серая намеренно: это предупреждение, а не реклама. В референсе на
   похожем месте стоит жёлтая плашка «Выгодно», но оформлять так же оговорку
   нельзя — она начала бы спорить со снимком и ценой. Кегль 9 px и отступы 3/7 —
   плашка прижимается к углу и не загораживает снимок: на 390 px она занимает
   около 245 px в одну строку.

   Плашка у правого нижнего угла, тем же отступом 10 px от края, что и
   избранное сверху: два этих элемента — единственные, что лежат на снимке,
   и держать их по разным краям не нужно. Во всю ширину она не тянется:
   у высоких снимков (object-fit: contain) по бокам остаётся поле, и подпись
   вылезла бы на фон. max-width держит её и слева от края. */
.product-photo-note {
  position: absolute;
  right: 8px;
  bottom: 8px;
  max-width: calc(100% - 16px);
  margin: 0;
  padding: 3px 7px;
  border-radius: 8px;
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  color: var(--hint);
  font-size: 9px;
  line-height: 1.3;
  text-align: left;
  box-shadow: 0 2px 8px rgba(15, 23, 42, .22);
}

/* Статус под снимком — прежняя серая плашка, ровно как была до переезда
   оговорки на фото. Читается без наложения на фотографию, поэтому держит
   рамку --edge, а не тень. */
.product-note {
  flex: none;
  max-width: 100%;
  margin: 0 0 0 auto;
  padding: 3px 8px;
  border-radius: 6px;
  /* Подложка --card на фоне --bg не читалась: #F4EEE1 против #FAF5EC — это
     контраст около 1.03, то есть почти один и тот же цвет, и плашка выглядела серым
     текстом без границы. Рамка --edge (#E7DDC9) отделяет её в обеих темах,
     где --card темнее --bg, а --edge — на два тона светлее. */
  border: 1px solid var(--edge);
  background: var(--surface);
  color: var(--hint);
  font-size: 10px;
  line-height: 1.35;
}

/* Избранное: та же кнопка .fav, что на карточке в каталоге, но поверх снимка.
   Круглая и с подложкой цвета карточки: в тёмной теме белая плашка на
   фотографии смотрелась бы пятном.
   Отступ от угла 10 px: вплотную к краю снимка кнопка выглядела приклеенной,
   а поля самого снимка на странице нет — фото идёт от края до края. */
.product-fav {
  position: absolute;
  top: 10px;
  right: 10px;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border-radius: 50%;
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  color: var(--hint);
  box-shadow: 0 2px 8px rgba(15, 23, 42, .22);
}
.product-fav svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; display: block; }
.product-fav:active { color: var(--accent); }
.product-fav.on { color: var(--accent); }
.product-fav.on svg { fill: currentColor; }

/* --- Цена ----------------------------------------------------------------- */
/* Оговорки под снимком: у товара без фотографии и не в наличии блока нет.
   Название и цену он больше не разделяет — они стоят в строке ниже. */
.product-notes { display: flex; flex-direction: column; gap: 2px; }
/* Тонкая линия перед названием: отделяет снимок от того, что товар собой
   представляет. */
.product-rule { border: 0; border-top: 1px solid var(--edge); margin: 2px 0 0; }

/* --- Название, цена и оценки ----------------------------------------------- */
.product-head { display: flex; flex-direction: column; gap: 6px; }
/* Название и цена в одной строке: у правого края цена, у левого название,
   между ними — свободное место. Название тянется на всю оставшуюся ширину и
   переносится по словам, цена не сжимается (flex: none), иначе «1 250 ₽»
   разбилось бы на две строки. Выравнивание по базовой линии, а не по центру:
   у названия 21 px, у суммы тот же кегль, но цифры без выносных элементов
   стоят ниже — приравнивание центров разъезжалось бы на пару пикселей. */
.product-head-line { display: flex; align-items: baseline; justify-content: space-between; gap: 14px; }
.product-name {
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
  font-size: 24px;
  font-weight: 800;
  line-height: 1.2;
  letter-spacing: -.02em;
  color: var(--fg);
  overflow-wrap: break-word;
  word-break: normal;
  hyphens: none;
}
/* Цена в строке с названием, поэтому кегль тот же: пока она была отдельной
   строкой, 26 px работали как акцент, но рядом с заголовком она перебивала бы
   его и название переставало читаться как заголовок. */
.product-price { flex: none; white-space: nowrap; font-size: 22px; font-weight: 800; line-height: 1.2; letter-spacing: -.02em; color: var(--fg); }
/* Оценки считаются по доставленным заказам, поэтому строки может не быть. */
.product-rate { display: flex; align-items: center; gap: 7px; margin: 0; font-size: 15px; line-height: 1.3; color: var(--fg); }
.product-rate b { color: var(--pg-star); font-weight: 400; }
.product-rate span { color: var(--hint); }

/* --- Рубрики -------------------------------------------------------------- */
/* Белая плашка со стрелкой — та же рубрика, что в шапке каталога: она ведёт
   на страницу категории, поэтому стрелка и здесь на месте. */
.product-tags { display: flex; gap: 8px; overflow-x: auto; scrollbar-width: none; }
.product-tag {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 16px;
  border-radius: 20px;
  background: var(--surface);
  color: var(--fg);
  font-size: 15px;
  font-weight: 600;
  white-space: nowrap;
}
.product-tag .chev { margin-left: 0; opacity: .5; }
.product-tag:active { background: var(--card); }

/* --- Пищевая ценность ----------------------------------------------------- */
.product-nutrition {
  margin: 0;
  padding: 14px 16px;
  background: var(--surface);
  border-radius: 24px;
  box-shadow: var(--pg-shadow);
  color: var(--fg);
  font-size: 13px;
}
.product-nutrition[hidden] { display: none; }
/* Блок состава теперь стоит отдельно от карточки КБЖУ и раскрыт всегда, а не по
   кнопке, поэтому правила .product-nutrition.bare к нему не относятся: подложку он
   получает сам, а содержимое перерисовывается на каждой смене выбора. */
.product-nutrition.bare { padding: 0; background: none; box-shadow: none; }
/* Вес выбранной порции — строкой под заголовком карточки КБЖУ (portionNote в
   nutrition.js). Отрицательный отступ сверху обязателен: у заголовка свой margin
   в 10px, и без него между «На всю порцию» и весом зияла бы пустая полоса. */
.product-nutrition-note {
  margin: -4px 0 10px;
  font-size: 13px;
  line-height: 1.3;
  color: var(--hint);
}
.product-nutrition-note[hidden] { display: none; }

/* Четыре значения в ряд, крупным числом над мелкой подписью, как в референсе.
   Порядок задаёт nutritionCard: калории, белки, жиры, углеводы — вес ушёл в
   заголовок («На 320 г»). Подписи переносятся по слогам: на 320 px «Углеводы»
   иначе ломается посреди слова. */
.product-nutrition-values { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 4px; }
/* Плитки бежевые: на белой карточке цифры читаются отдельными ячейками, а не
   строкой текста. Подложка --bg (крем в светлой, кофе в тёмной) — та же, что
   у плиток ингредиентов и опций, весь экран в одной гамме. */
.nutrition-cell {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  min-width: 0;
  padding: 8px 4px;
  border-radius: 12px;
  background: var(--bg);
  text-align: center;
}
.nutrition-cell b { font-size: 17px; font-weight: 700; line-height: 1.2; color: var(--fg); }
.nutrition-cell span { font-size: 13px; font-weight: 400; color: var(--hint); hyphens: auto; overflow-wrap: break-word; }

/* Кнопки раскрытия состава больше нет: состав показан всегда, без сворачивания. */

/* Блок «Ингредиенты» — такая же белая карточка, как карточка КБЖУ под ним.
   Раньше это был просто разделитель с линией сверху, и состав сливался с фоном
   страницы: единственным его признаком был заголовок. Теперь у блока своя
   подложка, скругление и тень — он читается как самостоятельный раздел, а не
   как продолжение предыдущего. Заголовок мельче, чем у карточки КБЖУ, потому что
   это подзаголовок: сами цифры порции главнее. */
.product-info {
  padding: 14px 16px;
  background: var(--surface);
  border-radius: 24px;
  box-shadow: var(--pg-shadow);
  color: var(--fg);
}
/* Подпись «выделено то, что меняет опция» убрана: плитки и так помечены
   подложкой и точкой, а объяснение под заголовком занимало строку и путало
   с подписью к порции выше. */
.product-info[hidden] { display: none; }
.product-info-title { margin: 0 0 4px; font-size: 15px; font-weight: 700; line-height: 1.3; color: var(--fg); }
/* Ингредиенты на странице товара идут плитками, как в окне состава: каждый
   продукт отдельной плашкой с точкой. Абзацем через « · » было короче, но
   выделенные строки в нём не читались — выделять строку внутри предложения
   нечем, и подсветка уходила в один акцентный цвет текста.
   Сетка в две колонки: на телефоне в одну плитка растягивалась бы на всю ширину
   и список из пяти ингредиентов занимал пол-экрана. */
.product-info .comp-list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 6px;
  margin: 8px 0 0;
  padding: 0;
}
.product-info .comp-list li {
  position: relative;
  max-width: 100%;
  padding: 8px 10px 8px 26px;
  border-radius: 10px;
  background: var(--bg);
  font-size: 14px;
  line-height: 1.3;
  color: var(--fg);
  overflow-wrap: break-word;
  word-break: normal;
  hyphens: none;
}
/* Точка у каждой плитки своя: у абзаца она была разделителем и рисовалась
   псевдоэлементом ::after, а здесь плитка стоит в своём ряду. */
.product-info .comp-list li::before {
  content: '';
  position: absolute;
  left: 10px;
  top: 50%;
  transform: translateY(-50%);
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
}
/* Выделенные строки — те, которых не было в базовом составе: их принесла
   выбранная опция. Собой они собираются в отдельный блок под основным списком,
   а не тонируются по месту: в общем списке подсветка терялась среди строк, что
   были и до выбора, и гость не мог понять, что именно изменилось.
   Подписи у блока намеренно нет — по просьбе. Плитки внутри тонированы акцентом,
   и этого достаточно. */
.comp-changed {
  display: block;
  margin-top: 6px;
  padding: 8px;
  border-radius: 14px;
  background: color-mix(in srgb, var(--accent) 9%, transparent);
}
.comp-changed .comp-list { margin: 0; }
.comp-changed .comp-list li { background: var(--surface); }
/* На узком экране одна колонка: две плитки в 160 px ломают «Корейская морковь»
   на три строки и растягивают плитку соседа — в сетке все строки одной высоты. */
@media (max-width: 359px) {
  .product-info .comp-list { grid-template-columns: minmax(0, 1fr); }
}

/* Аллергены — справочная строка в том же блоке, что и состав. Разделитель тонкий,
   текст вторичный — это справка, а не заголовок. */
.product-allergens {
  margin: 12px 0 0;
  padding-top: 12px;
  border-top: 1px solid var(--edge);
  font-size: 13px;
  line-height: 1.4;
  color: var(--hint);
  overflow-wrap: break-word;
  word-break: normal;
  hyphens: none;
}

/* --- Размер и другие группы выбора ---------------------------------------- */
/* Варианты — сеткой в три колонки: их бывает до пятнадцати (начинки пиццы,
   начинки роллов), и в две колонки группа растягивалась на четыре ряда и
   отодвигала кнопку добавления за экран. Выбранный сплошной акцентный,
   остальные — тёплый серый. */
.product-mods {
  padding: 14px 16px;
  background: var(--surface);
  border-radius: 24px;
  box-shadow: var(--pg-shadow);
}
.product-mod-groups { display: grid; gap: 16px; }
.product-mod-group { display: grid; gap: 10px; }
.product-mod-group-name {
  margin: 0;
  font-size: 17px;
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: -.01em;
  color: var(--fg);
}
.product-mod-group-name .req { color: var(--accent); }
.product-mod-opts:not(.is-list) {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 6px;
}
.product-mod-opts:not(.is-list)[data-cols="1"] { grid-template-columns: 1fr; }
.product-mod-opts:not(.is-list)[data-cols="2"] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.product-mod-opts:not(.is-list)[data-cols="3"] { grid-template-columns: repeat(3, minmax(0, 1fr)); }

/* Список модификаторов (layout: list) */
.product-mod-opts.is-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.product-mod-opt-row {
  display: flex;
  align-items: stretch;
  gap: 6px;
  width: 100%;
}
.product-mod-opts.is-list .product-mod-opt {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 42px;
  padding: 8px 12px;
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}
.product-mod-opt-main {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  flex: 1 1 auto;
}
.product-mod-opts.is-list .product-mod-opt-name {
  font-size: 14px;
  font-weight: 600;
  color: var(--fg);
}
.product-mod-opts.is-list .product-mod-opt.on {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, var(--surface));
  color: var(--fg);
  box-shadow: 0 2px 8px color-mix(in srgb, var(--accent) 15%, transparent);
}
.product-mod-opts.is-list .product-mod-opt.on .product-mod-opt-name {
  color: var(--fg);
}
.product-mod-opts.is-list .product-mod-opt.on .product-mod-opt-delta {
  color: var(--accent);
}
.product-mod-check {
  flex: none;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 1.5px solid var(--edge);
  background: var(--surface);
  display: grid;
  place-items: center;
  transition: border-color .14s, background .14s;
}
.product-mod-check.checkbox {
  border-radius: 5px;
}
.product-mod-opt.on .product-mod-check {
  border-color: var(--accent);
  background: var(--accent);
}
.product-mod-opt.on .product-mod-check.radio::after {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--surface);
}
.product-mod-opt.on .product-mod-check.checkbox::after {
  content: '';
  width: 4px;
  height: 8px;
  border: solid var(--on-accent);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg) translate(-1px, -1px);
}
.product-mod-info {
  flex: none;
  align-self: center;
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1.5px solid var(--edge);
  background: var(--bg);
  color: var(--hint);
  font-size: 14px;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
  transition: color .14s, border-color .14s, transform .12s, background .14s;
}
.product-mod-info:active {
  color: var(--accent);
  border-color: var(--accent);
  transform: scale(.92);
}

/* В горизонтальной раскладке (is-size / is-horizontal) */
.product-mod-opt-cell {
  position: relative;
  display: flex;
  align-items: stretch;
  min-width: 0;
}
.product-mod-opt-cell .product-mod-opt {
  width: 100%;
}
.product-mod-opt-cell .product-mod-info {
  position: absolute;
  top: 3px;
  right: 3px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: 1px solid var(--edge);
  background: var(--surface);
  color: var(--hint);
  font-size: 11px;
  z-index: 2;
}
.product-mod-opt-cell .product-mod-opt.on ~ .product-mod-info {
  background: var(--accent);
  color: var(--on-accent);
  border-color: color-mix(in srgb, var(--on-accent) 30%, transparent);
}

.product-mod-opt {
  position: relative;
  /* Колонкой: название и наценка друг под другом.
     Для размеров — по центру и в одну строку без разрывов. */
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 2px;
  min-width: 0;
  min-height: 48px;
  padding: 8px 10px;
  border: 1.5px solid var(--edge);
  border-radius: 14px;
  background: var(--bg);
  color: var(--fg);
  font-size: 13.5px;
  font-weight: 600;
  cursor: pointer;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .03);
  transition: background .14s, color .14s, border-color .14s, transform .12s, box-shadow .14s;
}
.product-mod-opts.is-size .product-mod-opt {
  align-items: center;
  text-align: center;
  padding: 8px 6px;
}
.product-mod-opt input { position: absolute; opacity: 0; pointer-events: none; }
.product-mod-opt.on {
  border-color: var(--accent);
  background: var(--accent);
  color: var(--on-accent);
  box-shadow: 0 4px 12px color-mix(in srgb, var(--accent) 30%, transparent);
}
.product-mod-opt:active { transform: scale(.96); opacity: .9; }
.product-mod-opt-name {
  min-width: 0;
  line-height: 1.25;
  word-break: normal;
  overflow-wrap: break-word;
  hyphens: none;
}
.product-mod-opts.is-size .product-mod-opt-name {
  white-space: nowrap;
}
/* Наценка — второй строкой: читается как уточнение */
.product-mod-opt-delta { font-size: 12.5px; font-weight: 700; color: var(--accent); white-space: nowrap; }
.product-mod-opt.on .product-mod-opt-delta { color: color-mix(in srgb, var(--on-accent) 88%, transparent); }
.product-total {
  margin: 10px 0 0;
  padding-top: 10px;
  border-top: 1px solid var(--edge);
  font-size: 15px;
  font-weight: 700;
  text-align: right;
  color: var(--fg);
}

/* --- Панель заказа -------------------------------------------------------- */
/* Два взаимоисключающих состояния, оба занимают всю ширину: пока позиции нет —
   одна большая кнопка, как только товар в корзине — один счётчик «− N +».
   Держать рядом обе кнопки незачем: «Добавить ещё» при уже лежащей позиции
   ничего не сообщает. */
.product-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  margin-top: 0;
}
/* Липкая панель покупки: прилипает над нижней навигацией, чтобы «Добавить»
   было под пальцем на длинной странице с модификаторами. Отступ снизу равен
   отступу тоста (96px + inset): панель встаёт ровно туда, где ничего нет.
   Полупрозрачный фон с блюром — контент под ней виден, но не спорит с ценой;
   без backdrop-filter (старые WebView) остаётся просто подложка. */
.product-stickybar {
  position: sticky;
  bottom: calc(96px + var(--tg-inset-bottom));
  z-index: 2;
  margin: 0 -4px;
  padding: 8px;
  border-radius: 18px;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
/* Что из двух показано — решает refreshQty по количеству в корзине. Прячем
   через hidden, поэтому правила с display ниже перебивают его явным [hidden]. */
.product-actions .step[hidden],
.product-actions .primary[hidden] { display: none; }
/* Счётчик в одиночку растягивается на всю панель: «−» и «+» уходят к краям,
   число остаётся посередине — нажимать удобно, ничего не ищется взглядом. */
.product-actions .step {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 4px;
  padding: 5px;
  border-radius: 16px;
  background: var(--surface);
  box-shadow: var(--pg-shadow);
}
.product-actions .step button {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 12px;
  background: var(--card);
  color: var(--fg);
}
.product-actions .step button:active { background: var(--edge); }
.product-actions .step button:disabled { opacity: .4; }
.product-actions .step .qty { flex: 1; min-width: 36px; text-align: center; font-size: 18px; font-weight: 700; color: var(--fg); }
.product-actions .primary {
  flex: 1 1 200px;
  width: auto;
  min-width: 0;
  /* Высота фиксированная, а не минимальная: подпись меняется между «Выберите:
     Размер» и «Добавить ещё · 1 200 ₽», и при min-height кнопка то
     подрастала на вторую строку, то нет — панель дёргалась под пальцем. */
  height: 48px;
  display: grid;
  place-items: center;
  text-align: center;
  line-height: 1.15;
  margin-top: 0;
  padding: 8px 12px;
  border-radius: 16px;
  background: var(--accent);
  color: var(--on-accent);
  font-size: 14px;
  font-weight: 700;
  box-shadow: 0 6px 16px color-mix(in srgb, var(--accent) 22%, transparent);
}
.product-actions .primary:active { filter: brightness(.96); }
/* Неактивную кнопку не гасим под фон: приглушённая заливка акцентом и рамка
   того же цвета читаются как «сюда надо вернуться», а не как выключенный
   элемент формы. Размер при этом прежний: рамка съедает часть высоты внутри
   рамки (box-sizing: border-box у всех элементов), так что панель не прыгает. */
.product-actions .primary:disabled {
  background: color-mix(in srgb, var(--accent) 12%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--accent) 26%, transparent);
  color: var(--accent);
  box-shadow: none;
  opacity: 1;
}
/* Подпись под кнопкой отдельной строкой больше не нужна: причина, по которой
   добавление невозможно, пишется прямо на кнопке (blockedReason в product.js),
   поэтому панель занимает ровно одну строку. */

@media (prefers-reduced-motion: reduce) {
  .product-mod-opt { transition: none; }
}
/* Узкие экраны (320 px) — две колонки вместо трёх: на плитку остаётся около
   80 px, и «Болгарский перец» в одну строку не влезал. 360 px ещё держит три. */
@media (max-width: 359px) {
  .product-mod-opts:not(.is-list) { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .product-mod-opts:not(.is-list)[data-cols="1"] { grid-template-columns: 1fr; }
}
/* Оговорка про внешний вид больше не делит строку с ценой: она живёт отдельной
   строкой в .product-notes, поэтому и переноситься ей некуда — на узком
   экране она просто занимает две строки, как любой серый текст. */

/* ============================================================================
   КОНСТРУКТОР ПИЦЦЫ

   Экран без своей вкладки (вход с баннера в каталоге) и без кнопки «‹ Назад»:
   назад уводит системная кнопка мессенджера, а снизу всегда есть вкладка «Меню».
   Поэтому шапка здесь проще, чем у страницы товара, — только название и цена.

   Имена классов не пересекаются с .product-*: оба экрана показывают цену и
   группы выбора, но у конструктора своя раскладка — шаги во всю ширину, а не
   раскрывающийся блок с чекбоксами. Общие примитивы (.primary, .req) не трогаем:
   на них держится остальной интерфейс.
   ============================================================================ */
.pizza-page {
  display: flex;
  flex-direction: column;
  gap: 12px;
  /* Нижний отступ — под вкладки и кнопку добавления, которая прилипает к низу. */
  padding-bottom: 24px;
}
/* Название и цена в одну строку: цена меняется при выборе размера и добавок,
   и если она во второй строке, при каждом нажатии прыгает вся шапка. */
.prod-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}
.prod-name { font-size: 22px; margin: 0; min-width: 0; }
.prod-price { font-size: 18px; font-weight: 700; color: var(--accent); white-space: nowrap; }

/* Снимок основы. Рисунок не меняется при выборе ингредиентов, поэтому это
   статичная картинка, а не холст: object-fit: cover гарантирует заполнение
   при любой высоте, а скругление задаёт CSS — углы картинки иначе вылезали бы
   за скруглённую рамку. */
.pizza-stage {
  background: var(--card);
  border-radius: 16px;
  overflow: hidden;
  aspect-ratio: 16 / 9;
  display: grid;
  place-items: center;
}
.pizza-photo { width: 100%; height: 100%; object-fit: cover; display: block; }
.pizza-empty { font-size: 64px; line-height: 1; }

/* Шаг: подпись группы и кнопки выбора. Карточка — та же белая плашка, что у
   блока состава на странице товара, поэтому экран читается единообразно. */
.prod-card { background: var(--surface); border-radius: 14px; padding: 14px 16px; }
/* Обязательный шаг помечен звёздочкой — тем же приёмом, что окно выбора
   модификаторов, чтобы правило «звёздочка = обязательно» было одно на всё. */
.prod-label { font-size: 13px; color: var(--hint); margin: 0 0 8px; text-transform: uppercase; letter-spacing: .03em; }
.prod-label .req { color: var(--danger); }
/* Счётчик «2 из 8» у ингредиентов: показывает, сколько добавок уже набрано
   и сколько ещё можно. Прижимаем вправо — он относится к набору, а не к названию. */
.prod-count { float: right; color: var(--hint); font-weight: 600; text-transform: none; letter-spacing: 0; }

/* Размеры — сегментированный переключатель в одну строку: вариантов мало,
   и подпись каждого — итоговая цена, которой нужно место. */
.prod-seg { display: flex; gap: 6px; }
.prod-seg-btn {
  flex: 1;
  display: grid;
  gap: 2px;
  padding: 9px 6px;
  border-radius: 12px;
  background: var(--bg);
  border: 1.5px solid var(--edge);
  font-size: 14px;
  text-align: center;
  transition: background .14s, border-color .14s, color .14s;
}
.prod-seg-btn em { font-style: normal; font-size: 13px; color: var(--hint); font-weight: 600; }
.prod-seg-btn.on { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }
.prod-seg-btn.on em { color: var(--on-accent); }

/* Ингредиенты — обычные кнопки в перенос: их бывает много, и в строку они не
   помещаются. Подпись добавки — прибавка к цене, поэтому она в em, как и в
   окне выбора модификаторов. */
.prod-chips { display: flex; flex-wrap: wrap; gap: 7px; }
.prod-chip {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 8px 12px;
  border-radius: 12px;
  background: var(--bg);
  border: 1.5px solid var(--edge);
  font-size: 14px;
  text-align: left;
  transition: background .14s, border-color .14s, color .14s;
}
.prod-chip em { font-style: normal; font-size: 13px; color: var(--hint); font-weight: 600; }
.prod-chip.on { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }
.prod-chip.on em { color: var(--on-accent); }
/* Ингредиент, до которого лимит уже не дотянуть: гасим, но не прячем — список
   добавок должен оставаться прежним, иначе подсказка «что можно выбрать» исчезает.
   Нажатие всё равно блокируется в pizza.js, здесь только внешний вид. */
.prod-chip.off { opacity: .45; }

/* Кнопка добавления прилипает к низу: на длинном списке ингредиентов до неё
   приходилось бы долго скроллить. position: sticky внутри .pizza-page — не
   fixed, чтобы не перекрывать нижние вкладки. */
.prod-buy { position: sticky; bottom: calc(76px + var(--tg-inset-bottom)); display: grid; gap: 6px; margin-top: 4px; }
.prod-add {
  width: 100%;
  padding: 14px;
  border-radius: 14px;
  background: var(--accent);
  color: var(--on-accent);
  font-weight: 600;
  box-shadow: 0 6px 20px rgba(20, 30, 60, .16);
}
.prod-add:disabled { opacity: .5; box-shadow: none; }
/* Подтверждение добавления: короткая обратная связь перед возвратом кнопки
   в обычный вид через 1.2 с (таймер в pizza.js). Без неё нажатие выглядит
   как игнорированное — корзина обновится, а экран не подаст знака. */
.prod-add.done { background: var(--ok); }
/* Товар в стоп-листе: кнопка гаснет, и под ней объясняется почему. */
.prod-add[data-state="out"] { background: var(--hint); }
/* Не хватает обязательного шага: кнопка остаётся активной, но окрашена иначе —
   нажать можно, и тогда toast объяснит, что выбрать. */
.prod-add[data-state="wait"] { background: var(--hint); }
/* Подпись под кнопкой: пустая строка не занимает место (в pizza.js она
   заполняется текстом только когда есть что сказать). */
.prod-hint { margin: 0; min-height: 0; font-size: 13px; color: var(--hint); text-align: center; }
.prod-hint:empty { display: none; }

/* ============================================================================
   ПРОФИЛЬ

   Экран собран из новых классов .pf-*, а не из общих .box и .mi: старые стили
   меню рассчитаны на плотный список внутри белой карточки, а здесь крупные
   плитки с цветными подложками и значками в кружках. Общие примитивы не трогаем —
   на них держится остальной интерфейс.

   Значки контурные (profile-glyphs.js): основной словарь рисует их заливкой, и
   рядом с заливкой рядом же смотрелись бы разнородно.
   ============================================================================ */
.pf { display: grid; gap: 12px; padding-bottom: 8px; }

.pf-head { display: flex; align-items: center; justify-content: space-between; min-height: 48px; padding: 4px 2px 10px; }
.pf-head b { font-size: 28px; font-weight: 800; letter-spacing: -.02em; }
.pf-head-btn { width: 44px; height: 44px; display: grid; place-items: center; border-radius: 12px; color: var(--fg); transition: background .16s, transform .12s; }
.pf-head-btn:active { background: var(--card); transform: scale(.94); }

/* --- Карточка человека ---------------------------------------------------- */
.pf-hero { display: flex; align-items: center; gap: 14px; width: 100%; padding: 16px 18px; background: var(--surface); border: 1px solid var(--edge); border-radius: 22px; box-shadow: 0 8px 24px rgba(20, 37, 74, .06); text-align: left; }
button.pf-hero:active { background: var(--card); }
.pf-avatar { flex: none; width: 60px; height: 60px; display: grid; place-items: center; border-radius: 50%; background: var(--pf-blue); color: var(--accent); font-size: 26px; font-weight: 800; }
.pf-hero-text { display: grid; gap: 2px; min-width: 0; }
.pf-hero-text b { font-size: 19px; font-weight: 800; letter-spacing: -.01em; }
.pf-hero-text small { color: var(--hint); font-size: 14px; }
.pf-verified { margin-left: auto; flex: none; display: inline-flex; align-items: center; gap: 4px; padding: 5px 10px; border-radius: 999px; background: var(--pf-mint); color: var(--ok); font-size: 12px; font-weight: 700; }

/* --- Статистика ----------------------------------------------------------- */
.pf-stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.pf-stat { display: grid; justify-items: center; gap: 2px; padding: 14px 8px; background: var(--surface); border: 1px solid var(--edge); border-radius: 20px; box-shadow: 0 8px 24px rgba(20, 37, 74, .06); text-align: center; }
.pf-stat-ico { display: grid; place-items: center; width: 36px; height: 36px; margin-bottom: 4px; border-radius: 50%; background: var(--pf-blue); color: var(--accent); }
.pf-stat b { font-size: 22px; font-weight: 800; line-height: 1.1; font-variant-numeric: tabular-nums; }
.pf-stat > span:last-child { color: var(--hint); font-size: 12px; font-weight: 600; line-height: 1.25; }

/* --- Плитки-призыглашения ------------------------------------------------- */
.pf-promo { position: relative; display: grid; gap: 6px; padding: 18px; border-radius: 22px; overflow: hidden; }
.pf-promo-blue { background: var(--pf-blue); }
.pf-promo-lilac { background: var(--pf-lilac); }
.pf-promo-mint { background: var(--pf-mint); }
.pf-promo-ico { display: grid; place-items: center; width: 46px; height: 46px; border-radius: 50%; background: color-mix(in srgb, var(--surface) 80%, transparent); color: var(--accent); }
/* Декоративный значок на фоне: полупрозрачный, не перехватывает нажатия. */
.pf-promo-deco { position: absolute; top: 14px; right: 14px; opacity: .14; color: var(--fg); pointer-events: none; }
.pf-promo b { position: relative; font-size: 18px; font-weight: 800; line-height: 1.25; letter-spacing: -.01em; }
.pf-promo-note { position: relative; margin: 0; max-width: 78%; color: var(--hint); font-size: 13px; font-weight: 500; }
.pf-promo-btn { position: relative; justify-self: start; display: inline-flex; align-items: center; gap: 2px; min-height: 44px; margin-top: 4px; padding: 0 16px; border-radius: 999px; background: var(--surface); color: var(--accent); font-size: 14px; font-weight: 700; box-shadow: 0 4px 12px rgba(20, 37, 74, .08); }
.pf-promo-btn:active { transform: scale(.98); }

/* --- Меню ----------------------------------------------------------------- */
.pf-toggle { display: flex; align-items: center; justify-content: center; gap: 4px; min-height: 48px; border-radius: 16px; background: var(--surface); border: 1px solid var(--edge); color: var(--accent); font-size: 15px; font-weight: 700; }
.pf-toggle .ico { transition: transform .2s ease; }
.pf-toggle[aria-expanded="true"] .ico { transform: rotate(90deg); }
.pf-rows { display: grid; gap: 2px; padding: 6px; margin-top: 12px; background: var(--surface); border: 1px solid var(--edge); border-radius: 22px; box-shadow: 0 8px 24px rgba(20, 37, 74, .06); }
.pf-row { display: flex; align-items: center; gap: 12px; width: 100%; min-height: 56px; padding: 8px 12px; border-radius: 18px; text-align: left; transition: background .16s; }
.pf-row:active { background: var(--card); }
.pf-row > .ico { flex: none; margin-left: auto; color: var(--hint); }
.pf-row-ico { flex: none; width: 24px; height: 24px; display: grid; place-items: center; color: var(--fg); }
.pf-badge { flex: none; margin-left: auto; padding: 3px 10px; border-radius: 999px; background: var(--card); color: var(--hint); font-size: 13px; font-weight: 700; }
.pf-row > .ico { margin-left: 0; }
.pf-row-text { display: grid; gap: 2px; min-width: 0; }
.pf-row-text b { font-size: 15px; font-weight: 600; }
.pf-tone-blue { background: var(--pf-blue); color: var(--accent); }
.pf-tone-lilac { background: var(--pf-lilac); color: #7c5cf0; }
.pf-tone-mint { background: var(--pf-mint); color: var(--ok); }
.pf-tone-sun { background: #fff3e0; color: #e8590c; }
.pf-tone-slate { background: var(--card); color: var(--hint); }
.pf-row-text { display: grid; gap: 2px; min-width: 0; }
.pf-row-text b { font-size: 15px; font-weight: 700; }
.pf-row-text small { color: var(--hint); font-size: 13px; font-weight: 500; }

/* --- Выход и подвал -------------------------------------------------------- */
.pf-logout { margin: 0; min-height: 52px; border-radius: 16px; font-weight: 700; }
.pf-foot { margin: 4px 0 0; color: var(--hint); font-size: 13px; font-weight: 500; text-align: center; opacity: .85; }

@media (prefers-reduced-motion: reduce) {
  .pf-head-btn, .pf-promo-btn, .pf-row, .pf-toggle .ico { transition: none; }
}

/* ============================================================================
   ORCHIDEYA brand styling & polish
   ============================================================================ */
.home-head { display: flex; align-items: center; justify-content: space-between; padding: 4px 2px 10px; }
.home-head b { font-size: 26px; font-weight: 800; letter-spacing: -0.02em; line-height: 1.1; }
.home-head small { display: flex; align-items: center; gap: 4px; color: var(--hint); font-size: 13px; margin-top: 2px; }
.home-gear { width: 40px; height: 40px; display: grid; place-items: center; border-radius: 50%; color: var(--fg); transition: background .15s, transform .12s; }
.home-gear:active { background: var(--edge); transform: scale(.92); }

.banners { margin: 2px 0 12px; }
.banners-track { display: flex; gap: 10px; overflow-x: auto; scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch; scrollbar-width: none; overscroll-behavior-x: contain; }
.banners-track::-webkit-scrollbar { display: none; }
.banner { position: relative; flex: 0 0 86%; aspect-ratio: 16 / 9; scroll-snap-align: start; overflow: hidden; padding: 0; border-radius: 18px; background: var(--card); border: 1px solid var(--edge); box-shadow: 0 4px 16px rgba(0, 0, 0, .06); display: grid; place-items: stretch; transition: transform .12s, filter .12s; }
.banner img { width: 100%; height: 100%; object-fit: cover; display: block; }
.banner:active img { filter: brightness(.92); }

.chips { display: flex; gap: 8px; overflow-x: auto; padding: 4px 2px 12px; scrollbar-width: none; border-bottom: 0; margin-bottom: 8px; }
.chips::-webkit-scrollbar { display: none; }
.cat-chip { flex: none; display: flex; align-items: center; gap: 4px; padding: 8px 14px; border-radius: 999px; background: var(--surface); border: 1px solid var(--edge); color: var(--fg); font-size: 14px; font-weight: 600; white-space: nowrap; transition: background .15s, border-color .15s, color .15s; margin-bottom: 0; }
.cat-chip .chev { font-style: normal; margin-left: 2px; opacity: .55; font-size: 13px; line-height: 1; }
.cat-chip:active { background: var(--card); }
.cat-chip.on { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }

.category-heading { display: flex; align-items: center; justify-content: space-between; padding: 6px 2px 8px; margin-top: 6px; }
.category-heading .sec-title { font-size: 20px; font-weight: 800; letter-spacing: -0.01em; margin: 0; }
.category-heading .cat-all { display: flex; align-items: center; gap: 2px; color: var(--accent); font-size: 14px; font-weight: 700; padding: 4px 8px; border-radius: 8px; transition: background .15s; }
.category-heading .cat-all:active { background: color-mix(in srgb, var(--accent) 12%, transparent); }
.category-heading .cat-all .chev { font-style: normal; margin-left: 2px; font-size: 14px; }

.items { border: 0; background: none; padding: 0; }
.catalog-items { display: flex; gap: 10px; padding: 2px 2px 12px; background: transparent; border-radius: 0; overflow-x: auto; scroll-snap-type: x proximity; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
.catalog-items::-webkit-scrollbar { display: none; }
.catalog-items li.item { flex: 0 0 168px; scroll-snap-align: start; }
.cat-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; padding: 0; background: none; }

.pcard { position: relative; display: flex; flex-direction: column; align-items: stretch; gap: 6px; padding: 10px; background: var(--surface); border: 1px solid var(--edge); border-radius: 18px; box-shadow: 0 2px 8px rgba(0, 0, 0, .04); transition: transform .12s, box-shadow .12s; }
.pcard:last-child { border-bottom: 1px solid var(--edge); }
.pcard .pic { position: relative; width: 100%; aspect-ratio: 3 / 2; border-radius: 12px; overflow: hidden; background: var(--card); }
.pcard .pic img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pcard .name { font-size: 14px; font-weight: 700; line-height: 1.25; margin-top: 2px; overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; }
.pcard .card-meta { margin: 0; font-size: 12px; color: var(--hint); }
.pcard .card-foot { display: flex; align-items: center; justify-content: space-between; gap: 6px; margin-top: auto; padding-top: 4px; }
.pcard .price { font-size: 15px; font-weight: 800; color: var(--fg); white-space: nowrap; }
.pcard .add-plus { flex: none; width: 34px; height: 34px; min-width: 34px; min-height: 34px; display: grid; place-items: center; border-radius: 10px; background: var(--accent); color: var(--on-accent); transition: transform .12s; }
.pcard .add-plus:active { transform: scale(.92); }
.pcard .step { flex: none; display: flex; align-items: center; background: var(--card); border-radius: 10px; overflow: hidden; }
.pcard .step button { width: 30px; height: 34px; min-width: 30px; min-height: 34px; display: grid; place-items: center; font-size: 16px; color: var(--fg); }
.pcard .step button:active { background: var(--edge); }
.pcard .step span { min-width: 18px; text-align: center; font-size: 13px; font-weight: 700; }

.primary, .add { min-height: 50px; font-size: 15px; font-weight: 700; border-radius: 16px; }
.primary:active { filter: brightness(.94); }

:root[data-theme="dark"] .tabs { background: #222321; border-color: #363733; }

