/*
 * Личный кабинет: экраны `Кабинет 01 - Активные записи`,
 * `Кабинет 05 - Детали записи` и окно отмены `Cabinet 06` / `Cabinet 07`.
 *
 * Общий файл на все три: у них одна шапка, одна колонка шириной 1000 px и
 * одни карточки. Окно отмены живёт здесь же — в прототипе оно нарисовано
 * поверх экрана деталей, а не отдельной страницей.
 *
 * Правило то же, что на остальных экранах: ни одного значения напрямую —
 * только `var(--tb-*)` из `tokens.css`. Проверяется так:
 *
 *   grep -nE '#[0-9A-Fa-f]{3,8}|[0-9]+px|rgba?\(' web/account.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,
select:focus-visible {
  outline: var(--tb-border-hairline) solid currentColor;
  outline-offset: var(--tb-space-4);
}

.cabinet {
  min-height: 100vh;
  width: var(--tb-page-width);
  margin: 0 auto;
}

.cabinet__body {
  max-width: var(--tb-cabinet-width);
  margin: 0 auto;
  padding: var(--tb-space-40) var(--tb-space-32) var(--tb-space-64);
}

/* ========================================================================
   Шапка кабинета
   ======================================================================== */

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

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

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

.top__nav {
  display: flex;
  gap: var(--tb-space-24);
}

.top__link {
  color: var(--tb-color-dim);
  font-size: var(--tb-text-14);
}

.top__link--current {
  color: var(--tb-color-surface);
  font-weight: var(--tb-weight-semibold);
}

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

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

.top__initials {
  width: var(--tb-initials-size);
  height: var(--tb-initials-size);
  border-radius: var(--tb-radius-circle);
  background: var(--tb-color-line-dark);
  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;
}

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

.top__logout {
  background: transparent;
  border: 0;
  color: var(--tb-color-dim);
  font-family: inherit;
  font-size: var(--tb-text-14);
  cursor: pointer;
  padding: 0;
}

/* ========================================================================
   Заголовок списка
   ======================================================================== */

.head {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: var(--tb-space-24);
  margin-bottom: var(--tb-space-28);
}

.head__title {
  font-size: var(--tb-text-30);
  font-weight: var(--tb-weight-black);
  letter-spacing: var(--tb-tracking-tight);
  margin: 0 0 var(--tb-space-6);
}

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

.btn-pill {
  display: inline-block;
  padding: var(--tb-space-12) var(--tb-space-22);
  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-14);
  font-weight: var(--tb-weight-semibold);
  cursor: pointer;
  flex-shrink: 0;
}

/* ========================================================================
   Вкладки
   ======================================================================== */

.tabs {
  display: flex;
  gap: var(--tb-space-28);
  border-bottom: var(--tb-border-hairline) solid var(--tb-color-line);
  margin-bottom: var(--tb-space-28);
}

.tab {
  padding: 0 0 var(--tb-space-12);
  background: transparent;
  border: 0;
  border-bottom: var(--tb-border-thick) solid transparent;
  font-family: inherit;
  font-size: var(--tb-text-14);
  color: var(--tb-color-muted);
  cursor: pointer;
}

.tab[aria-selected='true'] {
  border-bottom-color: var(--tb-color-ink);
  color: var(--tb-color-ink);
  font-weight: var(--tb-weight-semibold);
}

.tab__count {
  color: var(--tb-color-dim);
  margin-left: var(--tb-space-4);
}

.tab[aria-selected='true'] .tab__count {
  color: var(--tb-color-muted);
  font-weight: var(--tb-weight-medium);
}

/* ========================================================================
   Карточка записи в списке
   ======================================================================== */

.record {
  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);
}

/*
 * Ближайший визит. В прототипе обе карточки нарисованы одинаково, но
 * «ближайший» — это то, ради чего кабинет открывают, и на списке из пяти
 * записей он теряется. Выделение сделано теми же средствами, что и выбор на
 * шагах записи: рамка цветом текста, без нового цвета и без заливки.
 */
.record--next {
  border-color: var(--tb-color-ink);
}

.record__top {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--tb-space-24);
  flex-wrap: wrap;
}

.record__main {
  flex: 1;
  min-width: var(--tb-cabinet-card-min);
}

.record__marks {
  display: flex;
  align-items: center;
  gap: var(--tb-space-10);
  margin-bottom: var(--tb-space-10);
  flex-wrap: wrap;
}

.status {
  font-size: var(--tb-text-11);
  font-weight: var(--tb-weight-bold);
  padding: var(--tb-space-4) var(--tb-space-10);
  border-radius: var(--tb-radius-pill);
  text-transform: uppercase;
  letter-spacing: var(--tb-tracking-chip);
  background: var(--tb-color-surface-alt);
  color: var(--tb-color-outline-dark);
  white-space: nowrap;
}

.status--confirmed {
  background: var(--tb-color-success-surface);
  color: var(--tb-color-success);
}

.status--cancelled {
  background: var(--tb-color-danger-surface);
  color: var(--tb-color-danger);
}

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

.record__title {
  font-size: var(--tb-text-20);
  font-weight: var(--tb-weight-black);
  display: block;
  margin-bottom: var(--tb-space-12);
}

