/* ==========================================================================
   07-gamification.css — стили геймификации: сайдбар-виджет, страница
   прогресса, попапы начисления (XP/бейдж/стрик) и анонимный «наживка»-блок
   в карточке задания.

   ПОДКЛЮЧАЕТСЯ ПОСЛЕ 04-prose.css (см. templates/base.html). Все цвета —
   ролевые токены из 00-tokens.css (темозависимые), за исключением tiers
   (bronze/silver/gold/platinum): под них ниже заведены ЛОКАЛЬНЫЕ
   кастомные свойства, т.к. в дизайн-системе для тиров отдельных токенов нет.

   Состав:
     • локальные токены тиров (--tier-*);
     • A. Сайдбар-виджет (.gamification-widget, .gw-*);
     • B. Страница /progress/ (.gamification-progress, .gp-*);
     • C. Попапы (.xp-flash, .badge-flash, .streak-flash) — fixed, top-right,
       z-index выше шапки (102 — header 50, см. 02-layout.css);
     • D. Анонимный bait (.task-anon-bait);
     • E. Таблица лидеров (.gamification-leaderboard, .gl-*);
     • F. Стрик под угрозой и пауза (.gw-risk, .gw-pause, .gp-streak-controls);
     • prefers-reduced-motion: попапы без анимаций.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Локальные токены тиров. У геймификации своя «металлическая» шкала, которой
   в общей дизайн-системе нет аналога, поэтому цвета заведены здесь, а не в
   00-tokens.css. Заданы как oklch-литералы (в sRGB): тёплый бронзовый,
   холодный серебряный, золотой и яркий платиновый. Светлота подобрана так,
   чтобы тир читался и на светлой, и на тёмной карточке как ЦВЕТ ИКОНКИ/ТЕКСТА
   (это акцент, а не заливка под текстом — для заливки клался бы *-surface).
   --tier-*-raw хранит триплет L C H для композиции с альфой
   (oklch(var(--tier-gold-raw) / 0.15)).
   -------------------------------------------------------------------------- */
.gp-badge,
.badge-flash {
  --tier-bronze: oklch(0.62 0.09 55);
  --tier-bronze-raw: 0.62 0.09 55;
  --tier-silver: oklch(0.72 0.02 270);
  --tier-silver-raw: 0.72 0.02 270;
  --tier-gold: oklch(0.78 0.14 85);
  --tier-gold-raw: 0.78 0.14 85;
  --tier-platinum: oklch(0.85 0.04 240);
  --tier-platinum-raw: 0.85 0.04 240;
}

/* ==========================================================================
   A. САЙДБАР-ВИДЖЕТ (рендерится на КАЖДОЙ странице через сайдбар)
   Стилистически повторяет .sidebar-card: та же подложка --card, рамка --border,
   радиус --radius. Контейнер — не интерактивный; интерактив только у .gw-link.
   ========================================================================== */
.gamification-widget {
  background-color: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1rem 1.25rem;
  /* Едва заметная тень — как у .card (0 1px 3px rgba(0,0,0,.1)). */
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
  font-size: 0.9375rem;
  line-height: 1.5;
}

/* Анонимный вариант: чуть меньше плотности, т.к. внутри только «наживка».
   Модификатор, а не отдельный селектор — переопределяет только нужное. */
.gamification-widget--anon {
  padding: 1.25rem;
}

/* Блочная ссылка, оборачивающая весь аутентифицированный контент виджета.
   Без подчёркивания, со слабой подсветкой на ховере — вся плашка кликабельна
   и ведёт на /progress/. */
.gw-link {
  display: block;
  padding: 0.25rem 0;
  color: var(--foreground);
  text-decoration: none;
  border-radius: calc(var(--radius) - 0.25rem);
  transition: color 0.2s ease;
}
.gw-link:hover {
  color: var(--primary);
}
.gw-link:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 2px;
}

/* Строка уровня — крупнее и жирнее остальных строк виджета. */
.gw-level {
  font-size: 1rem;
  font-weight: 600;
  margin-bottom: 0.5rem;
  color: var(--foreground);
}

/* Трек прогресс-бара: нейтральная канавка --muted. */
.gw-progress {
  width: 100%;
  height: 0.5rem;
  background-color: var(--muted);
  border-radius: 9999px;
  overflow: hidden;
  margin-bottom: 0.5rem;
}
/* Заливка — --primary-surface (поверхности, не акцент-ссылка). Ширина ставится
   инлайном: style="width: {{ xp_pct }}%". transition на width мягчит htmx-свап. */
