/* ══════════════════════════════════════════════════════════════════════════
   «Крафт-Букет» — основные стили.

   ФАЙЛ СОБИРАЕТСЯ АВТОМАТИЧЕСКИ. Не редактируйте его руками:
   правьте css/components/*.css и запускайте `php tools/build-css.php`.

   Токены дизайн-системы — в css/critical.css, он инлайнится в <head>.
   Собрано: 2026-09-15 15:57
   ══════════════════════════════════════════════════════════════════════════ */

/* ═══ components/ui.css ═══ */

/* ── Компоненты интерфейса: кнопки, значки, крошки, пагинация, уведомления ── */

.btn--icon {
  width: 44px;
  min-height: 44px;
  padding: 0;
  background: transparent;
  color: var(--color-text);
  border-radius: var(--radius-pill);
}
.btn--icon:hover { color: var(--color-accent); background: var(--color-surface); }

.btn--large { min-height: 56px; padding: 0 40px; font-size: var(--fs-lg); }

/* ⚠ Два имени у одной кнопки — не небрежность, а починка.
   Сайт писался с `--small`, а вся панель КрафтОС — с `--sm`:
   55 кнопок в 19 файлах ссылались на класс, которого не существовало,
   и получали базовый размер. На телефоне это 52 px с широкими полями,
   то есть каждая второстепенная кнопка выглядела как главная — панель
   переставала походить на остальной сайт. Найдено владельцем 14.09.2026
   по кнопке «Скопировать» рядом с QR.

   Правим стилем, а не переименованием: половина этих файлов общая
   с соседним чатом, и массовая замена в них затёрла бы чужую работу
   ради косметики. */
.btn--small,
.btn--sm { min-height: 40px; padding: 0 20px; font-size: var(--fs-sm); }

/* .btn--small объявлена в styles.css, а мобильные 52px — в critical.css,
   который подключается раньше. По каскаду выигрывала уменьшенная кнопка,
   и «В корзину» в карточке каталога оказывалась 40px — ниже минимальной
   сенсорной зоны 44×44. На пальце это главная кнопка витрины */
@media (max-width: 900px) {
  .btn--small,
  .btn--sm { min-height: 44px; }
}

.btn[disabled],
.btn.is-disabled {
  background: var(--color-disabled);
  color: var(--color-muted);
  border-color: transparent;
  cursor: not-allowed;
  pointer-events: none;
}

.btn.is-loading { position: relative; color: transparent; pointer-events: none; }
.btn.is-loading::after {
  content: '';
  position: absolute;
  width: 18px; height: 18px;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  color: var(--color-on-accent);
  animation: kb-spin 700ms linear infinite;
}
@keyframes kb-spin { to { transform: rotate(360deg); } }

/* Иконки Lucide. Эмодзи в интерфейсе запрещены: на разных ОС они
   рендерятся по-разному и мгновенно роняют премиальность */
.icon {
  width: 20px; height: 20px;
  stroke: currentColor;
  stroke-width: 1.5;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex-shrink: 0;
}
.icon--sm { width: 16px; height: 16px; }
.icon--lg { width: 24px; height: 24px; }
.icon--xl { width: 32px; height: 32px; }

/* ── Статус наличия ────────────────────────────────────────────────────────
   Точка и слово одновременно. Цвет не может быть единственным носителем
   смысла — требование доступности и прямое правило trust-factors.md
   ───────────────────────────────────────────────────────────────────────── */

.stock {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 5px 12px 5px 10px;
  border-radius: var(--radius-pill);
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--color-muted);
}
.stock__dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--color-muted);
  flex-shrink: 0;
}

.stock--in-stock {
  color: var(--color-success);
  background: color-mix(in srgb, var(--color-success) 10%, transparent);
}
.stock--in-stock .stock__dot { background: var(--color-success); }

/* К1. «Под заказ» — не отказ, а вторая дата доставки. Серый здесь читался
   как «выключено», а по данным Posiflora так помечено больше половины
   каталога: витрина выглядела нерабочей при продающем тексте.

   Текст взят на тон темнее патча (--color-accent-hover вместо --color-accent):
   на подложке 28% accent-light исходное значение даёт 3.89:1 на кремовом фоне
   и 4.12:1 на белой карточке — ниже нормы 4.5:1, которую требует сам чек-лист
   приёмки. С accent-hover выходит 5.01–6.45:1 во всех четырёх сочетаниях
   тем и подложек. Токен существующий, золото сохраняется */
.stock--preorder {
  color: var(--color-accent-hover);
  /* Р2. Было 28%, тогда как у in-stock подложка 10%: недоступные позиции
     выделялись сильнее доступных, в тёмной теме перекос заметнее. Цель К1
     («под заказ — не отказ, а вторая дата») держится и на 10%: носителем
     остаются золотой текст и золотая точка */
  background: color-mix(in srgb, var(--color-accent-light) 10%, transparent);
}
.stock--preorder .stock__dot { background: var(--color-accent-deco); }

/* Букет, который собирают под заказ из сегодняшнего наличия. Отдельный
   статус, а не «под заказ»: срок здесь не при чём, товар делается сегодня.
   Цвет успеха был бы обманом (наличие мы не считаем), золото «под заказа»
   тоже: это не отложенная доставка. Нейтральный текст на приглушённой
   подложке — статус читается как пояснение, а не как светофор. */
.stock--assembled {
  color: var(--color-text-soft);
  background: color-mix(in srgb, var(--color-muted) 8%, transparent);
}
.stock--assembled .stock__dot { background: var(--color-text-soft); }

/* ── Значки ───────────────────────────────────────────────────────────────
   Зачёркнутых цен, «−50%» и «горящих» плашек в системе нет намеренно:
   если скидка всегда, это не скидка, а ценник
   ───────────────────────────────────────────────────────────────────────── */

.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 12px;
  border-radius: var(--radius-pill);
  background: var(--color-surface);
  color: var(--color-text-soft);
  font-size: var(--fs-xs);
  letter-spacing: 0.02em;
}
.badge--accent {
  background: color-mix(in srgb, var(--color-accent-light) 25%, transparent);
  color: var(--color-accent);
}

.tag {
  display: inline-flex;
  align-items: center;
  min-height: 40px;
  padding: 0 18px;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--color-text);
  font-size: var(--fs-sm);
  cursor: pointer;
  transition: all var(--transition-fast) ease-out;
}
.tag:hover { border-color: var(--color-accent); color: var(--color-accent); }
.tag.is-active {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: var(--color-on-accent);
}

/* ── Сообщения ─────────────────────────────────────────────────────────── */

.alert {
  display: flex;
  gap: 12px;
  padding: 16px 20px;
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border-strong);
  background: var(--color-surface);
  font-size: var(--fs-sm);
  margin-bottom: 24px;
}
.alert--error   { border-color: var(--color-error);   color: var(--color-error); }
.alert--success { border-color: var(--color-success); color: var(--color-success); }
.alert--warning { border-color: var(--color-warning); color: var(--color-warning); }

/* ── Хлебные крошки ────────────────────────────────────────────────────── */

.breadcrumbs { padding: 20px 0 0; }
.breadcrumbs__list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  list-style: none;
  margin: 0; padding: 0;
  font-size: var(--fs-sm);
  color: var(--color-muted);
}
.breadcrumbs__item + .breadcrumbs__item::before {
  content: '·';
  margin-right: 8px;
  color: var(--color-muted);
}
.breadcrumbs__item a { color: var(--color-muted); }
.breadcrumbs__item a:hover { color: var(--color-accent); }

/* О3. Третья крошка на карточке товара — полное название букета: на 390
   она занимала 97px в три строки и дословно дублировала <h1> под ней */
@media (max-width: 900px) {
  .breadcrumbs__list { flex-wrap: nowrap; }
  .breadcrumbs__item:last-child {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
}

/* ── Пагинация ─────────────────────────────────────────────────────────── */

.pagination {
  display: flex;
  justify-content: center;
  gap: 8px;
  margin-top: 56px;
  flex-wrap: wrap;
}
.pagination__item {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  height: 44px;
  padding: 0 12px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  color: var(--color-text);
  font-size: var(--fs-sm);
}
.pagination__item:hover { border-color: var(--color-accent); color: var(--color-accent); }
.pagination__item.is-active {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: var(--color-on-accent);
}

/* ── Пустое состояние ──────────────────────────────────────────────────── */

.empty-state {
  text-align: center;
  padding: 72px 24px;
  color: var(--color-text-soft);
  max-width: 480px;
  margin: 0 auto;
}
.empty-state__title { margin-bottom: 12px; }
.empty-state__text { margin-bottom: 24px; }

/* ── Появление секций при скролле ──────────────────────────────────────── */

.reveal {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity var(--transition-slow) var(--ease-in),
              transform var(--transition-slow) var(--ease-in);
}
.reveal.is-visible { opacity: 1; transform: none; }

/* Без JS содержимое обязано быть видимым */
.no-js .reveal { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; }
}

/* Метка «не звонить» в списке заказов. Цвет предупреждения, а не ошибки:
   это просьба клиента, а не сбой. */
.no-calls-mark {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: var(--fs-xs);
  color: var(--color-warning, #A8611B);
  white-space: nowrap;
}
.no-calls-mark svg { flex-shrink: 0; }

/* ═══ components/forms.css ═══ */

/* ── Формы ────────────────────────────────────────────────────────────────
   Поля строго 16px: меньший размер вызывает автозум в iOS Safari
   и ломает вёрстку чекаута — ключевого экрана конверсии.
   ───────────────────────────────────────────────────────────────────────── */

/* ⚠ display обязателен, хотя выглядит лишним. Почти везде `.field` —
   это <label>, то есть строчный элемент, а у строчного вертикальные
   отступы не работают вовсе: заданные 20px молча ничего не делали.
   На сайте и в кабинете это не было заметно — там формы выложены flex
   и grid, а дети такого контейнера блокифицируются сами. Но в обычном
   потоке отступа не было: на «Складе» плашки родов налезали на поле
   поиска (−2 px вместо 20), что владелец и увидел 15.09.2026. */
.field { display: block; margin-bottom: 20px; }

.field__label {
  display: block;
  font-size: var(--fs-sm);
  color: var(--color-text-soft);
  margin-bottom: 8px;
  font-weight: 500;
}
.field__label .required { color: var(--color-error); }

.field__hint {
  display: block;
  font-size: var(--fs-sm);
  color: var(--color-muted);
  margin-top: 6px;
}

.input,
.textarea,
.select {
  width: 100%;
  min-height: 52px;
  padding: 14px 16px;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-md);
  background: var(--color-surface-raised);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.4;
  transition: border-color var(--transition-fast) ease-out;
  -webkit-appearance: none;
  appearance: none;
}

.input::placeholder,
.textarea::placeholder { color: var(--color-muted); opacity: 1; }

.input:hover, .textarea:hover, .select:hover { border-color: var(--color-muted); }

.input:focus-visible,
.textarea:focus-visible,
.select:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
  border-color: var(--color-accent);
}

.textarea { min-height: 120px; resize: vertical; }

.select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='%236E6355' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 16px center;
  padding-right: 48px;
}

/* Ошибка поля — всегда со словами, никогда только цветом */
.field.has-error .input,
.field.has-error .textarea,
.field.has-error .select { border-color: var(--color-error); }

.field__error {
  display: block;
  font-size: var(--fs-sm);
  color: var(--color-error);
  margin-top: 6px;
}

.field-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 0 20px;
}

/* К10. Поле промокода — в узком сайдбаре корзины, а не в широкой форме:
   .field-row тут разъезжается в две колонки только от 440px. Инпут растёт,
   кнопка держит свою ширину */
.promo__form {
  display: flex;
  gap: 8px;
}
.promo__form .input { flex: 1; min-width: 0; }
.promo__form .btn { flex-shrink: 0; }

/* ── Чек-бокс и радио ─────────────────────────────────────────────────────
   Чек-бокс согласия на ПДн обязателен на всех формах и НЕ предотмечен:
   предотмеченное согласие согласием не является
   ───────────────────────────────────────────────────────────────────────── */

.checkbox,
.radio {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  cursor: pointer;
  font-size: var(--fs-sm);
  color: var(--color-text-soft);
  line-height: 1.5;
  padding: 6px 0;          /* добираем сенсорную зону до 44px по высоте */
  min-height: 44px;
}

.checkbox input,
.radio input {
  position: absolute;
  opacity: 0;
  width: 22px; height: 22px;
  margin: 0;
  cursor: pointer;
}

.checkbox__box,
.radio__box {
  width: 22px; height: 22px;
  flex-shrink: 0;
  border: 1px solid var(--color-border-strong);
  background: var(--color-surface-raised);
  border-radius: 6px;
  position: relative;
  transition: all var(--transition-fast) ease-out;
  margin-top: 1px;
}
.radio__box { border-radius: 50%; }

.checkbox input:checked ~ .checkbox__box,
.radio input:checked ~ .radio__box {
  background: var(--color-accent);
  border-color: var(--color-accent);
}

.checkbox input:checked ~ .checkbox__box::after {
  content: '';
  position: absolute;
  left: 7px; top: 3px;
  width: 6px; height: 11px;
  border: solid var(--color-on-accent);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

.radio input:checked ~ .radio__box::after {
  content: '';
  position: absolute;
  inset: 5px;
  border-radius: 50%;
  background: var(--color-on-accent);
}

.checkbox input:focus-visible ~ .checkbox__box,
.radio input:focus-visible ~ .radio__box {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

.checkbox__text a, .radio__text a { text-decoration: underline; }

.field.has-error .checkbox__box { border-color: var(--color-error); }

/* ── Сегмент-контрол: «Курьером / Самовывоз» ──────────────────────────── */

.segmented {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 8px;
  padding: 6px;
  background: var(--color-surface);
  border-radius: var(--radius-pill);
}

/* Горизонтальная прокрутка на узких экранах.
   grid-auto-columns: 1fr даёт трекам min-width: auto, то есть пол по
   min-content, а .segmented__label держит padding 0 16px и не переносит
   слова: три варианта «Курьером / Экспресс / Самовывоз» давали
   min-content 340px при доступных на 360px экране 312px, и переполнение
   уходило на весь документ. Сжимаем padding и разрешаем трекам
   ужиматься — сенсорная зона (min-height 48px) не затрагивается */
@media (max-width: 480px) {
  .segmented { gap: 4px; padding: 4px; }
  .segmented__option { min-width: 0; }
  .segmented__label { padding: 0 8px; text-align: center; }
}

.segmented__option { position: relative; }
.segmented__option input {
  position: absolute;
  opacity: 0;
  inset: 0;
  width: 100%; height: 100%;
  margin: 0;
  cursor: pointer;
}
.segmented__label {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding: 0 16px;
  border-radius: var(--radius-pill);
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--color-text-soft);
  cursor: pointer;
  text-align: center;
  transition: all var(--transition-fast) ease-out;
}
/* Д1. Состояние держалось на surface-raised поверх surface плюс тень:
   в тёмной теме разница фонов ~8%, тень на чёрном не видна вовсе, и
   «Курьером / Самовывоз» читалось как два неактивных сегмента.
   Носитель состояния берём тот же, что уже работает в .option-card */
.segmented__option input:checked ~ .segmented__label {
  background: var(--color-surface-raised);
  color: var(--color-text);
  box-shadow: inset 0 0 0 1px var(--color-accent), var(--shadow-sm);
}
.segmented__option input:focus-visible ~ .segmented__label {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

/* ── Карточки-варианты (способ доставки, вариант букета) ──────────────── */

.option-card { position: relative; }
.option-card input {
  position: absolute;
  opacity: 0;
  inset: 0;
  width: 100%; height: 100%;
  margin: 0;
  cursor: pointer;
}
.option-card__body {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  min-height: 64px;
  padding: 14px 20px;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-md);
  background: var(--color-surface-raised);
  cursor: pointer;
  transition: border-color var(--transition-fast) ease-out;
}
.option-card input:checked ~ .option-card__body {
  border-color: var(--color-accent);
  box-shadow: inset 0 0 0 1px var(--color-accent);
}
.option-card input:focus-visible ~ .option-card__body {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}
/* Ч9. Оба span были инлайновыми и склеивались в одну фразу:
   «9 роз под ленту В наличии», «Картой онлайн МИР, T-Pay — на защищённой
   странице банка». Это все варианты букета и все способы оплаты */
.option-card__title { font-weight: 500; font-size: var(--fs-base); display: block; }
.option-card__hint  { font-size: var(--fs-sm); color: var(--color-muted); display: block; }
.option-card__price { font-weight: 600; white-space: nowrap; }

/* ── Форма заявки ──────────────────────────────────────────────────────── */

.form-block {
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: 40px;
}
.form-block__title { margin-bottom: 8px; }
.form-block__lead { color: var(--color-text-soft); margin-bottom: 32px; }

@media (max-width: 768px) {
  .form-block { padding: 24px; }
}

/* Приманка для ботов: настоящий человек этого поля не видит и не заполнит */
.honeypot {
  position: absolute !important;
  left: -9999px !important;
  opacity: 0 !important;
  pointer-events: none;
}

/* Подсказка под формой заявки: способы написать флористу напрямую.
   Часть посетителей форму не заполняет принципиально — для них ссылка
   в мессенджер важнее самой формы. */
.form-block__note {
  margin: 16px 0 0;
  font-size: var(--fs-sm);
  color: var(--color-text-soft);
  text-align: center;
}

/* ── Инвентаризация ───────────────────────────────────────────────────────
   Страница для пересчёта склада: её открывают с телефона, стоя у стеллажа,
   часто одной рукой. Отсюда крупные поля, крупный шрифт и минимум
   украшений — считать неудобно, когда интерфейс мешает.
   ───────────────────────────────────────────────────────────────────────── */

/* Горизонтальные отступы задаются здесь, а не наследуются от .container:
   короткая запись `padding: 24px 0` их обнуляла, и на телефоне текст
   лип к самому краю экрана */
.inv { padding: 24px 16px 80px; max-width: 640px; }

.inv__title { font-family: var(--font-heading); font-size: var(--fs-h2); margin: 0; }
.inv__lead { color: var(--color-text-soft); margin: 12px 0 0; }

.inv__progress {
  margin-top: 16px;
  font-size: var(--fs-sm);
  color: var(--color-muted);
}
.inv__status { color: var(--color-success); }
.inv__status.is-bad { color: var(--color-error); }

.inv__group { margin-top: 32px; }
.inv__group-title {
  display: flex;
  align-items: baseline;
  gap: 10px;
  font-family: var(--font-heading);
  font-size: var(--fs-h3);
  margin: 0 0 12px;
  position: sticky;
  top: 0;
  background: var(--color-bg);
  padding: 8px 0;
  z-index: 2;
}
.inv__group-count { font-size: var(--fs-sm); color: var(--color-muted); font-family: var(--font-body); }

.inv__hint { font-size: var(--fs-sm); color: var(--color-muted); margin-bottom: 12px; }

.inv__row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 0;
  border-bottom: 1px solid var(--color-border);
}
.inv__row.is-done { opacity: .55; }

.inv__name { flex: 1; font-size: var(--fs-base); line-height: 1.35; }
.inv__unit { color: var(--color-muted); font-size: var(--fs-sm); }

/* 16px обязательны: при меньшем размере iOS зумит страницу на фокусе
   и сбивает прицел — считающий теряет строку */
.inv__input {
  width: 92px;
  flex: none;
  padding: 12px;
  font-size: 17px;
  text-align: center;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-md);
  background: var(--color-surface-raised);
  color: var(--color-text);
}
.inv__input:focus { outline: 2px solid var(--color-accent); outline-offset: 1px; }

.inv__name-input {
  flex: 1;
  padding: 12px;
  font-size: 16px;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-md);
  background: var(--color-surface-raised);
  color: var(--color-text);
}

.inv__row--custom { border-bottom: 0; margin-bottom: 8px; }

.inv__done { margin-top: 40px; }

/* Заметка по позиции. Свёрнута по умолчанию: 179 открытых полей превращают
   страницу в простыню, по которой невозможно пролистать до нужной строки. */
.inv__item { border-bottom: 1px solid var(--color-border); padding: 4px 0 8px; }
.inv__item.is-done { opacity: .55; }
.inv__item .inv__row { border-bottom: 0; }

.inv__note-toggle {
  background: none;
  border: 0;
  padding: 2px 0 4px;
  font-size: var(--fs-xs);
  color: var(--color-accent);
  cursor: pointer;
}

.inv__note {
  width: 100%;
  padding: 10px 12px;
  margin-bottom: 6px;
  font-size: 16px;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-md);
  background: var(--color-surface-raised);
  color: var(--color-text);
}
.inv__note[hidden] { display: none; }

/* ── Правки под вечерний пересчёт с телефона ─────────────────────────────
   Считают стоя, одной рукой, 179 позиций подряд. Всё, что не помогает
   считать, с этой страницы убрано: нижняя панель увела бы в каталог
   одним промахом, футер добавляет два экрана прокрутки в конце.
   ───────────────────────────────────────────────────────────────────── */

.page-inventory .bottom-bar,
.page-inventory .site-footer,
.page-inventory footer { display: none !important; }

/* Строка ужата: было ~215 px на позицию, стало ~96. На 179 позициях
   это разница между двадцатью экранами прокрутки и девятью */
.inv__item { padding: 2px 0 4px; }
.inv__row { padding: 6px 0; gap: 10px; }
.inv__name { font-size: var(--fs-base); }
.inv__name::first-letter { text-transform: uppercase; }
.inv__note-toggle { padding: 0 0 2px; font-size: 11px; }
.inv__input { width: 84px; padding: 10px; }

/* Липкая строка состояния: видно, сколько посчитано и сохранилось ли,
   не возвращаясь наверх. Считающий должен доверять странице */
.inv__bar {
  position: sticky;
  top: 0;
  z-index: 5;
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 -16px 12px;
  padding: 10px 16px;
  background: var(--color-bg);
  border-bottom: 1px solid var(--color-border);
  font-size: var(--fs-sm);
  color: var(--color-muted);
}
.inv__bar-count { color: var(--color-text); font-variant-numeric: tabular-nums; }
.inv__meter { flex: 1; height: 3px; border-radius: 2px; background: var(--color-border); overflow: hidden; }
.inv__meter i { display: block; height: 100%; width: 0; background: var(--color-accent); transition: width .2s; }

/* Поиск: 114 наименований цветка — найти «Пион Сара» пролистыванием
   дольше, чем посчитать ведро */
.inv__search {
  width: 100%;
  margin-bottom: 14px;
  padding: 12px 14px;
  font-size: 16px;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-md);
  background: var(--color-surface-raised);
  color: var(--color-text);
}
.inv__item[hidden], .inv__group[hidden] { display: none; }

/* Переходы по группам — чтобы вернуться к упаковке, не листая цветы */
.inv__chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 18px; }
.inv__chip {
  padding: 6px 11px;
  font-size: var(--fs-xs);
  color: var(--color-text-soft);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: 999px;
  text-decoration: none;
}
.inv__chip:hover { border-color: var(--color-accent); color: var(--color-accent); }

/* Заголовок группы липнет под строкой состояния, а не под шапкой сайта */
.inv__group-title { top: 42px; }

.inv__group-done { font-size: var(--fs-xs); color: var(--color-muted); font-family: var(--font-body); }

/* Финал: не «закройте страницу», а видимый итог работы */
.inv__done {
  margin-top: 32px;
  padding: 18px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
}

/* Опросник: вопрос, пояснение, поле. Пояснение обязательно — человек
   отвечает точнее, когда понимает, зачем спрашивают. */
.survey__q { padding: 14px 0 18px; border-bottom: 1px solid var(--color-border); }
.survey__label { display: block; font-size: var(--fs-lg); line-height: 1.35; }
.survey__hint { font-size: var(--fs-sm); color: var(--color-muted); margin: 6px 0 10px; }
.survey__q .input, .survey__q .textarea { width: 100%; }

/* ═══ components/cards.css ═══ */

/* ── Карточки ─────────────────────────────────────────────────────────── */

.card {
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  transition: transform var(--transition-fast) ease-out,
              box-shadow var(--transition-fast) ease-out;
}

/* ── Карточка товара ─────────────────────────────────────────────────────
   Соотношение 4:5 зарезервировано жёстко: без этого карточки прыгают при
   догрузке изображений — зафиксированный дефект старого сайта и прямой
   вклад в CLS
   ───────────────────────────────────────────────────────────────────────── */

.product-card {
  display: flex;
  flex-direction: column;
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
  transition: transform var(--transition-fast) ease-out,
              box-shadow var(--transition-fast) ease-out;
}
.product-card:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-lg);
}

.product-card__media {
  position: relative;
  display: block;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  background: var(--color-surface);
}
.product-card__media img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform var(--transition-normal) var(--ease-in);
}
.product-card:hover .product-card__media img { transform: scale(1.03); }

.product-card__body {
  display: flex;
  flex-direction: column;
  flex: 1;
  padding: 20px;
}

/* Р1. К2 разошёлся с Т2: на карточке товара заголовок и цена уравнены
   в кегле и разведены шрифтом и весом, а в сетке было наоборот —
   цена 22px против названия 20px, да ещё название обрезано по двум
   строкам. С реальными названиями из Posiflora витрина читалась
   прайс-листом. Возвращаем тот же принцип: имя ведёт, цена вторая */
.product-card__title {
  font-family: var(--font-heading);
  font-size: var(--fs-h3);
  font-weight: 400;
  line-height: 1.3;
  margin: 0;
  color: var(--color-text);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.product-card__title a { color: inherit; }
.product-card__title a:hover { color: var(--color-accent); }

.product-card__stock { margin: 12px 0 16px; }

/* К2. Подвал отделён линией: раньше цена и кнопка сливались с текстом
   карточки, и глазу не за что было зацепиться */
.product-card__footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: auto;
  padding-top: 16px;
  border-top: 1px solid var(--color-border);
}

/* Цена — честная и заметная, без зачёркиваний.
   К2. 22px вместо 18px: название антиквой и цена гротеском весили
   одинаково, а кнопка золотым пятном перетягивала обе.
   Табличные цифры — чтобы ряд цен в сетке выравнивался по разрядам */
.product-card__price {
  font-size: 1.375rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
  color: var(--color-text);
  white-space: nowrap;
}
.product-card__price-from {
  font-size: var(--fs-sm);
  font-weight: 400;
  color: var(--color-muted);
}

/* К7. Правило-столбик стояло на ≤480, а именно там сетка одноколоночная
   (карточка 342px) — цена и кнопка спокойно умещаются в строку, и вместо
   этого получался столбик из 12 растянутых кнопок вниз по странице.
   Столбик нужен наоборот, в 481–900, где сетка двухколоночная
   и карточка около 220px */
@media (min-width: 481px) and (max-width: 900px) {
  .product-card__footer { flex-direction: column; align-items: stretch; }
  .product-card__footer .btn { width: 100%; }
}


/* Д4. В сетке из 8–12 карточек залитая золотом кнопка складывается в ряд
   полос: в светлой теме тяжелее фотографии, в тёмной (--color-accent
   на почти чёрном) — самое светлое пятно экрана. Золотой primary остаётся
   у главного действия экрана: «Смотреть каталог», «Перейти к оформлению»,
   «Перейти к оплате». Геометрия и сенсорная зона не меняются */
.product-card__footer .btn--primary {
  background: transparent;
  color: var(--color-text);
  border-color: var(--color-border-strong);
}
.product-card__footer .btn--primary:hover {
  background: var(--color-text);
  color: var(--color-bg);
  border-color: var(--color-text);
}

/* ── Карточка направления (свадьбы, мероприятия, корпоратив, подписка) ── */

.service-card {
  display: flex;
  flex-direction: column;
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  transition: transform var(--transition-fast) ease-out,
              box-shadow var(--transition-fast) ease-out;
}
.service-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); }

.service-card__media { aspect-ratio: 16 / 9; overflow: hidden; background: var(--color-surface); }
.service-card__media img { width: 100%; height: 100%; object-fit: cover; }

.service-card__body { padding: 28px; display: flex; flex-direction: column; flex: 1; }
.service-card__title { font-size: var(--fs-h3); margin-bottom: 12px; }
.service-card__text  { color: var(--color-text-soft); margin-bottom: 20px; flex: 1; }
.service-card__price { font-size: var(--fs-sm); color: var(--color-muted); margin-bottom: 12px; }

/* ── Карточка отзыва ───────────────────────────────────────────────────── */

.testimonial {
  display: flex;
  flex-direction: column;
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: 28px;
  height: 100%;
}

.testimonial__stars {
  color: var(--color-accent-deco);
  font-size: var(--fs-sm);
  letter-spacing: 0.1em;
  margin-bottom: 16px;
}

.testimonial__text {
  font-family: var(--font-heading);
  font-size: var(--fs-h4);
  line-height: 1.5;
  color: var(--color-text);
  margin: 0 0 24px;
  flex: 1;
}