.record__services {
  font-size: var(--tb-text-14);
  color: var(--tb-color-outline-dark);
  margin-bottom: var(--tb-space-6);
}

.record__person {
  display: flex;
  align-items: center;
  gap: var(--tb-space-8);
  font-size: var(--tb-text-14);
  color: var(--tb-color-muted);
}

.initials {
  width: var(--tb-initials-inline);
  height: var(--tb-initials-inline);
  border-radius: var(--tb-radius-circle);
  background: var(--tb-color-surface-alt);
  color: var(--tb-color-outline-dark);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: var(--tb-text-10);
  font-weight: var(--tb-weight-bold);
  flex-shrink: 0;
}

.record__side {
  text-align: right;
  min-width: var(--tb-cabinet-side-min);
}

.record__price {
  font-size: var(--tb-text-22);
  font-weight: var(--tb-weight-black);
  margin-bottom: var(--tb-space-4);
}

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

.record__actions {
  display: flex;
  gap: var(--tb-space-10);
  margin-top: var(--tb-space-20);
  padding-top: var(--tb-space-20);
  border-top: var(--tb-border-hairline) solid var(--tb-color-surface-alt);
  flex-wrap: wrap;
}

.btn-line {
  display: inline-block;
  padding: var(--tb-space-10) var(--tb-space-18);
  border: var(--tb-border-hairline) solid var(--tb-color-light);
  border-radius: var(--tb-radius-pill);
  background: transparent;
  color: var(--tb-color-ink);
  font-family: inherit;
  font-size: var(--tb-text-13);
  font-weight: var(--tb-weight-semibold);
  cursor: pointer;
}

.btn-quiet {
  display: inline-block;
  padding: var(--tb-space-10) var(--tb-space-18);
  border: 0;
  border-radius: var(--tb-radius-pill);
  background: transparent;
  color: var(--tb-color-danger);
  font-family: inherit;
  font-size: var(--tb-text-13);
  font-weight: var(--tb-weight-semibold);
  cursor: pointer;
}

/* ========================================================================
   Пустой список — состояние того же экрана
   ======================================================================== */

/*
 * Записей нет — это состояние списка, а не отдельная страница: вкладки,
 * счётчики и кнопка «Записаться» остаются на месте, меняется только то,
 * что стоит вместо карточек.
 */
.empty {
  border: var(--tb-border-hairline) solid var(--tb-color-line);
  border-radius: var(--tb-radius-16);
  padding: var(--tb-space-56) var(--tb-space-24);
  text-align: center;
}

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

.empty__text {
  font-size: var(--tb-text-14);
  color: var(--tb-color-muted);
  margin-bottom: var(--tb-space-24);
}

.footnote {
  font-size: var(--tb-text-13);
  color: var(--tb-color-dim);
  margin-top: var(--tb-space-24);
}

.footnote a {
  color: var(--tb-color-muted);
  text-decoration: underline;
}

/* ========================================================================
   Экран деталей
   ======================================================================== */

.crumbs {
  font-size: var(--tb-text-13);
  color: var(--tb-color-muted);
  margin-bottom: var(--tb-space-24);
}

.crumbs a {
  color: var(--tb-color-muted);
}

.crumbs__sep {
  color: var(--tb-color-light);
}

.crumbs__here {
  color: var(--tb-color-ink);
  font-weight: var(--tb-weight-semibold);
}

.details__head {
  display: flex;
  align-items: center;
  gap: var(--tb-space-14);
  margin-bottom: var(--tb-space-8);
  flex-wrap: wrap;
}

.details__title {
  font-size: var(--tb-text-30);
  font-weight: var(--tb-weight-black);
  letter-spacing: var(--tb-tracking-tight);
  margin: 0;
}

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

.details__columns {
  display: flex;
  gap: var(--tb-space-24);
  align-items: flex-start;
  flex-wrap: wrap;
}

.details__main {
  flex: 1;
  min-width: var(--tb-cabinet-main-min);
}

.details__aside {
  width: var(--tb-cabinet-aside);
  flex-shrink: 0;
}

.panel {
  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);
}

.panel:last-child {
  margin-bottom: 0;
}

.panel__caption {
  font-size: var(--tb-text-11);
  font-weight: var(--tb-weight-bold);
  color: var(--tb-color-dim);
  text-transform: uppercase;
  letter-spacing: var(--tb-tracking-caption);
  margin-bottom: var(--tb-space-18);
}

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

.line:last-child {
  margin-bottom: 0;
}

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

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

/* Продолжительность стоит в том же списке, но это не позиция заказа. */
.line--service.line--muted .line__name,
.line--service.line--muted .line__value {
  color: var(--tb-color-muted);
  font-weight: var(--tb-weight-medium);
}

/* Состав заказа: строки разделены, итог крупнее. */
.line--service {
  margin-bottom: 0;
  padding: var(--tb-space-14) 0;
  border-bottom: var(--tb-border-hairline) solid var(--tb-color-surface-alt);
}

.line--service:first-of-type {
  padding-top: 0;
}

.line--total {
  align-items: center;
  padding-top: var(--tb-space-16);
  margin-bottom: 0;
}

