/*
 * Вид слоя эффектов боя. Логику держит public/vfx/arena-vfx.js, здесь — только
 * материал: бумага, чернила, маркер, приёмы самого сайта и КОЛПАЧКИ КЛАВИШ.
 *
 * Ни один узел этого файла не участвует в раскладке страницы и не принимает
 * нажатия: корень — position: fixed с overflow: hidden, поэтому и на телефоне
 * ничего не выпирает вбок и не даёт прокрутки.
 *
 * Краски берём у игры (public/dtf-theme.css): белые панели, синий #0b5dd7,
 * чёрный текст. Красный — ТОЛЬКО на урон, зелёный — только на лечение.
 * Ничего кислотного и ничего «магического»: спор в комментариях, а не фэнтези.
 *
 * Движение живёт в JS (Web Animations API) и трогает только transform, opacity
 * и filter. Здесь нет ни одного @keyframes: слой ничего не крутит сам по себе,
 * и, когда бой кончился, на экране не остаётся ни узла.
 *
 * ПОРЯДОК СЛОЁВ (z-index внутри сцены) — это порядок важности:
 *   8 штамп конца боя → 6 ЧИСЛО УРОНА → 5 плашки со словами → 3 клавиши →
 *   2 полосы, частицы и чернила → 1 вспышка и замирание кадра →
 *   0 иероглиф (он позади всего: это фон удара, а не надпись поверх боя).
 * Число лежит выше клавиш и частиц НАРОЧНО: зрелище не имеет права закрыть
 * то единственное, ради чего человек смотрит на удар.
 */

/* ── Корень слоя ──────────────────────────────────────────────────────────── */

.avfx {
  position: fixed;
  inset: 0;
  z-index: 40;
  pointer-events: none;
  overflow: hidden;
  contain: strict;
  opacity: 0;
  transition: opacity .18s linear;
  /* Тяжёлый гротеск — тот же голос, что у логотипа и заголовков игры. */
  --avfx-face: Roboto, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Arial, sans-serif;
  --avfx-ink: #111111;
  --avfx-paper: #ffffff;
  --avfx-blue: #0b5dd7;
  --avfx-red: #e5484d;
  --avfx-green: #2f9e44;
  --avfx-grey: #9a9a9a;
}

.avfx.is-active { opacity: 1; }

/*
 * Сцена — то, что дрожит на сильных ударах (cameraShake двигает именно её).
 * Собственного вида у неё нет: она только держит координаты и общий сдвиг.
 */
.avfx__stage {
  position: absolute;
  inset: 0;
}

.avfx__stage > * { position: fixed; left: 0; top: 0; }

/*
 * Потемнения по краям и «горящих» углов тут нет: владелец убрал их 11.08.2026
 * («в эффектах убери когда экран с 4-х углов темнеет»). Затемнение лезло поверх
 * всей страницы, а не только поверх боя, и спорило со светлой темой игры.
 * Тяжесть положения нагнетаем иначе — частицами, скоростью и весом (в JS это
 * scene.pressure), а видно её там, где ей и место: в полосах Жизни.
 */

/* ── Полоса маркера: сам удар ─────────────────────────────────────────────── */

/*
 * Выделение мышью, а не снаряд: широкая полоса поперёк цели.
 *
 * Краска намеренно ПОЛУПРОЗРАЧНАЯ и с растяжкой к концам: так полоса читается
 * маркером, а не заплаткой, и портрет под ней остаётся виден. Смешения красок
 * (mix-blend-mode) здесь нет и быть не может: корень слоя — свой контекст
 * наложения (position: fixed + z-index + contain), и multiply в нём всё равно
 * не дотянулся бы до страницы. Незачем платить за то, чего не видно.
 */
.avfx-mark {
  z-index: 2;
  border-radius: 3px 9px 5px 7px;
  will-change: transform, opacity;
}

/* Чернильный край на том конце, куда полосу дотянули. */
.avfx-mark::after {
  content: '';
  position: absolute;
  top: -2px;
  bottom: -2px;
  width: 4px;
  border-radius: 2px;
  background: var(--avfx-ink);
  opacity: .5;
}

.avfx-mark[data-dir='fwd']::after { right: -2px; }
.avfx-mark[data-dir='back']::after { left: -2px; }

.avfx-mark--hit {
  background: linear-gradient(90deg,
    rgba(229, 72, 77, .1), rgba(229, 72, 77, .58) 18%,
    rgba(229, 72, 77, .46) 76%, rgba(229, 72, 77, .08));
}

.avfx-mark--block {
  background: linear-gradient(90deg,
    rgba(120, 120, 120, .1), rgba(120, 120, 120, .46) 18%,
    rgba(120, 120, 120, .36) 76%, rgba(120, 120, 120, .08));
}

.avfx-mark--heal {
  background: linear-gradient(90deg,
    rgba(47, 158, 68, .1), rgba(47, 158, 68, .5) 18%,
    rgba(47, 158, 68, .4) 76%, rgba(47, 158, 68, .08));
}

.avfx-mark--move {
  background: linear-gradient(90deg,
    rgba(11, 93, 215, .1), rgba(11, 93, 215, .46) 18%,
    rgba(11, 93, 215, .36) 76%, rgba(11, 93, 215, .08));
}

/* ── Объёмная клавиша ─────────────────────────────────────────────────────── */

