/* Компоненты: поверхности, кнопки, поля, метки, карточки, списки, вкладки, лайк,
   таблица, пустое состояние, комментарии, уведомления, шапка и меню телефона.
   План: docs/Визуальный-план-v3.md, разделы 6 и 12. Только токены из tokens.css.

   Рамок нет. Разрешены только (6.2): рамка поля ввода, обводка фокуса, разделители
   внутри списков и таблиц, пунктир метки «не проверено», линия под вкладками.
   Теней нет. Элементы отделяются ступенью заливки: bg → surface-1 → surface-2 → surface-3 → surface-4 → surface-5.
   В тёмной теме каждая ступень светлее предыдущей, в светлой — темнее. */

/* ===== Поверхности (4.1, 4.2, 12.1) ===== */
.card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  padding: var(--card-pad);
  border-radius: var(--r-lg);
  background: var(--surface-1);
  transition: background-color var(--dur-base) var(--ease), transform var(--dur-base) var(--ease);
}
/* Главная карточка композиции (одна на композицию) */
.card--primary { background: var(--surface-2); }

/* Стекло: только там, где под элементом реально проходят фигуры */
.glass,
.card--glass {
  border-radius: var(--r-lg);
  background: var(--glass-bg);
  -webkit-backdrop-filter: blur(var(--glass-blur));
  backdrop-filter: blur(var(--glass-blur));
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .glass,
  .card--glass { background: var(--glass-fallback); }
}

/* Кликабельная карточка: растянутая ссылка на заголовке (.card__title a) или класс .card--link.
   Наведение — фон на ступень светлее и подъём на 2 px, рамка не появляется (11.3) */
.card--link:hover,
.card:has(.card__title a):hover { background: var(--surface-2); transform: translateY(var(--lift)); }
.card--primary.card--link:hover,
.card--primary:has(.card__title a):hover { background: var(--surface-3); }
.card--glass.card--link:hover,
.card--glass:has(.card__title a):hover { background: var(--glass-bg-hover); }

/* Ступень для элементов внутри карточки: метка, кнопка, «чек» суммы, наведение на строку и лайк.
   --raise — на ступень дальше от фона, чем карточка, --raise-hover — ещё на одну.
   Карточка под курсором сдвигается на ступень, и всё внутри сдвигается вместе с ней.
   Вне карточек элементы берут запасные значения (surface-2 / surface-3). */
.card { --raise: var(--surface-2); --raise-hover: var(--surface-3); }
.card--primary,
.card.card--link:hover,
.card:has(.card__title a):hover { --raise: var(--surface-3); --raise-hover: var(--surface-4); }
.card--primary.card--link:hover,
.card--primary:has(.card__title a):hover { --raise: var(--surface-4); --raise-hover: var(--surface-5); }

.card__title { font-size: var(--fs-h4); line-height: var(--lh-h4); letter-spacing: var(--ls-h4); text-wrap: balance; }
.card--primary .card__title { font-size: var(--fs-h3); line-height: var(--lh-h3); letter-spacing: var(--ls-h3); }
.card__title a::after { content: ""; position: absolute; inset: 0; border-radius: inherit; }
.card__title a:hover { color: var(--text); }

/* Город над названием */
.card__meta { order: -1; font-size: var(--fs-small); line-height: var(--lh-small); color: var(--text-2); }
.card > p:not([class]) { color: var(--text-2); }
.card__tags { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
/* Чипы и подпись под ними — один блок (в подвале выделенной карточки это один элемент ряда) */
.card__areas { display: flex; flex-direction: column; gap: var(--sp-1); min-width: 0; }
/* Подпись «ещё N» / «ещё N областей» под списком областей: карточки вузов, плитка «Области», «Области в базе» */
.more-note { color: var(--text-2); font-size: var(--fs-caption); line-height: var(--lh-caption); }
/* Низ карточек в ряду совпадает (7.2): к низу прижимается только подвал карточки,
   остальное содержимое стоит сверху. [допущение: в 14.3 было space-between на всей
   карточке — тогда в вытянутой карточке заголовок и список расходятся по высоте] */
.card__footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--sp-4);
  margin-top: auto;
  color: var(--text-2);
  font-size: var(--fs-small);
  line-height: var(--lh-small);
}
.card__actions { display: flex; align-items: center; gap: var(--sp-3); }
.card__actions a { white-space: nowrap; }
/* Кнопки и ссылки внутри кликабельной карточки — поверх растянутой ссылки */
.card__actions > *,
.card__tags a { position: relative; z-index: 1; }

/* Блоки на своей поверхности вне .card: комментарий — сплошная, вход и формы над фигурами — стекло */
.comment:not(.comment--reply) { border-radius: var(--r-lg); background: var(--surface-1); }
.auth {
  border-radius: var(--r-lg);
  background: var(--glass-bg);
  -webkit-backdrop-filter: blur(var(--glass-blur));
  backdrop-filter: blur(var(--glass-blur));
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .auth { background: var(--glass-fallback); }
}

/* ===== Кнопки (12.4) =====
   .btn без модификатора = .btn--secondary. На экране не больше одной .btn--primary.
   Фон вторичной всегда на ступень дальше от фона, чем подложка (--raise карточки). */
.btn {
  --btn-bg: var(--raise, var(--surface-2));
  --btn-bg-hover: var(--raise-hover, var(--surface-3));
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  min-height: var(--control-h);
  padding: var(--btn-pad-y) var(--btn-pad-x);
  border: 0;
  border-radius: var(--r-md);
  background: var(--btn-bg);
  color: var(--text);
  font-size: var(--fs-small);
  line-height: var(--lh-small);
  font-weight: var(--fw-regular);
  white-space: nowrap;
  cursor: pointer;
  transition:
    background-color var(--dur-fast) var(--ease),
    color var(--dur-fast) var(--ease),
    transform var(--dur-press) var(--ease);
}
.btn:hover { background: var(--btn-bg-hover); color: var(--text); }
.btn:active { transform: scale(var(--press-scale)); }

.btn--primary {
  --btn-bg: var(--accent);
  --btn-bg-hover: var(--accent-hover);
  color: var(--on-accent);
  font-weight: var(--fw-semibold);
}
.btn--primary:hover { color: var(--on-accent); }

/* Текстовая кнопка (12.4): без подчёркивания, цвет --text-2; при наведении подложка --raise и цвет --text.
   Поля внутрь (подложке есть где лечь) компенсированы отрицательным margin: текст стоит там же, где стоял
   бы без полей, и не прыгает рядом с другим текстом. Свой margin у кнопки — компенсировать там же. */
.btn--text {
  --btn-bg: transparent;
  --btn-bg-hover: var(--raise, var(--surface-2));
  min-height: auto;
  margin: calc(-1 * var(--sp-2)) calc(-1 * var(--sp-3));
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--r-md);
  color: var(--text-2);
  transition:
    background-color var(--dur-fast) var(--ease),
    color var(--dur-fast) var(--ease);
}
.btn--text:active { transform: none; }
/* Сразу за другой кнопкой в ряду («Войти» → «Регистрация», «Пройти заново» → «Смотреть вузы»)
   левую компенсацию не делаем: иначе подложка при наведении встаёт вплотную к соседней кнопке */
.btn + .btn--text { margin-inline-start: 0; }

.btn--lg {
  min-height: var(--control-h-lg);
  padding: var(--btn-pad-y-lg) var(--btn-pad-x-lg);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
}

