/* Приборная панель домашнего зала.
 *
 * Планшет стоит на подставке в полумраке, смотрят на него с полутора метров
 * и мокрыми руками. Отсюда весь вид: крупные табличные цифры как на весах и
 * таймере, волосяные линии вместо рамок, спокойный фон и ровно один холодный
 * акцент. Смысловые цвета (сделано / внимание / опасно) отдельно от акцента.
 *
 * Нейтральные не серые «по умолчанию», а с лёгким холодным уклоном в сторону
 * акцента: чистый серый выглядит невыбранным.
 */

/* Контраст намеренно умеренный: почти чёрный фон с почти белым текстом
   режет глаз на длинных экранах вроде дневника питания. Фон приподнят,
   текст приглушён — читается спокойнее, а иерархия держится не яркостью,
   а размером и расстоянием. */
:root {
  --bg: #15191d;
  --surface: #1c2126;
  --surface-2: #232a30;
  /* Линия почти невидима: разделяет, но не рисует сетку. */
  --line: #2f373e;
  --text: #d5dbe0;
  --muted: #8794a0;
  --accent: #52a9bb;
  --accent-ink: #071b20;
  --ok: #58b98a;
  --warn: #d99b45;
  --danger: #d96a70;

  --radius: 16px;
  --radius-sm: 10px;
  --tap: 64px;
  --pad: 20px;

  /* Шаг сетки: интервалы берутся отсюда, а не подбираются на глаз. */
  --gap-1: 4px;
  --gap-2: 8px;
  --gap-3: 14px;
  --gap-4: 22px;
  --gap-5: 34px;

  --shell: 760px;
}

/* Светлая тема — приглушённая.
 *
 * Не белый лист с чёрным текстом: чистый белый на большом экране бьёт по глазам
 * и делает интерфейс похожим на документ. Здесь бумажный холодноватый тон под
 * тем же бирюзовым акцентом, текст не абсолютно чёрный, линии едва заметны. */
:root[data-theme='light'] {
  --bg: #e8ecec;
  --surface: #f3f6f6;
  --surface-2: #dfe5e5;
  --line: #cbd5d5;
  --text: #1c2528;
  --muted: #66757a;
  --accent: #157480;
  --accent-ink: #f3f6f6;
  --ok: #17734f;
  --warn: #8a5b12;
  --danger: #a94048;
}

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

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font: 17px/1.45 -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, system-ui, sans-serif;
  -webkit-text-size-adjust: 100%;
  overscroll-behavior-y: contain;
}

body {
  min-height: 100dvh;
  /* Тап не должен подсвечиваться серым и не должен выделять текст на кнопках. */
  -webkit-tap-highlight-color: transparent;
}

button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; user-select: none; }
a { color: var(--accent); }

#app {
  max-width: var(--shell);
  margin: 0 auto;
  padding: var(--pad);
  /* Место под плавающие элементы в углах — заметка и статус модели
     не должны накрывать последнюю строку экрана. */
  padding-bottom: 96px;
  /* Экран не выпрыгивает, а проявляется. Коротко: в зале всё должно
     оставаться мгновенным, анимация тут — сглаживание, а не эффект. */
  animation: screen-in .16s ease-out;
}
@keyframes screen-in { from { opacity: .35; transform: translateY(4px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { #app { animation: none; } }

/* --- Типографика --- */
h1 { font-size: 34px; line-height: 1.12; margin: 0 0 12px; letter-spacing: -0.025em; }
h2 { font-size: 22px; margin: 28px 0 12px; letter-spacing: -0.01em; }
h3 { font-size: 18px; margin: 0 0 8px; }
p  { margin: 0 0 12px; }
.muted { color: var(--muted); }
.small { font-size: 15px; }
.big-number { font-size: clamp(64px, 18vw, 140px); font-weight: 700; line-height: 1; letter-spacing: -0.03em; font-variant-numeric: tabular-nums; }

/* --- Карточки --- */
.card {
  background: var(--surface);
  /* Рамка почти не видна: карточки различаются фоном и воздухом, а не сеткой
     линий. Раньше экран выглядел таблицей из одинаковых прямоугольников. */
  border: 1px solid color-mix(in srgb, var(--line) 60%, transparent);
  border-radius: var(--radius);
  padding: var(--pad);
  margin-bottom: 16px;
}
.card--flat { background: var(--surface-2); border-color: transparent; }
/* Карточка, требующая внимания: незакрытая тренировка, предложение тренера. */
.card--warn { border-color: color-mix(in srgb, var(--warn) 55%, var(--line)); }

/* --- Пустое состояние --- */
/* «Пока пусто» само по себе выглядит как поломка. Тут всегда есть иконка,
   объяснение и, если уместно, следующий шаг. */
.empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  text-align: center;
  padding: 28px 20px;
  border-radius: var(--radius);
  background: var(--surface-2);
  color: var(--muted);
}
.empty__icon {
  width: 56px;
  height: 56px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  color: var(--accent);
}
.empty b { color: var(--text); font-size: 18px; }
.empty p { margin: 0; max-width: 42ch; line-height: 1.5; }

/* --- Кнопки: минимум 64 px по высоте --- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: var(--tap);
  padding: 0 24px;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--surface-2);
  color: var(--text);
  font-size: 18px;
  font-weight: 600;
  transition: transform .06s ease, background .12s ease;
}
.btn:active { transform: scale(.97); filter: brightness(1.08); }
.btn--primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
  /* Главное действие приподнято над остальным — иерархия видна до чтения. */
  box-shadow: 0 6px 20px color-mix(in srgb, var(--accent) 28%, transparent);
}
.btn--ghost { background: transparent; }
.btn--danger { color: var(--danger); }
.btn--block { display: flex; width: 100%; }
.btn--hero {
  min-height: 132px;
  font-size: 28px;
  font-weight: 700;
  border-radius: 22px;
}
.btn[disabled] { opacity: .45; pointer-events: none; }

/* --- Сетки --- */
.row { display: flex; gap: 12px; flex-wrap: wrap; }
.row--tight { gap: 8px; }
.grid { display: grid; gap: 12px; }
.grid--2 { grid-template-columns: repeat(2, 1fr); }
.grid--3 { grid-template-columns: repeat(3, 1fr); }
.grid--auto { grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); }
.spacer { flex: 1; }

/* --- Плитки выбора (минуты, чек-ин) --- */
.tile {
  min-height: 88px;
  border-radius: 16px;
  border: 2px solid var(--line);
  background: var(--surface-2);
  color: var(--text);
  font-size: 22px;
  font-weight: 700;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
}
.tile small { font-size: 13px; font-weight: 500; color: var(--muted); }
.tile:active { transform: scale(.97); }
.tile.is-active { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 18%, var(--surface-2)); }

/* --- Шапка экрана (старая, вытесняется .bar) --- */
.topbar {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 20px;
  min-height: 56px;
}
.topbar .btn { min-height: 52px; padding: 0 18px; }

/* --- Полоски статуса --- */
.pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 14px;
  border-radius: 999px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  font-size: 14px;
  color: var(--muted);
}
.pill--ok { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 40%, var(--line)); }
.pill--warn { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 40%, var(--line)); }
.pill--danger { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 40%, var(--line)); }

/* --- Поля ввода --- */
.field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 4px; }
.field__label { font-size: 15px; font-weight: 600; color: var(--muted); }
.field__hint { font-size: 13px; color: var(--muted); opacity: .8; line-height: 1.3; }
.input {
  min-height: 56px;
  padding: 0 16px;
  border-radius: 12px;
  border: 1px solid var(--line);
  background: var(--surface-2);
  font-size: 20px;
  font-variant-numeric: tabular-nums;
  width: 100%;
}
.input:focus { outline: 2px solid var(--accent); outline-offset: -1px; }
/* Стрелки у number-полей на планшете только мешают попадать пальцем. */
.input[type=number]::-webkit-inner-spin-button,
.input[type=number]::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
.input[type=number] { -moz-appearance: textfield; }

/* --- Степпер «− значение +» --- */
.stepper { display: flex; align-items: center; gap: 10px; }
.stepper__btn {
  min-width: var(--tap);
  min-height: var(--tap);
  padding: 0;
  font-size: 30px;
  font-weight: 400;
  line-height: 1;
  flex: 0 0 auto;
}
.stepper__value {
  flex: 1;
  text-align: center;
  font-size: 28px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* --- Ряд достижимых весов --- */
.ladder {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 8px;
}
.ladder__item {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 10px 12px;
  border-radius: 12px;
  background: var(--surface);
  border: 1px solid var(--line);
}
.ladder__item b { font-size: 18px; font-variant-numeric: tabular-nums; }

/* --- Каталог упражнений --- */
.exercise-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
  gap: var(--gap-3);
}
.exercise-card__pattern { font-size: 12px; color: var(--muted); text-transform: lowercase; }
.exercise-card {
  display: flex;
  flex-direction: column;
  padding: 0;
  overflow: hidden;
  text-align: left;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  color: var(--text);
  min-height: var(--tap);
}
.exercise-card:active { transform: scale(.98); }
.exercise-card__gif {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  background: #fff;
  display: block;
}
.exercise-card__body {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 14px;
}
.exercise-card__body b { font-size: 17px; line-height: 1.25; }
.exercise-card__body span {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* GIF техники. Исходник библиотеки — 180×180, поэтому выше ~1,6× не растягиваем:
   лучше чёткая небольшая анимация плюс крупные cues, чем мыло на пол-экрана. */
/* 440 px, а не 290: ограничение стояло из-за исходных 180 px — растянутая
   мелкая картинка выглядела хуже маленькой. После пересборки в 540 px (M20)
   смысла жаться нет, а хват и положение спины наконец различимы. */
.exercise-hero {
  width: 100%;
  max-width: 440px;
  aspect-ratio: 1;
  object-fit: contain;
  background: #fff;
  border-radius: var(--radius);
  display: block;
  margin: 0 auto 20px;
}

.cues { margin: 0; padding-left: 22px; }
.cues li { margin-bottom: 10px; font-size: 18px; line-height: 1.35; }
.cues li:last-child { margin-bottom: 0; }
.mistakes { margin: 0; padding-left: 22px; color: var(--muted); }
.mistakes li { margin-bottom: 8px; }

/* --- Превью сессии --- */
.plan-row { display: flex; gap: 14px; align-items: center; padding: 12px 0; border-bottom: 1px solid var(--line); }
.plan-row:last-child { border-bottom: none; }
.plan-row__num {
  flex: 0 0 40px; height: 40px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--surface-2);
  font-weight: 700;
}
.plan-row__body { display: flex; flex-direction: column; gap: 2px; }
.plan-row__body b { font-size: 18px; }

/* --- Экран тренировки --- */
.workout { position: relative; }
.workout__title { font-size: 30px; margin-bottom: 16px; }
.workout__main { display: grid; grid-template-columns: 290px 1fr; gap: 24px; align-items: start; }
.workout__gif {
  width: 100%;
  aspect-ratio: 1;
  object-fit: contain;
  background: #fff;
  border-radius: var(--radius);
  display: block;
}
.workout__gif--empty { background: var(--surface-2); }
.workout__gif {
  background: #fff;
  border-radius: var(--radius);
  border: 1px solid var(--line);
}
.workout__controls { display: flex; flex-direction: column; gap: 14px; }
.workout__cues { margin: 22px 0 0; padding-left: 22px; color: var(--muted); }
.workout__cues li { margin-bottom: 6px; }