.testimonial__author { display: flex; align-items: center; gap: 12px; }
.testimonial__avatar {
  width: 48px; height: 48px;
  border-radius: 50%;
  object-fit: cover;
  background: var(--color-surface);
  flex-shrink: 0;
}
.testimonial__avatar--letter {
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-heading);
  font-size: var(--fs-h4);
  color: var(--color-accent);
  background: var(--color-surface);
}
.testimonial__name { font-size: var(--fs-sm); font-weight: 500; }
.testimonial__date { font-size: var(--fs-xs); color: var(--color-muted); }

.testimonial__photo {
  margin-top: 20px;
  border-radius: var(--radius-md);
  aspect-ratio: 3 / 2;
  object-fit: cover;
  width: 100%;
}

/* ── Карточка кейса (портфолио оформления) ─────────────────────────────── */

.case-card { position: relative; border-radius: var(--radius-lg); overflow: hidden; }
.case-card img { aspect-ratio: 3 / 2; object-fit: cover; width: 100%; }
.case-card__caption {
  position: absolute;
  left: 16px; bottom: 16px;
  background: var(--color-surface-raised);
  padding: 8px 16px;
  border-radius: var(--radius-pill);
  font-size: var(--fs-sm);
}

/* ── Сетки ─────────────────────────────────────────────────────────────── */

/* К2. Шаг сетки уменьшен с 32px до 24px: при той же ширине контейнера
   карточка становится крупнее, а фотография — главным элементом витрины */
.grid-products {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 24px;
}

@media (max-width: 900px) {
  .grid-products { grid-template-columns: repeat(2, 1fr); gap: 16px; }
}
@media (max-width: 480px) {
  .grid-products { grid-template-columns: 1fr; }
}

/* К8. Переключатель размера карточек: 44 товара в одну колонку на телефоне —
   долгий скролл. По умолчанию остаётся крупный вид (текущее поведение),
   компактный — по выбору и запоминается в localStorage */
.grid-products.is-compact {
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 16px;
}
@media (max-width: 900px) {
  .grid-products.is-compact { grid-template-columns: repeat(3, 1fr); gap: 12px; }
}
@media (max-width: 480px) {
  .grid-products.is-compact { grid-template-columns: repeat(2, 1fr); gap: 10px; }
}

.grid-products.is-compact .product-card__body { padding: 12px; }
.grid-products.is-compact .product-card__title { font-size: var(--fs-sm); }
.grid-products.is-compact .product-card__stock { margin: 6px 0 8px; font-size: var(--fs-xs); }
.grid-products.is-compact .product-card__footer { padding-top: 8px; gap: 8px; }
.grid-products.is-compact .product-card__price { font-size: var(--fs-base); }
.grid-products.is-compact .product-card__footer .btn {
  min-height: 32px;
  padding: 0 12px;
  font-size: var(--fs-xs);
}

/* ⚠ Цена и кнопка в строку в узкую карточку не помещаются: при карточке
   159 px содержимое подвала требует 158 px против 133 доступных, и кнопка
   «В корзину» торчала за правый край на 12 px. Столбиком — тем же приёмом,
   что правило К7 применяет к двухколоночной сетке 481–900 */
.grid-products.is-compact .product-card__footer {
  flex-direction: column;
  align-items: stretch;
}
.grid-products.is-compact .product-card__footer .btn { width: 100%; }

/* Плашка наличия — таблетка с боковыми полями 12 px. В узкой карточке
   её текст ложится в три строки, и таблетка вырастает в овал высотой
   74 px — пятая часть карточки под одну подпись. Текст не трогаем,
   он про смысл наличия: поджимаем поля и межстрочный интервал */
.grid-products.is-compact .product-card__stock {
  padding: 4px 8px;
  border-radius: var(--radius-md);
  line-height: 1.3;
}

/* К8-бис (15.09.2026). Крупный вид по умолчанию давал на телефоне 22 экрана
   на 24 букета: карточка 327×626 при полезной высоте 695 px — в экран
   не влезала даже одна целиком, и сравнить два букета было физически нельзя.
   Кнопка компактного вида существовала, но стояла в нижних 43 px первого
   экрана, под панелью вкладок, безымянными иконками: её никто не находил.

   Теперь на телефоне компактный вид — состояние ПО УМОЛЧАНИЮ, а крупный
   включается кнопкой (класс is-large). На планшете и компьютере ничего
   не меняется: там одноколоночной сетки и не было.

   ⚠ Селектор :not(.is-large), а не .is-compact: правило обязано работать
   до того, как отработает JS, иначе первый кадр телефона — одна колонка,
   и каталог дёргается на глазах у покупателя.

   ⚠ И только [data-catalog-grid], а не любой .grid-products. Тот же класс
   носят витрина «Собрано сегодня» на главной и на странице 1 сентября —
   а она на телефоне горизонтальная карусель (js/main.js, initShowcase),
   и две колонки её ломают. Ещё он на «похожих» в карточке товара и в
   результатах поиска: там переключателя нет, и навязать им вид, который
   нечем вернуть, нельзя. Метка есть ровно у двух сеток каталога */
@media (max-width: 480px) {
  .grid-products[data-catalog-grid]:not(.is-large) {
    grid-template-columns: repeat(2, 1fr);
    gap: 10px;
  }
  .grid-products[data-catalog-grid]:not(.is-large) .product-card__body { padding: 12px; }
  .grid-products[data-catalog-grid]:not(.is-large) .product-card__title { font-size: var(--fs-sm); }
  .grid-products[data-catalog-grid]:not(.is-large) .product-card__stock {
    margin: 6px 0 8px;
    font-size: var(--fs-xs);
  }
  .grid-products[data-catalog-grid]:not(.is-large) .product-card__footer { padding-top: 8px; gap: 8px; }
  .grid-products[data-catalog-grid]:not(.is-large) .product-card__price { font-size: var(--fs-base); }
  .grid-products[data-catalog-grid]:not(.is-large) .product-card__footer .btn {
    min-height: 32px;
    padding: 0 12px;
    font-size: var(--fs-xs);
    width: 100%;
  }

  /* То же, что в .is-compact: в строку цена и кнопка не помещаются */
  .grid-products[data-catalog-grid]:not(.is-large) .product-card__footer {
    flex-direction: column;
    align-items: stretch;
  }
  .grid-products[data-catalog-grid]:not(.is-large) .product-card__stock {
    padding: 4px 8px;
    border-radius: var(--radius-md);
    line-height: 1.3;
  }

  /* Выбор «крупно» возвращает ровно то, что было до правки */
  .grid-products[data-catalog-grid].is-large { grid-template-columns: 1fr; gap: 16px; }
}

.grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 24px; }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 32px; }
.grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 32px; }

@media (max-width: 1024px) {
  .grid-4 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 768px) {
  .grid-2, .grid-3, .grid-4 { grid-template-columns: 1fr; gap: 16px; }
}

/* ═══ components/sections.css ═══ */

/* ── Секции главной страницы ───────────────────────────────────────────── */

.section__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 24px;
  margin-bottom: 40px;
  flex-wrap: wrap;
}
.section__head .section__title { margin: 0; }

/* Тонкая охристая линия перед надзаголовком: разделяет смыслы, которые
   иначе читаются одинаковыми светлыми полосами (усиление №3 арт-дирекции) */
.section__eyebrow::before {
  content: '';
  display: inline-block;
  width: 24px;
  height: 1px;
  background: var(--color-accent-deco);
  vertical-align: middle;
  margin-right: 12px;
}

/* ── Экран 2: три факта ───────────────────────────────────────────────────
   На старом сайте здесь четыре нуля («0 букетов собрано») — худшая позиция
   на странице. Заменено тремя проверяемыми фактами
   ───────────────────────────────────────────────────────────────────────── */

.facts {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--color-surface-raised);
}

.fact {
  padding: 40px 32px;
  border-right: 1px solid var(--color-border);
}
.fact:last-child { border-right: 0; }

/* Слот иконки выдан всем трём карточкам (home.php), поэтому ряд больше
   не плывёт: раньше ★★★★★ были только у «5.0» и опускали её значение
   на 35px относительно соседей. Звёзды заменены на линейную иконку —
   эмодзи и типографские символы в интерфейсе запрещены art-direction.md */
/* Иконка стоит в одну строку со значением, а не над ним: отдельной
   строкой она добавляла карточке 30px высоты, и блок из трёх карточек
   становился ещё длиннее — при том, что жалоба была ровно на пустоту */
.fact__head {
  display: flex;
  align-items: center;
  gap: 10px;
}
.fact__icon {
  color: var(--color-accent);
  line-height: 0;
  flex: none;
}
.fact__value {
  font-family: var(--font-heading);
  font-size: var(--fs-h1);
  font-weight: 300;
  line-height: 1;
  color: var(--color-text);
}
.fact__label {
  font-size: var(--fs-sm);
  color: var(--color-muted);
  margin-top: 12px;
}

@media (max-width: 900px) {
  .facts { grid-template-columns: 1fr; }
  .fact {
    border-right: 0;
    border-bottom: 1px solid var(--color-border);
    /* Было 32px по вертикали при 74px содержимого — больше половины
       карточки занимал воздух, и три подряд читались как пустой блок */
    padding: 20px 24px;
  }
  .fact:last-child { border-bottom: 0; }
  .fact__label { margin-top: 8px; }
  .fact__value { font-size: var(--fs-h2); }
}

/* ── Экран 3: три входа в каталог ────────────────────────────────────────
   Не декоративная навигация, а отражение трёх типов покупателя:
   «букет ДЛЯ…», «букет ИЗ…», «а у вас ЕСТЬ…?»
   ───────────────────────────────────────────────────────────────────────── */

.entries { display: grid; grid-template-columns: repeat(3, 1fr); gap: 32px; }

.entry {
  display: flex;
  flex-direction: column;
  padding: 32px;
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  transition: transform var(--transition-fast) ease-out,
              box-shadow var(--transition-fast) ease-out;
}
.entry:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); }

.entry__icon { color: var(--color-accent); margin-bottom: 20px; }
.entry__title { font-size: var(--fs-h3); margin: 0; }
.entry__text  { color: var(--color-text-soft); margin: 12px 0 24px; flex: 1; }
.entry__link {
  font-size: var(--fs-sm);
  text-transform: uppercase;
  letter-spacing: var(--ls-caps);
  color: var(--color-accent);
  font-weight: 500;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
}

@media (max-width: 900px) {
  .entries { grid-template-columns: 1fr; gap: 16px; }
  .entry { padding: 24px; }
}

/* ── Экран 5: забота в деталях ───────────────────────────────────────────
   Без карточек-контейнеров — воздух вместо рамок. Иконки Lucide, не эмодзи
   ───────────────────────────────────────────────────────────────────────── */

.features { display: grid; grid-template-columns: repeat(4, 1fr); gap: 40px; }

.feature__icon { color: var(--color-accent); margin-bottom: 16px; }
.feature__title { font-size: var(--fs-h4); margin: 0 0 8px; }
.feature__text  { color: var(--color-text-soft); font-size: var(--fs-base); margin: 0; }

@media (max-width: 1024px) { .features { grid-template-columns: repeat(2, 1fr); gap: 32px; } }
@media (max-width: 600px)  { .features { grid-template-columns: 1fr; gap: 28px; } }

/* ── Экран 6: направления ──────────────────────────────────────────────── */

.directions { display: grid; grid-template-columns: repeat(2, 1fr); gap: 24px; }
@media (max-width: 768px) { .directions { grid-template-columns: 1fr; } }

/* ── Экран 7: отзывы ─────────────────────────────────────────────────────
   На мобильных — карусель со scroll-snap, край следующей карточки виден:
   это подсказка, что можно листать
   ───────────────────────────────────────────────────────────────────────── */

.reviews-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 32px; }

/* О1. height: 100% плюс flex: 1 на тексте давали 60–80px пустоты над
   автором в коротких отзывах. На мобильных .reviews-grid — карусель,
   там равная высота нужна, поэтому правка только от 901px.

   Одного align-items: start недостаточно: height: 100% на .testimonial
   (cards.css) считается от грид-области, а она и при start равна высоте
   ряда — по замеру все три карточки оставались по 285px. Высоту снимаем
   явно, тогда карточка становится по контенту */
@media (min-width: 901px) {
  .reviews-grid { align-items: start; }
  .reviews-grid .testimonial { height: auto; }
}

@media (max-width: 900px) {
  .reviews-grid {
    display: flex;
    gap: 16px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-padding: 0 24px;
    margin: 0 calc(-1 * var(--gutter));
    padding: 0 var(--gutter) 8px;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .reviews-grid::-webkit-scrollbar { display: none; }
  .reviews-grid > * {
    flex: 0 0 85%;
    scroll-snap-align: start;
  }
}

/* ── Виджет отзывов Яндекс.Карт ─────────────────────────────────────────
   Перенесён со старого сайта, где он был единственным носителем
   реальных отзывов. Там стоял голый iframe без рамки; здесь он получает
   ту же оболочку, что остальные тонированные блоки, — иначе светлый
   виджет в тёмной теме висит белым прямоугольником без края.

   Границу и скругление несёт обёртка, а не сам iframe: содержимое
   виджета чужое, его стили нам не принадлежат, и overflow: hidden —
   единственный способ, которым скругление до него доберётся.

   Высоты 560/480px — со старого сайта: они подобраны под содержимое
   виджета, а не под нашу сетку, и своего токена для них нет.
   ───────────────────────────────────────────────────────────────────── */

.ya-reviews {
  margin-top: 8px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--color-surface);
}

.ya-reviews__frame {
  display: block;
  width: 100%;
  height: 560px;
  border: 0;
}

/* Виджет верстает своё содержимое карточкой фиксированной ширины (~760px)
   и центрирует её на своём сером фоне. На 1440 контейнер сайта — 1152px,
   и справа от карточки оставалось 390px пустой серой плашки внутри нашей
   рамки. Ограничиваем ширину обёртки шириной самого виджета и центрируем:
   рамка садится по содержимому, пустого поля не остаётся.

   760px — ширина карточки виджета, замерено, своего токена под неё нет */
@media (min-width: 760px) {
  .ya-reviews__frame { height: 480px; }
  .ya-reviews { max-width: 760px; margin-left: auto; margin-right: auto; }
}

/* ── Экран 8: о нас и салон ────────────────────────────────────────────── */

/* О2. Текстовый блок короче карты (480px) и центрировался — получал
   по ~75px пустоты сверху и снизу внутри секции, у которой и без того
   120px зазоров. Во всех остальных сетках сайта стоит align-items: start */
.about {
  display: grid;
  grid-template-columns: 45fr 55fr;
  gap: 64px;
  align-items: start;
}
.about__note { color: var(--color-muted); font-size: var(--fs-sm); }
.about__map {
  border: 0;
  width: 100%;
  height: 480px;
  border-radius: var(--radius-lg);
  background: var(--color-surface);
}

/* Выбор салона над картой. Кнопки, а не вкладки-tablist: у tablist
   есть обязательства по управлению стрелками, а здесь два переключателя
   рядом с картой, и aria-pressed описывает состояние честнее */
.karta__taby {
  display: flex;
  gap: 8px;
  margin-bottom: 12px;
  flex-wrap: wrap;
}
.karta__tab {
  font: inherit;
  font-size: var(--fs-sm);
  color: var(--color-text);
  background: transparent;
  border: 1px solid var(--color-border);
  border-radius: 999px;
  padding: 8px 18px;
  cursor: pointer;
}
.karta__tab:hover { border-color: var(--color-accent); }
.karta__tab.is-active {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: #fff;
}
.karta__podpis {
  margin: 12px 0 0;
  color: var(--color-muted);
  font-size: var(--fs-sm);
}

@media (max-width: 900px) {
  .about { grid-template-columns: 1fr; gap: 32px; }
  .about__map { height: 320px; }
}

/* ── Экран 9: финальный CTA ──────────────────────────────────────────────
   Полнокадровый тёмный блок. Оверлей гарантирует контраст текста
   при любом фоновом изображении
   ───────────────────────────────────────────────────────────────────────── */

.cta-final {
  position: relative;
  min-height: 480px;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  background: var(--color-hero-bg);
  color: var(--color-hero-text);
  overflow: hidden;
}
.cta-final__bg {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}
.cta-final::after {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(20, 17, 13, 0.55);
}
.cta-final__inner { position: relative; z-index: 1; padding: 72px 24px; max-width: 720px; }
.cta-final__eyebrow {
  font-size: var(--fs-xs);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--color-accent-light);
  margin-bottom: 16px;
}
.cta-final__title {
  font-size: var(--fs-h1);
  font-weight: 300;
  color: var(--color-hero-text);
  margin: 0 0 16px;
}
.cta-final__text { color: var(--color-hero-soft); margin-bottom: 32px; }
.cta-final__note { margin-top: 20px; font-size: var(--fs-sm); color: var(--color-hero-muted); }
.cta-final__actions { display: flex; gap: 16px; justify-content: center; flex-wrap: wrap; }
.cta-final .btn--secondary {
  color: var(--color-hero-text);
  border-color: var(--color-hero-text);
}
.cta-final .btn--secondary:hover {
  background: var(--color-hero-text);
  color: var(--color-hero-bg);
}

@media (max-width: 900px) {
  .cta-final { min-height: 400px; }
  .cta-final__actions { flex-direction: column; }
  .cta-final__actions .btn { width: 100%; }
}

/* ── Бегущая строка с названиями цветов ──────────────────────────────────
   Удачная деталь старого сайта, сохраняем. Пауза при наведении,
   полная остановка при prefers-reduced-motion
   ───────────────────────────────────────────────────────────────────────── */

/* Г3 (а). Полоса 75px с зазорами около 120px с обеих сторон читалась
   случайным швом, а не переходом «витрина → забота в деталях».
   Половина существующего зазора, новых значений не вводится.

   Часть (б) того же патча — сокращение межсекционного разрыва на всех
   восьми стыках главной — не внедрена: она меняет ритм всей страницы,
   а не исправляет дефект, и решение за арт-дирекцией */
/* Атласная лента. Названия сортов едут не по плашке, а по ленте — той самой,
   которой перевязывают букет: она есть почти на каждом нашем кадре и это
   самый узнаваемый предмет салона после самих цветов.

   Собрана из градиентов, без картинок. Три слоя:
   1) продольные складки — несимметричные световые полосы, от них ткань
      перестаёт быть плоской заливкой;
   2) подвёрнутые края — затемнение сверху и снизу;
   3) блик — широкая мягкая полоса света, медленно идущая поперёк (::after).

   Цвет свой в обеих темах, как у тёмного hero: лента не мебель страницы,
   а предмет, и перекрашивать её вслед за темой так же странно, как менять
   ленту в уже собранном букете. */
.marquee {
  position: relative;
  margin: calc(-1 * var(--section-gap) / 2) 0;
  overflow: hidden;
  border: 0;
  padding: 22px 0;
  background:
    linear-gradient(93deg,
      transparent 0%,
      rgba(255, 255, 255, 0.11) 7%,
      transparent 16%,
      transparent 27%,
      rgba(255, 255, 255, 0.07) 33%,
      transparent 41%,
      transparent 55%,
      rgba(255, 255, 255, 0.12) 62%,
      transparent 71%,
      transparent 84%,
      rgba(255, 255, 255, 0.06) 89%,
      transparent 97%),
    linear-gradient(to bottom,
      rgba(28, 23, 18, 0.18) 0%,
      rgba(28, 23, 18, 0.06) 14%,
      rgba(255, 255, 255, 0.08) 44%,
      rgba(28, 23, 18, 0.08) 82%,
      rgba(28, 23, 18, 0.20) 100%),
    /* Кремовая вуаль поверх золота: уводит ленту на полтона к бежевому,
       чтобы полоса не спорила с акцентной кнопкой. Цвет фона страницы,
       не новый — приглушаем своим же */
    linear-gradient(rgba(250, 246, 239, 0.30), rgba(250, 246, 239, 0.30)),
    linear-gradient(to right,
      var(--color-accent-deco) 0%,
      var(--color-accent-light) 30%,
      var(--color-accent-deco) 58%,
      var(--color-accent-light) 100%);
}

/* Блик идёт медленнее самой строки: сравняй скорости — и свет «прилипнет»
   к тексту, перестав читаться как отражение */
.marquee::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(102deg,
    transparent 38%,
    rgba(255, 255, 255, 0.10) 47%,
    rgba(255, 255, 255, 0.15) 50%,
    rgba(255, 255, 255, 0.10) 53%,
    transparent 62%);
  background-size: 220% 100%;
  animation: kb-satin 11s linear infinite;
}

@keyframes kb-satin {
  from { background-position: 120% 0; }
  to   { background-position: -60% 0; }
}
.marquee__track {
  display: flex;
  gap: 48px;
  width: max-content;
  animation: kb-marquee 40s linear infinite;
}
.marquee:hover .marquee__track { animation-play-state: paused; }
/* Текст лежит НА ленте, поэтому цвет свой, а не из темы. Тёмно-коричневый
   по золоту плюс еле заметный светлый подбой снизу — надпись читается
   вытисненной по ткани, а не наклеенной поверх */
.marquee__item {
  position: relative;
  z-index: 1;
  font-family: var(--font-heading);
  font-size: var(--fs-h4);
  color: #2A1F12;
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.22);
  white-space: nowrap;
}
@keyframes kb-marquee {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}
@media (prefers-reduced-motion: reduce) {
  .marquee__track { animation: none; }
  /* Блик — тоже движение: выключаем вместе со строкой, ткань остаётся */
  .marquee::after { animation: none; background-position: 40% 0; }
}

/* ── Полоса срочности ────────────────────────────────────────────────────
   Срочность только фактическая — та, что действительно есть.
   После 20:00 текст сам переключается на «Доставим завтра с 10:00»
   ───────────────────────────────────────────────────────────────────────── */

.urgency {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 20px;
  background: color-mix(in srgb, var(--color-accent-light) 20%, transparent);
  border: 1px solid var(--color-border);   /* Д2. В тёмной теме подложка теряет контейнер */
  border-radius: var(--radius-md);
  font-size: var(--fs-sm);
  color: var(--color-text);
}
.urgency__icon { color: var(--color-accent); }

/* ── Д3. Тёмная тема: границы блоков ───────────────────────────────────────
   В тёмной теме --color-bg и --color-hero-bg — один и тот же #14110D,
   --color-surface отличается от фона на ~8%, а --shadow-sm построен
   на rgba(28, 23, 18, …), то есть тени тёмным по тёмному не существует.
   Следствие: hero, «три входа», «направления», .cta-final и фон между
   ними сливаются в непрерывное полотно, а чередование .section /
   .section--surface — носитель ритма всей главной — не читается вовсе.

   Носитель делаем структурный: хайрлайн на границе блока, а не более
   светлая заливка. Подъём --color-surface менял бы значение токена,
   что правилами пакета запрещено.

   Оба селектора обязательны: система объявляет тему дважды —
   prefers-color-scheme + :root:not([data-theme="light"]) для системной
   и :root[data-theme="dark"] для переключателя в шапке. Один селектор
   закрыл бы находку только у половины пользователей.

   В светлой теме не меняется ничего: там разница фонов честная.
   ───────────────────────────────────────────────────────────────────────── */

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .section--surface,
  :root:not([data-theme="light"]) .hero,
  :root:not([data-theme="light"]) .cta-final,
  :root:not([data-theme="light"]) .related {
    border-top: 1px solid var(--color-border);
    border-bottom: 1px solid var(--color-border);
  }
  :root:not([data-theme="light"]) .footer { border-top-color: var(--color-border-strong); }

  /* Соседние блоки дали бы 2px вместо 1px: border-collapse к блокам
     не применяется, снимаем дубль явно */
  :root:not([data-theme="light"]) .section--surface + .cta-final,
  :root:not([data-theme="light"]) .section--surface + .section--surface,
  :root:not([data-theme="light"]) .related + .footer { border-top: 0; }

}

:root[data-theme="dark"] .section--surface,
:root[data-theme="dark"] .hero,
:root[data-theme="dark"] .cta-final,
:root[data-theme="dark"] .related {
  border-top: 1px solid var(--color-border);
  border-bottom: 1px solid var(--color-border);
}
:root[data-theme="dark"] .footer { border-top-color: var(--color-border-strong); }

:root[data-theme="dark"] .section--surface + .cta-final,
:root[data-theme="dark"] .section--surface + .section--surface,
:root[data-theme="dark"] .related + .footer { border-top: 0; }

/* ── Сезонный блок под hero ───────────────────────────────────────────────
   Появляется к празднику и исчезает по дате из админки. Тёплая подложка
   вместо кричащего акцента: блок и так стоит первым после hero, кричать
   ему незачем — задача сообщить о поводе, а не перебить главный экран. */
.seasonal {
  padding: 20px 0;
  background: color-mix(in srgb, var(--color-accent-light) 14%, var(--color-surface));
  border-bottom: 1px solid var(--color-border);
}

.seasonal__inner {
  display: flex;
  align-items: center;
  gap: 24px;
  flex-wrap: wrap;
}

.seasonal__body { flex: 1; min-width: 260px; }

.seasonal__title {
  margin: 0;
  font-family: var(--font-heading);
  font-size: var(--fs-h3);
  font-weight: 400;
  line-height: 1.2;
  text-wrap: balance;
}

.seasonal__text {
  margin: 6px 0 0;
  font-size: var(--fs-sm);
  color: var(--color-text-soft);
  max-width: 60ch;
}

.seasonal__cta { flex: none; }

.seasonal__erid {
  flex-basis: 100%;
  margin: 0;
  font-size: var(--fs-xs);
  color: var(--color-muted);
}

@media (max-width: 700px) {
  .seasonal__inner { gap: 16px; }
  .seasonal__cta { width: 100%; }
}

/* ── Первый экран посадочной к 1 сентября ────────────────────────────────
   Фотография во всю секцию, текст поверх. Затемнение — градиентом слева,
   а не сплошной вуалью: справа кадр остаётся живым, слева гарантируется
   контраст под текстом. Кадр наш собственный, из каталога. */
.school-hero {
  position: relative;
  margin-top: calc(-1 * var(--header-height));
  padding-top: var(--header-height);
  background: var(--color-hero-bg);
  color: var(--color-hero-text);
  overflow: hidden;
}

.school-hero__bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 38%;
}

/* Два слоя: горизонтальный держит текст, вертикальный сажает секцию
   на фон страницы, чтобы низ кадра не обрубался жёсткой линией */
.school-hero::after {
  content: '';
  position: absolute;
  inset: 0;
  background:
    linear-gradient(100deg,
      rgba(20, 17, 13, 0.94) 0%,
      rgba(20, 17, 13, 0.86) 38%,
      rgba(20, 17, 13, 0.40) 68%,
      rgba(20, 17, 13, 0.30) 100%),
    linear-gradient(to bottom, rgba(20, 17, 13, 0.30), rgba(20, 17, 13, 0) 30%);
}

.school-hero__inner {
  position: relative;
  z-index: 1;
  min-height: 560px;
  display: flex;
  align-items: center;
}

.school-hero__content { max-width: 620px; padding: 72px 0; }

.school-hero__eyebrow {
  margin: 0 0 16px;
  font-size: var(--fs-xs);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  font-weight: 500;
  color: var(--color-accent-light);
}

.school-hero__title {
  margin: 0 0 20px;
  font-family: var(--font-heading);
  font-size: clamp(2rem, 5vw, 3.25rem);
  font-weight: 400;
  line-height: var(--lh-display);
  letter-spacing: var(--ls-display);
  text-wrap: balance;
}

.school-hero__text {
  margin: 0 0 32px;
  font-size: var(--fs-lg);
  line-height: var(--lh-body);
  color: var(--color-hero-soft);
  max-width: 48ch;
}

.school-hero__actions { display: flex; gap: 16px; flex-wrap: wrap; }

.school-hero .btn--secondary {
  border-color: rgba(250, 246, 239, 0.35);
  color: var(--color-hero-text);
  background: transparent;
}
.school-hero .btn--secondary:hover {
  border-color: var(--color-hero-text);
  background: rgba(250, 246, 239, 0.08);
}

.school-hero__trust {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin: 32px 0 0;
  font-size: var(--fs-sm);
  color: var(--color-hero-muted);
}
.school-hero__stars { color: var(--color-accent-light); letter-spacing: 0.1em; }

@media (max-width: 900px) {
  /* На узком экране горизонтальный градиент бесполезен: текст занимает
     всю ширину. Затемняем сверху вниз и оставляем кадр видимым внизу */
  .school-hero::after {
    background: linear-gradient(to bottom,
      rgba(20, 17, 13, 0.92) 0%,
      rgba(20, 17, 13, 0.86) 55%,
      rgba(20, 17, 13, 0.55) 100%);
  }
  .school-hero__inner { min-height: 480px; }
  .school-hero__content { padding: 56px 0 48px; }
  .school-hero__actions .btn { width: 100%; }
}

/* Блок «почему заявка»: кадр и объяснение рядом. Фотография здесь не
   украшение — она показывает тот самый букет, о котором идёт речь. */
