/*
 * Правила, общие для обоих кабинетов.
 *
 * Цвета здесь — переменные `--eb-*` из `palette.css`. Он подключается до
 * этого файла, и без него всё ниже теряет цвет.
 *
 * Раньше этот же набор был скопирован инлайновым <style> в
 * `prototypes/tenant-lk-v1/index.html` и `prototypes/platform-lk-v1/index.html`.
 * Две копии одного оформления расходятся молча: поправили стрелку у списка в
 * одном кабинете — во втором она осталась прежней, и никто не заметит.
 * Аудит 26.09.2026, находка O-11.
 *
 * Сюда попадает только то, что нельзя выразить утилитой Tailwind: стрелка у
 * нативного <select>, настройка переменного шрифта иконок и уважение к
 * системной просьбе убрать анимации.
 */

/* Единая стрелка у списка: нативный вид, но без ломки темы. */
select.eb-select {
  -webkit-appearance: none;
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='%235a5781'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M19 9l-7 7-7-7'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.65rem center;
  background-size: 1.125rem;
}

/*
 * Иконки — переменный шрифт; без этих осей глиф рисуется в начертании по
 * умолчанию и не совпадает по весу с текстом рядом.
 */
.material-symbols-outlined {
  font-variation-settings: "FILL" 0, "wght" 400, "GRAD" 0, "opsz" 24;
  display: inline-block;
  vertical-align: middle;
  font-size: 1.25rem;
}

/*
 * Человек попросил систему убрать движение — например, из-за укачивания или
 * вестибулярных нарушений. Просьба выполняется целиком, а не выборочно.
 */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ────────────────────────────────────────────────────────────────────────────
   Состояния: получилось / внимание / не получилось.

   Аудит 26.09.2026 насчитал в кабинетах 57 мест, где эти три смысла записаны
   27 разными наборами классов сырой палитры Tailwind: пять оттенков зелёного,
   четыре красного, четыре жёлтого. Одинаковое сообщение выглядело по-разному
   на соседних экранах, а половина сочетаний не проходила по контрасту.

   Цвета совпадают со значениями семантических токенов в
   `tailwind.eventbot-ui.config.cjs` — когда общий CSS пересоберут, вид не
   изменится. Контраст текста к фону проверен: 11,8:1 (получилось),
   14,1:1 (внимание), 12,6:1 (не получилось) — выше требования 4,5:1.
   ──────────────────────────────────────────────────────────────────────────── */

:root {
  --eb-ok: rgb(var(--eb-success));
  --eb-ok-bg: rgb(var(--eb-success-container));
  --eb-ok-fg: rgb(var(--eb-on-success-container));
  --eb-warn: rgb(var(--eb-warning));
  --eb-warn-bg: rgb(var(--eb-warning-container));
  --eb-warn-fg: rgb(var(--eb-on-warning-container));
  --eb-err: rgb(var(--eb-error));
  --eb-err-bg: rgb(var(--eb-error-container));
  --eb-err-fg: rgb(var(--eb-on-error-container));
  --eb-info: rgb(var(--eb-info));
  --eb-info-bg: rgb(var(--eb-info-container));
  --eb-info-fg: rgb(var(--eb-on-info-container));
  /* Нейтральная метка: «черновик», «завершено» — состояние без оценки. */
  --eb-muted-bg: rgb(var(--eb-surface-container));
  --eb-muted-fg: rgb(var(--eb-on-surface));
}

/*
 * `display` здесь не задаётся намеренно.
 *
 * Этот файл подключается ПОСЛЕ `eventbot-ui.css`, а специфичность у одного
 * класса та же — значит `.eb-note { display: block }` перебивал бы
 * `.hidden { display: none }` из Tailwind, и всё, что должно ждать своего
 * часа, было бы видно всегда. Так и вышло: предупреждение о тарифе на
 * карточке клиента, поле ошибки второго фактора и баннер «откройте через
 * HTTP» висели бы на экране постоянно. Все эти блоки — `div` и `p`, они
 * блочные сами по себе.
 *
 * Там, где `display` всё-таки нужен (метка — inline-flex), ниже стоит явная
 * уступка классу `hidden`.
 */
.eb-note {
  margin-bottom: 1rem;
  padding: 0.75rem 1rem;
  border: 1px solid;
  border-radius: 0.75rem;
  font-size: 0.875rem;
  line-height: 1.5;
}
.eb-note--ok {
  border-color: rgb(var(--eb-success)); /* запасной для браузеров без color-mix() */
  border-color: color-mix(in srgb, var(--eb-ok) 35%, transparent);
  background: var(--eb-ok-bg);
  color: var(--eb-ok-fg);
}
.eb-note--warn {
  border-color: rgb(var(--eb-warning));
  border-color: color-mix(in srgb, var(--eb-warn) 35%, transparent);
  background: var(--eb-warn-bg);
  color: var(--eb-warn-fg);
}
.eb-note--err {
  border-color: rgb(var(--eb-error));
  border-color: color-mix(in srgb, var(--eb-err) 35%, transparent);
  background: var(--eb-err-bg);
  color: var(--eb-err-fg);
}
/*
 * Точка состояния и заливка полосы. Сами по себе они бесцветны — цвет берут
 * отсюда, чтобы «внимание» на точке, в метке и в сообщении был одним цветом.
 *
 * Превышение лимита продаж — не ошибка: продажи идут дальше, просто сверх
 * лимита берётся процент. Поэтому обе ступени полосы жёлтые, вторая насыщеннее.
 */
.eb-dot--ok {
  background: var(--eb-ok);
}
.eb-dot--warn {
  background: var(--eb-warn);
}
.eb-dot--err {
  background: var(--eb-err);
}
.eb-fill--near {
  background: rgb(var(--eb-warning)); /* запасной для браузеров без CSS Color 5 */
  background: color-mix(in srgb, var(--eb-warn) 70%, white);
}
.eb-fill--over {
  background: var(--eb-warn);
}

/*
 * Только цвет, без геометрии.
 *
 * `.eb-note` и `.eb-badge` задают ещё и отступы, радиус и размер шрифта —
 * это удобно для нового блока и вредно для уже свёрстанного: врезка-таблетка
 * в строке превратилась бы в блочное сообщение. Здесь берут только три
 * значения цвета, а форму элемент оставляет свою.
 *
 * Отсюда же — присваивание из скрипта: `el.className = "… eb-tone--err"`.
 */
.eb-tone--ok {
  border-color: var(--eb-ok);
  background: var(--eb-ok-bg);
  color: var(--eb-ok-fg);
}
.eb-tone--warn {
  border-color: var(--eb-warn);
  background: var(--eb-warn-bg);
  color: var(--eb-warn-fg);
}
.eb-tone--err {
  border-color: var(--eb-err);
  background: var(--eb-err-bg);
  color: var(--eb-err-fg);
}
.eb-tone--info {
  border-color: var(--eb-info);
  background: var(--eb-info-bg);
  color: var(--eb-info-fg);
}
.eb-tone--muted {
  border-color: var(--eb-muted-fg);
  background: var(--eb-muted-bg);
  color: var(--eb-muted-fg);
}

/*
 * Компактное сообщение: то же по смыслу, но внутри карточки или строки, где
 * полноразмерный блок разорвал бы вёрстку. Отдельный класс, а не утилиты
 * Tailwind, потому что controls.css грузится после сборки и перебил бы их.
 */
.eb-note--sm {
  margin-bottom: 0.75rem;
  padding: 0.5rem 0.75rem;
  border-radius: 0.5rem;
  font-size: 0.75rem;
}
.eb-note--info {
  border-color: rgb(var(--eb-info));
  border-color: color-mix(in srgb, var(--eb-info) 35%, transparent);
  background: var(--eb-info-bg);
  color: var(--eb-info-fg);
}

