/* ============================================================
   BIGBOY HUB · компоновка экранов (§4–§29, §50–§52, §63)
   Использует только токены из tokens.css.
   ============================================================ */

/* ───────────────── SPLASH + ONBOARDING (§52) ──────────── */
.splash {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: grid;
  place-items: center;
  gap: var(--s-4);
  background:
    radial-gradient(70% 50% at 50% 30%, rgba(139, 92, 255, .3), transparent 70%),
    radial-gradient(60% 45% at 20% 85%, rgba(141, 14, 210, .18), transparent 70%),
    linear-gradient(180deg, var(--bg-2), var(--bg-0) 70%);
  transition: opacity var(--t-slow) var(--ease);
}

.splash::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(60% 45% at 50% 45%, rgba(7, 11, 24, .35), rgba(7, 11, 24, .92));
}

.splash__inner { position: relative; z-index: 2; display: grid; justify-items: center; gap: var(--s-4); padding: var(--pad); }
.splash__mark {
  font-family: var(--font-brand);
  font-size: var(--fs-3xl);
  font-weight: var(--fw-xbold);
  letter-spacing: .04em;
  line-height: 1;
  text-align: center;
}
.splash__mark em { font-style: normal; color: var(--accent); display: block; font-size: var(--fs-l); letter-spacing: .34em; }
.splash__bar { width: 132px; height: 3px; border-radius: var(--r-pill); background: rgba(255, 255, 255, .12); overflow: hidden; }
.splash__bar i { display: block; height: 100%; width: 30%; border-radius: inherit; background: var(--grad-cta); animation: load 1.1s var(--ease) infinite; }
@keyframes load { from { transform: translateX(-110%); } to { transform: translateX(360%); } }
.splash.is-hidden { opacity: 0; pointer-events: none; }

.avpick { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s-3); }
.avpick__cell {
  min-width: 0;
  aspect-ratio: var(--ar-1-1);
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: var(--glass-1);
  box-shadow: var(--rim);
  display: grid;
  place-items: center;
  cursor: pointer;
  transition: transform var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
}
/* аватар должен вписываться в ячейку, а не задавать её ширину: на 320 четыре
   штуки по 60px с зазорами не влезают в карточку и четвертую обрезает */
.avpick__cell > .avatar {
  width: calc(100% - var(--s-3));
  height: auto;
  aspect-ratio: var(--ar-1-1);
  font-size: clamp(13px, 4.4vw, var(--fs-l));
}
.avpick__cell:active { transform: scale(.96); }
.avpick__cell[data-on="true"] { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent-line), 0 10px 26px rgba(141, 14, 210, .22); }

/* выбранный аватар крупно, чтобы человек видел, что именно поставилось */
.avcur { display: flex; align-items: center; gap: var(--s-4); }
.avcur .avatar { width: 76px; height: 76px; font-size: var(--fs-xl); }
/* input с type=file нужен в DOM для programmatic click, но показывать его нельзя */
.avfile { display: none; }

/* ─────────────────── HOME · логотип портала ──────────── */
/* отступ сверху — это полоса для вывески на башне: между шапкой (0–69)
   и логотипом иначе не остаётся ни одного читаемого ряда окон */
/* верхний отступ логотипа — это полоса неба под шапкой: в неё встаёт
   вывеска на башне, и пока полоса есть, знак не ложится ни на одну строку */
.homebrand { margin: calc(var(--s-9) + var(--s-6)) 0 var(--s-5); text-align: center; }

.homebrand__mark {
  margin: 0;
  font-family: var(--font-brand);
  font-size: clamp(30px, 10.4vw, 46px);
  font-weight: 900;
  line-height: 1.04;
  letter-spacing: .01em;
  text-transform: uppercase;
  color: #FDEBF5;
  /* объём: ступенчатая тень вместо blur — надпись читается как логотип, а не как текст */
  text-shadow: 0 2px 0 rgba(168, 24, 96, .75), 0 4px 0 rgba(104, 14, 62, .7),
               0 6px 14px rgba(2, 5, 15, .55), 0 16px 40px rgba(2, 5, 15, .5);
}

.homebrand__mark em {
  font-style: normal;
  color: var(--accent);
  text-shadow: 0 2px 0 rgba(132, 12, 70, .85), 0 4px 0 rgba(78, 6, 42, .75),
               0 8px 20px rgba(2, 5, 15, .5), 0 0 34px rgba(141, 14, 210, .55);
}

.homebrand__tag {
  margin: var(--s-3) 0 0;
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--text-2);
}

/* ─────────────────── HOME · герой BIGBOY ─────────────── */
/* Плашки главной плотнее остальных: за ними живой ночной город с окнами,
   и на общем стекле (--veil-2 = .82) текст спорит с подсветкой башен.
   Правим сам --grad-glass, а не --veil-2: токен вычислен на :root и глубже
   по дереву уже подставлен, поэтому переопределение вуали сюда не доедет. */
#screen-home .hero,
#screen-home .contact {
  --grad-glass: linear-gradient(180deg, rgba(255, 255, 255, .09), rgba(255, 255, 255, .035)),
    linear-gradient(rgba(8, 12, 26, .89), rgba(8, 12, 26, .89));
}

.hero {
  position: relative;
  display: grid;
  justify-items: center;
  align-content: start;
  gap: var(--s-3);
  padding: var(--s-5) var(--s-4) var(--s-4);
  border-radius: var(--r-xl);
  border: 1px solid var(--line-2);
  background:
    radial-gradient(120% 62% at 50% 0%, rgba(139, 92, 255, .24), transparent 62%),
    var(--grad-glass);
  backdrop-filter: var(--blur);
  -webkit-backdrop-filter: var(--blur);
  box-shadow: var(--rim), var(--sh-2);
  overflow: hidden;
  text-align: center;
}

.hero__halo {
  position: absolute;
  top: -120px;
  left: 50%;
  transform: translateX(-50%);
  width: 300px;
  height: 300px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(141, 14, 210, .22), transparent 62%);
  filter: blur(26px);
  pointer-events: none;
}

.hero[data-live="true"] .hero__halo { background: radial-gradient(circle, rgba(255, 51, 85, .26), transparent 62%); }

.hero__face {
  position: relative;
  width: clamp(148px, 46vw, 196px);
  aspect-ratio: var(--ar-1-1);
  border-radius: 50%;
  overflow: hidden;
  border: 1px solid var(--line-2);
  background: var(--card);
  box-shadow: var(--rim-2), 0 20px 46px rgba(3, 7, 20, .6), 0 0 0 7px rgba(255, 255, 255, .035);
}
.hero__face img { position: relative; z-index: 1; width: 100%; height: 100%; object-fit: cover; object-position: 50% 26%; }
.hero[data-live="true"] .hero__face { border-color: rgba(255, 51, 85, .55); }

.hero__id { min-width: 0; }
.hero__name {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  font-family: var(--font-brand);
  font-size: clamp(17px, 5.2vw, 22px);
  font-weight: var(--fw-xbold);
  letter-spacing: .01em;
  line-height: 1.1;
  word-break: break-word;
}
.hero__bio { margin: var(--s-2) 0 0; font-size: var(--fs-sm); color: var(--text-2); line-height: var(--lh-loose); }