.gw-progress__bar {
  height: 100%;
  background-color: var(--primary-surface);
  border-radius: 9999px;
  transition: width 0.4s ease;
}

/* Строки статистики: XP, стрик, бейджи — приглушённый текст. */
.gw-xp,
.gw-streak,
.gw-badges {
  font-size: 0.8125rem;
  color: var(--muted-foreground);
  line-height: 1.6;
}

/* --- Анонимный «наживка»-блок внутри виджета ---
   CTA-кнопок «Войти»/«Регистрация» здесь больше нет: они дублировали шапку.
   Весь блок — одна ссылка на вход со стрелкой. */
.gw-anon {
  display: block;
  color: var(--muted-foreground);
  font-size: 0.875rem;
  line-height: 1.5;
  text-decoration: none;
  transition: color 0.15s ease;
}
.gw-anon:hover {
  color: var(--primary);
}
.gw-anon:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 2px;
  border-radius: 0.25rem;
}
/* Стрелка — акцентный «хвост» ссылки, не переносится на новую строку одна. */
.gw-anon__arrow {
  color: var(--primary);
  font-weight: 600;
  white-space: nowrap;
}

/* ==========================================================================
   B. СТРАНИЦА /progress/
   ========================================================================== */
.gamification-progress {
  /* Наследует фон страницы; внутри — карточки/секции. */
  max-width: 720px;
  margin: 0 auto;
}
.gamification-progress h1 {
  font-size: 1.75rem;
  font-weight: 700;
  color: var(--foreground);
  margin: 0 0 1.5rem;
}
.gamification-progress h2 {
  font-size: 1.25rem;
  font-weight: 600;
  color: var(--foreground);
  margin: 2rem 0 1rem;
}

/* Шапка: уровень + большой прогресс-бар + строки XP/стрика. */
.gp-header {
  background-color: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.25rem 1.5rem;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
}
.gp-level {
  font-size: 1.125rem;
  font-weight: 600;
  color: var(--foreground);
  margin-bottom: 0.75rem;
}
/* Прогресс-бар страницы — крупнее сайдбарного (читается как главный индикатор). */
.gp-progress {
  width: 100%;
  height: 0.75rem;
  background-color: var(--muted);
  border-radius: 9999px;
  overflow: hidden;
  margin-bottom: 0.75rem;
}
.gp-progress__bar {
  height: 100%;
  background-color: var(--primary-surface);
  border-radius: 9999px;
  transition: width 0.4s ease;
}
.gp-xp,
.gp-streak {
  font-size: 0.9375rem;
  color: var(--muted-foreground);
  line-height: 1.7;
}

/* --- 14-дневная полоса активности ---
   Ряд небольших квадратов; активный день подсвечен, неактивный — приглушён. */
.gp-calendar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3125rem;
  margin-top: 1.25rem;
}
.gp-calendar__day {
  width: 1.25rem;
  height: 1.25rem;
  border-radius: 0.25rem;
  background-color: var(--muted);
  border: 1px solid var(--border);
  display: inline-block;
}
.gp-calendar__day.is-active {
  /* Активный день — заливка успеха (прогресс = «выполнено»). */
  background-color: var(--success-surface);
  border-color: var(--success-surface);
}

/* --- Сетка карточек бейджей --- */
.gp-badge-grid {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 1rem;
}

/* Карточка бейджа. По умолчанию (без тира) — нейтральная; тиры ниже
   перекрашивают только левую полоску и иконку. */
.gp-badge {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.5rem;
  padding: 1rem 1rem 1rem 1.25rem;
  background-color: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
  overflow: hidden;
}
/* Цветная полоска слева — как акцент у .post-card::before. Здесь она
   статична (не растёт на ховере): карточка не интерактивная. */
.gp-badge::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 3px;
  background: var(--tier-bronze);
}

/* --- Тиры: перекрашивают полоску и иконку. Карточка остаётся --card. --- */
.gp-badge--bronze::before,
.gp-badge--bronze .gp-badge__icon { color: var(--tier-bronze); }
.gp-badge--silver::before,
.gp-badge--silver .gp-badge__icon { color: var(--tier-silver); }
.gp-badge--gold::before,
.gp-badge--gold .gp-badge__icon { color: var(--tier-gold); }
.gp-badge--platinum::before,
.gp-badge--platinum .gp-badge__icon { color: var(--tier-platinum); }