.line--total .line__name {
  font-size: var(--tb-text-15);
  font-weight: var(--tb-weight-bold);
  color: var(--tb-color-ink);
}

.line--total .line__value {
  font-size: var(--tb-text-22);
  font-weight: var(--tb-weight-black);
  font-variant-numeric: tabular-nums;
}

.comment {
  background: var(--tb-color-surface-alt);
  border-radius: var(--tb-radius-12);
  padding: var(--tb-space-14) var(--tb-space-16);
  font-size: var(--tb-text-14);
  color: var(--tb-color-outline-dark);
  line-height: var(--tb-leading-snug);
  margin-top: var(--tb-space-16);
}

/* ========================================================================
   История событий
   ======================================================================== */

.event {
  display: flex;
  gap: var(--tb-space-12);
  margin-bottom: var(--tb-space-16);
}

.event:last-child {
  margin-bottom: 0;
}

.event__dot {
  width: var(--tb-dot);
  height: var(--tb-dot);
  border-radius: var(--tb-radius-circle);
  background: var(--tb-color-light);
  margin-top: var(--tb-space-6);
  flex-shrink: 0;
}

.event__dot--good {
  background: var(--tb-color-success);
}

.event__dot--bad {
  background: var(--tb-color-danger);
}

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

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

/* ========================================================================
   Управление записью
   ======================================================================== */

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

.manage__left {
  font-size: var(--tb-text-13);
  color: var(--tb-color-muted);
  margin-bottom: var(--tb-space-20);
}

.btn-block {
  display: block;
  width: 100%;
  text-align: center;
  padding: var(--tb-space-13) var(--tb-space-20);
  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-14);
  font-weight: var(--tb-weight-semibold);
  cursor: pointer;
  margin-bottom: var(--tb-space-10);
}

.btn-block--danger {
  background: transparent;
  border: var(--tb-border-hairline) solid var(--tb-color-light);
  color: var(--tb-color-danger);
}

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

.manage__rules {
  font-size: var(--tb-text-12);
  color: var(--tb-color-dim);
  line-height: var(--tb-leading-snug);
  margin-top: var(--tb-space-16);
}

.manage__link {
  display: inline-block;
  font-size: var(--tb-text-13);
  color: var(--tb-color-muted);
  text-decoration: underline;
  margin-top: var(--tb-space-10);
}

/* ========================================================================
   Окно отмены — Cabinet 06 и Cabinet 07
   ======================================================================== */

/*
 * Одно окно на оба листа прототипа. `Cabinet 07` отличается предупреждением
 * о поздней отмене и предложением переноса — это состояние того же окна, и
 * выбирает его сервер: `cancellation.is_free_now`.
 */
.modal {
  position: fixed;
  inset: 0;
  background: var(--tb-overlay-modal);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--tb-space-24);
  z-index: var(--tb-z-modal);
}

.modal[hidden] {
  display: none;
}

.modal__box {
  background: var(--tb-color-surface);
  border-radius: var(--tb-radius-16);
  padding: var(--tb-space-32);
  width: 100%;
  max-width: var(--tb-modal-width);
  box-shadow: var(--tb-shadow-modal);
  max-height: 100%;
  overflow-y: auto;
}

.modal__title {
  font-size: var(--tb-text-22);
  font-weight: var(--tb-weight-black);
  letter-spacing: var(--tb-tracking-tight);
  margin: 0 0 var(--tb-space-20);
}

.modal__summary {
  border: var(--tb-border-hairline) solid var(--tb-color-line);
  border-radius: var(--tb-radius-12);
  padding: var(--tb-space-18);
  margin-bottom: var(--tb-space-16);
}

.modal__summary .line {
  margin-bottom: var(--tb-space-10);
}

.modal__summary .line:last-child {
  margin-bottom: 0;
}

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

/* Предупреждение о поздней отмене — лист `Cabinet 07`. */
.warn {
  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-20);
}

.warn__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;
}

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

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

.modal__select {
  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);
  margin-bottom: var(--tb-space-20);
}

.modal__instead {
  text-align: center;
  margin-bottom: var(--tb-space-20);
}

.modal__instead a {
  font-size: var(--tb-text-13);
  font-weight: var(--tb-weight-semibold);
  border-bottom: var(--tb-border-hairline) solid var(--tb-color-ink);
}

.modal__actions {
  display: flex;
  gap: var(--tb-space-10);
  justify-content: flex-end;
  align-items: center;
}

/* Чего не хватает, чтобы кнопка ожила — рядом с ней, как на шагах записи. */
.modal__hint {
  font-size: var(--tb-text-13);
  color: var(--tb-color-muted);
  margin-right: auto;
}

.btn-danger[disabled] {
  background: var(--tb-color-danger-border);
  color: var(--tb-color-danger-strong);
  cursor: not-allowed;
}

.btn-plain,
.btn-danger {
  padding: var(--tb-space-11) var(--tb-space-20);
  border: 0;
  border-radius: var(--tb-radius-pill);
  font-family: inherit;
  font-size: var(--tb-text-14);
  font-weight: var(--tb-weight-semibold);
  cursor: pointer;
}