.set-badge {
  align-self: flex-start;
  padding: 8px 18px;
  border-radius: 999px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  font-size: 17px;
  font-weight: 600;
}

/* Крупные «+/−»: попасть пальцем не глядя. */
.dial { display: flex; align-items: center; gap: 14px; }
.dial__btn {
  flex: 0 0 auto;
  min-width: 88px;
  min-height: 88px;
  font-size: 40px;
  font-weight: 400;
  line-height: 1;
  padding: 0;
  border-radius: 20px;
}
.dial__value { flex: 1; text-align: center; display: flex; flex-direction: column; gap: 2px; }
.dial__value b { font-size: 52px; font-weight: 700; line-height: 1; font-variant-numeric: tabular-nums; }
.dial__value span { font-size: 14px; color: var(--muted); }

/* --- Оверлей отдыха --- */
.rest {
  position: fixed;
  inset: 0;
  z-index: 80;
  background: color-mix(in srgb, var(--bg) 96%, transparent);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  text-align: center;
  padding: var(--pad);
}
.rest__label { font-size: 20px; color: var(--muted); text-transform: uppercase; letter-spacing: .12em; }
.rest__next { font-size: 20px; color: var(--muted); margin-top: 10px; }
/* Отдых закончился — видно с другого конца комнаты, даже если звук выключен. */
.rest--done .rest__label { color: var(--ok); }
.rest--done .big-number { color: var(--ok); }

@media (max-width: 900px) {
  .workout__main { grid-template-columns: 1fr; }
  .workout__gif { max-width: 360px; margin: 0 auto; }
}

/* --- История тренировок --- */
.history-row {
  display: flex;
  align-items: center;
  gap: 16px;
  width: 100%;
  min-height: var(--tap);
  padding: 16px 20px;
  margin-bottom: 10px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text);
  text-align: left;
  flex-wrap: wrap;
}
.history-row:active { transform: scale(.99); }
.history-row__main { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 160px; }
.history-row__main b { font-size: 18px; }

.set-row {
  display: flex;
  align-items: flex-end;
  gap: 12px;
  padding: 10px 0;
  border-bottom: 1px solid var(--line);
  flex-wrap: wrap;
}
.set-row:last-of-type { border-bottom: none; }
.set-row__num {
  flex: 0 0 36px; height: 36px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--surface-2);
  font-weight: 700;
  font-size: 15px;
}
/* Поле даты шире числового: «2026-08-04» не помещается в 110 px и вылезает. */
.set-row__field { display: flex; flex-direction: column; gap: 4px; width: 110px; }
.set-row__field--date { width: 168px; }
.set-row__field .input { width: 100%; }
.input--compact { min-height: 48px; font-size: 17px; padding: 0 10px; }
.input[type='date'] { font-size: 16px; }

/* Строка замера в списке: текст не должен липнуть к соседям. */
.set-row__body { display: flex; flex-direction: column; gap: 3px; min-width: 180px; padding-right: 14px; }
.set-row + .set-row { margin-top: 2px; }

/* --- Шкала чек-ина: попасть пальцем с первого раза --- */
.scale { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 20px; }
.scale__btn {
  flex: 1 1 90px;
  min-height: 110px;
  border-radius: 18px;
  border: 2px solid var(--line);
  background: var(--surface-2);
  color: var(--text);
  font-size: 32px;
  font-weight: 700;
}
.scale__btn:active { transform: scale(.96); border-color: var(--accent); }
.scale__labels {
  flex: 1 0 100%;
  display: flex;
  justify-content: space-between;
  color: var(--muted);
  font-size: 15px;
  margin-top: 4px;
}

/* --- Задачи недели --- */
.week-tasks { display: grid; gap: 8px; margin-top: 14px; }
.week-task {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  border-radius: 12px;
  background: var(--surface-2);
  font-size: 17px;
}
.week-task {
  width: 100%;
  min-height: var(--tap);
  border: 1px solid transparent;
  color: var(--text);
  text-align: left;
  cursor: pointer;
}
.week-task:active { transform: scale(.99); border-color: var(--accent); }
.week-task__go { color: var(--muted); font-size: 14px; }
.week-task__mark {
  width: 28px; height: 28px;
  flex: 0 0 28px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--bg);
  color: var(--muted);
  font-weight: 700;
}
.week-task.is-done { color: var(--ok); }
.week-task.is-done .week-task__mark { background: color-mix(in srgb, var(--ok) 22%, var(--bg)); color: var(--ok); }

/* --- Лестница прогрессии --- */
.ladder-steps { display: grid; gap: 8px; margin-top: 14px; }
.ladder-step {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 16px;
  border-radius: 14px;
  background: var(--surface-2);
  border: 2px solid transparent;
  cursor: pointer;
  min-height: var(--tap);
}
.ladder-step__mark {
  flex: 0 0 36px; height: 36px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--bg);
  font-weight: 700;
  color: var(--muted);
}
.ladder-step__body { display: flex; flex-direction: column; gap: 2px; flex: 1; }
.ladder-step.is-done { opacity: .6; }
.ladder-step.is-done .ladder-step__mark { color: var(--ok); }
.ladder-step.is-current { border-color: var(--accent); }
.ladder-step.is-current .ladder-step__mark { background: var(--accent); color: var(--accent-ink); }

/* --- Кардио: целевой пульс виден с дорожки --- */
.hr-block {
  text-align: center;
  padding: 24px 16px;
  margin: 20px 0;
  border-radius: var(--radius);
  background: var(--surface);
  border: 1px solid var(--line);
}
.hr-block__label { color: var(--muted); font-size: 17px; text-transform: uppercase; letter-spacing: .1em; }
.hr-block__value {
  font-size: clamp(64px, 14vw, 132px);
  font-weight: 800;
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
  color: var(--accent);
}
.hr-block__value--muted { color: var(--muted); font-size: clamp(40px, 8vw, 72px); }
/* Свой пульс с ремня: цвет отвечает на единственный вопрос — я в зоне или нет. */
.hr-block__value--in { color: var(--ok); }
.hr-block__value--out { color: var(--warn); }
.hr-block__hint { color: var(--muted); font-size: 15px; margin-top: 6px; }

.cardio-live { text-align: center; }
.cardio-live__step {
  font-size: 24px;
  color: var(--muted);
  margin-top: 10px;
}
/* На паузе экран приглушается — видно с дорожки, что время не идёт. */
.cardio-live.is-paused .big-number { opacity: .5; }
.cardio-live.is-paused .cardio-live__step { color: var(--warn); font-weight: 700; }

/* Быстрая минута — заметно даже боковым зрением с дорожки. */
.cardio-live.is-fast .big-number { color: var(--warn); }
.cardio-live.is-fast .cardio-live__step { color: var(--warn); font-weight: 700; }

/* --- Питание --- */
.habits { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 12px; margin-top: 12px; }
.habit {
  padding: 16px;
  border-radius: 14px;
  background: var(--surface-2);
  text-align: center;
  border: 2px solid transparent;
}
.habit b { display: block; font-size: 30px; font-variant-numeric: tabular-nums; }
.habit span { color: var(--muted); font-size: 14px; }
.habit.is-ok { border-color: color-mix(in srgb, var(--ok) 50%, transparent); }
.habit.is-ok b { color: var(--ok); }

.meal-card {
  display: flex;
  gap: 14px;
  align-items: center;
  padding: 12px;
  margin-bottom: 10px;
  border-radius: var(--radius);
  background: var(--surface);
  border: 1px solid var(--line);
  flex-wrap: wrap;
}
.meal-card__photo {
  width: 92px; height: 92px;
  flex: 0 0 92px;
  object-fit: cover;
  border-radius: 12px;
  background: var(--surface-2);
}
.meal-card__photo--empty { display: grid; place-items: center; font-size: 34px; }
.meal-card__body { display: flex; flex-direction: column; gap: 3px; flex: 1; min-width: 180px; }
.meal-card__body b { font-size: 18px; }

/* --- Чат с тренером --- */
.chat {
  display: flex;
  flex-direction: column;
  gap: 12px;
  max-height: 56vh;
  overflow-y: auto;
  padding: 4px;
}
.bubble {
  max-width: min(680px, 88%);
  padding: 14px 18px;
  border-radius: 18px;
  font-size: 17px;
  line-height: 1.45;
  white-space: pre-wrap;
}
.bubble--user {
  align-self: flex-end;
  background: var(--accent);
  color: var(--accent-ink);
  border-bottom-right-radius: 6px;
}
.bubble--assistant {
  align-self: flex-start;
  background: var(--surface);
  border: 1px solid var(--line);
  border-bottom-left-radius: 6px;
}

/* Адрес для подключения с телефона — набирается вручную, поэтому крупно. */
.net-url {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 19px;
  padding: 12px 14px;
  margin-bottom: 8px;
  border-radius: 12px;
  background: var(--surface-2);
  user-select: all;
  word-break: break-all;
}

/* Полоса отладочной базы: спутать её с боевой историей нельзя. */
.test-banner {
  background: var(--warn);
  color: #1a1206;
  font-weight: 700;
  text-align: center;
  padding: 10px 16px;
  letter-spacing: .04em;
}


/* Ссылка в роли кнопки не должна выглядеть ссылкой. */
a.btn { text-decoration: none; color: var(--text); display: inline-flex; align-items: center; justify-content: center; }
a.btn--primary { color: var(--accent-ink); }

/* --- Тренер между подходами --- */
/* Поверх табло отдыха: ответ приходит как раз в окно отдыха, и его надо видеть. */
.coach-sheet {
  position: fixed;
  inset: auto 0 0 0;
  z-index: 90;
  background: var(--surface);
  border-top: 1px solid var(--line);
  border-radius: var(--radius) var(--radius) 0 0;
  box-shadow: 0 -18px 50px rgba(0, 0, 0, .45);
  max-height: 78vh;
  overflow-y: auto;
  animation: sheet-up .18s ease-out;
}
.coach-sheet__body {
  padding: var(--pad);
  max-width: 900px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
@keyframes sheet-up { from { transform: translateY(18px); opacity: .4; } to { transform: none; opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .coach-sheet { animation: none; } }

/* Жёлтый = незавершённое: пауза, досрочное завершение, неполный успех недели. */
.btn--warn {
  background: var(--warn);
  color: #1a1206;
  border-color: transparent;
}
.week-task.is-paused {
  border: 1px solid var(--warn);
  color: var(--warn);
}
.week-task.is-paused .week-task__mark {
  background: color-mix(in srgb, var(--warn) 22%, var(--bg));
  color: var(--warn);
}
.history-row.is-partial { border-color: color-mix(in srgb, var(--warn) 55%, var(--line)); }

/* --- Список бэкапов --- */
.backup-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 0;
  border-bottom: 1px solid var(--line);
  flex-wrap: wrap;
}
.backup-row:last-of-type { border-bottom: none; }
.backup-row__body { display: flex; flex-direction: column; gap: 2px; min-width: 190px; }

/* --- Итоги дня по питанию --- */
.kcal-total {
  font-size: clamp(40px, 8vw, 64px);
  font-weight: 800;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  margin: 10px 0 2px;
}
.kcal-total small { font-size: 20px; font-weight: 600; color: var(--muted); margin-left: 10px; }
.pill--kcal { background: color-mix(in srgb, var(--accent) 22%, var(--surface-2)); }

/* Полоса дневной нормы: засечка — нижняя граница вилки, заливка — съеденное. */
.target-bar {
  position: relative;
  height: 12px;
  border-radius: 999px;
  background: var(--surface-2);
  overflow: hidden;
  margin-top: 6px;
}
.target-bar__fill {
  height: 100%;
  background: var(--ok);
  border-radius: 999px;
  transition: width .3s ease;
}
.target-bar__mark {
  position: absolute;
  top: 0;
  width: 2px;
  height: 100%;
  background: var(--text);
  opacity: .55;
}
.pill--cat { font-size: 13px; opacity: .85; }

/* Пока экран собирается (месячный отчёт ждёт модель) */
.loading { padding: 40px 4px; color: var(--muted); font-size: 18px; }

/* --- Графики --- */
.chart {
  width: 100%;
  height: 160px;
  display: block;
  margin: 14px 0 6px;
  overflow: visible;
}
.card--warn { border-color: color-mix(in srgb, var(--warn) 55%, var(--line)); }

/* --- Тост --- */
.toast {
  position: fixed;
  left: 50%;
  bottom: 32px;
  transform: translateX(-50%);
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 16px 24px;
  font-size: 17px;
  z-index: 100;
  box-shadow: 0 12px 40px rgba(0,0,0,.5);
  transition: opacity .4s ease;
}
.toast--error { border-color: var(--danger); color: var(--danger); }
.toast--ok { border-color: var(--ok); }
.toast.is-out { opacity: 0; }

/* Полка полос состояния: они складываются друг под другом, а не накладываются.
   Закреплена у края окна, а не приклеена к потоку: прокручиваемый контейнер здесь
   не body, и sticky-полоса отклеивалась на середине длинных экранов. Место под неё
   освобождает отступ страницы — высоту меряет core.js, полос может быть одна, две
   или ни одной. */
#banners {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 200;
}
body { padding-top: var(--banner-h, 0px); }

