/* REDNIK — Cinematic Noir. Токены взяты из site/glavnaya/DESIGN.md. */

:root {
  --surface:        #200f0e;
  --surface-low:    #1a0a09;
  --surface-card:   #291716;
  --surface-high:   #392524;
  --on-surface:     #fddbd8;
  --on-muted:       rgba(253, 219, 216, .6);
  --on-faint:       rgba(253, 219, 216, .38);
  --accent:         #e6192e;
  --accent-soft:    #ffb3ae;
  --glass:          rgba(255, 255, 255, .08);
  --glass-line:     rgba(255, 255, 255, .1);

  --r-sm: .25rem; --r: .5rem; --r-md: .75rem; --r-lg: 1rem; --r-xl: 1.5rem;
  --gutter: 24px;
  --max: 1280px;
  --section: 80px;

  --display: "Chivo", "Arial Black", system-ui, sans-serif;
  --body:    "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono:    "JetBrains Mono", ui-monospace, "Cascadia Mono", Consolas, monospace;
}

*, *::before, *::after { box-sizing: border-box; }

/*
 * Атрибут hidden прячет элемент через display:none в стилях браузера,
 * а любое наше правило display его перебивает. Из-за этого кнопка
 * «показать ещё» оставалась на месте, когда грузить было уже нечего.
 */
[hidden] { display: none !important; }

html { scroll-behavior: smooth; background: var(--surface); }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

body {
  margin: 0;
  /*
   * Фон держит html, а не body. Холст лучей лежит на z-index: -1, и фон body
   * закрасил бы его собой. Фон html уходит на подложку окна, под всё сразу.
   */
  background: transparent;
  color: var(--on-surface);
  font: 400 16px/1.6 var(--body);
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; display: block; }
a { color: inherit; }

/* ---------------------------------------------------------------- фон из лучей */
/*
 * Холст с движущимися лучами. Вся логика в assets/js/beams.js, там же
 * написано, что изменено против оригинального компонента и почему.
 *
 * z-index: -1 уводит холст под весь контент. Разметку из-за этого трогать
 * не пришлось: секции и карточки рисуются поверх, как рисовались.
 * Фон при этом снят с body и отдан html (см. выше), иначе body закрасил бы холст.
 *
 * Размеры заданы явно. canvas — заменяемый элемент: при width: auto он берёт
 * ширину из атрибута, а не растягивается по left/right, и остался бы 300x150.
 *
 * Вылет на 64px за края экрана нужен размытию. Фильтр подмешивает прозрачность
 * из-за границы элемента, и без запаса лучи выцветали бы по краям окна.
 *
 * Радиус размытия зависит от ширины экрана: 44px на телефоне размазали бы всё
 * в ровное пятно, 18px на десктопе оставили бы различимые полосы.
 */
.beams {
  position: fixed;
  top: -64px; left: -64px;
  width: calc(100vw + 128px);
  height: calc(100vh + 128px);
  z-index: -1;
  pointer-events: none;
  filter: blur(clamp(18px, 3.5vw, 44px));
}

.wrap { width: 100%; max-width: var(--max); margin-inline: auto; padding-inline: var(--gutter); }
@media (max-width: 640px) { .wrap { padding-inline: 16px; } }

.mono {
  font: 500 12px/1 var(--mono);
  letter-spacing: .1em;
  text-transform: uppercase;
}

/* Видно только скринридеру */
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

:focus-visible { outline: 2px solid var(--accent-soft); outline-offset: 3px; border-radius: var(--r-sm); }

/* ---------------------------------------------------------------- шапка */
.top {
  position: sticky; top: 0; z-index: 50;
  background: rgba(26, 10, 9, .72);
  backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
  border-bottom: 1px solid var(--glass-line);
}
.top__in { display: flex; align-items: center; gap: 32px; height: 68px; }
.logo {
  display: inline-flex; align-items: center; gap: 11px;
  font: 900 24px/1 var(--display); letter-spacing: -.02em;
  color: var(--on-surface); text-decoration: none; flex: none;
}
.logo img {
  width: 36px; height: 36px; border-radius: 50%; flex: none;
  border: 1.5px solid var(--accent);
  object-fit: cover;
}
@media (max-width: 560px) { .logo img { width: 30px; height: 30px; } }
.nav { display: flex; gap: 26px; margin-left: auto; }
.nav a {
  text-decoration: none; color: var(--on-muted); font-size: 15px;
  padding: 4px 0; border-bottom: 2px solid transparent; transition: color .18s, border-color .18s;
}
.nav a:hover { color: var(--on-surface); }
.nav a[aria-current] { color: var(--on-surface); border-bottom-color: var(--accent); }
@media (max-width: 800px) { .nav { gap: 18px; } .nav a { font-size: 14px; } }

/*
 * Морфинг навигации. По мотивам Morphic Navbar (kokonutui.com, MIT): пункты
 * слиты в одну плашку, выделенный выступает из неё отдельной таблеткой,
 * а соседи закругляют грани, обращённые к открывшемуся зазору.
 *
 * Три отступления от оригинала, все вынужденные.
 *
 * 1. Морф повешен на наведение, а не на клик. В оригинале это React: клик
 *    меняет состояние, и плашка перестраивается на месте. У нас страницы
 *    настоящие, клик уводит на другой адрес — перестраиваться нечему.
 *    Выделенный пункт при этом выступает постоянно, он и есть «вы здесь».
 *
 * 2. Зазор открывается не отступом, а сжатием подложки. В оригинале активный
 *    пункт получает mx-2 и раздвигает соседей — строка меняет ширину. У нас
 *    меню прижато вправо, поэтому оно дёргалось бы при каждом наведении.
 *    Здесь зазоры стоят в разметке всегда, а подложка каждого пункта по
 *    умолчанию вылезает на их половину и смыкается с соседской. Ширина строки
 *    не меняется вообще.
 *
 * 3. Только с 801px. Ниже начинают ужиматься шрифты и отступы, а с 560px
 *    из меню пропадает «Главная» — плашке там уже не хватает места рядом
 *    с логотипом. На узком экране остаётся прежняя раскладка ссылками.
 */
