/* ============================================================================
   ТОКЕНЫ CRM «Твой выбор» — такт 1 UI-кита.

   ПРАВИЛО, РАДИ КОТОРОГО ЭТОТ ФАЙЛ СУЩЕСТВУЕТ:
   цвета, радиусы, шрифты и плотность в шаблонах НЕ ПИШЕМ. Ни `style="..."`, ни классов
   с зашитым цветом, ни hex в других css. Всё живёт здесь. Дизайн в спринте 4 должен
   менять этот файл, а не двадцать экранов.
   Сторож правила — `crm/tests/test_ui_tokens.py`: он ищет hex/rgb, `border-radius`,
   `font-family` и `style="` за пределами этого файла и падает на находке.

   ФАЙЛ ДВУХСЛОЙНЫЙ, И ВТОРОЙ СЛОЙ ОБЯЗАТЕЛЕН.
   Слой 1 — глобальные переменные Bootstrap (`--bs-*`).
   Слой 2 — мостики компонентов (`.btn-primary { --bs-btn-bg: ... }`).
   Без слоя 2 обещание «цвет в одном файле» было бы ложным: Bootstrap 5.3 вычисляет
   `--bs-btn-bg`, `--bs-alert-*` и подобное Sass-миксинами на этапе сборки, и на смену
   глобального `--bs-primary` они не реагируют. Проверено: меняешь `--bs-primary` — ссылки
   и `.text-primary-emphasis` перекрашиваются, а `.btn-primary` остаётся синим.
   Мостики пишутся ЧЕРЕЗ `var(--bs-...)`, а не хардкодом: иначе цвет снова окажется
   в двух местах, просто оба внутри этого файла.

   Sass-сборки нет и не нужно: всё перечисленное настраивается CSS-переменными.
   Sass понадобился бы для `$theme-colors`, шкалы отступов и брейкпоинтов — их не трогаем.

   ПОДКЛЮЧАЕТСЯ СТРОГО ПОСЛЕ `bootstrap.min.css` — иначе каскад съест переопределения.

   Печатные формы (задание кухне, маршрутные листы, стикеры) сюда НЕ входят: они обязаны
   выглядеть как в 1С, у них свой `print.css` (сквозное соглашение 11а).
   ============================================================================ */

/* ---------- Слой 1: глобальные переменные ---------- */

/* Светлая тема объявляется и в `:root`, и в `[data-bs-theme="light"]` намеренно.
   Файл, задающий только `:root`, перебил бы встроенные ТЁМНЫЕ переменные Bootstrap
   порядком каскада — и тёмная тема поехала бы. */
:root,
[data-bs-theme="light"] {
  /* Фирменный зелёный: «Твой Выбор» — доставка правильного питания.
     Значения подобраны под контраст ≥ 4.5:1 с белым текстом (WCAG AA). */
  --bs-primary: #2e7d5b;
  --bs-primary-rgb: 46, 125, 91;
  --bs-primary-text-emphasis: #1d5039;
  --bs-primary-bg-subtle: #e4f1eb;
  --bs-primary-border-subtle: #b9dcca;

  --bs-body-bg: #f7f8f7;
  --bs-body-bg-rgb: 247, 248, 247;
  --bs-body-color: #1f2421;
  --bs-body-color-rgb: 31, 36, 33;
  --bs-secondary-color: rgba(31, 36, 33, 0.68);
  --bs-border-color: #dde2df;

  /* Поверхность карточек и шапки. Своя переменная, а не готовая из Bootstrap:
     на неё ссылаются мостики ниже, и менять её нужно в одном месте. */
  --crm-surface: #ffffff;
  --crm-header-bg: #ffffff;
  /* Текст НА фирменном цвете. В светлой теме фон тёмно-зелёный — текст белый. */
  --crm-on-primary: #ffffff;
}