/* Метка состояния в строке таблицы или рядом с заголовком. */
.eb-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.125rem 0.5rem;
  border-radius: 9999px;
  font-size: 0.75rem;
  font-weight: 600;
  white-space: nowrap;
}
.eb-badge--ok {
  background: var(--eb-ok-bg);
  color: var(--eb-ok-fg);
}
.eb-badge--warn {
  background: var(--eb-warn-bg);
  color: var(--eb-warn-fg);
}
.eb-badge--err {
  background: var(--eb-err-bg);
  color: var(--eb-err-fg);
}
.eb-badge--info {
  background: var(--eb-info-bg);
  color: var(--eb-info-fg);
}
/*
 * Нейтральная метка. Нужна ровно там, где состояние не «хорошо» и не «плохо»:
 * черновик, завершено, архив. Раньше это писали пятью оттенками серого
 * (bg-slate-100/200, text-slate-700/900) — читалось как разные состояния.
 */
.eb-badge--muted {
  background: var(--eb-muted-bg);
  color: var(--eb-muted-fg);
}

/*
 * Уступка классу `hidden`: этот файл грузится после Tailwind, и при равной
 * специфичности выигрывает он. Без этой строки метка, которую код прячет,
 * осталась бы на экране.
 */
/*
 * Цель нажатия не меньше 24 пикселей по высоте (WCAG 2.2, §2.5.8 «Target Size»).
 *
 * Кнопки-ссылки без отступов — «+ Ещё ссылка», «Детали», заголовки таблиц с
 * сортировкой — имели высоту строки: 16-20 пикселей. Мышью попасть трудно,
 * пальцем почти невозможно. Здесь добирается только высота: ширину и отступы
 * элемент оставляет свои, чтобы не разъезжалась вёрстка таблиц.
 */
/*
 * Число на значке шапки: сколько замечаний ждёт.
 *
 * Своя фигура, а не `.eb-badge`: та рассчитана на слово в строке текста, а
 * здесь кружок поверх кнопки. Минимальная ширина держит форму у однозначных
 * чисел, `padding` даёт вырасти двузначным, дальше показываем «9+».
 */
.eb-badge-count {
  position: absolute;
  top: -4px;
  right: -4px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 999px;
  background: rgb(var(--eb-error));
  color: rgb(var(--eb-on-error));
  font-size: 11px;
  font-weight: 700;
  line-height: 1;
  /* Кружок не должен сливаться с кнопкой под ним. */
  box-shadow: 0 0 0 2px rgb(var(--eb-surface-container-lowest));
}

/*
 * Уступка `hidden`: `controls.css` грузится ПОСЛЕ Tailwind, специфичность та
 * же, и без этой строки наш `display` перебил бы `.hidden`. Правило общее для
 * всех классов слоя, которые задают `display`.
 */
.eb-badge-count.hidden {
  display: none;
}

.eb-tap {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
}

/*
 * Действия в последней ячейке строки — «Изменить», «Статус», «Настроить».
 * Это список целей, а не ссылка в предложении, и они были высотой в строку
 * текста: 17-20 пикселей. Последняя ячейка выбрана намеренно: в ней короткие
 * подписи, а в первых бывает длинное название, которому нужен перенос по
 * словам — `inline-flex` его запретил бы.
 */
#app td:last-child a,
#app td:last-child button,
#app td:last-child summary {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
}

.eb-badge.hidden,
.eb-note.hidden,
.eb-tap.hidden {
  display: none;
}

/* Та же уступка для карточек выбора — отдельным правилом, чтобы предыдущее
   не расползалось и сторож мог читать его целиком. */
.eb-choice.hidden,
.eb-choice-group.hidden,
.eb-choice__body.hidden {
  display: none;
}

/* Цветной текст: «Сохранено» рядом с кнопкой, «Отозван» в таблице. */
.eb-text--ok {
  color: var(--eb-ok);
}
.eb-text--warn {
  color: var(--eb-warn);
}
.eb-text--err {
  color: var(--eb-err);
}

/* Кнопка необратимого действия — контурная, чтобы не тянуть на себя внимание. */
.eb-danger-outline {
  border: 1px solid rgb(var(--eb-error));
  border-color: color-mix(in srgb, var(--eb-err) 35%, transparent);
  background: rgb(var(--eb-error-container));
  background: color-mix(in srgb, var(--eb-err) 6%, rgb(var(--eb-surface-container-lowest)));
  color: var(--eb-err);
}
.eb-danger-outline:hover {
  background: rgb(var(--eb-error-container));
  background: color-mix(in srgb, var(--eb-err) 12%, rgb(var(--eb-surface-container-lowest)));
}

/* Подтверждающее действие, когда «сохранить» — это возврат к норме. */
.eb-ok-solid {
  background: var(--eb-ok);
  color: rgb(var(--eb-on-success));
}
.eb-ok-solid:hover {
  background: rgb(var(--eb-success));
  background: color-mix(in srgb, var(--eb-ok) 85%, rgb(var(--eb-on-primary-fixed)));
}

/*
 * Поле пароля с кнопкой «Показать».
 *
 * Отступ справа стоял классом `pr-12`, которого в собранном CSS нет
 * (Tailwind выпускает только увиденное сканером). Из-за этого набранный
 * пароль уезжал ПОД кнопку — на телефоне перекрытие было 64 пикселя, то
 * есть конец пароля не виден вовсе.
 *
 * Ширина кнопки и отступ поля берутся из одной переменной: разъехаться
 * они теперь не могут, даже если подпись на кнопке поменяют.
 */
.eb-pw-input,
.eb-pw-toggle {
  --eb-pw-toggle-w: 5.5rem;
}
.eb-pw-input {
  padding-right: var(--eb-pw-toggle-w);
}
.eb-pw-toggle {
  width: var(--eb-pw-toggle-w);
  border-top-right-radius: 0.75rem;
  border-bottom-right-radius: 0.75rem;
}
.eb-pw-input.hidden,
.eb-pw-toggle.hidden {
  display: none;
}

/*
 * Галочка и переключатель — 24 пикселя, не 20.
 *
 * `h-5 w-5` даёт ровно 20, а обязательный минимум по WCAG 2.2 — 24. Подпись
 * рядом связана через `for`, но она высотой в строку текста, так что
 * увеличить надо сам квадратик. Разница на глаз почти незаметна, а
 * промахов на телефоне заметно меньше.
 */
#app input[type="checkbox"],
#app input[type="radio"] {
  min-width: 24px;
  min-height: 24px;
}

/*
 * Раскрывающийся заголовок — цель касания, а не строка текста.
 *
 * «Где взять токен», «Как подключить канал», «Подсказка» были высотой в
 * строку — 20 пикселей. По WCAG 2.2 минимум 24, и это именно те подсказки,
 * которые открывают, когда уже запутались: промахиваться по ним обиднее
 * всего. Ставим 32: заметно больше минимума, но заголовок не превращается
 * в кнопку во всю ширину.
 */
#app summary[class] {
  display: flex;
  align-items: center;
  min-height: 32px;
}
#app summary[class].hidden {
  display: none;
}

/*
 * Раскрывающиеся разделы формы.
 *
 * Браузер рисует у <summary> свой треугольник, и рядом с нашей стрелкой их
 * становится два. `list-style` его убирает не везде: Safari до 18 слушает
 * только `::-webkit-details-marker`.
 */
summary[class]::-webkit-details-marker {
  display: none;
}
summary[class]::marker {
  content: "";
}

/* Стрелка смотрит вниз, когда закрыто, и вверх, когда открыто. */
details[open] > summary [aria-hidden="true"].material-symbols-outlined {
  transform: rotate(180deg);
}
details > summary [aria-hidden="true"].material-symbols-outlined {
  transition: transform 0.15s ease;
}

@media (prefers-reduced-motion: reduce) {
  details > summary [aria-hidden="true"].material-symbols-outlined {
    transition: none;
  }
}

