/**
 * ============================================================
 *  VÕ ĐÀI CHIBI — khung, võ đài, bảng điểm
 * ============================================================
 *  Sân khấu gốc 1080×1920 (khổ dọc TikTok). Mọi toạ độ trong file này tính
 *  bằng px thật trong khung đó; JS chỉ phóng cả sân khấu cho vừa cửa sổ.
 */

:root {
  --red: #e6203c;
  --red-soft: #ff6b7d;
  --blue: #1f6feb;
  --blue-soft: #7fc4ff;
  --gold: #ffd166;
  --ink: #05070f;
  --text: #f2f7ff;
  --font: "Bebas Neue", "Arial Narrow", "Helvetica Neue", Arial, sans-serif;
  --font-ui: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}

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

html, body {
  width: 100%;
  height: 100%;
  overflow: hidden;
  background: #000;
  color: var(--text);
  font-family: var(--font-ui);
}
body { display: flex; align-items: center; justify-content: center; }

.shell {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background: #000;
}

/* Sân khấu gốc — JS đặt --stage-scale và căn giữa */
.stage {
  position: absolute;
  top: 0;
  left: 0;
  width: 1080px;
  height: 1920px;
  overflow: hidden;
  transform-origin: top left;
  transform: scale(var(--stage-scale, 1));
  background: #05070f;
}

/* ============================================================
   NỀN VÕ ĐÀI
   ============================================================ */

.arena { position: absolute; inset: 0; }

/* ============================================================
   ARENA BACKDROP — built from the real photo
   ============================================================
   scripts/make-arena.py turns public/client/<photo>.png into bg.jpg plus
   three crowd strips. The drawn sky / dotted crowd / truss that used to live
   here are gone; the photo does that job far better. */
.arena__photo {
  position: absolute;
  inset: 0;
  background: url('/arena/bg.jpg') center / cover no-repeat;
}
/* Layer of moving crowd strips sitting on top of the still backdrop */
.arena__live {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 1230px;
  overflow: hidden;
  pointer-events: none;
}
.arena__band {
  position: absolute;
  left: 50%;
  background-position: center;
  background-size: 100% 100%;
  background-repeat: no-repeat;
  /* Chỉ nhích ngang vài px và sáng tối theo nhịp — đủ để khán đài "thở",
     không đủ để lộ ra là ảnh chụp bị kéo qua kéo lại */
  will-change: transform, filter;
}
/* Vị trí và ảnh của ba dải khán đài nằm ở /arena/bands.css — file đó do
   scripts/make-arena.py sinh ra cùng lúc với ảnh nền, nên toạ độ luôn khớp
   tuyệt đối với chỗ vừa cắt. Ở đây chỉ giữ phần nhịp chuyển động. */
.arena__band--1 { animation: crowdSway 4.6s ease-in-out infinite; }
.arena__band--2 { animation: crowdSway 5.9s ease-in-out infinite reverse; animation-delay: -1.7s; }
.arena__band--3 { animation: crowdSway 3.8s ease-in-out infinite; animation-delay: -2.9s; }
@keyframes crowdSway {
  0%, 100% { transform: translateX(-5px); filter: brightness(0.94); }
  50% { transform: translateX(5px); filter: brightness(1.12); }
}
/* Đèn flash máy ảnh lóe lên trong khán đài — thứ làm khán đài ra vẻ đang xem
   trận thật chứ không phải một tấm ảnh dán vào */
.arena__flash {
  position: absolute;
  left: 0;
  right: 0;
  top: 430px;
  height: 580px;
  pointer-events: none;
  background-image:
    radial-gradient(circle at 14% 22%, rgba(255,255,255,0.9) 0 2px, transparent 5px),
    radial-gradient(circle at 63% 12%, rgba(255,255,255,0.85) 0 2px, transparent 5px),
    radial-gradient(circle at 38% 61%, rgba(255,255,255,0.8) 0 2px, transparent 5px),
    radial-gradient(circle at 87% 44%, rgba(255,255,255,0.9) 0 2px, transparent 5px),
    radial-gradient(circle at 24% 79%, rgba(255,255,255,0.85) 0 2px, transparent 5px),
    radial-gradient(circle at 72% 71%, rgba(255,255,255,0.8) 0 2px, transparent 5px);
  animation: crowdFlash 1.1s steps(1) infinite;
}
@keyframes crowdFlash {
  0%   { background-position: 0 0, 0 0, 0 0, 0 0, 0 0, 0 0; opacity: 0.9; }
  25%  { background-position: 40px 20px, -30px 10px, 20px -25px, -50px 30px, 35px 15px, -20px -10px; opacity: 0.5; }
  50%  { background-position: -25px 45px, 55px -20px, -40px 30px, 25px -35px, -45px 25px, 30px 40px; opacity: 1; }
  75%  { background-position: 60px -15px, -45px 40px, 35px 20px, -20px -30px, 15px -40px, -55px 25px; opacity: 0.6; }
  100% { background-position: 0 0, 0 0, 0 0, 0 0, 0 0, 0 0; opacity: 0.9; }
}
/* Tối bốn góc cho hai võ sĩ ở giữa nổi lên */
.arena__vignette {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(ellipse 78% 58% at 50% 52%, transparent 40%, rgba(0,0,0,0.72) 100%);
}
.is-lite .arena__band,
.is-lite .arena__flash { animation: none; }

/* .arena__sky: thay bằng ảnh sân thật */