/* ЗАБЛОКИРОВАННЫЙ бейдж: ОБЕСЦВЕЧЕН, НО ЧИТАЕЛЕН.
   filter: grayscale(1) + opacity .45 — иконка и название остаются видны,
   пользователь видит, ЧТО это за бейдж и к чему стремиться. */
.gp-badge--locked {
  filter: grayscale(1);
  opacity: 0.45;
}

.gp-badge__icon {
  font-size: 1.5rem;
  line-height: 1;
  color: var(--tier-bronze); /* переопределяется модификатором тира выше */
}
.gp-badge__title {
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--foreground);
  line-height: 1.3;
}
.gp-badge__date {
  font-size: 0.75rem;
  color: var(--muted-foreground);
}

/* Прогресс к невыданному счётному бейджу — уменьшенная копия .gp-progress.
   Ширина на всю карточку: «7 / 10» под серой иконкой отвечает на вопрос
   «сколько осталось», ради которого заблокированный бейдж и показывают. */
.gp-badge__progress {
  width: 100%;
  height: 0.375rem;
  margin-top: auto;
  background-color: var(--muted);
  border-radius: 9999px;
  overflow: hidden;
}
.gp-badge__progress-bar {
  height: 100%;
  background-color: var(--primary-surface);
  border-radius: 9999px;
  transition: width 0.4s ease;
}
.gp-badge__progress-label {
  font-size: 0.75rem;
  color: var(--muted-foreground);
}

/* --- Списки: источники XP и последние события --- */
.gp-breakdown,
.gp-feed {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.gp-breakdown li,
.gp-feed li {
  padding: 0.625rem 0.875rem;
  background-color: var(--card);
  border: 1px solid var(--border);
  border-radius: 0.5rem;
  font-size: 0.9375rem;
  color: var(--foreground);
}
.gp-breakdown li strong {
  color: var(--success-text);
}
.gp-feed li {
  color: var(--muted-foreground);
}

/* ==========================================================================
   C. ПОПАПЫ (tut-celebrate.js — Task 16)
   position: fixed, правый верхний угол, z-index ВЫШЕ шапки.
   Шапка — sticky, z-index 50 (02-layout.css); мобильное меню — 1000/1001.
   Берём 1050: выше шапки и скользящих панелей, но ниже skip-link (1100) —
   попап не должен перекрывать навигацию с клавиатуры.
   ========================================================================== */
.xp-flash,
.levelup-flash,
.badge-flash,
.streak-flash {
  position: fixed;
  top: 1rem;
  right: 1rem;
  z-index: 1050;
  display: flex;
  align-items: center;
  gap: 0.625rem;
  padding: 0.75rem 1rem;
  background-color: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 10px 24px rgba(0, 0, 0, 0.18);
  font-size: 0.9375rem;
  color: var(--foreground);
  /* Появление/исчезновение делает JS; transition здесь мягчит opacity. */
  transition: opacity 0.25s ease, transform 0.25s ease;
}

/* «+35 XP» — акцентный текст успеха (начисление). */
.xp-flash {
  font-weight: 700;
  color: var(--success-text);
}

/* Level-up-попап: «⬆️ Уровень 3!». Акцент — основной цвет темы, а не
   металлическая шкала тиров: повышение уровня не награда-предмет (это бейдж)
   и не серия дней (это стрик), своей шкалы у него нет. */
.levelup-flash {
  border-left: 4px solid var(--primary);
  font-weight: 700;
  color: var(--primary);
}

/* Бейдж-попап: иконка + название. Тир подсвечивает левую границу и иконку. */
.badge-flash {
  border-left: 4px solid var(--tier-bronze); /* дефолт, перекрывается тиром */
}
.badge-flash__icon {
  font-size: 1.5rem;
  line-height: 1;
  color: var(--tier-bronze);
}
.badge-flash__title {
  font-weight: 600;
  color: var(--foreground);
}
/* Кнопка закрытия — единственный способ убрать попап с клавиатуры (клик по
   карточке для этого не годится: <div> в таб-порядок не попадает). Держим
   настоящей <button>, чтобы работали и Enter/Space, и видимый фокус. */
.badge-flash__close {
  margin-left: auto;
  padding: 0 0.25rem;
  background: none;
  border: none;
  color: var(--muted-foreground, var(--foreground));
  font-size: 1.25rem;
  line-height: 1;
  cursor: pointer;
}
.badge-flash__close:hover {
  color: var(--foreground);
}
.badge-flash__close:focus-visible {
  outline: 2px solid var(--ring, currentColor);
  outline-offset: 2px;
  border-radius: 2px;
}
.badge-flash--bronze { border-left-color: var(--tier-bronze); }
.badge-flash--bronze .badge-flash__icon { color: var(--tier-bronze); }
.badge-flash--silver { border-left-color: var(--tier-silver); }
.badge-flash--silver .badge-flash__icon { color: var(--tier-silver); }
.badge-flash--gold { border-left-color: var(--tier-gold); }
.badge-flash--gold .badge-flash__icon { color: var(--tier-gold); }
.badge-flash--platinum { border-left-color: var(--tier-platinum); }
.badge-flash--platinum .badge-flash__icon { color: var(--tier-platinum); }

/* Стрик-попап. Майлстоун (7/30 дней) — ярче: заливка успеха. */
.streak-flash {
  border-left: 4px solid var(--warning-text);
}
.streak-flash--milestone {
  border-left-color: var(--success-surface);
  background-color: oklch(var(--success-text-raw) / 0.12);
}

/* ==========================================================================
   D. АНОНИМНЫЙ «НАЖИВКА»-БЛОК в карточке задания (Task 17)
   Инлайн-блок после правильного ответа анонима — приглашение войти, чтобы XP
   засчитались. По тону близок к .alert--info (тинт акцента, не заливка).
   ========================================================================== */
.task-anon-bait {
  display: block;
  margin: 0.75rem 0 0;
  padding: 0.75rem 1rem;
  background-color: oklch(var(--primary-raw) / 0.1);
  border: 1px solid oklch(var(--primary-raw) / 0.25);
  border-radius: var(--radius);
  font-size: 0.9375rem;
  color: var(--foreground);
}
.task-anon-bait a {
  color: var(--primary);
  font-weight: 600;
  text-decoration: none;
}
.task-anon-bait a:hover {
  text-decoration: underline;
}

/* ==========================================================================
   E. ТАБЛИЦА ЛИДЕРОВ (/leaderboard/)
   Ширина и заголовки — как у /progress/ (страницы соседние по смыслу).
   Таблица горизонтально скроллится в своей обёртке: на узком экране она
   не должна растягивать страницу.
   ========================================================================== */
.gamification-leaderboard {
  max-width: 720px;
  margin: 0 auto;
}
.gamification-leaderboard h1 {
  font-size: 1.75rem;
  font-weight: 700;
  color: var(--foreground);
  margin: 0 0 1.5rem;
}

/* Вкладки периода — ссылки-«таблетки»; активная залита акцентом. */
.gl-tabs {
  display: flex;
  gap: 0.5rem;
  margin-bottom: 1.25rem;
}
.gl-tab {
  padding: 0.4375rem 1rem;
  border: 1px solid var(--border);
  border-radius: 9999px;
  background-color: var(--card);
  color: var(--muted-foreground);
  font-size: 0.9375rem;
  font-weight: 600;
  text-decoration: none;
}
.gl-tab:hover {
  color: var(--foreground);
  border-color: var(--primary);
}
.gl-tab:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}
.gl-tab.is-active {
  background-color: var(--primary-surface);
  border-color: var(--primary-surface);
  color: var(--primary-foreground);
}