/* Удаление: вторичная, текст цвета ошибки */
.btn--danger { color: var(--danger); }
.btn--danger:hover { color: var(--danger); }
/* Опасная главная (удаление аккаунта): заливка --danger вместо --accent, текст --on-danger */
.btn--primary.btn--danger { --btn-bg: var(--danger); --btn-bg-hover: var(--danger-hover); color: var(--on-danger); }
.btn--primary.btn--danger:hover { color: var(--on-danger); }

/* Недоступно: лучше избегать (12) */
.btn:disabled { --btn-bg-hover: var(--btn-bg); color: var(--text-3); cursor: not-allowed; transform: none; }

/* Кнопка-иконка: тема, лайк, бургер. 40×40, на телефоне 44×44. Без фона и рамки */
.btn--icon {
  --btn-bg: transparent;
  --btn-bg-hover: var(--raise, var(--surface-2));
  width: var(--icon-btn);
  height: var(--icon-btn);
  min-height: 0;
  padding: 0;
}
.btn--icon svg { width: var(--icon-size); height: var(--icon-size); }
.btn--icon[aria-current] { --btn-bg: var(--surface-2); }

/* Переключатель темы: в тёмной видно солнце, в светлой — луну */
.theme-toggle__moon,
[data-theme="light"] .theme-toggle__sun { display: none; }
[data-theme="light"] .theme-toggle__moon { display: block; }

/* ===== Ссылки в тексте: подчёркнуты тонко (1 px, --text-3), при наведении подчёркивание --text =====
   Текстовые кнопки (.btn--text) не подчёркиваются — у них подложка при наведении (12.4). */
.prose a,
.note a,
.empty a:not(.btn),
.field__hint a,
.checkbox a,
.table a,
.comment__meta a {
  color: var(--text);
  text-decoration: underline;
  text-decoration-thickness: var(--border);
  text-decoration-color: var(--text-3);
  text-underline-offset: var(--sp-1);
  transition: text-decoration-color var(--dur-fast) var(--ease);
}
.prose a:hover,
.note a:hover,
.empty a:not(.btn):hover,
.field__hint a:hover,
.checkbox a:hover,
.table a:hover,
.comment__meta a:hover { text-decoration-color: var(--text); }

/* Подписи */
.note { font-size: var(--fs-small); line-height: var(--lh-small); color: var(--text-2); }

/* ===== Формы (12.6) ===== */
.form { display: flex; flex-direction: column; gap: var(--sp-5); }
.form__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-4); }

.field { display: flex; flex-direction: column; gap: var(--sp-2); }
.field__label { font-size: var(--fs-small); line-height: var(--lh-small); color: var(--text); }
.field__hint { font-size: var(--fs-caption); line-height: var(--lh-caption); color: var(--text-2); }

/* Поле ввода — единственная постоянная рамка на сайте */
.input,
.form textarea {
  width: 100%;
  min-height: var(--field-h);
  padding: var(--field-pad-y) var(--field-pad-x);
  border: var(--border) solid var(--line);
  border-radius: var(--r-md);
  background: var(--field-bg);
  color: var(--text);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  transition: border-color var(--dur-fast) var(--ease);
}
.form textarea { resize: vertical; }
/* Числовое поле без браузерных стрелок: баллы и цену вводят с клавиатуры */
.input[type="number"] { -moz-appearance: textfield; appearance: textfield; }
.input[type="number"]::-webkit-inner-spin-button,
.input[type="number"]::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
.input::placeholder,
.form textarea::placeholder { color: var(--text-3); }
.input:hover,
.form textarea:hover { border-color: var(--line-strong); }

/* Ошибка: рамка поля, значок «!» в круге и текст. Смысл не только цветом */
.field:has(.field__error) .input,
.input[aria-invalid="true"] { border-color: var(--danger); }
.field__error,
.form__error {
  display: flex;
  align-items: baseline;
  gap: var(--sp-2);
  font-size: var(--fs-small);
  line-height: var(--lh-small);
  color: var(--danger);
}
/* Общая ошибка формы — на подложке, без рамки */
.form__error {
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--r-md);
  background: var(--surface-2);
}
/* Значок «!» в круге (12.17): контур круга — часть значка, а не рамка */
.field__error::before,
.form__error::before {
  content: "!";
  flex: none;
  display: inline-grid;
  place-items: center;
  width: var(--error-icon);
  height: var(--error-icon);
  border: var(--border) solid currentColor;
  border-radius: var(--r-round);
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  line-height: 1;
}

/* Чекбокс согласия: 20 px, рамка --line-strong; отмеченный — заливка --accent, галочка --on-accent */
.checkbox {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  font-size: var(--fs-small);
  line-height: var(--lh-small);
  cursor: pointer;
}
.checkbox input {
  appearance: none;
  -webkit-appearance: none;
  position: relative;
  flex: none;
  width: var(--checkbox-size);
  height: var(--checkbox-size);
  margin: 0;
  border: var(--border) solid var(--line-strong);
  border-radius: var(--r-sm);
  background: var(--field-bg);
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.checkbox input:checked { border-color: var(--accent); background: var(--accent); }
/* Галочка: два края повёрнутого прямоугольника */
.checkbox input:checked::after {
  content: "";
  position: absolute;
  inset: 0;
  width: 30%;
  height: 55%;
  margin: auto;
  border: solid var(--on-accent);
  border-width: 0 var(--border-strong) var(--border-strong) 0;
  transform: translateY(-10%) rotate(45deg);
}

/* Выпадающий список: то же поле 12.6, своя стрелка вместо браузерной [допущение].
   Без JS — обычный <select>. С JS (select.js) родной <select> скрыт, вместо него кнопка-поле .select__button и
   список .select__list в стиле сайта: панель на ступень выше поля, варианты как строки с наведением, выбранный —
   с галочкой (смысл не только цветом). Список проявляется и сдвигается на 4 px; вверх — .select--up */
.select { position: relative; display: block; }
.select select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: calc(var(--field-pad-x) * 2 + var(--icon-size));
  cursor: pointer;
}
.select__native { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.select__chevron {
  position: absolute;
  top: 50%;
  right: var(--field-pad-x);
  width: var(--icon-size);
  height: var(--icon-size);
  color: var(--text-2);
  transform: translateY(-50%);
  pointer-events: none;
  transition: transform var(--dur-base) var(--ease), color var(--dur-fast) var(--ease);
}
.select__button {
  display: flex;
  align-items: center;
  padding-right: calc(var(--field-pad-x) * 2 + var(--icon-size));
  text-align: left;
  font: inherit;
  cursor: pointer;
}
.select__value { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.select__button:focus-visible { outline: var(--border-strong) solid var(--focus); outline-offset: var(--focus-offset); }
.select.is-open .select__button { border-color: var(--line-strong); }
.select.is-open .select__chevron { transform: translateY(-50%) rotate(180deg); color: var(--text); }
.select__list {
  position: absolute;
  z-index: var(--z-header);
  top: calc(100% + var(--sp-1));
  left: 0;
  right: 0;
  max-height: min(18rem, 60vh);
  margin: 0;
  padding: var(--sp-1);
  overflow-y: auto;
  border: var(--border) solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-3);
  list-style: none;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-4px);
  transition: opacity var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease), visibility 0s linear var(--dur-fast);
}
.select--up .select__list { top: auto; bottom: calc(100% + var(--sp-1)); transform: translateY(4px); }
.select.is-open .select__list {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition-delay: 0s;
}
.select__option {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--r-sm);
  color: var(--text-2);
  font-size: var(--fs-small);
  line-height: var(--lh-small);
  cursor: pointer;
}
.select__option.is-active { background: var(--surface-4); color: var(--text); }
.select__option[aria-selected="true"] { color: var(--text); }
.select__option[aria-disabled="true"] { opacity: 0.45; cursor: default; }
.select__check { flex: none; width: var(--icon-size); height: var(--icon-size); opacity: 0; }
.select__option[aria-selected="true"] .select__check { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  .select__list, .select__chevron { transition: none; }
}

