/* Jetron constructor — дизайн-система стенда v2
   Radical redesign: тёмная сцена-витрина + нумерованные шаги + CTA-блок цены.
   Токены в :root. Имена классов/id совпадают с JS — не переименовывать. */

/* Спортивный акцентный шрифт для заголовков и цены (с кириллицей). */
@font-face {
  font-family: "Oswald";
  src: url("../../assets/fonts/Oswald.ttf") format("truetype");
  font-weight: 400 700;
  font-display: swap;
}
/* Основной шрифт интерфейса — Manrope (полная кириллица, вариативный). */
@font-face {
  font-family: "Manrope";
  src: url("../../assets/fonts/Manrope.ttf") format("truetype");
  font-weight: 300 800;
  font-display: swap;
}

:root {
  /* Шрифты */
  --font-display: "Oswald", "Manrope", -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
  --font-body: "Manrope", -apple-system, "Segoe UI", Roboto, Arial, sans-serif;

  /* Синий акцент — кнопка «+» загрузки, фокус полей, ссылки */
  --brand: #2f6fe0;
  --brand-strong: #1f56c4;
  --brand-soft: #eaf1ff;
  --brand-ring: rgba(47, 111, 224, .24);

  /* Тёмно-синий — главные кнопки (Оформить заказ, Перейти в каталог) */
  --navy: #14294c;
  --navy-strong: #0c1c39;

  /* Светлая тёплая сцена (макет-панель) */
  --stage-bg: #fdf9ef;
  --stage-card: #ffffff;
  --stage-border: #ece3d0;
  --stage-text: #8b8578;
  --stage-label: #1b1b1b;

  /* Нейтральные (тёплая кремовая гамма клиента) */
  --ink: #1b1b1b;
  --ink-2: #3a3a3a;
  --muted: #8b8578;
  --line: #ece5d6;
  --line-strong: #dad0bd;
  --surface: #ffffff;
  --surface-2: #f6f1e6;
  --bg: #fbf1db;

  /* Семантика */
  --success: #45b155;
  --success-soft: #e7f6ea;

  /* Тени (тёплые, мягкие) */
  --sh-sm: 0 1px 3px rgba(90, 70, 30, .07);
  --sh-md: 0 6px 22px rgba(90, 70, 30, .10);
  --sh-lg: 0 20px 60px rgba(60, 45, 15, .20);
  --sh-brand: 0 4px 18px rgba(20, 41, 76, .28);
  --sh-stage: 0 14px 44px rgba(90, 70, 30, .12);

  /* Радиусы */
  --r-xl: 24px;
  --r-lg: 16px;
  --r-md: 12px;
  --r-sm: 8px;

  --ease: cubic-bezier(.4, 0, .2, 1);
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.55;
  letter-spacing: -.006em;
  color: var(--ink);
  background: var(--bg);
  min-height: 100vh;
  /* Замер 31.08 (1366×768): последние 28 px вертикальной прокрутки давал не контент, а схлопывание
     полей. У `#app` `margin: 28px auto`; body без границ и padding не образует BFC, верхнее поле
     ребёнка ВЫХОДИТ наружу и сдвигает саму коробку body на 28 px вниз, а её высота при этом
     остаётся `min-height: 100vh` = 768. Итог: низ body 796 при экране 768, полоса прокрутки
     на пустом месте. `flow-root` запирает поле внутри: body снова начинается с нуля, высота
     содержимого 28 + 711 + 28 = 767, влезает. Внешне НИЧЕГО не меняется — отступ сверху
     по-прежнему 28 px, просто теперь его держит body, а не смещение body.
     ⚠️ Дефект был всегда, его просто не было видно за 250 px перелива до правок 31.08. */
  display: flow-root;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  font-feature-settings: "ss01", "cv01";
}

/* ── Шапка (тёмная, спортивная) ─────────────────────────── */
.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 10px 18px;
  padding: 15px 28px;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  box-shadow: 0 1px 0 rgba(90, 70, 30, .03), 0 6px 22px rgba(90, 70, 30, .05);
  position: sticky;
  top: 0;
  z-index: 40;
}
.brand { display: flex; align-items: center; gap: 13px; }
.brand-mark {
  width: 38px; height: 38px;
  display: grid; place-items: center;
  border-radius: 11px;
  background: linear-gradient(145deg, #1f56c4 0%, var(--navy) 100%);
  color: #fff; font-family: var(--font-display); font-weight: 700; font-size: 23px;
  box-shadow: var(--sh-brand), inset 0 1px 0 rgba(255, 255, 255, .30);
  position: relative;
}
/* Диагональный «скоростной» блик на бренд-марке */
.brand-mark::after {
  content: ''; position: absolute; inset: 0; border-radius: inherit;
  background: linear-gradient(115deg, transparent 55%, rgba(255, 255, 255, .22) 58%, transparent 62%);
  pointer-events: none;
}
.topbar .logo {
  font-family: var(--font-display);
  font-weight: 700; letter-spacing: 4.5px; font-size: 24px;
  text-transform: uppercase;
  color: var(--ink);
}
.topbar .tag {
  color: var(--muted); font-size: 12px; font-weight: 600;
  letter-spacing: .04em;
  background: var(--surface-2); border: 1px solid var(--line);
  padding: 5px 15px; border-radius: 999px;
}

/* ── Раскладка ───────────────────────────────────────────── */
#app {
  display: grid;
  grid-template-columns: 1fr 372px;
  gap: 24px;
  max-width: 1200px;
  margin: 28px auto;
  padding: 0 24px;
  align-items: start;
}

/* ── Тёмная сцена-витрина ────────────────────────────────── */
/* Клиент 31.08 (11:20): «палитру цветов влево», настройки остаются справа, эскизы моделей —
   прямо под картинкой. Сквозной критерий у него же: на ноутбуке 1366×768 конструктор должен
   помещаться без вертикальной прокрутки. Поэтому flex-колонка заменена на grid: палитра
   встаёт СБОКУ от макета и перестаёт съедать высоту. Мобильная раскладка — ниже,
   в существующем брейкпоинте 900px (нового не заводим). */
#stage {
  display: grid;
  grid-template-areas: "pal views" "models models";
  grid-template-columns: auto 1fr;
  align-items: start;
  justify-items: center;
  column-gap: 18px;
  background: var(--stage-bg);
  border: 1px solid var(--stage-border);
  border-radius: var(--r-xl);
  padding: 40px 32px 28px;
  position: relative;
  overflow: hidden;
  box-shadow: var(--sh-stage), inset 0 1px 0 #fff;
}

/* ── Холсты ─────────────────────────────────────────────── */
.views {
  display: flex; gap: 20px;
  justify-content: center; flex-wrap: wrap;
  position: relative; z-index: 1;
}
.canvas-col { display: flex; flex-direction: column; align-items: center; gap: 10px; }
.canvas-label {
  font-family: var(--font-display);
  font-weight: 600; font-size: 13px; color: var(--stage-label);
  text-transform: uppercase; letter-spacing: .16em;
}
/* ⚫ Правила крестика выхода (44 px в углу окна, с 17.07.2026) удалены 02.09.2026 вместе
   с самим узлом — клиент попросил кнопку убрать. Замер 02.09 объясняет и его вторую жалобу,
   «кнопки вообще вышли за рамки»: крестик стоял на 8 px ПРАВЕЕ правого края ряда пилюль
   (r=316 против r=308 на 320 px) и на бежевом фоне ВНЕ белой карточки — именно он и торчал.
   Возврат стережёт `tests/ExitButton.test.js`. */

/* Плашка линейки (клиент 2026-07-23): компактная кнопка по размеру текста, а не широкая полоса.
   Внешний .line-badge — прозрачная строка на всю ширину (flex-basis:100% держит перенос: холсты
   уходят под плашку); pointer-events:none, чтобы кликабелен был только сам pill, а не вся строка. */
.line-badge {
  /* Клиент 2026-07-24: плашку — внутрь поля, в левый-верхний угол поверх картинки (не отдельной
     строкой сверху). Абсолют в .views (position:relative) освобождает строку → холсты поднимаются
     выше, контролы цвета/формы ближе к экрану. pointer-events:none на обёртке — кликабельны
     только сами pill'ы.
     Клиент 2026-08-28: кнопка перехода — «справа наверху». Поэтому строка растянута на всю
     ширину (right:0), ярлык линейки остаётся слева, кнопка уходит к правому краю.
     Клиент 2026-08-31: между ними встала третья пилюля «Скачать макет». Раскладка переведена
     со space-between на grid `1fr auto 1fr` — только так середина стоит по центру КАРТИНКИ,
     а не посередине остатка между боковыми пилюлями разной ширины.
     ⚠️ Здесь был лишний закрывающий маркер комментария после абзаца 2026-08-28 (писать его
     внутри комментария НЕЛЬЗЯ — вложенных комментариев в CSS нет): комментарий обрывался,
     три строки ниже становились мусором внутри блока, и разбор CSS съедал их вместе с первым
     объявлением до `;` — то есть с `position: absolute`. Плашка вставала static, оставалась
     в потоке и растягивала `.views` до 640 px: на 375 px «Скачать макет» и «перейти в карточку»
     уезжали за экран и обрезались `#stage { overflow: hidden }`. Замер 31.08. */
  position: absolute; top: 0; left: 0; right: 0; z-index: 3;
  display: grid; grid-template-columns: 1fr auto 1fr;
  justify-items: center; align-items: start; gap: 8px;
  margin: 0; padding: 0;
  background: none; border: none;
  pointer-events: none;
}
/* Боковые пилюли прижаты к своим краям, средняя стоит по центру колонки. */
.line-badge-name { justify-self: start; }
.line-badge-cta { justify-self: end; }
/* Клиент 2026-08-31 (11:11): «все эти кнопочки уменьшить, они немножко крупные, буквально
   процентов на 20». Отсюда padding 6/14 → 5/11 и кегль 13 → 10.5 px. */
