/* ============================================================
   Пироги по-домашнему, Халяль — демо VisualVibe
   Концепт «Дастархан»: тепло восточного дома + свежий каркас
   ============================================================ */

:root {
  --bg:            #FBF4E9;
  --bg-soft:       #F5EBDB;
  --card:          #FFFDF8;
  --burgundy:      #88080B;
  --burgundy-hover:#A01115;
  --burgundy-deep: #5C0A0E;
  --burgundy-ink:  #3D060A;
  --gold:          #C9973F;
  --gold-soft:     #E6BD71;
  --gold-pale:     #F3E3C3;
  --green:         #1E7A46;
  --ink:           #2B1810;
  --ink-soft:      #7A6353;
  --white:         #FFFFFF;
  --shadow-card:   0 2px 10px rgba(92, 10, 14, .05), 0 10px 32px rgba(92, 10, 14, .08);
  --shadow-hover:  0 6px 16px rgba(92, 10, 14, .10), 0 22px 48px rgba(92, 10, 14, .16);
  --radius:        20px;
  --font-display: 'Prata', 'Georgia', serif;
  --font-body: 'Manrope', 'Segoe UI', sans-serif;
  --arch: 46% 46% 8px 8px;
}

* { margin: 0; padding: 0; box-sizing: border-box; }
html {
  scroll-behavior: smooth;
  /* Fluid-шкала (закон site_consistency, рецепт Z2/HUB):
     16px при 1920 → пропорционально сжимается/растёт с шириной окна.
     ВСЕ масштабные величины ниже — в rem от этой базы. */
  font-size: clamp(15px, 0.97vw, 21px); /* база ×1.16 — вердикт Яна 2026-07-15; нижняя граница 15px, чтобы вторичный текст не был мельче 13px */
  /* 🩸 25.08: правило стоит именно ЗДЕСЬ, а не только на body. Прокрутку страницы
     держит корневой элемент: с `overflow-x` на одном body документ продолжал
     выходить за окно (проверено замером — 1433 против 1425). */
  overflow-x: clip;
}
body {
  font-family: var(--font-body);
  font-size: 1.0625rem;
  line-height: 1.55;
  color: var(--ink);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  /* 🩸 25.08: страницу «возило» по горизонтали ровно на ширину полосы прокрутки.
     Причина — панорама кафе шириной `100vw`: `vw` считается ВМЕСТЕ со скроллбаром,
     а видимая область (`clientWidth`) — без него. На всех широких экранах документ
     выходил за окно на одно и то же число пикселей, на телефонах (полоса поверх
     содержимого) разницы не было — потому баг и не ловился на 375.
     Берём `clip`, а НЕ `hidden`: `hidden` создаёт контекст прокрутки и ломает
     `position: sticky` у шапки и ленты вкладок. `clip` просто обрезает лишнее. */
  overflow-x: clip;
}
img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
button { font-family: inherit; cursor: pointer; border: none; background: none; }
.container { max-width: 77.5rem; margin: 0 auto; padding: 0 1.5rem; }

/* заголовок только для поиска и скринридеров: с экрана убран по просьбе клиента,
   из разметки не выкинут — у страницы должен быть h1 (решение Оператора 2026-08-12) */
.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%);
  white-space: nowrap; border: 0;
}

::selection { background: var(--gold-pale); color: var(--burgundy-deep); }

/* ---------- орнаментальные утилиты ---------- */
/* восьмилучевая звезда-разделитель */
.divider {
  display: flex; align-items: center; justify-content: center;
  gap: 1.125rem; margin: 0 auto 1.375rem; max-width: 26.25rem;
}
.divider::before, .divider::after {
  content: ''; flex: 1; height: 1px;
  background: linear-gradient(90deg, transparent, var(--gold) 60%, var(--gold));
}
.divider::after { transform: scaleX(-1); }
.divider svg { flex-shrink: 0; }

/* тонкая girih-решётка для бордовых поверхностей (подключается в правилах секций) */
:root {
  --girih-dark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='96' height='96' viewBox='0 0 96 96'%3E%3Cg fill='none' stroke='%23E6BD71' stroke-opacity='.13' stroke-width='1'%3E%3Cpath d='M48 8 L88 48 L48 88 L8 48 Z'/%3E%3Cpath d='M48 24 L72 48 L48 72 L24 48 Z'/%3E%3Ccircle cx='48' cy='48' r='6'/%3E%3Cpath d='M0 0 L16 16 M96 0 L80 16 M0 96 L16 80 M96 96 L80 80'/%3E%3C/g%3E%3C/svg%3E");
}
/* едва заметная решётка для светлых поверхностей */
.pattern-light {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='96' height='96' viewBox='0 0 96 96'%3E%3Cg fill='none' stroke='%23C9973F' stroke-opacity='.10' stroke-width='1'%3E%3Cpath d='M48 8 L88 48 L48 88 L8 48 Z'/%3E%3Cpath d='M48 24 L72 48 L48 72 L24 48 Z'/%3E%3C/g%3E%3C/svg%3E");
}

