/* ═══════════════════════════════════════════════════════════
   Карточка брони — дело с закладками
   ═══════════════════════════════════════════════════════════
   Два блока не меняются при переключении разделов, потому что
   вопросов, которые задают всегда, тоже два: «кто и сколько
   должен» — светлая шапка, «когда» — тёмная лента под ней.
   Разделы за закладками отвечают на всё остальное и ничего
   из этих двух не повторяют.

   Тёмная лента здесь не приём ради приёма: бронь и есть
   отрезок времени, и рисовать его надо той же линейкой,
   что несёт шахматку. Она же даёт карточке второй уровень
   поверхности — без него окно было одной плоскостью.     */
.dlg.dlg-booking{
  /* Ширина приведена к содержанию, а не содержание растянуто по ширине:
     на восьмистах пикселях строки разъезжались, и справа у каждой
     оставалась треть пустоты. */
  width:min(716px,calc(100vw - 48px));max-height:min(88dvh,760px);position:fixed;
  --bs-menu:88px;
}

/* ── шапка ──
   Один блок с двумя строками, а не два блока со своими полями. Раньше
   имя, связь, лента и деньги стояли четырьмя полосами во всю ширину:
   перед содержанием было четыре этажа, и на коротком разделе они
   занимали больше половины карточки. */
/* Светлое здесь про человека, тёмное про время. Своей линии между ними
   не нужно: у ленты и так жёсткий край, и вторая черта рядом с ним —
   удвоенная граница. */
/* ── плита дела (SPEC §8.5) ──
   Голова карточки — один предмет, а не светлая шапка поверх тёмной
   ленты. Обе отвечают на один вопрос — кто это и когда, — и двумя
   поверхностями подряд читались двумя разными вещами. Материал общий
   с плитой картотеки: тот же лак, тот же свет, те же пигменты. */
.bs-plate{
  position:relative;isolation:isolate;flex-shrink:0;
  background:var(--band);color:var(--band-ink);
  box-shadow:inset 0 1px 0 rgb(255 255 255 / .07);
  /* Свет поднимает фон под текстом; вторичный тон здесь светлее ровно
     настолько, чтобы держать 4.5:1 в самой яркой точке (§8.3). */
  --band-ink-2:var(--plate-ink-2);
}
.bs-plate > :not(.plate-lite){position:relative;z-index:1}

/* ── как дело кладут на стол ──────────────────────────────────────────
   Три слоя, и каждый со своей задачей (SPEC §8.5).

   Среда: краски под лаком качнуло от толчка — они сжаты к центру и
   расходятся по очереди. `scale` отдельным свойством, потому что в
   `transform` уже сидит дрейф, а в `translate` — отклик на указатель.

   Свет: по лаку проходит блик — тот же, что при выдвижении карточки
   гостя, и по той же причине: предмет положили, и он поймал свет.

   Содержание: встаёт снизу ступенями. Снизу, а не слева, как в
   картотеке: там карточку выдвигают из ящика вбок, здесь дело кладут
   на стол — и оно оседает.

   Читать можно к 400 мс. Среда досаживается до 740, но её никто не
   ждёт: она ничего не сообщает. */
.bs-plate.fresh .orb{
  animation:gsDrift var(--t) cubic-bezier(.45,0,.55,1) infinite alternate,
    bsBloom .62s cubic-bezier(.16,.7,.2,1) both;
}
.bs-plate.fresh .red{animation-delay:0s, 0s}
.bs-plate.fresh .ochre{animation-delay:-12s, .06s}
.bs-plate.fresh .own{animation-delay:-21s, .11s}
@keyframes bsBloom{from{opacity:0;scale:.78}}

.bs-plate.fresh .bs-av,
.bs-plate.fresh .bs-name,
.bs-plate.fresh .bs-tags,
.bs-plate.fresh .bs-meta,
.bs-plate.fresh .bs-corner,
.bs-plate.fresh .bs-edge{animation:bsSettle .3s cubic-bezier(.2,.7,.2,1) both}
.bs-plate.fresh .bs-av{animation-delay:.06s}
.bs-plate.fresh .bs-name{animation-delay:.1s}
.bs-plate.fresh .bs-tags{animation-delay:.15s}
.bs-plate.fresh .bs-meta{animation-delay:.13s}
.bs-plate.fresh .bs-corner{animation-delay:.19s}
.bs-plate.fresh .bs-edge{animation-delay:.17s}
.bs-plate.fresh .bs-edge.end{animation-delay:.21s}
/* Деньги последними: они здесь итог, и приходят после того, как
   названо, кто и когда. */
.bs-plate.fresh .bs-edge.bill{animation-delay:.3s}
@keyframes bsSettle{from{opacity:0;transform:translate3d(0,8px,0)}}

/* Главное движение: лента отмеряет срок слева направо. Это не украшение —
   она в буквальном смысле измеряет бронь, и смотреть, как она набирает
   длину, значит увидеть, сколько человек стоит. Отсюда и её право быть
   самым долгим движением на плите. */
.bs-plate.fresh .bs-band{
  animation:bsMeasure .52s cubic-bezier(.16,.7,.2,1) both;animation-delay:.18s;
}
@keyframes bsMeasure{from{clip-path:inset(0 100% 0 0)}to{clip-path:inset(0)}}
.bs-plate.fresh .bs-under{animation:bsSettle .3s cubic-bezier(.2,.7,.2,1) both .32s}
/* Красная риска «сейчас» встаёт последней: она и есть та секунда,
   ради которой на ленту смотрят. */
.bs-plate.fresh .bs-now{animation:bsTick .26s cubic-bezier(.2,.7,.2,1) both .62s}
@keyframes bsTick{from{opacity:0;transform:scaleY(.3)}}

@media (prefers-reduced-motion:reduce){
  .bs-plate.fresh .orb,.bs-plate.fresh .bs-av,.bs-plate.fresh .bs-name,
  .bs-plate.fresh .bs-tags,.bs-plate.fresh .bs-meta,.bs-plate.fresh .bs-corner,
  .bs-plate.fresh .bs-edge,.bs-plate.fresh .bs-band,.bs-plate.fresh .bs-under,
  .bs-plate.fresh .bs-now,.bs-plate.fresh .sheen{animation:none}
}
/* Плита дела широкая и низкая, плита картотеки — высокая. Пятна
   размечены от её середины, иначе на ста семидесяти пикселях от них
   видна одна кромка. */
.bs-plate{
  --o1x:12%; --o1y:-180%;
  --o2x:70%; --o2y:-205%;
  --o3x:-6%; --o3y:-120%;
}
/* На живом фоне третья ступень серого не выживает: пятна поднимают
   подложку, и `--band-ink-3` уходил под порог на подписях 8.5–10.5 px
   («выезд», «оплачено», код, длительность). Ступеней на плите поэтому
   две, а не три — разница между ними держится размером и разрядкой,
   а не светлотой. */
.bs-plate{--band-ink-3:var(--plate-ink-3)}
/* Подписи под лентой — самый мелкий кегль на плите (9–9.5 px), и они
   же стоят там, где фон ярче всего. Тон у них полный: иерархию здесь
   держит размер, а не светлота, и 9 px бледнее 19 px не читается
   вторичным — оно просто не читается. */
.bs-plate .bs-span,
.bs-plate .bs-place u{color:var(--band-ink)}
/* Шеврон при имени — знак перехода, и читать его надо так же уверенно,
   как имя рядом. */
.bs-plate .bs-name i{color:var(--band-ink-2)}

/* Чернила плиты. Всё, что было набрано по бумаге, переводится на
   светлое: имя, связь, код, крестик. Иерархия та же, что была, —
   меняется только основа. */
.bs-plate .bs-name{color:var(--band-ink)}
@media (hover:hover) and (pointer:fine){
  .bs-plate .bs-name:hover{color:var(--plate-hi)}
}
.bs-plate .bs-meta,
.bs-plate .bs-meta span{color:var(--band-ink-2)}
.bs-plate .bs-tel{color:var(--band-ink-2)}
@media (hover:hover) and (pointer:fine){
  .bs-plate .bs-tel:hover{color:var(--band-ink)}
}
.bs-plate .bs-icon{color:var(--band-ink-2);border-color:rgb(237 234 227 / .18)}
@media (hover:hover) and (pointer:fine){
  .bs-plate .bs-icon:hover{color:var(--band-ink);background:rgb(237 234 227 / .1)}
}
.bs-plate .bs-code{color:var(--band-ink-3)}
@media (hover:hover) and (pointer:fine){
  .bs-plate .bs-code:hover{color:var(--band-ink);border-color:rgb(237 234 227 / .22)}
}
.bs-plate .sh-close{color:var(--band-ink-3)}
@media (hover:hover) and (pointer:fine){
  .bs-plate .sh-close:hover{background:rgb(237 234 227 / .12);color:var(--band-ink)}
}