/* Чип-чекбокс: интересы в фильтрах подбора [допущение: развитие метки области 12.8].
   Точка цвета области есть у всех чипов, не отмечен — нейтральный. Отмечен — тот же приём, что у «Моих областей»
   (.is-chosen, токены --pick-*): от точки плавно растекается градиент цвета области, точка светится.
   Свет — ::before под содержимым. При отметке он зажигается: круг растёт из точки от нуля до полного радиуса
   (--pick-k от 0 до 1, множитель радиуса света и ядра) и проявляется (opacity); при снятии сжимается обратно к точке.
   Точка загорается вместе с ним (box-shadow). При «уменьшить движение» — мгновенно.
   Смысл не только цветом: отмеченный чип светлее по тексту, а состояние читает скринридер (checkbox).
   <label class="chip c--investigative"><input type="checkbox" class="chip__input"> <span class="dot"> Название</label> */
.chips { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.chip {
  --pick-x: calc(var(--sp-3) + var(--dot) / 2);         /* центр точки: поле чипа + половина точки */
  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: var(--control-h);
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--r-md);
  background: var(--raise, var(--surface-2));
  color: var(--text-2);
  font-size: var(--fs-small);
  line-height: var(--lh-small);
  cursor: pointer;
  user-select: none;
  transition: background-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.chip::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: var(--pick-grad);
  --pick-k: 0;                                          /* свет «погашен»: радиус круга нулевой */
  opacity: 0;
  /* Круг меняет размер плавно (--ease почти весь путь проходит за первые 100 мс, глазом не видно). Переход берётся
     из того состояния, в которое чип приходит. Снят: круг сжимается к точке, а прозрачность гаснет только в самом конце
     (задержка = длительность сжатия минус длительность угасания), иначе свет исчез бы раньше, чем успел сжаться.
     Отмечен: прозрачность включается сразу, чтобы рост круга был виден с первого кадра. */
  transition: opacity var(--dur-fast) var(--ease) calc(var(--dur-reveal) - var(--dur-fast)), --pick-k var(--dur-reveal) var(--ease-float);
  pointer-events: none;
}
.chip .dot { background: var(--c, var(--text-3)); transition: box-shadow var(--dur-reveal) var(--ease-float); }
.chip:hover { background: var(--raise-hover, var(--surface-3)); color: var(--text); }
.chip__input { position: absolute; inset: 0; margin: 0; opacity: 0; cursor: pointer; }
.chip:has(.chip__input:checked) { color: var(--text); }
.chip:has(.chip__input:checked)::before { opacity: 1; --pick-k: 1; transition: opacity var(--dur-fast) var(--ease), --pick-k var(--dur-reveal) var(--ease-float); }
.chip:has(.chip__input:checked) .dot { box-shadow: var(--pick-glow); }
.chip:has(.chip__input:focus-visible) { outline: var(--border-strong) solid var(--focus); outline-offset: var(--focus-offset); }
.chip:active { transform: scale(var(--press-scale)); }

/* Значок группы шансов: форма, а не цвет (1.2.4, 1.2.5).
   Надёжно — круг, реально — половина, с ДВИ — контур с точкой, мечта — контур, не посчитать — пунктирный контур. */
.chance {
  flex: none;
  display: inline-block;
  width: var(--chance-size);
  height: var(--chance-size);
  border: var(--border-strong) solid var(--text);
  border-radius: var(--r-round);
}
.chance--safe { background: var(--text); }
.chance--real { background: linear-gradient(90deg, var(--text) 50%, transparent 50%); }
.chance--unknown { border-style: dashed; border-color: var(--text-3); }
/* С ДВИ — контур с точкой в центре: «ещё одно испытание» (не путать с мечтой — пустым контуром) */
.chance--dvi { background: radial-gradient(circle closest-side, var(--text) 55%, transparent 62%); }

/* ===== Метки (12.8) ===== */
.tag {
  display: inline-flex;
  align-items: center;
  padding: var(--tag-pad-y) var(--tag-pad-x);
  border-radius: var(--r-sm);
  background: var(--raise, var(--surface-2));
  color: var(--text-2);
  font-size: var(--fs-caption);
  line-height: var(--lh-caption);
  letter-spacing: var(--ls-caption);
  white-space: nowrap;
  transition: background-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
a.tag:hover { color: var(--text); }
/* Цветная точка слева внутри метки (чипы областей на карточках вузов) — у всех чипов одинаковая. Выбранная область
   (.is-chosen): градиент от точки (токены --pick-*, см. ниже) поверх обычного фона чипа и свечение точки, название
   --text; затухание короче, чем у строк (85% ширины), чтобы чип оставался чипом. Невыбранный чип нейтральный,
   название --text-2, без градиента и свечения */
.tag .dot { margin-right: var(--sp-2); }
.tag.is-chosen {
  --pick-r: 170px;
  --pick-x: calc(var(--tag-pad-x) + var(--dot) / 2);   /* центр точки: поле чипа + половина точки */
  color: var(--text);
  background: var(--pick-grad), var(--raise, var(--surface-2));
}

/* Точка типа: в списках рядом с областью (12.9) */
.dot {
  flex: none;
  display: inline-block;
  width: var(--dot);
  height: var(--dot);
  border-radius: var(--r-round);
  background: var(--c);
}

/* ===== Список со строками (12.9) ===== */
.list { list-style: none; }
.list__row {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) 0;
  border-top: var(--border) solid var(--divider);
}
.list__row:first-child { border-top: 0; }
.list__name { flex: 1; min-width: 0; }
.list__value { color: var(--text-2); font-variant-numeric: tabular-nums; }
/* Кликабельная строка: подложка при наведении. Отступы внутрь, чтобы текст не прыгал */
.list__row--link {
  position: relative;
  margin-inline: calc(-1 * var(--sp-3));
  padding-inline: var(--sp-3);
  border-radius: var(--r-md);
  transition: background-color var(--dur-fast) var(--ease);
}
/* Наведение — только на устройствах с мышью (на тач-экранах не залипает). Заливается вся строка; у выбранной
   (.is-chosen) тем же условием и на том же элементе градиент становится насыщеннее (--pick-from-hover), цвет
   остаётся цветным: нейтральная заливка у выбранной не используется */