/*
 * Таблица на телефоне — карточками.
 *
 * У всех таблиц кабинета стоит `min-w-[560px]`: на экране 375 пикселей это
 * значит, что половина колонок всегда за краем. Чтобы увидеть цену, надо
 * тянуть таблицу вбок, и заголовок уезжает вместе с ней — понять, что за
 * число ты смотришь, становится нельзя.
 *
 * Подпись каждой ячейки берётся из шапки (`data-label`, его расставляет
 * `tableWrap`), поэтому шапку можно убрать: она повторялась бы в каждой
 * карточке. Убираем её так, чтобы экранная читалка продолжала связывать
 * ячейку со столбцом.
 */
/*
 * Контейнер для запроса ниже: таблица спрашивает ширину у своей обёртки,
 * а не у окна. В кабинете это разные вещи — слева 256 пикселей меню, и на
 * ноутбуке 1024 окно «широкое», а таблице остаётся 702.
 */
.eb-table-host {
  container-type: inline-size;
}

/*
 * Порог — 820, а не «ширина телефона».
 *
 * Мерили: список мероприятий как таблица требует 808 пикселей. Ниже этого
 * он либо уезжает вбок, либо ужимается до нечитаемого. Порог по контейнеру
 * означает, что на широком экране таблицы остаются таблицами, а карточки
 * включаются там, где места действительно нет, — включая ноутбук 1024–1150,
 * где 256 пикселей забирает меню.
 */
@container (max-width: 820px) {
  .eb-table--cards {
    min-width: 0 !important;
    display: block;
  }
  .eb-table--cards thead {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border-width: 0;
  }
  .eb-table--cards tbody,
  .eb-table--cards tr,
  .eb-table--cards td {
    display: block;
    width: auto;
  }
  .eb-table--cards tr {
    border: 1px solid rgb(var(--eb-outline) / 0.18);
    border-radius: 16px;
    padding: 4px 14px;
    margin: 0 0 12px;
    background: rgb(var(--eb-surface-container-lowest));
  }
  .eb-table--cards tr:last-child {
    margin-bottom: 0;
  }
  .eb-table--cards td {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
    padding: 8px 0;
    border-bottom: 1px solid rgb(var(--eb-outline) / 0.1);
    text-align: left;
  }
  .eb-table--cards tr > td:last-child {
    border-bottom: 0;
  }
  .eb-table--cards td[data-label]::before {
    content: attr(data-label);
    flex: none;
    max-width: 45%;
    font-size: 12px;
    font-weight: 600;
    color: rgb(var(--eb-on-surface-variant));
  }
  /* Ячейка без подписи (и строка пустого состояния) занимает всю ширину. */
  .eb-table--cards td:not([data-label]) {
    justify-content: flex-start;
  }
  /*
   * Ячейка, которая на широком экране держит столбец, а значения не несёт.
   * В таблице это выравнивание, в карточке — строка «Категория» вообще без
   * ответа. Такие строки сеансов и выглядели мусором.
   */
  .eb-table--cards td.eb-cell--blank {
    display: none;
  }
  /* Выравнивание по правому краю в карточке не имеет смысла: там одна строка. */
  .eb-table--cards td.text-right {
    text-align: left;
  }
}

@media (max-width: 640px) {
  /*
   * Первая ячейка — это заголовок карточки. Подпись «Название» над словом
   * «Арена Холл» ничего не добавляет, а место занимает; и вторая строка
   * (адрес, код) должна вставать под именем, а не рядом с ним.
   */
  .eb-table--cards tr > td:first-child {
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    padding-top: 12px;
    font-size: 15px;
  }
  .eb-table--cards tr > td:first-child::before {
    display: none;
  }

  /*
   * Последняя ячейка — действия. В строку они не помещаются: «Удалить»
   * уезжало за край карточки, то есть кнопка была, а нажать её было нельзя.
   */
  .eb-table--cards tr > td:last-child {
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
    padding-bottom: 12px;
  }
  .eb-table--cards tr > td:last-child > * {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-start;
    gap: 8px;
  }
}

/*
 * «Меньше движения» — это настройка системы, а не пожелание.
 *
 * Её включают не ради вкуса: у части людей движение на экране вызывает
 * тошноту и головокружение (вестибулярные расстройства), у части — приступ.
 * Правило общее на весь кабинет, потому что анимации раскиданы по разным
 * файлам: скелетоны, выдвижное меню, стрелка раскрытия, всплывающие плашки.
 *
 * Нули, а не `none`: анимация должна ДОЙТИ ДО КОНЦА мгновенно, иначе
 * появляющиеся элементы, у которых стартовое состояние прозрачное, так и
 * останутся невидимыми.
 */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/*
 * Выбор из нескольких вариантов карточками.
 *
 * Внутри — настоящие радиокнопки: форма отправляется как раньше, клавиатура
 * (стрелки внутри группы) и экранная читалка работают без единой строчки
 * скриптов. Сама радиокнопка спрятана визуально, но НЕ убрана из потока
 * `display: none` — иначе она выпала бы из порядка обхода с клавиатуры.
 */
.eb-choice-group {
  display: grid;
  gap: 10px;
  margin-top: 4px;
}
@media (min-width: 640px) {
  .eb-choice-group {
    grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  }
}
.eb-choice {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 10px;
  min-height: 44px;
  padding: 12px 14px;
  border: 1px solid rgb(var(--eb-outline) / 0.28);
  border-radius: 16px;
  background: rgb(var(--eb-surface-container-lowest));
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s, box-shadow 0.15s;
}
.eb-choice:hover {
  border-color: rgb(var(--eb-primary) / 0.4);
  background: rgb(var(--eb-surface-container-lowest));
}
.eb-choice__input {
  margin: 2px 0 0;
  width: 18px;
  height: 18px;
  flex: none;
  accent-color: rgb(var(--eb-primary));
}
.eb-choice__body {
  display: flex;
  min-width: 0;
  flex-direction: column;
  gap: 2px;
}
.eb-choice__title {
  font-size: 14px;
  font-weight: 600;
  color: rgb(var(--eb-on-background));
}
.eb-choice__note {
  font-size: 12px;
  line-height: 1.45;
  color: rgb(var(--eb-on-surface-variant));
}
/* Выбранная карточка: рамка и подложка, а не одна только точка в кружке. */
.eb-choice:has(.eb-choice__input:checked) {
  border-color: rgb(var(--eb-primary));
  background: rgb(var(--eb-surface-container-low));
  box-shadow: inset 0 0 0 1px rgb(var(--eb-primary));
}
/*
 * Кольцо фокуса на всей карточке: у спрятанной радиокнопки его почти не
 * видно, а нажимают именно по карточке.
 */
.eb-choice:has(.eb-choice__input:focus-visible) {
  outline: 2px solid rgb(var(--eb-primary));
  outline-offset: 2px;
}

/*
 * Панель действий длинной формы.
 *
 * Форма мероприятия — полтора экрана на настольном и четыре на телефоне.
 * Кнопка «Создать» стояла в самом низу: чтобы сохранить правку в первом поле,
 * надо было пролистать всё, что ниже. А на телефоне, где клавиатура занимает
 * половину экрана, до неё было не добраться вообще, не закрыв клавиатуру.
 *
 * Держим её у нижнего края, пока форма не кончилась. `position: sticky`, а не
 * `fixed`: панель остаётся частью формы, не перекрывает нижнюю часть страницы
 * и исчезает вместе с формой при прокрутке дальше.
 */
.eb-form-actions {
  position: sticky;
  bottom: 0;
  z-index: 20;
  margin-top: 32px;
  padding: 16px 0 max(16px, env(safe-area-inset-bottom));
  border-top: 1px solid rgb(var(--eb-outline) / 0.18);
  background: rgb(var(--eb-surface-container-lowest));
  /* Тень наружу вверх: показывает, что под панелью есть ещё содержимое. */
  box-shadow: 0 -12px 20px -16px rgb(var(--eb-on-background) / 0.45);
}
.eb-form-actions.hidden {
  display: none;
}

