/* ==========================================================================
   VPEsports Hub — стили темы

   Перенос из React-проекта vpesports-game-hub (Tailwind v4 → рукописный CSS).
   Значения токенов скопированы дословно из src/styles.css, поэтому цвета,
   радиусы и градиенты совпадают с оригиналом точно.

   Порядок разделов:
     1. Шрифт
     2. Токены и утилиты дизайн-системы
     3. Сброс и база
     4. Каркас страницы
     5. Шапка
     6. Сайдбар
     7. Hero
     8. Popular Games
     9. Ряды игр
    10. Daily Challenge
    11. VPE Originals
    12. Leaderboards
    13. Подвал
    14. Адаптив
   ========================================================================== */

/* ── 1. Шрифт Outfit (SIL OFL), файл лежит в теме ────────────────────────── */

/*
 * Один файл на все начертания.
 *
 * Раньше здесь стояло шесть правил на шесть файлов — outfit-400 … outfit-900.
 * Все шесть файлов были байт в байт одинаковыми (MD5 FDF9C50…4A8D, по 32 292
 * байта каждый): это один и тот же вариативный Outfit, скопированный шесть раз
 * под разными именами. Браузер честно скачивал пять копий одного файла —
 * 163 КБ вместо 32 КБ, и все пять с приоритетом VeryHigh, то есть впереди
 * картинки первого экрана.
 *
 * Диапазон 100–900 в одном правиле даёт ровно те же начертания: ось wght у
 * файла на месте (таблица fvar присутствует), браузер инстанцирует нужный вес
 * сам. Ширины строки на весах 400…900 после замены совпадают с прежними
 * до сотых пикселя — проверено измерением в браузере.
 */
@font-face {
	font-family: "Outfit";
	font-style: normal;
	font-weight: 100 900;
	font-display: swap;
	src: url("../fonts/outfit-variable.woff2") format("woff2");
}

/* ── 2. Токены дизайн-системы ────────────────────────────────────────────── */

:root {
	/*
	 * Тёмная база осталась прежней. Акцент переведён с фиолетового на
	 * янтарный: пара «малиновый + янтарь» — это цвета аркадного автомата,
	 * они держат тёмный фон и не превращают интерфейс в дежурный
	 * розово-фиолетовый градиент, которым выглядит половина игровых
	 * шаблонов. Холодный тон остался ровно один и только для метки New —
	 * чтобы «горячее» и «новое» не читались одним пятном.
	 */
	--background: oklch(0.13 0.02 275);
	--foreground: oklch(0.97 0.005 275);
	--surface: oklch(0.16 0.025 275);
	--surface-2: oklch(0.21 0.03 275);
	--card: oklch(0.17 0.025 275);
	--card-foreground: oklch(0.97 0.005 275);
	--primary: oklch(0.62 0.235 22);
	--primary-foreground: oklch(0.99 0 0);

	/*
	 * Два малиновых, а не один, — и это не расползание палитры, а
	 * арифметика. Один и тот же красный работает в теме в двух ролях:
	 * как ТЕКСТ на тёмном фоне (активный пункт шапки, стрелка «дальше»)
	 * и как ЗАЛИВКА под белым текстом (кнопка Play, активный фильтр).
	 * Требования у этих ролей противоположные: чтобы поднять контраст с
	 * белым, красный надо гасить, а чтобы поднять контраст с фоном —
	 * наоборот высветлять. Замер на oklch(_ 0.235 22):
	 *
	 *   L      белый текст на нём   он текстом на --background
	 *   0.62   3.98  ✗              4.91  ✓   (было: провал по кнопкам)
	 *   0.595  4.40  ✗              4.42  ✗   (лучший общий — не проходит)
	 *   0.575  4.82  ✓              4.06  ✗
	 *
	 * Одного значения, проходящего 4.5:1 в обеих ролях, не существует:
	 * ровно поэтому Accessibility держался на 96. Роли разведены по
	 * токенам. --primary остаётся цветом-акцентом и цветом текста,
	 * --primary-solid* красит поверхности, на которых лежит белый текст.
	 */
	--primary-solid: oklch(0.575 0.235 22);
	--primary-solid-hover: oklch(0.545 0.235 22);
	--primary-solid-active: oklch(0.515 0.235 22);
	--secondary: oklch(0.24 0.035 275);
	--muted: oklch(0.24 0.035 275);
	--muted-foreground: oklch(0.68 0.02 275);
	--accent: oklch(0.78 0.16 68);
	--accent-foreground: oklch(0.22 0.05 60);
	--online: oklch(0.75 0.19 145);
	--danger: oklch(0.68 0.2 25);
	--border: oklch(0.3 0.035 275);
	--input: oklch(0.3 0.035 275);
	--ring: oklch(0.62 0.235 22);

	/* Поверхности интерактивных элементов — один набор на всю тему. */
	--layer-1: rgba(255, 255, 255, .04);
	--layer-2: rgba(255, 255, 255, .08);
	--layer-3: rgba(255, 255, 255, .12);
	--line-1: rgba(255, 255, 255, .10);
	--line-2: rgba(255, 255, 255, .25);

	/* Шаг отступов: 4px. Секции и сетки берут значения только отсюда. */
	--sp-1: .25rem;
	--sp-2: .5rem;
	--sp-3: .75rem;
	--sp-4: 1rem;
	--sp-5: 1.25rem;
	--sp-6: 1.5rem;
	--sp-8: 2rem;
	--sp-10: 2.5rem;
	--sp-12: 3rem;

	/* Радиусы: чип, контрол, карточка, панель, баннер. */
	--radius: 0.625rem;
	--r-xs: 8px;
	--r-sm: 12px;
	--r-md: 16px;
	--r-lg: 20px;
	--r-xl: 28px;
	--r-pill: 999px;

	/* Типографическая шкала. */
	--fs-xs: .75rem;
	--fs-sm: .8125rem;
	--fs-base: .9375rem;
	--fs-md: 1rem;
	--fs-lg: 1.25rem;
	--fs-h3: 1.25rem;
	--fs-h2: 1.5rem;
	--fs-h1: 2rem;

	/* Ширина колонки контента и тач-цель. */
	--content-max: 1680px;
	--tap: 44px;

	/* Тени: одна шкала, окрашена в primary, а не в случайный фиолетовый. */
	--sh-1: 0 8px 24px -14px oklch(0.62 0.235 22 / .5);
	--sh-2: 0 16px 38px -18px oklch(0.62 0.235 22 / .55);
	--sh-3: 0 24px 56px -24px oklch(0.62 0.235 22 / .6);

	/* Плавность из компонентов: EASE = cubic-bezier(.22,1,.36,1) и (.2,.8,.2,1) */
	--ease: cubic-bezier(.22, 1, .36, 1);
	--ease-2: cubic-bezier(.2, .8, .2, 1);

	/*
	 * Градиенты остались только там, где это заливка метки или декоративная
	 * полоска. Кнопки, активные пункты меню и заголовки красятся сплошным
	 * цветом: градиент на управляющем элементе съедает контраст текста и
	 * ровно он и читается как «сделано нейросетью».
	 */
	--grad-neon: linear-gradient(100deg, oklch(0.62 0.235 22), oklch(0.72 0.19 45) 60%, oklch(0.8 0.16 75));
	--grad-brand: linear-gradient(100deg, oklch(0.62 0.235 22), oklch(0.72 0.19 45));
	--grad-hot: linear-gradient(100deg, oklch(0.74 0.18 55), oklch(0.63 0.24 25));
	--grad-top: linear-gradient(100deg, oklch(0.75 0.16 65), oklch(0.84 0.15 85));
	--grad-updated: linear-gradient(100deg, oklch(0.72 0.13 215), oklch(0.82 0.12 195));
	--grad-originals: linear-gradient(100deg, oklch(0.58 0.16 250), oklch(0.66 0.14 225));

	color-scheme: dark;
}

/* Утилиты, перенесённые из @utility исходного проекта. */

.u-grad-neon { background-image: var(--grad-neon); }

.u-glow-primary {
	background-image: radial-gradient(closest-side, color-mix(in oklab, var(--primary) 45%, transparent), transparent);
}

.u-shine {
	background-image: linear-gradient(90deg, transparent, color-mix(in oklab, white 35%, transparent), transparent);
}

.u-shadow-glow {
	box-shadow: 0 0 0 1px color-mix(in oklab, var(--primary) 25%, transparent),
		0 8px 30px -8px color-mix(in oklab, var(--primary) 55%, transparent);
}

.u-scroll-neon {
	scrollbar-width: thin;
	scrollbar-color: color-mix(in oklab, var(--primary) 45%, transparent) transparent;
}

.u-scroll-neon::-webkit-scrollbar { width: 6px; height: 6px; }
.u-scroll-neon::-webkit-scrollbar-track { background: transparent; }

.u-scroll-neon::-webkit-scrollbar-thumb {
	border-radius: 999px;
	background: linear-gradient(180deg,
		color-mix(in oklab, var(--primary) 60%, transparent),
		color-mix(in oklab, var(--accent) 60%, transparent));
}

.u-scroll-neon::-webkit-scrollbar-thumb:hover {
	background: linear-gradient(180deg, var(--primary), var(--accent));
}

/* ── 3. Сброс и база ─────────────────────────────────────────────────────── */

*, *::before, *::after { box-sizing: border-box; border-color: var(--border); }

html { -webkit-text-size-adjust: 100%; }

body {
	margin: 0;
	background-color: var(--background);
	color: var(--foreground);
	font-family: "Outfit", ui-sans-serif, system-ui, sans-serif;
	font-size: 16px;
	line-height: 1.5;
	overflow-x: hidden;
}

/*
 * Атрибут hidden сильнее любого display у класса.
 *
 * Без этого правила блок с display: grid или flex оставался на экране,
 * даже когда скрипт ставил ему hidden. Видно это было на странице
 * избранного: карточка сохранённой игры и панель «Nothing saved yet»
 * показывались одновременно. В теме на такие случаи уже было два
 * точечных правила по классу — теперь достаточно одного общего.
 */
[hidden] { display: none !important; }

img, svg { display: block; max-width: 100%; }
img { height: auto; }
button, input { font: inherit; color: inherit; }
button { background: none; border: 0; padding: 0; cursor: pointer; }
a { color: inherit; text-decoration: none; }
h1, h2, h3, h4, p { margin: 0; }

:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; border-radius: 8px; }
:focus:not(:focus-visible) { outline: none; }

.vpe-i { width: 1rem; height: 1rem; flex: none; }

.vpe-skip {
	position: absolute;
	left: -9999px;
	top: 0;
	z-index: 100;
	padding: 12px 18px;
	background: var(--primary-solid);
	color: var(--primary-foreground);
	border-radius: 0 0 12px 0;
}

.vpe-skip:focus { left: 0; }

/* ── 4. Каркас ───────────────────────────────────────────────────────────── */

/*
 * Каркас во всю высоту окна. Подвал лежит внутри колонки контента, и на
 * короткой странице он повисал посередине: ниже оставалась полоса фона
 * в треть экрана. Колонка тянется, подвал уходит вниз — независимо от
 * того, сколько на странице содержимого.
 */
.vpe-shell {
	display: flex;
	flex-direction: column;
	min-height: 100vh;
	background: var(--background);
}

.vpe-layout { display: flex; flex: 1 1 auto; width: 100%; gap: var(--sp-4); }

.vpe-main {
	display: flex;
	flex-direction: column;
	min-width: 0;
	flex: 1 1 0%;
	padding-top: var(--sp-4);

	/* Потолок ширины колонки: без него на 1920 ряд растягивался до восьми
	   карточек в строку и обложки мельчали. */
	max-width: var(--content-max);
}

/* Подвал прижимается к низу, а нижнего отступа под ним больше нет —
   именно он и создавал пустую полосу. */
.vpe-main > .vpe-footer { margin-top: auto; }

/*
 * Отступы секций одинаковые слева и справа.
 *
 * В переносе из React справа стояло padding-right: 0 — «контент прижат к
 * краю». На макете это выглядело приёмом, в браузере — обрезанной сеткой:
 * четвёртая колонка карточек упиралась в край окна без единого пикселя
 * поля, а заголовок секции при этом отступал на 32px. Разные поля слева и
 * справа и есть то самое «элементы не выровнены».
 *
 * Заодно колонка контента получила потолок по ширине: без него на 1920
 * ряд растягивался до восьми карточек в строку и обложки мельчали.
 */
.vpe-pad {
	padding-left: var(--gutter, 1rem);
	padding-right: var(--gutter, 1rem);
}

/*
 * Один отступ на всю колонку контента. Раньше поля секций и поля баннера
 * задавались разными правилами: баннер начинался на 252-м пикселе, а
 * сетка карточек под ним — на 268-м, и вертикальная ось страницы
 * ломалась на первом же экране.
 */
:root { --gutter: 1rem; }

.vpe-hero,
.vpe-footer {
	margin-left: var(--gutter);
	margin-right: var(--gutter);
}


/* ── 5. Шапка ────────────────────────────────────────────────────────────── */

.vpe-header { position: sticky; top: 0; z-index: 50; width: 100%; }

.vpe-header__bar {
	position: relative;
	background: color-mix(in oklab, var(--surface) 85%, transparent);
	backdrop-filter: blur(24px);
}

.vpe-header__edge {
	pointer-events: none;
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	height: 1px;
	opacity: .4;
}

.vpe-header__glow {
	pointer-events: none;
	position: absolute;
	left: -2.5rem;
	top: 0;
	height: 100%;
	width: 20rem;
	opacity: .4;
	filter: blur(64px);
}

.vpe-header__inner {
	position: relative;
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto;
	align-items: center;
	gap: 1rem;
	padding: .75rem 1rem;
}

.vpe-logo {
	display: flex;
	min-width: 0;
	flex-shrink: 0;
	align-items: center;
	justify-content: flex-start;
	gap: .75rem;
}

.vpe-logo__wrap { position: relative; display: block; }

/*
 * Красное свечение за логотипом убрано по решению владельца — и в шапке,
 * и в подвале. Само пятно оставлено в разметке пустым: возвращается
 * одной строкой, если понадобится.
 */
.vpe-logo__glow { display: none; }

/*
 * Картинка не сжимается. В подвале рядом с логотипом стоит название,
 * и flex ужимал изображение по ширине: 101px вместо 141 при исходных
 * 192×60 — знак получался приплюснутым. object-fit тут не помогает,
 * потому что искажается сам бокс.
 */
.vpe-logo__img {
	height: 2.25rem;
	width: auto;
	flex-shrink: 0;
	transition: transform .5s var(--ease);
	/*
	 * Браузер сам ставит svg overflow: hidden, и всё, что не влезло в
	 * viewBox, срезается. Надпись в знаке рисует шрифт: с Outfit она
	 * занимает 186 единиц из 200, запасным шрифтом — 206.9, и «s» в
	 * «Games» отрезало по правому краю. Пока шрифт едет по сети,
	 * обрезанный логотип видит каждый первый посетитель.
	 *
	 * Место в вёрстке по-прежнему занимает viewBox, поэтому на соседей
	 * это не влияет: в шапке до бургера остаётся полтораста пикселей, в
	 * подвале до названия — промежуток в 12px против 5.6px выхода.
	 */
	overflow: visible;
}

.vpe-logo__wrap { flex-shrink: 0; }

.vpe-logo:hover .vpe-logo__img { transform: scale(1.04); }

.vpe-nav { display: none; align-items: center; gap: .25rem; }

.vpe-nav__link {
	position: relative;
	display: flex;
	align-items: center;
	gap: .375rem;
	padding: .625rem .75rem;
	font-size: 13px;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: .08em;
	color: color-mix(in oklab, var(--foreground) 80%, transparent);
	transition: color .3s var(--ease);
}

.vpe-nav__link:hover { color: var(--primary); }

.vpe-nav__link.is-active {
	color: var(--primary);
	text-shadow: 0 0 14px color-mix(in oklab, var(--primary) 55%, transparent);
}

.vpe-nav__link .vpe-i { width: .875rem; height: .875rem; opacity: .6; transition: transform .3s var(--ease); }
.vpe-nav__link:hover .vpe-i { transform: rotate(180deg); }

.vpe-nav__underline {
	pointer-events: none;
	position: absolute;
	bottom: .25rem;
	left: .75rem;
	right: .75rem;
	height: 2px;
	border-radius: 999px;
	background: var(--primary);
	transform: scaleX(0);
	transition: transform .3s var(--ease);
}

.vpe-nav__link:hover .vpe-nav__underline {
	transform: scaleX(1);
	box-shadow: 0 0 12px 2px color-mix(in oklab, var(--primary) 45%, transparent);
}

.vpe-nav__link.is-active .vpe-nav__underline {
	transform: scaleX(1);
	box-shadow: 0 0 12px 2px color-mix(in oklab, var(--primary) 60%, transparent);
}

/* Поиск занимает пространство сразу после меню, а не прижимается к краю:
   при margin-left:auto между меню и поиском оставалось до 300px пустоты,
   и шапка читалась как разъехавшаяся. */
/* Поиск прижат вправо: слева меню, справа кнопки, и пустоты между ними
   больше нет — раньше правая половина шапки простаивала. */
.vpe-search { display: none; width: 100%; max-width: 460px; margin: 0 .75rem 0 auto; }

/* Кнопка отправки нужна для работы без скриптов; на широком экране её
   заменяет Enter, поэтому визуально она не занимает места. */
.vpe-search__go {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	overflow: hidden;
	clip: rect(0 0 0 0);
	white-space: nowrap;
	border: 0;
}

.vpe-search__go:focus-visible {
	position: static;
	width: auto;
	height: auto;
	clip: auto;
	padding: .25rem .625rem;
	border-radius: .5rem;
	background: var(--primary-solid);
	color: #fff;
	font-size: 12px;
	font-weight: 700;
}

/* --- Раздел «Categories» в шапке --- */

.vpe-drop { position: relative; }

.vpe-drop__button {
	cursor: pointer;
	list-style: none;
	user-select: none;
}

.vpe-drop__button::-webkit-details-marker { display: none; }

.vpe-drop__chev {
	display: inline-flex;
	transition: transform .25s var(--ease-2);
}

.vpe-drop__chev .vpe-i { width: .875rem; height: .875rem; }
.vpe-drop[open] .vpe-drop__chev { transform: rotate(180deg); }

/*
 * Три колонки: двенадцать категорий в две вытягивались в длинный
 * столбец, по которому надо было вести глазом сверху вниз. Ширину
 * задаёт содержимое, так что список не съезжает за край экрана —
 * панель прижимается к правому краю кнопки на узких мониторах.
 */