/* фестончатый край — восточный бордюр на стыках бордовых секций */
.scallop-t, .scallop-b { position: relative; }
.scallop-t::before, .scallop-b::after {
  content: ''; position: absolute; left: 0; right: 0; height: 0.75rem; z-index: 2;
  background-image: radial-gradient(circle at 50% 0, var(--scallop-color, #5C0A0E) 11px, transparent 11.8px);
  background-size: 26px 12px;
  background-position: 0 0;
  background-repeat: repeat-x;
}
.scallop-t::before { top: -0.6875rem; }
.scallop-b::after { bottom: -0.6875rem; transform: scaleY(-1); }
.strip { --scallop-color: #88080B; }
#promo { --scallop-color: #5C0A0E; }

/* видимый фокус клавиатуры — контрастное кольцо на светлой и тёмной подложке */
:focus-visible {
  outline: 2px solid var(--burgundy);
  outline-offset: 2px;
}
/* На бордовых поверхностях бордовое кольцо не видно — там оно белое.
   Список поверхностей полный: секции сетов и акций, полоса козырей, подвал,
   плашка рейтинга в отзывах, шапка таблицы доставки, модалка и плавающие кнопки. */
#sets :focus-visible,
#promo :focus-visible,
.strip :focus-visible,
.footer :focus-visible,
.review-hero :focus-visible,
.delivery-table thead :focus-visible,
.mobile-nav :focus-visible,
.cart-fab:focus-visible,
.btn-primary:focus-visible,
.btn-phone:focus-visible {
  outline-color: #fff;
  outline-offset: 3px;
}

/* ---------- скролл-анимации ---------- */
.reveal { opacity: 0; transform: translateY(26px); transition: opacity .7s ease, transform .7s cubic-bezier(.22,.61,.36,1); }
.reveal.visible { opacity: 1; transform: none; }
.reveal-d1 { transition-delay: .08s; }
.reveal-d2 { transition-delay: .16s; }
.reveal-d3 { transition-delay: .24s; }
@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; transition: none; }
  html { scroll-behavior: auto; }
  *, *::before, *::after { transition-duration: 0s !important; animation-duration: 0s !important; }
}

/* ============ ВЕРХНЯЯ ПОЛОСА ============ */
/* Топбар = прод-геометрия (фикс px: чёткий текст на любом DPI,
   компактная центральная колонка — вердикт Яна 2026-07-15) */
.topbar {
  background: var(--burgundy-deep);
  color: #F3DDC2;
  font-size: 14px;
  padding: 7px 0;
}
.topbar .container {
  display: flex; justify-content: center;
  gap: clamp(24px, 5vw, 96px); /* блоки ближе друг к другу, по центру плашки */
  flex-wrap: nowrap;           /* всегда одна строка */
  max-width: none; padding: 0 24px;
}
.topbar span { display: inline-flex; align-items: center; gap: 7px; white-space: nowrap; }
.topbar svg { opacity: .75; }
.topbar b { color: var(--gold-soft); font-weight: 600; }
.topbar-social {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: 50%;
  background: rgba(255,255,255,.12); color: #F3DDC2;
  margin-left: 4px;
  transition: background .2s, transform .2s;
  min-width: 1.6rem; min-height: 1.6rem;
  padding: 0.4rem;
}
.topbar-social:hover { background: rgba(255,255,255,.26); transform: translateY(-1px); }
.topbar-social svg { opacity: 1; }

/* ============ ШАПКА ============ */
.header {
  position: sticky; top: 0; z-index: 90;
  background: rgba(251, 244, 233, .92);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid rgba(201, 151, 63, .25);
  transition: box-shadow .3s;
}
.header.scrolled { box-shadow: 0 4px 24px rgba(92, 10, 14, .10); }
.header .container { max-width: 85rem; } /* шапка шире центральной колонки */
.header-in { display: flex; align-items: center; gap: 1.125rem; padding: 0.75rem 0; }
.brand { display: flex; align-items: center; gap: 0.8125rem; flex-shrink: 0; }
.brand img { width: 3.75rem; height: 3.75rem; border-radius: 50%; box-shadow: 0 2px 10px rgba(92,10,14,.25); }
.brand-name { font-family: var(--font-display); font-size: 1.1875rem; line-height: 1.15; color: var(--burgundy); white-space: nowrap; }
/* 13.08, live-режим: Оператор выбрал вариант «Витрина». Подпись под названием набрана витринной
   Prata вместо капса Manrope — она входит в логотип как часть вывески, а не как ярлык. Кегль
   1.125rem подобран ползунком. Зелёный оставлен: по DESIGN.md этот цвет закреплён за халялем,
   звезда золотая — акцент. */
.brand-sub {
  display: inline-flex; align-items: baseline; gap: .38em;
  font-family: var(--font-display); font-weight: 400;
  font-size: 1.125rem; letter-spacing: .01em;
  text-transform: none; color: var(--green); line-height: 1.25;
}
.brand-sub svg { width: .62em; height: .62em; flex: none; color: var(--gold); align-self: center; }
.nav { display: flex; gap: 0; margin: 0 auto; white-space: nowrap; }
.nav a {
  padding: 0.5625rem 0.6875rem; border-radius: 0.75rem;
  font-weight: 600; font-size: 1.0625rem; color: var(--ink);
  transition: background .2s, color .2s;
  min-height: 1.6rem; display: inline-flex; align-items: center;
}
.nav a.nav-active { color: var(--burgundy); background: var(--gold-pale); }
.nav a:hover { background: var(--gold-pale); color: var(--burgundy); }
.header-cta { display: flex; align-items: center; gap: 0.75rem; flex-shrink: 0; }
/* База кегля на узком мониторе выросла до 15px, и шапка перестала вмещать
   навигацию вместе с плашкой рейтинга и кнопкой звонка — появлялась горизонтальная
   прокрутка. Плашка рейтинга уходит первой: её факт продублирован в полосе козырей
   и в разделе «Отзывы», потери нет. */
@media (max-width: 1440px) {
  .header .rating-chip { display: none; }
}
/* номер в шапке — только телефон: на десктопе рядом стоят рейтинг и кнопка «Позвонить» */
.header-phone { display: none; }
.rating-chip {
  display: flex; align-items: center; gap: 8px;
  background: var(--white); border: 1px solid var(--gold-pale);
  padding: 0.4375rem 0.75rem; border-radius: 0.875rem;
  box-shadow: 0 2px 8px rgba(92,10,14,.06);
  transition: transform .2s, box-shadow .2s;
}
.rating-chip:hover { transform: translateY(-1px); box-shadow: 0 4px 14px rgba(92,10,14,.12); }
.rating-chip .stars { color: #F5A623; font-size: 0.875rem; letter-spacing: 1px; }
.rating-chip b { font-size: 1.125rem; }
.rating-chip small { color: var(--ink-soft); font-size: 1rem; line-height: 1.2; }
.btn-phone {
  display: inline-flex; align-items: center; gap: 0.5625rem;
  background: var(--burgundy); color: #fff;
  padding: 0.75rem 1.25rem; border-radius: 0.875rem;
  font-weight: 700; font-size: 1.125rem;
  box-shadow: 0 4px 14px rgba(136, 8, 11, .35);
  transition: background .2s, transform .2s, box-shadow .2s;
  white-space: nowrap;
}
.btn-phone:hover { background: var(--burgundy-hover); transform: translateY(-1px); box-shadow: 0 6px 20px rgba(136, 8, 11, .45); }
.burger { display: none; flex-direction: column; gap: 5px; padding: 0.625rem; }
.burger span { width: 26px; height: 3px; border-radius: 2px; background: var(--burgundy); transition: .3s; }

/* ============ HERO (full-bleed фото/видео) ============
   Консистентность мониторов (урок Z2): hero = ровно первый экран
   (100svh минус шапка), все размеры внутри = clamp(vmin) — масштаб
   от МЕНЬШЕЙ стороны окна: раскладка одинакова на любом разрешении
   и масштабе Windows, контент всегда влезает целиком. */
.hero {
  position: relative; overflow: hidden;
  /* высота = контент в rem (от ширины окна) — НЕ зависит от высоты
     монитора: на любом экране одной ширины hero одинаков.
     🩸 12.08: после снятия заголовка и подзаголовка (ТЗ клиента) экран
     схлопнулся 750 → 522 px и обрезал пирог. Держим 57.5rem — ровно ту высоту,
     которую держал текст, — и центрируем содержимое.
     13.08: пробовала снизить до 44rem ради мёртвой полосы внизу — кадр при этом
     режется. Решение Оператора: высоту фото не трогать, а поднять на него
     следующий блок (см. .strip margin-top). */
  /* 17.08: пробовала привязать высоту к экрану — clamp(30rem, 100svh − шапка, 57.5rem).
     Машинно всё сходилось (первый экран влезал на всех 12 форматах), но вид Оператор
     забраковал: «ужасно выглядит». Вернули 57.5rem. Вывод на будущее: цифры «влезает»
     не равны «выглядит», решает глаз Оператора. Разбор — BUGS_2026-08-17.md. */
  min-height: 57.5rem;
  display: flex; align-items: center;
  background: var(--burgundy-deep);
  /* 13.08: наезд следующего блока делаем отрицательным ОТСТУПОМ СНИЗУ у самого экрана,
     а не подъёмом полосы козырей. Разница важная: при подъёме полосы низ кадра оставался
     в потоке и вылезал тёмной прослойкой под ней. Здесь кадр рисуется во всю высоту,
     но в потоке заканчивается на 11rem раньше — за козырями сразу идёт «Наше кафе». */
  margin-bottom: -11rem;
}
/* кадр увеличен и сдвинут трансформом — без обрезки он вылезает за окно и даёт
   горизонтальную прокрутку на узких ширинах */
.hero-media { position: absolute; inset: 0; z-index: 0; overflow: hidden; }
.hero-media img, .hero-media video {
  width: 100%; height: 100%; object-fit: cover;
  object-position: center 100%; /* самый низ кадра — пирог максимально вверху */
  transform: translate(-4%, -5%) scale(1.18);
  transform-origin: center bottom; /* приближение + сдвиг: пирог выше и левее */
  /* блюр убран: hero_gen.webp сгенерирован со своей глубиной резкости */
}
.hero-scrim {
  position: absolute; inset: 0;
  background:
    /* 12.08: подписи у кнопок («с удовольствием доставим!») попадают на светлое
       тесто пирога — белый по золотому не читался. Гасим левую треть кадра. */
    linear-gradient(to right, rgba(0,0,0,.62) 0%, rgba(0,0,0,.42) 32%, rgba(0,0,0,0) 58%),
    linear-gradient(to top, rgba(0,0,0,.80) 0%, rgba(0,0,0,.40) 45%, rgba(0,0,0,.18) 100%),
    rgba(0,0,0,.10);
}
/* ⚠️ горизонтальные поля тут были нулевыми, а узел несёт ещё класс container —
   его поля 1.5rem обнулялись этим правилом. На всех экранах шире 720 заголовок,
   кнопки и строка доставки упирались в самый край экрана (замер 14.08: left = 0
   на 721, 768, 834, 1024, 1180). Держим те же поля, что у остальных секций. */
.hero-in { position: relative; z-index: 1; padding: 0.25rem 1.5rem 2.75rem; width: 100%; }
/* Подъём блока: -16rem (12.08) → -8rem (круг 2). Оставляем -8rem: положение текста
   Оператора устраивает, лечим не его, а пустоту под ним — наездом полосы козырей. */
.hero-text { max-width: 48.75rem; margin-top: -8rem; }
.badge {
  display: inline-flex; align-items: center; gap: .5em;
  padding: .42em .85em; border-radius: 6.25rem;
  font-size: 1rem; font-weight: 700;
  background: rgba(255,255,255,.14); color: #fff;
  border: 1px solid rgba(255,255,255,.3);
}
/* 13.08: знак «100% Халяль» снят с первого экрана решением Оператора — экран отдан заголовку
   и паре кнопок. Халяль остался в шапке (лого «Пироги по-домашнему ★ ХАЛЯЛЬ»), в полосе козырей
   и в секции «О нас». Правила .hero-badges и .badge-halal удалены вместе с разметкой. */
.badge .star { color: #F5A623; }
/* ЗАГОЛОВОК первого экрана. Схема Оператора от 13.08: две строки, вторая золотом и со сдвигом
   вправо. Сдвиг задан в em, чтобы держать пропорцию к кеглю на любой ширине окна. */
.hero-title {
  font-family: var(--font-display);
  /* Prata существует только в 400. У h1 браузерное начертание — bold, и он рисует
     синтетический жир: утолщает контуры сам, буквы плывут. Держим 400 явно. */
  font-weight: 400;
  font-size: clamp(3.25rem, 7.6vw, 6rem);
  line-height: 1.0;
  color: #fff;
  margin: 0 0 2.75rem;
  text-shadow: 0 2px 6px rgba(0,0,0,.7), 0 12px 40px rgba(0,0,0,.55);
}
/* Обе строки от левой стенки: сдвиг второй строки снят решением Оператора 13.08.
   Сдвиг читался как случайность — он не совпадал ни с краем, ни с шириной слова. */
.hero-title-accent { display: block; color: var(--gold-soft); margin-left: 0; }

/* ДЕЙСТВИЯ. ТЗ клиента 12.08: две активные кнопки, у каждой свой текст рядом. Кнопки идут
   столбиком, подпись справа от своей кнопки, обе подписи ОДНОГО кегля — иначе каламбур клиента
   «достав-ем / ем» распадается и вторая половина читается как опечатка. */
/* 13.08: заголовок поднят, а весь нижний блок — кнопки, подписи, строка доставки — уменьшен,
   чтобы вес экрана держал заголовок, а не набор строк под ним. */
.hero-actions { display: flex; flex-direction: column; gap: 0.875rem; align-items: flex-start; }
.hero-cta { display: flex; align-items: center; gap: 1.125rem; }
/* Пилюли первого экрана тоньше по вертикали; высота ~52 px — цель нажатия выше порога 44.
   Ширина ЖЁСТКАЯ и общая для обеих: при min-width «Пироги» из шести букв растягивали пилюлю,
   «Кафе» из четырёх — нет, и подписи стартовали с разных вертикалей. Теперь обе одинаковые,
   поэтому просвет «кнопка → подпись» одинаков в обеих строках без подгонки отступов. */
.hero-cta .btn-lg {
  width: 11rem; justify-content: center;
  font-size: 1.25rem;
  padding-top: .72em; padding-bottom: .72em;
}
.hero-cta-note {
  font-family: var(--font-display);
  font-size: clamp(1.0625rem, 1.5vw, 1.375rem); line-height: 1.15;
  color: #fff;
  /* подпись частично ложится на светлое тесто — держим её плотной тенью */
  text-shadow: 0 1px 2px rgba(0,0,0,.75), 0 2px 16px rgba(0,0,0,.85);
  white-space: nowrap;
}
.btn-lg {
  display: inline-flex; align-items: center; gap: .6em;
  padding: 1em 2.1em; border-radius: .9em;
  font-size: 1.4375rem; font-weight: 800;
  transition: transform .2s, box-shadow .2s, background .2s;
}
.btn-primary {
  background: var(--burgundy); color: #fff;
  box-shadow: 0 6px 22px rgba(136, 8, 11, .38);
}
.btn-primary:hover { background: var(--burgundy-hover); transform: translateY(-2px); box-shadow: 0 10px 30px rgba(136, 8, 11, .48); }
.btn-ghost {
  background: rgba(255,255,255,.92); color: var(--burgundy);
  border: 2px solid rgba(255,255,255,.92);
}
.btn-ghost:hover { transform: translateY(-2px); }
/* «Кафе» — вторая активная кнопка. Кремовая заливка с бордовым текстом даёт 9,2:1: выбор
   Оператора 13.08 из пяти примеренных схем. Золотую заливку не берём: золотом набрано слово
   «пироги» в заголовке, и кнопка того же цвета перетягивала бы заголовок на себя. */
.btn-cream {
  background: var(--bg); color: var(--burgundy);
  border: 2px solid var(--bg);
  box-shadow: 0 6px 22px rgba(0, 0, 0, .28);
}
.btn-cream:hover { background: #fff; border-color: #fff; transform: translateY(-2px); }

/* 🩸 25.08: правило `.btn-set-v3 .btn-set-icon` снято вместе с третьей кнопкой
   «Сеты» на первом экране — она прожила сутки и убрана словом Оператора.
   Мёртвых правил от неё не оставляем: стили героя (`hero-actions`, `hero-cta`)
   под три кнопки не правились, поэтому откат ограничился разметкой и этой строкой.
   «Сеты» в ряду вкладок меню живут своим правилом `.tab-sets` — оно не тронуто. */

/* круглый знак «Halal Certified» снят с первого экрана по ТЗ клиента 12.08
   (бейдж «100% Халяль» в строке над кнопками оставлен) */

/* 12.08: плашки-метрики первого экрана (857 отзывов · 10:00 печём) сняты из разметки как
   шаблон hero-metric — прямой запрет craft-floor. Факты живут на своих местах: рейтинг в шапке
   и в «Отзывах», «печём с 10:00» в верхней полосе. Строка про бесплатную доставку осталась
   на экране — она про деньги гостя, ей тут место. Правила .hero-card удалены вместе с блоком. */
/* 13.08, live: принят вариант «Микродетали». Галочка в золотом кружке, волосяная линия отделяет
   строку от кнопок. Тень добавлена по находке полировки: у подписей у кнопок она была, а у этой
   строки нет — при том что стоит она на светлом тесте пирога и местами теряла контраст.
   Отступ сверху поднят до 2.1rem по просьбе Оператора: строка отходит от кнопок. */
.hero-note {
  display: inline-flex; align-items: center; gap: .68em;
  font-family: var(--font-body); font-size: .9375rem; font-weight: 500;
  letter-spacing: .01em; color: #fff; line-height: 1.4;
  margin-top: 2.1rem; padding-top: .9rem;
  border-top: 1px solid rgba(255,255,255,.22);
  text-shadow: 0 1px 2px rgba(0,0,0,.7);
}
.hero-note-tick {
  width: 1.5em; height: 1.5em; flex: none; display: grid; place-items: center;
  border-radius: 50%; background: rgba(230,189,113,.18);
  border: 1px solid rgba(230,189,113,.5); color: var(--gold-soft);
}
.hero-note-tick svg { width: .8em; height: .8em; }

/* ============ КОЗЫРИ ============ */
/* Полоса ложится поверх низа кадра — подъём задаёт .hero { margin-bottom }, здесь только
   z-index, чтобы она рисовалась над фотографией, а не под ней. */
/* Нижний добор (padding-bottom: 2.5rem) снят 13.08: он закрывал хвост фотографии, а эту работу
   теперь делает слой — #menu поднят над первым экраном. Без добора полоса вернулась к своей
   высоте, и между козырями и фестоном не осталось пустой красной зоны.
   Светлая линия по нижнему краю — кант скатерти: она отделяет полосу от фестончатого края,
   как на прежнем стенде. */
.strip {
  background: var(--girih-dark), var(--burgundy);
  position: relative; z-index: 2;
}
/* Кант скатерти — светлая линия по плоскому краю над полукружьями. Обычный border-bottom
   тут не годится: фестон (.scallop-b::after) начинается на 1 px выше края и рисуется поверх
   бордюра, линия была бы видна только в просветах. Поэтому отдельный слой выше фестона. */
.strip::before {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0;
  height: 2px; background: #fff; z-index: 3;
}
/* 13.08: секция после полосы обязана быть позиционированной. У .hero стоит position: relative,
   а позиционированный элемент рисуется поверх обычного — фотография первого экрана продолжалась
   под полосой и закрашивала кремовый фон. В просветах фестончатого края было видно тёмное тесто
   вместо крема, и светлая линия у стыка пропадала. Поднимаем «Меню» в тот же слой. */
#menu { position: relative; z-index: 1; }
.strip .container {
  display: grid; grid-template-columns: repeat(4, 1fr);
  gap: 0.75rem; padding-top: 2.125rem; padding-bottom: 2.125rem;
}
.strip-item { display: flex; align-items: center; gap: 0.9375rem; color: #fff; justify-content: center; }
.strip-icon {
  width: 3.25rem; height: 3.25rem; flex-shrink: 0;
  display: grid; place-items: center;
  background: rgba(230, 189, 113, .16);
  border: 1px solid rgba(230, 189, 113, .4);
  border-radius: 0.875rem; color: var(--gold-soft);
}
.strip-item b { display: block; font-size: 1.125rem; }
.strip-item small { color: rgba(243, 221, 194, .85); font-size: 0.875rem; }

/* ============ СЕКЦИИ ============ */
section { padding: 5.25rem 0; }
/* стандарт заголовков секций увеличен (вердикт Яна 2026-07-15) */
.sec-head { text-align: center; max-width: 46rem; margin: 0 auto 3rem; }
.sec-title {
  font-family: var(--font-display); font-weight: 400;
  font-size: clamp(2.125rem, 3.8vw, 3rem);
  color: var(--burgundy-ink); margin-bottom: 1rem;
}
.sec-sub {
  color: var(--ink-soft); font-size: 1.3125rem;
  text-wrap: balance;
  max-width: 70ch;
  margin-left: auto;
  margin-right: auto;
}

/* две колонки: левая для заголовка, правая для подзаголовка */
/* 13.08: двухколоночная шапка секций снята решением Оператора: заголовок стоял
   слева от звёздочки-разделителя. Вернулась центрированная стопка: заголовок — звёздочка — подпись. */
.sec-head--left {
  text-align: left;
  max-width: none;
  margin: 0 0 3rem;
}
.sec-head--left .sec-sub { display: none; }

/* служебный вход — одна строка, никаких подзаголовков */
.sec-head--service {
  text-align: center;
  max-width: 46rem;
  margin: 0 auto 3rem;
}
.sec-head--service .sec-sub { display: none; }
.sec-head--service .divider { display: none; }

/* ============ КАФЕ ============ */
#cafe { background: var(--bg); }
.cafe-photos { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.625rem; }
.cafe-photo { margin: 0; border-radius: var(--radius); overflow: hidden; }
.cafe-photo img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; box-shadow: var(--shadow-card); }
/* временная плитка вместо фото зала — держит место и размер будущего снимка */
.cafe-ph {
  aspect-ratio: 4 / 3; border-radius: var(--radius);
  display: grid; place-content: center; justify-items: center; gap: 6px;
  text-align: center; color: var(--gold);
  border: 1.5px dashed rgba(201, 151, 63, .55);
  background:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='96' height='96' viewBox='0 0 96 96'%3E%3Cg fill='none' stroke='%23C9973F' stroke-opacity='.16' stroke-width='1'%3E%3Cpath d='M48 8 L88 48 L48 88 L8 48 Z'/%3E%3Cpath d='M48 24 L72 48 L48 72 L24 48 Z'/%3E%3C/g%3E%3C/svg%3E"),
    linear-gradient(150deg, #F7EBD5, #F0DDBC);
}
.cafe-ph b { font-family: var(--font-display); font-weight: 400; font-size: 1.25rem; color: var(--burgundy); }
.cafe-ph small { color: var(--ink-soft); font-size: 0.875rem; }
.cafe-facts { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.75rem 2.25rem; margin-top: 2.25rem; }
.cafe-fact { display: inline-flex; align-items: center; gap: .55em; font-size: 1rem; font-weight: 600; color: var(--ink-soft); }
.cafe-fact svg { color: var(--gold); flex-shrink: 0; }

/* ============ МЕНЮ ============ */
#menu { padding-top: 72px; background: linear-gradient(var(--bg), var(--bg-soft) 30%, var(--bg)); }
.menu-tabs {
  display: flex; gap: 8px; flex-wrap: wrap; justify-content: center;
  margin-bottom: 2.625rem; position: sticky; top: 5.25rem; z-index: 40;
  background: rgba(251, 244, 233, .95); backdrop-filter: blur(10px);
  padding: 0.75rem; border-radius: 1.125rem;
  border: 1px solid rgba(201, 151, 63, .2);
  box-shadow: 0 4px 18px rgba(92, 10, 14, .06);
}
.tab {
  padding: 0.6875rem 1.25rem; border-radius: 6.25rem;
  font-weight: 700; font-size: 1rem; color: var(--ink);
  background: transparent; border: 1.5px solid transparent;
  transition: all .22s;
  min-height: 1.6rem; display: inline-flex; align-items: center;
}
.tab:hover { background: var(--gold-pale); }
.tab.active { background: var(--burgundy); color: #fff; box-shadow: 0 4px 14px rgba(136, 8, 11, .32); }
/* 24.08: «Сеты» — якорь в конце ряда вкладок, не категория (см. app.js). Заливка
   gold-pale/бордовый — 7,95:1, не спорит с двумя формами кнопок закона (это не
   .btn, а .tab: свой формат ряда), но и не путается с обычной/активной вкладкой. */
.tab-sets {
  background: var(--gold-pale); color: var(--burgundy);
  border-color: var(--gold); gap: .4em;
}
.tab-sets:hover { background: var(--gold-soft); }
.tab-sets svg { flex-shrink: 0; }
.menu-note { text-align: center; color: var(--ink-soft); margin-bottom: 2.125rem; font-size: 1.0312rem; font-style: italic; }

/* 13.08: поиск по меню снят решением Оператора — категорий восемь, их видно целиком,
   искать по 56 позициям нечего. Правила удалены вместе с разметкой и логикой. */

/* 13.08: ряд «Рекомендуем» снят решением Оператора — те же блюда стояли дважды
   на одном экране: в ряду и в сетке меню. Правила удалены вместе с разметкой. */

.menu-grid {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.625rem;
}
/* 13.08: карточка возвращена к оформлению прежнего стенда решением Оператора — подложка,
   скругление, тёплая тень, подъём на наведении. Плоский вариант из ночной чистки читался
   как список, а не как товар. */
.dish {
  background: var(--card); border-radius: var(--radius);
  overflow: hidden; box-shadow: var(--shadow-card);
  display: flex; flex-direction: column;
  transition: transform .25s, box-shadow .25s;
  position: relative;
  /* 13.08, /animate: смысл движения здесь — объяснить СМЕНУ СОСТОЯНИЯ. При нажатии на таб
     скрипт полностью перерисовывает сетку: двенадцать карточек исчезали и шесть появлялись
     мгновенно, без объяснения, что произошло. Анимация запускается самим фактом вставки
     нового узла, поэтому играет и на первом показе, и на каждой смене категории —
     скрипт для этого трогать не пришлось. */
  /* backwards, а не both: при both финальное `transform: none` анимации перебивало бы
     подъём на наведении — анимация в каскаде сильнее обычного правила. */
  animation: dish-in .42s cubic-bezier(.16, 1, .3, 1) backwards;
}
/* Ступенька задержки ограничена восемью карточками: дальше суммарное ожидание начинает
   читаться как медленный сайт, а не как приём. Девятая и следующие входят вместе с восьмой. */
.dish:nth-child(2) { animation-delay: .04s; }
.dish:nth-child(3) { animation-delay: .08s; }
.dish:nth-child(4) { animation-delay: .12s; }
.dish:nth-child(5) { animation-delay: .16s; }
.dish:nth-child(6) { animation-delay: .2s; }
.dish:nth-child(7) { animation-delay: .24s; }
.dish:nth-child(n+8) { animation-delay: .28s; }
@keyframes dish-in {
  from { opacity: 0; transform: translateY(14px); }
  to { opacity: 1; transform: none; }
}
/* 13.08, решение Оператора: карточка на наведении СТОИТ НА МЕСТЕ. Работает только
   снимок внутри — он чуть приближается. Подъём карточки со сменой тени убран:
   при живой сетке из двенадцати карточек прыжок читался как дребезг. */
.dish:hover { box-shadow: var(--shadow-card); }
.dish-img { position: relative; aspect-ratio: 4 / 3; overflow: hidden; background: var(--gold-pale); }
.dish-img img { width: 100%; height: 100%; object-fit: cover; transition: transform .5s ease; }
/* Второй кадр: пирог порцией, проступает под курсором поверх основного.
   Лежит абсолютом, поэтому высоту карточки не меняет; плашка «Хит» выше обоих.
   Движение — наплыв, а не мигание: кадр приходит с лёгкого приближения и садится
   на место, основной в это время чуть отступает вглубь. Вход неспешный (0.55 с),
   возврат быстрее (0.32 с) — так делают все выверенные переходы: уход не должен
   заставлять ждать. Кривая экспоненциальная, без пружин. */
.dish-img img.dish-img-slice {
  position: absolute; inset: 0; z-index: 1;
  opacity: 0; transform: scale(1.07);
  /* Возврат мягкий, но короче входа: 0.42 с против 0.55 — уход не должен заставлять ждать,
     и при этом не обрывается рывком (правка Оператора 13.08). */
  transition: opacity .42s ease, transform .48s cubic-bezier(.16, 1, .3, 1);
  will-change: opacity, transform;
}
.dish:hover .dish-img img.dish-img-slice, .dish:focus-within .dish-img img.dish-img-slice {
  opacity: 1; transform: scale(1);
  transition: opacity .55s ease .05s, transform .65s cubic-bezier(.16, 1, .3, 1) .05s;
}

/* Одиночные позиции: кадр ОДИН. В покое он показан крупно масштабом --zs, под
   курсором масштаб уходит к единице — кадр отъезжает и открывает сцену с дощечкой.
   Никакой подмены снимков: менять нечего, снимок тот же самый.
   Отсчёт от центра еды (--zx/--zy), иначе блюдо уползает к углу.
   Кривая неровная нарочно (Оператор 13.08): трогается медленно, в середине
   разгоняется, к концу мягко тормозит — как отъезд камеры, а не как переключатель. */
/* Оба селектора нарочно: ниже по файлу стоит .dish-photo.is-loaded со своим
   transition для проявления, и при равной специфичности он затирал переход
   трансформации — возврат срывался мгновенно. Здесь держим оба перехода разом. */
.dish-img img.dish-photo.dish-zoomout,
.dish-img img.dish-photo.dish-zoomout.is-loaded {
  transform-origin: var(--zx, 50%) var(--zy, 50%);
  transform: scale(var(--zs, 1.18));
  transition: transform .62s cubic-bezier(.32, 0, .16, 1), opacity .5s ease;  /* возврат короче входа */
  will-change: transform;
}
.dish:hover .dish-img img.dish-photo.dish-zoomout,
.dish:focus-within .dish-img img.dish-photo.dish-zoomout {
  transform: scale(1);
  transition: transform 1.05s cubic-bezier(.62, .02, .2, 1);
}
@media (prefers-reduced-motion: reduce) {
  .dish-img img.dish-photo.dish-zoomout { transition: none; }
  .dish:hover .dish-img img.dish-photo.dish-zoomout { transform: scale(var(--zs, 1.18)); }
}
/* Сенсорный экран наведения не знает: там второй кадр только тратил бы трафик. */
@media (hover: none), (prefers-reduced-motion: reduce) {
  .dish-img img.dish-img-slice { display: none; }
}
/* Основной кадр под наплывом уходит вглубь и слегка гаснет — тогда подмена читается
   как поворот блюда к гостю, а не как две картинки, сменившие друг друга. */
.dish:hover .dish-img img { transform: scale(1.045); }
/* 🩸 13.08: основной кадр под наплывом гасили до 0.55 — и сквозь него просвечивал
   золотой фон плитки. На карточках без второго кадра это читалось как жёлтая вспышка
   (Оператор: «дурацкий эффект»). Притухание снято: второй кадр непрозрачный и
   перекрывает сам, а основной только чуть отступает вглубь. */
.dish:hover .dish-img > img:not(.dish-img-slice) { transform: scale(1.02); }
.dish-img > img:not(.dish-img-slice) {
  transition: transform .6s cubic-bezier(.16, 1, .3, 1), opacity .45s ease;
}
/* Снимок карточки появляется, когда загрузился, а не когда вставлена разметка:
   при переключении вкладки на его месте была пустая плитка и мигание (Оператор 13.08).
   Плитка под ним — кремовая, поэтому пауза читается как выдержка, а не как поломка. */
.dish-img img.dish-photo { opacity: 0; }
.dish-img img.dish-photo.is-loaded { opacity: 1; transition: opacity .5s ease; }
/* притухание основного кадра снято 13.08 — см. комментарий выше */
@media (prefers-reduced-motion: reduce) {
  .dish-photo, .dish-photo.is-loaded { opacity: 1; transition: none; }
}
/* Плашка «Хит» / «Фирменный» — снова в верхнем углу снимка капсулой, как на прежнем стенде:
   снизу она наезжала на нижний край фотографии и читалась как подпись, а не как метка. */
.dish-tag {
  position: absolute; top: 0.875rem; left: 0.875rem;
  background: var(--burgundy); color: #fff;
  font-size: 0.7812rem; font-weight: 800; letter-spacing: .04em;
  padding: 6px 0.75rem; border-radius: 6.25rem;
  box-shadow: 0 3px 10px rgba(0,0,0,.25);
  /* z-index обязателен: в разметке плашка идёт ДО картинки, а на наведении картинка получает
     transform и попадает в слой позиционированных элементов. Будучи позже в разметке, она
     закрывала плашку — «Хит» пропадал при наведении на карточку. */
  z-index: 2;
}
/* 13.08: «Фирменный» был золотым с белым текстом — 2,5:1, вдвое ниже порога, буквы мутнели.
   Переведён на второй утверждённый формат: кремовая заливка, бордовый текст — 9,2:1.
   Пара «Хит» бордовый / «Фирменный» кремовый различается так же, как кнопки первого экрана. */
.dish-tag.gold { background: var(--bg); color: var(--burgundy); box-shadow: 0 3px 10px rgba(0,0,0,.2); }
.dish-noimg {
  aspect-ratio: 4 / 3;
  display: grid; place-items: center;
  background:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='96' height='96' viewBox='0 0 96 96'%3E%3Cg fill='none' stroke='%23C9973F' stroke-opacity='.16' stroke-width='1'%3E%3Cpath d='M48 8 L88 48 L48 88 L8 48 Z'/%3E%3Cpath d='M48 24 L72 48 L48 72 L24 48 Z'/%3E%3C/g%3E%3C/svg%3E"),
    linear-gradient(150deg, #F7EBD5, #F0DDBC);
}
.dish-noimg span {
  font-family: var(--font-display); font-size: 1.3125rem; text-align: center;
  color: var(--burgundy); opacity: .85; padding: 0 1.875rem; line-height: 1.35;
}
/* карточка, чей снимок ещё ждём (сейчас — «Олимп»): камера вместо дубля названия */
.dish-noimg { text-align: center; }
.dish-cam { color: var(--gold); }
.dish-photo-soon {
  display: block; margin-top: 6px; color: var(--ink-soft); font-size: 0.875rem;
  letter-spacing: .06em; text-transform: uppercase;
}
.dish-body { padding: 1.25rem 1.375rem 1.375rem; display: flex; flex-direction: column; flex: 1; }
/* название слева, вес прижат к правому краю — как на прежнем стенде */
.dish-top { display: flex; justify-content: space-between; align-items: baseline; gap: 0.625rem; margin-bottom: 8px; }
.dish h3 { font-size: 1.1875rem; font-weight: 800; line-height: 1.3; color: var(--ink); }
.dish-weight { color: var(--ink-soft); font-size: 0.875rem; white-space: nowrap; opacity: 0.85; }
/* Состав блюда гость читает перед тем, как выбрать, — прятать его нельзя.
   Но и спорить с названием он не должен: две строки, тихий тон, остальное отсекаем. */
.dish-desc {
  color: var(--ink-soft);
  font-size: 0.9375rem;
  line-height: 1.5;
  margin: 0.25rem 0 1rem;
  flex: 1;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.dish-foot { display: flex; justify-content: space-between; align-items: center; gap: 0.5rem; margin-top: auto; }
.dish-price { font-family: var(--font-display); font-size: 1.625rem; font-weight: 700; color: var(--burgundy-ink); }
.dish-price small { font-size: 0.875rem; color: var(--ink-soft); font-family: var(--font-body); }
/* 13.08, решение Оператора: на сайте живут ДВА формата кнопки — бордовая заливка с белым
   текстом и кремовая с бордовым. Золотая заливка с белым текстом давала 2,5:1 и не читалась.
   «В корзину» — главное действие карточки, поэтому бордовая: белый по #88080B даёт 10,1:1. */
.btn-add {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.4em;
  background: var(--burgundy); color: #fff;
  min-height: 1.6rem; padding: 0.5em 0.9em; border-radius: 0.6rem;
  font-size: 0.9375rem; font-weight: 700; font-family: inherit;
  transition: background .2s, transform .2s;
  white-space: nowrap;
  /* на 390 подпись «В корзину» вместе с ценой перестаёт помещаться в строку карточки
     и выдавливает её за экран — разрешаем кнопке сжиматься, а строке переноситься */
  min-width: 0; flex-shrink: 1;
}
.dish-foot { flex-wrap: wrap; gap: 0.5rem 0.75rem; }
/* На телефоне цена и «В корзину» в одну строку не помещаются и выдавливают карточку
   за экран. Ставим их друг под другом: цена сверху, действие во всю ширину карточки —
   так по нему и попасть пальцем легче. */
@media (max-width: 460px) {
  .dish-foot, .set-foot { flex-direction: column; align-items: stretch; }
  .dish-foot .add-slot, .dish-foot .btn-add, .dish-foot .qty-card,
  .set-foot .add-slot, .set-foot .btn-add, .set-foot .qty-card { width: 100%; }
  .btn-add { justify-content: center; }
}
.btn-add:hover { background: var(--burgundy-hover); transform: scale(1.05); }
.btn-add.added { background: var(--green); }

/* ============ СЕТЫ ============ */
#sets { background: var(--girih-dark), var(--burgundy-deep); position: relative; overflow: hidden; }
#sets .sec-title, #sets .sec-sub { color: #fff; }
#sets .sec-sub { color: rgba(243, 221, 194, .8); }
/* три ценовые группы, в каждой по два набора (ТЗ клиента 12.08) */
.sets-groups { display: flex; flex-direction: column; gap: 3.25rem; }
.set-group-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 1rem 1.5rem; flex-wrap: wrap; margin-bottom: 1.375rem;
  padding-bottom: 0.875rem; border-bottom: 1px solid rgba(230, 189, 113, .3);
}
.set-group-head h3 {
  font-family: var(--font-display); font-weight: 400;
  font-size: 1.875rem; color: #fff;
}
.set-group-gift {
  display: inline-flex; align-items: center; gap: .5em;
  color: var(--gold-soft); font-weight: 700; font-size: 1rem;
}
.set-group-gift svg { flex-shrink: 0; }
.sets-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1.625rem; }
.set-card {
  background: var(--card); border-radius: 24px; overflow: hidden;
  box-shadow: 0 20px 60px rgba(0, 0, 0, .35);
  display: flex; flex-direction: column;
  transition: transform .25s;
}
.set-card:hover { transform: translateY(-6px); }
.set-img { position: relative; aspect-ratio: 16 / 10; overflow: hidden; }
.set-img img { width: 100%; height: 100%; object-fit: cover; }
.set-count {
  /* плашка лежит поверх фото: длинный текст из панели («6 больших пирогов»)
     уезжал бы за край карточки. Держим её в ширине фото и разрешаем перенос. */
  max-width: calc(100% - 2rem); box-sizing: border-box;
  position: absolute; left: 1rem; bottom: 1rem;
  background: rgba(43, 24, 16, .95);
  color: #fff; font-weight: 700; font-size: 0.875rem;
  padding: 7px 0.875rem; border-radius: 6.25rem;
}
.set-body { padding: 1.5rem 1.625rem 1.625rem; flex: 1; display: flex; flex-direction: column; }
.set-body h4 { font-family: var(--font-display); font-weight: 400; font-size: 1.5625rem; color: var(--burgundy-ink); margin-bottom: 0.875rem; }
.set-items { list-style: none; margin-bottom: 1rem; flex: 1; }
.set-items li {
  display: flex; align-items: baseline; justify-content: space-between; gap: 1rem;
  padding: 7px 0 7px 1.625rem; position: relative;
  font-size: 15.5px; border-bottom: 1px dashed rgba(201, 151, 63, .3);
}
.set-items li:last-child { border-bottom: none; }
.set-items li b { color: var(--burgundy-ink); font-weight: 700; white-space: nowrap; }
.set-items li::before {
  content: ''; position: absolute; left: 2px; top: 0.8125rem;
  width: 8px; height: 8px; transform: rotate(45deg);
  background: var(--gold);
}
.set-gift {
  display: flex; align-items: center; gap: .55em;
  background: var(--gold-pale); color: var(--burgundy-deep);
  border-radius: 0.75rem; padding: 0.625rem 0.875rem;
  font-size: 0.9062rem; font-weight: 700; margin-bottom: 1.125rem;
}
.set-gift svg { flex-shrink: 0; }
.set-foot { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; }
.set-price { display: flex; flex-direction: column; }
.set-price small { color: var(--ink-soft); font-size: 0.8125rem; }
.set-price .new { font-family: var(--font-display); font-size: 1.6875rem; color: var(--burgundy); }
.set-price .new small { font-size: 1.0625rem; }
.sets-note { text-align: center; color: rgba(243, 221, 194, .65); font-size: 0.875rem; margin-top: 1.875rem; }

/* ============ КАЛЬКУЛЯТОР ГОСТЕЙ ============ */
#calc { padding: 5.25rem 0; }
.calc-card {
  max-width: 55rem; margin: 0 auto;
  background: var(--card); border-radius: 28px;
  box-shadow: var(--shadow-card);
  border: 1px solid rgba(201, 151, 63, .25);
  padding: 3rem 3.5rem;
  position: relative; overflow: hidden;
}
.calc-title { font-family: var(--font-display); font-size: 1.875rem; color: var(--burgundy-ink); text-align: center; margin-bottom: 8px; }
.calc-sub { text-align: center; color: var(--ink-soft); margin-bottom: 2.25rem; }
.calc-row { display: flex; align-items: center; gap: 1.625rem; margin-bottom: 2rem; }
.calc-guests {
  font-family: var(--font-display); font-size: 3.375rem; color: var(--burgundy);
  min-width: 7.5rem; text-align: center; line-height: 1;
}
.calc-guests small { display: block; font-family: var(--font-body); font-size: 0.875rem; color: var(--ink-soft); margin-top: 4px; }
/* Дорожка ползунка рисуется ПСЕВДОЭЛЕМЕНТОМ трека, а не фоном самого input.
   Фон на input при appearance:none Chrome не показывает — трек перекрывает его собой,
   и дорожка пропала совсем (найдено Оператором 13.08, сверено с живым сайтом). */
input[type="range"] {
  flex: 1; -webkit-appearance: none; appearance: none;
  height: 2rem;              /* высота области захвата = размер ручки */
  background: transparent;   /* фон здесь не рисуем: его даёт трек */
  outline: none; cursor: pointer;
}
input[type="range"]::-webkit-slider-runnable-track {
  height: 0.625rem; border-radius: 6.25rem;
  background: linear-gradient(90deg, var(--burgundy) var(--fill, 30%), var(--gold-pale) var(--fill, 30%));
}
input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 2rem; height: 2rem; border-radius: 50%;
  background: var(--burgundy);
  border: 4px solid #fff;
  box-shadow: 0 3px 12px rgba(136, 8, 11, .45);
  cursor: grab;
  margin-top: calc((0.625rem - 2rem) / 2);   /* ручка по центру дорожки */
}
input[type="range"]:active::-webkit-slider-thumb { cursor: grabbing; }
input[type="range"]::-moz-range-track {
  height: 0.625rem; border-radius: 6.25rem;
  background: linear-gradient(90deg, var(--burgundy) var(--fill, 30%), var(--gold-pale) var(--fill, 30%));
}
input[type="range"]::-moz-range-thumb {
  width: 1.625rem; height: 1.625rem; border-radius: 50%;
  background: var(--burgundy); border: 4px solid #fff;
  box-shadow: 0 3px 12px rgba(136, 8, 11, .45); cursor: grab;
}
.calc-result {
  background: var(--bg-soft); border-radius: 18px;
  padding: 1.625rem 1.875rem;
  display: flex; align-items: center; gap: 1.5rem; flex-wrap: wrap;
}
.calc-result .icon { font-size: 2.5rem; }
.calc-result-text { flex: 1; min-width: 15rem; }
.calc-result-text b { font-size: 1.1875rem; color: var(--burgundy-ink); }
.calc-result-text p { color: var(--ink-soft); font-size: 0.9688rem; margin-top: 4px; }
.calc-gift {
  margin-top: 1.125rem; display: none;
  align-items: center; gap: 0.625rem;
  color: var(--green); font-weight: 700; font-size: 0.9688rem;
}
.calc-gift.show { display: flex; }

/* ============ АКЦИИ ============ */
#promo { background: var(--girih-dark), linear-gradient(160deg, var(--burgundy) 0%, var(--burgundy-deep) 100%); position: relative; overflow: hidden; }
#promo .sec-title { color: #fff; }
#promo .sec-sub { color: rgba(243, 221, 194, .8); }
.promo-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1.625rem; max-width: 61.25rem; margin: 0 auto; }
.promo-card {
  border: 1.5px solid rgba(230, 189, 113, .45);
  background: rgba(255, 253, 248, .06);
  backdrop-filter: blur(4px);
  border-radius: 1.5rem; padding: 2.25rem 2.375rem;
  color: #fff; position: relative; overflow: hidden;
  transition: transform .25s, background .25s;
}
.promo-card:hover { transform: translateY(-4px); background: rgba(255, 253, 248, .1); }
.promo-from {
  font-size: 0.875rem; letter-spacing: .12em; text-transform: uppercase;
  color: var(--gold-soft); font-weight: 800; margin-bottom: 0.75rem;
}
.promo-card h3 { font-family: var(--font-display); font-weight: 400; font-size: 1.625rem; line-height: 1.3; margin-bottom: 0.75rem; }
.promo-card p { color: rgba(243, 221, 194, .85); font-size: 0.9688rem; }
.promo-card .gift-num {
  position: absolute; right: 1.375rem; top: 1.125rem;
  font-family: var(--font-display); font-size: 4.625rem;
  color: rgba(230, 189, 113, .18); line-height: 1;
}

/* ============ О НАС ============ */
#about { background: var(--bg); }
.about-in { display: grid; grid-template-columns: .95fr 1.05fr; gap: 3.75rem; align-items: center; }
.about-photos { display: grid; grid-template-columns: 1fr 1fr; gap: 1.125rem; }
.about-photos img {
  width: 100%; aspect-ratio: 3 / 4; object-fit: cover;
  border-radius: 44% 44% 0.625rem 0.625rem;
  box-shadow: var(--shadow-card);
}
.about-photos img:nth-child(2) { margin-top: 2.125rem; }
.about-text h2 { text-align: left; margin-bottom: 1.25rem; }
.about-text p { color: var(--ink-soft); font-size: 1.0625rem; margin-bottom: 1rem; }
.about-text p b { color: var(--ink); }
.about-feats { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin-top: 1.75rem; }
.about-feat {
  display: flex; gap: 0.8125rem; align-items: flex-start;
  background: var(--card); padding: 16px 18px;
  border-radius: 16px; box-shadow: var(--shadow-card);
}
.about-feat .ic {
  width: 2.625rem; height: 2.625rem; flex-shrink: 0; display: grid; place-items: center;
  background: var(--gold-pale); border-radius: 12px; color: var(--burgundy);
}
.about-feat b { display: block; font-size: 1rem; margin-bottom: 2px; }
.about-feat small { color: var(--ink-soft); font-size: 1rem; line-height: 1.4; }

/* ============ ОТЗЫВЫ ============ */
/* фон секции отзывов не нужен: они внутри «Наше кафе» */
/* Единый блок «Наше кафе» (13.08): слева зал, справа рассказ, отзывы полосой снизу.
   Раньше это были три секции подряд — #cafe, #about, #reviews. */
/* stretch: высоту задаёт колонка с фото, правая тянется под неё — карточки-факты
   разъезжаются по свободному месту, и обе колонки кончаются вровень. */
.cafe-in { display: grid; grid-template-columns: .95fr 1.05fr; gap: 3.75rem; align-items: stretch; }
/* Фото зала занимают всю высоту колонки: третье — во всю ширину, ряды равные.
   Заглушки тянутся вместе с ячейкой, иначе колонка обрывалась выше правой. */
.cafe-side { display: flex; flex-direction: column; }
.cafe-side .cafe-photos { flex: 1; grid-template-columns: 1fr 1fr; grid-auto-rows: 1fr; gap: 1.125rem; }
.cafe-side .cafe-photo { height: 100%; }
.cafe-side .cafe-photo:nth-child(3) { grid-column: 1 / -1; }
.cafe-side .cafe-ph { height: 100%; min-height: 10rem; }
.cafe-in + .cafe-facts { justify-content: center; gap: .75rem 2.25rem; margin-top: 2.5rem; }
.cafe-story-title {
  font-family: var(--font-display); font-weight: 400;
  font-size: clamp(1.75rem, 2.4vw, 2.375rem); line-height: 1.15;
  color: var(--burgundy-ink); margin: 0 0 1.25rem;
}
.cafe-story p { color: var(--ink-soft); font-size: 1.0625rem; margin-bottom: 1rem; }
.cafe-story p b { color: var(--ink); }
.cafe-reviews { margin-top: 3.75rem; padding-top: 2.5rem; border-top: 1px solid var(--gold-pale); }
.cafe-reviews-note { text-align: center; color: var(--ink-soft); margin-bottom: 1.75rem; }

/* Живая лента с Яндекс Карт — свёрнута, чтобы чужое оформление не спорило с нашим.
   Открывается по клику, тогда же грузится iframe (см. app.js). */
.reviews-live { margin-top: 2rem; }
.reviews-live > summary {
  display: flex; align-items: center; justify-content: center; gap: .5rem;
  padding: .875rem 1.25rem; cursor: pointer; list-style: none;
  font-size: 1rem; font-weight: 600; color: var(--burgundy-ink);
  background: var(--gold-pale); border-radius: 999px; width: fit-content; margin: 0 auto;
  transition: background .25s ease, color .25s ease;
}
.reviews-live > summary::-webkit-details-marker { display: none; }
.reviews-live > summary:hover { background: rgba(201, 151, 63, .28); }
.reviews-live > summary:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }
.reviews-live > summary svg { width: 1.125rem; height: 1.125rem; transition: transform .3s ease; }
.reviews-live[open] > summary svg { transform: rotate(180deg); }
/* Виджет рисует себя не шире ~47rem и на широком контейнере оставлял серую пустоту
   справа — держим рамку по его ширине и по центру. */
.reviews-live-frame {
  margin: 1.5rem auto 0; max-width: 47rem; border-radius: 18px; overflow: hidden;
  box-shadow: var(--shadow-card); background: var(--card);
}
.reviews-live-frame iframe { display: block; width: 100%; height: 34rem; border: none; }
@media (max-width: 700px) {
  .reviews-live-frame iframe { height: 30rem; }
}


@media (max-width: 900px) {
  .cafe-in { grid-template-columns: 1fr; gap: 2.5rem; }
  .cafe-side .cafe-facts { justify-content: center; }
}

.reviews-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.625rem; align-items: stretch; }
.review-card {
  background: var(--card); border-radius: 22px;
  padding: 30px 32px; box-shadow: var(--shadow-card);
  display: flex; flex-direction: column;
  position: relative;
}
.review-card .quote {
  font-family: var(--font-display); font-size: 3.75rem; line-height: 1;
  color: var(--gold-pale); position: absolute; top: 1.125rem; right: 1.625rem;
}
.review-stars { color: #F5A623; font-size: 1.0625rem; letter-spacing: 2px; margin-bottom: 0.875rem; }
.review-text { flex: 1; font-size: 1rem; line-height: 1.6; color: var(--ink); margin-bottom: 1.125rem; }
.review-author { display: flex; align-items: center; gap: 0.75rem; }
.review-ava {
  width: 2.75rem; height: 2.75rem; border-radius: 50%;
  display: grid; place-items: center;
  font-weight: 800; color: #fff; font-size: 1.0625rem;
}
.review-author b { display: block; font-size: 1rem; }
.review-author small { color: var(--ink-soft); font-size: 1rem; }
.review-hero {
  background: var(--girih-dark), var(--burgundy); color: #fff;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; gap: 6px;
}
.review-hero .big { font-family: var(--font-display); font-size: 4rem; line-height: 1; }
.review-hero .stars { color: var(--gold-soft); font-size: 1.25rem; letter-spacing: 3px; }
.review-hero p { color: rgba(243, 221, 194, .9); font-size: 1rem; margin: 8px 0 1.125rem; }
.btn-yandex {
  background: #fff; color: var(--burgundy-deep);
  padding: 0.8125rem 1.5rem; border-radius: 0.8125rem; font-weight: 800; font-size: 0.9375rem;
  transition: transform .2s, box-shadow .2s;
}
.btn-yandex:hover { transform: translateY(-2px); box-shadow: 0 8px 22px rgba(0,0,0,.25); }

/* ============ ДОСТАВКА ============ */
/* stretch, а не start: иначе правая колонка обрывается на 80 px выше левой и низ блока
   выглядит рваным. Карточки справа тянутся поровну и обе колонки заканчиваются вровень. */
.delivery-grid { display: grid; grid-template-columns: 1.15fr .85fr; gap: 2.5rem; align-items: stretch; }
.delivery-table {
  background: var(--card); border-radius: 22px; overflow: hidden;
  box-shadow: var(--shadow-card);
  /* на 390 три колонки перестали помещаться и таблица вылезала за экран на 7px:
     фиксированная раскладка держит колонки в пределах ширины родителя */
  width: 100%; table-layout: fixed;
}
.delivery-table th, .delivery-table td { word-break: break-word; }
.delivery-table table { width: 100%; border-collapse: collapse; }
.delivery-table th {
  background: var(--burgundy); color: #fff;
  font-size: 0.9375rem; text-align: left; padding: 1rem 1.5rem;
  font-weight: 700;
}
.delivery-table td { padding: 17px 24px; border-bottom: 1px solid rgba(201, 151, 63, .18); font-size: 0.9375rem; }
.delivery-table tr:last-child td { border-bottom: none; }
.delivery-table td b { font-size: 1.0625rem; }
.delivery-table .free { color: var(--green); font-weight: 800; }
.delivery-note {
  padding: 16px 24px; background: var(--gold-pale);
  color: var(--burgundy-deep); font-weight: 700; font-size: 0.9688rem;
  display: flex; align-items: center; gap: 0.625rem;
}
/* 14.08: таблица во всю ширину, три карточки под ней в ряд. Прежний строй в две колонки
   зажимал таблицу в 1,15 доли (цены — главное в блоке) и заставлял карточку «Оплата»
   тянуться под соседнюю, оставляя внизу пустоту. */
.delivery-table-wide { max-width: none; }
.delivery-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.625rem; margin-top: 1.625rem; }
.delivery-row > .delivery-card { height: 100%; }
/* «Предзаказ к дате и времени» — единственный заголовок в две строки, и его текст уходил
   ниже соседних: ряд читался съехавшим (Оператор 14.08). Держим место под две строки
   у всех трёх, тогда абзацы начинаются с одной линии. */
.delivery-row .delivery-card b { line-height: 1.3; min-height: 2.6em; }

@media (max-width: 1000px) {
  .delivery-row { grid-template-columns: 1fr; }
  .delivery-row .delivery-card b { min-height: 0; }
}

/* Самовывоз — полноценная карточка: это второй способ получить заказ, а не примечание */
.delivery-card.card-pickup {
  background: var(--card); border-radius: 22px; padding: 1.75rem 1.875rem;
  box-shadow: var(--shadow-card); border: none;
  display: flex; gap: 1.125rem; align-items: flex-start; flex-direction: row;
}
.delivery-card.card-pickup .ic {
  width: 3rem; height: 3rem; flex-shrink: 0; display: grid; place-items: center;
  background: rgba(201, 151, 63, .16); border-radius: 13px; color: var(--burgundy);
}
.delivery-card.card-pickup b { display: block; font-size: 1.1875rem; margin-bottom: .35rem; color: var(--burgundy-ink); }
.delivery-card.card-pickup p { color: var(--ink-soft); font-size: 1rem; line-height: 1.5; }
.delivery-card.card-pickup span:last-child { flex: 1; }

/* Правая колонка держит тот же строй, что левая: белая карточка, та же тень и радиус,
   иконка слева, текст справа. До 13.08 предзаказ был бежевым градиентом, а оплата —
   почти прозрачной сноской: колонки не читались как пара. */
.delivery-card.card-preorder,
.delivery-card.card-payment {
  background: var(--card); border-radius: 22px; padding: 1.75rem 1.875rem;
  box-shadow: var(--shadow-card); border: none;
  display: flex; gap: 1.125rem; align-items: flex-start; flex-direction: row;
}
.delivery-card.card-preorder .ic,
.delivery-card.card-payment .ic {
  width: 3rem; height: 3rem; flex-shrink: 0; display: grid; place-items: center;
  background: rgba(201, 151, 63, .16); border-radius: 13px; color: var(--burgundy);
  opacity: 1;
}
.delivery-card.card-preorder b,
.delivery-card.card-payment b {
  display: block; font-size: 1.1875rem; margin-bottom: .35rem;
  color: var(--burgundy-ink); font-weight: 700; opacity: 1;
}
.delivery-card.card-preorder p,
.delivery-card.card-payment p {
  color: var(--ink-soft); font-size: 1rem; line-height: 1.5; opacity: 1; margin-bottom: 0;
}
.delivery-card.card-preorder span:last-child,
.delivery-card.card-payment span:last-child { flex: 1; }

/* 13.08: плашки платёжных систем сняты решением Оператора — осталась одна строка про оплату.
   Правила .pay-methods/.pay-option удалены вместе с разметкой. */

/* Старый класс .pay-row и .pay-chip остаются для совместимости, если нужны */
.pay-row { display: none; }

/* Плашка про акцию снята 13.08: раздел о доставке, подарки живут в «Акциях». */

/* ============ КОНТАКТЫ ============ */
#contacts { background: var(--bg-soft); padding-bottom: 0; }
.contacts-grid { display: grid; grid-template-columns: .9fr 1.1fr; gap: 2.5rem; margin-bottom: 4rem; }
.contact-list { display: flex; flex-direction: column; gap: 8px; }
.contact-item {
  display: flex; gap: 1rem; align-items: flex-start;
  padding: 1.125rem 1.25rem; border-radius: 1rem;
  transition: background .2s;
}
.contact-item:hover { background: var(--card); }
.contact-item .ic {
  width: 2.875rem; height: 2.875rem; flex-shrink: 0; display: grid; place-items: center;
  background: var(--card); border: 1px solid rgba(201, 151, 63, .3);
  border-radius: 0.8125rem; color: var(--burgundy);
}
.contact-item b { display: block; font-size: 1.0625rem; margin-bottom: 3px; }
.contact-item a { min-height: 1.6rem; display: flex; align-items: center; }
.contact-item a b { transition: color .2s; }
.contact-item a:hover b { color: var(--burgundy); }
.contact-item small { color: var(--ink-soft); font-size: 1rem; }
.socials { display: flex; gap: 0.75rem; margin-top: 1.125rem; padding-left: 1.25rem; }
.social {
  width: 3.25rem; height: 3.25rem; border-radius: 0.9375rem;
  display: grid; place-items: center; color: #fff;
  transition: transform .2s, box-shadow .2s;
  min-width: 1.6rem; min-height: 1.6rem;
}
.social:hover { transform: translateY(-3px); box-shadow: 0 8px 20px rgba(0,0,0,.22); }
.social.vk { background: #0077FF; }
.social.wa { background: #25D366; }
.social.tg { background: #2AABEE; }
/* 19.08: кнопка МАКС по просьбе клиента. Фирменный градиент MAX — цвета сняты
   пипеткой с официальной иконки max.ru (левый низ #0CC0FA → правый #A210FC).
   Ссылки нет, поэтому не кликается: курсор обычный, подъём при наведении снят. */
.social.max { background: linear-gradient(120deg, #0CC0FA 0%, #3961FA 42%, #A210FC 100%); }
.social[aria-disabled="true"] { cursor: default; }
.social[aria-disabled="true"]:hover { transform: none; box-shadow: 0 4px 12px rgba(0,0,0,.14); }
.map-open { display: none; }   /* на десктопе карточка открыта прямо в виджете */
.map-wrap {
  border-radius: 1.5rem; overflow: hidden;
  box-shadow: var(--shadow-card);
  min-height: 420px; background: var(--gold-pale);
  position: relative;
}
.map-wrap iframe { width: 100%; height: 100%; min-height: 420px; border: 0; display: block; }

/* ============ FOOTER ============ */
.footer { background: var(--girih-dark), var(--burgundy-ink); color: rgba(243, 221, 194, .75); padding: 3rem 0 1.75rem; }
.footer-in { display: grid; grid-template-columns: 1.35fr 1fr 1fr; gap: 3.5rem; margin-bottom: 1.75rem; align-items: start; }
.footer .brand-name { color: var(--gold-soft); }
.footer p { font-size: 1rem; margin-top: 0.625rem; max-width: 21rem; line-height: 1.5; }
.footer h4 { color: #fff; font-size: 1rem; letter-spacing: .08em; text-transform: uppercase; margin-bottom: 0.75rem; }
.footer ul { list-style: none; }
.footer li { margin-bottom: 0.375rem; line-height: 1.4; }
.footer li a {
  font-size: 1rem; transition: color .2s;
  display: inline-flex; align-items: center;
  min-height: 1.6rem; padding: 0.4rem 0;
}
.footer li a:hover { color: var(--gold-soft); }
.footer-bottom {
  border-top: 1px solid rgba(230, 189, 113, .18);
  padding-top: 1.375rem; font-size: 0.875rem;
  display: flex; justify-content: space-between; gap: 0.875rem; flex-wrap: wrap;
  /* было .5 — замер дал 4.00:1 при пороге 4.5 для мелкого текста. Реквизиты
     ИП по закону читаемы, а не «есть где-то в подвале».
     .70, а не .64: под глифами проходит штрих гирих-паттерна, и в худшей точке
     фона .64 давало 4.58:1 — запас меньше двух процентов от порога. */
  color: rgba(243, 221, 194, .70);
}

/* ПРАВОВЫЕ ССЫЛКИ — своей строкой под реквизитами.
   В общем ряду со space-between они прижимались к правому краю и читались
   продолжением строки про студию: гость не понимал, что это документы магазина.
   Подчёркивание оставляем — единственный признак ссылки в подвале, где всё
   одного цвета. Контраст поднят до порога замером, не на глаз. */
.footer-legal {
  flex-basis: 100%;
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.25rem 0.5rem;
  /* ближе к реквизитам, чем к краю подвала: строка подчинена им, а не висит
     самостоятельным третьим элементом (замер: 32,5 px сверху против 29,25 снизу) */
  padding-top: 0.5rem;
}
.footer-legal a {
  /* .78, а не .88: ссылки меню и контактов в подвале идут на .75, и правовая
     обязаловка не должна быть самым ярким пятном подвала кафе. Порог держим
     замером с запасом, отличает их подчёркивание, а не яркость. */
  color: rgba(243, 221, 194, .78);
  text-decoration: underline; text-underline-offset: 3px;
  text-decoration-color: rgba(230, 189, 113, .5);
}
.footer-legal a:hover, .footer-legal a:focus-visible {
  color: #fff; text-decoration-color: currentColor;
}

/* Подпись студии в строке реквизитов: та же яркость и то же подчёркивание, что у
   правовых ссылок — в подвале всё одного цвета, и подчёркивание единственный
   признак ссылки. 8,19:1 на burgundy-ink (замер, не на глаз). */
.footer-studio {
  color: rgba(243, 221, 194, .78);
  text-decoration: underline; text-underline-offset: 3px;
  text-decoration-color: rgba(230, 189, 113, .5);
  transition: color .2s;
}
.footer-studio:hover, .footer-studio:focus-visible {
  color: #fff; text-decoration-color: currentColor;
}

/* ============ КОРЗИНА ============ */
/* 13.08: кнопка звонка снята решением Оператора — телефон есть в верхней полосе,
   в шапке и в контактах. Корзина осталась одна и встала на её место, став крупнее. */
.cart-fab {
  position: fixed; right: 1.625rem; bottom: 1.625rem; z-index: 95;
  width: 4.75rem; height: 4.75rem; border-radius: 50%;
  background: var(--burgundy); color: #fff;
  display: grid; place-items: center;
  box-shadow: 0 8px 26px rgba(136, 8, 11, .5);
  transition: transform .25s, opacity .25s;
  opacity: 0; transform: scale(.5); pointer-events: none;
}
/* значок растёт вместе с кнопкой, иначе в крупном круге он выглядит потерянным */
.cart-fab svg { width: 1.9rem; height: 1.9rem; }
.cart-fab.show { opacity: 1; transform: scale(1); pointer-events: auto; }
/* пустая корзина стоит на месте, но не кричит: тише по тону, пока в ней ничего нет */
.cart-fab.is-empty { background: var(--burgundy-deep); box-shadow: 0 6px 18px rgba(92, 10, 14, .35); }
.cart-fab:hover { transform: scale(1.08); }
.cart-count {
  position: absolute; top: -4px; right: -4px;
  background: var(--gold); color: #fff;
  min-width: 1.625rem; height: 1.625rem; border-radius: 6.25rem;
  display: grid; place-items: center;
  font-size: 0.875rem; font-weight: 800;
  border: 2.5px solid var(--bg);
  padding: 0 6px;
}
/* ползунок калькулятора: дорожка тонкая, но нажимать по ней пальцем надо —
   добираем высоту цели, не раздувая саму дорожку */
#calcRange { min-height: 1.6rem; padding: 0.5rem 0; background: transparent; }

/* модалка корзины */
.modal-overlay {
  position: fixed; inset: 0; z-index: 200;
  background: rgba(43, 24, 16, .55); backdrop-filter: blur(4px);
  display: none; align-items: center; justify-content: center;
  padding: 1.25rem;
}
.modal-overlay.open { display: flex; }
/* 🩸 17.08: страница за открытой корзиной прокручивалась колесом и пальцем —
   гость листал корзину, а под ней уезжало меню. Ширину полосы компенсирует JS. */
html.modal-open, body.modal-open { overflow: hidden; }
.modal {
  background: var(--bg); border-radius: 26px;
  width: 100%; max-width: 35rem; max-height: 90vh;
  overflow-y: auto; padding: 2.25rem 2.375rem;
  box-shadow: 0 40px 100px rgba(0,0,0,.4);
  position: relative;
  animation: modalIn .3s cubic-bezier(.22,.61,.36,1);
}
@keyframes modalIn { from { opacity: 0; transform: translateY(30px) scale(.97); } to { opacity: 1; transform: none; } }
.modal-close {
  position: absolute; top: 1.125rem; right: 1.125rem;
  width: 2.5rem; height: 2.5rem; border-radius: 50%;
  background: var(--bg-soft); color: var(--ink);
  font-size: 1.1875rem; display: grid; place-items: center;
  transition: background .2s;
}
.modal-close:hover { background: var(--gold-pale); }
.modal h3 { font-family: var(--font-display); font-weight: 400; font-size: 1.6875rem; color: var(--burgundy-ink); margin-bottom: 1.375rem; }
.cart-items { display: flex; flex-direction: column; gap: 4px; margin-bottom: 1.125rem; }
.cart-item {
  display: flex; align-items: center; gap: 0.875rem;
  padding: 12px 0; border-bottom: 1px dashed rgba(201, 151, 63, .35);
}
.cart-item img { width: 3.875rem; height: 3.125rem; object-fit: cover; border-radius: 0.625rem; }
.cart-item-info { flex: 1; }
.cart-item-info b { font-size: 0.9375rem; display: block; line-height: 1.3; }
.cart-item-info small { color: var(--ink-soft); font-size: 0.8125rem; }
.qty { display: flex; align-items: center; gap: 4px; }
.qty button {
  width: 2rem; height: 2rem; border-radius: 0.5625rem;
  background: var(--gold-pale); color: var(--burgundy-deep);
  font-size: 1.0625rem; font-weight: 800;
  transition: background .15s;
}
.qty button:hover { background: var(--gold-soft); }
.qty span { min-width: 1.75rem; text-align: center; font-weight: 800; }
/* степпер на карточке меню/сета (вместо кнопки «В корзину») */
.add-slot { display: inline-flex; }
.qty-card { gap: 4px; }
.qty-card button {
  background: var(--burgundy); color: #fff;
  width: 1.875rem; height: 1.875rem; border-radius: 4px;
  font-size: 1rem;
}
.qty-card button:hover { background: var(--burgundy-hover); }
.qty-card span { color: var(--burgundy-deep); font-size: 1rem; min-width: 1.5rem; }
.cart-item-price { font-weight: 800; min-width: 4.75rem; text-align: right; font-size: 0.9688rem; }
.cart-promo {
  background: var(--gold-pale); border-radius: 14px;
  padding: 0.8125rem 1.125rem; font-size: 0.9062rem; font-weight: 700;
  color: var(--burgundy-deep);
  display: flex; gap: 0.5625rem; align-items: center;
  margin-bottom: 1.25rem;
}
.cart-total {
  display: flex; justify-content: space-between; align-items: baseline;
  font-size: 1.1875rem; font-weight: 800; margin-bottom: 1.5rem;
}
.cart-total .sum { font-family: var(--font-display); font-size: 1.875rem; color: var(--burgundy); }
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0.875rem; margin-bottom: 1.25rem; }
.form-field { display: flex; flex-direction: column; gap: 6px; }
.form-field.wide { grid-column: 1 / -1; }
.form-field label { font-size: 0.875rem; font-weight: 700; color: var(--ink-soft); }
.form-field input, .form-field select {
  font-family: inherit; font-size: 1rem;
  padding: 0.8125rem 1rem; border-radius: 0.75rem;
  border: 1.5px solid rgba(201, 151, 63, .4);
  background: var(--card); color: var(--ink);
  outline: none; transition: border .2s;
}
.form-field input:focus, .form-field select:focus { border-color: var(--burgundy); }
/* ── ФОРМА ЗАКАЗА: по образцу боевой формы клиента (снято 22.08) ──────── */

/* текст акции — как у клиента, прямо в корзине, до выбора способа получения */
.cart-promo-static {
  background: var(--gold-pale); border-radius: 14px;
  padding: 0.8125rem 1.125rem; margin-bottom: 1.25rem;
  font-size: 0.9062rem; line-height: 1.5; color: var(--burgundy-deep);
}
.cart-promo-static b { font-weight: 800; }
.cart-promo-static .promo-left {
  display: block; margin-top: 0.375rem;
  font-weight: 700; color: var(--burgundy);
}

/* три варианта получения списком, а не двумя кнопками: у клиента их три,
   и «доставка в область» кнопкой в ряд не помещается */
.receive-choice { margin-bottom: 1.25rem; }
.receive-title { font-size: 0.9375rem; font-weight: 700; color: var(--ink-soft); margin-bottom: 0.625rem; }
.receive-row {
  display: flex; align-items: center; gap: 0.625rem;
  padding: 0.75rem 0.9375rem; margin-bottom: 0.5rem;
  border: 1.5px solid rgba(201, 151, 63, .4); border-radius: 0.8125rem;
  background: var(--card); cursor: pointer;
  font-size: 0.9375rem; line-height: 1.35;
  transition: border-color .2s, background .2s;
}
.receive-row input { accent-color: var(--burgundy); width: 18px; height: 18px; flex: none; }
.receive-row.active { border-color: var(--burgundy); background: rgba(136, 8, 11, .04); font-weight: 700; }

/* телефон: флаг страны слева, как в форме клиента; страна зашита — только Россия */
.phone-wrap { position: relative; display: flex; align-items: center; }
.phone-wrap .phone-flag {
  position: absolute; left: 0.875rem; display: flex; align-items: center;
  line-height: 1; pointer-events: none;
}
.phone-wrap input { flex: 1; padding-left: 2.875rem; }

/* адрес — многострочный, как у клиента */
.form-field textarea {
  font-family: inherit; font-size: 1rem;
  padding: 0.8125rem 1rem; border-radius: 0.75rem;
  border: 1.5px solid rgba(201, 151, 63, .4);
  background: var(--card); color: var(--ink);
  outline: none; resize: vertical; min-height: 5.25rem;
  transition: border .2s;
}
.form-field textarea:focus { border-color: var(--burgundy); }

/* пояснение под подписью поля — «Укажите интервал времени…» у клиента */
.field-note { font-size: 0.8125rem; color: var(--ink-soft); margin: -2px 0 2px; }

/* итоговая сумма перед кнопкой — второй раз, как в форме клиента */
.cart-total-final { margin-bottom: 1rem; }

.receive-toggle { display: flex; gap: 0.625rem; margin-bottom: 1.25rem; }
.receive-toggle button {
  flex: 1; padding: 0.8125rem; border-radius: 0.8125rem;
  border: 1.5px solid rgba(201, 151, 63, .4);
  background: var(--card); font-weight: 700; font-size: 15px;
  transition: all .2s;
}
.receive-toggle button.active {
  background: var(--burgundy); color: #fff; border-color: var(--burgundy);
}
.btn-submit {
  width: 100%; padding: 1.0625rem; border-radius: 0.9375rem;
  background: var(--burgundy); color: #fff;
  font-size: 1.125rem; font-weight: 800;
  box-shadow: 0 6px 20px rgba(136, 8, 11, .35);
  transition: background .2s, transform .2s;
}
.btn-submit:hover { background: var(--burgundy-hover); transform: translateY(-1px); }
.cart-empty { text-align: center; color: var(--ink-soft); padding: 1.875rem 0; }
.demo-note { text-align: center; font-size: 0.8125rem; color: var(--ink-soft); margin-top: 0.875rem; }

/* тост */
.toast {
  position: fixed; left: 50%; bottom: 2.125rem; z-index: 300;
  transform: translateX(-50%) translateY(80px);
  background: var(--burgundy-ink); color: #fff;
  padding: 0.9375rem 1.625rem; border-radius: 6.25rem;
  font-weight: 700; font-size: 0.9688rem;
  box-shadow: 0 12px 34px rgba(0,0,0,.35);
  opacity: 0; transition: all .35s cubic-bezier(.22,.61,.36,1);
  display: flex; align-items: center; gap: 0.625rem;
  pointer-events: none; max-width: 90vw;
}
.toast.show { transform: translateX(-50%); opacity: 1; }

/* ============ ЧАТ-ВИДЖЕТ (заглушка) ============ */

/* ============ АДАПТИВ ============ */
@media (max-width: 1100px) {
  .menu-grid { grid-template-columns: repeat(2, 1fr); }
  .sets-grid { grid-template-columns: repeat(2, 1fr); }
  .reviews-grid { grid-template-columns: repeat(2, 1fr); }
  .strip .container { grid-template-columns: repeat(2, 1fr); gap: 22px; }
  .nav { display: none; }
  .burger { display: flex; }
  /* планшеты: топбар может переноситься (nowrap только на широком десктопе) */
  .topbar .container { flex-wrap: wrap; gap: 6px 18px; }
  .hero { height: auto; min-height: 0; }
  /* Отрицательный отступ первого экрана — приём для широкого кадра, где фото высокое.
     На узком он загонял верх блока под липкую шапку. Здесь отступа нет, блок стоит от верха. */
  .hero-text { max-width: 100%; margin-top: 0; }
  /* 14.08: горизонтальные поля тут стояли нулевыми — на 721…1024 заголовок и кнопки
     упирались в самый край экрана. Держим поля секций. */
  .hero-in { padding: 32px 1.5rem 44px; }
  .hero-cta-note { font-size: 22px; }
  /* наезд слабее: на узком фото ниже и текст стоит от верха */
  .hero { margin-bottom: -5rem; }
  .badge { font-size: 14px; }
  .btn-lg { font-size: 17px; }
  .hero-note { font-size: 14px; }
  .about-in { grid-template-columns: 1fr; gap: 44px; }
  .delivery-grid { grid-template-columns: 1fr; }
  .contacts-grid { grid-template-columns: 1fr; }
  .footer-in { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 1024px) {
  body { font-size: 16px; }
  section { padding: 60px 0; }
  /* 14.08: одна карточка во всю ширину давала один экран на одно блюдо — 56 позиций
     листались бесконечно, а фото 4:3 занимало пол-экрана. Две в ряд: за экран видно
     четыре блюда, сравнение цен идёт глазом по горизонтали. Меньше кегль и отступы,
     но не ниже пола 13 px и не тесней 44 px у кнопки (аудитория возрастная). */
  .menu-grid { grid-template-columns: 1fr 1fr; gap: 0.875rem; }
  .menu-grid .dish-body { padding: 0.75rem 0.8125rem 0.875rem; }
  .menu-grid .dish-top { flex-direction: column; align-items: flex-start; gap: 2px; margin-bottom: 5px; }
  .menu-grid .dish h3 { font-size: 15px; line-height: 1.25; }
  .menu-grid .dish-weight { font-size: 13px; }
  .menu-grid .dish-desc { font-size: 13px; line-height: 1.4; margin-bottom: 0.625rem;
                          display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
                          overflow: hidden; }
  .menu-grid .dish-foot { flex-direction: column; align-items: stretch; gap: 8px; }
  .menu-grid .dish-price { font-size: 21px; }
  .menu-grid .btn-add { min-height: 44px; padding: 10px 12px; font-size: 14px; }
  .menu-grid .dish-tag { font-size: 12px; padding: 5px 10px; }
  /* 14.08, Оператор: одна карточка сета на экран — «слишком плотно», нужны две в ряд.
     В 170 px строка «С курицей жульен — 1 570 ₽» не помещается, поэтому на телефоне
     в составе остаются только названия: цена каждого пирога есть в самом меню, а в сете
     гостю важна итоговая. Всё остальное — фото, число пирогов, подарок, итог, кнопка —
     на месте. */
  /* 14.08: пробовали две карточки сета в ряд — Оператор отменил («плохо выглядят,
     лучше как было»). Возвращаем одну на всю ширину: состав с ценами читается
     целиком, а не ужимается до одних названий. */
  .sets-grid { grid-template-columns: 1fr; }
  .cafe-photos { grid-template-columns: 1fr; }
  .reviews-grid { grid-template-columns: 1fr; }
  .promo-grid { grid-template-columns: 1fr; }
  /* на мобильной наезда нет: там первый экран и так плотный, полоса перекрыла бы текст */
  .hero { margin-bottom: 0; }
  /* Козыри сеткой 2×2 занимали 339 px — целый экран за вычетом шапки, и вторая пара
     всё равно уходила под сгиб. Кладём их лентой в одну строку с прокруткой — приём
     из той же ниши (у Ассы так поданы категории): видно, что список продолжается. */
  /* 14.08, Оператор: «все четыре вместить и по высоте меньше». Лента с прокруткой
     прятала половину — возвращаем сетку 2×2, но плашки кладём горизонтально:
     значок слева, текст справа. Так каждая занимает две строки вместо четырёх. */
  .strip .container {
    display: grid; grid-template-columns: 1fr 1fr; gap: 8px;
    /* 14.08, Оператор: сетку поуже — карточки жались к самым краям экрана */
    padding-left: 1.75rem; padding-right: 1.75rem;
    /* и все четыре одной высоты: нижняя пара с длинными подписями была выше верхней,
       ряд об ряд не совпадал */
    grid-auto-rows: 1fr;
  }
  .strip-item {
    flex-direction: row; align-items: flex-start; justify-content: flex-start;
    text-align: left; gap: 6px; height: 100%;
    background: rgba(255, 255, 255, .07); border: 1px solid rgba(230, 189, 113, .28);
    border-radius: 0.75rem; padding: 0.5rem;
  }
  .strip .strip-icon { width: 24px; height: 24px; flex: 0 0 24px; }
  .strip .strip-icon svg { width: 13px; height: 13px; }
  .strip-item b {
    font-size: 13px; line-height: 1.2; white-space: nowrap;
    overflow: hidden; text-overflow: ellipsis; display: block;
  }
  .strip-item small {
    font-size: 12px; line-height: 1.2;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    overflow: hidden; min-height: 2.4em;
  }
  /* плашки набирали 90 и 133 px — пара с длинной подписью выпирала, и вторая строка
     уходила под панель. Ровняем по высоте и сжимаем межстрочное. */
  .strip .container { align-items: stretch; }
  .strip-item span:last-child { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
  /* 14.08, проход №2: полоса набирала 428 px — половину экрана под четыре короткие фразы,
     и вторая пара уходила под сгиб вместе с началом меню. Значок и подпись мельче,
     заголовок остаётся крупным: читают именно его. */
  .strip-icon { width: 38px; height: 38px; }
  .strip-icon svg { width: 20px; height: 20px; }
  .strip-item b { font-size: 15px; }
  .strip-item small { font-size: 12.5px; line-height: 1.35; }
  .about-feats { grid-template-columns: 1fr; }
  .form-grid { grid-template-columns: 1fr; }
  .calc-card { padding: 34px 24px; }
  .calc-row { flex-direction: column; gap: 18px; }
  /* Кнопка занимала 145 px из 345 и жалась к левому краю. На телефоне главное действие
     блока идёт во всю колонку — как остальные кнопки страницы. */
  .calc-result { flex-direction: column; align-items: stretch; text-align: left; gap: 12px; padding: 20px 18px; }
  .calc-result .btn, .calc-result .btn-lg, .calc-result a[class*="btn"], .calc-result button {
    width: 100%; justify-content: center; min-height: 48px;
  }
  .calc-result-text { min-width: 0; }
  /* Цифра держала 7.5rem по центру, и дорожка оставалась узкой полосой сбоку */
  .calc-guests { min-width: 0; }
  /* базовое flex:1 писалось под строку (управляло шириной); на телефоне .calc-row —
     колонка, и то же правило начало управлять ВЫСОТОЙ, схлопнув дорожку до 24 px.
     Ширину берём явно, высоту у flex забираем. */
  input[type="range"] { width: 100%; flex: 0 0 auto; }
  /* 🩸 13.08: горизонтальный отступ был обнулён заодно с вертикальным, и заголовок
     упирался в край экрана — на 390 срезало первую букву. Держим поля контейнера. */
  .hero-in { padding: 24px 1.25rem 36px; }
  /* На узком кнопка и её подпись встают друг под друга. Тогда расстояние решает, к какой кнопке
     подпись относится: внутри пары тесно, между парами просторно. Иначе подпись «доставим!»
     повисает ровно между кнопками и читается как подпись к «Кафе». */
  .hero-cta { flex-direction: row; align-items: center; gap: 11px; }
  .hero-cta .btn-lg { flex: 0 0 37%; }
  .hero-cta-note { flex: 1; text-align: left; }
  .hero-actions { gap: 11px; }
  /* на узком экране заголовок должен влезать в колонку, а не упираться в край: секция
     обрезает лишнее, и текст молча терялся слева. Сдвиг второй строки тут снят совсем —
     на 390 он съедал половину строки. */
  /* 14.08, Оператор: «домашние пироги должны быть больше, чем кнопки» — заголовок
     занимает всю ширину экрана, кнопки уходят в левую часть и становятся мельче. */
  .hero-title { font-size: clamp(2.6rem, 13.2vw, 3.6rem); margin-bottom: 1.25rem;
                letter-spacing: -.01em; }
  .hero-text { width: 100%; max-width: none; }
  .hero-title-accent { margin-left: 0; }
  .hero-cta-note { font-size: 15px; line-height: 1.22; white-space: normal; }
  .btn-lg { padding: 16px 26px; font-size: 16.5px; width: 100%; justify-content: center; }
  /* на узком пилюли снова во всю колонку — жёсткие 13rem с десктопа тут не нужны */
  .hero-cta .btn-lg { width: 100%; padding-top: 11px; padding-bottom: 11px; font-size: 17px; }
  .hero-actions { flex-direction: column; align-items: stretch; }
  .rating-chip { display: none; }
  /* топбар на мобиле: перенос разрешён (десктопный nowrap отменяем), компактно по центру */
  /* 14.08, проход №2: полоса занимала 84 px — выше самой шапки (45). Адрес переносился
     на две строки, хотя он же стоит в шапке-меню, в блоке доставки, в контактах и в подвале.
     На телефоне оставляем то, ради чего сюда смотрят: телефон и два мессенджера. */
  /* 14.08, Оператор: отдельной полосы сверху нет — номер встаёт в шапку справа от
     «Халяль», в то самое белое место. Кнопка звонка снята (номер и так написан),
     бургер снят (весь переход живёт в нижней панели). Шапка стала одной строкой. */
  .topbar { display: none; }
  .header .btn-phone, .burger { display: none; }
  .header-cta { gap: 0; }
  /* 14.08, Оператор: номер оформить пилюлей — «как у нас кнопка Пироги, белым внутри».
     Кегль ниже, зато сам блок читается кнопкой: по нему и правда звонят. */
  .header-phone {
    display: inline-flex; align-items: center; gap: 4px;
    /* 14.08, Оператор: «пилюлю поменьше везде» — компактная плашка на белой шапке */
    font-size: 12px; font-weight: 800; color: #fff;
    background: var(--burgundy); border-radius: 6.25rem;
    padding: 0 0.6875rem; min-height: 30px; align-self: center;
    white-space: nowrap; letter-spacing: -.01em;
    box-shadow: 0 3px 10px rgba(136, 8, 11, .3);
  }
  .header-phone:active { transform: scale(.97); }
  .header-cta { align-items: center; min-height: 44px; }
  /* значок телефона рядом с самим номером — лишний знак: слово уже сказано цифрами,
     а на 390 каждые 20 px решают, встанет название в строку или переломится */
  .header-phone svg { display: none; }
  /* 14.08, мобильный проход: восемь категорий переносом занимали три ряда — пол-экрана
     до первого блюда, и активная вкладка уезжала из поля зрения. Теперь одна строка
     с горизонтальной прокруткой, как в мобильных меню: видно, что список длиннее,
     и до любой категории один жест. Полосу прокрутки прячем, край подсказывает тенью. */
  /* 14.08, Оператор: боковая прокрутка не читается — «сделай в два ряда, чтобы точно
     наглядно». То, что уходило вправо, переносится вниз: все восемь категорий видны
     разом, ничего не надо угадывать. */
  /* Свободный перенос давал 2 ряда на 390 и 3 на 320: «Горячие блюда» шире соседей
     почти вдвое и ломает раскладку. Жёсткая сетка 4×2 — ровно два ряда на любой
     ширине, длинное название переносится внутри своей ячейки. */
  .menu-tabs {
    top: 45px; display: grid; grid-template-columns: repeat(4, 1fr);
    overflow: visible; padding: 7px; gap: 4px; border-radius: 0.875rem;
    -webkit-mask-image: none; mask-image: none;
  }
  .menu-tabs::-webkit-scrollbar { display: none; }
  /* 14.08, Оператор: «непонятно, что там несколько секций и есть что-то ещё».
     Между вкладками тонкие столбики — ряд читается как список, а не как одна кнопка
     с хвостом. Затухание у правого края глубже: обрезанная вкладка показывает,
     куда листать. */
  /* столбики-разделители были нужны при прокрутке в строку; в двух рядах они
     превращаются в мусор между переносами — сняты вместе с прокруткой */
  .tab { position: relative; }
  /* восемь категорий суммарно занимали 805 px — это 2,3 ряда. Ужимаем поля и кегль
     до 700, чтобы легли ровно в два. Цель нажатия остаётся 44 px по высоте. */

  /* между лентой категорий и подписью стоял двойной отступ — на телефоне это пустая полоса
     ровно там, где гость ждёт первое блюдо */
  .menu-note { margin: 0.875rem 0 1rem; font-size: 14.5px; }
  /* цель нажатия: было 37 px по высоте, палец требует 44 */
  /* правило писалось под ленту с прокруткой и стоит ниже нового — оно и держало
     кегль 15 с полями 11/15, из-за чего восемь категорий не укладывались в два ряда */
  .tab { white-space: normal; padding: 7px 4px; font-size: 13px;
         min-height: 44px; display: flex; align-items: center; justify-content: center;
         text-align: center; line-height: 1.15; hyphens: none; }
  /* плавающие кнопки: расстояние между ними, чтобы не перекрывали текст */
  .cart-fab { right: 18px; bottom: 30px; width: 66px; height: 66px; }
  /* на узких экранах (390px) кнопки сдвигаем вверх и раскладываем вертикально */
  @media (max-width: 420px) {
    .cart-fab { bottom: 36px; right: 14px; width: 62px; height: 62px; }
    body { padding-bottom: 0; }
  }
  .modal { padding: 28px 22px; }
  /* 14.08, Оператор: подвал занимал экран с лишним, всё шло одной колонкой.
     Схема: логотип с именем и рассказ по центру, под ними меню и контакты
     двумя колонками — контакты в рамке, реквизиты последней строкой. */
  /* 14.08, Оператор: контактам нужна ширина — адрес и «ВКонтакте, 14 000 подписчиков»
     рвались на две строки. Меню из коротких слов уступает им место. */
  .footer-in { grid-template-columns: 0.82fr 1.18fr; gap: 18px 10px; }
  .footer-in > :first-child { grid-column: 1 / -1; text-align: center; }
  .footer-in > :first-child .brand { justify-content: center; }
  /* рассказ под именем шёл в колонку 34 знака и ломался на четыре строки */
  .footer-in > :first-child p { max-width: none; margin: 0.625rem auto 0; font-size: 13.5px; line-height: 1.45; }
  .footer .brand img { width: 42px !important; height: 42px !important; }
  .footer .brand-name { font-size: 16px; }
  .footer h4 { font-size: 13px; margin-bottom: 0.5rem; }
  .footer li a { font-size: 13.5px; }
  /* рамку у контактов Оператор снял 14.08 — «здесь лишняя»: на бордовом фоне
     она читалась как отдельная плашка, хотя это просто вторая колонка */
  .footer-in > :last-child { padding: 0; }
  .footer-in > :nth-child(2) { padding: 0; }
  /* реквизиты и подпись студии — тоже держим пол 13 px: их читают внимательно */
  .footer-bottom { text-align: center; gap: 4px; font-size: 13px; line-height: 1.4; padding-top: 1rem; }
  /* на телефоне обе ссылки встают в столбик по центру: рядом они не помещаются
     в 375 px и рвались посреди слова «конфиденциальности» */
  .footer-legal { flex-direction: column; align-items: center; gap: 0; padding-top: 1.125rem; }
  /* точка-разделитель в столбике превращалась в отдельную строку из одного знака */
  .footer-legal > span[aria-hidden] { display: none; }
  /* 🩸 Замер критика: между двумя документами оказалось 33 px, а между
     реквизитами и подписью студии — 12,75. Ближе всего друг к другу стояли
     ЧУЖИЕ строки, а пара документов читалась как два оторванных блока —
     ровно та болезнь, от которой строку и отделяли. Лечим двумя вещами:
     коробка тап-цели ниже (разрыв внутри пары падает до ~22 px), а отступ
     сверху больше него — тогда пара видна как группа.
     44 px здесь не теряются: ссылка занимает всю ширину строки, и промах
     пальцем по вертикали ловится соседним полем той же ссылки. */
  .footer-legal a { min-height: 40px; }
  /* подпись студии — ПОСЛЕ документов: служебная строка чужого бренда стояла
     между реквизитами ИП и документами магазина и разрезала данные кафе пополам */
  /* и отодвинута от них: замер после перестановки дал 15 px снизу против 22 px
     внутри пары — студия снова липла к документам ближе, чем они друг к другу */
  .footer-bottom > span:nth-of-type(2) { order: 4; margin-top: 12px; }
  /* 🩸 центр держался длиной текста, а не правилом: `space-between` из базового
     правила остался, и подпись студии стояла на 12 px левее оси. Укоротил бы
     клиент реквизиты — строка уехала бы к левому краю. */
  .footer-bottom { justify-content: center; }
  .map-wrap { min-height: 320px; }
  /* кнопка перехода в карточку кафе — только на телефоне */
  .map-open {
    display: flex; align-items: center; justify-content: center; gap: 8px;
    margin-top: 10px; min-height: 48px; border-radius: 0.875rem;
    background: var(--burgundy); color: #fff; font-weight: 800; font-size: 15px;
    box-shadow: 0 4px 14px rgba(136, 8, 11, .28);
  }
  .map-open svg { width: 18px; height: 18px; }
  .map-open:active { transform: scale(.985); }
  .map-wrap iframe { min-height: 320px; }
  /* 14.08, Оператор: имя пекарни должно читаться первым. Было 15 px — почти как подпись. */
  /* 18 px вместе с номером не оставляли места — название ломалось на две строки.
     16,5 px тоже не помещалось: .brand стоял flex-shrink:0 и вместо переноса РАСПИРАЛ
     страницу до 434 px. Мобильный Chrome отмасштабировал layout, и правый край панели
     («Корзина») ушёл за экран — а проверка на переполнение молчала, потому что
     innerWidth уже был раздут вместе со страницей. Даём шапке сжиматься. */
  /* 14.08, Оператор: «надпись слишком маленькая сверху, сделать больше и по центру».
     Шапка становится сеткой из трёх колонок: логотип слева, имя ровно по середине
     экрана, номер справа. Боковые колонки равной доли — иначе имя съезжает к тому
     краю, где сосед шире. */
  /* 14.08: пробовали имя по центру и номер второй строкой — Оператор отменил
     («это уродство, верни как было»). Раскладка прежняя: логотип слева,
     имя с подписью «Халяль» рядом, номер справа, всё одной строкой. */
  /* 14.08: имя влезало впритык, запас нулевой — и браузер дорисовывал многоточие
     («что это за точки сверху»). Обрезку убираем совсем: имя пекарни не тот текст,
     который можно показать наполовину. Кегль и соседи подобраны с запасом. */
  .brand-name { font-size: 15px; overflow: visible; text-overflow: clip; }
  .brand { flex-shrink: 0; }
  .brand > span { min-width: 0; }
  .brand, .header-in, .header .container { min-width: 0; }
  .brand-sub { font-size: 13px; }
  .brand { gap: 0.4375rem; min-height: 44px; }
  .brand img { width: 38px; height: 38px; }
  /* 14.08, Оператор: пилюля должна лежать НА белой плашке с воздухом, а не занимать
     её целиком. Шапке даём собственные поля, пилюля становится ниже её на 12 px. */
  .header-in { gap: 6px; }
}
/* На 320 название вместе с номером в строку не встаёт — обоим по шагу навстречу.
   ⚠️ 14.08: этот блок открывался БЕЗ своей закрывающей скобки и съедал остаток
   мобильных правил — поля шапки и раскладка .brand переставали работать на 390.
   Скобки при этом сходились: сломанную структуру ловит только проверка на живой
   странице (у .header .container горизонтальный padding обнулялся). */
@media (max-width: 370px) {
  /* на узких экранах имя тоже должно влезать целиком, а не резаться */
  .brand-name { font-size: 13px; }
  .brand-sub { font-size: 13px; }
  .brand img { width: 32px; height: 32px; }
  .header-phone { font-size: 11.5px; padding: 0 0.5rem; }
  .header .container { padding: 0 0.625rem; }
}

@media (max-width: 1024px) {
  .brand { min-height: 44px; }
  /* 46 px тут перебивали 42 из блока выше, и имени не хватало ровно одного пикселя —
     «Пироги по-домашнему» уходило в многоточие. Размер задаётся один раз, выше. */
  /* Блок раскладки от 13.08 снят 14.08: он выравнивал логотип, название, кнопку
     звонка и бургер по краям (justify-content: space-between, .brand flex:1,
     имя 14,5 px). Звонка и бургера в шапке больше нет, имя стоит по центру сеткой —
     старые правила только перебивали новые, из-за чего кегль оставался 14,5. */
  .header .container { padding: 0 1rem; }
  .brand > span { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
}

/* мобильное меню */
.mobile-nav {
  position: fixed; inset: 0; z-index: 150;
  background: rgba(43, 24, 16, .5); backdrop-filter: blur(4px);
  display: none;
}
.mobile-nav.open { display: block; }
.mobile-nav-panel {
  position: absolute; top: 0; right: 0; bottom: 0;
  width: 18.75rem; max-width: 84vw;
  background: var(--bg); padding: 28px;
  display: flex; flex-direction: column; gap: 6px;
  box-shadow: -20px 0 60px rgba(0,0,0,.3);
  animation: slideIn .28s ease;
}
@keyframes slideIn { from { transform: translateX(100%); } to { transform: none; } }
.mobile-nav-panel a {
  padding: 0.875rem 1rem; border-radius: 0.8125rem;
  font-weight: 700; font-size: 1.0625rem;
  transition: background .2s;
  min-height: 1.6rem; display: inline-flex; align-items: center;
}
.mobile-nav-panel a:hover { background: var(--gold-pale); }
.mobile-nav-close { align-self: flex-end; font-size: 1.375rem; padding: 8px 0.75rem; color: var(--burgundy); }

/* ============ ВАЛИДАЦИЯ ФОРМЫ И ОШИБКИ ============ */
.form-field {
  position: relative;
}
.required {
  color: var(--burgundy);
  font-weight: 700;
  margin-left: 2px;
}
.form-field input[aria-invalid="true"],
.form-field select[aria-invalid="true"] {
  border-color: var(--burgundy);
  background-color: rgba(136, 8, 11, 0.03);
}
.error-message {
  display: none;
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--burgundy);
  line-height: 1.3;
  margin-top: 4px;
}
.form-field.has-error .error-message {
  display: block;
}

/* сообщение об ошибке рядом с полем (для видящего гостя) +
   aria-describedby для скринридера */
.form-field input:focus,
.form-field select:focus {
  border-color: var(--burgundy);
  box-shadow: 0 0 0 3px rgba(136, 8, 11, 0.1);
}

/* ============ ПОДТВЕРЖДЕНИЕ ЗАКАЗА ============ */
.order-confirmation {
  text-align: center;
  padding: 2rem 0;
  animation: confirmIn 0.5s cubic-bezier(0.22, 0.61, 0.36, 1);
}
@keyframes confirmIn {
  from {
    opacity: 0;
    transform: scale(0.95) translateY(10px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
.confirmation-icon {
  width: 4rem;
  height: 4rem;
  background: var(--green);
  color: #fff;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.875rem;
  font-weight: 800;
  margin: 0 auto 1rem;
  box-shadow: 0 4px 20px rgba(30, 122, 70, 0.25);
}
.order-confirmation h4 {
  font-family: var(--font-display);
  font-size: 1.625rem;
  font-weight: 400;
  color: var(--burgundy-ink);
  margin-bottom: 0.875rem;
}
.confirmation-main {
  font-size: 1rem;
  color: var(--ink);
  margin-bottom: 1.5rem;
  line-height: 1.5;
}
.confirmation-main b {
  color: var(--burgundy);
  font-weight: 800;
}
.confirmation-details {
  background: var(--gold-pale);
  border-radius: 1rem;
  padding: 1.125rem 1rem;
  margin-bottom: 1.5rem;
  text-align: left;
}
.confirmation-details div {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 0.9375rem;
  margin-bottom: 0.625rem;
}
.confirmation-details div:last-child {
  margin-bottom: 0;
}
.confirmation-details span {
  color: var(--ink-soft);
  font-weight: 600;
}
.confirmation-details b {
  color: var(--burgundy-deep);
  font-weight: 800;
}
.confirmation-text {
  font-size: 0.9375rem;
  color: var(--ink-soft);
  line-height: 1.5;
  margin-bottom: 1.5rem;
}
.btn-close-order {
  padding: 0.75rem 1.75rem;
  background: var(--burgundy);
  color: #fff;
  border-radius: 0.75rem;
  font-weight: 700;
  font-size: 1rem;
  transition: background 0.2s, transform 0.2s;
}
.btn-close-order:hover {
  background: var(--burgundy-hover);
  transform: translateY(-1px);
}

/* Разделитель между секциями: звезда с золотыми усиками — тот же знак, что в шапках. */
.sec-break {
  max-width: 75rem; margin: 0 auto; padding: 0 1.5rem;
  display: flex; align-items: center; justify-content: center; gap: 1.125rem;
}
.sec-break::before, .sec-break::after {
  content: ''; height: 1px; flex: 1; max-width: 13rem;
  background: linear-gradient(90deg, transparent, rgba(201, 151, 63, .5));
}
.sec-break::after { transform: scaleX(-1); }
.sec-break svg { flex: none; }

/* Плейсхолдер зала — принят в live-режиме 13.08 (вариант «тёмный якорь»).
   Три одинаковые кремовые заглушки левой колонки не держали блок: место занято, а веса нет.
   Бордовая плита с решёткой girih — тот же приём, что на полосе козырей и в сетах, —
   даёт колонке опору и честно говорит, что снимки будут. Тон и крупность узора выбраны
   Оператором ползунками (bordo, 1.1) и вшиты значениями. */
.ph-dark {
  height: 100%; min-height: 20rem;
  border-radius: var(--radius); overflow: hidden;
  background: var(--girih-dark), var(--burgundy);
  background-size: 105.6px 105.6px, auto;
  display: grid; place-items: center; text-align: center; padding: 2.5rem;
  box-shadow: 0 10px 32px rgba(92, 10, 14, .22);
}
.ph-dark .ph-in { display: grid; justify-items: center; gap: .5rem; }
.ph-dark .ph-cam { width: 3rem; height: 3rem; color: var(--gold-soft); }
.ph-dark b {
  font-family: var(--font-display); font-weight: 400;
  font-size: 1.75rem; color: #fff; line-height: 1.2;
}
.ph-dark small { color: rgba(243, 221, 194, .9); font-size: 1rem; }
.ph-dark .ph-dots { display: flex; gap: .5rem; margin-top: .75rem; }
.ph-dark .ph-dots i { width: .5rem; height: .5rem; border-radius: 50%; background: rgba(230, 189, 113, .55); }

/* Правая колонка «Наше кафе» — принят в live-режиме 13.08 (вариант «два столбца»).
   Рассказ и факты стоят рядом, а не друг под другом: колонка перестала быть длинной
   лентой, факты читаются перечнем. Разделители — волосяные золотые линии вместо плашек:
   четыре карточки внутри карточки были вложенностью без нужды. Ширина правой части
   и линии выбраны Оператором ползунками и вшиты значениями. */
/* 13.08, правка Оператора после приёмки: факты идут ПОД рассказом, а не третьим столбцом.
   В превью варианта они стояли сбоку, и на живой странице блок читался как три колонки —
   тёмная плита, текст, перечень. Вид перечня оставлен (иконка, строка, волосяная линия),
   изменилось только место: две колонки под текстом, во всю ширину правой части. */
.cafe-story { display: flex; flex-direction: column; height: 100%; }
.cafe-story > div { min-width: 0; }
/* 14.08: сетка 2×2 с линейками читалась таблицей и давала рваный низ — подписи
   разной длины ломали ряд. Теперь три пункта в ряд, разделяет воздух, а не линии;
   волосяная линия осталась одна — сверху, как отбивка от рассказа. */
.cafe-story .st-aside {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: 1.75rem; margin-top: auto; padding-top: 1.75rem;
  border-top: 1px solid rgba(201, 151, 63, .3);
}
/* Общая сетка строк: значок · заголовок · подпись. Без неё третий пункт (число вместо
   значка) поднимал свою подпись на девять пикселей выше соседних — ряд читался косым. */
.cafe-story .st-item {
  display: grid; grid-template-rows: auto auto 1fr;
  justify-items: start; gap: .4rem;
}
.cafe-story .st-item svg { width: 1.375rem; height: 1.375rem; color: var(--gold); flex: none; }
.cafe-story .st-item > b { font-size: 1rem; color: var(--burgundy-ink); line-height: 1.25; }
.cafe-story .st-item small { color: var(--ink-soft); font-size: .9375rem; line-height: 1.45; }
/* Число занимает обе верхние строки — место значка и заголовка разом. Каждый пункт
   живёт в своей сетке, поэтому строки соседей не связаны: держим высоту явно, из тех же
   величин (значок 1.375rem + зазор .4rem + строка заголовка 1.25rem) и прижимаем к низу. */
.cafe-story .st-item-num .st-num {
  grid-row: 1 / 3; min-height: 3.025rem; align-items: flex-end;
}

/* Третий пункт — числом: в блоке обещаний это единственное проверяемое утверждение.
   Цифра набрана заголовочным шрифтом и ведёт на карточку в Яндекс Картах. */
.cafe-story .st-num { display: flex; align-items: baseline; gap: .5rem; text-decoration: none; }
.cafe-story .st-num-big {
  font-family: var(--font-display, 'Prata', serif);
  font-size: 2.5rem; line-height: .95; color: var(--burgundy); font-weight: 400;
  transition: color .3s ease;
}
.cafe-story .st-num-cap { font-size: .9375rem; color: var(--ink-soft); }
.cafe-story .st-num-cap b { color: var(--gold-ink, var(--burgundy-ink)); }
.cafe-story .st-num:hover .st-num-big { color: var(--gold-ink, var(--gold)); }
.cafe-story .st-num:focus-visible { outline: 2px solid var(--gold); outline-offset: 4px; border-radius: 4px; }

@media (max-width: 900px) {
  .cafe-story .st-aside { grid-template-columns: 1fr; gap: 1.25rem; }
  .cafe-story .st-num-big { font-size: 2.125rem; }
}

/* ── Мобильный проход 13.08: пол кегля и цели нажатия ─────────────────────────
   Замер на настоящей эмуляции 390 (не на изменённом размере вкладки!) показал:
   плашки «Хит»/«Фирменный» набраны 11.7 px, вторичные подписи 12.2 px — ниже пола 13 px,
   а аудитория у кафе возрастная. Кнопка «В корзину» была 33 px высотой при пороге 44. */
@media (max-width: 1024px) {
  .dish-tag { font-size: 13px; padding: 7px .8rem; }
  .strip-item small, .cafe-ph small, .dish-weight { font-size: 13px; }
  .btn-add { min-height: 44px; padding: 11px 1.125rem; }
  .qty-card button { min-width: 44px; min-height: 44px; }
  .topbar-social { width: 36px; height: 36px; }
  .form-field input, .form-field select { min-height: 44px; }
}

/* Ползунок калькулятора и ссылки в подвале — до пальцевого порога на мобиле */
@media (max-width: 1024px) {
  input[type="range"] { height: 44px; min-height: 44px; }
  /* 14.08: правило писалось на .footer-col, а разметка подвала — обычные ul/li,
     поэтому ссылки так и остались 33 px. Целимся туда, где они есть на самом деле. */
  .footer li a, .contact-item a, .footer-legal a {
    min-height: 44px; display: inline-flex; align-items: center;
  }
  /* 🩸 у правовых ссылок коробка ниже: они стоят в столбик друг под другом, и
     44 px разводили пару документов на 33 px — дальше, чем от чужой строки
     сверху. Пара переставала читаться как одно целое. Ссылка занимает всю
     ширину строки, поэтому по горизонтали цель остаётся крупной. */
  .footer-legal a { min-height: 40px; }
  .footer li { margin-bottom: 0; }
  /* 14.08: замер на 390 показал 40 px — ниже пальцевого порога, а иконки стоят вплотную */
  .topbar-social { width: 44px; height: 44px; }
  /* «Итоговая стоимость» набиралась 12,2 px — ниже пола 13 px, а это строка с ценой сета */
  .set-price small { font-size: 13px; }
  /* плашки на снимке блюда: 12 px мельче пола, а читать их будет возрастной гость */
  .menu-grid .dish-tag { font-size: 13px; }

  /* 14.08, мобильный проход. Корзина 66 px садилась на цены сетов и на текст самовывоза —
     на телефоне она висит над узкой колонкой, и любой крупный кружок закрывает строку.
     Уменьшаем и прижимаем к углу; счётчик остаётся читаемым. */
  /* 14.08, проход №2. На девяти кадрах подряд круглая корзина садилась на строку:
     то на цену сета, то на текст самовывоза, то на «100% халяль». На телефоне она висит
     над узкой колонкой — куда её ни поставь, кому-то мешает. Референсы Оператора
     (Blank Street, Crouton) решают это одинаково: не круг поверх, а НИЖНЯЯ ПАНЕЛЬ.
     Контент получает под неё отступ и больше нигде не перекрыт. */
  .cart-fab { display: none; }

  /* 14.08, Оператор: на телефоне в кадр попадал гладкий бок пирога, а отрезанный кусок
     с начинкой оставался за правым краем. Уводим снимок влево — в узкое окно входит
     правая часть кадра, та самая, где виден срез и курица. */
  .hero-media img, .hero-media video {
    /* сдвиг делаем кадрированием, а не transform: при translate по X снимок уезжает
       от края и справа открывается бордовый фон секции (поймано кадром 14.08) */
    object-position: 88% 62%;
    transform: scale(1.02);
  }

  /* Строка корзины на 390: фото, название, счётчик и сумма в один ряд не помещались —
     «Курник «Всем добра!»» ломался на три строки, а «1 650 ₽ / шт» рвалось так, что «шт»
     уходило отдельной строкой. Раскладываем в две линии: сверху фото и название,
     снизу счётчик и сумма по краям. */
  .cart-item {
    display: grid; grid-template-columns: auto 1fr; grid-template-areas: "фото имя" "счёт сумма";
    align-items: center; gap: 8px 12px; padding: 14px 0;
  }
  .cart-item img { grid-area: фото; width: 3.25rem; height: 3.25rem; }
  .cart-item-info { grid-area: имя; }
  .cart-item-info b { font-size: 15px; }
  .cart-item-info small { font-size: 13px; white-space: nowrap; }
  .cart-item .qty-card { grid-area: счёт; justify-self: start; }
  .cart-item-price { grid-area: сумма; justify-self: end; font-size: 17px; min-width: 0; }

  /* Всплывашка «в корзине» падала поверх формы заказа и в узкой полосе ломалась на строки.
     Держим её одной строкой и поднимаем над плавающей корзиной. */
  .toast { bottom: 5.5rem; font-size: 15px; padding: 12px 18px; white-space: nowrap;
           max-width: calc(100vw - 2rem); overflow: hidden; text-overflow: ellipsis; }
  .modal-overlay.open ~ .toast, .toast.hidden-by-modal { display: none; }

  /* Секции: 60 px сверху и снизу на телефоне складывались в пустые полосы между блоками —
     на 844 px высоты это четверть экрана ни на что. Сжимаем, ритм остаётся. */
  section { padding: 44px 0; }
  /* Переход по пункту меню подводил секцию под липкую шапку, и у «Доставки и самовывоза»,
     «Нашего кафе», «Готовых сетов» срезало верхушки букв. Отступ ровно на высоту шапки. */
  section[id], .strip { scroll-margin-top: 46px; }
  /* 14.08, разбор ниши: у Ассы и Любови Пироговой заголовок раздела занимает 90 px,
     у нас блок с разделителем и подзаголовком набирал 400 — целый экран между
     первым экраном и первым блюдом. Ужимаем отступы, звёздочку оставляем. */
  .sec-head { margin-bottom: 1.25rem; }
  .sec-title { font-size: clamp(1.75rem, 7.6vw, 2.25rem); line-height: 1.15; }
  .sec-sub { font-size: 15px; line-height: 1.45; max-width: 30ch; margin-left: auto; margin-right: auto; }
  .divider { margin: 0.5rem auto 0.75rem; }
}


/* ============ НИЖНЯЯ ПАНЕЛЬ (только телефон) ============ */
/* Четыре цели, до которых гость тянется чаще всего. Живёт под контентом, не над ним. */
.tabbar { display: none; }
@media (max-width: 1024px) {
  .tabbar {
    display: grid; grid-template-columns: repeat(4, 1fr);
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 96;
    background: rgba(255, 251, 244, .94);
    -webkit-backdrop-filter: saturate(1.6) blur(14px);
            backdrop-filter: saturate(1.6) blur(14px);
    border-top: 1px solid rgba(201, 151, 63, .3);
    padding-bottom: env(safe-area-inset-bottom, 0);
    box-shadow: 0 -6px 22px rgba(60, 20, 10, .07);
  }
  .tabbar a, .tabbar button {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 3px; min-height: 56px; padding: 7px 1px 8px;
    font-family: var(--font-body); font-size: 13px; font-weight: 600; letter-spacing: -.03em;
    color: var(--ink-soft); background: none; border: 0; cursor: pointer;
    position: relative; transition: color .2s;
  }
  .tabbar svg { width: 22px; height: 22px; }
  .tabbar a.is-active { color: var(--burgundy); }
  /* корзина — единственное действие в ряду, поэтому тон бренда держит её всегда */
  /* 14.08, Оператор: корзина была кругом бренда и всегда горела красным — а красным
     в этом ряду помечается раздел, который сейчас на экране. Два разных смысла одним
     цветом путали: казалось, будто мы всё время «в корзине». Делаем её как соседей. */
  .tabbar .tab-cart { color: var(--ink-soft); }
  .tabbar .tab-cart svg {
    background: none; color: inherit; border-radius: 0; box-shadow: none;
    width: 22px; height: 22px; padding: 0; margin-top: 0;
  }
  /* с товаром внутри — выделяется, но это про состояние заказа, а не про «где я» */
  .tabbar .tab-cart:has(.tab-cart-count:not([hidden])) { color: var(--burgundy); }
  .tabbar .tab-cart:active svg { transform: scale(.94); }
  .tab-cart-count {
    position: absolute; top: 4px; left: calc(50% + 8px);
    min-width: 18px; height: 18px; padding: 0 4px; border-radius: 100px;
    background: var(--gold-deep, #A9791F); color: #fff;
    font-size: 11px; font-weight: 800; line-height: 18px; text-align: center;
  }
  .tab-cart-count[hidden] { display: none; }
  /* контент не должен упираться в панель */
  /* панель меряется в 70 px — отступ должен быть не меньше, иначе последняя
     строка страницы уходит под неё */
  body { padding-bottom: calc(76px + env(safe-area-inset-bottom, 0)); }
  /* якорная прокрутка и scrollIntoView должны останавливаться НАД панелью, иначе кнопка
     "В корзину" последнего ряда оказывается под ней и нажатие уходит в панель */
  html { scroll-padding-bottom: calc(88px + env(safe-area-inset-bottom, 0)); }
  .toast { bottom: calc(70px + env(safe-area-inset-bottom, 0)); }
}

/* Первый экран на телефоне: 57.5rem от базы 16 px давали 920 px при экране 844 —
   под строкой доставки оставался тёмный провал в треть экрана. Держимвысоту по окну.
   Полоса козырей внизу получает запас, чтобы плавающая корзина не садилась на текст. */
@media (max-width: 1024px) {
  /* 14.08, Оператор: первый экран забирал слишком много. Делаем короче и подкладываем
     под него полосу козырей — тот же приём, что на десктопе, только мягче. */
  /* Ниша до товара доезжает за 600–800 px, у нас выходило 1410. Первый экран
     ужимаем: кнопка и её подпись встают в одну строку (пара читается по-прежнему —
     подпись прижата к своей кнопке), заголовок ниже. Схема Оператора и слова клиента
     сохранены полностью, меняется только плотность. */
  .hero { min-height: 56svh; margin-bottom: -3.5rem; }
  .hero-in { padding-bottom: 4.25rem; }
  .hero-text { margin-top: 0; }
  .strip { position: relative; z-index: 2; padding-top: 0.875rem; padding-bottom: 0.875rem; }
  /* верхний отступ в 2 rem остался от прежней раскладки и держал полосу выше
     самих карточек на 32 px — обнуляем вместе с нижним */
  .strip .container { padding-top: 0; padding-bottom: 0; }
}

/* Таблица зон на телефоне: три колонки в 390 px рвали слова пополам —
   «Стоимо/сть», «Беспла/тно», «рассчит/аем». Таблица становится списком:
   зона строкой, под ней цена и условие. Разметка не меняется. */
@media (max-width: 1024px) {
  .delivery-table thead { display: none; }
  .delivery-table table, .delivery-table tbody, .delivery-table tr, .delivery-table td { display: block; width: auto; }
  .delivery-table tr { padding: 1.125rem 1.375rem; }
  .delivery-table tr + tr { border-top: 1px solid rgba(201, 151, 63, .25); }
  .delivery-table td { padding: 0; border: none; }
  .delivery-table td:first-child b { font-size: 1.0625rem; color: var(--burgundy-ink); }
  .delivery-table td:nth-child(2),
  .delivery-table td:nth-child(3) { display: inline-block; margin-top: .35rem; white-space: nowrap; }
  .delivery-table td:nth-child(3) { margin-left: .75rem; }
  .delivery-table td:nth-child(3)::before { content: "·"; margin-right: .75rem; color: var(--ink-soft); }

  /* Строка адрес/часы/халяль: при переносе элементы центрировались построчно
     и вставали лесенкой. На телефоне — столбиком по левому краю. */
  .cafe-facts { flex-direction: column; align-items: flex-start; gap: .75rem; }

  /* Плитка «фото зала скоро» держала 300 px — треть экрана под обещание.
     На телефоне ей хватает полосы: место застолблено, рассказ начинается сразу. */
  .ph-dark { aspect-ratio: auto; height: 190px; min-height: 0; padding: 1.5rem; }
  .ph-dark .ph-cam { width: 2.25rem; height: 2.25rem; }
  .ph-dark b { font-size: 1.25rem; }
  .ph-dark small { font-size: 0.875rem; }
}

/* ============ ТЕЛЕФОН: АНИМАЦИИ ОСТАВЛЕНЫ ============ */
/* 14.08. Сначала эффекты сняли, потом опыт на честной тач-эмуляции показал: при
   прокрутке снимок не шевелится, при касании отъезд играет и на касание в стороне
   возвращается — залипания нет. Решение Оператора: оставить. Здесь только то, что
   отличает телефон от десктопа: снимок в покое стоит КРУПНЕЕ (гость держит экран
   близко), а сам отъезд работает как везде. */
@media (max-width: 1024px) {
  .dish-img img.dish-photo.dish-zoomout,
  .dish-img img.dish-photo.dish-zoomout.is-loaded {
    transform: scale(calc(var(--zs, 1.25) * 1.18));
  }
  .dish-img img.dish-photo:not(.dish-zoomout) { transform: scale(1.2); }
  .dish:hover .dish-img img.dish-photo:not(.dish-zoomout) { transform: scale(1.24); }
}


/* ============ ПОЛ КЕГЛЯ ============ */
/* 13 px — нижняя граница для этой аудитории. На узких экранах пол держали давно,
   а на широких оставались плашки 11,7 и подписи 12,2: тот же текст, те же глаза. */
/* ⚠️ в rem писать нельзя: база кегля на этом сайте 15 px, и 0.8125rem дало 12,19 —
   снова ниже пола. Пол задаётся в пикселях, он абсолютный по смыслу. */
.dish-tag { font-size: 13px; }
.set-price small, .cafe-ph small, .strip-item small { font-size: 13px; }
.footer-bottom, .footer-bottom span { font-size: 13px; }
.review-card small, .contact-item small, .st-num-cap { font-size: 13px; }

/* ============ ВОЗДУХ ВОКРУГ ПИЛЮЛИ НОМЕРА ============ */
/* Узел шапки несёт ДВА класса — container и header-in. Правило .header .container
   с полями «0 1rem» стоит ниже по файлу и при равной специфичности побеждало:
   вертикальные поля обнулялись, пилюля упиралась в края плашки. Ставим в самом
   конце — после него перебивать нечему. */
@media (max-width: 1024px) {
  .header .container.header-in { padding-top: 7px; padding-bottom: 7px; }
}

/* пилюля всегда прижата к правому краю плашки и всегда с зазором от него:
   на 320 она упиралась в край, на 600 висела в 233 px от него — .header-cta
   не тянулся вправо, а поля контейнера на узком сжимались почти до нуля */
@media (max-width: 1024px) {
  .header .container.header-in { padding-left: 12px; padding-right: 12px; }
  .header-in .header-cta { margin-left: auto; }
}

/* 320 px: имя (189) и пилюля (118) вместе с полями требуют 337 при экране 320 —
   пилюля вылезала на 5 px за край. Ужимаем обе стороны ровно настолько, чтобы
   зазор появился. Кегль имени тут 12 px — осознанный компромисс на самых узких
   экранах: иначе имя пекарни пришлось бы резать. */
@media (max-width: 370px) {
  .header .brand-name { font-size: 12px; }
  .header .brand img { width: 30px; height: 30px; }
  .header .header-phone { font-size: 11px; padding: 0 0.4375rem; }
  .header .container.header-in { padding-left: 10px; padding-right: 10px; }
}

/* ============ ТЕЛЕФОН: ПЛАШКИ И КНОПКА КАРТОЧКИ ============ */
/* 14.08, Оператор. Плашки «Хит», «Фирменный», «Подарок от 5000 ₽» лежали поверх
   снимка и закрывали его: у яблочной шарлотки замер показал 91% ширины карточки —
   фото не видно вовсе. На узкой карточке им просто негде поместиться, поэтому на
   телефоне снимаем: «Хит» и «Фирменный» — украшение, а подарок за 5 000 ₽ подробно
   расписан в «Акциях» и в блоке сетов. */
@media (max-width: 1024px) {
  .menu-grid .dish-tag { display: none; }

  /* Кнопка «В корзину» занимала столько же места, сколько название блюда.
     Читают название, нажимают кнопку — вес должен быть у первого. */
  .menu-grid .btn-add {
    min-height: 40px; padding: 8px 10px; font-size: 14px; border-radius: 0.75rem;
  }
  .menu-grid .qty-card button { min-width: 40px; min-height: 40px; }
}

/* ============ ШАПКА РАСТЁТ ВМЕСТЕ С ЭКРАНОМ ============ */
/* 14.08, Оператор: «для надписи появилось больше места — надо им пользоваться».
   Кегли в шапке были заданы ступеньками (12 / 13 / 15 px по брейкпоинтам) и на
   430 выглядели так же, как на 360: свободное место просто пустовало. Переводим
   на плавный расчёт от ширины окна — от 12 px на 320 до 20 px к 600 и шире.
   Формулы подобраны так, чтобы на каждой ширине имя, логотип и пилюля вместе
   умещались в строку с запасом (проверено замером на 320…720). */
@media (max-width: 1024px) {
  .header .brand-name { font-size: clamp(12px, 4.2vw - 1.5px, 20px); }
  .header .brand-sub  { font-size: clamp(13px, 3.2vw - 1px, 16px); }
  .header .brand img  { width: clamp(30px, 9.2vw, 50px); height: clamp(30px, 9.2vw, 50px); }
  .header .header-phone { font-size: clamp(11px, 1.2vw + 7.5px, 15px);
                          min-height: clamp(28px, 7vw, 38px); }
}

/* ============ ПЛАНШЕТ 721–1024 ============ */
/* Логика мобильная — нижняя панель, пилюля с номером, вкладки в два ряда.
   Но места вдвое больше, поэтому сетки шире, а кегли крупнее: иначе карточки
   растягиваются на пол-экрана и страница выглядит увеличенным телефоном. */
@media (min-width: 721px) and (max-width: 1024px) {
  .menu-grid { grid-template-columns: repeat(3, 1fr); gap: 1.125rem; }
  .menu-grid .dish h3 { font-size: 1.0625rem; }
  .menu-grid .dish-desc { font-size: 14px; -webkit-line-clamp: 3; }
  .menu-grid .dish-price { font-size: 1.5rem; }
  .menu-grid .btn-add { min-height: 44px; font-size: 15px; }
  .sets-grid { grid-template-columns: 1fr 1fr; gap: 1.25rem; }
  .strip .container { grid-template-columns: repeat(4, 1fr); }
  .strip-item b { font-size: 15px; }
  .strip-item small { font-size: 13px; }
  .footer-in { grid-template-columns: 1fr 1fr 1fr; }
  .footer-in > :first-child { grid-column: auto; text-align: left; }
  .footer-in > :first-child .brand { justify-content: flex-start; }
  .footer-in > :first-child p { margin-left: 0; }
  .promo-grid, .reviews-grid, .cafe-photos, .about-feats { grid-template-columns: 1fr 1fr; }
  .form-grid { grid-template-columns: 1fr 1fr; }
  /* панель на планшете шире — подписи и значки крупнее */
  .tabbar a, .tabbar button { font-size: 14px; min-height: 62px; }
  .tabbar svg { width: 25px; height: 25px; }
  .tabbar .tab-cart svg { width: 38px; height: 38px; padding: 8px; }
  body { padding-bottom: calc(84px + env(safe-area-inset-bottom, 0)); }
  /* первый экран на планшете выше: кадр крупный, тексту есть где встать */
  .hero { min-height: 62svh; }
  .hero-title { font-size: clamp(3rem, 7.4vw, 4.25rem); }
  .hero-cta .btn-lg { flex: 0 0 30%; font-size: 20px; }
  .hero-cta-note { font-size: 19px; }
  .menu-tabs { grid-template-columns: repeat(4, 1fr); }
  .tab { font-size: 15px; }
  .sec-title { font-size: clamp(2rem, 4.6vw, 2.75rem); }
}

/* ============ ПЛАНШЕТ: СОБИРАЕМ, А НЕ РАСТЯГИВАЕМ ============ */
/* 14.08, Оператор: на планшете имя жалось к левому краю, пилюля к правому, между
   ними зияла пустая полоса; в нижней панели то же — шесть колонок по 1/6 ширины
   разносили значки по всему экрану. Ширина выросла, а содержимое не должно
   растекаться: собираем обе полосы к центру и держим разумный шаг между пунктами. */
@media (min-width: 721px) and (max-width: 1024px) {
  .header .container.header-in {
    justify-content: center; align-items: center;
    gap: clamp(40px, 8vw, 90px);
  }
  /* логотип, имя и пилюля стоят по одной средней линии: подпись «Халяль» тянула
     блок имени вниз, и пилюля казалась приподнятой */
  .header .brand { align-items: center; }
  .header .brand > span { justify-content: center; }
  .header .header-phone { align-self: center; }
  .header-in .header-cta { margin-left: 0; }

  .tabbar {
    grid-template-columns: repeat(4, auto);
    justify-content: center; column-gap: clamp(18px, 4.5vw, 54px);
  }
  .tabbar a, .tabbar button { padding-left: 6px; padding-right: 6px; }

  /* подвал: первая колонка с рассказом шире соседних, и «МЕНЮ» наезжало на текст */
  .footer-in { grid-template-columns: 1.35fr 0.85fr 1fr; gap: 20px 34px; }
  .footer-in > :first-child p { max-width: 32ch; }
}

/* ============ ДЕСКТОПНАЯ ШАПКА: СОБИРАЕМ ГРУППУ ============ */
/* 14.08, Оператор: «между пирогами, номером и менюшкой слишком много пространства».
   У .nav стоял margin: 0 auto — он раздвигал бренд и кнопку по краям, и на 1280
   между ними зияло по 152 px. Собираем три блока в группу по центру с ровным
   шагом; на очень широких мониторах шаг растёт, но в разумных пределах. */
@media (min-width: 1025px) {
  .header .container.header-in {
    justify-content: center; align-items: center;
    gap: clamp(28px, 3.4vw, 64px);
  }
  .nav { margin: 0; }
}

/* ============ ШОВ 1025–1100 ============ */
/* Дыра, найденная замером 14.08: мобильная логика кончается на 1024, а навигация
   в шапке включалась только с 1101. На 1025–1100 не было ни нижней панели, ни меню —
   один бургер посреди десктопной вёрстки. Закрываем шов: сразу после планшета
   в шапке появляется полное меню, бургер уходит. Кегль там мельче — иначе шесть
   пунктов вместе с логотипом и кнопкой в 1025 не помещаются. */
@media (min-width: 1025px) {
  .nav { display: flex; }
  .burger { display: none; }
}
@media (min-width: 1025px) and (max-width: 1240px) {
  .nav a { font-size: 0.9375rem; padding: 0.5rem 0.4375rem; }
  .brand-name { font-size: 1.0625rem; }
  .brand img { width: 3rem; height: 3rem; }
  .btn-phone { padding: 0.75rem 1.125rem; font-size: 0.9375rem; }
  .header .container.header-in { gap: clamp(18px, 2.2vw, 34px); }
}

/* ============ ПЕРВЫЙ ЭКРАН НА ДЕСКТОПЕ ============ */
/* 14.08, Оператор: «на большом мониторе не полностью вся картинка с пирогом».
   Кадр 1536×1024 — пропорция 1,50, а окно первого экрана на десктопе от 1,48 (1280)
   до 2,12 (2560). Приближение ×1,18 добавлялось поверх обрезки cover, и пирог
   уезжал за правый и нижний край — сильнее всего как раз на 1280–1440.
   Убираем приближение совсем и кладём кадр по нижней кромке: пирог стоит на самом
   низу исходника, поэтому именно так он входит целиком на любой ширине. */
@media (min-width: 1025px) {
  .hero-media img, .hero-media video {
    transform: none;
    object-position: center 100%;
  }
}
/* НОУТБУКИ: экран ниже, чем сам первый экран (57.5rem), поэтому низ кадра уходил под сгиб —
   «съела пирог вниз» (Оператор, 17.08). Высоту hero не трогаем: на большом мониторе Оператор
   её одобрил, а ужимание до окна он забраковал («ужасно выглядит») — вместе с ним снизу
   вылезала красная лента, которой на ноутбуке быть не должно.
   Лечим только КАДР: приближаем и поднимаем. Степень выбрана Оператором из трёх проб
   (z1 1.08/6% · z2 1.12/9% · z3 1.16/12%) — принят z2, кадры в
   artifacts/bugs_2026-08-17/hero_zoom/. Условие по ВЫСОТЕ окна: цепляет ноутбучные
   720–900, монитор 1080/1440 не трогает. */
@media (min-width: 1025px) and (max-height: 900px) {
  .hero-media img, .hero-media video {
    /* 17.08, второй круг Оператора: «фото чуть левее, блок текста чуть выше» */
    transform: translate(-3%, -9%) scale(1.12);
    transform-origin: center bottom;
  }
  .hero-text { margin-top: -10.5rem; } /* было -8rem общим правилом */
}

/* ============ ШАПКА НЕ ЛИПНЕТ НА ТЕЛЕФОНЕ И ПЛАНШЕТЕ ============ */
/* 14.08, Оператор: «шапка липнет — не должна, верхняя плашка не должна двигаться
   по всему сайту». Она стоит в самом верху страницы и уезжает вместе с контентом.
   Переход при этом не теряется: на узких экранах его держит нижняя панель, а лента
   категорий продолжает липнуть в своей секции — теперь к самому верху окна,
   потому что шапки над ней больше нет. */
@media (max-width: 1024px) {
  .header { position: static; }
  .menu-tabs { top: 0; }
  section[id], .strip { scroll-margin-top: 0; }
}

/* ============ КНОПКА ЗАКАЗА И СТЕППЕР ============ */
/* 14.08, Оператор: «кнопки в корзину и +/− больше, чем надо; когда нажимаешь,
   степпер съезжает влево, а надо по середине — и в сетах тот же баг».
   Причина съезда: на узком кнопка и степпер растягиваются на всю ширину карточки,
   но у степпера внутри не было выравнивания — минус, число и плюс липли к левому
   краю. Правило общее для меню и сетов, на всех ширинах. */
.add-slot { display: inline-flex; justify-content: center; }
.qty-card { justify-content: center; }

/* мельче по всей комплекции: кнопка ниже, степпер компактнее, цифра теснее */
.btn-add { padding: 0.42em 0.8em; font-size: 0.9rem; }
.qty-card button { width: 2.1rem; height: 2.1rem; font-size: 1rem; }
.qty-card span { min-width: 1.375rem; font-size: 0.9375rem; }

@media (max-width: 1024px) {
  .menu-grid .btn-add, .set-foot .btn-add { min-height: 38px; padding: 8px 10px; font-size: 14px; }
  .menu-grid .qty-card button, .set-foot .qty-card button { min-width: 36px; min-height: 36px; }
  .add-slot, .qty-card { width: 100%; }
}

/* ============ ЗАГОЛОВОК ГРУППЫ СЕТОВ ============ */
/* 14.08, Оператор: «надпись про сеты выровнять по центру, а то уехали куда-то».
   На широком экране «Сеты от 5 000 ₽» и строка подарка стоят по краям одной линии
   (space-between) — там это читается парой. На узком они падают друг под друга,
   и разнобой становится виден: заголовок с центром 135 против центра колонки 195.
   Собираем столбиком по центру. */
@media (max-width: 1024px) {
  .set-group-head { flex-direction: column; align-items: center; text-align: center; gap: 0.625rem; }
  .set-group-head h3 { text-align: center; }
  /* значок подарка растягивался во всю ширину строки и оставался у левого края,
     пока текст шёл по центру — держим их одним блоком */
  .set-group-gift { display: inline-flex; align-items: flex-start; justify-content: center;
                    text-align: left; gap: 0.5rem; max-width: 30ch; margin: 0 auto; }
}

/* ============ СТРОКА ЗАКАЗА И ПОЛЯ ФОРМЫ ============ */
/* 14.08, Оператор: «фотографии ближе к минусу, а не посередине — хочу их чуть
   больше и по центру, над количеством». Снимок стоит в той же колонке, что и
   степпер, но выравнивания не было — он липнул к левому краю ячейки. */
@media (max-width: 1024px) {
  .cart-item img {
    width: 4.25rem; height: 4.25rem; justify-self: center; align-self: center;
    border-radius: 0.875rem; object-fit: cover;
  }
  .cart-item .qty-card, .cart-item .qty { justify-self: center; }
}

/* Поля даты и времени выглядели системными: разная высота, чужой шрифт, серая
   стрелка календаря. Приводим к остальной форме — тот же кегль, поля и рамка,
   значок календаря в цвете бренда. */
.form-field input[type="date"],
.form-field input[type="time"],
.form-field select {
  font-family: inherit; font-size: 1rem; line-height: 1.2;
  appearance: none; -webkit-appearance: none;
  background-color: var(--white);
}
.form-field input[type="date"]::-webkit-calendar-picker-indicator {
  filter: invert(14%) sepia(84%) saturate(3200%) hue-rotate(352deg) brightness(88%) contrast(96%);
  cursor: pointer; opacity: .85; padding: 2px; margin-right: -2px;
}
.form-field input[type="date"]::-webkit-calendar-picker-indicator:hover { opacity: 1; }
/* у select своя стрелка вместо системной */
.form-field select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='9' viewBox='0 0 14 9'%3E%3Cpath d='M1 1l6 6 6-6' fill='none' stroke='%23880808' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 0.9rem center;
  padding-right: 2.4rem;
}


/* ═══════════════════════════════════════════════════════════════════════
   НАШЕ КАФЕ — разворот про зал. Пять кадров клиента (00_ТЗ/foto_zala_19-08).

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

   Формы взяты у самого кафе, не придуманы: арка — с резного потолка,
   фестон — край скатерти, girih — решётка с его же панелей.
   Подписей нет, по кадрам не кликают. Движение — в app.js (GSAP).
   ═══════════════════════════════════════════════════════════════════════ */

/* Шапка секции — общая .sec-head сайта, своих правил не заводим.
   Мера строки у подписи ограничена там же (70ch), центрирование оттуда же. */

/* ── Панорама: во всю ширину экрана, с фестонами по краям ────────────── */
.cafe-pano {
  position: relative; margin: 0 0 3rem;
  width: 100vw; margin-left: calc(50% - 50vw);   /* выход за колонку */
  --scallop-color: var(--bg);                     /* фестон выгрызает фон, не рисует его */
}
.cafe-pano-frame {
  position: relative; overflow: clip;
  aspect-ratio: 1600 / 470;
  background: var(--girih-dark), var(--burgundy-deep);
}
/* Кадр крупнее рамки: 118% по высоте — запас хода прокрутки, scale(1.1) —
   запас на смещение за курсором. Без него у края оголялась бы рамка. */
.cafe-pano-img {
  position: absolute; inset: 0; width: 100%; height: 118%;
  object-fit: cover; object-position: center 52%;   /* гости выше в кадре: снизу оригинал
     кончился, но внутри рамки оставалось ~8% запаса под ход параллакса — отдали их людям */
  transform: translateY(-7.6%) scale(1.1); will-change: transform;
}
/* Зубчатый край — тот же приём, что на стыках бордовых секций */
.cafe-pano::before, .cafe-pano::after {
  content: ""; position: absolute; left: 0; right: 0; height: 1.375rem; z-index: 2;
  background-image: radial-gradient(circle at 50% 0, var(--scallop-color) 11px, transparent 11.8px);
  background-size: 22px 22px; background-repeat: repeat-x;
}
.cafe-pano::before { top: -.0625rem; }
.cafe-pano::after  { bottom: -.0625rem; transform: scaleY(-1); }

/* ── Ряд «вход + рассказ»: арка слева, текст и козыри справа ─────────── */
.cafe-story-row {
  display: grid; grid-template-columns: .82fr 1.15fr .8fr; gap: 3rem 2.75rem;
  align-items: start;
}
/* Арка-михраб: форма с резного потолка кафе. Идёт вертикальному кадру. */
.cafe-arch { margin: 0; }
/* Радиус в процентах от СВОЕЙ высоты (--arch = 46%) на узком вертикальном кадре
   даёт не арку, а каплю: 46% от 1144 px — это полтора кадра. Здесь купол задан
   эллиптически — половина ширины по горизонтали, треть высоты по вертикали,
   и форма держится при любой колонке. height: auto нужен, чтобы пропорция
   считалась от ширины, а не бралась из атрибута height. */
.cafe-arch img {
  display: block; width: 100%; height: auto; aspect-ratio: 3 / 4;
  object-fit: cover; object-position: center 36%;
  border-radius: 50% 50% var(--radius) var(--radius) / 32% 32% var(--radius) var(--radius);
  box-shadow: var(--shadow-card);
}
.cafe-story-row .cafe-story { display: contents; }
.cafe-story-row .cafe-story > div:first-child { grid-column: 2; }
.cafe-story-row .st-aside {
  grid-column: 3; display: grid; grid-template-columns: 1fr; gap: 0;
  margin: 0; padding: 0; border: 0;
}
/* Козыри разделены волосяной линией — карточка тут лишняя: рядом стоит фото,
   и вторая поднятая плоскость спорит с ним за внимание. */
.cafe-story-row .st-item { padding: 1.125rem 0; border-bottom: 1px solid var(--gold-pale); }
.cafe-story-row .st-item:first-child { padding-top: 0; }
.cafe-story-row .st-item:last-child { border-bottom: 0; }
.cafe-story-row .st-item > svg {
  width: 1.75rem; height: 1.75rem; padding: .375rem; border-radius: 50%;
  background: var(--gold-pale); color: var(--burgundy); box-sizing: border-box;
}
/* Росчерк под заголовком — тот же, что у заголовков секций */
/* Над заголовком воздуха больше, чем под ним: иначе он визуально притягивается
   к своему же тексту снизу и отрывается от того, что стоит выше. */
.cafe-story-row .cafe-story-title { position: relative; margin-top: .5rem; padding-bottom: .875rem; margin-bottom: 1.125rem; }
.cafe-story-row .cafe-story-title::after {
  content: ""; position: absolute; left: 0; bottom: 0; width: 3.5rem; height: 2px;
  border-radius: 2px; background: linear-gradient(90deg, var(--gold) 0%, rgba(201,151,63,0) 100%);
}
.cafe-story-row .cafe-story-lead { font-size: 1.125rem; line-height: 1.55; }

/* ── Нижние кадры внахлёст ───────────────────────────────────────────── */
.cafe-spread {
  display: grid; grid-template-columns: 1fr .72fr; gap: 1.5rem 2rem;
  margin-top: 3.5rem; align-items: start;
}
.sp { margin: 0; }
.sp img {
  display: block; width: 100%; height: 100%; object-fit: cover;
  border-radius: var(--radius); box-shadow: var(--shadow-card);
}
.sp-stol { grid-column: 1; grid-row: 1; }
.sp-stol img { aspect-ratio: 3 / 2; }
.sp-kids { grid-column: 1; grid-row: 2; }
.sp-kids img { aspect-ratio: 1200 / 760; }
/* Колонна поднимается над линией стола и уходит ниже детской — она и рвёт ряд.
   Отрицательный отступ сверху безопасен: соседняя ячейка выше её на этот же шаг. */
/* Колонна тянется до низа кладки: при align-items:start она обрывалась выше
   детской и справа зияла дыра в полтораста пикселей. Своя пропорция снимается —
   высоту задаёт соседний столбец, ширину кадр добирает обрезкой по бокам.
   Колонка шире прежней (.52 -> .72fr): кадр зала не такой вытянутый, как был
   снимок пары, и в узком столбце от него остался бы огрызок. */
/* Нахлёст снят 20.08 по глазу Оператора: колонна начиналась выше соседа и ряд
   читался съехавшим. Верх выровнен, ступень держит сама разница высот кадров. */
.sp-zal { grid-column: 2; grid-row: 1 / span 2; align-self: stretch; }
.sp-zal img { height: 100%; aspect-ratio: auto; object-position: center 52%; }

/* ── Планшет и телефон ───────────────────────────────────────────────── */
@media (max-width: 64rem) {
  .cafe-pano { margin-bottom: 2rem; }
  .cafe-pano-frame { aspect-ratio: 16 / 10; }
  .cafe-pano-img { height: 112%; transform: translateY(-5.4%) scale(1.08); }
  .cafe-story-row { grid-template-columns: 1fr; gap: 1.75rem; }
  .cafe-arch { max-width: 20rem; }
  .cafe-story-row .cafe-story > div:first-child,
  .cafe-story-row .st-aside { grid-column: 1; }
  .cafe-story-row .st-aside { padding-top: 1.25rem; border-top: 1px solid var(--gold-pale); }
  .cafe-story-row .cafe-story-lead { font-size: 1.0625rem; }
  /* Нахлёст снимается: на одной колонке он превращается в кривой отступ */
  .cafe-spread { grid-template-columns: 1fr 1fr; gap: .875rem; margin-top: 2rem; }
  .sp-stol   { grid-column: 1 / -1; grid-row: 1; }
  .sp-kids   { grid-column: 1; grid-row: 2; }
  /* Нижняя пара идёт вровень: у детской своя пропорция 1.18, у зала 0.53 —
     рядом они давали разную высоту и дыру слева. Обоим одна рамка 3:4,
     остальное добирает cover. */
  .sp-zal { grid-column: 2; grid-row: 2; margin-top: 0; }
  .sp-kids img, .sp-zal img { aspect-ratio: 3 / 4; height: auto; }
  .sp-kids img { object-position: center 42%; }
}

/* ── Тихий режим ─────────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .cafe-pano-img { height: 100%; transform: none; }
}

/* ── Фото не утаскиваются мышью (просьба Оператора 20.08) ────────────────
   Полностью запретить сохранение в вебе нельзя — кадр всегда лежит в кеше.
   Здесь закрыты две простые двери: перетаскивание картинки на рабочий стол
   и выделение её как объекта. Третья дверь — правый клик — в app.js.
   Имена файлов скрыты отдельно: физические хэши, карта в images/_names_map.json. */
img {
  -webkit-user-drag: none;
  user-select: none;
  -webkit-user-select: none;
}