/*
 * Кольцо фокуса — везде и заметное.
 *
 * Работать с клавиатуры в кабинете было почти невозможно: у половины кнопок
 * и ссылок фокус не рисовался вовсе, потому что Tailwind-сброс убирает
 * `outline`, а `focus-visible` расставлен не везде. Общее правило дешевле и
 * надёжнее, чем сто мест с отдельными классами.
 *
 * `:focus-visible`, а не `:focus`: кольцо появляется при работе клавиатурой,
 * но не после обычного нажатия мышью.
 */
#app a:focus-visible,
#app button:focus-visible,
#app input:focus-visible,
#app select:focus-visible,
#app textarea:focus-visible,
#app summary:focus-visible,
#app [tabindex]:focus-visible {
  outline: 2px solid rgb(var(--eb-primary));
  outline-offset: 2px;
  border-radius: 6px;
}
/* На тёмной подложке синее кольцо теряется — там белое. */
#app .bg-primary:focus-visible,
#app .bg-error:focus-visible {
  outline-color: rgb(var(--eb-on-primary));
  outline-offset: 1px;
}

/*
 * Подпись колонки, по которой сортируют, — цель касания.
 *
 * Кнопка была высотой в строку текста: 15 пикселей при обязательном
 * минимуме 24 (WCAG 2.2). На телефоне попасть в такую подпись, не задев
 * соседнюю колонку, почти нельзя.
 */
.col-sort-btn {
  min-height: 24px;
}
.col-sort-btn.hidden {
  display: none;
}

/*
 * Таблица клиентов: управление колонками видно глазами.
 *
 * Раньше под таблицей висела строка «Колонки можно менять местами и тянуть
 * за край». Текст вместо органа управления: читать его нужно каждому и
 * каждый раз, а понять, ЧТО именно тянуть, он всё равно не помогал —
 * ручка ширины была полоской в один пиксель, а заголовок никак не
 * откликался на курсор.
 *
 * Значок «⋮⋮» остаётся приглушённым в покое (десять колонок × яркий значок
 * — это рябь) и наливается цветом на своей колонке. Так подсказка приходит
 * туда, куда человек уже смотрит.
 */
.eb-col-grip {
  color: rgb(var(--eb-on-surface-variant) / 0.35);
  transition: color 0.12s ease;
}
.eb-col-th:hover .eb-col-grip,
.eb-col-th:focus-within .eb-col-grip {
  color: rgb(var(--eb-primary));
}

/* Граница между колонками — она же ручка ширины. */
.eb-col-resize-line {
  width: 1px;
  height: 55%;
  border-radius: 1px;
  background-color: rgb(var(--eb-outline) / 0.45);
  transition: width 0.12s ease, height 0.12s ease, background-color 0.12s ease;
}
.col-resize-handle:hover .eb-col-resize-line,
.eb-col-th:hover .eb-col-resize-line {
  width: 2px;
  height: 70%;
  background-color: rgb(var(--eb-primary));
}
/* Захват: подсветка всей ручки — видно, что тянется именно она. */
.col-resize-handle:active,
.col-resize-handle.bg-primary\/25 {
  background-color: rgb(var(--eb-primary) / 0.16);
}
.col-resize-handle:active .eb-col-resize-line {
  width: 2px;
  height: 100%;
  background-color: rgb(var(--eb-primary));
}

@media (prefers-reduced-motion: reduce) {
  .eb-col-grip,
  .eb-col-resize-line {
    transition-duration: 0.01ms;
  }
}

/*
 * Выбор типа блока в конструкторе витрины.
 *
 * Кнопки были собраны инлайновыми стилями с шестнадцатеричными цветами
 * (rgb(var(--eb-outline-variant)), rgb(var(--eb-primary)), rgb(var(--eb-info-container)), rgb(var(--eb-on-surface-variant))), а подсветка при наведении — атрибутами
 * `onmouseover`/`onmouseout`, то есть исполняемым кодом в разметке. Строгая
 * политика содержимого, которая уже действует у оператора, такой код не
 * выполняет: кнопки перестали бы откликаться на курсор.
 */
.eb-block-pick {
  display: block;
  width: 100%;
  min-height: 44px;
  padding: 0.75rem;
  border: 1px solid var(--eb-line, rgb(var(--eb-outline) / 0.3));
  border-radius: 0.75rem;
  background: rgb(var(--eb-surface-container-lowest));
  text-align: left;
  cursor: pointer;
  transition: border-color 0.12s ease, background-color 0.12s ease;
}
.eb-block-pick:hover {
  border-color: rgb(var(--eb-primary));
  background: rgb(var(--eb-primary) / 0.06);
}
.eb-block-pick__emoji {
  display: block;
  font-size: 1.5rem;
  line-height: 1.2;
}
.eb-block-pick__name {
  display: block;
  margin-top: 0.25rem;
  font-size: 0.875rem;
  font-weight: 700;
}
.eb-block-pick__group {
  display: block;
  margin-top: 0.125rem;
  font-size: 0.6875rem;
  color: rgb(var(--eb-on-surface-variant));
}

/*
 * Уступка `hidden` из Tailwind. `controls.css` грузится ПОСЛЕ сборки
 * Tailwind, специфичность у одного класса та же — поэтому наш `display`
 * выиграл бы у `.hidden { display: none }`, и спрятанное стало бы видно.
 */
.eb-block-pick.hidden,
.eb-block-pick__emoji.hidden,
.eb-block-pick__name.hidden,
.eb-block-pick__group.hidden {
  display: none;
}

@media (prefers-reduced-motion: reduce) {
  .eb-block-pick {
    transition-duration: 0.01ms;
  }
}

/* ══════════════════════════════════════════════════════════════════════
   Кнопки
   ══════════════════════════════════════════════════════════════════════

   В кабинетах 304 кнопки и 148 разных наборов классов на них. Одна и та же
   по смыслу кнопка оказывалась то 44 пикселя высотой, то 40; то 700-го
   начертания, то 500-го; отступы то `px-5 py-2.5`, то `px-4` без
   вертикального вовсе. Это не стиль, это накопленный разнобой: каждый
   следующий набирал классы заново и чуть иначе.

   Пять видов покрывают всё, что кабинету нужно сказать кнопкой:

     primary   — главное действие экрана, одно на экран;
     secondary — обычное действие;
     danger    — необратимое; контурная, а не заливная: она не должна
                 тянуть на себя внимание, её жмут осознанно;
     ghost     — третьестепенное, внутри строки или карточки;
     link      — действие, выглядящее ссылкой (в тексте, в ячейке).

   Размеры: обычный 44 пикселя (цель касания), `--sm` 36 — для строк
   таблиц, где 44 разорвали бы ряд. Оба выше обязательного минимума 24.
*/
.eb-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: 2.75rem;
  padding: 0.625rem 1.25rem;
  border: 1px solid transparent;
  border-radius: 0.625rem;
  font-size: 0.875rem;
  font-weight: 700;
  line-height: 1.25;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}
.eb-btn:disabled,
.eb-btn[aria-disabled="true"] {
  opacity: 0.55;
  cursor: not-allowed;
}

.eb-btn--primary {
  background: rgb(var(--eb-primary));
  color: rgb(var(--eb-on-primary));
  box-shadow: 0 1px 2px rgb(var(--eb-inverse-surface) / 0.08);
}
.eb-btn--primary:hover:not(:disabled) {
  background: rgb(var(--eb-primary-dim));
}

.eb-btn--secondary {
  background: rgb(var(--eb-surface-container-lowest));
  border-color: rgb(var(--eb-outline-variant) / 0.55);
  color: rgb(var(--eb-on-background));
  font-weight: 600;
  box-shadow: 0 1px 2px rgb(var(--eb-inverse-surface) / 0.05);
}
.eb-btn--secondary:hover:not(:disabled) {
  border-color: rgb(var(--eb-outline) / 0.8);
  background: rgb(var(--eb-surface-container-lowest));
}