.btn-plain {
  background: transparent;
  color: var(--tb-color-ink);
}

.btn-danger {
  background: var(--tb-color-danger);
  color: var(--tb-color-surface);
}

/* На время запроса кнопка занята — курсор говорит об этом. */
.btn-danger--busy[disabled] {
  cursor: wait;
}

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

/* Любой неуспешный ответ становится видимым текстом: `message` написан для
   человека, его и показываем. */
.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;
}

.load-error {
  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;
}

.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: 45%; margin-bottom: var(--tb-space-12); }
.skeleton-line--text  { width: 70%; }
.skeleton-line--meta  { height: var(--tb-space-16); width: 30%; margin-bottom: 0; }

/* ========================================================================
   Шапка: колокольчик и профиль
   ======================================================================== */

.top__bell {
  position: relative;
  color: var(--tb-color-light);
  font-size: var(--tb-text-16);
  line-height: var(--tb-leading-solid);
}

/* Счётчик непрочитанных. Ноль не рисуется вовсе: пустой кружок сообщает
   ровно столько же, сколько его отсутствие, но требует внимания. */
.top__badge {
  position: absolute;
  top: calc(-1 * var(--tb-space-6));
  right: calc(-1 * var(--tb-space-8));
  min-width: var(--tb-badge-size);
  height: var(--tb-badge-size);
  padding: 0 var(--tb-space-4);
  border-radius: var(--tb-radius-pill);
  background: var(--tb-color-danger);
  color: var(--tb-color-surface);
  font-size: var(--tb-text-10);
  font-weight: var(--tb-weight-bold);
  display: flex;
  align-items: center;
  justify-content: center;
}

/* ========================================================================
   Лента уведомлений — Notif 01
   ======================================================================== */

.feed {
  max-width: var(--tb-feed-width);
  margin: 0 auto;
  padding: var(--tb-space-48) var(--tb-space-32);
}

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

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

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

/*
 * Карточка уведомления. Непрочитанное выделено фоном и рамкой, а не только
 * точкой справа: точка на краю карточки читается последней.
 */
.notice {
  display: flex;
  gap: var(--tb-space-14);
  padding: var(--tb-space-18) var(--tb-space-20);
  border-radius: var(--tb-radius-12);
  border: var(--tb-border-hairline) solid transparent;
  background: transparent;
  color: inherit;
  font-family: inherit;
  text-align: left;
  width: 100%;
}

button.notice {
  cursor: pointer;
}

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

/* Отмена сервисом — единственный тип, который отличается цветом: это
   сообщение о том, что планы человека сорвались не по его вине. */
.notice--alarm {
  background: var(--tb-color-danger-surface);
}

.notice__icon {
  width: var(--tb-notice-icon);
  height: var(--tb-notice-icon);
  border-radius: var(--tb-radius-circle);
  background: var(--tb-color-surface-alt);
  color: var(--tb-color-outline-dark);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--tb-text-14);
  flex-shrink: 0;
}

.notice--unread .notice__icon {
  background: var(--tb-color-ink);
  color: var(--tb-color-surface);
}

.notice--good .notice__icon {
  background: var(--tb-color-success-surface);
  color: var(--tb-color-success);
}

.notice--alarm .notice__icon {
  background: var(--tb-color-surface);
  color: var(--tb-color-danger);
}

.notice__body {
  flex: 1;
}

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

.notice--unread .notice__title {
  font-weight: var(--tb-weight-bold);
}

.notice__text {
  display: block;
  font-size: var(--tb-text-13);
  color: var(--tb-color-outline-dark);
  line-height: var(--tb-leading-snug);
  margin-top: var(--tb-space-4);
}

.notice__when {
  display: block;
  font-size: var(--tb-text-12);
  color: var(--tb-color-muted);
  margin-top: var(--tb-space-4);
}

.notice__action {
  display: inline-block;
  margin-top: var(--tb-space-10);
  padding: var(--tb-space-9) var(--tb-space-18);
  border-radius: var(--tb-radius-pill);
  background: var(--tb-color-ink);
  color: var(--tb-color-surface);
  font-size: var(--tb-text-12);
  font-weight: var(--tb-weight-semibold);
}

.notice__dot {
  width: var(--tb-dot);
  height: var(--tb-dot);
  border-radius: var(--tb-radius-circle);
  background: var(--tb-color-ink);
  flex-shrink: 0;
  margin-top: var(--tb-space-6);
}

/* ========================================================================
   Профиль — Profile 01 и Profile 02
   ======================================================================== */

.profile {
  max-width: var(--tb-profile-width);
  margin: 0 auto;
  padding: var(--tb-space-48) var(--tb-space-32);
}

.profile__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-32);
}

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

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

.submenu__link {
  padding: var(--tb-space-10) var(--tb-space-14);
  border-radius: var(--tb-radius-8);
  color: var(--tb-color-muted);
  font-size: var(--tb-text-14);
}

.submenu__link--current {
  background: var(--tb-color-surface-alt);
  color: var(--tb-color-ink);
  font-weight: var(--tb-weight-semibold);
}

.profile__person {
  display: flex;
  align-items: center;
  gap: var(--tb-space-16);
  margin-bottom: var(--tb-space-28);
}

