/*
 * Шаги записи: экраны `Booking 01 — Услуги` и `Booking 02 — Специалист IT`.
 *
 * Общий файл на оба шага: у них одна шапка, один шагомер, одна колонка
 * содержимого шириной 900 px и одна нижняя панель. Держать их врозь значит
 * развести оформление при первой же правке.
 *
 * Правило то же, что на лендинге и экранах входа: ни одного значения
 * напрямую — только `var(--tb-*)` из `tokens.css`. Проверяется так:
 *
 *   grep -nE '#[0-9A-Fa-f]{3,8}|[0-9]+px|rgba?\(' web/booking.css
 *
 * Вывод должен быть пустым.
 */

/*
 * `hidden` должен прятать.
 *
 * У кнопок, значков и блоков ниже проставлен `display`, а он сильнее
 * стандартного правила браузера для `[hidden]`. Без этой строки скрытый
 * элемент остаётся на экране: счётчик у колокольчика показывал бы ноль, а
 * кнопка «Отметить все прочитанными» предлагала бы отметить нечего.
 */
[hidden] {
  display: none !important;
}

/* ========================================================================
   Основа
   ======================================================================== */

*,
*::before,
*::after {
  box-sizing: border-box;
}

body {
  margin: 0;
  padding: 0;
  background: var(--tb-color-surface);
  color: var(--tb-color-ink);
  font-family: var(--tb-font-sans);
  -webkit-font-smoothing: antialiased;
  /* Прототип — макет фиксированной ширины, мобильной раскладки в нём нет.
     Повторяем это поведение, а не придумываем своё. */
  min-width: var(--tb-page-width);
}

a {
  color: var(--tb-color-ink);
  text-decoration: none;
}

a:focus-visible,
button:focus-visible {
  outline: var(--tb-border-hairline) solid currentColor;
  outline-offset: var(--tb-space-4);
}

/* Экран целиком: шапка, шагомер, содержимое, нижняя панель. */
.booking {
  min-height: 100vh;
  width: var(--tb-page-width);
  margin: 0 auto;
  display: flex;
  flex-direction: column;
}

/* ========================================================================
   Шапка
   ======================================================================== */

.booking__header {
  background: var(--tb-color-ink);
  padding: var(--tb-space-20) var(--tb-space-32);
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.booking__logo {
  color: var(--tb-color-surface);
  font-size: var(--tb-text-18);
  font-weight: var(--tb-weight-black);
  letter-spacing: var(--tb-tracking-tight);
}

.booking__leave {
  display: flex;
  align-items: center;
  gap: var(--tb-space-20);
}

.booking__cancel {
  color: var(--tb-color-light);
  font-size: var(--tb-text-14);
  font-weight: var(--tb-weight-medium);
}

.booking__close {
  width: var(--tb-step-badge);
  height: var(--tb-step-badge);
  border-radius: var(--tb-radius-circle);
  border: var(--tb-border-hairline) solid var(--tb-color-outline-dark);
  background: transparent;
  color: var(--tb-color-surface);
  font-size: var(--tb-text-14);
  font-family: inherit;
  cursor: pointer;
}

/* ========================================================================
   Шагомер
   ======================================================================== */

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

.steps {
  padding: var(--tb-space-24) var(--tb-space-32);
  border-bottom: var(--tb-border-hairline) solid var(--tb-color-line);
}

.steps__row {
  display: flex;
  align-items: center;
  max-width: var(--tb-booking-width);
  margin: 0 auto;
}

.step {
  display: flex;
  flex-direction: column;
  align-items: center;
  flex: 1;
}

a.step {
  cursor: pointer;
}

.step__badge {
  width: var(--tb-step-badge);
  height: var(--tb-step-badge);
  border-radius: var(--tb-radius-circle);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--tb-text-13);
  font-weight: var(--tb-weight-bold);
  background: var(--tb-color-ink);
  color: var(--tb-color-surface);
}

/* Будущий шаг: пустой кружок с приглушённой рамкой. */
.step--todo .step__badge {
  background: transparent;
  border: var(--tb-border-hairline) solid var(--tb-color-light);
  color: var(--tb-color-light);
}

.step__label {
  font-size: var(--tb-text-12);
  margin-top: var(--tb-space-8);
  font-weight: var(--tb-weight-semibold);
  color: var(--tb-color-ink);
}

.step--todo .step__label {
  font-weight: inherit;
  color: var(--tb-color-light);
}

.steps__line {
  height: var(--tb-border-hairline);
  background: var(--tb-color-line);
  flex: 1;
  margin-bottom: var(--tb-space-24);
}

/* Отрезок между пройденными шагами закрашен. */
.steps__line--done {
  background: var(--tb-color-ink);
}

/* ========================================================================
   Колонка содержимого
   ======================================================================== */

.booking__body {
  flex: 1;
  width: 100%;
  max-width: var(--tb-booking-width);
  margin: 0 auto;
  padding: var(--tb-space-40) var(--tb-space-32);
}

/* Под тёмной залипающей панелью итога нужен запас, иначе она накрывает
   последний ряд карточек. */
.booking__body--under-summary {
  padding-bottom: var(--tb-space-160);
}

.booking__title {
  font-size: var(--tb-text-34);
  font-weight: var(--tb-weight-black);
  letter-spacing: var(--tb-tracking-tight);
  margin: 0 0 var(--tb-space-8);
}

.booking__lead {
  font-size: var(--tb-text-14);
  color: var(--tb-color-muted);
  margin: 0 0 var(--tb-space-32);
}

/* ========================================================================
   Шаг 1: карточки услуг
   ======================================================================== */

.services {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--tb-space-16);
}

/*
 * Карточка — <button aria-pressed>, а не <div> с обработчиком: выбор услуги
 * должен работать с клавиатуры и читаться экранным диктором как переключатель.
 */
.service {
  display: flex;
  align-items: flex-start;
  gap: var(--tb-space-14);
  padding: var(--tb-space-20) var(--tb-space-22);
  border-radius: var(--tb-radius-12);
  border: var(--tb-border-hairline) solid var(--tb-color-line);
  background: var(--tb-color-surface);
  font-family: inherit;
  color: inherit;
  text-align: left;
  width: 100%;
  cursor: pointer;
}

.service[aria-pressed='true'] {
  border-color: var(--tb-color-ink);
  background: var(--tb-color-surface-alt);
}

.service__mark {
  width: var(--tb-choice-mark);
  height: var(--tb-choice-mark);
  border-radius: var(--tb-radius-6);
  background: var(--tb-color-surface);
  border: var(--tb-border-hairline) solid var(--tb-color-light);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  margin-top: var(--tb-space-2);
  font-size: var(--tb-text-13);
  font-weight: var(--tb-weight-bold);
  color: transparent;
}