[data-bs-theme="dark"] {
  --bs-primary: #6fcfa2;
  --bs-primary-rgb: 111, 207, 162;
  --bs-primary-text-emphasis: #a6e3c6;
  --bs-primary-bg-subtle: #143224;
  --bs-primary-border-subtle: #245c43;

  --bs-body-bg: #14171a;
  --bs-body-bg-rgb: 20, 23, 26;
  --bs-body-color: #e6eae8;
  --bs-body-color-rgb: 230, 234, 232;
  --bs-secondary-color: rgba(230, 234, 232, 0.68);
  --bs-border-color: #2c3a34;

  --crm-surface: #1b1f22;
  --crm-header-bg: #1b1f22;
  /* В тёмной теме фирменный цвет СВЕТЛЫЙ (#6fcfa2) — белый текст на нём даёт контраст
     около 1.9:1, то есть нечитаем. Поэтому текст на кнопке тёмный: 8:1. Пара «фон +
     текст на нём» обязана меняться вместе, иначе тёмная тема ломает читаемость кнопок. */
  --crm-on-primary: #10231a;
}

/* Общие для обеих тем: форма, плотность, типографика.
   Менеджеры вечером работают с телефона — интерфейс плотный, но цели тапабельные. */
:root {
  --bs-border-radius: 0.5rem;
  --bs-border-radius-sm: 0.375rem;
  --bs-border-radius-lg: 0.75rem;

  --bs-body-font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue",
    Arial, sans-serif;
  --bs-body-font-size: 1rem;
  --bs-body-line-height: 1.5;

  /* Плотность: вертикальный ритм экранов и минимальная высота интерактивных целей.
     44px — нижняя граница удобного касания на телефоне. */
  --crm-gap: 1rem;
  --crm-gap-sm: 0.5rem;
  --crm-tap-target: 44px;
}

/* ---------- Слой 2: мостики компонентов ----------
   Без этих строк смена `--bs-primary` выше не перекрасит кнопки и алерты.
   Значения берутся ИЗ переменных слоя 1 — цвет остаётся в одном месте. */

.btn-primary {
  --bs-btn-bg: var(--bs-primary);
  --bs-btn-border-color: var(--bs-primary);
  --bs-btn-color: var(--crm-on-primary);
  --bs-btn-hover-color: var(--crm-on-primary);
  --bs-btn-active-color: var(--crm-on-primary);
  --bs-btn-disabled-color: var(--crm-on-primary);
  --bs-btn-hover-bg: var(--bs-primary-text-emphasis);
  --bs-btn-hover-border-color: var(--bs-primary-text-emphasis);
  --bs-btn-active-bg: var(--bs-primary-text-emphasis);
  --bs-btn-active-border-color: var(--bs-primary-text-emphasis);
  --bs-btn-disabled-bg: var(--bs-primary);
  --bs-btn-disabled-border-color: var(--bs-primary);
}

.btn-outline-primary {
  --bs-btn-color: var(--bs-primary);
  --bs-btn-border-color: var(--bs-primary);
  --bs-btn-hover-bg: var(--bs-primary);
  --bs-btn-hover-border-color: var(--bs-primary);
  --bs-btn-active-bg: var(--bs-primary);
  --bs-btn-active-border-color: var(--bs-primary);
}

.alert-primary {
  --bs-alert-color: var(--bs-primary-text-emphasis);
  --bs-alert-bg: var(--bs-primary-bg-subtle);
  --bs-alert-border-color: var(--bs-primary-border-subtle);
}

.card {
  --bs-card-bg: var(--crm-surface);
  --bs-card-border-color: var(--bs-border-color);
}

.nav-pills {
  --bs-nav-pills-link-active-bg: var(--bs-primary);
}

.form-control:focus,
.form-select:focus {
  border-color: var(--bs-primary);
  box-shadow: 0 0 0 0.25rem rgba(var(--bs-primary-rgb), 0.25);
}

/* ---------- Каркас страницы ----------
   Только структура: шапка, основная область, подвал. Компонентов здесь нет — они
   появятся в такте 2, когда напишем 2–3 живых экрана и станет видно, что реально
   повторяется. Кит из вакуума — тридцать компонентов, из которых шесть используются. */

.crm-header {
  background: var(--crm-header-bg);
  border-bottom: 1px solid var(--bs-border-color);
}

.crm-header .navbar-brand {
  font-weight: 600;
  color: var(--bs-primary);
}