.school-why__grid {
  display: grid;
  grid-template-columns: 5fr 6fr;
  gap: 48px;
  align-items: center;
}

.school-why__media img {
  width: 100%;
  height: auto;
  display: block;
  border-radius: var(--radius-md);
}

.school-why__text p {
  margin: 0 0 16px;
  color: var(--color-text-soft);
  max-width: 60ch;
}
.school-why__text .btn { margin-top: 8px; }
.school-why__text .section__title { margin-bottom: 20px; }

@media (max-width: 860px) {
  .school-why__grid { grid-template-columns: 1fr; gap: 28px; }
}

/* Галерея работ. Кадры сняты на контровом закатном свете на тёмном фоне —
   поэтому карточки без рамок и подложек: любая рамка спорит с этим светом.
   Пропорция 4:5 повторяет вертикальный кадр съёмки, кроп не режет букет. */
.works {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 20px;
}

.works__item { margin: 0; }

.works__frame {
  display: block;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  border-radius: var(--radius-md);
  background: var(--color-surface);
}

.works__frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.works__caption {
  margin-top: 10px;
  font-size: var(--fs-sm);
  color: var(--color-text-soft);
}

@media (max-width: 1000px) {
  .works { grid-template-columns: repeat(3, 1fr); gap: 16px; }
}

@media (max-width: 700px) {
  .works { grid-template-columns: repeat(2, 1fr); gap: 12px; }
  .works__caption { font-size: var(--fs-xs); }
}

/* Раскрывающиеся блоки «если в букете». На обычных <details>, без скриптов:
   страницу открывают с телефона, стоя с букетом в руках, — она обязана
   работать до того, как догрузится хоть один скрипт. */
.faq__item {
  border-bottom: 1px solid var(--color-border);
}
.faq__item:first-of-type { border-top: 1px solid var(--color-border); }

.faq__q {
  cursor: pointer;
  list-style: none;
  padding: 18px 36px 18px 0;
  position: relative;
  font-family: var(--font-heading);
  font-size: var(--fs-h4);
  color: var(--color-text);
}
.faq__q::-webkit-details-marker { display: none; }

/* Плюс, превращающийся в минус: одна фигура вместо иконки и её поворота */
.faq__q::after,
.faq__q::before {
  content: "";
  position: absolute;
  right: 6px;
  top: 50%;
  width: 14px;
  height: 1.5px;
  background: var(--color-accent);
  transition: transform 0.2s ease, opacity 0.2s ease;
}
.faq__q::before { transform: translateY(-50%) rotate(90deg); }
.faq__q::after  { transform: translateY(-50%); }
.faq__item[open] .faq__q::before { transform: translateY(-50%) rotate(0deg); opacity: 0; }

.faq__a {
  padding: 0 0 20px;
  color: var(--color-text-soft);
}
.faq__a p { margin: 0 0 12px; }
.faq__a p:last-child { margin-bottom: 0; }

/* Широкая полоса макро между блоками текста. Страница ухода читается
   с телефона, стоя с букетом в руках, и сплошная простыня текста на ней
   утомляет быстрее обычного. Полоса даёт передышку и заодно показывает
   то, о чём речь, — лепестки вблизи.

   Кадры взяты из съёмки каталога: макро, а не букет целиком. Конкретный
   букет здесь обещал бы то, чего у читателя может не быть. */
.macro-band {
  margin: calc(-1 * var(--section-gap) / 2) 0;
  height: 260px;
  overflow: hidden;
  background: var(--color-surface);
}
.macro-band img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  display: block;
}

@media (max-width: 700px) {
  .macro-band { height: 170px; }
}

/* ═══ components/catalog.css ═══ */

/* ── Каталог ──────────────────────────────────────────────────────────── */

.page-head { padding: 40px 0 48px; }
.page-head__title { margin: 0 0 16px; }
.page-head__lead {
  color: var(--color-text-soft);
  max-width: 60ch;
  font-size: var(--fs-lg);
  margin: 0;
  /* На старом сайте этот текст обрывался на «покажем фото пер…» */
}

/* ── Три входа-переключателя ──────────────────────────────────────────────
   Равноправные переключатели, а не вложенные фильтры: это три разных
   типа покупателя, и ни один не является частным случаем другого
   ───────────────────────────────────────────────────────────────────────── */

.entry-switch {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 8px;
  padding: 6px;
  background: var(--color-surface);
  border-radius: var(--radius-pill);
  margin-bottom: 32px;
}
.entry-switch__item {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 48px;
  padding: 0 20px;
  border-radius: var(--radius-pill);
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--color-text-soft);
  text-align: center;
  transition: all var(--transition-fast) ease-out;
}
.entry-switch__item:hover { color: var(--color-accent); }
/* Д1. В тёмной теме surface-raised на surface даёт ~8% разницы, а тень
   не видна — входы каталога читались как список без выбора */
.entry-switch__item.is-active {
  background: var(--color-surface-raised);
  color: var(--color-text);
  box-shadow: inset 0 0 0 1px var(--color-accent), var(--shadow-sm);
}

@media (max-width: 768px) {
  .entry-switch {
    grid-auto-flow: row;
    grid-auto-columns: auto;
    border-radius: var(--radius-lg);
  }
  .entry-switch__item { border-radius: var(--radius-md); justify-content: flex-start; }
}

/* ── Подкатегории ──────────────────────────────────────────────────────── */

.subcats {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 32px;
}

@media (max-width: 768px) {
  .subcats {
    flex-wrap: nowrap;
    overflow-x: auto;
    margin: 0 calc(-1 * var(--gutter)) 24px;
    padding: 0 var(--gutter) 8px;
    scrollbar-width: none;
  }
  .subcats::-webkit-scrollbar { display: none; }
  .subcats .tag { flex: 0 0 auto; }
}

/* ── Фильтры ───────────────────────────────────────────────────────────── */

/* К3. Сайдбар 260px и зазор 48px оставляли сетке 844px, а minmax(280px, 1fr)
   укладывал в них ровно две колонки: страница, чья работа — сравнение,
   показывала меньше товара, чем витрина главной с тремя колонками.
   240px — ширина сайдбара из .cabinet-layout, --gutter на десктопе 24px:
   1152 − 240 − 24 = 888 = 3 × 280 + 2 × 24, ровно три колонки.

   К4. Плюс отступ от подвала: пагинация лежала на его линии, зазор ноль.
   80px взяты у .cart-layout */
.catalog-layout {
  display: grid;
  grid-template-columns: 240px 1fr;
  gap: var(--gutter);
  align-items: start;
  padding-bottom: 80px;
}

/* К4. Ветка «Готово сейчас»: сетка лежит прямо в контейнере, без .catalog-layout */
.page-catalog .container > .grid-products { margin-bottom: 80px; }

.filters {
  position: sticky;
  top: calc(var(--header-height) + 24px);
  padding: 24px;
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
}
.filters__group { margin-bottom: 28px; }
.filters__group:last-child { margin-bottom: 0; }
.filters__title {
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: var(--ls-caps);
  color: var(--color-muted);
  margin-bottom: 14px;
  font-weight: 500;
}
.filters__list { display: flex; flex-direction: column; gap: 2px; }
.filters__reset { margin-top: 20px; }

.price-range { display: flex; align-items: center; gap: 10px; }
.price-range .input { min-height: 44px; padding: 10px 12px; }
.price-range span { color: var(--color-muted); }

.catalog-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 24px;
  flex-wrap: wrap;
}
.catalog-count { color: var(--color-muted); font-size: var(--fs-sm); }

.view-toggle { display: flex; align-items: center; gap: 4px; }

/* Кнопка подписана словом (15.09.2026). Раньше это были две безымянные
   иконки 36×36, а подпись жила в title — на телефоне его не существует,
   наводить нечем. Ширина теперь по содержимому, высота сенсорной зоны
   та же 36 px */
.view-toggle__btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-width: 36px;
  height: 36px;
  padding: 0 10px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface-raised);
  color: var(--color-muted);
  cursor: pointer;
  transition: color var(--transition-fast) ease-out, border-color var(--transition-fast) ease-out;
}
.view-toggle__label { font-size: var(--fs-sm); line-height: 1; white-space: nowrap; }
.view-toggle__btn:hover { color: var(--color-text); }
.view-toggle__btn.is-active {
  color: var(--color-text);
  border-color: var(--color-border-strong);
  background: var(--color-surface);
}

/* К5. На 390 это был самый тяжёлый элемент каталога: btn--secondary
   во всю ширину с обводкой --color-text при двух фильтрах всего.
   Кнопка перетягивала внимание с товара и с трёх входов в каталог */
.filters-toggle {
  display: none;
  border-color: var(--color-border-strong);
  color: var(--color-text-soft);
}
.filters-toggle:hover {
  background: transparent;
  color: var(--color-accent);
  border-color: var(--color-accent);
}

@media (max-width: 1024px) {
  .catalog-layout { grid-template-columns: 1fr; gap: 24px; }
  .filters-toggle { display: inline-flex; }
  .filters {
    position: static;
    display: none;
  }
  .filters.is-open { display: block; }
}

/* ── Карточка товара ───────────────────────────────────────────────────── */

.product {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 64px;
  padding: 32px 0 80px;
  align-items: start;
}

@media (max-width: 900px) {
  .product { grid-template-columns: 1fr; gap: 32px; padding-bottom: 48px; }
}

/* Галерея 4:5 */
.gallery__main {
  aspect-ratio: 4 / 5;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--color-surface);
}
.gallery__main img { width: 100%; height: 100%; object-fit: cover; }

.gallery__thumbs {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(72px, 1fr));
  gap: 12px;
  margin-top: 12px;
}

/* ⚠ На телефоне сетка миниатюр ложится в две строки и съедает 158 px —
   ровно столько, сколько нужно названию и цене, чтобы попасть в первый
   экран. Пятая миниатюра при этом уходила под липкую панель покупки.
   Лентой с прокруткой они занимают одну строку в 72 px */
@media (max-width: 600px) {
  .gallery__thumbs {
    display: flex;
    gap: 8px;
    overflow-x: auto;
    scroll-snap-type: x proximity;
    padding-bottom: 4px;
    scrollbar-width: none;
  }
  .gallery__thumbs::-webkit-scrollbar { display: none; }
  .gallery__thumb {
    flex: 0 0 64px;
    scroll-snap-align: start;
  }
}
.gallery__thumb {
  aspect-ratio: 1;
  border-radius: var(--radius-sm);
  overflow: hidden;
  border: 1px solid var(--color-border);
  background: var(--color-surface);
  padding: 0;
  cursor: pointer;
}
.gallery__thumb.is-active { border-color: var(--color-accent); }
.gallery__thumb img { width: 100%; height: 100%; object-fit: cover; }

/* ── Т1. Порядок блоков правой колонки ───────────────────────────────────
   Кнопка «В корзину» была шестым элементом колонки: перед ней шли две
   тонированные плашки, и на 1440×800 главное действие уходило за сгиб.
   Порядок меняется через order во флекс-контейнере — разметка и DOM
   остаются нетронутыми.
   ───────────────────────────────────────────────────────────────────────── */

.product > div:last-child { display: flex; flex-direction: column; }

.product__title      { order: 1; }
.product__price-row  { order: 2; }
.product__stock      { order: 3; margin-bottom: 20px; }
.product__variants   { order: 4; margin-bottom: 20px; }
.product__actions    { order: 5; margin: 8px 0 20px; }
.product__urgency    { order: 6; margin-bottom: 16px; }
.product__promise    { order: 7; margin-bottom: 20px; }
.product__block      { order: 8; }

/* Т2. Заголовок 56px против цены 28px: решение принимают по цене,
   а крупнее всего было имя букета. Теперь оба по 40px, вес разводит их */
.product__title {
  font-size: var(--fs-h2);
  font-weight: 400;
  margin: 0 0 12px;
}

.product__price-row {
  display: flex;
  align-items: baseline;
  gap: 16px;
  margin-bottom: 16px;
}
.product__price {
  font-size: var(--fs-h2);
  font-weight: 600;
  font-family: var(--font-body);
  letter-spacing: -0.015em;
  /* Цена меняется при выборе варианта — табличные цифры не дают ей прыгать */
  font-variant-numeric: tabular-nums;
  color: var(--color-text);
}
.product__price-note { font-size: var(--fs-sm); color: var(--color-muted); }

/* Статус на карточке товара крупнее, чем в сетке каталога */
.product__stock .stock { font-size: var(--fs-base); }

.product__variants-title {
  font-size: var(--fs-sm);
  color: var(--color-text-soft);
  margin-bottom: 12px;
  font-weight: 500;
}
.product__variant-list { display: flex; flex-direction: column; gap: 10px; }

.product__actions { display: flex; gap: 12px; flex-wrap: wrap; }
.product__actions .btn { flex: 1; min-width: 180px; }

/* Цена внутри панели действий — только для липкой мобильной версии
   (включается ниже, в медиазапросе ≤900). На компьютере цена стоит
   своей строкой над кнопками, второй раз она там не нужна */
.product__actions-price { display: none; }

.product__block {
  padding: 20px 0;
  border-top: 1px solid var(--color-border);
}
/* Т6. Было 14px/600 над текстом в 16px — заголовок мельче того, что он
   озаглавливает. Берём готовый паттерн микро-заголовка из .filters__title,
   .footer__title и .section__eyebrow */
.product__block-title {
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: var(--ls-caps);
  color: var(--color-muted);
  font-weight: 500;
  margin-bottom: 8px;
}
.product__block-text { color: var(--color-text-soft); margin: 0; }

/* Обещание «фото букета перед отправкой» — на карточке товара,
   не только в общем блоке о заботе */
/* Т5. Срочность и обещание были одинаковыми плашками — одинаковый кегль,
   цвет, подложка и иконка слева: 130px общей серой зоны, ни одна
   не выигрывает. Срочность остаётся плашкой (это временный факт),
   обещание становится блоком в ряду остальных фактов о товаре.
   Иконка остаётся золотой — единственное пятно, она и держит внимание */
.product__promise {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  padding: 16px 0 0;
  border-top: 1px solid var(--color-border);
  font-size: var(--fs-sm);
  color: var(--color-text-soft);
}
.product__promise .icon { color: var(--color-accent); margin-top: 2px; }

/* Т4. Галерея заканчивалась на миниатюрах, а блоки «Состав / О букете /
   Как ухаживать / Доставка» уходили вниз узкой правой колонкой — почти
   вся левая половина ниже миниатюр оставалась пустой. Приём тот же,
   что в .filters и .summary */
@media (min-width: 901px) {
  .product > div:first-child {
    position: sticky;
    top: calc(var(--header-height) + 24px);
  }
}

/* Т3. Липкой была полоса срочности, но после перестановки order (Т1) она
   стоит шестой — на 390 это 1 384px, ниже кнопки «В корзину» (1 240px).
   Липкий элемент не может приклеиться выше своего места в потоке, так что
   обещание «полоса под шапкой» не выполнялось никогда, а у главного
   действия липкости не было вовсе. Меняем роли местами: срочность
   информирует и остаётся в потоке, липким становится действие.

   Заодно вынос в край: --gutter на мобильных 16px, а боковое поле
   контейнера --container-pad = 24px, старый margin не доходил 8px */
@media (max-width: 900px) {
  .product__urgency {
    position: static;
    margin: 0 0 16px;
    border-radius: var(--radius-md);
  }
  /* Спека Т3 предлагала sticky, но sticky с bottom отпускает элемент, как
     только поток догоняет его позицию: при order: 5 из 8 кнопки уезжали
     на 1 899px, хотя колонка описания тянется до 2 972px. Замер на 390:
     видна с 826 до 1541, дальше нет. Механизм тот же, что уже работает
     в Ч1 и Ч5, — fixed плюс отступ на body (см. nav.css) */
  .product__actions {
    position: fixed;
    left: 0;
    right: 0;
    bottom: calc(56px + env(safe-area-inset-bottom));   /* 56px — высота .bottom-bar */
    z-index: 90;
    flex-direction: row;
    gap: 12px;
    margin: 0;
    padding: 12px var(--gutter);
    background: var(--color-bg);
    border-top: 1px solid var(--color-border);
    box-shadow: 0 -4px 16px rgba(28, 23, 18, 0.08);
  }
  .product__actions .btn {
    flex: 1 1 0;
    min-width: 0;
    padding: 0 var(--gutter);
  }

  /* ⚠ Цена показывается только здесь, в липкой панели. Замер на 375×812:
     фото 409 px и две строки миниатюр уводят название на 745-й пиксель,
     цену — на 854-й. На первом экране покупатель видел фото и кнопку
     «В корзину», но ни имени букета, ни суммы */
  .product__actions-price {
    display: block;
    flex: 0 0 auto;
    font-size: 1.125rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    color: var(--color-text);
  }

  /* Трубка без подписи: три полноценных элемента в строку не помещаются.
     ⚠ Селектор с .product__actions обязателен: правило выше раздаёт
     кнопкам flex: 1 1 0 и одним классом его не перебить */
  .product__actions .product__call {
    flex: 0 0 56px;
    width: 56px;
    min-width: 0;
    padding: 0;
  }
  .product__call-text { display: none; }
}

/* ── Похожие товары ───────────────────────────────────────────────────── */

.related { padding: 64px 0; border-top: 1px solid var(--color-border); }

/* ── Готовые букеты ───────────────────────────────────────────────────── */

.ready-note {
  padding: 16px 20px;
  border-left: 2px solid var(--color-accent-deco);
  background: var(--color-surface);
  color: var(--color-text-soft);
  font-size: var(--fs-sm);
  border-radius: 0 var(--radius-md) var(--radius-md) 0;
  margin-bottom: 32px;
}

/* ── Поиск ─────────────────────────────────────────────────────────────── */

.search-form { display: flex; gap: 12px; margin-bottom: 40px; max-width: 560px; }
.search-form .input { flex: 1; }

/* ═══ components/builder.css ═══ */

/* ═══════════════════════════════════════════════════════════════════════════
   «Соберите свой букет» — конструктор из живых остатков.

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

.builder {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;
  gap: 40px;
  align-items: start;
  margin-bottom: 64px;
}

/* ── Палитра ──────────────────────────────────────────────────────────── */

.builder__palette { display: flex; flex-direction: column; gap: 44px; min-width: 0; }

.builder__group { display: flex; flex-direction: column; gap: 16px; }

.builder__group-title {
  display: flex;
  align-items: baseline;
  gap: 10px;
  font-size: var(--fs-h3);
  font-weight: 500;
  margin: 0;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--color-border);
}

.builder__group-count {
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--color-muted);
  font-variant-numeric: tabular-nums;
}

.builder__group-note { color: var(--color-text-soft); font-size: var(--fs-sm); margin: 0; }

.builder__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(158px, 1fr));
  gap: 12px;
}

/* ── Карточка цветка ──────────────────────────────────────────────────── */

.flower {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 18px 12px 12px;
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  text-align: center;
  transition: border-color var(--transition-fast) ease-out,
              box-shadow var(--transition-fast) ease-out;
}

/* Выбранный цветок обязан отличаться не только числом в поле:
   при двадцати карточках взгляд теряет, что уже набрано */
.flower.is-picked {
  border-color: var(--color-accent);
  box-shadow: 0 0 0 1px var(--color-accent);
}

.flower__art {
  color: var(--color-accent);
  height: 64px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 6px;
}
.flower__art img { height: 64px; width: 64px; object-fit: cover; border-radius: 50%; }

.flower__name {
  font-family: var(--font-body);
  font-size: 0.8125rem;
  font-weight: 500;
  line-height: 1.3;
  margin: 0;
  /* Названия сортов длинные («Роза кустовая Экслюзив Сенсейшен») —
     без переноса они рвут сетку */
  overflow-wrap: anywhere;
}

.flower__price {
  font-size: 0.9375rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.flower__stock {
  font-size: 0.75rem;
  color: var(--color-muted);
  font-variant-numeric: tabular-nums;
}

.flower__pick {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-top: 10px;
}

.flower__step {
  width: 34px;
  height: 34px;
  flex: none;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  color: var(--color-text);
  font-size: 1.125rem;
  line-height: 1;
  cursor: pointer;
  transition: border-color var(--transition-fast) ease-out;
}
.flower__step:hover:not(:disabled) { border-color: var(--color-accent); }
.flower__step:disabled { opacity: .4; cursor: not-allowed; }

.flower__qty {
  width: 46px;
  height: 34px;
  text-align: center;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  color: var(--color-text);
  /* 16px — иначе iOS Safari зумит поле при фокусе и ломает вёрстку */
  font-size: 16px;
  font-variant-numeric: tabular-nums;
}
.flower__qty::-webkit-outer-spin-button,
.flower__qty::-webkit-inner-spin-button { appearance: none; margin: 0; }
.flower__qty { appearance: textfield; }

/* ── Упаковка ─────────────────────────────────────────────────────────── */

.builder__pack { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 8px; }

.pack { position: relative; display: block; cursor: pointer; }
.pack input { position: absolute; opacity: 0; width: 0; height: 0; }

.pack__body {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  padding: 13px 16px;
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  transition: border-color var(--transition-fast) ease-out;
}
.pack input:checked + .pack__body {
  border-color: var(--color-accent);
  box-shadow: 0 0 0 1px var(--color-accent);
}
.pack input:focus-visible + .pack__body { outline: 2px solid var(--color-accent); outline-offset: 2px; }

.pack__name  { font-size: var(--fs-sm); }
.pack__price { font-size: var(--fs-sm); font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }

/* ── Сводка ───────────────────────────────────────────────────────────── */

.builder__summary {
  position: sticky;
  top: 88px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 24px;
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
}

.builder__summary-title {
  font-family: var(--font-heading);
  font-size: var(--fs-h3);
  font-weight: 500;
  margin: 0;
}

/* Заголовок-кнопка. На широком экране раскрывать нечего — состав виден
   всегда, поэтому кнопка ведёт себя как обычный заголовок */
.builder__toggle {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 0;
  background: none;
  border: 0;
  color: inherit;
  text-align: left;
  cursor: default;
}
.builder__toggle .icon { display: none; }
.builder__toggle-count { display: none; }

.builder__collapsible { display: flex; flex-direction: column; gap: 14px; }
.builder__foot { display: flex; flex-direction: column; gap: 14px; }

.builder__lines { display: flex; flex-direction: column; gap: 8px; }

.builder__empty { color: var(--color-muted); font-size: var(--fs-sm); margin: 0; }

.builder__line {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  font-size: var(--fs-sm);
}
.builder__line span:first-child { color: var(--color-text-soft); }
.builder__line span:last-child { font-variant-numeric: tabular-nums; white-space: nowrap; }

.builder__total {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding-top: 14px;
  border-top: 1px solid var(--color-border);
}
.builder__total strong {
  font-family: var(--font-heading);
  font-size: var(--fs-h2);
  font-weight: 300;
  font-variant-numeric: tabular-nums;
}

.builder__hint { font-size: var(--fs-sm); color: var(--color-muted); margin: 0; }
.builder__hint.is-blocking { color: var(--color-accent); }

.builder__note { font-size: 0.75rem; color: var(--color-muted); margin: 0; line-height: 1.5; }

/* ── Мобильные ────────────────────────────────────────────────────────── */

@media (max-width: 900px) {
  .builder { grid-template-columns: 1fr; gap: 28px; }
  .builder__grid { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 10px; }

  /* Сводка прижата к низу экрана и свёрнута до полосы: итог, подсказка
     и кнопка. Развёрнутая панель закрывала половину экрана и мешала
     выбирать цветы. Состав раскрывается по нажатию на заголовок */
  .builder__summary {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 56px;                    /* над нижней панелью навигации */
    top: auto;
    z-index: 70;
    gap: 10px;
    padding: 12px 16px calc(12px + env(safe-area-inset-bottom));
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    border-bottom: 0;
    box-shadow: 0 -8px 24px rgb(0 0 0 / 12%);
    max-height: 72vh;
    overflow-y: auto;
  }

  .builder__toggle { cursor: pointer; }
  .builder__toggle .icon {
    display: block;
    margin-left: auto;
    flex: none;
    transform: rotate(90deg);
    transition: transform var(--transition-fast) ease-out;
  }
  .builder__summary.is-open .builder__toggle .icon { transform: rotate(-90deg); }

  .builder__toggle-count {
    display: inline;
    font-size: var(--fs-sm);
    color: var(--color-muted);
    font-variant-numeric: tabular-nums;
  }

  .builder__summary-title { font-size: 1.0625rem; }

  /* Свёрнуто по умолчанию — открывается нажатием */
  .builder__collapsible { display: none; }
  .builder__summary.is-open .builder__collapsible { display: flex; }

  /* Итог поднимаем в строку заголовка: отдельной строкой он добавлял
     полосе 44px, а полоса и так съедала четверть экрана.
     display:contents распускает .builder__foot, чтобы его дети стали
     ячейками сетки самой сводки */
  .builder__summary {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: center;
    column-gap: 12px;
    row-gap: 8px;
  }
  .builder__toggle { grid-column: 1; }
  .builder__foot { display: contents; }

  .builder__total {
    grid-column: 2;
    grid-row: 1;
    padding-top: 0;
    border-top: 0;
    display: block;
  }
  .builder__total span { display: none; }        /* слово «Итого» здесь лишнее */
  .builder__total strong { font-size: 1.5rem; }

  .builder__hint {
    grid-column: 1 / -1;
    font-size: 0.8125rem;
    line-height: 1.35;
  }
  .builder__summary [data-builder-submit] { grid-column: 1 / -1; }
  .builder__collapsible { grid-column: 1 / -1; }

  /* Кнопка в полосе не должна быть ростом с кнопку на странице товара */
  .builder__summary .btn--large { padding: 13px 20px; font-size: var(--fs-base); }

  /* Место под полосу, чтобы она не закрывала последние карточки:
     56 (навигация) + 168 (свёрнутая сводка с запасом) */
  body.page-builder.has-bottom-bar { padding-bottom: 224px; }
}

@media (prefers-reduced-motion: reduce) {
  .builder__toggle .icon { transition: none; }
}

@media (max-width: 400px) {
  .builder__grid { grid-template-columns: repeat(2, 1fr); }
  .flower { padding: 14px 8px 10px; }
}

/* Иллюстрация вместо фотографии в корзине: у собранного букета
   снимка нет, но пустой прямоугольник читается как «картинка не
   загрузилась», а не как «этот букет вы собрали сами» */
.cart-item__art {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 4 / 5;
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  color: var(--color-accent);
}

/* Пояснение к пометке «под заказ» на карточке товара. Мелким и приглушённым:
   это снятие тревоги, а не заявление — оно не должно спорить с ценой
   и кнопкой за внимание */
.product__stock-why {
  margin: 10px 0 0;
  font-size: var(--fs-sm);
  line-height: 1.5;
  color: var(--color-text-soft);
  max-width: 56ch;
}

/* ═══════════════════════════════════════════════════════════════════════════
   Напоминания о важных датах на оформлении заказа.

   Блок предложения, а не шаг формы: без номера, без обязательных полей,
   визуально мягче соседей. Человек пришёл купить букет, а не заполнять
   анкету, — если блок будет выглядеть как требование, он оттолкнёт
   на самом дорогом экране сайта.
   ═══════════════════════════════════════════════════════════════════════════ */

/* Двойной класс-селектор — не стиль, а необходимость: .checkout-step
   в checkout.css задаёт padding: 32px 0 (только сверху/снизу, без
   боковых) и по сборке (tools/build-css.php) идёт ПОСЛЕ builder.css.
   При равной специфичности одного класса побеждает более поздний по
   каскаду — боковой паддинг у этой карточки обнулялся целиком, текст
   и поля упирались прямо в рамку. .checkout-step.checkout-step--offer
   специфичнее любого из них по отдельности и не зависит от того,
   в каком порядке компоненты попадут в общий файл */
.checkout-step.checkout-step--offer {
  /* Ступенью темнее полей внутри (surface, не surface-raised) — иначе
     в тёмной теме карточка и поля совпадают почти один в один, и вместо
     аккуратных полей на карточке видно тонкие обводки на одном фоне.
     Тот же приём, что у .checkout__consent рядом */
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: 24px;
}

.checkout-step__title--plain { display: block; }

.checkout-step__lead {
  color: var(--color-text-soft);
  font-size: var(--fs-sm);
  margin: 0 0 18px;
  max-width: 56ch;
}

.dates { display: flex; flex-direction: column; gap: 10px; }

.dates__row { display: grid; grid-template-columns: minmax(140px, 190px) 1fr; gap: 10px; }

/* 16px обязателен: при меньшем размере iOS Safari зумит поле
   при фокусе и ломает вёрстку оформления */
.dates__date,
.dates__what { font-size: 16px; }

.dates__add {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 12px;
  padding: 8px 0;
  background: none;
  border: 0;
  color: var(--color-accent);
  font-size: var(--fs-sm);
  cursor: pointer;
}
.dates__add:hover { text-decoration: underline; }
.dates__add[hidden] { display: none; }

.dates__consent { margin-top: 20px; }

.dates__note {
  margin: 10px 0 0;
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--color-muted);
  max-width: 60ch;
}