.service[aria-pressed='true'] .service__mark {
  background: var(--tb-color-ink);
  border-color: var(--tb-color-ink);
  color: var(--tb-color-surface);
}

/* Внутренности карточки — <span>: содержимое <button> по спецификации
   строчное, а раскладку задаёт display. */
.service__body {
  display: block;
  flex: 1;
}

.service__title {
  display: block;
  font-size: var(--tb-text-16);
  font-weight: var(--tb-weight-bold);
}

.service__text {
  display: block;
  font-size: var(--tb-text-13);
  color: var(--tb-color-outline-dark);
  line-height: var(--tb-leading-snug);
  margin: var(--tb-space-6) 0 var(--tb-space-10);
}

.service__meta {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.service__term {
  font-size: var(--tb-text-13);
  color: var(--tb-color-muted);
}

.service__price {
  font-size: var(--tb-text-17);
  font-weight: var(--tb-weight-black);
  font-variant-numeric: tabular-nums;
}

/* ========================================================================
   Шаг 1: панель итога
   ======================================================================== */

.summary {
  position: sticky;
  bottom: 0;
  background: var(--tb-color-ink);
  padding: var(--tb-space-20) var(--tb-space-32);
}

.summary__row {
  max-width: var(--tb-booking-width);
  margin: 0 auto;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--tb-space-16);
}

.summary__text {
  color: var(--tb-color-surface);
  font-size: var(--tb-text-14);
  font-weight: var(--tb-weight-semibold);
}

/* Пока выбирать нечего, панель объясняет, чего не хватает, — приглушённо. */
.summary--empty .summary__text {
  color: var(--tb-color-dim);
}

.summary__price {
  color: var(--tb-color-surface);
  font-size: var(--tb-text-16);
  font-weight: var(--tb-weight-bold);
  font-variant-numeric: tabular-nums;
  margin-left: auto;
}

/* ========================================================================
   Кнопки шагов
   ======================================================================== */

.btn-next,
.btn-dark {
  padding: var(--tb-space-14) var(--tb-space-32);
  border: 0;
  border-radius: var(--tb-radius-pill);
  font-size: var(--tb-text-15);
  font-weight: var(--tb-weight-semibold);
  font-family: inherit;
  cursor: pointer;
}

/* Светлая — на тёмной панели итога. */
.btn-next {
  background: var(--tb-color-surface);
  color: var(--tb-color-ink);
}

/* Тёмная — на светлой панели навигации. */
.btn-dark {
  background: var(--tb-color-ink);
  color: var(--tb-color-surface);
}

/* Неактивные состояния разные, и оба сняты с прототипа: тёмная панель итога
   в `Booking 01` гасит кнопку в тёмно-серый, светлая панель навигации в
   `Booking 03a` — в светло-серый. Одно значение на обе панели читалось бы
   как пятно на одной из них. */
.btn-next[disabled] {
  background: var(--tb-color-line-dark);
  color: var(--tb-color-muted);
  cursor: not-allowed;
}

.btn-dark[disabled] {
  background: var(--tb-color-surface-alt);
  color: var(--tb-color-light);
  cursor: not-allowed;
}

.btn-back {
  padding: var(--tb-space-14) var(--tb-space-28);
  background: transparent;
  color: var(--tb-color-ink);
  border: var(--tb-border-hairline) solid var(--tb-color-ink);
  border-radius: var(--tb-radius-pill);
  font-size: var(--tb-text-15);
  font-weight: var(--tb-weight-semibold);
  display: inline-block;
}

/* ========================================================================
   Шаг 2: строка выбранных услуг
   ======================================================================== */

.chosen {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--tb-space-16);
  padding: var(--tb-space-14) var(--tb-space-20);
  background: var(--tb-color-surface-alt);
  border-radius: var(--tb-radius-10);
  margin-bottom: var(--tb-space-28);
}

.chosen__text {
  font-size: var(--tb-text-14);
  font-weight: var(--tb-weight-semibold);
}

.chosen__edit {
  font-size: var(--tb-text-13);
  font-weight: var(--tb-weight-semibold);
  border-bottom: var(--tb-border-hairline) solid var(--tb-color-ink);
  flex-shrink: 0;
}

/* ========================================================================
   Шаг 2: «Любой свободный специалист»
   ======================================================================== */

.any {
  display: flex;
  align-items: center;
  gap: var(--tb-space-16);
  padding: var(--tb-space-20) var(--tb-space-24);
  border-radius: var(--tb-radius-12);
  border: var(--tb-border-hairline) solid var(--tb-color-line);
  background: var(--tb-color-surface);
  margin-bottom: var(--tb-space-12);
  width: 100%;
  font-family: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}

.any[aria-pressed='true'] {
  border-color: var(--tb-color-ink);
  background: var(--tb-color-surface-alt);
}

/* Весь набор услуг никому не по силам целиком — «любого свободного» тоже
   выбрать нельзя, и карточка гаснет вместе с остальными. */
.any[aria-disabled='true'] {
  opacity: var(--tb-opacity-disabled);
  cursor: not-allowed;
}

.any__icon {
  width: var(--tb-choice-avatar);
  height: var(--tb-choice-avatar);
  border-radius: var(--tb-radius-circle);
  background: var(--tb-color-surface-alt);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--tb-text-20);
  flex-shrink: 0;
}

.any__body {
  display: block;
  flex: 1;
}

.any__title {
  display: block;
  font-size: var(--tb-text-16);
  font-weight: var(--tb-weight-bold);
}

.any__note {
  display: block;
  font-size: var(--tb-text-13);
  color: var(--tb-color-muted);
  margin-top: var(--tb-space-2);
}

.any__mark {
  width: var(--tb-choice-mark);
  height: var(--tb-choice-mark);
  border-radius: var(--tb-radius-circle);
  background: var(--tb-color-surface);
  border: var(--tb-border-hairline) solid var(--tb-color-light);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  font-size: var(--tb-text-12);
  font-weight: var(--tb-weight-bold);
  color: transparent;
}

.any[aria-pressed='true'] .any__mark {
  background: var(--tb-color-ink);
  border-color: var(--tb-color-ink);
  color: var(--tb-color-surface);
}

/* ========================================================================
   Шаг 2: карточки специалистов
   ======================================================================== */

.specialists {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--tb-space-16);
}

.specialist {
  border: var(--tb-border-hairline) solid var(--tb-color-line);
  background: var(--tb-color-surface);
  border-radius: var(--tb-radius-16);
  overflow: hidden;
  padding: 0;
  width: 100%;
  font-family: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}