/* ---------- Шапка не выталкивает выход за экран (11–12.09.2026) ----------

   Дефект приёмки: у старшего менеджера и владельца на окне 1280 px ширина страницы была
   1453 px, кнопка «Выйти» лежала за правой границей. Менеджер этого не видел: у него на три
   пункта меньше, и прежняя e2e-проверка ширины входила именно им.

   Вся правка — арифметика. Шапка живёт в `.container`: на 992 px он шириной 960, на 1200
   и 1280 — 1140, с 1400 — 1320. Содержимое роли с полным меню до правки: 217 (логотип) +
   683 (разделы) + 453 (имя · роль, «Служебное», «Выйти») = 1353 px. Переезд «Кухонь»
   и «Настроек» в «Справочники» снял около 213 px — этого хватило, чтобы уложиться в размер
   ОКНА, но не в размер КОНТЕЙНЕРА: на 1200 px дефект возвращался.

   1. Бургер до 1280 px (порог согласован Юлией 12.09.2026; поднимали 992 → 1200 → 1280).
      На 992 несжимаемый минимум строки — 217 + 683 + 123 («Служебное») + 65 («Выйти») =
      1088 px — не влезает в контейнер 960 никаким сжатием; на 1200 строка помещается,
      но блоку «имя · роль» остаётся колонка 99 px и слова рвутся посреди слога.
   2. Шапка — и только она — занимает всю ширину окна с 1280 px. Содержимое страниц
      остаётся в контейнере. Без этого колонка блока имени сжимается примерно до 90 px,
      слова рвутся посередине и блок уходит в шесть строк — при этом ни прокрутки,
      ни обрезки нет, то есть автотесты зелёные, а читать невозможно.
   3. Текст в блоке «имя · роль» ПЕРЕНОСИТСЯ. `overflow-wrap: anywhere` нужен и для фамилий
      в тридцать букв, и для того, чтобы блок вообще умел сжиматься: он делает min-content
      блока крошечным, и `min-width: auto` флекс-элемента перестаёт держать строку.

   ⚠️ Потолка высоты у блока НЕТ, и это главный вывод четырёх кругов критики. Он стоял
   трижды — 4em, 8em, 12em — и каждый раз оказывался выставлен по самому тяжёлому набору
   ИЗ ТЕСТОВ, а не из жизни: следующий круг приносил ФИО подлиннее, и потолок молча срезал
   роль. Подгонять константу под данные можно бесконечно; вместо этого её нет вовсе. Блок
   растёт в высоту, не режется ни при каких данных, а цена — высокая шапка на узкой полке —
   названа в отчёте и принята заказчицей 12.09.2026: «не сохраняй полный ряд меню ценой
   исчезновения данных пользователя».

   ⚠️ Отвергнутые решения, каждое давало ЗЕЛЁНЫЕ автотесты при сломанной на глазах шапке:
   - `flex-wrap: wrap` — у левого списка `me-auto`, и в переносящей строке автоотступ
     забирает всё свободное место: правый блок уезжает на второй этаж ВСЕГДА, включая
     менеджера без дефекта и ширину 2560 px;
   - `min-width: 0` разом на обоих списках — левый становится уже содержимого, `overflow`
     у него видимый, и «Справочники» налезают на имя буквами поверх букв;
   - усечение многоточием — на 1280 px давало «М.» вместо «Марина · Старший менеджер»;
   - скрытие роли или всего блока — отменено заказчицей: сотрудник должен понимать,
     под кем вошёл;
   - `line-clamp` — режет по глифам, хвост строки выглядывает из-под нижней границы.

   ⚠️ Читаемость проверяется ГЕОМЕТРИЕЙ, а не `innerText`: последний возвращает и тот текст,
   который скрыт `overflow`, поэтому ассерт «роль есть в тексте» был зелёным ровно тогда,
   когда роль срезало нижней границей. */

