/*
  Тема BestTests.ru. Задача 0.10, разделы 3 и 29.1 ТЗ.

  Раздел 3 требует Bootstrap с оформлением по образцу Paper Dashboard:
  его цвета, отступы, радиусы, размеры и шрифты. Тема сделана слоем
  поверх собранного Bootstrap, а не пересборкой из Sass: пересборка
  притащила бы в проект Node и сборочный конвейер ради десятка
  переменных, а обновление Bootstrap перестало бы быть заменой одного
  файла.

  Bootstrap 5.3 генерирует цвета компонентов литералами, а не через
  --bs-primary, поэтому мало переопределить палитру в :root — цвет
  задаётся ещё и переменными самих компонентов (--bs-btn-bg и подобные).
*/

/* --------------------------------------------------------------------
   Шрифт. Раздел 3: локально с сервера, без обращения к внешним CDN;
   кириллица обязательна. Montserrat — шрифт Paper Dashboard.
   Файл переменный, одним начертанием закрывает весь диапазон
   насыщенности, поэтому его хватает одного на подмножество символов.
   -------------------------------------------------------------------- */

@font-face {
  font-family: "Montserrat";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("../fonts/montserrat-cyrillic.6fd02dd74afd.woff2") format("woff2");
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

@font-face {
  font-family: "Montserrat";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("../fonts/montserrat-latin.311d352d9323.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+2074, U+20AC,
    U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* --------------------------------------------------------------------
   Палитра раздела 29.1 и базовые токены
   -------------------------------------------------------------------- */

:root {
  --bt-blue: #51bcda;
  --bt-blue-dark: #3d9fba;
  --bt-green: #6bd098;
  --bt-green-dark: #55b47e;
  --bt-yellow: #fbc658;
  --bt-yellow-dark: #e0a938;
  --bt-red: #f5593d;
  --bt-red-dark: #d4432a;
  --bt-dark: #66615b;
  --bt-grey: #b9c2cc;
  --bt-light: #f4f3ef;

  /* Paper Dashboard: почти круглые кнопки, мягкие тени, тонкие линии. */
  --bt-radius: 0.75rem;
  --bt-radius-pill: 30px;
  --bt-shadow: 0 1px 15px 1px rgba(39, 39, 39, 0.08);
  --bt-shadow-hover: 0 12px 20px -10px rgba(39, 39, 39, 0.16);

  --bs-primary: #51bcda;
  --bs-success: #6bd098;
  --bs-warning: #fbc658;
  --bs-danger: #f5593d;
  --bs-primary-rgb: 81, 188, 218;
  --bs-body-color: #66615b;
  --bs-body-color-rgb: 102, 97, 91;
  --bs-body-font-family: "Montserrat", system-ui, -apple-system, "Segoe UI", sans-serif;
  --bs-body-font-size: 0.95rem;
  --bs-body-font-weight: 400;
  --bs-link-color: #51bcda;
  --bs-link-color-rgb: 81, 188, 218;
  --bs-link-hover-color: #3d9fba;
  --bs-border-color: #ddd8d0;
  --bs-border-radius: var(--bt-radius);
  --bs-border-radius-sm: 0.5rem;
  --bs-border-radius-lg: 1rem;
  --bs-focus-ring-color: rgba(81, 188, 218, 0.25);

  /* Bootstrap задаёт цвет полосы прогресса и вторичной кнопки
     литералами внутри самих компонентов, а не через --bs-primary
     и --bs-secondary. Поэтому переопределение палитры их не касается,
     и на странице появляется чужой синий #0d6efd рядом с нашим
     голубым — это видно сразу и выглядит как недоделка. */
  --bs-progress-bar-bg: #51bcda;
  --bs-secondary: #66615b;
  --bs-secondary-rgb: 102, 97, 91;

  /* Дорожка полос и колец. Светло-серый Bootstrap (#e9ecef) на нашем
     сером фоне почти не виден: полоса без начала выглядит не пустой,
     а отсутствующей. */
  --bt-track: #e3e0d8;
}

.progress { background-color: var(--bt-track); }

body {
  /* Paper Dashboard: страница серая, карточки на ней белые. Белое
     на белом лишает карточку края — она перестаёт читаться как
     отдельный объект, и экран превращается в сплошной список. */
  background: var(--bt-light);
  /* Футер прижат книзу и на короткой странице: раздел 5.4 требует его
     на всех страницах, а «висящий» посередине футер выглядит поломкой. */
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

/* Карточка остаётся белой независимо от фона страницы: Bootstrap
   берёт её цвет из --bs-body-bg, а тот менять нельзя — от него
   зависят поля ввода, выпадающие списки и модальные окна. */
.card,
.modal-content,
.list-group-item {
  --bs-card-bg: #fff;
  background-color: #fff;
}

.bt-page {
  flex: 1 0 auto;
  padding-top: 2rem;
  padding-bottom: 3rem;
}

h1, h2, h3, h4, h5, h6 {
  font-weight: 600;
  color: var(--bt-dark);
}

h1 { font-size: 1.75rem; }
h2 { font-size: 1.4rem; }
h3 { font-size: 1.2rem; }

/* --------------------------------------------------------------------
   Кнопки и поля в стиле Paper Dashboard
   -------------------------------------------------------------------- */

.btn {
  --bs-btn-border-radius: var(--bt-radius-pill);
  --bs-btn-padding-x: 1.4rem;
  --bs-btn-padding-y: 0.5rem;
  --bs-btn-font-weight: 600;
  transition: box-shadow 0.15s ease, transform 0.15s ease;
}

.btn:hover { box-shadow: var(--bt-shadow-hover); }
.btn:active { transform: translateY(1px); }

.btn-primary {
  --bs-btn-bg: var(--bt-blue);
  --bs-btn-border-color: var(--bt-blue);
  --bs-btn-hover-bg: var(--bt-blue-dark);
  --bs-btn-hover-border-color: var(--bt-blue-dark);
  --bs-btn-active-bg: var(--bt-blue-dark);
  --bs-btn-active-border-color: var(--bt-blue-dark);
  --bs-btn-disabled-bg: var(--bt-blue);
  --bs-btn-disabled-border-color: var(--bt-blue);
}

.btn-success {
  --bs-btn-bg: var(--bt-green);
  --bs-btn-border-color: var(--bt-green);
  --bs-btn-hover-bg: var(--bt-green-dark);
  --bs-btn-hover-border-color: var(--bt-green-dark);
  --bs-btn-active-bg: var(--bt-green-dark);
  --bs-btn-active-border-color: var(--bt-green-dark);
}

.btn-warning {
  --bs-btn-bg: var(--bt-yellow);
  --bs-btn-border-color: var(--bt-yellow);
  --bs-btn-color: #fff;
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-bg: var(--bt-yellow-dark);
  --bs-btn-hover-border-color: var(--bt-yellow-dark);
}

.btn-danger {
  --bs-btn-bg: var(--bt-red);
  --bs-btn-border-color: var(--bt-red);
  --bs-btn-hover-bg: var(--bt-red-dark);
  --bs-btn-hover-border-color: var(--bt-red-dark);
}

.btn-outline-primary {
  --bs-btn-color: var(--bt-blue);
  --bs-btn-border-color: var(--bt-blue);
  --bs-btn-hover-bg: var(--bt-blue);
  --bs-btn-hover-border-color: var(--bt-blue);
  --bs-btn-active-bg: var(--bt-blue-dark);
  --bs-btn-active-border-color: var(--bt-blue-dark);
}

.form-control, .form-select {
  border-radius: var(--bt-radius);
  padding: 0.55rem 0.9rem;
}

.form-control:focus, .form-select:focus {
  border-color: var(--bt-blue);
  box-shadow: 0 0 0 0.2rem var(--bs-focus-ring-color);
}

.card {
  border: 0;
  border-radius: var(--bt-radius);
  box-shadow: var(--bt-shadow);
}

/* --------------------------------------------------------------------
   Шапка. Раздел 5.1: название сайта и мини-аватарка на всех страницах.
   -------------------------------------------------------------------- */

.bt-header {
  background: #fff;
  box-shadow: var(--bt-shadow);
}

.bt-header .navbar-brand {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-weight: 700;
  color: var(--bt-dark);
}

.bt-header .navbar-brand:hover { color: var(--bt-blue); }
.bt-logo { height: 34px; width: auto; }

/* Раздел 5.2: три индикатора слева от аватарки. На мобильных они
   сжимаются до иконки с числом — за это отвечает .bt-indicator__label,
   которая прячется на узком экране. Сами величины появятся вместе
   со стриком, дневной целью и лигой (очередь 2). */
.bt-indicators {
  display: flex;
  align-items: center;
  gap: 0.35rem;
}

.bt-indicator {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.3rem 0.7rem;
  border-radius: var(--bt-radius-pill);
  background: var(--bt-light);
  color: var(--bt-dark);
  font-size: 0.85rem;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
}

.bt-indicator:hover { background: #ebe9e3; color: var(--bt-dark); }
.bt-indicator--streak i { color: var(--bt-red); }
.bt-indicator--goal i { color: var(--bt-green); }
.bt-indicator--league i { color: var(--bt-yellow); }

.bt-indicator__icon { width: 1.05rem; height: 1.05rem; object-fit: contain; }
.bt-indicator__value { font-variant-numeric: tabular-nums; }

/* Индикатор без величины: стрик ещё не начат или раздел не написан.
   Гасится, но с места не уходит — раздел 5.2 задаёт три индикатора,
   и шапка, в которой их становится три позже, переедет у всех
   на глазах. */
.bt-indicator--off { opacity: 0.45; }
.bt-indicator--off:hover { background: var(--bt-light); }

/* Раздел 5.2: «на мобильных они сжимаются до иконки с числом».
   Прячется подпись, число остаётся: индикатор без числа
   не индикатор. */
@media (max-width: 575.98px) {
  .bt-indicator { padding: 0.25rem 0.45rem; gap: 0.25rem; font-size: 0.8rem; }
  .bt-indicator__label { display: none; }
  .bt-indicators { gap: 0.25rem; }
}

.bt-avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  object-fit: cover;
  border: 2px solid transparent;
}

/* Раздел 5.1: аватарка незалогиненного — неактивная. */
.bt-avatar--guest { opacity: 0.55; }
.dropdown-toggle.bt-avatar-toggle::after { display: none; }
.bt-header .dropdown-menu { border: 0; box-shadow: var(--bt-shadow); border-radius: var(--bt-radius); }
.bt-header .dropdown-item.active,
.bt-header .dropdown-item:active { background: var(--bt-blue); }

/* Пункт меню, раздел которого ещё не написан. Показывается серым
   и не кликается: раздел 5.1 задаёт состав меню целиком, и прятать
   половину пунктов — значит потерять из виду, что осталось сделать. */
.dropdown-item.disabled .bt-soon {
  font-size: 0.75rem;
  color: var(--bt-grey);
  margin-left: 0.35rem;
}

/* Полоса «Подтвердите e-mail» — раздел 6.3. Жёлтая, а не красная:
   аккаунт работает, ограничение касается только покупок и
   восстановления пароля. */
.bt-confirm-bar {
  background: var(--bt-yellow);
  color: #5a4a1f;
  font-size: 0.9rem;
  padding: 0.5rem 0;
}

.bt-confirm-bar .btn-warning {
  --bs-btn-bg: #fff;
  --bs-btn-border-color: #fff;
  --bs-btn-color: #5a4a1f;
  --bs-btn-hover-bg: #fdf6e6;
  --bs-btn-hover-border-color: #fdf6e6;
  --bs-btn-hover-color: #5a4a1f;
}

/* --------------------------------------------------------------------
   Футер и полоса cookie — разделы 5.3 и 5.4
   -------------------------------------------------------------------- */

.bt-footer {
  flex-shrink: 0;
  padding: 1.5rem 0;
  border-top: 1px solid var(--bs-border-color);
  font-size: 0.85rem;
  color: var(--bt-dark);
  /* Своей заливки нет: страница уже серая, и вторая такая же полоса
     внизу только рисовала бы лишнюю границу. */
  background: transparent;
  /* По центру — текст футера короткий и служебный; выключка влево
     оставляет справа рваный край во всю ширину экрана. */
  text-align: center;
}

/* Ширину строки ограничиваем: центрированный текст на 1280 растянут
   в одну длинную строку и читается хуже, чем в две коротких. */
.bt-footer .container { max-width: 46rem; }

.bt-footer a {
  color: var(--bt-blue);
  text-decoration: underline;
}

/* Полоса не перекрывает контент (5.3): она в потоке, а не поверх него. */
.bt-cookie-bar {
  position: sticky;
  bottom: 0;
  z-index: 1030;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem;
  padding: 0.75rem 1rem;
  background: var(--bt-dark);
  color: #fff;
  font-size: 0.85rem;
}

.bt-cookie-bar a { color: var(--bt-yellow); }
.bt-cookie-bar .btn { margin-left: auto; }

/* На узком экране полоса переносится в три строки, и прижатая вправо
   кнопка оказывается висящей в углу. Центр её возвращает на место. */
@media (max-width: 575.98px) {
  .bt-cookie-bar { justify-content: center; text-align: center; }
  .bt-cookie-bar .btn { margin-left: 0; }
  .bt-confirm-bar { text-align: center; }
  .bt-confirm-bar .container { justify-content: center; }
  .bt-confirm-bar form.ms-auto { margin-left: 0 !important; }
}

/* Экран вопроса — раздел 12.1. */
.bt-timer {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.25rem 0.7rem;
  border-radius: var(--bt-radius-pill);
  background: var(--bt-light);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* Последние секунды — красным: ноль не должен наступать внезапно. */
.bt-timer--low { background: var(--bt-red); color: #fff; }

/* Вариант ответа — рамка, внутри флажок и подпись.

   Раскладка своя, а не бутстраповская: `.form-check` отодвигает
   подпись отступом слева и вытаскивает флажок наружу отрицательным
   margin. Внутри рамки это давало флажок, сидящий **на** границе
   наполовину снаружи. Флекс ставит их в ряд честно.

   Подпись растянута на всю строку намеренно: попасть пальцем
   в флажок 16 на 16 точек трудно, а в строку целиком — легко. */
.bt-option {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.6rem 0.9rem;
  border: 1px solid var(--bs-border-color);
  border-radius: var(--bt-radius);
  margin-bottom: 0.5rem;
  background: #fff;
}

.bt-option .form-check-input {
  margin: 0;
  float: none;
  flex: 0 0 auto;
}

.bt-option .form-check-label {
  margin: 0;
  flex: 1 1 auto;
  cursor: pointer;
}

.bt-option:hover { border-color: var(--bt-blue); }
.bt-option:has(.form-check-input:checked) {
  border-color: var(--bt-blue);
  background: rgba(81, 188, 218, 0.07);
}

/* --------------------------------------------------------------------
   Отдельные страницы
   -------------------------------------------------------------------- */

/* Вход и восстановление пароля — разделы 6.1 и 6.5. */
.bt-auth { max-width: 26rem; margin: 0 auto; }

/* Юридический документ: узкая колонка, читаемая длина строки. */
.bt-legal { max-width: 46rem; }
.bt-legal p { line-height: 1.7; }
.bt-legal h1 { font-size: 1.6rem; }
.bt-legal h2 { font-size: 1.2rem; margin-top: 1.5rem; }
.bt-legal ul { line-height: 1.7; padding-left: 1.4rem; }
.bt-legal li { margin-bottom: 0.3rem; }

/* Редакция и дата под заголовком документа. */
.bt-legal__meta { color: var(--bs-secondary-color, #66615b); font-size: 0.9rem; }

/* Таблица «Цели обработки» в политике конфиденциальности — раздел 5.4.

   Ячейки широкие и текст в них длинный, поэтому на узком экране
   таблица прокручивается внутри себя, а не растягивает страницу:
   горизонтальная прокрутка всей страницы ломает чтение остального
   документа. Верхнее выравнивание обязательно — в объединённой
   ячейке перечень данных вчетверо длиннее соседних, и по центру
   он оторвался бы от строки, к которой относится. */
.bt-legal table {
  display: block;
  overflow-x: auto;
  width: 100%;
  border-collapse: collapse;
  margin: 1rem 0;
  font-size: 0.95rem;
}
.bt-legal th,
.bt-legal td {
  border: 1px solid var(--bs-border-color, #dee2e6);
  padding: 0.5rem 0.7rem;
  vertical-align: top;
  min-width: 14rem;
}
.bt-legal th { background: #ebe9e3; text-align: left; }

/* Изображение раздела 29, для которого файла ещё нет: заглушка того же
   размера. Раздел 29.1 требует, чтобы отсутствие файла не ломало
   вёрстку, — рамка показывает, что место занято черновиком. */
.bt-img--placeholder {
  border: 1px dashed var(--bt-grey);
  border-radius: var(--bt-radius);
  opacity: 0.75;
}

/* Панель математических символов над полем ответа — раздел 23.3.
   Кнопки мелкие и плотные: их двадцать семь, и на телефоне они должны
   уместиться в две-три строки, не оттеснив само поле ввода за экран. */
.bt-symbols {
  display: flex;
  flex-wrap: wrap;
  gap: .25rem;
}

.bt-symbols .btn {
  min-width: 2.25rem;
  padding: .15rem .35rem;
  font-size: 1rem;
  line-height: 1.4;
}

/* Кольцевой индикатор дневной цели — раздел 9.1.
   Рисуется conic-gradient, а не скриптом: кольцо меняется на каждом
   ответе, а везти ради одной дуги библиотеку при запрете CDN
   (раздел 3) не стоит того. Доля приходит переменной --доля. */
.bt-ring {
  --доля: 0%;
  width: 3.5rem;
  height: 3.5rem;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: conic-gradient(var(--bt-blue) var(--доля), var(--bt-track) 0);
}
.bt-ring__text {
  width: 2.6rem;
  height: 2.6rem;
  border-radius: 50%;
  background: var(--bs-body-bg, #fff);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: .7rem;
  font-weight: 600;
  color: var(--bs-body-color, #66615B);
}

/* Строка «Другие режимы» (9.1). На узком экране четыре ссылки
   переносятся в две строки, и выключка влево оставляет вторую строку
   с рваным правым краем под первой. */
@media (max-width: 575.98px) {
  .bt-modes { justify-content: center; }
}

/* Пара действий у слабой темы (9.1). Обе кнопки одной ширины и одной
   высоты: длинная подпись переносится в две строки, и без выравнивания
   соседняя однострочная кнопка выглядит случайно уменьшенной. */
.bt-actions {
  display: flex;
  align-items: stretch;
  gap: 0.5rem;
}
.bt-actions > form,
.bt-actions > .btn {
  flex: 1 1 0;
  min-width: 0;
}
.bt-actions > form > .btn { width: 100%; height: 100%; }

/* Кольцо в шапке — то же самое кольцо, что на главной, только меньше.
   Общие правила лежат в .bt-ring, здесь только размеры: два разных
   кольца одной величины на одном экране читались бы как два разных
   показателя. */
.bt-ring--mini {
  width: 1.4rem;
  height: 1.4rem;
}
.bt-ring--mini .bt-ring__text {
  width: 1.05rem;
  height: 1.05rem;
  font-size: 0.6rem;
  background: var(--bt-light);
}
.bt-indicator:hover .bt-ring--mini .bt-ring__text { background: #ebe9e3; }

/* Баннер «Установить приложение» — раздел 5.5.

   Липнет к низу и не перекрывает содержимое, как и полоса cookie
   (5.3): предложение установить приложение не должно мешать решать
   вопросы — иначе оно работает против того, ради чего показано. */
.bt-install {
  position: sticky;
  bottom: 0;
  z-index: 1029;
  padding: 0.6rem 0;
  background: #fff;
  border-top: 1px solid var(--bs-border-color);
  box-shadow: 0 -2px 12px rgba(39, 39, 39, 0.06);
}

.bt-install__icon {
  width: 40px;
  height: 40px;
  border-radius: 0.6rem;
  object-fit: cover;
  flex: 0 0 auto;
}

@media (max-width: 575.98px) {
  .bt-install .container { text-align: center; justify-content: center; }
  .bt-install__icon { display: none; }
}

/* ------------------------------------------------------------------
   Лига — раздел 15.
   ------------------------------------------------------------------ */

/* Иконка дивизиона в шапке раздела (29.4) и мелкая аватарка в таблице
   группы. Размеры заданы здесь, а не в разметке: одна и та же таблица
   рисуется на трёх страницах, и три разных размера одной аватарки
   читаются как три разных элемента. */
.bt-division { width: 64px; height: 64px; object-fit: contain; }
.bt-badge { width: 48px; height: 48px; object-fit: contain; }
.bt-empty { width: 120px; height: 120px; object-fit: contain; }
.bt-avatar--sm { width: 24px; height: 24px; margin-right: 0.35rem; }

/* Зоны повышения и понижения (15.2). Цвет фона, а не значок сбоку:
   человек ищет в таблице себя, а не легенду, и граница зоны должна
   читаться боковым зрением. Полоса слева нужна тем, кто не различает
   зелёный и красный, — одного цвета для такого разделения мало. */
.bt-league tbody tr { border-left: 3px solid transparent; }
.bt-zone-up { background-color: rgba(107, 208, 152, 0.14); border-left-color: #6BD098; }
.bt-zone-down { background-color: rgba(239, 132, 87, 0.14); border-left-color: #EF8157; }
.bt-me td { font-weight: 600; }

/* Тостер начисления очков — раздел 15.1.

   «Держится 2 секунды, не перекрывает кнопку „Ответить"». Отсюда
   позиция сверху: кнопка ответа стоит внизу карточки вопроса,
   и плашка над содержимым была бы ровно тем, что ТЗ запрещает. */
.bt-xp-toast {
  position: fixed;
  top: 4.5rem;
  left: 50%;
  transform: translateX(-50%);
  z-index: 1080;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  align-items: center;
  pointer-events: none;
}
.bt-xp-toast__item {
  background: #6BD098;
  color: #fff;
  border-radius: 2rem;
  padding: 0.35rem 1rem;
  font-weight: 600;
  box-shadow: 0 4px 14px rgba(39, 39, 39, 0.18);
  animation: bt-xp-fade 2s ease-out forwards;
}
@keyframes bt-xp-fade {
  0%   { opacity: 0; transform: translateY(-0.5rem); }
  15%  { opacity: 1; transform: translateY(0); }
  80%  { opacity: 1; }
  100% { opacity: 0; transform: translateY(-0.5rem); }
}

/* Столбики очков по дням (18.3). График рисуется разметкой, а не
   библиотекой: девяносто столбиков — это девяносто div-ов, а любая
   библиотека графиков весит больше, чем весь остальной JS сайта,
   и её пришлось бы поставлять локально (раздел 3). */
.bt-chart {
  display: flex;
  align-items: flex-end;
  gap: 1px;
  height: 6rem;
  padding: 0.25rem 0;
}
.bt-chart__bar {
  flex: 1 1 0;
  min-width: 2px;
  background: var(--bt-track);
  border-radius: 1px 1px 0 0;
}
.bt-chart__bar--active { background: #51BCDA; }

/* Подпись на значке сезона — раздел 29.8.

   «Лента или медаль с местом для подписи „Алмаз, сезон 3" — подпись
   накладывается кодом, на изображении её нет». На рисунке две кремовые
   плашки одна под другой; координаты ниже измерены по самому файлу
   badge-season.png (256×256) и переведены в проценты, чтобы подпись
   ехала вместе с картинкой на любом её размере.

   Измерено по гарантированно кремовому прямоугольнику — тому, который
   остаётся кремовым во всех строках плашки. У плашки скруглённые
   концы, и прямоугольник по её крайним точкам вывел бы текст
   на золотую рамку. */
.bt-badge-box { text-align: center; width: 5rem; }
.bt-badge-art {
  position: relative;
  width: 100%;
  aspect-ratio: 1;
  container-type: inline-size;
}
.bt-badge-art .bt-badge { width: 100%; height: 100%; }

.bt-badge-line {
  position: absolute;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  white-space: nowrap;
  color: #2c3e6b;
  font-weight: 700;
  line-height: 1;
  /* Запасной размер для браузеров без единиц контейнера: лучше мелко,
     чем во всю карточку. Ниже он перекрывается расчётом от ширины. */
  font-size: 0.5rem;
  font-size: 7.2cqw;
}

/* Верхняя плашка — дивизион. Кремовая середина в файле: x 76–179,
   y 105–123 из 256, отступ по 2 px с каждой стороны от края кремового.
   Кегль подобран по худшим словам «Платина» и «Серебро»: они длиннее
   всех прочих названий дивизионов и при 7,2% ширины значка занимают
   93 px из 99 доступных. Мерилось шрифтом шире Montserrat, так что
   в браузере запас ещё больше. */
.bt-badge-line--1 { left: 30.5%; top: 41%; width: 38.7%; height: 7.4%; }

/* Нижняя плашка — номер сезона. Кремовая середина: x 87–167,
   y 137–154. Кегль меньше верхнего: плашка уже, а строка длиннее.
   Проверено на «сезон 100» — это пятнадцать лет работы продукта,
   и подпись не должна сломаться раньше, чем он до них доживёт. */
.bt-badge-line--2 {
  left: 34.8%; top: 53.5%; width: 29.7%; height: 7%;
  font-size: 0.42rem;
  font-size: 5.8cqw;
}

/* ------------------------------------------------------------------ */
/* Друзья и профиль — раздел 14.1                                      */
/* ------------------------------------------------------------------ */

/* Строка человека — не таблица. Раздел 14.1 перечисляет семь колонок,
   и на 360 точках таблица из семи колонок либо уезжает в горизонтальную
   прокрутку, либо сжимает ник до двух букв. Здесь показатели переносятся
   на вторую строку и остаются читаемыми. */
.bt-person {
  display: flex;
  /* Перенос обязателен. Без него кнопки «Вызвать» и «…» отбирают
     у ника двести точек, и на экране в 360 точек ему остаётся полоса
     в две буквы: «Хит/ры/й ен/от 741» столбиком. Теперь кнопки уезжают
     на свою строку, а ник получает всю ширину. Найдено на скриншотах
     29.08.2026 — на широком экране этого не видно вовсе. */
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem;
  padding: 0.6rem 0;
  border-bottom: 1px solid #ebe9e3;
}
.bt-person:last-child { border-bottom: 0; }

.bt-person__face { flex: 0 0 auto; }

/* Базис в 12 рем — это и есть порог переноса: пока нику хватает
   двенадцати рем, кнопки стоят справа от него; как только перестаёт
   хватать, они переходят на следующую строку целиком. */
.bt-person__main { min-width: 0; flex: 1 1 12rem; }

.bt-person__nick {
  font-weight: 600;
  color: var(--bt-dark);
  text-decoration: none;
  /* `break-word`, а не `anywhere`: второй разрешает браузеру считать
     минимальной шириной блока одну букву, и flex этим пользуется —
     колонка схлопывается ещё до того, как что-то не поместилось.
     `break-word` рвёт слово только тогда, когда оно и правда не влезло. */
  overflow-wrap: break-word;
}
.bt-person__nick:hover { color: var(--bt-blue); }

.bt-person__link {
  font-size: 0.8rem;
  color: var(--bt-grey);
  margin-left: 0.4rem;
}

.bt-person__stats {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: 0.15rem;
  font-size: 0.85rem;
  color: var(--bs-secondary-color, #66615b);
  font-variant-numeric: tabular-nums;
}
.bt-person__stats i { margin-right: 0.2rem; }
.bt-person__stats .bi-fire { color: var(--bt-red); }
.bt-person__stats .bi-lightning-charge { color: var(--bt-yellow); }

.bt-person__division {
  width: 1.1rem;
  height: 1.1rem;
  object-fit: contain;
  vertical-align: -0.2rem;
}

.bt-person__actions {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 0.4rem;
  /* Прижимает кнопки к правому краю и на своей строке тоже: перенос
     оставил бы их под аватаркой, где они читались бы как продолжение
     показателей. */
  margin-left: auto;
}

/* «Друг» — взаимная подписка (14.1). Отдельный вид у значка, а не
   просто текст: взаимные связи выводятся наверх обеих вкладок, и глаз
   должен различать их до чтения. */
.bt-badge-friend {
  background: var(--bt-green);
  color: #fff;
  font-weight: 600;
  vertical-align: 0.05rem;
}

/* Погашенная кнопка «Вызвать»: колонка задана разделом 14.1, а дуэли
   пишутся задачей 3.2. Подпись задачи — тем же способом, что в меню. */
.btn.disabled .bt-soon {
  font-size: 0.7rem;
  margin-left: 0.3rem;
  opacity: 0.75;
}

.bt-invite-qr {
  width: 180px;
  height: 180px;
  image-rendering: pixelated;
}

/* Аватар профиля. 96 точек, а не 72: он стоит по центру карточки
   отдельной строкой, и в этой роли меньший размер читается как
   иконка рядом с заголовком, а не как портрет человека. */
.bt-profile__avatar {
  display: block;
  width: 96px;
  height: 96px;
  border-radius: 50%;
  object-fit: cover;
  background: var(--bt-light);
  margin-left: auto;
  margin-right: auto;
}

.bt-profile__facts {
  display: flex;
  flex-wrap: wrap;
  gap: 1.25rem;
}

.bt-profile__value {
  font-size: 1.25rem;
  font-weight: 700;
  line-height: 1.2;
  font-variant-numeric: tabular-nums;
}
.bt-profile__value .bi-fire { color: var(--bt-red); }

.bt-profile__label {
  font-size: 0.8rem;
  color: var(--bs-secondary-color, #66615b);
}

.bt-profile__division {
  width: 1.6rem;
  height: 1.6rem;
  object-fit: contain;
  vertical-align: -0.3rem;
}

/* Картинка внутри карточки с `text-center`.

   `.card` в Bootstrap — колоночный flex-контейнер, а `text-align`
   до flex-элемента не дотягивается: изображение прижимается к левому
   краю, хотя текст под ним честно центрируется. Лечится автоотступами —
   в flex они работают. Найдено на скриншотах 29.08.2026; касалось
   пяти мест сразу: пустых состояний раздела «Друзья» и лиги, карточки
   диагностики на главной и заглушки офлайна. */
.card.text-center > img {
  margin-left: auto;
  margin-right: auto;
}

/* Показатели профиля — по центру карточки. Ряд коротких чисел,
   прижатый к левому краю, на широком экране висит в пустоте:
   справа от него полкарточки воздуха. По центру он читается
   как одна группа, а не как начало таблицы. */
.bt-profile__facts {
  justify-content: center;
}

/* QR личной ссылки — тоже по центру: он квадратный и заметно уже
   карточки, и слева от него так же остаётся пустая половина. */
.bt-invite-qr {
  display: block;
  margin: 0.5rem auto 0;
}

/* Наш рисунок вместо фотографии — аватарка животного из ника (6.6)
   или общая по умолчанию.

   Круглая маска ему не нужна: он уже нарисован круглым. Хуже того,
   она вредна — часть рисунка намеренно выходит за круг: шапочка
   выпускника, кисточка, посох. У барсука за кругом два процента
   изображения, и это ровно те два процента, ради которых рисунок
   делали. Измерено по самим файлам 29.08.2026.

   `contain` вместо `cover`: обрезать нечего, рисунок квадратный
   и должен помещаться целиком. */
.bt-avatar--art,
.bt-profile__avatar.bt-avatar--art {
  border-radius: 0;
  object-fit: contain;
  background: transparent;
}

/* Нарисованные иконки геймификации — раздел 29.4: пламя стрика,
   снежинка заморозки, кольцо выполненной цели.

   Размер в `em`, а не в точках: одна и та же иконка встречается при
   разных кеглях — 0,85 rem в шапке и в строке списка друзей, 1,25 rem
   в профиле, 2 rem в карточке «Прогресса». Единый размер в точках
   сделал бы её крупной в одном месте и мелкой в другом; в `em` она
   всегда одной величины с соседним числом. 1,25 em при кегле шапки
   даёт те же 1,05 rem, что были у прежней иконки, — шапка не переехала.

   Заводятся взамен служебной иконки Bootstrap `bi-fire` и эмодзи
   «🔥» и «❄». Эмодзи рисует шрифт операционной системы: на телефоне
   заказчика это одна картинка, на школьном компьютере другая,
   а рядом в шапке — наш собственный рисунок. Заметил заказчик
   29.08.2026 по разным огням на одном экране. */
.bt-gicon {
  width: 1.25em;
  height: 1.25em;
  object-fit: contain;
  vertical-align: -0.2em;
}

/* Погасший стрик нарисован серым отдельным файлом, поэтому гасить его
   ещё и прозрачностью не нужно: два способа сказать одно и то же
   складываются, и пламя становится едва различимым. Остальная часть
   индикатора приглушается по-прежнему. */
.bt-indicator--off .bt-gicon { opacity: 1; }

/* Снежинка в клетке календаря активности (10.2). Клетка маленькая,
   и число дня в ней прячется — вместо него стоит снежинка, потому что
   день заморозки узнаётся именно по ней. Размер в процентах от клетки:
   клетка задана через aspect-ratio и меняется вместе с шириной экрана.
   Картинка идёт через тег `{% img %}`, как и вся графика раздела 29,
   поэтому фоном её задать нельзя — фон не умеет подставлять заглушку. */
.bt-day__freeze {
  width: 70%;
  height: 70%;
  object-fit: contain;
}

/* Кольцо выполненной дневной цели — раздел 29.4, 128×128.
   Показывается на экране «Сегодня закрыто» (10.1: «при выполнении
   цели — анимация»). */
.bt-goal-done {
  width: 96px;
  height: 96px;
  object-fit: contain;
  animation: bt-goal-done 0.6s ease-out both;
}

@keyframes bt-goal-done {
  from { transform: scale(0.4); opacity: 0; }
  60%  { transform: scale(1.08); opacity: 1; }
  to   { transform: scale(1); opacity: 1; }
}

/* Человеку, который просил систему не двигать картинки, её и не двигаем.
   Само кольцо остаётся: оно несёт смысл, а не украшает. */
@media (prefers-reduced-motion: reduce) {
  .bt-goal-done { animation: none; }
}