.specialist[aria-pressed='true'] {
  border-color: var(--tb-color-ink);
  background: var(--tb-color-surface-alt);
}

/*
 * Специалист, который не выполняет часть выбранных услуг. Он остаётся на
 * экране, а не исчезает: пропавшая карточка выглядит как сбой, а приглушённая
 * с пояснением сразу говорит, почему выбрать её нельзя и что для этого надо
 * поменять.
 */
.specialist[aria-disabled='true'] {
  opacity: var(--tb-opacity-disabled);
  cursor: not-allowed;
}

.specialist__photo {
  height: var(--tb-specialist-photo);
  background: var(--tb-stripe-light);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--tb-font-mono);
  font-size: var(--tb-text-9);
  color: var(--tb-color-dim);
}

.specialist__photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.specialist__body {
  display: block;
  padding: var(--tb-space-16);
  position: relative;
}

.specialist__mark {
  position: absolute;
  top: var(--tb-space-16);
  right: var(--tb-space-16);
  width: var(--tb-choice-mark);
  height: var(--tb-choice-mark);
  border-radius: var(--tb-radius-circle);
  background: var(--tb-color-ink);
  color: var(--tb-color-surface);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--tb-text-12);
  font-weight: var(--tb-weight-bold);
}

.specialist__name {
  display: block;
  font-size: var(--tb-text-15);
  font-weight: var(--tb-weight-bold);
  margin-bottom: var(--tb-space-2);
  /* Место под галочку выбора в правом верхнем углу карточки. */
  padding-right: var(--tb-space-26);
}

.specialist__role,
.specialist__years {
  display: block;
  font-size: var(--tb-text-12);
  color: var(--tb-color-muted);
  margin-bottom: var(--tb-space-2);
}

.specialist__years {
  margin-bottom: var(--tb-space-8);
}

.specialist__rating {
  display: block;
  font-size: var(--tb-text-12);
  font-weight: var(--tb-weight-semibold);
}

.specialist__blocked {
  display: block;
  font-size: var(--tb-text-11);
  color: var(--tb-color-danger);
  font-weight: var(--tb-weight-semibold);
  margin-top: var(--tb-space-8);
  line-height: var(--tb-leading-compact);
}

/* ========================================================================
   Шаг 2: панель навигации
   ======================================================================== */

.navbar {
  position: sticky;
  bottom: 0;
  background: var(--tb-color-surface);
  border-top: var(--tb-border-hairline) solid var(--tb-color-line);
  padding: var(--tb-space-20) var(--tb-space-32);
}

.navbar__row {
  max-width: var(--tb-booking-width);
  margin: 0 auto;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--tb-space-16);
}

.navbar__next {
  display: flex;
  align-items: center;
  gap: var(--tb-space-16);
}

/* Чего не хватает, чтобы кнопка ожила. Стоит рядом с ней, а не в углу
   экрана: иначе неактивная кнопка выглядит поломкой. */
.navbar__hint,
.summary__hint {
  font-size: var(--tb-text-13);
  color: var(--tb-color-muted);
}

.summary__hint {
  color: var(--tb-color-dim);
}

/* ========================================================================
   Заглушки на время загрузки
   ======================================================================== */

/*
 * Пока ответ API не пришёл, на месте списка стоят карточки той же формы и
 * того же размера. Иначе страница «прыгает», когда данные приезжают.
 */

.skeleton {
  display: block;
  background: var(--tb-color-line);
  border-radius: var(--tb-radius-12);
  color: transparent;
  animation: tb-pulse 1.4s ease-in-out infinite;
}

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

@keyframes tb-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.45; }
}

.skeleton-line {
  height: var(--tb-space-12);
  margin-bottom: var(--tb-space-8);
}

.skeleton-line--title { height: var(--tb-space-20); width: 60%; margin-bottom: var(--tb-space-12); }
.skeleton-line--text  { width: 100%; }
.skeleton-line--meta  { height: var(--tb-space-16); width: 45%; margin-bottom: 0; }
.skeleton-line--name  { height: var(--tb-space-16); width: 70%; margin-bottom: var(--tb-space-8); }
.skeleton-line--role  { height: var(--tb-space-12); width: 85%; margin-bottom: 0; }

.skeleton-photo {
  height: var(--tb-specialist-photo);
  border-radius: 0;
}

.service--skeleton,
.specialist--skeleton {
  pointer-events: none;
}

/* ========================================================================
   Отказ загрузки
   ======================================================================== */

/*
 * Если API не ответил, на месте списка появляется не пустота и не вечная
 * заглушка, а объяснение и кнопка повтора: молчащая страница выглядит
 * сломанной, и человек не понимает, ждать ему или уходить.
 */

.load-error {
  grid-column: 1 / -1;
  border: var(--tb-border-hairline) solid var(--tb-color-line);
  border-radius: var(--tb-radius-16);
  padding: var(--tb-space-28);
  background: var(--tb-color-surface);
}

.load-error__text {
  font-size: var(--tb-text-15);
  color: var(--tb-color-muted);
  line-height: var(--tb-leading-snug);
  margin: 0 0 var(--tb-space-16);
}

.load-error__retry {
  font-family: var(--tb-font-sans);
  font-size: var(--tb-text-14);
  font-weight: var(--tb-weight-semibold);
  color: var(--tb-color-ink);
  background: transparent;
  border: 0;
  border-bottom: var(--tb-border-hairline) solid var(--tb-color-ink);
  padding: 0;
  cursor: pointer;
}

/* ========================================================================
   Шаг 3: сводка заказа
   ======================================================================== */

/* Та же плашка, что строка выбранных услуг на шаге 2, но с двумя ссылками
   «Изменить» — на состав и на специалиста. */
.recap {
  display: flex;
  align-items: center;
  padding: var(--tb-space-14) var(--tb-space-20);
  background: var(--tb-color-surface-alt);
  border-radius: var(--tb-radius-10);
  margin-bottom: var(--tb-space-28);
}

.recap__text {
  font-size: var(--tb-text-14);
  font-weight: var(--tb-weight-semibold);
}

.recap__edit {
  font-size: var(--tb-text-12);
  font-weight: var(--tb-weight-semibold);
  border-bottom: var(--tb-border-hairline) solid var(--tb-color-ink);
  margin-left: var(--tb-space-4);
}

/* ========================================================================
   Шаг 3: две колонки — календарь и время
   ======================================================================== */

.picker {
  display: grid;
  grid-template-columns: 1fr 1.2fr;
  gap: var(--tb-space-40);
  align-items: start;
}

/* ========================================================================
   Шаг 3: календарь месяца
   ======================================================================== */

.calendar {
  border: var(--tb-border-hairline) solid var(--tb-color-line);
  border-radius: var(--tb-radius-16);
  padding: var(--tb-space-24);
}

