/* Своя тема оформления: палитра светлая (по умолчанию) и тёмная (атрибут data-theme на <html> ставит session.applyScheme()).
   Если Telegram передал --tg-theme-*, они по-прежнему сильнее: палитра нужна там, где Telegram-темы нет (браузер, PWA, переход между адресами). */
:root{--p:#E63946;--a:#FFB703;--r:14px;--pal-bg:#fff;--pal-tx:#1b1b1f;--pal-hint:#80808a;--pal-card:#f3f3f6;--pal-ln:rgba(128,128,140,.25);--pal-sh:rgba(0,0,0,.16);--bg:var(--tg-theme-bg-color,var(--pal-bg));--tx:var(--tg-theme-text-color,var(--pal-tx));--hint:var(--tg-theme-hint-color,var(--pal-hint));--card:var(--tg-theme-secondary-bg-color,var(--pal-card));--ln:var(--pal-ln);--sh:var(--pal-sh);--ok:#2e9e5b;--no:#d64545;color-scheme:light;font-family:system-ui,-apple-system,"Segoe UI",Roboto,sans-serif}
:root[data-theme=dark]{--pal-bg:#14141a;--pal-tx:#f1f1f5;--pal-hint:#9b9ba6;--pal-card:#1e1e26;--pal-ln:rgba(180,180,200,.22);--pal-sh:rgba(0,0,0,.6);color-scheme:dark}
/* Системная настройка — запасной путь: страницы без JS (панель платформы) и самый первый кадр до выбора темы. */
@media (prefers-color-scheme:dark){:root:not([data-theme=light]){--pal-bg:#14141a;--pal-tx:#f1f1f5;--pal-hint:#9b9ba6;--pal-card:#1e1e26;--pal-ln:rgba(180,180,200,.22);--pal-sh:rgba(0,0,0,.6);color-scheme:dark}}
*{box-sizing:border-box;margin:0;-webkit-tap-highlight-color:transparent}
/* Патч T28e: атрибут hidden должен работать всегда. Наши правила вида display:flex сильнее встроенного [hidden]{display:none},
   из-за чего «спрятанные» блоки формы промокода (строка выбора, полоса «Сколько раз на человека») оставались видимыми. */
[hidden]{display:none !important}
body{background:var(--bg);color:var(--tx);padding-bottom:var(--bar-h,env(safe-area-inset-bottom));min-height:100vh}   /* запас снизу = реальная высота нижнего блока (--bar-h), а не «магическое» число */
button{font:inherit;color:inherit;border:0;background:none;cursor:pointer}
input,textarea{font:inherit;color:inherit;background:var(--card);border:1px solid var(--ln);border-radius:var(--r);padding:12px;width:100%}
.top{padding:18px 16px 8px}.top h1{font-size:22px}.top small{color:var(--hint)}
.banner{margin:8px 16px;padding:12px;border-radius:var(--r);background:var(--card);border-left:4px solid var(--a)}
/* Патч U6.1: заглушка загрузки — простой текст по центру окна, а НЕ карточка-предупреждение. Раньше стартовая
   заглушка магазина и заглушки мастера /start использовали .banner (серый фон, скругление, жёлтая кромка слева).
   Цвет — второстепенный текст темы (--hint, та же переменная, что у .mut). На компьютере «окно-телефон» (#app) —
   flex-колонка, первый ребёнок растёт (flex:1 0 auto), поэтому текст встаёт ровно по центру окна. */
.loading{flex:1 0 auto;display:grid;place-items:center;color:var(--hint);text-align:center;padding:24px 16px}
.cats{display:flex;gap:8px;overflow-x:auto;padding:8px 16px;position:sticky;top:0;background:var(--bg);z-index:5;scrollbar-width:none}
.chip{padding:8px 14px;border-radius:99px;background:var(--card);white-space:nowrap;font-size:14px}.chip.on{background:var(--p);color:#fff}
h2{font-size:18px;margin:18px 16px 8px}
.grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;padding:0 16px}
.item{background:var(--card);border-radius:var(--r);overflow:hidden;text-align:left;display:flex;flex-direction:column;cursor:pointer}
.pic{position:relative}.item img,.ph{width:100%;aspect-ratio:1/1;object-fit:cover;background:var(--ln);display:grid;place-items:center;font-size:40px}
.badge{position:absolute;top:8px;right:8px;min-width:24px;height:24px;border-radius:99px;background:var(--p);color:#fff;font-size:13px;font-weight:700;display:grid;place-items:center;padding:0 6px}
.item .b{padding:10px;display:flex;flex-direction:column;gap:4px;flex:1}.item .t{font-weight:600;font-size:15px;line-height:1.25}
.item .d{font-size:12px;color:var(--hint);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.buy{margin-top:auto;padding-top:6px;display:flex;flex-direction:column;gap:8px}
.add{background:var(--bg);border:1.5px solid var(--p);color:var(--p);border-radius:99px;padding:8px 10px;font-weight:600;font-size:14px;width:100%}
.item .qty{justify-content:space-between;gap:4px;background:var(--bg);border-radius:99px;padding:3px}
.item .qty button{background:var(--p);color:#fff}
.tiles{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;padding:8px 16px}
.tile{background:var(--card);border-radius:var(--r);overflow:hidden;text-align:left;display:flex;flex-direction:column;padding-bottom:10px}
.tile img,.tile .ph{width:100%;aspect-ratio:4/3;object-fit:cover}.tt{font-weight:700;font-size:16px;padding:10px 12px 2px}.tile .mut{padding:0 12px}
img.big{width:100%;max-height:220px;object-fit:cover;border-radius:var(--r)}
.qn{width:52px!important;text-align:center;padding:6px 2px!important;font-weight:700;background:transparent!important;border:0!important;-moz-appearance:textfield}
.qn::-webkit-outer-spin-button,.qn::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.price{font-weight:700;margin-top:auto}.sold{opacity:.5}
.btn{background:var(--p);color:#fff;padding:14px;border-radius:var(--r);font-weight:600;width:100%;text-align:center}.btn.sec{background:var(--card);color:var(--tx)}.btn.sm{padding:9px 14px;width:auto;font-size:14px}.btn[disabled]{opacity:.5}
.sechead{display:flex;align-items:flex-start;gap:12px;padding:14px 16px 8px}   /* строка заголовка подраздела: круглая кнопка «Назад» слева, заголовок справа; flex-start держит круг у первой строки при переносе */
.backnav{position:relative;flex:none;width:40px;height:40px;display:grid;place-items:center;margin:-6px 0 0;border-radius:50%;color:var(--tx);background:color-mix(in srgb,var(--tx) 12%,var(--bg))}   /* видимый круг 40×40 у левого края контента, стрелка 22px по центру, цвет и фон из темы */
.backnav::after{content:'';position:absolute;inset:-2px;border-radius:50%}   /* зона нажатия невидимо расширена до 44×44 */
.backnav:active{filter:brightness(.92)}   /* отклик: фон круга чуть темнее, без акцента */
.sechead h1{font-size:24px;font-weight:700}.sechead small{color:var(--hint)}   /* заголовок 24px/700; подзаголовок ровно под началом его текста */
/* ── Нижний блок страницы магазина: ОДИН закреплённый контейнер — сверху кнопка «Корзина», под ней меню.
   Зазор 8px задаёт сам контейнер, поэтому кнопка стоит РОВНО над меню любой высоты (2 или 5 вкладок, шрифт,
   полоса жеста) — прежнее жёсткое смещение кнопки от низа больше не нужно. Зазор сквозной для нажатий. ── */
.bottombar{position:fixed;left:0;right:0;bottom:0;z-index:20;display:flex;flex-direction:column;gap:8px;pointer-events:none}
.bottombar>*{pointer-events:auto}
.bar{position:fixed;left:0;right:0;bottom:0;background:var(--bg);border-top:1px solid var(--ln);padding:8px 12px calc(8px + env(safe-area-inset-bottom));z-index:20}
.bottombar .bar{position:static;left:auto;right:auto;bottom:auto}   /* в контейнере меню лежит в потоке: своё место ему больше не нужно */
.nav{display:flex}.nav button{flex:1;padding:8px 2px;font-size:12px;color:var(--hint);display:flex;flex-direction:column;align-items:center;gap:2px}.nav button.on{color:var(--p)}.nav span{font-size:20px}
.cartbar{margin:0 12px}   /* положение кнопки «Корзина» задаёт контейнер, своих отступов от низа у неё нет */
.sheet{position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:30;display:flex;align-items:flex-end}
.sheet>div{background:var(--bg);width:100%;max-height:92vh;overflow:auto;border-radius:20px 20px 0 0;padding:16px;display:flex;flex-direction:column;gap:12px}
.row{display:flex;justify-content:space-between;align-items:center;gap:10px}
.grp{background:var(--card);border-radius:var(--r);padding:10px;display:flex;flex-direction:column;gap:6px}.grp label{display:flex;justify-content:space-between;padding:6px 0}
.qty{display:flex;align-items:center;gap:6px}.qty button{width:36px;height:36px;border-radius:50%;background:var(--card);font-size:20px;flex:none}
.qtybox{display:flex;flex-direction:column;gap:2px;min-width:0}
.card{background:var(--card);border-radius:var(--r);padding:12px;margin:10px 16px;display:flex;flex-direction:column;gap:8px}
.st{font-size:12px;padding:3px 10px;border-radius:99px;background:var(--a);color:#222}
.opts{display:flex;gap:8px;flex-wrap:wrap}.opts .chip{flex:1;text-align:center}
.mut{color:var(--hint);font-size:13px}.ok{color:var(--ok)}.no{color:var(--no)}.err{color:#d00;font-size:14px}.was{color:var(--hint);font-size:13px;text-decoration:line-through}
/* ── Патч U5: ошибки в форме оформления заказа. Цвета — из существующей переменной темы --no,
   поэтому подсветка одинаково читается в светлой и тёмной теме (новых цветов не вводим). ── */
input.bad,textarea.bad,label.bad{color:var(--no)}
input.bad,textarea.bad{border-color:var(--no)}
.err.hint{color:var(--no);font-size:12px;margin-top:2px}
#toast{position:fixed;top:12px;left:50%;transform:translateX(-50%);background:#222;color:#fff;padding:10px 16px;border-radius:12px;z-index:50;opacity:0;transition:.25s;pointer-events:none;max-width:90vw}#toast.on{opacity:1}
select{font:inherit;color:inherit;background:var(--card);border:1px solid var(--ln);border-radius:var(--r);padding:12px;width:100%}
.fl{display:flex;flex-direction:column;gap:4px;font-size:13px;color:var(--hint)}.fl.ck{flex-direction:row;align-items:center;justify-content:space-between;color:var(--tx);font-size:15px}
input[type=color]{padding:2px;height:44px}textarea{resize:vertical}.btn.dg{background:#c62828;color:#fff}
.chat{display:flex;flex-direction:column;gap:8px;padding:8px 16px}
.bub{max-width:90%;padding:10px 12px;border-radius:var(--r);background:var(--card);white-space:pre-wrap;word-break:break-word;font-size:15px;line-height:1.35}
.chat.pad{padding-bottom:96px}.chat>*{scroll-margin-bottom:96px}
.bub.me{align-self:flex-end;background:var(--p);color:#fff}.bub.wait{color:var(--hint)}
.rate{display:flex;gap:6px;margin-top:6px}.rate button{font-size:15px;padding:2px 8px;border-radius:99px;background:var(--bg);opacity:.75}.rate button.on{opacity:1;outline:2px solid var(--a)}
.ask{display:flex;gap:8px;padding:8px 16px;align-items:flex-end}.ask textarea{min-height:46px;max-height:140px;resize:none}.ask .btn{width:auto;padding:12px 16px}
.plate{margin:8px 16px;padding:12px;border-radius:var(--r);background:var(--card);border-left:4px solid #2e9e5b;display:flex;justify-content:space-between;align-items:center;gap:10px}.plate.warn{border-left-color:var(--a)}
/* Приветствие после создания магазина (N2b): тёплая карточка БЕЗ левой полосы (такой вид у заглушки «Загрузка…»
   мы убрали как «карточку-предупреждение»): рамка по периметру, крупный эмодзи и заголовок, кнопка на всю ширину.
   Всё на переменных темы — светлая и тёмная работают одинаково. */
.greet{margin:8px 16px;padding:16px;border-radius:var(--r);background:var(--card);border:1px solid var(--ln);display:flex;flex-direction:column;gap:10px}
.greet-emoji{font-size:32px;line-height:1}
.greet-t{font-size:15px;line-height:1.5}
.greet .btn{width:100%}
/* Плашка «Заказы пока некуда присылать» (N2b): текст-кнопка слева, действия справа. */
.plate-t{flex:1;min-width:0;text-align:left;display:flex;flex-direction:column;gap:2px}
.plate-a{display:flex;align-items:center;gap:10px;flex:none}
/* Новый верх «Управления» (патч U1): всё на переменных темы — светлая и тёмная работают одинаково. */
.subline{display:flex;justify-content:space-between;align-items:center;gap:10px;margin:8px 16px;font-size:13px;color:var(--hint)}
.subline.warn{color:var(--p);font-weight:600}
.lnk{color:var(--p);font-weight:600;font-size:13px}
.toplink{color:var(--p);font-weight:600;font-size:14px;white-space:nowrap}
.dot{display:inline-block;width:9px;height:9px;border-radius:50%;background:var(--ok);margin-right:6px;vertical-align:middle}
.dot.closed{background:var(--no)}
.shopurl{flex:1;min-width:0;text-align:left;color:inherit;font-size:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* Компактная карточка магазина: адрес в тонком поле, «Копировать» красным справа внутри поля, каналы тонкой строкой. */
.urlfield{display:flex;align-items:center;gap:8px;background:var(--ln);border-radius:8px;padding:6px 10px}
.shopurl-copy{flex:none;color:var(--p);font-size:12px;font-weight:600}
.card.compact{gap:6px;padding:10px 12px}
.stline{display:flex;align-items:center;font-size:13px;color:var(--hint)}
.chans{margin-top:2px}
.chans>summary{display:flex;align-items:center;gap:6px;list-style:none;cursor:pointer;font-size:13px;color:var(--hint)}
.chans>summary::-webkit-details-marker{display:none}
.chsum{flex:1;min-width:0;display:flex;align-items:center;overflow:hidden;white-space:nowrap}
.chnames{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.chrest{flex:none}
.chev{flex:none;opacity:.7}
.chanlist{display:flex;flex-direction:column;gap:2px;margin-top:6px}
.chan{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:6px 2px;font-size:13px;border-top:1px solid var(--ln)}
.dangerlink{display:block;margin:16px;padding:6px 0;color:var(--hint);font-size:13px;text-decoration:underline;text-align:left}
.cp{display:flex;justify-content:space-between;align-items:center;gap:10px;width:100%;text-align:left;background:var(--card);border-radius:var(--r);padding:12px}.cp>span:first-child{display:flex;flex-direction:column;gap:2px;min-width:0;word-break:break-word}.cp b{font-size:17px}.cpb{font-size:13px;color:var(--p);white-space:nowrap;font-weight:600}
.step{display:flex;flex-direction:column;gap:8px}
.per{display:flex;justify-content:space-between;align-items:center;gap:10px;background:var(--card);border-radius:var(--r);padding:16px;text-align:left;width:100%}
.fl.bad>input,.fl.bad>select,.fl.bad>textarea,.fl.bad>.grp{border-color:#e53935!important;background:rgba(229,57,53,.10)!important;box-shadow:0 0 0 2px rgba(229,57,53,.25)}
.fl.bad{color:#e53935}.fe{color:#e53935;font-size:13px;font-weight:600}

.blk{margin:10px 16px;background:var(--card);border-radius:var(--r);overflow:hidden}
.blk>summary{padding:14px;font-weight:700;cursor:pointer;list-style:none;display:flex;justify-content:space-between}
.blk>summary::after{content:'⌄';opacity:.6}.blk[open]>summary::after{content:'⌃'}
.blk>summary::-webkit-details-marker{display:none}
.blk .per{width:100%;border-radius:0;border-top:1px solid rgba(128,128,128,.18);margin:0;background:transparent}
.blk>.card{margin:10px 0}

.sw{position:relative;display:inline-block;width:52px;height:32px;flex:none}
.sw input{opacity:0;width:0;height:0;position:absolute}
.sw span{position:absolute;inset:0;background:var(--ln);border-radius:16px;transition:.25s;cursor:pointer}
.sw span::before{content:'';position:absolute;width:26px;height:26px;left:3px;top:3px;background:#fff;border-radius:50%;transition:.25s}
.sw input:checked+span{background:var(--ok)}.sw input:checked+span::before{transform:translateX(20px)}
.sw input:focus-visible+span{outline:2px solid var(--p);outline-offset:2px}

/* Патч T28b: нижний ряд карточки промокода (тумблер + подпись слева, значки справа) и кнопка-значок не меньше 44 px. */
.promoline{border-top:1px solid var(--ln);padding-top:8px}
.ibtn{min-width:44px;min-height:44px;display:inline-flex;align-items:center;justify-content:center;padding:0!important}

/* Патч T28b.2: выключенный промокод гасим не целиком, а только информационные части (код, значок, «Использовано…»,
   условия). Приглушение задаём ЦВЕТОМ, а не opacity: тумблер и кнопки остаются обычной яркости, а смесь основного
   текста с фоном карточки читается и в тёмной, и в светлой теме (контраст ≥ 4.5:1). Идут ПОСЛЕ .mut/.no, поэтому
   у выключенного промокода цвет приглушения берёт верх. */
.card.promo-off{background:color-mix(in srgb,var(--card) 92%,#000)}   /* фон карточки чуть темнее */
.promo-dim{color:color-mix(in srgb,var(--tx) 66%,var(--card))}
.st.promo-dim{background:color-mix(in srgb,var(--a) 65%,var(--card));color:#222}   /* значок тусклее, а тёмный текст на нём читается (≥4.5:1) */
.ibtn.link{color:var(--p)}   /* значок-ссылка: лёгкий акцентный оттенок темы (как акцент промокодов) */

/* Шторка «Ссылка со скидкой»: ссылка — обычный блок текста (видна целиком, на сколько нужно строк; нажатие копирует),
   «Закрыть» — лёгкая текстовая кнопка (без заливки). Фон ссылки чуть темнее листа шторки (var(--bg)). */
.share-link{padding:12px 14px;border-radius:var(--r);background:color-mix(in srgb,var(--bg) 92%,#000);font-size:15px;line-height:1.35;word-break:break-all;user-select:all;cursor:pointer}
.share-close{display:flex;align-items:center;justify-content:center;min-height:44px;color:var(--hint);font-weight:600;background:none}

/* ── Патч T28b.1: блок промокода в корзине. Свёрнутая строка, плавное раскрытие, зелёная плашка успеха.
   Все цвета — из переменных темы, поэтому светлая и тёмная читаются одинаково. Раскрытие ≤200 мс;
   при prefers-reduced-motion анимации нет. ── */
.promo-block{display:flex;flex-direction:column;gap:8px}
.promo-sum{display:flex;justify-content:space-between;align-items:center;gap:10px;width:100%;padding:10px 4px;color:var(--tx);text-align:left;font-weight:600}
.promo-arrow{color:var(--hint);font-size:18px;line-height:1}
.promo-panel{display:flex;flex-direction:column;gap:6px;max-height:0;opacity:0;overflow:hidden;transition:max-height .2s ease,opacity .2s ease}
.promo-panel.on{max-height:200px;opacity:1}
.promo-plaque{display:flex;justify-content:space-between;align-items:center;gap:10px;padding:6px 6px 6px 12px;border-radius:var(--r);background:color-mix(in srgb,var(--ok) 16%,var(--bg));border:1px solid color-mix(in srgb,var(--ok) 45%,var(--ln))}
.promo-code{color:var(--ok);font-weight:700}
.promo-note{font-size:12px}
.dsc{color:var(--ok);font-size:14px}
.total-now{font-size:20px;font-weight:700}
.consent-note{color:var(--hint)}
@media (prefers-reduced-motion:reduce){.promo-panel{transition:none}}

/* ── Патч T28c: промокод «на что действует скидка». Все цвета — из переменных темы (светлая и тёмная). ── */
/* Сегментированная полоса на всю ширину: две равные половины, активная — акцентная (красная). */
.segbar{display:flex;width:100%;border-radius:var(--r);overflow:hidden;background:var(--card);border:1px solid var(--ln)}
.segbar .seg{flex:1;padding:11px 8px;text-align:center;font-size:14px;color:var(--tx)}
.segbar .seg.on{background:var(--p);color:#fff;font-weight:600}
/* Знак % или ₽ внутри поля справа (серым). */
.inbox{position:relative;display:flex}
.inbox input{padding-right:40px}
.inbox .suf{position:absolute;right:12px;top:50%;transform:translateY(-50%);color:var(--hint);pointer-events:none;font-size:14px}
/* Строка-сводка выбора: названия одной строкой с многоточием, справа действие. */
.selrow{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;text-align:left;color:var(--tx);background:var(--card);border:1px solid var(--ln);border-radius:var(--r);padding:11px 12px}
.selrow.bad{border-color:var(--no)}
.scope-names{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.scope-act{flex:none;color:var(--p);font-weight:600;font-size:13px;white-space:nowrap}
/* Шторка выбора: поиск, категории (три состояния), блюда с ценой. */
.scope-search{margin-bottom:2px}
.scope-list{display:flex;flex-direction:column;gap:2px;max-height:52vh;overflow-y:auto}
.cathead{display:flex;align-items:center;gap:8px}
.catrow{flex:1;display:flex;align-items:center;gap:10px;min-height:44px;text-align:left}
.catbox,.prodbox{flex:none;width:22px;height:22px;border-radius:6px;border:1.5px solid var(--ln);display:grid;place-items:center;font-size:14px;color:var(--hint)}
.catbox.on,.prodbox.on{background:var(--p);border-color:var(--p);color:#fff}
.catbox.part{border-color:var(--p);color:var(--p)}
.cattitle{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.catcount{flex:none;font-size:12px}
.chev{flex:none;width:44px;min-height:44px;display:grid;place-items:center;color:var(--hint);cursor:pointer}
.prodrow{display:flex;align-items:center;gap:10px;min-height:44px;padding-left:32px;text-align:left}
.prodtitle{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.prodprice{flex:none;font-size:13px}
.scope-done{margin-top:4px}
/* Патч T28d: «Действует до» — одна треть строки, по левому краю; значок календаря остаётся (выбор даты работает). */
.promo-date{width:34%}
.promo-date input{padding:12px 6px}
/* Патч T28d: тонкая разделительная линия между «Кому доступно» и полями минимума/лимита. */
.promo-div{border-top:1px solid var(--ln)}
/* Патч T28d: код акцентным цветом в шторке «Ссылка со скидкой» (в фразе и в хвосте ссылки). */
.share-code{color:var(--p);font-weight:700}

.ask{position:fixed;left:0;right:0;bottom:var(--bar-h,env(safe-area-inset-bottom));z-index:19;background:var(--bg);border-top:1px solid var(--ln);padding:8px 12px;gap:8px;align-items:flex-end}
.ask textarea{border-radius:22px;padding:11px 16px;min-height:44px;line-height:1.3;overflow-y:auto}
.sendb{flex:none;width:44px;height:44px;border-radius:50%;background:var(--p);color:#fff;font-size:18px;display:flex;align-items:center;justify-content:center}
/* патч 2: тонкая полоска «Нет связи» сверху */
.netbar{position:fixed;left:0;right:0;top:0;z-index:60;background:#222;color:#fff;padding:5px 12px;font-size:13px;text-align:center}

/* ── экраны входа, развилки и шаблонов (без Telegram-темы): тёмное полотно, свои карточки и кнопки ── */
.ns{position:relative;overflow:hidden;background:#0b0b0e;color:#fff;padding:20px 16px calc(26px + env(safe-area-inset-bottom));display:flex;flex-direction:column;gap:14px;min-height:100vh;min-height:100dvh}
.ns>*{position:relative}   /* мягкие серые пятна уходят под содержимое */
.ns::before,.ns::after{content:'';position:absolute;pointer-events:none;border-radius:50%;filter:blur(46px)}
.ns::before{width:320px;height:320px;top:-110px;left:-80px;background:radial-gradient(circle,rgba(168,168,182,.30),transparent 70%)}
.ns::after{width:280px;height:280px;bottom:-120px;right:-90px;background:radial-gradient(circle,rgba(224,34,45,.16),transparent 70%)}
.ns-head{display:flex;flex-direction:column;gap:6px}
.ns-head h1{font-size:26px;font-weight:700;line-height:1.2}
.ns-head p{color:#b6b6bf;font-size:15px;line-height:1.4}
.ns-logo{width:46px;height:46px;border-radius:14px;display:grid;place-items:center;background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.10);color:#e0222d}
.ncard{background:rgba(255,255,255,.045);border:1px solid rgba(255,255,255,.10);border-radius:20px;padding:16px;margin:0;display:flex;flex-direction:column;gap:10px;color:#fff;text-align:left;width:100%}
.ncard-head{display:flex;align-items:center;gap:10px}.ncard-head b{font-size:17px}
.nicon{flex:none;width:38px;height:38px;border-radius:12px;display:grid;place-items:center;background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.10)}
.nmut{color:#b6b6bf;font-size:14px;line-height:1.4}
.nbtn{background:linear-gradient(180deg,#e8141f,#8f0a12);color:#fff;border-radius:16px;padding:15px;font-weight:700;width:100%;text-align:center}
.nbtn.sec{background:#2a2a2e;color:#fff}.nbtn[disabled]{opacity:.45}
.ns-list{display:flex;flex-direction:column;gap:10px}
.npick{flex-direction:row;align-items:center;gap:12px}
.npick-t{display:flex;flex-direction:column;gap:2px;min-width:0}
.ncard.on{border-color:#e0222d;box-shadow:0 0 0 1px #e0222d,0 0 22px rgba(224,34,45,.45)}
.ns-link{color:#b6b6bf;font-size:14px;text-align:left;padding:4px 0;text-decoration:underline}
.ns-note{color:#8d8d96;font-size:13px;text-align:center}
.ns .nfl{display:flex;flex-direction:column;gap:6px;font-size:13px;color:#b6b6bf}
.ns input,.ns textarea{background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.12);border-radius:14px;padding:14px;color:#fff}
.ns input::placeholder{color:#8d8d96}
.ns .err{color:#ff8a8a}

/* ── Патч T26c / T26c.1: страница заказа покупателя (/o/<код>). Цвета берём из переменных темы (--p акцент, --ok
   пройденный шаг, --ln линия, --hint приглушённый текст), новых цветов нет: одинаково в светлой и тёмной теме.
   Имена с префиксом o*, чтобы не задеть класс .step из «Управления». Отступы кратны 4/8/12/16/24 (единая шкала). ── */
.osteps{margin:8px 16px 0;display:flex;flex-direction:column}
.ostep{display:flex;gap:12px;align-items:flex-start;padding:8px 0}
.ostep .odot{flex:none;width:18px;height:18px;margin-top:3px;border-radius:50%;border:2px solid var(--ln);background:var(--bg);position:relative;display:grid;place-items:center;font-size:11px;line-height:1;color:#fff}
.ostep.on .odot{border-color:var(--p);background:var(--p);animation:opulse 1.8s ease-in-out infinite}   /* текущий шаг мягко пульсирует */
.ostep.done .odot{border-color:var(--ok);background:var(--ok)}
.ostep.done .otx b{color:var(--hint);font-weight:600}
.ostep .cap{color:var(--hint);font-size:13px;margin-top:2px}   /* живая подпись под текущим шагом */
/* Линия между шагами: серая дорожка + зелёная заливка, которая плавно «прорастает» вниз при переходе (~400 мс) */
.ostep:not(:last-child) .odot::after{content:'';position:absolute;left:6px;top:17px;width:2px;height:24px;background:var(--ln)}
.ostep.done:not(:last-child) .odot::before{content:'';position:absolute;left:6px;top:17px;width:2px;height:24px;background:var(--ok);transform-origin:top;animation:ofill .4s ease both}
@keyframes ofill{from{transform:scaleY(0)}to{transform:scaleY(1)}}
@keyframes opulse{0%,100%{transform:scale(1)}50%{transform:scale(1.14)}}
/* Кнопки страницы: боковые отступы как у карточки, 24 px от шагов, 12 px между кнопками; главная кнопка акцентная */
.oacts{margin:24px 16px;display:flex;flex-direction:column;gap:12px}
/* Карточка заказа: состав по строкам, доставка отдельной строкой, «Итого» крупно и читаемо на солнце */
.ocard-t{font-size:18px}
.otime{font-size:17px;font-weight:600}
.ocomp{display:flex;flex-direction:column;gap:8px;margin-top:4px}
.orow{display:flex;justify-content:space-between;gap:12px}
.orow .oit{overflow-wrap:anywhere}
.osum{margin-top:4px;padding-top:12px;border-top:1px solid var(--ln);align-items:baseline}
.osum span{font-size:15px;color:var(--hint)}.osum b{font-size:22px}
/* Скелетон загрузки: серая «форма» карточки и шагов вместо пустого экрана (принцип UX №5) */
.oskel{height:12px;border-radius:6px;background:var(--ln);margin:8px 0;animation:osheen 1.4s ease-in-out infinite}
.oskel-card{margin:10px 16px;background:var(--card);border-radius:var(--r);padding:12px}
.oskel-steps{margin:8px 16px}
.oskel-step{display:flex;align-items:center;gap:12px;padding:8px 0}
.oskel-dot{flex:none;width:18px;height:18px;border-radius:50%;background:var(--ln)}
.oskel-step .oskel{flex:1;margin:0}
@keyframes osheen{0%,100%{opacity:1}50%{opacity:.4}}
/* Анимация успеха после оформления: галочка в круге и крупная фраза «Заказ принят» (принцип UX №6) */
.osuccess{margin:16px 16px 0;padding:24px 16px;border-radius:var(--r);background:var(--card);display:flex;flex-direction:column;align-items:center;gap:12px}
.osuccess-ic{width:72px;height:72px;border-radius:50%;background:var(--ok);color:#fff;display:grid;place-items:center;font-size:40px;line-height:1;animation:opop .5s ease both}
.osuccess-t{font-size:24px;font-weight:700;animation:opop .5s .1s ease both}
@keyframes opop{from{transform:scale(.6);opacity:0}to{transform:scale(1);opacity:1}}
/* Экран «ссылки больше нет»: спокойный, понятный, с кнопкой «В меню» (принцип UX №5 — нет тупиков) */
.onf{margin:16px;padding:24px;border-radius:var(--r);background:var(--card);display:flex;flex-direction:column;gap:12px}
.onf-ic{font-size:32px}
.onf-t{font-size:20px;font-weight:700;margin:0}
/* Уважаем настройку «меньше движения»: анимации выключаем, содержимое остаётся на месте (принцип UX №8) */
@media (prefers-reduced-motion:reduce){
  .ostep.on .odot,.ostep.done:not(:last-child) .odot::before,.oskel,.osuccess-ic,.osuccess-t{animation:none}
}


/* ── Патч U8: магазин на телефоне (ширина экрана до 700 px) — страница ровно в размер ЭКРАНА.
   Причина (владелец, скриншот в Chrome на телефоне): (1) справа у самого края тонкая светлая вертикальная линия
   и пустой зазор ~3-4 px; (2) страница прокручивается, хотя содержимого мало.
   Отчего: body задавал min-height:100vh, а 100vh на телефоне — высота «как будто адресная строка спрятана»,
   то есть БОЛЬШЕ видимой части экрана. Страница всегда получалась выше экрана — отсюда лишняя прокрутка и
   собственная ПОЛОСА ПРОКРУТКИ браузера у правого края (Chrome в мобильном виде рисует её в нескольких
   пикселях от края: та самая «линия» и зазор). 100dvh — высота ВИДИМОЙ части экрана. Строка со 100vh оставлена
   ПЕРВОЙ как запасной вариант для старых браузеров (dvh они не знают и берут прежнее значение).
   Ширина задана в процентах: тело страницы и #app занимают ровно ширину экрана, без зазоров.
   Правило целиком в медиа-запросе до 700 px, поэтому «окно-телефон» (блок U6 ниже, от 700 px: 390 px, срез
   8 px, рамка, тень, тёмная тема) не меняется вообще. Внутри Telegram те же правила дают тот же вид: в его
   окне динамических панелей браузера нет, значит dvh равно vh. Класс shop стоит прямо в разметке страницы
   (frontend/index.html), поэтому правило работает и в первый кадр — на «Загрузке…» и на тёмных экранах. ── */
@media (max-width:699.98px){
  body.shop{min-height:100vh;min-height:100dvh;width:100%;max-width:100%}   /* высота — по видимой части, ширина — по экрану */
  body.shop #app{width:100%;max-width:100%}                                  /* содержимое тянется на всю ширину, зазора справа нет */
  /* Тёмные экраны (.ns: вход, «Откройте заново», ошибки) несут свою кнопку внизу и нижнего меню не имеют,
     поэтому запас под меню им не нужен: без этого под экраном остаётся пустая полоса и лишняя прокрутка.
     Селектор :has() старые браузеры не знают — там правило просто не применится. */
  body.shop:has(#app>.ns){padding-bottom:0}
}

/* ── Патч U6: магазин по ссылке в браузере — «окно-телефон» на компьютере. Срабатывает только от 700 px
   и только на странице магазина (class="shop" на <body> в frontend/index.html): мастер /start и панель
   платформы остаются во всю ширину, а телефон правило не затрагивает вовсе (оно целиком в медиа-запросе) —
   на телефоне магазин по-прежнему занимает весь экран.
   Почему так: раньше на компьютере приложение было колонкой 560 px ВО ВСЮ высоту окна браузера — получалась
   узкая полоса с пустотой внизу, а не экран смартфона. Теперь это компактное окно по центру со СВОЕЙ прокруткой
   внутри: как окно мини-аппа. Размер окна задан числами ниже (--ph-w и --ph-nat), углы — --ph-r (править их просто).
   Высоты считаем в vh, а не dvh: правило работает только на широком экране компьютера, где 100vh и есть видимая
   высота окна (динамических панелей браузера там нет). Тема (светлая/тёмная) берётся из настроек браузера. ── */
@media (min-width:700px){
  /* размер «окна-телефона»: --ph-nat — высота от природы, --ph-h — она же, но не выше экрана;
     --ph-r — срез углов (небольшой, как у окна Telegram: тем же радиусом срезаны плашки и шторки);
     --ph-top — тот же верх окна для элементов, которые живут в <body> и рамку не видят. */
  body.shop{--ph-w:min(390px,calc(100vw - 32px));--ph-nat:880px;--ph-h:min(var(--ph-nat),calc(100vh - 32px));--ph-r:8px;--ph-top:max(16px,calc((100vh - var(--ph-nat)) / 2));
    background:var(--card);display:grid;place-items:center;padding-bottom:0}   /* фон вокруг окна спокойный, из переменных темы */
  /* Окно телефона: своя прокрутка ВНУТРИ, тонкая рамка цветом линий темы и широкая мягкая тень.
     flex-колонка нужна, чтобы содержимое занимало свободное место, а нижние плашки уходили в самый низ ОКНА. */
  body.shop #app{width:var(--ph-w);height:var(--ph-h);display:flex;flex-direction:column;overflow:auto;
    overscroll-behavior:contain;background:var(--bg);border:1px solid var(--ln);border-radius:var(--ph-r);box-shadow:0 18px 80px var(--sh)}
  body.shop #app>:first-child{flex:1 0 auto}   /* содержимое вкладки заполняет окно, плашки прижимаются вниз */
  /* Нижний блок (кнопка «Корзина» + меню) больше не крепится к краям БРАУЗЕРА: он липнет к низу ОКНА
     (position:sticky внутри #app). Углы, которыми он касается краёв окна, срезаны тем же радиусом, что и само
     окно, — за срезанные углы ничего не вылезает. Внутри контейнера кнопка и меню лежат в потоке. */
  body.shop .bottombar{position:sticky;bottom:0;left:auto;right:auto;flex:0 0 auto}
  body.shop .bottombar .bar{position:static;left:auto;right:auto;bottom:auto;border-radius:0 0 var(--ph-r) var(--ph-r)}   /* нижнее меню — низ окна */
  body.shop .bottombar .cartbar{position:static;left:auto;right:auto;bottom:auto;margin:0 12px;border-radius:var(--ph-r)}
  body.shop .ask{position:sticky;bottom:var(--bar-h,env(safe-area-inset-bottom));left:auto;right:auto;flex:0 0 auto;border-radius:var(--ph-r)}   /* композер помощника — над нижним блоком */
  /* Полоска «Нет связи», всплывающая подсказка и шторки живут в <body> (не в #app) — привязываем их к геометрии окна. */
  body.shop .netbar{left:50%;right:auto;transform:translateX(-50%);width:var(--ph-w);top:var(--ph-top);border-radius:var(--ph-r) var(--ph-r) 0 0}   /* полоска — верх окна */
  body.shop #toast{top:calc(var(--ph-top) + 12px);left:50%;transform:translateX(-50%);max-width:min(460px,90vw)}
  body.shop .sheet{inset:auto;left:50%;top:50%;transform:translate(-50%,-50%);width:var(--ph-w);height:var(--ph-h);border-radius:var(--ph-r);overflow:hidden}
  body.shop .sheet>div{max-height:92%;border-radius:var(--ph-r) var(--ph-r) 0 0}
  body.shop .ns{min-height:100%}   /* тёмные экраны входа/ошибок — по высоте окна, а не всего монитора */
}

.card-link{cursor:pointer}
.card-link:focus-visible{outline:2px solid var(--p);outline-offset:2px}