.vpe-drop__panel {
	position: absolute;
	top: calc(100% + .5rem);
	left: 0;
	z-index: 60;
	display: grid;
	grid-template-columns: repeat(3, minmax(8.5rem, 1fr));
	gap: .125rem;
	width: max-content;
	max-width: min(44rem, calc(100vw - 2rem));
	padding: .5rem;
	border-radius: .875rem;
	border: 1px solid var(--border);
	background: color-mix(in oklab, var(--surface) 96%, transparent);
	box-shadow: 0 24px 48px -20px rgba(0, 0, 0, .8);
	backdrop-filter: blur(18px);
}

@media (min-width: 1024px) and (max-width: 1199px) {
	.vpe-drop__panel {
		left: auto;
		right: 0;
	}
}

.vpe-drop__link {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	min-height: 2.25rem;
	padding: .375rem .625rem;
	border-radius: .5rem;
	font-size: 13px;
	font-weight: 600;
	color: var(--muted-foreground);
	transition: background-color .2s var(--ease-2), color .2s var(--ease-2);
}

.vpe-drop__link:hover { background: var(--surface-2); color: var(--foreground); }

.vpe-drop__count {
	font-size: 11px;
	font-variant-numeric: tabular-nums;
	color: color-mix(in oklab, var(--muted-foreground) 70%, transparent);
}

.vpe-drop__all {
	grid-column: 1 / -1;
	display: flex;
	align-items: center;
	justify-content: center;
	gap: .375rem;
	min-height: 2.25rem;
	margin-top: .25rem;
	border-top: 1px solid color-mix(in oklab, var(--border) 60%, transparent);
	padding-top: .5rem;
	font-size: 13px;
	font-weight: 700;
	color: var(--foreground);
}

.vpe-drop__all .vpe-i { width: .875rem; height: .875rem; }

/* --- Кнопки справа в шапке --- */

.vpe-act {
	display: none;
	align-items: center;
	gap: .4375rem;
	min-height: 2.375rem;
	flex-shrink: 0;
	padding: 0 .875rem;
	border-radius: 999px;
	border: 1px solid color-mix(in oklab, var(--border) 70%, transparent);
	background: color-mix(in oklab, var(--surface-2) 60%, transparent);
	font-size: 13px;
	font-weight: 700;
	white-space: nowrap;
	color: var(--foreground);
	transition: transform .2s var(--ease-2), border-color .2s var(--ease-2), background-color .2s var(--ease-2);
}

.vpe-act:hover {
	transform: translateY(-1px);
	border-color: color-mix(in oklab, var(--primary) 55%, transparent);
	background: color-mix(in oklab, var(--surface-2) 90%, transparent);
}

.vpe-act .vpe-i { width: 1rem; height: 1rem; }
.vpe-act:hover .vpe-i { color: var(--primary); }

.vpe-act--ghost { background: transparent; }

.vpe-act__label { display: none; }

.vpe-act__count {
	display: inline-grid;
	place-items: center;
	min-width: 1.25rem;
	height: 1.25rem;
	padding: 0 .3125rem;
	border-radius: 999px;
	background: var(--primary-solid);
	font-size: 11px;
	font-weight: 800;
	font-variant-numeric: tabular-nums;
	color: #fff;
}

.vpe-act__count[hidden] { display: none; }

.vpe-search__box {
	position: relative;
	display: flex;
	align-items: center;
	gap: .75rem;
	border-radius: .75rem;
	border: 1px solid color-mix(in oklab, var(--border) 60%, transparent);
	background: color-mix(in oklab, var(--surface-2) 60%, transparent);
	padding: .625rem 1rem;
	transition: border-color .5s var(--ease), background-color .5s var(--ease), box-shadow .5s var(--ease);
}

.vpe-search__box:hover {
	border-color: color-mix(in oklab, var(--primary) 40%, transparent);
	background: color-mix(in oklab, var(--surface-2) 90%, transparent);
}

.vpe-search__box:focus-within {
	border-color: color-mix(in oklab, var(--primary) 60%, transparent);
	background: var(--surface-2);
	box-shadow: 0 0 0 1px color-mix(in oklab, var(--primary) 25%, transparent),
		0 8px 30px -8px color-mix(in oklab, var(--primary) 55%, transparent);
}

.vpe-search__icon {
	flex: none;
	color: var(--muted-foreground);
	transition: transform .5s var(--ease), color .5s var(--ease);
}

.vpe-search__box:focus-within .vpe-search__icon { transform: scale(1.1); color: var(--primary); }

.vpe-search__input {
	min-width: 0;
	flex: 1;
	background: transparent;
	border: 0;
	outline: none;
	font-size: .875rem;
	color: var(--foreground);
}

.vpe-search__input::placeholder { color: var(--muted-foreground); }

.vpe-search__keys { display: none; flex-shrink: 0; align-items: center; gap: .25rem; }

.vpe-kbd {
	border-radius: .375rem;
	border: 1px solid color-mix(in oklab, var(--border) 80%, transparent);
	background: var(--surface);
	padding: .125rem .375rem;
	font-size: 11px;
	font-weight: 500;
	color: var(--muted-foreground);
}

.vpe-header__actions { display: flex; flex-shrink: 0; align-items: center; gap: .5rem; }

.vpe-burger {
	display: grid;
	place-items: center;
	width: 2.75rem;
	height: 2.75rem;
	border-radius: .75rem;
	border: 1px solid color-mix(in oklab, var(--border) 70%, transparent);
	background: color-mix(in oklab, var(--surface-2) 70%, transparent);
	color: var(--foreground);
}

.vpe-burger .vpe-i { width: 1.25rem; height: 1.25rem; }
.vpe-burger__close { display: none; }
.vpe-burger.is-open .vpe-burger__open { display: none; }
.vpe-burger.is-open .vpe-burger__close { display: block; }

.vpe-mobile {
	overflow: hidden;
	border-top: 1px solid color-mix(in oklab, var(--border) 60%, transparent);
	max-height: 0;
	opacity: 0;
	transition: max-height .5s var(--ease), opacity .5s var(--ease);
}

/*
 * Мобильное меню прокручивается внутри себя.
 *
 * Жёсткие 420px при overflow: hidden обрезали список: содержимое панели
 * набирает 1116px, и четырнадцать пунктов из двадцати одного — весь блок
 * категорий, «Surprise me» и «All categories» — были нарисованы, но
 * недоступны ни пальцем, ни с клавиатуры. Замерено на 390 и 768.
 *
 * Панель ограничена высотой экрана и прокручивается сама, страница под
 * ней при этом не уезжает (overscroll-behavior). Первым идёт запасное
 * значение для браузеров без min().
 */
.vpe-mobile.is-open {
	max-height: 420px;
	max-height: min(80vh, 1200px);
	opacity: 1;
	overflow-x: hidden;
	overflow-y: auto;
	overscroll-behavior: contain;
}

.vpe-mobile__inner { padding: 1rem; display: grid; gap: .75rem; }

.vpe-mobile__search {
	display: flex;
	align-items: center;
	gap: .75rem;
	border-radius: .75rem;
	border: 1px solid color-mix(in oklab, var(--border) 70%, transparent);
	background: color-mix(in oklab, var(--surface-2) 80%, transparent);
	padding: .75rem 1rem;
}

.vpe-mobile__search .vpe-i { color: var(--muted-foreground); }

.vpe-mobile__nav { display: grid; gap: .25rem; }

.vpe-mobile__link {
	border-radius: .5rem;
	padding: .75rem 1rem;
	font-size: .875rem;
	font-weight: 600;
	color: color-mix(in oklab, var(--foreground) 80%, transparent);
	transition: background-color .3s var(--ease), color .3s var(--ease);
}

.vpe-mobile__link:hover { background: var(--surface-2); }

.vpe-mobile__link.is-active {
	background: color-mix(in oklab, var(--primary) 10%, transparent);
	color: var(--primary);
}

/* ── 6. Сайдбар ──────────────────────────────────────────────────────────── */

.vpe-sidebar {
	position: sticky;
	top: 72px;
	display: none;
	height: calc(100vh - 72px);
	width: 220px;
	flex-shrink: 0;
	align-self: flex-start;
}

.vpe-sidebar__inner {
	position: relative;
	display: flex;
	height: 100%;
	flex-direction: column;
	overflow: hidden;
	border-right: 1px solid color-mix(in oklab, var(--border) 60%, transparent);
	background: color-mix(in oklab, var(--surface) 60%, transparent);
	backdrop-filter: blur(24px);
}

.vpe-sidebar__glow-a {
	pointer-events: none;
	position: absolute;
	left: -4rem;
	top: -2.5rem;
	width: 14rem;
	height: 14rem;
	opacity: .25;
	filter: blur(64px);
}

.vpe-sidebar__glow-b {
	pointer-events: none;
	position: absolute;
	right: -2.5rem;
	bottom: -4rem;
	width: 14rem;
	height: 14rem;
	border-radius: 999px;
	background: color-mix(in oklab, var(--accent) 20%, transparent);
	filter: blur(64px);
}

.vpe-sidebar__nav {
	position: relative;
	flex: 1;
	overflow-y: auto;
	padding: 1rem .75rem;
	display: flex;
	flex-direction: column;
	gap: .25rem;
}

/*
 * Без flex-shrink:0 колонка фиксированной высоты сжимает свои пункты,
 * вместо того чтобы прокручиваться: при раскрытии More основной список
 * плющило с 41px до 20px, и высоты переставали совпадать с панелью.
 * Теперь пункты держат высоту, а лишнее уходит в прокрутку.
 */
.vpe-sidebar__nav > * { flex-shrink: 0; }

.vpe-navitem {
	position: relative;
	display: flex;
	align-items: center;
	gap: var(--sp-3);
	overflow: hidden;
	border-radius: var(--r-sm);
	min-height: var(--tap);
	padding: var(--sp-2) var(--sp-3);
	font-size: .875rem;
	font-weight: 500;
	color: var(--muted-foreground);
	transition: color .3s var(--ease);
}

.vpe-navitem:hover { color: var(--foreground); }

/*
 * Активный пункт заливается сплошным primary, а не градиентом. На
 * градиенте белая подпись меняла контраст по длине пункта, а сам приём
 * трёхцветной заливки на элементе меню и делал сайдбар похожим на
 * дежурный шаблон.
 */
.vpe-navitem.is-active {
	color: var(--primary-foreground);
	box-shadow: 0 0 0 1px color-mix(in oklab, var(--primary) 25%, transparent), var(--sh-1);
}

.vpe-navitem__bg {
	pointer-events: none;
	position: absolute;
	inset: 0;
	border-radius: var(--r-sm);
	background-color: var(--primary-solid);
	opacity: 0;
	transform: scale(.95);
	transition: opacity .5s var(--ease), transform .5s var(--ease);
}

.vpe-navitem:hover .vpe-navitem__bg { opacity: .16; transform: scale(1); }
.vpe-navitem.is-active .vpe-navitem__bg { opacity: 1; transform: scale(1); }

.vpe-navitem__bar {
	pointer-events: none;
	position: absolute;
	left: 0;
	top: 50%;
	height: 1.5rem;
	width: 3px;
	transform: translateY(-50%);
	border-radius: 0 999px 999px 0;
	background: var(--primary);
	opacity: 0;
	transition: opacity .3s var(--ease);
}

.vpe-navitem:not(.is-active):hover .vpe-navitem__bar { opacity: 1; }

.vpe-navitem__icon {
	position: relative;
	width: 18px;
	height: 18px;
	flex: none;
	transition: transform .3s var(--ease), color .3s var(--ease);
}

.vpe-navitem:not(.is-active):hover .vpe-navitem__icon { transform: scale(1.1); color: var(--primary); }

.vpe-navitem__label {
	position: relative;
	min-width: 0;
	flex: 1;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	transition: transform .3s var(--ease);
}

.vpe-navitem:hover .vpe-navitem__label { transform: translateX(2px); }

.vpe-navitem__badge {
	position: relative;
	flex: none;
	border-radius: 999px;
	background: color-mix(in oklab, var(--primary) 15%, transparent);
	padding: .125rem .5rem;
	font-size: 10px;
	font-weight: 600;
	color: var(--primary);
}

.vpe-more {
	display: flex;
	width: 100%;
	align-items: center;
	gap: .75rem;
	border-radius: .75rem;
	padding: .625rem .75rem;
	font-size: .875rem;
	font-weight: 500;
	color: var(--muted-foreground);
	transition: background-color .3s var(--ease), color .3s var(--ease);
}

.vpe-more:hover { background: color-mix(in oklab, var(--surface-2) 70%, transparent); color: var(--foreground); }
.vpe-more__icon { width: 18px; height: 18px; flex: none; transition: transform .3s var(--ease); }
.vpe-more:hover .vpe-more__icon { transform: scale(1.1); }
.vpe-more__label { flex: 1; text-align: left; }
.vpe-more__chev { width: 1rem; height: 1rem; transition: transform .5s var(--ease); }
.vpe-more.is-open .vpe-more__chev { transform: rotate(180deg); color: var(--primary); }

.vpe-more-panel {
	display: grid;
	grid-template-rows: 0fr;
	opacity: 0;
	transition: grid-template-rows .5s var(--ease), opacity .5s var(--ease);
}

.vpe-more-panel.is-open { grid-template-rows: 1fr; opacity: 1; }
.vpe-more-panel__clip { overflow: hidden; }
.vpe-more-panel__list { display: flex; flex-direction: column; gap: .25rem; padding-top: .25rem; }

.vpe-sidebar__divider {
	margin: 1rem 0;
	height: 1px;
	background-image: var(--grad-neon);
	opacity: .3;
}

.vpe-sidebar__title {
	padding: 0 .75rem .5rem;
	font-size: 11px;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: .18em;
	color: color-mix(in oklab, var(--muted-foreground) 70%, transparent);
}

.vpe-collections { display: flex; flex-direction: column; gap: .25rem; }

.vpe-collection {
	display: flex;
	align-items: center;
	gap: .75rem;
	border-radius: .75rem;
	padding: .5rem .75rem;
	font-size: .875rem;
	color: var(--muted-foreground);
	transition: transform .3s var(--ease), background-color .3s var(--ease), color .3s var(--ease);
}

.vpe-collection:hover {
	transform: translateX(2px);
	background: color-mix(in oklab, var(--surface-2) 70%, transparent);
	color: var(--foreground);
}

.vpe-collection__icon {
	display: grid;
	place-items: center;
	width: 2rem;
	height: 2rem;
	flex: none;
	border-radius: .5rem;
	color: var(--primary-foreground);
	transition: transform .3s var(--ease), box-shadow .3s var(--ease);
}

.vpe-collection:hover .vpe-collection__icon {
	transform: scale(1.05);
	box-shadow: 0 0 0 1px color-mix(in oklab, var(--primary) 25%, transparent),
		0 8px 30px -8px color-mix(in oklab, var(--primary) 55%, transparent);
}

.vpe-collection__icon .vpe-i { width: 1rem; height: 1rem; }
/* Длинное название переносится на вторую строку, а не обрезается
   многоточием: обрезанное «No Download Ga…» не читается вовсе. */
.vpe-collection__label {
	min-width: 0;
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
	line-height: 1.3;
}

/* ── 7. Hero ─────────────────────────────────────────────────────────────── */

/*
 * Баннер и подвал больше не прижаты к правому краю и скруглены со всех
 * сторон. Односторонний радиус читался как обрезанный блок: слева поле,
 * справа блок упирался в край окна.
 */
.vpe-hero {
	position: relative;
	width: auto;
	overflow: hidden;
	border-radius: var(--r-xl);
	padding: 1px;
}

.vpe-hero__border, .vpe-footer__border {
	position: absolute;
	inset: 0;
	border-radius: var(--r-xl);
	background: linear-gradient(125deg,
		oklch(0.68 0.22 22 / 0.7),
		oklch(0.74 0.18 50 / 0.4) 32%,
		transparent 58%,
		oklch(0.8 0.16 75 / 0.45));
}

.vpe-hero__inner {
	position: relative;
	overflow: hidden;
	border-radius: calc(var(--r-xl) - 1px);
	background: oklch(0.16 0.06 270);
}

.vpe-hero__bg {
	pointer-events: none;
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center right;
}

.vpe-hero__fade-l {
	pointer-events: none;
	position: absolute;
	inset: 0;
	background: linear-gradient(90deg,
		oklch(0.13 0.05 270 / 0.92) 0%,
		oklch(0.13 0.05 270 / 0.72) 24%,
		oklch(0.13 0.05 270 / 0.35) 48%,
		transparent 78%);
}

.vpe-hero__fade-b {
	pointer-events: none;
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	height: 45%;
	background: linear-gradient(to top, oklch(0.12 0.05 270 / 0.75), transparent);
}

/*
 * Затемнение слева направо рассчитано на десктоп: там текст слева, а
 * иллюстрация справа, и правая часть картинки остаётся открытой нарочно.
 * На телефоне текст идёт во всю ширину, правым краем выходит на светлое
 * место, и подзаголовок читается с трудом. Делаем завесу равномерной —
 * иллюстрация видна, но текст лежит на ровном фоне.
 */
@media (max-width: 767px) {
	.vpe-hero__fade-l {
		background: linear-gradient(180deg,
			oklch(0.13 0.05 270 / 0.86) 0%,
			oklch(0.13 0.05 270 / 0.78) 55%,
			oklch(0.13 0.05 270 / 0.86) 100%);
	}
}

.vpe-hero__glow-a, .vpe-hero__glow-b {
	pointer-events: none;
	position: absolute;
	border-radius: 999px;
	filter: blur(120px);
}

.vpe-hero__glow-a {
	left: -8rem;
	top: -6rem;
	width: 26rem;
	height: 26rem;
	background: oklch(0.62 0.235 22 / 0.16);
}

.vpe-hero__glow-b {
	bottom: -8rem;
	left: 33%;
	width: 24rem;
	height: 24rem;
	background: oklch(0.78 0.16 68 / 0.14);
}

/* Композиция баннера: сверху служебная строка — слева метка и счётчик,
   справа жанры; ниже основной блок с заголовком и кнопками. Иллюстрация
   остаётся открытой, ничего её не перекрывает. */
.vpe-hero__grid {
	position: relative;
	display: flex;
	flex-direction: column;
	gap: 1.5rem;
	padding: 1.25rem;
}

.vpe-hero__grid > * { min-width: 0; }

/* Без space-between: он растягивал заголовок, текст и кнопки на всю
   высоту баннера и оставлял между ними провалы. Теперь блок собран
   плотно, а расстояния задаются явными отступами. */
/* Блок целиком по центру вертикали баннера и слегка отодвинут от
   левого края — так он не липнет к сайдбару и читается как единая группа. */