.profile__initials {
  width: var(--tb-profile-avatar);
  height: var(--tb-profile-avatar);
  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-20);
  font-weight: var(--tb-weight-bold);
  flex-shrink: 0;
  overflow: hidden;
}

.profile__initials img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

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

/*
 * Поля формы профиля.
 *
 * Разметка `Profile 01` и `Profile 02` использует те же классы, что формы
 * на шагах записи и на экранах входа, — но оформления у них здесь не было,
 * и браузер рисовал поля по умолчанию: подпись в строку с полем, ширина по
 * содержимому. Правила повторяют `booking.css` теми же токенами, чтобы поле
 * в профиле выглядело так же, как поле в заказе.
 */
.fields {
  display: flex;
  flex-direction: column;
  gap: var(--tb-space-16);
  margin-bottom: var(--tb-space-24);
}

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

.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);
}

/* Почта показывается, но не правится: смена адреса меняет и вход. */
.field__input[readonly],
.field__input[disabled] {
  background: var(--tb-color-surface-alt);
  color: var(--tb-color-muted);
}

/* Неверное поле называет сервер в `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;
}

/* Подтверждённая почта — метка внутри поля, как в прототипе. */
.field__wrap {
  position: relative;
}

.field__badge {
  position: absolute;
  right: var(--tb-space-10);
  top: 50%;
  transform: translateY(-50%);
  padding: var(--tb-space-4) var(--tb-space-12);
  border-radius: var(--tb-radius-pill);
  background: var(--tb-color-success-surface);
  color: var(--tb-color-success);
  font-size: var(--tb-text-11);
  font-weight: var(--tb-weight-semibold);
}

.profile__buttons {
  display: flex;
  gap: var(--tb-space-10);
  margin-bottom: var(--tb-space-40);
}

.btn-mid {
  padding: var(--tb-space-12) var(--tb-space-24);
  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-14);
  font-weight: var(--tb-weight-semibold);
  cursor: pointer;
}

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

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

.profile__danger {
  border-top: var(--tb-border-hairline) solid var(--tb-color-line);
  padding-top: var(--tb-space-24);
}

.profile__danger-link {
  font-size: var(--tb-text-14);
  font-weight: var(--tb-weight-semibold);
  color: var(--tb-color-danger);
  border: 0;
  border-bottom: var(--tb-border-hairline) solid var(--tb-color-danger-border);
  background: transparent;
  font-family: inherit;
  padding: 0;
  cursor: pointer;
}

.profile__danger-text {
  font-size: var(--tb-text-13);
  color: var(--tb-color-muted);
  margin: var(--tb-space-8) 0 0;
  max-width: var(--tb-auth-visual-width);
}

/* Надёжность нового пароля — те же три полоски, что на экранах входа. */
.strength {
  display: flex;
  gap: var(--tb-space-4);
  margin-top: var(--tb-space-8);
}

.strength__bar {
  flex: 1;
  height: var(--tb-strength-bar-height);
  border-radius: var(--tb-radius-2);
  background: var(--tb-color-line);
}

.strength__bar--weak   { background: var(--tb-color-danger); }
.strength__bar--medium { background: var(--tb-color-warning); }
.strength__bar--strong { background: var(--tb-color-success); }

.strength__hint {
  font-size: var(--tb-text-11);
  color: var(--tb-color-muted);
  margin-top: var(--tb-space-6);
}

/* ========================================================================
   Активные сессии
   ======================================================================== */

.sessions {
  border-top: var(--tb-border-hairline) solid var(--tb-color-line);
  padding-top: var(--tb-space-24);
  margin-top: var(--tb-space-40);
}

.sessions__caption {
  font-size: var(--tb-text-13);
  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-16);
}

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

.session {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--tb-space-16);
  border: var(--tb-border-hairline) solid var(--tb-color-line);
  border-radius: var(--tb-radius-12);
  padding: var(--tb-space-16) var(--tb-space-18);
}

.session__name {
  font-size: var(--tb-text-14);
  font-weight: var(--tb-weight-bold);
}

.session__where {
  font-size: var(--tb-text-12);
  color: var(--tb-color-muted);
  margin-top: var(--tb-space-2);
}

.session__current {
  font-size: var(--tb-text-12);
  color: var(--tb-color-success);
  font-weight: var(--tb-weight-semibold);
  flex-shrink: 0;
}

.btn-revoke {
  padding: var(--tb-space-9) var(--tb-space-18);
  background: transparent;
  color: var(--tb-color-danger);
  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;
  flex-shrink: 0;
}

/* Сообщение об удаче — на месте отказа, тем же блоком. */
.done-note {
  display: flex;
  gap: var(--tb-space-12);
  align-items: flex-start;
  background: var(--tb-color-success-surface);
  border: var(--tb-border-hairline) solid var(--tb-color-success);
  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-success);
  line-height: var(--tb-leading-snug);
}

/* ========================================================================
   Раздел администратора — справочники услуг и специалистов
   ======================================================================== */