.hero__status {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  max-width: 100%;
  padding: 6px var(--s-4);
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  background: var(--glass-2);
  box-shadow: var(--rim);
}
.hero__where {
  min-width: 0;
  font-size: var(--fs-sm);
  font-weight: var(--fw-bold);
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.hero__nums { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-2); width: 100%; }
.hero__num {
  display: grid;
  gap: 3px;
  min-width: 0;
  padding: var(--s-3);
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: var(--glass-1);
  box-shadow: var(--rim);
}
.hero__num .num { font-size: var(--fs-xl); line-height: 1; color: #fff; font-variant-numeric: tabular-nums; }
.hero__num span { font-size: var(--fs-xs); letter-spacing: .1em; text-transform: uppercase; color: var(--text-2); }
.hero__since { margin: 0; font-size: var(--fs-s); color: var(--text-3); }
.hero .btn { margin-top: var(--s-1); }

.hero__cap { margin-bottom: var(--s-3); }

/* ─────────── HOME · свет софитов на сцене ─────────── */
/* Фон держится на окне, а не на ленте: при скролле свет остаётся на
   месте, плашки проходят под него — экран читается сценой ночного
   стрима, а не простынёй. Слой служебный: в раскладку он не
   вмешивается, поэтому высота экрана от него не зависит ни на пиксель.
   Ширина ограничена колонкой приложения: на десктопе свет не должен
   выливаться за карточку-витрину. */
.homefx {
  position: fixed;
  inset: 0;
  z-index: -1;
  max-width: var(--app-max);
  margin: 0 auto;
  overflow: hidden;
  pointer-events: none;
  background:
    radial-gradient(115% 44% at 50% -12%, rgba(139, 92, 255, .26), transparent 64%),
    radial-gradient(76% 32% at 94% 28%, rgba(255, 79, 208, .13), transparent 66%),
    radial-gradient(70% 30% at 4% 60%, rgba(52, 217, 164, .10), transparent 68%);
}
/* следующий после фона блок не должен платить за него отступом */
.homefx + * { margin-top: 0; }

/* засвет стены под вывеской: то, что продаёт «дорого» лучше самого луча.
   Свет ложится на верхнюю треть и гаснет до середины — как в клубе, где
   софит светит на задник, а не вам в лицо. */
.homefx::before {
  content: "";
  position: absolute;
  left: -12%;
  right: -12%;
  top: -16%;
  height: 64%;
  filter: blur(34px);
  background:
    radial-gradient(44% 50% at 16% 28%, rgba(169, 112, 255, .36), transparent 70%),
    radial-gradient(40% 46% at 86% 16%, rgba(255, 79, 208, .24), transparent 68%),
    radial-gradient(30% 40% at 52% 6%, rgba(242, 201, 121, .16), transparent 72%);
}

/* конус: узкая вершина над краем экрана, база гаснет на середине.
   Форму несёт ::before, а blur — на родителе: clip-path режет уже
   размытое, поэтому если клип и фильтр на одном элементе, у луча
   остаются три идеально ровных края и он читается заплаткой.
   Маска от вершины гасит базу, screen кладёт свет поверх фона слоями. */
.homefx__beam {
  position: absolute;
  top: -14%;
  width: 38%;
  height: 78%;
  filter: blur(22px);
  mix-blend-mode: screen;
  transform-origin: 50% 0;
}
.homefx__beam::before {
  content: "";
  position: absolute;
  inset: 0;
  clip-path: polygon(46% 0, 54% 0, 94% 100%, 6% 100%);
  mask-image: radial-gradient(60% 66% at 50% 0, #000 0, rgba(0, 0, 0, .5) 44%, transparent 76%);
  -webkit-mask-image: radial-gradient(60% 66% at 50% 0, #000 0, rgba(0, 0, 0, .5) 44%, transparent 76%);
}
.homefx__beam--l {
  left: 2%;
  animation: homefx-l 13s var(--ease) infinite alternate;
}
.homefx__beam--l::before {
  background: linear-gradient(180deg, rgba(228, 240, 255, .38), rgba(169, 112, 255, .16) 38%, transparent 72%);
}
.homefx__beam--r {
  right: 2%;
  animation: homefx-r 17s var(--ease) infinite alternate;
}
.homefx__beam--r::before {
  background: linear-gradient(180deg, rgba(255, 202, 244, .32), rgba(242, 201, 121, .14) 40%, transparent 74%);
}
/* разные периоды и встречные ходы: конусы не ходят парой, иначе свет
   начинает мигать ритмом, а это уже дешёвая вывеска */
@keyframes homefx-l {
  from { transform: rotate(9deg) scaleY(.96); }
  to { transform: rotate(24deg) scaleY(1.05); }
}
@keyframes homefx-r {
  from { transform: rotate(-11deg) scaleY(1.04); }
  to { transform: rotate(-25deg) scaleY(.95); }
}

/* дымка стелется по низу сцены и дышит — от неё фиолетовый горизонт.
   По ширине она не вылезает за экран: .homefx её всё равно режет, а
   вот аудит правильно считает торчащий элемент выходом за вёрстку */
.homefx__haze {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -14%;
  height: 52%;
  filter: blur(30px);
  background: radial-gradient(74% 88% at 50% 100%, rgba(141, 14, 210, .5), rgba(255, 79, 208, .16) 52%, transparent 78%);
  animation: homefx-haze 11s var(--ease) infinite alternate;
}
@keyframes homefx-haze {
  from { opacity: .7; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(-8px); }
}

/* зерно поверх света: без него градиенты ложатся полосами, а с ним
   плашки перестают выглядеть приклеенными к фону. 5 % — на границе
   видимости, поэтому сдвиг по шагам, а не плавный: глаз не цепляется. */
.homefx__grain {
  position: absolute;
  inset: 0;
  opacity: .05;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
  animation: homefx-grain 1.4s steps(5) infinite;
}
@keyframes homefx-grain {
  from { background-position: 0 0; }
  to { background-position: 70px 55px; }
}

/* ────────── HOME · ночной Москва-Сити ─────────────────────
   Полоса привязана к верху экрана фиксированной высотой в пикселях:
   шапка и логотип стоят в тех же пикселях, поэтому башни держатся под
   текстом и на 320, и на 430. Линии земли в кадре нет — основания башен
   уходят за стекло первой плашки, где их съедает blur.
   none, а не meet/slice: растягивается только ширина колонки, а она шире
   430 px не бывает никогда — силуэт от этого не деформируется. */
/* Город — фотография ночного Москва-Сити, а не рисунок. Кадр прибит к
   верху полосы и масштабируется по её ВЫСОТЕ (cover): множитель один на
   всех ширинах, поэтому вывеска держится своей башни и на 320, и на 430 —
   по горизонтали кадр только симметрично режется. */
.homefx__city {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 560px;
  background: #05060f url("../assets/hub/city-night-moscow.jpg") top center / cover no-repeat;
  opacity: .95;
  mask-image: linear-gradient(180deg, #000 0, #000 56%, rgba(0, 0, 0, .42) 84%, transparent 100%);
  -webkit-mask-image: linear-gradient(180deg, #000 0, #000 56%, rgba(0, 0, 0, .42) 84%, transparent 100%);
}
/* вывеска застройщика на грани башни. Отдельным слоем, а не картинкой в
   снимке: фирменный знак нельзя растягивать вместе с фоном, и только так
   он остаётся резким на любом экране и может дышать, как ночная подсветка.
   Координаты считает JS по мерке кадра. */
.homefx__city::after {
  content: "";
  position: absolute;
  left: var(--sign-x, 4px);
  top: var(--sign-y, 83px);
  width: var(--sign-w, 64px);
  aspect-ratio: 304 / 272;
  background: url("../assets/hub/sign-melstroy.png") no-repeat center / contain;
  filter: drop-shadow(0 0 4px rgba(206,164,255,.9)) drop-shadow(0 0 14px rgba(141,14,210,.62));
  animation: signGlow 8s var(--ease) infinite;
}
@keyframes signGlow {
  0%, 100% { opacity: .84; }
  50% { opacity: 1; }
}
.homefx__city .star {
  fill: #E9DCFF;
  animation: starTwinkle 7s var(--ease) infinite;
}
@keyframes starTwinkle {
  0%, 100% { opacity: .5; }
  50% { opacity: .12; }
}
/* окна гаснут и возвращаются вразнобой и медленно: город дышит, а не
   мигает табло. Отрицательная задержка из сида разводит фазы */
.homefx__city .win--slow { animation: winSlow 17s var(--ease) infinite; }
@keyframes winSlow {
  0%, 100% { opacity: .66; }
  44% { opacity: .1; }
  62% { opacity: .48; }
}
/* корона башни залита светом и медленно дышит — этот свет видно с
   другого конца набережной, он и продаёт «ночной город» */
.homefx__city .crownlite { animation: crownGlow 9s var(--ease) infinite; }
.homefx__city .crownlite--h { animation: crownHalo 9s var(--ease) infinite; }
@keyframes crownGlow {
  0%, 100% { opacity: .4; }
  50% { opacity: .74; }
}
@keyframes crownHalo {
  0%, 100% { opacity: .12; }
  50% { opacity: .24; }
}
/* авиационный огонь на макушках: редкая двойная вспышка, как на вышках.
   Покой анимации — горение: при prefers-reduced-motion остаётся светлым */
.homefx__city .beacon {
  fill: #FF4D6D;
  transform-box: fill-box;
  transform-origin: 50% 50%;
  animation: beacon 3.4s var(--ease) infinite;
}
@keyframes beacon {
  0%, 100% { opacity: .85; transform: scale(1); }
  10% { opacity: 1; transform: scale(1.15); }
  20% { opacity: .16; transform: scale(.9); }
  30% { opacity: .95; }
  44% { opacity: .16; }
  62% { opacity: .85; }
}
/* отсвет, идущий по стеклу: косая мягкая полоса проходит по силуэту.
   Две, встречные и с не кратными периодами, — иначе свет ходит ритмом */
.homefx__city .shim--a { animation: shimA 19s linear infinite; }
.homefx__city .shim--b { animation: shimB 27s linear infinite; }
@keyframes shimA {
  from { transform: translateX(0); }
  to { transform: translateX(560px); }
}
@keyframes shimB {
  from { transform: translateX(0); }
  to { transform: translateX(-620px); }
}
/* борт над городом: один на весь экран, медленный, с мигающим огоньком */
.homefx__city .plane { animation: planeFly 52s linear infinite; }
@keyframes planeFly {
  from { transform: translateX(-26px); }
  to { transform: translateX(464px); }
}
.homefx__city .plane__light {
  fill: #FF5C7A;
  animation: planeBlink 2.2s steps(1, end) infinite;
}
@keyframes planeBlink {
  0%, 100% { opacity: .12; }
  40% { opacity: 1; }
}
@media (max-width: 359px) {
  /* на 320 строк плотнее: город чуть глушим, чтобы окна не подмигивали
     из-под букв логотипа */
  .homefx__city { opacity: .82; }
}

/* ────────── HOME · контакты объёмными логотипами ─────── */
/* 2×2: в 4 колонки на 390 имя бренда обрезается, а логотип — главное в блоке */
.contacts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-3); }

.contact {
  position: relative;
  display: grid;
  justify-items: center;
  gap: var(--s-2);
  min-width: 0;
  padding: var(--s-4) var(--s-2);
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  background: var(--grad-glass);
  box-shadow: var(--rim);
  color: var(--text);
  font-family: var(--font);
  cursor: pointer;
  transition: transform var(--t-fast) var(--ease), border-color var(--t) var(--ease);
}
.contact:active:not(:disabled) { transform: scale(.97); }
.contact:hover:not(:disabled) { border-color: var(--brand); }
.contact:disabled { cursor: default; }
/* на 320 px в ячейку не влезает «@BigBoyLegenda_bot» — забираем воздух у карточки */
@media (max-width: 360px) {
  .contacts { gap: var(--s-2); }
  .contact { padding-left: var(--s-1); padding-right: var(--s-1); }
}

.contact__logo {
  position: relative;
  z-index: 1;
  width: 62px;
  height: 62px;
  display: grid;
  place-items: center;
  border-radius: var(--r-lg);
  color: var(--brand);
  background: linear-gradient(160deg, rgba(255, 255, 255, .16), rgba(255, 255, 255, .03));
  border: 1px solid var(--line-2);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .22), 0 12px 28px rgba(3, 7, 20, .5);
}
.contact__logo::before {
  content: "";
  position: absolute;
  inset: -5px;
  z-index: -1;
  border-radius: inherit;
  background: var(--brand);
  opacity: .2;
  filter: blur(14px);
}
.contact__logo svg { width: 36px; height: 36px; filter: drop-shadow(0 3px 8px rgba(0, 0, 0, .5)); }

.contact__name {
  max-width: 100%;
  font-size: var(--fs-sm);
  font-weight: var(--fw-xbold);
  letter-spacing: .08em;
  text-transform: uppercase;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.contact__handle {
  max-width: 100%;
  font-size: var(--fs-xs);
  color: var(--text-3);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.contact--off { opacity: .42; cursor: default; }
.contact--off .contact__logo { color: var(--text-3); box-shadow: var(--rim); }
.contact--off .contact__logo::before { display: none; }

/* ───────────────────── персональные полосы ───────────── */
.balance {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  column-gap: var(--s-3);
  row-gap: var(--s-2);
  align-items: center;
  padding: var(--s-3) var(--s-4);
  border-radius: var(--r-lg);
  border: 1px solid var(--line-2);
  background: linear-gradient(100deg, rgba(141, 14, 210, .07), var(--card) 45%);
}
.balance__id { min-width: 0; }
.balance__lvl { grid-column: 2 / -1; display: grid; grid-template-columns: minmax(0, 1fr); gap: 2px; min-width: 0; }
.balance__lvl > * { min-width: 0; }
/* span остаётся inline → overflow:hidden его не режет, нужнен блочный контекст */
.balance__name { display: block; font-weight: var(--fw-xbold); font-size: var(--fs-m); min-width: 0; }
.balance__xp { font-size: var(--fs-xs); color: var(--text-2); font-variant-numeric: tabular-nums; }
@media (max-width: 359px) {
  .balance { column-gap: var(--s-2); padding-left: var(--s-2); padding-right: var(--s-2); }
}

.hello {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: var(--card);
  font-size: var(--fs-sm);
  font-weight: var(--fw-bold);
}
.hello[data-tone="back"] { border-color: var(--gold-line); background: var(--gold-soft); color: var(--gold); }
.hello[data-tone="live"] { border-color: rgba(255, 51, 85, .42); background: var(--live-soft); color: #FF7A8C; }
.hello[data-tone="rank"] { border-color: var(--accent-line); background: var(--accent-soft); color: var(--accent); }

/* ──────────────────── SOCIAL RAIL (§5) ───────────────── */
.social {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--s-3);
}
.social__item {
  position: relative;
  display: grid;
  justify-items: center;
  gap: var(--s-2);
  min-width: 0;
  padding: var(--s-4) var(--s-2);
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: var(--card);
  overflow: hidden;
  cursor: pointer;
  transition: transform var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease), background var(--t) var(--ease);
}
.social__item:active { transform: scale(.96); background: var(--card-2); }
.social__glyph { width: 26px; height: 26px; display: grid; place-items: center; color: #fff; }
.social__glyph svg { width: 26px; height: 26px; }
.social__name { font-size: var(--fs-xs); font-weight: var(--fw-bold); letter-spacing: .1em; text-transform: uppercase; color: var(--text-2); max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* на телефоне четыре бренд-плитки в ряд: имя бренда длиннее колонки */
@media (max-width: 430px) {
  .social { gap: var(--s-2); }
  .social__name { font-size: 10px; letter-spacing: 0; }
  .social__item { padding-left: 3px; padding-right: 3px; }
}
/* на 320 даже так не умещаются — переходим на 2×2 */
@media (max-width: 359px) {
  .social { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .social__name { font-size: var(--fs-xs); letter-spacing: .08em; }
  .social__item { padding-left: var(--s-2); padding-right: var(--s-2); }
}
.social__item[data-brand="kick"] { border-color: rgba(82, 255, 113, .3); }
.social__item[data-brand="kick"] .social__glyph { color: #52FF71; }
.social__item[data-brand="twitch"] { border-color: rgba(145, 70, 255, .3); }
.social__item[data-brand="twitch"] .social__glyph { color: #A970FF; }
.social__item[data-brand="telegram"] .social__glyph { color: #59B8F7; }
.social__item[data-brand="instagram"] { border-color: rgba(255, 90, 140, .28); }
.social__item[data-brand="instagram"] .social__glyph { color: #FF6EA6; }

/* ───────────────────── календарь стримов ─────────────── */
.timeline { display: grid; gap: var(--s-2); position: relative; }
.timeline::before { content: ""; position: absolute; left: 11px; top: 12px; bottom: 12px; width: 1px; background: var(--line-2); }
.slotrow {
  position: relative;
  display: grid;
  grid-template-columns: 24px 1fr auto;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-3) var(--s-3) var(--s-3) 0;
  border-radius: var(--r-md);
  border: 1px solid transparent;
  background: transparent;
  cursor: pointer;
  text-align: left;
  color: inherit;
  font-family: var(--font);
  width: 100%;
}
.slotrow:active { background: var(--card); }
.slotrow__dot {
  width: 9px;
  height: 9px;
  margin-left: 7px;
  border-radius: 50%;
  background: var(--text-3);
  box-shadow: 0 0 0 3px var(--bg-0);
}
.slotrow[data-now="true"] .slotrow__dot { background: var(--accent); box-shadow: 0 0 0 3px var(--bg-0), 0 0 14px rgba(182, 255, 0, .7); }
.slotrow__when { font-size: var(--fs-xs); color: var(--text-2); letter-spacing: .08em; text-transform: uppercase; }
.slotrow__name { font-size: var(--fs-m); font-weight: var(--fw-bold); }
.slotrow__time { font-size: var(--fs-m); font-weight: var(--fw-xbold); font-variant-numeric: tabular-nums; }

/* ──────────────────────── POLL (§16–§18) ─────────────── */
.poll { display: grid; gap: var(--s-3); }
/* содержимое sheet'а секретного гостя: банк, правила, стороны, взнос */
.pool { display: grid; gap: var(--s-3); }
.pollcard {
  position: relative;
  display: grid;
  grid-template-columns: 96px minmax(0, 1fr);
  gap: var(--s-3);
  padding: var(--s-3);
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: var(--card);
  text-align: left;
  cursor: pointer;
  transition: border-color var(--t-fast) var(--ease), transform var(--t-fast) var(--ease);
  width: 100%;
  font-family: var(--font);
  color: inherit;
}
.pollcard:active { transform: scale(.99); }
.pollcard[data-on="true"] { border-color: var(--accent-line); background: linear-gradient(90deg, var(--accent-soft), var(--card) 55%); }
.pollcard__img { position: relative; border-radius: var(--r-sm); overflow: hidden; aspect-ratio: var(--ar-4-5); }
.pollcard__img img { width: 100%; height: 100%; object-fit: cover; }
/* Без фото бок не пустует: заглушка растягивается на него целиком, и карточка
   читается как «фото придёт», а не как дырка в макете. */
.pollcard__ph { display: grid; height: 100%; }
.pollcard__ph .avatar { width: 100%; height: 100%; border-radius: 0; font-size: var(--fs-2xl); }
.pollcard__no {
  position: absolute;
  top: 4px;
  left: 4px;
  padding: 1px 5px;
  border-radius: 6px;
  background: rgba(7, 11, 24, .72);
  font-size: 10px;
  font-weight: var(--fw-xbold);
  font-variant-numeric: tabular-nums;
  color: var(--gold);
}
.pollcard__name { font-size: var(--fs-m); font-weight: var(--fw-xbold); text-transform: uppercase; letter-spacing: .01em; }
.pollcard__meta { font-size: var(--fs-xs); color: var(--text-2); margin-top: 2px; }
.pollcard__bar { margin-top: var(--s-2); }
.pollcard__pct { display: flex; justify-content: space-between; font-size: var(--fs-xs); color: var(--text-2); margin-top: var(--s-1); font-variant-numeric: tabular-nums; }
/* без «ТВОЙ ВЫБОР» у строки один ребёнок, и space-between прижал бы процент
   влево, к чужой логике */
.pollcard__pct--solo { justify-content: flex-end; }
/* лидер получает не цифру в углу, а медаль: в голосовании за гостя месяца
   вопрос «кто первый» человек читает по картинке, а не по списку */
.pollcard__no--lead {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  left: 6px;
  top: 6px;
  padding: 2px 6px;
  border-radius: var(--r-pill);
  background: linear-gradient(140deg, #FFE8AE, var(--gold) 58%, #C79A54);
  color: #1A1004;
  box-shadow: 0 2px 10px rgba(242, 201, 121, .38);
}
.pollcard__no--lead svg { width: 11px; height: 11px; }

/* ─────────── банк угадавших (§18.1, СЕКРЕТНЫЙ ГОСТЬ) ───────────
   Строка-ставка, а не карточка кандидата: здесь человек выбирает сторону,
   на которую кладёт COIN, и должен видеть банк и множитель одной строкой. */
.poolrow {
  display: grid;
  grid-template-columns: 52px minmax(0, 1fr);
  gap: var(--s-3);
  align-items: center;
  width: 100%;
  padding: var(--s-2);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--card);
  text-align: left;
  font-family: var(--font);
  color: inherit;
  cursor: pointer;
  transition: transform var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
}
.poolrow:active { transform: scale(.99); }
.poolrow[data-on="true"] { border-color: var(--gold-line); background: linear-gradient(90deg, var(--gold-soft), var(--card) 62%); }
.poolrow[data-win="true"] { border-color: var(--ok-line); background: linear-gradient(90deg, var(--ok-soft), var(--card) 62%); }
.poolrow__img { position: relative; display: block; width: 52px; height: 52px; border-radius: var(--r-xs); overflow: hidden; background: var(--card-2); }
.poolrow__img img { width: 100%; height: 100%; object-fit: cover; }
.poolrow__img .pollcard__ph .avatar { font-size: var(--fs-l); }
.poolrow__name { font-size: var(--fs-s); font-weight: var(--fw-xbold); text-transform: uppercase; }
.poolrow .progress { margin-top: 5px; }
.poolrow__meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  margin-top: 3px;
  font-size: var(--fs-xs);
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
}
.pool__result {
  padding: var(--s-3);
  border: 1px dashed var(--line-2);
  border-radius: var(--r-sm);
  font-size: var(--fs-s);
  color: var(--text-2);
}
.pool__result--hit {
  border: 1px solid var(--ok-line);
  background: var(--ok-soft);
  color: var(--ok);
  font-weight: var(--fw-bold);
}
/* шаги взноса плотнее обычных табов: их пять, и на 320 они обязаны влезать
   без горизонтального скролла внутри модалки */
.segbar--steps .seg { flex: 1 1 0; min-width: 0; padding: 0 var(--s-2); font-size: var(--fs-xs); text-align: center; }

/* норма дня на карточке серии: цифра, к которой человек себя примеряет */
.daily__norm {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-2);
  padding: var(--s-3);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--glass-1);
}

/* ─── компактное голосование в ленте ДВИЖа: лидер + переход внутрь ─── */
/* плотнее обычной карточки: в ленте две-три такие плашки идут подряд, и
   штатный отступ card--pad съедал бы половину экрана */
.minipoll { padding: var(--s-4); }
.minipoll__lead {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr);
  gap: var(--s-3);
  align-items: center;
  width: 100%;
  margin-top: var(--s-3);
  padding: 0;
  border: 0;
  background: none;
  text-align: left;
  color: inherit;
  font-family: var(--font);
  cursor: pointer;
}
.minipoll__lead:active { opacity: .82; }
.minipoll__img {
  position: relative;
  display: block;
  width: 44px;
  height: 44px;
  border-radius: var(--r-xs);
  overflow: hidden;
  background: var(--card-2);
}
.minipoll__img img { width: 100%; height: 100%; object-fit: cover; }
.minipoll__img .pollcard__ph { height: 44px; }
.minipoll__img .pollcard__ph .avatar { font-size: var(--fs-m); }
/* «1 место» садится на угол фото: лидер должен читаться до строки с процентами */
.minipoll__medal {
  position: absolute;
  right: -2px;
  bottom: -2px;
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 1px 5px;
  border-radius: var(--r-pill);
  background: linear-gradient(140deg, #FFE8AE, var(--gold) 58%, #C79A54);
  color: #1A1004;
  font-size: 10px;
  font-weight: var(--fw-xbold);
  box-shadow: 0 2px 8px rgba(0, 0, 0, .45);
}
.minipoll__medal svg { width: 10px; height: 10px; }
.minipoll__name { display: block; font-size: var(--fs-m); font-weight: var(--fw-xbold); text-transform: uppercase; }
.minipoll__meta { display: block; margin-top: 2px; font-size: var(--fs-xs); color: var(--text-2); font-variant-numeric: tabular-nums; }

.guestcard { width: 168px; }
/* в рельсе карточка гостя вертикальная: фото сверху, подпись снизу */
.guestcard .pollcard { grid-template-columns: 1fr; }
.guestcard .pollcard__img { aspect-ratio: var(--ar-4-5); }

/* ──────────────────────── QUESTS (§15) ───────────────── */
.quest {
  display: grid;
  grid-template-columns: 24px minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--s-3);
  min-height: var(--touch);
  min-width: 0;
  padding: var(--s-3);
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: var(--card);
  cursor: pointer;
  width: 100%;
  font-family: var(--font);
  color: inherit;
  text-align: left;
  transition: border-color var(--t-fast) var(--ease);
}
.quest > * { min-width: 0; }
.quest__box {
  width: 22px;
  height: 22px;
  border-radius: 7px;
  border: 1.5px solid var(--line-3);
  display: grid;
  place-items: center;
  color: transparent;
  transition: all var(--t) var(--ease);
}
.quest__title { font-size: var(--fs-m); font-weight: var(--fw-bold); line-height: var(--lh-tight); width: fit-content; max-width: 100%; }
.quest__meta { font-size: var(--fs-xs); color: var(--text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.quest__reward { font-size: var(--fs-sm); font-weight: var(--fw-xbold); color: var(--gold); font-variant-numeric: tabular-nums; white-space: nowrap; }
.quest[data-done="true"] { border-color: var(--accent-line); }
.quest[data-done="true"] .quest__box { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.quest[data-done="true"] .quest__title { color: var(--text-2); position: relative; }
/* перечёркивание — псевдоэлемент, а не text-decoration: у анимации штриха
   должен быть свой масштабируемый отрезок, иначе он прорисовывался бы скачком */
.quest[data-done="true"] .quest__title::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 52%;
  height: 1.5px;
  background: var(--text-3);
  transform-origin: 0 50%;
}
.quest[data-claimed="1"] .quest__reward { opacity: .55; }

/* готовое к выдаче задание дышит: награда лежит и ждёт тапа. Пульс идёт по
   боксу, а не по всей карточке, — мигающая строка читалась бы как ошибка */
.quest[data-done="true"][data-claimed="0"] .quest__box { animation: quest-ready 2.2s var(--ease) infinite; }
@keyframes quest-ready {
  0%, 100% { box-shadow: 0 0 0 0 rgba(141, 14, 210, 0); }
  50% { box-shadow: 0 0 0 4px rgba(141, 14, 210, .2), 0 0 14px rgba(169, 112, 255, .45); }
}

/* забор задания: бокс упруго щёлкает, галочка обводится штрихом, перечёркнутая
   строка дотягивается до конца. JS снимает атрибут, поэтому всё это — ровно
   один раз после награды, а не при каждом входе на экран */
.quest[data-flash="claim"] .quest__box { animation: quest-pop 420ms var(--ease-spring) 1; }
@keyframes quest-pop {
  0% { transform: scale(1); }
  45% { transform: scale(1.34); }
  100% { transform: scale(1); }
}
.quest[data-flash="claim"] .quest__box svg path {
  stroke-dasharray: 26;
  animation: check-draw 340ms var(--ease-out) 1;
}
@keyframes check-draw { from { stroke-dashoffset: 26; } to { stroke-dashoffset: 0; } }
.quest[data-flash="claim"] .quest__title::after { animation: strike 420ms var(--ease-out) 1; }
@keyframes strike { from { transform: scaleX(0); } to { transform: scaleX(1); } }

.combo {
  display: grid;
  gap: var(--s-2);
  padding: var(--s-4);
  border-radius: var(--r-md);
  border: 1px dashed var(--gold-line);
  background: var(--gold-soft);
}
/* связка идёт сразу за списком заданий: в плотном стеке она обязана
   читаться отдельным блоком, а не ещё одной строкой списка */
.stack > .combo { margin-top: var(--s-3); }
.combo[data-on="true"] { border-style: solid; border-color: var(--accent-line); background: var(--accent-soft); }

/* ─────────────────── DAILY STREAK (§13) ──────────────── */
.streak { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: var(--s-2); }
.streak__day {
  display: grid;
  justify-items: center;
  gap: 3px;
  min-width: 0;
  padding: var(--s-2) 2px;
  border-radius: var(--r-sm);
  border: 1px solid var(--line);
  background: var(--card);
  font-size: 10px;
  font-weight: var(--fw-bold);
  color: var(--text-2);
}
.streak__day b { font-size: var(--fs-xs); color: var(--gold); font-variant-numeric: tabular-nums; }
.streak__day[data-done="true"] { border-color: var(--accent-line); background: var(--accent-soft); color: var(--accent); }
.streak__day[data-done="true"] b { color: var(--accent); }
.streak__day[data-today="true"] { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent-line); }

/* ─────────────── SLOT «BIGBOY MACHINE» (§19) ──────────── */
/* Витрина без города и прочего ширма: только ночь, золото и свет.
   Ячейка нарочно крупная — барабан читают с телефона, и символ на нём
   должен быть больше, чем значок в списке. */
.slot--machine {
  --cell: clamp(84px, 26.5vw, 104px);
  position: relative;
  isolation: isolate;
  overflow: hidden;
  border-radius: var(--r-xl);
  border: 1px solid var(--gold-line);
  background: #05060f;
  box-shadow: var(--sh-2);
}
/* задник: ночная стена под прожекторами. Фото города здесь спорило с
   барабанами и тянуло экран в открытку — свет сам рисует глубину */
.machine__bg {
  position: absolute;
  inset: -6% -4%;
  z-index: 0;
  background:
    radial-gradient(70% 44% at 50% 0%, rgba(141, 14, 210, .5), transparent 66%),
    radial-gradient(52% 34% at 12% 26%, rgba(255, 79, 208, .22), transparent 70%),
    radial-gradient(58% 40% at 88% 62%, rgba(52, 217, 164, .12), transparent 72%),
    linear-gradient(180deg, #150C2E 0%, #0A0718 46%, #05060F 100%);
}
.machine__veil {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    radial-gradient(90% 52% at 50% 44%, rgba(141, 14, 210, .22), transparent 72%),
    linear-gradient(180deg, rgba(5, 6, 15, .5), rgba(5, 6, 15, 0) 38%, rgba(5, 6, 15, .6));
}
/* два прожектора водят конусами по витрине. Клипа здесь нет намеренно:
   луч рисует conic-градиент с растёканными краями, и он не требует
   размытия — у clip-path всегда есть три ровных ребра, которые на тёмном
   фоне читаются как вырезанная плёнка. mix-blend-mode здесь тоже нет: blend
   заставляет браузер держать отдельную поверхность под всем автоматом, и
   во время прокрутки это второй источник чёрных провалов. На почти чёрном
   заднике обычный режим рисует тот же свет. */
.machine__veil::before,
.machine__veil::after {
  content: "";
  position: absolute;
  left: -60%;
  right: -60%;
  bottom: -34%;
  height: 128%;
  transform-origin: 50% 100%;
  animation: beam 11s var(--ease) infinite alternate;
}
.machine__veil::before {
  background: conic-gradient(from -8deg at 50% 100%, transparent 0deg, rgba(186, 208, 255, .22) 8deg, transparent 16deg);
}
.machine__veil::after {
  background: conic-gradient(from -8deg at 50% 100%, transparent 0deg, rgba(169, 112, 255, .2) 8deg, transparent 16deg);
  animation-duration: 8.5s;
  animation-delay: -3.4s;
}
@keyframes beam {
  from { transform: rotate(-22deg); }
  to { transform: rotate(18deg); }
}
.machine__inner {
  position: relative;
  z-index: 2;
  display: grid;
  gap: var(--s-2);
  padding: var(--s-3) var(--s-3) var(--s-4);
}
.machine__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

/* ── вывеска: жёлтое тело, красная обводка, красное дыхание ──
   Обводка — штрихом, а не тенью: текст-тень это копия глифа, она
   закрыла бы прозрачную заливку целиком. */
.machine__logo {
  display: grid;
  justify-items: center;
  gap: 3px;
  position: relative;
  margin: 0 0 var(--s-1);
  font-family: var(--font-brand);
  font-weight: 900;
  text-align: center;
  /* подсветка корпуса — статичный фильтр: он растеризуется один раз */
  filter: drop-shadow(0 3px 0 #5E0116);
}
/* дыхание неона рисует мягкий свет отдельным слоем и дышит он opacity.
   Анимировать сам filter нельзя: каждый кадр пересобирает поверхность
   размытия, и на телефоне это стоит экрану чёрных провалов во время
   прокрутки барабанов */
.machine__logo::before {
  content: "";
  position: absolute;
  left: 6%;
  right: 6%;
  top: -12%;
  bottom: -18%;
  z-index: -1;
  border-radius: 50%;
  filter: blur(7px);
  background: radial-gradient(58% 58% at 50% 50%, rgba(255, 45, 75, .6), rgba(255, 45, 75, 0) 72%);
  animation: logo-red 1.9s var(--ease) infinite alternate;
}
.machine__logo-top {
  font-size: 30px;
  line-height: 1;
  letter-spacing: .01em;
  color: var(--gold);
  -webkit-text-stroke: 2.4px #E11236;
}
@supports (background-clip: text) or (-webkit-background-clip: text) {
  .machine__logo-top {
    color: transparent;
    background-image: linear-gradient(180deg, #FFF3C4 8%, #FFD24A 44%, #F2A21C 64%, #FFDE6B 100%);
    -webkit-background-clip: text;
    background-clip: text;
  }
}
.machine__logo-bot {
  font-size: 12px;
  letter-spacing: .28em;
  padding: 3px 9px 3px 12px;
  border-radius: 7px;
  color: #FFE58A;
  background: linear-gradient(180deg, #FF3355, #A5062A);
  border: 1px solid #5E0116;
  box-shadow: 0 2px 0 #5E0116, 0 6px 16px rgba(255, 51, 85, .35);
}
@keyframes logo-red {
  from { opacity: .3; }
  to { opacity: 1; }
}

/* ── копилка джекпота ────────────────────────────────────
   Табло висит над барабанами: игрок обязан видеть, за чем пришёл, до того
   как потратил ставку. Цифра растёт с платными спинами и падает к базе
   после линии BIGBOY — это единственный в машине счёт, который меняется
   между вращениями сам. */
.machine__pot {
  justify-self: center;
  display: flex;
  align-items: center;
  gap: var(--s-2);
  padding: 5px 13px 5px 11px;
  border-radius: 999px;
  background:
    radial-gradient(80% 150% at 50% 0, rgba(242, 201, 121, .2), transparent 68%),
    linear-gradient(180deg, #1A1230, #0A0716);
  border: 1px solid rgba(242, 201, 121, .4);
  box-shadow: inset 0 1px 0 rgba(255, 236, 170, .26), 0 6px 18px rgba(0, 0, 0, .45);
  transition: box-shadow var(--t) var(--ease), border-color var(--t) var(--ease);
}
.pot__cap {
  font-size: var(--fs-xs);
  font-weight: var(--fw-xbold);
  letter-spacing: .18em;
  color: #FFE58A;
  opacity: .78;
}
.pot__val {
  font-size: var(--fs-l);
  font-weight: var(--fw-xbold);
  color: var(--gold);
  font-variant-numeric: tabular-nums;
  text-shadow: 0 0 12px rgba(242, 201, 121, .45);
}
.slot--machine[data-jackpot="true"] .machine__pot {
  border-color: #FFDE8F;
  box-shadow: inset 0 1px 0 rgba(255, 236, 170, .4), 0 0 26px rgba(255, 205, 110, .55);
}

/* ── три барабана в золотой оправе ─────────────────────── */
/* Перспектива живёт только в окне барабана. У самой сцены её быть не
   должно: тогда цилиндр искажается один раз (своей перспективой), а не
   два — и барабаны перестают расходиться по швам на узких экранах. */
.machine__stage {
  position: relative;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s-2);
  padding: 14px 12px;
  border-radius: var(--r-md);
  border: 1px solid var(--gold-line);
  background:
    linear-gradient(180deg, rgba(255, 240, 200, .12), rgba(0, 0, 0, .5)),
    rgba(4, 6, 16, .8);
  box-shadow:
    inset 0 0 0 2px rgba(242, 201, 121, .3),
    inset 0 1px 0 rgba(255, 255, 255, .16),
    inset 0 -16px 28px rgba(0, 0, 0, .5),
    0 18px 40px rgba(2, 4, 12, .6),
    0 0 46px rgba(141, 14, 210, .34);
}
/* золотые щёчки по краям блока — как у настоящего автомата */
.machine__stage::before,
.machine__stage::after {
  content: "";
  position: absolute;
  top: 5px;
  bottom: 5px;
  width: 6px;
  border-radius: var(--r-pill);
  background: linear-gradient(90deg, #6B4D13, #F2C979 45%, #8A6318);
}
.machine__stage::before { left: 2px; }
.machine__stage::after { right: 2px; }
.machine__line {
  position: absolute;
  left: 8px;
  right: 8px;
  top: 50%;
  height: 2px;
  transform: translateY(-50%);
  z-index: 4;
  pointer-events: none;
  opacity: .45;
  background: linear-gradient(90deg, transparent, rgba(255, 45, 75, .9), transparent);
  box-shadow: 0 0 12px rgba(255, 45, 75, .55);
}
/* ── барабан: цилиндр из 16 граней на общей оси ─────────── */
.reel {
  position: relative;
  height: calc(var(--cell) * 3);
}
/* окно: здесь живёт перспектива, за его пределы грани не выходят.
   --r (радиус) и --p (дистанцию зрителя) считает JS из высоты ячейки. */
.reel__win {
  position: absolute;
  inset: 0;
  overflow: hidden;
  border-radius: 12px;
  perspective: var(--p, 580px);
  background: radial-gradient(130% 96% at 50% 44%, #2A2350, #070713 76%);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .55), inset 0 0 30px rgba(0, 0, 0, .65);
}
.reel__cyl {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  will-change: transform;
  transform: translateZ(-194px);
}
/* грань стоит в полосе средней строки — вокруг её центра намотана ось.
   Грань тёмная намеренно: на белом барабане автомат превращается в ленту
   принтера, а монета и купюра живут в темноте и светятся сами */
.reel__face {
  position: absolute;
  left: 0;
  right: 0;
  top: var(--cell);
  height: var(--cell);
  display: grid;
  place-items: center;
  overflow: hidden;
  backface-visibility: hidden;
  transform: rotateX(calc(var(--i) * var(--step, 30deg))) translateZ(var(--r, 194px));
  background: linear-gradient(180deg, #241B44 0%, #16102C 46%, #0C0819 100%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .14),
    inset 0 0 0 1px rgba(4, 3, 12, .8),
    inset 0 -10px 18px rgba(0, 0, 0, .55);
}
/* торец цилиндра: золото ложится сверху и снизу, как настоящая оправа */
.reel::before,
.reel::after {
  content: "";
  position: absolute;
  left: -3px;
  right: -3px;
  height: 16px;
  z-index: 4;
  border-radius: 8px;
  background: linear-gradient(180deg, #4A3409, #C99A34 22%, #F7DD9A 44%, #B8862A 68%, #3A2908);
  box-shadow: 0 2px 9px rgba(0, 0, 0, .7), inset 0 1px 0 rgba(255, 255, 255, .55);
}
.reel::before { top: -8px; }
.reel::after { bottom: -8px; }
/* свет прожекторов по цилиндру: средняя строка ловит блик, края тонут
   в темноте под торцами. До темноты не дожимаем — соседняя грань и есть
   доказательство объёма, совсем невидимая, барабан снова станет плашкой */
.reel__shade {
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  border-radius: 12px;
  background:
    linear-gradient(180deg, rgba(4, 6, 16, .9) 0%, rgba(4, 6, 16, .56) 12%,
      rgba(4, 6, 16, .16) 27%, rgba(4, 6, 16, 0) 39%, rgba(4, 6, 16, 0) 61%,
      rgba(4, 6, 16, .16) 73%, rgba(4, 6, 16, .56) 88%, rgba(4, 6, 16, .9) 100%),
    linear-gradient(180deg, rgba(255, 255, 255, 0) 40%, rgba(255, 246, 222, .1) 50%,
      rgba(255, 255, 255, 0) 60%),
    linear-gradient(90deg, rgba(4, 6, 16, .62), rgba(255, 255, 255, .12) 44%,
      rgba(255, 255, 255, .03) 58%, rgba(4, 6, 16, .62));
}
/* Смаз движения — один статичный слой поверх граней, а не filter на каждой
   из них. Любой фильтр внутри preserve-3d (drop-shadow на символе, blur на
   грани) превращает каждую грань в отдельный слой, который браузер пересобирает
   на каждом кадре прокрутки: на телефоне это провалы экрана в чёрное.
   Объём грани делает её собственный градиент, фильтры в цилиндре не нужны. */
.reel__win::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  opacity: 0;
  transition: opacity .16s var(--ease);
  background: repeating-linear-gradient(180deg, rgba(255, 255, 255, .08) 0 1px,
    rgba(255, 255, 255, 0) 1px 11px);
}
.reel[data-spinning="true"] .reel__win::after { opacity: 1; }
.reel__face .sym { filter: none; }
.reel[data-win="true"] .reel__win {
  box-shadow: inset 0 0 0 2px var(--gold), 0 0 30px rgba(242, 201, 121, .6);
}

/* Между спинами автомат не замирает: линия выплаты дышит, свет на барабанах
   ходит вразнобой. Трансформы цилиндров не трогаем — их считает JS, любая
   анимация поверх них сдвинула бы грани относительно оси */
.machine__line { animation: line-idle 3.6s var(--ease) infinite; }
@keyframes line-idle {
  0%, 100% { opacity: .4; }
  50% { opacity: .78; }
}
.reel__shade { animation: shade-idle 6s var(--ease) infinite alternate; }
.machine__stage .reel:nth-child(2) .reel__shade { animation-duration: 7.4s; animation-delay: -2.1s; }
.machine__stage .reel:nth-child(3) .reel__shade { animation-duration: 8.2s; animation-delay: -4.4s; }
@keyframes shade-idle {
  from { opacity: .84; }
  to { opacity: 1; }
}

/* ── символы: BIGBOY — главный выигрыш, крупнее и дороже всех ── */
.sym {
  display: block;
  max-width: 100%;
  object-fit: contain;
  filter: drop-shadow(0 4px 6px rgba(0, 0, 0, .35));
}
.sym--xl { height: 98%; }   /* BIGBOY занимает грань целиком */
.sym--l { height: 62%; }   /* купюры */
/* монета — та же COIN, что лежит в балансе, только крупная. Её рисует
   CSS, а не картинка: на гранях барабана растр мылится первым делом.
   Размер держит .sym--m (квадрат от высоты грани), диск — .sym__disc */
.sym--coin {
  display: grid;
  place-items: center;
}
.sym--m {
  height: 58%;
  aspect-ratio: 1 / 1;
}
.sym__disc {
  width: 100%;
  height: 100%;
  display: grid;
  place-items: center;
  border-radius: 50%;
  font-family: var(--font-brand);
  font-weight: 900;
  font-size: calc(var(--cell) * .22);
  line-height: 1;
  color: #56390A;
  text-shadow: 0 1px 0 rgba(255, 250, 226, .55);
  background: radial-gradient(circle at 36% 24%, #FFF7DA 0%, #FFDE8F 26%, #E8A93A 56%,
    #A9701C 82%, #6E4A10 100%);
  box-shadow:
    inset 0 0 0 3px rgba(255, 248, 220, .62),
    inset 0 6px 12px rgba(255, 255, 255, .42),
    inset 0 -8px 14px rgba(96, 58, 6, .55),
    0 6px 16px rgba(0, 0, 0, .6),
    0 0 20px rgba(242, 201, 121, .3);
}
/* глянец как у настоящей «7»: верхний блик, тёмная середина, отражение
   снизу. Обводка — штрихом: text-shadow это копия глифа, она закрыла бы
   прозрачную заливку. */
.sym--word {
  display: grid;
  align-content: center;
  justify-items: center;
  font-family: var(--font-brand);
  font-weight: 900;
  font-size: calc(var(--cell) * .3);
  line-height: .82;
  letter-spacing: -.03em;
  white-space: nowrap;
  background: linear-gradient(180deg, #FFC9D2 0%, #FF4A66 22%, #B00A26 48%,
    #FF7A90 62%, #D5122F 82%, #7A0318 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-stroke: 1.8px #F2C979;
  filter: drop-shadow(0 2px 0 #5E0116) drop-shadow(0 6px 8px rgba(0, 0, 0, .45));
}

/* ── нижняя панель: баланс, ставка, SPIN ───────────────── */
.machine__panel {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: center;
  gap: var(--s-2);
  margin-top: var(--s-2);
  padding: var(--s-2);
  border-radius: var(--r-md);
  border: 1px solid var(--line-2);
  background: rgba(4, 6, 16, .76);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .08);
}
.gauge { display: grid; gap: 2px; min-width: 0; }
.gauge__cap {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: .16em;
  color: var(--text-3);
}
.gauge__val { display: flex; align-items: center; gap: var(--s-1); min-width: 0; }
.gauge__val .num {
  font-size: var(--fs-l);
  font-weight: var(--fw-xbold);
  font-variant-numeric: tabular-nums;
  color: var(--gold);
}
.gauge--bet .gauge__val { justify-content: space-between; }
.gauge--bet .num {
  min-width: 40px;
  text-align: center;
  color: var(--text);
}
.mstep {
  flex: 0 0 auto;
  width: 28px;
  height: 28px;
  display: grid;
  place-items: center;
  border-radius: 9px;
  border: 1px solid var(--line-2);
  background: var(--glass-2);
  color: var(--text);
  cursor: pointer;
  transition: transform var(--t-fast) var(--ease);
}
.mstep:active { transform: scale(.9); background: var(--accent-soft); }
.mstep i { display: block; line-height: 0; }
/* Пока крутятся дневные free-спины, ставка игрока ни на что не влияет — шаги
   гаснут, чтобы не выглядеть контролом, который что-то меняет. */
.gauge--bet[data-free="true"] .mstep { opacity: .3; pointer-events: none; }
.mspin {
  position: relative;
  flex: 0 0 auto;
  width: 62px;
  height: 62px;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 1px;
  border-radius: 50%;
  border: 2px solid var(--gold);
  background: radial-gradient(62% 62% at 50% 28%, #FF5C78, #C00E30 56%, #6C0419);
  color: #fff;
  cursor: pointer;
  box-shadow:
    0 0 0 4px rgba(255, 45, 75, .16),
    0 10px 24px rgba(2, 4, 12, .6),
    inset 0 1px 0 rgba(255, 255, 255, .35);
  transition: transform var(--t-fast) var(--ease);
}
.mspin:active { transform: scale(.94); }
.mspin__ico { display: block; line-height: 0; }
.mspin__cap {
  font-family: var(--font-brand);
  font-size: 9px;
  font-weight: 800;
  letter-spacing: .1em;
}
/* бесплатная прокрутка видна до нажатия: красная кнопка — «плачу COIN»,
   сиреневая с числом — «кручу дневное». Без этого человек смотрит на
   неподвижный баланс и решают, что free-спинов не существует */
.mspin[data-free="true"] {
  border-color: var(--violet);
  background: radial-gradient(62% 62% at 50% 28%, #D89BFF, var(--accent) 58%, #480A80);
  box-shadow:
    0 0 0 4px rgba(141, 14, 210, .2),
    0 10px 24px rgba(2, 4, 12, .6),
    inset 0 1px 0 rgba(255, 255, 255, .35);
}
.mspin__free {
  position: absolute;
  top: -4px;
  right: -3px;
  min-width: 19px;
  height: 19px;
  padding: 0 4px;
  display: grid;
  place-items: center;
  border-radius: 10px;
  border: 1px solid rgba(5, 6, 15, .85);
  background: var(--gold);
  color: #2A1B04;
  font-family: var(--font-brand);
  font-size: 11px;
  font-weight: 900;
  line-height: 1;
  box-shadow: 0 2px 6px rgba(2, 4, 12, .6);
}
.mspin[data-free="false"] .mspin__free { display: none; }
.mspin[data-busy="true"] .mspin__ico { animation: spin-ico .7s linear infinite; }
@keyframes spin-ico { to { transform: rotate(360deg); } }
.machine__tools {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s-2);
  margin-top: var(--s-2);
}
/* в панели автомата места мало: кнопки плотнее, чем обычные .btn */
.machine__tools .btn { padding: 0 var(--s-2); letter-spacing: .01em; }

/* ── строка результата и таблица выплат ────────────────── */
.slot__msg {
  min-height: 20px;
  display: grid;
  place-items: center;
  font-size: var(--fs-sm);
  font-weight: var(--fw-xbold);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: rgba(242, 245, 255, .72);
  text-shadow: 0 2px 8px rgba(0, 0, 0, .6);
}
.slot__msg[data-tone="win"] { color: var(--gold); }
.slot__msg[data-tone="jackpot"] { color: #FF6A80; }
.slot__msg[data-tone="near"] { color: var(--violet); }
.slot__msg[data-tone="loss"] { color: var(--text-3); }
.slot__pay { display: grid; gap: var(--s-2); font-size: var(--fs-xs); color: var(--text-2); }
/* копилка в тех же правилах, что и множители: без строки о ней покупали бы
   вслепую */
.slot__extra { display: grid; gap: var(--s-2); margin-top: var(--s-4); }
.slot__pay i {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  font-style: normal;
  font-variant-numeric: tabular-nums;
}
.pay__l { display: flex; align-items: center; gap: var(--s-2); min-width: 0; }
.pay__ico { width: 26px; height: 26px; object-fit: contain; }
/* монета в таблице — тот же диск, что на барабане, только сжатый до
   высоты строки: два разных рисунка одной валюты путают */
.pay__disc {
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  font-family: var(--font-brand);
  font-size: 13px;
  font-weight: 900;
  line-height: 1;
  color: #56390A;
  background: radial-gradient(circle at 34% 26%, #FFF2CC, #F2C979 46%, #B9862B 100%);
  box-shadow: inset 0 0 0 2px rgba(255, 246, 214, .55), inset 0 -3px 6px rgba(112, 72, 12, .5);
}
.pay__word {
  font-family: var(--font-brand);
  font-size: var(--fs-m);
  font-weight: 900;
  letter-spacing: -.01em;
  color: #E11236;
}
.pay__r { color: var(--gold); font-weight: var(--fw-bold); }

@keyframes jackpot {
  0%, 100% { transform: scale(1); }
  30% { transform: scale(1.05) rotate(-1.2deg); }
  60% { transform: scale(1.02) rotate(1.2deg); }
}
.slot--machine[data-jackpot="true"] { animation: jackpot 600ms var(--ease) 2; }
.slot--machine[data-jackpot="true"] .machine__logo { animation-duration: .32s; }

/* ── моушен результата ───────────────────────────────────
   Выдачу сопровождают свет, линия и копилка: на один текст реакция
   приходит позже, чем его дочитывают. Атрибуты снимает JS, поэтому
   каждый следующий выигрыш перезапускает анимацию, а не доедает прошлую. */
.machine__sweep {
  position: absolute;
  inset: 0;
  z-index: 5;
  pointer-events: none;
  overflow: hidden;
}
.machine__sweep::before {
  content: "";
  position: absolute;
  top: -18%;
  bottom: -18%;
  left: -46%;
  width: 38%;
  background: linear-gradient(90deg, transparent, rgba(255, 246, 214, .34) 48%, transparent);
  filter: blur(7px);
}
.slot--machine[data-flash] .machine__sweep { animation: machine-sweep 780ms var(--ease-out) 1; }
.slot--machine[data-flash="jackpot"] .machine__sweep { animation-duration: 1150ms; }
@keyframes machine-sweep {
  0% { opacity: 0; transform: translateX(0); }
  14% { opacity: 1; }
  86% { opacity: 1; }
  100% { opacity: 0; transform: translateX(370%); }
}
.machine__line[data-flare] { animation: line-flare 700ms var(--ease-out) 1; }
.machine__line[data-flare="jackpot"] { animation-duration: 1100ms; }
@keyframes line-flare {
  0%, 100% {
    opacity: .45;
    transform: translateY(-50%) scaleY(1);
    box-shadow: 0 0 12px rgba(255, 45, 75, .55);
  }
  18% {
    opacity: 1;
    transform: translateY(-50%) scaleY(2.6);
    box-shadow: 0 0 28px rgba(255, 226, 150, .95);
  }
  60% { opacity: .9; transform: translateY(-50%) scaleY(1.5); }
}
.machine__pot[data-gain="true"] { animation: pot-pop 620ms var(--ease-spring) 1; }
@keyframes pot-pop {
  0%, 100% { transform: scale(1); }
  32% { transform: scale(1.06); }
}
/* цилиндр останавливается не в ноль, а с просадом: тяжёлый барабан иначе
   неотличим от картинки, которая просто сменилась */
.reel[data-settle="true"] { animation: reel-settle 320ms var(--ease-out) 1; }
@keyframes reel-settle {
  0%, 100% { transform: translateY(0); }
  35% { transform: translateY(3px); }
  72% { transform: translateY(-1px); }
}

@media (max-width: 359px) {
  .machine__logo-top { font-size: 26px; }
  .machine__logo-bot { font-size: 11px; letter-spacing: .22em; }
  .mspin { width: 56px; height: 56px; }
  .gauge__val .num { font-size: var(--fs-base); }
}
@media (prefers-reduced-motion: reduce) {
  .machine__veil::before,
  .machine__veil::after,
  .machine__logo::before,
  .mspin[data-busy="true"] .mspin__ico,
  .slot--machine[data-flash] .machine__sweep,
  .machine__line[data-flare],
  .machine__pot[data-gain="true"],
  .reel[data-settle="true"] { animation: none; }
}

/* ──────────────────── плитки игр (GAMES) ──────────────── */
.gamegrid { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--s-3); }
/* одна игра в разделе — плитка во всю ширину, иначе справа зияет пустота */
.gametile--wide { grid-column: 1 / -1; }
.gametile {
  position: relative;
  display: grid;
  align-content: start;
  gap: var(--s-2);
  min-height: 116px;
  padding: var(--s-4);
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--text);
  font-family: var(--font);
  text-align: left;
  cursor: pointer;
  overflow: hidden;
  transition: transform var(--t-fast) var(--ease), border-color var(--t) var(--ease), background var(--t) var(--ease);
}
.gametile:active { transform: scale(.98); }
.gametile__ic {
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  border-radius: var(--r-sm);
  background: var(--accent-soft);
  border: 1px solid var(--accent-line);
  color: var(--accent);
}
.gametile__name { font-size: var(--fs-m); font-weight: var(--fw-xbold); letter-spacing: .04em; text-transform: uppercase; }
/* «ПОЛЬЗОВАТЕЛИ» — длинное слово: на 320 не влезает в плитку даже без переноса */
@media (max-width: 359px) {
  .gametile__name { font-size: var(--fs-s); letter-spacing: .02em; }
}
.gametile__note { font-size: var(--fs-xs); color: var(--text-2); line-height: 1.3; }
.gametile__go { position: absolute; right: var(--s-3); bottom: var(--s-3); color: var(--text-3); display: inline-flex; }
.gametile[data-tone="gold"] .gametile__ic { background: var(--gold-soft); border-color: var(--gold-line); color: var(--gold); }
.gametile[data-tone="gold"] .gametile__name { color: var(--gold); }
/* задания — не золото и не пурпур: это второй акцент палитры, тот же, что
   у свечений. На фоне тёмной плашки чистый --accent читался серым пятном */
.gametile[data-tone="violet"] .gametile__ic { background: rgba(169, 112, 255, .13); border-color: rgba(169, 112, 255, .34); color: var(--violet); }

/* ─────────────── витрина COIN (§26) ───────────────────
   Карточка позиции: превью того, что отдаётся (рамка показана на аватаре,
   а не описана словами), цена и одна кнопка. Состояние карточки читается
   по data-state, а не по цвету текста. */
.shop { display: grid; gap: var(--s-3); }
.shop__card { display: grid; gap: var(--s-2); }
.shop__card[data-state="on"] { border-color: var(--gold-line); box-shadow: 0 0 22px rgba(242, 201, 121, .14); }
/* куплено, но не надето: карточка живая, просто без свечения */
.shop__card[data-state="own"] { border-color: var(--gold-line); }
.shop__card[data-state="done"] { opacity: .62; }
.shop__head { display: flex; align-items: flex-start; gap: var(--s-3); }
.shop__prev { flex: 0 0 auto; width: 44px; display: grid; place-items: center; }
.shop__glyph {
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  border-radius: var(--r-sm);
  background: var(--accent-soft);
  border: 1px solid var(--accent-line);
  color: var(--accent);
}
.shop__name { font-size: var(--fs-m); font-weight: var(--fw-xbold); letter-spacing: .03em; text-transform: uppercase; }
.shop__hint { margin: 2px 0 0; font-size: var(--fs-xs); color: var(--text-2); line-height: 1.35; }
.shop__stock { display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-3); }
.shop__note { font-size: var(--fs-xs); color: var(--gold); }
.shop__note--lack { color: var(--text-3); }
.shop__foot { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); }
.shop__foot .btn { min-width: 116px; }
.shop__done { font-size: var(--fs-xs); font-weight: var(--fw-xbold); letter-spacing: .1em; text-transform: uppercase; color: var(--text-3); }

/* Витрина дышит только там, где это что-то значит: золотой блик бежит по
   цене, когда позиции уже по карману, и лежит на месте, когда до неё ещё
   копить. Мигать тем, чего сегодня не купить, — обещание без денег за ним */
.shop__card[data-buy="yes"] .shop__foot .coin { position: relative; overflow: hidden; }
.shop__card[data-buy="yes"] .shop__foot .coin::after {
  content: "";
  position: absolute;
  top: -20%;
  bottom: -20%;
  left: -20%;
  width: 18%;
  background: linear-gradient(90deg, transparent, rgba(255, 246, 222, .5), transparent);
  animation: shop-sheen 3.6s var(--ease) infinite;
}
@keyframes shop-sheen {
  0% { transform: skewX(-18deg) translateX(0); opacity: 0; }
  12% { opacity: 1; }
  55%, 100% { transform: skewX(-18deg) translateX(720%); opacity: 0; }
}
/* надетая рамка светится на превью: рамку человек уже носит, и превью должно
   показывать это, а не просто лежать золотой плашкой */
.shop__card[data-state="on"] .shop__prev { animation: tryon 3s var(--ease) infinite; }
@keyframes tryon {
  0%, 100% { filter: drop-shadow(0 0 0 rgba(242, 201, 121, 0)); }
  50% { filter: drop-shadow(0 0 9px rgba(242, 201, 121, .55)); }
}
@media (max-width: 359px) {
  .shop__foot .btn { min-width: 92px; }
}

/* ──────── статусы-короны (§26.1) ─────────────────────── */
/* список собран по образцу витрины подарков: корона, имя своим цветом, цена,
   стрелка. Строка — кнопка целиком, чтобы тап попадал в карточку статуса,
   а не терялся между иконкой и ценой */
.statlist { display: grid; gap: var(--s-2); }
.statrow {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  width: 100%;
  padding: var(--s-3);
  border-radius: var(--r-sm);
  border: 1px solid var(--line);
  background: var(--glass-1);
  color: var(--text);
  text-align: left;
  cursor: pointer;
  transition: border-color var(--t) var(--ease), background var(--t) var(--ease);
}
.statrow:active { transform: scale(.99); }
.statrow[data-state="on"] { border-color: var(--line-3); background: var(--glass-2); }
/* далёкий статус не гаснем сильно: цену всё равно должно быть видно — она и
   есть причина, по которой человек сюда зашёл */
.statrow[data-state="far"] { opacity: .82; }
.statrow__ic { flex: 0 0 auto; width: 42px; display: grid; place-items: center; line-height: 0; }
.statrow__name {
  display: block;
  font-size: var(--fs-m);
  font-weight: var(--fw-xbold);
  letter-spacing: .06em;
  text-transform: uppercase;
}
.statrow__note { display: block; margin-top: 2px; font-size: var(--fs-xs); color: var(--text-2); }
.statrow__go { flex: 0 0 auto; color: var(--text-3); display: grid; place-items: center; line-height: 0; }
/* надетая корона дышит — в списке должно читаться не только название, но и
   то, что человек носит это прямо сейчас */
.statrow[data-state="on"] .statrow__ic { animation: crownbreath 2.8s var(--ease) infinite; }
@keyframes crownbreath {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.08); }
}
.statprev { display: grid; place-items: center; padding: var(--s-2) 0 0; }

/* корона на макушке: выступает за аватар, потому живёт в обёртке и ничего
   не ловит тапами — тап по аватару остаётся тапом по аватару.
   Покой — с наклоном и опорой на край головы: pivot низа, а не центра,
   иначе при повороте обод уезжал бы то в лоб, то в макушку */
.avcrown {
  position: absolute;
  left: 50%;
  transform: translateX(-50%) rotate(-14deg);
  transform-origin: 50% 86%;
  line-height: 0;
  z-index: 2;
  pointer-events: none;
}
.avcrown svg { display: block; }

/* ── корона как предмет, а не как значок ──────────────────
   Блик бежит по металлу только на крупных коронах (класс --glint навешивает
   hub-icons при размере 28+): в списке статусов и в превью это тот самый
   «хочется купить», а в чипе под ником он превратился бы в мигание.
   Звёзды есть только у высшей короны — они и есть отличие ЛЕГЕНДЫ. */
.crownart .cr-glint { opacity: 0; }
.crownart--glint .cr-glint { animation: crownglint 3.8s var(--ease) infinite; }
@keyframes crownglint {
  0%, 46% { transform: translateX(0); opacity: 0; }
  54% { opacity: .85; }
  82% { opacity: .6; }
  100% { transform: translateX(42px); opacity: 0; }
}
.cr-star {
  transform-box: fill-box;
  transform-origin: 50% 50%;
  animation: crstar 2.8s var(--ease) infinite;
}
.cr-star + .cr-star { animation-delay: -1.4s; }
@keyframes crstar {
  0%, 100% { opacity: .55; transform: scale(.9); }
  45% { opacity: 1; transform: scale(1.22); }
}

/* корона садится на голову: приходит сверху с разворота, пружинит и
   остаёт лежать набок. Ровно по центру она выглядела бы наклейкой,
   с наклоном — предметом, который надели */
.avcrown.is-land { animation: crownLand .72s var(--ease-spring) both; }
@keyframes crownLand {
  0% { opacity: 0; transform: translateX(-50%) translateY(-30px) rotate(-46deg) scale(1.24); }
  38% { opacity: 1; }
  70% { transform: translateX(-50%) translateY(3px) rotate(-9deg) scale(.96); }
  100% { opacity: 1; transform: translateX(-50%) rotate(-14deg); }
}
/* искры в момент посадки: одна вспыка точек по кругу, без конфетти */
.avspark {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 3px;
  height: 3px;
  margin: -1.5px 0 0 -1.5px;
  border-radius: 50%;
  color: rgba(255, 226, 150, .95);
  background: currentColor;
  box-shadow: -17px -13px 0 0 currentColor, 15px -19px 0 0 currentColor, 21px 5px 0 -1px currentColor,
    -19px 9px 0 -1px currentColor, 3px 21px 0 -1px currentColor, -5px -23px 0 -1px currentColor;
  pointer-events: none;
  animation: crownSpark .78s var(--ease-out) both;
}
@keyframes crownSpark {
  0% { opacity: 0; transform: scale(.4); }
  26% { opacity: 1; }
  100% { opacity: 0; transform: scale(1.6); }
}

/* ── живые иконки плашек раздела ───────────────────────────
   Каждая двигает то, что означает: у автомата ходят барабаны и тянется
   рычаг, у витрины приоткрывается крышка и поднимается монета, у заданий
   по очереди прорисовываются галочки. Конечный кадр всегда «на месте» —
   при выключенном движении плашка выглядит законченной, а не недорисованной */
.tfx { display: block; }
.tfx-reel { transform-box: fill-box; }
.tfx-reel--1 { animation: tfxReel 1.15s var(--ease) infinite alternate; }
.tfx-reel--2 { animation: tfxReel 1.6s var(--ease) -.5s infinite alternate; }
.tfx-reel--3 { animation: tfxReel 2s var(--ease) -1s infinite alternate; }
@keyframes tfxReel {
  from { transform: translateY(-2px); opacity: .5; }
  50% { opacity: 1; }
  to { transform: translateY(2px); opacity: .5; }
}
.tfx-lever {
  transform-box: fill-box;
  transform-origin: 0% 100%;
  animation: tfxLever 3.8s var(--ease) infinite;
}
@keyframes tfxLever {
  0%, 58% { transform: rotate(0); }
  70% { transform: rotate(38deg); }
  84% { transform: rotate(-5deg); }
  100% { transform: rotate(0); }
}
.tfx-line {
  stroke-dasharray: 13.2;
  stroke-dashoffset: 13.2;
  opacity: 0;
  animation: tfxLine 3.8s var(--ease) infinite;
}
@keyframes tfxLine {
  0%, 66% { opacity: 0; stroke-dashoffset: 13.2; }
  72% { opacity: 1; }
  92%, 100% { opacity: 0; stroke-dashoffset: 0; }
}
.tfx-lid {
  transform-box: fill-box;
  transform-origin: 34% 100%;
  animation: tfxLid 4.4s var(--ease) infinite;
}
@keyframes tfxLid {
  0%, 40% { transform: translateY(0) rotate(0); }
  52% { transform: translateY(-1.8px) rotate(-7deg); }
  66% { transform: translateY(-.4px) rotate(-1deg); }
  80%, 100% { transform: translateY(0) rotate(0); }
}
.tfx-coin {
  transform-box: fill-box;
  opacity: 0;
  animation: tfxCoin 4.4s var(--ease) infinite;
}
@keyframes tfxCoin {
  0%, 42% { opacity: 0; transform: translateY(4px) scale(.6); }
  56% { opacity: 1; transform: translateY(0) scale(1); }
  72% { opacity: 1; transform: translateY(-2.4px) scale(1); }
  86%, 100% { opacity: 0; transform: translateY(-4.4px) scale(.85); }
}
.tfx-spark {
  transform-box: fill-box;
  transform-origin: 50% 50%;
  animation: tfxSpark 2.4s var(--ease) infinite;
}
@keyframes tfxSpark {
  0%, 100% { opacity: .4; transform: scale(.85); }
  50% { opacity: 1; transform: scale(1.2); }
}
/* покоящаяся галочка — нарисованная: база именно такая, иначе при
   выключенном движении (длительность .01ms, fill none) список возвращался бы
   к пустой заливке и плашка выглядела сломанной */
.tfx-tick {
  stroke-dasharray: 9;
  stroke-dashoffset: 0;
  opacity: 1;
  animation: tfxTick 3.6s var(--ease) infinite;
}
.tfx-tick--2 { animation-delay: .4s; }
.tfx-tick--3 { animation-delay: .8s; }
@keyframes tfxTick {
  0% { opacity: 0; stroke-dashoffset: 9; }
  14% { opacity: 1; stroke-dashoffset: 0; }
  100% { opacity: 1; stroke-dashoffset: 0; }
}
.tfx-scan {
  opacity: 0;
  animation: tfxScan 3.6s var(--ease) infinite;
}
@keyframes tfxScan {
  0% { opacity: 0; transform: translateY(-1px); }
  18% { opacity: .2; }
  46% { opacity: 0; transform: translateY(11px); }
  100% { opacity: 0; transform: translateY(11px); }
}

/* чип статуса под ником: цвет имени приходит из конфига тира, поэтому здесь
   остаются только форма и подложка */
.statname {
  display: inline-flex;
  align-items: center;
  gap: var(--s-1);
  padding: 3px 8px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line-2);
  background: var(--glass-2);
  font-size: 10px;
  font-weight: var(--fw-xbold);
  letter-spacing: .1em;
  text-transform: uppercase;
  line-height: 1.4;
}
.statname i { display: grid; place-items: center; line-height: 0; }

@media (max-width: 359px) {
  .statrow { padding: var(--s-2) var(--s-3); }
  .statrow__note { font-size: 10px; }
}

/* ──────── BIGBOY MACHINE: главный автомат раздела ─────── */
/* единственная игра в GAME, поэтому она не плитка в сетке, а полоса-герой.
   Подложка — тот же свет, что внутри автомата, а не фото города: автомат
   про BIGBOY и деньги, город в витрине был чужим сюжетом */
.slot-hero {
  position: relative;
  display: grid;
  align-content: end;
  gap: var(--s-2);
  width: 100%;
  min-height: 214px;
  padding: var(--s-5);
  border-radius: var(--r-lg);
  border: 1px solid var(--gold-line);
  background:
    radial-gradient(86% 54% at 50% -8%, rgba(242, 201, 121, .26), transparent 62%),
    radial-gradient(96% 74% at 16% 110%, rgba(141, 14, 210, .55), transparent 68%),
    radial-gradient(70% 60% at 92% 84%, rgba(255, 79, 208, .22), transparent 70%),
    linear-gradient(180deg, #1A1240, #080B18 72%);
  color: var(--text);
  font-family: var(--font);
  text-align: left;
  cursor: pointer;
  overflow: hidden;
  box-shadow: var(--rim), 0 20px 46px rgba(141, 14, 210, .26);
  transition: transform var(--t-fast) var(--ease), box-shadow var(--t) var(--ease);
}

.slot-hero:active { transform: scale(.985); }
.slot-hero__scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(10, 8, 26, .18) 0%, rgba(8, 9, 22, .7) 46%, rgba(5, 7, 15, .95) 100%);
}
.slot-hero__cap, .slot-hero__name, .slot-hero__note, .slot-hero__cta {
  position: relative;
  z-index: 1;
}
/* живой автомат в углу плашки: он движется точно так же, как экран внутри,
   и занимает пустой верх — текст прижат книзу, конфликта нет */
.slot-hero__fx {
  position: absolute;
  right: var(--s-4);
  top: var(--s-4);
  z-index: 1;
  color: var(--gold);
  opacity: .92;
  line-height: 0;
  filter: drop-shadow(0 4px 14px rgba(242, 201, 121, .32));
}
.slot-hero__cap {
  font-size: var(--fs-xs);
  font-weight: var(--fw-xbold);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--gold);
}
.slot-hero__name {
  font-family: var(--font-brand);
  font-size: clamp(21px, 6.6vw, 30px);
  line-height: 1.04;
  letter-spacing: -.02em;
  text-transform: uppercase;
  color: #FFF3D6;
  text-shadow: 0 4px 26px rgba(0, 0, 0, .65);
}
.slot-hero__note { font-size: var(--fs-s); line-height: 1.35; color: var(--text-2); max-width: 34ch; }
.slot-hero__cta { display: flex; align-items: center; gap: var(--s-3); margin-top: var(--s-2); }
.slot-hero__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 42px;
  padding: 0 var(--s-5);
  border-radius: var(--r-pill);
  background: var(--grad-cta);
  color: var(--accent-ink);
  font-size: var(--fs-s);
  font-weight: var(--fw-xbold);
  letter-spacing: .05em;
  text-transform: uppercase;
  white-space: nowrap;
  box-shadow: var(--rim-2), 0 10px 26px rgba(141, 14, 210, .45);
}
.slot-hero__hits { margin-left: auto; font-size: var(--fs-xs); color: var(--text-2); font-variant-numeric: tabular-nums; white-space: nowrap; }
@media (max-width: 359px) {
  .slot-hero { min-height: 196px; padding: var(--s-4); }
  .slot-hero__cta { flex-wrap: wrap; gap: var(--s-2); }
  .slot-hero__hits { margin-left: 0; }
}

/* ──────────────────────── BINGO (§21) ────────────────── */
.bingo { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s-2); }
.bingo__cell {
  position: relative;
  aspect-ratio: var(--ar-1-1);
  padding: var(--s-3) var(--s-2) var(--s-2);
  border-radius: var(--r-sm);
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--text-2);
  font-family: var(--font);
  font-size: 10px;
  font-weight: var(--fw-bold);
  line-height: 1.25;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  cursor: pointer;
  transition: all var(--t) var(--ease);
  overflow: hidden;
}
.bingo__cell > i {
  position: absolute;
  top: 5px;
  left: 7px;
  font-style: normal;
  font-size: 9px;
  color: var(--text-3);
  font-variant-numeric: tabular-nums;
}
.bingo__no { font-size: 9px; }
.bingo__cell[data-on="true"] { background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent); }
.bingo__cell[data-on="true"] > i { color: var(--accent); }
.bingo__cell[data-free="true"] { background: var(--gold-soft); border-color: var(--gold-line); color: var(--gold); font-size: 9px; letter-spacing: .08em; text-transform: uppercase; cursor: default; }

/* ────────────────────── PREDICTIONS (§22) ────────────── */
.pick { display: grid; gap: var(--s-2); }
.pick__opt {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  min-height: var(--h);
  padding: 0 var(--s-4);
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--text);
  font-family: var(--font);
  font-size: var(--fs-m);
  font-weight: var(--fw-bold);
  cursor: pointer;
  transition: all var(--t) var(--ease);
}
.pick__opt:active { transform: scale(.99); }
.pick__opt[data-on="true"] { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); }
.pick__opt[data-hit="true"] { border-color: var(--accent); background: var(--accent); color: var(--accent-ink); }
.pick__opt[data-miss="true"] { border-color: rgba(255, 51, 85, .38); color: #FF7A8C; }
.pick__pct { font-variant-numeric: tabular-nums; color: var(--text-2); font-size: var(--fs-sm); }
/* лицо кандидата нужно в момент выбора, а не только в ленте: без фото
   голосовать приходится по подписи */
.pick__img {
  position: relative;
  flex: 0 0 auto;
  display: block;
  width: 40px;
  height: 40px;
  border-radius: var(--r-xs);
  overflow: hidden;
  background: var(--card-2);
}
.pick__img img { width: 100%; height: 100%; object-fit: cover; }
.pick__img .pollcard__ph { height: 40px; }
.pick__img .pollcard__ph .avatar { font-size: var(--fs-m); }

/* ──────────────────────── CHAT (§8, §28) ─────────────── */
.chathead {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-2) var(--s-3);
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: var(--glass-1);
  box-shadow: var(--rim);
}
.chathead__who { display: flex; align-items: center; gap: var(--s-2); min-width: 0; flex: 1 1 auto; }
.chathead__who > * { min-width: 0; }
.chathead__who .avatar { flex: 0 0 auto; }

/* лента растёт вместе со страницей: внутренний скролл здесь спорит
   с закреплённым композером и режет последние сообщения */
.chat {
  display: grid;
  gap: var(--s-2);
  padding: var(--s-3);
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  background: var(--grad-glass);
  backdrop-filter: var(--blur);
  -webkit-backdrop-filter: var(--blur);
  box-shadow: var(--rim), var(--sh-1);
}
.msg { display: grid; grid-template-columns: 34px minmax(0, 1fr); gap: var(--s-2); align-items: start; }
.msg__pin {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-2) var(--s-3);
  border-radius: var(--r-sm);
  border: 1px dashed var(--gold-line);
  background: var(--gold-soft);
  color: var(--gold);
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
}
.msg__b { min-width: 0; }
.msg__head { display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap; }
.msg__nick { font-size: var(--fs-sm); font-weight: var(--fw-xbold); color: #fff; background: none; border: 0; padding: 0; font-family: var(--font); cursor: pointer; }
.msg__nick:active { color: var(--accent); }
/* ачивка в ленте — маленькая золотая пилюля: читается рядом с ролью и не спорит с текстом */
.achvchip {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  height: 18px;
  padding: 0 var(--s-1) 0 3px;
  border-radius: var(--r-pill);
  border: 1px solid var(--gold-line);
  background: var(--gold-soft);
  color: var(--gold);
  font-size: 10px;
  font-weight: var(--fw-xbold);
  letter-spacing: .04em;
  text-transform: uppercase;
  white-space: nowrap;
}
.achvchip i { font-style: normal; }
.msg__text {
  margin-top: 3px;
  padding: var(--s-2) var(--s-3);
  border-radius: 4px var(--r-sm) var(--r-sm) var(--r-sm);
  background: rgba(255, 255, 255, .05);
  font-size: var(--fs-m);
  line-height: 1.45;
  word-break: break-word;
}
.msg--me .msg__text { background: var(--accent-soft); border: 1px solid var(--accent-line); }
.msg__acts { display: flex; gap: var(--s-1); margin-top: 3px; }
.react {
  min-width: 30px;
  height: 24px;
  padding: 0 var(--s-2);
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  background: rgba(255, 255, 255, .04);
  color: var(--text-2);
  font-size: 11px;
  font-weight: var(--fw-bold);
  font-family: var(--font);
  cursor: pointer;
  transition: all var(--t-fast) var(--ease);
}
.react:active { transform: scale(.94); }
.react[data-on="true"] { border-color: var(--accent-line); background: var(--accent-soft); color: var(--accent); }
/* хаб открыт в браузере: поля ввода нет, есть одна дорога в чат */
.chatgate {
  position: sticky;
  bottom: calc(var(--nav-bar) + var(--s-2));
  display: flex;
  align-items: center;
  gap: var(--s-3);
  margin-top: var(--s-4);
  padding: var(--s-3) var(--s-4);
  border-radius: var(--r-lg);
  border: 1px solid var(--accent-line);
  background: var(--accent-soft);
}
.chatgate__t { flex: 1 1 auto; display: grid; gap: 2px; min-width: 0; }
.chatgate__t b { font-size: var(--fs-s); letter-spacing: .01em; }
.chatgate .btn { flex: 0 0 auto; }

.composer {
  position: fixed;
  bottom: calc(var(--nav-bar) + var(--s-2));
  left: 0;
  right: 0;
  margin-inline: auto;
  z-index: 22;
  width: calc(var(--app-max) - var(--pad) * 2);
  max-width: calc(100% - var(--pad) * 2);
  display: grid;
  /* без явного minmax(0,1fr) трек берёт max-content текстового поля и
     вылезает за экран на 320 */
  grid-template-columns: minmax(0, 1fr);
  gap: var(--s-2);
  padding: var(--s-2);
  border-radius: var(--r-xl);
  border: 1px solid var(--line-2);
  background: rgba(23, 32, 62, .92);
  backdrop-filter: blur(18px) saturate(150%);
  -webkit-backdrop-filter: blur(18px) saturate(150%);
  box-shadow: var(--rim), var(--sh-2);
}

.tgrow { display: flex; align-items: flex-end; gap: var(--s-2); }

/* поле — пилюля, как в Telegram: эмодзи слева, скрепка справа, текст между */
.tgfield {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: flex-end;
  gap: 2px;
  padding: 2px var(--s-1);
  border-radius: var(--r-pill);
  border: 1px solid var(--line-2);
  background: rgba(7, 11, 24, .6);
  box-shadow: var(--rim);
  transition: border-color var(--t) var(--ease-out), box-shadow var(--t) var(--ease-out);
}
.tgfield:focus-within { border-color: var(--accent-line); box-shadow: var(--rim), 0 0 0 3px var(--accent-soft); }
.tgfield textarea {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 36px;
  max-height: 96px;
  padding: var(--s-2) 0;
  border: 0;
  background: none;
  color: var(--text);
  font-family: var(--font);
  font-size: var(--fs-base);
  line-height: 1.35;
  resize: none;
  outline: none;
}
.tgfield textarea::placeholder { color: var(--text-3); }
.tgfield__ic {
  flex: 0 0 auto;
  width: 36px;
  height: 36px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--text-2);
  display: grid;
  place-items: center;
  cursor: pointer;
  transition: color var(--t) var(--ease-out), transform var(--t-fast) var(--ease-spring);
}
.tgfield__ic:hover { color: var(--accent); }
.tgfield__ic:active { transform: scale(.86); }

/* круглая справа: микрофон, пока поле пустое, отправка — когда есть текст */
.tgsend {
  position: relative;
  flex: 0 0 auto;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--grad-cta);
  color: var(--accent-ink);
  box-shadow: var(--rim-2), 0 6px 18px rgba(141, 14, 210, .3);
  cursor: pointer;
  transition: transform var(--t-fast) var(--ease-spring), box-shadow var(--t) var(--ease-out);
}
.tgsend:active { transform: scale(.92); }
.tgsend__ic {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  transition: opacity var(--t) var(--ease-out), transform var(--t-slow) var(--ease-spring);
}
.tgsend__ic--send { opacity: 0; transform: scale(.6); }
.tgsend[data-mode="send"] .tgsend__ic:not(.tgsend__ic--send) { opacity: 0; transform: scale(.6); }
.tgsend[data-mode="send"] .tgsend__ic--send { opacity: 1; transform: none; }

.emojibar {
  display: none;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 2px;
  padding-bottom: var(--s-1);
  margin-bottom: var(--s-1);
  border-bottom: 1px solid var(--line);
}
.emojibar[data-open="true"] { display: grid; animation: pop var(--t-slow) var(--ease-out); }
.emojibar__b {
  min-height: 34px;
  border: 0;
  border-radius: var(--r-sm);
  background: transparent;
  font-size: 19px;
  line-height: 1;
  cursor: pointer;
  transition: transform var(--t-fast) var(--ease-spring), background var(--t) var(--ease);
}
.emojibar__b:hover { background: var(--glass-1); }
.emojibar__b:active { transform: scale(.84); }

/* композер висит над лентой: экрану нужен запас снизу, иначе последнее
   сообщение окажется под плавающей панелью */
.screen--composer { padding-bottom: calc(var(--nav-h) + var(--s-8)); }

/* ────────── ЧАТ · окно настоящего Telegram (§8) ────────── */
/* Вкладка начинается с окна чата: оно основное, поэтому экрану нужен
   размер, а не «остаток от страницы». Лентой скроллит сам iframe —
   иначе на телефоне два вложенных скролла дергают страницу. */
.screen--tg > .segbar { margin-bottom: var(--s-3); }

.tgwin {
  position: relative;
  height: calc(100dvh - 320px);
  min-height: 340px;
  overflow: hidden;
  border: 1px solid var(--line-2);
  border-radius: var(--r-lg);
  background: var(--glass-1);
  box-shadow: var(--rim), var(--sh-2);
}
.tgwin iframe { position: relative; z-index: 1; display: block; width: 100%; height: 100%; border: 0; background: transparent; }
/* виджет грузится извне: пока он пустой, под прозрачным iframe видна
   своя лента-скелетон, и окно не выглядит сломанным */
.tgwin__wait {
  position: absolute;
  inset: var(--s-4);
  z-index: 0;
  display: grid;
  align-content: start;
  gap: var(--s-3);
}
.tgwin__wait .sk { height: 14px; }

/* плавающая кнопка как в самом Telegram: ведёт в настоящий чат приложения */
.tgfloat {
  position: fixed;
  z-index: 45;
  bottom: calc(var(--nav-bar) + var(--s-2));
  right: max(var(--s-4), calc(50% - var(--app-max) / 2 + var(--s-4)));
  width: 54px;
  height: 54px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--grad-cta);
  color: var(--accent-ink);
  box-shadow: var(--rim-2), 0 14px 34px rgba(141, 14, 210, .45);
  transition: transform var(--t-fast) var(--ease);
}
.tgfloat:active { transform: scale(.92); }
/* подпись под окном уходит из-под плавающей кнопки, иначе последние слова
   читаются через неё */