.eb-btn--danger {
  background: rgb(var(--eb-error) / 0.05);
  border-color: rgb(var(--eb-error) / 0.35);
  color: rgb(var(--eb-error));
  font-weight: 600;
}
.eb-btn--danger:hover:not(:disabled) {
  background: rgb(var(--eb-error) / 0.1);
}

.eb-btn--ghost {
  background: transparent;
  color: rgb(var(--eb-on-surface-variant));
  font-weight: 600;
}
.eb-btn--ghost:hover:not(:disabled) {
  background: rgb(var(--eb-surface-container-low));
  color: rgb(var(--eb-on-background));
}

.eb-btn--link {
  min-height: 1.5rem;
  padding: 0;
  background: transparent;
  border-color: transparent;
  color: rgb(var(--eb-primary));
  font-weight: 600;
  box-shadow: none;
}
.eb-btn--link:hover:not(:disabled) {
  text-decoration: underline;
}

/*
 * Выбранная кнопка в ряду: шаблон витрины, тип карточки, вариант оплаты.
 * Это по-прежнему обычная кнопка, просто с отметкой «сейчас выбрана» —
 * поэтому модификатор, а не отдельный вид.
 */
.eb-btn--selected {
  border-color: rgb(var(--eb-primary) / 0.4);
  background: rgb(var(--eb-primary) / 0.06);
  color: rgb(var(--eb-on-background));
}
.eb-btn--selected:hover:not(:disabled) {
  background: rgb(var(--eb-primary) / 0.1);
}

/* Необратимое действие, выглядящее ссылкой: «Удалить» в конце строки. */
.eb-btn--link-danger {
  min-height: 1.5rem;
  padding: 0;
  background: transparent;
  border-color: transparent;
  color: rgb(var(--eb-error));
  font-weight: 600;
  text-decoration: underline;
  text-decoration-color: rgb(var(--eb-error) / 0.4);
  box-shadow: none;
}
.eb-btn--link-danger:hover:not(:disabled) {
  text-decoration-color: rgb(var(--eb-error));
}

/* Строка таблицы: 44 пикселя разорвали бы ряд, 36 — нет. */
.eb-btn--sm {
  min-height: 2.25rem;
  padding: 0.25rem 0.75rem;
  font-size: 0.8125rem;
}
/* Во всю ширину: вход, регистрация, узкие карточки. */
.eb-btn--block {
  display: flex;
  width: 100%;
}
/* Только значок: подпись остаётся для читалки в `aria-label`. */
.eb-btn--icon {
  min-width: 2.75rem;
  padding: 0;
}
.eb-btn--icon.eb-btn--sm {
  min-width: 2.25rem;
}

/*
 * Уступки утилитам скрытия.
 *
 * `controls.css` грузится после сборки Tailwind, а специфичность у одного
 * класса та же — значит `display` из `.eb-btn` побеждает `hidden`. Кнопка
 * закрытия бокового меню так и осталась видимой на широком экране: у неё
 * стоит `lg:hidden`, и он проигрывал.
 *
 * Отзывчивые варианты приходится перечислять: обойти это одним правилом
 * нельзя, зато их в кабинете ровно столько, сколько перечислено, и сторож
 * следит, чтобы не появилось новых.
 */
.eb-btn.hidden,
.eb-btn--block.hidden {
  display: none;
}
@media (min-width: 640px) {
  .eb-btn.sm\:hidden {
    display: none;
  }
}
@media (min-width: 768px) {
  .eb-btn.md\:hidden {
    display: none;
  }
}
@media (min-width: 1024px) {
  .eb-btn.lg\:hidden {
    display: none;
  }
}

/* ══════════════════════════════════════════════════════════════════════
   Окно поверх страницы
   ══════════════════════════════════════════════════════════════════════

   Окна собирались из <div> поверх страницы, и к каждому руками
   дописывалась ловушка фокуса и обработка Esc — по сорок строк на окно, с
   разным поведением. Родной <dialog> даёт и то, и другое, и затемнение,
   и возврат фокуса при закрытии — бесплатно и одинаково.
*/
.eb-dialog {
  width: min(32rem, calc(100vw - 2rem));
  max-height: min(85vh, 48rem);
  padding: 0;
  border: 1px solid rgb(var(--eb-outline-variant) / 0.35);
  border-radius: 1rem;
  background: rgb(var(--eb-surface-container-lowest));
  color: rgb(var(--eb-on-background));
  box-shadow: 0 24px 48px rgb(var(--eb-inverse-surface) / 0.18);
  overflow: hidden;
}
.eb-dialog::backdrop {
  background: rgb(var(--eb-inverse-surface) / 0.45);
}
.eb-dialog__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 1.25rem 1.25rem 0;
}
.eb-dialog__title {
  margin: 0;
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.5;
}
.eb-dialog__body {
  padding: 0.75rem 1.25rem 0;
  overflow-y: auto;
  font-size: 0.875rem;
  line-height: 1.5;
}
.eb-dialog__foot {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 0.5rem;
  padding: 1.25rem;
}
.eb-dialog.hidden {
  display: none;
}

/* ══════════════════════════════════════════════════════════════════════
   Вкладки раздела
   ══════════════════════════════════════════════════════════════════════

   Полоска вкладок набиралась по месту: в магазине одними классами, в
   конструкторе витрины — инлайновыми стилями с шестнадцатеричными
   цветами. Текущая вкладка там отличалась заливкой, здесь — подчёркиванием.
*/
.eb-tabs {
  display: flex;
  flex-wrap: nowrap;
  gap: 1.5rem;
  margin-bottom: 1.5rem;
  border-bottom: 1px solid rgb(var(--eb-outline-variant) / 0.35);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
}
.eb-tabs::-webkit-scrollbar {
  display: none;
}
.eb-tab {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  flex: none;
  min-height: 2.75rem;
  padding: 0 0.25rem 0.625rem;
  border-bottom: 2px solid transparent;
  color: rgb(var(--eb-on-surface-variant));
  font-size: 0.875rem;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
  background: none;
  cursor: pointer;
}
.eb-tab:hover {
  color: rgb(var(--eb-on-background));
  border-bottom-color: rgb(var(--eb-outline-variant) / 0.6);
}
.eb-tab[aria-current="page"],
.eb-tab[aria-selected="true"] {
  color: rgb(var(--eb-primary));
  border-bottom-color: rgb(var(--eb-primary));
}
.eb-tabs.hidden,
.eb-tab.hidden {
  display: none;
}

/* ══════════════════════════════════════════════════════════════════════
   Фишка: выбранное значение, которое можно снять
   ══════════════════════════════════════════════════════════════════════ */
.eb-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  min-height: 1.75rem;
  padding: 0.125rem 0.5rem;
  border: 1px solid rgb(var(--eb-outline-variant) / 0.45);
  border-radius: 9999px;
  background: rgb(var(--eb-surface-container-lowest));
  color: rgb(var(--eb-on-background));
  font-size: 0.75rem;
  font-weight: 600;
}
.eb-chip__remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* 24 пикселя — нижняя граница WCAG 2.2 для цели указателя. */
  min-width: 1.5rem;
  min-height: 1.5rem;
  margin-right: -0.25rem;
  border: 0;
  border-radius: 9999px;
  background: none;
  color: rgb(var(--eb-on-surface-variant));
  cursor: pointer;
  line-height: 1;
}
.eb-chip__remove:hover {
  background: rgb(var(--eb-error) / 0.1);
  color: rgb(var(--eb-error));
}
.eb-chip.hidden {
  display: none;
}

/* ══════════════════════════════════════════════════════════════════════
   Шапка страницы: заголовок, пояснение и ряд действий
   ══════════════════════════════════════════════════════════════════════ */
.eb-page-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 0.75rem;
  margin-bottom: 1.5rem;
}
.eb-page-head__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}
.eb-page-head.hidden {
  display: none;
}