/* --- Индикатор офлайна --- */
.offline-bar {
  background: var(--warn);
  color: #1b1200;
  text-align: center;
  padding: 6px;
  font-size: 14px;
  font-weight: 600;
  z-index: 90;
}

/* --- Заметки о доработках --- */
/* Кнопка живёт в углу и намеренно неброская: она не часть тренировки,
   но должна быть под рукой ровно в тот момент, когда что-то не понравилось. */
.note-fab {
  position: fixed;
  right: 14px;
  bottom: 14px;
  z-index: 70;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--muted);
  font-size: 20px;
  line-height: 1;
  opacity: .55;
  cursor: pointer;
  box-shadow: 0 6px 18px rgba(0, 0, 0, .35);
}
.note-fab:hover,
.note-fab:focus-visible { opacity: 1; color: var(--text); }
.note-fab:active { transform: scale(.94); }

/* Видео техники. Несколько ракурсов в ряд: на широком экране рядом,
   на телефоне друг под другом — сравнивать всё равно приходится глазами. */
.clip-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: var(--gap-2);
}
.clip {
  width: 100%;
  border-radius: var(--radius);
  background: #000;
  display: block;
}

/* Крайние точки движения: два кадра рядом — так видно разницу между ними,
   а по отдельности каждый выглядит просто человеком в зале. */
.photo-pair {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: var(--gap-2);
}
.photo-pair__img {
  width: 100%;
  border-radius: var(--radius);
  display: block;
  background: var(--surface-2);
}

/* Оценка подхода на отдыхе: три слова, один тап. Спрашиваем, пока ощущение
   свежее, — в конце тренировки «в среднем по больнице» это уже не оценка. */
.rpe-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 18px;
}
.rpe-row__label { font-size: 13px; color: var(--muted); }

/* Как усложняем сегодня, когда вес упёрся в потолок. Заметно, но не спорит
   с главным действием: это условие подхода, а не отдельная задача. */
.style-hint {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 10px 14px;
  border-radius: var(--radius-sm, 10px);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 30%, var(--line));
}
.style-hint b { font-size: 15px; color: var(--accent); }
.style-hint span { font-size: 13px; color: var(--muted); line-height: 1.35; }

/* Фото во весь экран. Тап в любое место закрывает: разглядывать снимок
   приходят на секунду, и искать крестик в этот момент — лишняя работа. */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 300;
  background: rgb(0 0 0 / .92);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 16px;
  cursor: zoom-out;
}
.lightbox img {
  max-width: 100%;
  max-height: 82vh;
  object-fit: contain;
  border-radius: var(--radius);
}
.lightbox__hint { color: #cfd6db; font-size: 14px; text-align: center; }
.meal-row__photo.is-clickable { cursor: zoom-in; }

/* Переключатель дня в дневнике питания. */
.day-switch {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap-2);
  padding: 10px 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
}
.day-switch b { font-size: 15px; }

/* Фото еды в ленте — на месте значка, того же размера: строка не должна
   разъезжаться из-за того, что к одному приёму пищи есть снимок, а к другому нет. */
.ev__photo {
  width: 34px;
  height: 34px;
  border-radius: 9px;
  object-fit: cover;
  flex: 0 0 auto;
  background: var(--surface-2);
}

/* Вопрос о сне: строка, а не карточка — он необязателен и не должен
   выглядеть важнее главного действия дня. */
.sleep-row {
  display: flex;
  align-items: center;
  gap: var(--gap-2);
  flex-wrap: wrap;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
}
.sleep-row__label {
  font-size: 14px;
  color: var(--muted);
  flex: 0 0 auto;
}

/* Возврат к незакрытой тренировке. Яркая и с текстом, в отличие от кнопки
   заметки: заметка — дело необязательное, а брошенный посреди зала подход —
   нет. Стоит над кнопкой заметки, чтобы не спорить с ней за угол. */
.resume-fab {
  position: fixed;
  right: 14px;
  bottom: 76px;
  z-index: 71;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 16px 10px 13px;
  min-height: 52px;
  border-radius: 999px;
  border: 1px solid transparent;
  background: var(--accent);
  color: var(--accent-ink);
  box-shadow: 0 6px 20px rgb(0 0 0 / .28);
  cursor: pointer;
  text-align: left;
}
.resume-fab span { display: flex; flex-direction: column; line-height: 1.15; }
.resume-fab b { font-size: 15px; font-weight: 700; }
.resume-fab span span { font-size: 12px; opacity: .8; }
.resume-fab:active { transform: scale(.97); }

/* На тренировке внизу — «Готово», и промах по нему стоит подхода.
   Кнопка заметки уходит наверх, подальше от главного действия. */
body[data-route^="/workout"] .note-fab { bottom: auto; top: 12px; opacity: .35; }

/* Лист поверх всего: заметку пишут, не уходя с экрана, о котором она. */
.sheet {
  position: fixed;
  inset: 0;
  z-index: 210;
  background: color-mix(in srgb, var(--bg) 80%, transparent);
  display: flex;
  align-items: flex-end;
  justify-content: center;
}
.sheet__body {
  width: min(720px, 100%);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius) var(--radius) 0 0;
  box-shadow: 0 -18px 50px rgba(0, 0, 0, .45);
  padding: var(--pad);
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.sheet__input { font-size: 17px; min-height: 96px; resize: vertical; }

/* --- Лента дней --- */
/* Порядок как в переписке: история выше, сегодняшний день внизу под рукой. */
.feed { display: flex; flex-direction: column; gap: var(--gap-4); }
.feed-history { display: flex; flex-direction: column; gap: var(--gap-4); }
/* Расстояния в «Сегодня».
   Было одинаково крупно между всеми блоками, и подпись «ТРЕНЕР» висела
   ровно посередине между готовностью и советом — непонятно, к чему она
   относится. Теперь блоки разделены, а подпись прижата к своим словам. */
.feed-today { display: flex; flex-direction: column; gap: var(--gap-3); }
.feed-start { text-align: center; padding: 12px 0; color: var(--muted); font-size: 14px; opacity: .7; }

/* Шапка экрана: меню, день, профиль. Липкая — меню нужно с любой прокрутки. */
.bar {
  position: sticky;
  top: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  gap: var(--gap-3);
  padding: 10px 0 12px;
  margin-bottom: calc(var(--gap-2) * -1);
  background: linear-gradient(var(--bg) 72%, transparent);
  backdrop-filter: blur(6px);
}
.bar__title { display: flex; flex-direction: column; line-height: 1.15; flex: 1; min-width: 0; }
.bar__title b { font-size: 26px; letter-spacing: -0.02em; }
.bar__date { font-size: 13px; color: var(--muted); }

.icon-btn {
  width: 48px;
  height: 48px;
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  color: var(--text);
}
.icon-btn:active { transform: scale(.94); }
/* Три полосы рисуются рамками — отдельная иконка ради этого не нужна. */
.burger, .burger::before, .burger::after {
  display: block;
  width: 18px;
  height: 2px;
  border-radius: 2px;
  background: currentColor;
}
.burger { position: relative; }
.burger::before, .burger::after { content: ''; position: absolute; left: 0; }
.burger::before { top: -6px; }
.burger::after { top: 6px; }

.chip {
  flex: 0 0 auto;
  min-height: 44px;
  padding: 0 14px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: transparent;
  color: var(--text);
  font-size: 15px;
  font-weight: 600;
  white-space: nowrap;
}

/* --- Главное действие --- */
/* Приборная панель, а не леденец: тач-зона та же, вид спокойнее. */
.hero {
  display: flex;
  align-items: center;
  gap: var(--gap-3);
  width: 100%;
  min-height: 116px;
  padding: 18px 20px;
  border: 1px solid color-mix(in srgb, var(--accent) 55%, var(--line));
  border-radius: var(--radius);
  background:
    linear-gradient(135deg, color-mix(in srgb, var(--accent) 14%, transparent), transparent 62%),
    var(--surface);
  color: var(--text);
  text-align: left;
  transition: transform .06s ease, border-color .15s ease;
}
.hero:active { transform: scale(.985); border-color: var(--accent); }
.hero__body { display: flex; flex-direction: column; gap: 3px; flex: 1; min-width: 0; }
.hero__label {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .14em;
  color: var(--accent);
  font-weight: 700;
}
.hero__title { font-size: 30px; line-height: 1.1; letter-spacing: -0.03em; }
.hero__sub { font-size: 14px; color: var(--muted); font-variant-numeric: tabular-nums; }
.hero__go { color: var(--accent); flex: 0 0 auto; }
/* Незакрытая тренировка — жёлтым, как всё незавершённое в приложении. */
.hero.is-paused { border-color: color-mix(in srgb, var(--warn) 60%, var(--line)); }
.hero.is-paused .hero__label, .hero.is-paused .hero__go { color: var(--warn); }
.hero.is-paused {
  background:
    linear-gradient(135deg, color-mix(in srgb, var(--warn) 12%, transparent), transparent 62%),
    var(--surface);
}

/* Мелкие действия в строке списка: они не должны спорить по весу
   с главным действием экрана, но остаются пальцевыми (40 px). */
.lrow__acts { display: flex; flex-wrap: wrap; gap: 6px; flex: 0 0 auto; }
.mini {
  min-height: 40px;
  padding: 0 12px;
  border-radius: 9px;
  border: 1px solid var(--line);
  background: transparent;
  color: var(--muted);
  font-size: 13px;
  font-weight: 600;
}
.mini:active { background: var(--surface-2); }
.mini.is-primary { color: var(--accent-ink); background: var(--accent); border-color: var(--accent); }
.mini.is-danger { color: var(--danger); }

/* --- Фильтры-чипсы --- */
/* Кнопки в полный рост под фильтры избыточны: это не действия, а переключение
   вида, и они не должны спорить по весу с главным действием экрана. */