.screen--tg > .tiny { padding-right: calc(54px + var(--s-4)); }

/* ─────────────────────── PROFILE (§9) ────────────────── */
.phead {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--s-4);
  align-items: center;
  padding: var(--s-5);
  border-radius: var(--r-xl);
  border: 1px solid var(--line-2);
  background:
    radial-gradient(110% 80% at 0% 0%, var(--accent-soft), transparent 55%),
    linear-gradient(180deg, var(--card-2), var(--card));
}
.phead__nick { font-family: var(--font-display); font-size: var(--fs-2xl); font-weight: var(--fw-xbold); letter-spacing: -.01em; }
/* Колонка текста шапки: ник и стаж на одном левом краю, одним шагом. Без
   сетки отступы каждой строки жили своей жизнью, и блок рядом с высоким
   аватаром расползался в лесенку. */
.phead__col { display: grid; justify-items: start; gap: var(--s-2); min-width: 0; }
/* Строка плашек — на всю ширину карточки (grid-column 1/-1): в колонке рядом
   с аватаром ей не хватало места, и третья плашка падала второй строкой.
   Шаг 4 px, а не 8: с короной и счётчиком достижений строка впритык к ширине
   375, и лишний зазор как раз ломает её на два ряда. */
.phead__row {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  gap: var(--s-1);
  flex-wrap: wrap;
}
/* Роль, корона и счётчик достижений стоят в одной строке, а компоненты у них
   разные: у `.badge` отступ 5 px и обычный трекинг, у `.statname` 3 px и
   разрядка .1em — рядом плашки кажутся то выше, то крупнее. В этой строке
   они обязаны читаться одним семейством, поэтому высота, шрифт, разрядка и
   боковой отступ общие; в других местах `.statname` остаётся собой. */