@media (max-width: 560px) {
  .checkout-step.checkout-step--offer { padding: 20px 16px; }
  .dates__row { grid-template-columns: 1fr; }
}

/* ═══ components/checkout.css ═══ */

/* ── Корзина ──────────────────────────────────────────────────────────── */

.cart-layout {
  display: grid;
  grid-template-columns: 1fr 380px;
  gap: 48px;
  align-items: start;
  padding-bottom: 80px;
}

.cart-item {
  display: grid;
  grid-template-columns: 96px 1fr auto;
  gap: 20px;
  padding: 20px 0;
  border-bottom: 1px solid var(--color-border);
  /* Ч3. Выравнивание по верху: при центрировании цена уезжала к середине
     карточки и переставала читаться в одну линию с названием */
  align-items: start;
}
.cart-item__media {
  width: 96px;
  aspect-ratio: 4 / 5;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--color-surface);
}
.cart-item__media img { width: 100%; height: 100%; object-fit: cover; }
.cart-item__title { font-family: var(--font-heading); font-size: var(--fs-h4); margin: 0 0 4px; }
.cart-item__title a { color: inherit; }
.cart-item__variant { font-size: var(--fs-sm); color: var(--color-muted); }
.cart-item__price {
  font-size: var(--fs-lg);
  font-weight: 600;
  white-space: nowrap;
  text-align: right;
  padding-top: 2px;
}
.cart-item__controls { display: flex; align-items: center; gap: 16px; margin-top: 12px; }

.qty {
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-pill);
  overflow: hidden;
}
.qty__btn {
  width: 44px; height: 44px;
  border: 0;
  background: transparent;
  color: var(--color-text);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.qty__btn:hover { color: var(--color-accent); }
.qty__value {
  min-width: 40px;
  text-align: center;
  font-size: var(--fs-base);
  font-weight: 500;
}

.cart-item__remove {
  border: 0;
  background: none;
  color: var(--color-muted);
  cursor: pointer;
  font-size: var(--fs-sm);
  min-height: 44px;
  padding: 0 4px;
}
.cart-item__remove:hover { color: var(--color-error); }

@media (max-width: 768px) {
  .cart-item { grid-template-columns: 80px 1fr; }
  .cart-item__media { width: 80px; }
  .cart-item__price { grid-column: 2; text-align: left; }
}

/* Ч2. Предупреждающая плашка в корзине сообщает не об ошибке, а о второй
   дате доставки. Жёлтый цвет ошибки в момент готовности платить работает
   против заказа, хотя текст сообщения продающий */
/* Р3. Ч2 смягчил цвет плашки, но факт остался задвоенным золотом: плашка
   сверху колонки товаров и золотой пилл «Под заказ — привезём к среде»
   у самой позиции. Носитель — пилл, он стоит там, где факт относится
   к делу; плашка становится примечанием.

   Селектор сужен до плашки в колонке товаров: предупреждение о минимальной
   сумме заказа живёт внутри .summary и остаётся полноценной плашкой */
.page-cart .cart-layout > div > .alert--warning {
  border: 0;
  background: transparent;
  padding: 0 0 20px;
  margin-bottom: 0;
  color: var(--color-muted);
}
.page-cart .cart-layout > div > .alert--warning .icon { color: var(--color-muted); }

/* ── Сводка заказа ────────────────────────────────────────────────────── */

.summary {
  position: sticky;
  top: calc(var(--header-height) + 24px);
  padding: 24px;
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-lg);
}
/* Ч3. Слово «Итого» было набрано антиквой 28px, а сама сумма — 18px:
   заголовок весил больше числа, ради которого сводку и открывают */
.summary__title { font-size: var(--fs-h4); margin: 0 0 16px; }
.summary__row {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding: 8px 0;
  font-size: var(--fs-sm);
  color: var(--color-text-soft);
}
/* Ч3. Сумма к оплате — главное число сводки. Табличные цифры обязательны:
   стоимость доставки пересчитывается по адресу на лету, и без них
   итог дёргается по горизонтали при каждом пересчёте */
.summary__row--total {
  align-items: baseline;
  border-top: 1px solid var(--color-border-strong);
  margin-top: 14px;
  padding-top: 18px;
  font-size: var(--fs-h3);
  font-weight: 600;
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
  color: var(--color-text);
}
.summary__row--total span:first-child {
  font-size: var(--fs-base);
  font-weight: 500;
  color: var(--color-text-soft);
}
.summary__note { font-size: var(--fs-sm); color: var(--color-muted); margin-top: 16px; }
.summary__actions { margin-top: 24px; }
/* Ч8. Значение строки сводки не переносится: колонка сжимается под длинным
   названием букета из Posiflora, и «4 900 ₽» встаёт в три строки */
.summary__row > span:last-child { white-space: nowrap; }

/* ── Чекаут ───────────────────────────────────────────────────────────────
   Ключевой экран конверсии. Ни одного лишнего поля.
   Регистрация не обязательна — предлагается ПОСЛЕ успешного заказа
   ───────────────────────────────────────────────────────────────────────── */

.checkout-layout {
  display: grid;
  grid-template-columns: 58fr 42fr;
  gap: 48px;
  align-items: start;
  padding-bottom: 120px;
}

.checkout-step {
  padding: 32px 0;
  border-bottom: 1px solid var(--color-border);
}
.checkout-step:first-child { padding-top: 0; }
.checkout-step:last-child  { border-bottom: 0; }

.checkout-step__title {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: var(--fs-h3);
  margin: 0 0 24px;
}
.checkout-step__num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px; height: 32px;
  border-radius: 50%;
  /* Д2. В тёмной теме surface на bg неотличим — от шага оставалась
     висящая золотая цифра без кружка */
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border-strong);
  color: var(--color-accent);
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  font-weight: 600;
  flex-shrink: 0;
}

.checkout__consent {
  margin: 24px 0;
  padding: 20px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);   /* Д2 */
  border-radius: var(--radius-md);
}

.checkout__pay { margin-top: 24px; }
.checkout__secure {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 16px;
  font-size: var(--fs-sm);
  color: var(--color-muted);
}

/* Сводка на мобильных: свёрнута сверху, кнопка оплаты — липкая снизу */
.summary-mobile { display: none; }
/* Ч7. Липкая кнопка — мобильный элемент. Без этого на 1440 она остаётся
   обычным блоком в потоке и даёт второй «Перейти к оплате» под согласием */
.checkout__sticky { display: none; }

@media (max-width: 900px) {
  .cart-layout,
  .checkout-layout { grid-template-columns: 1fr; gap: 24px; padding-bottom: 96px; }

  /* Ч4. order: -1 поднимал сводку выше состава заказа: человек читал
     «К оплате» раньше товаров, а предупреждение «часть под заказ»
     оказывалось ниже кнопки, которую оно уточняет */
  .summary { position: static; }

  /* Ч6. Две роли одной сводки: сверху — живая сумма строкой в <details>,
     полный расчёт — под формой. Кнопку и примечания в aside глушим:
     их работу на мобильных делает .checkout__sticky */
  .page-checkout .summary { order: 1; }
  .page-checkout .summary .checkout__pay,
  .page-checkout .summary .summary__note { display: none; }

  /* Ч5. Главное действие корзины — в зоне большого пальца.
     56px — высота .bottom-bar, тот же литерал, что в nav.css */
  .page-cart .summary__actions {
    position: fixed;
    left: 0;
    right: 0;
    bottom: calc(56px + env(safe-area-inset-bottom));
    z-index: 90;
    margin: 0;
    padding: 12px var(--gutter);
    background: var(--color-bg);
    border-top: 1px solid var(--color-border);
    box-shadow: 0 -4px 16px rgba(28, 23, 18, 0.08);
  }
  /* Ч10. «Перейти к оформлению» ломалось на две строки: btn--large держит
     padding: 0 40px при ширине 342px. 28px — боковое поле базовой .btn */
  .summary__actions .btn--large { padding: 0 28px; }

  .summary-mobile {
    display: block;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: var(--color-surface-raised);
    margin-bottom: 24px;
  }
  .summary-mobile summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 16px 20px;
    min-height: 56px;
    cursor: pointer;
    font-weight: 500;
    list-style: none;
  }
  .summary-mobile summary::-webkit-details-marker { display: none; }
  .summary-mobile[open] summary { border-bottom: 1px solid var(--color-border); }
  .summary-mobile__body { padding: 16px 20px; }

  .checkout__sticky {
    display: block;          /* Ч7 */
    position: fixed;
    left: 0; right: 0; bottom: 0;
    z-index: 90;
    padding: 12px var(--gutter);
    padding-bottom: calc(12px + env(safe-area-inset-bottom));
    background: var(--color-bg);
    border-top: 1px solid var(--color-border);
    box-shadow: 0 -4px 16px rgba(28, 23, 18, 0.08);
  }
  .checkout__sticky .btn { width: 100%; }
}

/* ── Успешный заказ ───────────────────────────────────────────────────── */

.order-success {
  max-width: 640px;
  margin: 0 auto;
  padding: 72px 0 96px;
  text-align: center;
}
.order-success__icon { color: var(--color-success); margin-bottom: 24px; }
.order-success__number {
  font-family: var(--font-mono);
  font-size: var(--fs-lg);
  padding: 8px 20px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);   /* Д2 */
  border-radius: var(--radius-pill);
  display: inline-block;
  margin-bottom: 24px;
}
.order-success__text { color: var(--color-text-soft); margin-bottom: 32px; }

.order-success__register {
  margin-top: 48px;
  padding: 32px;
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  text-align: left;
}

/* ── Отслеживание заказа ──────────────────────────────────────────────── */

.track-steps { display: flex; flex-direction: column; gap: 0; margin: 32px 0; }
.track-step {
  display: flex;
  gap: 20px;
  padding-bottom: 32px;
  position: relative;
}
.track-step:last-child { padding-bottom: 0; }
.track-step::before {
  content: '';
  position: absolute;
  left: 15px; top: 32px; bottom: 0;
  width: 1px;
  background: var(--color-border);
}
.track-step:last-child::before { display: none; }
.track-step__dot {
  width: 32px; height: 32px;
  border-radius: 50%;
  border: 1px solid var(--color-border-strong);
  background: var(--color-bg);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  z-index: 1;
  color: var(--color-muted);
}
.track-step.is-done .track-step__dot {
  background: var(--color-success);
  border-color: var(--color-success);
  /* Белый здесь литералом намеренно: галочка лежит на зелёном фоне
     в обеих темах, и --color-on-accent, который в тёмной теме
     становится почти чёрным, дал бы нечитаемый контраст */
  color: #FFFFFF;
}
.track-step.is-current .track-step__dot {
  border-color: var(--color-accent);
  color: var(--color-accent);
}
.track-step__title { font-weight: 500; }
.track-step__time  { font-size: var(--fs-sm); color: var(--color-muted); }

/* ── Личный кабинет ───────────────────────────────────────────────────── */

.cabinet-layout {
  display: grid;
  grid-template-columns: 240px 1fr;
  gap: 48px;
  align-items: start;
  padding: 32px 0 96px;
}

.cabinet-nav { display: flex; flex-direction: column; gap: 4px; }
.cabinet-nav__item {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 48px;
  padding: 0 16px;
  border-radius: var(--radius-md);
  color: var(--color-text-soft);
  font-size: var(--fs-sm);
}
.cabinet-nav__item:hover { background: var(--color-surface); color: var(--color-text); }
.cabinet-nav__item.is-active {
  background: var(--color-surface);
  color: var(--color-accent);
  font-weight: 500;
}

.order-row {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 20px;
  align-items: center;
  padding: 20px 24px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-surface-raised);
  margin-bottom: 12px;
}
.order-row__id { font-family: var(--font-mono); font-size: var(--fs-sm); }
.order-row__meta { font-size: var(--fs-sm); color: var(--color-muted); }
.order-row__total { font-weight: 600; white-space: nowrap; }

@media (max-width: 900px) {
  .cabinet-layout { grid-template-columns: 1fr; gap: 24px; }
  .cabinet-nav {
    flex-direction: row;
    overflow-x: auto;
    margin: 0 calc(-1 * var(--gutter));
    padding: 0 var(--gutter) 8px;
    scrollbar-width: none;
  }
  .cabinet-nav::-webkit-scrollbar { display: none; }
  .cabinet-nav__item { flex: 0 0 auto; }
  .order-row { grid-template-columns: 1fr auto; }
}

/* ── Вход и регистрация ───────────────────────────────────────────────── */

.auth-page {
  max-width: 420px;
  margin: 0 auto;
  padding: 64px 0 96px;
}
.auth-page__title { text-align: center; margin-bottom: 8px; }
.auth-page__lead {
  text-align: center;
  color: var(--color-text-soft);
  margin-bottom: 32px;
}
.auth-page__footer {
  text-align: center;
  margin-top: 24px;
  font-size: var(--fs-sm);
  color: var(--color-muted);
}

/* ═══ components/nav.css ═══ */

/* ── Мобильное меню ───────────────────────────────────────────────────────
   Полноэкранное, много воздуха. Модальных окон на входе — ноль:
   у конкурента их три, и это трение до первого касания с товаром
   ───────────────────────────────────────────────────────────────────────── */

.mobile-menu {
  position: fixed;
  inset: 0;
  z-index: 150;
  background: var(--color-bg);
  display: flex;
  flex-direction: column;
  transform: translateX(100%);
  transition: transform var(--transition-normal) var(--ease-in);
  overflow-y: auto;
  visibility: hidden;
}
.mobile-menu.is-open { transform: none; visibility: visible; }

.mobile-menu__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: var(--header-height);
  padding: 0 var(--gutter);
  border-bottom: 1px solid var(--color-border);
  flex-shrink: 0;
}

.mobile-menu__nav {
  display: flex;
  flex-direction: column;
  padding: 32px var(--gutter);
  gap: 4px;
  flex: 1;
}
.mobile-menu__link {
  font-family: var(--font-heading);
  font-size: var(--fs-h3);
  color: var(--color-text);
  padding: 12px 0;
  min-height: 44px;
}
.mobile-menu__link:hover,
.mobile-menu__link.is-active { color: var(--color-accent); }

.mobile-menu__footer {
  padding: 24px var(--gutter) 32px;
  border-top: 1px solid var(--color-border);
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.mobile-menu__phone {
  font-size: var(--fs-lg);
  font-weight: 500;
  color: var(--color-text);
}

body.is-menu-open { overflow: hidden; }

/* ── Нижняя панель на мобильных ──────────────────────────────────────────
   Корзина и телефон должны быть доступны всегда, в зоне большого пальца
   ───────────────────────────────────────────────────────────────────────── */

.bottom-bar { display: none; }

@media (max-width: 768px) {
  .bottom-bar {
    position: fixed;
    left: 0; right: 0; bottom: 0;
    z-index: 80;
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    background: var(--color-bg);
    border-top: 1px solid var(--color-border);
    padding-bottom: env(safe-area-inset-bottom);
  }
  .bottom-bar__item {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    min-height: 56px;
    font-size: 11px;
    color: var(--color-muted);
    position: relative;
  }
  .bottom-bar__item.is-active { color: var(--color-accent); }
  .bottom-bar__badge {
    position: absolute;
    top: 6px;
    left: 50%;
    margin-left: 4px;
    min-width: 16px; height: 16px;
    padding: 0 4px;
    border-radius: var(--radius-pill);
    background: var(--color-accent);
    color: var(--color-on-accent);
    font-size: 10px;
    line-height: 16px;
    font-weight: 600;
    text-align: center;
  }

  /* Отступ под нижнюю панель: она fixed и не занимает места в потоке */
  body.has-bottom-bar { padding-bottom: 56px; }

  /* Ч1. Липкая кнопка оплаты (fixed, bottom 0, z-index 90) ложилась поверх
     нижней панели (z-index 80): на экране оплаты вся навигация была закрыта,
     а padding-bottom на body на fixed-элемент не действует.

     На чекауте единственное действие экрана — оплата. Панель убираем */
  body.page-checkout .bottom-bar { display: none; }
  body.page-checkout.has-bottom-bar { padding-bottom: 0; }

  /* Ч5. Здесь стояло `body.page-cart .checkout__sticky { bottom: 56px }` —
     мёртвое правило: .checkout__sticky есть только в checkout.php, в корзине
     такого узла нет. Липким сделан .summary__actions (см. checkout.css),
     а здесь ему освобождается место: 132px = 56 (панель) + 76 (12 + 52 + 12) */
  body.page-cart.has-bottom-bar { padding-bottom: 132px; }

  /* Т3. Тем же приёмом освобождается место под кнопки карточки товара */
  body.page-product.has-bottom-bar { padding-bottom: 132px; }

  /* Cookie-баннер не должен уходить под липкую кнопку */
  body.has-bottom-bar .cookie-banner { bottom: 84px; }
  /* В корзине и на карточке товара над панелью стоит ещё и кнопка */
  body.page-cart.has-bottom-bar .cookie-banner,
  body.page-product.has-bottom-bar .cookie-banner { bottom: 160px; }
}

/* ── Подвал ───────────────────────────────────────────────────────────────
   Уровень 4 триггеров доверия: реквизиты ИП, платёжные логотипы
   монохромом, обещание про карточные данные, юридические страницы
   ───────────────────────────────────────────────────────────────────────── */

.footer {
  background: var(--color-surface);
  border-top: 1px solid var(--color-border);
  padding: 72px 0 32px;
  margin-top: auto;
}

.footer__grid {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr 1.4fr;
  gap: 48px;
  padding-bottom: 48px;
}

.footer__logo {
  font-family: var(--font-heading);
  font-size: var(--fs-h3);
  color: var(--color-text);
  display: inline-block;
  margin-bottom: 16px;
}
.footer__tagline { color: var(--color-text-soft); font-size: var(--fs-sm); max-width: 32ch; }

.footer__title {
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: var(--ls-caps);
  color: var(--color-muted);
  margin-bottom: 16px;
  font-weight: 500;
}

.footer__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.footer__link {
  color: var(--color-text-soft);
  font-size: var(--fs-sm);
  display: inline-flex;
  align-items: center;
  min-height: 36px;
}
.footer__link:hover { color: var(--color-accent); }

.footer__contact { font-size: var(--fs-sm); color: var(--color-text-soft); }
.footer__phone {
  font-size: var(--fs-lg);
  font-weight: 500;
  color: var(--color-text);
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}

/* Часы салона и окно доставки разведены намеренно: клиент, заказывающий
   в 19:30, не должен прочитать «10:00–21:00» как «уже поздно» */
.footer__hours { margin-top: 12px; line-height: 1.8; }
.footer__hours b { font-weight: 500; color: var(--color-text); }

.footer__socials { display: flex; gap: 8px; margin-top: 16px; }
.footer__social {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px; height: 44px;
  border: 1px solid var(--color-border-strong);
  border-radius: 50%;
  color: var(--color-text-soft);
}
.footer__social:hover { border-color: var(--color-accent); color: var(--color-accent); }

.footer__payments {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}
/* Логотипы платёжных систем монохромные — они подтверждают,
   а не рекламируют */
.footer__payment {
  height: 22px;
  width: auto;
  filter: grayscale(1);
  opacity: 0.55;
}

.footer__bottom {
  border-top: 1px solid var(--color-border);
  padding-top: 28px;
  display: flex;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
  font-size: var(--fs-sm);
  color: var(--color-muted);
}
.footer__legal { max-width: 60ch; line-height: 1.7; }
.footer__legal-links { display: flex; gap: 16px; flex-wrap: wrap; }

@media (max-width: 1024px) {
  .footer__grid { grid-template-columns: 1fr 1fr; gap: 32px; }
}
@media (max-width: 600px) {
  .footer { padding-top: 48px; }
  .footer__grid { grid-template-columns: 1fr; gap: 28px; }
  .footer__bottom { flex-direction: column; gap: 16px; }
}

/* ── Cookie-баннер ────────────────────────────────────────────────────────
   На действующем сайте отсутствует — регуляторный пробел
   (regulatory-checklist.md). Выбор пишется в cookie_consents
   ───────────────────────────────────────────────────────────────────────── */

.cookie-banner {
  position: fixed;
  left: 24px; right: 24px; bottom: 24px;
  z-index: 160;
  max-width: 720px;
  margin: 0 auto;
  padding: 24px 28px;
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  display: flex;
  align-items: center;
  gap: 24px;
  flex-wrap: wrap;
  transform: translateY(calc(100% + 24px));
  transition: transform var(--transition-normal) var(--ease-in);
}
.cookie-banner.is-visible { transform: none; }

.cookie-banner__text {
  flex: 1;
  min-width: 240px;
  font-size: var(--fs-sm);
  color: var(--color-text-soft);
  margin: 0;
}
.cookie-banner__actions { display: flex; gap: 12px; flex-wrap: wrap; }

@media (max-width: 600px) {
  .cookie-banner {
    left: 12px; right: 12px; bottom: 12px;
    padding: 20px;
    gap: 16px;
  }
  .cookie-banner__actions { width: 100%; flex-direction: column-reverse; }
  .cookie-banner__actions .btn { width: 100%; }
  /* Ч1. Баннер обязан проходить и над панелью, и над липкой кнопкой оплаты */
  body.has-bottom-bar .cookie-banner { bottom: 84px; }
  body.page-cart.has-bottom-bar .cookie-banner,
  body.page-product.has-bottom-bar .cookie-banner { bottom: 160px; }
}

/* ── Плашка нерабочего времени ────────────────────────────────────────────
   Стоит над шапкой, в потоке: уезжает вверх при скролле и не отнимает
   экран у товара. Тон приглушённый, декоративный — это справка о режиме
   работы, а не ошибка: салон закрыт, но заказ принимается, и красная
   тревожная плашка здесь врала бы о серьёзности повода. */
.salon-notice {
  background: color-mix(in srgb, var(--color-accent-light) 16%, var(--color-surface));
  border-bottom: 1px solid var(--color-border);
}
:root.salon-notice-off .salon-notice { display: none; }

.salon-notice__inner {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 40px;
  padding-top: 8px;
  padding-bottom: 8px;
}

.salon-notice__dot {
  flex: none;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--color-accent-deco);
}

.salon-notice__text {
  flex: 1;
  margin: 0;
  font-size: var(--fs-sm);
  line-height: 1.4;
  color: var(--color-text-soft);
}

.salon-notice__close {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  margin-right: -8px;
  border: 0;
  border-radius: var(--radius-pill);
  background: none;
  color: var(--color-muted);
  cursor: pointer;
  transition: color var(--transition-fast) ease-out;
}
.salon-notice__close:hover { color: var(--color-text); }

@media (max-width: 600px) {
  .salon-notice__inner { align-items: flex-start; }
  .salon-notice__dot { margin-top: 7px; }
}

/* ═══ components/legal.css ═══ */

/* ── Юридические и текстовые страницы ─────────────────────────────────────
   Ширина текстового блока ограничена: длинная строка юридического текста
   не читается, а прочитать его человек должен
   ───────────────────────────────────────────────────────────────────────── */

.legal { padding: 40px 0 96px; }

.legal__content {
  max-width: var(--measure-max);
  color: var(--color-text-soft);
}

.legal__content h2 {
  font-size: var(--fs-h3);
  color: var(--color-text);
  margin: 48px 0 16px;
}
.legal__content h3 {
  font-size: var(--fs-h4);
  color: var(--color-text);
  margin: 32px 0 12px;
}
.legal__content p { margin: 0 0 16px; }
.legal__content ul,
.legal__content ol { margin: 0 0 20px; padding-left: 24px; }
.legal__content li { margin-bottom: 8px; }
.legal__content a { text-decoration: underline; }

.legal__updated {
  font-size: var(--fs-sm);
  color: var(--color-muted);
  padding-bottom: 24px;
  border-bottom: 1px solid var(--color-border);
  margin-bottom: 32px;
}

.legal__toc {
  padding: 24px 28px;
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  margin-bottom: 40px;
}
.legal__toc-title { font-weight: 500; color: var(--color-text); margin-bottom: 12px; }
.legal__toc ul { list-style: none; padding: 0; margin: 0; }
.legal__toc li { margin-bottom: 4px; }

/* ── Таблица тарифов ─────────────────────────────────────────────────────
   На мобильных перестраивается в карточки — горизонтального скролла
   быть не должно
   ───────────────────────────────────────────────────────────────────────── */

.pricing-table {
  width: 100%;
  border-collapse: collapse;
  margin: 24px 0 32px;
  font-size: var(--fs-base);
}
.pricing-table th,
.pricing-table td {
  padding: 16px;
  text-align: left;
  border-bottom: 1px solid var(--color-border);
}
.pricing-table th {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--color-text);
  text-transform: none;
}
.pricing-table tbody tr:nth-child(odd) { background: var(--color-surface); }
.pricing-table td:last-child { text-align: right; white-space: nowrap; font-weight: 500; }

@media (max-width: 700px) {
  .pricing-table,
  .pricing-table tbody,
  .pricing-table tr,
  .pricing-table td { display: block; width: 100%; }
  .pricing-table thead { display: none; }
  .pricing-table tr {
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    margin-bottom: 12px;
    padding: 8px 16px;
    background: var(--color-surface-raised) !important;
  }
  .pricing-table td {
    border: 0;
    padding: 8px 0;
    display: flex;
    justify-content: space-between;
    gap: 16px;
    text-align: left !important;
  }
  .pricing-table td::before {
    content: attr(data-label);
    font-size: var(--fs-sm);
    color: var(--color-muted);
    flex-shrink: 0;
  }
}

/* ── Ключевой информационный блок ─────────────────────────────────────── */

.info-box {
  padding: 24px 28px;
  background: var(--color-surface);
  border-left: 2px solid var(--color-accent);
  border-radius: 0 var(--radius-md) var(--radius-md) 0;
  margin: 24px 0 32px;
}
.info-box p:last-child { margin-bottom: 0; }
.info-box b { color: var(--color-text); font-weight: 600; }

/* ── Аккордеон (вопросы и ответы) ─────────────────────────────────────── */

.accordion { border-top: 1px solid var(--color-border); }
.accordion__item { border-bottom: 1px solid var(--color-border); }
.accordion__summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 20px 0;
  min-height: 44px;
  cursor: pointer;
  font-size: var(--fs-lg);
  color: var(--color-text);
  list-style: none;
}
.accordion__summary::-webkit-details-marker { display: none; }
.accordion__summary::after {
  content: '';
  width: 10px; height: 10px;
  border-right: 1.5px solid var(--color-muted);
  border-bottom: 1.5px solid var(--color-muted);
  transform: rotate(45deg);
  transition: transform var(--transition-fast) ease-out;
  flex-shrink: 0;
}
.accordion__item[open] .accordion__summary::after { transform: rotate(-135deg); }
.accordion__body { padding: 0 0 24px; color: var(--color-text-soft); max-width: 60ch; }

/* ── Шаги ─────────────────────────────────────────────────────────────── */

.steps { counter-reset: step; display: grid; gap: 32px; }
.step { position: relative; padding-left: 56px; counter-increment: step; }
.step::before {
  content: counter(step);
  position: absolute;
  left: 0; top: 0;
  width: 40px; height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--color-accent-deco);
  border-radius: 50%;
  font-family: var(--font-heading);
  font-size: var(--fs-h4);
  color: var(--color-accent);
}
.step__title { font-size: var(--fs-h4); margin: 0 0 8px; }
.step__text { color: var(--color-text-soft); margin: 0; }

/* ── Страница 404 ─────────────────────────────────────────────────────── */

.error-page {
  text-align: center;
  padding: 120px 24px;
  max-width: 560px;
  margin: 0 auto;
}
.error-page__code {
  font-family: var(--font-heading);
  font-size: var(--fs-display);
  font-weight: 300;
  color: var(--color-accent-deco);
  line-height: 1;
  margin-bottom: 16px;
}
.error-page__text { color: var(--color-text-soft); margin-bottom: 32px; }

/* ═══ components/florist.css ═══ */

/* Панель флориста (florist/*.php) — каркас и «Работа».
   Разметка панели существовала без единого правила стиля: собирали
   markup под конкретные экраны (rb__*, fl__*), а сам css/components/
   для панели так и не завели. На телефоне это выглядело голым текстом —
   ни карточек, ни границ, ни полос прогресса.

   Переиспользует токены и часть паттернов postavka.css (карточка,
   пилюли-плашки, .pk__field), потому что это тот же инструмент
   в руках того же человека — не хочется, чтобы «Работа» и разбор
   поставки выглядели как два разных приложения. */

body.fl { background: var(--color-bg); min-height: 100vh; }

.fl__head {
  padding: 20px var(--container-pad, 16px) 4px;
  max-width: 640px;
  margin: 0 auto;
}
.fl__head-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }

/* Тема переехала из нижнего меню сюда: в таббаре она была шестым пунктом
   среди разделов, хотя это настройка. Пять разделов — и ни одного лишнего */