.bs-head{
  /* Три колонки, а не поток: знак, содержание и правый край. Правый
     край при этом одна вертикаль на обе строки — раньше крестик, значки
     связи и код стояли на трёх разных, и край шапки был рваным. */
  display:grid;grid-template-columns:auto minmax(0,1fr) auto;
  align-items:center;gap:0 14px;padding:16px 16px 14px 20px;flex-shrink:0;
}
.bs-who{flex:1;min-width:0}
/* Кружок держит обе строки шапки — имя и справку под ним, — поэтому он
   крупный и стоит слева от них, а не втиснут в строку имени. Инициалы
   плотные и без разрядки: в круге они читаются как знак, а не как обрывок слова. */
/* Знак человека: тот же, что в картотеке, — скруглённый квадрат со
   своим цветом. На тёмной плите он единственное цветное пятно слева
   и опознаёт всю голову целиком. Круг среди прямых линий читался
   пузырём мессенджера. */
.bs-av{
  display:flex;align-items:center;justify-content:center;flex-shrink:0;
  width:40px;height:40px;border-radius:var(--r-mark);align-self:center;
  background:var(--av,var(--band-3));color:var(--av-ink);
  box-shadow:inset 0 0 0 1px rgb(255 255 255 / .16), 0 2px 7px rgb(0 0 0 / .3);
  font-size:13px;font-weight:600;letter-spacing:.02em;
}
.bs-av.shut{background:var(--band-3);color:var(--band-ink-2);box-shadow:none}
/* У блокировки гостя нет: «Ремонт печи» дал бы инициалы «РП» и читался
   бы человеком. Вместо букв — замок, и круг тише. */
.bs-av.shut{background:var(--sunk);color:var(--ink-3)}
.bs-line{display:flex;align-items:center;gap:10px}
.bs-line .sh-close{margin-left:auto}
/* Имя ведёт к карточке гостя: нажал на человека — попал к человеку.
   Отдельная кнопка «Карточка гостя» для этого больше не нужна, а была
   она четвёртой в ряду и по виду не отличалась от способов связи. */
.bs-name>span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.bs-name{
  /* Имя не растягивается на всю строку: состояние должно стоять при нём,
     а не у края окна — оно про эту бронь, а не про окно. */
  display:flex;align-items:baseline;gap:4px;flex:0 1 auto;min-width:0;
  font-size:19px;font-weight:600;letter-spacing:-.035em;line-height:1.15;
  color:var(--ink);text-align:left;border-radius:var(--r-xs);
  transition:color .13s;
}
.bs-name i{
  font-style:normal;font-size:16px;color:var(--ink-3);
  opacity:0;transform:translateX(-3px);
  transition:opacity .13s, transform .13s cubic-bezier(.2,.8,.3,1);
}
/* Шеврон выходит под курсором: в покое имя остаётся именем, а не
   выглядит ссылкой посреди шапки. */