.phead__row .badge,
.phead__row .statname { min-height: 26px; padding: 0 var(--s-2); }
.phead__row .statname { font-size: var(--fs-xs); letter-spacing: .03em; }
/* кошелёк под шапкой: баланс и суммарный XP одной строкой. Шкала уровня
   уехала в плашку ранга под шапку — две полоски прогресса рядом спорили бы */
.phead__xp {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  margin-top: var(--s-4);
}
/* аватар в шапке — кнопка: тап открывает редактор (фото, цвет, рамка) */
.phead__av {
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  line-height: 0;
  border-radius: var(--r-pill);
  transition: transform var(--t-fast) var(--ease);
}
.phead__av:active { transform: scale(.94); }
.phead__av:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* ник ведущего длинный: на мобильных уменьшаем шаг шрифта, а не режем */
@media (max-width: 430px) { .phead__nick { font-size: var(--fs-xl); } }

/* на 320 ник в 24px не встаёт рядом с аватаром 84px — уводим аватара на строку выше */
@media (max-width: 359px) {
  .phead { grid-template-columns: 1fr; justify-items: center; text-align: center; padding: var(--s-4); gap: var(--s-3); }
  .phead__nick { font-size: var(--fs-xl); }
  .phead__row { justify-content: center; }
}

.achv { display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: var(--s-3); }
/* Ачивка должна считываться за кадр: взятая — это медальон в своём тоне с
   подписью «взято», закрытая — серая заглушка с замком. Разница не в
   прозрачности, а в цвете, обводке и подписи: на 320 полупрозрачные плашки
   сливались в одну стену */