.calendar__head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: var(--tb-space-16);
}

.calendar__month {
  font-size: var(--tb-text-16);
  font-weight: var(--tb-weight-bold);
}

.calendar__nav {
  display: flex;
  gap: var(--tb-space-8);
}

.calendar__arrow {
  width: var(--tb-nav-button);
  height: var(--tb-nav-button);
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: var(--tb-radius-circle);
  background: transparent;
  color: var(--tb-color-ink);
  font-family: inherit;
  font-size: var(--tb-text-14);
  cursor: pointer;
}

/* За сегодняшний месяц назад и за горизонт записи вперёд листать некуда. */
.calendar__arrow[disabled] {
  color: var(--tb-color-light);
  cursor: not-allowed;
}

.calendar__weekdays,
.calendar__days {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: var(--tb-space-4);
  text-align: center;
}

.calendar__weekdays {
  font-size: var(--tb-text-11);
  color: var(--tb-color-dim);
  margin-bottom: var(--tb-space-8);
}

/*
 * День месяца. Недоступные дни — прошедшие, выходные специалиста и занятые —
 * остаются на месте и гаснут: убрать их значит сломать сетку недели, и по
 * дырам всё равно не понять, что именно случилось с этим днём.
 */
.calendar__day {
  padding: var(--tb-space-10) 0;
  border: 0;
  border-radius: var(--tb-radius-pill);
  background: transparent;
  color: var(--tb-color-ink);
  font-family: inherit;
  font-size: var(--tb-text-13);
  cursor: pointer;
}

.calendar__day[aria-disabled='true'] {
  color: var(--tb-color-light);
  cursor: not-allowed;
}

.calendar__day[aria-pressed='true'] {
  background: var(--tb-color-ink);
  color: var(--tb-color-surface);
  font-weight: var(--tb-weight-bold);
}

/* Хвост предыдущего месяца в первой неделе: виден, но выбрать нельзя. */
.calendar__day--outside {
  color: var(--tb-color-light);
}

/* ========================================================================
   Шаг 3: сетка времени
   ======================================================================== */

.times__title {
  font-size: var(--tb-text-15);
  font-weight: var(--tb-weight-bold);
  margin-bottom: var(--tb-space-16);
}

.times__group {
  font-size: var(--tb-text-12);
  font-weight: var(--tb-weight-semibold);
  text-transform: uppercase;
  letter-spacing: var(--tb-tracking-label);
  color: var(--tb-color-muted);
  margin-bottom: var(--tb-space-10);
}

.times__row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--tb-space-10);
  margin-bottom: var(--tb-space-20);
}

.slot {
  text-align: center;
  padding: var(--tb-space-14) 0;
  border-radius: var(--tb-radius-8);
  border: var(--tb-border-hairline) solid var(--tb-color-light);
  background: transparent;
  color: var(--tb-color-ink);
  font-family: inherit;
  font-size: var(--tb-text-14);
  font-weight: var(--tb-weight-semibold);
  font-variant-numeric: tabular-nums;
  cursor: pointer;
}

.slot[aria-pressed='true'] {
  background: var(--tb-color-ink);
  border-color: var(--tb-color-ink);
  color: var(--tb-color-surface);
}

/* Занято чужим созвоном — зачёркнуто, но видно: пропавшее время выглядит как
   дыра в расписании, а зачёркнутое объясняет, почему его нельзя выбрать. */
.slot--taken {
  border-color: transparent;
  background: var(--tb-color-surface-alt);
  color: var(--tb-color-dim);
  text-decoration: line-through;
  cursor: not-allowed;
}

/* Нерабочий час: блокировка, слишком близкий срок или созвон не помещается
   до конца окна. Не зачёркнуто — здесь никто не занимал время. */
.slot--unavailable {
  border-color: transparent;
  background: var(--tb-color-surface-alt);
  color: var(--tb-color-light);
  opacity: var(--tb-opacity-dim);
  cursor: not-allowed;
}

/* Приглашение выбрать день — без верхней черты: она отделяет подпись от
   сетки, а здесь сетки ещё нет. */
.times__prompt {
  font-size: var(--tb-text-14);
  color: var(--tb-color-muted);
  margin: 0;
}

.times__note {
  font-size: var(--tb-text-13);
  color: var(--tb-color-muted);
  margin: var(--tb-space-16) 0 0;
  border-top: var(--tb-border-hairline) solid var(--tb-color-line);
  padding-top: var(--tb-space-16);
}

/* Во сколько закончится стартовый созвон — считается из времени начала и
   kickoff_duration_min, других полей для этого в ответе нет. */
.times__note b {
  color: var(--tb-color-ink);
  font-weight: var(--tb-weight-semibold);
}

/* ========================================================================
   Шаг 3: загрузка сетки времени
   ======================================================================== */

/*
 * Пустая сетка и «нет свободного времени» — разные вещи, и клиент должен их
 * различать. Пока ответ едет, на месте сетки стоят полосы той же формы.
 */
.slot--skeleton {
  border-color: transparent;
  cursor: default;
  pointer-events: none;
}

/* ========================================================================
   Шаг 3: нет свободного времени (Booking 03a)
   ======================================================================== */

/*
 * Это состояние той же страницы, а не отдельный экран: календарь слева
 * остаётся на месте, меняется только правая колонка. Пунктирная рамка
 * отличает «здесь ничего нет» от «здесь что-то есть».
 */
.nothing {
  text-align: center;
  padding: var(--tb-space-48) var(--tb-space-32);
  border: var(--tb-border-hairline) dashed var(--tb-color-light);
  border-radius: var(--tb-radius-16);
}

.nothing__icon {
  width: var(--tb-status-icon);
  height: var(--tb-status-icon);
  border-radius: var(--tb-radius-circle);
  background: var(--tb-color-surface-alt);
  margin: 0 auto var(--tb-space-20);
}

.nothing__title {
  font-size: var(--tb-text-20);
  font-weight: var(--tb-weight-bold);
  margin-bottom: var(--tb-space-8);
}

.nothing__text {
  font-size: var(--tb-text-14);
  color: var(--tb-color-muted);
  margin: 0 0 var(--tb-space-28);
}

/* Кнопка «Ближайшее свободное время — 3 сентября»: она не уводит с экрана,
   а переводит календарь на нужный месяц и отмечает дату. */
.nothing__jump {
  width: 100%;
  padding: var(--tb-space-14);
  background: var(--tb-color-ink);
  color: var(--tb-color-surface);
  border: 0;
  border-radius: var(--tb-radius-pill);
  font-family: inherit;
  font-size: var(--tb-text-15);
  font-weight: var(--tb-weight-semibold);
  cursor: pointer;
  margin-bottom: var(--tb-space-20);
}

