@font-face {
  font-family: 'Golos';
  src:
    url('/assets/fonts/golos.woff2') format('woff2'),
    url('/assets/fonts/golos.woff') format('woff');
  /* Файл вариативный (внутри fvar/gvar/STAT), а объявлен был одним начертанием — браузер брал
     единственный вес 400 и «дорисовывал» жирность сам для каждого fw-semi-bold и заголовка.
     Синтетический жирный размазывает контуры, отсюда ощущение мутного текста (до правки ширина
     строки на весах 300…800 не менялась вовсе, 636 px везде).

     Верхняя граница диапазона — 600, а не 900, намеренно: всё, что тема просит жирнее (fw-bold
     700, fw-bolder 800, плашка номера заказа), обрезается до 600. Настоящие 700 и 800 заметно
     тяжелее той подделки, к которой все привыкли, и сумма в корзине начинала кричать на весь
     экран. Обрезку по границе диапазона одинаково делают Chromium, Firefox и WebKit — проверено
     замером в трёх движках; дескриптор font-variation-settings, которым это делалось раньше,
     WebKit молча игнорирует, поэтому его здесь нет. */
  font-weight: 100 600;
  font-style: normal;
}

/* Вес 500 в теме — это «medium», и просит она его у ВСЕХ заголовков, кнопок, подписей полей и
   пунктов меню. Пока Golos был одним начертанием, показать его браузер не мог (синтетику он
   включает только от 600) и рисовал обычным; с настоящими начертаниями интерфейс потяжелел там,
   где никто этого не просил. Возвращаем прежний вид перечислением — CSS не умеет «взять всё, у
   чего 500», а дескриптор @font-face, которым это делалось короче, не работает в WebKit.
   !important — потому что у части правил темы вес тоже с !important. */
h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6,
.btn, [data-list] .page, label, .nav-link, .navbar .dropdown-item, .navbar-standard,
.navbar-vertical .navbar-nav, .tab-active-caret .nav-link, .terms-sidebar .nav-link,
.btn-accordion, .po-seg__opt span, .po-item.is-picked .po-item__title, .inv-title, .inv-qty { font-weight: 400 !important; }


/* Кэшбэк выключен владельцем (раздел «Бонусная программа»): вкладка бонусов в карточке корзины
   и кнопка снятия привязки кассиру не нужны — акции, которой они управляют, больше нет. Прячем
   классом на <body>, потому что карточку перерисовывает AJAX: обход DOM пришлось бы повторять
   после каждой перерисовки, а правило CSS действует и на свежую разметку. */
body.cashback-off #profile-tab,
body.cashback-off #tab-profile,
body.cashback-off #bonus_del_btn {
  display: none !important;
}

/* Тема задаёт .content{min-height:100vh;padding-bottom:6.375rem} и .footer{position:absolute;bottom:0}
   для липкого подвала — при коротком списке заказов это создавало огромный отступ до подвала.
   Делаем нормальный липкий футер через flex-колонку на всю высоту экрана: #operatorContainer
   (родитель navbar + #operatorContent) растягивается на 100vh, #operatorContent занимает всё
   свободное место (flex:1), а футер прижимается к его низу через margin-top:auto. Если контента
   больше экрана — всё просто течёт естественно, без лишней прокрутки. Переопределяем только для
   этой страницы через ID, не трогая тему глобально. */
#operatorContainer {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}
#operatorContent {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  padding-bottom: 0;
}
#operatorFooter {
  position: static;
  margin-top: auto;
}
/* Список заказов под каталогом занимает свободное место до подвала: пустой день не обрывает карточку
   посреди экрана. flex: 1 0 auto — растёт только в пустоту, а длинный список течёт как обычно,
   поэтому лишней прокрутки это не добавляет */
.orders-list-fill {
  flex: 1 0 auto;
}
.orders-list-fill > .col-12 {
  display: flex;
  flex-direction: column;
}
.orders-list-fill #realOrdersTable {
  flex: 1 0 auto;
}

/* .fs-9 в этой сборке темы тоже отсутствует, а в примерах-образцах встречается часто */
.fs-9 {
  font-size: 1rem !important;
}

/* "..." в нумерованной пагинации List.js (pagination:true в data-list) — у неё нет data-i/
   data-page, клик по ней ничего не делает (так и задумано в самой библиотеке); класс disabled
   у <li> ставится только для неё, не для обычных номеров — прячем, раз кликом всё равно
   не пользуется */
#realOrdersTable .pagination li.disabled {
  display: none;
}

.bg-soft-yellow {
  background-color: #FFF59D;
}

.bg-soft-blue {
  background-color: #cce5ff;
}

.bg-soft-violet {
  background-color: #DDD6FE;
}

/* Как штатные .badge-soft-* темы (пара цветов, светлая/тёмная тема через .dark на предке —
   тот же селектор, что у --freepos-badge-soft-warning-* в theme.min.css), но на базе
   --freepos-orange (#fd7e14), а не --freepos-warning — тот уже занят бейджем "Не оплачен" */
.badge-soft-orange {
  color: #a04b0a;
  background-color: #ffe5d0;
}
.dark .badge-soft-orange {
  color: #ffab5e;
  background-color: #3d2008;
}

.tooltip .tooltip-inner {
  background-color: rgba(240, 240, 240, 0.95) !important; /* мягкий светлый фон */
  color: #2c3e50 !important;                             /* спокойный тёмно‑синий текст */
  border-radius: 6px;                                    /* чуть более округлые углы */
  padding: 6px 10px;  
}
.bs-tooltip-right {
  margin-left: 1.5rem; /* можно увеличить до 0.75rem или 1rem */
}
.bs-tooltip-bottom {
  margin-right: 3.5rem; /* можно увеличить до 0.75rem или 1rem */
}
.tooltip .tooltip-arrow::before {
  border-color: transparent !important;
  
}

/* стрелка под цвет фона */
.bs-tooltip-top .tooltip-arrow::before { border-top-color: rgba(240,240,240,0.95) !important; }
.bs-tooltip-bottom .tooltip-arrow::before { border-bottom-color: rgba(240,240,240,0.95) !important; }
.bs-tooltip-start .tooltip-arrow::before { border-left-color: rgba(240,240,240,0.95) !important; }
.bs-tooltip-end .tooltip-arrow::before { border-right-color: rgba(240,240,240,0.95) !important; }

  /* Скрываем стрелки */
.basket-scroll::-webkit-scrollbar-button {
  display: none;
}

/* Общие параметры контейнера прокрутки */
.basket-scroll,
.catitems-scroll {
  overflow-y: auto;
  overflow-x: hidden;
  position: relative;
  width: 100%;
}

/* WebKit (Chrome, Safari, Edge) */
.basket-scroll::-webkit-scrollbar,
.catitems-scroll::-webkit-scrollbar {
  width: 6px;
}

.basket-scroll::-webkit-scrollbar-track,
.catitems-scroll::-webkit-scrollbar-track {
  background: #f8f9fa;
  border-radius: 3px;
}

.basket-scroll::-webkit-scrollbar-thumb,
.catitems-scroll::-webkit-scrollbar-thumb {
  background: #adb5bd;
  border-radius: 3px;
}

.basket-scroll::-webkit-scrollbar-thumb:hover,
.catitems-scroll::-webkit-scrollbar-thumb:hover {
  background: #6c757d;
}

/* Firefox */
.basket-scroll,
.catitems-scroll {
  scrollbar-width: thin;
  scrollbar-color: #adb5bd #f8f9fa;
}



.basket-scroll-wrapper {
  position: relative;
  height: 100%;
  width: 100%;
}

.basket-fade-overlay {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 10px;
  /* не заходить на полосу прокрутки .basket-scroll (реальная ширина скроллбара,
     замерено через el.offsetWidth - el.clientWidth — фактически шире, чем
     заданные в ::-webkit-scrollbar 6px) */
  height: 48px;
  /* высота градиента: верхние ~70% — плавный переход, нижние ~30% — сплошной белый,
     чтобы обрезанная строка полностью скрывалась, а не проступала серым текстом */
  background: linear-gradient(to bottom,
      transparent 0%,
      hsl(0, 0%, 100%) 70%
      /* ← цвет фона bg-light */
    );
  pointer-events: none;
  /* клики проходят сквозь */
  z-index: 10;
  transition: opacity 0.2s ease;
}

/* Важно: родитель должен иметь position: relative */
#backet_items {
  position: relative;
}

/* Без этого над текстом в ячейках (номер, клиент, дата и т.п.) курсор превращался в I-образный
   выделения текста ("auto" так себя ведёт над текстовыми узлами в <td>) — адрес/комментарий уже
   были cursor:default точечно из-за тултипа, теперь так же для всей строки */
#table-real-orders-body tr {
  cursor: default;
}

.hover-highlight:hover {
  background-color: #e9ecef !important;
  /* Цвет при наведении */
  transform: scale(1.05);
  /* Легкое увеличение */
  transition: all 0.2s ease-in-out;
  /* Плавный переход */
}

/* .btn-light в этой теме почти не отличает hover от обычного состояния (#f9fafd -> #fafbfd —
   разница на глаз незаметна, см. theme.min.css) — тот же серый, что у .hover-highlight выше,
   но без scale — это обычная прямоугольная кнопка с текстом, не маленькая круглая иконка */
.btn-light:hover {
  background-color: #e9ecef;
  border-color: #e9ecef;
}

.quantity-control {
  display: inline-flex;
  /* Ширина по содержимому */
  align-items: center;
  background-color: #f8f9fa;
  border-radius: 0.5rem;
  padding: 0.25rem;
  box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
}

.btn-quantity {
  width: 1.5rem;
  /* Уменьшена ширина */
  height: 1.5rem;
  /* Уменьшена высота */
  border-radius: 0.375rem;
  /* Слегка уменьшен радиус скругления */
  font-size: 1rem;
  /* Уменьшен размер шрифта */
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid #dee2e6;
  background-color: white;
}

.quantity-value {
  font-size: 0.9rem;
  /* Уменьшен размер шрифта */
  font-weight: 500;
  min-width: 2.5rem;
  /* Уменьшена минимальная ширина */
  text-align: center;
  padding: 0 0.25rem;
  /* Уменьшены отступы */
  cursor: pointer; /* курсор-рука при наведении */
}


.quantity-input {
  width: 50px;
  border: none;
  outline: none;
  text-align: center;
  font: inherit; /* наследует шрифт и размер */
}


.menu-row thead th {
  position: sticky;
  top: 0;
  background: #edf2f9;
  /* цвет фона */
  z-index: 2;
}

.notification-indicator[data-state="comment"]::before
{ 
  width: 0.6rem; 
  height: 0.6rem;
  top:0px;
  left:-0.5rem;
}

.notification-indicator[data-state="sale"]::before,
.notification-indicator[data-state="filter"]::before
{
  width: 0.6rem;
  height: 0.6rem;
  top:-3px;
  left:2px;

}

/* Черновики без связи: у кнопки есть подпись, поэтому счётчик выносим в правый верхний угол
   (по базовому правилу темы он встаёт поверх текста — оно рассчитано на кнопку-иконку) */