.line-badge-pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 11px;
  background: var(--stage-card); color: #111;
  border: 1px solid var(--stage-border);
  border-radius: 10px;
  font-weight: 700; font-size: 10.5px; letter-spacing: .06em; text-transform: uppercase;
  /* Пилюля живёт в ОДНУ строку и переносом текста ширину себе не добирает. Без этого
     на 360 px в десктопном браузере (узкое окно, `pointer: fine`) «в карточку →» просила
     109 px, а колонка `1fr` давала 103.1 — и кнопка срывалась на вторую строку: ряд рос
     28.3 → 40 px и садился прямо на ворот формы, зазор до чернил падал до нуля (замер 02.09).
     Перелива `nowrap` не создаёт: сумма трёх пилюль без переносов + зазоры 12 px на самой
     узкой ширине укладывается в ряд с запасом — проверено замером на 320/360, не на глаз.
     ⚠️ Считать надо сумму ТРЁХ пилюль, а не одну: в сетке `1fr auto 1fr` правая колонка
     не может стать уже своего min-content, и лишнее забирает короткий ярлык линейки. */
  white-space: nowrap;
  box-shadow: 0 2px 8px rgba(0, 0, 0, .08);
  transition: border-color .2s var(--ease), transform .2s var(--ease), box-shadow .2s var(--ease);
}
/* Ярлык «что показано» — не действие: не кликается и не подсвечивается. Раньше он был частью
   кнопки, и именно из-за этого клиент 27.08 не нашёл кнопку перехода: всё выглядело подписью. */
.line-badge-name { pointer-events: none; }
/* Кнопка перехода: синяя, как ссылка — цвет отделяет глагол от подписи и делает нажимаемость
   видимой без наведения. */
.line-badge-dl {
  pointer-events: auto;
  cursor: pointer;
  font-family: inherit;
  letter-spacing: .06em; text-transform: uppercase;
}
.line-badge-dl:hover { border-color: var(--navy); transform: translateY(-1px); }
.line-badge-cta {
  pointer-events: auto;
  color: var(--navy);
  font-weight: 800;
  cursor: pointer;
  font-family: inherit;
  letter-spacing: .06em; text-transform: uppercase;
}
.line-badge-cta:hover {
  border-color: var(--navy);
  transform: translateY(-1px);
  box-shadow: 0 6px 16px rgba(0, 0, 0, .12);
  text-decoration: underline;
}
.line-badge-cta:focus-visible {
  outline: 2px solid var(--navy);
  outline-offset: 2px;
}
.canvas-wrap {
  background: var(--stage-card);
  border: 1px solid var(--stage-border);
  border-radius: var(--r-md);
  padding: 12px;
  /* Клиент 02.09 (волна 5): «белая рамка одна, намертво зафиксирована, не гуляет вверх-вниз,
     а внутри пускай плавают как хотят». Размер карточки задаёт JS (fitCanvasInCard), холст
     центрируется в ней; у линеек выше Champion по бокам остаётся белое поле того же цвета. */
  display: flex;
  align-items: center;
  justify-content: center;
  /* ⚠️ Обязательно content-box: глобальное `* { box-sizing: border-box }` (строка 72) съело бы
     padding 12px и рамку 1px внутрь ширины, которую ставит JS, и картинка стала бы на 26 px уже. */
  box-sizing: content-box;
  box-shadow: var(--sh-md);
  transition: box-shadow .25s var(--ease), transform .25s var(--ease), border-color .25s var(--ease);
}
/* ⚫ `transform: translateY(-4px)` убран 04.09 (клиент 03.09: «ролик мышку подвожу рамка
   поднимается и наоборот»). Замер: мышь в стороне y=69, мышь НА рамке y=65, убрали — снова 69;
   колесом то же самое при НЕПОДВИЖНОМ курсоре, потому что рамка проезжает под ним сама
   (-4 → 0 → … → -4). На боевом конструктор — iframe на странице WP 3443, где прокрутка есть
   всегда, поэтому клиент ловит это каждым движением колеса. Это продолжение просьбы 01.09
   «вот это гуляние рамки возможно убрать?», по которой тогда сняли `scale()` у `.pcolor`.
   Тень оставлена намеренно: она не двигает геометрию, отклик на курсор сохраняется.
   Сторож — `tests/FrameStill.test.js`. */
.canvas-wrap:hover {
  box-shadow: 0 16px 44px rgba(90, 70, 30, .16), 0 0 0 1px rgba(47, 111, 224, .3);
}
.canvas-wrap canvas { display: block; border-radius: 6px; }

.note {
  color: var(--muted); font-size: 12px; margin-top: 24px;
  max-width: 500px; text-align: center; line-height: 1.65;
  position: relative; z-index: 1;
}

/* ── Панель управления ───────────────────────────────────── */
/* min-width: 0 у панели, списка и карточки — иначе flex-умолчание min-width:auto
   не даёт им стать уже содержимого, и самая длинная строка в списке шрифтов
   («Germany Euro 2024 · лат.», 162 px + отступы) задирает минимум страницы до 381 px.
   Клиент 2026-09-07: «когда на шрифт и цвет нажимаешь, смещается всё вправо». */
.panel {
  display: flex; flex-direction: column; gap: 10px;
  counter-reset: step;
  min-width: 0;
}
.panel > section {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 18px 20px;
  box-shadow: var(--sh-sm);
  transition: box-shadow .2s var(--ease);
}
.panel > section:hover { box-shadow: var(--sh-md); }

/* Нумерация первых 3 секций (Модель, Размер, Опции) */
.panel > section:nth-child(1),
.panel > section:nth-child(2),
.panel > section:nth-child(3) { counter-increment: step; }

.panel h3 {
  margin: 0 0 14px;
  font-family: var(--font-display);
  font-size: 14px; font-weight: 600;
  text-transform: uppercase; letter-spacing: .07em; color: var(--ink-2);
  display: flex; align-items: center; gap: 10px;
}
.panel h3 small {
  font-family: var(--font-body);
  color: var(--brand); font-weight: 700; text-transform: none;
  letter-spacing: 0; font-size: 13px; margin-left: auto;
}

/* Цифровые бейджи шагов */
.panel > section:nth-child(1) h3::before,
.panel > section:nth-child(2) h3::before,
.panel > section:nth-child(3) h3::before {
  content: counter(step);
  display: inline-grid; place-items: center;
  flex-shrink: 0; width: 22px; height: 22px;
  border-radius: 50%;
  background: var(--brand); color: #fff;
  font-size: 11px; font-weight: 900;
  text-transform: none; letter-spacing: 0;
}

/* Активная зона — левый акцент */
#zone-tool {
  border-left: 3px solid var(--brand);
  background: linear-gradient(135deg, #ffffff 0%, var(--brand-soft) 100%);
}
#zone-tool h3 { color: var(--brand-strong); }
#zone-tool .hint {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 14px 16px; margin: 0;
  background: rgba(31, 95, 214, .06);
  border: 1px dashed rgba(31, 95, 214, .28);
  border-radius: var(--r-sm);
  color: var(--brand-strong); font-size: 13px; font-weight: 500;
  line-height: 1.5;
}
#zone-tool .hint::before {
  content: '⬡';
  font-size: 18px; opacity: .5; flex-shrink: 0; margin-top: 1px;
}

.panel label {
  display: flex; align-items: center; gap: 8px;
  font-size: 14px; margin: 6px 0; cursor: pointer; color: var(--ink-2);
}
.panel label input[type="radio"],
.panel label input[type="checkbox"] {
  accent-color: var(--brand); flex-shrink: 0; width: 16px; height: 16px;
}

.panel input[type="text"],
.panel select,
.panel input[type="file"],
.panel input[type="number"] {
  width: 100%; padding: 10px 12px;
  border: 1.5px solid var(--line-strong); border-radius: var(--r-sm);
  margin: 4px 0 10px; font-size: 14px; font-family: inherit; color: var(--ink);
  background: var(--surface-2);
  transition: border-color .15s var(--ease), box-shadow .15s var(--ease), background .15s var(--ease);
}
.panel input[type="text"]:focus,
.panel select:focus,
.panel input[type="number"]:focus {
  outline: none; border-color: var(--brand);
  background: #fff; box-shadow: 0 0 0 4px var(--brand-ring);
}
.panel input[type="file"] { padding: 8px; cursor: pointer; }
.panel input[type="number"] { width: 72px; display: inline-block; margin: 0 0 0 4px; }

.hint { color: var(--muted); font-size: 13px; margin: 4px 0 0; line-height: 1.55; }

/* ── Палитра цвета изделия (ТЗ §2.1) ─────────────────────── */
/* justify-content:center + боковой запас 5px: кольцо активного цвета (box-shadow 4.5px) больше
   не срезается левым краем, справа не остаётся «лишнего» отступа — ряд отцентрован
   (клиент 2026-07-27: «слева рамка залезает, справа наоборот отступ, отцентровать»). */