.vpe-hero__left {
	display: flex;
	flex: 1;
	min-width: 0;
	max-width: 38rem;
	flex-direction: column;
	justify-content: center;
	gap: 0;
	padding: 0 0 1.5rem 1rem;
}

.vpe-hero__meta { margin-bottom: 1.125rem; }

.vpe-hero__meta { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem; }

.vpe-badge-trending {
	display: inline-flex;
	align-items: center;
	gap: .375rem;
	border-radius: 999px;
	border: 1px solid oklch(0.7 0.2 10 / 0.5);
	background: oklch(0.6 0.2 10 / 0.14);
	padding: .375rem .875rem;
	font-size: 11px;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: .18em;
	color: oklch(0.78 0.17 15);
	backdrop-filter: blur(12px);
}

.vpe-badge-trending .vpe-i { width: .875rem; height: .875rem; }

.vpe-hero__count { font-size: .875rem; color: var(--muted-foreground); }

.vpe-hero__title {
	margin-top: 0;
	font-size: 2.25rem;
	font-weight: 900;
	line-height: 1.02;
	letter-spacing: -.025em;
	color: var(--foreground);
}

/*
 * Вторая строка заголовка — сплошной фирменный цвет, без заливки текста
 * градиентом. Розово-фиолетовый перелив на 60-пиксельных буквах терял
 * контраст к середине строки и был первым, что бросалось в глаза как
 * «дежурный ИИ-баннер».
 */
.vpe-hero__title-grad {
	margin-top: var(--sp-1);
	display: block;
	color: oklch(0.72 0.2 30);
}

.vpe-hero__lead {
	margin-top: .875rem;
	max-width: 32rem;
	font-size: 1rem;
	line-height: 1.6;
	color: var(--muted-foreground);
}

.vpe-hero__cta { margin-top: 1.5rem; display: flex; flex-wrap: wrap; gap: .75rem; }

/*
 * Главная кнопка — сплошная заливка primary. Трёхцветный градиент на
 * кнопке даёт разный контраст подписи по её длине и ровно он и читается
 * как шаблонная генерация. Состояния разведены по яркости, а не по
 * добавочному свечению.
 */
.vpe-btn-play {
	position: relative;
	display: inline-flex;
	height: 64px;
	min-width: 240px;
	align-items: center;
	justify-content: center;
	overflow: hidden;
	border-radius: var(--r-md);
	background: var(--primary-solid);
	padding: 0 var(--sp-8);
	font-size: 1.0625rem;
	font-weight: 700;
	color: var(--primary-foreground);
	box-shadow: var(--sh-2), inset 0 1px 1px rgba(255, 255, 255, .22);
	transition: transform .25s var(--ease), box-shadow .25s var(--ease), background-color .25s var(--ease);
}

.vpe-btn-play:hover {
	transform: translateY(-3px);
	background: var(--primary-solid-hover);
	box-shadow: var(--sh-3), inset 0 1px 1px rgba(255, 255, 255, .3);
}

.vpe-btn-play:active { transform: translateY(0) scale(.98); background: var(--primary-solid-active); }

.vpe-btn-play__ring { pointer-events: none; position: absolute; inset: 0; border-radius: var(--r-md); border: 1px solid rgba(255, 255, 255, .22); }

.vpe-btn-play__shine {
	pointer-events: none;
	position: absolute;
	inset: 0;
	transform: translateX(-100%);
	transition: transform .9s var(--ease);
}

.vpe-btn-play:hover .vpe-btn-play__shine { transform: translateX(100%); }

/* Слой перекраски при наведении больше не нужен: цвет меняет сама
   кнопка. Оставлен пустым, чтобы не править разметку в пяти шаблонах. */
.vpe-btn-play__hover { display: none; }
.vpe-btn-play__body { position: relative; display: flex; align-items: center; gap: .75rem; }

.vpe-btn-play__icon {
	display: grid;
	place-items: center;
	width: 2rem;
	height: 2rem;
	border-radius: 999px;
	background: rgba(255, 255, 255, .2);
	box-shadow: inset 0 1px 2px rgba(255, 255, 255, .3);
	transition: transform .35s var(--ease);
}

.vpe-btn-play:hover .vpe-btn-play__icon { transform: scale(1.1); }

.vpe-btn-browse {
	position: relative;
	display: inline-flex;
	height: 4rem;
	min-width: 230px;
	align-items: center;
	justify-content: center;
	gap: .625rem;
	overflow: hidden;
	border-radius: 1rem;
	border: 1px solid rgba(255, 255, 255, .15);
	background: rgba(255, 255, 255, .06);
	padding: 0 3rem;
	font-size: 17px;
	font-weight: 700;
	color: var(--foreground);
	backdrop-filter: blur(24px);
	transition: transform .25s var(--ease), border-color .25s var(--ease), background-color .25s var(--ease), box-shadow .25s var(--ease);
}

.vpe-btn-browse:hover {
	transform: translateY(-3px);
	border-color: rgba(255, 255, 255, .35);
	background: rgba(255, 255, 255, .12);
	box-shadow: 0 18px 45px -16px oklch(0.62 0.235 22 / .5);
}

.vpe-btn-browse:active { transform: translateY(0) scale(.985); }

.vpe-btn-browse__shine {
	pointer-events: none;
	position: absolute;
	inset: 0;
	opacity: .4;
	transform: translateX(-100%);
	transition: transform .9s var(--ease);
}

.vpe-btn-browse:hover .vpe-btn-browse__shine { transform: translateX(100%); }
.vpe-btn-browse .vpe-i { position: relative; width: 1.25rem; height: 1.25rem; transition: transform .35s var(--ease); }
.vpe-btn-browse:hover .vpe-i { transform: rotate(90deg); }

/*
 * Стили карточек баннера, аватаров «сейчас играют» и жанровых пилюль
 * удалены вместе с разметкой: карточки и аватары сняли раньше (данных
 * под них нет), ряд пилюль снят этой задачей как дубль фильтров под
 * «Popular Games». Оставлять 180 строк мёртвого CSS с ровно тем
 * розово-фиолетовым набором, который запрещён, — приглашение вернуть
 * его обратно.
 */
.vpe-star { fill: oklch(0.78 0.17 60); color: oklch(0.78 0.17 60); }

/* ── 8. Popular Games ────────────────────────────────────────────────────── */

.vpe-section { position: relative; margin-top: 2.5rem; }

.vpe-sechead { display: flex; align-items: flex-end; justify-content: space-between; gap: 1rem; }

.vpe-h2 {
	font-size: 1.5rem;
	font-weight: 800;
	letter-spacing: -.025em;
	color: var(--foreground);
}

.vpe-viewall {
	display: inline-flex;
	flex-shrink: 0;
	align-items: center;
	gap: .375rem;
	border-radius: 999px;
	border: 1px solid rgba(255, 255, 255, .1);
	background: rgba(255, 255, 255, .04);
	padding: .5rem 1rem;
	font-size: .875rem;
	font-weight: 600;
	color: color-mix(in oklab, var(--foreground) 80%, transparent);
	backdrop-filter: blur(12px);
	transition: transform .25s var(--ease-2), border-color .25s var(--ease-2), background-color .25s var(--ease-2), color .25s var(--ease-2), box-shadow .25s var(--ease-2);
}

.vpe-viewall:hover {
	transform: translateY(-2px);
	border-color: rgba(255, 255, 255, .25);
	background: rgba(255, 255, 255, .08);
	color: var(--foreground);
	box-shadow: 0 8px 24px -12px oklch(0.62 0.235 22 / .6);
}

.vpe-viewall .vpe-i { width: .875rem; height: .875rem; transition: transform .3s var(--ease-2); }
.vpe-viewall:hover .vpe-i { transform: translateX(2px); }

.vpe-filters { margin-top: 1.25rem; display: flex; flex-wrap: wrap; gap: .625rem; }

.vpe-filter {
	display: inline-flex;
	align-items: center;
	gap: var(--sp-2);
	min-height: var(--tap);
	border-radius: var(--r-pill);
	border: 1px solid var(--line-1);
	background: var(--layer-1);
	padding: 0 var(--sp-5);
	font-size: var(--fs-base);
	font-weight: 600;
	color: color-mix(in oklab, var(--foreground) 70%, transparent);
	transition: transform .3s var(--ease-2), border-color .3s var(--ease-2), background-color .3s var(--ease-2), color .3s var(--ease-2), box-shadow .3s var(--ease-2);
}

.vpe-filter:hover {
	transform: translateY(-2px);
	border-color: rgba(255, 255, 255, .25);
	background: rgba(255, 255, 255, .08);
	color: var(--foreground);
	box-shadow: 0 10px 26px -12px oklch(0.62 0.235 22 / .45);
}

.vpe-filter.is-active {
	border-color: transparent;
	background: var(--primary-solid);
	color: #fff;
	box-shadow: 0 10px 28px -10px oklch(0.62 0.235 22 / .55), inset 0 1px 0 0 rgba(255, 255, 255, .25);
}

.vpe-filter.is-active:hover {
	box-shadow: 0 14px 32px -10px oklch(0.62 0.235 22 / .55), inset 0 1px 0 0 rgba(255, 255, 255, .35);
}

.vpe-filter .vpe-i { width: 1rem; height: 1rem; transition: transform .3s var(--ease-2); }
.vpe-filter:hover .vpe-i { transform: scale(1.1); }

.vpe-grid-popular { margin-top: 1.5rem; display: grid; grid-template-columns: 1fr; gap: 1rem; }

/*
 * Карточка — колонка во всю высоту ячейки сетки. Раньше высоту задавал
 * её собственный текст, и в ряду, где у одной игры есть подпись «Mobile»,
 * а у соседней нет, нижние края разъезжались.
 */
.vpe-gamecard {
	position: relative;
	display: flex;
	flex-direction: column;
	height: 100%;
	overflow: hidden;
	border-radius: var(--r-lg);
	border: 1px solid var(--line-1);
	background: color-mix(in oklab, var(--card) 40%, transparent);
	backdrop-filter: blur(12px);
	transition: transform .25s var(--ease-2), border-color .25s var(--ease-2), box-shadow .25s var(--ease-2);
}

.vpe-gamecard:hover {
	transform: translateY(-5px);
	border-color: rgba(255, 255, 255, .25);
	box-shadow: 0 20px 50px -20px oklch(0.62 0.235 22 / .55);
}

.vpe-gamecard__glow {
	pointer-events: none;
	position: absolute;
	inset: 0;
	border-radius: 20px;
	opacity: 0;
	box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .15), 0 0 40px -12px oklch(0.62 0.235 22 / .6);
	transition: opacity .3s var(--ease-2);
}

.vpe-gamecard:hover .vpe-gamecard__glow { opacity: 1; }

/* display:block обязателен: элемент стал ссылкой, а у инлайнового
   aspect-ratio не применяется — карточка вытягивается по высоте
   картинки и ломает всю сетку. */
.vpe-gamecard__media { display: block; position: relative; aspect-ratio: 16 / 10; overflow: hidden; }

.vpe-gamecard__img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform .25s var(--ease-2);
}

.vpe-gamecard:hover .vpe-gamecard__img { transform: scale(1.04); }

.vpe-gamecard__shade {
	pointer-events: none;
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	height: 50%;
	background: linear-gradient(to top, rgba(8, 10, 28, .95), transparent);
}

.vpe-gamecard__hot {
	position: absolute;
	left: .75rem;
	top: .75rem;
	display: inline-flex;
	align-items: center;
	gap: .25rem;
	border-radius: .375rem;
	border: 1px solid rgba(255, 255, 255, .15);
	background: var(--grad-hot);
	padding: .25rem .5rem;
	font-size: 10px;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: .025em;
	color: #fff;
	box-shadow: 0 6px 18px -8px oklch(0.62 0.235 22 / .6);
}

.vpe-gamecard__hot .vpe-i { width: .75rem; height: .75rem; }

/*
 * Значок запуска переехал из правого верхнего угла в центр обложки и
 * появляется при наведении. В углу он делил место с сердечком избранного:
 * два полупрозрачных кружка по диагонали спорили друг с другом и с
 * метками Hot/New, а поверх пёстрой обложки читались оба плохо.
 *
 * Там, где наведения нет (телефон, планшет), значок виден всегда:
 * подсказка «карточка запускает игру» на тач-экране нужнее.
 */
.vpe-gamecard__play {
	position: absolute;
	left: 50%;
	top: 50%;
	display: grid;
	place-items: center;
	width: 3.25rem;
	height: 3.25rem;
	border-radius: var(--r-pill);
	border: 1px solid rgba(255, 255, 255, .35);
	background: color-mix(in oklab, var(--primary) 88%, transparent);
	color: var(--primary-foreground);
	transform: translate(-50%, -50%) scale(.9);
	box-shadow: var(--sh-2);
	transition: transform .25s var(--ease-2), opacity .25s var(--ease-2);
}

.vpe-gamecard__play .vpe-i { width: 1.125rem; height: 1.125rem; margin-left: 2px; }

@media (hover: hover) {
	.vpe-gamecard__play { opacity: 0; }

	.vpe-gamecard:hover .vpe-gamecard__play,
	.vpe-gamecard:focus-within .vpe-gamecard__play {
		opacity: 1;
		transform: translate(-50%, -50%) scale(1);
	}
}

/* Обёртка обложки: по ней позиционируется кнопка избранного. */
.vpe-gamecard__cover { position: relative; }

/*
 * Метки поверх обложки. Стопка, а не один бейдж: Featured приходит из
 * данных провайдера, Hot и New считаются у нас, и совпасть они могут.
 * Позиционируется контейнер, сами метки — обычные плашки, поэтому их
 * можно ставить и в других местах.
 */
.vpe-gamecard__flags {
	position: absolute;
	left: var(--sp-3);
	top: var(--sp-3);
	display: flex;
	flex-wrap: wrap;
	gap: var(--sp-1);
	/* Правый верхний угол занят кнопкой избранного — не наезжаем на неё. */
	max-width: calc(100% - 3.75rem);
}

.vpe-flag {
	display: inline-flex;
	align-items: center;
	gap: .25rem;
	border-radius: .375rem;
	border: 1px solid rgba(255, 255, 255, .15);
	padding: .25rem .5rem;
	font-size: 10px;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: .025em;
	color: #fff;
}

.vpe-flag .vpe-i { width: .75rem; height: .75rem; }

.vpe-flag--featured {
	background: var(--grad-hot);
	box-shadow: 0 6px 18px -8px oklch(0.62 0.235 22 / .6);
}

.vpe-flag--hot {
	background: linear-gradient(100deg, oklch(0.74 0.18 55), oklch(0.63 0.24 25));
	box-shadow: 0 6px 18px -8px oklch(0.63 0.24 25 / .9);
}

/*
 * Новое — холодным, чтобы «Hot» и «New» не читались одним пятном на
 * периферии зрения. Текст тёмный: на светлой бирюзе белый не читается.
 */
.vpe-flag--new {
	background: linear-gradient(100deg, oklch(0.83 0.14 175), oklch(0.76 0.13 205));
	color: oklch(0.22 0.03 250);
	box-shadow: 0 6px 18px -8px oklch(0.78 0.13 190 / .8);
}

/*
 * Кнопка 44×44 — это тач-цель, а не размер видимого кружка: сам кружок
 * 36px, как у иконки Play в противоположном углу, а лишние восемь
 * пикселей вокруг него нужны пальцу.
 */
.vpe-gamecard__fav {
	position: absolute;
	right: .125rem;
	top: .125rem;
	display: grid;
	place-items: center;
	width: var(--tap);
	height: var(--tap);
	padding: 0;
	border: 0;
	background: none;
	color: #fff;
	cursor: pointer;
	z-index: 1;
}

.vpe-gamecard__fav-dot {
	display: grid;
	place-items: center;
	width: 2.25rem;
	height: 2.25rem;
	border-radius: 999px;
	border: 1px solid rgba(255, 255, 255, .25);
	background: rgba(10, 12, 32, .55);
	backdrop-filter: blur(12px);
	transition: transform .25s var(--ease-2), border-color .25s var(--ease-2), background-color .25s var(--ease-2), color .25s var(--ease-2);
}

.vpe-gamecard__fav .vpe-i { width: 1rem; height: 1rem; }

.vpe-gamecard__fav:hover .vpe-gamecard__fav-dot {
	transform: scale(1.1);
	border-color: rgba(255, 255, 255, .45);
	background: rgba(10, 12, 32, .8);
}

.vpe-gamecard__fav.is-on .vpe-gamecard__fav-dot {
	border-color: color-mix(in oklab, var(--primary) 70%, transparent);
	background: color-mix(in oklab, var(--primary) 85%, transparent);
	color: var(--primary-foreground);
	box-shadow: 0 8px 22px -10px color-mix(in oklab, var(--primary) 90%, transparent);
}

/* Залитое сердце вместо контурного: состояние читается без цвета. */
.vpe-gamecard__fav.is-on .vpe-i { fill: currentColor; }

@media (prefers-reduced-motion: reduce) {
	.vpe-gamecard__fav-dot { transition: none; }
	.vpe-gamecard__fav:hover .vpe-gamecard__fav-dot { transform: none; }
}

.vpe-gamecard__info {
	position: relative;
	display: flex;
	flex: 1 1 auto;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--sp-1);
	border-top: 1px solid rgba(255, 255, 255, .08);
	background: rgba(10, 12, 32, .75);
	padding: var(--sp-3);
}

.vpe-gamecard__title {
	width: 100%;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	font-size: var(--fs-base);
	font-weight: 700;
	color: var(--foreground);
}

/*
 * Строка признаков прижата к низу плашки: у одной игры есть «Mobile», у
 * соседней нет, и без этого нижние строки в ряду стояли на разной высоте.
 */
.vpe-gamecard__stats {
	margin-top: auto;
	padding-top: var(--sp-2);
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--sp-2);
	font-size: var(--fs-xs);
	color: var(--muted-foreground);
}

.vpe-gamecard__stats span { display: inline-flex; align-items: center; gap: .25rem; }
.vpe-gamecard__stats .vpe-i { width: .875rem; height: .875rem; }
.vpe-gamecard__rating { font-weight: 600; color: color-mix(in oklab, var(--foreground) 90%, transparent); }
.vpe-star-gold { fill: oklch(0.85 0.16 85); color: oklch(0.85 0.16 85); }

/*
 * Чип жанра стоит в строке признаков и живёт по её правилам: тот же
 * кегль, тот же промежуток. Отдельного «правого угла» у него больше нет.
 * Оттенки сведены к одной шкале — тёплые для активных жанров, холодные
 * для спокойных: пять случайных цветов из разных семейств выглядели как
 * пять разных наборов иконок в одном интерфейсе.
 */