@media (hover: hover) {
  .list__row--link:not(.is-chosen):hover { background: var(--raise, var(--surface-2)); }
  .list__row--link.is-chosen:hover { --pick-now: var(--pick-from-hover); }
}
.list__row--link a::after { content: ""; position: absolute; inset: 0; border-radius: inherit; }
/* «Область, которую вы выбрали» («Мои области», .is-chosen) — один приём везде (строки плитки «Области», «Области в
   базе», строки программ, чипы, плитки типов): от точки области расходится свет. Слой — радиальный градиент с центром
   в самой точке (--pick-x, --pick-y) и радиусом --pick-r: свет идёт кругом, как от лампы; границы элемента его
   просто обрезают. Плюс ядро у точки (--pick-core). Справа и по краям рамки нет, градиент гаснет сам.
   Тёмная тема: свет светлее поверхности — цвет типа (--c), точка светится.
   Светлая тема — наоборот: светлее бумаги стать нельзя, поэтому от точки расходятся чернила: пятно тёмного оттенка
   типа (--c-ink), темнее поверхности; точка получает тёмный ободок без свечения.
   Токены задаются один раз на самом элементе, правила пишутся один раз и читают их:
     --pick-x / --pick-y  центр точки (по горизонтали — поле строки + половина точки; по вертикали 50 %). У плитки
                          типа и строки программы точка стоит в разных местах, их точный центр замеряет
                          pick-light.js (запасные значения — в pages.css);
     --pick-r             радиус света в px (200 у строки и чипа, 170 у метки вуза, у плитки и программы — свой, pages.css);
     --pick-core          радиус ядра у точки;       --pick-core-from  цвет ядра в центре;
     --pick-from          цвет света у точки;        --pick-from-hover он же при наведении;
     --pick-glow          кольцо и свечение (тёмная) или ободок (светлая) вокруг точки (box-shadow);
     --pick-now           текущий цвет у точки (в покое = from, при наведении = from-hover);
     --pick-grad          готовый градиент из них.
   Цвет типа (--c) есть у всех областей, свет и ободок — только у выбранных.
   Основной вид — цвет в oklch (оранжевый и голубой не мутнеют в коричневый и серо-синий). Браузеры без
   color-mix in oklch (Safari до 16.4) получают запасной вид: один слой света из rgba-подложки типа --c-tint, без
   ядра и без oklch; наведение там без смены яркости. --pick-now — зарегистрированный <color>: смена яркости при
   наведении плавная (где @property не поддерживается — мгновенная). */
@property --pick-now { syntax: "<color>"; inherits: true; initial-value: transparent; }
/* --pick-k — «яркость включения» света: множитель радиуса круга и ядра, 1 в покое. Анимируется только у чипов
   фильтра (0 → 1 при отметке, обратно при снятии); без @property радиус меняется скачком */
@property --pick-k { syntax: "<number>"; inherits: true; initial-value: 1; }
.is-chosen,
.chip {
  --pick-x: calc(var(--sp-3) + var(--dot) / 2);        /* поле строки + половина точки */
  --pick-y: 50%;
  --pick-r: 200px;
  --pick-core: 28px;
  --pick-core-from: transparent;
  --pick-from: var(--c-tint);
  --pick-from-hover: var(--c-tint);
  --pick-glow: 0 0 0 3px var(--c-tint), 0 0 10px var(--c-tint);
  --pick-now: var(--pick-from);
}
/* Градиент собирается отдельно и на ::before чипа тоже: var(--pick-k) подставляется там, где объявлено, а у
   ::before свой --pick-k (анимация зажигания), поэтому на чипе и его ::before градиент считается дважды */
.is-chosen,
.chip,
.chip::before {
  --pick-grad: radial-gradient(circle max(1px, calc(var(--pick-r) * var(--pick-k))) at var(--pick-x) var(--pick-y), var(--pick-now) 0, transparent 100%);
}
@supports (background: color-mix(in oklch, red, blue)) {
  .is-chosen,
  .chip {                                               /* тёмная тема: свет цвета типа, 24 / 30 %, ядро +18 % */
    --pick-from: color-mix(in oklch, var(--c) 24%, transparent);
    --pick-from-hover: color-mix(in oklch, var(--c) 30%, transparent);
    --pick-core-from: color-mix(in oklch, var(--c) 36%, transparent);
    --pick-glow: 0 0 0 3px color-mix(in oklch, var(--c) 24%, transparent), 0 0 12px 2px color-mix(in oklch, var(--c) 52%, transparent);
  }
  .is-chosen,
  .chip,
  .chip::before {                                       /* ядро у точки + плавное затухание, без «края» в конце */
    --pick-grad:
      radial-gradient(circle max(1px, calc(var(--pick-core) * var(--pick-k))) at var(--pick-x) var(--pick-y), var(--pick-core-from) 0, transparent 100%),
      radial-gradient(circle max(1px, calc(var(--pick-r) * var(--pick-k))) at var(--pick-x) var(--pick-y),
        var(--pick-now) 0,
        color-mix(in oklch, var(--pick-now) 78%, transparent) 25%,
        color-mix(in oklch, var(--pick-now) 48%, transparent) 50%,
        color-mix(in oklch, var(--pick-now) 20%, transparent) 75%,
        transparent 100%);
  }
  [data-theme="light"] .is-chosen,
  [data-theme="light"] .chip {                          /* светлая тема: чернила — цвет типа, затемнённый к --c-ink (насыщеннее
                                                           чистого --c-ink: не серый), темнее поверхности; 32 / 40 %, ядро 14 % */
    --pick-ink: color-mix(in oklch, var(--c) 55%, var(--c-ink));
    --pick-from: color-mix(in oklch, var(--pick-ink) 32%, transparent);
    --pick-from-hover: color-mix(in oklch, var(--pick-ink) 40%, transparent);
    --pick-core-from: color-mix(in oklch, var(--pick-ink) 14%, transparent);
    --pick-glow: 0 0 0 3px color-mix(in oklch, var(--pick-ink) 32%, transparent);
  }
}
.is-chosen .dot { box-shadow: var(--pick-glow); }
/* Строка списка: поля внутрь (минус margin и плюс padding гасят друг друга) — текст не двигается и не меняет ширину.
   Градиент затухает к правому краю, поэтому разделитель у выбранной строки и у следующей остаётся, но слабее */
.list__row.is-chosen {
  margin-inline: calc(-1 * var(--sp-3));
  padding-inline: var(--sp-3);
  border-radius: var(--r-md);
  background: var(--pick-grad);
  transition: --pick-now var(--dur-fast) var(--ease);
}
.list__row.is-chosen .list__name { color: var(--text); }
.list__row.is-chosen,
.list__row.is-chosen + .list__row { border-top-color: color-mix(in srgb, var(--divider) 40%, transparent); }
/* Разделитель не виден под подложкой наведения: убираем у соседней строки */
@media (hover: hover) {
  .list__row--link:hover + .list__row { border-top-color: transparent; }
}

/* ===== Числа с подписью (12.11): подпись над числом, числа одной линией =====
   <dl class="stats"><div class="stat"><dt>Проходной, бюджет, 2025</dt><dd class="num">262</dd></div></dl> */
.stats {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, var(--stat-min)), 1fr));
  gap: var(--sp-4) var(--sp-5);
}
.stat { display: flex; flex-direction: column; justify-content: flex-end; gap: var(--sp-1); }
.stat dt {
  color: var(--text-2);
  font-size: var(--fs-caption);
  line-height: var(--lh-caption);
  letter-spacing: var(--ls-caption);
}
.stat dd {
  margin: 0;
  font-size: var(--fs-h2);
  line-height: var(--lh-h2);
  letter-spacing: var(--ls-h2);
  font-weight: var(--fw-semibold);
}

/* ===== Полосы по типам (10.2, 12.13): название и процент, под ними полоса =====
   Цвет полосы — тип строки (c--<тип>), без класса — нейтральная. Растут при появлении (10.3):
   motion.js ставит .is-visible с шагом --stagger-bars; без JS и при «уменьшить движение» — сразу целиком. */