/* ---------- Порог раскрытия меню: 1280 px (согласовано Юлией 12.09.2026) ----------

   Ниже 1280 — бургер, с 1280 — полный ряд. Класса `navbar-expand-*` на шапке нет:
   брейкпоинта 1280 у Bootstrap нет (xl — 1200, xxl — 1400), а значения задаются при сборке
   Sass, которой у проекта нет. Поэтому раскрытие меню целиком описано здесь. Второе место,
   где встречается 1280, — полка состава имени ниже; там это верхняя граница «короткого
   имени», а не отдельный порог.

   ⚠️ Первая попытка оставляла `navbar-expand-xl` и отменяла его на 1200–1279 зеркальным
   медиазапросом. Так делать не надо: порог xl зашит не только в классе раскрытия, но
   и в каждой `-xl-`утилите шаблона, и зеркало их не покрывало — на 1200–1279 бургер
   прилипал к логотипу, а правая группа уезжала в середину контейнера. Функционально всё
   работало, прокрутки не было, спеки были зелёными: они проверяют видимость и ширину,
   а не выравнивание (критик результата, круг 5, BUGS 1). Поэтому утилиты `align-items-xl-
   center`, `me-xl-3` и `dropdown-menu-xl-end` переехали сюда же под своими зацепками.

   Ниже — те же свойства, что даёт `.navbar-expand-*`, плюс три бывшие утилиты. */
@media (min-width: 1280px) {
  .crm-header .navbar {
    flex-wrap: nowrap;
    justify-content: flex-start;
    /* пункты чуть плотнее ботстраповских 0.5rem: семь пунктов × две стороны дают
       около 20 px, и это та разница, из-за которой имя переносилось лишний раз */
    --bs-navbar-nav-link-padding-x: 0.3rem;
  }

  .crm-header .navbar-toggler {
    display: none;
  }

  .crm-header .navbar-collapse {
    display: flex !important;
    flex-basis: auto;
  }

  .crm-header .navbar-nav {
    flex-direction: row;
  }

  .crm-header .navbar-nav .nav-link {
    padding-right: var(--bs-navbar-nav-link-padding-x);
    padding-left: var(--bs-navbar-nav-link-padding-x);
  }

  .crm-header .navbar-nav .dropdown-menu {
    position: absolute;
  }

  /* было `align-items-xl-center` */
  .crm-header .crm-shapka-sprava {
    align-items: center;
    /* Прижимает правую группу к правому краю САМА, не полагаясь на `me-auto` соседа.
       Раньше отступ стоял у левого списка разделов — и страница отказа, которая этот
       список гасит, получала шапку с правой группой у логотипа (критик результата,
       круг 2). Раскладка не должна зависеть от того, есть ли на странице меню. */
    margin-left: auto;
  }


  /* было `dropdown-menu-xl-end`: служебное меню прижимается к правому краю */
  .crm-header .crm-menyu-sluzhebnoe {
    right: 0;
    left: auto;
  }

  .crm-header > .navbar.container {
    max-width: none;
    padding-inline: 1rem;
  }

  .crm-header .crm-kto-ya .navbar-text {
    display: block;
    max-width: 100%;
    overflow-wrap: anywhere;
    line-height: 1.15;
    /* было `me-xl-3`: блок имени не слипается со «Служебным» */
    margin-right: 1rem;
  }
}

/* Состав имени по полкам ширины: полное ФИО в бургере (до 1280 px) и на широком экране
   (с 1400 px); на 1280–1399, где колонка 179 px, — короткое имя, а если его нет —
   фамилия или логин. Роль показывается на ВСЕХ полках.

   ⚠️ Сокращать имя ботстраповскими `d-xxl-none` / `d-none d-xxl-inline` нельзя: `xxl` —
   это 1400 px, и такие классы убирают фамилию на всех ширинах ниже, включая бургер, где
   места сколько угодно. Так и вышло в первой редакции, и регрессия прошла молча — ни один
   тест не проверял, что фамилия вообще где-то видна (критик, круг 3, BUGS 3). Поэтому
   полки заданы своими медиазапросами, а состав имени на каждой стережёт спека Б-01д. */
.crm-header .crm-imya-korotkoe {
  display: none;
}

@media (min-width: 1280px) and (max-width: 1399.98px) {
  .crm-header .crm-imya-polnoe {
    display: none;
  }

  .crm-header .crm-imya-korotkoe {
    display: inline;
  }
}

.crm-main {
  padding-block: var(--crm-gap);
}

/* Цели касания: на телефоне мелкие ссылки в шапке промахиваются. */
.crm-header .nav-link,
.crm-header .btn {
  min-height: var(--crm-tap-target);
  display: inline-flex;
  align-items: center;
}