.nothing__hints {
  display: flex;
  flex-direction: column;
  gap: var(--tb-space-10);
}

.nothing__hint {
  font-size: var(--tb-text-13);
  font-weight: var(--tb-weight-semibold);
  border: 0;
  border-bottom: var(--tb-border-hairline) solid var(--tb-color-ink);
  background: transparent;
  color: var(--tb-color-ink);
  font-family: inherit;
  padding: 0;
  align-self: center;
  cursor: pointer;
}

/* ========================================================================
   Шаг 4: подтверждение записи
   ======================================================================== */

/* Колонка шире, чем на шагах 1–3: слева форма, справа сводка визита. */
.booking__body--confirm {
  max-width: var(--tb-confirm-width);
  padding-bottom: var(--tb-space-64);
}

.confirm {
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  gap: var(--tb-space-40);
  align-items: start;
}

.booking__title--confirm {
  margin-bottom: var(--tb-space-32);
}

/* ========================================================================
   Шаг 4: форма
   ======================================================================== */

.fields {
  display: flex;
  flex-direction: column;
  gap: var(--tb-space-16);
  margin-bottom: var(--tb-space-20);
}

.field__label {
  display: block;
  font-size: var(--tb-text-13);
  font-weight: var(--tb-weight-semibold);
  margin-bottom: var(--tb-space-6);
}

.field__optional {
  color: var(--tb-color-dim);
  font-weight: normal;
}

.field__input {
  width: 100%;
  padding: var(--tb-space-12) var(--tb-space-16);
  border: var(--tb-border-hairline) solid var(--tb-color-light);
  border-radius: var(--tb-radius-4);
  background: var(--tb-color-surface);
  color: var(--tb-color-ink);
  font-family: inherit;
  font-size: var(--tb-text-14);
}

textarea.field__input {
  resize: vertical;
}

/* Неверное поле называет сервер в `error.details` — подсветка идёт оттуда. */
.field--invalid .field__input {
  border-color: var(--tb-color-danger);
  background: var(--tb-color-danger-surface);
}

.field__error {
  font-size: var(--tb-text-12);
  color: var(--tb-color-danger);
  margin-top: var(--tb-space-4);
}

.field__error:empty {
  display: none;
}

/* Пока время занято, форму трогать бессмысленно — она гаснет целиком. */
.fields--frozen {
  opacity: var(--tb-opacity-disabled);
}

.consent {
  display: flex;
  align-items: flex-start;
  gap: var(--tb-space-10);
  font-size: var(--tb-text-13);
  color: var(--tb-color-outline-dark);
  cursor: pointer;
}

.consent__box {
  width: var(--tb-consent-size);
  height: var(--tb-consent-size);
  border-radius: var(--tb-radius-4);
  border: var(--tb-border-hairline) solid var(--tb-color-light);
  background: var(--tb-color-surface);
  color: transparent;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: var(--tb-text-12);
  flex-shrink: 0;
  margin-top: var(--tb-space-2);
}

.consent input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}

.consent input:checked + .consent__box {
  background: var(--tb-color-ink);
  border-color: var(--tb-color-ink);
  color: var(--tb-color-surface);
}

.consent input:focus-visible + .consent__box {
  outline: var(--tb-border-hairline) solid var(--tb-color-ink);
  outline-offset: var(--tb-space-2);
}

.consent__link {
  font-weight: var(--tb-weight-semibold);
  border-bottom: var(--tb-border-hairline) solid var(--tb-color-ink);
}

/* ========================================================================
   Booking 04a: вход или регистрация поверх брони
   ======================================================================== */

/*
 * Переключатель вкладок вместо двух отдельных страниц: дата уже удержана, и
 * уход на общий экран входа означал бы уход со сводкой и таймером.
 */
.switch {
  display: flex;
  gap: var(--tb-space-4);
  background: var(--tb-color-surface-alt);
  border-radius: var(--tb-radius-pill);
  padding: var(--tb-space-4);
  width: fit-content;
  margin-bottom: var(--tb-space-24);
}

.switch__item {
  padding: var(--tb-space-9) var(--tb-space-20);
  border: 0;
  border-radius: var(--tb-radius-pill);
  background: transparent;
  color: var(--tb-color-dim);
  font-family: inherit;
  font-size: var(--tb-text-14);
  font-weight: var(--tb-weight-semibold);
  cursor: pointer;
}

.switch__item--on {
  background: var(--tb-color-ink);
  color: var(--tb-color-surface);
}

.switch__foot {
  text-align: center;
  font-size: var(--tb-text-13);
  color: var(--tb-color-dim);
  margin: var(--tb-space-16) 0 0;
}

/* Согласие стоит перед кнопкой, а не в стороне: без него она ведёт в отказ. */
.field--consent {
  margin-bottom: var(--tb-space-20);
}

/* Смена вкладки — не переход по адресу: это кнопка, но выглядит ссылкой. */
.switch__link {
  border: 0;
  background: none;
  padding: 0;
  font-family: inherit;
  font-size: var(--tb-text-13);
  font-weight: var(--tb-weight-semibold);
  color: var(--tb-color-ink);
  cursor: pointer;
}

/* ========================================================================
   Шаг 4: таймер брони
   ======================================================================== */

/*
 * Пока идёт оформление, дата держится за клиентом `hold_ttl_minutes` минут.
 * Таймер показывает остаток, а не прячет его: без него человек не знает,
 * что у заполнения формы есть срок, и узнаёт об этом только из отказа.
 */
.hold {
  display: flex;
  align-items: center;
  gap: var(--tb-space-10);
  padding: var(--tb-space-14) var(--tb-space-18);
  border-radius: var(--tb-radius-12);
  background: var(--tb-color-ink);
  color: var(--tb-color-surface);
  font-size: var(--tb-text-13);
  font-weight: var(--tb-weight-semibold);
  margin-bottom: var(--tb-space-16);
}

.hold__dot {
  width: var(--tb-dot);
  height: var(--tb-dot);
  border-radius: var(--tb-radius-circle);
  background: var(--tb-color-success);
  flex-shrink: 0;
}

/* Меньше минуты: цвет меняется вместе со смыслом — это уже предупреждение. */
.hold--soon {
  background: var(--tb-color-warning-surface);
  color: var(--tb-color-warning-strong);
}

.hold--soon .hold__dot {
  background: var(--tb-color-warning);
}

/* Бронь снята — по таймеру или потому, что дату заняли. */
.hold--gone {
  background: var(--tb-color-surface-alt);
  color: var(--tb-color-outline-dark);
}