@media (min-width: 801px) {
  /* Зазор держится в разметке всегда, подложка его закрывает. */
  .nav { gap: 16px; }
  .nav a {
    position: relative;
    padding: 9px 16px;
    border-bottom: 0;
    transition: color .3s;
  }

  .nav a::before {
    content: "";
    position: absolute; z-index: -1;
    top: 0; bottom: 0; left: -8px; right: -8px;
    background: var(--surface-high);
    border-radius: var(--nav-l, 0) var(--nav-r, 0) var(--nav-r, 0) var(--nav-l, 0);
    transition: left .3s, right .3s, border-radius .3s, background .3s;
  }

  /* Внешние края плашки скруглены и наружу не вылезают. */
  .nav a:first-child::before { left: 0;  --nav-l: var(--r-md); }
  .nav a:last-child::before  { right: 0; --nav-r: var(--r-md); }

  /* Соседи выступающего пункта отводят подложку и закругляют грань у зазора. */
  .nav a:has(+ a:hover)::before,
  .nav a:has(+ a:focus-visible)::before,
  .nav a:has(+ a[aria-current])::before { right: 0; --nav-r: var(--r-md); }
  .nav a:hover + a::before,
  .nav a:focus-visible + a::before,
  .nav a[aria-current] + a::before { left: 0; --nav-l: var(--r-md); }

  /* Сам выступающий пункт: подложка поджимается к своим границам. */
  /* Фокус с клавиатуры морфит наравне с курсором: иначе обводка режет плашку,
     а человек без мыши не получает той же подсказки. */
  .nav a:hover::before,
  .nav a:focus-visible::before,
  .nav a[aria-current]::before {
    left: 0; right: 0;
    --nav-l: var(--r-md); --nav-r: var(--r-md);
  }
  .nav a:hover::before,
  .nav a:focus-visible::before { background: var(--surface-card); }

  /*
   * Текущая страница красным. В оригинале активный пункт отличается только
   * формой и насыщенностью шрифта, но на этом сайте текущий раздел всегда
   * помечался акцентом, и терять эту подсказку ради точности переноса
   * не стоит: форму считает не каждый.
   */
  .nav a[aria-current] { color: #fff; font-weight: 700; border-bottom-color: transparent; }
  .nav a[aria-current]::before,
  .nav a[aria-current]:hover::before { background: var(--accent); }
}
@media (max-width: 560px) {
  .top__in { height: 60px; gap: 10px; }
  /* Аватар в логотипе съел ширину, поэтому шапку ужимаем целиком. */
  .top .logo { font-size: 20px; gap: 9px; }
  .nav { gap: 12px; }
  .nav a { font-size: 13px; }
  /* «Главная» лишняя — на неё ведёт логотип слева. */
  .nav a:first-child { display: none; }
}
/*
 * На узких телефонах подгонять размеры бесполезно — рано или поздно
 * не влезет. Оставляем в логотипе только аватар: он и так узнаваем,
 * а название студии стоит в заголовке страницы прямо под шапкой.
 */
@media (max-width: 420px) {
  .top .logo span { display: none; }
  .nav a { font-size: 14px; }
}

/* ---------------------------------------------------------------- кнопки */
/*
 * Все кнопки сайта — по мотивам Command Button (kokonutui.com, MIT):
 * вертикальный градиент, рамка, светлеющая под курсором, и блик,
 * пробегающий поперёк за полсекунды. Значков нет: на сайте их не водится,
 * кроме искры у клубной кнопки — она собрана из тех же правил плюс значок.
 *
 * Два отступления от оригинала.
 *
 * 1. Цвета свои. У оригинала база нейтрально-серая; у нас главный призыв
 *    остаётся студийным красным, а второстепенная кнопка берёт тональные
 *    слои сайта — так задано в макете.
 *
 * 2. Блик сделан анимацией, а не переходом. В оригинале это transition
 *    на transform, и полоса уезжает обратно, когда курсор уходит, — выходит
 *    второй, обратный проход. Здесь один чистый проход на въезд курсора.
 */
.btn {
  position: relative; overflow: hidden;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 13px 24px; border-radius: var(--r); border: 1px solid transparent;
  font: 700 15px/1 var(--display); text-decoration: none; cursor: pointer;
  transition: border-color .3s, box-shadow .3s, transform .3s;
}

.btn--primary {
  background: linear-gradient(180deg, #f5233a, #b8121f);
  border-color: rgba(255, 255, 255, .18);
  color: #fff;
}
.btn--primary:hover {
  border-color: rgba(255, 255, 255, .34);
  box-shadow: 0 0 22px rgba(230, 25, 46, .4);
  transform: translateY(-1px);
}

.btn--ghost {
  background: linear-gradient(180deg, var(--surface-high), var(--surface-low));
  border-color: var(--glass-line);
  color: var(--on-surface);
}
.btn--ghost:hover { border-color: var(--on-faint); transform: translateY(-1px); }

.btn--wide { width: 100%; }
.btn[disabled] { opacity: .55; cursor: not-allowed; transform: none; box-shadow: none; }

/*
 * Полоса блика узкая и с наклоном. У оригинала блик размазан на всю ширину:
 * на его сером фоне это заметно, а на насыщенном красном читается как вспышка
 * целиком, а не как пробегающий блик.
 *
 * Полоса идёт поверх надписи — так же, как в оригинале: там слой блика стоит
 * последним и накрывает и значок, и текст.
 */
.btn--primary::after,
.btn--ghost::after {
  content: "";
  position: absolute; inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(105deg,
    rgba(255, 255, 255, 0) 38%,
    rgba(255, 255, 255, .34) 50%,
    rgba(255, 255, 255, 0) 62%);
}
.btn--primary:hover::after, .btn--primary:focus-visible::after,
.btn--ghost:hover::after,   .btn--ghost:focus-visible::after { animation: btn-shine .5s ease-out; }
@keyframes btn-shine {
  from { transform: translateX(-100%); }
  to   { transform: translateX(100%); }
}

/* Клубная кнопка — та же основа плюс искра, которая оживает под курсором. */
.btn__spark { flex: none; transition: transform .3s; }
.btn--club:hover .btn__spark { transform: scale(1.1) rotate(-4deg); }
.btn--club:active .btn__spark { transform: scale(.95); }

/* ---------------------------------------------------------------- герой */
.hero { padding: 72px 0 var(--section); }
.eyebrow { display: inline-flex; align-items: center; gap: 9px; color: var(--on-muted); margin-bottom: 26px; }
.onair {
  width: 7px; height: 7px; border-radius: 50%; background: var(--accent);
  box-shadow: 0 0 0 0 rgba(230, 25, 46, .65); animation: pulse 2.4s ease-out infinite;
}
@keyframes pulse {
  70%  { box-shadow: 0 0 0 9px rgba(230, 25, 46, 0); }
  100% { box-shadow: 0 0 0 0 rgba(230, 25, 46, 0); }
}
.hero__top {
  display: grid; grid-template-columns: 1.05fr .95fr;
  gap: 56px; align-items: center;
}
@media (max-width: 900px) { .hero__top { grid-template-columns: 1fr; gap: 40px; } }

.hero h1 {
  margin: 0 0 20px;
  font: 900 clamp(32px, 4vw, 52px)/1.08 var(--display);
  letter-spacing: -.03em; max-width: 17ch;
}
.hero h1 em { font-style: normal; color: var(--accent-soft); }
.hero__lead { margin: 0 0 32px; max-width: 46ch; font-size: 17px; color: var(--on-muted); }
.hero__cta { display: flex; flex-wrap: wrap; gap: 12px; }

/* --- последний выпуск рядом с заголовком --- */
.feature__label { color: var(--on-faint); margin: 0 0 12px; }
.feature__card {
  position: relative;          /* точка отсчёта для блика */
  display: block; text-decoration: none;
  border: 1px solid var(--glass-line); border-radius: var(--r-xl);
  background: var(--surface-card); overflow: hidden;
  transition: border-color .18s, transform .18s;
}
.feature__card:hover { border-color: rgba(230, 25, 46, .55); transform: translateY(-3px); }
.feature__shot { position: relative; display: block; aspect-ratio: 16 / 9; background: var(--surface-low); }
.feature__shot img { width: 100%; height: 100%; object-fit: cover; }
.feature__play {
  position: absolute; inset: 0; margin: auto;
  width: 62px; height: 62px; border-radius: 50%;
  display: grid; place-items: center;
  background: rgba(230, 25, 46, .92); color: #fff;
  font-size: 21px; padding-left: 4px;
  box-shadow: 0 0 26px rgba(230, 25, 46, .45);
  transition: transform .18s;
}
.feature__card:hover .feature__play { transform: scale(1.08); }
.feature__body { display: flex; flex-direction: column; gap: 6px; padding: 20px 22px 22px; }
/* Кнопка вместо ссылки: у неё своя ширина и своё выравнивание текста. */
.feature__card--locked { width: 100%; text-align: left; font: inherit; color: inherit; }
.feature__title { font: 700 22px/1.25 var(--display); }
.feature__body .card__meta { margin-top: 8px; padding-top: 0; }

/*
 * Наклон карточки за курсором. Сами углы пишет rednik.js инлайном, здесь
 * только то, что от них не зависит.
 *
 * На время ведения transform из перехода убираем: с задержкой .18s карточка
 * тянулась бы за курсором с отставанием. Возврат в исходное, наоборот, идёт
 * переходом — класс снимается раньше, чем стирается инлайновый transform.
 */
.feature__card.is-tilting { transition: border-color .18s; will-change: transform; }

/*
 * Блик повторяет приём vanilla-tilt: не пятно под курсором, а длинная светлая
 * полоса, развёрнутая в его сторону. Сторона полосы вдвое больше кадра,
 * поэтому её край не выезжает на видное место ни при каком повороте. Поворот
 * вокруг своего угла, а `translate(-50%, -50%)` после поворота возвращает
 * центр полосы в центр кадра.
 *
 * Лежит внутри `.feature__shot`, не на всей карточке: подпись под кадром
 * блик обесцвечивал. Скругление держит `overflow: hidden` самой карточки.
 */
.feature__glare {
  position: absolute; inset: 0; overflow: hidden;
  border-radius: inherit; pointer-events: none;
}
.feature__glare > span {
  position: absolute; top: 50%; left: 50%; display: block;
  transform-origin: 0 0; opacity: 0;
  background-image: linear-gradient(0deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 100%);
  transition: opacity .18s;
}

/* --- signature: весь архив одной звуковой дорожкой --- */
.track { margin-top: 56px; }
.track__head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 16px; margin-bottom: 12px; color: var(--on-faint);
}
.track__bars {
  display: flex; align-items: flex-end; gap: 2px;
  height: 96px; padding: 0; margin: 0; list-style: none;
  border-bottom: 1px solid var(--glass-line);
  overflow: hidden;
}
.track__bars li { flex: 1 1 0; min-width: 0; display: flex; align-items: flex-end; height: 100%; }
.track__bars a {
  display: block; width: 100%; border-radius: 1px 1px 0 0;
  background: var(--surface-high);
  transition: background .16s;
}
.track__bars a:hover, .track__bars a:focus-visible { background: var(--accent-soft); }
/*
 * Красный в дорожке означает клуб, и только его.
 *
 * Раньше им горела свежая дюжина, но «свежесть» на дорожке и так читается —
 * это правый край. Красное на всю ширину архива теперь показывает то, чего
 * иначе не увидеть: где лежат закрытые выпуски. Их единицы, поэтому цвет
 * работает как метка, а не как заливка.
 *
 * Согласовано с подписью рядом: «10 в клубе» — тоже красная ссылка.
 */
.track__bars li.is-club a { background: var(--accent); }
.track__bars li.is-club a:hover { background: var(--accent-soft); }
/*
 * Столбиков больше трёхсот, а зазоры между ними не сжимаются: на узком
 * экране одни зазоры занимают больше ширины, чем сам экран. Поэтому там
 * показываем каждый третий — рисунок дорожки сохраняется, а столбики
 * остаются видимой толщины.
 */
@media (max-width: 640px) {
  /* Подпись в строку не влезает: «архив студии» ломается пополам, а счёт
     остаётся на огрызке ширины. Ставим друг под друга — счёт получает
     всю строку и на телефоне укладывается целиком. */
  .track__head { flex-direction: column; align-items: flex-start; gap: 6px; }
  .track__bars { height: 64px; gap: 1px; }
  .track__bars li:nth-child(3n+2),
  .track__bars li:nth-child(3n+3) { display: none; }
  /* Клубную полоску прореживание не трогает: она в архиве одна на десяток,
     и попади она в скрытую треть — пропала бы с телефона совсем. */
  .track__bars li.is-club { display: flex; }
}

/* ---------------------------------------------------------------- секции */
.section { padding-block: var(--section); border-top: 1px solid var(--glass-line); }
.section__head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 20px; margin-bottom: 34px; flex-wrap: wrap;
}
.section h2 { margin: 0 0 6px; font: 700 clamp(26px, 3.4vw, 40px)/1.2 var(--display); letter-spacing: -.02em; }
.section__sub { margin: 0; color: var(--on-muted); }
.link-more { color: var(--on-muted); text-decoration: none; white-space: nowrap; }
.link-more:hover { color: var(--accent-soft); }