.chips { display: flex; flex-wrap: wrap; gap: var(--gap-2); }
.chips__item {
  min-height: 40px;
  padding: 0 14px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: transparent;
  color: var(--muted);
  font-size: 14px;
  font-weight: 600;
}
.chips__item.is-active { background: var(--surface-2); color: var(--text); border-color: transparent; }

/* --- Вердикт чек-ина --- */
/* Ответ на вопрос «что мне сегодня можно» — главное на экране, и выглядеть
   он должен как ответ, а не как обычный заголовок с абзацем. */
.verdict {
  display: flex;
  flex-direction: column;
  gap: var(--gap-2);
  padding: 20px 22px;
  border-radius: var(--radius);
  border: 1px solid color-mix(in srgb, var(--accent) 45%, var(--line));
  background:
    linear-gradient(135deg, color-mix(in srgb, var(--accent) 12%, transparent), transparent 60%),
    var(--surface);
}
.verdict b { font-size: 26px; letter-spacing: -0.02em; }
.verdict p { margin: 0; color: var(--muted); font-size: 17px; line-height: 1.5; }

/* --- Выбор профиля --- */
.gate { gap: var(--gap-4); padding-top: 6vh; }
.gate__head { display: flex; flex-direction: column; gap: var(--gap-2); }
.gate__head b { font-size: 30px; letter-spacing: -0.025em; }
.gate__head span { color: var(--muted); max-width: 46ch; line-height: 1.5; }

/* Это ворота на входе, а не раздел: заголовок крупный, карточки крупные,
   всё остальное убрано с глаз. */
.profile-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: var(--gap-3); }
.profile-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  min-height: 150px;
  padding: 20px 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text);
}
.profile-card__emoji { font-size: 44px; line-height: 1; }
.profile-card b { font-size: 19px; }
.profile-card.is-current { border-color: var(--accent); box-shadow: 0 8px 26px color-mix(in srgb, var(--accent) 18%, transparent); }
.profile-card--add { border-style: dashed; color: var(--muted); background: transparent; }
.profile-card:active { transform: scale(.98); }

/* --- Прогресс тренировки --- */
/* Полосу видно боковым зрением между подходами, строчку «3 из 5» надо читать. */
.wprogress { display: flex; gap: 4px; margin: 2px 0 14px; }
.wprogress__seg {
  flex: 1;
  height: 6px;
  border-radius: 3px;
  background: var(--line);
}
.wprogress__seg.is-done { background: var(--ok); }
.wprogress__seg.is-current { background: var(--accent); }

.set-dots { display: flex; align-items: center; gap: 8px; }
.set-dots__d {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  border: 2px solid var(--line);
}
.set-dots__d.is-done { background: var(--ok); border-color: var(--ok); }
.set-dots__d.is-current { border-color: var(--accent); }
.set-dots__text { font-size: 14px; color: var(--muted); margin-left: 4px; }

/* Раскладка блинов под весом: считать её в уме на тренировке — лишняя работа. */
.load-hint {
  margin-top: 6px;
  text-align: center;
  font-size: 14px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* Часы тренировки в шапке: сколько уже идёт. */
.elapsed {
  flex: 0 0 auto;
  font-size: 15px;
  font-weight: 600;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* Вес следующего упражнения на табло отдыха. */
.rest__weight { display: flex; flex-direction: column; align-items: center; gap: 2px; margin-top: 6px; }
.rest__weight b { font-size: 26px; font-variant-numeric: tabular-nums; }
.rest__weight span { font-size: 13px; color: var(--muted); }

/* Техника во время отдыха: свёрнута, чтобы не спорить с таймером. */
.rest__how {
  margin-top: 18px;
  max-width: 520px;
  width: 100%;
  text-align: left;
}
.rest__how > summary {
  min-height: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  color: var(--muted);
  font-size: 15px;
  cursor: pointer;
  list-style: none;
}
.rest__how > summary::-webkit-details-marker { display: none; }
.rest__how .cues { margin: 12px 0 0; padding-left: 22px; text-align: left; }
.rest__how .cues li { margin-bottom: 8px; line-height: 1.45; }
.rest__mistake { margin: 8px 0 0; font-size: 14px; color: var(--warn); }

/* --- Пульс на отдыхе --- */
/* Под кнопкой и мельче её: замер необязателен и не должен спорить
   с главным действием табло. */
.hr-row { display: flex; gap: var(--gap-2); margin-top: 22px; }
.hr-field {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  min-width: 92px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: transparent;
}
.hr-field span { font-size: 11px; color: var(--muted); }
.hr-field b { font-size: 24px; font-variant-numeric: tabular-nums; }
.hr-field__input {
  width: 68px;
  border: 0;
  background: transparent;
  color: var(--text);
  font-size: 24px;
  font-weight: 700;
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.hr-field__input::-webkit-inner-spin-button { -webkit-appearance: none; }
.hr-field.is-done b { color: var(--text); }
.hr-field.is-result { border-color: color-mix(in srgb, var(--ok) 50%, var(--line)); }
.hr-field.is-result b { color: var(--ok); }
/* Кнопка ремня стоит в одном ряду с полями пульса и не должна их перевешивать. */
.hr-field--connect {
  min-height: 0;
  font-size: 13px;
  color: var(--muted);
}
/* Живой пульс на отдыхе: подпись, а не показатель — цифра и так меняется. */
.rest__hint--live { font-variant-numeric: tabular-nums; }
.rest__hint { margin-top: 10px; font-size: 13px; color: var(--muted); }

/* --- Долгие операции --- */
/* Плашка о готовности: не модальное окно и не тост, который исчезнет раньше,
   чем его заметят. Висит, пока не откроют или не отложат. */
.job-chip {
  position: fixed;
  left: 50%;
  bottom: 18px;
  transform: translateX(-50%);
  z-index: 120;
  display: flex;
  align-items: center;
  gap: 10px;
  max-width: calc(100vw - 32px);
  padding: 10px 12px 10px 16px;
  border-radius: 999px;
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: 0 12px 34px rgba(0, 0, 0, .35);
  font-size: 15px;
}
.job-chip__dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--accent);
  animation: pulse 1.4s ease-in-out infinite;
}
@keyframes pulse { 0%, 100% { opacity: .35; } 50% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .job-chip__dot { animation: none; } }
body.has-sidebar .job-chip { left: calc(50% + 118px); }

.waiting {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--gap-3);
  padding: 24px;
  border-radius: var(--radius);
  border: 1px dashed var(--line);
  background: var(--surface-2);
}
.waiting b { font-size: 20px; }
.waiting p { margin: 0; color: var(--muted); max-width: 50ch; line-height: 1.5; }

.report__text { margin: 0; font-size: 19px; line-height: 1.55; white-space: pre-wrap; }

/* --- Дневник питания --- */
/* Калории — главное число экрана, и выглядит оно как показание прибора. */
.kcal { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.kcal b {
  font-size: 40px;
  font-weight: 700;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.kcal span { color: var(--muted); font-size: 15px; }

/* Приёмы пищи лентой: время в колонке, миниатюра, калории справа. */
.mlist { display: flex; flex-direction: column; }
.meal-row {
  display: grid;
  /* Пять колонок: время, миниатюра, название, калории, действия.
     При четырёх пятый элемент переносился на вторую строку и строка
     вырастала вдвое. */
  grid-template-columns: 42px 44px 1fr auto auto;
  align-items: center;
  gap: var(--gap-3);
  padding: 10px 0;
  border-bottom: 1px solid color-mix(in srgb, var(--line) 55%, transparent);
}
.meal-row:last-child { border-bottom: 0; }
.meal-row__time { font-size: 13px; color: var(--muted); font-variant-numeric: tabular-nums; }
.meal-row__photo {
  width: 44px;
  height: 44px;
  border-radius: var(--radius-sm);
  object-fit: cover;
  background: var(--surface-2);
}
.meal-row__photo--empty {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--muted);
  font-size: 20px;
}
.meal-row__body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.meal-row__body b { font-weight: 600; }
.meal-row__meta { font-size: 13px; color: var(--muted); }
.meal-row__kcal {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  font-size: 17px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.meal-row__kcal small { font-size: 11px; font-weight: 500; color: var(--muted); }
/* Неразобранное — приглушено: оно ещё не участвует в подсчёте дня. */
.meal-row.is-pending .meal-row__body b { color: var(--muted); }

/* Совет тренера по еде — речь, а не карточка. */
.advice { display: flex; flex-direction: column; gap: 6px; padding-left: 14px; border-left: 2px solid var(--accent); }
.advice__label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .08em; color: var(--muted); }
.advice p { margin: 0; font-size: 17px; line-height: 1.5; }

/* Полоса нормы: заполнение — съеденное, метка — нижняя граница нормы. */
.target-bar {
  position: relative;
  height: 8px;
  border-radius: 4px;
  background: var(--surface-2);
  overflow: visible;
}
.target-bar__fill { height: 100%; border-radius: 4px; background: var(--accent); transition: width .4s ease; }
.target-bar__mark { position: absolute; top: -3px; width: 2px; height: 14px; background: var(--muted); border-radius: 1px; }

/* --- Список строк --- */
/* Вместо «карточка на каждый элемент»: подряд идущие карточки одинакового
   веса читаются как забор и съедают втрое больше места. */
.list {
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid color-mix(in srgb, var(--line) 60%, transparent);
  border-radius: var(--radius);
  overflow: hidden;
}
.lrow {
  display: flex;
  align-items: center;
  gap: var(--gap-3);
  width: 100%;
  min-height: 58px;
  padding: 12px 16px;
  border: 0;
  border-bottom: 1px solid color-mix(in srgb, var(--line) 55%, transparent);
  background: transparent;
  color: var(--text);
  text-align: left;
}
.lrow:last-child { border-bottom: 0; }
button.lrow:active { background: var(--surface-2); }
.lrow__body { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.lrow__body b { font-weight: 600; }
.lrow__meta { font-size: 13px; color: var(--muted); }
.lrow__value {
  font-size: 17px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  flex: 0 0 auto;
  color: var(--text);
}
.lrow.is-ok .lrow__value { color: var(--ok); }
.lrow.is-warn .lrow__value { color: var(--warn); }
.lrow.is-muted { opacity: .6; }
/* Пойманная ошибка. Отмечена не только цветом: полоса слева видна и тем,
   кто цвет различает плохо, и боковым зрением в списке из двадцати строк. */
.lrow.is-error { border-left: 3px solid var(--danger); padding-left: 13px; }
.lrow.is-error .lrow__body b { color: var(--text); }

/* --- Строка замера --- */
/* Вся работа здесь — вписать число раз в неделю, и строки хватает. */
.mrow { display: flex; flex-direction: column; gap: 6px; padding: 12px 0; border-bottom: 1px solid var(--line); }
.mrow:last-child { border-bottom: 0; padding-bottom: 0; }
.mrow:first-child { padding-top: 0; }
.mrow__head { display: flex; align-items: baseline; gap: 10px; }
.mrow__hint { font-size: 13px; color: var(--muted); }
.mrow__edit { display: flex; align-items: center; gap: var(--gap-2); }
.mrow__edit .input { max-width: 130px; min-height: 52px; font-size: 18px; }
.mrow__unit { color: var(--muted); font-size: 14px; margin-right: auto; }

/* --- Оболочка экрана --- */
.page { display: flex; flex-direction: column; gap: var(--gap-4); }
/* Отступы задаёт раскладка, а не поля каждой карточки: иначе они то
   схлопываются, то удваиваются в зависимости от соседа. */
.page > .card { margin-bottom: 0; }
.page__body { display: flex; flex-direction: column; gap: var(--gap-4); }
.sec { display: flex; flex-direction: column; gap: var(--gap-3); }
.sec__title {
  margin: 0;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted);
}

/* Сводка: показатели рядом, цифры табличные — читаются столбиком. */
.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: var(--gap-2);
}
.stat {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}
.stat__label { font-size: 12px; color: var(--muted); text-transform: lowercase; }
.stat__value { font-size: 22px; font-variant-numeric: tabular-nums; letter-spacing: -0.02em; }
.stat.is-ok .stat__value { color: var(--ok); }
.stat.is-warn .stat__value { color: var(--warn); }