.color-palette {
  display: flex; flex-wrap: wrap; gap: 9px; margin-bottom: 14px;
  justify-content: center; padding: 0 5px;
}
.pcolor {
  width: 34px; height: 34px; border-radius: 8px;
  border: 2.5px solid #fff;
  box-shadow: 0 0 0 1.5px var(--line-strong), var(--sh-sm);
  cursor: pointer; padding: 0;
  transition: transform .18s var(--ease), box-shadow .18s var(--ease);
}
/* ⚫ `transform: scale()` убран 01.09 (клиент, видео): «вот это гуляние рамки возможно убрать?».
   Образец раздувался на 12 % под курсором и оставался на 8 % больше в активном состоянии —
   замер показал активный свотч 36.7×36.7 при x=143.6 против 34×34 при x=145 у остальных,
   то есть кольцо съезжало с сетки на 1.4 px при каждом движении мыши. Отклик на наведение
   оставлен, но только цветом кольца: он не двигает ни одного пикселя геометрии. */
.pcolor:hover { box-shadow: 0 0 0 1.5px var(--navy), var(--sh-sm); }
.pcolor.active { box-shadow: 0 0 0 2px #fff, 0 0 0 4.5px var(--brand); }

/* ── Карусель форм выбранного цвета ──────────────────────── */
.model-carousel {
  display: flex; gap: 10px; overflow-x: auto;
  /* left/right padding >= ширины кольца активной карточки (2px), иначе кольцо
     обрезается краем overflow-контейнера (клиент 2026-07-21: «рамка обрезается слева»). */
  padding: 6px 8px 10px; margin: 0 -6px;
  scroll-padding-left: 8px;
  scroll-snap-type: x proximity;
  scrollbar-width: thin;
  scrollbar-color: var(--line-strong) transparent;
}
.model-carousel::-webkit-scrollbar { height: 7px; }
.model-carousel::-webkit-scrollbar-thumb { background: var(--line-strong); border-radius: 999px; }
.model-carousel::-webkit-scrollbar-track { background: transparent; }
/* Превью-модели: чистые картинки без рамок/подписей (клиент 2026-07-12) —
   видно только само изделие, активная выделяется мягким кольцом. */
.model-card {
  flex: 0 0 auto; width: 88px;
  display: block; padding: 0; border: 0; background: none;
  cursor: pointer; scroll-snap-align: start;
  transition: box-shadow .18s var(--ease), transform .18s var(--ease);
}
.model-card:hover { transform: translateY(-2px); }
.model-thumb {
  width: 100%; aspect-ratio: 3 / 4; border-radius: var(--r-sm);
  overflow: hidden; background: transparent;
  display: grid; place-items: center;
  transition: box-shadow .18s var(--ease);
}
.model-card:hover .model-thumb { box-shadow: 0 0 0 2px var(--brand-ring); }
.model-card.active .model-thumb { box-shadow: 0 0 0 2px var(--brand); }
.model-thumb img { width: 100%; height: 100%; object-fit: contain; display: block; }

/* Совместимость: старые текст-цвет свотчи в инструменте зоны */
.swatches { display: flex; flex-wrap: wrap; gap: 10px; }

.color-row { margin: 8px 0 10px; }
.color-sw {
  width: 30px; height: 30px; border-radius: 8px;
  border: 2px solid #fff; box-shadow: 0 0 0 1.5px var(--line-strong);
  cursor: pointer; padding: 0;
  transition: transform .15s var(--ease), box-shadow .15s var(--ease);
}
.color-sw:hover { transform: scale(1.14); }
.color-sw.active { box-shadow: 0 0 0 2px #fff, 0 0 0 4px var(--brand); transform: scale(1.10); }

/* ── Сегмент текст / логотип ─────────────────────────────── */
.seg {
  display: flex; gap: 4px; margin: 6px 0 12px;
  padding: 4px; background: var(--surface-2);
  border: 1.5px solid var(--line); border-radius: 11px;
}
.panel .seg-btn {
  flex: 1; padding: 8px 0; border: none; border-radius: 8px;
  background: transparent; color: var(--muted); cursor: pointer;
  font-size: 14px; font-weight: 600; font-family: inherit;
  transition: background .18s var(--ease), color .18s var(--ease), box-shadow .18s var(--ease);
}
.panel .seg-btn:hover { color: var(--ink); }
.panel .seg-btn.active { background: #fff; color: var(--brand-strong); box-shadow: var(--sh-sm); }

/* ── Размер выбирается первым ────────────────────────────── */
/* Клиент 09.09: «переносим кнопки из комплектации, детская и взрослая, в самый верх… а внизу
   кнопка таблица размеров, человек её открывает, видит какие есть размеры, сразу выбирает
   размер, а дальше уже пошёл по конструктору рисовать» — блок стоит НАД конструктором опций. */
.size-first { margin: 0 0 14px; }
.size-first .seg { margin: 0 0 8px; }
/* «Просто надпись взрослая и детская, покрупнее сделаем» (голосовое 08:42): этот сегмент
   крупнее, чем сегмент «текст / логотип» ниже по панели, — он первое, что видит покупатель. */
.panel .size-first .seg-btn { padding: 11px 0; font-size: 16px; }
.size-first-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.size-chosen { font-size: 13px; color: var(--muted); }
.size-chosen b { color: var(--ink); font-weight: 700; }

/* ── Кнопки ──────────────────────────────────────────────── */
.row { display: flex; gap: 8px; flex-wrap: wrap; }

/* Панельные кнопки самостоятельны (.cta, .opt-toggle, .opt-del, .qty-stepper,
   .linkbtn, .price-lines-toggle). Общий стиль отключён, чтобы не перебивать их. */
.panel button:disabled { opacity: .4; cursor: not-allowed; box-shadow: none; transform: none; filter: none; }

/* ── Блок цены (тёмная карточка = акцент) ───────────────── */
#price-box {
  position: sticky; top: 76px;
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: var(--sh-md);
}
#price-box h3 { color: var(--muted); }

#price-box .pline {
  display: flex; justify-content: space-between;
  font-size: 14px; padding: 5px 0; color: var(--ink-2);
}
#price-box .pline.discount { color: var(--success); font-weight: 700; }
#price-lines { margin-bottom: 6px; }

/* Клиент 31.08 обвёл красным короткую чёрточку над ценой: «Убрать эту полоску».
   Это был border-top на #price-total — а он <span>, то есть inline, и рамка рисовалась
   только над шириной самой цены, справа. Вместе с рамкой сняты margin-top и padding-top:
   они стояли ради отбивки от неё. */
#price-total {
  margin-top: 12px;
  font-family: var(--font-display);
  font-size: 32px; font-weight: 700; letter-spacing: .01em;
  text-align: right; color: var(--ink);
}
#price-total strong { font-weight: 700; }
/* Микро-удар цены при изменении суммы */
#price-total.bump { animation: price-bump .32s var(--ease); }
@keyframes price-bump {
  0%   { transform: scale(1); }
  35%  { transform: scale(1.07); color: #9ec1ff; }
  100% { transform: scale(1); }
}

#order-btn {
  width: 100%; margin-top: 14px; padding: 14px;
  font-size: 15px; font-weight: 800; letter-spacing: .04em;
  border-radius: 999px;
  background: var(--navy);
  color: #fff;
  box-shadow: 0 6px 20px rgba(20, 41, 76, .30);
}
#order-btn:hover {
  background: var(--navy-strong);
  box-shadow: 0 10px 30px rgba(20, 41, 76, .42);
}

/* ── Блок выбора цвета/модели ПОД макетом (тёмная сцена) ─── */
/* На ПК палитра — левая колонка сцены, поэтому ни ширины на весь ряд, ни разделительной
   черты сверху, ни верхнего отступа ей больше не нужно (всё это было от жизни под макетом).
   На мобильной старое поведение возвращается в брейкпоинте 900px. */
.colorpick { grid-area: pal; position: relative; z-index: 1; }
.modelpick { grid-area: models; width: 100%; max-width: 640px; margin-top: 14px; }
.views { grid-area: views; }
/* ОДНА колонка свотчей — клиент 01.09: «слева палитру нужно сделать в одну строку».
   ⚫ Прежние две колонки по 34 px были не прихотью: одна колонка того же размера даёт
   15 × 34 + 14 × 9 + 10 = 646 px против 491 px, которые оставляет рядом стоящий макет, —
   то есть возвращала бы вертикальную прокрутку, а её у клиента жёсткий запрет
   (на 1366×768 перелив обязан быть 0). Поэтому колонка одна, но образец мельче:
   15 × 26 + 14 × 5 + 10 = 470 px, запас к 491 остаётся 21 px.
   Зазор 5 px выбран не на глаз: кольцо активного цвета это `box-shadow` на 4.5 px,
   активен всегда ровно один образец, и 5 px — минимум, при котором кольцо не наезжает
   на соседа. Боковой запас держит `padding: 5px`, иначе кольцо срезал бы край колонки.

   🔴 `min-width: 901px` обязателен, и это не аккуратность, а починка регресса 01.09.
   Медиазапрос НЕ повышает специфичность: `.colorpick .pcolor` это (0,2,0), а мобильные
   `.pcolor { width: 40px }` и `@media (pointer: coarse) .pcolor { width: 44px }` — (0,1,0).
   Без обёртки колоночные 26 px протекали на телефон и побеждали оба мобильных правила:
   замер на 360×640 дал свотч 26×26 вместо 44 (ниже тач-минимума) и `gap` 5 вместо 11.
   Правило описывает раскладку «палитра сбоку», которой ниже 901 px просто нет. */