.achv__cell {
  display: grid;
  justify-items: center;
  gap: var(--s-2);
  width: 100%;
  padding: var(--s-4) var(--s-2);
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: var(--card);
  text-align: center;
  transition: box-shadow var(--t) var(--ease), border-color var(--t) var(--ease);
}
/* Медаль, а не наклейка: у неё толстый насеченный обод, утопленная площадка
   со знаком, гравировка и собственный свет. Насечка (repeating-conic) поверх
   общего conic — именно они дают «катаный металл»; один conic оставался
   плоским кольцом. Закрытая — сталь, взятая — золото или аметист по тону. */
.achv__ic {
  position: relative;
  width: 62px;
  height: 62px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  padding: 4px;
  background:
    repeating-conic-gradient(from 0deg, rgba(255, 255, 255, .14) 0deg 1.5deg, rgba(0, 0, 0, .16) 1.5deg 3deg),
    conic-gradient(from 210deg, #5B5B68, #22222B 26%, #71717E 48%, #14141C 74%, #5B5B68);
  box-shadow:
    0 9px 18px rgba(2, 5, 15, .62),
    0 2px 4px rgba(2, 5, 15, .5),
    inset 0 1px 1px rgba(255, 255, 255, .34),
    inset 0 -2px 5px rgba(0, 0, 0, .55);
}
/* свет только с одной стороны: у вещи есть источник, у наклейки — нет */
.achv__ic::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: linear-gradient(163deg, rgba(255, 255, 255, .46), rgba(255, 255, 255, 0) 44%);
  pointer-events: none;
}
.achv__disc {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  display: grid;
  place-items: center;
  color: var(--text-3);
  background: radial-gradient(circle at 34% 24%, #2B2B38, #0A0D18 74%);
  box-shadow:
    inset 0 2px 6px rgba(0, 0, 0, .9),
    inset 0 -1px 2px rgba(255, 255, 255, .08);
}
/* знак гравирован в площадке: блик из-под канта сверху и тень от канта вниз
   дают утопленную черту без растровой картинки */
.achv__disc svg {
  filter: drop-shadow(0 1px 0 rgba(255, 255, 255, .2)) drop-shadow(0 -1px 1px rgba(0, 0, 0, .75));
}
.achv__name { font-size: var(--fs-xs); font-weight: var(--fw-xbold); letter-spacing: .06em; text-transform: uppercase; }
.achv__hint { font-size: 10px; color: var(--text-2); line-height: 1.3; }
.achv__state { font-size: 10px; font-weight: var(--fw-xbold); letter-spacing: .08em; text-transform: uppercase; color: var(--text-3); }
.achv__cell[data-locked="false"][data-tone="gold"] { border-color: var(--gold-line); }
.achv__cell[data-locked="false"][data-tone="gold"] .achv__ic {
  background:
    repeating-conic-gradient(from 0deg, rgba(255, 255, 255, .18) 0deg 1.5deg, rgba(60, 34, 0, .22) 1.5deg 3deg),
    conic-gradient(from 210deg, #F6DCA6, #8F6E2E 28%, #F2C979 46%, #6A4E1E 72%, #F6DCA6);
  box-shadow:
    0 9px 18px rgba(2, 5, 15, .62),
    0 0 24px rgba(242, 201, 121, .26),
    inset 0 1px 1px rgba(255, 255, 255, .5),
    inset 0 -2px 5px rgba(72, 40, 0, .55);
}
.achv__cell[data-locked="false"][data-tone="gold"] .achv__disc {
  color: var(--gold);
  background: radial-gradient(circle at 34% 24%, #3A2C14, #0C0912 74%);
}
.achv__cell[data-locked="false"][data-tone="gold"] .achv__state { color: var(--gold); }
.achv__cell[data-locked="false"][data-tone="accent"] { border-color: var(--accent-line); }
.achv__cell[data-locked="false"][data-tone="accent"] .achv__ic {
  background:
    repeating-conic-gradient(from 0deg, rgba(255, 255, 255, .18) 0deg 1.5deg, rgba(24, 0, 48, .24) 1.5deg 3deg),
    conic-gradient(from 210deg, #E4D2FF, #6A12E0 28%, #A970FF 46%, #3B0A6B 72%, #E4D2FF);
  box-shadow:
    0 9px 18px rgba(2, 5, 15, .62),
    0 0 24px rgba(169, 112, 255, .28),
    inset 0 1px 1px rgba(255, 255, 255, .5),
    inset 0 -2px 5px rgba(30, 0, 60, .55);
}
.achv__cell[data-locked="false"][data-tone="accent"] .achv__disc {
  color: #DCBFFF;
  background: radial-gradient(circle at 34% 24%, #34154F, #0F0A1C 74%);
}
.achv__cell[data-locked="false"][data-tone="accent"] .achv__state { color: var(--accent); }
/* жетон дышит только у взятой ачивки: движение = «это уже моё». У закрытых
   неподвижный замок читается как витрина, которая ещё не открылась */
.achv__cell[data-locked="false"] .achv__ic { animation: achv-breathe 3.4s var(--ease) infinite; }
@keyframes achv-breathe {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.05); }
}
.achv__cell[data-locked="true"] { opacity: .5; }
/* Вешается на аватар только престижное (`top`) — у остальных плиток атрибута
   нет, значит нет и курсора: тап вхолостую был бы мёртвым контролом */
.achv__cell[data-pin] { cursor: pointer; }
.achv__cell[data-pin]:active { transform: translateY(1px); }
.achv__cell[data-pin="on"] {
  border-color: var(--gold);
  box-shadow: 0 0 0 1px var(--gold-line), 0 0 22px rgba(242, 201, 121, .2);
}
.achv__cell[data-pin="on"] .achv__state { color: var(--gold); }
.achv__cell[data-pin="off"] .achv__state { color: var(--text-2); }

/* ──────────────────────── CLIPS (§26) ────────────────── */
.clips { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--s-3); }
.clip { position: relative; border-radius: var(--r-md); overflow: hidden; border: 1px solid var(--line); background: var(--card); cursor: pointer; }
.clip__thumb { aspect-ratio: var(--ar-16-9); position: relative; background: var(--card-3); overflow: hidden; }
.clip__thumb img { width: 100%; height: 100%; object-fit: cover; }

/* миниатюра стрима в расписании (§11) */
.sched__thumb {
  flex: 0 0 auto;
  width: 52px;
  height: 52px;
  border-radius: var(--r-sm);
  overflow: hidden;
  background: var(--card-3);
}
.sched__thumb img { width: 100%; height: 100%; object-fit: cover; }
.clip__play {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  color: #fff;
  background: rgba(8, 9, 11, .3);
}
.clip__title { padding: var(--s-2) var(--s-3) 0; font-size: var(--fs-sm); font-weight: var(--fw-bold); line-height: 1.3; }
.clip__meta { padding: 2px var(--s-3) var(--s-2); font-size: var(--fs-xs); color: var(--text-2); font-variant-numeric: tabular-nums; }
.clip__reacts { display: flex; flex-wrap: wrap; gap: var(--s-1); padding: 0 var(--s-3) var(--s-3); }

/* ─────────────────── MEME FACTORY (§27) ──────────────── */
.memegrid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s-3); }
.memegrid__cell {
  position: relative;
  aspect-ratio: var(--ar-1-1);
  border-radius: var(--r-sm);
  overflow: hidden;
  border: 2px solid var(--line);
  background: var(--card);
  cursor: pointer;
  padding: 0;
  transition: border-color var(--t-fast) var(--ease), transform var(--t-fast) var(--ease);
}
.memegrid__cell img { width: 100%; height: 100%; object-fit: cover; }
.memegrid__cell b {
  position: absolute;
  inset: auto 0 0 0;
  padding: 16px var(--s-1) var(--s-1);
  font-size: 10px;
  font-weight: var(--fw-bold);
  text-align: center;
  background: linear-gradient(180deg, transparent, rgba(8, 9, 11, .92));
}
.memegrid__cell[data-on="true"] { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent-line); transform: translateY(-2px); }
.meme__stage { border-radius: var(--r-lg); overflow: hidden; border: 1px solid var(--line-2); background: #050608; position: relative; }
.meme__stage canvas { display: block; width: 100%; height: auto; }
.loader {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: var(--fs-xs);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--text-2);
  background: rgba(5, 6, 8, .72);
}
.loader.hidden { display: none; }