/* Шапка экрана: стрелка возврата вместо гамбургера на вложенных. */
.bar .icon-btn { font-size: 22px; }

/* --- Ответ дня --- */
/* Первое, что читают. Без рамки и фона: это речь тренера, а не карточка. */
.brief { display: flex; flex-direction: column; gap: var(--gap-3); }
/* Обоснование — не заголовок экрана. Раньше 21 px спорил с кнопкой действия
   за внимание, и взгляд первым делом падал на рассуждение, а не на то,
   что нужно сделать. */
.brief__text {
  margin: 0;
  font-size: 16px;
  line-height: 1.5;
  color: color-mix(in srgb, var(--text) 82%, transparent);
  text-wrap: pretty;
}
/* Совет по питанию: часть того же сообщения тренера, но своя мысль —
   отделён линией, а не отдельной карточкой. */
.brief__food {
  margin: 10px 0 0;
  padding-top: 10px;
  border-top: 1px solid var(--line);
  color: var(--muted);
  font-size: 14px;
  line-height: 1.45;
}

.brief__again {
  align-self: flex-start;
  min-height: 40px;
  padding: 0 12px;
  font-size: 14px;
  border: 0;
  background: transparent;
  color: var(--muted);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* Бюджеты времени: цифра крупная, подпись тихая — как на шкале. */
.minutes { display: flex; flex-direction: column; gap: var(--gap-2); }
.minutes__label { font-size: 14px; color: var(--muted); }
.minutes__row { display: flex; gap: var(--gap-2); }
.minutes__item {
  flex: 1;
  min-height: 62px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text);
}
.minutes__item b { font-size: 20px; font-variant-numeric: tabular-nums; letter-spacing: -0.02em; }
.minutes__item span { font-size: 11px; color: var(--muted); }
.minutes__item:active { transform: scale(.96); background: var(--surface-2); }

/* --- День как расписание --- */
.day { display: flex; flex-direction: column; gap: var(--gap-2); }
.day__head {
  display: flex;
  align-items: baseline;
  gap: var(--gap-2);
  flex-wrap: wrap;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--line);
}
.day__head b { font-size: 15px; letter-spacing: .01em; }
.day__totals { font-size: 13px; color: var(--muted); font-variant-numeric: tabular-nums; }
.day__events { display: flex; flex-direction: column; }

/* Время отдельной колонкой: день читается сверху вниз как расписание. */
.ev {
  display: grid;
  /* Четвёртая колонка — под карандаш правки. Без неё он уезжал на новую
     строку сетки и удваивал высоту каждой записи в ленте. Ширина фиксирована,
     чтобы строки без правки не разъезжались относительно строк с ней. */
  grid-template-columns: 44px 34px 1fr 32px;
  align-items: start;
  gap: var(--gap-3);
  width: 100%;
  min-height: 54px;
  padding: 9px 0;
  border: 0;
  background: transparent;
  color: var(--text);
  text-align: left;
}
.ev[disabled] { opacity: 1; pointer-events: none; }
.ev:not([disabled]):active { background: var(--surface-2); border-radius: var(--radius-sm); }
.ev__time {
  font-size: 13px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  padding-top: 3px;
}
.ev__dot { display: flex; align-items: center; justify-content: center; color: var(--muted); padding-top: 1px; }
.ev__dot.is-workout, .ev__dot.is-cardio { color: var(--accent); }
.ev__dot.is-checkin { color: var(--ok); }
.ev__body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ev__body b { font-weight: 600; }
.ev__detail { font-size: 14px; color: var(--muted); }
/* Незакрытое помечено словом и цветом текста, а не планкой сбоку. */
.ev.is-partial .ev__body b { color: var(--warn); }

/* --- Разговор на экране тренера --- */
/* Пузыри мессенджера здесь ни к чему: это не переписка двух людей, а вопрос
   и ответ. Реплики различаются подписью и линией слева, как в ленте дня. */
.chat { display: flex; flex-direction: column; gap: var(--gap-3); }
.talk {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 10px 0 10px 14px;
  border-left: 2px solid var(--line);
}
.talk--assistant { border-left-color: var(--accent); }
.talk__who { font-size: 11px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: .08em; }
.talk__text { line-height: 1.55; white-space: pre-wrap; }

/* --- Разговор в ленте --- */
/* Реплика в ленте — напоминание о разговоре, а не его копия: целиком он живёт
   на экране тренера. Ответ в пять строк превращал день в стену текста, где
   сами события терялись, поэтому здесь две строки и подпись в той же строке. */
.feed-talk {
  padding: 5px 0 5px 12px;
  border-left: 2px solid var(--line);
  margin: 2px 0 2px 44px;
  cursor: pointer;
}
.feed-talk--coach { border-left-color: var(--accent); }
.feed-talk__who {
  font-size: 11px;
  font-weight: 700;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: .08em;
  margin-right: 4px;
}
/* Время реплики мельче, чем колонка времени у событий: там оно опора взгляда,
   здесь — сноска. Одинаковый размер делал разговор вторым расписанием. */
.feed-talk__time {
  font-size: 11px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  margin-right: 6px;
}
.feed-talk__text {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  font-size: 14px;
  line-height: 1.4;
  color: var(--muted);
  white-space: pre-wrap;
}
/* Развёрнутая реплика читается как раньше: тап по ней — осознанное «покажи
   целиком», и обрезать текст после этого было бы издевательством. */
.feed-talk.is-open .feed-talk__text { -webkit-line-clamp: unset; color: var(--text); }

.feed-ask { display: flex; gap: var(--gap-2); align-items: center; }
.feed-ask__input { font-size: 16px; min-height: 52px; }
.feed-ask .btn { flex: 0 0 auto; min-height: 52px; }

/* --- Постоянное меню (ноут) --- */
/* На широком экране разделы всегда на виду: прятать их за кнопку — лишний
   тап на каждый переход. Ниже 1040 px тот же список уезжает в выдвижное меню. */
.sidebar {
  position: fixed;
  top: var(--banner-h, 0px);
  left: 0;
  bottom: 0;
  width: 236px;
  padding: var(--pad) 10px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  overflow-y: auto;
  background: var(--surface);
  border-right: 1px solid var(--line);
  z-index: 50;
}
.sidebar__head { padding: 4px 12px 18px; }
.sidebar__head b { font-size: 16px; letter-spacing: -0.01em; }
.sidebar__items { display: flex; flex-direction: column; gap: 2px; }

/* Содержимое центрируется в оставшемся месте, а не липнет к меню:
   иначе на широком ноуте экран выглядит сдвинутым в угол. */
body.has-sidebar #app {
  width: min(var(--shell), calc(100vw - 236px - 2 * var(--pad)));
  margin-left: max(236px, calc((100vw - var(--shell)) / 2));
  margin-right: 0;
}
body.has-sidebar .nav-btn { display: none; }
/* Плавающие кнопки не должны заезжать под меню. */
body.has-sidebar .llm-chip { left: calc(236px + 14px); }

/* --- Выдвижное меню --- */
.nav {
  position: fixed;
  inset: 0;
  z-index: 220;
  background: color-mix(in srgb, #000 55%, transparent);
  display: flex;
}
.nav__panel {
  width: min(300px, 82vw);
  height: 100%;
  overflow-y: auto;
  background: var(--surface);
  border-right: 1px solid var(--line);
  padding: var(--pad) 12px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  animation: nav-in .16s ease-out;
}
@keyframes nav-in { from { transform: translateX(-14px); opacity: .6; } to { transform: none; opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .nav__panel { animation: none; } }

.nav__head { display: flex; align-items: center; justify-content: space-between; padding: 0 10px 14px; }
.nav__head b { font-size: 17px; }
.nav__close {
  width: 44px; height: 44px;
  border: 0; background: transparent; color: var(--muted);
  font-size: 28px; line-height: 1;
}
.nav__item {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 52px;
  padding: 0 12px;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text);
  font-size: 16px;
  text-align: left;
}
.nav__item:active { background: var(--surface-2); }
.nav__item.is-current { background: var(--surface-2); color: var(--accent); font-weight: 600; }
.nav__item .icon { color: var(--muted); }
.nav__item.is-current .icon { color: var(--accent); }

/* --- Иконки --- */
/* Размер от шрифта родителя, цвет от текста: иконка нигде не выбивается
   и не требует отдельной перекраски под тему. */
.icon { display: block; flex: 0 0 auto; }

/* Старые стили недели (кольцо, плитки задач, .wk) удалены вместе с карточкой
   недели: они перехватывали новый класс .wk и возвращали блоку рамку. */

/* --- Список покупок --- */
.buy-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 4px solid var(--line);
  border-radius: var(--radius);
  padding: 14px 16px;
  margin-bottom: 10px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  justify-content: space-between;
}
/* Предложение тренера ждёт согласия — жёлтым, как всё незакрытое. */
.buy-card.is-suggested { border-left-color: var(--warn); }
.buy-card.is-needed { border-left-color: var(--accent); }
.buy-card.is-bought { border-left-color: var(--ok); opacity: .7; }
.buy-card.is-declined { opacity: .55; }
.buy-card__body { display: flex; flex-direction: column; gap: 4px; min-width: 220px; flex: 1 1 260px; }

/* --- Индикатор молчащей модели --- */
/* Появляется только когда модель не отвечает: пока всё работает, экран чистый. */
.llm-chip {
  position: fixed;
  left: 14px;
  bottom: 14px;
  z-index: 70;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  padding: 0 14px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--muted);
  font-size: 14px;
  font-weight: 600;
  box-shadow: 0 6px 18px rgba(0, 0, 0, .35);
}
.llm-chip__dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--muted);
  flex: 0 0 auto;
}
body[data-route^="/workout"] .llm-chip { bottom: auto; top: 12px; opacity: .5; }
/* На главном о молчании модели уже сказано в самом совете — плашка в углу
   была бы вторым сообщением о том же и накрывала бы строку ленты. */
body[data-route="/"] .llm-chip { display: none; }

/* Плашка «модель молчит» внутри экрана: там, где ответ ждали, а его не будет. */
.llm-note {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  border-radius: 14px;
  background: var(--surface-2);
  border: 1px dashed var(--line);
  color: var(--muted);
  font-size: 15px;
  margin-bottom: 12px;
}

.note-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 4px solid var(--line);
  border-radius: var(--radius);
  padding: 14px 16px;
  margin-bottom: 10px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  justify-content: space-between;
}
.note-card.is-new { border-left-color: var(--accent); }
.note-card.is-doing { border-left-color: var(--warn); }
.note-card.is-done { border-left-color: var(--ok); opacity: .7; }
.note-card__body { display: flex; flex-direction: column; gap: 4px; min-width: 220px; flex: 1 1 260px; }