.fl__theme {
  flex: 0 0 auto;
  width: 40px; height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--color-border);
  border-radius: 50%;
  background: var(--color-surface);
  color: var(--color-muted);
  cursor: pointer;
}
.fl__theme:hover { color: var(--color-accent); }

.fl__title {
  font-family: var(--font-body);
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -0.01em;
}
.fl__sub { margin-top: 4px; font-size: var(--fs-sm); color: var(--color-muted); }

.fl__main {
  max-width: 640px;
  margin: 0 auto;
  padding: 12px 16px calc(84px + env(safe-area-inset-bottom, 0px));
}
.fl__main--bare { padding-top: 0; }

/* ── Нижнее меню ───────────────────────────────────────────────────────── */
.fl__nav {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 50;
  display: flex;
  background: var(--color-surface-raised);
  border-top: 1px solid var(--color-border);
  padding-bottom: env(safe-area-inset-bottom, 0px);
}
.fl__nav-item {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  padding: 9px 4px 8px;
  border: 0;
  background: none;
  color: var(--color-muted);
  font-size: 11px;
  line-height: 1.2;
  cursor: pointer;
}
.fl__nav-item svg { width: 22px; height: 22px; }
.fl__nav-item.is-active { color: var(--color-success); }
.fl__nav-item:hover { color: var(--color-accent); }
.fl__nav-item.is-active:hover { color: var(--color-success); }

/* ── Вход по коду ──────────────────────────────────────────────────────── */
.fl__lead { color: var(--color-text-soft); font-size: var(--fs-lg); margin-bottom: 20px; }
.fl__login { display: flex; flex-direction: column; gap: 12px; }
.fl__login input {
  width: 100%;
  font-size: 20px;
  letter-spacing: 0.04em;
  text-align: center;
  padding: 14px 10px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  color: var(--color-text);
}

/* ── Общие мелочи панели ───────────────────────────────────────────────── */
.fl__hint { font-size: var(--fs-sm); color: var(--color-muted); line-height: 1.5; margin: 8px 0 16px; }
.fl__back { font-size: var(--fs-sm); margin-bottom: 12px; }

/* Предупреждение читается на телефоне в зале, поэтому не серым по серому:
   флорист смотрит на экран мельком, между покупателями. */
.fl__hint--warn {
  color: var(--color-text);
  background: rgba(220, 120, 60, .12);
  border-left: 3px solid rgba(220, 120, 60, .7);
  padding: 10px 12px;
  border-radius: 6px;
}

.fl__tag {
  display: inline-block;
  font-size: 11px;
  padding: 1px 6px;
  margin-left: 6px;
  border-radius: 10px;
  background: var(--color-surface-2, rgba(0, 0, 0, .06));
  color: var(--color-muted);
  vertical-align: middle;
}

.fl__h2, .rb__group {
  font-family: var(--font-body);
  font-size: 17px;
  font-weight: 700;
  margin: 26px 0 10px;
}
.fl__h2:first-child, .rb__group:first-child { margin-top: 4px; }

.fl__warn {
  background: #fff5e2;
  border-left: 4px solid #e0a03a;
  border-radius: 10px;
  padding: 11px 13px;
  font-size: 13.5px;
  line-height: 1.5;
  color: #6d4c12;
  margin: 12px 0;
}

/* Строка «подпись — значение»: тарифы доставки, телефоны салонов,
   отложенное под заказ в Posiflora — везде одна и та же пара b/span */
.fl__wait {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  padding: 10px 0;
  border-top: 1px solid var(--color-border);
  font-size: 14px;
}
.fl__wait:first-child { border-top: none; }
.fl__wait span { color: var(--color-muted); white-space: nowrap; }

/* Аккордеон памятки и справочника цветов */
.fl__sec {
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  margin-bottom: 10px;
  overflow: hidden;
}
.fl__sec > summary {
  padding: 14px 16px;
  cursor: pointer;
  list-style: none;
  font-weight: 600;
  font-size: 15px;
  position: relative;
}
.fl__sec > summary::-webkit-details-marker { display: none; }
.fl__sec > summary::after {
  content: '+';
  position: absolute;
  right: 16px; top: 50%;
  transform: translateY(-50%);
  color: var(--color-muted);
  font-size: 20px;
  font-weight: 400;
}
.fl__sec[open] > summary::after { content: '\2212'; }
.fl__sec > div {
  padding: 0 16px 16px;
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--color-text-soft);
}
.fl__sec > div p { margin: 0 0 12px; }
.fl__sec > div p:last-child { margin-bottom: 0; }
.fl__legend { font-size: 12px; color: var(--color-muted); line-height: 1.5; margin: 4px 0 16px; }

/* ── Справочник «Цветы» ────────────────────────────────────────────────── */
.fl__search input {
  width: 100%;
  font-size: 16px;
  padding: 12px 14px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-pill);
  background: var(--color-surface);
  color: var(--color-text);
  margin-bottom: 14px;
}
.fl__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
}
.fl__cell {
  display: flex;
  flex-direction: column;
  gap: 6px;
  color: var(--color-text);
}
.fl__cell img {
  aspect-ratio: 1;
  width: 100%;
  object-fit: cover;
  border-radius: var(--radius-md);
  background: var(--color-surface);
}
.fl__cell-empty {
  aspect-ratio: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-md);
  background: var(--color-surface);
  color: var(--color-muted);
  font-size: 11px;
  text-align: center;
  padding: 4px;
}
.fl__cell b { font-size: 13px; font-weight: 600; line-height: 1.3; }

.fl__photos {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
  gap: 8px;
  margin-bottom: 12px;
}
.fl__photos img {
  aspect-ratio: 1;
  width: 100%;
  object-fit: cover;
  border-radius: var(--radius-md);
}
.fl__photo-add {
  aspect-ratio: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  font-size: 12px;
  color: var(--color-accent);
  border: 1px dashed var(--color-border-strong);
  border-radius: var(--radius-md);
  padding: 6px;
  cursor: pointer;
}

@media (max-width: 420px) {
  .fl__grid { grid-template-columns: repeat(2, 1fr); }
}

/* ── «Работа»: задачи, отложенное, заказы к сборке ────────────────────── */
.rb__task {
  display: flex;
  flex-direction: column;
  gap: 6px;
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: 14px 16px;
  margin-bottom: 10px;
  color: var(--color-text);
}
.rb__kind {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: var(--ls-caps);
  color: var(--color-accent);
  font-weight: 600;
}
.rb__name { font-size: 16px; font-weight: 650; }
.rb__meta { font-size: 13px; color: var(--color-muted); }

.rb__bar {
  display: block;
  height: 6px;
  border-radius: var(--radius-pill);
  background: var(--color-surface);
  overflow: hidden;
  margin-top: 2px;
}
.rb__bar i { display: block; height: 100%; background: var(--color-success); border-radius: inherit; }

/* Отложенное под заказ в Posiflora + любой другой инфо-блок-контейнер
   (в т.ч. «Сказать владельцу») — общая карточка-обёртка */
.rb__note {
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: 14px 16px;
  margin-bottom: 16px;
}
.rb__note-why { font-size: 13.5px; color: var(--color-text-soft); line-height: 1.5; margin-bottom: 10px; }
.rb__note textarea {
  width: 100%;
  font-size: 15px;
  padding: 10px 12px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  color: var(--color-text);
  resize: vertical;
  margin-bottom: 10px;
}
.rb__note-status { font-size: var(--fs-xs); color: var(--color-muted); margin-top: 8px; min-height: 1.2em; }

.rb__order {
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: 14px 16px;
  margin-bottom: 10px;
}
.rb__order-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 10px;
  font-size: 14.5px;
  margin-bottom: 8px;
}
.rb__order-head span { color: var(--color-muted); font-size: 13px; white-space: nowrap; }
.rb__items { font-size: 14.5px; line-height: 1.5; margin: 0 0 6px; }
.rb__card { font-size: 13.5px; color: var(--color-text-soft); margin: 0 0 6px; }
.rb__order .rb__meta { margin-bottom: 10px; }

/* ── Витрина ───────────────────────────────────────────────────────────── */
/* Плитка в две колонки: на телефоне это предел, при котором на карточке
   ещё читается номер и цена, а листать не приходится до бесконечности. */
.vt__add { width: 100%; margin-bottom: 16px; }

.vt__grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; }

.vt__card {
  position: relative;
  display: block;
  padding: 8px;
  border-radius: 10px;
  background: var(--color-surface, rgba(0,0,0,.03));
  text-decoration: none;
  color: inherit;
}

/* Номер поверх фото: именно его флорист ищет глазами, когда покупатель
   протянул ценник. */
.vt__num {
  position: absolute; top: 12px; left: 12px;
  padding: 2px 8px; border-radius: 10px;
  background: rgba(0,0,0,.65); color: #fff;
  font-size: var(--fs-sm); font-weight: 600;
}

.vt__photo { width: 100%; aspect-ratio: 3/4; object-fit: cover; border-radius: 8px; }
.vt__price { display: block; margin-top: 6px; font-size: var(--fs-md); }
.vt__meta  { display: block; font-size: 12px; color: var(--color-muted); }

.vt__sheet {
  position: fixed; inset: 0; z-index: 50;
  background: var(--color-bg, #fff);
  overflow-y: auto;
}
.vt__sheet-inner { padding: 20px 16px 100px; max-width: 640px; margin: 0 auto; }

.vt__kind { display: flex; gap: 16px; margin: 12px 0; font-size: var(--fs-sm); }

.vt__found { display: flex; flex-direction: column; gap: 4px; margin-bottom: 12px; }
.vt__found-item {
  display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
  padding: 8px 10px; border: 0; border-radius: 8px;
  background: var(--color-surface-2, rgba(0,0,0,.05));
  text-align: left; font: inherit; cursor: pointer;
}
.vt__found-item span { font-size: 12px; color: var(--color-muted); }

.vt__row {
  display: grid; grid-template-columns: 1fr 80px auto auto;
  gap: 8px; align-items: center; padding: 6px 0;
}
.vt__qty { padding: 6px 8px; }

.vt__total {
  display: flex; justify-content: space-between; align-items: baseline;
  padding: 10px 0; margin: 8px 0;
  border-top: 1px solid var(--color-border, rgba(0,0,0,.1));
  font-size: var(--fs-md);
}

.vt__actions { display: flex; gap: 10px; margin-top: 16px; }
.vt__actions .btn { flex: 1; }

.vt__err {
  margin-top: 12px; padding: 10px 12px; border-radius: 8px;
  background: rgba(200, 60, 60, .12); color: var(--color-text);
  font-size: var(--fs-sm);
}

/* ── Касса ─────────────────────────────────────────────────────────────── */
.ks { margin-bottom: 8px; }

/* Итог дня крупно: это первое, на что флорист смотрит, открывая панель,
   и единственная цифра, которую он держит в голове всю смену. */
.ks__today {
  display: flex; align-items: baseline; gap: 8px;
  padding: 10px 12px; margin-bottom: 10px;
  border-radius: var(--radius-md);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
}
.ks__today b { font-size: 22px; font-weight: 700; }
.ks__today span { font-size: var(--fs-sm); color: var(--color-muted); }

.ks__buttons { display: flex; gap: 10px; }
.ks__buttons .btn { flex: 1; }

/* Номер набирают при покупателе — цифры крупные, как на кассовом поле */
.ks__number { font-size: 24px; text-align: center; letter-spacing: 0.08em; }

.ks__found {
  display: flex; flex-direction: column; gap: 4px;
  padding: 10px 12px; margin-bottom: 12px;
  border-radius: var(--radius-md);
  background: var(--color-surface);
}
.ks__found span { font-size: var(--fs-sm); color: var(--color-muted); }

/* Поле «получено» и кнопка «без сдачи» в одну строку: это одно действие,
   а не два разных — покупатель либо дал ровно, либо дал крупную. */
.ks__exact { display: flex; gap: 8px; align-items: center; }
.ks__exact input { flex: 1; }
.ks__exact .btn { white-space: nowrap; }

/* ── Компактная витрина на «Работе» ────────────────────────────────────── */
.vt__head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.rb__group--flush { margin: 20px 0 10px; }
.vt__count {
  display: inline-block; min-width: 20px; padding: 0 6px;
  border-radius: 10px; background: var(--color-surface-2, rgba(0,0,0,.06));
  font-size: 12px; font-weight: 600; color: var(--color-muted);
  vertical-align: middle;
}

/* Лента вместо сетки: витрина не должна съедать пол-экрана рабочего
   стола. Букеты листаются вбок, как карточки в телефоне. */
.vt__strip {
  display: flex; gap: 10px;
  overflow-x: auto; scroll-snap-type: x mandatory;
  margin: 0 -16px; padding: 2px 16px 6px;
  -webkit-overflow-scrolling: touch;
}
.vt__strip::-webkit-scrollbar { display: none; }
.vt__strip .vt__card { flex: 0 0 132px; scroll-snap-align: start; }
.vt__strip .vt__photo { aspect-ratio: 1; }

/* ── Шторка ────────────────────────────────────────────────────────────── */
.vt__sheet-inner {
  position: relative;
  border-radius: 16px 16px 0 0;
  background: var(--color-bg);
  min-height: 100%;
}

/* Ручка: подсказывает, что лист тянется вниз, и служит зоной захвата.
   Мельче 36px по ширине палец не находит вслепую. */
.sheet__grip {
  width: 100%; padding: 10px 0 14px;
  cursor: grab; touch-action: none;
}
.sheet__grip::before {
  content: ''; display: block; width: 44px; height: 4px; margin: 0 auto;
  border-radius: 2px; background: var(--color-border-strong, rgba(0,0,0,.2));
}

.vt__photo-pick { display: flex; gap: 10px; margin: 8px 0; }
.vt__photo-pick .btn { flex: 1; justify-content: center; cursor: pointer; }

.vt__preview { margin: 10px 0; }
.vt__preview img {
  width: 100%; max-height: 240px; object-fit: cover;
  border-radius: var(--radius-md);
}

/* ── Плитки основного меню ─────────────────────────────────────────────── */
/* Крупные: в них тычут мокрым пальцем между покупателями. */
.fl__tiles { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; }
.fl__tile {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 8px; padding: 22px 10px;
  border: 1px solid var(--color-border); border-radius: var(--radius-md);
  background: var(--color-surface-raised);
  color: var(--color-text); text-decoration: none;
  font-size: 15px; font-weight: 600;
}
.fl__tile:hover { color: var(--color-accent); }


.ks__disc-note { font-size: var(--fs-sm); color: var(--color-muted); margin: -4px 0 12px; }

/* Скидка выше потолка. Красным и заметно: это не подсказка, а причина,
   по которой кнопка «Провести» сейчас откажет, и прочитать её надо
   до нажатия, а не после. */
.ks__disc-note.is-over {
  color: var(--color-danger, #b3261e);
  font-weight: 600;
}

/* Покупатель свёрнут: его спрашивают не всегда, и разворачивать форму
   на каждую продажу значит замедлять самый частый случай. */
.ks__client { margin: 4px 0 12px; }
.ks__client > summary {
  cursor: pointer; padding: 10px 0; font-weight: 600; font-size: 15px;
  list-style: none;
}
.ks__client > summary::-webkit-details-marker { display: none; }
.ks__client > summary span { font-weight: 400; color: var(--color-muted); font-size: 13px; }


/* ── Главная кабинета ──────────────────────────────────────────────────── */
.fh { margin-bottom: 20px; }
.fh__hello { font-size: 20px; line-height: 1.3; margin-bottom: 14px; }
.fh__hello b { font-weight: 700; }

.fh__note {
  padding: 14px 16px;
  border-radius: var(--radius-md);
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border);
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--color-text-soft);
}
.fh__note p { margin: 0 0 10px; }
.fh__note p:last-child { margin-bottom: 0; }
.fh__note--empty { color: var(--color-muted); }

/* Плитки: три в ряд помещаются на любом телефоне и не требуют прокрутки,
   а значит всё меню видно целиком — ради этого экран и существует. */