/*
 * Своего файла стилей у раздела нет — это правило 8 `frontend-rules.md`:
 * страницы `/admin` подключают `account.css` и пользуются его классами.
 * Строка справочника — `record`, метка — `status`, кнопки — `btn-line` и
 * `btn-quiet`, форма — `modal` и `fields`, пустой список — `empty`.
 *
 * Ниже только то, чего в кабинете нет вовсе: приглушённая строка
 * отключённой услуги, форма справочника в две колонки и отметки услуг
 * флажками. Новых токенов при этом не заводится — правило 4.
 */

/*
 * Отключённая строка. Она не исчезает из списка и не уезжает вниз:
 * администратор должен видеть её, чтобы включить обратно, а клиенту она не
 * показывается вовсе — это решает сервер, а не оформление.
 */
.record--off {
  border-style: dashed;
  background: var(--tb-color-surface-alt);
}

/* Разделитель над кнопками у отключённой строки: обычный совпадает с её
   заливкой и пропадает. */
.record--off .record__actions {
  border-top-color: var(--tb-color-line);
}

/* Служебные подробности строки: порядок, буфер, число заказов. */
.record__facts {
  font-size: var(--tb-text-13);
  color: var(--tb-color-muted);
  margin-top: var(--tb-space-8);
}

/* Форма справочника шире окна отмены: в ней одиннадцать полей, а не одно. */
.modal__box--form {
  max-width: var(--tb-content-width);
}

/* Цена, срок, буфер и порядок — короткие поля, столбцом форма уходит на два
   экрана. Длинным полям остаётся вся ширина: `field--wide`. */
.fields--cols {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--tb-space-16);
}

.field--wide {
  grid-column: 1 / -1;
}

/*
 * Отметки «какие услуги выполняет». Флажки, а не список выбранного: вопрос
 * задаётся к каждой услуге отдельно, и снятая отметка должна быть видна
 * так же, как поставленная, — иначе непонятно, из чего выбирали.
 */
.checks {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--tb-space-8);
  border: var(--tb-border-hairline) solid var(--tb-color-line);
  border-radius: var(--tb-radius-8);
  padding: var(--tb-space-14);
}

.check {
  display: flex;
  align-items: center;
  gap: var(--tb-space-8);
  font-size: var(--tb-text-13);
  min-height: var(--tb-tap);
}

.check input {
  width: var(--tb-consent-size);
  height: var(--tb-consent-size);
  accent-color: var(--tb-color-ink);
  flex-shrink: 0;
}

/* Снятую с продажи услугу специалист выполнять может — отметка остаётся
   доступной, приглушением сказано только, что клиенту её не предлагают. */
.check--off {
  color: var(--tb-color-muted);
}

/* ========================================================================
   Раздел администратора — день записей
   ======================================================================== */

/*
 * То же правило, что и выше: страница `/admin` берёт классы кабинета —
 * строка записи это `record`, состояние `status`, предупреждение о
 * наложении `warn`, заголовок списка `panel__caption`, окна `modal`.
 *
 * Ниже только то, чего в кабинете нет вовсе: две кнопки в заголовке
 * раздела, переключатель дня с отбором и время визита в начале строки.
 * Новых токенов при этом не заводится — правило 4.
 */

/* В кабинете у заголовка раздела одна кнопка («Записаться»), здесь их две:
   новая запись и блокировка времени. */
.head__actions {
  display: flex;
  gap: var(--tb-space-10);
  align-items: center;
  flex-shrink: 0;
}

/*
 * Переключение дня и отбор по специалисту. Не `tabs`: вкладки перечисляют
 * заранее известный набор, а дней у сервиса столько же, сколько дат.
 */
.toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: var(--tb-space-16);
  align-items: flex-end;
  margin-bottom: var(--tb-space-24);
}

.toolbar__day {
  display: flex;
  gap: var(--tb-space-8);
  align-items: flex-end;
}

/* Стрелки и «Сегодня» стоят рядом с полем даты, а не под его подписью. */
.toolbar__day .btn-line {
  min-height: var(--tb-tap);
}

.toolbar__field {
  display: block;
}

/* Отбор по специалисту не растягивается на всю оставшуюся строку: имя
   короткое, а поле во весь экран читается как пустое место. */
.toolbar__field--wide {
  flex: 0 1 var(--tb-cabinet-aside);
  min-width: var(--tb-cabinet-side-min);
}

/*
 * Заголовок списка и кнопка «Обновить» в одной строке.
 *
 * В кабинете такого элемента нет: там список читают и уходят, а эту
 * страницу держат открытой весь день, и рядом с заголовком нужно место под
 * две вещи — когда данные прочитаны в последний раз и чем перечитать их
 * сейчас. Отступ переезжает с самой подписи на строку, иначе кнопка встаёт
 * выше неё на высоту этого отступа.
 */
.list-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--tb-space-16);
  margin-bottom: var(--tb-space-18);
}

.list-head .panel__caption {
  margin-bottom: 0;
}

/*
 * Время визита — первое, что читают в строке дня: список просматривают
 * сверху вниз как расписание. Час приходит из ответа в UTC и переводится в
 * пояс салона, который лежит там же, в поле `timezone`, — не в поясе
 * браузера: панель открывают и из другого города.
 */