/* Активный раздел меню (08.09.2026). Bootstrap красит `.nav-link.active` переменной
   `--bs-navbar-active-color`, а подчёркивание — наше: цвет тот же фирменный, через
   переменную, чтобы дизайн спринта 4 менял его в одном месте. Толщина линии — не цвет
   и не радиус, поэтому она здесь допустима. */
.crm-header .navbar {
  --bs-navbar-active-color: var(--bs-primary);
}

.crm-header .nav-link.active {
  font-weight: 600;
  box-shadow: inset 0 -2px 0 var(--bs-primary);
}

/* Кнопка-раскрывашка меню выглядит как ссылка: без этого у неё рамка и фон кнопки. */
.crm-header button.nav-link {
  background: none;
  border: 0;
}

/* Активный подпункт выпадающего меню. `--bs-dropdown-link-active-bg` у Bootstrap
   вычислен на сборке (синий) и на `--bs-primary` не реагирует — тот же класс мостика,
   что у `.btn-primary` выше. */
.dropdown-menu {
  --bs-dropdown-link-active-bg: var(--bs-primary);
  --bs-dropdown-link-active-color: var(--crm-on-primary);
}

/* Широкие таблицы (журнал, списки) скроллятся ВНУТРИ себя — это `.table-responsive`
   самого Bootstrap. Своего класса здесь больше нет: он повторял бутстраповский слово
   в слово, и из расхождения «где какой» уже вырос пропуск подсказки о прокрутке. */

/* Индикатор htmx: показывается, пока летит запрос. Без него фильтры журнала
   выглядят «не нажались». */
.crm-indicator {
  display: none;
}

.htmx-request .crm-indicator,
.htmx-request.crm-indicator {
  display: inline-flex;
}

/* Сообщение об упавшем htmx-запросе прилипает к верху окна.
   Отказ на длинной странице (пагинация журнала внизу, поиск после прокрутки) иначе
   показывается за пределами экрана: элемент виден в разметке, а человек его не видит —
   и это ровно тот молчаливый отказ, ради которого обработчик и писался. */
.crm-oshibka {
  position: sticky;
  top: 0;
  z-index: 1020;
}

/* Форма-карточка: узкая колонка, чтобы поля не растягивались на всю ширину монитора.
   Класс, а не инлайн-стиль: ширина форм — визуальное решение, оно живёт в токенах
   (соглашение №11а), иначе дизайн спринта 4 придётся править по двадцати шаблонам. */
.crm-forma {
  max-width: 40rem;
}

/* Строка внутри flex-ряда, которой разрешено сжиматься. Без `min-width: 0` элемент flex
   не уходит уже своего содержимого, и слитная строка (свободный хвост исключения — до 200
   символов) растягивает карточку: на экране 375 px документ уезжал до 750 px. Классом, а не
   инлайн-стилем: инлайн-стили в шаблонах запрещены тестом-сторожем. */
.crm-szhimaemaya {
  min-width: 0;
}

/* Окно подсказки для разговора.

   `<dialog>` без `showModal()` рисуется В ПОТОКЕ документа: окно уезжало под карточку
   задач, и текст под ним читался сквозь него (поймано снимком браузерного прогона
   09.09.2026). Модальность включает скрипт фрагмента; эти правила — и рамка окна, и
   страховка на случай, если скрипт не отработал: окно всё равно останется поверх
   страницы, а не под ней.

   Ширина ограничена и по `vw`, и в пикселях: на телефоне 390 px окно обязано влезать
   без горизонтальной прокрутки, на десктопе — не растягиваться во весь экран. */
.crm-podskazka {
  position: fixed;
  inset-block-start: 3vh;
  inset-inline: 50%;
  transform: translateX(-50%);
  z-index: 1080;
  width: min(60rem, 94vw);
  max-height: 90vh;
  overflow-y: auto;
  background-color: var(--bs-body-bg);
  color: var(--bs-body-color);
}

.crm-podskazka::backdrop {
  background-color: rgb(0 0 0 / 40%);
}

/* Свободный текст, набранный человеком: переносы строк — часть смысла.
   Передача смены пишется списком дел, и склеенная в абзац она читается вдвое медленнее.
   Классом, а не инлайн-стилем: инлайн-стили в шаблонах запрещены тестом-сторожем
   (`tests/test_ui_tokens.py`), потому что мимо токенов уезжают цвета и отступы. */