.vpe-genre {
	flex-shrink: 0;
	border-radius: var(--r-pill);
	border: 1px solid;
	padding: .1875rem .5rem;
	font-size: var(--fs-xs);
	font-weight: 600;
	line-height: 1.35;
}

.vpe-genre--action { color: oklch(0.74 0.19 25); border-color: oklch(0.74 0.19 25 / .35); background: oklch(0.74 0.19 25 / .12); }
.vpe-genre--racing { color: oklch(0.78 0.16 60); border-color: oklch(0.78 0.16 60 / .35); background: oklch(0.78 0.16 60 / .12); }
.vpe-genre--arcade { color: oklch(0.82 0.15 85); border-color: oklch(0.82 0.15 85 / .35); background: oklch(0.82 0.15 85 / .12); }
.vpe-genre--puzzle { color: oklch(0.78 0.14 175); border-color: oklch(0.78 0.14 175 / .35); background: oklch(0.78 0.14 175 / .12); }
.vpe-genre--multiplayer { color: oklch(0.74 0.13 225); border-color: oklch(0.74 0.13 225 / .35); background: oklch(0.74 0.13 225 / .12); }

/* ── 9. Ряды игр ─────────────────────────────────────────────────────────── */

.vpe-row { margin-top: 2.5rem; }

.vpe-row__head { display: inline-flex; align-items: center; gap: .375rem; text-align: left; }

.vpe-row__title { font-size: 1.25rem; font-weight: 800; letter-spacing: -.025em; color: var(--foreground); }

.vpe-row__chev {
	width: 1.25rem;
	height: 1.25rem;
	color: color-mix(in oklab, var(--foreground) 60%, transparent);
	transition: transform .3s var(--ease-2), color .3s var(--ease-2);
}

.vpe-row__head:hover .vpe-row__chev { transform: translateX(4px); color: var(--foreground); }

.vpe-row__grid {
	margin-top: 1rem;
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: .75rem;
	padding-bottom: .75rem;
}

.vpe-rowcard {
	position: relative;
	min-width: 0;
	cursor: pointer;
	overflow: hidden;
	border-radius: 1rem;
	border: 1px solid rgba(255, 255, 255, .1);
	background: color-mix(in oklab, var(--card) 40%, transparent);
	transition: transform .25s var(--ease-2), border-color .25s var(--ease-2), box-shadow .25s var(--ease-2);
}

.vpe-rowcard:hover {
	transform: translateY(-2px);
	border-color: rgba(255, 255, 255, .25);
	box-shadow: 0 22px 46px -22px oklch(0.62 0.235 22 / .55);
}

/* Тот же случай: медиа-блок ряда бывает ссылкой. */
.vpe-rowcard__media { display: block; position: relative; aspect-ratio: 16 / 9; overflow: hidden; }

.vpe-rowcard__img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform .4s var(--ease-2);
}

.vpe-rowcard:hover .vpe-rowcard__img { transform: scale(1.08); }

.vpe-rowcard__shade {
	pointer-events: none;
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	height: 45%;
	background: linear-gradient(to top, rgba(8, 10, 28, .92), transparent);
}

.vpe-tag {
	position: absolute;
	left: .5rem;
	top: .5rem;
	display: inline-flex;
	align-items: center;
	gap: .25rem;
	border-radius: .375rem;
	padding: .125rem .5rem;
	font-size: 10px;
	font-weight: 700;
}