.record__time {
  font-size: var(--tb-text-20);
  font-weight: var(--tb-weight-bold);
  white-space: nowrap;
}

/*
 * Метки над обеими колонками.
 *
 * В кабинете `record__marks` — первая строчка левой колонки, и там это
 * верно: правой колонке нечего с ней равнять. В дне записей колонки две, и
 * обе несут по крупному значению — время слева, сумму справа. Пока метки
 * лежали внутри левой, они сдвигали время вниз, а сумма оставалась у верха
 * карточки: у записи с двумя метками расхождение 30 px, у записи с четырьмя
 * (метки переносились на вторую строку) — 60 px, и соседние строки дня
 * переставали читаться как таблица. Вынесенные наверх, метки переносятся
 * сколько угодно, а колонки начинаются с одной высоты.
 */
.record--day > .record__marks,
.record--block > .record__marks {
  margin-bottom: var(--tb-space-14);
}

/*
 * Длинное значение переносится, а не выходит за карточку.
 *
 * Почта, имя и название услуги приходят из базы, и ни одно из них не обязано
 * содержать пробел: адрес `innokentiy.vsevolodovich@otdelmarketinga…example`
 * выезжал за скруглённую границу карточки на 190 px при ширине окна 360 px.
 * Заметно это только на длинных значениях и только по `scrollWidth`: рамка
 * карточки остаётся на месте, за неё уходит текст.
 */
.record__facts,
.record--day .record__title,
.record--day .record__services,
.record--block .record__title,
.warn__text {
  overflow-wrap: anywhere;
}

/*
 * Предупреждение о наложении внутри карточки.
 *
 * Отступ снизу `warn` получил от окна поздней отмены, где он последний
 * элемент перед кнопками. В карточке под ним стоит разделитель со своим
 * отступом, и вместе они давали 40 px против 20 px у строк без наложения —
 * соседние карточки одного дня расходились по вертикальному ритму.
 */
.record--day .warn {
  margin-bottom: 0;
}

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

/*
 * Кабинет тот же: те же вкладки, те же карточки, те же действия. Меняется
 * только раскладка — колонки складываются в одну, строки «название — цена»
 * перестают тянуться в ниточку, а меню шапки сворачивается в кнопку.
 *
 * Ничего не убирается: на телефоне доступны те же записи, тот же перенос и
 * та же отмена, что на компьютере. Точки перелома — в конце `tokens.css`.
 */

/* Кнопка «Меню». На широком экране её нет: разделы и так стоят строкой. */
.burger {
  display: none;
  padding: var(--tb-space-8) var(--tb-space-14);
  border: var(--tb-border-hairline) solid var(--tb-color-outline-dark);
  border-radius: var(--tb-radius-pill);
  background: transparent;
  color: var(--tb-color-surface);
  font-family: inherit;
  font-size: var(--tb-text-13);
  font-weight: var(--tb-weight-semibold);
  cursor: pointer;
}

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

  .cabinet {
    width: 100%;
  }
}

@media (max-width: 900px) {
  /* Детали записи и профиль: правая колонка уходит под левую. */
  .details__aside {
    width: 100%;
  }

  .profile__columns {
    grid-template-columns: 1fr;
    gap: var(--tb-space-24);
  }

  /* Подменю профиля — в строку: столбец из трёх пунктов над формой занял бы
     весь первый экран. Что не поместилось, переносится на вторую строку:
     обрезанный по краю пункт читается как поломка, а не как «прокрутите». */
  .submenu {
    flex-direction: row;
    flex-wrap: wrap;
    gap: var(--tb-space-8);
  }

  .submenu__link {
    white-space: nowrap;
  }

  .cabinet__body,
  .feed,
  .profile {
    padding-left: var(--tb-space-20);
    padding-right: var(--tb-space-20);
  }

  /*
   * Шапка кабинета: разделы сворачиваются в кнопку и раскрываются строкой
   * во всю ширину. Логотип, колокольчик, имя и «Выйти» остаются на месте —
   * это вход в сервис и выход из него.
   */
  .top {
    flex-wrap: wrap;
    gap: var(--tb-space-12);
    padding: var(--tb-space-14) var(--tb-space-20);
  }

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

  .burger {
    display: block;
  }

  .top__nav {
    display: none;
    flex-basis: 100%;
    flex-direction: column;
    gap: var(--tb-space-4);
  }

  .top[data-open] .top__nav {
    display: flex;
  }

  .top__link {
    padding: var(--tb-space-10) 0;
  }

  /*
   * Правая часть шапки ужимается, а не выталкивает себя за край.
   *
   * В шапке раздела администратора на один элемент больше, чем в кабинете, —
   * метка роли «Администратор» с `white-space: nowrap`. Вместе с именем и
   * выходом она требовала 347 px там, где есть 280, и страница получала
   * горизонтальную прокрутку целиком: у кабинета на той же ширине её нет.
   * Имя сокращается многоточием — оно единственное здесь произвольной длины,
   * а метка роли и кнопка выхода, обрезанные наполовину, теряют смысл.
   * `min-width: 0` нужен обоим родителям: без него флекс-элемент не
   * сжимается меньше своего содержимого, и многоточию неоткуда взяться.
   */
  .top__right {
    margin-left: auto;
    gap: var(--tb-space-14);
    min-width: 0;
  }

  .top__user {
    min-width: 0;
  }

  .top__name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
}