/* ---------------------------------------------------------------- карточки */
.grid { display: grid; gap: var(--gutter); grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); }
@media (max-width: 640px) { .grid { grid-template-columns: 1fr; } }

.card {
  display: flex; flex-direction: column;
  background: var(--surface-card); border: 1px solid var(--glass-line);
  border-radius: var(--r-lg); overflow: hidden; text-decoration: none;
  transition: border-color .18s, transform .18s;
}
.card:hover { border-color: rgba(230, 25, 46, .5); transform: translateY(-3px); }
.card__shot { position: relative; aspect-ratio: 16 / 9; background: var(--surface-low); }
.card__shot img { width: 100%; height: 100%; object-fit: cover; }
.card__chip {
  position: absolute; left: 12px; top: 12px;
  padding: 6px 10px; border-radius: 999px;
  background: rgba(26, 10, 9, .72); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
  border: 1px solid var(--glass-line); color: var(--on-surface);
}
.card__time {
  position: absolute; right: 12px; bottom: 12px;
  padding: 5px 9px; border-radius: var(--r-sm);
  background: rgba(0, 0, 0, .68); color: var(--on-surface);
  font: 500 12px/1 var(--mono);
}
.card__body { padding: 18px; display: flex; flex-direction: column; gap: 6px; flex: 1; }
.card__title { margin: 0; font: 700 19px/1.3 var(--display); }
.card__ep { color: var(--accent-soft); font: 500 13px/1 var(--mono); letter-spacing: .06em; }
.card__meta { margin-top: auto; padding-top: 12px; color: var(--on-faint); font-size: 13px; display: flex; gap: 14px; }