.hold--gone .hold__dot {
  background: var(--tb-color-danger);
}

/* ========================================================================
   Шаг 4: сводка визита
   ======================================================================== */

.visit {
  position: sticky;
  top: var(--tb-space-24);
}

.visit__card {
  border: var(--tb-border-hairline) solid var(--tb-color-line);
  border-radius: var(--tb-radius-16);
  padding: var(--tb-space-24);
}

/* Бронь снята — сводка остаётся на экране, но гаснет: она уже про прошлое.
   Ссылки «Изменить» из неё уходят: менять в снятой брони нечего. */
.visit__card--gone {
  opacity: var(--tb-opacity-dim);
}

.visit__card--gone .visit__edit,
.visit__card--gone .visit__back {
  display: none;
}

.visit__row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: var(--tb-space-20);
}

.visit__person {
  display: flex;
  gap: var(--tb-space-12);
  align-items: center;
}

.visit__photo {
  width: var(--tb-summary-avatar);
  height: var(--tb-summary-avatar);
  border-radius: var(--tb-radius-circle);
  background: var(--tb-stripe-fine);
  flex-shrink: 0;
  overflow: hidden;
}

.visit__photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.visit__caption {
  font-size: var(--tb-text-12);
  color: var(--tb-color-muted);
  text-transform: uppercase;
  letter-spacing: var(--tb-tracking-label);
  font-weight: var(--tb-weight-semibold);
}

.visit__value {
  font-size: var(--tb-text-15);
  font-weight: var(--tb-weight-bold);
}

/* Дата, которую уже заняли: зачёркнута, а не убрана — видно, что пропало. */
.visit__value--gone {
  text-decoration: line-through;
}

/* Время стартового созвона под датой: в прототипе его в сводке нет, но
   выбирали его на шаге 3, и проверять запись без него нечестно. */
.visit__sub {
  font-size: var(--tb-text-13);
  color: var(--tb-color-muted);
  margin-top: var(--tb-space-4);
}

.visit__edit {
  font-size: var(--tb-text-12);
  font-weight: var(--tb-weight-semibold);
  border-bottom: var(--tb-border-hairline) solid var(--tb-color-ink);
  flex-shrink: 0;
}

.visit__block {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: var(--tb-space-16);
  padding-bottom: var(--tb-space-16);
  border-bottom: var(--tb-border-hairline) solid var(--tb-color-line);
}

.visit__block--top {
  align-items: flex-start;
  padding-bottom: 0;
  border-bottom: 0;
  margin-bottom: var(--tb-space-12);
}

.visit__services {
  display: flex;
  flex-direction: column;
  gap: var(--tb-space-8);
  margin-bottom: var(--tb-space-16);
  padding-bottom: var(--tb-space-16);
  border-bottom: var(--tb-border-hairline) solid var(--tb-color-line);
}

.visit__service {
  display: flex;
  justify-content: space-between;
  gap: var(--tb-space-12);
  font-size: var(--tb-text-14);
}

.visit__price {
  font-weight: var(--tb-weight-bold);
  font-variant-numeric: tabular-nums;
}

.visit__line {
  display: flex;
  justify-content: space-between;
  margin-bottom: var(--tb-space-4);
}

.visit__line-name {
  font-size: var(--tb-text-14);
  color: var(--tb-color-muted);
}

.visit__line-value {
  font-size: var(--tb-text-14);
  font-weight: var(--tb-weight-semibold);
}

.visit__total {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: var(--tb-space-24);
}

.visit__total-name {
  font-size: var(--tb-text-16);
  font-weight: var(--tb-weight-bold);
}

.visit__total-value {
  font-size: var(--tb-text-20);
  font-weight: var(--tb-weight-black);
  font-variant-numeric: tabular-nums;
}

.visit__total--last {
  margin-bottom: 0;
}

.btn-wide {
  width: 100%;
  padding: var(--tb-space-15);
  background: var(--tb-color-ink);
  color: var(--tb-color-surface);
  border: 0;
  border-radius: var(--tb-radius-pill);
  font-family: inherit;
  font-size: var(--tb-text-15);
  font-weight: var(--tb-weight-semibold);
  cursor: pointer;
}

/* Кнопкой может быть и ссылка — «В личный кабинет» на экране успеха. */
a.btn-wide {
  display: block;
  text-align: center;
  color: var(--tb-color-surface);
}

a.btn-wide--ghost {
  color: var(--tb-color-ink);
}

.btn-wide[disabled] {
  background: var(--tb-color-surface-alt);
  color: var(--tb-color-light);
  cursor: not-allowed;
}

.btn-wide--ghost {
  background: transparent;
  color: var(--tb-color-ink);
  border: var(--tb-border-hairline) solid var(--tb-color-ink);
}

.visit__back {
  display: block;
  text-align: center;
  padding: var(--tb-space-13);
  color: var(--tb-color-outline-dark);
  font-size: var(--tb-text-14);
  font-weight: var(--tb-weight-semibold);
}

/* ========================================================================
   Шаг 4: время заняли (Booking 04b)
   ======================================================================== */

/*
 * Состояние того же экрана, а не отдельная страница: сводка справа остаётся
 * и показывает, что именно пропало, а форма гаснет. Отказ без вариантов —
 * тупик, поэтому вместе с сообщением сервер присылает ближайшие свободные
 * слоты, и они становятся кнопками.
 */
.taken {
  background: var(--tb-color-danger-surface);
  border: var(--tb-border-hairline) solid var(--tb-color-danger-border);
  border-radius: var(--tb-radius-12);
  padding: var(--tb-space-24);
  margin-bottom: var(--tb-space-24);
}

.taken__head {
  display: flex;
  gap: var(--tb-space-12);
  align-items: flex-start;
  margin-bottom: var(--tb-space-16);
}

.taken__badge {
  width: var(--tb-alert-badge);
  height: var(--tb-alert-badge);
  border-radius: var(--tb-radius-circle);
  background: var(--tb-color-danger);
  color: var(--tb-color-surface);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--tb-text-13);
  font-weight: var(--tb-weight-bold);
  flex-shrink: 0;
}

/* Заголовок — сообщение сервера дословно. Своего текста здесь нет. */
.taken__title {
  font-size: var(--tb-text-17);
  font-weight: var(--tb-weight-black);
  color: var(--tb-color-danger-strong);
}

.taken__text {
  font-size: var(--tb-text-13);
  color: var(--tb-color-danger-text);
  line-height: var(--tb-leading-snug);
  margin: var(--tb-space-4) 0 0;
}

.taken__slots {
  display: flex;
  gap: var(--tb-space-10);
  margin-bottom: var(--tb-space-14);
  flex-wrap: wrap;
}