/* ─────────────────────── REWARDS (§49) ───────────────── */
.float {
  position: fixed;
  z-index: 75;
  pointer-events: none;
  font-weight: var(--fw-xbold);
  font-size: var(--fs-l);
  color: var(--gold);
  font-variant-numeric: tabular-nums;
  text-shadow: 0 2px 12px rgba(0, 0, 0, .7);
  animation: floatup 900ms var(--ease-out) forwards;
}
@keyframes floatup {
  0% { opacity: 0; transform: translateY(6px) scale(.9); }
  25% { opacity: 1; }
  100% { opacity: 0; transform: translateY(-46px) scale(1.05); }
}

/* монета летит от карточки к пилюле баланса: награда кончается там, где её
   видно и тратят, а не подписью в воздухе. Путь считает JS (WAAPI), здесь
   только тело монеты */
.flycoin {
  position: fixed;
  z-index: 76;
  width: 18px;
  height: 18px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  font-size: 10px;
  font-weight: var(--fw-xbold);
  line-height: 1;
  color: #3A2A0C;
  background: radial-gradient(circle at 34% 28%, #F2DFAE, var(--gold) 58%, #8F6E2E);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .3), 0 0 12px rgba(242, 201, 121, .5);
  pointer-events: none;
}

.levelup {
  position: fixed;
  inset: 0;
  z-index: 85;
  display: none;
  place-items: center;
  padding: var(--pad);
  background: rgba(4, 5, 7, .82);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.levelup[data-open="true"] { display: grid; }
.levelup__card {
  width: 100%;
  max-width: 340px;
  display: grid;
  justify-items: center;
  gap: var(--s-3);
  padding: var(--s-7) var(--s-5);
  border-radius: var(--r-xl);
  border: 1px solid var(--gold-line);
  background: linear-gradient(180deg, var(--gold-soft), var(--bg-1));
  box-shadow: var(--sh-3);
  text-align: center;
  animation: pop var(--t-slow) var(--ease-out);
}
@keyframes pop { from { transform: scale(.9); opacity: 0; } }
.levelup__kicker { color: var(--accent); font-size: var(--fs-s); font-weight: var(--fw-xbold); letter-spacing: .3em; text-transform: uppercase; }
.levelup__num { font-family: var(--font-display); font-size: 62px; font-weight: var(--fw-xbold); line-height: .9; }
.confetti { position: absolute; width: 8px; height: 12px; border-radius: 2px; opacity: .9; animation: fall 1400ms var(--ease) forwards; }
@keyframes fall {
  0% { transform: translateY(-40vh) rotate(0); opacity: 1; }
  100% { transform: translateY(90vh) rotate(540deg); opacity: 0; }
}

/* ─────────────────────── ADMIN (§31) ─────────────────── */
.admin { display: grid; gap: var(--s-2); }
.admintile {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-4);
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: var(--card);
  text-align: left;
  cursor: pointer;
  color: inherit;
  font-family: var(--font);
  width: 100%;
}
.admintile__ic { width: 34px; height: 34px; border-radius: var(--r-sm); display: grid; place-items: center; background: var(--accent-soft); border: 1px solid var(--accent-line); color: var(--accent); }
.kv { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-3); padding: var(--s-2) 0; border-bottom: 1px solid var(--line); font-size: var(--fs-sm); }
.kv:last-child { border-bottom: 0; }
.kv b { font-variant-numeric: tabular-nums; }