/* Планшет в портретной ориентации — растягиваем главное действие. */
@media (max-width: 900px) {
  :root { --pad: 16px; }
  h1 { font-size: 28px; }
  .grid--3 { grid-template-columns: repeat(2, 1fr); }
}

/* --- Телефон --- */
/* Планшет остаётся основным носителем тренировки, но чек-ин, фото еды, воду
   и вопрос тренеру удобнее делать с телефона: он всегда в кармане. */
@media (max-width: 560px) {
  :root { --pad: 14px; }
  h1 { font-size: 25px; }
  h2 { font-size: 19px; }

  /* Фиксированные колонки на узком экране всегда обрезают правый край. */
  .grid--2,
  .grid--3 { grid-template-columns: 1fr; }
  .grid--auto { grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); }

  /* Плитки «у меня N минут» — по три в ряд, а не по одной на строку. */
  .tile { min-height: 76px; font-size: 24px; }
  .tile small { font-size: 12px; }

  /* Кнопки перестают быть в ряд и занимают ширину: пальцем так вернее. */
  .row > .btn { flex: 1 1 100%; }
  .row--tight > .btn,
  .row--tight > .pill { flex: 0 1 auto; }

  .ladder { grid-template-columns: repeat(auto-fill, minmax(116px, 1fr)); }
  .ladder__item { padding: 8px 10px; }
  .ladder__item b { font-size: 16px; }

  .exercise-grid { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); }
  .habits { grid-template-columns: 1fr 1fr; }

  .meal-card__photo { width: 68px; height: 68px; flex-basis: 68px; }
  .meal-card__body { min-width: 140px; }

  .chart { height: 130px; }
  .bubble { max-width: 94%; }
  .chat { max-height: 62vh; }

  /* Степпер: значение крупное, кнопки не сжимаются. */
  .stepper__btn { min-width: 56px; min-height: 56px; font-size: 26px; }
  .stepper__value { font-size: 24px; }
  .scale__btn { flex: 1 1 60px; min-height: 84px; font-size: 26px; }
}

/* --- Экран тренировки на телефоне: одной рукой --- */
@media (max-width: 560px) {
  .workout__title { font-size: 22px; margin-bottom: 10px; }
  .workout__gif { max-width: 190px; }
  .workout__cues { font-size: 15px; margin-top: 14px; }

  /* Порядок сверху вниз: что делать → сколько → «Готово» под большим пальцем. */
  .workout__controls { gap: 10px; }
  .dial__btn { min-width: 74px; min-height: 74px; font-size: 34px; border-radius: 18px; }
  .dial__value b { font-size: 40px; }

  .btn--hero { min-height: 84px; font-size: 22px; }

  /* Табло отдыха и кардио — цифры во весь экран, читаются с вытянутой руки. */
  .big-number { font-size: clamp(72px, 30vw, 128px); }
  .hr-block__value { font-size: clamp(52px, 20vw, 96px); }
  .rest__next { font-size: 17px; }
}


/* ==========================================================================
   Перекомпоновка экрана «Сегодня»
   ========================================================================== */

/* ==========================================================================
   Неделя — инфографика, а не семь кнопок
   ==========================================================================
   Первый вариант рисовал каждый день рамкой с заливкой. Получался ряд из
   семи одинаковых плиток: пустой вторник выглядел ровно так же весомо, как
   день с проведённой тренировкой, а сама полоса читалась как переключатель,
   который зачем-то не нажимается. Информации — ноль.

   Здесь вес несёт только заполненная метка: день с тренировкой — залитый
   кружок с буквой, пустой день — точка на сетке. Взгляд сразу видит ритм
   недели: где густо, где пусто. Цель «≥2 тренировки» показана двумя точками
   рядом с заголовком — правило, которое не нужно помнить. */
.wk {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 2px 2px 0;
}


/* Две точки цели: залитая — сделанная тренировка. */





.wk__carry { margin: 0; font-size: 12px; color: var(--muted); }

.wk__days { display: flex; gap: 2px; }
.wk__day {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  padding: 2px 0 4px;
  border: 0;
  background: transparent;
  color: var(--muted);
  min-width: 0;
  cursor: pointer;
  border-radius: 8px;
}
.wk__day-name {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .04em;
  line-height: 1;
}
/* Что было в этот день — словом под значком. Одна метка без подписи означала
   «что-то было», и это ровно тот вопрос, на который полоса должна отвечать. */
.wk__day-what {
  font-size: 9px;
  line-height: 1;
  min-height: 9px;
  color: var(--muted);
  letter-spacing: .02em;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.wk__day.is-workout .wk__day-what { color: var(--accent); font-weight: 700; }
/* Метка дня всегда одного размера — иначе полоса дёргается по высоте,
   когда в день добавляется вторая запись. */
.wk__day-mark {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  font-size: 12px;
  font-weight: 700;
  line-height: 1;
  background: color-mix(in srgb, var(--muted) 14%, transparent);
}
/* Пустой день — просто точка. Кольцо вокруг точки делало из недели ряд
   радиокнопок: семь одинаковых кружков с точкой посередине — это форма
   выбора, а не запись о прошедших днях. Кольца больше нет, осталась
   отметка «здесь ничего не было». */
.wk__day:not(.is-done) .wk__day-mark {
  background: none;
  box-shadow: none;
}
.wk__day:not(.is-done) .wk__day-mark::after {
  content: '';
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--muted) 42%, transparent);
}
/* Тренировка — залитая метка: главное событие недели видно издалека.
   Сауна и растяжка отмечаются, но тише: они не двигают счёт недели. */
.wk__day.is-workout .wk__day-mark { background: var(--accent); color: var(--on-accent, #fff); }
/* Неделя закрыта — метки зеленеют. Это единственное обозначение успеха:
   строка «Неделя успешная — 4 тренировки, 1 неделя подряд» требовала
   расшифровки каждого своего слова, а цвет читается сразу. */
.wk__day.is-goal .wk__day-mark { background: var(--ok); }
.wk__day.is-goal .wk__day-what { color: var(--ok); }
.wk__day.is-done:not(.is-workout) .wk__day-mark {
  background: color-mix(in srgb, var(--accent) 18%, transparent);
  color: var(--accent);
}
/* Сегодня — подчёркнутый день, а не выделенная заливкой плитка: заливка
   спорила с меткой тренировки, и было непонятно, что важнее. */
/* Сегодня — подчёркнутое имя дня. Обводка вокруг метки возвращала тот же
   вид «выбранной радиокнопки», от которого мы и уходили. */
.wk__day.is-today .wk__day-name {
  color: var(--text);
  font-weight: 700;
}
.wk__day.is-today {
  border-bottom: 2px solid var(--accent);
  border-radius: 8px 8px 0 0;
}
/* Метка сегодняшнего пустого дня — крупнее и чётче: это день, который ещё
   можно заполнить, а не такой же прочерк, как в прошлый вторник. */
.wk__day.is-today:not(.is-done) .wk__day-mark::after {
  width: 7px;
  height: 7px;
  background: color-mix(in srgb, var(--accent) 70%, transparent);
}

/* ==========================================================================
   Альтернативы главному действию
   ==========================================================================
   Мелко и приглушённо: это отступление от плана, а не равноправный выбор.
   Раньше то же самое занимало два отдельных блока и спорило с главной
   кнопкой за внимание. */
.alt {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-top: 10px;
}
.alt__label {
  font-size: 12px;
  color: var(--muted);
  flex: 0 0 auto;
}
/* Одной строкой с переносом: минуты и задачи недели — это один вопрос
   «а если иначе», и делить его на два ряда незачем. */
.alt__row { display: flex; gap: 5px; flex-wrap: wrap; flex: 1 1 auto; }
.alt__item {
  padding: 5px 11px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: transparent;
  color: var(--muted);
  font-size: 13px;
  cursor: pointer;
}
.alt__item.is-paused { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 45%, var(--line)); }
.alt__item.is-blocked { opacity: .5; }

/* Кнопка действия внутри карточки совета — первой, до текста: экран
   открывают с вопросом «что сейчас», а не «почитать рассуждение». */
.brief .hero { margin-top: 2px; }

/* Обоснование свёрнуто до трёх строк: развернуть можно тапом, но каждый раз
   читать пять предложений незачем. */
.brief__text {
  cursor: pointer;
  margin: 14px 0 0;
}
.brief__text.is-clamped {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
/* Многоточие само по себе не говорит, что текст можно раскрыть. */
.brief__text.is-clamped::after {
  content: '';
}

/* Вопрос дня: сон, стресс, болезненность — по одному, в одном месте
   и одной формой. Раньше это жило в трёх разных углах приложения. */
.qcard {
  display: flex;
  align-items: center;
  gap: var(--gap-2);
  flex-wrap: wrap;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
}
.qcard__label { font-size: 14px; color: var(--muted); flex: 0 0 auto; }
.qcard.is-answered { color: var(--muted); }
.qcard.is-answered b { color: var(--text); font-size: 15px; }
.qcard.is-answered .mini { margin-left: auto; }

/* Подпись «это сказал тренер» и оценка на полях — мелко и в одну строку
   с ним: отметка на полях, а не отдельное действие. */
.brief__head {
  display: flex;
  align-items: center;
  gap: var(--gap-2);
  margin-bottom: 8px;
}
.brief__who {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 12px;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--accent);
}
/* Пока модель думает — подпись приглушена: карточка уже полностью рабочая,
   ждём только обоснование. */
.brief__who.is-thinking { color: var(--muted); }
.brief__who.is-switch { gap: 2px; }
/* Два источника рядом: «по фактам» и то, что успела сказать модель.
   Нажатие переключает текст — это единственное место, где человек видит
   ответ, который не прошёл разбор. */
.brief__who-btn {
  padding: 3px 7px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--muted);
  font: inherit;
  font-size: 11px;
  letter-spacing: .04em;
  text-transform: uppercase;
  cursor: pointer;
}
.brief__who-btn.is-active {
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  color: var(--accent);
}
/* Черновик читается иначе, чем проверенный совет: курсив — тихая пометка
   «это не то, за что тренер отвечает». */
.brief__text.is-draft { font-style: italic; }

/* «Переделать» — единственная кнопка оценки. «По делу» нажимать было незачем:
   если совет подходит, человек просто идёт тренироваться, а не отчитывается. */
.brief__redo {
  margin-left: auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border: 0;
  border-radius: 9px;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
}
.brief__redo:hover, .brief__redo:focus-visible {
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  color: var(--accent);
}
.brief__redo.is-busy { color: var(--accent); animation: spin .9s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

/* Стили пары «по делу / не то» удалены вместе с самими кнопками: мёртвый CSS
   уже однажды перехватил новый класс и вернул блоку чужой вид. */

/* Ряд «сколько у меня есть» — уточнение к главному действию, а не
   самостоятельный блок: ниже ростом и без лишнего воздуха. */
.minutes--compact { margin-top: 8px; }
.minutes--compact .minutes__item { min-height: 46px; padding: 4px 0; }
.minutes--compact .minutes__item b { font-size: 17px; }

/* Профиль внизу меню. */
.sidebar__profile {
  margin-top: auto;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-2);
  color: var(--text);
  font-size: 14px;
  cursor: pointer;
}
.sidebar__profile:hover { border-color: color-mix(in srgb, var(--accent) 40%, var(--line)); }
.sidebar__profile-emoji { font-size: 17px; }

/* Тренировки в ленте — заметнее прочего: это главные события дня,
   а они терялись между едой и замерами. */