.crm-tekst-kak-napisan {
  white-space: pre-wrap;
}

/* ⚠️ Переноса подписи события здесь НЕТ намеренно. Попытка была: у FullCalendar 7 все
   собственные классы захешированы, внутренний узел подписи несёт `white-space: nowrap`
   со своим `!important`, и правило на родителе его не перебивало — селектор
   `.crm-den .fc-event-title` не существует вовсе. Правило висело мёртвым и создавало
   впечатление, что обрезка починена (поймано критиком результата 31.08).

   Обрезка длинной подписи осталась, и это осознанный размен: статус дня стоит в подписи
   ПЕРВЫМ словом («пауза · на 2 дня»), поэтому он переживает обрезку в любой ширине
   ячейки — а именно он и есть то, ради чего менеджер смотрит в сетку.

   Исключение одно — след «снят с плана» (04.10.2026): его подпись рисует свой узел из
   `eventContent`, и перенос у него работает (`.crm-den-podpis-perenos` ниже). */

/* Выбранный день в календаре заказа (08.09.2026). Обводка фирменным цветом через
   переменную: клик по дню обязан быть виден в самой сетке, а не только панелью ниже.
   Класс ставит `kalendar-zakaza.js` (`eventDidMount`), у FullCalendar 7 свои классы
   захешированы, и другой зацепки нет. */
.crm-den {
  cursor: pointer;
}

/* След «Снят с плана» (03.10.2026): визита нет, бумага осталась. Приглушён целиком —
   цвет события FullCalendar ставит сам, а прозрачность корня переживает его стили. */
.crm-den.crm-den-snyat {
  opacity: 0.55;
}

/* Подпись следа — свой узел из `eventContent` (`kalendar-zakaza.js`), поэтому перенос
   здесь работает, в отличие от узла подписи FullCalendar (см. выше). Только у следа:
   «снят с плана» не начинается со слова-статуса, обрезка до «снят с» его не называет
   (решение Макса 03.10.2026). */
.crm-den-podpis-perenos {
  display: block;
  white-space: normal;
  overflow-wrap: anywhere;
  line-height: 1.15;
  padding: 0 2px;
}

.crm-den.crm-den-vybran {
  box-shadow: 0 0 0 2px var(--bs-primary);
  font-weight: 600;
}

/* Дашборд «Сегодня» (09.09.2026). Ссылка «↓ К цифрам» на телефоне ведёт к продажам,
   а липкая шапка не должна накрыть заголовок — отступ прокрутки под её высоту. */
#prodazhi {
  scroll-margin-top: 4.5rem;
}

/* Показатели в ячейке календаря (09.09.2026). Календарь перестал быть лентой фамилий и
   стал ежедневным отчётом: в дне — продажи и пакеты по категориям.

   Кегль задан относительным (`em`), а не в пикселях: сетка на телефоне вдвое уже, и
   фиксированный размер там либо ломает вёрстку, либо требует второго набора правил. */
.crm-den-pokazateli {
  display: flex;
  flex-direction: column;
  gap: 0.1em;
  font-size: 0.8em;
  line-height: 1.25;
  text-align: start;
  width: 100%;
  /* ⚠️ `min-width: 0` и перенос — не косметика. Без них строка «платные 0 · бартер 0 ·
     прочее 0» не помещается в ячейку и вылезает на соседние: на снимке прогона 1280 px
     текст шёл сплошняком через границы столбцов, а на 390 px календарь превращался
     в кашу. Ячейка календаря узкая по построению, и содержимое обязано в неё складываться. */
  min-width: 0;
  max-width: 100%;
  overflow: hidden;
  overflow-wrap: anywhere;
  word-break: break-word;
  /* Кнопка внутри ячейки: клик по дню открывает попап. Своя, а не `navLink` календаря —
     у FullCalendar обёртка номера дня может быть ссылкой, а вкладывать интерактивный
     элемент в `<a>` HTML запрещает. */
  background: none;
  border: 0;
  padding: 0.15em 0.25em;
  color: inherit;
  cursor: pointer;
}

.crm-den-pokazateli:focus-visible {
  outline: 2px solid var(--bs-primary);
  outline-offset: 1px;
}