.bars { display: flex; flex-direction: column; gap: var(--sp-4); list-style: none; }
.bar {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: baseline;
  gap: var(--sp-2) var(--sp-4);
  font-size: var(--fs-small);
  line-height: var(--lh-small);
}
/* Полосы типов цветные всегда. «Главное» — яркостью: главные на полной яркости (название и процент --text),
   остальные (.bar--dim) тем же цветом типа, но слабее (заливка с прозрачностью), название и процент --text-2.
   Главных нет — .bar--dim нет ни у кого, все полосы яркие */
.bar__name, .bar__value { color: var(--text); }
.bar--dim .bar__name, .bar--dim .bar__value { color: var(--text-2); }
.bar--dim .bar__fill { opacity: var(--bar-dim-opacity, 0.5); }
.bar__track {
  grid-column: 1 / -1;
  height: var(--bar-h);
  overflow: hidden;
  border-radius: var(--r-sm);
  background: var(--surface-3);
}
.bar__fill {
  display: block;
  width: var(--value);
  height: 100%;
  border-radius: inherit;
  background: var(--c);
  transform-origin: left;
  transition: transform var(--dur-slow) var(--ease);
}
.has-motion .bar__fill:not(.is-visible) { transform: scaleX(0); }

/* ===== Линейный график (10.2, 10.3): templates/components/_chart_line.html =====
   Цвет — --c типа области (c--<тип> на обёртке), без него — цвет текста.
   Холст тянется по ширине, линия держит 2 px (non-scaling-stroke); точка и годы — HTML поверх. */
.chart { position: relative; color: var(--c, var(--text)); }
.chart__plot { position: relative; }
.chart__svg { display: block; width: 100%; height: var(--chart-h); overflow: visible; }
.chart--mini .chart__svg { height: var(--chart-mini-h); }
.chart__line {
  fill: none;
  stroke: currentColor;
  stroke-width: var(--chart-line);
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}
.chart__line--paid { stroke-dasharray: var(--chart-dash); }
.chart__dot {
  position: absolute;
  width: calc(var(--chart-dot) * 2);
  height: calc(var(--chart-dot) * 2);
  border-radius: var(--r-round);
  background: currentColor;
  transform: translate(-50%, -50%);
}
/* Базовая линия и подписи годов (--fs-caption, --text-3), без сетки */
/* Числа у точек бюджетной линии (values=True): над точкой, последнее — --text, остальные — --text-2.
   Место над линией — поле у .chart__plot (проценты у точки считаются от самого холста, поле их не сдвигает) */
.chart--values .chart__plot { margin-top: var(--sp-5); }
.chart__value {
  position: absolute;
  color: var(--text-2);
  font-size: var(--fs-caption);
  line-height: var(--lh-caption);
  transform: translate(-50%, calc(-100% - var(--sp-2)));
  white-space: nowrap;
}
.chart__value:first-child { transform: translate(0, calc(-100% - var(--sp-2))); }
.chart__value:last-child { color: var(--text); transform: translate(-100%, calc(-100% - var(--sp-2))); }
@media (max-width: 599.98px) {
  .chart--dense .chart__value:not(:first-child):not(:last-child) { display: none; }
}
.chart__years {
  position: relative;
  height: calc(var(--fs-caption) * var(--lh-caption) + var(--sp-2));
  margin-top: var(--sp-1);
  border-top: var(--border) solid var(--divider);
}
.chart__year {
  position: absolute;
  top: var(--sp-1);
  color: var(--text-3);
  font-size: var(--fs-caption);
  line-height: var(--lh-caption);
  transform: translateX(-50%);
  white-space: nowrap;
}
.chart__year:first-child { transform: none; }
.chart__year:last-child { transform: translateX(-100%); }
.chart__legend { display: flex; flex-wrap: wrap; gap: var(--sp-4); margin-top: var(--sp-2); color: var(--text-2); font-size: var(--fs-caption); line-height: var(--lh-caption); }
.chart__key { display: inline-flex; align-items: center; gap: var(--sp-2); }
.chart__swatch { width: var(--sp-5); border-top: var(--chart-line) solid var(--c, var(--text)); }
.chart__swatch--paid { border-top-style: dashed; }

/* Прорисовка (10.3): только когда motion.js запущен; без JS и при «уменьшить движение» — сразу целиком */
.has-motion .chart__line:not(.chart__line--paid):not(.is-done) {
  stroke-dasharray: calc(var(--len, 0) * 1px);
  stroke-dashoffset: calc(var(--len, 0) * 1px);
  transition: stroke-dashoffset var(--dur-draw) var(--ease);
}
.has-motion .chart__line.is-drawn:not(.is-done) { stroke-dashoffset: 0; }
.has-motion .chart__line--paid { opacity: 0; transition: opacity var(--dur-draw) var(--ease); }
.has-motion .chart.is-drawn .chart__line--paid { opacity: 1; }
.has-motion .chart__dot { opacity: 0; transition: opacity var(--dur-base) var(--ease) var(--dur-draw); }
.has-motion .chart.is-drawn .chart__dot { opacity: 1; }
.has-motion .chart__value { opacity: 0; transition: opacity var(--dur-base) var(--ease) var(--dur-draw); }
.has-motion .chart.is-drawn .chart__value { opacity: 1; }
/* motion.js на время повторной разметки: пересчёт стилей без переходов (график в закрытом <details>) */
.chart.is-settling,
.chart.is-settling * { transition: none !important; }

/* ===== Карточка вуза (12.10): includes/university_card.html и выделенная в ленте =====
   Город и лайк сверху (в разметке заголовок первым — так его читает программа экрана). */
.uni-card__top {
  order: -1;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--sp-3);
  margin-block: calc(-1 * var(--sp-2));   /* лайк 40–44 px не раздувает строку города */
}
.uni-card .card__tags { margin-top: var(--sp-1); }
.uni-card__counts { margin-top: auto; color: var(--text-2); font-size: var(--fs-small); line-height: var(--lh-small); }
.uni-card .card__footer .uni-card__counts { margin-top: 0; }

/* Выделенная (XL): лучшая программа, мини-график и крупный балл рядом */
.uni-card__program { color: var(--text); }
.uni-card__label {
  display: block;
  color: var(--text-2);
  font-size: var(--fs-caption);
  line-height: var(--lh-caption);
  letter-spacing: var(--ls-caption);
}
.uni-card__score {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: end;
  gap: var(--sp-5);
  margin-top: var(--sp-2);
}
.uni-card__score .stats { grid-template-columns: auto; text-align: right; }
.uni-card__score .stat dd { font-size: var(--fs-score); line-height: 1; }
/* Один год баллов — графика нет, число встаёт слева */
.uni-card__score:not(:has(.chart)) { grid-template-columns: auto; }
.uni-card__score:not(:has(.chart)) .stats { text-align: left; }
.uni-card__no-score { color: var(--text-2); font-size: var(--fs-small); line-height: var(--lh-small); }
.uni-card--featured .card__footer { flex-wrap: wrap; }

/* ===== Карточка программы (промт подбора 4.1): роль «данные», размер M =====
   Сверху вниз: вуз и город, название, область, два числа, причины, «В мой список».
   Группа шансов — подписью, не цветом; цвет типа только у точки области. */