/* ────────────────────── NOTIFICATIONS (§30) ──────────── */
.notif {
  display: grid;
  grid-template-columns: 34px 1fr auto;
  gap: var(--s-3);
  align-items: start;
  padding: var(--s-3);
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: var(--card);
  width: 100%;
  text-align: left;
  font-family: var(--font);
  color: inherit;
  cursor: pointer;
}
.notif__ic { width: 34px; height: 34px; border-radius: var(--r-sm); display: grid; place-items: center; background: rgba(255, 255, 255, .05); border: 1px solid var(--line); }
.notif__t { font-size: var(--fs-m); font-weight: var(--fw-bold); line-height: 1.3; }
.notif__b { font-size: var(--fs-xs); color: var(--text-2); margin-top: 2px; line-height: 1.4; }
.notif__time { font-size: 10px; color: var(--text-3); white-space: nowrap; font-variant-numeric: tabular-nums; }
.notif[data-unread="true"] { border-color: var(--accent-line); }
.notif[data-unread="true"] .notif__ic { background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent); }

/* ────────────────── REFERRAL (§14) ───────────────────── */
.reflink {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-3);
  border-radius: var(--r-sm);
  border: 1px dashed var(--line-3);
  background: rgba(7, 11, 24, .6);
  font-size: var(--fs-sm);
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  color: var(--text-2);
  word-break: break-all;
}
.reflink__url { flex: 1 1 auto; min-width: 0; }