/*
 * Закрытая карточка. Обложка уходит под блюр, поэтому она приходит
 * в 480px — крупнее незачем. Масштаб 1.06 нужен, чтобы размытие
 * не подмешивало прозрачность у краёв и они не выцветали.
 */
.card--locked {
  /* .card рисовалась под ссылку, у кнопки свои умолчания. */
  appearance: none;
  border: 1px solid var(--glass-line);
  background: var(--surface-card);
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
  width: 100%;
}
/*
 * Тизера у трети постов нет — показывать нечего. Плашка-заглушка идёт
 * фоном, а не псевдоэлементом: абсолютный ::before рисовался бы ПОВЕРХ
 * статичной картинки и прятал бы её. Фон же виден ровно тогда, когда
 * картинки нет, — она накрывает блок целиком через object-fit: cover.
 */
.card--locked .card__shot {
  /*
   * Основа — цвет самой карточки, а не более тёмный surface-low. Края
   * картинки растворяются именно в него, и любой другой оттенок под ними
   * проступал бы тёмным прямоугольником. Особенно у трети постов,
   * где тизера нет вовсе и видна одна эта подложка.
   */
  background:
    radial-gradient(120% 90% at 50% 0%, rgba(230, 25, 46, .20), transparent 72%),
    var(--surface-card);
}
/*
 * Запас под размытие. Фильтр подмешивает прозрачность из-за границы
 * элемента, и без запаса внешняя полоса картинки выцветает, обнажая фон:
 * получается тёмная рамка с жёсткими углами и кромкой по краям.
 *
 * Той же граблёй болел фон из лучей, там она лечится вылетом на 64px.
 * scale(1.06) давал вылет пропорционально: 11px по горизонтали
 * и всего 6px по вертикали при радиусе размытия 14px. Мало.
 *
 * Здесь вылет одинаковый со всех сторон и с двойным запасом.
 */