.vpe-tag .vpe-i { width: .75rem; height: .75rem; }
.vpe-tag--hot { background: var(--grad-hot); color: #fff; }
.vpe-tag--top { background: var(--grad-top); color: #231603; }
.vpe-tag--updated { background: var(--grad-updated); color: #fff; }
.vpe-tag--originals { background: var(--grad-originals); color: #fff; }

.vpe-rowcard__play {
	position: absolute;
	inset: 0;
	display: grid;
	place-items: center;
	background: rgba(8, 10, 28, .35);
	opacity: 0;
	backdrop-filter: blur(2px);
	transition: opacity .3s var(--ease-2);
}

.vpe-rowcard:hover .vpe-rowcard__play { opacity: 1; }

.vpe-rowcard__play span {
	display: grid;
	place-items: center;
	width: 3.25rem;
	height: 3.25rem;
	border-radius: var(--r-pill);
	background: color-mix(in oklab, var(--primary) 88%, transparent);
	color: #fff;
	box-shadow: 0 12px 30px -10px oklch(0.62 0.235 22 / .6);
}

.vpe-rowcard__play .vpe-i { width: 1.25rem; height: 1.25rem; }

.vpe-rowcard__title {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	padding: 0 .875rem .75rem;
	font-size: 15px;
	font-weight: 700;
	color: var(--foreground);
}

/* ------------------------------------------------------------------ *
 * Обычная страница: о сайте, политика, правила, DMCA.
 *
 * Ширина ограничена по числу знаков, а не по пикселям: юридический
 * текст читают строками, и на широком мониторе строка в полтора экрана
 * теряется при переходе на следующую.
 * ------------------------------------------------------------------ */

.vpe-page { max-width: 72ch; }

.vpe-page__head { margin-bottom: 1.5rem; }

.vpe-page__meta {
	margin-top: .5rem;
	font-size: 13px;
	color: var(--muted-foreground);
}

.vpe-page__body h2 {
	margin-top: 2rem;
	margin-bottom: .625rem;
	font-size: 1.25rem;
	font-weight: 800;
	letter-spacing: -.02em;
	color: var(--foreground);
}

.vpe-page__body p { margin-bottom: 1rem; }

.vpe-page__body ul {
	margin: 0 0 1rem 1.25rem;
	list-style: disc;
}

.vpe-page__body li { margin-bottom: .5rem; }

.vpe-page__body a {
	color: var(--primary);
	text-decoration: underline;
	text-underline-offset: 2px;
}

.vpe-page__body a:hover { color: var(--foreground); }

/* ------------------------------------------------------------------ *
 * Частые вопросы.
 * ------------------------------------------------------------------ */

.vpe-game__related { padding-left: 0; }

.vpe-explore {
	display: grid;
	grid-template-columns: minmax(0, 1.4fr) minmax(16rem, 1fr);
	gap: 1.5rem;
	padding: 1.25rem;
	border: 1px solid var(--border);
	border-radius: calc(var(--radius) + .375rem);
	background: var(--surface);
}

.vpe-explore__group { min-width: 0; }
.vpe-explore__group .vpe-h2 { margin-bottom: .75rem; }

.vpe-explore__links {
	display: flex;
	flex-wrap: wrap;
	gap: .5rem;
}

.vpe-explore__link {
	display: inline-flex;
	align-items: center;
	justify-content: space-between;
	gap: .625rem;
	min-height: 2.75rem;
	max-width: 100%;
	padding: .625rem .875rem;
	border: 1px solid var(--border);
	border-radius: 999px;
	background: var(--card);
	font-size: .875rem;
	font-weight: 700;
	transition: transform .2s var(--ease-2), border-color .2s var(--ease-2), background-color .2s var(--ease-2);
}

.vpe-explore__link small {
	color: var(--muted-foreground);
	font-size: .75rem;
	font-variant-numeric: tabular-nums;
}

.vpe-explore__link:hover {
	transform: translateY(-1px);
	border-color: color-mix(in oklab, var(--primary) 55%, var(--border));
	background: var(--surface-2);
}

@media (max-width: 767px) {
	.vpe-explore { grid-template-columns: minmax(0, 1fr); }
	.vpe-explore__link { flex: 1 1 9rem; }
}

.vpe-faq {
	display: grid;
	gap: .5rem;
	max-width: 60rem;
}

.vpe-faq__item {
	overflow: hidden;
	border-radius: .875rem;
	border: 1px solid var(--border);
	background: color-mix(in oklab, var(--card) 55%, transparent);
	transition: border-color .2s var(--ease-2);
}

.vpe-faq__item[open] { border-color: color-mix(in oklab, var(--primary) 45%, transparent); }

.vpe-faq__q {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	min-height: 3.25rem;
	padding: .875rem 1.125rem;
	cursor: pointer;
	list-style: none;
	font-size: 15px;
	font-weight: 700;
	color: var(--foreground);
}

.vpe-faq__q::-webkit-details-marker { display: none; }
.vpe-faq__q:hover { background: color-mix(in oklab, var(--surface-2) 45%, transparent); }

.vpe-faq__chev {
	display: inline-flex;
	flex-shrink: 0;
	color: var(--muted-foreground);
	transition: transform .25s var(--ease-2);
}

.vpe-faq__chev .vpe-i { width: 1.125rem; height: 1.125rem; }
.vpe-faq__item[open] .vpe-faq__chev { transform: rotate(180deg); }

.vpe-faq__a {
	padding: 0 1.125rem 1.125rem;
	max-width: 72ch;
	font-size: 14px;
	line-height: 1.65;
	color: var(--muted-foreground);
}

/* ------------------------------------------------------------------ *
 * Кнопка «наверх».
 *
 * Слева на десктопе места нет — там сайдбар, справа у края свободно.
 * На телефоне поднята выше нижнего края: там живут системные жесты.
 * ------------------------------------------------------------------ */

.vpe-totop {
	position: fixed;
	right: 1rem;
	bottom: 1.5rem;
	z-index: 70;
	display: grid;
	place-items: center;
	width: 2.75rem;
	height: 2.75rem;
	border-radius: 999px;
	border: 1px solid color-mix(in oklab, var(--border) 80%, transparent);
	background: color-mix(in oklab, var(--surface-2) 92%, transparent);
	color: var(--foreground);
	box-shadow: 0 12px 32px -12px rgba(0, 0, 0, .9);
	backdrop-filter: blur(14px);
	transition: transform .2s var(--ease-2), background-color .2s var(--ease-2), border-color .2s var(--ease-2);
}

.vpe-totop[hidden] { display: none; }

.vpe-totop:hover {
	transform: translateY(-2px);
	border-color: color-mix(in oklab, var(--primary) 60%, transparent);
	background: var(--surface-2);
}

/* Стрелка вверх — тот же значок, развёрнутый. Отдельная иконка ради
   поворота на 180 градусов не нужна. */
.vpe-totop .vpe-i { width: 1.25rem; height: 1.25rem; transform: rotate(180deg); }

@media (min-width: 1024px) {
	.vpe-totop { right: 1.5rem; bottom: 2rem; width: 3rem; height: 3rem; }
}

/* ------------------------------------------------------------------ *
 * Страница избранного.
 * ------------------------------------------------------------------ */

.vpe-favs__sub {
	margin-top: .375rem;
	max-width: 46ch;
	font-size: 14px;
	color: var(--muted-foreground);
}

.vpe-favs__empty {
	display: grid;
	justify-items: center;
	gap: .5rem;
	margin-top: 2rem;
	padding: 3rem 1.5rem;
	border-radius: 1.25rem;
	border: 1px dashed var(--border);
	background: color-mix(in oklab, var(--card) 40%, transparent);
	text-align: center;
}

.vpe-favs__icon {
	display: grid;
	place-items: center;
	width: 3.5rem;
	height: 3.5rem;
	border-radius: 999px;
	background: color-mix(in oklab, var(--primary) 16%, transparent);
	color: var(--primary);
}

.vpe-favs__icon .vpe-i { width: 1.5rem; height: 1.5rem; }

.vpe-favs__title {
	font-size: 1.125rem;
	font-weight: 800;
	color: var(--foreground);
}

.vpe-favs__hint {
	max-width: 38ch;
	font-size: 14px;
	color: var(--muted-foreground);
}

.vpe-favs__empty .vpe-btn-pill { margin-top: var(--sp-3); }

.vpe-favs__tools {
	display: flex;
	justify-content: center;
	margin-top: 1.5rem;
}

/* ------------------------------------------------------------------ *
 * Тач-цели на узких экранах.
 *
 * Логотип, «All games», пилюли героя и чипы жанра по высоте не дотягивают
 * до 44px — пальцем в них попадают через раз. Каждому своё лечение.
 *
 * Логотип и «All games» стоят на свободном месте: им просто ставим высоту.
 *
 * Пилюли героя высоту менять нельзя — ряд в баннере выверен по месту и от
 * лишних четырёх пикселей переносится на вторую строку. Им растягиваем
 * область нажатия невидимым слоем: +2px сверху и снизу, меньше половины
 * промежутка между рядами, так что соседнюю пилюлю он не перекрывает.
 *
 * Чипу жанра невидимый слой не даём: он живёт внутри карточки каталога,
 * и растянутый до 44px перекрыл бы её заголовок — нажатие по названию
 * игры уводило бы в категорию. Увеличиваем сам чип, пусть и не до нормы:
 * это второстепенная ссылка, а карточка рядом — цель во весь свой размер.
 *
 * Поле поиска — отдельный случай: сам input был 23px внутри рамки в 43px,
 * и нажатие мимо него не ставило курсор. Padding с компенсирующим
 * отрицательным margin растягивает input на всю рамку, не сдвигая текст.
 * ------------------------------------------------------------------ */

@media (max-width: 1023px) {
	/*
	 * Отступы по обе стороны. Прижатый к правому краю контент и
	 * скругление только слева — это десктопная композиция: там справа от
	 * блока край экрана, а слева сайдбар. Без сайдбара блок упирается в
	 * правый край и выглядит съехавшим, а односторонние скругления
	 * читаются как недоделка.
	 */


	.vpe-logo,
	.vpe-viewall { min-height: 2.75rem; }

	/* Ссылки подвала были высотой в строку — 19px. Их там три десятка,
	   и промахнуться по соседней проще, чем попасть по нужной. */
	.vpe-footer__link { min-height: 2.75rem; }

	/*
	 * Высоту ссылки подвала добрали выше, а ширина осталась по слову:
	 * у «3D» это 18px при норме 44. Ширину нельзя лечить ни min-width,
	 * ни отрицательными полями — список стоит в сетке
	 * repeat(auto-fit, minmax(8.5rem, 1fr)), на 390 это две колонки, и
	 * растянутая цель полезла бы в соседнюю.
	 *
	 * Поэтому не ширина, а выравнивание: justify-self: start заменяем на
	 * stretch, и ссылка занимает свою ячейку целиком — 171px на 390.
	 * Ячейки сетки не пересекаются по определению, между ними ещё и
	 * промежуток в 1rem, так что перекрыться цели не могут. Текст
	 * остаётся у левого края, подчёркивание на hover висит на внутреннем
	 * span и по-прежнему равно ширине слова, а не ячейки.
	 *
	 * Селектор с родителем не для красоты: базовое правило
	 * .vpe-footer__link { justify-self: start } стоит ниже по файлу, и при
	 * равном весе побеждало бы оно.
	 */
	.vpe-footer__list .vpe-footer__link { justify-self: stretch; }

	/*
	 * Название игры в карточке — тоже ссылка, и высотой оно было в одну
	 * строку. Обложка рядом большая и ведёт туда же, но по названию
	 * тянутся не реже. Добираем высоту отступами внутри самой ссылки:
	 * невидимый слой здесь не годится, он накрыл бы соседний чип жанра.
	 */
	/*
	 * Ссылка-название занимает плашку по всей ширине: у короткого имени
	 * вроде «HEX» inline-flex давал цель в 31px, и добрать её было нечем —
	 * min-width на ссылке внутри обрезающего заголовка ломает многоточие.
	 *
	 * block, а не flex: у flex-контейнера text-overflow не работает — текст
	 * становится анонимным flex-элементом, и длинное название обрезалось бы
	 * без многоточия. С block многоточие ставит сама ссылка, а высоту в
	 * 44px даёт line-height, он же держит строку по центру плашки.
	 */
	.vpe-gamecard__title a,
	.vpe-catcard__title a {
		display: block;
		width: 100%;
		min-height: 2.75rem;
		line-height: 2.75rem;
		overflow: hidden;
		text-overflow: ellipsis;
		white-space: nowrap;
	}

	.vpe-gamecard__info { padding-top: .25rem; padding-bottom: .25rem; }

	/* «See all» в витрине категории — 21px, заголовок ряда — 36px. */
	.vpe-spot__all,
	.vpe-row__head { min-height: 2.75rem; }

	/*
	 * Ссылки без класса прошлые правила не поймали: правило было написано
	 * по классу .vpe-footer__link, а юридический ряд внизу подвала и
	 * ссылки категорий в характеристиках игры — обычные <a>.
	 *
	 * Юридические ссылки особенно важны: по ним идут именно тогда, когда
	 * что-то не так, и промахиваться там хуже всего.
	 */
	.vpe-footer__legal a {
		display: inline-flex;
		align-items: center;
		min-height: 2.75rem;
	}

	/*
	 * По высоте юридические ссылки уже 44px, а по ширине «DMCA» — 33.
	 * Ряд переносится, поэтому растягивать нечем: min-width раздвинул бы
	 * соседей и на второй строке цели встали бы вплотную.
	 *
	 * Добираем ширину отступами внутри самой ссылки, а промежуток ряда
	 * уменьшаем ровно настолько, насколько выросли отступы: расстояние
	 * между словами остаётся прежним, а между областями нажатия
	 * сохраняется зазор в 4px — они соприкасаются, но не пересекаются.
	 */
	.vpe-footer__legal { gap: .25rem; }
	.vpe-footer__legal a { padding-inline: .625rem; }

	/*
	 * Крошки: «Home» — 31px в ширину. Тот же приём, что и у ссылок в
	 * характеристиках игры ниже — отступ увеличивает область нажатия,
	 * отрицательное поле возвращает текст на прежнее место, и внешне
	 * дорожка не расползается. Между соседними ссылками остаётся
	 * разделитель «/» и два промежутка по 8px: даже с учётом вылета в
	 * 8px с каждой стороны цели не смыкаются.
	 */
	.vpe-crumbs a {
		display: inline-flex;
		align-items: center;
		min-height: 2.75rem;
		padding-inline: .5rem;
		margin-inline: -.5rem;
	}

	/*
	 * Ссылке в характеристиках игры inline-flex не подходит: она перестаёт
	 * переноситься, и на экране 320 длинное название категории уезжает за
	 * край. Отступы увеличивают область нажатия, не влияя на высоту
	 * строки, а отрицательные поля возвращают текст на прежнее место.
	 */
	.vpe-game__body dd a {
		padding: .6875rem .5rem;
		margin: -.6875rem -.5rem;
	}

	.vpe-viewall { align-items: center; }

	/* 11px я поставил сам предыдущей правкой ради компактности — на
	   телефоне это ниже читаемого. Возвращаю 12px. */
	/* 10px базовых и 11px из моей прошлой правки — оба ниже читаемого
	   на телефоне. 12px это нижняя граница, с которой ещё не щуришься. */
	.vpe-genre,
	.vpe-eyebrow {
		padding: .4375rem .625rem;
		font-size: 12px;
	}

	/*
	 * Чипу жанра теперь можно дать полноценную тач-цель. Раньше нельзя
	 * было: он стоял справа от названия игры, и растянутая до 44px область
	 * нажатия накрывала заголовок — тап по названию уводил в категорию.
	 * После перестройки карточки чип ушёл в нижнюю строку признаков,
	 * над ним описание, а не ссылка, и перекрывать нечего.
	 */
	.vpe-gamecard__stats .vpe-genre { position: relative; }

	.vpe-gamecard__stats .vpe-genre::after {
		content: "";
		position: absolute;
		left: 0;
		right: 0;
		top: 50%;
		height: var(--tap);
		transform: translateY(-50%);
	}

	.vpe-search__input {
		padding: .75rem 0;
		margin: -.75rem 0;
	}
}

/* ------------------------------------------------------------------ *
 * Нижняя граница цели на широких экранах.
 *
 * С 1024 включается указательная раскладка: появляется сайдбар, меню и
 * подвал становятся плотными. Норма в 44px здесь не действует — это
 * мерка для пальца, и растянуть до неё два с половиной десятка ссылок
 * подвала значит переписать раскладку, которую только что задал дизайн.
 *
 * Но и оставлять как было нельзя: ссылка подвала занимала 19×22, а
 * название игры в карточке — 33×19. Для указателя норма своя, WCAG 2.5.8
 * AA: 24×24. Её и берём — она не меняет композицию, разница в считанные
 * пиксели, зато промахов по ссылке становится заметно меньше.
 *
 * Что здесь НЕ сделано и сделано сознательно: цели 24-43px на ширинах от
 * 1024 остаются. На планшете в альбомной ориентации это та же указательная
 * раскладка, но палец. Довести её до 44px — отдельное решение по дизайну,
 * а не правка вёрстки.
 * ------------------------------------------------------------------ */

@media (min-width: 1024px) {
	.vpe-footer__link,
	.vpe-footer__legal a,
	.vpe-crumbs a,
	.vpe-spot__all {
		display: inline-flex;
		align-items: center;
		min-height: 1.5rem;
	}

	/*
	 * Ссылка занимает свою ячейку сетки целиком — ширина цели вместо 19px
	 * становится равной колонке. Текст остаётся у левого края, а
	 * подчёркивание на hover висит на внутреннем span и по-прежнему равно
	 * ширине слова.
	 */
	.vpe-footer__list .vpe-footer__link { justify-self: stretch; }

	/* Название игры в карточке — 19px в высоту. Обрезку многоточием
	   оставляем заголовку, поэтому высоту добираем строкой, а не flex. */
	.vpe-gamecard__title a,
	.vpe-catcard__title a {
		display: block;
		min-height: 1.5rem;
		line-height: 1.5rem;
	}

	/*
	 * Поле поиска — 23px внутри рамки в 43px: нажатие в рамку мимо самого
	 * input не ставило курсор. Та же правка, что и на узких экранах, —
	 * отступ растягивает поле на всю рамку, отрицательное поле возвращает
	 * текст на место.
	 */
	.vpe-search__input {
		padding-block: .625rem;
		margin-block: -.625rem;
	}
}

/* ------------------------------------------------------------------ *
 * Витрина категории: крупная игра + список.
 *
 * Ряды карточек на главной идут один за другим и сливаются. Этот блок
 * ломает сетку намеренно: одна обложка во всю высоту и нумерованный
 * список рядом. На узком экране список уходит под обложку.
 * ------------------------------------------------------------------ */

.vpe-spot {
	overflow: hidden;
	border-radius: 1.25rem;
	border: 1px solid var(--border);
	background:
		radial-gradient(120% 140% at 100% 0%, color-mix(in oklab, var(--accent) 16%, transparent), transparent 60%),
		color-mix(in oklab, var(--card) 70%, transparent);
}

.vpe-spot__head {
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: 1rem;
	padding: 1.25rem 1.25rem .875rem;
	border-bottom: 1px solid color-mix(in oklab, var(--border) 70%, transparent);
}

.vpe-spot__title {
	font-size: 1.25rem;
	font-weight: 800;
	letter-spacing: -.025em;
	color: var(--foreground);
}

.vpe-spot__sub {
	margin-top: .125rem;
	font-size: 13px;
	color: var(--muted-foreground);
}

.vpe-spot__all {
	display: inline-flex;
	flex-shrink: 0;
	align-items: center;
	gap: .375rem;
	font-size: 14px;
	font-weight: 600;
	color: var(--muted-foreground);
	transition: color .2s var(--ease-2);
}

.vpe-spot__all:hover { color: var(--foreground); }
.vpe-spot__all .vpe-i { width: 1rem; height: 1rem; }

.vpe-spot__body {
	display: grid;
	gap: 1rem;
	padding: 1rem 1.25rem 1.25rem;
}

/*
 * Элемент grid по умолчанию не сжимается ниже ширины своего содержимого.
 * Длинное название игры распирало карточку: на экране 320 за край
 * вылезали все четыре витрины, на 390 — та, где название длиннее.
 * Прокрутки при этом не было, потому что блок обрезан по краю, и часть
 * обложки просто не показывалась.
 */
.vpe-spot__body > * { min-width: 0; }

.vpe-spot__lead {
	position: relative;
	display: block;
	min-width: 0;
	overflow: hidden;
	border-radius: 1rem;
	aspect-ratio: 16 / 9;
	border: 1px solid rgba(255, 255, 255, .08);
}

.vpe-spot__leadimg {
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform .45s var(--ease);
}

.vpe-spot__lead:hover .vpe-spot__leadimg { transform: scale(1.05); }

.vpe-spot__leadshade {
	position: absolute;
	inset: 0;
	background: linear-gradient(to top, rgba(0, 0, 0, .88) 4%, rgba(0, 0, 0, .35) 42%, transparent 72%);
}

.vpe-spot__leadbody {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: .75rem;
	padding: 1rem;
}

.vpe-spot__leadname {
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	font-size: 1.125rem;
	font-weight: 800;
	letter-spacing: -.02em;
	color: #fff;
}

.vpe-spot__play {
	display: inline-flex;
	flex-shrink: 0;
	align-items: center;
	gap: .375rem;
	min-height: var(--tap);
	padding: 0 var(--sp-4);
	border-radius: var(--r-pill);
	background: var(--primary-solid);
	font-size: 13px;
	font-weight: 700;
	color: var(--primary-foreground);
	transition: transform .2s var(--ease-2), background-color .2s var(--ease-2);
}

.vpe-spot__lead:hover .vpe-spot__play { transform: translateY(-2px); background: var(--primary-solid-hover); }
.vpe-spot__play .vpe-i { width: .875rem; height: .875rem; }

.vpe-spot__list {
	display: grid;
	gap: .25rem;
	list-style: none;
	align-content: start;
}

/* То же, что и для карточки выше: длинное название игры распирало
   строку списка и тянула её за край экрана. */
.vpe-spot__list > * { min-width: 0; }

.vpe-spot__link {
	display: flex;
	align-items: center;
	gap: .75rem;
	min-width: 0;
	padding: .5rem;
	border-radius: .75rem;
	transition: background-color .2s var(--ease-2);
}

.vpe-spot__link:hover { background: color-mix(in oklab, var(--surface-2) 70%, transparent); }

.vpe-spot__thumb {
	position: relative;
	flex-shrink: 0;
	display: block;
	width: 4.5rem;
	aspect-ratio: 4 / 3;
	overflow: hidden;
	border-radius: .5rem;
	background: var(--surface-2);
}

.vpe-spot__thumbimg { width: 100%; height: 100%; object-fit: cover; }

.vpe-spot__text { min-width: 0; }

.vpe-spot__name {
	display: block;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	font-size: 14px;
	font-weight: 700;
	color: var(--foreground);
}

.vpe-spot__meta {
	display: block;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	font-size: 12px;
	color: var(--muted-foreground);
}

/*
 * На узком экране название и кнопка в одну строку не помещаются, и имя
 * игры обрезается на середине слова. Ставим в столбец — название целиком
 * в две строки, кнопка под ним.
 */
@media (max-width: 559px) {
	.vpe-spot__leadbody {
		flex-direction: column;
		align-items: flex-start;
		gap: .5rem;
	}

	.vpe-spot__leadname {
		display: -webkit-box;
		-webkit-line-clamp: 2;
		-webkit-box-orient: vertical;
		white-space: normal;
		font-size: 1rem;
		line-height: 1.25;
	}
}

@media (min-width: 900px) {
	.vpe-spot__head { padding: var(--sp-6) var(--sp-6) var(--sp-4); }

	.vpe-spot__body {
		grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
		gap: var(--sp-6);
		padding: var(--sp-5) var(--sp-6) var(--sp-6);
	}

	/*
	 * Обложка тянется на всю высоту блока. С жёстким 16/9 она была на
	 * 110px ниже списка справа, и под ней оставалось пустое чёрное поле
	 * в треть блока — самая заметная дыра на главной.
	 */
	.vpe-spot__lead {
		aspect-ratio: auto;
		height: 100%;
		min-height: 22rem;
	}

	.vpe-spot__list { align-content: stretch; }
	.vpe-spot__leadname { font-size: 1.375rem; }
}

.vpe-morecard {
	position: relative;
	display: flex;
	aspect-ratio: 16 / 9;
	min-width: 0;
	cursor: pointer;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	overflow: hidden;
	border-radius: 1rem;
	border: 1px solid rgba(255, 255, 255, .1);
	background: color-mix(in oklab, var(--card) 40%, transparent);
	transition: transform .25s var(--ease-2), border-color .25s var(--ease-2), background-color .25s var(--ease-2), box-shadow .25s var(--ease-2);
}

.vpe-morecard:hover {
	transform: translateY(-2px);
	border-color: rgba(255, 255, 255, .25);
	background: color-mix(in oklab, var(--card) 60%, transparent);
	box-shadow: 0 22px 46px -22px oklch(0.62 0.235 22 / .55);
}

.vpe-morecard__icon {
	display: grid;
	place-items: center;
	width: 3rem;
	height: 3rem;
	border-radius: 999px;
	background: var(--grad-brand);
	color: #fff;
	box-shadow: 0 10px 26px -8px oklch(0.62 0.235 22 / .6);
	transition: transform .3s var(--ease-2);
}

.vpe-morecard:hover .vpe-morecard__icon { transform: scale(1.1); }
.vpe-morecard__icon .vpe-i { width: 1.25rem; height: 1.25rem; transition: transform .3s var(--ease-2); }
.vpe-morecard:hover .vpe-morecard__icon .vpe-i { transform: rotate(90deg); }

.vpe-morecard__label {
	margin-top: .5rem;
	font-size: .875rem;
	font-weight: 700;
	color: var(--muted-foreground);
	transition: color .3s var(--ease-2);
}

.vpe-morecard:hover .vpe-morecard__label { color: var(--foreground); }

/* ── 10. Daily Challenge ─────────────────────────────────────────────────── */

.vpe-daily__glow {
	pointer-events: none;
	position: absolute;
	left: -4rem;
	top: 1.5rem;
	width: 18rem;
	height: 18rem;
	border-radius: 999px;
	background: radial-gradient(circle, oklch(0.72 0.19 45 / .16), transparent 70%);
	filter: blur(40px);
}

.vpe-daily__head {
	position: relative;
	display: flex;
	flex-wrap: wrap;
	align-items: flex-end;
	justify-content: space-between;
	gap: .75rem;
}

.vpe-eyebrow {
	display: inline-flex;
	align-items: center;
	gap: .375rem;
	border-radius: 999px;
	border: 1px solid rgba(255, 255, 255, .15);
	background: rgba(255, 255, 255, .05);
	padding: .25rem .625rem;
	/* 11px было ниже читаемого на телефоне. Правило в медиазапросе выше
	   по файлу этого не перебивало: медиазапрос не добавляет веса, а
	   побеждает правило, стоящее позже. Поднимаем базовое значение. */
	font-size: 12px;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: .18em;
	color: color-mix(in oklab, var(--foreground) 70%, transparent);
}

.vpe-eyebrow .vpe-i { width: .75rem; height: .75rem; }
.vpe-eyebrow--cyan .vpe-i { color: #22d3ee; }
.vpe-eyebrow--gold .vpe-i { color: #fbbf24; fill: #fbbf24; }

.vpe-sub { margin-top: .25rem; font-size: .875rem; color: color-mix(in oklab, var(--foreground) 55%, transparent); }

.vpe-daily__chips { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; }

.vpe-chip {
	display: inline-flex;
	align-items: center;
	gap: .375rem;
	border-radius: 999px;
	padding: .375rem .75rem;
	font-size: .75rem;
	font-weight: 600;
	color: var(--muted-foreground);
	background: rgba(255, 255, 255, .08);
}

.vpe-chip .vpe-i { width: .875rem; height: .875rem; }
.vpe-chip--streak { background: rgba(255, 76, 150, .14); color: #ff7ab3; font-weight: 700; }

.vpe-daily__grid { margin-top: 1.5rem; display: grid; gap: 1rem; }

.vpe-challenge {
	position: relative;
	overflow: hidden;
	border-radius: 22px;
	border: 1px solid rgba(255, 255, 255, .1);
	background: rgba(10, 12, 30, .6);
	backdrop-filter: blur(24px);
	transition: transform .28s var(--ease-2), border-color .28s var(--ease-2), box-shadow .28s var(--ease-2);
}

.vpe-challenge:hover {
	transform: translateY(-6px);
	border-color: rgba(255, 255, 255, .25);
	box-shadow: 0 26px 56px -26px rgba(120, 80, 255, .75);
}

.vpe-challenge__line {
	pointer-events: none;
	position: absolute;
	left: 0;
	right: 0;
	top: 0;
	height: 1px;
	background: linear-gradient(90deg, transparent, oklch(0.62 0.235 22 / .65), oklch(0.8 0.16 75 / .65), transparent);
}

.vpe-challenge__top { display: flex; align-items: center; gap: .875rem; padding: 1rem; }

.vpe-challenge__thumb {
	position: relative;
	width: 4rem;
	height: 4rem;
	flex: none;
	overflow: hidden;
	border-radius: 1rem;
	border: 1px solid rgba(255, 255, 255, .1);
}

.vpe-challenge__thumb img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform .5s var(--ease-2);
}

.vpe-challenge:hover .vpe-challenge__thumb img { transform: scale(1.1); }
.vpe-challenge__body { min-width: 0; flex: 1; }

.vpe-challenge__game {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	font-size: 11px;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: .14em;
	color: color-mix(in oklab, var(--foreground) 45%, transparent);
}

.vpe-challenge__title {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	font-size: 15px;
	font-weight: 700;
	color: var(--foreground);
}

.vpe-challenge__goal {
	margin-top: .125rem;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	font-size: .75rem;
	color: var(--muted-foreground);
}

.vpe-challenge__reward {
	display: inline-flex;
	flex-shrink: 0;
	align-items: center;
	gap: .25rem;
	border-radius: .5rem;
	background: rgba(251, 191, 36, .14);
	padding: .25rem .5rem;
	font-size: 11px;
	font-weight: 800;
	color: #fbbf24;
}

.vpe-challenge__reward .vpe-i { width: .75rem; height: .75rem; }
.vpe-challenge__track { padding: 0 1rem; }

.vpe-progress {
	height: .375rem;
	width: 100%;
	overflow: hidden;
	border-radius: 999px;
	background: rgba(255, 255, 255, .08);
}

.vpe-progress__fill {
	display: block;
	height: 100%;
	border-radius: 999px;
	background: var(--grad-neon);
	transition: width .7s var(--ease-2);
}

.vpe-challenge__foot { display: flex; align-items: center; justify-content: space-between; gap: .75rem; padding: 1rem; }

.vpe-challenge__pct { font-size: .75rem; font-weight: 600; color: color-mix(in oklab, var(--foreground) 60%, transparent); }

.vpe-btn-pill {
	display: inline-flex;
	align-items: center;
	gap: .375rem;
	border-radius: 999px;
	padding: .5rem 1rem;
	font-size: .875rem;
	font-weight: 700;
	transition: transform .3s var(--ease-2), box-shadow .3s var(--ease-2);
}

.vpe-btn-pill .vpe-i { width: 1rem; height: 1rem; }

.vpe-btn-pill--play {
	background: var(--primary-solid);
	color: #fff;
	box-shadow: 0 14px 34px -16px oklch(0.62 0.235 22 / .6);
}

.vpe-btn-pill--play:hover { transform: translateY(-2px); box-shadow: 0 18px 42px -16px oklch(0.62 0.235 22 / .6); }
.vpe-btn-pill--done { background: rgba(34, 197, 94, .16); color: #4ade80; }

/* ── 11. VPE Originals ───────────────────────────────────────────────────── */

.vpe-originals__glow {
	pointer-events: none;
	position: absolute;
	left: -2.5rem;
	top: 2.5rem;
	width: 18rem;
	height: 18rem;
	border-radius: 999px;
	background: radial-gradient(circle, oklch(0.62 0.235 22 / .18), transparent 70%);
	filter: blur(40px);
}

.vpe-band {
	position: relative;
	overflow: hidden;
	border-top: 1px solid rgba(255, 255, 255, .1);
	border-bottom: 1px solid rgba(255, 255, 255, .1);
	background: rgba(10, 12, 30, .6);
	padding: 1.75rem 1rem;
	backdrop-filter: blur(24px);
}

.vpe-band__line {
	pointer-events: none;
	position: absolute;
	left: 0;
	right: 0;
	top: 0;
	height: 1px;
	background: linear-gradient(90deg, transparent, oklch(0.62 0.235 22 / .7), oklch(0.72 0.19 45 / .7), oklch(0.8 0.16 75 / .7), transparent);
}

/* Заголовок красится цветом, а не заливкой текста градиентом: у длинной
   строки контраст переливом уезжает к середине. */
.vpe-h2--grad { color: oklch(0.72 0.2 30); }

.vpe-scroller {
	margin-top: 1.5rem;
	display: flex;
	gap: 1rem;
	overflow-x: auto;
	padding-bottom: .75rem;
	scroll-snap-type: x proximity;
}

.vpe-original {
	position: relative;
	width: 200px;
	flex: none;
	scroll-snap-align: start;
	cursor: pointer;
	overflow: hidden;
	border-radius: 22px;
	border: 1px solid rgba(255, 255, 255, .1);
	transition: transform .28s var(--ease-2), border-color .28s var(--ease-2), box-shadow .28s var(--ease-2);
}

.vpe-original:hover {
	transform: translateY(-8px);
	border-color: transparent;
	box-shadow: 0 28px 60px -24px rgba(180, 60, 255, .75);
}

.vpe-original__ring {
	pointer-events: none;
	position: absolute;
	inset: 0;
	z-index: 20;
	border-radius: 22px;
	opacity: 0;
	padding: 1.5px;
	background: var(--grad-neon);
	-webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
	-webkit-mask-composite: xor;
	mask-composite: exclude;
	transition: opacity .3s var(--ease-2);
}

.vpe-original:hover .vpe-original__ring { opacity: 1; }
.vpe-original__media { position: relative; aspect-ratio: 3 / 4; overflow: hidden; }

.vpe-original__img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform .5s var(--ease-2);
}

.vpe-original:hover .vpe-original__img { transform: scale(1.07); }

.vpe-original__shade {
	pointer-events: none;
	position: absolute;
	inset: 0;
	background: linear-gradient(to top, rgba(6, 8, 24, .95) 10%, rgba(6, 8, 24, .35) 45%, transparent 75%);
}

.vpe-original__rank {
	position: absolute;
	left: .625rem;
	top: .625rem;
	display: inline-flex;
	align-items: center;
	gap: .25rem;
	border-radius: .375rem;
	background: rgba(6, 8, 24, .6);
	padding: .25rem .5rem;
	font-size: 10px;
	font-weight: 800;
	text-transform: uppercase;
	letter-spacing: .05em;
	color: color-mix(in oklab, var(--foreground) 85%, transparent);
	backdrop-filter: blur(12px);
}

.vpe-original__tag { left: auto; right: .625rem; top: .625rem; }
.vpe-original__body { position: absolute; left: 0; right: 0; bottom: 0; padding: .875rem; }

.vpe-original__title {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	font-size: 15px;
	font-weight: 700;
	color: var(--foreground);
}

.vpe-original__meta {
	margin-top: .25rem;
	display: flex;
	align-items: center;
	gap: .5rem;
	font-size: 11px;
	color: color-mix(in oklab, var(--foreground) 60%, transparent);
}

.vpe-original__dot { width: .25rem; height: .25rem; border-radius: 999px; background: color-mix(in oklab, var(--foreground) 30%, transparent); }
.vpe-original__meta span { display: inline-flex; align-items: center; gap: .25rem; }
.vpe-original__meta .vpe-i { width: .75rem; height: .75rem; }

.vpe-original__cta {
	margin-top: .75rem;
	display: flex;
	height: 2.5rem;
	align-items: center;
	justify-content: center;
	gap: .375rem;
	border-radius: 999px;
	background: var(--grad-brand);
	font-size: 13px;
	font-weight: 700;
	color: #fff;
	opacity: 0;
	transform: translateY(8px);
	box-shadow: 0 14px 30px -12px oklch(0.62 0.235 22 / .6);
	transition: opacity .3s var(--ease-2), transform .3s var(--ease-2);
}

.vpe-original:hover .vpe-original__cta { opacity: 1; transform: translateY(0); }
.vpe-original__cta .vpe-i { width: .875rem; height: .875rem; }

/* ── 12. Leaderboards ────────────────────────────────────────────────────── */

.vpe-lb { position: relative; overflow: hidden; border-top: 1px solid rgba(255, 255, 255, .1); border-bottom: 1px solid rgba(255, 255, 255, .1); }

.vpe-lb__bg { pointer-events: none; position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

.vpe-lb__overlay {
	pointer-events: none;
	position: absolute;
	inset: 0;
	background: linear-gradient(100deg, rgba(8, 10, 28, .95) 0%, rgba(8, 10, 28, .86) 45%, rgba(8, 10, 28, .6) 100%);
}

.vpe-lb__inner { position: relative; padding: 1.75rem 1rem; }

.vpe-lb__head { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem 1rem; }

.vpe-lb__trophy {
	display: grid;
	place-items: center;
	width: 2.75rem;
	height: 2.75rem;
	border-radius: 1rem;
	background: var(--grad-top);
	color: #231603;
	box-shadow: 0 12px 30px -12px rgba(251, 191, 36, .9);
}

.vpe-lb__trophy .vpe-i { width: 1.5rem; height: 1.5rem; }
.vpe-lb__title { display: inline-flex; align-items: center; gap: .375rem; }
.vpe-chip--season { background: rgba(34, 197, 94, .15); color: #4ade80; font-weight: 700; }
.vpe-chip--plain { background: rgba(255, 255, 255, .1); }
.vpe-lb__note { font-size: .875rem; color: var(--muted-foreground); }
.vpe-lb__scroller { margin-top: 1.25rem; gap: .875rem; }

.vpe-lbcard {
	position: relative;
	width: 230px;
	flex: none;
	scroll-snap-align: start;
	cursor: pointer;
	overflow: hidden;
	border-radius: 1rem;
	border: 1px solid rgba(255, 255, 255, .1);
	background: rgba(12, 14, 36, .7);
	backdrop-filter: blur(24px);
	transition: transform .25s var(--ease-2), border-color .25s var(--ease-2), box-shadow .25s var(--ease-2);
}

.vpe-lbcard:hover {
	transform: translateY(-6px);
	border-color: rgba(255, 255, 255, .3);
	box-shadow: 0 22px 46px -22px rgba(251, 191, 36, .6);
}

.vpe-lbcard__media { position: relative; aspect-ratio: 16 / 10; overflow: hidden; }

.vpe-lbcard__img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform .4s var(--ease-2);
}

.vpe-lbcard:hover .vpe-lbcard__img { transform: scale(1.06); }

.vpe-lbcard__shade {
	pointer-events: none;
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	height: 60%;
	background: linear-gradient(to top, rgba(8, 10, 28, .94), transparent);
}

.vpe-lbcard__rank {
	position: absolute;
	right: .5rem;
	top: .5rem;
	border-radius: .375rem;
	background: rgba(8, 10, 28, .7);
	padding: .125rem .5rem;
	font-size: 10px;
	font-weight: 700;
	color: #fbbf24;
	backdrop-filter: blur(12px);
}

.vpe-lbcard__play {
	position: absolute;
	inset: 0;
	display: grid;
	place-items: center;
	background: rgba(8, 10, 28, .35);
	opacity: 0;
	backdrop-filter: blur(2px);
	transition: opacity .3s var(--ease-2);
}

.vpe-lbcard:hover .vpe-lbcard__play { opacity: 1; }

.vpe-lbcard__play span {
	display: grid;
	place-items: center;
	width: 3rem;
	height: 3rem;
	border-radius: 999px;
	background: var(--grad-brand);
	color: #fff;
}

.vpe-lbcard__foot { display: flex; align-items: center; justify-content: space-between; gap: .5rem; padding: .625rem .875rem; }

.vpe-lbcard__title {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	font-size: .875rem;
	font-weight: 700;
	color: var(--foreground);
}

.vpe-lbcard__score { flex-shrink: 0; font-size: .75rem; font-weight: 600; color: var(--muted-foreground); }

/* ── 13. Подвал ──────────────────────────────────────────────────────────── */

.vpe-footer { position: relative; margin-top: var(--sp-12); width: auto; overflow: hidden; border-radius: var(--r-xl); padding: 1px; }

.vpe-footer__inner {
	position: relative;
	overflow: hidden;
	border-radius: calc(var(--r-xl) - 1px);
	background: color-mix(in oklab, var(--surface) 60%, transparent);
	backdrop-filter: blur(24px);
}

.vpe-footer__glow-a, .vpe-footer__glow-b { pointer-events: none; position: absolute; border-radius: 999px; filter: blur(100px); }
.vpe-footer__glow-a { left: -5rem; top: -5rem; width: 22rem; height: 22rem; opacity: .3; }
.vpe-footer__glow-b { right: 0; bottom: -6rem; width: 20rem; height: 20rem; background: oklch(0.78 0.16 68 / 0.12); }

/* Подвал вдвое ниже: колонок стало больше, а высоту задавала самая
   длинная из них — список категорий на двенадцать строк. */
.vpe-footer__pad { position: relative; padding: 1.5rem 1.25rem; }

.vpe-footer__topline {
	pointer-events: none;
	position: absolute;
	left: 2.5rem;
	right: 2.5rem;
	top: 0;
	height: 1px;
	background-image: var(--grad-neon);
	opacity: .4;
}

.vpe-footer__grid { display: grid; gap: 1.5rem; }

.vpe-footer__brandname { font-size: 1.125rem; font-weight: 900; letter-spacing: -.025em; color: var(--foreground); }

/*
 * Знак и название материнского бренда переносятся на вторую строку, если
 * колонка узкая. Раньше строка не переносилась и «VPEsports» наезжало на
 * заголовок соседней колонки подвала.
 */
.vpe-footer .vpe-logo { flex-wrap: wrap; row-gap: var(--sp-1); }

.vpe-footer__about {
	margin-top: 1rem;
	max-width: 20rem;
	font-size: .875rem;
	line-height: 1.625;
	color: var(--muted-foreground);
}

.vpe-socials { margin-top: 1.5rem; display: flex; flex-wrap: wrap; align-items: center; gap: .75rem; }

.vpe-social {
	display: grid;
	place-items: center;
	width: 2.5rem;
	height: 2.5rem;
	border-radius: .75rem;
	border: 1px solid rgba(255, 255, 255, .1);
	background: color-mix(in oklab, var(--surface-2) 50%, transparent);
	color: var(--muted-foreground);
	transition: transform .3s var(--ease), border-color .3s var(--ease), color .3s var(--ease), box-shadow .3s var(--ease);
}

.vpe-social:hover {
	transform: scale(1.05);
	border-color: color-mix(in oklab, var(--primary) 40%, transparent);
	color: var(--primary);
	box-shadow: 0 0 0 1px color-mix(in oklab, var(--primary) 25%, transparent),
		0 8px 30px -8px color-mix(in oklab, var(--primary) 55%, transparent);
}

.vpe-social .vpe-i { width: 18px; height: 18px; transition: transform .3s var(--ease); }
.vpe-social:hover .vpe-i { transform: scale(1.1); }

.vpe-footer__title {
	display: flex;
	align-items: center;
	gap: .5rem;
	font-size: .75rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: .18em;
	color: var(--foreground);
}

.vpe-footer__title .vpe-i { width: 1rem; height: 1rem; color: var(--primary); }

/*
 * Списки в две колонки и с плотным шагом. В одну колонку высоту подвала
 * задавал самый длинный список, и ради восьми ссылок страница получала
 * шестьсот пикселей почти пустого места.
 */
/*
 * Список ссылок сам решает, влезают ли два столбца. Жёсткие два столбца
 * в колонке подвала на 1024 давали по 60px на столбец: «All games»
 * переносилось по слову, и весь подвал читался как сломанный.
 */
.vpe-footer__list {
	margin-top: .875rem;
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr));
	gap: .375rem 1rem;
}

.vpe-footer__link {
	position: relative;
	display: inline-flex;
	align-items: center;
	gap: .5rem;
	font-size: .875rem;
	color: var(--muted-foreground);
	transition: color .3s var(--ease);
	justify-self: start;
}

.vpe-footer__link:hover { color: var(--foreground); }
.vpe-footer__link span { position: relative; }

.vpe-footer__link span::after {
	content: "";
	position: absolute;
	left: 0;
	bottom: -2px;
	height: 2px;
	width: 0;
	border-radius: 999px;
	background: var(--primary);
	transition: width .3s var(--ease);
}

.vpe-footer__link:hover span::after { width: 100%; }

.vpe-news {
	margin-top: 2rem;
	border-radius: 1rem;
	border: 1px solid rgba(255, 255, 255, .1);
	background: color-mix(in oklab, var(--surface-2) 40%, transparent);
	padding: 1rem;
}

.vpe-news__title { font-size: .875rem; font-weight: 700; color: var(--foreground); }
.vpe-news__text { margin-top: .25rem; font-size: .75rem; color: var(--muted-foreground); }
.vpe-news__form { margin-top: .75rem; display: flex; align-items: center; gap: .5rem; }
.vpe-news__field { position: relative; flex: 1; }

.vpe-news__icon {
	pointer-events: none;
	position: absolute;
	left: .75rem;
	top: 50%;
	transform: translateY(-50%);
	color: var(--muted-foreground);
}

.vpe-news__input {
	width: 100%;
	border-radius: .75rem;
	border: 1px solid rgba(255, 255, 255, .1);
	background: color-mix(in oklab, var(--surface) 70%, transparent);
	padding: .625rem .75rem .625rem 2.25rem;
	font-size: .875rem;
	color: var(--foreground);
	outline: none;
	transition: border-color .3s var(--ease), box-shadow .3s var(--ease);
}

.vpe-news__input::placeholder { color: var(--muted-foreground); }

.vpe-news__input:focus {
	border-color: color-mix(in oklab, var(--primary) 50%, transparent);
	box-shadow: 0 0 0 1px color-mix(in oklab, var(--primary) 25%, transparent),
		0 8px 30px -8px color-mix(in oklab, var(--primary) 55%, transparent);
}

.vpe-news__send {
	display: grid;
	place-items: center;
	width: 2.5rem;
	height: 2.5rem;
	flex-shrink: 0;
	border-radius: .75rem;
	background-image: var(--grad-neon);
	color: var(--primary-foreground);
	box-shadow: 0 0 0 1px color-mix(in oklab, var(--primary) 25%, transparent),
		0 8px 30px -8px color-mix(in oklab, var(--primary) 55%, transparent);
	transition: box-shadow .3s var(--ease);
}

.vpe-news__send:hover {
	box-shadow: 0 0 0 1px color-mix(in oklab, var(--primary) 40%, transparent),
		0 14px 45px -8px color-mix(in oklab, var(--primary) 75%, transparent);
}

.vpe-news__send .vpe-i { width: 1rem; height: 1rem; transition: transform .3s var(--ease); }
.vpe-news__send:hover .vpe-i { transform: translate(2px, -2px); }

.vpe-footer__bottom {
	position: relative;
	margin-top: 1.25rem;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	border-top: 1px solid rgba(255, 255, 255, .1);
	padding: 1.5rem .5rem 0;
}

.vpe-footer__copy { font-size: .75rem; color: var(--muted-foreground); }

.vpe-footer__legal {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: 1rem;
	font-size: .75rem;
	color: var(--muted-foreground);
}

.vpe-footer__legal a { transition: color .3s var(--ease); }
.vpe-footer__legal a:hover { color: var(--foreground); }

/* ── 14. Адаптив ─────────────────────────────────────────────────────────── */

/* sm: 640px */
@media (min-width: 640px) {
	:root { --gutter: 1.5rem; }
	.vpe-hero__grid { padding: 1.5rem 1.75rem; }
	.vpe-hero__title { font-size: 3rem; }
	.vpe-h2 { font-size: 1.875rem; }
	.vpe-row__title { font-size: 1.5rem; }
	.vpe-grid-popular { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.vpe-row__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
	.vpe-daily__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.vpe-band { padding-left: 1.5rem; padding-right: 1.5rem; }
	.vpe-lb__inner { padding-left: 1.5rem; padding-right: 1.5rem; }
	.vpe-original { width: 220px; }
	.vpe-footer__pad { padding-left: 1.75rem; padding-right: 1.75rem; }
	.vpe-footer__bottom { flex-direction: row; }
}

/* md: 768px */
@media (min-width: 768px) {
	.vpe-footer__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* lg: 1024px — появляется сайдбар и десктопная шапка */
@media (min-width: 1024px) {
	:root { --gutter: 2rem; }

	/*
	 * Промежутки на этой ширине узкие намеренно. При 1.5rem логотип,
	 * меню, поиск и кнопки в 1024 не помещались: поиск заканчивался на
	 * 1062-м пикселе, кнопка избранного на 1144-м — то есть за краем
	 * экрана. Просторнее становится с 1280.
	 */
	.vpe-header__inner {
		display: flex;
		gap: .75rem;
		padding-left: 0;
		padding-right: 1.25rem;
	}

	/* Только логотип шапки: в подвале рядом стоит название, и жёсткая
	   ширина колонки там сплющивала знак. */
	.vpe-header .vpe-logo { width: auto; justify-content: flex-start; }
	.vpe-header .vpe-logo__img { height: 2rem; }
	/*
	 * Меню не сжимается, сжимается поиск. Иначе flex ужимал сам блок
	 * меню, а его пункты оставались прежней ширины и наезжали на поиск —
	 * по кнопке «Categories» нельзя было попасть, клик перехватывало
	 * поле ввода.
	 */
	.vpe-nav { display: flex; flex-shrink: 0; }
	.vpe-search { display: block; flex: 1 1 auto; min-width: 8.75rem; }
	.vpe-burger { display: none; }

	/* Правая часть шапки: раньше там был только бургер, скрытый на
	   десктопе, и половина полосы пустовала. */
	.vpe-act { display: inline-flex; }

	/* «Surprise me» появляется, когда для него есть место: на 1024
	   вторая кнопка выдавливает поиск за край. Ссылка при этом никуда
	   не девается — она есть в сайдбаре. */
	.vpe-act--ghost { display: none; }
	.vpe-mobile { display: none; }
	.vpe-sidebar { display: block; }

	/* Иллюстрация видна целиком: карточек справа больше нет.
	   Высота уменьшена с 640px — под текст столько не нужно. */
	.vpe-hero__inner { min-height: 440px; }
	.vpe-hero__grid { padding: 1.75rem 2.5rem 2.5rem; min-height: 440px; }
	.vpe-row__grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
	.vpe-band { padding-left: 2rem; padding-right: 2rem; }
	.vpe-lb__inner { padding-left: 2rem; padding-right: 2rem; }
	.vpe-footer__pad { padding: 1.75rem 2.5rem; }
	/* Четыре колонки вместо трёх: место, которое занимала нарисованная
	   форма подписки, отдано настоящим разделам каталога. */
	/*
	 * Колонки одинаковой ширины: каждая вмещает список в два столбца,
	 * и самый длинный из них теперь четыре строки вместо восьми.
	 * Именно длина списка и задавала высоту всего подвала.
	 */
	/*
	 * На 1024 колонка контента сузилась сайдбаром до ~650px, и пятиколоночный
	 * подвал давал по 139px на колонку. Здесь остаются две колонки из
	 * предыдущей ступени, а разбивка на пять переезжает на 1280.
	 */
	.vpe-footer__grid { gap: 1.5rem 2rem; }
}

/* xl: 1280px */
@media (min-width: 1280px) {
	/*
	 * Пять колонок подвала одной строкой. Прежняя запись — сетка на 12
	 * колонок и пять блоков по span 3 — давала 15 колонок из 12: пятый
	 * блок «Company» переносился на вторую строку, и справа от него
	 * оставалось пустое поле в три четверти ширины подвала.
	 */
	.vpe-footer__grid { grid-template-columns: 1.4fr repeat(4, minmax(0, 1fr)); }

	.vpe-hero__grid { padding: 2.5rem 3rem; }
	.vpe-hero__title { font-size: 3.75rem; }

	/* Вторая кнопка появляется, когда для неё есть место. Ссылка на
	   случайную игру при этом не теряется — она есть в сайдбаре. */
	.vpe-act--ghost { display: inline-flex; }

	.vpe-header__inner { gap: 1.25rem; padding-right: 2rem; }
	
	.vpe-header .vpe-logo__img { height: 2.25rem; }
	.vpe-grid-popular { grid-template-columns: repeat(4, minmax(0, 1fr)); }

	/* Пять колонок вместо семи: при семи карточка выходила 157×89, и
	   обложка игры в ней просто не читалась. */
	.vpe-row__grid { grid-template-columns: repeat(5, minmax(0, 1fr)); }
	.vpe-daily__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (prefers-reduced-motion: reduce) {
	*, *::before, *::after {
		animation-duration: .01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: .01ms !important;
		scroll-behavior: auto !important;
	}
}

/* ── 15. Каталог: архивы, категории, поиск, 404 ──────────────────────────── */

.vpe-h1 { font-size: 2rem; font-weight: 900; letter-spacing: -.025em; color: var(--foreground); }

.vpe-archive__head { margin-bottom: 1.5rem; }
.vpe-archive__intro { margin-top: .75rem; max-width: 60ch; font-size: .95rem; line-height: 1.65; color: var(--muted-foreground); }

/*
 * Шапка раздела с обложкой. У категорий появилась своя иллюстрация, и
 * ей нужно место, которое не отодвигает игры за пределы экрана.
 *
 * До 900px — одна колонка: сначала заголовок и вводный текст, потом
 * картинка. Наоборот нельзя: сверху телефона должно быть написано, куда
 * человек попал, а не стоять декоративный кадр во весь экран.
 *
 * С 900px — две колонки, картинка справа и не шире 320px. Собственное
 * соотношение 4:3 сохраняется, поэтому кадр не режется.
 */
.vpe-archive__head--cover {
	display: grid;
	gap: var(--sp-5);
	align-items: center;
}

.vpe-archive__headtext { min-width: 0; }

/*
 * Рамка держит соотношение 4:3 сама, а картинка кроется по ней. Без
 * этого высота блока зависела бы от того, какой подразмер выбрал
 * браузер, и на соседних категориях шапка стояла бы на разной высоте.
 */
.vpe-archive__cover {
	position: relative;
	overflow: hidden;
	aspect-ratio: 4 / 3;
	border: 1px solid var(--border);
	border-radius: var(--r-lg);
	background: var(--surface-2);
}

.vpe-archive__coverimg {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* Та же завеса, что у плиток витрины: набор обложек читается как один. */
.vpe-archive__cover::after {
	content: "";
	position: absolute;
	inset: 0;
	background: linear-gradient(to top, rgba(6, 8, 20, .55), transparent 60%);
}

.vpe-gamecard__img.cgimg-placeholder { object-fit: cover; }

@media (min-width: 900px) {
	.vpe-archive__head--cover {
		grid-template-columns: minmax(0, 1fr) minmax(0, 22rem);
		gap: var(--sp-8);
	}
}

/*
 * Заголовок сетки — служебный уровень между h1 и карточками, и звучать
 * он должен тише h1, иначе на странице два заголовка спорят за главный.
 * Размер как у названия ряда на главной, цвет приглушённый.
 */
.vpe-archive__gridtitle {
	margin-top: 1.75rem;
	font-size: 1.125rem;
	font-weight: 700;
	letter-spacing: 0;
	color: var(--muted-foreground);
}

.vpe-archive__gridtitle + .vpe-grid-popular { margin-top: .875rem; }

.vpe-crumbs { margin-bottom: 1rem; font-size: .8125rem; color: var(--muted-foreground); }
.vpe-crumbs ol { display: flex; flex-wrap: wrap; gap: .5rem; margin: 0; padding: 0; list-style: none; }
.vpe-crumbs li { display: inline-flex; gap: .5rem; align-items: center; }
.vpe-crumbs a { transition: color .3s var(--ease); }
.vpe-crumbs a:hover { color: var(--foreground); }
.vpe-crumbs [aria-current] { color: color-mix(in oklab, var(--foreground) 80%, transparent); }

/*
 * Ровно две строки: и обрезка, и минимальная высота. Клампа без
 * min-height не хватало — у короткого описания плашка была на строку
 * ниже соседней, и ряд карточек шёл ступеньками.
 */
.vpe-gamecard__excerpt {
	font-size: var(--fs-sm);
	line-height: 1.45;
	min-height: 2.9em;
	color: var(--muted-foreground);
	display: -webkit-box;
	-webkit-line-clamp: 2;
	line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

.vpe-gamecard__title a { color: inherit; }

/*
 * Плитка без обложки. Раньше это была фирменная заливка на 35% — яркое
 * цветное пятно там, где картинки как раз нет, привлекало больше внимания,
 * чем игры с обложкой. Теперь спокойная поверхность в тон карточки.
 */
.vpe-gamecard__ph {
	display: block;
	width: 100%;
	height: 100%;
	background:
		repeating-linear-gradient(135deg, rgba(255, 255, 255, .03) 0 10px, transparent 10px 20px),
		var(--surface-2);
}
a.vpe-genre { text-decoration: none; }

/* Пагинация */
/*
 * Заголовок «Games navigation» WordPress выводит для программ чтения с
 * экрана классом screen-reader-text. В теме этого класса не было вовсе,
 * и служебная подпись висела над кнопками как обычный заголовок.
 */
.screen-reader-text {
	position: absolute !important;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip: rect(0 0 0 0);
	white-space: nowrap;
	border: 0;
}

.vpe-pagination { margin-top: 2.5rem; padding-bottom: 1rem; }

/* По центру: страничные кнопки — единственное, ради чего сюда доходят
   глазами, и искать их у левого края неудобно. */
.vpe-pagination .nav-links {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	align-items: center;
	gap: .5rem;
}

.vpe-pagination .page-numbers {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 2.75rem;
	height: 2.75rem;
	padding: 0 .875rem;
	border-radius: 999px;
	border: 1px solid rgba(255, 255, 255, .1);
	background: rgba(255, 255, 255, .04);
	font-size: .9375rem;
	font-weight: 700;
	color: color-mix(in oklab, var(--foreground) 75%, transparent);
	transition: transform .25s var(--ease-2), border-color .25s var(--ease-2), background-color .25s var(--ease-2), color .25s var(--ease-2);
}

.vpe-pagination .page-numbers:hover {
	transform: translateY(-2px);
	border-color: rgba(255, 255, 255, .25);
	background: rgba(255, 255, 255, .08);
	color: var(--foreground);
}

.vpe-pagination .page-numbers.current {
	border-color: transparent;
	background: var(--primary-solid);
	color: #fff;
	box-shadow: 0 10px 28px -10px oklch(0.62 0.235 22 / .55);
}

/* Пустые состояния и 404 */
.vpe-empty {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: .75rem;
	max-width: 46rem;
	margin: 2rem 0;
	padding: 2rem;
	border: 1px solid rgba(255, 255, 255, .1);
	border-radius: 22px;
	background: rgba(10, 12, 30, .6);
}

.vpe-empty--404 { align-items: flex-start; }
.vpe-404__search { display: flex; flex-wrap: wrap; gap: .5rem; width: 100%; margin-top: .5rem; }
.vpe-404__search .vpe-news__input { flex: 1 1 14rem; padding-left: .875rem; }
.vpe-404__links { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: .25rem; }

/*
 * Кнопки на 404 — тот же компонент, что и на первом экране главной,
 * но внутри панели у неё уже есть свой gap .75rem: собственный отступ
 * hero-версии в 1.5rem складывался бы с ним в разрыв на две строки.
 */
.vpe-404__cta { margin-top: .25rem; }

/*
 * Поиск на 404 — это первое, к чему тянется палец, а высота у поля и
 * кнопки набиралась одними отступами: 43px и 37px по замеру попаданием
 * на 390px. Ниже 44px тач-цель не должна опускаться, и в этой теме такое
 * ограничение уже стоит на .vpe-tagchip ровно в этой же границе ширины.
 */
@media (max-width: 1023px) {
	.vpe-404__search .vpe-news__input,
	.vpe-404__search .vpe-btn-pill {
		min-height: 44px;
	}
}

/* Длинный SEO-текст под сеткой */
.vpe-seo-body {
	max-width: 70ch;
	margin-top: 3rem;
	padding-top: 2rem;
	border-top: 1px solid rgba(255, 255, 255, .1);
	font-size: .95rem;
	line-height: 1.75;
	color: var(--muted-foreground);
}

.vpe-seo-body h2, .vpe-seo-body h3 { margin: 1.5rem 0 .5rem; color: var(--foreground); font-weight: 800; }
.vpe-seo-body h2 { font-size: 1.25rem; }
.vpe-seo-body h3 { font-size: 1.0625rem; }
.vpe-seo-body p { margin-bottom: 1rem; }
.vpe-seo-body a { color: var(--primary); text-decoration: underline; text-underline-offset: 2px; }
.vpe-seo-body ul, .vpe-seo-body ol { margin: 0 0 1rem 1.25rem; }
.vpe-seo-body li { margin-bottom: .375rem; }

.vpe-chips-nav { margin-top: 2rem; }
.vpe-chips-nav .vpe-h2 { margin-bottom: 1rem; }

@media (max-width: 767px) {
	.vpe-h1 { font-size: 1.5rem; }
	.vpe-empty { padding: 1.25rem; }
}

/* ── 16. Страница игры ───────────────────────────────────────────────────── */

.vpe-game__head { margin-bottom: 1.25rem; }
.vpe-game__intro { margin-top: .75rem; max-width: 70ch; font-size: 1rem; line-height: 1.65; color: var(--muted-foreground); }

.vpe-player { margin-bottom: 1.5rem; }

.vpe-player__stage {
	position: relative;
	overflow: hidden;
	border-radius: 20px;
	border: 1px solid rgba(255, 255, 255, .1);
	background: rgba(8, 10, 28, .85);
	aspect-ratio: var(--vpe-ratio, 16 / 9);
	display: grid;
	place-items: center;

	/* Без потолка по высоте широкий экран даёт плеер под 900px: игра и
	   преролл провайдера просто не помещаются в окно. Ограничиваем высоту
	   и центрируем сцену — ширина подстраивается под соотношение сторон. */
	max-height: calc(100vh - 13rem);
	margin: 0;
	width: 100%;
	max-width: calc((100vh - 13rem) * var(--vpe-ratio-num, 1.7778));
}

.vpe-player__poster { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

/*
 * Завеса поверх постера — нейтральный чёрный с виньеткой к краям, а не
 * ровная сине-фиолетовая пелена: она перекрашивала обложку игры и весь
 * экран запуска уходил в лиловый.
 */
.vpe-player__veil {
	position: absolute;
	inset: 0;
	background:
		radial-gradient(60% 60% at 50% 50%, rgba(0, 0, 0, .35), rgba(0, 0, 0, .72) 100%),
		rgba(0, 0, 0, .2);
}

.vpe-player__frame { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; display: block; background: #000; }

.vpe-player__stage.is-playing .vpe-player__poster,
.vpe-player__stage.is-playing .vpe-player__veil { display: none; }

.vpe-player__start {
	position: relative;
	display: inline-flex;
	align-items: center;
	gap: .75rem;
	min-height: 56px;
	padding: 0 var(--sp-8);
	border-radius: var(--r-pill);
	background: var(--primary-solid);
	font-size: 1.0625rem;
	font-weight: 800;
	color: var(--primary-foreground);
	box-shadow: var(--sh-3);
	transition: transform .25s var(--ease), box-shadow .25s var(--ease), background-color .25s var(--ease);
}

.vpe-player__start:hover { transform: translateY(-3px); background: var(--primary-solid-hover); }
.vpe-player__start:active { transform: translateY(0) scale(.98); background: var(--primary-solid-active); }

.vpe-player__start-icon {
	display: grid;
	place-items: center;
	width: 2rem;
	height: 2rem;
	border-radius: 999px;
	background: rgba(255, 255, 255, .2);
}

.vpe-player__loading, .vpe-player__failed {
	position: relative;
	max-width: 34rem;
	padding: 0 1rem;
	text-align: center;
	font-size: .9375rem;
	color: var(--muted-foreground);
}

.vpe-player__failed { color: #ff9aa8; }

.vpe-player__stage--off { background: rgba(10, 12, 30, .75); }
.vpe-player__off { position: relative; display: flex; flex-direction: column; align-items: center; gap: .75rem; padding: 2rem; text-align: center; }
.vpe-player__off .vpe-sub { max-width: 44ch; }

/*
 * Панель ровно по ширине плеера. Раньше она растягивалась на всю ширину
 * страницы, а сама игра стоит по центру и уже — кнопки разъезжались к
 * краям экрана, между ними была пустая полоса в половину монитора.
 *
 * Ширину задаёт то же правило, что и сцене: потолок по высоте окна,
 * пересчитанный в ширину через соотношение сторон игры.
 */
.vpe-player__bar {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: var(--sp-2);
	margin: var(--sp-3) 0 0;
	width: 100%;
	max-width: calc((100vh - 13rem) * var(--vpe-ratio-num, 1.7778));
}

.vpe-player__group { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; }

.vpe-player__btn {
	display: inline-flex;
	align-items: center;
	gap: .5rem;
	min-height: 44px;
	padding: 0 1rem;
	border-radius: 999px;
	border: 1px solid rgba(255, 255, 255, .1);
	background: rgba(255, 255, 255, .04);
	font-size: .875rem;
	font-weight: 600;
	color: color-mix(in oklab, var(--foreground) 80%, transparent);
	transition: transform .25s var(--ease-2), border-color .25s var(--ease-2), background-color .25s var(--ease-2), color .25s var(--ease-2);
}

.vpe-player__btn:hover:not(:disabled) { transform: translateY(-2px); border-color: rgba(255, 255, 255, .25); background: rgba(255, 255, 255, .08); color: var(--foreground); }
.vpe-player__btn.is-on { border-color: transparent; background: var(--grad-top); color: #231603; }
.vpe-player__btn .vpe-i { width: 1rem; height: 1rem; }

/* Кнопка видна и до запуска, но неактивна: разворачивать и
   перезагружать нечего, пока игра не открыта. */
.vpe-player__btn:disabled { opacity: .45; cursor: not-allowed; }

.vpe-player__btn.is-done {
	border-color: transparent;
	background: color-mix(in oklab, var(--online) 22%, transparent);
	color: var(--online);
}

/*
 * Театральный режим: игра во всю ширину колонки контента.
 *
 * Отрицательное поле считалось от переменной --vpe-pad-left, которую
 * никто не выставлял: она разворачивалась в 0px, и кнопка «Theater mode»
 * только убирала скругление. Теперь поля берутся из того же --gutter,
 * что и у самой секции, а потолок по высоте поднимается — иначе шире
 * плеер всё равно не станет.
 */
.vpe-game.is-theater .vpe-player {
	margin-left: calc(var(--gutter) * -1);
	margin-right: calc(var(--gutter) * -1);
}

.vpe-game.is-theater .vpe-player__stage {
	border-radius: 0;
	border-left: 0;
	border-right: 0;
	max-height: calc(100vh - 6rem);
	max-width: calc((100vh - 6rem) * var(--vpe-ratio-num, 1.7778));
}

.vpe-game.is-theater .vpe-player__bar {
	max-width: none;
	padding-left: var(--gutter);
	padding-right: var(--gutter);
}

/* Жалоба */
.vpe-report {
	margin: 0 0 1.5rem;
	padding: 1.25rem;
	border: 1px solid rgba(255, 255, 255, .1);
	border-radius: 18px;
	background: rgba(10, 12, 30, .6);
}

.vpe-report__row { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: .75rem; }
.vpe-report__row .vpe-news__input { flex: 1 1 12rem; padding-left: .875rem; }
.vpe-report__status { margin-top: .75rem; font-size: .875rem; color: var(--muted-foreground); }

/* Текст и метаданные */
.vpe-game__body { display: grid; gap: 2rem; margin-top: 2rem; }
.vpe-game__block { margin-bottom: 2rem; }
.vpe-game__block .vpe-h2 { margin-bottom: .75rem; }
.vpe-game__block .vpe-seo-body { margin-top: 0; padding-top: 0; border-top: 0; }

.vpe-controls { display: grid; gap: 1.25rem; }
.vpe-controls__title { margin-bottom: .5rem; font-size: .8125rem; font-weight: 800; text-transform: uppercase; letter-spacing: .14em; color: color-mix(in oklab, var(--foreground) 55%, transparent); }
.vpe-controls__list { margin: 0; padding-left: 1.1rem; color: var(--muted-foreground); font-size: .9375rem; line-height: 1.7; }

.vpe-features { display: grid; gap: .5rem; margin: 0; padding: 0; list-style: none; }
.vpe-features li { display: flex; align-items: flex-start; gap: .625rem; font-size: .9375rem; color: var(--muted-foreground); }
.vpe-features .vpe-i { width: 1rem; height: 1rem; margin-top: .25rem; flex: none; color: #4ade80; }

.vpe-game__aside {
	align-self: start;
	padding: 1.25rem;
	border: 1px solid rgba(255, 255, 255, .1);
	border-radius: 18px;
	background: rgba(10, 12, 30, .6);
}

.vpe-game__aside .vpe-h2 { margin-bottom: .75rem; font-size: 1.125rem; }
.vpe-meta { display: grid; grid-template-columns: auto 1fr; gap: .5rem 1rem; margin: 0; font-size: .875rem; }
.vpe-meta dt { color: color-mix(in oklab, var(--foreground) 50%, transparent); }
.vpe-meta dd { margin: 0; color: var(--foreground); }
.vpe-meta a { color: var(--primary); }

@media (min-width: 1024px) {
	.vpe-game__body { grid-template-columns: minmax(0, 1fr) 20rem; }
	.vpe-controls { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 767px) {
	.vpe-player__start { min-height: 48px; padding: 0 1.25rem; font-size: .9375rem; }
	.vpe-game__aside { padding: 1rem; }
}

/* Тач-цели крошек: на телефоне 20px по высоте не хватает для пальца. */
@media (max-width: 1023px) {
	.vpe-crumbs li a,
	.vpe-crumbs li [aria-current] {
		display: inline-flex;
		align-items: center;
		min-height: 44px;
	}

	.vpe-crumbs ol { gap: 0 .5rem; }
}

/* Крошки на тач-экранах: 20px по высоте пальцем не попасть. */
@media (max-width: 1023px) {
	.vpe-crumbs ol { gap: .25rem .5rem; }
	.vpe-crumbs a { display: inline-flex; align-items: center; min-height: 44px; }
	.vpe-crumbs [aria-current] { display: inline-flex; align-items: center; min-height: 44px; }
}

/* ── 17. Статьи ──────────────────────────────────────────────────────────── */

.vpe-articles { display: grid; gap: 1rem; margin-top: 1.5rem; }

.vpe-article-card {
	display: grid;
	gap: 1rem;
	overflow: hidden;
	border: 1px solid rgba(255, 255, 255, .1);
	border-radius: 18px;
	background: color-mix(in oklab, var(--card) 40%, transparent);
	transition: transform .25s var(--ease-2), border-color .25s var(--ease-2), box-shadow .25s var(--ease-2);
}

.vpe-article-card:hover {
	transform: translateY(-3px);
	border-color: rgba(255, 255, 255, .25);
	box-shadow: 0 20px 46px -22px oklch(0.62 0.235 22 / .55);
}

.vpe-article-card__media { display: block; position: relative; aspect-ratio: 16 / 9; overflow: hidden; }
.vpe-article-card__img { width: 100%; height: 100%; object-fit: cover; }
.vpe-article-card__body { padding: 0 1.25rem 1.25rem; }
.vpe-article-card__title { font-size: 1.125rem; font-weight: 800; line-height: 1.3; }
.vpe-article-card__title a { color: var(--foreground); }
.vpe-article-card__meta { margin-top: .375rem; font-size: .8125rem; color: var(--muted-foreground); }
.vpe-article-card__excerpt { margin-top: .625rem; font-size: .9375rem; line-height: 1.6; color: var(--muted-foreground); }

.vpe-post__head { margin-bottom: 1.25rem; }
.vpe-post__meta { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: .75rem; font-size: .875rem; color: var(--muted-foreground); }
.vpe-post__cover { margin: 0 0 1.5rem; overflow: hidden; border-radius: 20px; border: 1px solid rgba(255, 255, 255, .1); }
.vpe-post__cover-img { width: 100%; height: auto; display: block; }

.vpe-post__body { display: grid; gap: 2rem; }
.vpe-post__main .vpe-seo-body { margin-top: 0; padding-top: 0; border-top: 0; max-width: 72ch; }

.vpe-toc {
	margin-bottom: 1.5rem;
	padding: 1rem 1.25rem;
	border: 1px solid rgba(255, 255, 255, .1);
	border-radius: 16px;
	background: rgba(10, 12, 30, .6);
}

.vpe-toc__title { font-size: .75rem; font-weight: 800; text-transform: uppercase; letter-spacing: .14em; color: color-mix(in oklab, var(--foreground) 55%, transparent); }
.vpe-toc ol { margin: .75rem 0 0; padding-left: 1.2rem; display: grid; gap: .375rem; }
.vpe-toc a { font-size: .9375rem; color: var(--muted-foreground); transition: color .25s var(--ease); }
.vpe-toc a:hover { color: var(--foreground); }

.vpe-post__nav { display: grid; gap: .75rem; margin-top: 2.5rem; padding-top: 1.5rem; border-top: 1px solid rgba(255, 255, 255, .1); }

.vpe-post__nav-link {
	display: grid;
	gap: .25rem;
	padding: 1rem 1.25rem;
	border: 1px solid rgba(255, 255, 255, .1);
	border-radius: 14px;
	background: rgba(255, 255, 255, .03);
	font-weight: 700;
	color: var(--foreground);
	transition: border-color .25s var(--ease-2), background-color .25s var(--ease-2);
}

.vpe-post__nav-link:hover { border-color: rgba(255, 255, 255, .25); background: rgba(255, 255, 255, .07); }
.vpe-post__nav-link--next { text-align: right; }
.vpe-post__nav-label { font-size: .75rem; font-weight: 600; text-transform: uppercase; letter-spacing: .12em; color: var(--muted-foreground); }

.vpe-post__aside { align-self: start; }
.vpe-post__aside .vpe-h2 { font-size: 1.125rem; margin-bottom: .875rem; }
.vpe-post__games { display: grid; gap: .625rem; margin-bottom: 1rem; }

.vpe-post__game {
	display: grid;
	grid-template-columns: 88px 1fr;
	gap: .75rem;
	align-items: center;
	padding: .5rem;
	border: 1px solid rgba(255, 255, 255, .08);
	border-radius: 12px;
	transition: border-color .25s var(--ease-2), background-color .25s var(--ease-2);
}

.vpe-post__game:hover { border-color: rgba(255, 255, 255, .22); background: rgba(255, 255, 255, .05); }
.vpe-post__game-thumb { display: block; overflow: hidden; border-radius: 8px; aspect-ratio: 4 / 3; }
.vpe-post__game-img { width: 100%; height: 100%; object-fit: cover; }
.vpe-post__game-title { font-size: .875rem; font-weight: 700; color: var(--foreground); }

@media (min-width: 640px) {
	.vpe-article-card { grid-template-columns: 260px 1fr; align-items: stretch; }
	.vpe-article-card__media { aspect-ratio: auto; height: 100%; }
	.vpe-article-card__body { padding: 1.25rem 1.25rem 1.25rem 0; }
	.vpe-post__nav { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 1024px) {
	.vpe-post__body { grid-template-columns: minmax(0, 1fr) 18rem; }
}

/* Жанровая метка в карточке — 19px по высоте, пальцем не попасть.
   Растягиваем область нажатия псевдоэлементом: внешний вид не меняется,
   а цель становится нормального размера. */
@media (max-width: 1023px) {
	a.vpe-genre { position: relative; }

	a.vpe-genre::after {
		content: "";
		position: absolute;
		left: 0;
		right: 0;
		top: 50%;
		height: 44px;
		transform: translateY(-50%);
	}
}

/* Ссылки в блоке деталей игры и в крошках — тот же приём расширения цели. */
@media (max-width: 1023px) {
	.vpe-meta dd a { position: relative; display: inline-block; }

	.vpe-meta dd a::after {
		content: "";
		position: absolute;
		left: 0;
		right: 0;
		top: 50%;
		height: 44px;
		transform: translateY(-50%);
	}
}

/* Баннер на узких экранах: текстовый блок занимает всю ширину. */
@media (max-width: 1023px) {
	.vpe-hero__left { max-width: none; }
}

@media (max-width: 767px) {
	.vpe-hero__grid { gap: 1.25rem; }
	.vpe-hero__cta { margin-top: 1.25rem; }
}

/* ── 18. Сетка категорий на главной ──────────────────────────────────────── */

.vpe-catgrid {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: .75rem;
	margin-top: 1.5rem;
}

.vpe-cattile {
	display: flex;
	align-items: center;
	gap: .875rem;
	padding: .875rem 1rem;
	border: 1px solid rgba(255, 255, 255, .1);
	border-radius: 14px;
	background: color-mix(in oklab, var(--card) 40%, transparent);
	transition: transform .25s var(--ease-2), border-color .25s var(--ease-2), background-color .25s var(--ease-2), box-shadow .25s var(--ease-2);
}

.vpe-cattile:hover {
	transform: translateY(-3px);
	border-color: rgba(255, 255, 255, .25);
	background: color-mix(in oklab, var(--card) 65%, transparent);
	box-shadow: 0 16px 36px -20px oklch(0.62 0.235 22 / .55);
}

.vpe-cattile__icon {
	display: grid;
	place-items: center;
	width: 2.5rem;
	height: 2.5rem;
	flex: none;
	border-radius: 10px;
	background: var(--grad-neon);
	color: #fff;
	transition: transform .25s var(--ease-2);
}

.vpe-cattile:hover .vpe-cattile__icon { transform: scale(1.06); }
.vpe-cattile__icon .vpe-i { width: 1.125rem; height: 1.125rem; }

.vpe-cattile__body { display: grid; gap: .125rem; min-width: 0; }

.vpe-cattile__name {
	font-size: .9375rem;
	font-weight: 700;
	color: var(--foreground);
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.vpe-cattile__count { font-size: .75rem; color: var(--muted-foreground); }

@media (min-width: 640px) { .vpe-catgrid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1024px) { .vpe-catgrid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (min-width: 1600px) { .vpe-catgrid { grid-template-columns: repeat(6, minmax(0, 1fr)); } }

/*
 * Подписи у кнопок шапки — только когда для них правда есть место.
 * С добавлением пункта Home меню выросло до 618px, и на 1280 подписи
 * сжимали поиск до 140 пикселей, то есть до бесполезного поля.
 */
@media (min-width: 1440px) {
	.vpe-act__label { display: inline; }
}

/*
 * Баннер и подвал на узком экране: отступы с обеих сторон и полное
 * скругление. Прижатый вправо блок со скруглением только слева — это
 * десктопная композиция, где справа край экрана, а слева сайдбар.
 *
 * Блок стоит в самом конце файла намеренно: базовые правила .vpe-hero и
 * .vpe-footer с width: 100% лежат ниже медиазапросов выше по файлу, а
 * медиазапрос веса не добавляет — побеждает то правило, что записано
 * позже. Из-за этого первая попытка правки не сработала, и подвал
 * вылезал на 16px за правый край.
 */
@media (max-width: 1023px) {
	.vpe-hero,
	.vpe-footer { border-radius: var(--r-lg); }

	.vpe-hero__inner,
	.vpe-footer__inner { border-radius: calc(var(--r-lg) - 1px); }
}

/* ── 19. Метки на странице игры ──────────────────────────────────────────── */

.vpe-meta__title {
	margin: 1.25rem 0 .625rem;
	font-size: .75rem;
	font-weight: 800;
	text-transform: uppercase;
	letter-spacing: .14em;
	color: color-mix(in oklab, var(--foreground) 55%, transparent);
}

.vpe-tags { display: flex; flex-wrap: wrap; gap: .375rem; }

.vpe-tagchip {
	display: inline-flex;
	align-items: center;
	min-height: 32px;
	padding: 0 .75rem;
	border: 1px solid rgba(255, 255, 255, .1);
	border-radius: 999px;
	background: rgba(255, 255, 255, .04);
	font-size: .8125rem;
	color: var(--muted-foreground);
	transition: border-color .25s var(--ease-2), background-color .25s var(--ease-2), color .25s var(--ease-2);
}

.vpe-tagchip:hover {
	border-color: rgba(255, 255, 255, .25);
	background: rgba(255, 255, 255, .08);
	color: var(--foreground);
}

@media (max-width: 1023px) { .vpe-tagchip { min-height: 44px; } }

/* ── 20. Плитки категорий с обложками ────────────────────────────────────── */

.vpe-cattile {
	position: relative;
	display: block;
	overflow: hidden;
	aspect-ratio: 4 / 3;
	border: 1px solid rgba(255, 255, 255, .1);
	border-radius: 16px;
	background: var(--card);
	padding: 0;
	transition: transform .28s var(--ease-2), border-color .28s var(--ease-2), box-shadow .28s var(--ease-2);
}

.vpe-cattile:hover {
	transform: translateY(-4px);
	border-color: rgba(255, 255, 255, .28);
	box-shadow: 0 22px 46px -22px oklch(0.62 0.235 22 / .55);
}

.vpe-cattile__img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform .5s var(--ease-2);
}

.vpe-cattile:hover .vpe-cattile__img { transform: scale(1.07); }

/*
 * Затемнение снизу: без него подпись теряется на светлых обложках.
 * Проверено на плитке «Casual» — обложка там почти белая, и на прежней
 * завесе белая подпись с числом игр читалась через раз.
 */
.vpe-cattile__shade {
	position: absolute;
	inset: 0;
	background: linear-gradient(to top,
		rgba(6, 8, 20, .97) 0%,
		rgba(6, 8, 20, .88) 26%,
		rgba(6, 8, 20, .45) 55%,
		rgba(6, 8, 20, .08) 100%);
}

.vpe-cattile__body {
	position: absolute;
	inset: auto 0 0 0;
	display: grid;
	gap: .125rem;
	padding: .75rem .875rem;
}

.vpe-cattile__name {
	font-size: 1rem;
	font-weight: 800;
	line-height: 1.2;
	color: #fff;
	text-shadow: 0 1px 8px rgba(0, 0, 0, .8);
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.vpe-cattile__count {
	font-size: .75rem;
	font-weight: 600;
	color: rgba(255, 255, 255, .72);
}

@media (max-width: 639px) {
	.vpe-cattile__name { font-size: .875rem; }
	.vpe-cattile__body { padding: .625rem .75rem; }
}

/* -- 21. Состояния интерактивных элементов ------------------------------- */

/*
 * Пять состояний на все управляющие элементы темы, а не на каждый свои.
 * Раньше hover был описан у каждой кнопки отдельно, active — у двух из
 * восьми, disabled — только у панели плеера, а состояния загрузки не было
 * вовсе: живой поиск ставил aria-busy, и ничего не менялось.
 *
 * hover    — подъём на 2-3px и более светлая поверхность;
 * focus    — общая обводка :focus-visible из раздела 3;
 * active   — возврат на место и лёгкое сжатие;
 * disabled — прозрачность .45 и курсор not-allowed, без смены цвета;
 * loading  — пульсация прозрачности, только opacity.
 */

.vpe-btn-play:disabled,
.vpe-btn-browse:disabled,
.vpe-btn-pill:disabled,
.vpe-player__btn:disabled,
.vpe-filter[aria-disabled="true"],
.vpe-viewall[aria-disabled="true"] {
	opacity: .45;
	cursor: not-allowed;
	transform: none;
	box-shadow: none;
	pointer-events: none;
}

.vpe-filter:active,
.vpe-viewall:active,
.vpe-player__btn:active:not(:disabled),
.vpe-pagination .page-numbers:active,
.vpe-tagchip:active {
	transform: translateY(0) scale(.985);
}

/* Живой поиск на время запроса. Атрибут ставит search-autocomplete.js —
   до этой правки он не давал никакой обратной связи. */
.vpe-live-search[aria-busy="true"] {
	position: relative;
	animation: vpe-pulse 1.1s var(--ease-2) infinite;
}

@keyframes vpe-pulse {
	0%, 100% { opacity: 1; }
	50% { opacity: .55; }
}

/* Ошибка: единственный цвет тревоги в теме. */
.vpe-player__failed,
.vpe-note--error { color: var(--danger); }

@media (prefers-reduced-motion: reduce) {
	.vpe-live-search[aria-busy="true"] { animation: none; opacity: .7; }
}

/* ── 22. Подборки: витрина на главной и страница /collections/ ───────────── */

/*
 * Горизонтальная карточка, а не плитка. Выше по главной уже стоят плитки
 * категорий (раздел 20) и ряды карточек игр — третья сетка того же ритма
 * слила бы подборки с ними в один длинный список.
 *
 * Форму задаёт содержимое: подборке нужна строка описания, иначе «Игры на
 * двоих» читается как ещё одна категория с непонятным именем. Место под
 * эту строку есть только рядом с обложкой, а не под ней.
 *
 * Значения — только из токенов раздела 2.
 */

.vpe-sechead__text { display: grid; gap: var(--sp-1); min-width: 0; }

.vpe-sechead__sub {
	font-size: var(--fs-base);
	line-height: 1.45;
	color: var(--muted-foreground);
	max-width: 46ch;
}

.vpe-colshelf {
	margin-top: var(--sp-5);
	display: grid;
	gap: var(--sp-4);
	grid-template-columns: minmax(0, 1fr);
}

.vpe-colcard {
	position: relative;
	display: grid;
	grid-template-columns: 7.5rem minmax(0, 1fr);
	align-items: center;
	gap: var(--sp-4);
	min-height: var(--tap);
	padding: var(--sp-3);
	border: 1px solid var(--line-1);
	border-radius: var(--r-md);
	background: var(--card);
	transition: transform .28s var(--ease-2), border-color .28s var(--ease-2), box-shadow .28s var(--ease-2);
}

.vpe-colcard:hover {
	transform: translateY(-3px);
	border-color: var(--line-2);
	box-shadow: var(--sh-2);
}

.vpe-colcard:active { transform: translateY(0) scale(.99); }

.vpe-colcard__media {
	position: relative;
	overflow: hidden;
	aspect-ratio: 4 / 3;
	border-radius: var(--r-sm);
	background: var(--surface-2);
}

.vpe-colcard__img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform .5s var(--ease-2);
}

.vpe-colcard:hover .vpe-colcard__img { transform: scale(1.06); }

/* Обложки ещё нет: место держим, чтобы соседние карточки не поехали. */
.vpe-colcard__ph {
	position: absolute;
	inset: 0;
	display: grid;
	place-items: center;
	color: color-mix(in oklab, var(--foreground) 30%, transparent);
}

.vpe-colcard__ph .vpe-i { width: 1.5rem; height: 1.5rem; }

.vpe-colcard__body { display: grid; gap: var(--sp-1); min-width: 0; }

/*
 * display: block обязателен: у flex-контейнера текст становится анонимным
 * flex-элементом, и text-overflow: ellipsis к нему не применяется.
 */
.vpe-colcard__name {
	display: block;
	font-size: var(--fs-md);
	font-weight: 800;
	line-height: 1.25;
	color: var(--foreground);
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.vpe-colcard__text {
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
	font-size: var(--fs-sm);
	line-height: 1.45;
	color: var(--muted-foreground);
}

.vpe-colcard__meta {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--sp-2);
}

.vpe-colcard__count {
	font-size: var(--fs-xs);
	font-weight: 600;
	color: color-mix(in oklab, var(--foreground) 72%, transparent);
}

.vpe-colcard__go {
	display: inline-flex;
	flex-shrink: 0;
	color: var(--primary);
	transition: transform .3s var(--ease-2);
}

.vpe-colcard__go .vpe-i { width: .875rem; height: .875rem; }

.vpe-colcard:hover .vpe-colcard__go { transform: translateX(3px); }

/* Медиазапросы идут ПОСЛЕ базовых правил: вес селектора они не повышают. */

@media (min-width: 720px) {
	.vpe-colshelf { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 1100px) {
	.vpe-colcard { grid-template-columns: 15rem minmax(0, 1fr); gap: var(--sp-5); }
	.vpe-colcard__name { font-size: var(--fs-lg); }
	.vpe-colcard__text { font-size: var(--fs-base); }
}

/*
 * Три колонки не вводим и на самых широких экранах: карточка стала бы
 * узкой, описание ушло бы в многоточие, и получилась бы та самая сетка
 * 3xN, ради ухода от которой блок и сделан горизонтальным.
 */