.notification-indicator[data-state="offline-drafts"]::before,
.notification-indicator[data-state="offline-drafts"] .notification-indicator-number
{
  width: 0.9rem;
  height: 0.9rem;
  top: -5px;
  right: -5px;
}
.notification-indicator[data-state="offline-drafts"] .notification-indicator-number
{
  font-size: 0.6rem;
}



.input-wrapper {
  position: relative;
}

.clear-btn {
  position: absolute;
  right: 10px;
  top: 50%;
  transform: translateY(-50%);
  cursor: pointer;
  color: #888;
  display: none;
}

/* Форма оформления заказа (шаг 2 корзины) */

/* Дом №/Кв.Оф/Подъезд/Этаж/Домофон: flex-shrink:0 — колонка не сжимается ниже 90px (иначе
   браузер предпочитает сжимать и переносить текст лейбла ВНУТРИ колонки, а не саму колонку
   на новую строку); при нехватке места весь блок целиком уходит на новую строку через flex-wrap */
#orderStepForm .addr-fields-col {
  flex: 1 0 90px;
  min-width: 90px;
}

/* Карточки способа оплаты — как на референсе (равная ширина, скругление, подсветка выбранной рамкой).
   min-width + flex-wrap на контейнере (см. шаблон) — на узких экранах карточка не сжимается и не
   вылезает за пределы контейнера (из-за чего "пропадала" рамка), а переносится на новую строку.
   #productOptionsPanel переиспользует те же карточки для варианта/модификаторов товара в модалке
   productOptionsModal (см. operator_product_options.html) — тот же визуальный паттерн выбора. */
#orderStepForm .pay-method-card,
#productOptionsPanel .pay-method-card,
#courierPickPanel .pay-method-card,
#waiterPickPanel .pay-method-card,
#hallActionBody .pay-method-card,
#orderPaymentModal .pay-method-card,
#giftCertModal .pay-method-card {
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1.5px solid #e3e6ed;
  border-radius: 0.75rem;
  background-color: #fff;
  color: #344050;
  font-size: 0.75rem;
  font-weight: 500;
  padding: 0.6rem 0.25rem;
  white-space: nowrap;
  flex: 1 0 90px;
  min-width: 90px;
}

#orderStepForm .pay-method-card i,
#productOptionsPanel .pay-method-card i,
#courierPickPanel .pay-method-card i,
#waiterPickPanel .pay-method-card i,
#hallActionBody .pay-method-card i,
#orderPaymentModal .pay-method-card i,
#giftCertModal .pay-method-card i {
  font-size: 0.85rem;
}

#orderStepForm .pay-method-card:hover,
#productOptionsPanel .pay-method-card:hover,
#courierPickPanel .pay-method-card:hover,
#waiterPickPanel .pay-method-card:hover,
#hallActionBody .pay-method-card:hover,
#orderPaymentModal .pay-method-card:hover,
#giftCertModal .pay-method-card:hover {
  border-color: var(--freepos-400, #b6c1d2);
}

#orderStepForm .btn-check:checked + .pay-method-card,
#productOptionsPanel .btn-check:checked + .pay-method-card,
#courierPickPanel .btn-check:checked + .pay-method-card,
#waiterPickPanel .btn-check:checked + .pay-method-card,
#hallActionBody .pay-method-card.is-primary,
#orderPaymentModal .btn-check:checked + .pay-method-card,
#giftCertModal .btn-check:checked + .pay-method-card {
  border-color: var(--freepos-primary, #2c7be5);
  color: var(--freepos-primary, #2c7be5);
  background-color: #fff;
  box-shadow: none;
}

#orderStepForm .btn-check:checked + .pay-method-card:hover,
#productOptionsPanel .btn-check:checked + .pay-method-card:hover,
#courierPickPanel .btn-check:checked + .pay-method-card:hover,
#waiterPickPanel .btn-check:checked + .pay-method-card:hover,
#hallActionBody .pay-method-card.is-primary:hover,
#orderPaymentModal .btn-check:checked + .pay-method-card:hover,
#giftCertModal .btn-check:checked + .pay-method-card:hover {
  border-color: var(--freepos-colored-link-primary-hover-color, #2362b7);
}

/* Карточка курьера — та же рамка/подсветка, что и у способа оплаты выше, но раскладка своя:
   полная ширина, аватар слева, имя/телефон в строку (а не центрированная пилюля фиксированной
   ширины, как у способа оплаты/варианта товара) */
#courierPickPanel .pay-method-card,
#waiterPickPanel .pay-method-card,
#hallActionBody .pay-method-card {
  justify-content: flex-start;
  white-space: normal;
  flex: unset;
  min-width: 0;
  width: 100%;
  padding: 1rem 1.25rem;
}

/* is-invalid на скрытом .btn-check визуально ничего не даёт — подсвечиваем сами карточки
   через обёртку #payMethodGroup, на которую JS вешает класс is-invalid при неудачной валидации */
#orderStepForm #payMethodGroup.is-invalid .pay-method-card,
#orderPaymentModal #orderPaymentModalGroup.is-invalid .pay-method-card {
  border-color: var(--freepos-danger, #e63757);
}

/* Подтверждение «деньги получены» и снятие ожидания онлайн-оплаты: JS вешает is-invalid на
   ОБЁРТКУ (.form-check / .alert), а тема красит только сам .form-check-input — без этих правил
   отказ «поставьте галочку» был не виден вовсе, и кнопка «Подтвердить» выглядела сломанной */
#orderPaymentModal #orderPaymentConfirmWrap.is-invalid .form-check-input,
#orderPaymentModal #orderPaymentOnlineWarn.is-invalid .form-check-input {
  border-color: var(--freepos-danger, #e63757);
}
#orderPaymentModal #orderPaymentConfirmWrap.is-invalid .form-check-label,
#orderPaymentModal #orderPaymentOnlineWarn.is-invalid .form-check-label {
  color: var(--freepos-danger, #e63757);
}
#orderPaymentModal #orderPaymentOnlineWarn.is-invalid {
  border-color: var(--freepos-danger, #e63757);
}

/* Город/Улица обёрнуты Choices.js — реальный <select> скрыт, is-invalid вешается на .choices,
   подсвечиваем видимую рамку .choices__inner */
#orderStepForm .choices.is-invalid .choices__inner {
  border-color: var(--freepos-danger, #e63757);
}

/* Лейбл "Город" убран для компактности — звёздочка "обязательное поле" переехала в плейсхолдер.
   Библиотека дефолтно рисует плейсхолдер через opacity:.5 — она "проступает" и через ::after,
   размывая красный цвет, поэтому сбрасываем opacity и берём приглушённый цвет через color вместо неё.
   #receivingSupplier (панель прихода) использует тот же приём, поэтому те же правила — на оба
   контейнера формы, а не только на #orderStepForm */
#orderStepForm .choices--required-placeholder .choices__placeholder,
#receivingForm .choices--required-placeholder .choices__placeholder {
  opacity: 1;
  color: var(--freepos-500, #9da9bb);
}

#orderStepForm .choices--required-placeholder .choices__placeholder::after,
#receivingForm .choices--required-placeholder .choices__placeholder::after {
  content: " *";
  color: var(--freepos-danger, #e63757);
}

/* Choices.js сам подмешивает плейсхолдер-пункт первой строкой в открытый список, пока поиск не
   начат — тот же текст, что уже показан свёрнутым (не относится к .choices__list--single, там
   его трогать не нужно) */
#orderStepForm .choices__list--dropdown .choices__placeholder,
#receivingForm .choices__list--dropdown .choices__placeholder {
  display: none;
}

/* Высота закрытого select и поля поиска в раскрытом списке — как у ZABOR/PERSONS (2.6rem).
   #receivingSupplier (панель прихода) без этих правил оставался в дефолтной, более высокой
   разметке Choices.js — та же компактность нужна и там, обе формы в одной по высоте карточке */
#orderStepForm .choices,
#receivingForm .choices {
  margin-bottom: 0;
}

#orderStepForm .choices__inner,
#receivingForm .choices__inner {
  min-height: 2.6rem;
  padding: 0.45rem 2.5rem 0.45rem 0.75rem;
  font-size: 0.85rem;
}

#orderStepForm .choices__list--single,
#receivingForm .choices__list--single {
  padding: 0 !important;
  margin-top: 0 !important;
}

#orderStepForm .choices__input,
#receivingForm .choices__input {
  min-height: 2.2rem;
  padding: 0.3rem 0.75rem !important;
  font-size: 0.85rem;
  margin-bottom: 0;
}

#orderStepForm .choices__input--cloned,
#receivingForm .choices__input--cloned {
  margin-top: 0 !important;
  font-size: 0.85rem;
}

/* choices__item--selectable здесь — сам плейсхолдер/выбранное значение, свёрнутое в одну строку
   закрытого select (не пункты раскрытого списка — те уже сжаты через .choices__inner выше) */
#orderStepForm .choices__item,
#receivingForm .choices__item {
  font-size: 0.85rem !important;
  line-height: 1.5rem !important;
  padding-top: 0 !important;
  padding-bottom: 0 !important;
}

/* Раскрытый список поставщиков рисуется абсолютно позиционированным блоком под полем — без
   собственного z-index он проигрывает шапке таблицы накладной (та рисуется позже в DOM того же
   стекового контекста и перекрывает список несмотря на meньший визуальный порядок) */
#receivingForm .choices__list--dropdown {
  z-index: 20;
}

/* Уменьшенная высота form-floating для select/input (по умолчанию в теме — calc(3.5rem + 2px)).
   Один размер у всех слоёв карточки корзины: форма заказа, шапка накладной прихода, поля
   производства. Они сменяют друг друга в одном и том же месте экрана, и разъехавшийся масштаб
   бросается в глаза при переключении. Новый слой обязан попасть в этот список */
#orderStepForm .form-floating > .form-select,
#orderStepForm .form-floating > .form-control,
#receivingForm .form-floating > .form-select,
#receivingForm .form-floating > .form-control,
#production-panel .form-floating > .form-select,
#production-panel .form-floating > .form-control {
  height: 2.6rem;
  min-height: 2.6rem;
  padding: 1rem 0.75rem 0.3rem;
  font-size: 0.85rem;
}

#orderStepForm .form-floating > label,
#receivingForm .form-floating > label,
#production-panel .form-floating > label {
  padding: 0.55rem 0.75rem;
  font-size: 0.85rem;
}

/* Расстояние между блоками формы уменьшено вдвое (тема задаёт .mb-4 = 1.8rem) */
#orderStepForm .mb-4 {
  margin-bottom: 0.9rem !important;
}

/* Карточка корзины на время правки существующего заказа — чтобы оператор с одного взгляда
   отличал правку от набора нового заказа. Цвет не новый: --freepos-success (#00d27a) — тот же
   зелёный, что у класса .border-success в теме, поэтому берём переменную, а не фиксированный hex.
   Ширина рамки 2px на габариты не влияет — у .card box-sizing:border-box */
.basket-card-editing {
  border-color: var(--freepos-success) !important;
  border-width: 2px;
}

/* Подсветка строки корзины, к которой прокрутили оператора — тот же зелёный, что и у
   .basket-card-editing (--freepos-success), но временная вспышка, а не постоянная рамка.
   Используется, когда добавление/правка блокируется из-за дубликата (см. flashBasketRow в
   extra.js) — оператору нужно с одного взгляда найти строку, где увеличить количество вручную */