.program-card__area {
  color: var(--text-2);
  font-size: var(--fs-small);
  line-height: var(--lh-small);
}
.program-card__area .dot { margin-right: var(--sp-2); vertical-align: 0.1em; }

/* Два числа рядом: проходной и запас — общий блок .stats в две равные колонки:
   длинная подпись переносится внутри своей колонки, числа стоят на одной линии */
.program-card__nums { grid-template-columns: repeat(2, minmax(0, 1fr)); margin-top: var(--sp-2); }

.program-card__problem { color: var(--text-2); font-size: var(--fs-small); line-height: var(--lh-small); }

/* Из чего сложилась сумма: «чек» на подложке на ступень светлее карточки (4.1) —
   предмет слева, балл справа столбиком, итог под чертой */
.program-card__sum {
  display: grid;
  gap: var(--sp-1);
  margin: 0;
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--r-md);
  background: var(--raise, var(--surface-2));
  color: var(--text-2);
  font-size: var(--fs-small);
  line-height: var(--lh-small);
}
.program-card__sum-row { display: flex; justify-content: space-between; align-items: baseline; gap: var(--sp-3); }
.program-card__sum-row dt { min-width: 0; }
.program-card__sum-row dd { flex: none; margin: 0; }
.program-card__sum-total {
  margin-top: var(--sp-1);
  padding-top: var(--sp-2);
  border-top: var(--border) solid var(--divider);
  color: var(--text);
  font-weight: var(--fw-semibold);
}

/* Причины: тихий список со строками (12.9), мельче основного текста */
.program-card__reasons { color: var(--text-2); font-size: var(--fs-small); line-height: var(--lh-small); }
.program-card__reasons .list__row { padding-block: var(--sp-2); }

.program-card__chart { display: flex; flex-direction: column; gap: var(--sp-2); }
.program-card__chart-label {
  color: var(--text-2);
  font-size: var(--fs-caption);
  line-height: var(--lh-caption);
  letter-spacing: var(--ls-caption);
}

/* «Как посчитали»: строка со стрелкой, раскрывается как строки программ (disclosure.js). Поверх растянутой ссылки названия */
.program-card__how { --disclosure-dur: var(--dur-slow); position: relative; z-index: 1; }
.program-card__how-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  padding-block: var(--sp-2);
  border-top: var(--border) solid var(--divider);
  color: var(--text-2);
  font-size: var(--fs-small);
  line-height: var(--lh-small);
  list-style: none;
  cursor: pointer;
}
.program-card__how-summary::-webkit-details-marker { display: none; }
.program-card__how-summary:hover { color: var(--text); }
.program-card__how-summary:focus-visible { outline: var(--border-strong) solid var(--focus); outline-offset: var(--focus-offset); border-radius: var(--r-md); }
.program-card__how-chevron {
  flex: none;
  width: var(--icon-size);
  height: var(--icon-size);
  transition: transform var(--disclosure-dur) var(--ease);
}
.program-card__how[open]:not(.is-closing) .program-card__how-chevron { transform: rotate(180deg); }
.program-card__how-body { display: flex; flex-direction: column; gap: var(--sp-3); padding-block: var(--sp-2); }

/* Выбранная область («Мои области» или чип фильтра): строка области с градиентом от точки и светящейся точкой.
   Токены --pick-* и .is-chosen .dot — выше; отступы внутрь, как у строк списков, чтобы текст не сдвигался */
.program-card__area { margin-inline: calc(-1 * var(--sp-3)); padding: var(--sp-1) var(--sp-3); border-radius: var(--r-md); }
.program-card__area.is-chosen {
  background: var(--pick-grad);
  color: var(--text);
}
/* Название забирает свободное место, область и числа прижаты к низу: в ряду они стоят на одной линии */
.program-card .card__title { flex: 1 0 auto; }
.program-card__part { display: flex; flex-direction: column; gap: var(--sp-2); }

/* Выбранная карточка (её панель открыта под рядом): ступенью светлее, как главная */
.program-card.is-open {
  background: var(--surface-2);
  --raise: var(--surface-3);
  --raise-hover: var(--surface-4);
}
.program-card.is-open .program-card__how-chevron { transform: rotate(180deg); }

/* Панель «Как посчитали» под рядом карточек (podbor-detail.js): вставляется в сетку на всю ширину после последней
   карточки ряда, поэтому ряды остаются ровными. Раскрывается по высоте (grid-template-rows 0fr → 1fr) и проявляется;
   «выступ» сверху указывает на открытую карточку (--notch — её центр). На телефоне ряд — одна карточка, панель под ней */
@property --notch { syntax: "<length>"; inherits: true; initial-value: 0px; }
.program-detail {
  position: relative;
  grid-column: 1 / -1;
  display: grid;
  grid-template-rows: 0fr;
  opacity: 0;
  scroll-margin-block: calc(var(--header-h) + var(--header-offset) + var(--sp-4)) var(--sp-4);
  transition: grid-template-rows var(--dur-slow) var(--ease), opacity var(--dur-base) var(--ease), --notch var(--dur-slow) var(--ease);
}
.program-detail.is-open { grid-template-rows: 1fr; opacity: 1; }
.program-detail__inner { min-height: 0; overflow: hidden; }
.program-detail::before {
  /* Указатель на открытую карточку: ромб того же цвета, что карточка и панель; острие касается низа карточки.
     --notch — центр карточки; при переключении на соседнюю карточку ряда указатель плавно переезжает */
  content: "";
  position: absolute;
  top: calc(var(--sp-2) * -1);
  left: calc(var(--notch) - (var(--sp-4) + var(--sp-1)) / 2);
  width: calc(var(--sp-4) + var(--sp-1));
  height: calc(var(--sp-4) + var(--sp-1));
  border-radius: var(--r-sm);
  background: var(--surface-2);
  transform: rotate(45deg);
}
.program-detail__panel {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  padding: var(--card-pad);
  border-radius: var(--r-lg);
  background: var(--surface-2);
  --raise: var(--surface-3);
  --raise-hover: var(--surface-4);
}
.program-detail__head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-4); }
.program-detail__title { font-size: var(--fs-small); line-height: var(--lh-small); color: var(--text-2); }
.program-detail__title strong { color: var(--text); font-weight: var(--fw-semibold); }
.program-detail__close {
  flex: none;
  border: 0;
  background: none;
  padding: 0;
  cursor: pointer;
  align-self: center;
  display: grid;
  place-items: center;
  width: var(--control-h);
  height: var(--control-h);
  margin: calc(var(--sp-2) * -1);
  border-radius: var(--r-md);
  color: var(--text-2);
  transition: background-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.program-detail__close:hover { background: var(--raise-hover); color: var(--text); }
.program-detail__close:focus-visible { outline: var(--border-strong) solid var(--focus); outline-offset: var(--focus-offset); }
.program-detail__close svg { width: var(--icon-size); height: var(--icon-size); }
.program-detail__body { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr)); gap: var(--sp-5); }
@media (prefers-reduced-motion: reduce) {
  .program-detail { transition: none; }
}

.program-card .card__footer { flex-wrap: wrap; }
.program-card__actions { margin-left: auto; }