/*
 * Уступки `hidden` внутренним частям. Их не прячут поодиночке, но правило
 * одно на всех: класс, задающий display, обязан уступать утилите скрытия —
 * иначе спрятанное останется видимым.
 */
.eb-dialog__head.hidden,
.eb-dialog__foot.hidden,
.eb-chip__remove.hidden,
.eb-page-head__actions.hidden {
  display: none;
}

/* ══════════════════════════════════════════════════════════════════════
   Поля ввода
   ══════════════════════════════════════════════════════════════════════

   466 полей в двух кабинетах, у 107 из них собственный набор классов — 52
   разных. Отсюда и разнобой: где-то `px-4 py-2.5`, где-то `px-3 py-2`,
   высота то 44, то 38.

   Размер шрифта 16 пикселей на телефоне и 14 на широком экране — не
   прихоть: Safari на iOS приближает страницу, когда фокус попадает в поле
   мельче 16, и обратно уже не отдаляет.
*/
.eb-field {
  width: 100%;
  min-height: 2.75rem;
  margin-top: 0;
  padding: 0.625rem 1rem;
  border: 1px solid rgb(var(--eb-outline-variant) / 0.4);
  border-radius: 0.625rem;
  background: rgb(var(--eb-surface-container-lowest));
  color: rgb(var(--eb-on-background));
  font-size: 1rem;
  line-height: 1.4;
  box-shadow: 0 1px 2px rgb(var(--eb-inverse-surface) / 0.05);
  transition: border-color 0.12s ease, box-shadow 0.12s ease;
}
@media (min-width: 640px) {
  .eb-field {
    font-size: 0.875rem;
  }
}
.eb-field::placeholder {
  color: rgb(var(--eb-on-surface-variant));
}
.eb-field:hover:not(:disabled) {
  border-color: rgb(var(--eb-outline) / 0.7);
}
.eb-field:focus {
  border-color: rgb(var(--eb-primary));
  outline: none;
  box-shadow: 0 0 0 2px rgb(var(--eb-primary) / 0.25);
}
.eb-field:disabled {
  background: rgb(var(--eb-surface-container-low) / 0.9);
  color: rgb(var(--eb-on-surface-variant) / 0.6);
  cursor: not-allowed;
}
/* Выпадающий список: место справа под собственную стрелку браузера. */
.eb-field--select {
  padding-right: 2.5rem;
  cursor: pointer;
}
.eb-field--textarea {
  min-height: 5.5rem;
  padding: 0.75rem 1rem;
  resize: vertical;
}
/* Компактное поле для строк таблиц: 36, как у маленькой кнопки. */
.eb-field--sm {
  min-height: 2.25rem;
  padding: 0.375rem 0.625rem;
  font-size: 0.875rem;
}
.eb-field--sm.eb-field--select {
  padding-right: 2rem;
}
.eb-field.hidden {
  display: none;
}

/* Поле, в котором нашли ошибку: рамка и кольцо цветом ошибки. */
.eb-field[aria-invalid="true"] {
  border-color: rgb(var(--eb-error) / 0.7);
}
.eb-field[aria-invalid="true"]:focus {
  border-color: rgb(var(--eb-error));
  box-shadow: 0 0 0 2px rgb(var(--eb-error) / 0.25);
}

/* ══════════════════════════════════════════════════════════════════════
   Загрузка файлов
   ══════════════════════════════════════════════════════════════════════

   Было голое `<input type="file">`: подпись «Файл не выбран», никакого
   предпросмотра и никакого признака, что что-то происходит. Человек
   выбирал афишу и до самого сохранения не знал, ту ли.

   Площадка принимает перетаскивание, показывает выбранное плитками и
   говорит, сколько осталось. Сам `<input>` не прячется от клавиатуры:
   он лежит поверх площадки прозрачным слоем, поэтому Tab и Enter
   работают как обычно, а читалка объявляет его подпись.
*/
.eb-drop {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.25rem;
  min-height: 7rem;
  padding: 1rem;
  border: 1px dashed rgb(var(--eb-outline) / 0.55);
  border-radius: 0.625rem;
  background: rgb(var(--eb-surface-container-lowest));
  color: rgb(var(--eb-on-surface-variant));
  font-size: 0.875rem;
  text-align: center;
  transition: border-color 0.12s ease, background-color 0.12s ease;
}
.eb-drop__input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  cursor: pointer;
}
.eb-drop:hover,
.eb-drop:has(.eb-drop__input:focus-visible) {
  border-color: rgb(var(--eb-primary));
  background: rgb(var(--eb-primary) / 0.04);
}
.eb-drop:has(.eb-drop__input:focus-visible) {
  outline: 2px solid rgb(var(--eb-primary));
  outline-offset: 2px;
}
.eb-drop--over {
  border-color: rgb(var(--eb-primary));
  border-style: solid;
  background: rgb(var(--eb-primary) / 0.08);
}
.eb-drop__title {
  font-weight: 600;
  color: rgb(var(--eb-on-background));
}
.eb-drop__note {
  font-size: 0.75rem;
}