.card--locked .card__shot {
  overflow: hidden;   /* иначе размытие вылезет на текст карточки */
}
.card--locked .card__shot img {
  position: absolute;
  top: -32px; left: -32px;
  width: calc(100% + 64px);
  height: calc(100% + 64px);
  object-fit: cover;
  filter: blur(14px) saturate(.75) brightness(.7);
}
.card--locked .card__shot::after {
  content: "";
  position: absolute;
  inset: 0;
  /*
   * Растворяем картинку в карточке со всех четырёх сторон, а не только снизу:
   * иначе размытое пятно всё равно кончается прямоугольником, и видно рамку.
   *
   * Цвет краёв — surface-card, тот же, что у тела карточки. Прозрачный конец
   * задан тем же цветом с нулевой альфой, а не ключевым словом transparent:
   * так гарантированно нет серой мути на переходе.
   *
   * Низ растворяется дальше остальных: под ним подпись, и граница там
   * заметнее всего. Бока уже — им нельзя съедать картинку.
   */
  background:
    linear-gradient(180deg, var(--surface-card) 0%, rgba(41, 23, 22, 0) 20%),
    linear-gradient(0deg,   var(--surface-card) 0%, rgba(41, 23, 22, 0) 38%),
    linear-gradient(90deg,  var(--surface-card) 0%, rgba(41, 23, 22, 0) 13%),
    linear-gradient(270deg, var(--surface-card) 0%, rgba(41, 23, 22, 0) 13%),
    linear-gradient(180deg, rgba(26, 10, 9, .18), rgba(26, 10, 9, .5));
}
.card__lock {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  color: var(--accent-soft);
  z-index: 1;
}
.card__chip--club {
  z-index: 1;
  color: #fff;
  background: var(--accent);
  border-color: transparent;
  letter-spacing: .1em;
}
.card__locknote { color: var(--accent-soft); }
.card--locked:hover { border-color: rgba(230, 25, 46, .5); transform: translateY(-3px); }
.card--locked:focus-visible { outline: 2px solid var(--accent-soft); outline-offset: 3px; }

/* ---------------------------------------------------------------- поддержка */
.support { display: grid; gap: var(--gutter); grid-template-columns: 1.25fr 1fr; align-items: start; }
@media (max-width: 900px) { .support { grid-template-columns: 1fr; } }

.panel {
  background: var(--surface-card); border: 1px solid var(--glass-line);
  border-radius: var(--r-xl); padding: 30px;
}
.panel--club { background: linear-gradient(160deg, var(--surface-high), var(--surface-low)); }
.panel h3 { margin: 0 0 14px; font: 700 24px/1.3 var(--display); }

.perks { list-style: none; margin: 0 0 26px; padding: 0; display: grid; gap: 12px; }
.perks li { display: flex; gap: 11px; align-items: flex-start; color: var(--on-muted); }
.perks li::before {
  content: ""; flex: none; width: 6px; height: 6px; margin-top: 9px;
  border-radius: 50%; background: var(--accent);
}
.price { display: flex; align-items: baseline; gap: 9px; margin-bottom: 20px; }
/* Строка про площадки жмётся к цене, поэтому отступ цены переезжает на неё. */
.price:has(+ .pay-note) { margin-bottom: 7px; }
.pay-note { margin: 0 0 22px; color: var(--on-faint); font-size: 14px; }
.price b { font: 900 44px/1 var(--display); letter-spacing: -.03em; }
.price span { color: var(--on-muted); }

.goal { margin-top: 26px; }
.goal__bar { height: 8px; border-radius: 999px; background: var(--surface-low); overflow: hidden; margin: 12px 0 9px; }
.goal__fill { height: 100%; border-radius: 999px; background: linear-gradient(90deg, var(--accent), var(--accent-soft)); }
.goal__nums { display: flex; justify-content: space-between; color: var(--on-muted); font-size: 14px; }

.ways { display: grid; gap: 10px; }

/*
 * Кнопки способов поддержки. По мотивам Gradient Button (kokonutui.com, MIT).
 *
 * Оригинал набран на Tailwind из шести вложенных div-ов. Здесь то же самое
 * собрано слоями на одном элементе, поэтому разметку почти не тронули —
 * добавился только модификатор, который подставляет цвета бренда.
 *
 * Заливка остаётся тёмной, фирменный цвет держат рамка, свечение и название.
 * Заливать кнопку брендом целиком нельзя: четыре чужих логотипа рядом
 * рассыпали бы блок на лоскуты и перебили студийный красный.
 */
.way {
  position: relative;
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  padding: 15px 18px;
  border: 1px solid transparent;
  border-radius: var(--r-md);
  text-decoration: none;
  isolation: isolate;
  /*
   * Градиентная рамка. Обычному border градиент задать нельзя, поэтому
   * два слоя фона: нижний красит border-box, верхний закрывает padding-box.
   */
  background:
    linear-gradient(var(--surface-low), var(--surface-low)) padding-box,
    linear-gradient(150deg, var(--brand), rgba(0, 0, 0, 0) 45%, var(--brand-deep)) border-box;
  box-shadow: inset 0 0 14px -4px var(--brand-glow);
  transition: box-shadow .25s, transform .25s;
}
.way::before,
.way::after {
  content: ""; position: absolute; inset: 0; z-index: 0;
  border-radius: calc(var(--r-md) - 1px);
  pointer-events: none;
}
/* Постоянное свечение снизу — то, что в оригинале даёт слой accent. */
.way::before {
  background: radial-gradient(130% 150% at 50% 130%, var(--brand-glow), transparent 68%);
}
/* Поперечная подсветка, проявляется на наведении. В оригинале это слой hover. */
.way::after {
  background: linear-gradient(90deg, transparent, var(--brand-glow), transparent);
  opacity: 0; transition: opacity .3s;
}
.way:hover::after, .way:focus-visible::after { opacity: 1; }
.way:hover { box-shadow: inset 0 0 18px -2px var(--brand-glow); transform: translateY(-1px); }