@media (max-width: 600px) {
  /*
   * Карточка записи вместо строки таблицы: цена и подпись переезжают под
   * состав заказа и выравниваются по левому краю. Правая колонка шириной
   * в 180 px рядом с составом оставляла бы на телефоне по слову в строке.
   */
  .record {
    padding: var(--tb-space-20);
  }

  .record__top {
    gap: var(--tb-space-14);
  }

  .record__main,
  .record__side {
    min-width: 0;
    flex-basis: 100%;
  }

  .record__side {
    text-align: left;
  }

  /* Действия карточки — кнопки во всю ширину: в ряд по три они сжимаются
     до нечитаемых пилюль. */
  .record__actions {
    flex-direction: column;
  }

  /* Форма справочника и отметки услуг — в одну колонку: двумя они дают по
     слову в строке. */
  .fields--cols,
  .checks {
    grid-template-columns: 1fr;
  }

  /* Заголовок раздела складывается в колонку, и обе его кнопки тянутся во
     всю ширину — как «Записаться» в кабинете. */
  .head__actions {
    flex-direction: column;
    align-items: stretch;
  }

  .head__actions > * {
    text-align: center;
    min-height: var(--tb-tap);
    display: flex;
    align-items: center;
    justify-content: center;
  }

  /* Заголовок дня с подписью о свежести занимает две-три строки — кнопка
     «Обновить» уезжает под него, а не сжимается в столбик из букв. */
  .list-head {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--tb-space-10);
  }

  /* Переключатель дня: поле даты занимает строку целиком, стрелки и
     «Сегодня» остаются рядом с ним. */
  .toolbar__day {
    flex-wrap: wrap;
  }

  .toolbar__day .toolbar__field {
    flex: 1 1 var(--tb-cabinet-side-min);
  }

  .record__actions > * {
    width: 100%;
    text-align: center;
    min-height: var(--tb-tap);
    display: flex;
    align-items: center;
    justify-content: center;
  }

  /* Заголовок списка и вкладки. Вкладок три, и на узком экране они уходят
     в прокрутку, а не переносятся: перенесённая вкладка теряет строку,
     по которой видно, какая из них выбрана. */
  .head {
    flex-direction: column;
    align-items: stretch;
    gap: var(--tb-space-16);
  }

  .head .btn-pill {
    text-align: center;
    min-height: var(--tb-tap);
    display: flex;
    align-items: center;
    justify-content: center;
  }

  .tabs {
    gap: var(--tb-space-20);
    overflow-x: auto;
  }

  .tab {
    white-space: nowrap;
  }

  /*
   * Строка «название — значение» перестаёт быть строкой таблицы: на узком
   * экране длинное название и цена делили ширину пополам, и обе половины
   * ломались по буквам. Теперь значение встаёт под названием слева.
   */
  .line {
    flex-direction: column;
    gap: var(--tb-space-2);
  }

  .line__value {
    text-align: left;
  }

  /* Итог остаётся строкой: два коротких слова помещаются и рядом. */
  .line--total {
    flex-direction: row;
    justify-content: space-between;
    gap: var(--tb-space-16);
  }

  .details__columns {
    gap: var(--tb-space-16);
  }

  .details__main {
    min-width: 0;
  }

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

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

  /*
   * Окно подтверждения отмены и переноса. На телефоне оно занимает высоту
   * экрана целиком и прокручивается внутри себя, а кнопки стоят снизу
   * отдельной строкой и видны всегда — иначе «Отменить запись» уезжает за
   * нижний край вместе с длинным текстом правил.
   */
  .modal {
    padding: 0;
    align-items: stretch;
  }

  .modal__box {
    max-width: none;
    border-radius: 0;
    max-height: 100vh;
    padding: var(--tb-space-20);
    display: flex;
    flex-direction: column;
  }

  .modal__actions {
    position: sticky;
    bottom: 0;
    flex-wrap: wrap;
    justify-content: stretch;
    gap: var(--tb-space-10);
    margin-top: auto;
    padding-top: var(--tb-space-16);
    background: var(--tb-color-surface);
  }

  .modal__actions > button {
    flex: 1;
    min-height: var(--tb-tap);
  }

  .modal__hint {
    flex-basis: 100%;
    margin-right: 0;
  }

  /* Лента уведомлений и активные сессии: строка с кнопкой справа
     переносится, чтобы длинное название не выдавливало кнопку за край. */
  .feed__head {
    flex-direction: column;
    align-items: stretch;
    gap: var(--tb-space-14);
  }

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

  .notice {
    padding: var(--tb-space-14) var(--tb-space-16);
  }

  .session {
    flex-wrap: wrap;
    gap: var(--tb-space-12);
  }

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

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

  .profile__buttons {
    flex-direction: column;
  }

  .profile__buttons > * {
    width: 100%;
    min-height: var(--tb-tap);
  }

  .btn-pill,
  .btn-line,
  .btn-block {
    min-height: var(--tb-tap);
  }
}