/* Khán đài: hàng nghìn chấm sáng lờ mờ, đủ để thấy đây là sân vận động */
/* .arena__crowd: thay bằng ảnh sân thật */

@keyframes crowdTwinkle {
  0%, 100% { background-position: 0 0, 13px 11px; }
  50% { background-position: 3px 2px, 10px 9px; }
}

/* Giàn đèn treo ngang trên đỉnh */
/* .arena__truss: thay bằng ảnh sân thật */


/* Hai chùm đèn rọi xuống sàn đấu */
.arena__spot {
  position: absolute;
  top: 176px;
  width: 460px;
  height: 1080px;
  clip-path: polygon(44% 0, 56% 0, 100% 100%, 0 100%);
  mix-blend-mode: screen;
  animation: spotSwing 5.2s ease-in-out infinite;
}
.arena__spot--l {
  left: 60px;
  background: linear-gradient(180deg, rgba(255, 120, 140, 0.42), rgba(255, 120, 140, 0.08) 50%, transparent 82%);
}
.arena__spot--r {
  right: 60px;
  background: linear-gradient(180deg, rgba(120, 180, 255, 0.42), rgba(120, 180, 255, 0.08) 50%, transparent 82%);
  animation-delay: -2.4s;
}
@keyframes spotSwing {
  0%, 100% { transform: rotate(-5deg); opacity: 0.7; }
  50% { transform: rotate(5deg); opacity: 1; }
}

/* ---------- Sàn đấu + dây võ đài ---------- */
/* Mặt sàn nghiêng theo phối cảnh: xa hẹp, gần rộng */
.arena__mat {
  position: absolute;
  left: 50%;
  top: 1210px;
  width: 1240px;
  height: 330px;
  margin-left: -620px;
  clip-path: polygon(19% 0, 81% 0, 100% 100%, 0 100%);
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.16) 0 3px, transparent 3px),
    linear-gradient(180deg, #2c3550 0%, #1d2438 44%, #121828 100%);
  box-shadow: inset 0 -30px 60px rgba(0, 0, 0, 0.6);
}
.arena__mat-line {
  position: absolute;
  left: 8%;
  right: 8%;
  top: 52%;
  height: 4px;
  background: linear-gradient(90deg, transparent, rgba(255, 209, 102, 0.6), transparent);
}
.arena__mat-logo {
  position: absolute;
  left: 50%;
  top: 58%;
  transform: translate(-50%, -50%);
  font-family: var(--font);
  font-size: 130px;
  font-weight: 900;
  letter-spacing: 0.1em;
  color: rgba(255, 255, 255, 0.06);
  text-shadow: 0 2px 0 rgba(0, 0, 0, 0.3);
}

/* Dây võ đài chạy ngang trước mặt hai võ sĩ */
/* Dây võ đài xếp TRƯỚC võ sĩ (z 40 > .ring 30) — nhìn từ ngoài vào thì dây
   phải cắt ngang chân họ, thiếu cái đó là hai người như đứng ngoài sàn. */
.arena__ring {
  position: absolute;
  left: 0;
  right: 0;
  top: 1210px;
  height: 330px;
  /* Trên cả mép sàn (45) — dây phải vắt qua trước mặt sàn mới ra hình võ đài */
  z-index: 46;
  pointer-events: none;
}
/**
 * DÂY VÕ ĐÀI.
 *
 * Dây thật là ống bọc vải căng giữa hai cột: sáng ở mép trên nơi đèn hắt vào,
 * tối dần xuống bụng dây, và võng nhẹ ở giữa nhịp. Ba dải màu khác nhau —
 * trên đỏ, giữa trắng, dưới xanh — cho ra đúng chất võ đài nhà nghề thay vì
 * ba vạch vàng giống hệt nhau.
 */