/*
 * НАСТОЯЩИЙ КОЛПАЧОК, А НЕ КАРТИНКА КОЛПАЧКА.
 *
 * Колпачок ЧЁРНЫЙ, надпись БЕЛАЯ — как на клавиатуре, с которой владелец прислал
 * образцы (11.08.2026). У него видна ТОЛЩИНА: боковые стенки, скос от площадки к
 * основанию, низ темнее верха. Углы скруглены мягко, поверхность матовая с одним
 * лёгким верхним бликом — не глянец и не плоский прямоугольник. Надпись
 * некрупная и стоит ближе к верхнему краю площадки, как на настоящих.
 *
 * Геометрия честная: верхняя площадка вынесена на +kd/2, низ — на −kd/2, между
 * ними четыре боковые стенки. Стенки нарисованы псевдоэлементами площадки
 * (левая и правая) и низа (верхняя и нижняя), поэтому весь колпачок стоит
 * четыре узла, а не восемь: ::before и ::after внутри preserve-3d — такие же
 * полноправные грани, как отдельные div, но своих узлов в бюджет не берут.
 *
 * Три слоя и зачем их три:
 *   .avfx-key       — место на экране, прозрачность, размытие, ТЕНЬ И perspective.
 *                     Прозрачность и размытие «сплющивают» 3D-контекст того
 *                     элемента, на котором стоят, — но сплющивать перспективную
 *                     коробку как раз и надо: тело внутри неё остаётся объёмным.
 *                     Повесь мы filter на тело — объём исчез бы совсем;
 *   .avfx-key__body — глубина и кувырок по трём осям, transform-style: preserve-3d;
 *   площадки и низы — сами грани.
 *
 * Точка схода у каждой клавиши своя (--kox/--koy считает JS от середины окна):
 * колпачок справа показывает левый бок, слева — правый, как показала бы
 * настоящая клавиша на настоящем столе.
 */

/*
 * ТЕНЬ НА СТРАНИЦУ — ЭТО НЕ УКРАШЕНИЕ, А ТО, ЧЕМ ЧИТАЕТСЯ ГЛУБИНА.
 *
 * Чёрный колпачок на светлом интерфейсе игры очень заметен, и без тени он
 * рискует прочитаться ЭЛЕМЕНТОМ ИНТЕРФЕЙСА — тёмной плашкой, вставшей поверх
 * панели. Тень со смещением говорит обратное: предмет НАД экраном.
 *
 * Тень взята drop-shadow'ом, а не отдельным пятном: она честно повторяет
 * перспективную проекцию колпачка и растёт вместе с ним, когда тот подлетает к
 * глазу. Больше смещения, меньше размытия — прежнее мутное серое облако под
 * клавишей читалось грязью, а не тенью. Те же числа продублированы в JS
 * (KEY_SHADOW): у размытых клавиш встроенный filter перекрывает это правило.
 */
.avfx-key {
  z-index: 3;
  width: var(--kw, 44px);
  height: var(--kh, 44px);
  perspective: var(--kp, 700px);
  perspective-origin: calc(50% + var(--kox, 0px)) calc(50% + var(--koy, 0px));
  filter: drop-shadow(10px 13px 3px rgba(17, 17, 17, .44));
  will-change: transform, opacity;
}

.avfx-key.is-camera { filter: drop-shadow(18px 22px 5px rgba(17, 17, 17, .48)); }

.avfx-key__body {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  will-change: transform;
}

/*
 * Верхняя площадка. Блик один и только сверху (матовая пластмасса, а не глянец),
 * по нижней кромке — тень: видно, что площадка утоплена в колпачок. Надпись
 * прижата к верху отступом, а не выключена по центру.
 */