.taken__slot {
  flex: 1;
  padding: var(--tb-space-12);
  background: var(--tb-color-surface);
  color: var(--tb-color-danger-strong);
  border: var(--tb-border-hairline) solid var(--tb-color-danger-border);
  border-radius: var(--tb-radius-pill);
  font-family: inherit;
  font-size: var(--tb-text-13);
  font-weight: var(--tb-weight-semibold);
  cursor: pointer;
}

.taken__slot[disabled] {
  cursor: wait;
}

.taken__link {
  display: inline-block;
  font-size: var(--tb-text-13);
  font-weight: var(--tb-weight-semibold);
  color: var(--tb-color-danger-strong);
  border-bottom: var(--tb-border-hairline) solid var(--tb-color-danger-strong);
}

/* ========================================================================
   Шаг 4: прочие отказы сервера
   ======================================================================== */

/* 401, 429, истёкшая бронь — текст сервера над формой, без своих слов. */
.alert {
  display: flex;
  gap: var(--tb-space-12);
  align-items: flex-start;
  background: var(--tb-color-danger-surface);
  border: var(--tb-border-hairline) solid var(--tb-color-danger-border);
  border-radius: var(--tb-radius-8);
  padding: var(--tb-space-16);
  margin-bottom: var(--tb-space-24);
  font-size: var(--tb-text-14);
  color: var(--tb-color-danger-strong);
  line-height: var(--tb-leading-snug);
}

.alert__badge {
  width: var(--tb-alert-icon-size);
  height: var(--tb-alert-icon-size);
  border-radius: var(--tb-radius-circle);
  background: var(--tb-color-danger);
  color: var(--tb-color-surface);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--tb-text-12);
  font-weight: var(--tb-weight-bold);
  flex-shrink: 0;
}

.alert__link {
  font-weight: var(--tb-weight-semibold);
  color: var(--tb-color-danger-strong);
  border-bottom: var(--tb-border-hairline) solid var(--tb-color-danger-strong);
}

/* ========================================================================
   Экран успеха (Booking 05)
   ======================================================================== */

.done {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--tb-space-64) var(--tb-space-32);
}

.done__card {
  width: 100%;
  max-width: var(--tb-success-width);
  text-align: center;
}

.done__icon {
  width: var(--tb-status-icon-xl);
  height: var(--tb-status-icon-xl);
  border-radius: var(--tb-radius-circle);
  background: var(--tb-color-success-surface);
  color: var(--tb-color-success);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--tb-text-32);
  font-weight: var(--tb-weight-black);
  margin: 0 auto var(--tb-space-28);
}

.done__title {
  font-size: var(--tb-text-36);
  font-weight: var(--tb-weight-black);
  letter-spacing: var(--tb-tracking-tight);
  margin: 0 0 var(--tb-space-32);
}

.done__facts {
  text-align: left;
  border: var(--tb-border-hairline) solid var(--tb-color-line);
  border-radius: var(--tb-radius-16);
  padding: var(--tb-space-24);
  margin-bottom: var(--tb-space-16);
  display: flex;
  flex-direction: column;
  gap: var(--tb-space-12);
}

.done__fact {
  display: flex;
  justify-content: space-between;
  gap: var(--tb-space-16);
  font-size: var(--tb-text-14);
}

.done__fact-name {
  color: var(--tb-color-muted);
  flex-shrink: 0;
}

.done__fact-value {
  font-weight: var(--tb-weight-semibold);
  text-align: right;
}

.done__fact--total {
  padding-top: var(--tb-space-12);
  border-top: var(--tb-border-hairline) solid var(--tb-color-line);
}

.done__fact--total .done__fact-value {
  font-size: var(--tb-text-17);
  font-weight: var(--tb-weight-black);
  font-variant-numeric: tabular-nums;
}

.done__note {
  font-size: var(--tb-text-13);
  color: var(--tb-color-muted);
  margin: 0 0 var(--tb-space-32);
}

.done__actions {
  display: flex;
  flex-direction: column;
  gap: var(--tb-space-10);
}

.done__again {
  padding: var(--tb-space-13);
  font-size: var(--tb-text-14);
  font-weight: var(--tb-weight-semibold);
  color: var(--tb-color-outline-dark);
}

/* ========================================================================
   Перенос записи — Booking 06
   ======================================================================== */

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

.moving {
  background: var(--tb-color-surface-alt);
  padding: var(--tb-space-16) var(--tb-space-32);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--tb-space-16);
}

.moving__text {
  font-size: var(--tb-text-14);
  font-weight: var(--tb-weight-semibold);
}

.moving__cancel {
  font-size: var(--tb-text-13);
  font-weight: var(--tb-weight-semibold);
  border-bottom: var(--tb-border-hairline) solid var(--tb-color-ink);
  flex-shrink: 0;
}

/* Остаток переносов — предупреждение, а не подпись: их конечное число. */
.limit {
  display: flex;
  gap: var(--tb-space-10);
  align-items: flex-start;
  background: var(--tb-color-warning-surface);
  border: var(--tb-border-hairline) solid var(--tb-color-warning-border);
  border-radius: var(--tb-radius-8);
  padding: var(--tb-space-12) var(--tb-space-14);
  margin-bottom: var(--tb-space-28);
}

.limit__badge {
  width: var(--tb-alert-icon-size);
  height: var(--tb-alert-icon-size);
  border-radius: var(--tb-radius-circle);
  background: var(--tb-color-warning);
  color: var(--tb-color-surface);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--tb-text-11);
  font-weight: var(--tb-weight-bold);
  flex-shrink: 0;
}

.limit__text {
  font-size: var(--tb-text-13);
  color: var(--tb-color-warning-strong);
  line-height: var(--tb-leading-compact);
}

/* Старая дата в календаре: обведена, но выбрать её нельзя — перенос на тот
   же день сервис отклоняет. */
.calendar__day--current {
  border: var(--tb-border-thick) solid var(--tb-color-outline-dark);
  font-weight: var(--tb-weight-bold);
}

.legend {
  display: flex;
  gap: var(--tb-space-16);
  margin-top: var(--tb-space-16);
  font-size: var(--tb-text-11);
  color: var(--tb-color-muted);
}

.legend__mark {
  display: inline-block;
  width: var(--tb-dot);
  height: var(--tb-dot);
  border-radius: var(--tb-radius-circle);
  margin-right: var(--tb-space-4);
}

.legend__mark--current {
  border: var(--tb-border-thick) solid var(--tb-color-outline-dark);
}

.legend__mark--new {
  background: var(--tb-color-ink);
}

/* ========================================================================
   Запись перенесена — Booking 07
   ======================================================================== */