/* ===== Вкладки (12.7) =====
   Ряд не прокручивается: ни overflow, ни полосы прокрутки. Раньше стояло overflow-x: auto — из-за отрицательного
   margin-bottom у вкладок (подчёркивание ложится на линию ряда) содержимое выше ряда на 1 px, и ряд прокручивался
   по вертикали колесом, а в браузерах без scrollbar-width (Safari до 18.2) у правого края ряда появлялась тонкая
   вертикальная полоса прокрутки. На узких экранах все вкладки помещаются в одну строку: зазор и кегль уменьшаются
   через clamp (на 360 px кегль 13 px и зазор 8 px, от ~420 px — 15 px и растущий зазор до 24 px); если названия длиннее и всё равно не помещаются — вкладки
   переносятся на вторую строку, а не уходят за край. */
.tabs {
  display: flex;
  flex-wrap: wrap;
  column-gap: clamp(var(--sp-2), calc(4.5vw - 8px), var(--sp-5));
  border-bottom: var(--border) solid var(--divider);
}
.tabs a,
.tabs [role="tab"] {
  flex: none;
  margin-bottom: calc(-1 * var(--border));   /* подчёркивание ложится на линию ряда */
  padding: var(--sp-3) 0;
  border: 0;
  border-bottom: var(--border-strong) solid transparent;
  background: none;
  color: var(--text-2);
  font-size: clamp(13px, 3.55vw, var(--fs-tab));
  white-space: nowrap;
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.tabs a:hover,
.tabs [role="tab"]:hover { color: var(--text); }
.tabs a[aria-current],
.tabs [aria-selected="true"] { border-bottom-color: var(--text); color: var(--text); }
/* Внутри тематического блока подчёркивание — цветом типа (4.4) */
.tabs[class*="c--"] [aria-selected="true"] { border-bottom-color: var(--c); }
.tabs a:focus-visible,
.tabs [role="tab"]:focus-visible { outline-offset: calc(-1 * var(--border-strong)); }

/* ===== Лайк (12.5): кнопка-иконка, контур → заливка цветом текста =====
   Тот же приём у закладки программы («В мой список»): сердечко — вуз, закладка — программа */
.like-form { display: inline-flex; margin: 0; }
.like {
  display: inline-grid;
  place-items: center;
  width: var(--icon-btn);
  height: var(--icon-btn);
  padding: 0;
  border: 0;
  border-radius: var(--r-md);
  background: transparent;
  color: var(--text);
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease), transform var(--dur-press) var(--ease);
}
.like:hover { background: var(--raise, var(--surface-2)); color: var(--text); }
.like:active { transform: scale(var(--press-scale)); }
.like__icon {
  width: 26px;
  height: 26px;
  fill: transparent;
  stroke: currentColor;
  stroke-width: var(--icon-stroke);
  stroke-linejoin: round;
  transition: fill var(--dur-base) var(--ease);
}
.like[aria-pressed="true"] .like__icon { fill: currentColor; }
/* Анимация лайка и закладки (like.js) — одна на обоих: значок мягко «входит» из чуть меньшего размера
   с лёгким пружинящим выходом на место, а заливка проявляется плавно. Без колец и вспышек.
   Так же и при снятии, заливка при этом уходит. Та же анимация в главе «Мой список» на главной (pages.css, .keep) */
@keyframes like-in {
  0% { transform: scale(.8); }
  100% { transform: scale(1); }
}
.like__icon { transform-box: fill-box; transform-origin: center; }
.like--pop .like__icon { animation: like-in 380ms cubic-bezier(.34, 1.56, .64, 1); }
@media (prefers-reduced-motion: reduce) {
  .like--pop .like__icon { animation: none; }
}
.like__label {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ===== Таблица (12.11): строки через разделители, цифры справа ===== */
.table { width: 100%; border-collapse: collapse; font-size: var(--fs-small); line-height: var(--lh-small); }
.table th,
.table td {
  padding: var(--sp-3) var(--sp-4);
  border-bottom: var(--border) solid var(--divider);
  text-align: left;
  white-space: nowrap;
}
.table th {
  color: var(--text-2);
  font-size: var(--fs-caption);
  line-height: var(--lh-caption);
  letter-spacing: var(--ls-caption);
  font-weight: var(--fw-regular);
}
/* Заголовок строки (год) — как обычная ячейка, приглушённый */
.table tbody th { color: var(--text-2); font-size: var(--fs-small); line-height: var(--lh-small); letter-spacing: 0; }
.table tbody tr:last-child > * { border-bottom: 0; }
.table .num { text-align: right; font-variant-numeric: tabular-nums; }

/* ===== Пустое состояние (12.15): фигура, заголовок, фраза, одна вторичная кнопка ===== */
.empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-7) var(--card-pad);
  border-radius: var(--r-lg);
  background: var(--surface-1);
  color: var(--text-2);
  text-align: center;
}
.empty__title { color: var(--text); font-size: var(--fs-h4); line-height: var(--lh-h4); letter-spacing: var(--ls-h4); }
.empty .btn { margin-top: var(--sp-2); }
/* Короткая строка-заглушка внутри карточки или вкладки — без своей подложки */
.card .empty { padding: var(--sp-5) 0; background: none; }

/* ===== Комментарии (12.14) ===== */
.comment { padding: var(--comment-pad-y) var(--comment-pad-x); }
.comment__head { display: flex; align-items: center; gap: var(--sp-3); }
.comment__author { font-size: var(--fs-small); line-height: var(--lh-small); font-weight: var(--fw-semibold); }
.comment__meta { font-size: var(--fs-small); line-height: var(--lh-small); color: var(--text-2); }
.comment__date { font-size: var(--fs-caption); line-height: var(--lh-caption); color: var(--text-2); }
.comment__text { margin-top: var(--sp-2); color: var(--text); }
.comment__edit { margin-inline-start: 0; }  /* подложка «Изменить» не встаёт вплотную к дате */

/* Аватар-буква: круг на --surface-3, без рамки и фото */
.avatar {
  flex: none;
  display: inline-grid;
  place-items: center;
  width: var(--avatar);
  height: var(--avatar);
  border-radius: var(--r-round);
  background: var(--surface-3);
  color: var(--text);
  font-size: var(--fs-small);
  font-weight: var(--fw-semibold);
  line-height: 1;
}

/* Ответ: вложенная подложка на ступень светлее, без линии слева [допущение] */
.comment--reply {
  margin-top: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--r-md);
  background: var(--surface-2);
}
.comment--reply .avatar { background: var(--surface-3); }

.comment__reply { margin-top: var(--sp-3); }
.comment__reply summary {
  width: fit-content;
  color: var(--text-2);
  font-size: var(--fs-small);
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease);
}
.comment__reply summary:hover { color: var(--text); }
.comment__reply .comment-form { margin-top: var(--sp-3); }

.comment-form { max-width: var(--measure); }
.comment-form .btn { align-self: flex-start; }

/* ===== Шапка-стекло (12.2) =====
   Закреплена сверху и «парит»: отступ 8 px от краёв экрана, а на широком экране
   край стекла стоит так, что логотип совпадает с краем контента.
   Стекло без рамки; высота 64 px, на телефоне 56 px (--header-h). */
.site-header {
  position: sticky;
  top: var(--header-offset);
  z-index: var(--z-header);
  margin-top: var(--header-offset);
  padding-inline: max(var(--header-offset), calc(var(--gutter) - var(--sp-4)));
}
.site-header__bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-6);
  max-width: calc(var(--container) - 2 * var(--gutter) + 2 * var(--sp-4));
  min-height: var(--header-h);
  margin-inline: auto;
  padding: var(--sp-2) var(--sp-2) var(--sp-2) var(--sp-4);
  background: var(--glass-bg);
  -webkit-backdrop-filter: blur(var(--glass-blur));
  backdrop-filter: blur(var(--glass-blur));
  border-radius: var(--r-lg);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .site-header__bar { background: var(--glass-fallback); }
}