.arena__rope {
  position: absolute;
  left: 1.5%;
  right: 1.5%;
  height: 14px;
  border-radius: 8px;
  background:
    linear-gradient(180deg,
      rgba(255, 255, 255, 0.95) 0 2px,
      var(--rope, #e8e8ee) 2px 42%,
      color-mix(in srgb, var(--rope, #e8e8ee) 55%, #000) 78%,
      rgba(0, 0, 0, 0.6) 100%);
  box-shadow:
    0 4px 12px rgba(0, 0, 0, 0.6),
    inset 0 -2px 4px rgba(0, 0, 0, 0.4);
}
/* Vòng bọc siết dây, rải đều dọc theo — chi tiết nhỏ mà thiếu nó dây trông
   như một thanh nhựa liền */
.arena__rope::after {
  content: "";
  position: absolute;
  inset: -3px 0;
  border-radius: 9px;
  background: repeating-linear-gradient(90deg,
    transparent 0 116px,
    rgba(20, 24, 36, 0.85) 116px 124px,
    rgba(255, 255, 255, 0.25) 124px 127px,
    transparent 127px 243px);
}
/* Chân võ sĩ chạm sàn ở y 1290; dây dưới cùng nằm hẳn phía trước bàn chân,
   hai dây trên vắt ngang mặt sàn phía sau — đúng kiểu nhìn từ ngoài vào. */
.arena__rope--1 { top: 118px; --rope: #e0263c; }
.arena__rope--2 { top: 208px; --rope: #f2f4f8; }
.arena__rope--3 { top: 292px; --rope: #2f6fd0; }
.arena__post {
  position: absolute;
  top: 84px;
  width: 34px;
  height: 250px;
  border-radius: 8px;
  background:
    linear-gradient(90deg,
      #10141f 0 5%, #6a7690 26%, #99a6c0 44%,
      #5c6880 66%, #0d1119 100%);
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.7);
}
.arena__post--l { left: 1.2%; }
.arena__post--r { right: 1.2%; }
/* Đệm góc bọc quanh cột — mảng màu to nhất của võ đài thật */
.arena__pad {
  position: absolute;
  top: 100px;
  width: 52px;
  height: 216px;
  border-radius: 14px;
  background:
    linear-gradient(180deg,
      #e0263c 0 33%, #f2f4f8 33% 66%, #2f6fd0 66% 100%);
  box-shadow:
    inset -10px 0 16px rgba(0, 0, 0, 0.45),
    inset 8px 0 12px rgba(255, 255, 255, 0.25),
    0 8px 22px rgba(0, 0, 0, 0.65);
}
.arena__pad--l { left: 0.4%; }
.arena__pad--r { right: 0.4%; }

/* ============================================================
   BẢNG MÁU
   ============================================================ */

.hud {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  z-index: 60;
  padding: 26px 26px 0;
}
.hud__round {
  text-align: center;
  margin-bottom: 12px;
}
.hud__round b {
  display: inline-block;
  padding: 6px 26px;
  border-radius: 999px;
  background: rgba(10, 14, 28, 0.8);
  border: 2px solid rgba(255, 209, 102, 0.5);
  font-family: var(--font);
  font-size: 34px;
  letter-spacing: 0.16em;
  color: var(--gold);
}
.hud__bars {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 16px;
}
.hud__vs {
  font-family: var(--font);
  font-size: 56px;
  font-weight: 900;
  color: #fff;
  text-shadow: 0 0 18px rgba(255, 209, 102, 0.8), 0 4px 0 #000;
}

.bar__top {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 6px;
}
.bar--blue .bar__top { justify-content: flex-end; }
.bar__team {
  font-family: var(--font);
  font-size: 40px;
  letter-spacing: 0.06em;
  text-shadow: 0 3px 0 rgba(0, 0, 0, 0.6);
}
.bar--red .bar__team { color: var(--red-soft); }
.bar--blue .bar__team { color: var(--blue-soft); }
/* Số cổ động viên */
.bar__fans {
  font-size: 26px;
  font-weight: 800;
  color: #cfe0ff;
  opacity: 0.85;
}
.bar__fans::before { content: "👥 "; }

/**
 * THANH MÁU.
 *
 * Ba lớp chồng nhau như thanh máu game đối kháng: rãnh tối khoét sâu, một
 * thanh "máu vừa mất" màu vàng tụt chậm phía sau, và thanh máu thật tụt ngay.
 * Nhờ lớp vàng ấy mà mắt bắt được ngay là vừa ăn bao nhiêu sát thương — thứ
 * một thanh trơn không nói được.
 */
.bar__track {
  position: relative;
  height: 40px;
  border-radius: 8px;
  background: linear-gradient(180deg, #05070f, #0d1424);
  border: 3px solid rgba(255, 255, 255, 0.28);
  overflow: hidden;
  box-shadow:
    inset 0 4px 12px rgba(0, 0, 0, 0.85),
    0 3px 10px rgba(0, 0, 0, 0.6);
  /* Vát chéo hai đầu cho ra dáng bảng điểm thi đấu */
  clip-path: polygon(14px 0, 100% 0, calc(100% - 14px) 100%, 0 100%);
}
.bar--blue .bar__track {
  clip-path: polygon(0 0, calc(100% - 14px) 0, 100% 100%, 14px 100%);
}
/* Vạch chia mỗi 10% — đọc nhanh còn bao nhiêu máu */
.bar__track::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: repeating-linear-gradient(90deg,
    transparent 0 9.9%, rgba(0, 0, 0, 0.55) 9.9% 10.1%);
}
.bar__fill {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 100%;
  /* Máu tụt mượt chứ không giật cục từng nấc */
  transition: width 0.35s cubic-bezier(0.2, 0.9, 0.3, 1);
}
/* Vệt bóng chạy dọc mặt thanh — thanh máu "sống" chứ không phẳng lì */
.bar__fill::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg,
    rgba(255, 255, 255, 0.45) 0 34%,
    rgba(255, 255, 255, 0.08) 34% 58%,
    rgba(0, 0, 0, 0.28) 100%);
}
.bar--red .bar__fill {
  left: 0;
  background: linear-gradient(90deg, #8d0e20, var(--red) 40%, #ff5a6e 100%);
  box-shadow: 0 0 20px rgba(230, 32, 60, 0.75);
}
/* Lớp "máu vừa mất" — tụt chậm hơn nửa giây phía sau thanh chính */
.bar--red .bar__ghost { left: 0; }
/* Thanh phe xanh vơi từ trái sang cho hai bên đối xứng nhau */
.bar--blue .bar__fill {
  right: 0;
  background: linear-gradient(90deg, #5ab6ff 0%, var(--blue) 60%, #0d3c86 100%);
  box-shadow: 0 0 20px rgba(31, 111, 235, 0.75);
}
.bar--blue .bar__ghost { right: 0; }

/* Thanh máu vừa mất: cùng chỗ, màu vàng, tụt chậm hơn để lộ ra đúng phần
   sát thương của cú vừa rồi */
.bar__ghost {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 100%;
  background: linear-gradient(180deg, #ffe27a, #d98f12);
  transition: width 0.75s ease-out 0.28s;
}
/* Máu cạn thì thanh nhấp nháy báo động */
.bar__fill.is-low { animation: hpLow 0.5s steps(2) infinite; }
@keyframes hpLow {
  0%, 100% { filter: brightness(1); }
  50% { filter: brightness(2.2) saturate(1.4); }
}
.bar__name {
  margin-top: 6px;
  font-size: 27px;
  font-weight: 800;
  letter-spacing: 0.04em;
  color: #eaf2ff;
  text-shadow: 0 2px 6px #000;
}
.bar--blue .bar__name { text-align: right; }

/* ============================================================
   HAI VÕ SĨ
   ============================================================ */

/**
 * Khung đứng của hai võ sĩ.
 *
 * Chân chạm sàn ở y = 1400 trong sân khấu 1920. Phóng 1.45 lần thì mỗi người
 * cao 420×1.45 ≈ 610px, chiếm hẳn khoảng giữa màn — trước đây để 1.06 nên hai
 * nhân vật lọt thỏm giữa một mảng nền trống.
 */
.ring {
  position: absolute;
  left: 0;
  right: 0;
  top: 500px;
  height: 790px;
  z-index: 30;
}
.slot {
  position: absolute;
  bottom: 0;
  width: 300px;
  height: 470px;
}
/* Đứng gần nhau vừa tầm đấm; phe xanh lùi lại 14px cho có lớp trước lớp sau */
.slot--red { left: 96px; }
.slot--blue { right: 96px; bottom: 14px; }

.slot .fg { --s: 1.62; }
.slot--blue .fg { --s: 1.54; }

/* Tên treo TRÊN đầu võ sĩ.
   Để dưới chân là đụng đúng dải dây võ đài và bảng cổ động viên; treo trên
   đầu thì luôn trống trải, đọc được cả lúc hai người xáp lá cà. */
.fg__name {
  position: absolute;
  left: 50%;
  top: -14px;
  transform: translateX(-50%);
  padding: 3px 16px;
  border-radius: 999px;
  background: rgba(6, 10, 22, 0.85);
  border: 2px solid rgba(255, 255, 255, 0.25);
  font-size: 24px;
  font-weight: 800;
  white-space: nowrap;
  color: #eaf2ff;
}
body[data-labels="off"] .fg__name { display: none; }

/* ============================================================
   HIỆU ỨNG VA CHẠM + MÁU
   ============================================================ */

.fx {
  position: absolute;
  inset: -200px -60px;
  pointer-events: none;
  z-index: 50;
  overflow: visible;
}

/* Ngôi sao va chạm — vẽ bằng conic-gradient, không cần ảnh */
.hit {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: var(--d, 190px);
  height: var(--d, 190px);
  margin: calc(var(--d, 190px) / -2) 0 0 calc(var(--d, 190px) / -2);
  background: conic-gradient(
    from 0deg,
    #fff 0 6deg, transparent 6deg 30deg,
    #ffe27a 30deg 36deg, transparent 36deg 60deg,
    #fff 60deg 66deg, transparent 66deg 90deg,
    #ffd166 90deg 96deg, transparent 96deg 120deg,
    #fff 120deg 126deg, transparent 126deg 150deg,
    #ffe27a 150deg 156deg, transparent 156deg 180deg,
    #fff 180deg 186deg, transparent 186deg 210deg,
    #ffd166 210deg 216deg, transparent 216deg 240deg,
    #fff 240deg 246deg, transparent 246deg 270deg,
    #ffe27a 270deg 276deg, transparent 276deg 300deg,
    #fff 300deg 306deg, transparent 306deg 330deg,
    #ffd166 330deg 336deg, transparent 336deg 360deg
  );
  border-radius: 50%;
  animation: hitPop 0.42s cubic-bezier(0.2, 0.9, 0.3, 1) forwards;
}
@keyframes hitPop {
  0% { opacity: 0; transform: scale(0.2) rotate(0deg); }
  30% { opacity: 1; transform: scale(1.15) rotate(30deg); }
  100% { opacity: 0; transform: scale(1.5) rotate(60deg); }
}
/* Lõi trắng loá ở tâm cú đấm */
.hit::after {
  content: "";
  position: absolute;
  inset: 26%;
  border-radius: 50%;
  background: radial-gradient(circle, #fff 0 40%, rgba(255, 226, 122, 0.6) 62%, transparent 78%);
}

/* Vòng sóng xung kích của đòn nặng */
.shock {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: 120px;
  height: 120px;
  margin: -60px 0 0 -60px;
  border-radius: 50%;
  border: 8px solid rgba(255, 255, 255, 0.9);
  animation: shockOut 0.5s ease-out forwards;
}
@keyframes shockOut {
  0% { opacity: 1; transform: scale(0.3); border-width: 12px; }
  100% { opacity: 0; transform: scale(4.4); border-width: 1px; }
}

/* ---------- Máu ---------- */
/* Mỗi giọt là một hạt bay theo đường parabol rồi rơi xuống */
.blood {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: var(--w, 16px);
  height: var(--h, 22px);
  border-radius: 60% 60% 50% 50% / 70% 70% 40% 40%;
  background: linear-gradient(180deg, #ff2a3a, #a3000f 70%, #5c0009);
  box-shadow: 0 0 8px rgba(190, 10, 25, 0.8);
  animation: bloodFly var(--dur, 0.9s) cubic-bezier(0.25, 0.5, 0.6, 1) forwards;
  animation-delay: var(--delay, 0s);
  opacity: 0;
}
@keyframes bloodFly {
  0% { opacity: 0; transform: translate(0, 0) scale(0.5) rotate(0deg); }
  12% { opacity: 1; }
  60% { transform: translate(calc(var(--dx) * 0.7), calc(var(--dy) * 1.0)) scale(1) rotate(140deg); }
  100% { opacity: 0.9; transform: translate(var(--dx), calc(var(--dy) + 240px)) scale(0.8) rotate(300deg); }
}
/* Vệt máu đọng trên sàn sau đòn nặng */
.splat {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: var(--d, 120px);
  height: calc(var(--d, 120px) * 0.42);
  margin-left: calc(var(--d, 120px) / -2);
  border-radius: 50%;
  background: radial-gradient(ellipse, rgba(150, 5, 18, 0.85) 0 44%, rgba(110, 2, 12, 0.4) 70%, transparent 84%);
  animation: splatIn 0.4s ease-out forwards, splatFade 4s ease-in 2.4s forwards;
}
@keyframes splatIn {
  0% { opacity: 0; transform: scale(0.2); }
  100% { opacity: 1; transform: scale(1); }
}
@keyframes splatFade { to { opacity: 0; } }

body[data-blood="off"] .blood,
body[data-blood="off"] .splat { display: none; }

/* Số sát thương bay lên */
.dmg {
  position: absolute;
  left: var(--x);
  top: var(--y);
  transform: translate(-50%, -50%);
  font-family: var(--font);
  font-size: 62px;
  font-weight: 900;
  color: #fff;
  text-shadow: 0 0 14px rgba(255, 90, 90, 0.9), 0 5px 0 #7a0010;
  animation: dmgUp 0.9s cubic-bezier(0.2, 0.9, 0.3, 1) forwards;
}
.dmg--big { font-size: 104px; color: #ffe27a; text-shadow: 0 0 22px #ff3b30, 0 6px 0 #6a0008; }
@keyframes dmgUp {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(0.4); }
  25% { opacity: 1; transform: translate(-50%, -80%) scale(1.2); }
  100% { opacity: 0; transform: translate(-50%, -180%) scale(1); }
}

/* Rung màn hình khi trúng đòn nặng */
.stage.is-shake { animation: shake 0.42s cubic-bezier(0.36, 0.07, 0.19, 0.97); }
@keyframes shake {
  10%, 90% { transform: scale(var(--stage-scale, 1)) translate(-8px, 4px); }
  20%, 80% { transform: scale(var(--stage-scale, 1)) translate(14px, -8px); }
  30%, 50%, 70% { transform: scale(var(--stage-scale, 1)) translate(-18px, 10px); }
  40%, 60% { transform: scale(var(--stage-scale, 1)) translate(18px, -6px); }
}
body[data-shake="off"] .stage.is-shake { animation: none; }

/* Chớp đỏ toàn màn khi vỡ mồm */
.stage.is-flash::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 70;
  pointer-events: none;
  background: radial-gradient(ellipse 80% 50% at 50% 55%, rgba(255, 40, 60, 0.55), transparent 72%);
  animation: flashOut 0.36s ease-out forwards;
}
@keyframes flashOut { to { opacity: 0; } }

/* ============================================================
   BĂNG CHỮ ĐÒN ĐÁNH
   ============================================================ */

.callout {
  position: absolute;
  left: 50%;
  top: 690px;
  z-index: 65;
  transform: translateX(-50%);
  padding: 10px 40px;
  border-radius: 14px;
  font-family: var(--font);
  font-size: 54px;
  letter-spacing: 0.1em;
  white-space: nowrap;
  color: #fff;
  background: rgba(8, 12, 24, 0.85);
  border: 3px solid rgba(255, 255, 255, 0.3);
  text-shadow: 0 3px 0 #000;
  animation: calloutIn 0.3s cubic-bezier(0.2, 1.4, 0.4, 1);
}
.callout--red { border-color: var(--red); box-shadow: 0 0 26px rgba(230, 32, 60, 0.6); }
.callout--blue { border-color: var(--blue); box-shadow: 0 0 26px rgba(31, 111, 235, 0.6); }
.callout--big { font-size: 76px; color: var(--gold); }
@keyframes calloutIn {
  0% { opacity: 0; transform: translateX(-50%) scale(0.5); }
  100% { opacity: 1; transform: translateX(-50%) scale(1); }
}

/* ============================================================
   BẢNG CỔ ĐỘNG VIÊN
   ============================================================ */

/* Hai bảng cổ động viên dưới đáy đã bỏ: top 3 giờ bay quanh chính võ sĩ của
   họ, còn hai bảng thì vừa lặp lại vừa che mất lồng bát giác ở ảnh nền. */
.boards { display: none; }
.boards--legacy {
  position: absolute;
  left: 24px;
  right: 24px;
  top: 1520px;
  z-index: 55;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px;
}
.board {
  padding: 12px 14px;
  border-radius: 16px;
  background: rgba(6, 10, 22, 0.72);
  border: 2px solid rgba(255, 255, 255, 0.14);
}
.board--red { border-color: rgba(230, 32, 60, 0.5); }
.board--blue { border-color: rgba(31, 111, 235, 0.5); }
.board__title {
  font-family: var(--font);
  font-size: 30px;
  letter-spacing: 0.08em;
  margin-bottom: 8px;
}
.board--red .board__title { color: var(--red-soft); }
.board--blue .board__title { color: var(--blue-soft); }
.board__list { list-style: none; display: grid; gap: 5px; }
.board__row {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 25px;
  font-weight: 700;
}
.board__rank { width: 34px; color: var(--gold); font-family: var(--font); font-size: 28px; }
.board__pic {
  width: 34px;
  height: 34px;
  flex: none;
  border-radius: 50%;
  object-fit: cover;
  background: #223;
  display: grid;
  place-items: center;
  font-size: 19px;
}
.board__nick {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.board__coins { color: var(--gold); font-weight: 900; }

/* ============================================================
   HƯỚNG DẪN
   ============================================================ */

/* Sáu dòng xếp một cột thì chồm hẳn lên bảng cổ động viên — chia hai cột ba
   dòng, vừa gọn vừa đọc nhanh hơn khi đang live. */
.guide {
  position: absolute;
  left: 24px;
  right: 24px;
  bottom: 22px;
  z-index: 58;
  display: grid;
  grid-auto-flow: column;
  grid-template-rows: repeat(3, auto);
  column-gap: 26px;
  row-gap: 9px;
}
.guide__row { display: flex; align-items: center; gap: 12px; }
.guide__key {
  min-width: 96px;
  text-align: center;
  padding: 4px 14px;
  border-radius: 999px;
  background: rgba(8, 12, 24, 0.85);
  border: 2px solid rgba(255, 255, 255, 0.3);
  font-family: var(--font);
  font-size: 34px;
  letter-spacing: 0.06em;
  color: #fff;
}
.guide__key--red { border-color: var(--red); color: var(--red-soft); }
.guide__key--blue { border-color: var(--blue); color: var(--blue-soft); }
.guide__key--gift { border-color: var(--gold); }
.guide__zh { font-size: 30px; font-weight: 800; color: var(--gold); }
.guide__vi { font-size: 25px; font-weight: 700; color: #dfe9ff; text-shadow: 0 2px 6px #000; }

/* ============================================================
   MÀN K.O
   ============================================================ */

.ko {
  position: absolute;
  inset: 0;
  z-index: 80;
  display: grid;
  place-content: center;
  text-align: center;
  background: rgba(2, 4, 10, 0.72);
}
.ko[hidden] { display: none; }
.ko__flash {
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at 50% 45%, rgba(255, 255, 255, 0.9), transparent 60%);
  animation: flashOut 0.5s ease-out forwards;
}
.ko__word {
  font-family: var(--font);
  font-size: 260px;
  font-weight: 900;
  letter-spacing: 0.08em;
  color: #fff;
  text-shadow: 0 0 40px #ff2a3a, 0 10px 0 #6a0008, 0 0 90px #ff2a3a;
  animation: koPop 0.6s cubic-bezier(0.2, 1.5, 0.4, 1);
}
@keyframes koPop {
  0% { opacity: 0; transform: scale(3) rotate(-14deg); }
  60% { opacity: 1; transform: scale(0.92) rotate(3deg); }
  100% { transform: scale(1) rotate(0deg); }
}
.ko__who {
  margin-top: 6px;
  font-family: var(--font);
  font-size: 74px;
  color: var(--gold);
  text-shadow: 0 4px 0 #000;
}
.ko__sub { margin-top: 12px; font-size: 32px; font-weight: 700; color: #cfe0ff; }

/* Nút vào bảng điều khiển — nhỏ, góc phải dưới */
.cog {
  position: absolute;
  right: 18px;
  bottom: 16px;
  z-index: 90;
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: rgba(10, 14, 28, 0.6);
  color: #8fa3c8;
  font-size: 22px;
  text-decoration: none;
}

/* Máy yếu: bỏ mấy lớp nền chạy hoạt ảnh suốt */
.is-lite .arena__crowd,
.is-lite .arena__spot { animation: none; }

/* ============================================================
   QUẢ CẦU KHÍ — đòn chưởng
   ============================================================
   Bay từ bàn tay người đánh sang mặt đối thủ; thời gian bay khớp đúng lúc
   tay duỗi hết (arena.js truyền --dur từ bảng nhịp trong fighter.js). */
.chi {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: 120px;
  height: 120px;
  margin: -60px 0 0 -60px;
  border-radius: 50%;
  background:
    radial-gradient(circle at 40% 38%, #fff 0 20%, rgba(255, 255, 255, 0.7) 34%, transparent 62%),
    radial-gradient(circle, var(--chi, #ffd166) 0 46%, rgba(255, 209, 102, 0.25) 66%, transparent 78%);
  box-shadow: 0 0 40px 12px var(--chi, #ffd166);
  animation: chiFly var(--dur, 330ms) cubic-bezier(0.3, 0, 0.7, 1) forwards;
}
.chi--red { --chi: #ff5a4a; }
.chi--blue { --chi: #5ac8ff; }
/* Vệt đuôi kéo dài phía sau quả cầu */
.chi::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 190px;
  height: 26px;
  margin: -13px 0 0 -95px;
  border-radius: 999px;
  background: linear-gradient(90deg, transparent, var(--chi, #ffd166));
  filter: blur(6px);
  opacity: 0.85;
}
@keyframes chiFly {
  0% { opacity: 0; transform: translate(0, 0) scale(0.3); }
  18% { opacity: 1; transform: translate(calc(var(--tx) * 0.18), calc(var(--ty) * 0.18)) scale(1); }
  100% { opacity: 1; transform: translate(var(--tx), var(--ty)) scale(1.25); }
}
.is-lite .chi::after { display: none; }

/* ============================================================
   VÕ SĨ BẰNG ẢNH
   ============================================================
   Thay chỗ của .fg (chibi vẽ CSS) khi cầu thủ đó đã có bộ sprite. Khung neo
   mép dưới vào vạch sàn; sprite.js lo cỡ và độ dìm theo từng tư thế. */
.sp {
  position: absolute;
  left: 50%;
  bottom: 0;
  width: 0;
  height: 0;
}
.sp__img {
  position: absolute;
  left: 50%;
  bottom: 0;
  transform: translateX(-50%);
  transform-origin: 50% 100%;
  display: block;
  /* Viền sáng ngược quanh người cho tách khỏi nền tối, kèm bóng đổ xuống sàn */
  filter:
    drop-shadow(0 0 3px rgba(255, 255, 255, 0.35))
    drop-shadow(0 18px 22px rgba(0, 0, 0, 0.75));
  /* Đổi tư thế thì bung nhẹ một cái cho cú đánh có lực */
  animation: spPop 0.16s ease-out;
}
@keyframes spPop {
  0% { transform: translateX(-50%) scale(0.97); }
  100% { transform: translateX(-50%) scale(1); }
}
/* Phe xanh đứng bên phải — tranh gốc ai cũng quay mặt sang phải nên phải lật */
.sp--blue .sp__img { transform: translateX(-50%) scaleX(-1); }
.sp--blue .sp__img { animation-name: spPopFlip; }
@keyframes spPopFlip {
  0% { transform: translateX(-50%) scaleX(-1) scale(0.97); }
  100% { transform: translateX(-50%) scaleX(-1) scale(1); }
}

/* Hào quang theo phe — thứ làm nên không khí trong ảnh mẫu */
.sp::before {
  content: "";
  position: absolute;
  left: 50%;
  bottom: 40px;
  width: 460px;
  height: 620px;
  margin-left: -230px;
  border-radius: 50% 50% 44% 44%;
  background: radial-gradient(
    ellipse at 50% 62%,
    var(--aura, rgba(255, 90, 90, 0.42)) 0 26%,
    rgba(255, 90, 90, 0.12) 52%,
    transparent 76%
  );
  mix-blend-mode: screen;
  animation: auraPulse 1.5s ease-in-out infinite;
  pointer-events: none;
}
.sp--red { --aura: rgba(255, 70, 60, 0.5); }
.sp--blue { --aura: rgba(70, 170, 255, 0.5); }
@keyframes auraPulse {
  0%, 100% { opacity: 0.65; transform: scale(1); }
  50% { opacity: 1; transform: scale(1.06); }
}

/* Tên treo trên đầu */
.sp__name {
  position: absolute;
  left: 50%;
  bottom: 660px;
  transform: translateX(-50%);
  padding: 3px 18px;
  border-radius: 999px;
  background: rgba(6, 10, 22, 0.85);
  border: 2px solid rgba(255, 255, 255, 0.28);
  font-size: 26px;
  font-weight: 800;
  white-space: nowrap;
  color: #eaf2ff;
}
body[data-labels="off"] .sp__name { display: none; }
.is-lite .sp::before { animation: none; }

/**
 * MÉP SÀN PHÍA TRƯỚC.
 *
 * Ảnh sprite hàng 1 chỉ vẽ từ thắt lưng trở lên, cắt ngang một nhát. Dải này
 * xếp TRƯỚC võ sĩ (z 45 > .ring 30) đúng chỗ vết cắt, nên nhìn ra hai người
 * đứng sau mép sàn chứ không phải hai nửa thân trôi lơ lửng.
 */
.arena__apron {
  position: absolute;
  left: -6%;
  right: -6%;
  top: 1236px;
  height: 250px;
  z-index: 45;
  border-radius: 50% 50% 0 0 / 46px 46px 0 0;
  background:
    linear-gradient(180deg,
      rgba(190, 225, 255, 0.5) 0 3px,
      #2b3550 3px 16%,
      #1b2337 46%, #0d1220 100%);
  box-shadow: 0 -10px 30px rgba(0, 0, 0, 0.7);
  pointer-events: none;
}

/* ============================================================
   RING GIRL
   ============================================================
   Stands on the apron between the two fighters. Hidden by default and only
   slides in at round start, a knockout and the winner call — the fight is the
   show, she is the punctuation. */
.girl {
  position: absolute;
  left: 50%;
  bottom: -40px;
  width: 0;
  height: 0;
  z-index: 47;
  pointer-events: none;
  opacity: 0;
  transform: translateY(60px);
  transition: opacity 0.4s ease, transform 0.5s cubic-bezier(0.2, 0.9, 0.3, 1);
}
.girl.is-on { opacity: 1; transform: translateY(0); }
.girl__img {
  position: absolute;
  left: 50%;
  bottom: 0;
  transform: translateX(-50%);
  display: block;
  filter:
    drop-shadow(0 0 3px rgba(255, 255, 255, 0.4))
    drop-shadow(0 14px 18px rgba(0, 0, 0, 0.7));
}

/* Winner name printed onto the board the ring girl holds — one plate that
   follows the board from pose to pose, instead of eight edited pictures. */
.girl__sign {
  position: absolute;
  transform-origin: 50% 50%;
  text-align: center;
  font-family: var(--font);
  font-size: 26px;
  line-height: 1.05;
  letter-spacing: 0.03em;
  color: #fff8dc;
  text-shadow: 0 2px 4px rgba(0, 0, 0, 0.9);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  pointer-events: none;
}

/* ============================================================
   TOP-3 SUPPORTERS, DRIFTING AROUND THEIR FIGHTER
   ============================================================
   Three round avatars per side, name beside each, bobbing on their own beat.
   They stay up for the whole fight — the people paying for the punches should
   be on screen while the punches land, not only on the results card. */
/* Nằm trong .ring (đã ở y 500) nên toạ độ ở đây là tương đối — ba avatar rơi
   vào khoảng y 690…1090 của sân khấu, tức ngang thân hai võ sĩ. */
.fans {
  position: absolute;
  top: 190px;
  width: 300px;
  height: 430px;
  z-index: 44;
  pointer-events: none;
}
.fans--red { left: 8px; }
.fans--blue { right: 8px; }

.fan {
  position: absolute;
  display: flex;
  align-items: center;
  gap: 9px;
  animation: fanFloat var(--dur, 5s) ease-in-out infinite;
  animation-delay: var(--delay, 0s);
}
.fans--blue .fan { flex-direction: row-reverse; }
/* Ba chỗ đứng lệch nhau, tránh chồng lên mặt võ sĩ */
.fan:nth-child(1) { top: 0; left: 0; --dur: 5.2s; --delay: 0s; }
.fan:nth-child(2) { top: 128px; left: 26px; --dur: 6.1s; --delay: -1.4s; }
.fan:nth-child(3) { top: 256px; left: 4px; --dur: 4.6s; --delay: -2.7s; }
.fans--blue .fan:nth-child(1) { left: auto; right: 0; }
.fans--blue .fan:nth-child(2) { left: auto; right: 26px; }
.fans--blue .fan:nth-child(3) { left: auto; right: 4px; }
@keyframes fanFloat {
  0%, 100% { transform: translate(0, 0); }
  50% { transform: translate(6px, -18px); }
}

.fan__pic {
  width: 68px;
  height: 68px;
  flex: none;
  border-radius: 50%;
  object-fit: cover;
  background: #1a2338;
  display: grid;
  place-items: center;
  font-size: 30px;
  font-weight: 900;
  color: #eaf2ff;
  border: 3px solid var(--ring, #fff);
  box-shadow: 0 0 16px var(--ring, #fff), 0 4px 10px rgba(0, 0, 0, 0.6);
}
.fans--red .fan__pic { --ring: var(--red); }
.fans--blue .fan__pic { --ring: var(--blue); }
/* Vòng sáng chạy quanh avatar — hạng 1 sáng nhất */
.fan:nth-child(1) .fan__pic { width: 82px; height: 82px; border-width: 4px; }

.fan__side {
  display: grid;
  gap: 1px;
  padding: 4px 12px;
  border-radius: 999px;
  background: rgba(6, 10, 22, 0.82);
  border: 1px solid rgba(255, 255, 255, 0.2);
}
.fans--blue .fan__side { text-align: right; }
.fan__name {
  font-size: 22px;
  font-weight: 800;
  color: #eaf2ff;
  max-width: 168px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fan__coins { font-size: 19px; font-weight: 900; color: var(--gold); }
.fan__coins::after { content: " ◆"; font-size: 14px; }

/* ============================================================
   CHEER POP — whoever just commented or sent a gift
   ============================================================ */
.shout {
  position: absolute;
  left: 50%;
  top: 1150px;
  z-index: 58;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 12px;
  max-width: 940px;
  padding: 8px 22px 8px 8px;
  border-radius: 999px;
  background: rgba(8, 12, 24, 0.9);
  border: 3px solid var(--gold);
  box-shadow: 0 0 26px rgba(255, 209, 102, 0.45);
  animation: shoutIn 0.28s cubic-bezier(0.2, 1.5, 0.4, 1);
}
.shout[hidden] { display: none; }
.shout--red { border-color: var(--red); box-shadow: 0 0 26px rgba(230, 32, 60, 0.55); }
.shout--blue { border-color: var(--blue); box-shadow: 0 0 26px rgba(31, 111, 235, 0.55); }
@keyframes shoutIn {
  0% { opacity: 0; transform: translateX(-50%) scale(0.7); }
  100% { opacity: 1; transform: translateX(-50%) scale(1); }
}
.shout__meme {
  width: 74px;
  height: 74px;
  flex: none;
  object-fit: contain;
}
.shout__pic {
  width: 54px;
  height: 54px;
  flex: none;
  border-radius: 50%;
  object-fit: cover;
  background: #1a2338;
  display: grid;
  place-items: center;
  font-size: 24px;
  font-weight: 900;
}
.shout__body { display: grid; gap: 1px; min-width: 0; }
.shout__who { font-size: 25px; font-weight: 900; color: var(--gold); }
.shout__msg {
  font-size: 24px;
  font-weight: 700;
  color: #eaf2ff;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 700px;
}

/* Top-3 names scrolling under the winner card */
.ko__marquee {
  margin-top: 18px;
  width: 900px;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
}
.ko__track {
  display: inline-flex;
  gap: 46px;
  white-space: nowrap;
  font-size: 34px;
  font-weight: 800;
  color: #ffe9b0;
  animation: koScroll 9s linear infinite;
}
@keyframes koScroll {
  0% { transform: translateX(30%); }
  100% { transform: translateX(-100%); }
}
.is-lite .fan { animation: none; }

/* Ring girl steps forward for the winner call — bigger and centred */
.girl.is-big { transform: translateY(-30px) scale(1.42); }
.girl.is-big .girl__img { filter: drop-shadow(0 0 8px rgba(255,255,255,.55)) drop-shadow(0 16px 20px rgba(0,0,0,.8)); }