.bs-name:hover i,.bs-name:focus-visible i{opacity:1;transform:none}
@media (hover:hover) and (pointer:fine){
  .bs-name:hover{color:var(--accent-2)}
}
.bs-name:focus-visible{outline:2px solid var(--ink);outline-offset:3px}
.bs-line>b{
  flex:1;min-width:0;font-size:19px;font-weight:600;letter-spacing:-.035em;
  line-height:1.15;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
/* Состояние — точка и слово в тоне, без плашки: круглая плашка спорила
   с прямыми линиями шахматки, а цвет и так принадлежит статусу. */
/* Состояние — один из двух главных фактов о броне (второй деньги), и
   стоять ему рядом с именем, а не шёпотом в углу окна. */
/* Точка и слово, без плашки: цвет в этом продукте — пигмент статуса,
   а не залитая таблетка. Выигрыш здесь в месте — состояние стоит при
   имени, — а не в заливке. */
/* ── метки гостя в шапке (SPEC §4.7) ──
   Стоят там, где раньше была надпись состояния: состояние повторяло
   деньги на ленте, а метка не сказана больше нигде. Окно выбора то же,
   что в картотеке, поэтому позиционируется от этой строки. */
/* Метки стоят встык к имени, а не у края окна: они про этого человека,
   как и имя. `margin-left:auto` здесь делил свободное место с крестиком,
   и наклейки уезжали в другой конец строки — от имени они отрывались, а
   к крестику не относились.

   Имя ужимается первым: наклейка короткая и обрезать её нечего, а
   фамилия обрежется многоточием и останется читаемой. */
.bs-tags{
  position:relative;display:flex;align-items:center;
  gap:5px;flex-shrink:0;max-width:52%;
}
.bs-tags .gs-tag{
  max-width:118px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  display:block;line-height:21px;
}

.bs-state-tag{
  display:flex;align-items:center;gap:6px;flex-shrink:0;
  font-size:11px;font-weight:500;color:var(--tone);white-space:nowrap;
}
.bs-state-tag i{
  width:6px;height:6px;border-radius:50%;background:var(--tone);flex-shrink:0;position:relative;
}
.bs-state-tag.ok{--tone:var(--ok)}
.bs-state-tag.wait{--tone:var(--wait)}
.bs-state-tag.late{--tone:var(--late)}
.bs-state-tag.stop{--tone:var(--stop)}

/* Вторая строка: слева сведения о госте, справа два действия. Телефон
   стоит здесь текстом — его читают вслух, а не нажимают, — но остаётся
   ссылкой: по нему по-прежнему звонят. */
.bs-meta{display:flex;align-items:center;gap:10px;margin-top:6px}
/* Код читают, когда о нём спросили: место ему с краю и моноширинным.
   В общей строке через точку он весил столько же, сколько имя гостя. */
/* ── правый край ──
   Крестик и код — одна колонка: сверху выход, под ним справка. Код
   читают, когда о нём спросили, и висеть ему у самого края. */
.bs-corner{
  display:flex;flex-direction:column;align-items:flex-end;gap:9px;align-self:center;
}
/* Код — то, что берут в руки: им называют бронь в письме поддержке. Он
   кнопка, а не подпись: выделять мышью мелкий моноширинный текст, попадая
   между дефисами, — работа, которой быть не должно.

   Тихим он остаётся за счёт кегля и рамки, а не за счёт бледности: на
   прозрачности .65 контраст падал до 1,98 при нужных 4,5 (WCAG AA для
   мелкого текста). Проверено расчётом. */
.bs-code{
  display:flex;align-items:center;gap:5px;
  padding:4px 7px;margin:-4px -7px -4px 0;border-radius:var(--r-sm);
  border:1px solid transparent;background:none;
  font-family:var(--mono);font-size:10.5px;letter-spacing:-.01em;
  color:var(--ink-2);white-space:nowrap;transition:var(--t-tap) var(--ease);transition-property:color,background-color,border-color,transform;
}
.bs-code i{display:flex;color:var(--ink-3);opacity:0;transition:opacity .13s var(--ease)}
@media (hover:hover) and (pointer:fine){
  .bs-code:hover{border-color:var(--rule);background:var(--card);color:var(--ink)}
}
.bs-code:hover i{opacity:1}
.bs-code:active{transform:scale(.97)}
.bs-code:focus-visible{outline:2px solid var(--ink);outline-offset:1px}
/* Скопировано — знак сменился на галку, и он же объясняет, что произошло.
   Отдельного сообщения для этого не нужно: ответ стоит там, где нажали. */
.bs-code.done{border-color:var(--ok-line);background:var(--ok-bg);color:var(--ok)}
.bs-code.done i{opacity:1;color:var(--ok)}
@media (prefers-reduced-motion:reduce){
  .bs-code{transition:none} .bs-code:active{transform:none}
}
.bs-meta>span{
  min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  font-size:11.5px;color:var(--ink-2);
}
.bs-tel{
  font-size:12px;letter-spacing:0;
  color:var(--ink-2);text-decoration:none;
  border-bottom:1px solid transparent;transition:var(--t-tap) var(--ease);transition-property:color,border-color;
}
@media (hover:hover) and (pointer:fine){
  .bs-tel:hover{color:var(--ink);border-bottom-color:var(--rule)}
}

/* Действия — два знака без подписей. Рамка вокруг них весила больше,
   чем строка сведений, к которой они относятся: в покое это текстовая
   строка, и знаки в ней должны быть такими же тихими. Подложка приходит
   под курсором — тогда, когда до них тянутся. */
.bs-links{
  /* Значки идут сразу за строкой, к которой относятся, а не к правому
     краю: прижатые к краю, они заводили вторую правую кромку в шестидесяти
     пикселях от колонки с кодом. */
  display:flex;gap:6px;flex-shrink:0;
}
.bs-icon{
  display:flex;align-items:center;justify-content:center;
  /* 26 px — над порогом WCAG 2.5.8 (24×24 для веба), и между знаками
     остаётся зазор: вплотную поставленные цели промахиваются. */
  width:26px;height:26px;border-radius:var(--r-sm);
  background:none;color:var(--ink-2);
  transition:var(--t-tap) var(--ease);transition-property:color,background-color,border-color,transform;
}
@media (hover:hover) and (pointer:fine){
  .bs-icon:hover{background:var(--sunk);color:var(--ink)}
}
.bs-icon:active{transform:scale(.94)}
.bs-icon:focus-visible{outline:2px solid var(--ink);outline-offset:1px}

/* ── лента брони ──
   Та же линейка, что несёт шахматку: пройденное залито, уборка
   штриховкой, «сейчас» — тонкая красная черта. */
/* Второй ярус плиты: измеренное. От первого его отделяет волосяная
   черта, а не смена поверхности — предмет остаётся один. */
.bs-rail{
  display:flex;align-items:center;gap:18px;flex-shrink:0;
  padding:15px 20px 16px;border-top:1px solid rgb(237 234 227 / .1);
}
.bs-edge{flex-shrink:0}
.bs-edge.end{text-align:right}
.bs-edge em{
  display:block;font-size:11px;font-style:normal;font-weight:500;
  color:var(--band-ink-3);
}
.bs-edge b{
  display:block;margin-top:4px;font-size:19px;font-weight:600;
  letter-spacing:-.02em;line-height:1;color:var(--band-ink);font-variant-numeric:tabular-nums;
}
.bs-edge span{display:block;margin-top:4px;font-size:11px;color:var(--band-ink-2);white-space:nowrap}

.bs-track{flex:1;min-width:0}
.bs-band{
  position:relative;height:12px;border-radius:var(--r-xs);overflow:hidden;
  background:var(--band-3);
}
.bs-band i{position:absolute;top:0;bottom:0}
/* Занятое — светлая заливка на тёмном: на приборной полосе прибор
   светится, а не темнеет. */
.bs-stay{left:0;right:var(--buf,0%);background:var(--band-ink-2)}
.bs-tick{left:var(--at);width:1px;background:rgba(var(--ink-rgb),.35);z-index:1}
.bs-buf{
  right:0;width:var(--buf,0%);z-index:2;
  background:repeating-linear-gradient(45deg,var(--band-ink-3) 0 1.5px,transparent 1.5px 5px);
  opacity:.55;
}
.bs-now{left:var(--at);width:2px;margin-left:-1px;background:var(--now);z-index:2}

/* ── лента снимает показание ──
   Прибор не возникает готовым, а отмеряет отрезок слева направо: сперва
   протяжённость брони, следом уборка после выезда, и только потом на
   шкалу опускается стрелка «сейчас». Порядок не декоративный — он тот
   же, в котором эти события идут во времени.

   Двигаются transform и opacity, ширина не трогается: она заставила бы
   пересчитывать раскладку в каждом кадре. Вся сцена укладывается в
   520 мс — ровно столько же длится перегон кривой в шапке, и два прибора
   продукта отвечают одинаково. */
.bs-band{--e:cubic-bezier(.2,.8,.3,1)}
@keyframes bs-draw{from{transform:scaleX(0)}}
@keyframes bs-hatch{from{opacity:0;transform:scaleX(0)}}
@keyframes bs-needle{from{opacity:0;transform:scaleY(.35)}}
/* Идущая бронь дышит стрелкой: время в ней и правда идёт, и полоса
   этим отличается от той, что просто показывает прошлое. Период 2,4 с —
   вне того медленного диапазона, от которого укачивает. */

.bs-stay,.bs-past,.bs-buf{transform-origin:left center}
.bs-stay{animation:bs-draw .36s var(--e) both}
.bs-past{
  left:0;width:var(--past,0%);background:var(--band-ink);z-index:1;
  animation:bs-draw .28s var(--e) both .2s;
}
.bs-buf{animation:bs-hatch .22s var(--e) both .24s}
.bs-now{
  transform-origin:center;
  /* Встаёт последней и стоит: мигание было вторым движением карточки, а
     §8.5 оставляет ей одно — ленту, отмеряющую срок. */
  animation:bs-needle .18s var(--e) both .34s;
}

/* Сокращённое движение — не «никакого»: отрезок всё равно должен
   появиться заметно, иначе непонятно, отрисовался прибор или нет. */
@media (prefers-reduced-motion:reduce){
  .bs-stay,.bs-past,.bs-buf,.bs-now{animation:bs-hatch .16s ease both;transform:none}
  .bs-now{animation:bs-hatch .16s ease both}
}
/* Под полосой — что забронировано и на сколько. Объекта в шапке не было
   вовсе: карточка говорила, кто и когда, но не что, и на вопрос «в каком
   доме Волков» приходилось листать ниже. */
.bs-under{display:flex;align-items:center;gap:12px;margin-top:9px}
.bs-place{display:flex;align-items:center;gap:7px;min-width:0}
.bs-place .ricon{width:14px;height:14px;display:flex;color:var(--band-ink-3);flex-shrink:0}
.bs-place .ricon svg{width:14px;height:14px}
.bs-place b{
  font-size:12px;font-weight:600;letter-spacing:-.02em;color:var(--band-ink);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
/* Пакет назван числом: четыре имени сюда не влезут, а список их есть
   отдельным разделом. */
.bs-place u{
  text-decoration:none;flex-shrink:0;padding:1.5px 6px;border-radius:var(--r-pill);
  background:rgba(255,255,255,.09);
  font-size:9.5px;letter-spacing:0;color:var(--band-ink-2);
}
.bs-span{
  margin-left:auto;flex-shrink:0;font-size:11px;
  color:var(--band-ink-3);
}

/* Колонка зовётся `bill`, а не `money`: класс `money` в продукте уже
   занят блоком сумм в модальных окнах, и колонка забирала себе его
   светлую плашку прямо на тёмной ленте.

   Деньги — последняя колонка ленты, а не своя полоса под ней: обе
   величины отвечают «сколько», обе нужны в любом разделе, и держать их
   двумя полосами подряд значило тратить на постоянное вдвое больше
   места. На тёмном цвет берётся осветлённый: статусные тона палитры
   рассчитаны на бумагу и в чернилах читаются грязью. */
.bs-edge.bill{padding-left:18px;border-left:1px solid rgba(237,234,227,.14);text-align:right}
.bs-edge.bill b{color:var(--tone)}
.bs-edge.bill.settled{--tone:var(--plate-ok)}
.bs-edge.bill.ok{--tone:var(--plate-ok)}
.bs-edge.bill.wait{--tone:var(--plate-wait)}
.bs-edge.bill.late{--tone:var(--plate-late)}
.bs-edge.bill.stop{--tone:var(--band-ink-2)}

/* ── тело: закладки и документ ── */
.bs-body{display:grid;grid-template-columns:var(--bs-menu) 1fr;flex:1;min-height:0}
.bs-menu{
  position:relative;padding:12px 7px;
  border-right:1px solid var(--rule);background:var(--paper);overflow-y:auto;
}
/* Закладки и плашка живут в своей коробке ростом ровно в них: нижний
   край плашки отмеряется от низа этой коробки, а колонка меню тянется
   во всю высоту карточки и меняет её вместе с разделом. */
.bs-menu-in{position:relative;display:flex;flex-direction:column;gap:3px}
/* Одна плашка на всё меню: она переезжает к выбранному разделу, а не
   гаснет в одном месте и загорается в другом. Глаз идёт за ней и
   понимает, что это тот же экран сменил раздел. */
.bs-mark{
  /* Едет плашка не переносом, а двумя краями — `top` и `bottom`, — и
     края эти движутся с разной скоростью. Передний уходит первым, задний
     догоняет: на переезде плашка вытягивается в сторону цели и там
     собирается обратно. Это и есть подсказка направления — по первым
     же кадрам видно, куда всё едет, ещё до того, как оно приехало.
     Одним переносом такого не сделать: он двигает оба края разом.

     Раскладку это не трогает — плашка вынута из потока и детей у неё
     нет, так что пересчёт касается её одной.

     Лежит она поверх закладок, а не под ними: светлая копия внутри неё
     должна закрывать настоящую подпись — иначе тёмная подпись остаётся
     видна на тёмной плашке (2,0:1, то же самое, с чего всё начиналось,
     только наоборот). Закладки никуда не деваются: там, где плашки нет,
     видны они.

     Начальные `top:0;height:0` — состояние до замера: пока скрипт не
     нашёл выбранную закладку, плашки нет вовсе, и раздел рисует
     выбранным сама закладка. */
  position:absolute;left:0;right:0;top:0;height:0;opacity:0;z-index:2;
  border-radius:var(--r);background:var(--accent);pointer-events:none;
  transition-property:top,bottom,opacity,transform;
  transition-duration:var(--t-move),var(--t-move),var(--t-move),var(--t-tap);
  transition-timing-function:var(--ease);
}
/* Замеренная плашка живёт двумя краями, а не высотой. */
.bs-menu.has-mark .bs-mark{height:auto;opacity:1}

/* Светлая копия колонки под плашкой.
   Плашка обрезает её собой (`overflow:hidden`), и подпись становится
   светлой ровно там, где её накрыл край, — по пикселю, а не по таймеру.
   Копия смещается против хода плашки теми же длительностями, поэтому в
   колонке она стоит неподвижно. */
.bs-mark{overflow:hidden}
.bs-lit{
  position:absolute;left:0;top:0;
  display:flex;flex-direction:column;gap:3px;
  transition:top var(--t-move) var(--ease);
}
.bs-lit .bs-tab{color:var(--accent-ink);background:none}
.bs-lit .bs-tab i{color:var(--accent-ink);opacity:1}
.bs-lit .bs-tab s{color:var(--accent-ink);opacity:.8}
/* Плашка отрывается от бумаги на время переезда и садится обратно.
   Тень здесь не украшение, а причина: неподвижное лежит, движущееся
   приподнято — и по одной этой тени видно, что переезд ещё идёт.
   Тень вынесена в `filter`, потому что `box-shadow` у плашки занят
   кольцом фокуса, а совпасть эти два состояния могут. */
.bs-menu.moving .bs-mark{filter:drop-shadow(0 5px 12px rgba(25,24,21,.16))}
/* Нажатие на выбранный раздел чувствует плашка: сама закладка лежит
   под ней, и её собственное «вдавливание» не видно. */
.bs-menu-in:has(>.bs-tab.on:active) .bs-mark{transform:scale(.97)}
/* Кольцо фокуса выбранной закладки рисует плашка: сама закладка лежит
   под ней, и её кольцо было бы наполовину закрыто. */
.bs-menu-in:has(>.bs-tab.on:focus-visible) .bs-mark{
  box-shadow:inset 0 0 0 2px var(--accent-ink);
}
.bs-tab{z-index:1}
/* Пока плашка не измерена, выбранную закладку рисует она сама: без
   скриптов раздел всё равно должен быть виден выбранным. Как только
   плашка измерена, настоящая закладка перестаёт краситься совсем —
   и подложку, и светлый цвет за неё берёт на себя копия под плашкой. */
.bs-menu.has-mark .bs-menu-in>.bs-tab.on{background:none;color:var(--ink-2)}
.bs-menu.has-mark .bs-menu-in>.bs-tab.on i{color:var(--ink-2);opacity:.75}
.bs-menu.has-mark .bs-menu-in>.bs-tab.on s{color:var(--ink-2)}
/* Колонка шириной в один значок: подпись стоит под ним, а не рядом.
   Так меню занимает семьдесят восемь пикселей вместо ста пятидесяти,
   и всё освободившееся уходит разделу — ради него карточку и открыли. */
.bs-tab{
  position:relative;display:flex;flex-direction:column;align-items:center;gap:6px;
  padding:11px 4px 10px;border-radius:var(--r);
  /* Десять пикселей — ниже собственной шкалы продукта: всё остальное
     второстепенное в нём набрано одиннадцатью-двенадцатью, и меню
     выпадало из неё вниз, оттого и казалось мелким. */
  font-size:11.5px;font-weight:500;letter-spacing:-.01em;color:var(--ink-2);
  transition:background-color var(--t-tap) var(--ease),color var(--t-tap) var(--ease);
}

/* Значок был --ink-3 на бумаге: 2,6:1 при норме 3,0 для значимой
   графики (WCAG 1.4.11) — то есть бледнее допустимого. */
.bs-tab i{display:flex;color:var(--ink-2);opacity:.75;
  transition:opacity var(--t-tap) var(--ease),color var(--t-tap) var(--ease)}
.bs-tab span{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* Счётчик — в углу значка, а не в строке: строки под значком нет. */
/* Счётчик — сколько всего внутри раздела. Подложка ему не нужна: на
   бумажной колонке она либо неотличима от неё (--sunk давал ровно это),
   либо превращает тихий столбец в пять белых пилюль. Нужен контраст —
   он и был проблемой: --ink-3 давал 2,6:1. */
.bs-tab s{
  position:absolute;top:8px;right:10px;transition:color var(--t-tap) var(--ease);
  font-size:10.5px;text-decoration:none;color:var(--ink-2);
  font-variant-numeric:tabular-nums;
}
@media (hover:hover) and (pointer:fine){
  .bs-tab:hover{background:var(--sunk);color:var(--ink)}
}
.bs-tab:hover i{opacity:1;color:var(--ink)}
.bs-tab:active{transform:scale(.97)}
.bs-tab.on{background:var(--accent);color:var(--accent-ink);font-weight:550}
.bs-tab.on i{color:var(--accent-ink);opacity:1}
.bs-tab.on s{color:var(--accent-ink);opacity:.8}
.bs-tab:focus-visible{outline:2px solid var(--ink);outline-offset:-2px}

/* Нижняя граница области раздела: без неё карточка меняла высоту на
   двести с лишним пикселей при каждом переключении закладки — окно
   дёргалось под курсором. Предсказуемый размер важнее подогнанного:
   короткий раздел живёт с воздухом, длинный по-прежнему прокручивается. */
.bs-page{padding:17px 22px 20px;overflow-y:auto;min-height:498px}
/* Раздел приходит туда же, куда уехала плашка: вниз по меню — снизу,
   вверх по меню — сверху. Направление берётся у плашки (`--in`), и
   поэтому переключение читается одним движением, а не двумя разными.

   Уходящий раздел не провожают: содержимое подменяется сразу по
   нажатию. Проводы стоили бы полторы десятых секунды задержки на
   каждом переключении, а платить задержкой за красоту ухода нельзя —
   отклик важнее.

   Едет не сама страница, а её блоки, по очереди: страница целиком
   двинулась бы одним полотном, и переключение выглядело бы как смена
   окна, а не как смена раздела в том же окне. Когда раздел — один
   список, очередь идёт по строкам списка (`:only-child`). */
.bs-page.is-in>*,
.bs-page.is-in>:only-child>*{
  animation:bsRise var(--t-page) var(--ease) both;
  animation-delay:var(--d,0ms);
}
.bs-page.is-in>:only-child{animation:none}
@keyframes bsRise{from{opacity:0;transform:translateY(calc(var(--in,1) * 9px))}}
.bs-sec+.bs-sec{margin-top:18px}
.bs-sec h3{
  display:flex;align-items:center;gap:9px;margin-bottom:10px;
  font-size:11px;font-weight:500;
  color:var(--ink-3);
}
.bs-sec h3::after{content:"";flex:1;height:1px;background:var(--rule-2)}
.bs-empty{
  padding:13px 15px;border:1px dashed var(--rule);border-radius:var(--r);
  font-size:11.5px;line-height:1.5;color:var(--ink-3);
}
.bs-hint{
  padding:11px 13px;border:1px dashed var(--rule);border-radius:var(--r);
  font-size:11.5px;line-height:1.45;color:var(--ink-3);
}

/* ── что сделать ──
   Дела стоят первыми и собраны из тех же данных, что лежат в «Деньгах»
   и «Документах»: чтобы понять «можно ли заселять», больше не нужно
   обходить три раздела.

   Кромка плашки — самое срочное из списка. Она красит не каждое дело, а
   весь наряд: спрашивают «всё ли готово», а не «сколько дел жёлтых». */
.bs-jobs{
  border:1px solid var(--rule-2);border-radius:var(--r);background:var(--card);
  box-shadow:inset 3px 0 0 var(--edge,var(--rule));overflow:hidden;
}
.bs-jobs.wait{--edge:var(--wait)}
.bs-jobs.late{--edge:var(--late)}

.bs-job{
  display:grid;grid-template-columns:18px 1fr auto auto;align-items:center;gap:9px;
  width:100%;padding:10px 12px 10px 13px;text-align:left;
  border-bottom:1px solid var(--rule-2);transition:background-color .12s var(--ease);
}
.bs-job:last-child{border-bottom:none}
/* Дело со своим местом ведёт туда: прочитать «договор не создан» и потом
   искать раздел руками — работа, которую экран делает сам. */
button.bs-job{cursor:pointer}
@media (hover:hover) and (pointer:fine){
  button.bs-job:hover{background:var(--paper)}
}
button.bs-job:active{background:var(--sunk)}
button.bs-job:focus-visible{outline:2px solid var(--ink);outline-offset:-2px}
button.bs-job>svg:last-child{color:var(--rule);transition:transform .16s var(--ease),color .12s}
@media (hover:hover) and (pointer:fine){
  button.bs-job:hover>svg:last-child{color:var(--ink-3);transform:translateX(2px)}
}

/* Знак дела: у подготовки — значок услуги, тот же, что на шахматке;
   у остальных — точка. Цвет несёт срочность, а не род дела. */
.bs-job>i{
  display:flex;align-items:center;justify-content:center;
  width:18px;height:18px;color:var(--tone,var(--ink-3));
}
.bs-job>i:empty::before{
  content:"";width:7px;height:7px;border-radius:50%;background:var(--tone,var(--ink-3));
}
.bs-job.wait{--tone:var(--wait)}
.bs-job.late{--tone:var(--late)}
.bs-job.ok{--tone:var(--ok)}
.bs-job.stop{--tone:var(--stop)}
.bs-job>b{font-size:12.5px;font-weight:550;letter-spacing:-.01em;color:var(--ink)}
.bs-job>u{
  text-decoration:none;font-size:11px;letter-spacing:0;
  color:var(--ink-2);white-space:nowrap;
}
.bs-job.late>u{color:var(--late)}
.bs-job.wait>u{color:var(--wait)}

/* Делать нечего — тоже ответ, но не награда: зелёная плашка во всю
   ширину кричала об этом громче, чем сами дела. */
.bs-done{
  display:flex;align-items:center;gap:8px;padding:2px 1px;
  font-size:11.5px;color:var(--ink-2);
}
.bs-done svg{flex-shrink:0;color:var(--ok)}

/* ── бланк визита ──
   Слева спрошено, справа отвечено. Крупные числа-плашки («4 гостя»,
   «1 объект») отсюда убраны: такой кегль обещает величину, за которой
   следят, а это поля бланка — и в бланке они читаются быстрее.

   Сюда идёт только то, чего нет в шапке: даты, объект и деньги там уже
   стоят, и повторять их значит заставлять читать одно и то же дважды. */
.bs-form{
  border:1px solid var(--rule-2);border-radius:var(--r);background:var(--card);
  overflow:hidden;
}
.bs-form>div{
  display:grid;grid-template-columns:104px 1fr;align-items:baseline;gap:12px;
  padding:9px 13px;border-bottom:1px solid var(--rule-2);
}
.bs-form>div:last-child{border-bottom:none}
/* Подпись поля — обычный текст, а не тихая сноска: на --ink-3 она даёт
   3,1:1 при норме 4,5, и «Откуда бронь» приходится разбирать. */
.bs-form dt{font-size:11.5px;color:var(--ink-2)}
.bs-form dd{font-size:12.5px;font-weight:500;letter-spacing:-.01em;color:var(--ink)}
/* Гость на объекте прямо сейчас — тем же зелёным, что и метка в шапке;
   уехавший гладко гаснет: это уже прошлое, а не состояние. */
.bs-form dd.live{color:var(--ok)}
.bs-form dd.past{color:var(--ink-3)}
/* Заметка — не поле справочника, а то, что о госте сказали словами:
   «просят баню к 18:00» решает вечер. Своя бумага, чтобы не потерялась
   среди «4 гостя», — но не цветом и не заливкой: янтарный в наборе
   значит «ждёт оплату» (§8.3), а коробка на разлинованном листе это
   вторая форма поверх первой. Черта вдоль текста говорит то же и
   ничего не перекрывает. */
.bs-form .note dd{padding-left:13px;box-shadow:inset 1px 0 0 var(--rule)}
.bs-form .note dd{font-weight:400;line-height:1.45}

/* ── строки списков ──
   Одна форма на объекты, товары и документы: знак, имя с пояснением,
   и то, что справа — состояние или сумма. */
.bs-rows{border:1px solid var(--rule);border-radius:var(--r);overflow:hidden;background:var(--card)}
.bs-row{display:flex;align-items:center;gap:11px;padding:10px 13px}
.bs-row+.bs-row{border-top:1px solid var(--rule-2)}
.bs-row>i{
  display:flex;align-items:center;justify-content:center;width:28px;height:28px;flex-shrink:0;
  border-radius:var(--r-sm);background:var(--sunk);color:var(--ink-2);
}
.bs-row>i .ricon{display:flex;width:15px;height:15px}
.bs-row>i .ricon svg{width:100%;height:100%}
.bs-row>span{
  flex:1;min-width:0;font-size:12.5px;font-weight:550;letter-spacing:-.015em;color:var(--ink);
}
.bs-row>span u{
  display:block;margin-top:2px;font-size:10.5px;font-weight:400;
  letter-spacing:0;color:var(--ink-3);text-decoration:none;
}
.bs-row>b{
  font-size:12.5px;font-weight:500;letter-spacing:-.01em;
  color:var(--ink);font-variant-numeric:tabular-nums;white-space:nowrap;
}
/* Метка объекта стоит при его имени, а не у правого края карточки: там
   она отрывалась от названия на полкарточки и читалась отдельной
   колонкой неизвестно о чём. */
.bs-row>span s{
  margin-left:9px;font-size:11px;font-weight:500;
  color:var(--ink-3);
  text-decoration:none;white-space:nowrap;
}
.bs-state{
  font-size:11px;font-style:normal;white-space:nowrap;
  padding:3px 9px;border-radius:var(--r-sm);
}
.bs-state.ok{background:var(--ok-bg);color:var(--ok)}
.bs-state.wait{background:var(--wait-bg);color:var(--wait)}
.bs-state.none{background:var(--sunk);color:var(--ink-3)}

/* ── документы брони: опись ──
   Строка выпущенного — кнопка: открывает лист на столе. Состояние тем же
   ярлыком тона, что у всей карточки; аннулированный — серый и зачёркнутый,
   расхождение с бронью — знаком и словами под номером, а не кромкой. */
.bs-state.late{background:var(--late-bg);color:var(--late)}
.bs-state.plain,.bs-state.void{background:var(--sunk);color:var(--ink-3)}
button.bs-row{width:100%;text-align:left;transition:background-color var(--t-tap) var(--ease)}
@media (hover:hover) and (pointer:fine){
  button.bs-row:hover{background:var(--paper)}
}
button.bs-row:focus-visible{outline:2px solid var(--ink);outline-offset:-2px}
.bs-doc.void>span{color:var(--ink-3);text-decoration:line-through;text-decoration-color:var(--ink-3)}
.bs-doc.void>span u{text-decoration:none}
.bs-drift{
  display:flex;gap:6px;align-items:flex-start;margin-top:4px;
  font-size:11px;font-style:normal;font-weight:400;letter-spacing:0;line-height:1.35;color:var(--wait);
}
.bs-drift::before{
  content:"";width:12px;height:12px;flex-shrink:0;background:currentColor;
  -webkit-mask:var(--glyph-alert) center / contain no-repeat;mask:var(--glyph-alert) center / contain no-repeat;
}
.bs-empty+.bs-sec{margin-top:18px}
.bs-doc-new>svg{color:var(--ink-3);flex-shrink:0}
@media (hover:hover) and (pointer:fine){
  .bs-doc-new:hover>svg{color:var(--ink)}
}

/* ── деньги: ведомость ──
   Ответ «сколько должен» стоит в корешке шапки и виден из любого раздела.
   Значит, задача этого экрана — не повторить его шкалой и строкой под
   ней, а показать, **откуда он взялся**: начислено, получено, остаток.

   Ведомость — один документ, а не три вложенных бокса: разрыв бумаги
   делил счёт на несколько счетов, и арифметика между ними терялась. */
.bs-led{
  border:1px solid var(--rule-2);border-radius:var(--r);background:var(--card);
  overflow:hidden;
}
/* У части свой итог: можно прочитать одни заголовки и знать всю историю. */
.bs-led-h{
  display:flex;align-items:baseline;justify-content:space-between;gap:12px;
  padding:11px 13px 9px;background:var(--paper);
  border-bottom:1px solid var(--rule-2);
}
.bs-led-h+.bs-led-rows{border-top:none}
/* Заголовки частей и итога набраны на тон темнее прочих надписей-кромок:
   на серой бумаге --ink-3 давал 2,6:1, и «начислено» приходилось
   разбирать. Ими же ведомость и читают, если читают только заголовки. */
.bs-led-h h4{
  font-size:11px;font-weight:500;
  color:var(--ink-2);
}
.bs-led-h b{
  font-size:12.5px;font-weight:500;letter-spacing:-.01em;
  color:var(--ink-2);font-variant-numeric:tabular-nums;white-space:nowrap;
}
.bs-led-rows:not(:last-child){border-bottom:1px solid var(--rule-2)}

/* Строка: за что, из чего сложилось и сколько. Суммы — одной колонкой
   табличными цифрами: столбик читают сверху вниз, а не по одному числу. */
.bs-led-r{
  display:grid;grid-template-columns:1fr auto auto;align-items:baseline;
  gap:10px 12px;padding:9px 13px;
}
.bs-led-r+.bs-led-r{border-top:1px solid var(--rule-2)}
.bs-led-r>span{
  min-width:0;font-size:12.5px;color:var(--ink);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
/* «2 × 900 ₽» — не украшение строки, а то, из чего сложилась сумма:
   набрано читаемым тоном, а не сноской в 3,1:1. */
.bs-led-r>u{
  text-decoration:none;font-size:11px;letter-spacing:0;
  color:var(--ink-2);white-space:nowrap;
}
.bs-led-r>b{
  font-size:12.5px;font-weight:500;letter-spacing:-.01em;
  color:var(--ink);font-variant-numeric:tabular-nums;white-space:nowrap;min-width:74px;
  text-align:right;
}
/* Пришедшие деньги — единственное зелёное на экране: их и ищут глазом. */
.bs-led-r.pay>b{color:var(--ok)}
/* Акция снимает, а не приносит: тон обычных чернил, не зелёный. */
.bs-led-r.promo>b{color:var(--ink-2)}
.bs-led-r.promo>span::before{content:"";display:inline-block;width:6px;height:6px;margin-right:7px;border-radius:50%;background:var(--wait);vertical-align:1px}
/* Заметка к платежу — единственное место, где он объяснён словами. */
.bs-led-r>i{
  grid-column:1 / -1;font-style:normal;font-size:11px;line-height:1.4;color:var(--ink-2);
}
/* Квитанции платежа — под строкой: номер, который гость просит сразу. */
.bs-rcpts{grid-column:1 / -1;display:flex;flex-wrap:wrap;gap:4px 12px;margin-top:-4px}
.bs-rcpt{font-size:11px;color:var(--ink-2);border-bottom:1px dotted var(--ink-3);padding:1px 0;transition:color var(--t-tap) var(--ease)}
@media (hover:hover) and (pointer:fine){
  .bs-rcpt:hover{color:var(--ink)}
}
.bs-rcpt.void{color:var(--ink-3);text-decoration:line-through}
/* Только что принятый платёж: на длинном списке «прошло ли» — это
   вопрос о том, какая строка легла последней. */
.bs-led-r.fresh{animation:bsPayIn .5s var(--ease) backwards}
@keyframes bsPayIn{
  from{background:var(--ok-bg)}
  60%{background:var(--ok-bg)}
  to{background:transparent}
}
/* Подпись группы внутри ведомости: делит не вид позиции, а происхождение —
   насчитано при заведении брони или пробито потом. */
.bs-led-g{
  padding:10px 13px 3px;border-top:1px solid var(--rule-2);
  font-size:11px;font-weight:500;
  color:var(--ink-3);
}
.bs-led-g+.bs-led-r{border-top:none}
.bs-led-none{padding:11px 13px;font-size:11.5px;line-height:1.45;color:var(--ink-2)}

/* Итог — вывод из двух частей выше, а не ещё одно сообщение: тёмная
   бумага и крупное число, и на нём же стоит действие. */
.bs-led-sum{
  display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:13px 13px;
  /* Итог подводят чертой, а не заливкой: серое поле уравнивало вывод
     с заголовками частей, которые тоже на серой бумаге. */
  border-top:1.5px solid var(--ink);
}
.bs-led-sum h4{
  font-size:11px;font-weight:500;
  color:var(--ink-2);
}
.bs-led-sum b{
  font-size:19px;font-weight:600;letter-spacing:-.02em;
  color:var(--ink);font-variant-numeric:tabular-nums;
}
.bs-led-sum.wait b{color:var(--wait)}
.bs-led-sum.late b{color:var(--late)}
/* Ноль — тоже ответ, и он зелёный: «долга нет» словами повторяло бы
   само число, а два раза об одном не говорят. */
.bs-led-sum.settled b{color:var(--ok)}

/* Залог — чужие деньги, а не выручка: он вне арифметики счёта и сказан
   словами, иначе читается как ещё одно поступление. Отделён пунктиром
   сверху — так в ведомости отчёркивают то, что в итог не входит. */
.bs-hold{
  display:flex;align-items:baseline;gap:9px;margin-top:14px;padding-top:11px;
  border-top:1px dashed var(--rule);
}
.bs-hold b{
  font-size:13px;font-weight:500;letter-spacing:-.02em;
  color:var(--ink-2);font-variant-numeric:tabular-nums;white-space:nowrap;
}
.bs-hold span{font-size:11.5px;line-height:1.45;color:var(--ink-2)}

/* Счёт продажи в разделе товаров — та же строка итога, что и раньше. */
.bs-bill{display:flex;align-items:baseline;gap:12px;padding:9px 13px}
.bs-bill>span{flex:1;min-width:0;font-size:12.5px;color:var(--ink)}
.bs-bill>b{
  font-size:12.5px;font-weight:500;letter-spacing:-.01em;
  color:var(--ink);font-variant-numeric:tabular-nums;white-space:nowrap;
}
.bs-bill.total{
  margin-top:11px;padding:11px 13px 0;border-top:1px solid var(--rule);
  align-items:baseline;
}
.bs-bill.total>span{
  font-size:11px;font-weight:500;
  color:var(--ink-3);flex:1;
}
.bs-bill.total>b{font-size:16px;letter-spacing:-.045em}

@media (prefers-reduced-motion:reduce){.bs-led-r.fresh{animation:none}}

/* Подвал ведомости: два действия одной строкой, разделённые кромкой.
   Главное отличается весом и тоном — заливка нужна там, где кнопку ищут
   среди прочего, а здесь их ровно две, и обе на своём месте. */
.bs-led-do{
  display:grid;grid-template-columns:1fr 1fr;
  border-top:1px solid var(--rule-2);background:var(--card);
}
.bs-led-do button{
  display:flex;align-items:center;justify-content:center;gap:8px;
  min-height:44px;padding:12px 10px;
  font-size:12px;font-weight:500;letter-spacing:-.01em;color:var(--ink-2);
  transition:background-color .12s var(--ease),color .12s;
}
.bs-led-do button+button{border-left:1px solid var(--rule-2)}
@media (hover:hover) and (pointer:fine){
  .bs-led-do button:hover{background:var(--paper);color:var(--ink)}
}
.bs-led-do button:active{background:var(--sunk)}
.bs-led-do button:focus-visible{outline:2px solid var(--ink);outline-offset:-2px}
.bs-led-do button.on{color:var(--ink);font-weight:600}
.bs-led-do i{display:flex;color:var(--ink-3);transition:color .12s}
/* Знак главного действия — в залитом кружке: столько заливки, сколько
   нужно, чтобы отличить, и не столько, чтобы спорить с подвалом карточки. */
.bs-led-do button.on i{
  width:22px;height:22px;align-items:center;justify-content:center;
  border-radius:50%;background:var(--accent);color:var(--accent-ink);
}
@media (hover:hover) and (pointer:fine){
  .bs-led-do button:hover i{color:var(--ink-2)}
  .bs-led-do button.on:hover i{color:var(--accent-ink)}
}

.bs-acts{display:flex;gap:8px;margin-top:18px}
.btn-sm{padding:7px 12px;font-size:11.5px}
.bs-acts .btn[disabled]{opacity:.4;pointer-events:none}

/* ── товары ──
   Одна строка на оба случая: набранное имя фильтрует справочник и оно же
   становится своей позицией, если в справочнике такого нет. */
.bs-add{display:flex;gap:7px;margin-bottom:11px}

/* ── поле цены: появляется только под свой случай ──
   Пока позицию выбирают из справочника, цена своя, и спрашивать её не о
   чем. Поле выезжает на той букве, где справочник кончился: набранное
   имя перестало что-то находить — значит пробиваем своё (SPEC §6.1).

   Движение рассказывает именно это: строка имени **отдаёт место**, поле
   раскрывается на освободившемся, и кнопка приходит следом — а не всё
   трое возникают разом. Поэтому раскрытие идёт по основе (flex-basis)
   с торможением к концу, содержимое поля догоняет его на 90 мс позже,
   а кнопка — ещё на 30 мс. Уход вдвое короче входа: исчезновение никто
   не разглядывает.

   Класс живёт одну перерисовку: справочник фильтруется на каждой букве,
   и дёргать поле на каждой было бы враньём о том, что что-то изменилось. */
.bs-add:not(.ask) .bs-add-price,
.bs-add:not(.ask) .bs-add-go{display:none}

.bs-add.in .bs-add-price{animation:bsAskOpen .3s var(--ease) backwards;overflow:hidden}
.bs-add.in .bs-add-price>*{animation:bsAskInk .22s var(--ease) .09s backwards}
.bs-add.in .bs-add-go{animation:bsAskGo .26s var(--ease) .12s backwards}

@keyframes bsAskOpen{
  from{flex-basis:0;opacity:0;border-color:transparent}
  40%{opacity:1}
  to{flex-basis:96px;opacity:1}
}
@keyframes bsAskInk{from{opacity:0;transform:translateX(-7px)}to{opacity:1;transform:none}}
@keyframes bsAskGo{from{opacity:0;transform:scale(.94)}to{opacity:1;transform:none}}

/* Уход: место возвращается имени, поле схлопывается туда же, откуда
   вышло. `forwards` держит его закрытым до следующей перерисовки. */
.bs-add.out .bs-add-price,.bs-add.out .bs-add-go{display:flex;pointer-events:none}
.bs-add.out .bs-add-price{animation:bsAskShut .16s var(--ease) forwards;overflow:hidden}
.bs-add.out .bs-add-go{animation:bsAskGoShut .12s var(--ease) forwards}
@keyframes bsAskShut{
  from{flex-basis:96px;opacity:1}
  to{flex-basis:0;opacity:0;border-color:transparent}
}
@keyframes bsAskGoShut{from{opacity:1}to{opacity:0;width:0;padding:0;margin:0;border-width:0}}

@media (prefers-reduced-motion:reduce){
  .bs-add.in .bs-add-price,.bs-add.in .bs-add-price>*,.bs-add.in .bs-add-go{animation:none}
  .bs-add.out .bs-add-price,.bs-add.out .bs-add-go{display:none;animation:none}
}

.bs-add-name{
  position:relative;display:flex;align-items:center;flex:1;min-width:0;
  border:1px solid var(--rule);border-radius:var(--r-sm);background:var(--card);transition:var(--t-tap) var(--ease);transition-property:border-color,box-shadow;
}
.bs-add-name>svg{position:absolute;left:11px;color:var(--ink-3);pointer-events:none}
.bs-add-name input{
  flex:1;min-width:0;padding:9px 12px 9px 34px;border:0;background:none;outline:none;
  font-size:13px;color:var(--ink);
}
.bs-add-price{
  position:relative;display:flex;align-items:center;flex:0 0 96px;
  border:1px solid var(--rule);border-radius:var(--r-sm);background:var(--card);transition:var(--t-tap) var(--ease);transition-property:border-color,box-shadow;
}
.bs-add-price input{
  width:100%;padding:9px 26px 9px 12px;border:0;background:none;outline:none;text-align:right;
  font-size:13px;letter-spacing:-.01em;color:var(--ink);
}
.bs-add-price span{
  position:absolute;right:11px;font-size:12px;color:var(--ink-3);
  pointer-events:none;
}
.bs-add-name:focus-within,.bs-add-price:focus-within{
  border-color:var(--ink);box-shadow:0 0 0 3px var(--focus-ring);
}
.bs-add input::placeholder{color:var(--ink-3)}
.bs-add .btn{flex:0 0 auto;padding:0 14px}
.bs-add .btn[disabled]{opacity:.35;pointer-events:none}

/* Заголовок группы справочника — та же тихая строчная надпись с волосяной
   линией, что у разделов карточки: справочник разложен, а не свален. */
.bs-pick-g{
  display:flex;align-items:center;gap:9px;margin:14px 0 7px;
  font-size:11px;font-weight:500;
  color:var(--ink-3);
}
.bs-pick-g:first-child{margin-top:0}
.bs-pick-g::after{content:"";flex:1;height:1px;background:var(--rule-2)}
.bs-picks{display:grid;grid-template-columns:repeat(3,1fr);gap:7px;align-items:stretch}
.bs-pick{
  position:relative;display:flex;flex-direction:column;gap:3px;padding:9px 11px;text-align:left;
  border:1px solid var(--rule);border-radius:var(--r-sm);background:var(--card);transition:var(--t-tap) var(--ease);transition-property:background-color,border-color,transform;
}
/* Строка под ценой объясняет, из чего она сложилась: «12 × 650 ₽ за гостя
   в ночь». Она есть только у того, что считается не штуками, поэтому
   плитки в ряду разной высоты — их равняет `align-items:stretch`, а не
   пустая строка у остальных. */
.bs-pick em{
  margin-top:auto;padding-top:2px;font-style:normal;
  font-size:10px;letter-spacing:0;color:var(--ink-3);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.bs-pick span{
  font-size:12px;font-weight:550;letter-spacing:-.015em;color:var(--ink);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.bs-pick u{
  font-size:11px;letter-spacing:-.01em;color:var(--ink-3);
  text-decoration:none;
}
/* В углу плитки живут две вещи по очереди: в покое — звезда избранного,
   под курсором — плюс. Место одно, потому что и говорят они об одном и том
   же углу: «эта позиция особая» и «нажми, и она в счёте». */
.bs-pick i{
  position:absolute;top:7px;right:8px;display:flex;line-height:0;
  color:var(--ink-3);transition:opacity .12s;
}
.bs-pick::after{
  content:"+";position:absolute;top:6px;right:9px;font-size:13px;line-height:1;
  color:var(--accent);opacity:0;transition:opacity .12s;
}
@media (hover:hover) and (pointer:fine){
  .bs-pick:hover{border-color:var(--accent);background:var(--sunk)}
}
.bs-pick:hover::after{opacity:1}
.bs-pick:hover i{opacity:0}
/* Отмеченная плитка заметна и без звезды: рамка у неё в тоне чернил, а не
   в тоне линейки. Звезда — для поиска, где заголовка «Избранное» нет. */
.bs-pick.fav{border-color:var(--ink-3)}
.bs-pick:active{transform:scale(.97)}
.bs-pick:focus-visible{outline:2px solid var(--ink);outline-offset:1px}

/* Количество меняется прямо в строке: ноль убирает позицию, и кнопка
   «удалить» тут лишняя. */
.bs-qty{display:flex;align-items:center;gap:2px;flex-shrink:0}
.bs-qty button{
  width:22px;height:22px;border-radius:var(--r-sm);border:1px solid var(--rule);
  background:var(--card);color:var(--ink-2);font-size:13px;line-height:1;transition:var(--t-tap) var(--ease);transition-property:color,background-color,border-color,transform;
}
@media (hover:hover) and (pointer:fine){
  .bs-qty button:hover{border-color:var(--ink-3);background:var(--sunk);color:var(--ink)}
}
.bs-qty button:active{transform:scale(.92)}
.bs-qty em{
  min-width:22px;text-align:center;font-size:12px;font-style:normal;
  font-weight:500;letter-spacing:-.01em;color:var(--ink);font-variant-numeric:tabular-nums;
}

/* ── история ──
   События сгруппированы по дням: журнал без дней читается сплошной
   лентой, а спрашивают обычно «что было вчера». */
.bs-log{position:relative;padding-left:14px}
.bs-log::before{
  content:"";position:absolute;left:3px;top:6px;bottom:6px;width:1px;background:var(--rule-2);
}
.bs-log-day{
  margin:14px 0 8px;font-size:11px;font-weight:500;
  color:var(--ink-3);
}
.bs-log-day:first-child{margin-top:0}
.bs-log-row{display:flex;align-items:baseline;gap:10px;padding:5px 0}
.bs-log-row>b{
  font-size:11px;font-weight:500;letter-spacing:-.01em;
  color:var(--ink-3);white-space:nowrap;
}
/* Род события — точка на линии журнала: деньги, документ, правка. */
.bs-log-row>i{
  position:absolute;left:0;width:7px;height:7px;border-radius:50%;margin-top:5px;
  background:var(--rule);box-shadow:0 0 0 3px var(--card);
}
.bs-log-row>i[data-kind="money"]{background:var(--ok)}
.bs-log-row>i[data-kind="doc"]{background:var(--ink-3)}
.bs-log-row>i[data-kind="new"]{background:var(--ink)}
.bs-log-row>span{flex:1;min-width:0;font-size:12px;line-height:1.4;color:var(--ink)}
.bs-log-row>span em{
  display:block;margin-top:1px;font-size:10.5px;font-style:normal;color:var(--ink-3);
}

/* ── подвал ── */
.bs-foot{
  display:flex;gap:8px;justify-content:flex-end;flex-shrink:0;
  padding:13px 22px;border-top:1px solid var(--rule);background:var(--paper);
}

@media (max-width:760px){
  .dlg.dlg-booking{--bs-menu:52px}
  .bs-tab span{display:none}
  .bs-tab{padding:9px 0}
  .bs-rail{flex-wrap:wrap;gap:12px}
  .bs-picks{grid-template-columns:repeat(2,1fr)}
}
@media (prefers-reduced-motion:reduce){
  .bs-icon,.bs-name i,.bs-tab,.bs-pick,.bs-qty button,.bs-mpaid{transition:none}
  .bs-icon:active,.bs-tab:active,.bs-pick:active,.bs-qty button:active,
  .bs-menu-in:has(>.bs-tab.on:active) .bs-mark{transform:none}
  /* Шеврон у имени в покое скрыт — при сокращённом движении показываем его сразу,
     иначе о переходе к гостю ничто не сообщает. */
  .bs-name i{opacity:1;transform:none}
}

/* Форма платежа жила здесь, внутри карточки: `open_` закрывает всё
   открытое, и вторым окном карточка бы схлопнулась. Теперь у окна
   оплаты свой слой (modal.js) и своё оформление (payment.css), а две
   разные формы для одного действия не нужны. */

/* Уменьшенное движение — не отсутствие обратной связи, а её тихий
   вариант: плашка встаёт на место без переезда, раздел появляется без
   подъёма. Задержки подписей при этом обнуляются — ждать больше нечего,
   плашка уже там. */
@media (prefers-reduced-motion:reduce){
  .bs-mark,.bs-lit{transition:none}
  .bs-menu.moving .bs-mark{filter:none}
  .bs-page.is-in>*,
  .bs-page.is-in>:only-child>*{animation-name:bsFade;animation-delay:0ms}
}
@keyframes bsFade{from{opacity:0}}

/* «Остальное — поиском» стоит под избранным, а не над ним: сначала то,
   что нужно, потом дорога к тому, что нужно реже. */
.bs-pick-rest{margin-top:9px;font-size:11px;line-height:1.45;color:var(--ink-3)}

/* Примечание к платежу — своей строкой под ним: это объяснение, а не
   ещё одно поле в ряду. */
.bs-payrow i{
  flex-basis:100%;margin-top:3px;font-style:normal;font-size:11px;line-height:1.4;
  color:var(--ink-2);
}
.bs-payrow{flex-wrap:wrap}

/* ── свежий платёж ──
   Деньги приняли — строка печатается, а не появляется готовой. На длинном
   списке оплат это и есть ответ на вопрос «прошло ли»: видно, какая из
   строк только что легла.

   Язык тот же, что у строки чека в продаже: лента подаётся, строка
   проступает, чернила подсыхают. Одно действие в двух окнах не должно
   выглядеть двумя разными. */
/* Строка не проявляется из прозрачности, а въезжает и подсыхает.
   Разница не косметическая: пока кадры не идут — вкладка в фоне, движок
   придержал ленту, — прозрачная строка не видна вовсе, а это принятые
   деньги. Сдвиг и подложка такого не умеют: не доиграло — строка просто
   стоит на месте. */
.bs-payrow.fresh{animation:bsPayIn .34s var(--ease) backwards}
@keyframes bsPayIn{
  0%  {transform:translateY(-7px);background:rgba(30,85,64,.16)}
  60% {transform:translateY(0)}
  100%{background:rgba(30,85,64,0)}
}
/* Шкала догоняет строку, а не опережает её: сперва видно, что платёж
   лёг, и только потом — насколько он закрыл долг. */
.bs-payrow.fresh~* .bs-mpaid,.bs-meter .bs-mpaid{transition-delay:.12s}

@media (prefers-reduced-motion:reduce){
  .bs-payrow.fresh{animation:bsFade .2s ease backwards}
  .bs-meter .bs-mpaid{transition:none}
}

/* Приём оплаты прямо из раздела продаж.
   Гость взял веник и достаёт кошелёк — это одно движение, а не переход
   в другой раздел. Кнопка стоит при итоге и тише главных действий:
   чаще товар всё-таки записывают на живущего и рассчитываются при
   выезде, и предлагать оплату вместо счёта было бы навязчиво. */
.bs-paynow{
  display:flex;align-items:center;justify-content:center;gap:7px;
  width:100%;margin-top:11px;min-height:40px;padding:9px 13px;
  border:1px solid var(--rule);border-radius:var(--r-sm);background:var(--card);
  font-size:12.5px;font-weight:500;letter-spacing:-.015em;color:var(--ink-2);
  transition:var(--t-tap) var(--ease);transition-property:color,background-color,border-color,transform;
}
.bs-paynow svg{color:var(--ink-3);transition:color .13s var(--ease)}
@media (hover:hover) and (pointer:fine){
  .bs-paynow:hover{border-color:var(--ink);background:var(--sunk);color:var(--ink)}
  .bs-paynow:hover svg{color:var(--ink)}
}
.bs-paynow:active{transform:scale(.99)}
.bs-paynow:focus-visible{outline:2px solid var(--ink);outline-offset:2px}
@media (prefers-reduced-motion:reduce){ .bs-paynow{transition:none} .bs-paynow:active{transform:none} }

/* Строка счёта въезжает тогда, когда до неё долетела щепка. Раньше она
   появлялась готовой в момент нажатия — то есть до того, как стало видно
   отчего, — и это читалось как рывок, а не как перенос.

   `backwards` — не приём: свёрнутой строка бывает только до начала
   движения, после — обычной строкой счёта. Нет движения — есть строка;
   позиций, за которые гость платит, невидимыми не бывает. */
.bs-row.landing{animation:bsRowIn .28s var(--ease) var(--land,0ms) backwards}
@keyframes bsRowIn{
  /* Сворачиваются и поля: без них строка занимала двадцать один пиксель
     ещё до того, как в неё что-то прилетело, и место под неё «дёргалось»
     дважды — сперва при нажатии, потом при посадке. */
  from{height:0;padding-top:0;padding-bottom:0;opacity:0;
       transform:translateY(-6px);overflow:hidden}
  to  {height:var(--h);opacity:1;transform:translateY(0);overflow:hidden}
}

/* Убранная позиция уходит сворачиванием: пропавшая без следа строка
   читается как сбой, а не как «убрали». Уход короче прихода — то, что
   исчезает, внимания уже не просит. */
.bs-row.leaving{animation:bsRowOut .19s cubic-bezier(.4,0,1,1) forwards}
@keyframes bsRowOut{
  from{height:var(--h);opacity:1}
  to  {height:0;padding-top:0;padding-bottom:0;opacity:0;overflow:hidden}
}
@media (prefers-reduced-motion:reduce){ .bs-row.leaving{animation:bsFade .15s ease reverse forwards} }

/* Остаток отзывается на прилетевшую позицию.
   Считать он начинает не в момент нажатия, а когда щепка долетела:
   иначе число меняется раньше, чем видно, отчего. Подсветка короткая —
   это отметка события, а не состояние. */
/* Отзыв остатка — не вспышка. Подложка, вспыхивающая на тёмной ленте,
   читается как моргание; цифра, которая на мгновение потяжелела и
   встала на место, — как «сюда прибыло». Движение при этом остаётся на
   самой цифре, а лента под ней не шевелится. */
.bs-edge.bill.hit b{animation:bsPurseUp .54s cubic-bezier(.2,.8,.3,1)}
@keyframes bsPurseUp{
  0%  {transform:translateY(3px) scale(1.06)}
  100%{transform:translateY(0) scale(1)}
}
.bs-edge.bill.hit em{animation:bsPurseLit .54s cubic-bezier(.2,.8,.3,1)}
@keyframes bsPurseLit{
  0%  {color:var(--accent-ink)}
  100%{color:var(--band-ink-3)}
}
@media (prefers-reduced-motion:reduce){
  .bs-edge.bill.hit b,.bs-edge.bill.hit em{animation:none}
  .bs-row.landing{animation:none}
}


/* ── возврат в ведомости счёта ──
   Деньги ходят в обе стороны по одному счёту, поэтому возврат стоит в тех
   же «Получено», а не отдельным списком. Отличают его три вещи, и ни одна
   из них не цвет в одиночку: слово «Возврат» в строке, минус перед суммой
   и кромка слева. Тон — тот же, каким продукт помечает ушедшее
   (§8.3): охра ожидания, а не красный тревоги: возврат не поломка.

   Дверь «вернуть» у платежа появляется по наведению, а на касании стоит
   всегда: скрытое действие, до которого нельзя дотянуться пальцем, — не
   действие. */
.bs-led-r.back{position:relative}
.bs-led-r.back::before{
  content:"";position:absolute;left:-10px;top:6px;bottom:6px;width:2px;border-radius:1px;
  background:var(--wait);
}
.bs-led-r.back > b{color:var(--wait)}
.bs-back{
  margin-left:10px;padding:1px 6px;border-radius:var(--r-sm);
  border:1px solid transparent;background:none;
  font-size:10.5px;color:var(--ink-3);vertical-align:1px;
  transition:border-color var(--t-tap) var(--ease), color var(--t-tap) var(--ease),
    background-color var(--t-tap) var(--ease), opacity var(--t-tap) var(--ease);
}
@media (hover:hover) and (pointer:fine){
  .bs-back:hover{border-color:var(--rule);background:var(--card);color:var(--ink)}
}
.bs-back:active{transform:scale(.96)}
.bs-back:focus-visible{outline:2px solid var(--ink);outline-offset:1px}
@media (hover:hover) and (pointer:fine){
  .bs-back{opacity:0}
  .bs-led-r.pay:hover .bs-back,.bs-back:focus-visible{opacity:1}
}
@media (prefers-reduced-motion:reduce){ .bs-back:active{transform:none} }