.avfx-key__cap {
  position: absolute;
  left: 50%;
  top: 50%;
  width: var(--kw, 44px);
  height: var(--kh, 44px);
  margin: calc(var(--kh, 44px) / -2) 0 0 calc(var(--kw, 44px) / -2);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding-top: 13%;
  border-radius: 17%/19%;
  transform-style: preserve-3d;
  transform: translateZ(calc(var(--kd, 13px) / 2));
  font-family: var(--avfx-face);
  font-size: var(--kf, 20px);
  font-weight: 700;
  line-height: 1;
  letter-spacing: .01em;
  color: #f2f2ef;
  background:
    radial-gradient(150% 88% at 50% -14%, rgba(255, 255, 255, .28), rgba(255, 255, 255, 0) 56%),
    linear-gradient(180deg, #3d3d41, #26262a 54%, #151517);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .3),
    inset 0 -3px 0 rgba(0, 0, 0, .5),
    inset 0 0 0 1px rgba(0, 0, 0, .62);
}

/* Боковые стенки: левая и правая. Обе уходят от площадки вглубь, на −kd. */
.avfx-key__cap::before,
.avfx-key__cap::after {
  content: '';
  position: absolute;
  top: 0;
  width: var(--kd, 13px);
  height: 100%;
  border-radius: 2px;
}

/* Левая: якорь на левом ребре, поворот на +90° уводит её в глубину. */
.avfx-key__cap::before {
  left: 0;
  transform-origin: 0 50%;
  transform: rotateY(90deg);
  background: linear-gradient(180deg, #37373b, #232327 62%, #131316);
}

/* Правая: якорь на правом ребре, поворот на −90°. Темнее левой: свет сверху‑слева. */
.avfx-key__cap::after {
  right: 0;
  transform-origin: 100% 50%;
  transform: rotateY(-90deg);
  background: linear-gradient(180deg, #2c2c30, #1b1b1e 62%, #0e0e10);
}

/* Низ колпачка — самая тёмная плита: клавишу видно и снизу, дырок в объёме нет. */
.avfx-key__base {
  position: absolute;
  left: 50%;
  top: 50%;
  width: var(--kw, 44px);
  height: var(--kh, 44px);
  margin: calc(var(--kh, 44px) / -2) 0 0 calc(var(--kw, 44px) / -2);
  border-radius: 15%/17%;
  transform-style: preserve-3d;
  transform: translateZ(calc(var(--kd, 13px) / -2));
  background: linear-gradient(180deg, #101012, #060607);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .8);
}

/* Верхняя и нижняя стенки — псевдоэлементы низа, поднимаются к площадке. */
.avfx-key__base::before,
.avfx-key__base::after {
  content: '';
  position: absolute;
  left: 0;
  width: 100%;
  height: var(--kd, 13px);
  border-radius: 2px;
}

/* Верхняя стенка ловит свет, нижняя — самая тёмная грань колпачка. */
.avfx-key__base::before {
  top: 0;
  transform-origin: 50% 0;
  transform: rotateX(90deg);
  background: linear-gradient(90deg, #313135, #3d3d42 40%, #26262a);
}

.avfx-key__base::after {
  bottom: 0;
  transform-origin: 50% 100%;
  transform: rotateX(-90deg);
  background: linear-gradient(90deg, #0c0c0e, #151517 40%, #08080a);
}

/*
 * Г-ОБРАЗНЫЙ ENTER — тот, что летит в лицо на метком.
 *
 * Собран из двух площадок и двух низов: ВЕРХНЯЯ ПЛАНКА во всю ширину и НИЖНИЙ
 * БЛОК поуже, прижатый вправо. Никакого clip-path: он «сплющил» бы 3D-контекст,
 * и вместе с ним пропали бы боковые стенки, то есть вся толщина.
 *
 * Нижний блок стоит на волосок ближе к зрителю (+.6px): без этого две площадки
 * в месте стыка оказались бы ровно на одной глубине и замерцали бы.
 */
.avfx-key.is-iso .avfx-key__cap,
.avfx-key.is-iso .avfx-key__base {
  left: 0;
  top: 0;
  margin: 0;
  width: var(--kw, 44px);
  height: calc(var(--kh, 44px) * .48);
}

.avfx-key.is-iso .avfx-key__cap { padding-top: 15%; }

.avfx-key.is-iso .avfx-key__cap--low,
.avfx-key.is-iso .avfx-key__base--low {
  left: auto;
  right: 0;
  top: auto;
  bottom: 0;
  width: calc(var(--kw, 44px) * .66);
  height: calc(var(--kh, 44px) * .53);
}

.avfx-key.is-iso .avfx-key__cap--low {
  transform: translateZ(calc(var(--kd, 13px) / 2 + .6px));
}

.avfx-key.is-iso .avfx-key__base--low {
  transform: translateZ(calc(var(--kd, 13px) / -2 - .6px));
}

/*
 * Пробел без подписи — как на настоящей клавиатуре. Отдельного правила ему не
 * нужно: пустой текст и есть весь его вид.
 */

/* Клавиши быстрого набора: чуть теплее — это свои, а не прилетевшие. */
.avfx-key.is-type .avfx-key__cap {
  background:
    radial-gradient(150% 88% at 50% -14%, rgba(255, 255, 255, .26), rgba(255, 255, 255, 0) 56%),
    linear-gradient(180deg, #423f39, #2b2925 54%, #171613);
}

/*
 * СЛУЖЕБНЫЕ КОЛПАЧКИ — Esc и Ctrl на блоке, связка на приёме. На настоящих
 * клавиатурах модификаторы часто отлиты чуть светлее буквенных, и здесь то же:
 * тот же чёрный, только на полтона выше. Вместе с шириной это и говорит, что в
 * кадре Ctrl, а не буква, — цветом ничего не подкрашиваем.
 */
.avfx-key.is-hard .avfx-key__cap,
.avfx-key.is-press .avfx-key__cap {
  background:
    radial-gradient(150% 88% at 50% -14%, rgba(255, 255, 255, .3), rgba(255, 255, 255, 0) 56%),
    linear-gradient(180deg, #4a4a4f, #313136 54%, #1d1d20);
}

/* ── Знак удара: число ────────────────────────────────────────────────────── */

/*
 * ЧИСЛО — ГЛАВНЫЙ ГЕРОЙ СЦЕНЫ, и набрано оно как ЗНАК УДАРА, а не как подпись.
 *
 * Прежде здесь была таблетка: сплошная заливка и скругление 999px. Такую рисует
 * любой шаблон, и от кнопки интерфейса она ничем не отличалась (владелец,
 * 12.08.2026: «выглядит слишком просто и дёшево»). Разница между подписью и
 * знаком — в трёх вещах, и все три собраны здесь:
 *
 *   1. ГЛАВНОЕ — НАБОР. Тяжёлый гротеск (тот же голос, что у логотипа и
 *      заголовков игры), плотный трекинг, лёгкий наклон. Кегль считает JS по
 *      весу удара (pillSize): на тычке знак почти втрое мельче, чем на метком,
 *      и величина урона читается ещё до того, как прочитано само число.
 *      Наклон двойной — курсивный сдвиг и поворот всей вещи (его задаёт JS):
 *      один только сдвиг читался бы шрифтовым курсивом, а знак должен выглядеть
 *      ПРИЛОЖЕННЫМ к бою, а не набранным в строке.
 *   2. ВЕС — СМЕЩЁННЫЙ ОТПЕЧАТОК, а не мягкая тень. Краска прошла мимо дважды:
 *      бумагой вверх-влево и чернилами вниз-вправо. РАЗМЫТИЯ НЕТ НИ В ОДНОМ
 *      отпечатке, только сдвиг. На метком к ним добавляется третий, красный, и
 *      разъезжаются они сильнее.
 *   3. ПОДЛОЖКА ЛЕЖИТ ПОД ЧИСЛОМ, А НЕ ВОКРУГ НЕГО. Это ::before и ::after с
 *      z-index: -1 (своих узлов псевдоэлементы не стоят, и бюджету слоя знак
 *      по-прежнему обходится в один узел). Подложка КОРОЧЕ числа по высоте,
 *      сдвинута и повёрнута отдельно от него: цифры выходят за её край сверху,
 *      как выходят за след маркера. Прямоугольника нет нигде — край рваный
 *      (clip-path), концы бледнеют, поверх идут полосы от маркерного пера.
 *
 * ЧЕТЫРЕ ИСХОДА — ЧЕТЫРЕ РАЗНЫХ ЗНАКА, и различаются они СИЛУЭТОМ, а не только
 * краской: у урона и лечения след маркера, и повёрнуты они в разные стороны;
 * у блока — надорванный клочок бумаги; у промаха — тот же клочок бледнее и число
 * перечёркнуто. Их видно с одного взгляда, не читая.
 *
 * КОНТРАСТ (WCAG 2.1, замерено 12.08.2026): чернильное число на красном мазке
 * 4.82:1, на зелёном 5.48:1, на клочке блока 11.55:1, на клочке промаха 9.02:1
 * — всё выше 4.5:1. Подложки к белой панели боя: красная 3.91:1, зелёная 3.45:1,
 * у бумажных клочков за контраст отвечает чернильный край (5.33:1) — всё выше
 * 3:1. Поэтому сердцевина мазка НЕПРОЗРАЧНА: полупрозрачная краска поверх
 * тёмного портрета роняла контраст числа до 3.7:1, то есть ниже нормы.
 */

/*
 * Рваные края. Один контур на след маркера, другой на клочок бумаги: у маркера
 * дрожит вся длинная кромка и косо срезаны концы, у бумаги надрыв крупнее и
 * реже — так рвётся лист, а не так ведёт перо.
 */
.avfx {
  --num-edge-mark: polygon(
    0.6% 30%, 4% 9%, 11% 19%, 20% 6%, 31% 16%, 43% 5%, 55% 14%, 67% 4%, 78% 15%, 89% 7%, 98.6% 17%,
    99.4% 74%, 95% 93%, 85% 82%, 74% 96%, 62% 85%, 50% 97%, 38% 86%, 27% 96%, 16% 84%, 6% 95%, 1.2% 78%
  );
  --num-edge-torn: polygon(
    1% 12%, 10% 2%, 24% 10%, 39% 3%, 55% 11%, 70% 2%, 84% 9%, 95% 3%, 99% 18%,
    96% 80%, 99% 93%, 87% 87%, 73% 97%, 57% 88%, 42% 98%, 28% 89%, 14% 97%, 3% 86%
  );
}

.avfx-num {
  z-index: 6;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 .05em;
  font-family: var(--avfx-face);
  font-weight: 900;
  line-height: .94;
  /* Тесный трекинг: знак должен стоять плотным блоком, а не строкой цифр. */
  letter-spacing: -.055em;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  color: var(--avfx-ink);
  text-shadow: var(--num-print);
  /* Свой контекст наложения: подложка ушла под число и наружу не вылезла. */
  isolation: isolate;
  will-change: transform, opacity;
  --num-print: .055em .065em 0 rgba(17, 17, 17, .34);
  --num-turn: -2deg;
  --num-turn2: 1.4deg;
}

/*
 * Подложка. ДВА СЛОЯ, и оба под числом: первый — основной след, второй — второй
 * прогон пера (у маркера) или чернильный край надрыва (у бумаги). Именно второй
 * слой и не даёт подложке прочитаться ровной плашкой.
 */
.avfx-num::before,
.avfx-num::after {
  content: '';
  position: absolute;
  z-index: -1;
  pointer-events: none;
}

/* Основной след: короче числа сверху, длиннее по бокам, повёрнут отдельно. */
.avfx-num::before {
  left: -.3em;
  right: -.24em;
  top: .3em;
  bottom: -.04em;
  transform: rotate(var(--num-turn));
  background: var(--num-lay);
  clip-path: var(--num-edge, var(--num-edge-mark));
}

/* Второй прогон: тоньше, ниже и в другую сторону — как повели пером дважды. */
.avfx-num::after {
  left: -.12em;
  right: -.38em;
  top: .66em;
  bottom: -.14em;
  transform: rotate(var(--num-turn2));
  background: var(--num-lay2);
  clip-path: var(--num-edge2, var(--num-edge-mark));
}

/*
 * УРОН — след красного маркера. Полосы от пера идут поперёк хода руки, концы
 * бледнеют: перо там уже оторвалось от бумаги.
 *
 * ОТПЕЧАТОК ДВУЦВЕТНЫЙ, и это не украшение. Красный отпечаток на красном мазке
 * не виден вовсе — знак остался бы плоским ровно там, где на него и смотрят.
 * Поэтому краска ложится мимо ДВАЖДЫ: вверх-влево бумагой, вниз-вправо
 * чернилами. Получается сдвиг оттиска, который читается и на мазке, и на белой
 * панели, куда цифра выходит верхушкой.
 */
.avfx-num.is-hurt {
  --num-lay:
    repeating-linear-gradient(97deg, rgba(255, 255, 255, .14) 0 2px, rgba(255, 255, 255, 0) 2px 8px),
    linear-gradient(93deg, rgba(229, 72, 77, .42) 0%, #e5484d 9%, #e5484d 88%, rgba(229, 72, 77, .3) 100%);
  --num-lay2: linear-gradient(93deg, rgba(229, 72, 77, 0) 0%, rgba(229, 72, 77, .52) 30%, rgba(229, 72, 77, .16) 100%);
  --num-print: -.035em -.04em 0 rgba(255, 255, 255, .92), .065em .08em 0 rgba(17, 17, 17, .62);
  --num-turn: -2.4deg;
  --num-turn2: 2.6deg;
}

/*
 * ЛЕЧЕНИЕ — тот же маркер, но развёрнутый в другую сторону: силуэт знака должен
 * отличаться от урона ещё до того, как разглядели краску и знак «+».
 */
.avfx-num.is-heal {
  --num-lay:
    repeating-linear-gradient(83deg, rgba(255, 255, 255, .14) 0 2px, rgba(255, 255, 255, 0) 2px 8px),
    linear-gradient(87deg, rgba(47, 158, 68, .3) 0%, #2f9e44 12%, #2f9e44 91%, rgba(47, 158, 68, .42) 100%);
  --num-lay2: linear-gradient(87deg, rgba(47, 158, 68, .16) 0%, rgba(47, 158, 68, .52) 70%, rgba(47, 158, 68, 0) 100%);
  /* Оттиск разъезжается в другую сторону: у лечения даже сдвиг зеркальный. */
  --num-print: .04em -.04em 0 rgba(255, 255, 255, .92), -.06em .08em 0 rgba(17, 17, 17, .62);
  --num-turn: 2.2deg;
  --num-turn2: -2.4deg;
}

/*
 * БЛОК — надорванный клочок бумаги, а не мазок: удар был, краски не осталось.
 * Нижний слой чернильный и вылезает вниз-вправо — это край надрыва, он же и
 * держит контраст подложки к странице (у самой бумаги его быть не может).
 */
.avfx-num.is-zero {
  color: #222222;
  --num-edge: var(--num-edge-torn);
  --num-edge2: var(--num-edge-torn);
  --num-lay: rgba(17, 17, 17, .62);
  --num-lay2: linear-gradient(180deg, #e6e5df, #dcdcd6 62%, #cfcec6);
  --num-print: .045em .055em 0 rgba(255, 255, 255, .8);
  --num-turn: -1.4deg;
  --num-turn2: -1.4deg;
}

/* Клочок блока: бумага лежит поверх чернильного края и чуть сдвинута с него. */
.avfx-num.is-zero::before { left: -.26em; right: -.2em; top: .3em; bottom: -.1em; }
.avfx-num.is-zero::after { left: -.3em; right: -.24em; top: .26em; bottom: -.04em; }

/*
 * ПРОМАХ — тот же клочок, но выцветший, и число перечёркнуто: удар был, да не
 * дошёл. Черта идёт ПОВЕРХ цифры (это text-decoration, а не подложка) — иначе
 * «зачёркнуто» пришлось бы вычитывать.
 */
.avfx-num.is-miss {
  color: #3d3d3d;
  --num-edge: var(--num-edge-torn);
  --num-edge2: var(--num-edge-torn);
  --num-lay: rgba(17, 17, 17, .34);
  --num-lay2: linear-gradient(180deg, #f4f3ee, #eceae2 62%, #e2e0d6);
  --num-print: .04em .05em 0 rgba(255, 255, 255, .85);
  --num-turn: 2.6deg;
  --num-turn2: 2.6deg;
  text-decoration: line-through;
  text-decoration-thickness: .12em;
  text-decoration-color: #5f5f5f;
  text-decoration-skip-ink: none;
}

.avfx-num.is-miss::before { left: -.24em; right: -.18em; top: .32em; bottom: -.08em; }
.avfx-num.is-miss::after { left: -.28em; right: -.22em; top: .28em; bottom: -.02em; }

/*
 * МЕТКИЙ — тот же знак, но пропечатан дважды и жирнее: чернильный оттиск и за
 * ним красный, оба со сдвигом и оба без размытия. Кегль ему поднимает JS.
 */
.avfx-num.is-crit {
  --num-print:
    -.045em -.05em 0 rgba(255, 255, 255, .95),
    .075em .09em 0 var(--avfx-ink),
    .14em .17em 0 rgba(229, 72, 77, .85);
  --num-turn: -3.6deg;
  --num-turn2: 3.4deg;
}

/* На метком след шире и грубее: маркер вели с нажимом. */
.avfx-num.is-crit::before { left: -.36em; right: -.28em; top: .26em; bottom: -.08em; }

/* ── Частицы: материал этого мира ─────────────────────────────────────────── */

/*
 * Не «снежок из точек», а то, из чего сделан спор: бумажная крошка, чернильные
 * брызги, обрывки набранного текста и те самые плюсы с минусами.
 *
 * Три плана — три расстояния до глаза. Близкий крупнее, быстрее и слегка не в
 * фокусе; дальний мельче, медленнее и бледнее. Разная скорость планов (её
 * задаёт JS) и есть глубина: одинаково летящая крошка выглядит наклейкой.
 */
.avfx-bit {
  z-index: 2;
  font-family: var(--avfx-face);
  font-weight: 800;
  line-height: 1;
}

/* Бумажная крошка: обрывок листа со сгибом. */
.avfx-bit--paper {
  background: linear-gradient(135deg, #ffffff 46%, #e8e6df 47%, #f6f5f0);
  box-shadow: 0 0 0 1px rgba(17, 17, 17, .22);
  border-radius: 1px 3px 1px 2px;
}

/* Чернильная брызга: неправильная капля, как настоящая. */
.avfx-bit--ink {
  background: rgba(17, 17, 17, .82);
  border-radius: 58% 42% 47% 53% / 46% 58% 42% 54%;
}

/* Обрывок набранного текста: слово, вылетевшее из спора. */
.avfx-bit--text {
  color: rgba(17, 17, 17, .72);
  white-space: nowrap;
  font-weight: 700;
}

/* Плюс и минус — те самые, что ставят под комментариями. */
.avfx-bit--plus { color: var(--avfx-green); }
.avfx-bit--minus { color: var(--avfx-red); }

/* Планы. Близкий чуть не в фокусе — только он и платит за размытие. */
.avfx-bit.is-near { filter: blur(1.1px); opacity: .95; }
.avfx-bit.is-mid { opacity: .9; }
.avfx-bit.is-far { opacity: .5; }

/* ── Чернила: клякса и капли ──────────────────────────────────────────────── */

.avfx-blot {
  z-index: 2;
  border-radius: 47% 53% 61% 39% / 55% 42% 58% 45%;
  background:
    radial-gradient(58% 58% at 40% 38%, rgba(17, 17, 17, .96), rgba(17, 17, 17, .82) 62%, rgba(17, 17, 17, 0) 100%);
  will-change: transform, opacity;
}

.avfx-drop {
  z-index: 2;
  border-radius: 58% 42% 47% 53% / 46% 58% 42% 54%;
  background: rgba(17, 17, 17, .9);
  will-change: transform, opacity;
}

/* ── Блок: плашка комментария ─────────────────────────────────────────────── */

/*
 * Стена — это чужой комментарий, вставший поперёк. Плашка с рамкой и одной
 * «строкой» внутри: узнаётся мгновенно и не спорит с портретом.
 *
 * ПОЛУПРОЗРАЧНАЯ И РОСТОМ С ЗОНУ УДАРА. Прежняя — глухо-белая, в 56 px и с
 * двумя серыми полосками — закрывала имя соперника и его полосу Жизни и
 * читалась серым скелетом загрузки, будто интерфейс не догрузился. Высоту
 * задаёт JS (--plate-h, ровно высота полосы маркера), а сквозь плашку теперь
 * видно, что за ней: стена есть, а бой за ней не пропал.
 */
.avfx-plate {
  z-index: 3;
  border-radius: 8px;
  background: rgba(255, 255, 255, .58);
  border: 2px solid rgba(17, 17, 17, .78);
  box-shadow: 3px 3px 0 rgba(17, 17, 17, .16);
  will-change: transform, opacity;
}

/* Одна строка текста внутри плашки — намёк, а не надпись. */
.avfx-plate::before {
  content: '';
  position: absolute;
  left: 12px;
  right: 22px;
  top: 50%;
  height: 5px;
  margin-top: -2.5px;
  border-radius: 3px;
  background: rgba(17, 17, 17, .26);
}

/* Скол, отлетевший от края плашки. */
.avfx-chip {
  z-index: 3;
  background: rgba(255, 255, 255, .96);
  border: 2px solid var(--avfx-ink);
  border-radius: 2px;
  will-change: transform, opacity;
}

/* ── Иероглиф: вспышка на большое событие ─────────────────────────────────── */

/*
 * Крупный знак ПОЗАДИ бойцов, как в драках в аниме. Значения — в JS (KANJI):
 * 撃 удар, 破 пробитый блок, 避 уворот, 守 блок, 痛 меткий, 決 добивание.
 *
 * ЛЕЖИТ НИЖЕ ВСЕГО СЛОЯ (z-index 0) и, сверх того, ВЫРЕЗАН НАД ПОРТРЕТАМИ:
 * маска гасит черты кругами вокруг обоих бойцов (координаты кладёт JS в
 * --hx/--hy/--hr), и знак читается уходящим им за спину. По-настоящему заехать
 * под карточку слой не может: он целиком лежит над страницей, а трогать чужую
 * разметку ради этого нельзя.
 *
 * Черты РИСОВАНЫ ПУТЯМИ, а не набраны шрифтом: шрифта с этими знаками на части
 * машин нет, и вместо 撃 человек увидел бы пустой прямоугольник.
 */
.avfx-kanji {
  z-index: 0;
  -webkit-mask-image:
    radial-gradient(circle at var(--hx1, -999px) var(--hy1, -999px),
      transparent 0 var(--hr1, 0px), #000 calc(var(--hr1, 0px) + 30px)),
    radial-gradient(circle at var(--hx2, -999px) var(--hy2, -999px),
      transparent 0 var(--hr2, 0px), #000 calc(var(--hr2, 0px) + 30px));
  -webkit-mask-composite: source-in;
  mask-image:
    radial-gradient(circle at var(--hx1, -999px) var(--hy1, -999px),
      transparent 0 var(--hr1, 0px), #000 calc(var(--hr1, 0px) + 30px)),
    radial-gradient(circle at var(--hx2, -999px) var(--hy2, -999px),
      transparent 0 var(--hr2, 0px), #000 calc(var(--hr2, 0px) + 30px));
  mask-composite: intersect;
  will-change: transform, opacity;
}

.avfx-kanji__ink {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
}

/*
 * Штрих КИСТЕВОЙ: круглые концы, разная толщина у разных черт (её задаёт JS) и
 * рваный край от лёгкого дрожания контура. Ничего гладко-типографского.
 */
.avfx-kanji__ink g {
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/*
 * Красный оттиск сдвинут — тот же приём, что у чернильной тени под числом.
 * Ни та ни другая краска не глухая: знак лежит поверх интерфейса, и сквозь него
 * обязано читаться, что там под ним.
 */
.avfx-kanji__red {
  stroke: var(--avfx-red);
  opacity: .7;
  transform: translate(2.4px, 3px);
}

.avfx-kanji__black {
  stroke: var(--avfx-ink);
  opacity: .84;
}

/* ── Уворот: смазанная лента ──────────────────────────────────────────────── */

/*
 * Не «двойник бойца», а строки, размазанные быстрой прокруткой: ровно то, что
 * видишь, когда лента дёрнулась под пальцем.
 */
.avfx-ghost {
  z-index: 2;
  border-radius: 6px;
  background: linear-gradient(90deg, rgba(11, 93, 215, .04), rgba(17, 17, 17, .26), rgba(11, 93, 215, .04));
  filter: blur(2.5px);
  will-change: transform, opacity;
}

/* ── Приём: цитата и волна ────────────────────────────────────────────────── */

.avfx-quote {
  z-index: 5;
  display: flex;
  align-items: center;
  max-width: 76vw;
  padding: 7px 12px 7px 13px;
  border-radius: 8px;
  background: var(--avfx-paper);
  border: 1px solid #dcdcdc;
  border-left: 4px solid var(--avfx-blue);
  box-shadow: 3px 3px 0 rgba(17, 17, 17, .16);
  overflow: hidden;
  will-change: transform, opacity;
}

/* Набегающая заливка — «цитату» словно выделяют по мере чтения. */
.avfx-quote__fill {
  position: absolute;
  inset: 0;
  background: #e8f2ff;
  transform-origin: left center;
  transform: scaleX(0);
}

.avfx-quote__text {
  position: relative;
  font-family: var(--avfx-face);
  font-size: 13px;
  font-weight: 700;
  line-height: 1.25;
  color: var(--avfx-ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Волна на выпуске: полоса бумаги, идущая от автора приёма к сопернику. */
.avfx-wave {
  z-index: 2;
  background: linear-gradient(90deg, rgba(11, 93, 215, 0), rgba(11, 93, 215, .2), rgba(11, 93, 215, 0));
  will-change: transform, opacity;
}

/* ── Серия: разделитель треда ─────────────────────────────────────────────── */

/*
 * Серия — событие раунда, и подаётся не как удар, а как отбивка в ленте:
 * синяя черта и набранное капителью слово.
 */
.avfx-combo {
  z-index: 5;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  border-radius: 999px;
  background: var(--avfx-paper);
  border: 2px solid var(--avfx-blue);
  box-shadow: 3px 3px 0 rgba(11, 93, 215, .2);
  transform-origin: 50% 50%;
  overflow: hidden;
  will-change: transform, opacity;
}

.avfx-combo__rule {
  flex: 0 0 auto;
  width: 12px;
  height: 3px;
  border-radius: 2px;
  background: var(--avfx-blue);
}

.avfx-combo__text {
  font-family: var(--avfx-face);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: .7px;
  text-transform: uppercase;
  color: var(--avfx-blue);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ── Лечение: короткие плюсы ──────────────────────────────────────────────── */

.avfx-tick {
  z-index: 5;
  font-family: var(--avfx-face);
  font-size: 22px;
  font-weight: 900;
  line-height: 1;
  color: var(--avfx-green);
  text-shadow: 1px 1px 0 rgba(255, 255, 255, .9);
  will-change: transform, opacity;
}

/* ── Бумага дрогнула: вспышка и замирание кадра ───────────────────────────── */

/*
 * Оба листа лежат НИЖЕ всего остального (z-index: 1): вспышка обязана
 * подсветить сцену, а не смыть с неё число.
 *
 * ОБА ПРОЗРАЧНЫ В ПОКОЕ, и это не мелочь. Это единственные узлы слоя размером
 * во весь экран: стоит анимации по любой причине не примениться — не начаться,
 * доиграть до конца или сорваться, — и непрозрачный лист закроет собой всю
 * страницу белым. Прозрачность в покое делает такой кадр невозможным: видимыми
 * они бывают только пока их ведёт анимация.
 */
.avfx-flash {
  z-index: 1;
  position: fixed;
  inset: 0;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  background: #ffffff;
}

/*
 * Замирание кадра: лист на миг «садится» — чуть темнее и всё. Этот, в отличие
 * от вспышки, живёт БЕЗ анимации (его ставит и снимает hitstop по таймеру),
 * поэтому в покое он видим — иначе замирания не было бы вовсе. Опасности в этом
 * нет: краска еле заметная, а таймер снимает лист при любом исходе сцены.
 */
.avfx-freeze {
  z-index: 1;
  position: fixed;
  inset: 0;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  background: rgba(17, 17, 17, .07);
}

/* ── Конец боя: штамп ─────────────────────────────────────────────────────── */

/*
 * Бой должен КОНЧАТЬСЯ. Штамп бьёт по бумаге как настоящий: двойная рамка,
 * тяжёлые буквы, чуть криво. Кегль на clamp — на 375 px надпись «КОММЕНТАРИЙ
 * УДАЛЁН» целиком помещается в экран и не даёт прокрутки вбок.
 */
.avfx-stamp {
  z-index: 8;
  padding: 10px 20px 12px;
  max-width: 92vw;
  border-radius: 6px;
  font-family: var(--avfx-face);
  font-size: clamp(19px, 5.6vw, 46px);
  font-weight: 900;
  line-height: 1;
  letter-spacing: .06em;
  white-space: nowrap;
  text-align: center;
  background: rgba(255, 255, 255, .88);
  will-change: transform, opacity;
}

.avfx-stamp.is-win {
  color: var(--avfx-blue);
  border: 4px double var(--avfx-blue);
  box-shadow: 0 0 0 2px rgba(11, 93, 215, .18), 6px 6px 0 rgba(11, 93, 215, .16);
}

.avfx-stamp.is-lose {
  color: #a42d32;
  border: 4px double #a42d32;
  box-shadow: 0 0 0 2px rgba(164, 45, 50, .18), 6px 6px 0 rgba(164, 45, 50, .16);
}

/* ── Узкий экран ──────────────────────────────────────────────────────────── */

/*
 * На телефоне карточки бойцов стоят друг под другом и занимают почти всю
 * ширину. Плашки ужимаем, чернильные тени укорачиваем — иначе они лезут за
 * кромку листа. Прокрутки вбок всё равно не будет (overflow: hidden у корня),
 * но и упираться в край незачем.
 *
 * ЧАСТИЦЫ НЕ УМЕНЬШАЕМ: на телефоне их МЕНЬШЕ (счёт ведёт JS), но не мельче —
 * мелкая крошка на маленьком экране просто пропала бы, и эффекта не стало бы
 * вовсе. Клавишам размер сбавляем: колпачок обязан оставить видимыми и полосы
 * Жизни, и число.
 */
@media (max-width: 560px) {
  .avfx-quote { max-width: 84vw; padding: 6px 10px 6px 11px; }
  .avfx-quote__text { font-size: 12px; }
  .avfx-combo { padding: 5px 8px; }
  .avfx-combo__text { font-size: 9px; letter-spacing: .5px; }
  .avfx-plate { box-shadow: 2px 2px 0 rgba(17, 17, 17, .18); }
  .avfx-plate::before { left: 9px; right: 14px; }
  .avfx-stamp { padding: 8px 14px 10px; letter-spacing: .04em; }
  .avfx-tick { font-size: 18px; }
  /* Тень на телефоне короче: там всё ближе к краю листа. */
  .avfx-key { filter: drop-shadow(6px 8px 2px rgba(17, 17, 17, .42)); }
  .avfx-key.is-camera { filter: drop-shadow(11px 14px 3px rgba(17, 17, 17, .46)); }
}

/* ── «Меньше движения» ────────────────────────────────────────────────────── */

/*
 * Спокойный вариант — не пустой: полоса маркера, число в таблетке, ОБЪЁМНАЯ
 * клавиша, стоящая вполоборота, и штамп на месте. У всего этого меняется одна
 * прозрачность (это делает JS) — ничто не летит и не кувыркается, но шутка про
 * клавиатуру остаётся видимой.
 *
 * Здесь снимаем всё, что живёт само: размытия и жёсткие тени, от которых рябит.
 */
@media (prefers-reduced-motion: reduce) {
  .avfx { transition: none; }
  .avfx-ghost { filter: none; }
  .avfx-bit.is-near { filter: none; }
  /* Тень у неподвижного колпачка короче: спокойной сцене резкость ни к чему. */
  .avfx-key,
  .avfx-key.is-camera { filter: drop-shadow(5px 7px 2px rgba(17, 17, 17, .4)); }
  /*
   * Знак остаётся знаком: набор, подложка и смещённый отпечаток на месте — здесь
   * и так ничего не двигается. Убираем только лишний разъезд второго отпечатка
   * на метком: неподвижная сцена от него рябит.
   */
  .avfx-num.is-crit { --num-print: .06em .07em 0 var(--avfx-ink); }
}