.crm-den-summa {
  font-weight: 600;
}

.crm-den-kategorii {
  color: var(--bs-secondary-color);
  white-space: normal;
}

/* На телефоне в ячейку помещаются только два числа — сумма и пакеты. Разбивку по
   категориям там не показываем совсем: втиснутая, она сливается в нечитаемую кашу и
   мешает увидеть главное. Разбивка никуда не девается — она в раскрытии дня, куда ведёт
   та же ячейка. Порог 768 px — граница `md` Bootstrap, ниже которой сетка календаря
   сжимается до нечитаемого. */
@media (max-width: 767.98px) {
  .crm-den-kategorii {
    display: none;
  }

  .crm-den-pokazateli {
    font-size: 0.7em;
  }
}

/* ⚠️ Ограничитель ширины висит на ЯЧЕЙКЕ FullCalendar, а не на нашей кнопке, и это не
   перестраховка. Настоящий flex-элемент внутри дня — сгенерированный календарём div со
   своими полями; при узкой сетке он шире ячейки, а родитель центрирует переполнение в обе
   стороны, поэтому содержимое дня наезжает на соседний. `min-width`/`max-width` на кнопке
   на него не влияют вовсе: первая правка (круг 1) повесила их не на тот элемент, и на
   390 px дни продолжали накладываться (критик результата, круг 2, BUGS 2).

   Селектор по `[data-date]`, потому что собственные классы FullCalendar 7 захешированы:
   `fc-daygrid-day-frame` в бандле не существует. */
#kalendar-segodnya [data-date] div {
  min-width: 0;
  max-width: 100%;
  align-self: stretch;
}

/* Отметка превышения лимита кухни. ⚠️ Цветом дело не ограничивается намеренно: рядом
   стоит значок и текстовая подпись (`title` + скрытый текст в разметке). Отметка, видимая
   только цветом, для дальтоника и для скринридера не существует вовсе, а речь о том, что
   кухня не сварит заказанное. */
.crm-den-limit {
  color: var(--bs-danger-text-emphasis, var(--bs-body-color));
  font-weight: 600;
}

/* Превью стикера на экране перепечатки. Ширина здесь — не «дизайн», а физический размер
   наклейки в масштабе: крупнее она не читается лучше, а мельче на ней не разобрать код
   рациона. Живёт в токенах, потому что это экран, а не печатная форма. */
.crm-stiker-preview {
  max-width: 18rem;
}

/* Иконки блоков (04.09.2026). Обводкой, `currentColor` — перекрашиваются вместе с текстом
   и переживут тёмную тему спринта 4 без второго набора файлов.

   Размер задан в `em`, а не в пикселях: иконка стоит в заголовке и обязана расти вместе
   с кеглем, иначе на крупном шрифте она превращается в точку. Толщина обводки одна на все
   иконки — разнобой читается как разное качество рисунка, а не как акцент. */
.crm-ikonka {
  width: 1.15em;
  height: 1.15em;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  vertical-align: -0.15em;
  flex: none;
}

/* Сам спрайт — только хранилище символов, показывать его нельзя. `display: none`
   на нём не годится: часть браузеров вместе с ним выключает и `<use>`. */