/* Плитки выбранного: видно, что именно взяли, и можно убрать лишнее. */
.eb-drop-list {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 0.5rem;
}
.eb-drop-tile {
  position: relative;
  width: 5rem;
  height: 5rem;
  border: 1px solid rgb(var(--eb-outline-variant) / 0.4);
  border-radius: 0.5rem;
  overflow: hidden;
  background: rgb(var(--eb-surface-container-lowest));
}
.eb-drop-tile img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.eb-drop-tile__name {
  position: absolute;
  inset: auto 0 0 0;
  padding: 0.125rem 0.25rem;
  background: rgb(var(--eb-inverse-surface) / 0.65);
  color: rgb(var(--eb-inverse-on-surface));
  font-size: 0.625rem;
  line-height: 1.2;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Полоска хода загрузки — поверх плитки, чтобы не двигать раскладку. */
.eb-drop-tile__bar {
  position: absolute;
  inset: auto 0 0 0;
  height: 3px;
  background: rgb(var(--eb-primary) / 0.2);
}
.eb-drop-tile__bar > span {
  display: block;
  height: 100%;
  width: 0;
  background: rgb(var(--eb-primary));
  transition: width 0.2s ease;
}
.eb-drop.hidden,
.eb-drop__input.hidden,
.eb-drop-list.hidden,
.eb-drop-tile.hidden {
  display: none;
}

@media (prefers-reduced-motion: reduce) {
  .eb-drop,
  .eb-drop-tile__bar > span {
    transition-duration: 0.01ms;
  }
}

/* ══════════════════════════════════════════════════════════════════════
   Выбор нескольких значений

   Родной `<select multiple>` выбирают щелчком с зажатым Ctrl. Этого почти
   никто не знает: человек щёлкает по второму пункту, теряет первый и
   решает, что «не работает». На телефоне список превращается в узкий
   прокручиваемый столбик, где не видно, что выбрано.

   Здесь выбранное вынесено наверх фишками — видно сразу, снимается одним
   нажатием, — а сам выбор идёт флажками, по которым можно попасть пальцем.
   Значения остаются обычными `<input type="checkbox" name="…">`, поэтому
   форма отправляется прежним способом.
   ══════════════════════════════════════════════════════════════════════ */
.eb-multi {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.eb-multi__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
  align-items: center;
  min-height: 1.75rem;
}
.eb-multi__none {
  margin: 0;
  color: rgb(var(--eb-on-surface-variant));
  font-size: 0.75rem;
  line-height: 1.45;
}
.eb-multi__list {
  display: grid;
  gap: 0.125rem;
  max-height: 14rem;
  overflow: auto;
  padding: 0.5rem;
  border: 1px solid rgb(var(--eb-outline-variant) / 0.35);
  border-radius: 0.625rem;
  background: rgb(var(--eb-surface-container-lowest));
}
@media (min-width: 640px) {
  .eb-multi__list {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.125rem 0.75rem;
  }
}
.eb-multi__opt {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  /* 32 пикселя строки: попасть пальцем, не растягивая список на экран. */
  min-height: 2rem;
  padding: 0.25rem 0.5rem;
  border-radius: 0.5rem;
  color: rgb(var(--eb-on-background));
  font-size: 0.875rem;
  line-height: 1.45;
  cursor: pointer;
}
.eb-multi__opt:hover {
  background: rgb(var(--eb-surface-container-low));
}
.eb-multi__opt:has(input:focus-visible) {
  outline: 2px solid rgb(var(--eb-primary));
  outline-offset: 1px;
}
.eb-multi__opt > span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.eb-multi__empty {
  margin: 0;
  padding: 0.25rem 0.5rem;
  color: rgb(var(--eb-on-surface-variant));
  font-size: 0.75rem;
}
.eb-multi__chips.hidden,
.eb-multi__none.hidden,
.eb-multi__list.hidden,
.eb-multi__opt.hidden,
.eb-multi__empty.hidden,
.eb-multi.hidden {
  display: none;
}

/* ══════════════════════════════════════════════════════════════════════
   Подпись под полем даты

   `datetime-local` показывает «15.06.2026 20:00» — день недели не виден.
   Организатор переносит дату с афиши, и ошибка в дне недели замечается
   тогда, когда никто не пришёл. Подписываем словами.
   ══════════════════════════════════════════════════════════════════════ */
.eb-dt-echo {
  display: block;
  margin-top: 0.25rem;
  color: rgb(var(--eb-on-surface-variant));
  font-size: 0.75rem;
  line-height: 1.45;
}
.eb-dt-echo:empty {
  display: none;
}
.eb-dt-echo--past {
  color: rgb(var(--eb-error));
  font-weight: 600;
}
.eb-dt-echo.hidden {
  display: none;
}

/* ═════════════════════════════════════════════════════════════════════
   Заслон: экран до завершения регистрации

   Два таких экрана были собраны каждый по-своему из голых утилит.
   Здесь один вид на оба: панель по центру, отступы по шкале, типографика
   по назначению.

   Меню слева остаётся открытым на широком экране — это обещано текстом
   самого заслона, поэтому модальным он не делается.
   ═════════════════════════════════════════════════════════════════════ */
.eb-gate {
  position: fixed;
  /*
   * Шапку не накрываем. На телефоне заслон ложился поверх всего,
   * включая кнопку меню и выход из кабинета, хотя сам же обещал:
   * «меню слева доступно для навигации». Высоту шапки держит
   * `--eb-header-h`: она меняется, когда заголовок переносится на две строки.
   */
  top: var(--eb-header-h, 0px);
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 120;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 2.5rem 1rem;
  background: rgb(var(--eb-inverse-surface) / 0.35);
  backdrop-filter: blur(2px);
  overflow: auto;
}
@media (min-width: 1024px) {
  .eb-gate {
    left: 16rem;
  }
}
.eb-gate__panel {
  width: 100%;
  max-width: 36rem;
  padding: 1.5rem;
  border: 1px solid rgb(var(--eb-outline-variant) / 0.3);
  border-radius: 1.5rem;
  background: rgb(var(--eb-surface-container-lowest));
  box-shadow: 0 25px 50px -12px rgb(var(--eb-inverse-surface) / 0.25);
}
/* Панель принимает фокус при появлении; свою рамку не рисуем. */
.eb-gate__panel:focus {
  outline: none;
}
.eb-gate__kicker {
  margin: 0;
  color: rgb(var(--eb-primary));
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  line-height: 1.45;
}
.eb-gate__title {
  margin: 0.25rem 0 0;
  font-size: 1.125rem;
  font-weight: 700;
  line-height: 1.55;
  color: rgb(var(--eb-on-background));
}
.eb-gate__intro {
  margin: 0.25rem 0 0;
  color: rgb(var(--eb-on-surface-variant));
  font-size: 0.875rem;
  line-height: 1.45;
}
.eb-gate__note {
  margin: 1rem 0 0;
  color: rgb(var(--eb-on-surface-variant));
  font-size: 0.75rem;
  line-height: 1.45;
}
.eb-gate__form {
  display: grid;
  gap: 1rem;
  margin-top: 1.5rem;
}
.eb-gate.hidden,
.eb-gate__panel.hidden,
.eb-gate__form.hidden {
  display: none;
}

/* ═════════════════════════════════════════════════════════════════════
   Быстрый переход (Ctrl/⌘ K)

   Поиска по кабинету не было вовсе: чтобы попасть в раздел, надо
   было вспомнить, в какой из восьми групп он лежит. Теперь можно набрать
   название.
   ═════════════════════════════════════════════════════════════════════ */
.eb-palette {
  width: min(36rem, calc(100vw - 2rem));
  max-width: none;
  padding: 0;
  border: 1px solid rgb(var(--eb-outline-variant) / 0.3);
  border-radius: 1rem;
  background: rgb(var(--eb-surface-container-lowest));
  box-shadow: 0 25px 50px -12px rgb(var(--eb-inverse-surface) / 0.3);
}
.eb-palette::backdrop {
  background: rgb(var(--eb-inverse-surface) / 0.35);
}
.eb-palette__field {
  display: block;
  width: 100%;
  padding: 1rem 1.25rem;
  border: 0;
  border-bottom: 1px solid rgb(var(--eb-outline-variant) / 0.3);
  border-radius: 1rem 1rem 0 0;
  font-size: 1rem;
  line-height: 1.5;
  color: rgb(var(--eb-on-background));
}
.eb-palette__field:focus {
  outline: none;
}
.eb-palette__list {
  max-height: 22rem;
  margin: 0;
  padding: 0.5rem;
  overflow: auto;
  list-style: none;
}
.eb-palette__item {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  width: 100%;
  /* 44 пикселя: строка списка, в которую попадают пальцем. */
  min-height: 2.75rem;
  padding: 0.5rem 0.75rem;
  border: 0;
  border-radius: 0.625rem;
  background: none;
  color: rgb(var(--eb-on-background));
  font-size: 0.875rem;
  line-height: 1.45;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
}
.eb-palette__item:hover,
.eb-palette__item[aria-selected="true"] {
  background: rgb(var(--eb-surface-container-low));
}
.eb-palette__where {
  margin-left: auto;
  color: rgb(var(--eb-on-surface-variant));
  font-size: 0.75rem;
}
.eb-palette__empty {
  margin: 0;
  padding: 1rem 1.25rem;
  color: rgb(var(--eb-on-surface-variant));
  font-size: 0.875rem;
}
.eb-palette__hint {
  display: flex;
  gap: 1rem;
  padding: 0.5rem 1.25rem;
  border-top: 1px solid rgb(var(--eb-outline-variant) / 0.25);
  color: rgb(var(--eb-on-surface-variant));
  font-size: 0.75rem;
}
.eb-palette.hidden,
.eb-palette__item.hidden,
.eb-palette__empty.hidden,
.eb-palette__field.hidden,
.eb-palette__hint.hidden,
.eb-palette__list.hidden {
  display: none;
}

/* ═════════════════════════════════════════════════════════════════════
   Полоска заполнения

   Сколько продано из скольки. Раньше это были два соседних столбца с
   голыми числами — «400» и «128», — и чтобы понять, хорошо ли идут продажи,
   организатор делил в уме.

   Цвет не единственный признак: рядом всегда стоит число.
   ═════════════════════════════════════════════════════════════════════ */
.eb-meter {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  min-width: 8rem;
}
.eb-meter__track {
  position: relative;
  height: 0.5rem;
  border-radius: 9999px;
  background: rgb(var(--eb-surface-container));
  overflow: hidden;
}
.eb-meter__fill {
  display: block;
  height: 100%;
  border-radius: 9999px;
  background: rgb(var(--eb-primary));
}
.eb-meter--full .eb-meter__fill {
  background: rgb(var(--eb-success));
}
.eb-meter--low .eb-meter__fill {
  background: rgb(var(--eb-warning));
}
.eb-meter__text {
  color: rgb(var(--eb-on-background));
  font-size: 0.75rem;
  line-height: 1.45;
  font-variant-numeric: tabular-nums;
}
.eb-meter__note {
  color: rgb(var(--eb-on-surface-variant));
  font-size: 0.75rem;
  line-height: 1.45;
}
.eb-meter.hidden,
.eb-meter__track.hidden,
.eb-meter__fill.hidden,
.eb-meter__text.hidden,
.eb-meter__note.hidden {
  display: none;
}
@media (prefers-reduced-motion: no-preference) {
  .eb-meter__fill {
    transition: width 0.25s ease;
  }
}

/* ═════════════════════════════════════════════════════════════════════
   Шаги длинной формы

   Форма рассылки была одним столбцом из восьми полей подряд, где
   рядом стояли «Сообщение» и «За последние N дней» — вещи из разных
   вопросов. Шаги группируют поля по вопросу: кому, что, когда.

   Это одна форма, а не мастер с переходами: всё видно сразу, можно
   вернуться к любому шагу, а отправка осталась одним запросом — шаги с
   сохранением между экранами потребовали бы черновиков на сервере.
   ═════════════════════════════════════════════════════════════════════ */
.eb-step {
  position: relative;
  padding-left: 3rem;
  padding-bottom: 1.5rem;
}
.eb-step:last-child {
  padding-bottom: 0;
}
/* Линия между номерами: видно, что шаги — одна цепочка. */
.eb-step:not(:last-child)::before {
  content: "";
  position: absolute;
  top: 2.25rem;
  bottom: 0.25rem;
  left: 1.09375rem;
  width: 2px;
  background: rgb(var(--eb-outline-variant) / 0.4);
}
.eb-step__num {
  position: absolute;
  top: 0;
  left: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 9999px;
  background: rgb(var(--eb-primary));
  color: rgb(var(--eb-on-primary));
  font-size: 0.875rem;
  font-weight: 700;
}
.eb-step__title {
  margin: 0.25rem 0 0;
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.5;
  color: rgb(var(--eb-on-background));
}
.eb-step__note {
  margin: 0.25rem 0 0;
  color: rgb(var(--eb-on-surface-variant));
  font-size: 0.875rem;
  line-height: 1.45;
}
.eb-step__body {
  display: grid;
  gap: 1rem;
  margin-top: 1rem;
}
.eb-step.hidden,
.eb-step__body.hidden,
.eb-step__note.hidden,
.eb-step__num.hidden,
.eb-step__title.hidden {
  display: none;
}
@media (max-width: 480px) {
  .eb-step {
    padding-left: 2.5rem;
  }
  .eb-step:not(:last-child)::before {
    left: 0.96875rem;
  }
  .eb-step__num {
    width: 2rem;
    height: 2rem;
  }
}

/* Предпросмотр сообщения: как его увидит гость в переписке. */
.eb-bubble {
  max-width: 28rem;
  padding: 0.625rem 0.875rem;
  border-radius: 1rem 1rem 1rem 0.25rem;
  background: rgb(var(--eb-surface-container-low));
  color: rgb(var(--eb-on-background));
  font-size: 0.875rem;
  line-height: 1.5;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.eb-bubble:empty::before {
  content: "Здесь появится текст, который увидит гость.";
  color: rgb(var(--eb-on-surface-variant));
}
.eb-bubble.hidden {
  display: none;
}


/*
 * Длинный адрес в `<code>` не толкает страницу вбок.
 *
 * Адрес для уведомлений от YooKassa — одно слово без пробелов, и на
 * телефоне он вылезал за край на 98 пикселей, увозя вместе с собой
 * всю страницу в боковую прокрутку (найдено обходом ширин).
 *
 * Правило общее: адреса, ключи и идентификаторы встречаются в кабинете
 * в десятках мест, и следующий такой же сломает экран так же.
 */
#app code,
.eb-gate code,
.eb-dialog code {
  overflow-wrap: anywhere;
}

/* ═════════════════════════════════════════════════════════════════════
   Переключатель оформления

   Три кнопки, а не тумблер: «как в системе» — это отдельный выбор,
   а не отсутствие выбора.
   ═════════════════════════════════════════════════════════════════════ */
.eb-theme-switch {
  display: grid;
  gap: 0.125rem;
  padding: 0.5rem 0.75rem 0.25rem;
}
.eb-theme-btn {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  width: 100%;
  /* 44 пикселя: это пункт списка, в который попадают пальцем. */
  min-height: 2.75rem;
  padding: 0.5rem 0.75rem;
  border: 0;
  border-radius: 0.625rem;
  background: none;
  color: rgb(var(--eb-on-surface));
  font-size: 0.875rem;
  font-weight: 500;
  line-height: 1.45;
  text-align: left;
  cursor: pointer;
}
.eb-theme-btn:hover {
  background: rgb(var(--eb-surface-container-low));
}
/* Выбранный отмечен и цветом, и атрибутом — читалке цвет не виден. */
.eb-theme-btn[aria-pressed="true"] {
  background: rgb(var(--eb-primary) / 0.12);
  color: rgb(var(--eb-primary));
  font-weight: 700;
}
.eb-theme-btn:focus-visible {
  outline: 2px solid rgb(var(--eb-primary));
  outline-offset: -2px;
}
.eb-theme-switch.hidden,
.eb-theme-btn.hidden {
  display: none;
}

/* ═════════════════════════════════════════════════════════════════════
   Переключатель из нескольких кнопок в одной обойме

   Период оплаты, оформление, период аналитики — всюду одна и та же
   вещь, но собранная три раза по-разному.
   ═════════════════════════════════════════════════════════════════════ */
.eb-seg {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 0.25rem;
  padding: 0.25rem;
  border-radius: 1rem;
  background: rgb(var(--eb-surface-container-low));
}
.eb-seg__btn {
  /* 36 пикселей: кнопки стоят в обойме и цель складывается с её полями. */
  min-height: 2.25rem;
  padding: 0.375rem 0.875rem;
  border: 0;
  border-radius: 0.625rem;
  background: none;
  color: rgb(var(--eb-on-surface-variant));
  font-size: 0.875rem;
  font-weight: 600;
  line-height: 1.45;
  cursor: pointer;
}
.eb-seg__btn:hover {
  color: rgb(var(--eb-on-surface));
}
/* Выбранный отмечен и атрибутом: читалке цвет не виден. */
.eb-seg__btn[aria-pressed="true"] {
  background: rgb(var(--eb-surface-container-lowest));
  color: rgb(var(--eb-on-surface));
  box-shadow: 0 1px 2px rgb(var(--eb-inverse-surface) / 0.08);
}
.eb-seg__btn:focus-visible {
  outline: 2px solid rgb(var(--eb-primary));
  outline-offset: -2px;
}
.eb-seg.hidden,
.eb-seg__btn.hidden {
  display: none;
}

/*
 * Кнопка-аватар в шапке.
 *
 * Собиралась по месту из семи утилит и была последним набором, который
 * не брался из слоя. Сама по себе она не кнопка в смысле вида — это
 * инициалы в кружке, — но правила у неё должны жить там же, где у всех.
 */
.eb-avatar-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  /* 44 пикселя: цель для пальца. */
  height: 2.75rem;
  min-width: 2.75rem;
  border: 0;
  border-radius: 0.625rem;
  background: rgb(var(--eb-secondary-container));
  color: rgb(var(--eb-on-secondary-container));
  font-family: Manrope, system-ui, sans-serif;
  font-size: 0.75rem;
  font-weight: 700;
  cursor: pointer;
  transition: box-shadow 0.15s;
}
.eb-avatar-btn:hover {
  box-shadow: 0 0 0 2px rgb(var(--eb-primary) / 0.25);
}
.eb-avatar-btn:focus-visible {
  outline: 2px solid rgb(var(--eb-primary));
  outline-offset: 2px;
}
.eb-avatar-btn.hidden {
  display: none;
}