.gl-table-wrap {
  overflow-x: auto;
  background-color: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
}
.gl-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9375rem;
}
.gl-table__caption {
  caption-side: top;
  padding: 0.875rem 1rem 0;
  text-align: left;
  color: var(--muted-foreground);
  font-size: 0.875rem;
}
.gl-table th,
.gl-table td {
  padding: 0.625rem 1rem;
  text-align: left;
  border-bottom: 1px solid var(--border);
}
.gl-table thead th {
  color: var(--muted-foreground);
  font-weight: 600;
  white-space: nowrap;
}
.gl-table tbody tr:last-child td {
  border-bottom: none;
}
.gl-table__rank {
  width: 3rem;
  color: var(--muted-foreground);
}
.gl-table__xp {
  text-align: right;
  font-weight: 600;
  color: var(--foreground);
  white-space: nowrap;
}
.gl-row td {
  color: var(--foreground);
}
/* Своя строка — тинт акцента слева, чтобы находиться в таблице взглядом. */
.gl-row--me td {
  background-color: oklch(var(--primary-raw) / 0.1);
  font-weight: 600;
}
.gl-row--me td:first-child {
  box-shadow: inset 3px 0 0 var(--primary);
}
.gl-you {
  margin-left: 0.375rem;
  padding: 0.0625rem 0.375rem;
  border-radius: 9999px;
  background-color: oklch(var(--primary-raw) / 0.2);
  color: var(--primary);
  font-size: 0.75rem;
  font-weight: 600;
}