/*
 * Тот же строй, что у экрана успеха, но шире: здесь две карточки в ряд —
 * «Было» и «Стало». Отдельный экран нужен именно ради этой пары: на
 * карточке записи видна только новая дата, а перенос это про обе.
 */
.done__card--wide {
  max-width: var(--tb-moved-width);
}

.done__icon--sm {
  width: var(--tb-status-icon-lg);
  height: var(--tb-status-icon-lg);
  font-size: var(--tb-text-28);
  margin-bottom: var(--tb-space-24);
}

.done__title--moved {
  font-size: var(--tb-text-34);
}

.swap {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--tb-space-16);
  margin-bottom: var(--tb-space-24);
}

.swap__box {
  border: var(--tb-border-hairline) solid var(--tb-color-line);
  border-radius: var(--tb-radius-16);
  padding: var(--tb-space-24);
}

/* Прежняя дата: приглушена и зачёркнута — её больше нет. */
.swap__box--was {
  opacity: var(--tb-opacity-disabled);
}

.swap__box--now {
  border-color: var(--tb-color-ink);
  background: var(--tb-color-surface-alt);
}

.swap__caption {
  font-size: var(--tb-text-12);
  font-weight: var(--tb-weight-semibold);
  text-transform: uppercase;
  letter-spacing: var(--tb-tracking-label);
  color: var(--tb-color-muted);
  margin-bottom: var(--tb-space-8);
}

.swap__value {
  font-size: var(--tb-text-19);
  font-weight: var(--tb-weight-bold);
}

.swap__box--was .swap__value {
  text-decoration: line-through;
  color: var(--tb-color-dim);
}

.swap__box--now .swap__value {
  font-weight: var(--tb-weight-black);
}

/* ========================================================================
   Узкий экран
   ======================================================================== */

/*
 * Шаги записи те же и в том же порядке; меняется только то, что на узком
 * экране не помещается. Ничего не убирается — на телефоне доступны те же
 * услуги, те же дни и то же время, что на компьютере.
 *
 * Значения точек перелома — в конце `tokens.css`.
 */

@media (max-width: 1279px) {
  /* 1280 px — ширина прототипа, а не требование к окну. */
  body {
    min-width: 0;
  }

  .booking {
    width: 100%;
  }
}

@media (max-width: 900px) {
  /*
   * Две колонки становятся одной. На выборе времени сверху остаётся
   * календарь, под ним — сетка слотов: сначала выбирают день, потом час, и
   * этот же порядок читается сверху вниз.
   */
  .picker,
  .confirm {
    grid-template-columns: 1fr;
    gap: var(--tb-space-28);
  }

  /* Сводка визита в одной колонке не липнет: липкий блок во всю ширину
     закрыл бы форму, к которой человек как раз возвращается. */
  .visit {
    position: static;
  }

  .booking__header,
  .steps,
  .moving,
  .summary,
  .navbar {
    padding-left: var(--tb-space-20);
    padding-right: var(--tb-space-20);
  }

  .booking__body {
    padding: var(--tb-space-28) var(--tb-space-20);
  }

  .specialists {
    grid-template-columns: repeat(2, 1fr);
  }

  .swap {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 600px) {
  /*
   * Шагомер: подписи в четыре колонки наезжают друг на друга, поэтому
   * отрезки между кружками убираются, а подписи получают всю ширину своей
   * доли и переносятся по словам. Ни один шаг не пропадает — иначе по
   * шагомеру нельзя вернуться назад.
   */
  .steps {
    padding: var(--tb-space-16) var(--tb-space-12);
  }

  .steps__row {
    gap: var(--tb-space-4);
  }

  .steps__line {
    display: none;
  }

  .step {
    min-width: 0;
  }

  .step__label {
    font-size: var(--tb-text-10);
    margin-top: var(--tb-space-6);
    text-align: center;
    line-height: var(--tb-leading-compact);
    overflow-wrap: anywhere;
  }

  /* Карточки услуг и специалистов — в один столбец. */
  .services,
  .specialists {
    grid-template-columns: 1fr;
  }

  /*
   * Сетка времени — в два столбца: три кнопки в ряд на телефоне сужаются
   * до полоски, в которую не попасть пальцем. Высота кнопки — не меньше
   * пальца (`--tb-tap`), и это относится и к занятому времени: оно
   * остаётся видимым, просто не нажимается.
   */
  .times__row {
    grid-template-columns: repeat(2, 1fr);
    gap: var(--tb-space-8);
  }

  .slot {
    min-height: var(--tb-tap);
    font-size: var(--tb-text-15);
  }

  /* День месяца — такая же цель для пальца, но в сетке из семи столбцов:
     квадрат по ширине доли, а не по содержимому. */
  .calendar {
    padding: var(--tb-space-16);
  }

  .calendar__day {
    aspect-ratio: 1;
    padding: 0;
    font-size: var(--tb-text-14);
  }

  .calendar__weekdays,
  .calendar__days {
    gap: var(--tb-space-2);
  }

  /*
   * Панели итога и навигации остаются внизу и не наезжают на содержимое:
   * `sticky` занимает место в потоке, поэтому последняя карточка списка
   * не уходит под панель. На телефоне строка панели переносится, а кнопка
   * растягивается во всю ширину — по ней проще попасть.
   */
  .summary,
  .navbar {
    padding: var(--tb-space-14) var(--tb-space-16);
  }

  .summary__row,
  .navbar__row {
    flex-wrap: wrap;
    gap: var(--tb-space-10);
  }

  .navbar__next {
    flex-wrap: wrap;
    width: 100%;
  }

  .summary__price {
    margin-left: auto;
  }

  .btn-next,
  .btn-dark {
    width: 100%;
    min-height: var(--tb-tap);
  }

  .summary__hint,
  .navbar__hint {
    width: 100%;
  }

  /* Шапка шага: «Отменить запись» словами и ✕ рядом не помещаются. */
  .booking__header {
    padding: var(--tb-space-14) var(--tb-space-16);
  }

  .moving {
    flex-wrap: wrap;
    gap: var(--tb-space-8);
  }

  .chosen,
  .recap {
    flex-wrap: wrap;
    gap: var(--tb-space-8);
  }

  .booking__title {
    font-size: var(--tb-text-28);
  }

  .visit__card,
  .done__card,
  .taken {
    padding: var(--tb-space-20);
  }

  /* Ближайшие свободные точки — в столбец: три пилюли в ряд не помещаются. */
  .taken__slots {
    flex-direction: column;
  }

  .taken__slot {
    min-height: var(--tb-tap);
  }

  .legend {
    flex-wrap: wrap;
    gap: var(--tb-space-10);
  }

  .btn-wide {
    min-height: var(--tb-tap);
  }
}