@media (min-width: 901px) {
  .colorpick .color-palette {
    display: grid; grid-template-columns: 26px;
    gap: 5px; margin-bottom: 0; padding: 5px;
  }
  .colorpick .pcolor { width: 26px; height: 26px; border-radius: 7px; border-width: 2px; }
}
/* ⚫ Правила `.cp-download`, `.cp-head`, `.cp-title`, `.cp-models-label` удалены 31.08 вместе
   с самими надписями и кнопкой: клиент попросил убрать надписи над блоками, а «Скачать макет»
   перенести на плашку внутрь картинки. Разметки под них больше нет ни одной. */
.stage-btn {
  padding: 8px 16px; border-radius: 999px;
  background: #fff;
  border: 1px solid var(--line-strong);
  color: var(--ink); cursor: pointer;
  font-size: 13px; font-weight: 700; font-family: inherit;
  box-shadow: var(--sh-sm);
  transition: background .15s var(--ease), border-color .15s var(--ease), transform .15s var(--ease);
}
.stage-btn:hover { border-color: var(--navy); transform: translateY(-1px); }

/* ── Заголовок панели-конструктора ───────────────────────── */
.panel-title { padding: 4px 4px 6px; }
.panel-title h2 {
  margin: 0 0 6px;
  font-family: var(--font-display);
  font-size: 22px; font-weight: 700; letter-spacing: .01em;
  text-transform: uppercase; color: var(--ink);
}
.panel-title p { margin: 0; color: var(--muted); font-size: 13.5px; line-height: 1.5; }

/* Убираем нумерованные бейджи шагов старого макета */
.panel > section h3::before { content: none !important; }