.fl__tiles { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.fl__tile {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 8px; padding: 18px 8px;
  border: 1px solid var(--color-border); border-radius: var(--radius-md);
  background: var(--color-surface-raised);
  color: var(--color-text); text-decoration: none;
  font-size: 13.5px; font-weight: 600; text-align: center;
}
.fl__tile svg { color: var(--color-accent); }
.fl__tile:hover { border-color: var(--color-accent); }

/* ── Строка состава ────────────────────────────────────────────────────── */
/* Было: грид с кнопкой «убрать» в полный рост — она перекрывала цену
   и весила больше самой позиции. Стало: имя, количество, сумма, крестик. */
.vt__row {
  display: grid;
  grid-template-columns: 1fr 64px auto 32px;
  gap: 10px;
  align-items: center;
  padding: 10px 0;
  border-bottom: 1px solid var(--color-border);
  font-size: 14.5px;
}
.vt__row:last-child { border-bottom: none; }
.vt__row > span { line-height: 1.3; }
.vt__row > b { white-space: nowrap; font-weight: 600; }
.vt__qty { padding: 7px 8px; text-align: center; font-size: 15px; }

.vt__drop {
  width: 32px; height: 32px; padding: 0;
  border: 0; border-radius: 50%;
  background: var(--color-surface);
  color: var(--color-muted);
  font-size: 20px; line-height: 1;
  cursor: pointer;
}
.vt__drop:hover { color: var(--color-error, #c0392b); }

/* ── Подсказки поиска ──────────────────────────────────────────────────── */
/* Название и цифры — разными строками. Слитая строка «Роза Эксплорер
   6010 шт · 270 ₽» читается как одно слово: глаз не отделяет длину
   стебля от количества. */
.vt__found-item {
  display: flex; flex-direction: column; align-items: flex-start; gap: 3px;
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--color-border); border-radius: var(--radius-md);
  background: var(--color-surface-raised);
  text-align: left; font: inherit; color: var(--color-text);
  cursor: pointer;
}
.vt__found-item b { font-size: 15px; font-weight: 600; line-height: 1.25; }
.vt__found-item span { font-size: 13px; color: var(--color-muted); }
.vt__found-item:hover { border-color: var(--color-accent); }

.vt__found { display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px; }

/* ── Шапка кабинета со знаком ──────────────────────────────────────────
   Только на главной: знак на каждом экране перестают замечать, а место
   на телефоне дороже. Размер знака привязан к строке текста, чтобы
   шапка не «прыгала» при смене названия точки. */
.fl__brand { display: flex; align-items: center; gap: 12px; min-width: 0; }
.fl__brand-mark { flex: 0 0 auto; width: 34px; height: 34px; color: var(--color-accent); }
.fl__brand-mark svg { display: block; width: 100%; height: 100%; }
.fl__brand-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.fl__brand-text b { font-size: 17px; font-weight: 700; line-height: 1.2; }
.fl__brand-text em {
  font-style: normal; font-size: 12px; letter-spacing: .04em;
  text-transform: uppercase; color: var(--color-muted);
}

/* ── Утренний обход витрины ────────────────────────────────────────────
   Строка списком, а не карточкой: их читают стоя, большим пальцем,
   между покупателями. Горящее отделено цветом слева — на солнце
   в зале фон почти не виден, а полоса видна. */
.ob__list { display: flex; flex-direction: column; gap: 8px; margin-bottom: 18px; }
.ob__item {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 12px 14px;
  border: 1px solid var(--color-border); border-left: 3px solid transparent;
  border-radius: var(--radius-md);
  background: var(--color-surface-raised);
  color: inherit; text-decoration: none;
}
/* --color-error, а не выдуманный --color-danger: такого токена в проекте
   нет, и правило молча не сработало бы — полоса осталась бы прозрачной. */
.ob__item.is-burn { border-left-color: var(--color-error); }
.ob__item.is-done { opacity: .55; }
.ob__body { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
/* Две кнопки в столбик: на 375 пикселях рядом они сжимаются до нечитаемого,
   а промахнуться мимо «Оставил» и списать цветок — дорогая ошибка. */
.ob__acts { display: flex; flex-direction: column; gap: 6px; flex: 0 0 auto; }
.ob__acts .btn { white-space: nowrap; }

/* ── Плашка о новом ────────────────────────────────────────────────────
   Висит над нижним меню, а не сверху: большой палец достаёт до неё,
   не перехватывая телефон, и она не закрывает заголовок экрана,
   на котором человек работает. */
.nv {
  position: fixed; left: 12px; right: 12px; bottom: calc(64px + env(safe-area-inset-bottom, 0px));
  z-index: 60;
  display: flex; align-items: center; gap: 10px;
  padding: 12px 14px;
  border-radius: var(--radius-md);
  background: var(--color-accent); color: var(--color-on-accent);
  box-shadow: 0 8px 24px rgba(28, 23, 18, .28);
  animation: nv-in .18s ease-out;
}
.nv.is-urgent { background: var(--color-error); }
.nv__body { flex: 1 1 auto; min-width: 0; color: inherit; text-decoration: none; }
.nv__body b { display: block; font-size: 15px; line-height: 1.25; }
.nv__body span { display: block; font-size: 13px; opacity: .85; overflow-wrap: anywhere; }
/* Кнопка словом, а не крестиком: крестик читается как
   «больше не напоминай», а напоминание вернётся через пять минут. */
.nv__close {
  flex: 0 0 auto; padding: 7px 12px; border: 0; border-radius: 999px;
  background: rgba(255, 255, 255, .18); color: inherit;
  font-size: 13px; font-weight: 600; line-height: 1; white-space: nowrap;
  cursor: pointer;
}
@keyframes nv-in { from { transform: translateY(8px); opacity: 0; } to { transform: none; opacity: 1; } }

/* ── Квесты ────────────────────────────────────────────────────────────
   Карточка читается сверху вниз за три секунды: название, награда,
   зачем это нужно, сколько осталось. Награда крупная и справа — она
   и есть причина, по которой человек это читает. Выполненный квест
   не исчезает: он показывает, что деньги не приснились. */
.qs { display: flex; flex-direction: column; gap: 10px; margin-bottom: 20px; }
.qs__item {
  padding: 12px 14px;
  border: 1px solid var(--color-border); border-left: 3px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface-raised);
  transition: border-color .15s ease, background .15s ease;
}
.qs__item.is-go   { border-left-color: var(--color-accent); }
.qs__item.is-done { border-left-color: var(--color-success); opacity: .8; }
.qs__item[open]   { background: var(--color-surface); }

/* Свёрнутая плашка: название, сколько осталось и награда — три вещи,
   ради которых на неё смотрят. Остальное по нажатию. */
.qs__head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  cursor: pointer; list-style: none;
}
.qs__head::-webkit-details-marker { display: none; }
.qs__head-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.qs__title  { font-size: 16px; font-weight: 700; line-height: 1.25; }
.qs__reward { font-size: 16px; font-weight: 700; color: var(--color-accent); white-space: nowrap; }
.qs__item.is-done .qs__reward { color: var(--color-success); }

/* Текст выезжает, а не появляется рывком: на телефоне резкая смена
   высоты сбивает — пропадает ощущение, что нажал именно сюда. */
.qs__lead {
  margin: 10px 0; font-size: 14px; line-height: 1.5; color: var(--color-text-soft);
  animation: qs-open .18s ease-out;
}
@keyframes qs-open { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }

.qs__bar {
  height: 6px; border-radius: 3px; overflow: hidden;
  background: var(--color-border); margin-bottom: 6px;
}
/* Полоса подрастает на глазах при открытии карточки — маленькая радость,
   ради которой на экран возвращаются. */
.qs__bar i { display: block; height: 100%; background: var(--color-accent); animation: qs-fill .5s ease-out; }
@keyframes qs-fill { from { width: 0; } }
.qs__meta { font-size: 13px; color: var(--color-muted); }
.qs__done { margin: 0; font-size: 13px; color: var(--color-success); }

/* Смена не открыта: экран заработка объясняет, откуда берутся деньги,
   вместо того чтобы показывать ноль. */
.zp__empty {
  padding: 16px; margin-bottom: 16px;
  border: 1px dashed var(--color-border-strong); border-radius: var(--radius-md);
}
.zp__empty b { display: block; font-size: 16px; margin-bottom: 6px; }
.zp__empty p { margin: 0 0 12px; font-size: 14px; color: var(--color-text-soft); }

/* Снимки списания: маленькие квадраты в ряд с переносом — их бывает
   пять и больше, и каждый должен быть виден, чтобы понять, что снял. */
.ob__shots { display: flex; flex-wrap: wrap; gap: 6px; margin: 8px 0 4px; }
.ob__shots img {
  width: 54px; height: 54px; object-fit: cover; border-radius: 8px;
  border: 1px solid var(--color-border);
}

/* Две кнопки в строке настройки: «Проверить» и «Включён» рядом,
   но не слипаются на узком экране. */
.fh__tour-btns { display: flex; gap: 8px; flex: 0 0 auto; justify-content: flex-end; }

/* Ссылка на сайт: та же форма, что у «Моего заработка» — оба ведут
   наружу из кабинета и читаются как одна пара. */
.fh__site {
  display: flex; align-items: center; gap: 12px;
  padding: 14px 16px; margin-bottom: 12px;
  border: 1px solid var(--color-border); border-radius: var(--radius-md);
  background: var(--color-surface-raised); color: inherit; text-decoration: none;
}
.fh__site b { display: block; font-size: 15px; }
.fh__site em { display: block; font-style: normal; font-size: 13px; color: var(--color-muted); }

/* Открыто из мессенджера: предупреждение, а не украшение — без браузера
   не будет ни приложения, ни уведомлений. */
.pv__inapp {
  border: 1px solid var(--color-warning); border-radius: var(--radius-md);
  padding: 14px 16px; margin-bottom: 18px;
}
.pv__inapp h2 { margin-top: 0; }

/* Приветствие тестировщику: тот же блок, что и остальные на первом
   экране, но с полем обратной связи внизу. */
.pv__test ol { margin: 8px 0 12px; padding-left: 20px; display: grid; gap: 4px; }
.pv__feedback { margin-top: 14px; display: grid; gap: 8px; }
.pv__feedback textarea {
  width: 100%; padding: 10px 12px; font: inherit;
  border: 1px solid var(--color-border); border-radius: var(--radius-md);
  background: var(--color-surface); color: var(--color-text); resize: vertical;
}

/* Клиент в кассе: блок, а не свёрнутая деталь — свёрнутое не спрашивают.
   Свёрнутыми остались только имя и дата: их дозаполняют, когда человек
   уже согласился назваться. */
.fl__h3 { margin: 14px 0 6px; font-size: 16px; font-weight: 700; }
.ks__client-more summary {
  font-size: 14px; color: var(--color-accent); cursor: pointer; padding: 6px 0;
}
.ks__client-more summary::-webkit-details-marker { display: none; }
.ob__name { font-size: 15px; font-weight: 600; line-height: 1.25; }
.ob__why  { font-size: 13px; color: var(--color-muted); }
.ob__done { margin-top: 22px; }

/* Подсказка склада в журнале потерь. Своя пара классов, а не общая
   с витриной: там кнопка выбирает цветок в букет, здесь — позицию,
   которую сейчас спишут с остатка. Одинаковы они сегодня, но меняться
   будут по-разному, и общий класс это скроет. */
.pt__found { display: flex; flex-direction: column; gap: 6px; margin: 4px 0 12px; }
.pt__found-item {
  width: 100%;
  padding: 9px 12px;
  border: 1px solid var(--color-border); border-radius: var(--radius-md);
  background: var(--color-surface-raised);
  text-align: left; font: inherit; font-size: 14px; color: var(--color-text);
  cursor: pointer;
}
.pt__found-item:hover { border-color: var(--color-accent); }

/* ── Кнопки листа ──────────────────────────────────────────────────────── */
/* Действие и отмена не равны по весу: «Продать» — основная кнопка,
   «Отмена» рядом не должна выглядеть второй такой же. */
.vt__actions {
  display: flex; gap: 10px; align-items: center;
  margin: 20px 0 8px;
}
.vt__actions .btn--ghost { flex: 0 0 auto; }
.vt__actions .btn--primary { flex: 1; justify-content: center; }

.vt__total {
  display: flex; justify-content: space-between; align-items: baseline;
  padding: 14px 0 10px; margin-top: 6px;
  border-top: 1px solid var(--color-border);
  font-size: var(--fs-md);
}
.vt__total b { font-size: 20px; font-weight: 700; }

/* ── hidden обязан скрывать ────────────────────────────────────────────── */
/* Атрибут hidden — это display:none по умолчанию, но любое собственное
   правило display его перебивает. Мы задали .field{display:…} и
   .vt__found{display:flex} — и скрытые поля начали показываться:
   в штучной продаже висело пустое поле номера, а список подсказок
   не закрывался после выбора.

   Правило намеренно с !important и в самом низу файла: это не украшение,
   а восстановление поведения, на которое опирается вся логика панели. */
[hidden] { display: none !important; }


/* ── Обложка кабинета ──────────────────────────────────────────────────── */
/* Панель была честной, но сухой: сетка полей на плоском фоне. Картинка
   здесь одна и в одном месте — там, где нет данных. Под текстом
   градиентная вуаль, иначе имя тонет в светлых участках снимка. */
.fh__cover {
  position: relative;
  border-radius: var(--radius-lg, 16px);
  overflow: hidden;
  margin-bottom: 18px;
  aspect-ratio: 16 / 10;
}
.fh__cover img {
  width: 100%; height: 100%;
  object-fit: cover; object-position: center 35%;
  display: block;
}
.fh__cover::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(180deg,
    rgba(20, 17, 13, .15) 0%,
    rgba(20, 17, 13, .55) 55%,
    rgba(20, 17, 13, .85) 100%);
}
.fh__cover-text {
  position: absolute; left: 0; right: 0; bottom: 0;
  z-index: 1;
  padding: 18px 18px 16px;
}
.fh__hello {
  color: #fff;
  font-family: var(--font-display, inherit);
  font-size: 26px;
  line-height: 1.15;
  margin: 0 0 4px;
  text-shadow: 0 1px 12px rgba(0, 0, 0, .35);
}
.fh__hello b { font-weight: 700; color: var(--color-accent-light, #D9B383); }
.fh__where { color: rgba(255, 255, 255, .82); font-size: 13.5px; margin: 0; }

/* ── Фирменный узор ────────────────────────────────────────────────────── */
/* Чистый CSS, ни одного лишнего запроса: у флориста мобильный интернет.
   Узор еле заметен — он должен оживлять фон, а не соперничать с текстом. */
body.fl {
  background-image:
    radial-gradient(circle at 18% 12%, rgba(185, 138, 70, .07) 0, transparent 42%),
    radial-gradient(circle at 82% 78%, rgba(185, 138, 70, .05) 0, transparent 38%);
  background-attachment: fixed;
}

/* ── Плитки разделов ───────────────────────────────────────────────────── */
.fl__tile {
  position: relative;
  overflow: hidden;
  transition: border-color .15s ease, transform .15s ease;
}
/* Иконка в круге: плитки перестают быть просто прямоугольниками,
   а палец видит цель, а не весь блок. */
.fl__tile svg {
  padding: 9px;
  border-radius: 50%;
  background: var(--color-surface);
  color: var(--color-accent);
  box-sizing: content-box;
}
.fl__tile:active { transform: scale(.97); }

/* ── Заголовки блоков ──────────────────────────────────────────────────── */
/* Тонкая черта акцентом вместо голого текста: разделы становятся видны
   при беглом взгляде, а панель перестаёт читаться сплошным списком. */
.rb__group {
  display: flex;
  align-items: center;
  gap: 10px;
}
.rb__group::after {
  content: '';
  flex: 1;
  height: 1px;
  background: linear-gradient(90deg, var(--color-border) 0%, transparent 100%);
}

/* ── Карточки задач ────────────────────────────────────────────────────── */
/* Полоска акцентом слева: задача выглядит задачей, а не абзацем текста. */
.rb__task {
  position: relative;
  padding-left: 16px;
}
.rb__task::before {
  content: '';
  position: absolute; left: 0; top: 12px; bottom: 12px;
  width: 3px; border-radius: 2px;
  background: var(--color-accent-deco, #B98A46);
  opacity: .7;
}

/* Итог дня в кассе — карточка с мягким золотым отливом, чтобы главная
   цифра смены читалась сразу, а не терялась среди полей. */
.ks__today {
  background:
    linear-gradient(135deg, rgba(185, 138, 70, .10) 0%, transparent 60%),
    var(--color-surface-raised);
}
.ks__today b { color: var(--color-accent); }


/* ── Карточка букета ───────────────────────────────────────────────────── */
.bk__photo {
  width: 100%; aspect-ratio: 4/3; object-fit: cover;
  border-radius: var(--radius-md); margin-bottom: 14px;
}
.bk__head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-bottom: 6px;
}
.bk__price { display: block; font-size: 26px; font-weight: 700; line-height: 1.1; }
.bk__meta  { font-size: var(--fs-sm); color: var(--color-muted); }

.bk__row {
  display: grid; grid-template-columns: 1fr auto 32px;
  gap: 10px; align-items: center;
  padding: 12px 0; border-bottom: 1px solid var(--color-border);
  font-size: 15px;
}
.bk__row:last-child { border-bottom: none; }
.bk__qty { color: var(--color-muted); white-space: nowrap; }

.bk__actions { display: flex; gap: 10px; margin: 18px 0 10px; }
.bk__actions .btn { flex: 1; }

/* Разбор — действие редкое и необратимое, поэтому не рядом с обычными
   кнопками и без акцентного цвета: его ищут осознанно. */
.bk__break { width: 100%; color: var(--color-muted); }
.bk__break[disabled] { opacity: .45; }

.bk__fate { display: flex; gap: 10px; margin: 6px 0 14px; }
.bk__fate .btn { flex: 1; }
.bk__fate .btn.is-active {
  border-color: var(--color-accent);
  color: var(--color-accent);
}

/* ── Поручения ─────────────────────────────────────────────────────────── */
.zd { display: flex; flex-direction: column; gap: 10px; margin-bottom: 8px; }

/* ⚠ Колонка, а не строка. Здесь стоял flex с justify-content:
   space-between — и это работало, пока в карточке было двое детей:
   текст слева, кнопка справа. Потом добавились поля ответа
   и переписка, детей стало четыре — и поручение встало в ряд
   четырьмя узкими колонками, текст поверх полей (владелец,
   15.09.2026). Карточка растёт сверху вниз, и раскладка обязана
   выдержать любое число блоков, а не ровно те, что были вчера. */
.zd__item {
  display: grid; gap: 12px;
  padding: 14px 16px;
  border: 1px solid var(--color-border);
  border-left: 3px solid var(--color-border-strong, rgba(0,0,0,.2));
  border-radius: var(--radius-md);
  background: var(--color-surface-raised);
}
/* Срочное и просроченное — цветом слева, а не красным текстом: заметно
   боковым зрением, но не кричит на весь экран. */
.zd__item.is-urgent  { border-left-color: var(--color-accent); }
.zd__item.is-overdue { border-left-color: var(--color-error, #c0392b); }

.zd__body { min-width: 0; }
.zd__title { display: block; font-size: 15.5px; line-height: 1.3; }
.zd__note  { margin: 6px 0 0; font-size: 13.5px; color: var(--color-text-soft); line-height: 1.5; }
.zd__due   { display: inline-block; margin-top: 6px; font-size: 12.5px; color: var(--color-muted); }
.zd__item.is-overdue .zd__due { color: var(--color-error, #c0392b); }
/* Кнопка внизу во всю ширину: это телефон в зале, и попасть
   пальцем важнее аккуратности. На широком экране кнопка во всю
   карточку выглядит плакатом, там она по содержимому. */
.zd__item > .btn { justify-self: stretch; }

@media (min-width: 900px) {
  .zd__item > .btn { justify-self: start; }
}


/* ── Пошаговые подсказки ───────────────────────────────────────────────── */
.tour { position: fixed; inset: 0; z-index: 200; }

/* ⚠ Здесь стояло `body.tour-open { overflow: hidden }` — и именно оно
   ломало весь тур. Блокировка прокрутки включалась ДО того, как движок
   вызывал scrollIntoView, поэтому прокрутка просто не происходила:
   страница оставалась там, где была, рамка вставала вокруг случайного
   блока, а нужный элемент был за краем экрана.

   Замок больше не нужен: рамка пересчитывается каждый кадр и следует
   за элементом, даже если человек листает страницу пальцем. */

.tour__dim { position: absolute; inset: 0; background: rgba(0, 0, 0, .55); }

.tour__ring {
  position: absolute;
  border-radius: 12px;
  /* Сама рамка и затемнение всего остального — одной тенью: вырез
     в тёмном слое делает подсвеченное место единственным светлым
     пятном на экране, мимо не посмотришь. */
  box-shadow: 0 0 0 9999px rgba(0, 0, 0, .62),
              0 0 0 3px var(--color-accent-light, #D9B383),
              0 0 22px 4px rgba(217, 179, 131, .45);
  pointer-events: none;
  animation: tour-pulse 1.6s ease-in-out infinite;
}

/* Лёгкое дыхание рамки: на фото экрана и в движении глаз цепляется
   за изменение, а не за статичную линию. */
@keyframes tour-pulse {
  0%, 100% { box-shadow: 0 0 0 9999px rgba(0, 0, 0, .62),
                         0 0 0 3px var(--color-accent-light, #D9B383),
                         0 0 22px 4px rgba(217, 179, 131, .45); }
  50%      { box-shadow: 0 0 0 9999px rgba(0, 0, 0, .62),
                         0 0 0 3px var(--color-accent-light, #D9B383),
                         0 0 30px 10px rgba(217, 179, 131, .22); }
}

@media (prefers-reduced-motion: reduce) { .tour__ring { animation: none; } }

/* ⚠ Карточка стоит у КРАЯ ЭКРАНА, а не у элемента. Привязка к элементу
   уводила её за нижний край на длинных страницах: экран темнел, текста
   видно не было. Теперь она всегда на виду, а куда смотреть — показывает
   подсветка. */
.tour__tip {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  width: min(92vw, 440px);
  padding: 18px 20px 16px;
  border-radius: 16px;
  background: var(--color-surface-raised);
  color: var(--color-text);
  box-shadow: 0 14px 48px rgba(0, 0, 0, .5);
  transition: top .2s ease, bottom .2s ease;
}
.tour__tip--bottom { bottom: max(20px, env(safe-area-inset-bottom, 0px) + 16px); top: auto; }
.tour__tip--top    { top: max(20px, env(safe-area-inset-top, 0px) + 16px); bottom: auto; }
.tour__tip--center { top: 50%; bottom: auto; transform: translate(-50%, -50%); }

/* Точки прогресса: видно, сколько осталось, и тур перестаёт казаться
   бесконечным. */
.tour__dots { display: flex; gap: 5px; margin-bottom: 10px; }
.tour__dots i {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--color-border-strong, rgba(0,0,0,.25));
}
.tour__dots i.is-now  { background: var(--color-accent); width: 18px; border-radius: 3px; }
.tour__dots i.is-done { background: var(--color-accent-light, #D9B383); }

.tour__title { font-size: 17px; font-weight: 700; margin: 0 0 8px; line-height: 1.25; }
.tour__text  { font-size: 14.5px; line-height: 1.6; color: var(--color-text-soft); margin: 0; }

.tour__row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-top: 16px;
}
.tour__nav { display: flex; align-items: center; gap: 10px; }
.tour__skip, .tour__back {
  border: 0; background: none; padding: 8px 0;
  color: var(--color-muted); font: inherit; font-size: 14px; cursor: pointer;
}
.tour__back { text-decoration: underline; }

/* Строки настроек кабинета: подсказки, звук, уведомления. Раньше это был
   голый текст с кнопкой сбоку — между карточками «Мой заработок» и
   «Открыть сайт» такие строки читались как обрывки, а на узком экране
   кнопки уезжали друг под друга. Теперь та же карточка, что у соседей,
   и кнопки всегда в один ряд. */
.fh__tour {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  flex-wrap: wrap;
  padding: 12px 16px; margin-bottom: 12px;
  border: 1px solid var(--color-border); border-radius: var(--radius-md);
  background: var(--color-surface-raised);
  font-size: var(--fs-sm); color: var(--color-text-soft);
}
.fh__tour > span:first-child { flex: 1 1 150px; }


/* Кнопки в шапке: подсказки и тема — одного размера и рядом. */
.fl__head-tools { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }
a.fl__theme { text-decoration: none; }

/* ── Заработок ─────────────────────────────────────────────────────────── */
/* Итог крупно, разбор под ним: зарплату смотрят ради суммы, но верят ей
   только когда видно, из чего она сложилась. */
.zp__total {
  display: flex; flex-direction: column; gap: 2px;
  padding: 16px 18px; margin-bottom: 14px;
  border-radius: var(--radius-md);
  background:
    linear-gradient(135deg, rgba(185, 138, 70, .12) 0%, transparent 60%),
    var(--color-surface-raised);
  border: 1px solid var(--color-border);
}
.zp__total span { font-size: var(--fs-sm); color: var(--color-muted); }
.zp__total b { font-size: 30px; font-weight: 700; color: var(--color-accent); }

.zp__rows { display: flex; flex-direction: column; }
.zp__row {
  display: grid; grid-template-columns: 1fr auto;
  gap: 2px 12px; padding: 12px 0;
  border-bottom: 1px solid var(--color-border);
}
.zp__row:last-child { border-bottom: none; }
.zp__row span { font-size: 15px; }
.zp__row b { grid-column: 1; font-size: 13px; font-weight: 400; color: var(--color-muted); }
.zp__row em { grid-row: 1 / span 2; grid-column: 2; align-self: center;
  font-style: normal; font-size: 16px; font-weight: 600; }

.zp__tier {
  margin-top: 16px; padding: 14px 16px;
  border-radius: var(--radius-md); background: var(--color-surface);
  font-size: 14.5px; line-height: 1.55;
}
.zp__tier p { margin: 0 0 8px; }
.zp__tier p:last-child { margin-bottom: 0; }
.zp__next { color: var(--color-accent); }

.fh__money {
  display: flex; align-items: center; gap: 12px;
  padding: 14px 16px; margin-bottom: 14px;
  border: 1px solid var(--color-border); border-radius: var(--radius-md);
  background: var(--color-surface-raised); color: var(--color-text);
  text-decoration: none;
}
.fh__money svg { color: var(--color-accent); flex: 0 0 auto; }
.fh__money b { display: block; font-size: 15.5px; }
.fh__money em { font-style: normal; font-size: 13px; color: var(--color-muted); }

/* ── Смена ─────────────────────────────────────────────────────────────── */
.sm {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 12px 14px; margin-bottom: 14px;
  border: 1px solid var(--color-border); border-radius: var(--radius-md);
  background: var(--color-surface);
}
/* Своя смена — спокойный вид. Чужая остаётся заметной: если вышел
   не тот, кто записан, это надо увидеть до первой продажи. */
.sm.is-mine { border-color: var(--color-border); background: var(--color-surface-raised); }
.sm:not(.is-mine) { border-left: 3px solid var(--color-accent); }
.sm__body b { display: block; font-size: 15px; }
.sm__body span { font-size: 13px; color: var(--color-muted); }


/* Копейки в счётчике — мельче рублей: сумма читается сразу, а движение
   заметно боковым зрением и не мельтешит. */
.zp__total b small { font-size: 0.5em; font-weight: 600; letter-spacing: .01em; }

/* ── Чек-лист ──────────────────────────────────────────────────────────── */
.cl__progress { display: flex; align-items: center; gap: 10px; margin: 4px 0 18px; }
.cl__bar { flex: 1; height: 6px; border-radius: 3px; background: var(--color-surface); overflow: hidden; }
.cl__bar i { display: block; height: 100%; background: var(--color-accent); transition: width .3s ease; }
.cl__progress span { font-size: var(--fs-sm); color: var(--color-muted); white-space: nowrap; }

.cl__item {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 12px 0; border-bottom: 1px solid var(--color-border);
}
.cl__item.is-done .cl__text { color: var(--color-muted); text-decoration: line-through; }

/* Кружок-галочка крупный: по нему попадают мокрым пальцем, стоя
   со шваброй, и промах раздражает сильнее, чем сама уборка. */
.cl__check {
  flex: 0 0 auto; width: 30px; height: 30px; margin-top: 2px;
  border: 2px solid var(--color-border-strong, rgba(0,0,0,.25));
  border-radius: 50%; background: none; cursor: pointer;
  font-size: 17px; line-height: 1; color: var(--color-accent);
}
.cl__item.is-done .cl__check { border-color: var(--color-accent); background: rgba(185,138,70,.12); }

.cl__body { min-width: 0; flex: 1; }
.cl__text { margin: 0; font-size: 15px; line-height: 1.45; }
.cl__need {
  display: inline-block; margin-top: 4px; font-size: 12px;
  color: var(--color-accent); 
}
.cl__who { display: block; margin-top: 4px; font-size: 12px; color: var(--color-muted); }
.cl__photo { display: block; margin-top: 8px; width: 120px; border-radius: 8px; }

.cl__camera {
  flex: 0 0 auto; width: 38px; height: 38px;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--color-border); border-radius: 50%;
  color: var(--color-muted); cursor: pointer;
}

/* ── Первый вход ───────────────────────────────────────────────────────── */
.pv { max-width: 640px; margin: 0 auto; padding: 0 16px 40px; }

.pv__hero {
  position: relative; margin: 0 -16px 24px;
  aspect-ratio: 4/3; overflow: hidden;
}
.pv__hero img { width: 100%; height: 100%; object-fit: cover; object-position: center 35%; display: block; }
.pv__hero::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(20,17,13,.1) 0%, rgba(20,17,13,.85) 100%);
}
.pv__hero-text { position: absolute; left: 20px; right: 20px; bottom: 20px; z-index: 1; }
.pv__hello {
  margin: 0 0 6px; color: #fff; font-size: 28px; line-height: 1.15;
  font-family: var(--font-display, inherit);
}
.pv__hello b { color: var(--color-accent-light, #D9B383); }
.pv__where { margin: 0; color: rgba(255,255,255,.85); font-size: 14px; }

.pv__block { margin-bottom: 28px; }
.pv__block h2 { font-size: 18px; margin: 0 0 10px; }
.pv__block p { margin: 0 0 10px; font-size: 15px; line-height: 1.6; color: var(--color-text-soft); }

/* Шаги установки — нумерованные и крупные: по ним идут пальцем,
   сверяясь с экраном телефона, а не читают глазами. */
.pv__steps {
  margin: 14px 0; padding-left: 22px;
  font-size: 15px; line-height: 1.7; color: var(--color-text);
}
.pv__steps li { margin-bottom: 8px; }

.pv__btn { width: 100%; margin-top: 8px; }
.pv__other {
  margin-top: 10px; padding: 6px 0; border: 0; background: none;
  color: var(--color-muted); font: inherit; font-size: 14px;
  text-decoration: underline; cursor: pointer;
}
.pv__all {
  margin-top: 10px; padding: 12px 14px; border-radius: var(--radius-md);
  background: var(--color-surface); font-size: 14px; line-height: 1.6;
}
.pv__all p { margin: 0 0 8px; }
.pv__all p:last-child { margin: 0; }
.pv__skip { margin-top: 14px; text-align: center; font-size: 14px; }


/* ── Быстрый переход на главной кабинета ───────────────────────────────
   Папки отвечают на вопрос «что здесь вообще есть», но в ежедневной
   работе открывают одни и те же восемь мест. Одной строкой их ставить
   нельзя — на телефоне получается горизонтальная лента, и половина
   уезжает за край незамеченной. Поэтому сетка: видно всё сразу. */
.qt {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(88px, 1fr));
  gap: 8px;
}

.qt__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  gap: 6px;
  padding: 12px 6px 10px;
  min-height: 84px;
  border-radius: 14px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  color: var(--color-text);
  text-decoration: none;
  text-align: center;
  transition: border-color .15s ease, transform .12s ease;
}

.qt__item:active { transform: scale(.96); }
.qt__item:hover  { border-color: var(--color-accent-light, #D9B383); }
.qt__item svg    { color: var(--color-accent); flex: none; }
.qt__item span   { font-size: 12px; line-height: 1.25; }

@media (min-width: 600px) {
  .qt { grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); }
  .qt__item span { font-size: 13px; }
}

/* ═══ Клиент на кассе ════════════════════════════════════════════════════
   Экран для одного движения: ввёл телефон — увидел баллы — провёл покупку.
   Крупные цифры и большие поля: флорист работает стоя, одной рукой,
   пока покупатель ждёт */
.kl {
    /* ⚠ Было var(--fl-card, #fff): такой переменной в проекте нет,
       то есть всегда применялся запасной белый. В тёмной теме выходила
       белая карточка с чёрным полем ввода внутри. */
    background: var(--color-surface-raised);
    border-radius: 14px;
    padding: 16px;
    margin-bottom: 14px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .06);
}

.kl h2 { margin: 0 0 8px; font-size: 18px; }

.kl__big {
    font-size: 30px;
    font-weight: 700;
    margin: 6px 0 10px;
    line-height: 1.1;
}

/* Итог проведения выделен: именно здесь написано, какую скидку
   поставить в кассовой программе — пропустить это нельзя */
.kl--result { border-left: 4px solid var(--color-accent, #b07d4b); }

.kl__form { display: flex; flex-direction: column; gap: 12px; margin-top: 12px; }

/* Поля крупные: на телефоне в них попадают пальцем, а не курсором */
.kl__form .input { font-size: 17px; padding: 12px 14px; }
.kl__form .btn { padding: 14px; font-size: 16px; }

/* Ячейка, которую нельзя рвать переносом: «230 ₽», «10 шт», «3 дн.».
   На узком экране браузер уносит знак рубля на вторую строку, и колонка
   цен читается как каша. */
.nowrap { white-space: nowrap; }

/* Кто вошёл и выход — подвал кабинета. Мелко и без акцента: нажимают
   один раз за смену, но найтись должно с первого взгляда, иначе на общем
   телефоне пересменка проходит под чужим именем. */
.fh__who {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  margin: 18px 0 4px; font-size: var(--fs-sm); color: var(--color-muted);
}

/* Пометка личного поручения: адресное и общее иначе выглядят одинаково,
   и «это к тебе, а не к тому, кто выйдет завтра» пропадает. */
.zd__mine {
  display: inline-block; margin-bottom: 4px;
  padding: 1px 8px; border-radius: 10px;
  background: var(--color-accent); color: #fff;
  font-size: 11px; font-weight: 600; letter-spacing: .02em;
}

/* Поле выбора файла: прозрачное и размером в пиксель, но не display:none.
   Замечание 13.09.2026 — фото не добавлялось: часть встроенных браузеров
   по скрытому через hidden полю выбор файла не открывает вовсе. */
.vt__file, .file-pick {
  position: absolute; width: 1px; height: 1px;
  opacity: 0; overflow: hidden; clip-path: inset(50%);
}
/* Кнопка-подпись должна быть точкой отсчёта для спрятанного поля,
   иначе оно улетает в угол страницы и на части телефонов клик
   по подписи до него не доходит. */
label:has(> .file-pick), label:has(> .vt__file) { position: relative; }
.vt__photo-pick .btn { position: relative; }

/* Остатки по видам: строка-заголовок группы внутри таблицы. Слева
   название вида, справа — сколько в нём позиций. */
.sk__group th {
  padding-top: 18px; background: transparent; text-align: left;
  font-family: inherit; font-size: 15px; font-weight: 700;
  text-transform: none; letter-spacing: 0; color: var(--color-text);
  border-bottom: 1px solid var(--color-border-strong);
}
.sk__group:first-child th { padding-top: 4px; }
.sk__count {
  margin-left: 8px; font-size: 12px; font-weight: 500; color: var(--color-muted);
}
/* Минус по остатку — не украшение: эту позицию надо поправить первой. */
.sk__minus { background: rgba(200, 60, 60, .14); color: var(--color-error); }

/* Витрина сеткой: две колонки на телефоне. Букет узнают по фотографии,
   а не по номеру — в ленте по 132 пикселя три розовых букета
   неразличимы. */
.vt__grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; }
.vt__grid .vt__photo { aspect-ratio: 3/4; }
@media (min-width: 520px) {
  .vt__grid { grid-template-columns: repeat(3, 1fr); }
}

/* Выбор букета на кассе картинкой. Плитки мельче витринных: здесь
   не любуются, а опознают — и рядом должно остаться место для суммы. */
.ks__pick {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px;
  margin-top: 6px;
}
.ks__pick-item {
  position: relative; padding: 0; border: 2px solid transparent;
  border-radius: 10px; overflow: hidden; background: var(--color-surface);
  cursor: pointer; text-align: left; line-height: 0;
}
.ks__pick-item img { width: 100%; aspect-ratio: 1; object-fit: cover; display: block; }
.ks__pick-item.is-on { border-color: var(--color-accent); }
.ks__pick-nophoto {
  display: flex; align-items: center; justify-content: center;
  aspect-ratio: 1; font-size: 11px; line-height: 1.3;
  color: var(--color-muted); background: var(--color-surface-raised);
}
.ks__pick-num {
  position: absolute; top: 5px; left: 5px;
  padding: 1px 6px; border-radius: 8px;
  background: rgba(0, 0, 0, .65); color: #fff;
  font-size: 12px; font-weight: 600; line-height: 1.5;
}
.ks__pick-price {
  display: block; padding: 5px 6px; font-size: 12px; line-height: 1.3;
  color: var(--color-text);
}
/* Заказанный с сайта на витрине стоит, но продать его второй раз нельзя */
.ks__pick-flag {
  position: absolute; top: 5px; right: 5px;
  padding: 1px 6px; border-radius: 8px;
  background: var(--color-warning, #b8781c); color: #fff;
  font-size: 11px; line-height: 1.5;
}

/* Несколько клиентов с одинаковым хвостом номера: выбирает человек.
   Имя крупнее номера — узнают всё-таки по имени. */
.kl__matches { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; }
.kl__match {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  padding: 12px 14px; border: 1px solid var(--color-border);
  border-radius: var(--radius-md); background: var(--color-surface-raised);
  color: var(--color-text); text-decoration: none;
}
.kl__match b { font-size: 16px; }
.kl__match span { color: var(--color-muted); font-size: var(--fs-sm); }
.kl__match em { margin-left: auto; font-style: normal; color: var(--color-accent); font-weight: 600; }

/* Поиск по панели: одно поле и кнопка, без фильтров — в зале не выбирают,
   где искать, а набирают слово. */
.ps__form { display: flex; gap: 8px; margin-bottom: 14px; }
.ps__input { flex: 1; font-size: 16px; }
.ps__hints { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 18px; }
.ps__hint {
  padding: 6px 12px; border-radius: var(--radius-pill);
  border: 1px solid var(--color-border); background: var(--color-surface);
  color: var(--color-text-soft); font-size: var(--fs-sm); text-decoration: none;
}
.ps__list { display: flex; flex-direction: column; gap: 8px; margin-bottom: 6px; }
.ps__item {
  display: block; padding: 12px 14px;
  border: 1px solid var(--color-border); border-radius: var(--radius-md);
  background: var(--color-surface-raised); color: var(--color-text);
  text-decoration: none;
}
.ps__item b { display: block; font-size: 15px; margin-bottom: 3px; }
.ps__item span { display: block; font-size: 13px; line-height: 1.5; color: var(--color-muted); }
/* Найденное слово подсвечено: иначе непонятно, почему строка в списке */
.ps__item mark {
  background: rgba(200, 150, 60, .3); color: inherit; padding: 0 2px; border-radius: 3px;
}

/* Как считается процент: таблица слоёв. Человек должен уметь пересчитать
   свою зарплату на бумаге — иначе цифра выглядит назначенной сверху. */
.zp__how {
  margin: 14px 0 18px; padding: 14px 16px;
  border: 1px solid var(--color-border); border-radius: var(--radius-md);
  background: var(--color-surface-raised);
}
.zp__how > summary { cursor: pointer; font-weight: 600; font-size: 15px; }
.zp__how p { margin: 12px 0; font-size: var(--fs-sm); line-height: 1.55; }
.zp__layers { width: 100%; border-collapse: collapse; font-size: 13px; margin: 10px 0; }
.zp__layers th {
  text-align: left; padding: 6px 8px; color: var(--color-muted);
  font-weight: 500; border-bottom: 1px solid var(--color-border);
}
.zp__layers td { padding: 7px 8px; border-bottom: 1px solid var(--color-border); }
.zp__layers td:nth-child(2), .zp__layers td:nth-child(3) { white-space: nowrap; }
/* Слой, до которого точка уже дошла: по нему деньги и считаются */
.zp__layers tr.is-on td { font-weight: 600; color: var(--color-text); }
.zp__layers tr:not(.is-on) td { color: var(--color-muted); }

/* Кто ещё в зале: на точке бывает двое, и человек должен видеть,
   открыта ли смена у напарника — от этого зависит, на кого запишется
   продажа. */
.sm__sosedi {
  display: block; margin-top: 6px;
  font-size: 12px; color: var(--color-accent);
}

/* ── QR приглашения и ссылка под ним ─────────────────────────────────
   Блок был в разметке с рождения, а стилей у него не было вовсе:
   картинка ложилась прямо на фон страницы, ссылка и кнопка вставали
   друг под другом во всю ширину.

   ⚠ Подложка под QR — белая в обеих темах, и это не оформление.
   Код рисуется тёмно-коричневым по прозрачному фону, и в тёмной теме
   он становится тёмным по тёмному: камера такой не читает вообще.
   Найдено владельцем 14.09.2026. Белое поле по краю тоже обязательно —
   это «тихая зона», без неё сканер не находит границы кода. */
.qs__qr {
  display: flex;
  gap: 14px;
  align-items: flex-start;
  margin-top: 10px;
}

.qs__qr img {
  flex: none;
  background: #fff;
  padding: 8px;
  border-radius: var(--radius-sm, 8px);
  /* Рамка нужна в светлой теме: белое на белом теряет границы */
  border: 1px solid var(--color-border, rgba(0, 0, 0, .1));
}

.qs__qr-side { min-width: 0; display: flex; flex-direction: column; gap: 8px; }

.qs__invite {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

/* Ссылка длинная, а место на телефоне узкое: даём ей сжиматься
   и переносить, а кнопке — остаться по размеру текста. */
.qs__invite code {
  flex: 1 1 180px;
  min-width: 0;
  overflow-wrap: anywhere;
  font-size: 12px;
  line-height: 1.35;
  color: var(--color-muted);
  background: var(--color-surface-2, rgba(0, 0, 0, .05));
  padding: 6px 8px;
  border-radius: var(--radius-sm, 8px);
}

.qs__invite .btn { flex: none; }

@media (max-width: 420px) {
  .qs__qr { gap: 10px; }
  .qs__qr img { width: 96px; height: 96px; }
}

/* ── Продажи смены и возврат ─────────────────────────────────────────── */
.ks__sales { display: flex; flex-direction: column; gap: 8px; margin-bottom: 20px; }

.ks__sale {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 12px 14px;
  background: var(--color-surface);
  border-radius: var(--radius-md, 12px);
  box-shadow: inset 0 0 0 1px var(--color-border, rgba(0,0,0,.08));
}

/* Возвращённая продажа гасится, но не прячется: она была, и в списке
   смены её отсутствие выглядело бы как пропавшие деньги. */
.ks__sale.is-refunded { opacity: .6; }

.ks__sale-main  { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ks__sale-time  { font-size: 13px; color: var(--color-muted); }
.ks__sale-items {
  font-size: 12px; color: var(--color-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ks__sale-back {
  font-size: 13px; color: var(--color-danger, #b3261e); white-space: nowrap;
}

/* ── Разделы списком: экран «Ещё» ────────────────────────────────────────
 *
 * Заменили плитки (14.09.2026). Пять одинаковых квадратов уравнивают
 * всё подряд: «Цветы» открывают каждый день, «Потери» — раз в неделю,
 * а выглядели они одинаково важными. Строка с подписью говорит не только
 * куда ведёт, но и зачем.
 *
 * Группы сшиты в одну карточку с разделителями между строками, а не
 * разложены отдельными плашками: так видно, что это один список, и глаз
 * не пересчитывает рамки. */
.fl__groups { margin-bottom: 4px; }

.fl__group-title {
  margin: 18px 0 8px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--color-muted);
}

.fl__group {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface-raised);
  overflow: hidden;
}

/* Внутренние блоки настроек (звук, уведомления, подсказки) лежат в той
   же карточке — снимаем их собственные рамки, чтобы не было рамки
   в рамке, и оставляем один разделитель на стык. */
.fl__group > .fh__tour {
  margin: 0;
  border: 0;
  border-radius: 0;
  background: none;
}
.fl__group > * + * { border-top: 1px solid var(--color-border); }

.fl__row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 13px 14px;
  color: inherit;
  text-decoration: none;
}
.fl__row-icon { flex: 0 0 auto; display: flex; color: var(--color-accent); }
.fl__row-text { flex: 1 1 auto; min-width: 0; }
.fl__row-text b { display: block; font-size: 15px; font-weight: 600; }
.fl__row-text em {
  display: block;
  font-style: normal;
  font-size: 13px;
  line-height: 1.35;
  color: var(--color-muted);
}
/* Стрелка — подсказка направления, а не элемент: приглушена намеренно,
   иначе пять стрелок спорят за внимание с названиями. */
.fl__row > svg:last-child { flex: 0 0 auto; color: var(--color-border); }
.fl__row:hover { background: var(--color-surface); }
.fl__row:hover .fl__row-text b { color: var(--color-accent); }
.fl__row:active { background: var(--color-surface); }

/* ═══ Ноутбук: те же пять разделов, но колонкой слева ══════════════════════
 *
 * Панель родилась под телефон, и на ноутбуке выглядела узкой полосой
 * посередине пустого экрана — 640 пикселей содержимого на 1600 экрана.
 * Владелец 14.09.2026: часть флористов привыкла работать с ноутбука,
 * и там «можно сделать красиво, чтобы всё было по полочкам».
 *
 * Разделы те же и в том же порядке — человек, пересевший с телефона
 * за ноутбук, не переучивается. Меняется только направление: полоска
 * внизу разворачивается в колонку слева.
 *
 * Почему 900px, а не 768: на планшете в альбомной ориентации нижняя
 * полоска ещё удобнее — до неё достаёт большой палец, а до левого края
 * тянуться через весь экран. Колонка оправдана там, где есть мышь.
 *
 * Всё держится на медиазапросе в css: разметка одна и та же, и второй
 * ветки шаблонов, которая неизбежно разошлась бы с первой, не заводим. */
@media (min-width: 900px) {
  :root { --fl-rail: 232px; }

  .fl__nav {
    top: 0;
    right: auto;
    width: var(--fl-rail);
    flex-direction: column;
    justify-content: flex-start;
    gap: 2px;
    padding: 88px 12px 16px;
    border-top: 0;
    border-right: 1px solid var(--color-border);
    background: var(--color-surface);
  }

  .fl__nav-item {
    flex: 0 0 auto;
    flex-direction: row;
    justify-content: flex-start;
    gap: 12px;
    padding: 11px 14px;
    border-radius: var(--radius-md);
    font-size: 15px;
    font-weight: 500;
  }

  /* На телефоне активный раздел показан цветом подписи — этого хватает,
     когда пунктов пять в ряд. В колонке подписи стоят одна под другой,
     и цвет один среди пяти читается хуже заливки. */
  .fl__nav-item.is-active {
    background: var(--color-surface-raised);
    color: var(--color-text);
  }
  .fl__nav-item.is-active svg { color: var(--color-success); }
  .fl__nav-item:hover { background: var(--color-surface-raised); }

  .fl__head,
  .fl__main {
    max-width: 1040px;
    margin-left: calc(var(--fl-rail) + 32px);
    margin-right: 32px;
  }

  /* Нижней полоски нет — и запас под неё не нужен: на широком экране
     это была бы пустая треть страницы под последней строкой. */
  .fl__main { padding-bottom: 40px; }

  .fl__head { padding-top: 28px; }
  .fl__title { font-size: 26px; }

  /* Списки разделов и настроек встают в две колонки: на ширине 1040
     одноколоночный список — это строка в 15 слов и полметра пустоты
     справа от неё. */
  .fl__groups {
    display: grid;
    grid-template-columns: 1fr 1fr;
    align-items: start;
    gap: 4px 24px;
  }
  .fl__gblock:nth-child(-n+2) .fl__group-title { margin-top: 0; }

  /* Обложка кабинета не растягивается на всю ширину: фотография
     в 1040 пикселей перестаёт быть шапкой и становится баннером. */
  .fh__cover { max-width: 560px; }

  /* Слово компании читают, а не просматривают: строка длиннее
     примерно ста знаков теряется на переносе. */
  .fh__note { max-width: 72ch; }

  /* Таблицы (склад, заработок, продажи) на телефоне ужимаются по
     содержимому — на широком экране от этого остаётся узкий столбик
     у левого края и полметра пустоты. Числа при этом перестают быть
     столбиком: глаз сравнивает их по правому краю, а край плавает. */
  .fl__main table { width: 100%; }

  /* Витрина: четвёртая колонка помещается без потери размера кадра,
     а букет по-прежнему узнают по фотографии. */
  .vt__grid { grid-template-columns: repeat(4, 1fr); }

  /* Форма обратной связи и поля ввода не растягиваются на всю ширину:
     поле в 1000 пикселей выглядит как приглашение написать сочинение. */
  .rb__note textarea,
  .fl__main .field { max-width: 640px; }
}

/* Широкий экран: содержимое перестаёт расти, а поля растут. Читать
   строку длиннее ста знаков тяжело независимо от того, сколько места
   на столе. */
@media (min-width: 1500px) {
  .fl__head,
  .fl__main { margin-left: auto; margin-right: auto; padding-left: 24px; padding-right: 24px; }
}

/* ── Плашки быстрого выбора рода ─────────────────────────────────────────
 *
 * Горизонтальная лента над поиском: в зале их листают большим пальцем,
 * а не переносят на три строки — перенос съел бы половину экрана
 * ровно в тот момент, когда на нём нужен список товара.
 *
 * Полоса прокрутки спрятана, но края намеренно не выровнены по контейнеру:
 * последняя плашка чуть «выглядывает», и по ней видно, что лента длиннее
 * экрана. Ровный край читается как конец списка. */
.rd {
  display: flex;
  gap: 8px;
  /* Воздух с обеих сторон: лента плашек — это отдельный способ
     искать, а не подпись к полю и не шапка таблицы. Слипшись
     с полем сверху и со списком снизу, она читается как часть
     то одного, то другого. */
  margin: 14px 0 20px;
  padding-bottom: 4px;
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.rd::-webkit-scrollbar { display: none; }

.rd__chip {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 13px;
  border: 1px solid var(--color-border);
  border-radius: 999px;
  background: var(--color-surface-raised);
  color: var(--color-text-soft);
  font-size: 14px;
  line-height: 1.2;
  white-space: nowrap;
  cursor: pointer;
}
.rd__chip:hover { border-color: var(--color-accent); color: var(--color-accent); }

/* Выбранная плашка залита, а не обведена: обводка на ленте из восьми
   одинаковых пилюль теряется, особенно на солнце. */
.rd__chip.is-active {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: #fff;
}
.rd__chip.is-active:hover { color: #fff; }

/* Счётчик позиций: он подсказывает, стоит ли вообще нажимать. */
.rd__n { font-size: 12px; color: var(--color-muted); }
.rd__chip.is-active .rd__n { color: rgba(255, 255, 255, .8); }

.rd__chip--off { color: var(--color-muted); }

/* На ноутбуке ленте прокручиваться незачем — места хватает, и плашки
   раскладываются в несколько рядов. */
@media (min-width: 900px) {
  .rd { flex-wrap: wrap; overflow-x: visible; }
}

/* ── Личный кабинет сотрудника ───────────────────────────────────────────
 *
 * Кружок с фотографией или инициалами. Пустой серый круг читается как
 * поломка, буква — как заготовка, которую хочется заменить. */
.lk__avatar {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 96px; height: 96px;
  border-radius: 50%;
  overflow: hidden;
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border);
  color: var(--color-muted);
  font-size: 30px;
  font-weight: 600;
  letter-spacing: .02em;
}
.lk__avatar img { width: 100%; height: 100%; object-fit: cover; }
.lk__avatar--sm { width: 44px; height: 44px; font-size: 16px; }

.lk__avatar-row { display: flex; align-items: center; gap: 16px; margin-bottom: 18px; }
.lk__pick { display: inline-flex; position: relative; }

/* Строка «Мой профиль» в кабинете: та же форма, что у разделов ниже,
   но с лицом вместо значка — она про человека, а не про раздел. */
.lk__me {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  margin: 12px 0;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface-raised);
  color: inherit;
  text-decoration: none;
}
.lk__me-text { flex: 1 1 auto; min-width: 0; }
.lk__me-text b { display: block; font-size: 15px; font-weight: 600; }
.lk__me-text em {
  display: block; font-style: normal; font-size: 13px; line-height: 1.35;
  color: var(--color-muted);
}
.lk__me > svg:last-child { flex: 0 0 auto; color: var(--color-border); }
.lk__me:hover { border-color: var(--color-accent); }
.lk__me:hover .lk__me-text b { color: var(--color-accent); }

/* Условия работы: не поля, а факты. Показываются строкой «слева
   название, справа значение» — так же, как итоги в кассе, чтобы
   не выглядели незаполненной формой. */
.lk__fact {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  padding: 12px 14px;
  font-size: 14px;
  color: var(--color-text-soft);
}
.lk__fact + .lk__fact { border-top: 1px solid var(--color-border); }
.lk__fact b { font-size: 15px; color: var(--color-text); text-align: right; }

.lk__form { margin-bottom: 8px; }

/* ── Карточки сотрудников в админке ──────────────────────────────────────
 *
 * Строка таблицы отвечала «какой у неё код» и молчала обо всём
 * остальном. Карточка отвечает на вопрос, с которым сюда приходят:
 * как у человека дела. */
.lyudi { display: grid; gap: 14px; }

@media (min-width: 900px) {
  .lyudi { grid-template-columns: repeat(auto-fill, minmax(380px, 1fr)); }
}

.lyudi__card {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface-raised);
  padding: 14px 16px;
}
.lyudi__card.is-off { opacity: .55; }

.lyudi__head { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.lyudi__who { flex: 1 1 auto; min-width: 0; }
.lyudi__who b { display: block; font-size: 16px; font-weight: 650; }
.lyudi__who span { display: block; font-size: 13px; color: var(--color-muted); }

/* Четыре числа в ряд: выручка, чеки, средний чек, ставка. На телефоне
   в два столбца — иначе цифра сжимается до нечитаемой. */
.lyudi__nums {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px 14px;
  margin: 14px 0 10px;
}
@media (min-width: 560px) { .lyudi__nums { grid-template-columns: repeat(4, 1fr); } }

.lyudi__nums span {
  display: block; font-size: 12px; color: var(--color-muted);
  text-transform: uppercase; letter-spacing: .03em;
}
.lyudi__nums b { font-size: 17px; font-variant-numeric: tabular-nums; }

.lyudi__meta { font-size: 13px; color: var(--color-muted); line-height: 1.5; margin: 0 0 8px; }
.lyudi__about {
  font-size: 14px; color: var(--color-text-soft); font-style: italic;
  margin: 0 0 10px;
}

.lyudi__more { margin-bottom: 8px; }
.lyudi__more > summary {
  cursor: pointer; font-size: 13.5px; color: var(--color-text-soft);
  padding: 6px 0;
}
.lyudi__more[open] > summary { color: var(--color-accent); }

.lyudi__doc { display: flex; justify-content: space-between; gap: 10px; font-size: 14px; margin: 6px 0; }
.lyudi__doc span { color: var(--color-muted); font-size: 12.5px; white-space: nowrap; }

.lyudi__doc-add,
.lyudi__code { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-top: 8px; }
.lyudi__doc-add .input,
.lyudi__code .input { flex: 1 1 140px; min-width: 0; }

.lyudi__act { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 10px; }

/* Цифра на плитке быстрого перехода.
   Счётчики работы показывались только в боковом меню, а на телефоне оно
   скрыто — там владелец не видел ни одного счётчика вовсе. Угол плитки
   стоит дёшево и отвечает на «куда идти» до того, как открыть раздел. */
.qt__item { position: relative; }
.qt__item.has-n { border-color: var(--color-accent); }
.qt__n {
  position: absolute;
  top: 6px;
  right: 6px;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: var(--radius-pill, 999px);
  background: var(--color-accent);
  color: var(--color-on-accent);
  font-size: 11px;
  font-weight: 500;
  line-height: 18px;
  text-align: center;
}

/* Поля внутри поручения: система спрашивает число, а не «сделано ли». */
/* Отступы даёт gap самой карточки — свои margin здесь удвоили бы его. */
.zd__form { display: grid; gap: 10px; margin: 0; }
.zd__form .field { margin: 0; }

/* Переписка по поручению. Реплики разных сторон отличаются краем,
   а не цветом: цветных пузырей в панели нет нигде, и заводить их ради
   двух строк значит сделать поручение похожим на мессенджер, которым
   оно не является. */
.zd__chat { margin: 0; display: grid; gap: 8px; }
.zd__msg {
  padding: 8px 10px;
  border-left: 3px solid var(--color-border);
  background: var(--color-surface);
  border-radius: 0 var(--radius-sm, 8px) var(--radius-sm, 8px) 0;
  font-size: 14px;
  line-height: 1.45;
}
.zd__msg--owner { border-left-color: var(--color-accent); }
.zd__msg--system { border-left-color: var(--color-muted); font-style: italic; }
.zd__msg-who { display: block; font-size: 12px; color: var(--color-muted); margin-bottom: 2px; }

.zd__say { display: flex; gap: 8px; align-items: center; }
.zd__say .input { flex: 1 1 auto; min-width: 0; }
/* Кнопка по размеру поля, без слова: на 375 px текст «Отправить»
   забирал треть строки у того, ради чего она стоит. */
.zd__send {
  flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  width: 42px; height: 42px; padding: 0;
}

.zd__adm { margin-top: 8px; }
.zd__adm > summary { cursor: pointer; font-size: 13px; color: var(--color-muted); }
.zd__adm .zd__msg { margin-top: 6px; }
.zd__adm .zd__say { margin-top: 8px; }

/* Полоса прогресса длинной операции. Не украшение: тридцать секунд
   молчащей кнопки читаются как «не работает», человек жмёт ещё раз
   и занимает второй процесс php из пяти — на этом сервере этого хватает,
   чтобы админка перестала отвечать. */
.ofd__go { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.ofd__progress { margin-top: 12px; }
.ofd__bar {
  height: 8px;
  border-radius: 999px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  overflow: hidden;
}
.ofd__bar i {
  display: block;
  height: 100%;
  background: var(--color-accent);
  transition: width .3s ease;
}

/* Погода в углу обложки. Мелко и поверх фото: это справка на полсекунды,
   а не содержимое экрана. */
.fh__pogoda {
  position: absolute;
  top: 10px; right: 10px;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 10px;
  border-radius: 999px;
  background: rgba(0, 0, 0, .45);
  backdrop-filter: blur(6px);
  color: #fff;
  font-size: 13px;
  line-height: 1;
}
.fh__pogoda-znak { font-size: 15px; }
.fh__pogoda-temp { font-weight: 700; font-variant-numeric: tabular-nums; }
.fh__pogoda-slovo { opacity: .85; }

/* Плашка про упаковку в дождь. Заметная намеренно: она появляется
   редко и должна остановить взгляд именно в тот день, когда льёт. */
.fh__alert {
  padding: 12px 14px;
  margin-bottom: 12px;
  border: 1px solid var(--color-warning);
  border-left-width: 4px;
  border-radius: var(--radius-md);
  background: var(--color-surface-raised);
  font-size: 14px;
  line-height: 1.5;
}
.fh__alert b { display: block; margin-bottom: 2px; }

/* Сезон и ближайшая дата: фон без рамки — это фоновое знание,
   а не задача. Рамка поставила бы его вровень с поручениями. */
.fh__sezon {
  padding: 12px 14px;
  margin-bottom: 12px;
  border-radius: var(--radius-md);
  background: var(--color-surface);
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--color-text-soft);
}
.fh__sezon p { margin: 0; }
.fh__sezon-den { margin-top: 6px !important; color: var(--color-text); }

/* ── Памятка про баллы на экране «Клиент» ─────────────────────────────
   Флорист читает её не за чаем, а между покупателями. Отсюда крупная
   фраза-реплика сверху (её произносят вслух) и свёрнутые подробности:
   развёрнутый текст на этом экране отодвинул бы поиск по телефону,
   ради которого сюда и заходят. */
.kl--pamyatka { background: var(--color-surface); }
.kl__skazat {
  margin: 0 0 8px;
  padding: 12px 14px;
  border-radius: var(--radius-md);
  background: var(--color-bg);
  border-left: 3px solid var(--color-accent, #b07d4b);
  font-size: 16px;
  line-height: 1.45;
}

.kl__det { margin-top: 10px; }
.kl__det > summary {
  cursor: pointer;
  padding: 10px 0;
  font-weight: 600;
  font-size: 15px;
  list-style: none;
}
.kl__det > summary::-webkit-details-marker { display: none; }
.kl__det > summary::before { content: '▸ '; color: var(--color-muted); }
.kl__det[open] > summary::before { content: '▾ '; }

.kl__qa { margin: 4px 0 0; }
.kl__qa dt { margin-top: 12px; font-weight: 600; font-size: 14.5px; }
.kl__qa dd {
  margin: 4px 0 0;
  font-size: 14px;
  line-height: 1.5;
  color: var(--color-text-soft);
}

/* Переписка показана перепиской, а не списком фраз: флорист должен
   узнать этот вид, когда клиент повернёт к нему телефон. */
.kl__chat { display: flex; flex-direction: column; gap: 6px; margin: 10px 0; }
.kl__msg {
  margin: 0;
  max-width: 85%;
  padding: 9px 12px;
  border-radius: 14px;
  font-size: 14px;
  line-height: 1.45;
}
.kl__msg--bot { align-self: flex-start; background: var(--color-bg); border-bottom-left-radius: 4px; }
.kl__msg--man {
  align-self: flex-end;
  background: var(--color-accent, #b07d4b);
  color: #fff;
  border-bottom-right-radius: 4px;
}

.kl__qr { display: flex; gap: 14px; align-items: flex-start; margin-top: 14px; }
.kl__qr img { border-radius: var(--radius-md); background: #fff; flex: none; }
.kl__qr b { display: block; margin-bottom: 4px; }
.kl__qr p { margin: 0; }

/* Чужая касса объясняется один раз на точку, над её карточками:
   под каждым человеком та же фраза читалась бы как шум. */
.lyudi__tochka-slovo {
  font-size: 13.5px; color: var(--color-muted); line-height: 1.5;
  margin: -4px 0 12px; max-width: 62ch;
}

/* ═══ components/osnovy.css ═══ */

/* Курс «Основы» в панели флориста (florist/osnovy*.php).

   Отдельный файл, а не хвост florist.css: там каркас панели, который
   касается всех экранов, а здесь — учебные страницы со своей графикой.
   Смешаешь — и правка схемы поедет проверять «Работу» и «Цветы».

   Всё построено под чтение с телефона одной рукой в зале: короткие блоки,
   крупные зоны нажатия, схемы во всю ширину. Цвета долек цветового круга
   приходят из PHP атрибутом fill — это данные (какие тона бывают у цветка),
   а не оформление, и держать их в CSS было бы враньём про источник истины. */

/* ── Оглавление курса ──────────────────────────────────────────────────── */
.ku__list { list-style: none; margin: 0 0 4px; padding: 0; }

.ku__card {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 13px 14px;
  margin-bottom: 8px;
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  color: var(--color-text);
}
.ku__card:hover { border-color: var(--color-accent); }

.ku__num {
  flex: 0 0 auto;
  width: 28px; height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  font-size: 13px;
  font-weight: 700;
  color: var(--color-muted);
}
.ku__body { flex: 1 1 auto; min-width: 0; }
.ku__body b { display: block; font-size: 15.5px; font-weight: 700; }
.ku__body i { display: block; font-style: normal; font-size: 12.5px; color: var(--color-muted); line-height: 1.4; }

.ku__mins { flex: 0 0 auto; font-size: 12px; color: var(--color-muted); white-space: nowrap; }

/* Прочитанный урок не прячем и не гасим целиком: к нему возвращаются
   за конкретным правилом, а не читают заново — гашение мешало бы искать */
.ku__card.is-done .ku__num {
  background: var(--color-success, #2f9e6e);
  border-color: transparent;
  color: #fff;
  font-size: 0;
}
.ku__card.is-done .ku__num::after { content: '✓'; font-size: 14px; }

/* ── Значки достоверности ──────────────────────────────────────────────── */
.ku__badge {
  display: inline-block;
  padding: 1px 7px;
  border-radius: var(--radius-pill);
  font-size: 11px;
  font-weight: 600;
  line-height: 1.6;
  white-space: nowrap;
  vertical-align: baseline;
  cursor: help;
}
.ku__badge--kanon    { background: #e3f1e8; color: #1f6b45; }
.ku__badge--praktika { background: #e6edf7; color: #2b4f80; }
.ku__badge--spor     { background: #fdf0dd; color: #7a5312; }
.ku__badge--mif      { background: #fae3e1; color: #7d2f2a; }

.ku__legend p { margin: 0 0 8px; font-size: 13.5px; line-height: 1.55; color: var(--color-text-soft); }

/* ── Шапка урока ───────────────────────────────────────────────────────── */
.ku__progress {
  position: sticky;
  top: 0;
  z-index: 20;
  height: 3px;
  margin: -12px -16px 10px;
  background: var(--color-border);
}
.ku__progress i { display: block; height: 100%; width: 0; background: var(--color-accent); }

.fl__back { display: flex; justify-content: space-between; align-items: center; }

/* «Если читать некогда» — весь урок в пяти строках. Стоит первым экраном
   намеренно: флорист в зале часто заходит за одним конкретным правилом */
.ku__tldr {
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border);
  border-left: 4px solid var(--color-accent);
  border-radius: var(--radius-md);
  padding: 13px 15px;
  margin-bottom: 18px;
}
.ku__tldr b { display: block; font-size: 13px; text-transform: uppercase; letter-spacing: .04em; color: var(--color-muted); margin-bottom: 8px; }
.ku__tldr ul { margin: 0; padding-left: 18px; }
.ku__tldr li { font-size: 14.5px; line-height: 1.5; margin-bottom: 6px; }
.ku__tldr li:last-child { margin-bottom: 0; }

/* ── Интерактивные схемы ───────────────────────────────────────────────── */
.ku__demo {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px;
  padding: 14px;
  margin: 4px 0 16px;
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
}
.ku__demo > svg { flex: 0 0 auto; width: 200px; max-width: 100%; height: auto; margin-inline: auto; }
.ku__demo-side { flex: 1 1 200px; min-width: 180px; display: flex; flex-direction: column; gap: 9px; }
.ku__demo-note { margin: 0; font-size: 13px; line-height: 1.5; color: var(--color-text-soft); }

.ku__count { display: flex; align-items: baseline; gap: 6px; }
.ku__count b { font-size: 26px; font-weight: 700; line-height: 1; }
.ku__count span { font-size: 13px; color: var(--color-muted); }

.ku__ghost { background: transparent; border: 1px solid var(--color-border); color: var(--color-text); }

.ku__switch { display: flex; align-items: center; gap: 8px; font-size: 14px; cursor: pointer; min-height: 34px; }
.ku__switch input { width: 20px; height: 20px; accent-color: var(--color-accent); }

.ku__range { display: block; font-size: 13px; color: var(--color-muted); }
.ku__range input { width: 100%; margin-top: 6px; accent-color: var(--color-accent); height: 28px; }

.ku__toggle { display: flex; gap: 6px; }
.ku__toggle button {
  flex: 1;
  min-height: 40px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-pill);
  background: var(--color-surface);
  color: var(--color-text);
  font-size: 13.5px;
  cursor: pointer;
}
.ku__toggle button.is-active { background: var(--color-text); border-color: var(--color-text); color: var(--color-bg); }

/* Графика схем. Один набор классов на все уроки: линия стебля, головка,
   шапка, размерная линия — они повторяются в каждой схеме курса */
.ku__ring       { fill: none; stroke: var(--color-border); stroke-width: 1; stroke-dasharray: 4 4; }
.ku__knot       { fill: var(--color-accent); }
/* Зона связки — обвязка поверх стеблей, поэтому полупрозрачная заливка:
   сплошная спрятала бы под собой сходящиеся концы, то есть самое главное */
.ku__knot-zone  { fill: rgba(0, 0, 0, .05); stroke: var(--color-accent); stroke-width: 2; }
.ku__stem-line  { stroke: var(--color-text-soft); stroke-width: 2; stroke-linecap: round; }
.ku__stem-head  { fill: var(--color-surface); stroke: var(--color-text); stroke-width: 1.5; }
/* Головка на интерактивной схеме: заливка фоном, чтобы стебли не сквозили
   сквозь лепестки, и контур той же толщины, что у стебля */
.ku__bud { fill: var(--color-surface); stroke: var(--color-text); stroke-width: 1.6; }
.ku__bud--accent { fill: var(--color-accent); stroke: var(--color-accent); }
.ku__head       { fill: var(--color-surface); stroke: var(--color-text); stroke-width: 2; }
.ku__cut        { stroke: var(--color-muted); stroke-width: 1; stroke-dasharray: 4 3; }
.ku__grid line  { stroke: var(--color-muted); stroke-width: 1; stroke-dasharray: 3 3; }
.ku__dot        { fill: var(--color-accent); }

.ku__vase  { fill: none; stroke: var(--color-text); stroke-width: 2; }
.ku__crown { fill: var(--color-surface-raised); stroke: var(--color-text); stroke-width: 2; }
.ku__stem  { stroke: var(--color-text); stroke-width: 2; }
.ku__dim   { stroke: var(--color-muted); stroke-width: 1; stroke-dasharray: 4 3; }
.ku__dim-t { fill: var(--color-muted); font-size: 11px; font-family: var(--font-body); }

.ku__ratio { margin: 10px 0 14px; }
.ku__ratio svg { width: 100%; max-width: 300px; height: auto; display: block; margin-inline: auto; }

/* ── Выбор силуэта ─────────────────────────────────────────────────────
   Контуры, а не фотографии: у формы важен силуэт, а фотография показывает
   в первую очередь конкретные цветы — то есть ровно то, что здесь неважно */
.ku__forms {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 7px;
  margin-bottom: 12px;
}
@media (min-width: 480px) { .ku__forms { grid-template-columns: repeat(7, 1fr); } }

.ku__form {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  padding: 7px 3px 6px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  color: var(--color-muted);
  cursor: pointer;
}
.ku__form svg { width: 100%; height: auto; }
.ku__form span { font-size: 11px; line-height: 1.2; text-align: center; }
.ku__form.is-active {
  border-color: var(--color-accent);
  background: var(--color-surface-raised);
  color: var(--color-text);
}

.ku__silh { fill: none; stroke: currentColor; stroke-width: 5; stroke-linecap: round; stroke-linejoin: round; }
.ku__form.is-active .ku__silh { stroke-width: 6; }

/* Головки ставятся через transform scale, а он масштабирует и обводку:
   крупный бутон заливался в чёрное пятно, мелкий бледнел до ниточки.
   Обводку фиксируем — толщина считается в координатах схемы, а не головки */
.ku__bud, .ku__bud * { vector-effect: non-scaling-stroke; }

/* Головки внутри силуэта тоньше стеблей и без заливки: на кнопке шириной
   60 пикселей залитый контур превращается в чёрное пятно, а нужен силуэт */
.ku__silh .ku__bud { stroke-width: 3.4; fill: none; }
.ku__silh .ku__ground { stroke-width: 6; }

/* Задуманная форма — бледным пунктиром: она подсказка, а не часть букета */
.ku__silh .ku__guide { stroke-width: 3; stroke-dasharray: 7 6; opacity: .45; }

.ku__form-detail {
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 14px 16px;
  margin-bottom: 16px;
}
.ku__form-detail h3 { font-size: 17px; font-weight: 700; margin: 0; }
.ku__form-lead { margin: 2px 0 10px; font-size: 12.5px; color: var(--color-muted); }
.ku__form-detail > p { font-size: 14.5px; line-height: 1.55; color: var(--color-text-soft); margin: 0 0 12px; }
.ku__form-detail dl { margin: 0; }
.ku__form-detail dt {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--color-muted);
  margin-top: 10px;
}
.ku__form-detail dd { margin: 2px 0 0; font-size: 14px; line-height: 1.55; color: var(--color-text-soft); }

.ku__density { flex: 0 0 auto; width: 180px; }

/* Выбор повода: пилюли переносятся по строкам — поводов десяток, и в один
   ряд они не встанут ни на каком телефоне */
.ku__pills { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; }
.ku__pill {
  min-height: 38px;
  padding: 0 13px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-pill);
  background: var(--color-surface);
  color: var(--color-text);
  font-size: 13.5px;
  cursor: pointer;
}
.ku__pill.is-active { background: var(--color-text); border-color: var(--color-text); color: var(--color-bg); }

/* «Чего нельзя» — единственная строка разбора, которую нельзя пролистать
   мимо: у траура и роддома это вопрос обиды и безопасности, а не вкуса */
.ku__form-detail dt.is-taboo { color: #a33f36; }
.ku__form-detail dd.is-taboo { color: var(--color-text); }

/* ── Шесть вопросов ────────────────────────────────────────────────────── */
.ku__qa { list-style: none; counter-reset: qa; margin: 0 0 16px; padding: 0; }
.ku__qa li {
  counter-increment: qa;
  position: relative;
  padding: 10px 0 10px 34px;
  border-top: 1px solid var(--color-border);
}
.ku__qa li:first-child { border-top: none; }
.ku__qa li::before {
  content: counter(qa);
  position: absolute;
  left: 0; top: 10px;
  width: 24px; height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  font-size: 12px;
  font-weight: 700;
  color: var(--color-muted);
}
.ku__qa b { display: block; font-size: 14.5px; }
.ku__qa span { display: block; font-size: 13.5px; line-height: 1.55; color: var(--color-muted); margin-top: 2px; }

/* ── Диагностика: симптом → разбор ─────────────────────────────────────── */
.ku__diag { margin-bottom: 14px; }
.ku__diag-row {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  margin-bottom: 6px;
  background: var(--color-surface-raised);
  overflow: hidden;
}
.ku__diag-row > summary {
  padding: 11px 14px;
  cursor: pointer;
  list-style: none;
  font-size: 14.5px;
  font-weight: 600;
  position: relative;
}
.ku__diag-row > summary::-webkit-details-marker { display: none; }
.ku__diag-row > summary::after {
  content: '+';
  position: absolute;
  right: 14px; top: 50%;
  transform: translateY(-50%);
  color: var(--color-muted);
  font-size: 18px;
}
.ku__diag-row[open] > summary::after { content: '\2212'; }
.ku__diag-row > div { padding: 0 14px 12px; }
.ku__diag-row p { margin: 0 0 4px; font-size: 13.5px; line-height: 1.5; color: var(--color-text-soft); }
.ku__diag-row span { color: var(--color-muted); }

/* ── Правило-плашка: то, что нужно унести из раздела ───────────────────── */
.ku__rule {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-left: 4px solid var(--color-success, #2f9e6e);
  border-radius: 10px;
  padding: 12px 14px;
  margin: 12px 0 16px;
  font-size: 14px;
  line-height: 1.55;
  color: var(--color-text-soft);
}
.ku__rule b { display: block; color: var(--color-text); margin-bottom: 3px; }

/* ── Тройка карточек (инструменты, приёмы) ─────────────────────────────── */
.ku__three { display: grid; gap: 8px; margin: 4px 0 16px; }
.ku__three > div {
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 12px 14px;
}
.ku__three b { display: block; font-size: 14.5px; margin-bottom: 3px; }
.ku__three span { font-size: 13.5px; line-height: 1.5; color: var(--color-muted); }

/* ── Списки шагов и ошибок ─────────────────────────────────────────────── */
.ku__steps { margin: 0 0 12px; padding-left: 20px; }
.ku__steps li { margin-bottom: 7px; }

.ku__errs { list-style: none; margin: 0 0 12px; padding: 0; }
.ku__errs li { padding: 8px 0; border-top: 1px solid var(--color-border); }
.ku__errs li:first-child { border-top: none; }
.ku__errs b { color: var(--color-text); }

/* ── Фотопримеры ───────────────────────────────────────────────────────
   Фото стоят там, где схема бессильна: показать, как выглядит правильно
   собранная плотность или как невеста держит букет, контуром нельзя.
   Подпись обязательна — без неё непонятно, на что именно смотреть */
.ku__photo { margin: 4px 0 16px; }
.ku__photo img {
  width: 100%;
  height: auto;
  display: block;
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border);
}
.ku__photo figcaption {
  margin-top: 6px;
  font-size: 13px;
  line-height: 1.5;
  color: var(--color-muted);
}

/* Пара кадров рядом — только на широком экране: на телефоне они встают
   друг под друга, иначе от каждого остаётся полоска в полпальца */
.ku__photos { display: grid; gap: 12px; }
@media (min-width: 560px) { .ku__photos { grid-template-columns: 1fr 1fr; } }

/* ── Народные средства: вердикт рядом с названием ──────────────────────── */
.ku__folk { margin: 4px 0 14px; }
.ku__folk-row {
  padding: 10px 0;
  border-top: 1px solid var(--color-border);
}
.ku__folk-row:first-child { border-top: none; }
.ku__folk-row b { font-size: 14.5px; margin-right: 7px; }
.ku__folk-row span { display: block; font-size: 13.5px; line-height: 1.5; color: var(--color-muted); margin-top: 3px; }

/* ── Таблица стойкости ─────────────────────────────────────────────────
   Причина увядания спрятана в раскрывающуюся строку: четвёртой колонкой
   она не помещается ни на одном телефоне, а обрезать её до слова «этилен»
   бессмысленно — польза именно в объяснении */
.ku__table-wrap { overflow-x: auto; margin-bottom: 6px; }
.ku__table { width: 100%; border-collapse: collapse; font-size: 14px; }
.ku__table th {
  text-align: left;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .03em;
  color: var(--color-muted);
  font-weight: 600;
  padding: 6px 8px;
}
.ku__table td { padding: 10px 8px; border-top: 1px solid var(--color-border); }
.ku__table td:first-child { font-weight: 600; }
.ku__row { cursor: pointer; }
.ku__row:hover td { background: var(--color-surface-raised); }
.ku__row-why { display: none; }
.ku__row-why.is-open { display: table-row; }
.ku__row-why td {
  border-top: none;
  padding-top: 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--color-muted);
}

/* ── Чек-лист самопроверки ─────────────────────────────────────────────── */
.ku__check { list-style: none; margin: 0 0 18px; padding: 0; }
.ku__check li {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  margin-bottom: 7px;
  background: var(--color-surface-raised);
}
.ku__check label {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 12px 14px;
  cursor: pointer;
  font-size: 14.5px;
  line-height: 1.4;
}
.ku__check input { width: 22px; height: 22px; flex: 0 0 auto; accent-color: var(--color-success, #2f9e6e); }
.ku__check li.is-done span { color: var(--color-muted); text-decoration: line-through; }

/* ── Переход к следующему уроку ────────────────────────────────────────── */
.ku__next {
  display: block;
  padding: 14px 16px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface-raised);
  color: var(--color-text);
  margin-bottom: 8px;
}
.ku__next span { font-size: 12px; color: var(--color-muted); }
.ku__next b { display: block; font-size: 16px; margin-top: 2px; }
.ku__next i { display: block; font-style: normal; font-size: 13px; color: var(--color-muted); margin-top: 2px; }

/* ── Цветовой круг (урок «Цвет») ───────────────────────────────────────── */
.os__wheel-wrap {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 18px;
  margin: 6px 0 14px;
}
.os__wheel { flex: 0 0 auto; width: 260px; max-width: 100%; height: auto; margin-inline: auto; }

.os__sec {
  cursor: pointer;
  stroke: var(--color-bg);
  stroke-width: 2;
  transition: opacity .15s ease, transform .15s ease;
  transform-origin: 150px 150px;
}
.os__sec:hover { opacity: .85; }
.os__sec:focus-visible { outline: 2px solid var(--color-text); outline-offset: 2px; }

/* Невыбранные не прячем совсем: круг должен остаться кругом, иначе
   пропадает сама мысль «эти тона стоят напротив друг друга».
   Гасили до 0.22 — тон становился неразличим, и было непонятно,
   что вообще осталось за подсветкой */
.os__sec.is-off { opacity: .35; }
.os__sec.is-on  { transform: scale(1.03); }

/* Букет в середине круга: ради него всё и затевалось — видно не «какие
   тона дружат», а что из них получится. Обводка головок фоном, чтобы
   соседние не слипались в пятно */
.os__bud { stroke: var(--color-bg); stroke-width: 1.2; }
.os__bud, .os__bud * { vector-effect: non-scaling-stroke; }

.os__center-hint { fill: var(--color-muted); font-size: 12px; font-family: var(--font-body); }

.os__pick-level { margin: 0 0 8px; font-size: 12.5px; color: var(--color-muted); }
.os__share { font-style: normal; font-size: 11.5px; color: var(--color-muted); }

/* Метка доступности тона. Два разных знака, а не один: «краски не бывает
   вовсе» и «бывает, но не у розы» — разные новости для флориста, и
   сливать их в одну точку значило бы потерять половину смысла */
.os__mark { pointer-events: none; stroke-width: 1.4; }
.os__mark--paint { fill: #fff; stroke: rgba(0, 0, 0, .5); }
.os__mark--rare  { fill: rgba(255, 255, 255, .45); stroke: rgba(255, 255, 255, .9); }

.os__key {
  display: inline-block;
  width: 9px; height: 9px;
  border-radius: 50%;
  vertical-align: middle;
  margin-right: 2px;
}
.os__key--paint { background: #fff; border: 1px solid rgba(0, 0, 0, .5); }
.os__key--rare  { background: #cfcfcf; border: 1px solid rgba(0, 0, 0, .3); }

.os__tag {
  font-style: normal;
  font-size: 11px;
  padding: 1px 6px;
  border-radius: var(--radius-pill);
  white-space: nowrap;
}
.os__tag--paint { background: #fae3e1; color: #7d2f2a; }
.os__tag--rare  { background: #fdf0dd; color: #7a5312; }

/* ── Доли цвета: полоса 60/30/10 против «поровну» ──────────────────────── */
.ku__share {
  flex: 1 1 100%;
  display: flex;
  height: 64px;
  border-radius: var(--radius-md);
  overflow: hidden;
  border: 1px solid var(--color-border);
}
.ku__share i {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
}
.ku__share b {
  font-size: 12px;
  font-weight: 700;
  color: #fff;
  text-shadow: 0 1px 2px rgba(0, 0, 0, .35);
}

/* ── Светлота: два набора образцов и переключатель в ч/б ───────────────── */
.ku__demo--wide > .ku__values { flex: 1 1 100%; }

.ku__values { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.ku__values > div > span { display: block; font-size: 12px; color: var(--color-muted); margin-bottom: 5px; }
.ku__values.is-gray .ku__swatches { filter: grayscale(1); }

.ku__swatches { display: flex; height: 54px; border-radius: 10px; overflow: hidden; }
.ku__swatches i { flex: 1; }

/* ── Две колонки «дёшево / дорого» ─────────────────────────────────────── */
.ku__two { display: grid; gap: 10px; margin: 6px 0 14px; }
.ku__two > div {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 12px 14px;
  background: var(--color-surface-raised);
}
.ku__two b { display: block; font-size: 14.5px; margin-bottom: 6px; }
.ku__two ul { margin: 0; padding-left: 18px; }
.ku__two li { font-size: 13.5px; line-height: 1.5; margin-bottom: 5px; color: var(--color-text-soft); }
.ku__two-bad  { border-left: 4px solid #c46a62; }
.ku__two-good { border-left: 4px solid var(--color-success, #2f9e6e); }

@media (min-width: 560px) {
  .ku__two   { grid-template-columns: 1fr 1fr; }
  .ku__three { grid-template-columns: repeat(3, 1fr); }
}

.os__pick { flex: 1 1 220px; min-width: 200px; }
.os__pick-empty { color: var(--color-muted); font-size: var(--fs-sm); margin: 0; }

.os__row {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 8px 0;
  border-top: 1px solid var(--color-border);
}
.os__row:first-child { border-top: none; }
.os__row i {
  flex: 0 0 auto;
  width: 18px; height: 18px;
  margin-top: 2px;
  border-radius: 50%;
  border: 1px solid rgba(0, 0, 0, .12);
}
.os__row b { display: block; font-size: 14px; font-weight: 600; }
.os__row span { display: block; font-size: 12.5px; color: var(--color-muted); line-height: 1.45; }

.os__schemes { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }
.os__scheme {
  min-height: 40px;
  padding: 0 14px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-pill);
  background: var(--color-surface);
  color: var(--color-text);
  font-size: 14px;
  cursor: pointer;
}
.os__scheme.is-active { background: var(--color-text); border-color: var(--color-text); color: var(--color-bg); }

.os__note {
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 13px 15px;
  font-size: 14px;
  line-height: 1.6;
  color: var(--color-text-soft);
}
.os__note-lead  { margin: 0 0 8px; }
.os__note-catch { margin: 0; font-size: 13.5px; color: var(--color-muted); }

/* ═══ components/postavka.css ═══ */

/* Приёмка поставки — рабочий экран флориста.
   Это отчёт, который заполняют: сверху шапка и цифры поставки, дальше
   аккордеон по позициям, внутри — разбор из отчёта Cowork и поля ввода.
   Работают с телефона, одной рукой, между покупателями. */

.pk { max-width: 640px; padding-bottom: 80px; }

/* ── Шапка поставки ───────────────────────────────────────────────────── */
.pk__hero {
  background: linear-gradient(150deg, #2f5d3f, #4a7c5c);
  color: #fff;
  border-radius: var(--radius-lg);
  padding: 20px 18px;
  margin: 20px 0 16px;
}
.pk__title { font-size: 20px; font-weight: 700; letter-spacing: -0.3px; margin-bottom: 10px; color: #fff; }
.pk__hero p { font-size: 13.5px; opacity: 0.92; margin: 3px 0; }
.pk__tax {
  margin-top: 10px;
  font-size: 12.5px;
  line-height: 1.45;
  background: rgba(255, 255, 255, 0.16);
  padding: 8px 11px;
  border-radius: 10px;
}

.pk__kpi { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 16px; }
.pk__kpi div {
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 12px 14px;
}
.pk__kpi span {
  display: block;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: var(--ls-caps);
  color: var(--color-muted);
  margin-bottom: 4px;
}
.pk__kpi b { font-size: 18px; font-weight: 700; }
.pk__kpi .g { color: var(--color-success); }

/* Строка состояния липнет к верху: флорист должен видеть, что введённое
   дошло до сервера, не возвращаясь к началу списка */
.pk__bar {
  position: sticky;
  top: 0;
  z-index: 5;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  padding: 10px 0;
  margin-bottom: 12px;
  background: var(--color-bg);
  border-bottom: 1px solid var(--color-border);
  font-size: var(--fs-sm);
}
.pk__bar-count { font-weight: 600; }
.pk__status { color: var(--color-muted); font-size: var(--fs-xs); }
.pk__status.is-bad { color: var(--color-error); }

/* ── Карточка позиции ─────────────────────────────────────────────────── */
.pk__card {
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  margin-bottom: 11px;
  overflow: hidden;
}
.pk__card > summary { padding: 15px 16px; cursor: pointer; list-style: none; }
.pk__card > summary::-webkit-details-marker { display: none; }
.pk__card.is-sent { opacity: 0.65; }
.pk__card.is-submitted { border-color: var(--color-success); }
.pk__card.is-absent { opacity: 0.7; }

.pk__cname {
  font-size: 16.5px;
  font-weight: 650;
  line-height: 1.35;
  margin-bottom: 11px;
}
.pk__flag {
  display: inline-block;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--ls-caps);
  background: var(--color-surface);
  color: var(--color-muted);
  padding: 2px 8px;
  border-radius: 8px;
  vertical-align: 2px;
  white-space: nowrap;
}
.pk__flag.is-ok { background: rgba(47, 93, 63, 0.14); color: var(--color-success); }
.pk__flag.is-wait { background: rgba(176, 109, 43, 0.14); color: var(--color-warning); }

.pk__pills { display: flex; gap: 7px; flex-wrap: wrap; margin-bottom: 10px; }
.pk__pill { flex: 1 1 auto; min-width: 84px; border-radius: 13px; padding: 9px 11px; text-align: center; }
.pk__pill span {
  display: block;
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  opacity: 0.75;
  margin-bottom: 2px;
}
.pk__pill b { font-size: 18px; font-weight: 750; letter-spacing: -0.4px; }
.pk__pill--qty  { background: #e8ecef; color: #3f4d59; }
.pk__pill--cost { background: #f0efe9; color: #5d6b5e; }
.pk__pill--shop { background: #e3f0e6; color: #255c38; }
.pk__pill--flau { background: #fdeede; color: #a15a17; }

.pk__meta {
  font-size: 13px;
  color: var(--color-muted);
  display: flex;
  justify-content: space-between;
  gap: 8px;
  flex-wrap: wrap;
}
.pk__tap { color: var(--color-success); font-weight: 600; white-space: nowrap; }
.pk__card[open] .pk__tap { opacity: 0.4; }

.pk__body { padding: 2px 16px 18px; border-top: 1px solid var(--color-border); }

/* ── Разбор из отчёта Cowork ──────────────────────────────────────────── */
/* Разметка приходит из отчёта как есть: h4-заголовки, списки, блок расчёта
   и три вида плашек. Переписывать её под свои классы значило бы ломать
   отчёт при каждом изменении шаблона Cowork. */
.pk__body h4 {
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--color-success);
  margin: 16px 0 7px;
  font-weight: 750;
}
.pk__body ul { padding-left: 19px; }
.pk__body ul.plain { list-style: none; padding-left: 0; }
.pk__body li { font-size: 14.5px; margin: 5px 0; }
.pk__body .calc { background: var(--color-surface); border-radius: 13px; padding: 12px 13px; font-size: 14px; }
.pk__body .calc div { margin: 5px 0; line-height: 1.55; }
.pk__body .hl { color: var(--color-success); font-size: 15.5px; }
.pk__body .warn, .pk__warn {
  background: #fff5e2;
  border-left: 4px solid #e0a03a;
  border-radius: 10px;
  padding: 11px 13px;
  font-size: 13.5px;
  margin-top: 14px;
  color: #6d4c12;
}
.pk__body .note {
  background: #eef2f4;
  border-left: 4px solid #7a97a3;
  border-radius: 10px;
  padding: 11px 13px;
  font-size: 13px;
  margin-top: 14px;
  color: #3f4d59;
}
.pk__body .good {
  background: #e6f2e8;
  border-left: 4px solid #3d7a52;
  border-radius: 10px;
  padding: 11px 13px;
  font-size: 13px;
  margin-top: 14px;
  color: #1d4a2c;
}

/* ── Поля разбора ─────────────────────────────────────────────────────── */
.pk__h4 {
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--color-success);
  margin: 20px 0 8px;
  font-weight: 750;
}
.pk__fields { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
.pk__extra { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 10px; }
.pk__field { display: flex; flex-direction: column; gap: 4px; }
.pk__field-label {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: var(--ls-caps);
  color: var(--color-muted);
  line-height: 1.3;
}
.pk__field-label small { display: block; text-transform: none; letter-spacing: 0; font-size: 10px; }

.pk__field input,
.pk__field select,
.pk__note {
  width: 100%;
  /* 16px ровно: меньше — и iOS зумит страницу при фокусе, флорист каждый раз
     возвращает масштаб пальцами */
  font-size: 16px;
  padding: 10px;
  text-align: center;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  color: var(--color-text);
}
.pk__note { text-align: left; margin-top: 10px; }

/* ── Журнал потерь (florist/poteri.php) ──────────────────────────────── */
.pt { max-width: 640px; padding: 20px 0 80px; }
.pt__kind { display: flex; gap: 8px; margin: 16px 0; }
.pt__kind-btn {
  flex: 1;
  padding: 12px;
  font-size: 15px;
  font-weight: 600;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface-raised);
  color: var(--color-text-soft);
}
.pt__kind-btn.is-active {
  border-color: var(--color-success);
  color: var(--color-success);
  background: var(--color-surface);
}

.pk__sum {
  margin-top: 10px;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  font-size: var(--fs-sm);
  background: var(--color-surface);
  color: var(--color-muted);
}

/* Фото и комментарий к «Бою»/«Рекламации» — отдельный блок от общего фото
   при вскрытии: тот показывает коробку целиком, этот — конкретный дефект */
.pk__evidence {
  margin-top: 16px;
  padding: 12px;
  border: 1px dashed var(--color-border);
  border-radius: var(--radius-md);
}
.pk__evidence .pk__h4 { margin-top: 0; }
.pk__sum.is-ok { background: rgba(47, 93, 63, 0.12); color: var(--color-success); font-weight: 600; }
.pk__sum.is-bad { background: rgba(196, 85, 63, 0.12); color: var(--color-error); font-weight: 600; }

.pk__actions {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  margin-top: 14px;
  flex-wrap: wrap;
}
.pk__absent { display: flex; align-items: center; gap: 8px; font-size: var(--fs-sm); color: var(--color-text-soft); }
.pk__absent input { width: 20px; height: 20px; }
.pk__done-note { font-size: var(--fs-sm); color: var(--color-muted); margin-top: 14px; }

/* ── Итоги поставки ───────────────────────────────────────────────────── */
.pk__totals {
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: 16px;
  margin-top: 20px;
}
.pk__totals h3 { font-size: 15px; margin-bottom: 12px; }
.pk__totals h5 {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin-bottom: 7px;
}
.pk__totals .trow {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  padding: 8px 0;
  border-top: 1px solid var(--color-border);
  font-size: 14.5px;
}
.pk__totals .trow:first-of-type { border-top: none; }
.pk__totals .scn { margin-top: 14px; border-radius: 13px; padding: 12px 13px; }
.pk__totals .scn.a { background: #e9f2ea; } .pk__totals .scn.a h5 { color: #255c38; }
.pk__totals .scn.b { background: #fdf1e4; } .pk__totals .scn.b h5 { color: #a15a17; }
.pk__totals .warn, .pk__totals .note { margin-top: 14px; }

.pk__hint { margin-top: 16px; font-size: var(--fs-xs); color: var(--color-muted); line-height: 1.5; }

@media (max-width: 520px) {
  .pk__fields { grid-template-columns: repeat(2, 1fr); }
  .pk__extra { grid-template-columns: 1fr; }
}

/* Цена, которая стоит в CRM сейчас: без неё флорист не поймёт,
   менять ли ценник и на сколько */
.pk__price-was { font-size: 13px; color: var(--color-muted); margin-bottom: 8px; }
.pk__price-was .is-up { color: var(--color-error); font-weight: 600; }
.pk__price-was .is-down { color: var(--color-success); font-weight: 600; }

/* Упаковка: сколько веток внутри, знает только тот, кто её вскрыл */
.pk__pack {
  background: #fff5e2;
  border-left: 4px solid #e0a03a;
  border-radius: 10px;
  padding: 12px 13px;
  color: #6d4c12;
}
.pk__pack p { font-size: 13.5px; line-height: 1.5; margin-bottom: 10px; }
.pk__pack .pk__field { max-width: 200px; }
.pk__pack-done { margin: 10px 0 0; color: #1d4a2c; }

/* ── Привязка позиции к карточке в CRM (когда нет posiflora_id) ─────────── */
.pk__link {
  margin-top: 10px;
  padding: 12px;
  border: 1px dashed var(--color-border);
  border-radius: var(--radius-md);
}
.pk__link .pk__h4 { margin-top: 0; }
.pk__link-results { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; }
.pk__link-item {
  text-align: left;
  padding: 9px 11px;
  font-size: 14px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface-raised);
  color: var(--color-text);
  cursor: pointer;
}
.pk__link-item:hover { border-color: var(--color-success); }
.pk__link-create {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px dashed var(--color-border);
}
.pk__link-status { font-size: var(--fs-xs); color: var(--color-muted); margin-top: 8px; min-height: 1.2em; }

/* ── Шаги разбора ────────────────────────────────────────────────────────
 *
 * Карточка позиции была набором разделов без порядка: расчёт, уход,
 * поля, фото, цена. Флорист видел всё сразу и решал сам, с чего начать,
 * а фото при вскрытии стояло ниже полей разбора — то есть после того,
 * как считать уже поздно.
 *
 * Номер делает из набора последовательность: вскрыл → снял → посчитал.
 * Порядок здесь не украшение, а защита доказательства. */
.pk__step { display: flex; align-items: center; gap: 10px; }
.pk__step i {
  flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px;
  border-radius: 50%;
  background: var(--color-accent);
  color: #fff;
  font-style: normal; font-size: 13px; font-weight: 700;
}

/* Сколько всего разносить — над полями. Пилюля наверху карточки уезжает
   за экран, как только человек начинает вводить. */
.pk__razbor-total {
  margin: -4px 0 12px;
  font-size: 14px;
  line-height: 1.45;
  color: var(--color-text-soft);
}
.pk__razbor-total b { font-size: 16px; color: var(--color-text); }

.pk__send-all { margin: 20px 0 8px; }

/* Свёрнутая форма заведения поставки: список важнее формы, к которой
   возвращаются раз в несколько дней. */
.admin-akk > summary { cursor: pointer; list-style: none; }
.admin-akk > summary::-webkit-details-marker { display: none; }
.admin-akk__head::after {
  content: ' ▾';
  font-size: .8em;
  color: var(--color-muted);
}
.admin-akk[open] > .admin-akk__head::after { content: ' ▴'; }

/* Свёрнутый шаг разбора. Карточка с расчётом, уходом, витриной и полями
   разом — два экрана прокрутки, и до полей человек доходит уставшим. */
.pk__fold { margin: 14px 0; }
.pk__fold > summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 15px;
  font-weight: 650;
  padding: 6px 0;
}
.pk__fold > summary::-webkit-details-marker { display: none; }
.pk__fold > summary::after {
  content: '▾';
  margin-left: auto;
  font-size: .75em;
  color: var(--color-muted);
}
.pk__fold[open] > summary::after { content: '▴'; }
.pk__fold > summary i {
  flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px;
  border-radius: 50%;
  background: var(--color-accent);
  color: #fff;
  font-style: normal; font-size: 13px; font-weight: 700;
}

/* Снимок с крестиком: снять не тот кадр — обычное дело, телефон в одной
   руке, коробка в другой. Крестик поверх угла, а не отдельной строкой:
   снимков до пяти, и пять подписей «удалить» съели бы экран. */
.pk__shot { position: relative; display: inline-block; }
.pk__shot-x {
  position: absolute;
  top: -6px; right: -6px;
  width: 22px; height: 22px;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--color-border);
  border-radius: 50%;
  background: var(--color-surface-raised);
  color: var(--color-text-soft);
  font-size: 15px; line-height: 1;
  cursor: pointer;
}
.pk__shot-x:hover { color: var(--color-error); border-color: var(--color-error); }