@keyframes basketRowFlashSuccess {
  0%, 80% {
    border-color: var(--freepos-success);
    box-shadow: 0 0 0 2px rgba(var(--freepos-success-rgb), .35);
  }
  100% {
    border-color: var(--bs-border-color);
    box-shadow: none;
  }
}
.basket-row-flash-success {
  animation: basketRowFlashSuccess 5s ease-out;
}

/* Анимация "заказ принят" в панели корзины после успешного оформления (см. extra.js) —
   котик, ленточки и конфетти на 10 секунд, потом сама возвращается к пустой корзине */
.order-success-wrap {
  overflow: hidden;
}

.order-success-confetti {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.order-success-confetti-piece {
  position: absolute;
  top: -16px;
  animation-name: orderConfettiFall;
  animation-timing-function: cubic-bezier(0.35, 0, 0.65, 1);
  animation-fill-mode: forwards;
}

@keyframes orderConfettiFall {
  0%   { transform: translateY(0) rotate(0deg); opacity: 1; }
  85%  { opacity: 1; }
  100% { transform: translateY(230px) rotate(360deg); opacity: 0; }
}

@keyframes orderSuccessCatBounce {
  0%, 100% { transform: translateY(0) rotate(-4deg); }
  50%      { transform: translateY(-10px) rotate(4deg); }
}

@keyframes orderSuccessRibbonFlutter {
  0%, 100% { transform: rotate(-10deg); }
  50%      { transform: rotate(10deg); }
}

@keyframes orderSuccessPop {
  0%   { transform: scale(0.4); opacity: 0; }
  60%  { transform: scale(1.15); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}

@keyframes orderSuccessFadeIn {
  0%   { opacity: 0; transform: translateY(6px); }
  100% { opacity: 1; transform: translateY(0); }
}

.order-success-content {
  z-index: 1;
  /* без этого подпись садится вплотную к нижнему краю панели — .order-success-media
     (flex-grow) забирает всё оставшееся место до самого низа */
  padding-bottom: 1.5rem;
  animation: orderSuccessPop 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.order-success-cat {
  font-size: 3.75rem;
  display: inline-block;
  line-height: 1;
  animation: orderSuccessCatBounce 1s ease-in-out infinite;
}

/* Котиков временно заменили на Lottie-анимацию (см. extra.js, showOrderSuccessAnimation) —
   .order-success-cat выше не удалён, вдруг вернём */
.order-success-media {
  /* flex-grow снова — забирает всё, что осталось в колонке ПОСЛЕ текста ниже (у текстовых div
     нет flex-grow, значит их естественная высота вычитается первой и всегда сохраняется) */
  flex: 1 1 0;
  min-height: 0; /* без этого flex-item не сжимается меньше контента, и рост не считается корректно */
  width: 100%;
}

.order-success-lottie {
  /* Без aspect-ratio: он вместе с height:100% требует высоту больше оставшегося места, и подпись
     снизу срезается (overflow:hidden на .order-success-wrap). Вписываемся в уже посчитанную
     flex-box — Lottie-SVG внутри не растягивается, а центрируется сам (preserveAspectRatio) */
  display: inline-block;
  height: 100%;
  width: 90%; /* ленточек по бокам больше нет, места для них уступать не нужно */
}

.order-success-ribbon {
  font-size: 1.5rem;
  display: inline-block;
  animation: orderSuccessRibbonFlutter 1.1s ease-in-out infinite;
}

.order-success-ribbon.order-success-ribbon-right {
  animation-delay: 0.3s;
}

.order-success-text {
  animation: orderSuccessFadeIn 0.5s ease-out 0.2s both;
}

.order-success-subtitle {
  margin-top: -0.35rem; /* приподнимает подпись ("Начинаем готовить" и т.п.) ближе к заголовку */
}

/* Кратковременная подсветка строки нового заказа при живом добавлении в список (см.
   orders-poll.js) — класс сам снимать не нужно: без animation-fill-mode после проигрывания
   background-color просто возвращается к обычному каскаду (полоска table-striped и т.п.) */
@keyframes orderRowNewHighlight {
  0%   { background-color: rgba(44, 123, 229, 0.3); } /* --freepos-primary */
  100% { background-color: transparent; }
}

.order-row-new {
  animation: orderRowNewHighlight 3s ease-out;
}

/* Затухание строки перед удалением из списка (см. removeOrderRowAfterDelay в extra.js) —
   forwards, чтобы не мигнуть обратно к opacity:1 в момент между концом анимации и вызовом
   row.remove() из JS (0.4s ниже должно совпадать с delayMs второго setTimeout там же) */
@keyframes orderRowFadeOut {
  0%   { opacity: 1; }
  100% { opacity: 0; }
}

.order-row-completing {
  animation: orderRowFadeOut 0.4s ease-in forwards;
}

/* Подсветка строки заказа — двумя независимыми триггерами: .order-row-menu-active, пока открыто
   её меню действий (три точки, см. show/hide.bs.dropdown в extra.js), и .order-row-selected —
   одиночным кликом по самой строке (см. initRealOrdersBulkSelect там же), выбор один за раз.
   outline, а не border/box-shadow: у <tr> в таблице с border-collapse обычная рамка не рисуется
   предсказуемо, а box-shadow красится ПОД дочерними элементами и на полосатых (table-striped)
   строках перекрывается непрозрачным фоном самих <td> — на них рамка была не видна вовсе. outline
   рисуется поверх содержимого ячеек, поэтому виден всегда, независимо от полосатости строки.
   Тот же зелёный, что и .basket-card-editing (--freepos-success) */
.order-row-menu-active,
.order-row-selected {
  outline: 2px solid var(--freepos-success);
  outline-offset: -2px;
}

/* Меню строки заказа на сенсорном экране (правого клика там нет): кнопка «⋮» в ячейке номера и
   долгое нажатие на строку (extra.js, openOrderRowMenu) — меню панелью снизу экрана: пункты крупные,
   до них дотягивается большой палец. На компьютере кнопки нет — там правый клик */
/* «Статус» — последняя видимая колонка списка заказов, но не последняя ячейка строки (за ней скрытая ячейка
   меню), поэтому отступ темы для последней колонки (.table td:last-child, 1.25rem) до неё не доходит —
   даём его явно, иначе пилюли статуса упираются в край карточки */
#realOrdersTable td.status, #realOrdersTable th[data-sort="status"] { padding-right: 1.25rem; }

.order-row-more { display: none; }
.touch-ui .order-row-more {
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0; width: 34px; height: 34px; padding: 0; border-radius: 50%; vertical-align: middle;
}
/* Ячейка меню в конце строки скрыта (меню открывает правый клик); на сенсорном экране в ней кнопка «⋮» */
.touch-ui #realOrdersTable .order-menu-cell {
  width: auto !important; padding: 0 .5rem 0 0 !important; overflow: visible !important; vertical-align: middle; white-space: nowrap;
  border-width: 0 0 1px 0 !important; border-style: solid !important; border-color: inherit !important;
}
.touch-ui #realOrdersTable td.status, .touch-ui #realOrdersTable th[data-sort="status"] { padding-right: .25rem; }

/* «Мои столы» официанта (body.orders-mine, OrdersMineOperator): только № с временем, стол («Забор»), сумма,
   оплата и статус — имя гостя у заказа со стола повторяет стол, адрес и дата официанту не нужны */
.orders-mine #realOrdersTable .mine-hide { display: none !important; }
.order-time-mini { display: none; margin-top: 2px; font-size: .75rem; color: var(--freepos-500); }
.orders-mine .order-time-mini { display: block; }
.orders-mine #realOrdersTable td.amount::after { content: attr(data-paid-mini); display: block; font-size: .75rem; color: var(--freepos-500); white-space: nowrap; }
/* Ширины — у <col> по счёту, а не у колонки (table-layout:fixed): скрытые ячейки не занимают места, и видимые
   берут первые ширины подряд — № с временем, стол, сумма с оплатой, статус и на сенсорном экране «⋮» */
.orders-mine #realOrdersTable table { width: 100%; }
.orders-mine #realOrdersTable colgroup col { width: 0 !important; }
.orders-mine #realOrdersTable colgroup col:nth-child(1) { width: 66px !important; }
.orders-mine #realOrdersTable colgroup col:nth-child(2) { width: 86px !important; }
.orders-mine #realOrdersTable colgroup col:nth-child(3) { width: 86px !important; }
.orders-mine #realOrdersTable colgroup col:nth-child(4) { width: 100px !important; }
.touch-ui .orders-mine #realOrdersTable colgroup col:nth-child(5) { width: 42px !important; }
.touch-ui #table-real-orders-body tr { -webkit-touch-callout: none; -webkit-user-select: none; user-select: none; }
.order-menu-backdrop { position: fixed; inset: 0; background: rgba(11, 23, 39, .35); z-index: 1084; }
.dropdown-menu.order-menu-sheet {
  display: block; position: fixed !important; inset: auto 0 0 0 !important; transform: none !important;
  width: 100%; max-height: 75vh; overflow-y: auto; margin: 0 !important; z-index: 1085;
  border-radius: 16px 16px 0 0; padding: 4px 0 calc(8px + env(safe-area-inset-bottom));
  box-shadow: 0 -6px 24px rgba(11, 23, 39, .18);
}
.order-menu-sheet .order-menu-sheet__head {
  padding: 12px 20px 8px; font-weight: 600; font-size: 1rem; color: var(--freepos-900);
  border-bottom: 1px solid var(--freepos-200); margin-bottom: 4px;
}
/* Цветной пункт меню на подсветке. Тема красит выделенный пункт в белый, но «Снять курьера»
   (text-primary), «Внести оплату» (text-warning) и «Отменить заказ» (text-danger) несут утилиты
   Bootstrap с !important — они побеждают, и синее слово на синей подсветке становится невидимым,
   а оранжевое и красное выглядят грязно. На выделении цвет значения больше не имеет: пункт и так
   виден тем, что подсвечен, — поэтому белым становятся все, вместе со значками. Только для
   выделенного состояния: в покое цвета остаются, они и отличают опасные действия от обычных */
.dropdown-item.active, .dropdown-item.active i,
.dropdown-item:active, .dropdown-item:active i {
  color: var(--freepos-dropdown-link-active-color) !important;
}

.order-menu-sheet .dropdown-item { padding: .75rem 1.25rem; font-size: 1rem; }
.order-menu-sheet .dropdown-item i { width: 1.4em; }



/* Поле без стрелок-спиннеров. В терминале правило точечное, а не на все number-поля разом (как в
   панели): терминал стоит на планшете, и там по стрелкам иногда тыкают пальцем — снимать их
   везом без спроса нельзя. Тип остаётся number ради проверки min/step и цифровой клавиатуры.
   Класс, а не id: следующее такое поле просто получит его же */
.no-spinner::-webkit-outer-spin-button,
.no-spinner::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.no-spinner {
  -moz-appearance: textfield;
  appearance: textfield;
}

/* Единица измерения внутри поля выхода заготовки. По нижнему краю, а не по середине: у поля с
   липкой подписью текст прижат вниз (сверху место занимает подпись), и единица, выровненная по
   центру, повисала выше самого числа. Отступы повторяют padding поля, чтобы «45» и «кг.» стояли
   на одной линии */
.production-unit {
  right: 0.75rem;
  bottom: 0.3rem;
  line-height: 1.5;
  pointer-events: none;
}


/* Значок-подсказка внутри поля ввода. Только вид, не орган управления: клики сквозь него идут
   в само поле, иначе попадание в значок не ставит курсор */
.field-icon {
  pointer-events: none;
}

/* Кнопка-галочка только со значком. Обычная pay-method-card держит flex: 1 0 90px — две таких
   в одной трети ряда не помещаются и обе сжимаются до 90px, обрезая подпись соседа. Этой отдаём
   ширину по содержимому: значок понятен без слова, а место достаётся тому, у кого слово есть */
#orderStepForm .pay-method-card--icon {
  flex: 0 0 auto;
  min-width: 0;
  padding-left: 0.7rem;
  padding-right: 0.7rem;
}

/* Значок тега блюда в строке каталога. Без плашки и без подписи: строка узкая, а цветной пузырь
   на каждой строке превратил бы список в рябь. Цвет задаётся инлайново — он свой у каждого тега.
   Тот же класс и тот же смысл, что у .dash-tag-mark в панели. */
.dash-tag-mark {
  font-size: 0.7rem;
  margin-left: 0.35rem;
}

/* Строка производства, в которую повар вписал свой расход: дальше она не пересчитывается ни
   выходом, ни правкой соседей. Тот же приём, что в панели — синяя рамка */
.production-fact-own{border-color:#2c7be5;color:#2c7be5;font-weight:600}

/* Окно выбора варианта и добавок (operator_product_options.html, initProductOptionsModal в extra.js).
   Варианты и ряды вариантов — сегменты: светлая дорожка, выбранное белым с синим текстом. Добавки —
   плитки в сетку: название слева, доплата справа, у выбранной синяя рамка и галочка, у пункта со
   счётчиком вместо галочки «− N +» внутри плитки. Сверх лимита группы невыбранные плитки гаснут
   (is-off) — вместо красной ошибки. Свои классы po-*, а не .pay-method-card: тот живёт ещё в
   каталоге и выборе курьера */
.po-group{margin-bottom:1.25rem}
.po-group__head{display:flex;align-items:baseline;gap:.5rem;margin-bottom:.5rem}
.po-group__title{font-size:.875rem;font-weight:600;color:#344050}
.po-group__rule{font-size:.75rem;color:#9da9bb}
.po-group__error{margin-top:.375rem;font-size:.75rem;color:#e63757}
.po-group__error:empty{display:none}
.po-seg{display:flex;flex-wrap:wrap;gap:4px;padding:4px;border-radius:.75rem;background:#edf2f9}
.po-seg__opt{position:relative;flex:1 1 6rem;margin:0;cursor:pointer}
.po-seg__opt input{position:absolute;opacity:0;pointer-events:none}
.po-seg__opt span{display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:2.125rem;padding:.25rem .75rem;border-radius:.5rem;font-size:.875rem;font-weight:500;line-height:1.2;text-align:center;color:#5e6e82;transition:background-color .15s,color .15s,box-shadow .15s}
.po-seg__opt span small{font-size:.75rem;font-weight:400;color:#9da9bb}
.po-seg__opt input:checked+span{background:#fff;color:#2c7be5;box-shadow:0 1px 4px rgba(21,22,25,.12)}
.po-seg__opt input:focus-visible+span{outline:2px solid rgba(44,123,229,.45)}
.po-items{display:grid;grid-template-columns:repeat(auto-fill,minmax(12rem,1fr));gap:.5rem}
.po-item{position:relative;display:flex;align-items:center;min-height:2.5rem;border:1px solid #d8e2ef;border-radius:.75rem;background:#fff;transition:border-color .15s,background-color .15s,opacity .15s}
.po-item__input{position:absolute;opacity:0;pointer-events:none}
.po-item__main{flex:1;display:flex;align-items:center;gap:.5rem;min-width:0;align-self:stretch;margin:0;padding:.5rem .75rem;cursor:pointer}
.po-item__title{flex:1;min-width:0;font-size:.875rem;line-height:1.25;color:#344050}
.po-item__title small{color:#9da9bb}
.po-item__price{flex-shrink:0;font-size:.8125rem;white-space:nowrap;color:#9da9bb}
.po-item__price:empty{display:none}
/* Font Awesome меняет <span class="fas"> на <svg> и подключает свой CSS позже этого файла — его
   .svg-inline--fa{display:inline-block} перебил бы одиночный класс, поэтому здесь два класса */
.po-item .po-item__check{display:none;margin-right:.875rem;font-size:.8125rem;color:#2c7be5}
.po-item.is-picked{border-color:#2c7be5;background:#f3f8fe}
.po-item.is-picked .po-item__title{font-weight:500;color:#2c7be5}
.po-item.is-picked .po-item__check{display:block}
.po-item.has-qty .po-item__check{display:none}
.po-item.is-off{opacity:.45}
.po-item.is-off .po-item__main{cursor:default}
.po-item__input:focus-visible+.po-item__main{outline:2px solid rgba(44,123,229,.45);outline-offset:-2px;border-radius:.75rem}
.po-qty{display:none;align-items:center;gap:.25rem;margin-right:.5rem}
.po-item.is-picked .po-qty{display:flex}
.po-qty__btn{display:flex;align-items:center;justify-content:center;width:1.625rem;height:1.625rem;padding:0;border:0;border-radius:50%;font-size:.6875rem;color:#fff;background:#2c7be5;transition:background-color .15s}
.po-qty__btn:disabled{background:#d8e2ef;cursor:default}
.po-qty__value{min-width:1.25rem;font-size:.875rem;font-weight:600;text-align:center;color:#2c7be5}
.po-total{font-size:1rem;font-weight:600;color:#344050}

/* Инвентаризация в терминале (#inventory-panel, initInventory в extra.js). Поле факта — высотой под палец
   (оператор ходит по складу с планшетом), шрифт — как у остальных полей терминала. Непосчитанная строка — тёплая метка слева,
   чтобы пропуск был виден, не читая чисел; повторный выбор позиции в каталоге — короткая вспышка
   строки вместо второй такой же (пересчёт не суммируется) */
.inv-title{font-weight:500;line-height:1.3;color:#344050}
.inv-qty-wrap{position:relative;display:inline-block;width:8.5rem}
.inv-qty{height:2.25rem;padding-right:2.75rem;font-size:.875rem;font-weight:500;text-align:right}
.inv-note{font-size:.875rem}
.inv-unit{position:absolute;right:.75rem;top:50%;transform:translateY(-50%);font-size:.75rem;color:#9da9bb;pointer-events:none}
.inv-qty-wrap.has-mode{display:inline-flex;align-items:center;gap:.25rem;width:auto}
.inv-qty-wrap.has-mode .inv-qty{width:5rem;padding-right:.5rem}
.inv-mode{width:auto;max-width:7.5rem;height:2.25rem;padding:.25rem 1.5rem .25rem .5rem;font-size:.75rem;color:#5e6e82;background-position:right .375rem center}
.inv-row td{padding-top:.5rem;padding-bottom:.5rem}
.inv-row.is-empty td:first-child{box-shadow:inset 3px 0 0 #f5803e}
.inv-row.is-empty .inv-qty{background:#fff8f2;border-color:#f7c7a3}
.inv-row--flash td{animation:inv-flash 1.2s ease-out}
@keyframes inv-flash{from{background:#fff3cd}to{background:transparent}}
.inv-empty-icon{display:inline-flex;align-items:center;justify-content:center;width:3rem;height:3rem;border-radius:50%;font-size:1.25rem;color:#2c7be5;background:#edf2f9}

/* Список заказов терминала (operator_orders_list.html, applyOrderFields в extra.js): номер — на
   плашке в цвете статуса (ORDER_NUMBER_STATUS_CLASS) вместо пяти разных значков статуса. Плашка
   одной ширины у номера из любого числа знаков, у значка источника своё поле — метки после них
   стоят в одну линию */
.order-number{min-width:2.9rem;padding:.35em .55em;font-size:.875rem;font-weight:500;font-variant-numeric:tabular-nums}
.order-source{display:inline-block;width:1.25rem;margin-left:.25rem;text-align:center;line-height:1}
.order-number--new{animation:order-number-pulse 1.8s ease-out infinite}
@keyframes order-number-pulse{0%{box-shadow:0 0 0 0 rgba(230,55,87,.55)}70%{box-shadow:0 0 0 .4rem rgba(230,55,87,0)}100%{box-shadow:0 0 0 0 rgba(230,55,87,0)}}
@media (prefers-reduced-motion:reduce){.order-number--new{animation:none}}
/* Синяя кнопка в стиль серой .btn-freepos-default: та же многослойная тень с тонкой обводкой, на
   наведении тень плавно растёт (переход задан у .btn темы), кнопка чуть светлеет, при нажатии тень
   уходит. Тень с синим отливом — иначе рядом с серой синяя выглядит плоской наклейкой. Зеркало —
   в dashboard/css/dashboard.css: у панели своя копия темы.
   :not(:disabled) — выключенная кнопка пагинации List.js ([data-list-pagination].btn-primary[disabled])
   оформлена темой как светлая, её не трогаем */
.btn-primary{border-color:#2c7be5;box-shadow:0 0 0 1px rgba(31,94,178,.3),0 2px 5px 0 rgba(44,123,229,.22),0 1px 1.5px 0 rgba(0,0,0,.07),0 1px 2px 0 rgba(0,0,0,.08),inset 0 1px 0 rgba(255,255,255,.14)}
.btn-primary:hover:not(:disabled):not(.disabled),.btn-primary:focus:not(:disabled):not(.disabled){color:#fff;background-color:#3585ec;border-color:#3585ec;box-shadow:0 0 0 1px rgba(31,94,178,.3),0 2px 5px 0 rgba(44,123,229,.28),0 3px 9px 0 rgba(44,123,229,.24),0 1px 1.5px 0 rgba(0,0,0,.08),0 1px 2px 0 rgba(0,0,0,.08),inset 0 1px 0 rgba(255,255,255,.14)}
.btn-primary:active:not(:disabled):not(.disabled){background-color:#2569c3;border-color:#2569c3;box-shadow:none}
/* Красная кнопка — тем же приёмом, что синяя выше: тень с обводкой и красным отливом, на наведении
   тень растёт, при нажатии кнопка темнеет и тень уходит. Светлеть на наведении, как синяя, ей
   нельзя — светлый красный уходит в розовый и выглядит блёкло; вместо этого чуть насыщеннее */
.btn-danger{border-color:#e63757;box-shadow:0 0 0 1px rgba(176,32,58,.3),0 2px 5px 0 rgba(230,55,87,.22),0 1px 1.5px 0 rgba(0,0,0,.07),0 1px 2px 0 rgba(0,0,0,.08),inset 0 1px 0 rgba(255,255,255,.14)}
.btn-danger:hover:not(:disabled):not(.disabled),.btn-danger:focus:not(:disabled):not(.disabled){color:#fff;background-color:#e82c4f;border-color:#e82c4f;box-shadow:0 0 0 1px rgba(176,32,58,.3),0 2px 5px 0 rgba(230,55,87,.28),0 3px 9px 0 rgba(230,55,87,.24),0 1px 1.5px 0 rgba(0,0,0,.08),0 1px 2px 0 rgba(0,0,0,.08),inset 0 1px 0 rgba(255,255,255,.14)}
.btn-danger:active:not(:disabled):not(.disabled){background-color:#c42f4a;border-color:#c42f4a;box-shadow:none}.bonus-off-icon{position:relative;display:inline-block;margin-right:.3rem;font-size:.7rem;color:#9da9bb;vertical-align:.05em}
.bonus-off-icon::after{content:"";position:absolute;left:-.15em;right:-.15em;top:48%;border-top:1.5px solid currentColor;transform:rotate(-40deg)}
/* Аватар оператора в шапке терминала — 36px вместо стандартных 32px у .avatar-xl, но без роста
   строки .navbar-nav-icons: отрицательный вертикальный отступ компенсирует разницу в высоте
   ровно на ту же величину, что добавляет увеличенный круг (36-32=4px, по 2px с каждой стороны) */
.navbar-nav-icons .avatar-xl{width:2.25rem;height:2.25rem;margin-top:-.125rem;margin-bottom:-.125rem}
.navbar-nav-icons .avatar-xl .avatar-name{font-size:.75rem}

/* Поле со своей кнопкой-значком у правого края (.has-field-btn: «Тел» — значок гостя, «Имя» —
   аноним). Отступ справа — под кнопку; у невалидного поля значок ошибки Bootstrap встаёт левее
   кнопки, а не под неё, и отступ растёт на его ширину */
.form-control.has-field-btn{padding-right:2rem}
.form-control.has-field-btn.is-invalid,.was-validated .form-control.has-field-btn:invalid{padding-right:calc(2.25rem + .75em + .375rem);background-position:right 2rem center}

/* Подсказки кассиру в шапке терминала (templates/_terminal_hints.html): за сколько отдаём заказ и
   кому из курьеров его отдать. Пилюли в цвет шапки; «дольше обычного» — красный значок «!» в пилюле, чтобы
   кассир заметил, не открывая справку */
.terminal-hints{gap:.5rem;margin-right:.75rem}
.terminal-hint{display:inline-flex;align-items:center;gap:.6rem;height:2rem;padding:0 .75rem;border:1px solid var(--freepos-border-color,#d8e2ef);border-radius:1rem;background:var(--freepos-card-bg,#fff);color:var(--freepos-700,#5e6e82);font-size:.8125rem;font-weight:600;line-height:1;white-space:nowrap;cursor:pointer;transition:background-color .15s,border-color .15s}
.terminal-hint:hover,.terminal-hint[aria-expanded="true"]{background:var(--freepos-gray-100,#f9fafd);border-color:#b6c1d2}
.terminal-hint__item{display:inline-flex;align-items:center}
.terminal-hint__icon{margin-right:.35rem;font-size:.75rem;opacity:.7}
/* Велосипед курьера — глиф широкий и низкий: в общем размере значков выходил вдвое мельче соседних */
.terminal-hint__icon.bi-bicycle{font-size:1rem}
.terminal-hint__alert{font-size:.8125rem;color:var(--freepos-danger,#e63757)}
/* Меню раскрывается ВНУТРИ шапки терминала, а у неё font-weight:600 от темы — без сброса весь
   текст подсказки шёл полужирным, и выделять в нём было нечего. Обычный вес здесь, акценты —
   точечно: заголовок, названия групп и цифры (fw-semi-bold в разметке) */
.terminal-hint__menu{min-width:17rem;max-width:22rem;padding:0;font-size:.8125rem;font-weight:400}
/* Отступы и фон — на внутреннем блоке, а не на самом меню: его фон закрывает нижнюю половину
   выступа-каретки, иначе она видна целым ромбом (см. .dropdown-menu:after в теме) */
.terminal-hint__body{padding:.75rem 1rem;background:var(--freepos-card-bg,#fff);border-radius:.375rem}
.terminal-hint__title{font-weight:600;margin-bottom:.5rem;color:var(--freepos-900,#0b1727)}
.terminal-hint__group{margin:.6rem 0 .25rem;font-size:.6875rem;font-weight:600;text-transform:uppercase;letter-spacing:.03em;color:var(--freepos-600,#748194)}
.terminal-hint__row{display:flex;align-items:center;gap:.5rem;padding:.2rem 0}
.terminal-hint__row-icon{width:1rem;text-align:center;color:var(--freepos-500,#9da9bb)}
.terminal-hint__sub{margin:0 0 .35rem 1.5rem;font-size:.75rem;font-weight:400;color:var(--freepos-600,#748194)}
.terminal-hint__note{margin-top:.6rem;padding-top:.6rem;border-top:1px solid var(--freepos-border-color,#d8e2ef);font-size:.75rem;font-weight:400;color:var(--freepos-700,#5e6e82);white-space:normal}
.terminal-hint__dot{width:.5rem;height:.5rem;border-radius:50%;flex:0 0 .5rem}
.terminal-hint__dot--coming{background:#00d27a}
.terminal-hint__dot--free{background:#2c7be5}
.terminal-hint__dot--busy{background:#b6c1d2}
@media (max-width:575.98px){.terminal-hints{margin-right:.25rem;gap:.35rem}.terminal-hint{padding:0 .55rem;gap:.4rem;font-size:.75rem}.terminal-hint__name{max-width:6rem}}

/* Трубка в тосте о входящем звонке: покачивается, пока разговор идёт. Чистый CSS, без таймеров в
   JS. prefers-reduced-motion уважаем — у части людей от такого кружится голова */
@keyframes voip-ringing{0%,60%,100%{transform:rotate(0)}5%,15%,25%{transform:rotate(-14deg)}10%,20%,30%{transform:rotate(14deg)}}
.voip-ringing{display:inline-block;transform-origin:50% 60%;animation:voip-ringing 1.6s ease-in-out infinite}
@media (prefers-reduced-motion:reduce){.voip-ringing{animation:none}}
body.delivery-off [data-courier-only],body.delivery-off #zaborSelect option[value="delivery"]{display:none!important}

/* Окно «Гость»: вердикт и отменённые заказы в списке. Цвет здесь — подсказка, а не заливка.
   Сплошной оранжевый фон строки («table-warning») поверх полосатой таблицы читался грязно и
   кричал громче красного, хотя значит всего лишь «присмотритесь». У жёлтого осталась только полоса слева, у красного — ещё и
   еле заметный фон: так важное видно раньше. Фон задаём переменными таблицы, как это делает .table-danger в теме,
   иначе полосатость (inset box-shadow на каждой ячейке) легла бы поверх */
.guest-row--danger{--freepos-table-bg:#fdf0f2;--freepos-table-striped-bg:#fbe8ec;--freepos-table-hover-bg:#f9dfe4}
.guest-row--warning{--freepos-table-hover-bg:#fbead9}
.guest-row--danger>td:first-child,.guest-row--warning>td:first-child{border-left-style:solid;border-left-width:.1875rem;padding-left:.5625rem}
.guest-row--danger>td:first-child{border-left-color:var(--freepos-danger,#e63757)}
.guest-row--warning>td:first-child{border-left-color:var(--freepos-warning,#f5803e)}
.guest-verdict{display:flex;align-items:flex-start;gap:.75rem;padding:.75rem 1rem;border-radius:.375rem;background:var(--freepos-100,#f9fafd);border-left:.25rem solid var(--freepos-300,#d8e2ef)}
.guest-verdict--danger{border-left-color:var(--freepos-danger,#e63757)}
.guest-verdict--warning{border-left-color:var(--freepos-warning,#f5803e)}
.guest-verdict--success{border-left-color:var(--freepos-success,#00d27a)}

/* Шапки таблиц в панелях карточки корзины (приход, списание, производство, инвентаризация).
   Подписи столбцов идут подряд на сплошной заливке и сливались в одну строку — разделяем
   вертикальными линиями. Только в шапке: в теле строки и так разделены горизонтальными
   линиями, а полная сетка превратила бы карту в Excel */
.panel-table thead th + th { border-left: 1px solid var(--freepos-300, #d8e2ef); }

/* Подпись оплаты заказа: при делёной оплате её части приходят РАЗНЫМИ СТРОКАМИ
   (OrderPaymentLabel с PAYMENT_LABEL_GLUE) — «Наличные 300 ₽» и «Моб. терминал 460 ₽». Без
   pre-line перенос схлопнулся бы в пробел, и две суммы слиплись бы в одну фразу */
.payment-label { white-space: pre-line; }

/* Заголовок первого экрана главной: слово в нём печатается само (typed.js — «умное», «простое»,
   «бесплатное»). На телефоне перенос строки после слова скрыт, поэтому заголовок течёт как абзац:
   пустой он занимает две строки, с любым словом — три, и на КАЖДОМ цикле анимации весь экран под
   ним прыгал на строку вверх-вниз (замерено: высота 67↔100 px, кнопка ездила на 34 px).

   Лечим не анимацию, а место под неё: рядом с живым заголовком лежит его невидимый двойник с самым
   длинным словом, оба в одной ячейке grid — высота блока равна большей из двух и не зависит ни от
   ширины экрана, ни от того, какое слово печатается сейчас. Поэтому здесь нет ни одного подобранного
   числа: подставите слово длиннее — место под него посчитается само (двойник править вместе со
   строкой data-typed-text) */
.hero-heading { display: grid; }
.hero-heading > * { grid-area: 1 / 1; margin: 0; }
/* Двойник не читается ни глазами, ни экранным диктором (aria-hidden в разметке), но занимает место */
.hero-heading__ghost { visibility: hidden; }

/* Самые узкие экраны (320 px): там «бесплатное» не помещается в три строки и уезжает в четвёртую —
   двойник честно зарезервировал бы её, и под остальными пятью словами висела бы пустая строка.
   Дешевле немного уменьшить кегль: тогда в три строки помещаются все слова */
@media (max-width: 359.98px) {
  .hero-heading h1, .hero-heading .h1 { font-size: 1.55rem; }
}

/* Меню главной на телефоне (navbar-expand-lg, то есть до 992 px).
   Бургер превращается в крестик, пока меню открыто: та же кнопка его и закрывает, но по бургеру
   это не читается.
   Фон открытого меню — на САМОЙ шапке и по своему классу menu-open (ставит main.html по событиям
   раскрытия). Почему так, а не иначе, выяснено на двух видео владельца:
   • тема красит шапку инлайн-стилем rgba(…, alpha) от прокрутки и вдобавок СНИМАЕТ с неё тёмный
     класс в своём обработчике resize — а на iOS resize срабатывает при каждом появлении адресной
     строки, то есть ровно при возврате наверх: меню при открытом состоянии становилось прозрачным;
   • фон на самом выпавшем блоке не годится: блок лежит внутри .container с его отступами и не
     доходит до краёв экрана — получался тёмный квадрат посреди прозрачной шапки.
   !important — потому что спорим с инлайн-стилем темы, а не с её классом. Только цвет: отступы и
   скругление здесь уже портили раскрытие, меняя высоту блока во время анимации */
@media (max-width: 991.98px) {
  .navbar-standard.menu-open {
    background-color: #0b1727 !important;
  }

  .navbar-standard .navbar-toggler:not(.collapsed) .navbar-toggler-icon {
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255,255,255,0.85%29' stroke-width='2.2' stroke-linecap='round' d='M8 8 L22 22 M22 8 L8 22'/%3e%3c/svg%3e");
  }
}

/* Зал в кассе (operator_hall.html, hall.js). Плитка — стол: номер крупно, под ним сумма, гости и
   время, внизу состояние. Свой стол — рамкой цвета темы, чужой — обычной; цвет фона — состояние:
   свободен белый, занят голубой, «счёт выдан» жёлтый, оплачен зелёный. Красного нет намеренно:
   его читают как ошибку, а у стола ошибок не бывает */
.hall-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(7.5rem, 1fr)); gap: .5rem; align-content: start; }
.hall-tile {
  position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  min-height: 7rem; padding: .5rem .25rem; border: 1px solid var(--freepos-300); border-radius: .5rem;
  background: var(--freepos-white); color: var(--freepos-900); line-height: 1.15; cursor: pointer;
  transition: border-color .15s, box-shadow .15s, transform .1s;
}
.hall-tile:hover, .hall-tile:focus-visible { box-shadow: 0 0 0 .15rem rgba(44, 123, 229, .25); outline: 0; }
.hall-tile:active { transform: scale(.98); }
.hall-tile--round { border-radius: 50%; aspect-ratio: 1; min-height: 0; }
.hall-tile--busy { background: #eaf2fd; }
.hall-tile--precheck { background: #fef6e6; }
.hall-tile--paid { background: #e6f7ee; }
.hall-tile--mine { border: 2px solid var(--freepos-primary, #2c7be5); }
/* Стол, за который сейчас сажают или дозаказывают (markActiveTile в hall.js) */
.hall-tile--active, .hall-tile--active:hover, .hall-tile--active:focus-visible { box-shadow: 0 0 0 3px #e63757; }
.hall-tile__number { font-size: 1.5rem; font-weight: 600; }
.hall-tile__sum { font-size: .875rem; font-weight: 600; }
.hall-tile__meta { font-size: .75rem; color: var(--freepos-700, #5e6e82); white-space: nowrap; }
.hall-tile__meta .fas { font-size: .625rem; }
.hall-tile__badge { font-size: .6875rem; font-weight: 500; }
.hall-tile__waiter { max-width: 100%; font-size: .6875rem; color: var(--freepos-600, #748194); }
.hall-tile__checks { position: absolute; top: .25rem; right: .25rem; font-size: .625rem; }
.hall-tabs .nav-link { color: var(--freepos-700, #5e6e82); }
.hall-tabs .nav-link.active { color: #fff; }
/* «Каталог / Зал» — тот же переключатель, что в панели управления (.dash-segmented в dashboard.css):
   дорожка, белый бегунок уезжает под выбранный пункт. Пункты равной ширины — бегунку нужны равные доли */
/* Высота переключателя — как у поля поиска рядом (29 px): шапка каталога обязана уложиться в расчётные 61 px
   (operator_catalog_row.html), иначе каталог показывает меньше строк, чем задано в настройке */
.hall-view-switch { position: relative; display: inline-grid; grid-template-columns: 1fr 1fr; gap: 4px; padding: 3px;
  border-radius: 999px; background: #edf2f9; }
.hall-view-switch__thumb { position: absolute; top: 3px; left: 3px; width: calc(50% - 5px); height: calc(100% - 6px);
  border-radius: 999px; background: #fff; box-shadow: 0 2px 6px rgba(21, 22, 25, .10); pointer-events: none;
  transition: transform .28s cubic-bezier(.4, 0, .2, 1); }
.hall-view-switch:has(.hall-view-switch__option:last-child.active) .hall-view-switch__thumb { transform: translateX(calc(100% + 4px)); }
.hall-view-switch__option { position: relative; z-index: 1; display: flex; align-items: center; justify-content: center;
  height: 23px; padding: 0 14px; border: 0; border-radius: 999px; background: transparent; color: #5e6e82;
  font-size: .8125rem; line-height: 1; white-space: nowrap; cursor: pointer; transition: color .2s; }
.hall-view-switch__option.active { color: var(--freepos-primary, #2c7be5); }
.hall-view-switch__option:focus-visible { outline: 2px solid rgba(44, 123, 229, .45); outline-offset: 1px; }
@media (prefers-reduced-motion: reduce) { .hall-view-switch__thumb { transition: none; } }
/* Точка на «Зал», пока официант в каталоге: красная — зовут со стола, зелёная — на его столе всё готово */
.hall-view-switch__dot { position: absolute; top: 3px; right: 6px; width: 8px; height: 8px; border-radius: 50%; box-shadow: 0 0 0 2px #edf2f9; }
.hall-view-switch__dot[data-hall-attention="call"] { background: #e63757; }
.hall-view-switch__dot[data-hall-attention="carry"] { background: #00d27a; }
.hall-view-switch__option.active .hall-view-switch__dot { display: none; }
.hall-guests-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: .5rem; }
.hall-guests-grid .btn { font-size: 1.125rem; font-weight: 600; padding: .5rem 0; }
/* Гостей больше, чем мест за столом: можно, но видно, что это сверх */
.hall-guests-grid .btn.hall-guests-over { border-style: dashed; color: var(--freepos-500, #9da9bb); }
.table-bar { background: #eaf2fd; }
/* Схема зала: клетки редактора панели без пустых краёв (HallTerminalState). Схема вписывается в
   ширину панели, клетки квадратные (пропорция — числом колонок и строк), поэтому пустой ряд — проход
   между столами — не схлопывается. Не крупнее 5.5rem на клетку и не выше панели; мельче 2.75rem
   (палец) — не сжимается, а листается вбок */
/* Прокрутка вбок обрезает всё, что выходит за края, и по вертикали тоже — подсветка плитки при
   наведении срезалась. Отступ даёт тени место, отрицательное поле возвращает схему на своё место */
.hall-plan-scroll { overflow-x: auto; padding: .3rem; margin: -.3rem; }
.hall-plan {
  display: grid; gap: .375rem; width: 100%; margin: 0 auto; aspect-ratio: var(--plan-cols) / var(--plan-rows);
  /* Вписывается и в высоту панели (--hall-h, минус поля и «Брони» внизу): иначе на большом экране
     квадратные клетки растягивали схему ниже края, и зал листался вниз */
  max-width: min(calc(var(--plan-cols) * 5.5rem), calc((var(--hall-h, 100vh) - 5rem) * var(--plan-cols) / var(--plan-rows)));
  min-width: calc(var(--plan-cols) * 2.75rem);
  grid-template-columns: repeat(var(--plan-cols), minmax(0, 1fr)); grid-template-rows: repeat(var(--plan-rows), minmax(0, 1fr));
}
.hall-tile--compact { min-height: 0; padding: .25rem; gap: 0; overflow: hidden; }
/* Круглый стол 1 × 1 — круг по высоте ряда посреди клетки; вытянутый (2 × 1) — овал на свои клетки */
.hall-tile--compact.hall-tile--round { aspect-ratio: auto; }
.hall-tile--compact.hall-tile--round.hall-tile--even { aspect-ratio: 1; height: 100%; justify-self: center; }
.hall-tile--compact .hall-tile__number { font-size: 1.125rem; }
.hall-tile--compact .hall-tile__sum { font-size: .75rem; font-weight: 500; }
.hall-tile--compact .hall-tile__checks { top: .125rem; right: .125rem; }
.hall-tile__dot { position: absolute; bottom: .375rem; left: .375rem; width: .5rem; height: .5rem; border-radius: 50%; }
.hall-tile--round .hall-tile__dot { bottom: 18%; left: 18%; }
.hall-tile__dot--ready { background: #00d27a; }
/* Вызов со стола (QR): колокольчик в левом верхнем углу, пульсирует — официант ищет его глазами */
.hall-tile__call { position: absolute; top: .25rem; left: .3rem; display: flex; align-items: center; justify-content: center;
  width: 1.4rem; height: 1.4rem; border-radius: 50%; background: #e63757; color: #fff; font-size: .7rem;
  animation: hall-call-pulse 1.4s ease-in-out infinite; }
.hall-tile--round .hall-tile__call { top: 10%; left: 10%; }
@keyframes hall-call-pulse { 50% { box-shadow: 0 0 0 .35rem rgba(230, 55, 87, .25); } }
@media (prefers-reduced-motion: reduce) { .hall-tile__call { animation: none; } }
.hall-tile__dot--held { background: #f5803e; }
/* Серая точка — стол давно без дозаказа: не тревога, а повод подойти, поэтому цвет приглушённый.
   Зелёная и оранжевая важнее и показываются вместо неё (см. operator_hall.html) */
.hall-tile__dot--idle { background: #b6c1d2; }
.hall-tile__held { margin-top: .125rem; font-size: .625rem; font-weight: 500; white-space: nowrap; }
/* Телефон официанта: три стола в ряд — иначе круглый стол во всю половину экрана */
@media (max-width: 575.98px) {
  .hall-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .hall-tile { min-height: 6rem; }
  /* Круг высотой в содержимое занятого стола раздвигал бы колонку за край экрана — на телефоне
     круглый стол рисуется скруглённой плиткой по ширине колонки */
  .hall-grid .hall-tile--round { aspect-ratio: auto; border-radius: 2.5rem; }
}
/* Бронь на свободном столе — жёлтая рамка: стол свободен, но скоро за ним будут гости */
.hall-tile--reserved { border: 2px dashed #f5803e; background: #fffaf3; }

/* Окно деления счёта: два списка одной высоты с прокруткой */
.split-list { min-height: 12rem; max-height: 50vh; overflow-y: auto; }
.split-list .split-row--active { cursor: pointer; }
.split-list .split-row--active:hover { color: var(--freepos-primary, #2c7be5); }

/* Значок зала — круглый стол и стул (assets/img/icons/hall-table-round.png, рисунок шире высоты — и
   значок шире строки): маска в цвет текста, как у шрифтовых значков, поэтому он серый, синий или белый
   вместе с подписью рядом. Прозрачность файла — темнота рисунка: белые линии внутри остаются просветами */
.icon-hall { display: inline-block; width: 1.6em; height: 1.15em; vertical-align: -.22em; background-color: currentColor;
  -webkit-mask: url(/assets/img/icons/hall-table-round.png?v=2) center / contain no-repeat;
  mask: url(/assets/img/icons/hall-table-round.png?v=2) center / contain no-repeat; }
/* Низ зала: «Брони» справа у нижнего края панели — и когда столов мало (margin-top: auto в колонке),
   и когда зал длинный и листается (sticky) */
#hall-panel:not(.d-none) { display: flex; flex-direction: column; }
.hall-footer { position: sticky; bottom: 0; z-index: 2; display: flex; justify-content: flex-end; margin-top: auto; padding: .5rem;
  background: linear-gradient(to bottom, rgba(255, 255, 255, 0), #fff 45%); }
/* Выделение строк корзины стола: официант выбирает строки и переносит их гостю или в курс (hall.js).
   Рамка и лёгкий фон — состояние видно, но строка читается как прежде */
.hall-line-selected { border-color: var(--freepos-primary, #2c7be5) !important;
  box-shadow: inset 0 0 0 1px var(--freepos-primary, #2c7be5); background-color: #f3f8fe; }
/* Крестик пустого гостя/курса внутри чипа: заметен при наведении, не мешает нажатию самого чипа */
.hall-chip-x { margin-left: .4rem; padding: 0 .15rem; color: var(--freepos-500, #9da9bb); font-weight: 700; }
button:hover .hall-chip-x { color: var(--freepos-danger, #e63757); }
.btn-primary .hall-chip-x, .btn-warning .hall-chip-x { color: rgba(255, 255, 255, .8); }
/* Чип гостя/курса, где выделенные строки уже стоят: обводка, не заливка — залитый в режиме
   выделения читался бы как цель переноса */
.hall-chip-own { border-color: var(--freepos-primary, #2c7be5) !important; color: var(--freepos-primary, #2c7be5) !important; }
/* Окно деления: подзаголовок группы гостя в левой колонке */
.split-group { background: var(--freepos-100, #f9fafd); font-size: .75rem; font-weight: 600; color: var(--freepos-700, #5e6e82); }
#splitTarget { max-width: 100%; }
/* Телефон: колонки деления друг под другом, списки со своей прокруткой */
@media (max-width: 575.98px) { .split-list { max-height: 30vh; overflow-y: auto; } }
/* Окна зала перетаскиваются за шапку (makeModalDraggable, hall.js) */
[data-modal-drag] { cursor: move; touch-action: none; user-select: none; -webkit-user-select: none; }
/* Промокод при привязанном к корзине госте бонусной программы: предупреждение под полем кода */
#promo_bonus_hint { display: none; }
body:not(.cashback-off):has(#basket_discount_data[data-discount-type="cashback"]) #promo_bonus_hint { display: block; }

/* Каталог на телефоне: название и цена. «Ед.изм» и «Кол-во» официанту у стола не нужны, кружок с
   буквами у блюда ничего не сообщает, а длинное название переносится, чтобы цена не уезжала за край */
@media (max-width: 575.98px) {
  .catalog-table > thead > tr > th:nth-child(3), .catalog-table > thead > tr > th:nth-child(4),
  .catalog-table td.pcs, .catalog-table td.amount { display: none; }
  .catalog-table td.num { width: 44px !important; padding-right: 0; }
  .catalog-table td.num .avatar { display: none; }
  .catalog-table td.num .fs-2 { font-size: 1.4rem !important; }
  .catalog-table td.name { white-space: normal !important; width: auto; }
  .catalog-table > thead > tr > th:nth-child(2) { max-width: 0; overflow: hidden; text-overflow: ellipsis; }
  .catalog-table td.price { width: 1%; padding-left: .5rem; }
}
/* Сколько позиции уже в корзине — у цены строки каталога (initBasketPeek), пока корзина стоит под
   каталогом и её не видно. Зелёная вспышка строки — позиция только что добавилась */
.cat-in-basket { display: none; }
@media (max-width: 991.98px) {
  .cat-in-basket { display: block; font-size: .75rem; font-weight: 600; color: var(--freepos-success, #00d27a); line-height: 1.2; }
}
@keyframes catAdded { from { background-color: rgba(0, 210, 122, .28); } to { background-color: transparent; } }
.catalog-table tr.cat-added > td { animation: catAdded .9s ease-out; }
/* Плашка корзины внизу экрана (initBasketPeek): только когда корзина под каталогом и не на экране */
.basket-peek {
  position: fixed; left: 12px; right: 12px; bottom: calc(12px + env(safe-area-inset-bottom, 0px)); z-index: 1029;
  display: flex; align-items: center; gap: .6rem; padding: .7rem 1rem; border: 0; border-radius: 14px;
  background: var(--freepos-primary, #2c7be5); color: #fff; font-size: .9rem; text-align: left;
  box-shadow: 0 6px 20px rgba(11, 23, 39, .25);
  transform: translateY(0); transition: transform .2s, opacity .2s;
}
.basket-peek[hidden] { display: none; }
.basket-peek .basket-peek-sum { margin-left: auto; font-weight: 600; white-space: nowrap; }
@keyframes basketPeekBump { 0% { transform: scale(1); } 40% { transform: scale(1.05); } 100% { transform: scale(1); } }
.basket-peek.bump { animation: basketPeekBump .35s ease-out; }
body.basket-peek-on .toast-dock { padding-bottom: calc(76px + env(safe-area-inset-bottom, 0px)) !important; }

/* Шапка каталога на телефоне — одна строка: переключатель «Каталог / Зал» значками (подписи в title),
   поиск на остаток ширины. У точки без зала заголовок не нужен — поиск во всю строку */
.hall-view-switch .hall-view-switch__icon { display: none; }
.hall-view-switch__hall-icon { margin-right: .25rem; }
@media (max-width: 575.98px) {
  .catalog-head { flex-wrap: nowrap; }
  .catalog-head > .catalog-head-title { flex: 0 0 auto; width: auto; }
  .catalog-head > .catalog-head-title > h5 { display: none; }
  .catalog-head > .catalog-head-title:not(:has(.hall-view-switch)) { display: none !important; }
  .catalog-head > .catalog-head-search { flex: 1 1 auto; width: auto; min-width: 0; }
  .catalog-head .hall-view-switch__option { padding: 0 12px; }
  .catalog-head .hall-view-switch__label { display: none; }
  .catalog-head .hall-view-switch .hall-view-switch__icon { display: inline-block; }
  .catalog-head > .catalog-head-search { padding-left: .5rem; }
  /* Лупа рядом с полем — украшение, а не кнопка (поиск идёт по вводу): на телефоне место нужнее полю */
  .catalog-head-search .input-group > .input-group-text:not(#searchClearBtn) { display: none; }
  .catalog-head-search .input-group:has(#searchClearBtn.d-none) > .search { border-top-right-radius: .25rem !important; border-bottom-right-radius: .25rem !important; }
  .catalog-head .hall-view-switch__hall-icon { margin-right: 0; }
}
/* Подвал корзины: «%» и «Сдача с…» — всегда в ряд. Safari ужимал группу (у .input-group перенос) до
   ширины одной кнопки, и калькулятор уезжал под «%» */
#promocode_and_extra { flex-wrap: nowrap; flex: 0 0 auto; width: auto; }
/* Стол, который оплата закрыла сама недавно (HallTerminalState → LEFT_MIN): свободен, но гости, скорее
   всего, ещё сидят — бледная зелёная рамка, ничего не блокирует */
.hall-tile--free.hall-tile--left { border: 2px dashed rgba(0, 210, 122, .55); background: #f4fcf8; }

/* Цвет гостя счёта стола: Г1 и Г2 одной синей плашкой на бегу не различить. Шесть цветов по кругу
   (guest-tag--1…6 = ((N−1) mod 6) + 1) — одни в корзине, карточке заказа, окне деления и у кнопок гостей.
   Жёлтого и красного нет: жёлтым помечен курс «К2», красный читается ошибкой */
.guest-tag { font-weight: 600; }
.guest-tag--1 { background-color: #d5e5fa; color: #1c4f93; }
.guest-tag--2 { background-color: #ccf6e4; color: #00754a; }
.guest-tag--3 { background-color: #e8defd; color: #5f35c4; }
.guest-tag--4 { background-color: #d4f2ff; color: #11698f; }
.guest-tag--5 { background-color: #fde1ef; color: #b01f63; }
.guest-tag--6 { background-color: #e3e8f0; color: #44546d; }
/* Кнопка гостя над корзиной — кружок его цвета перед номером */
.guest-dot { display: inline-block; width: .55rem; height: .55rem; border-radius: 50%; margin-right: .3rem; vertical-align: .05em; }
.guest-dot.guest-tag--1 { background-color: #2c7be5; } .guest-dot.guest-tag--2 { background-color: #00b074; }
.guest-dot.guest-tag--3 { background-color: #7b4ee8; } .guest-dot.guest-tag--4 { background-color: #1ba6d6; }
.guest-dot.guest-tag--5 { background-color: #e0398a; } .guest-dot.guest-tag--6 { background-color: #7486a3; }
/* Выбранная кнопка гостя залита его цветом, кружок — белый */
.guest-chip-on { color: #fff !important; border-color: transparent !important; }
.guest-chip-on.guest-tag--1 { background-color: #2c7be5; } .guest-chip-on.guest-tag--2 { background-color: #00a36b; }
.guest-chip-on.guest-tag--3 { background-color: #7b4ee8; } .guest-chip-on.guest-tag--4 { background-color: #1795c2; }
.guest-chip-on.guest-tag--5 { background-color: #d6337f; } .guest-chip-on.guest-tag--6 { background-color: #64758f; }
.guest-chip-on .guest-dot { background-color: #fff !important; }
/* Полоса гостей и курса: между группами зазор шире, чем между кнопками; перенесённая строка — без сдвига */
#tableGuestBar { column-gap: .75rem; row-gap: .35rem; }
/* Кнопки гостей и курсов переносятся по одной, следом за подписью, — а не всем рядом на новую строку
   (подпись «Гость:» оставалась одна). Группа «Курс» при этом уходит вниз целиком */
#tableGuestChips, #tableCourseChips { display: contents !important; }

/* Окна «Переработка» и «Фото накладной» (processing.js): пикер позиции — как в техкартах панели (dashboard.css, .choices--staff и
   .dash-recipe-add): белое поле высотой с form-control-sm, белые строки списка, название жирным и под ним мелкой
   строкой артикул, рубрика, вид, единица, остаток и цена; подсветка строки — серая, а не синяя тема. В закрытом
   поле — только название: вторая строка растягивала бы поле на две */
:is(#processingModal, #receiptPhotoModal) .choices { margin-bottom: 0; }
:is(#processingModal, #receiptPhotoModal) .choices__inner {
  min-height: calc(1.5em + .8rem + 2px); padding: .25rem .5rem; display: flex; align-items: center;
  font-size: .875rem; background-color: #fff; border-radius: .25rem;
}
:is(#processingModal, #receiptPhotoModal) .choices__list--single { padding: 0 !important; }
:is(#processingModal, #receiptPhotoModal) .choices__list--single .choices__item { font-size: .875rem !important; line-height: 1.5 !important; padding: 0 !important; }
:is(#processingModal, #receiptPhotoModal) .choices__list--single .processing-opt-meta { display: none !important; }
:is(#processingModal, #receiptPhotoModal) .choices__list--single .processing-opt-name { font-weight: 400; }
:is(#processingModal, #receiptPhotoModal) .choices__input { font-size: .8rem; padding: .35rem .5rem !important; margin-bottom: 0; }
:is(#processingModal, #receiptPhotoModal) .choices__list--dropdown .choices__item,
:is(#processingModal, #receiptPhotoModal) .choices__list--dropdown .choices__item--selectable,
:is(#processingModal, #receiptPhotoModal) .choices__list--dropdown .choices__placeholder {
  font-size: .8rem !important; line-height: 1.25 !important; padding: .35rem .75rem !important;
  background-color: #fff; color: var(--freepos-900, #344050);
}
:is(#processingModal, #receiptPhotoModal) .choices__list--dropdown .choices__item--selectable.is-highlighted,
:is(#processingModal, #receiptPhotoModal) .choices__list--dropdown .choices__item--selectable:hover {
  background-color: var(--freepos-200, #edf2f9); color: var(--freepos-900, #344050);
}
.processing-opt { display: flex; flex-direction: column; min-width: 0; }
.processing-opt-name { font-weight: 600; color: var(--freepos-900, #344050); }
.processing-opt-meta { font-size: .72rem; color: var(--freepos-700, #5e6e82); }
:is(#processingModal, #receiptPhotoModal) .choices__list--dropdown:not(.is-active) { display: none; }
/* Выход карты разделки в режиме «только по картам» не меняют: список серый и без стрелки */
#processingModal .choices.is-disabled .choices__inner { background-color: var(--freepos-200); cursor: default; }
#processingModal .choices.is-disabled[data-type*="select-one"]::after { display: none; }
/* Окно «Фото накладной» на телефоне: строка сопоставления — карточкой (документ, позиция, пересчёт, сумма
   друг под другом), а не таблицей с прокруткой вбок — как окно УПД в панели */
@media (max-width: 575.98px) {
  #receiptPhotoModal thead { display: none; }
  #receiptPhotoModal tbody, #receiptPhotoModal tbody tr, #receiptPhotoModal tbody td { display: block; width: 100%; }
  #receiptPhotoModal tbody tr { padding: .5rem 0; border-bottom: 1px solid var(--freepos-200, #edf2f9); }
  #receiptPhotoModal tbody td { border: 0; padding: .2rem 0; }
  #receiptPhotoModal tbody td[data-rp-sum] { text-align: left !important; font-weight: 600; }
  #receiptPhotoModal [data-rp-conv].invisible { display: none !important; }
}
/* Раскрытый список Choices — перенос по словам: у Choices по умолчанию break-all, и «остаток» рвался на
   «остато / к». Для всех списков кассы, как в панели (dashboard.css) */
.choices__list--dropdown .choices__item, .choices__list[aria-expanded] .choices__item { word-break: normal; overflow-wrap: break-word; }

/* Окна наличных кассы (operator_cash_drawer.html, operator_cash_shift_close.html): четыре операции с
   ящиком — плитками в ряд, на телефоне два на два; подзаголовки разделов сводки закрытия смены */
.cash-kinds { display: grid; grid-template-columns: repeat(4, 1fr); gap: .5rem; }
.cash-kinds .btn { display: flex; flex-direction: column; align-items: center; gap: .25rem; padding: .5rem .25rem; font-size: .8125rem; }
.cash-kinds .btn .fas { font-size: 1rem; opacity: .75; }
.cash-kinds .btn.active { background: var(--freepos-primary); border-color: var(--freepos-primary); color: #fff; }
.cash-kinds .btn.active .fas { opacity: 1; }
@media (max-width: 420px) { .cash-kinds { grid-template-columns: repeat(2, 1fr); } }
.cash-section { font-size: .75rem; font-weight: 600; text-transform: uppercase; letter-spacing: .03em; color: var(--freepos-600); margin-bottom: .25rem; }
/* Строка формы операции: описание, сумма, кнопка; на узком экране описание встаёт строкой выше */
.cash-form-row { display: flex; flex-wrap: wrap; gap: .5rem; }
.cash-form-row [name="COMMENT_TEXT"] { flex: 1 1 14rem; }
.cash-form-row [name="AMOUNT"] { flex: 1 1 6.5rem; max-width: 9rem; }
.cash-form-row .btn { flex: 0 0 auto; }
/* «?» с подсказкой в кассе — как .dash-q в панели управления, но открывается касанием (initPosHints в
   extra.js): у сенсорного экрана нет наведения, а длинный текст под полем отнимает высоту окна */
.pos-q { display: inline-flex; align-items: center; justify-content: center; width: 1.1rem; height: 1.1rem; margin-left: .25rem; padding: 0; border: 0; border-radius: 50%; background: var(--freepos-200); color: var(--freepos-700); font-size: .7rem; font-weight: 600; line-height: 1; cursor: help; vertical-align: .1em; }
.pos-q:hover, .pos-q:focus-visible, .pos-q[aria-expanded="true"] { background: var(--freepos-primary); color: #fff; outline: none; }

/* Окно просмотра заказа (operator_order_view.html): лестница шагов горизонтально во всю ширину, под ней
   полоса агрегатора или службы доставки и две колонки фактов — «Гость» и «Заказ и оплата» */
.ov-steps { display: flex; margin: 4px 0 2px; }
.ov-step { flex: 1 1 0; min-width: 0; position: relative; text-align: center; padding: 0 2px; }
.ov-step-line { position: absolute; top: 15px; left: calc(-50% + 20px); right: calc(50% + 20px); border-top: 2px dashed var(--freepos-table-border-color); }
.ov-step-line.is-reached { border-top-color: var(--freepos-primary); }
.ov-step-dot { position: relative; display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; border-radius: 50%; }
.ov-step-paid { position: absolute; right: -6px; bottom: -4px; width: 16px; height: 16px; border-radius: 50%; display: flex; align-items: center; justify-content: center; border: 2px solid var(--freepos-card-bg, #fff); }
.ov-step-paid i { font-size: 8px; }
.ov-step-label { margin-top: 4px; font-size: .8125rem; line-height: 1.2; overflow-wrap: anywhere; }
.ov-step-time { font-size: .75rem; }
.ov-panel-title { font-size: .6875rem; text-transform: uppercase; letter-spacing: .06em; font-weight: 600; color: var(--freepos-500); border-bottom: 1px solid var(--freepos-border-color); padding-bottom: 4px; margin-bottom: 8px; }
.ov-panel-title--row { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
/* Заголовок панели набран прописными с разрядкой — значку гостя это ни к чему: он фраза, а не подпись */
.ov-panel-title .badge { text-transform: none; letter-spacing: normal; font-weight: 600; }
.ov-facts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 16px; }
.ov-facts > .ov-wide { grid-column: 1 / -1; }
.ov-ribbon { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; border-radius: .5rem; padding: 10px 12px; margin-bottom: 8px; }
.ov-ribbon--agg { background: rgba(var(--freepos-warning-rgb), .1); border: 1px solid rgba(var(--freepos-warning-rgb), .35); }
.ov-ribbon--svc { background: rgba(var(--freepos-info-rgb), .08); border: 1px solid rgba(var(--freepos-info-rgb), .3); }
.ov-ribbon-main { display: flex; align-items: center; gap: 10px; flex: 1 1 260px; min-width: 0; }
.ov-ribbon-icon { width: 32px; height: 32px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; background: var(--freepos-card-bg, #fff); flex-shrink: 0; }
.ov-ribbon-code { margin-left: auto; font-weight: 600; font-size: 1.25rem; letter-spacing: .06em; background: var(--freepos-card-bg, #fff); border-radius: .375rem; padding: 2px 10px; white-space: nowrap; }
.ov-ribbon-side { flex: 0 1 auto; }
.ov-ribbon-foot { flex: 1 1 100%; display: flex; flex-wrap: wrap; gap: 4px 16px; }
.ov-note { background: var(--freepos-100); border-radius: .375rem; padding: 8px 12px; }
@media (max-width: 575.98px) { .ov-step-label { font-size: .6875rem; } .ov-step-time { font-size: .625rem; } }
/* Фирменный значок площадки агрегатора у номера в списке заказов — на месте значка источника (.order-source) */
.agg-logo{display:inline-block;width:1rem;height:1rem;border-radius:.25rem;background:center/cover no-repeat;vertical-align:-.15em}.agg-logo--ye{background-image:url(/assets/img/agg/ye.png)}.agg-logo--dc{background-image:url(/assets/img/agg/dc.png)}.agg-logo--kuper{background-image:url(/assets/img/agg/kuper.png)}

/* «Показать гостю» в строке каталога: только пока экран гостя открыт (body.gs-live, initGuestScreenShow в extra.js) */
.gs-show-btn{display:none;padding:.15rem .55rem;margin-left:.5rem;border-radius:1rem;line-height:1;color:var(--freepos-600);background:var(--freepos-200)}
body.gs-live .gs-show-btn{display:inline-block}
.gs-show-btn:hover,.gs-show-btn.active{color:#fff;background:var(--freepos-primary)}

/* Экран блокировки кассы (#screenLock, screen-lock.js): выше любых окон и меню (меню заказа — 1085), тосты видны над ним, но не нажимаются */
.screen-lock{position:fixed;inset:0;z-index:2000;display:flex;align-items:center;justify-content:center;padding:16px;background:rgba(237,242,249,.82);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);overflow-y:auto}
.screen-lock__card{width:100%;max-width:340px;padding:24px 24px 20px;border-radius:1rem;background:#fff;box-shadow:0 20px 50px rgba(11,21,36,.16),0 0 0 1px rgba(11,21,36,.05);text-align:center}
.screen-lock__clock{font-size:2.6rem;font-weight:300;line-height:1;color:var(--freepos-900)}
.screen-lock__date{margin-top:4px;font-size:.83rem;color:var(--freepos-600)}
.screen-lock__who{display:flex;align-items:center;gap:12px;margin:18px 0 16px;padding:10px 12px;border-radius:.75rem;background:var(--freepos-100)}
.screen-lock__who .fw-semi-bold{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:210px}
.screen-lock__dots{display:flex;justify-content:center;gap:14px;height:16px}
.screen-lock__dots i{width:14px;height:14px;border-radius:50%;border:2px solid var(--freepos-400);transition:background-color .12s,border-color .12s}
.screen-lock__dots i.on{background:var(--freepos-primary);border-color:var(--freepos-primary)}
.screen-lock__dots.shake{animation:screenLockShake .4s}
@keyframes screenLockShake{20%,60%{transform:translateX(-8px)}40%,80%{transform:translateX(8px)}}
.screen-lock__msg{min-height:2.6em;margin:8px 0 4px;font-size:.8rem;line-height:1.3;color:var(--freepos-700);display:flex;align-items:center;justify-content:center}
.screen-lock__msg--error{color:var(--freepos-danger)}
.screen-lock__msg--ok{color:var(--freepos-success)}
.screen-lock__pad{display:grid;grid-template-columns:repeat(3,64px);justify-content:center;gap:12px 22px}
.screen-lock__key{width:64px;height:64px;border-radius:50%;border:1px solid var(--freepos-300);background:#fff;font-size:1.5rem;color:var(--freepos-900);line-height:1;transition:background-color .1s;touch-action:manipulation;-webkit-user-select:none;user-select:none}
.screen-lock__key:hover{background:var(--freepos-100)}
.screen-lock__key:active{background:var(--freepos-200)}
.screen-lock__key--aux{border-color:transparent;font-size:1.25rem;color:var(--freepos-600)}
.screen-lock__key--aux.active{color:#fff;background:var(--freepos-primary)}
.screen-lock__hint{margin-top:16px;font-size:.75rem;line-height:1.35;color:var(--freepos-600)}
body.screen-locked .toast-dock{z-index:2010!important;pointer-events:none}
body.screen-locked #sessionEndedToast{pointer-events:auto}
@media (max-height:640px){.screen-lock__clock{font-size:2rem}.screen-lock__who{margin:12px 0 10px}.screen-lock__key{width:56px;height:56px}.screen-lock__pad{grid-template-columns:repeat(3,56px)}}