/* ────────────────────── HALL OF FAME ─────────────────── */
.podium { display: grid; grid-template-columns: 1fr 1.15fr 1fr; gap: var(--s-2); align-items: end; }
.podium__col { display: grid; justify-items: center; gap: var(--s-2); padding: var(--s-3) var(--s-2); border-radius: var(--r-md); border: 1px solid var(--line); background: var(--card); text-align: center; }
.podium__col[data-rank="1"] { border-color: var(--gold-line); background: linear-gradient(180deg, var(--gold-soft), var(--card)); }
.podium__col[data-rank="2"] { border-color: var(--line-2); }
.podium__medal { font-family: var(--font-display); font-size: var(--fs-xl); font-weight: var(--fw-xbold); color: var(--gold); }
/* ник чемпиона важнее экономии строки: вместо «@GOLDE…» в столбик
   разбиваем его на две строки */
.podium__col > .truncate {
  width: 100%;
  white-space: normal;
  overflow-wrap: anywhere;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  line-height: 1.15;
}
@media (max-width: 359px) {
  .podium { grid-template-columns: 1fr 1.1fr 1fr; gap: var(--s-1); }
  .podium__col { padding: var(--s-2) 2px; gap: var(--s-1); }
  .podium__col > .num { font-size: var(--fs-sm); }
  /* на 320 px столбец уже, чем ник: без шага вниз по кеглю «@GOLDEN_T»
     разрывался посреди слова («@GOLDEN _T»), и ник читался как опечатка */
  .podium__col > .truncate { font-size: var(--fs-sm); }
}

/* экраны-обёртки */
.pane { display: none; }
.pane[data-open="true"] { display: block; }
.backlink {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  min-height: var(--touch);
  padding: 0 var(--s-2) 0 0;
  margin-bottom: var(--s-2);
  border: 0;
  background: none;
  color: var(--text-2);
  font-family: var(--font);
  font-size: var(--fs-sm);
  font-weight: var(--fw-bold);
  cursor: pointer;
}
.backlink:active { color: var(--accent); }

.disclaimer {
  margin-top: var(--s-6);
  padding: var(--s-4);
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: rgba(255, 255, 255, .02);
  font-size: var(--fs-s);
  line-height: var(--lh-loose);
  color: var(--text-3);
  text-align: center;
}

/* ─────────────── DESKTOP / TEST ОБОЛОЧКА (§59) ──────────
   На широком экране приложение — это 430px «устройство» по центру:
   высота фиксирована, скроллится только .content, а навигация и
   композер лепятся внутри оболочки, а не к окну браузера. */
@media (min-width: 521px) {
  html, body { height: 100%; overflow: hidden; }
  .app { height: min(844px, calc(100vh - 48px)); overflow: hidden; }
  .content { overflow-y: auto; -webkit-overflow-scrolling: touch; }
  .bottomnav {
    position: absolute;
    left: var(--nav-gap);
    right: var(--nav-gap);
    width: auto;
    max-width: none;
    transform: none;
  }
  .composer {
    position: absolute;
    left: var(--pad);
    right: var(--pad);
    bottom: calc(var(--nav-bar) + var(--s-2));
    width: auto;
    max-width: none;
    transform: none;
  }
}