.site-header__logo {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-weight: var(--fw-semibold);
}
.site-header__logo:hover { color: var(--text); }
.site-header__mark { width: var(--icon-size); height: var(--icon-size); }

.site-header__nav { display: flex; align-items: center; gap: var(--sp-5); }
.site-header__link { color: var(--text-2); font-size: var(--fs-tab); transition: color var(--dur-fast) var(--ease); }
.site-header__link:hover,
.site-header__link[aria-current] { color: var(--text); }

/* Подсказка в шапке (data-tip): своя вместо системной, со стрелкой к элементу.
   Выезжает снизу: проявляется, чуть сдвигается и «вырастает» от 96 %. Появляется не сразу (--dur-tip-wait),
   чтобы не мигала при проходе курсора, уходит быстрее. Только там, где есть наведение, и при фокусе с клавиатуры.
   Стрелка — повёрнутый квадрат того же цвета: ::before под плашкой ::after, видна только выпуклая часть.
   По умолчанию по центру элемента; data-tip-end — по правому краю (крайняя кнопка, чтобы не вылезать за экран),
   стрелка тогда над серединой кнопки. При «уменьшить движение» — только проявление. */
.site-header [data-tip] { position: relative; }
.site-header [data-tip]::before,
.site-header [data-tip]::after {
  position: absolute;
  z-index: var(--z-header);
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}
.site-header [data-tip]::after {
  content: attr(data-tip);
  top: calc(100% + var(--sp-3));
  left: 50%;
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--r-md);
  background: var(--surface-4);
  color: var(--text);
  font-size: var(--fs-small);
  line-height: var(--lh-small);
  font-weight: var(--fw-regular);
  white-space: nowrap;
  transform: translate(-50%, calc(var(--sp-1) * -1)) scale(0.96);
  transform-origin: 50% 0;
}
.site-header [data-tip]::before {
  content: "";
  top: calc(100% + var(--sp-3) - var(--tip-arrow) / 2);
  left: 50%;
  width: var(--tip-arrow);
  height: var(--tip-arrow);
  border-radius: 2px;
  background: var(--surface-4);
  transform: translate(-50%, calc(var(--sp-1) * -1)) rotate(45deg);
}
.site-header [data-tip-end]::after {
  left: auto;
  right: 0;
  transform: translate(0, calc(var(--sp-1) * -1)) scale(0.96);
  transform-origin: 100% 0;
}
.site-header [data-tip-end]::before {
  left: auto;
  right: calc(var(--icon-btn) / 2 - var(--tip-arrow) / 2);
  transform: translate(0, calc(var(--sp-1) * -1)) rotate(45deg);
}
@media (hover: hover) {
  .site-header [data-tip]:hover::before,
  .site-header [data-tip]:hover::after {
    opacity: 1;
    transition-duration: var(--dur-tip);
    transition-delay: var(--dur-tip-wait);
  }
  .site-header [data-tip]:hover::after { transform: translate(-50%, 0) scale(1); }
  .site-header [data-tip]:hover::before { transform: translate(-50%, 0) rotate(45deg); }
  .site-header [data-tip-end]:hover::after { transform: translate(0, 0) scale(1); }
  .site-header [data-tip-end]:hover::before { transform: translate(0, 0) rotate(45deg); }
}
.site-header [data-tip]:focus-visible::before,
.site-header [data-tip]:focus-visible::after { opacity: 1; transition-duration: var(--dur-tip); }
.site-header [data-tip]:focus-visible::after { transform: translate(-50%, 0) scale(1); }
.site-header [data-tip]:focus-visible::before { transform: translate(-50%, 0) rotate(45deg); }
.site-header [data-tip-end]:focus-visible::after { transform: translate(0, 0) scale(1); }
.site-header [data-tip-end]:focus-visible::before { transform: translate(0, 0) rotate(45deg); }
@media (prefers-reduced-motion: reduce) {
  .site-header [data-tip]::before,
  .site-header [data-tip]::after { transition-property: opacity; }
}

.site-header__actions { display: flex; align-items: center; gap: var(--sp-2); margin-left: auto; }

/* Бургер: только на телефоне и только с JS */
.burger { display: none; }
.burger__close,
.burger[aria-expanded="true"] .burger__open { display: none; }
.burger[aria-expanded="true"] .burger__close { display: block; }

@media (max-width: 599.98px) {
  .js .site-header__bar { flex-wrap: nowrap; }
  .js .site-header__nav,
  .js .site-header__wide { display: none; }
  .js .burger { display: inline-flex; }
}

/* ===== Меню телефона (12.3): полноэкранное стекло ===== */
.nav-panel {
  position: fixed;
  inset: 0;
  z-index: var(--z-nav);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--sp-7);
  overflow-y: auto;
  padding:
    calc(var(--header-offset) * 2 + var(--header-h) + var(--sp-6))
    var(--gutter)
    var(--sp-6);
  /* Плотное стекло: крупные пункты лежат прямо над страницей и должны читаться [допущение] */
  background: var(--glass-fallback);
  -webkit-backdrop-filter: blur(var(--glass-blur));
  backdrop-filter: blur(var(--glass-blur));
  opacity: 0;
  transition: opacity var(--dur-slow) var(--ease);
}
.nav-panel.is-open { opacity: 1; }

/* Пока меню открыто: шапка поверх панели (там крестик), страница не прокручивается */
.nav-open { overflow: hidden; }
.nav-open .site-header { z-index: calc(var(--z-nav) + 1); }

.nav-panel__nav { display: flex; flex-direction: column; align-items: flex-start; gap: var(--sp-4); }
.nav-panel__link {
  font-size: var(--fs-h2);
  line-height: var(--lh-h2);
  letter-spacing: var(--ls-h2);
  font-weight: var(--fw-semibold);
  color: var(--text-2);
  opacity: 0;
  transform: translateY(var(--sp-4));
  transition: opacity var(--dur-slow) var(--ease), transform var(--dur-slow) var(--ease), color var(--dur-fast) var(--ease);
}
.nav-panel__link[aria-current],
.nav-panel__link:hover { color: var(--text); }
.nav-panel__hint { display: block; margin-top: var(--sp-1); font-size: var(--fs-small); line-height: var(--lh-small); font-weight: var(--fw-regular); letter-spacing: 0; color: var(--text-3); }
.nav-panel.is-open .nav-panel__link { opacity: 1; transform: none; }
/* Пункты всплывают по очереди */
.nav-panel__link:nth-child(2) { transition-delay: var(--stagger); }
.nav-panel__link:nth-child(3) { transition-delay: calc(var(--stagger) * 2); }
.nav-panel__link:nth-child(4) { transition-delay: calc(var(--stagger) * 3); }

.nav-panel__footer { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3); }

/* ===== Уменьшенное движение: без подъёма и сжатия ===== */
@media (prefers-reduced-motion: reduce) {
  .btn:active,
  .like:active,
  .chip:active,
  .card--link:hover,
  .card:has(.card__title a):hover,
  .nav-panel__link { transform: none; }
  .nav-panel,
  .nav-panel__link,
  .chip::before,
  .chip .dot { transition-duration: 0.01ms; transition-delay: 0s; }
}