.ev.is-session {
  background: color-mix(in srgb, var(--accent) 7%, transparent);
  border-radius: 10px;
}
.ev.is-session .ev__body b { color: var(--text); font-weight: 700; }
.ev__dot.is-workout, .ev__dot.is-cardio, .ev__dot.is-sauna {
  background: color-mix(in srgb, var(--accent) 16%, transparent);
  border-radius: 9px;
}

/* ==========================================================================
   Отклик на курсор и лёгкое движение
   ==========================================================================
   На планшете наведения нет, но приложение открывают и с ноутбука, где
   неподсвеченная кнопка выглядит неживой. Всё через @media (hover: hover):
   на тач-экране такие правила залипают после тапа. */
@media (hover: hover) {
  .btn:hover:not(:disabled),
  .mini:hover:not(:disabled),
  .chips__item:hover,
  .minutes__item:hover,
  .wk:hover,
  .lrow:hover:not(:disabled) {
    border-color: color-mix(in srgb, var(--accent) 45%, var(--line));
  }
  .hero:hover { border-color: var(--accent); }
  .ev:hover:not(:disabled) { background: color-mix(in srgb, var(--accent) 10%, transparent); }
  .wk__day:hover .wk__day-mark { box-shadow: inset 0 0 0 1.5px var(--accent); }
  /* Карандаш на мыши: появляется у той строки, на которую смотришь. */
  .ev:hover .ev__edit { opacity: 1; }
  .talk:hover .talk__del { opacity: 1; }
  .ask-link:hover { border-color: color-mix(in srgb, var(--accent) 45%, var(--line)); }
}

/* Движение — только там, где оно объясняет: нажатие отзывается, новый блок
   не выпрыгивает. Длительности маленькие: анимация, которую замечаешь,
   в приложении между подходами мешает. */
.btn, .mini, .chips__item, .alt__item, .wk__day, .hero, .lrow, .ev, .ask-link {
  transition: border-color .15s ease, background-color .15s ease, color .15s ease;
}
.btn:active:not(:disabled),
.alt__item:active,
.hero:active { transform: scale(.985); }

.brief, .qcard { animation: rise .18s ease-out; }
@keyframes rise {
  from { opacity: 0; transform: translateY(4px); }
  to { opacity: 1; transform: none; }
}

/* Уважение к настройке системы: кому анимация мешает, тому её нет. */
@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}


/* ==========================================================================
   Слова тренера — с линией слева
   ==========================================================================
   Совет и кнопка под ним — это чья-то реплика, а не текст приложения.
   В ленте дня реплики уже отмечены линией слева; главный совет ничем не
   отличался от интерфейса, и было непонятно, кто это говорит. */
.brief__said {
  display: flex;
  flex-direction: column;
  gap: var(--gap-3);
  padding-left: 14px;
  border-left: 2px solid color-mix(in srgb, var(--accent) 55%, transparent);
}

/* ==========================================================================
   Карандаш правки — по наведению и по удержанию
   ==========================================================================
   Пять записей в дне — пять одинаковых карандашей, которые нужны раз в
   неделю: экран захламлён ради редкого действия. Теперь карандаш появляется
   у строки под курсором, а на планшете его заменяет удержание пальцем. */
.ev__edit {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  min-height: 32px;
  color: var(--muted);
  opacity: 0;
  transition: opacity .12s ease;
}
.ev.is-editing .ev__edit { opacity: 1; color: var(--accent); }
/* Пока экран трогают пальцем, наведения нет — карандаш не мигает вовсе. */
@media (hover: none) {
  .ev__edit { opacity: 0; }
}

/* Время и заголовок — по одной базовой линии.
   Выравнивание по верху ставило 13-пиксельное время выше 16-пиксельного
   заголовка: колонка времени читалась как съехавшая. */
.ev__time { align-self: baseline; padding-top: 0; }
.ev__body { align-self: baseline; }
/* Значок и фотография — в одинаковой рамке, иначе колонка рваная:
   фото 34 px рядом со значком 26 px не давали общей вертикали. */
.ev__dot, .ev__photo {
  width: 34px;
  height: 34px;
  flex: 0 0 34px;
  box-sizing: border-box;
}
.ev__dot { padding: 0; }
/* Эмодзи еды: цветной значок вместо серой вилки у записей без снимка.
   Размер чуть меньше рамки — иначе тарелка выпирает за колонку. */
.ev__dot.is-food { font-size: 24px; line-height: 1; }

/* ==========================================================================
   Вход в разговор с тренером
   ==========================================================================
   Поле ввода прямо в ленте обещало переписку, которой не было: свой вопрос
   на месте не оставался, ответ приходил через минуту в другое место экрана.
   Строка-ссылка ведёт туда, где разговор действительно живёт. */
.ask-link {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-height: 52px;
  padding: 0 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--muted);
  font-size: 15px;
  text-align: left;
  cursor: pointer;
}
.ask-link span { flex: 1; }
.ask-link svg { flex: 0 0 auto; }

/* Разговор на своём экране листается страницей, а не внутренним окошком:
   в клетке высотой 56vh новое сообщение оказывалось ниже видимой части,
   и человек не находил только что отправленный вопрос. */
.chat--page { max-height: none; overflow: visible; padding: 0; }
.talk { position: relative; }
.talk__del {
  position: absolute;
  top: 6px;
  right: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border: 0;
  background: transparent;
  color: var(--muted);
  opacity: 0;
  cursor: pointer;
  transition: opacity .12s ease;
}
.talk__del:hover, .talk__del:focus-visible { color: var(--warn); opacity: 1; }
/* Пальцем наведения нет — своя реплика показывает крестик сразу, приглушённо. */
@media (hover: none) {
  .talk--user .talk__del { opacity: .45; }
}
.talk.is-pending { opacity: .6; }

/* ==========================================================================
   Кнопка возврата к сегодняшнему дню
   ==========================================================================
   Плавающая, и только когда сегодняшний день ушёл с экрана. Без position:
   fixed она оставалась просто широкой кнопкой в самом низу ленты — там,
   где ей нечего делать. */
.to-today {
  position: fixed;
  left: 50%;
  bottom: calc(16px + env(safe-area-inset-bottom, 0px));
  z-index: 30;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 18px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text);
  box-shadow: 0 6px 20px rgb(0 0 0 / .18);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  opacity: 0;
  transform: translate(-50%, 12px);
  pointer-events: none;
  transition: opacity .16s ease, transform .16s ease;
}
.to-today.is-visible { opacity: 1; transform: translate(-50%, 0); pointer-events: auto; }


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

   На узком экране замечание идёт под записью, на широком — справа от неё,
   отдельной колонкой: там для него есть место, и день читается как таблица. */
.ev__coach {
  grid-column: 3 / 4;
  font-size: 13px;
  line-height: 1.4;
  color: color-mix(in srgb, var(--accent) 85%, var(--text));
  text-align: left;
}
.ev__coach:empty { display: none; }
.ev__coach.is-filled::before {
  content: '';
  display: inline-block;
  width: 12px;
  height: 1px;
  margin: 0 6px 4px 0;
  background: currentColor;
  opacity: .5;
}
@media (min-width: 760px) {
  .ev { grid-template-columns: 44px 34px minmax(0, 1fr) minmax(0, 0.75fr) 32px; }
  .ev__time { grid-column: 1; }
  .ev__dot, .ev__photo { grid-column: 2; }
  .ev__body { grid-column: 3; }
  .ev__coach { grid-column: 4; grid-row: 1; align-self: baseline; }
  .ev__edit { grid-column: 5; grid-row: 1; }
  .ev__coach.is-filled::before { display: none; }
}


/* Подпись под роликом техники: с какой стороны снято. Два ракурса без
   подписи выглядят как два одинаковых ролика, и второй просто не смотрят. */
.clip-figure { margin: 0; display: flex; flex-direction: column; gap: 6px; }
.clip-figure__cap {
  font-size: 12px;
  color: var(--muted);
  text-transform: lowercase;
  letter-spacing: .02em;
}

/* Ролик техники в отдыхе: шире экрана ему быть незачем, а высоту держим
   небольшой — это подсказка между подходами, а не просмотр видео. */
.rest__clip {
  width: 100%;
  max-width: 420px;
  max-height: 220px;
  border-radius: var(--radius-sm);
  background: #000;
  margin-bottom: var(--gap-2);
}


/* ==========================================================================
   Приёмка ролика человеком
   ==========================================================================
   Модель по кадрам путает разведение с жимом, а махи в стороны с подъёмами
   перед собой, и доверять ей удаление медиа нельзя. Человек, открывший
   карточку, видит движение целиком — вопрос задаётся ему, один раз.
   Сказал «да» — строка исчезает навсегда. */
.clip-check {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  font-size: 12px;
  color: var(--muted);
}
.clip-check__btn {
  min-height: 30px;
  padding: 0 12px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  font-size: 12px;
  cursor: pointer;
}
.clip-check__btn.is-yes:hover { color: var(--ok); border-color: var(--ok); }
.clip-check__btn.is-no:hover { color: var(--warn); border-color: var(--warn); }
.clip-check.is-flagged { color: var(--warn); }
/* Помеченный ролик остаётся на экране: другого-то пока нет. Но видно,
   что ему не доверяют. */
.clip-figure:has(.clip-check.is-flagged) .clip { opacity: .55; }


/* Тренировка, состав которой подобрал тренер. Отличается от соседних кнопок:
   это не «то же самое, но за другое время», а другой способ собрать день. */
.alt__item.is-ai {
  border-color: color-mix(in srgb, var(--accent) 45%, var(--line));
  color: var(--accent);
}
.alt__item.is-ai:hover { background: color-mix(in srgb, var(--accent) 12%, transparent); }

/* Почему сегодня такой состав — словами тренера, над списком упражнений. */
.ai-why {
  margin: 0 0 var(--gap-3);
  padding-left: 12px;
  border-left: 2px solid color-mix(in srgb, var(--accent) 55%, transparent);
  font-size: 15px;
  line-height: 1.5;
  color: color-mix(in srgb, var(--text) 85%, transparent);
}


/* ==========================================================================
   Пересмотр программы
   ==========================================================================
   Каждое предложение — своя карточка со своим решением. Кнопки «принять всё»
   тут нет намеренно: она превращает пересмотр в формальность, а это ровно
   то место, где стоит подумать. */