.crm-sprite {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

/* Фото блюда рядом с заказом. Пропорция фиксирована, чтобы карточка не прыгала на длине
   загрузки, а сама картинка кадрируется по центру: у брендов фото разного формата. */
.crm-foto-menyu {
  width: 100%;
  /* `height: auto` обязателен: у картинки есть атрибуты width/height (они держат место
     до загрузки и не дают странице дёрнуться), а заданная высота ПЕРЕБИВАЕТ aspect-ratio —
     без этой строки фото растягивается на все 800 px исходника. Поймано визуальной
     проверкой 04.09.2026. */
  height: auto;
  aspect-ratio: 3 / 2;
  object-fit: cover;
}

/* --- Столбчатый график продаж по дням (09.09.2026) ---

   Высота столбца задана КЛАССОМ-ступенькой, а не инлайн-стилем: `style="height:…"` в
   шаблоне запрещён сторожем `tests/test_ui_tokens.py`, и запрет верный — визуальные
   решения обязаны жить здесь. Ступеней двадцать, по 5 %: точное число всё равно читается
   не линейкой, а из доступного имени кнопки и из таблицы рядом.

   Кликабельна ВСЯ колонка, а не закрашенная часть: у дня с маленькой суммой столбик
   низкий, и цель касания меньше 24×24 px нарушила бы WCAG 2.2 §2.5.8. Поэтому кнопка —
   вся колонка, а `.crm-stolbik-zalivka` внутри неё только рисует. */
.crm-grafik {
  display: flex;
  align-items: flex-end;
  gap: 2px;
  height: 8rem;
  overflow-x: auto;
}

.crm-stolbik {
  display: flex;
  /* Ширина ограничена сверху: при одном дне продаж `flex: 1 0 auto` растягивал
     единственный столбец на всю карточку, и график читался как сплошная заливка, а не как
     столбик (поймано снимком на 390 px). Снизу держит цель касания 24 px из WCAG 2.5.8:
     когда дней много, столбцы упираются в неё и карточка начинает прокручиваться вбок —
     это лучше, чем нажимаемая полоска в один пиксель. */
  flex: 1 1 auto;
  max-width: 3rem;
  align-items: flex-end;
  justify-content: center;
  min-width: var(--crm-tap-target, 24px);
  min-height: var(--crm-tap-target, 24px);
  height: 100%;
  padding: 0;
  background: none;
  border: 0;
}

.crm-stolbik-zalivka {
  width: 100%;
  min-height: 2px;
  background-color: var(--bs-primary);
}

.crm-stolbik[aria-pressed="true"] .crm-stolbik-zalivka {
  background-color: var(--bs-warning);
}

.crm-stolbik-0 .crm-stolbik-zalivka { height: 0; }
.crm-stolbik-1 .crm-stolbik-zalivka { height: 5%; }
.crm-stolbik-2 .crm-stolbik-zalivka { height: 10%; }
.crm-stolbik-3 .crm-stolbik-zalivka { height: 15%; }
.crm-stolbik-4 .crm-stolbik-zalivka { height: 20%; }
.crm-stolbik-5 .crm-stolbik-zalivka { height: 25%; }
.crm-stolbik-6 .crm-stolbik-zalivka { height: 30%; }
.crm-stolbik-7 .crm-stolbik-zalivka { height: 35%; }
.crm-stolbik-8 .crm-stolbik-zalivka { height: 40%; }
.crm-stolbik-9 .crm-stolbik-zalivka { height: 45%; }
.crm-stolbik-10 .crm-stolbik-zalivka { height: 50%; }
.crm-stolbik-11 .crm-stolbik-zalivka { height: 55%; }
.crm-stolbik-12 .crm-stolbik-zalivka { height: 60%; }
.crm-stolbik-13 .crm-stolbik-zalivka { height: 65%; }
.crm-stolbik-14 .crm-stolbik-zalivka { height: 70%; }
.crm-stolbik-15 .crm-stolbik-zalivka { height: 75%; }
.crm-stolbik-16 .crm-stolbik-zalivka { height: 80%; }
.crm-stolbik-17 .crm-stolbik-zalivka { height: 85%; }
.crm-stolbik-18 .crm-stolbik-zalivka { height: 90%; }
.crm-stolbik-19 .crm-stolbik-zalivka { height: 95%; }
.crm-stolbik-20 .crm-stolbik-zalivka { height: 100%; }

/* Шапка узкой денежной таблицы. В колонке дашборда на треть экрана заголовок
   «При выполнении плана» не помещался и обрезался на «При выполнени…»: пользователь видел
   обрубок там, где стоит смысл второй колонки. Перенос по словам вместо обрезки. */
.crm-tablica-deneg th {
  white-space: normal;
  overflow-wrap: anywhere;
}

/* Поле отчёта в строке закрытия задачи. С появлением выбора результата (отказ от продления)
   строка формы на 375 px ужимала единственный растяжимый элемент — само поле «что сделано» —
   до полоски шириной с курсор, хотя отчёт при отказе обязателен. Минимальная ширина плюс
   перенос строки у формы: на узком экране селект и кнопка уезжают на вторую строку, поле
   остаётся читаемым. Найдено критиком результата 19.09.2026 на снимке 375 px. */
.crm-otchyot-zadachi {
  min-width: 12rem;
}
