@import url("/static/tokens/tokens.css");

/* ==========================================================================
   РАЗГОН — мини-апп на дизайн-системе «Форма».

   Ни одного сырого hex и ни одного произвольного px: всё, что не пришло
   из tokens.css напрямую, собрано из токенов через calc() в блоке ниже.
   Единственные литералы во всём файле — --line-w (1px) и --ring-w (2px):
   толщину волосяной линии система числом не задаёт, а components.md
   сам пишет «1px solid var(--stroke-strong)».
   ========================================================================== */

/* --------------------------------------------------------------------------
   Шрифты. Локальные вариативные woff2, сабсеты cyrillic + latin, 165 КБ.
   Внешних запросов нет: мини-апп грузится в вебвью и должен открываться сразу.
   Источник — комментарий со ссылкой на Google Fonts в tokens.css.
   -------------------------------------------------------------------------- */

@font-face {
  font-family: "Unbounded";
  font-style: normal;
  font-weight: 300 600;
  font-display: swap;
  src: url("/static/fonts/Unbounded-cyrillic.woff2") format("woff2");
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: "Unbounded";
  font-style: normal;
  font-weight: 300 600;
  font-display: swap;
  src: url("/static/fonts/Unbounded-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Onest";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("/static/fonts/Onest-cyrillic.woff2") format("woff2");
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: "Onest";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("/static/fonts/Onest-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 400 500;
  font-display: swap;
  src: url("/static/fonts/JetBrainsMono-cyrillic.woff2") format("woff2");
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 400 500;
  font-display: swap;
  src: url("/static/fonts/JetBrainsMono-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

/* --------------------------------------------------------------------------
   Прикладной слой размеров. Каждое значение собрано из токенов —
   произвольных чисел здесь нет.
   -------------------------------------------------------------------------- */

:root {
  --line-w: 1px;                                           /* волосяная линия */
  --ring-w: 2px;                                           /* обводка «сегодня» */

  --size-sign: calc(var(--space-6) + var(--space-1));       /* 28 — знак в шапке */
  --size-avatar: calc(var(--touch-min) - var(--space-2));   /* 36 */
  --size-avatar-sm: calc(var(--touch-min) - var(--space-4));/* 28 — аватар в строке */
  --size-dot: calc(var(--touch-min) - var(--space-2));      /* 36 — кружок ленты */
  --size-check: var(--space-6);                             /* 24 — чекбокс */
  --size-icon: calc(var(--space-4) + var(--space-1));       /* 20 */
  --size-icon-sm: var(--space-4);                           /* 16 */

  --h-btn-md: var(--touch-min);                             /* 44 */
  --h-btn-lg: calc(var(--touch-min) + var(--space-2));      /* 52 */
  --h-bar: var(--space-1);                                  /* 4 — сплит-бар */
  --lift: calc(var(--space-1) * -0.75);                     /* -3 — ховер карточки */

  --nav-pad: var(--space-2);                                /* вставка пилюли */
  --nav-h: calc(var(--touch-min) + var(--nav-pad) * 2);     /* 60 */

  --page-pad: var(--space-4);                               /* поля мини-аппа */
  --measure: calc(var(--page-max) / 2 - var(--space-6));     /* 616 — мера строки ~620 */
  --stagger: 40ms;                                          /* раздел «Анимация» */
}

/* --------------------------------------------------------------------------
   Каркас
   -------------------------------------------------------------------------- */

html {
  background: var(--canvas);
  -webkit-text-size-adjust: 100%;
}

body {
  min-height: 100%;
  overflow-x: hidden;
  overscroll-behavior-y: none;
  text-wrap: pretty;
}

button {
  font: inherit;
  color: inherit;
  margin: 0;
  border: 0;
  background: none;
  text-align: left;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

svg { display: block; }

#app {
  max-width: var(--page-max);
  margin: 0 auto;
  padding: var(--space-4) var(--page-pad)
    calc(var(--nav-h) + var(--tg-bottom-inset) + var(--space-6) + env(safe-area-inset-bottom));
}

.screen { display: none; }

.screen.is-active {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
}

/* min-width флекс-элемента по умолчанию auto: без этого длинное моно-значение
   или лента дней могут распереть колонку по горизонтали. */
.screen.is-active > * { min-width: 0; }

/* --------------------------------------------------------------------------
   Типографические примитивы
   -------------------------------------------------------------------------- */

.mono {
  font: var(--text-label);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  overflow-wrap: anywhere;
}

.mono-dim { color: var(--ink-70); }
.mono-off { color: var(--ink-40); }

.metric {
  display: block;
  font: var(--text-metric);
  letter-spacing: var(--tracking-metric);
  font-variant-numeric: tabular-nums;
}

.h1 {
  margin: 0;
  font: var(--text-h1);
  letter-spacing: var(--tracking-h1);
  text-wrap: balance;
}

.h2 {
  margin: 0;
  font: var(--text-h2);
  letter-spacing: var(--tracking-h2);
  text-wrap: balance;
  overflow-wrap: anywhere;
  hyphens: auto;
}

/* --------------------------------------------------------------------------
   Кнопки — по components.md
   -------------------------------------------------------------------------- */

.btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  font: var(--text-ui);
  border-radius: var(--radius-md);
  padding-inline: var(--space-6);
  transition: background var(--dur-micro) var(--ease-out),
    color var(--dur-micro) var(--ease-out);
}

.btn-md { min-height: var(--h-btn-md); }
.btn-lg { min-height: var(--h-btn-lg); width: 100%; }

/* Главная: светлая заливка на тёмном. Не лайм — см. «Так / не так». */
.btn-primary { background: var(--ink); color: var(--canvas); }
.btn-primary:hover { background: var(--ink-hover); }

/* Акцентная: только внутри карточки, которая и без неё тянет внимание. */
.btn-accent { background: var(--accent); color: var(--on-accent); }
.btn-accent:hover { background: var(--accent-deep); }

.btn-outline {
  background: transparent;
  color: var(--ink);
  border: var(--line-w) solid var(--stroke-strong);
}
.btn-outline:hover { background: var(--surface); }

.btn-ghost { color: var(--ink-70); }
.btn-ghost:hover { color: var(--ink); }

.btn.is-done,
.btn[disabled] {
  background: var(--surface);
  color: var(--ink-40);
  cursor: not-allowed;
}

/* --------------------------------------------------------------------------
   Шапка: знак 28 + курс моно-капсом + аватар 36
   -------------------------------------------------------------------------- */

.topbar {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

/* components.md рисует знак как «--ink с лаймовой буквой» — это верно для
   светлой темы, где --ink тёмный. В тёмной --ink светлый, и лайм на нём даёт
   контраст ~1.3:1. Правило контраста из design-system.md старше, поэтому
   буква тёмная — тот же приём, что у главной кнопки. */
.sign {
  flex: none;
  width: var(--size-sign);
  height: var(--size-sign);
  border-radius: var(--radius-sm);
  background: var(--ink);
  color: var(--canvas);
  display: grid;
  place-items: center;
  font: var(--text-ui);
  font-family: var(--font-display);
}

.topbar-course {
  flex: 1;
  min-width: 0;
  color: var(--ink-70);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.avatar {
  flex: none;
  width: var(--size-avatar);
  height: var(--size-avatar);
  border-radius: var(--radius-full);
  overflow: hidden;
  background: var(--paper);
  color: var(--ink-40);
  display: grid;
  place-items: center;
}

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

/* --------------------------------------------------------------------------
   Карточки и сетка плиток
   -------------------------------------------------------------------------- */

.card {
  background: var(--surface);
  border-radius: var(--radius-lg);
  padding: var(--space-4);
  display: flex;
  flex-direction: column;
  transition: transform var(--dur-micro) var(--ease-out);
}

.grid-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-4);
  align-items: stretch;
}

/* Единственная поверхность с --wash-live. Занимает всю ширину строки:
   раньше она была растянута по высоте двух правых плиток и набирала
   66px пустоты между названием и данными. Теперь высота — ровно по контенту. */
.card-live {
  grid-column: 1 / -1;
  background: var(--wash-live);
  gap: var(--space-6);
}

.card-live:hover { transform: translateY(var(--lift)); }
.card-live:active { transform: none; }

.card-live-head {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* Название — главный элемент экрана, поэтому крупнее метрик в плитках */
.card-live-title {
  font: var(--text-h1);
  letter-spacing: var(--tracking-h1);
  text-wrap: balance;
  overflow-wrap: anywhere;
  hyphens: auto;
}

/* Подвал: две моно-строки данных слева, действие справа */
.card-live-foot {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-4);
}

.card-live-data {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
}

.card-live-foot .btn { flex: none; }

/* Плитка данных: подпись сверху → крупное значение → моно → график снизу */
.tile {
  justify-content: space-between;
  gap: var(--space-6);
}

.tile-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* Сплит-бар. Лайма нет: бюджет акцента на этом экране занят кружком ленты,
   поэтому градация идёт --ink-80 (закрыто) → --chart-grey (сегодня) → трек. */
.splitbar {
  display: flex;
  gap: var(--line-w);
  height: var(--h-bar);
  border-radius: var(--radius-full);
  background: var(--sunken);
  overflow: hidden;
}

.splitbar span {
  display: block;
  width: 0;
  transition: width var(--dur-panel) var(--ease-panel);
}

.splitbar-done { background: var(--ink-80); }
.splitbar-now { background: var(--chart-grey); }

/* --------------------------------------------------------------------------
   Лента дней — во всю ширину, горизонтальный скролл, автоцентровка
   -------------------------------------------------------------------------- */

.tape-wrap { margin-inline: calc(var(--page-pad) * -1); }

.tape {
  display: flex;
  gap: var(--space-2);
  padding-inline: var(--page-pad);
  overflow-x: auto;
  scrollbar-width: none;
}

.tape::-webkit-scrollbar { display: none; }

.tape-day {
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);
}

.tape-dot {
  width: var(--size-dot);
  height: var(--size-dot);
  border-radius: var(--radius-full);
  display: grid;
  place-items: center;
  background: var(--sunken);
  color: var(--ink-70);
  transition: background var(--dur-panel) var(--ease-panel),
    color var(--dur-panel) var(--ease-panel),
    box-shadow var(--dur-panel) var(--ease-panel);
}

.tape-dot .icon { width: var(--size-icon); height: var(--size-icon); }

.tape-num {
  font: var(--text-label);
  letter-spacing: var(--tracking-label);
  color: var(--ink-40);
  font-variant-numeric: tabular-nums;
}

/* Пройденные */
.tape-day.is-done .tape-dot { background: var(--surface); color: var(--ink-70); }

/* Сегодняшний — единственное лаймовое пятно экрана */
.tape-day.is-today .tape-dot {
  background: transparent;
  box-shadow: inset 0 0 0 var(--ring-w) var(--accent);
}

.tape-day.is-today .tape-num { color: var(--ink); }

.tape-pip {
  width: var(--space-2);
  height: var(--space-2);
  border-radius: var(--radius-full);
  background: var(--accent);
}

/* После чек-ина кружок заливается целиком */
.tape-day.is-lit .tape-dot {
  background: var(--accent);
  color: var(--on-accent);
  box-shadow: none;
}

.tape-day.is-lit .tape-pip { display: none; }

/* --------------------------------------------------------------------------
   План на сегодня — чек-лист строками через --hairline
   -------------------------------------------------------------------------- */

.plan {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.checklist { display: flex; flex-direction: column; }

.check {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  min-height: var(--touch-min);
  padding-block: var(--space-2);
  border-bottom: var(--line-w) solid var(--hairline);
}

.check:last-child { border-bottom: 0; }

.check-box {
  flex: none;
  width: var(--size-check);
  height: var(--size-check);
  border-radius: var(--radius-full);
  display: grid;
  place-items: center;
  color: transparent;
  box-shadow: inset 0 0 0 var(--line-w) var(--ink-40);
  transition: background var(--dur-micro) var(--ease-out),
    box-shadow var(--dur-micro) var(--ease-out),
    color var(--dur-micro) var(--ease-out);
}

.check-box .icon { width: var(--size-icon-sm); height: var(--size-icon-sm); }

.check-text {
  flex: 1;
  min-width: 0;
  font: var(--text-body);
  color: var(--ink-40);
  transition: color var(--dur-micro) var(--ease-out);
}

.check-dur {
  flex: none;
  color: var(--ink-40);
  font-variant-numeric: tabular-nums;
}

/* Текущий пункт */
.check.is-current .check-box { box-shadow: inset 0 0 0 var(--line-w) var(--chart-grey); }
.check.is-current .check-text { color: var(--ink-80); }

/* Выполненный пункт */
.check.is-checked .check-box {
  background: var(--accent);
  color: var(--on-accent);
  box-shadow: none;
}
.check.is-checked .check-text { color: var(--ink); }
.check.is-checked .check-dur { color: var(--ink-70); }

/* --------------------------------------------------------------------------
   Таб-бар — плавающая пилюля. Хром, вне бюджета акцента.
   -------------------------------------------------------------------------- */

.tabbar {
  position: fixed;
  left: var(--page-pad);
  right: var(--page-pad);
  bottom: calc(var(--tg-bottom-inset) + env(safe-area-inset-bottom));
  z-index: 2;
  max-width: calc(var(--page-max) - var(--page-pad) * 2);
  margin-inline: auto;
}

.tabbar-inner {
  display: flex;
  gap: var(--space-1);
  padding: var(--nav-pad);
  border-radius: var(--radius-full);
  background: var(--surface);
  box-shadow: var(--shadow-lift);
}

.tab {
  flex: 1;
  min-height: var(--touch-min);
  border-radius: var(--radius-md);
  display: grid;
  place-items: center;
  color: var(--ink-70);
  transition: background var(--dur-micro) var(--ease-out),
    color var(--dur-micro) var(--ease-out);
}

/* display: grid перебивает display: none из UA-стилей для [hidden] */
.tab[hidden] { display: none; }

.tab:hover { color: var(--ink); }

.tab.is-active {
  background: var(--accent);
  color: var(--on-accent);
}

/* --------------------------------------------------------------------------
   Иконки
   -------------------------------------------------------------------------- */

.icon {
  width: var(--size-icon);
  height: var(--size-icon);
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* --------------------------------------------------------------------------
   Тосты
   -------------------------------------------------------------------------- */

.toasts {
  position: fixed;
  left: var(--page-pad);
  right: var(--page-pad);
  bottom: calc(var(--nav-h) + var(--tg-bottom-inset) + var(--space-3) + env(safe-area-inset-bottom));
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  pointer-events: none;
}

.toast {
  max-width: 100%;
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-full);
  background: var(--paper);
  color: var(--ink);
  font: var(--text-ui);
  box-shadow: var(--shadow-lift);
  animation: toast-in var(--dur-panel) var(--ease-panel) both;
}

.toast.is-leaving { animation: toast-out var(--dur-panel) var(--ease-out) both; }

@keyframes toast-in { from { opacity: 0; transform: translateY(var(--space-3)); } }
@keyframes toast-out { to { opacity: 0; transform: translateY(var(--space-2)); } }

/* --------------------------------------------------------------------------
   Появление экрана — stagger 40ms, один раз, ничего не циклится
   -------------------------------------------------------------------------- */

@keyframes enter { from { opacity: 0; transform: translateY(var(--space-3)); } }

.screen.is-active > * {
  animation: enter var(--dur-data) var(--ease-panel) both;
  animation-delay: calc(var(--stagger) * var(--i, 0));
}

.screen.is-active > *:nth-child(1) { --i: 0; }
.screen.is-active > *:nth-child(2) { --i: 1; }
.screen.is-active > *:nth-child(3) { --i: 2; }
.screen.is-active > *:nth-child(4) { --i: 3; }
.screen.is-active > *:nth-child(5) { --i: 4; }
.screen.is-active > *:nth-child(6) { --i: 5; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
  }
}

/* --------------------------------------------------------------------------
   Шапка экрана: моно-подпись сверху, заголовок снизу
   -------------------------------------------------------------------------- */

.screen-head {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.prose {
  margin: 0;
  max-width: var(--measure);
  font: var(--text-body);
  color: var(--ink-80);
}

.stack {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.btn-back { align-self: flex-start; padding-inline: 0; }

/* --------------------------------------------------------------------------
   Строки списка — рейтинг, награды, ученики куратора.
   Лента идёт в край экрана, содержимое строки выровнено с заголовком.
   -------------------------------------------------------------------------- */

.rows {
  display: flex;
  flex-direction: column;
  margin-inline: calc(var(--page-pad) * -1);
}

.row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--touch-min);
  padding: var(--space-3) var(--page-pad);
  border-bottom: var(--line-w) solid var(--hairline);
}

.row:last-child { border-bottom: 0; }

.row-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.row-title {
  font: var(--text-ui);
  color: var(--ink);
  overflow-wrap: anywhere;
}

.row-sub { color: var(--ink-40); font: var(--text-caption); }

/* Моно-вариант подстроки: два класса перебивают одиночный .row-sub выше */
.row-sub.mono {
  font: var(--text-label);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
}

.row-value {
  flex: none;
  color: var(--ink-80);
  font-variant-numeric: tabular-nums;
}

/* Маркер индекса: моно [ 01 ] на --surface при --radius-full (components.md) */
.marker {
  flex: none;
  display: grid;
  place-items: center;
  min-height: var(--space-6);
  padding-inline: var(--space-2);
  border-radius: var(--radius-full);
  background: var(--surface);
  color: var(--ink-70);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Аватар участника: фото из Telegram или монохромный силуэт. Без инициалов. */
.row-avatar {
  flex: none;
  width: var(--size-avatar-sm);
  height: var(--size-avatar-sm);
  border-radius: var(--radius-full);
  overflow: hidden;
  background: var(--paper);
  color: var(--ink-40);
  display: grid;
  place-items: center;
}

.row-avatar img { width: 100%; height: 100%; object-fit: cover; }
.row-avatar svg { width: 100%; height: 100%; }

/* Своя строка в рейтинге: заливка --paper, метка ТЫ справа */
.row.is-you {
  background: var(--paper);
  border-radius: var(--radius-md);
  border-bottom-color: transparent;
  margin-inline: var(--space-2);
  padding-inline: calc(var(--page-pad) - var(--space-2));
}

.row.is-you .row-avatar { background: var(--surface); }
.row.is-you .row-value { color: var(--ink); }

.chip-you {
  flex: none;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  background: var(--accent);
  color: var(--on-accent);
}

/* Награды. Лайм — только у последней полученной, закрытые уходят в --ink-40. */
.row.is-locked .marker { color: var(--ink-40); }
.row.is-locked .row-title { color: var(--ink-70); }
.row.is-latest .marker { background: var(--accent); color: var(--on-accent); }

/* Ученики куратора: свотч состояния accent → chart-grey → ink-40 */
.row-swatch {
  flex: none;
  width: var(--space-2);
  height: var(--space-2);
  border-radius: var(--radius-full);
  background: var(--chart-grey);
}

.row.is-at-risk .row-swatch { background: var(--ink-40); }
.row.is-at-risk .row-title { color: var(--ink-70); }
.row.is-at-risk .row-value { color: var(--ink-40); }

/* Мелкая плитка метрики — три в ряд на ширине мини-аппа */
.grid-3 {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-2);
}

.tile-sm {
  gap: var(--space-3);
  padding: var(--space-3);
}