/* Ссылка на лидерборд из сайдбар-виджета: отдельная строка под .gw-link. */
.gw-leaderboard {
  display: block;
  margin-top: 0.5rem;
  padding-top: 0.5rem;
  border-top: 1px solid var(--border);
  color: var(--primary);
  font-size: 0.875rem;
  font-weight: 600;
  text-decoration: none;
}
.gw-leaderboard:hover {
  text-decoration: underline;
}
.gw-leaderboard:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}

.gl-empty,
.gl-myrank,
.gl-optout,
.gl-back {
  margin: 1rem 0 0;
  font-size: 0.9375rem;
  color: var(--muted-foreground);
}
.gl-myrank strong {
  color: var(--foreground);
}
.gl-optout a,
.gl-back a {
  color: var(--primary);
  font-weight: 600;
  text-decoration: none;
}
.gl-optout a:hover,
.gl-back a:hover {
  text-decoration: underline;
}

/* ==========================================================================
   F. СТРИК ПОД УГРОЗОЙ И ПАУЗА
   Плашка в виджете (.gw-risk) и её развёрнутая версия на /progress/
   (.gp-streak-controls). Тон предупреждения, а не ошибки: стрик ещё цел,
   день не кончился — поэтому тинт янтаря (--warning-text-raw, темозависимый
   янтарь в роли текста), а не --destructive.
   Пауза (.gw-pause) — состояние покоя: нейтральный --muted, ничего срочного.
   ========================================================================== */
.gw-risk {
  margin-top: 0.75rem;
  padding: 0.625rem 0.75rem;
  background-color: oklch(var(--warning-text-raw) / 0.12);
  border: 1px solid oklch(var(--warning-text-raw) / 0.3);
  border-radius: var(--radius);
}
.gw-risk__text {
  margin: 0;
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--foreground);
}
/* Кнопка паузы — во всю ширину плашки: в узком сайдбаре обрезанный текст
   читается хуже переноса. */
.gw-risk__pause,
.gp-streak-controls__pause {
  display: block;
  width: 100%;
  margin-top: 0.5rem;
  padding: 0.4375rem 0.75rem;
  background-color: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font: inherit;
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--foreground);
  cursor: pointer;
  transition: background-color 0.2s ease, border-color 0.2s ease;
}
.gw-risk__pause:hover,
.gp-streak-controls__pause:hover {
  background-color: var(--muted);
  border-color: var(--primary);
}
.gw-risk__pause:focus-visible,
.gp-streak-controls__pause:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}

/* Пауза в виджете: строка того же ритма, что .gw-xp/.gw-streak. */
.gw-pause {
  margin-top: 0.75rem;
  padding: 0.5rem 0.75rem;
  background-color: var(--muted);
  border-radius: var(--radius);
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--muted-foreground);
}

/* Развёрнутый блок на /progress/ — внутри .gp-header, отделён линией. */
.gp-streak-controls:not(:empty) {
  margin-top: 0.75rem;
  padding-top: 0.75rem;
  border-top: 1px solid var(--border);
}
.gp-streak-controls__risk,
.gp-streak-controls__paused,
.gp-streak-controls__hint {
  margin: 0;
  font-size: 0.9375rem;
  line-height: 1.7;
  color: var(--muted-foreground);
}
.gp-streak-controls__risk {
  color: var(--foreground);
  font-weight: 600;
}
.gp-streak-controls__hint {
  margin-top: 0.5rem;
  font-size: 0.875rem;
}
/* На широкой странице кнопка по содержимому, а не во всю ширину карточки. */
.gp-streak-controls__pause {
  width: auto;
  font-size: 0.875rem;
}

/* ==========================================================================
   PREFERS-REDUCED-MOTION
   tut-celebrate.js уже уважает reduce; CSS не должен с ним конфликтовать.
   У попапов гасим ВСЕ переходы и анимации — появление/исчезновение мгновенное.
   Прогресс-бары (width transition) тоже мгновенные — движение заполнения
   убирается. Это касается только явно анимированных выше классов.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  .xp-flash,
  .levelup-flash,
  .badge-flash,
  .streak-flash,
  .gw-progress__bar,
  .gp-progress__bar,
  .gp-badge__progress-bar,
  .gw-link,
  .gw-anon,
  .gw-risk__pause,
  .gp-streak-controls__pause,
  .task-anon-bait,
  .task-anon-bait a {
    transition: none !important;
    animation: none !important;
  }
}