.way b, .way span { position: relative; z-index: 1; }
.way b { font: 700 16px/1 var(--display); color: var(--brand-text); }
/*
 * Название градиентом. Под color: transparent текст пропадает там, где
 * background-clip не поддержан, поэтому включаем только через @supports.
 */
@supports (background-clip: text) or (-webkit-background-clip: text) {
  .way b {
    background: linear-gradient(180deg, var(--brand-text), var(--brand));
    -webkit-background-clip: text; background-clip: text;
    color: transparent;
    filter: drop-shadow(0 0 9px var(--brand-glow));
  }
}
.way span { color: var(--on-faint); font-size: 13px; }

/* Цвета сняты со страниц самих сервисов, а не подобраны на глаз. */
.way--boosty { --brand: #f15f2c; --brand-deep: #b23c15; --brand-text: #ffb08e; --brand-glow: rgba(241,  95,  44, .30); }
.way--vk     { --brand: #0077ff; --brand-deep: #0047a8; --brand-text: #8fc2ff; --brand-glow: rgba(  0, 119, 255, .32); }
.way--tg     { --brand: #2aabee; --brand-deep: #1b7fb5; --brand-text: #9bdcfa; --brand-glow: rgba( 42, 171, 238, .30); }

/* ---------------------------------------------------------------- заказ */
.order { display: grid; gap: var(--gutter); grid-template-columns: 1.1fr .9fr; align-items: start; }
@media (max-width: 900px) { .order { grid-template-columns: 1fr; } }

.note { color: var(--on-muted); font-size: 14px; margin: 0; }

/* Кнопки связи в блоке заказа: в столбик, чтобы обе были одинаково заметны. */
.contacts { display: grid; gap: 10px; }

/* «Как это работает» — шаги заказа. Номера набраны моноширинным,
   как и остальные служебные подписи на сайте. */
.how__title {
  margin: 20px 0 12px; color: var(--on-muted);
  font: 500 12px/1 var(--mono); letter-spacing: .08em; text-transform: uppercase;
}
.how { list-style: none; margin: 0; padding: 0; counter-reset: how; display: grid; gap: 11px; }
.how li {
  counter-increment: how;
  display: grid; grid-template-columns: 26px 1fr; gap: 12px; align-items: start;
  color: var(--on-muted); font-size: 14px; line-height: 1.55;
}
.how li::before {
  content: counter(how);
  display: grid; place-items: center;
  width: 26px; height: 26px; border-radius: 50%;
  background: var(--surface-low); border: 1px solid var(--glass-line);
  color: var(--accent-soft); font: 500 13px/1 var(--mono);
}

/* ------------------------------------------ колода постеров под подпиской */
/*
 * Два состояния. Основа — ряд постеров: так блок выглядит без скрипта
 * и при выключенном движении, видно всё сразу и каждый постер кликабелен.
 * Скрипт вешает на обёртку `is-deck` и превращает ряд в стопку с
 * перетаскиванием. Всё, что зависит от номера карточки, скрипт пишет
 * инлайном — здесь только общее.
 */
.deck__label { color: var(--on-faint); margin: 0 0 14px; }
.deck__stack { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.deck__card {
  position: relative; display: block; overflow: hidden;
  aspect-ratio: 480 / 679;
  border: 1px solid var(--glass-line); border-radius: var(--r-lg);
  background: var(--surface-low); text-decoration: none; color: inherit;
}
.deck__poster { display: block; width: 100%; height: 100%; object-fit: cover; }

/*
 * Подпись поверх постера: на самих постерах названия корейские.
 * Затемнение до плотного низа и с запасом по высоте — под подписью
 * оказывается корейский текст, и на слабой заливке счётчик выпусков
 * в него утыкался.
 */
.deck__cap {
  position: absolute; inset: auto 0 0 0;
  display: flex; flex-direction: column; gap: 3px;
  padding: 76px 14px 13px;
  /*
   * Плотная часть держится до 46 % высоты и только выше уходит в ноль.
   * Пробовал ровный переход от .97 к нулю — на высоте названия он давал
   * уже около .4, и корейский заголовок постера лез сквозь русский.
   */
  background: linear-gradient(to top,
    rgba(10, 6, 7, .98) 0%, rgba(10, 6, 7, .96) 46%,
    rgba(10, 6, 7, .5) 72%, rgba(10, 6, 7, 0) 100%);
}
.deck__cap b { font: 700 15px/1.25 var(--display); }
.deck__cap span { color: var(--on-faint); font-size: 12px; }

/* --- стопка --- */
/*
 * Ширину держит вся колода целиком, а не одна стопка: иначе заголовок
 * и стрелки расходятся с постерами по краям.
 *
 * Ширина задана явно, а не через max-width. Колода — элемент грида,
 * и там `margin-inline: auto` отменяет растягивание: с одним только
 * max-width блок съезжает на ширину содержимого, у нас вышло 128px.
 */
.deck.is-deck { width: min(100%, 296px); margin-inline: auto; }
.deck.is-deck .deck__stack {
  display: block; position: relative;
  /*
   * Уже колоды: задние карточки уходят вправо и должны уместиться в те же
   * 296px, что и полоски под ними. Иначе стопка вылезала бы за них вбок.
   */
  width: calc(100% - 40px);
  aspect-ratio: 480 / 679;
  /*
   * Забираем себе только горизонтальный жест. Со своим `none`, как у плашки,
   * страница перестала бы прокручиваться пальцем прямо по колоде, а она
   * занимает пол-экрана на мобильной.
   */
  touch-action: pan-y;
  -webkit-user-select: none; user-select: none;
}
.deck.is-deck .deck__card {
  position: absolute; inset: 0;
  box-shadow: 0 20px 44px -20px rgba(0, 0, 0, .85);
  transition: transform .34s cubic-bezier(.22, .61, .36, 1), opacity .34s;
}
/* На время ведения переход снимаем: иначе карточка тянется за пальцем
   с отставанием — та же история, что с наклоном в герое. */
.deck.is-deck .deck__stack.is-dragging .deck__card { transition: none; }

/*
 * Листалка — полоски, а не кружки со стрелками. Тот же приём, что в дорожке
 * архива вверху страницы: узкая полоса, краснеющая при наведении. Заодно
 * решает и то, чего стрелки не умели, — попасть сразу в нужное шоу.
 *
 * Сама полоса 3px, но кнопка вокруг неё 14px: в три пикселя мышью не попасть.
 */
.deck__nav { display: flex; gap: 4px; margin-top: 14px; }
.deck__seg {
  position: relative; flex: 1 1 0;
  height: 14px; padding: 0; border: 0; cursor: pointer;
  background: transparent;
}
.deck__seg::before {
  content: ''; position: absolute; inset: 50% 0 auto; transform: translateY(-50%);
  height: 3px; border-radius: 2px;
  background: var(--surface-high); transition: background .18s;
}
.deck__seg:hover::before { background: var(--accent-soft); }
.deck__seg.is-on::before { background: var(--accent); }

/* ---------------------------------------------------------------- архив */
.filters { display: flex; flex-wrap: wrap; gap: 9px; margin-bottom: 18px; }
.chip {
  padding: 9px 16px; border-radius: 999px; cursor: pointer;
  background: transparent; border: 1px solid var(--glass-line); color: var(--on-muted);
  font: 500 12px/1 var(--mono); letter-spacing: .08em; text-transform: uppercase;
  transition: border-color .18s, color .18s, background .18s;
}
.chip:hover { color: var(--on-surface); border-color: var(--on-faint); }
.chip[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: #fff; }

.search { position: relative; max-width: 340px; width: 100%; }
.search input {
  width: 100%; padding: 12px 16px; border-radius: 999px;
  background: var(--surface-low); border: 1px solid var(--glass-line);
  color: var(--on-surface); font: 400 15px/1.4 var(--body);
}
.search input:focus { outline: none; border-color: var(--accent); }

.toolbar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 26px; }
.count { color: var(--on-faint); font: 500 12px/1 var(--mono); letter-spacing: .08em; text-transform: uppercase; }
.empty { padding: 60px 0; text-align: center; color: var(--on-muted); }

/* ---------------------------------------------------------------- подвал */
.foot { border-top: 1px solid var(--glass-line); padding-block: 40px; color: var(--on-faint); }
.foot__in { display: flex; flex-wrap: wrap; align-items: center; gap: 18px 28px; }
.foot nav { display: flex; flex-wrap: wrap; gap: 20px; margin-inline: auto; }
.foot a { color: var(--on-muted); text-decoration: none; }
.foot a:hover { color: var(--accent-soft); }
.foot__sync { font: 500 11px/1 var(--mono); letter-spacing: .08em; text-transform: uppercase; }
@media (max-width: 700px) { .foot nav { margin-inline: 0; width: 100%; } }

/*
 * Плашка снизу. Порт smooth-drawer с kokonutui.
 * Оригинал держится на Vaul и Framer Motion; здесь родной <dialog>
 * и CSS-анимация. Пружину оригинала (stiffness 300, damping 30)
 * подменяет cubic-bezier с небольшим перелётом.
 */
.drawer {
  border: 0;
  padding: 0;
  background: transparent;
  /*
   * Цвет задаём явно. Браузер в своих стилях ставит <dialog> собственный
   * color: CanvasText — чёрный, — и он перебивает наследование от body.
   * Без этой строки заголовок и цена внутри плашки выходили чёрными
   * по чёрному, а заметно это только там, где цвет не задан своим правилом.
   */
  color: var(--on-surface);
  max-width: 100%;
  max-height: 100%;
  width: 100%;
  margin: auto auto 0;   /* прижата к низу */
  overflow: visible;
}
.drawer::backdrop { background: rgba(12, 5, 5, .72); }
/* То же и для самой плашки: жест по подложке не должен дёргать страницу. */
.drawer { overscroll-behavior: contain; }

.drawer__sheet {
  position: relative;
  margin: 0 auto;
  width: min(28rem, 100%);
  padding: 14px 24px 28px;
  border: 1px solid var(--glass-line);
  border-bottom: 0;
  border-radius: var(--r-xl) var(--r-xl) 0 0;
  background: var(--surface-card);
  box-shadow: 0 -24px 60px rgba(0, 0, 0, .55);
  max-height: 88vh;
  overflow-y: auto;
  /*
   * Цепочку прокрутки наружу не пускаем. Без этого Chrome на Android
   * принимает потягивание вниз за pull-to-refresh и перезагружает страницу
   * прямо из-под открытой плашки — смахивание становится невозможным.
   */
  overscroll-behavior: contain;
  /*
   * Совсем низкое окно — ниже 389 пикселей — прокрутку всё же включает.
   * Системная полоса в такой плашке выглядит деталью чужого интерфейса,
   * поэтому она тонкая и в цвет.
   */
  scrollbar-width: thin;
  scrollbar-color: var(--on-faint) transparent;
  /*
   * Запасное значение. Настоящее ставит скрипт при открытии: если
   * содержимое влезает целиком (а оно влезает почти всегда), жест
   * забираем себе полностью через touch-action: none.
   */
  touch-action: pan-y;
}

.drawer__grip {
  width: 44px; height: 4px;
  margin: 0 auto 16px;
  border-radius: 999px;
  background: var(--on-faint);
}
.drawer__close {
  position: absolute; top: 12px; right: 14px;
  width: 34px; height: 34px;
  border: 0; border-radius: 50%;
  background: var(--glass); color: var(--on-muted);
  font-size: 22px; line-height: 1; cursor: pointer;
}
.drawer__close:hover { color: var(--on-surface); }

.drawer__row  { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; }
.drawer__row .card__chip { position: static; }
.drawer__sub  { color: var(--accent-soft); font-size: 13px; letter-spacing: .06em; }
.drawer__title{ margin: 0 0 10px; font: 700 24px/1.25 var(--display); }
.drawer__text { margin: 0 0 18px; color: var(--on-muted); font-size: 15px; line-height: 1.5; }
.drawer__price{ margin: 0 0 20px; font: 700 32px/1 var(--display); }
.drawer__price span { font: 400 15px/1 var(--body); color: var(--on-muted); }
/* Пути подписки внутри плашки — те же плашки способов, что в блоке поддержки:
   цвета площадок уже написаны, и повторять их здесь незачем. */

/*
 * Низкое окно: плашка ужимается, а не прячет нижний путь под прокрутку.
 *
 * С тремя путями лист вырос с ~322 до 418 пикселей, и при max-height: 88vh
 * он перестаёт влезать уже на 475 пикселях высоты окна — а это обычный
 * ноутбук с открытыми панелями. Прокрутка внутри есть, но её не видно:
 * плашка выглядит законченной, и последний путь просто срезан пополам.
 * Порог с запасом: ужатый лист — 346 пикселей, хватает до 394.
 */
@media (max-height: 560px) {
  .drawer__sheet { padding-top: 10px; padding-bottom: 18px; }
  .drawer__grip  { margin-bottom: 10px; }
  .drawer__row   { margin-bottom: 10px; }
  .drawer__title { font-size: 20px; }
  .drawer__text  { margin-bottom: 12px; font-size: 14px; }
  .drawer__price { margin-bottom: 14px; font-size: 26px; }
  .drawer .ways  { gap: 8px; }
  .drawer .way   { padding: 11px 16px; }
}

/* Выезд снизу с лёгким наклоном — как в оригинале. */
@keyframes drawer-in {
  from { transform: translateY(100%) rotateX(5deg); opacity: 0; }
  to   { transform: translateY(0)    rotateX(0);    opacity: 1; }
}
@keyframes drawer-item {
  from { transform: translateY(20px); opacity: 0; }
  to   { transform: translateY(0);    opacity: 1; }
}
/*
 * Вход играется РОВНО ОДИН РАЗ: класс is-opening скрипт снимает,
 * когда лесенка доиграла.
 *
 * Грабля, стоившая всей мобильной версии. Раньше анимация висела
 * на `.drawer[open]`, а `.is-dragging` гасил её через `animation: none
 * !important`. Снятие этого класса на pointerup ЗАПУСКАЛО анимацию заново
 * с первого кадра — лист уезжал на свои 100% вниз, за пределы экрана.
 * Клик после этого попадал в подложку и закрывал плашку, а до ссылок
 * не доходил вовсе. На телефоне каждое касание перезапускало выезд.
 *
 * Отсюда правило: ничто не должно менять свойство animation у листа
 * после открытия. Перетаскивание двигает лист только инлайновым transform.
 */
.drawer__sheet { transform-origin: bottom center; }
.drawer__sheet.is-opening { animation: drawer-in .42s cubic-bezier(.22, 1.2, .36, 1) both; }

/* Лесенка: задержка 200 мс, шаг 70 мс — значения оригинала. */
.drawer__sheet.is-opening .drawer__row,
.drawer__sheet.is-opening .drawer__title,
.drawer__sheet.is-opening .drawer__text,
.drawer__sheet.is-opening .drawer__price,
.drawer__sheet.is-opening .ways {
  animation: drawer-item .34s cubic-bezier(.22, 1, .36, 1) both;
}
.drawer__sheet.is-opening .drawer__row   { animation-delay: .20s; }
.drawer__sheet.is-opening .drawer__title { animation-delay: .27s; }
.drawer__sheet.is-opening .drawer__text  { animation-delay: .34s; }
.drawer__sheet.is-opening .drawer__price { animation-delay: .41s; }
.drawer__sheet.is-opening .ways          { animation-delay: .48s; }

/* Пока палец тянет, переход мешает — двигаем напрямую. Анимацию не трогаем. */
.drawer__sheet.is-dragging  { transition: none; }
.drawer__sheet.is-returning { transition: transform .3s cubic-bezier(.22, 1, .36, 1); }

/*
 * Движение выключено — плашка появляется сразу. Смахивание остаётся:
 * это прямое управление, а не украшение. Общее правило вверху файла
 * уже гасит длительности, здесь снимаем и сдвиг с прозрачностью,
 * иначе содержимое мигнёт.
 */
@media (prefers-reduced-motion: reduce) {
  .drawer__sheet.is-opening,
  .drawer__sheet.is-opening .drawer__row,
  .drawer__sheet.is-opening .drawer__title,
  .drawer__sheet.is-opening .drawer__text,
  .drawer__sheet.is-opening .drawer__price,
  .drawer__sheet.is-opening .drawer__acts { animation: none; opacity: 1; }
}

@media (min-width: 640px) {
  .drawer__sheet { border-bottom: 1px solid var(--glass-line); }
}

/* Чип клуба отличается от разделов: за ним не раздел каталога, а подписка. */
.chip--club[aria-pressed="false"] { color: var(--accent-soft); border-color: rgba(230, 25, 46, .45); }

/* Ссылка на клуб в дорожке архива. Клаузу не рвём: перенос внутри
   «9 в клубе» разрывал и фразу, и подчёркивание. */
.track__more { white-space: nowrap; }
.track__club { color: var(--accent-soft); text-decoration: none; border-bottom: 1px solid rgba(255, 179, 174, .35); }
.track__club:hover { color: var(--on-surface); }