/* ── Карточки опций (аккордеон + тумблер + крестик) ───────── */
.opt-list { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.opt-card {
  background: var(--surface);
  border: 1.5px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--sh-sm);
  overflow: hidden;
  min-width: 0;
  transition: border-color .2s var(--ease), box-shadow .2s var(--ease), background .2s var(--ease);
}
.opt-card:hover { box-shadow: var(--sh-md); }
/* Активная (показана на макете) — подсветка рамкой + фоном (клиент 2026-07-12) */
.opt-card.active {
  border-color: var(--success);
  background: linear-gradient(135deg, #ffffff 0%, var(--success-soft) 100%);
  box-shadow: 0 0 0 3px rgba(69, 177, 85, .14), var(--sh-sm);
}
.opt-card.open { box-shadow: var(--sh-md); }

/* Клиент 01.09 (три голосовых + два его макета): подпись «Номер на шортах включён в стоимость»
   уезжала на вторую строку ровно в тот момент, когда появлялся тумблер, и карточка росла
   с 66.2 до 82.4 px. Причина была не в длине текста, а в раскладке: шапка была flex-строкой,
   `.opt-head-right` не сжимался, а текстовая колонка сжималась — 218.9 → 210.7 px при нужных 219.
   Шапка переведена в сетку 2×2: заголовок и правый блок в первом ряду, подпись во втором ряду
   на ВСЮ ширину. Подписи достаётся 338 px вместо 210.7, она держится в одну строку, а появление
   тумблера больше не отнимает у неё ничего. Это и есть первый из двух вариантов клиента.

   ⚫ Пустой слот под тумблер (`visibility: hidden` вместо вставки узла) пробовали и убрали:
   он держал правый блок на 115.3 px всегда, а не 65.3, и от этого заголовок «Логотип на спине
   под номером» ломался на две строки — карточка 48.8 → 72 px, страница 768 → 790, то есть
   возвращалась прокрутка, которой клиент не должен видеть. Подпись и так больше не зависит
   от тумблера, потому что лежит в своём ряду на всю ширину, — слот оказался лишним. */
.opt-head {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  align-items: center; column-gap: 12px; row-gap: 2px;
  padding: 15px 16px; cursor: pointer; user-select: none;
}
/* `display: contents` вместо своего бокса: заголовок и подпись становятся элементами
   сетки шапки напрямую, поэтому подпись может растянуться под правым блоком. */
.opt-head-text { display: contents; }
.opt-title { grid-column: 1; grid-row: 1; }
.opt-sub { grid-column: 1 / -1; grid-row: 2; }
.opt-head-right { grid-column: 2; grid-row: 1; }
.opt-title { font-weight: 800; font-size: 15.5px; color: var(--ink); letter-spacing: -.01em; }
.opt-sub { font-size: 12px; color: var(--muted); line-height: 1.35; }
.opt-head-right { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }
.opt-price {
  font-family: var(--font-display);
  font-size: 15px; font-weight: 700; color: var(--ink);
  white-space: nowrap;
}
.opt-card.active .opt-price { color: var(--ink); }
/* Клиент 31.08 обвёл стрелки раскрытия: «Эти кнопки сделать крупнее».
   16 px вместо 12 px; тот же размер у стрелок «Комплектации» и раскрытия цены,
   иначе три одинаковых по смыслу стрелки разъедутся. */
.opt-chev {
  color: var(--line-strong); font-size: 16px;
  transition: transform .22s var(--ease);
}
.opt-card.open .opt-chev { transform: rotate(180deg); color: var(--navy); }

/* Тумблер ON/OFF (появляется только когда есть данные) */
.opt-toggle {
  position: relative; width: 40px; height: 23px; flex-shrink: 0;
  border-radius: 999px; border: none; cursor: pointer; padding: 0;
  background: var(--line-strong);
  transition: background .2s var(--ease);
}
.opt-toggle .knob {
  position: absolute; top: 2.5px; left: 2.5px;
  width: 18px; height: 18px; border-radius: 50%;
  background: #fff; box-shadow: 0 1px 3px rgba(0, 0, 0, .3);
  transition: transform .2s var(--ease);
}
.opt-toggle.on { background: var(--success); }
.opt-toggle.on .knob { transform: translateX(17px); }

/* Тело карточки */
/* ⚫ `border-top: 1px dashed var(--line)` убран 01.09 по голосовому клиента: «когда я начал
   заполнять, появилась пунктирная линия вдоль всего блока, если есть возможность её убрать,
   будет замечательно». Шапку от тела и так отделяет отступ, разделитель был лишним. */
.opt-body {
  padding: 4px 16px 16px;
  animation: opt-open .22s var(--ease);
}
@keyframes opt-open { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
.opt-fields { display: flex; gap: 8px; }
.opt-fields .opt-in { margin-bottom: 0; }
.opt-in {
  width: 100%; padding: 11px 13px; margin: 10px 0 0;
  border: 1.5px solid var(--line-strong); border-radius: var(--r-sm);
  font-size: 14px; font-family: inherit; color: var(--ink);
  background: var(--surface-2);
  transition: border-color .15s var(--ease), box-shadow .15s var(--ease), background .15s var(--ease);
}
.opt-in:focus { outline: none; border-color: var(--brand); background: #fff; box-shadow: 0 0 0 4px var(--brand-ring); }
.opt-in:disabled { opacity: .5; background: var(--line); cursor: not-allowed; }
.opt-in-sm { flex: 0 0 88px; text-align: center; }
.opt-or {
  text-align: center; font-size: 12px; color: var(--muted);
  margin: 10px 0 2px; text-transform: uppercase; letter-spacing: .08em;
}

/* Кнопка загрузки (+ / ✓ / ×) — рабочая версия, финал клиент дорисует */
/* Ряд из двух кнопок: «Загрузить логотип» + «Удалить фон» (эскиз клиента 5.png).
   На узких экранах переносится в столбик, чтобы кнопки не сжимались до нечитаемого. */
.opt-upload-row {
  display: flex; align-items: stretch; gap: 10px; margin-top: 10px; flex-wrap: wrap;
}
/* Обе кнопки ряда — одинаковой высоты и рамки (клиент 2026-07-22: «сделать одинаковыми»).
   Клиент 2026-07-27: плашка загрузки должна быть ШИРЕ, «Удалить фон» — чуть уже, при этом
   высота у обеих одна (align-items:stretch в .opt-upload-row) и значки НЕ уменьшаем. */
.opt-upload-row .opt-upload,
.opt-upload-row .opt-rmbg { margin: 0; min-width: 0; }
.opt-upload-row .opt-upload { flex: 1.25 1 150px; }
.opt-upload-row .opt-rmbg { flex: 0.85 1 124px; }
.opt-upload {
  /* justify-content:center — содержимое (кружок + подпись) по центру плашки, как в «Удалить фон».
     Клиент 2026-07-27: «кружочек и надпись сильно смещены влево, надо центровать». */
  display: flex; align-items: center; justify-content: center; gap: 11px;
  margin-top: 10px; padding: 12px 14px;
  border: 1.5px dashed var(--line-strong); border-radius: var(--r-sm);
  background: var(--surface-2); cursor: pointer;
  transition: border-color .15s var(--ease), background .15s var(--ease);
}
.opt-upload:hover { border-color: var(--brand); background: #fff; }
/* Кнопка «Удалить фон» — тот же дашед-стиль, палочка + подпись. */
.opt-rmbg {
  display: flex; align-items: center; justify-content: center; gap: 9px;
  flex: 0 0 auto; padding: 12px 14px; white-space: nowrap;
  border: 1.5px dashed var(--line-strong); border-radius: var(--r-sm);
  background: var(--surface-2); color: var(--ink-2);
  font-size: 13.5px; font-weight: 600; cursor: pointer;
  transition: border-color .15s var(--ease), background .15s var(--ease), opacity .15s var(--ease);
}
.opt-rmbg:hover { border-color: var(--brand); background: #fff; }
.opt-rmbg-icon { display: grid; place-items: center; flex-shrink: 0; }
/* Рамка не бледнеет в покое — обе кнопки выглядят одинаково (клиент 2026-07-22). */
.opt-rmbg.is-idle { opacity: 1; }
.opt-rmbg.busy { pointer-events: none; opacity: .7; }
.opt-upload-icon {
  display: grid; place-items: center; flex-shrink: 0;
  width: 28px; height: 28px; border-radius: 50%;
  background: var(--brand); color: #fff; font-size: 18px; font-weight: 700; line-height: 1;
}
.opt-upload.has { border-style: solid; border-color: var(--success); background: var(--success-soft); }
.opt-upload.has .opt-upload-icon { background: var(--success); }
/* flex:0 1 auto — подпись не растягивается, поэтому кружок+текст стоят единой группой по центру
   плашки (клиент 2026-07-27). Раньше flex:1 распирал текст и прижимал кружок к левому краю. */
.opt-upload-text { font-size: 13.5px; font-weight: 600; color: var(--ink-2); flex: 0 1 auto; }
.opt-del {
  /* Без margin-left:auto — крестик больше не прилипает к краю рамки, стоит в общей группе
     с отступом (клиент 2026-07-27: «крестик прилип к рамке, надо от рамы отлепить»). */
  display: grid; place-items: center; flex-shrink: 0;
  width: 26px; height: 26px; border-radius: 50%;
  background: rgba(0, 0, 0, .06); color: var(--muted);
  font-size: 18px; line-height: 1; cursor: pointer;
  transition: background .15s var(--ease), color .15s var(--ease);
}
.opt-del:hover { background: #fde2e2; color: #d1263a; }
.opt-note { color: #d1263a; font-size: 12.5px; margin: 8px 0 0; }

/* Свёрнутый «Шрифт и цвет» */
.opt-font { margin-top: 12px; }
.opt-font summary {
  font-size: 13px; font-weight: 700; color: var(--brand-strong);
  cursor: pointer; list-style: none; padding: 4px 0;
  display: inline-flex; align-items: center; gap: 6px;
}
.opt-font summary::-webkit-details-marker { display: none; }
.opt-font summary::before { content: '⚙'; opacity: .6; }
/* Список превью шрифтов: образец нарисован самим шрифтом, список прокручивается —
   человек листает и сразу видит начертание (клиент 2026-07-12). */
.font-list {
  margin: 8px 0 2px; max-height: 232px; overflow-y: auto;
  display: flex; flex-direction: column; gap: 6px;
  padding: 2px; scrollbar-width: thin; scrollbar-color: var(--line-strong) transparent;
}
.font-list::-webkit-scrollbar { width: 7px; }
.font-list::-webkit-scrollbar-thumb { background: var(--line-strong); border-radius: 999px; }
.font-opt {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  width: 100%; padding: 9px 12px; text-align: left; cursor: pointer;
  border: 1.5px solid var(--line-strong); border-radius: var(--r-sm);
  background: var(--surface-2); color: var(--ink);
  transition: border-color .16s var(--ease), box-shadow .16s var(--ease), background .16s var(--ease);
}
.font-opt:hover { border-color: var(--brand); }
.font-opt.active {
  border-color: var(--brand); background: var(--brand-soft);
  box-shadow: 0 0 0 2px var(--brand-ring);
}
.font-opt-sample {
  font-size: 21px; line-height: 1.15; color: var(--ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; flex: 1;
}
.font-opt-name {
  flex: 0 0 auto; font-size: 11px; font-weight: 700; color: var(--muted);
  text-transform: uppercase; letter-spacing: .04em; white-space: nowrap;
}
.font-opt.active .font-opt-name { color: var(--brand-strong); }
/* Клиент 2026-07-16: латинский шрифт при русском тексте недоступен — приглушаем и запрещаем. */
.font-opt.locked { opacity: .4; cursor: not-allowed; filter: grayscale(1); }
.font-opt.locked:hover { border-color: var(--line-strong); }

/* ── Доп.комплектация ────────────────────────────────────── */
/* Клиент 2026-07-17: весь раздел «Комплектация» шрифтом Calibri. */
.opt-extra, .opt-extra * { font-family: Calibri, 'Segoe UI', Candara, 'Trebuchet MS', sans-serif; }
/* Сворачиваемый заголовок «Комплектация» (клиент 2026-07-15: подтянуть «Итого» выше). */
.extra-toggle {
  display: flex !important; align-items: center; justify-content: space-between;
  width: 100%; padding: 12px 0 !important; margin: 0;
  background: none !important; border: none; box-shadow: none !important;
  color: var(--ink) !important; cursor: pointer;
  /* Заголовок «Комплектация» — тем же шрифтом, что «Логотип»/«Детализация» (клиент 2026-07-22),
     перебивая общий Calibri раздела .opt-extra (тело блока остаётся на Calibri по правке 07-17). */
  font-family: var(--font-body); font-size: 15.5px; font-weight: 800; letter-spacing: -.01em;
}
/* Клиент 31.08: «слово Комплектация написано другим шрифтом». Так и было: сама надпись
   лежит во вложенном <span>, в который `.opt-extra *` попадает НАПРЯМУЮ, а `.extra-toggle`
   доставал его только наследованием — прямое совпадение бьёт наследование, и заголовок
   уезжал на Calibri. Дотягиваемся до потомков явно; тело блока остаётся на Calibri. */
.extra-toggle * { font-family: var(--font-body); }
.extra-toggle:hover { color: var(--brand-strong) !important; transform: none !important; filter: none !important; }
.extra-toggle .chev { color: var(--line-strong); font-size: 16px; transition: transform .2s var(--ease); }
.extra-toggle[aria-expanded="true"] .chev { transform: rotate(180deg); }
.extra-body[hidden] { display: none; }
.extra-body { padding-top: 2px; }
/* Выбор конкретного размера кликом по строке (клиент 2026-07-15: «размеры не могу выбрать»). */
.size-select tbody tr { cursor: pointer; }
.size-select tbody tr:hover { background: var(--brand-soft); }
.size-select tr.sel { background: var(--brand-soft); }
.size-select tr.sel td { color: var(--brand-strong); font-weight: 700; }
.size-select td.pick, .size-select thead th:first-child { width: 34px; text-align: center; padding-right: 0; }
.size-hint { margin: 8px 0 0; font-size: 13px; color: var(--muted); }
.size-hint.need { color: #c0392b; font-weight: 700; }
.extra-block { margin: 4px 0 12px; }
.extra-label {
  display: block; font-size: 12px; font-weight: 700; color: var(--muted);
  text-transform: uppercase; letter-spacing: .05em; margin-bottom: 7px;
}
.opt-extra .seg { margin: 0; }
.extra-check {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 0; margin: 0; font-size: 14px; cursor: pointer; color: var(--ink-2);
  border-top: 1px solid var(--line);
}
.extra-check span { display: flex; align-items: center; gap: 8px; flex: 1; }
.extra-check em {
  font-style: normal; margin-left: auto; font-weight: 700; font-size: 13px;
  color: var(--brand-strong);
}
.qty-block { display: flex; align-items: center; justify-content: space-between; margin-top: 14px; }
.qty-block .extra-label { margin: 0; }
.qty-stepper {
  display: flex; align-items: center; gap: 0;
  border: 1.5px solid var(--line-strong); border-radius: var(--r-sm); overflow: hidden;
}
.qty-stepper button {
  width: 38px; height: 40px; border: none; background: var(--surface-2);
  color: var(--ink-2); font-size: 20px; font-weight: 700; cursor: pointer;
  transition: background .15s var(--ease);
}
.qty-stepper button:hover { background: var(--brand-soft); color: var(--brand-strong); }
.qty-stepper input {
  width: 52px; height: 40px; border: none; text-align: center;
  font-size: 15px; font-weight: 700; color: var(--ink); background: #fff;
  border-left: 1.5px solid var(--line); border-right: 1.5px solid var(--line);
  -moz-appearance: textfield;
}
.qty-stepper input::-webkit-outer-spin-button,
.qty-stepper input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.extra-links { margin-top: 14px; }
.linkbtn {
  background: none !important; border: none; box-shadow: none !important; padding: 0 !important;
  color: var(--brand) !important; font-weight: 700; font-size: 13.5px; cursor: pointer;
  text-decoration: underline; text-underline-offset: 3px;
}
.linkbtn:hover { color: var(--brand-strong) !important; transform: none !important; filter: none !important; }

/* ── Итог + CTA (тёмная липкая карточка) ─────────────────── */
.price-box.price-box {
  position: sticky; top: 76px;
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: var(--sh-md);
  padding: 18px 20px;
}
.price-lines-toggle {
  display: flex !important; align-items: center; justify-content: space-between;
  width: 100%; padding: 0 0 4px !important; margin: 0;
  background: none !important; border: none; box-shadow: none !important;
  color: var(--ink) !important; cursor: pointer;
  /* <button> не наследует шрифт body (UA даёт системный Arial) — задаём явно, чтобы
     заголовок «Детализация» совпал с «Логотип»/«Комплектация» (клиент 2026-07-22). */
  font-family: var(--font-body); font-size: 15.5px; font-weight: 800; letter-spacing: -.01em;
}
.price-lines-toggle:hover { color: var(--ink) !important; transform: none !important; filter: none !important; }
.price-lines-toggle .chev { color: var(--line-strong); font-size: 16px; transition: transform .2s var(--ease); }
.price-lines-toggle.open .chev { transform: rotate(180deg); }
.price-lines { padding: 8px 0 4px; }
.price-lines .pline {
  display: flex; justify-content: space-between;
  font-size: 13.5px; padding: 4px 0; color: var(--ink-2);
}
.price-lines .pline.discount { color: var(--success); font-weight: 700; }
.price-foot {
  display: flex; align-items: baseline; justify-content: space-between;
  padding-top: 4px; margin-top: 0;
}
.price-foot-label {
  font-family: var(--font-display); font-size: 13px; font-weight: 600;
  text-transform: uppercase; letter-spacing: .08em; color: var(--muted);
}
.price-total {
  font-family: var(--font-display);
  font-size: 30px; font-weight: 700; letter-spacing: .01em; color: var(--ink);
}
.price-total.bump { animation: price-bump .32s var(--ease); }
.cta.cta {
  width: 100%; margin-top: 14px; padding: 15px;
  font-size: 15px; font-weight: 800; letter-spacing: .04em;
  border-radius: 999px;
  background: var(--navy);
  color: #fff;
  box-shadow: 0 6px 20px rgba(20, 41, 76, .30);
}
.cta.cta:hover { background: var(--navy-strong); box-shadow: 0 10px 30px rgba(20, 41, 76, .42); }

/* ── Тост статуса ────────────────────────────────────────── */
.status {
  position: fixed; left: 50%; bottom: 22px; transform: translateX(-50%);
  background: var(--ink); color: #fff; padding: 13px 22px; border-radius: 12px;
  font-size: 14px; max-width: 80vw; box-shadow: var(--sh-lg); z-index: 200;
}

/* ── Модалка заказа ──────────────────────────────────────── */
.order-overlay {
  position: fixed; inset: 0; background: rgba(8, 13, 26, .82);
  display: flex; align-items: center; justify-content: center;
  padding: 20px; z-index: 100;
  animation: overlay-in .2s var(--ease);
}
@keyframes overlay-in { from { opacity: 0; } to { opacity: 1; } }

.order-card {
  background: #fff; border-radius: var(--r-xl); width: 100%; max-width: 560px;
  max-height: 92vh; overflow: auto; box-shadow: var(--sh-lg);
  animation: card-in .22s var(--ease);
}
@keyframes card-in {
  from { opacity: 0; transform: translateY(16px) scale(.97); }
  to   { opacity: 1; transform: none; }
}
.order-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 20px 24px; border-bottom: 1px solid var(--line);
  position: sticky; top: 0; background: #fff; z-index: 1;
}
.order-head h2 {
  margin: 0; font-family: var(--font-display); font-size: 21px; font-weight: 600;
  text-transform: uppercase; letter-spacing: .04em;
}
.order-close {
  border: none; background: rgba(0, 0, 0, .06);
  font-size: 20px; line-height: 1; color: var(--muted);
  cursor: pointer; width: 36px; height: 36px; border-radius: 50%;
  display: grid; place-items: center;
  transition: background .15s var(--ease), color .15s var(--ease);
}
.order-close:hover { background: rgba(0, 0, 0, .11); color: var(--ink); }

.order-body { padding: 20px 24px; }
.order-body h3 {
  font-family: var(--font-display);
  font-size: 13px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--ink-2); font-weight: 600; margin: 18px 0 8px;
}
.order-row {
  display: flex; justify-content: space-between; align-items: center;
  padding: 7px 0; font-size: 14px;
}
.order-row > span { color: var(--muted); }
.order-row b { display: inline-flex; align-items: center; font-weight: 700; }
.order-row .dot {
  display: inline-block; width: 14px; height: 14px;
  border-radius: 50%; margin-right: 8px;
  box-shadow: 0 0 0 1.5px rgba(0, 0, 0, .14);
}
.order-items {
  width: 100%; border-collapse: collapse; margin: 10px 0; font-size: 13px;
}
.order-items th {
  text-align: left; color: var(--muted); font-weight: 800;
  padding: 8px 10px; border-bottom: 2px solid var(--line);
  font-size: 11px; text-transform: uppercase; letter-spacing: .07em;
}
.order-items td { padding: 9px 10px; border-bottom: 1px solid var(--line); color: var(--ink-2); }
.order-items tr:last-child td { border-bottom: none; }
.order-items .num, .order-totals .num { text-align: right; }
.order-items .dim { color: var(--muted); }

/* Lines inside totals section (plain colours, no override needed) */
.pline {
  display: flex; justify-content: space-between;
  font-size: 14px; padding: 4px 0; color: var(--ink-2);
}
.pline.discount { color: var(--success); font-weight: 600; }
#price-lines { margin-bottom: 4px; }

.order-totals {
  margin-top: 14px; background: var(--surface-2);
  border: 1px solid var(--line); border-radius: var(--r-md); padding: 14px 16px;
}
.order-grand {
  margin-top: 14px; padding: 16px 18px; border-radius: var(--r-md);
  background: var(--navy); color: rgba(255, 255, 255, .65);
  font-family: var(--font-display);
  font-size: 26px; font-weight: 700; text-align: right; letter-spacing: .01em;
}
.order-grand b { color: #ffffff; }

.order-foot {
  display: flex; flex-wrap: wrap; gap: 10px; justify-content: flex-end;
  padding: 16px 24px; border-top: 1px solid var(--line);
  position: sticky; bottom: 0; background: #fff;
}
.order-foot button {
  /* Клиент 2026-07-15: на планшете «В корзину» наезжала на «Продолжить редактирование».
     wrap на контейнере не даёт перекрытия; кнопки жмутся по контенту, а текст
     внутри кнопки не переносится (nowrap) — «Продолжить редактирование» одной строкой. */
  flex: 1 1 auto; min-width: max-content; text-align: center; white-space: nowrap;
  padding: 12px 20px; border: none; border-radius: 999px;
  background: var(--navy);
  color: #fff; cursor: pointer; font-size: 14px; font-weight: 700; font-family: inherit;
  box-shadow: var(--sh-brand); transition: transform .15s var(--ease), filter .15s var(--ease);
}
.order-foot button:hover { transform: translateY(-1px); filter: brightness(1.07); }
.order-foot button.ghost {
  background: var(--surface-2); color: var(--ink-2);
  border: 1.5px solid var(--line-strong); box-shadow: none;
}
.order-foot button.ghost:hover {
  background: #fff; border-color: var(--brand); color: var(--brand-strong);
  transform: none; filter: none;
}

/* ── Появление элементов (мягкий подъём) ─────────────────── */
@keyframes rise-in {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}
.canvas-col { animation: rise-in .5s var(--ease) both; }
.canvas-col:nth-child(2) { animation-delay: .08s; }
.panel > section { animation: rise-in .45s var(--ease) both; }
.panel > section:nth-child(2) { animation-delay: .05s; }
.panel > section:nth-child(3) { animation-delay: .10s; }
.panel > section:nth-child(4) { animation-delay: .14s; }

/* ── Доступность ─────────────────────────────────────────── */
:focus-visible { outline: 2.5px solid var(--brand); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important; animation-delay: 0 !important;
    transition-duration: .01ms !important;
  }
}

/* ── Тач-эргономика (телефоны/планшеты) ──────────────────── */
button, .pcolor, .color-sw, .seg-btn, .model-card, label,
input[type="radio"], input[type="checkbox"] {
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}
/* Инерционный скролл карусели на iOS */
.model-carousel { -webkit-overflow-scrolling: touch; overscroll-behavior-x: contain; }

/* ── Низкий экран ноутбука: уплотняем правую колонку ─────── */
/* Клиент 31.08: «на ноутбуке 1366×768 конструктор должен помещаться без вертикальной
   прокрутки». Холст в высоту вписывает `_availHeight()` + `capWidthByHeight` (JS), но замер
   31.08 показал, что после этого ЛЕВАЯ колонка укладывается ровно (низ #stage 739 при 768),
   а переливается ПРАВАЯ: #panel набирал 782 px при доступных 712.
   Раскладка из двух колонок, высота страницы = высота самой длинной, поэтому холст можно
   ужимать сколько угодно — прокрутка от этого не уйдёт. Ужимать надо панель.
   Замер по слагаемым: заголовок 50 + три зазора 30 + шесть карточек опций 423 +
   «Комплектация» 83 + блок цены 196. Отсюда и правки ниже — режем ВОЗДУХ (padding и gap),
   не трогая шрифты и не пряча ничего: −8 px на карточку × 6, −3 на зазор × 8, −8 на секцию × 2
   ≈ 88 px, то есть с запасом на разницу шрифтов у клиента.
   ⚠️ Порог 860 px по ВЫСОТЕ, а не по ширине: на 1366×768 надо, на 1920×1080 не надо.
   ⚠️ `min-width: 901px` обязателен — ниже работает мобильная раскладка (одна колонка),
   там правая колонка идёт под макетом и прокрутка законна. */
@media (min-width: 901px) and (max-height: 860px) {
  .panel { gap: 7px; }
  .panel > section { padding: 14px 20px; }
  .opt-list { gap: 7px; }
  .opt-head { padding: 11px 16px; }
}

/* ── Мобильная раскладка ─────────────────────────────────── */
@media (max-width: 900px) {
  #app {
    grid-template-columns: 1fr; gap: 16px; margin-top: 16px;
    padding-left: max(24px, env(safe-area-inset-left));
    padding-right: max(24px, env(safe-area-inset-right));
  }
  /* Клиент 31.08: влево палитра уезжает только на ПК, «на мобильной как сейчас» — то есть
     обратно в колонку под макет. Порядок его же: макет → цвета → эскизы моделей. */
  #stage {
    padding: 28px 16px 22px; border-radius: var(--r-lg);
    grid-template-areas: "views" "pal" "models";
    /* ⚠️ Именно minmax(0, 1fr), а НЕ 1fr. У `1fr` минимум равен `auto`, то есть min-content
       самого широкого ребёнка, и колонка раздувается под него. Замер 31.08 на 375 px:
       колонка вставала 640 px (по `.colorpick { max-width: 640px }`) при доступных 344,
       а `justify-items: center` центрировал холст внутри этой фиктивной ширины —
       (640 − 336) / 2 + 8 = 160, ровно измеренный сдвиг. Макет и все три пилюли уезжали
       вправо за экран и обрезались `overflow: hidden`, горизонтальной прокрутки при этом
       не было, то есть добраться до «перейти в карточку» было нельзя вообще.
       Нижняя граница 0 запрещает колонке расти под ребёнка. */
    grid-template-columns: minmax(0, 1fr);
  }
  /* 🔴 Зазор «ряд плашки линейки → чернила формы», волна 5 (02.09). Полоса 560px ниже поднимает
     его 30 -> 33 по той же причине: белая полоса над формой это 60 пикселей КАДРА, а кадры линеек
     разной высоты (836 у Champion … 937 у New); когда все кадры вписаны в карточку ОДНОЙ высоты,
     у высокого кадра те же 60 px дают на экране меньше, и форма подходит к ряду ближе.
     На 768 просело сильнее всего: 17 -> 12.6, и эта полоса своего `padding-top` не имела вовсе.
     Клиент 02.09 назвал зазор единственным условием к шагу 1 («верхние кнопки слишком близко
     не приближались»), поэтому возвращаем потерянное. 5px, а не 2px, как у 560: там просело 2. */
  .views { padding-top: 5px; }
  /* Цвета в ОДНУ строку с прокруткой, по образцу карусели форм снизу — клиент 31.08 (11:07):
     «цветов очень много, получается две строки… чтобы были в одну строчку и просто
     пролистывать влево-вправо». Боковой padding 5px обязателен: кольцо активного свотча
     (box-shadow 4.5px) иначе срезается краем overflow-контейнера — на этом уже спотыкались
     27.07. Две колонки — раскладка ПК, здесь она снимается.

     🔴 Низ ряда 01.09 (клиент, голосовое 15:28): «синяя рамка… она заходит на бегунок,
     на этот ползунок». Замер на 360×640 показал ровно это: кольцо активного свотча
     (`box-shadow` 4.5 px) доходило до 35.5 при высоте блока 36 px, то есть 0.5 px до края,
     а поверх этой же полосы Chromium рисует overlay-бегунок горизонтальной прокрутки
     (`clientHeight` == `offsetHeight` — места под него не резервируется, он именно НАВЕРХУ).
     Поэтому низ разведён явно: 4.5 кольцо + ~7 бегунок + 2.5 просвет = 14 px. Верх и бока
     остаются 5 px — там кольцу мешает только край overflow-контейнера. */
  .colorpick { width: 100%; max-width: 640px; margin-top: 16px; }
  .colorpick .color-palette {
    display: flex; flex-wrap: nowrap; overflow-x: auto;
    justify-content: flex-start;
    padding: 5px 5px 14px;
    scroll-snap-type: x proximity;
    scrollbar-width: thin;
    scrollbar-color: var(--line-strong) transparent;
    -webkit-overflow-scrolling: touch; overscroll-behavior-x: contain;
  }
  .colorpick .pcolor { flex: 0 0 auto; }
  .modelpick { margin-top: 12px; }
  /* Крестик выхода — position:fixed в правом верхнем углу ОКНА (44px + отступ 10px, низ на
     y = 54). Ряд плашки стоит от верха `.views`, а это y = 35, поэтому правый pill попадал
     ровно под крестик: замер 28.08 на 375px и 640px дал перекрытие 42×19 и 13 px.
     ⚫ Прежнее лечение — `margin-right: 54px` у правой колонки — держало кнопку в 54 px
     от края и съедало ей ширину: колонка `1fr` на 360 px оставляла под текст 41 px,
     и «в карточку» вставало в ТРИ строки (замер 01.09: pill 90.9×68). Клиент увидел ровно
     это на скриншоте 15:05, а голосовым 15:28 попросил обратное: «перейти в карточку так же
     нужно приклеить к правому верхнему углу».
     🔴 Поэтому зазор снят и разведены не по горизонтали, а по ВЕРТИКАЛИ: весь ряд опущен
     на 20 px, ниже крестика (54 - 35 = 19, берём 20). Кнопка встаёт вплотную к правому краю
     картинки — в тот самый угол, — и в крестик больше не попадает ни пикселем.
     ⚠️ 20 px привязано к геометрии крестика (`_installExitButton`: top 10 + 44) и к тому,
     что `.views` начинается на 35 px от верха окна на ЛЮБОЙ узкой ширине: отступы `#app`
     и `#stage` там константы. Меняете любое из трёх — перемеряйте на 320/360/414. */
  /* Зазор между пилюлями 8 -> 6: `1fr auto 1fr` отдаёт правой колонке ровно
     `(ряд - зазоры - средняя) / 2`, и на 360 px это давало 103.05 при нужных 105 —
     кнопка срывалась во вторую строку из-за 1.9 px. Шесть вместо восьми дают 104.05,
     а вместе с padding 9 -> 8 (пилюли ужимаются на 2 px каждая) запас становится 1 px
     с плюсом. Числа проверены замером на 320/360/375/414, не подобраны на глаз. */
  /* 🔴 01.09, вторая жалоба клиента: «кнопки сверху гульнули». `top: 20px` (ниже) опускал
     ряд на 55..91 px, а форма после среза белой полосы начинается на 57.5 px (замер 360 px:
     полоса 60 кадровых × 0.373 = 22.4 экранных) — то есть пилюли садились ровно на плечи
     и ворот. Возвращаем ряд к верхней кромке картинки, а разводим с крестиком не ряд,
     а САМ крестик: он уменьшен и поднят правилом ниже (32 px, 1..33), ряд идёт с 35 px.
     ⚠️ Полностью убрать нахлёст, оставив ряд ВНУТРИ картинки, нельзя: полоса 22.4 px,
     ряд 36 px. Вынести ряд отдельной строкой над картинкой — значит опустить форму
     примерно на 45 px и вернуть почти всё, что дал срез полосы (58 px), а срез клиент
     просил сам. Оставшийся нахлёст — только нижняя кромка ряда над воротом. */
  .line-badge { padding-right: 0; top: 0; gap: 6px; }
  .line-badge-cta { margin-right: 0; }
  /* ⚫ Мобильные 32 px крестика удалены 02.09 вместе с кнопкой. */
  #price-box { position: static; }
  .topbar { position: static; padding-top: max(15px, env(safe-area-inset-top)); }
  /* Ряд кнопок в панели тянется на всю ширину — удобнее пальцем */
  .row { gap: 10px; }
  .row button:not(.swatch):not(.color-sw):not(.seg-btn) { flex: 1 1 auto; min-height: 46px; }
}
@media (max-width: 560px) {
  /* Клиент 2026-07-16: превью и весь фильтр — во весь экран без полей, максимально расширены. */
  #app {
    padding-left: max(4px, env(safe-area-inset-left));
    padding-right: max(4px, env(safe-area-inset-right));
  }
  #stage { padding: 18px 4px 16px; }
  /* Холст-обёртка без карточной рамки — картинка тянется до краёв (chrome≈6 в _displayWidth).
     ⚠️ Фон белый, а НЕ transparent: с 02.09 карточка держит постоянную пропорцию, и у линеек
     выше Champion по бокам холста остаются поля. Прозрачный фон показал бы кремовую страницу
     (--bg: #fbf1db) — вместо одной белой рамки клиент увидел бы кремовые полосы по краям. */
  .canvas-wrap { padding: 0; border: 0; border-radius: 10px; background: var(--stage-card); box-shadow: none; }
  .canvas-wrap:hover { transform: none; box-shadow: none; }
  /* 🔴 Отступ под ряд плашки — вторая половина починки жалобы 01.09 «кнопки сверху гульнули».
     Ряд 36 px физически не влезает в белую полосу мокапа: после среза 01.09 она 60 кадровых
     пикселей, а на экране это 19.5 px при 320, 22.4 при 360, 25.5 при 412 — форма начинается
     раньше, чем ряд заканчивается, и пилюли садятся на ворот и плечи (замер до правки:
     нахлёст 16.5 / 13.5 / 10.5 px, видно на скриншотах).
     18 px закрывает худший случай (320) с запасом. Отступ у `.views`, а НЕ у ряда: ряд
     абсолютный, и его containing block — padding-box, поэтому `top: 0` оставляет его на
     месте, а вниз уезжает только картинка.
     ⚠️ Форма опускается на 18 px, но срез полосы дал 58 px — три четверти выигрыша остаются.
     Полностью «бесплатного» решения тут нет: клиент просил и форму выше, и кнопки в углу,
     и кнопки не на форме, а полоса под них одна.

     🔴 18 -> 30 (02.09): «форма приклеилась к кнопкам, отступа от кнопок практически нету,
     надо чуть-чуть отодвинуть». Нахлёста уже не было, но зазор до чернил формы держался
     на 1.1 / 4 / 5 / 6.1 / 7 px (320 / 360 / 375 / 393 / 412, замер с эмуляцией касания) —
     на глаз это и есть «вплотную». Двенадцать пикселей переводят его в 13.1 / 16 / 17 /
     18.1 / 19: видно, но без потери картинки.
     ⚠️ Считать зазор надо на ТАЧ-профиле: под `pointer: coarse` пилюли выше (36 px против
     28.3), и ряд ближе к вороту. Замер в десктопном профиле даёт зазор больше настоящего —
     ровно на этом промахнулся первый замер волны 4.
     ⚠️ Правило живёт в блоке `max-width: 560px`, поэтому высоту холста на ноутбуке оно
     не трогает: критерий приёмки «конструктор в один экран на 1366×768» не задет.

     🔴 30 -> 33 (02.09, волна 5). Одна рамка на все линейки отняла часть этого зазора, и вот
     почему: белая полоса над формой это 60 пикселей КАДРА, а кадры у линеек разной высоты
     (836 у Champion … 937 у New). Когда все кадры вписаны в карточку одной высоты, у высокого
     кадра те же 60 пикселей дают на экране меньше — форма подходит к ряду ближе. Замер после
     правки рамки: 11.7 / 14.5 / 14.6 / 17.6 на 320 / 360 / 375 / 412 против 13.1 / 16 / 17 / 19
     до неё. Замер после правки (мин по восьми линейкам): 14.5 / 17.5 / 17.8 / 20.6 — база
     превышена всюду. ⚠️ 32 px не хватало: на 375 оставалось 16.8 против базовых 17. */
  .views { gap: 12px; padding-top: 33px; }
  .panel > section { padding: 16px; }
  .topbar { padding: 12px 16px; }
  .topbar .logo { font-size: 21px; letter-spacing: 3.5px; }
  #price-total { font-size: 26px; }
  /* Пункт списка/чекбоксы — крупнее для касания */
  /* :not(.opt-upload) — плашка «Загрузить логотип» это <label>, и общее мобильное правило
     сбивало ей padding до 3px, из-за чего она была НИЖЕ кнопки «Удалить фон»
     (клиент 2026-07-27: «удалить фон выше, чем загрузить логотип»). Её отступы держит .opt-upload. */
  .panel label:not(.opt-upload) { padding: 3px 0; min-height: 30px; }
  /* 40 -> 32: клиент 01.09 (голосовое 15:28) «сами квадратики… процентов на 20 уменьшить».
     Ровно −20 %. Парная правка для тач-указателя — в блоке `pointer: coarse` ниже. */
  .pcolor { width: 32px; height: 32px; }
  .color-palette { gap: 11px; }
  /* Карусель моделей — карточки чуть крупнее и заметнее, что скроллятся */
  .model-card { width: 96px; }
  /* Заказ раскрывается как нижняя «шторка» на всю высоту — привычно на телефоне */
  .order-overlay { padding: 0; align-items: flex-end; }
  .order-card {
    max-width: 100%; max-height: 96vh; width: 100%;
    border-radius: var(--r-xl) var(--r-xl) 0 0;
    animation: sheet-up .26s var(--ease);
  }
  .order-foot { padding-bottom: max(16px, env(safe-area-inset-bottom)); }
  /* Клиент 2026-07-16 (мобайл): не давать тексту «Продолжить редактирование»
     переноситься на 2 строки — min-width:max-content держит nowrap, а flex-wrap
     контейнера роняет кнопки в столбик на всю ширину, когда обе не влезают в ряд. */
  .order-foot button { flex: 1 1 auto; min-width: max-content; min-height: 48px; white-space: nowrap; }
}
@keyframes sheet-up {
  from { opacity: 0; transform: translateY(28px); }
  to   { opacity: 1; transform: none; }
}

/* ── Тач-цели ────────────────────────────────────────────────────────
   Привязаны к типу указателя, а не к ширине экрана: планшет шире 560px, но палец
   там такой же. Замер 31.07 на 768px: 20 целей меньше минимума 44px (iOS HIG) —
   свотчи цвета 34×34, «Детализация» 26px, плашка линейки 29px, «Скачать макет» 36px.
   Блок отработан на конструкторе футболок и перенесён сюда без изменений подхода. */
@media (pointer: coarse) {
  /* ⚠️ 44 -> 36 это ОСОЗНАННЫЙ отход от минимума 44 px, а не недосмотр: клиент 01.09
     (голосовое 15:28) «сами квадратики… процентов на 20 уменьшить», 44 × 0.8 = 35.2.
     Именно палитра, и только она: остальные цели блока минимум держат. Промахов не
     прибавится — свотчи стоят в ряд с зазором 11 px, соседняя цель дальше 47 px от центра.
     Возвращать 44 без слова клиента нельзя, он просил обратное. */
  .pcolor { width: 36px; height: 36px; }
  .color-sw { width: 40px; height: 40px; }
  .seg-btn { min-height: 46px; }
  .stage-btn { min-height: 44px; }
  .cta.cta, #order-btn { min-height: 52px; }
  .price-lines-toggle { min-height: 44px; padding: 8px 0 !important; }
  .extra-toggle { min-height: 48px; }
  /* Кликабельна теперь только .line-badge-cta (2026-08-28), но тач-цель держим у обоих pill'ов:
     высота строки задаётся ими, и ярлык не должен быть ниже кнопки.
     ⚠️ 44/12/14 -> 36/7/9 — это НЕ откат тач-цели по невнимательности. Клиент 31.08 (11:11)
     просил «все эти кнопочки уменьшить, процентов на 20», и правку тогда получил только ПК
     (`.line-badge-pill` padding 5/11, кегль 10.5): здесь она перебивалась обратно на 12/14.
     На телефоне это выходило боком дважды — пилюли закрывали плечи формы, а три штуки
     в одну строку не помещались (замер 01.09 на 360 px: сумма nowrap 330.4 + зазоры 16 = 346
     против 336 доступных, поэтому переносило). 36 px тач-цели остаётся рабочей и совпадает
     с размером свотчей палитры, который клиент тем же голосовым назначил сам. */
  .line-badge { min-height: 36px; }
  .line-badge-pill { min-height: 36px; padding: 7px 8px; }
  /* 🔴 Клиент 01.09 обвёл стрелки раскрытия ВТОРОЙ раз: «эти кнопки в телефоне не
     увеличились». И это правда: правка 31.08 подняла кегль 12 -> 16 px в БАЗОВОМ правиле,
     мобильного переопределения не завела вообще, поэтому телефон получил ровно то же, что
     и ПК (замер 01.09: `.opt-chev` = 16 px на обеих ширинах, бокс 12.9 × 24.8). На экране
     в 360 px это читается как «не изменилось».
     22 px = 16 × 1.375; бокс становится ~17.7 px и попадает в 44-пиксельную тач-цель
     `.opt-head`, который и ловит нажатие (стрелка сама по себе не кликабельна).
     ⚠️ Три стрелки правим ВМЕСТЕ, иначе разъедутся — оговорка из базового правила в силе.
     ⚠️ У сестёр селектор `.extra-toggle .chev` — специфичность (0,2,0), одним `.chev`
     их не перебить: медиазапрос специфичность НЕ повышает (урок волны 01.09). */
  .opt-chev { font-size: 22px; }
  .extra-toggle .chev, .price-lines-toggle .chev { font-size: 22px; }
  .opt-head { min-height: 56px; }
  .opt-in { min-height: 46px; }
  .opt-upload, .opt-rmbg { min-height: 50px; }
  .font-opt { min-height: 48px; }
  .qty-stepper button { min-height: 44px; }
  .order-close { width: 44px; height: 44px; }
  .order-foot button { min-height: 48px; }
  .model-card { min-height: 44px; }
  /* Крестик удаления опции лежит на карточке: визуально его раздувать нельзя,
     поэтому растим невидимую зону нажатия. */
  /* position:relative обязателен: без него невидимая зона привяжется к чужому предку. */
  .opt-del { width: 30px; height: 30px; position: relative; }
  .opt-del::before { content: ''; position: absolute; inset: -7px; border-radius: 50%; }
  /* ⚫ Тач-цель крестика выхода жила здесь до 02.09 и удалена вместе с кнопкой.
     Урок правила остаётся в силе для всего блока: `pointer: coarse` идёт ПОСЛЕ
     `max-width: 900px`, специфичность у них одинаковая, и решает порядок в файле. */
}

/* ── Совсем узкие экраны (SE первого поколения, сложенный Fold) ──────
   ⚠️ Стоит ПОСЛЕ блока `pointer: coarse` намеренно. Медиазапрос не повышает специфичность:
   `.line-badge-pill` там и здесь одинаковые (0,1,0), и решает порядок в файле. Внутри
   `max-width: 900px` это правило молча проигрывало (замер 01.09: padding оставался 8 px).

   ⚠️ Считать надо НЕ сумму трёх пилюль: в сетке `1fr auto 1fr` правая колонка всегда равна
   ЛЕВОЙ, то есть `(ряд - зазоры - середина) / 2`, и лишняя ширина уходит короткому ярлыку
   линейки впустую. На 320 px это давало кнопке «в карточку» 90.5 при нужных 94.9 — вторая
   строка. Кегль 10.5 -> 9.5 (×0.905) и боковой padding 8 -> 6 дают колонке 92.5 против
   нужных 90.9. Порог 340, а не 360: на 360 колонка и так 106.05 при нужных 103 (замер),
   лишний раз мельчить текст незачем. */
@media (max-width: 340px) {
  .line-badge-pill { font-size: 9.5px; padding: 7px 6px; }
}