.prow {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 14px 0;
  border-bottom: 1px solid var(--line);
}
.prow:last-of-type { border-bottom: 0; }
.prow.is-decided { opacity: .6; }
.prow__head { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.prow__kind { font-size: 13px; color: var(--accent); }
.prow__num { font-size: 13px; color: var(--muted); }
.prow__why { margin: 0; font-size: 15px; line-height: 1.45; color: var(--muted); }
.prow__status { font-size: 13px; color: var(--muted); }
.prow__status.is-accepted { color: var(--ok); }

.pfacts { display: flex; flex-direction: column; gap: 6px; font-size: 15px; }
.pfacts b { font-size: 19px; }


/* Строка веса на экране прогрессий: где стоишь и что откроет прибавку. */
.wrow {
  display: flex;
  align-items: center;
  gap: var(--gap-3);
  width: 100%;
  padding: 12px 0;
  border: 0;
  border-bottom: 1px solid var(--line);
  background: transparent;
  color: var(--text);
  text-align: left;
  cursor: pointer;
}
.wrow:last-of-type { border-bottom: 0; }
.wrow__body { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.wrow__num { font-variant-numeric: tabular-nums; white-space: nowrap; }
.wrow.is-up .wrow__num b { color: var(--ok); }

/* Что произойдёт по нажатию «Принять». Кнопка с неизвестными последствиями —
   кнопка, которую не нажимают. */
.prow__effect {
  margin: 0 0 4px;
  font-size: 13px;
  line-height: 1.45;
  color: color-mix(in srgb, var(--accent) 80%, var(--text));
}


/* ==========================================================================
   Цель
   ==========================================================================
   Не график и не дашборд: ответ на два вопроса — чего я хочу и работает ли
   то, что я делаю. Разбор чужих проектов показал, что функций у нас не
   меньше, чем у зрелых трекеров; не хватало рамки, в которой они означают
   одно и то же. */
.goal-text { margin: 0 0 8px; font-size: 19px; line-height: 1.45; }
.goal-headline {
  margin: 12px 0 0;
  padding-top: 12px;
  border-top: 1px solid var(--line);
  color: var(--accent);
  font-size: 15px;
}

.gtarget { padding: 14px 0; border-bottom: 1px solid var(--line); }
.gtarget:last-child { border-bottom: 0; }
.gtarget__head { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.gtarget__now { color: var(--muted); font-size: 14px; }
.gtarget__left { margin-left: auto; font-size: 13px; color: var(--muted); }
.gtarget__left.is-done { color: var(--ok); }
.gtarget__scale {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  margin-top: 4px;
  font-size: 12px;
  color: var(--muted);
}
/* Середина шкалы — доля пути: полоса без числа не читается. */
.gtarget__scale span:nth-child(2) { color: var(--text); }

.gbar {
  height: 8px;
  margin-top: 8px;
  border-radius: 999px;
  background: var(--surface-2);
  overflow: hidden;
}
.gbar i { display: block; height: 100%; background: var(--accent); transition: width .3s ease; }
.gbar.is-done i { background: var(--ok); }
/* Ушли не туда — полоса пустая и подкрашена: ноль процентов честнее, чем
   бодрая полоска. */
.gbar.is-back { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--warn) 50%, transparent); }
/* Доля пути неизвестна — это не ноль. Пустая полоса читается как «сломано»,
   штриховка — как «пока нечего показать». */
.gbar.is-unknown {
  background: repeating-linear-gradient(
    135deg,
    var(--surface-2) 0 6px,
    color-mix(in srgb, var(--line) 60%, transparent) 6px 12px
  );
}

.gkinds { display: flex; flex-direction: column; gap: 8px; }
.gkinds__row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}
.gkinds__row.is-on { border-color: color-mix(in srgb, var(--accent) 45%, var(--line)); }
.gkinds__name { flex: 1; font-size: 15px; }
.gkinds__value { max-width: 120px; min-height: 44px; }


/* ==========================================================================
   Готовность к нагрузке
   ==========================================================================
   Одна строка вместо пяти дневников. Стоит между неделей и советом: неделя
   отвечает «где мы в неделе», готовность — «что со мной сегодня», совет —
   «что из этого делать». */
.ready {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text);
  font-size: 14px;
  text-align: left;
  cursor: pointer;
}
.ready__text { flex: 1; min-width: 0; }
.ready__score { font-variant-numeric: tabular-nums; color: var(--muted); font-size: 13px; }
.ready__dot { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; background: var(--muted); }
.ready--high .ready__dot { background: var(--ok); }
.ready--normal .ready__dot { background: var(--accent); }
.ready--low .ready__dot { background: var(--warn); }
.ready--low { border-color: color-mix(in srgb, var(--warn) 40%, var(--line)); }


/* Что уже сделано сегодня — значками у заголовка. Раньше это приходилось
   искать в ленте дня внизу экрана. */
.bar__marks { display: flex; align-items: center; gap: 8px; margin-left: auto; }
.bar__mark { color: var(--muted); display: flex; }
.bar__mark.is-workout, .bar__mark.is-cardio { color: var(--accent); }
.bar__mark.is-checkin { color: var(--ok); }

/* Подпись «ТРЕНЕР» стоит вплотную к своим словам, а не посередине между
   готовностью и советом: она относится к тому, что ниже. */
.brief { gap: 6px; }
.brief__head { margin-bottom: 0; }
/* Между полосой недели и готовностью — воздух: это разные вопросы
   («где мы в неделе» и «что со мной сегодня»). */
.wk { margin-bottom: 4px; }
.brief__said { gap: var(--gap-3); }


/* Подпись «Тренер» над колонкой замечаний в ленте дня.
   Без неё замечания читаются как часть самой записи — а это чьи-то слова,
   и видно должно быть чьи. Показывается, только когда замечания есть. */
.day__coach-label {
  display: none;
  align-items: center;
  gap: 5px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--accent);
}
.day:has(.ev__coach.is-filled) .day__coach-label { display: flex; }
/* На широком экране замечания идут правой колонкой — подпись встаёт над ней,
   а не в конец строки итогов. */
@media (min-width: 760px) {
  .day:has(.ev__coach.is-filled) .day__head {
    display: grid;
    grid-template-columns: 44px 34px minmax(0, 1fr) minmax(0, 0.75fr) 32px;
    align-items: baseline;
  }
  .day__head b { grid-column: 1 / 4; }
  .day__totals { grid-column: 1 / 4; }
  .day__coach-label { grid-column: 4; }
}


/* ==========================================================================
   Тренировка: весь список занятий
   ==========================================================================
   «Захочу побегать — а не могу, нет нигде такой кнопки». Главный экран
   показывает одно уместное действие, остальное запускалось только через
   карточку незакрытой задачи недели. Здесь список целиком, и ничего
   не заблокировано: несвоевременное помечено словами. */
.train { display: flex; flex-direction: column; gap: var(--gap-3); }

.train__item {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  overflow: hidden;
}
/* Не ко времени — приглушено, но нажимается: это подсказка, а не запрет. */
.train__item.is-untimely { opacity: .72; }

.train__main {
  display: flex;
  align-items: center;
  gap: var(--gap-3);
  width: 100%;
  min-height: 64px;
  padding: 14px 16px;
  background: transparent;
  color: var(--text);
  text-align: left;
}
.train__icon { flex: 0 0 24px; color: var(--accent); display: flex; }
.train__body { flex: 1; display: flex; flex-direction: column; gap: 3px; }
.train__body b { font-size: 17px; }
.train__text { font-size: 14px; color: var(--muted); line-height: 1.35; }
.train__warn { font-size: 13px; color: var(--warn); }
.train__go { flex: 0 0 20px; color: var(--muted); display: flex; }

.train__times {
  display: flex;
  gap: var(--gap-2);
  padding: 0 16px 14px 56px;
  flex-wrap: wrap;
}
/* Умолчание отмечено, но остальные окна такие же нажимаемые. */
.train__times .chip { min-height: 40px; padding: 0 12px; font-size: 14px; }
.train__times .chip.is-on {
  border-color: color-mix(in srgb, var(--accent) 55%, var(--line));
  color: var(--accent);
}

@media (max-width: 480px) {
  .train__times { padding-left: 16px; }
}

/* Занятие, поданное тренером прямо в разговоре. Кнопка ниже реплики, а не
   вместо неё: совет остаётся текстом, кнопка избавляет от поисков экрана. */
.talk__open { display: flex; flex-wrap: wrap; gap: var(--gap-2); margin-top: 8px; }
.talk__open-btn {
  min-height: 40px;
  padding: 0 14px;
  font-size: 14px;
  border: 1px solid color-mix(in srgb, var(--accent) 45%, var(--line));
  color: var(--accent);
  background: transparent;
}

/* Расход модели по неделям. Цифра нужна не ради красоты: облачная модель
   считает токены, и без неё счёт приходит неожиданно. */
.usage { padding: 10px 0; border-bottom: 1px solid var(--line); }
.usage:last-child { border-bottom: none; }
.usage__head { display: flex; align-items: baseline; gap: var(--gap-2); }
.usage__total { margin-left: auto; font-variant-numeric: tabular-nums; color: var(--accent); font-weight: 600; }
.usage__meta { font-size: 13px; color: var(--muted); margin-top: 2px; }
.usage__model {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 6px;
  font-size: 13px;
  color: var(--muted);
}
.usage__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.usage__num { margin-left: auto; font-variant-numeric: tabular-nums; }

/* Веха: факт из истории с датой. Не значок и не медаль — строка. */
.mstone {
  display: flex;
  align-items: baseline;
  gap: var(--gap-3);
  padding: 9px 0;
  border-bottom: 1px solid var(--line);
}
.mstone:last-child { border-bottom: none; }
.mstone__body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.mstone__date {
  margin-left: auto;
  flex: 0 0 auto;
  font-size: 13px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* Строка рекорда: название, результат, дата — тремя колонками, чтобы
   вертикаль читалась и числа стояли друг под другом.
   Имя с префиксом `rec-`: `.prow` уже занято строкой разбора программы,
   и без префикса раскладка молча не применялась — те же грабли, что с `.mrow`. */
.rec-row {
  display: flex;
  flex-direction: row;
  align-items: baseline;
  gap: var(--gap-2);
  width: 100%;
  padding: 9px 0;
  border-bottom: 1px solid var(--line);
  background: transparent;
  color: var(--text);
  text-align: left;
  min-height: 44px;
}
.rec-row:last-child { border-bottom: none; }
.rec-row__name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rec-row__value { font-weight: 600; font-variant-numeric: tabular-nums; }
.rec-row__date { flex: 0 0 auto; width: 72px; text-align: right; font-size: 13px; color: var(--muted); }

/* Правила прогрессии: сначала предложениями, потом числами.
   Имя с префиксом `rule-`, чтобы не столкнуться с `.row` и `.prow`. */
.rule-line { margin: 0 0 8px; font-size: 15px; line-height: 1.45; }
.rule-line:last-child { margin-bottom: 0; }

.rules-edit { margin-top: var(--gap-2); }
.rules-edit > summary {
  min-height: 44px;
  display: flex;
  align-items: center;
  cursor: pointer;
  color: var(--accent);
  font-size: 15px;
}
.rule-row {
  display: flex;
  align-items: center;
  gap: var(--gap-3);
  padding: 8px 0;
  border-bottom: 1px solid var(--line);
}
.rule-row:last-of-type { border-bottom: none; }
.rule-row__body { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.rule-row__input { width: 84px; flex: 0 0 84px; min-height: 44px; text-align: center; }

/* Шапка реплики: кто и когда. Время приглушено — оно нужно, чтобы понять,
   утро это или прошлая неделя, а не чтобы его читали. */
.talk__head { display: flex; align-items: baseline; gap: 8px; }
.talk__time { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }

/* ==========================================================================
   Вход
   ==========================================================================
   Пока сессии нет, на экране только форма: меню, лента и очередь не нужны,
   и наполнить их всё равно нечем — сервер отвечает 401. */
.login {
  min-height: 70vh;
  display: flex;
  align-items: center;
  justify-content: center;
}
.login__card {
  width: 100%;
  max-width: 380px;
  padding: 24px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
}
.login__title { margin: 0 0 10px; font-size: 24px; }
.login__lead { margin: 0 0 18px; color: var(--muted); line-height: 1.45; }
/* Шесть цифр крупно и вразрядку: их вводят с телефона, глядя в другой экран. */
.login__code {
  width: 100%;
  min-height: 64px;
  font-size: 30px;
  letter-spacing: .32em;
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.login__error { min-height: 20px; margin: 8px 0 12px; color: var(--danger); font-size: 14px; }
.login__hint { margin: 14px 0 0; font-size: 13px; color: var(--muted); line-height: 1.4; }
