/* css/duel.css — CHỈ ".wd-root". Không một selector top-level nào ngoài nó.
 *
 * BIẾN KHAI LẠI TRONG .wd-root, KHÔNG Ở :root. Khai ở :root là ghi đè theme của cả app cho
 * mọi trang khác — tools/test.mjs khẳng định điều này cho từng game.
 *
 * MÀU NỀN RIÊNG, và đó là một bất biến thiết kế chứ không phải sở thích ("nhìn màu nền là
 * biết đang ở game nào" — css/pets.css:6-9). Bảy màu đã có chỗ: #efe2c9, #221d29, #131a2b,
 * #14262b, #181425, #eaf4e2, #1a1522, #1b1512. Trò này lấy RỪNG SÂU #12241c — không game
 * nào đang ở dải lục tối, nên nó nhận ra được ngay từ ảnh chụp màn hình.
 *
 * MÀN HÌNH VẼ LẠI TOÀN KHỐI (innerHTML) ở #wdFoe và #wdHand, nên `transition` trên đổi-trạng-
 * thái không tìm được khung đầu để chạy ở hai chỗ ấy. Ba phần tử SỐNG SÓT qua mọi lượt vẽ
 * (#wdHeroBar, #wdClockBar và băng #wdFlash) thì transition chạy thật — và đó là lý do thanh
 * đồng hồ nằm trong khung shell chứ không nằm trong chuỗi do screens.js sinh.
 */

.wd-root {
  --bg: #12241c;
  --panel: #17301f;
  --panel2: #1e3d29;
  --ink: #ecf4ea;
  --dim: #8fae97;
  --line: #2c5138;
  --accent: #f2b544;
  --accent-d: #d0972f;
  --danger: #e8615f;
  --good: #6fce89;
  --r-sm: 8px;
  --r-md: 12px;
  --r-lg: 16px;
  --fs-1: 11px;
  --fs-2: 13px;
  --fs-3: 15px;
  --fs-4: 19px;

  /* Tràn viền: huỷ padding của .view (18px trên, 16px hai bên, 64px dưới). Giống hệt sáu
     game kia — .view là khung của trang học, không phải khung của một cái sân. */
  margin: -18px -16px -64px;
  background: var(--bg);
  color: var(--ink);
  -webkit-tap-highlight-color: transparent;
  overscroll-behavior: contain;
}

.wd-root * { box-sizing: border-box; }

.wd-root #wdApp {
  display: flex;
  flex-direction: column;
  height: calc(100vh - 60px);          /* Safari cũ: dvh chưa có */
  height: calc(100dvh - 60px);
  min-height: 440px;
  overflow: hidden;
  padding-left: env(safe-area-inset-left);
  padding-right: env(safe-area-inset-right);
}

/* ---- thanh trên ---- */
.wd-root #wdTop {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  padding-top: calc(10px + env(safe-area-inset-top));
  border-bottom: 1px solid var(--line);
  background: var(--panel);
}
.wd-root .wd-turn { font-size: var(--fs-2); color: var(--dim); }
.wd-root .wd-turn b { color: var(--ink); font-size: var(--fs-3); }
.wd-root .wd-hero-hp {
  position: relative;
  flex: 1 1 auto;
  height: 18px;
  border-radius: 999px;
  background: var(--panel2);
  overflow: hidden;
}
.wd-root .wd-hero-hp i {
  display: block;
  height: 100%;
  width: 100%;
  background: linear-gradient(90deg, #56b96f, #8fe0a4);
  transition: width .28s ease;
}
.wd-root .wd-hero-hp span {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: var(--fs-1);
  font-weight: 800;
  color: #0d1c14;
  /* VIỀN SÁNG quanh chữ tối. Con số đứng YÊN giữa thanh trong khi thanh thì rút ngắn dần,
     nên đúng lúc máu thấp — lúc con số quan trọng nhất — nó nằm trên nền tối var(--panel2)
     và tương phản rơi xuống 1,47:1. Không đổi màu chữ được (nền kia lại sáng), nên trả
     tương phản bằng một quầng sáng: đọc được trên cả nền xanh lẫn nền tối. */
  text-shadow: 0 0 3px rgba(255, 255, 255, .95), 0 0 5px rgba(255, 255, 255, .7);
}
.wd-root .wd-tbtn {
  flex: 0 0 auto;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: var(--panel2);
  color: var(--ink);
  font-weight: 800;
  cursor: pointer;
}
.wd-root .wd-tbtn:active { transform: translateY(1px); }
/* NỚI VÙNG CHẠM RA 44px MÀ KHÔNG NỚI HÌNH TRÒN. Nút vẽ 34px cho vừa thanh trên ở khổ thấp
   (cả bố cục đã được đo ở 375x550), nhưng 34px là dưới mức ngón tay chạm trúng. Lớp giả
   này to ra mà không chiếm chỗ, nên không đẩy #wdStage bé lại. */
.wd-root .wd-tbtn { position: relative; }
.wd-root .wd-tbtn::after {
  content: "";
  position: absolute;
  inset: -5px;
  border-radius: 50%;
}

/* ---- sân ---- */
.wd-root #wdStage {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 12px;
  min-height: 0;
  /* Sprite 180px + thanh máu + thẻ khiên có thể CAO HƠN sân ở khổ thấp; flex căn giữa sẽ
     cho nội dung tràn ra CẢ HAI ĐẦU — tức sprite đè lên thanh máu ở đầu màn. Cắt tại đây:
     mất đỉnh mũ của sprite còn hơn mất thanh máu. Đo được ở khổ xem trước 375×812 khi thanh
     điều khiển ăn bớt chiều cao. */
  overflow: hidden;
}
.wd-root .wd-foe { width: 100%; max-width: 420px; text-align: center; }
.wd-root .wd-foe-art { font-size: 64px; line-height: 1; }
.wd-root .wd-foe-bar {
  position: relative;
  height: 22px;
  margin-top: 8px;
  border-radius: 999px;
  background: var(--panel2);
  border: 1px solid var(--line);
  overflow: hidden;
}
.wd-root .wd-foe-bar i { display: block; height: 100%; background: linear-gradient(90deg, #c2453f, #e8615f); }
.wd-root .wd-foe-bar span {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: var(--fs-1);
  font-weight: 800;
  /* Cùng lý do như thanh máu của mình, ngược chiều: chữ sáng trôi từ nền đỏ sang nền tối. */
  text-shadow: 0 1px 3px rgba(0, 0, 0, .8);
}
.wd-root .wd-shield {
  margin-top: 8px;
  padding: 6px 10px;
  border-radius: var(--r-md);
  background: rgba(242, 181, 68, .12);
  border: 1px solid var(--accent-d);
}
.wd-root .wd-shield b { display: block; font-size: var(--fs-2); color: var(--accent); }
.wd-root .wd-shield small { font-size: var(--fs-1); color: var(--dim); }

/* CẮT Ở KHỐI NHÂN VẬT, KHÔNG CẮT Ở BĂNG PHẢN HỒI. #wdStage cắt tràn (xem trên), và trong
   một hộp flex căn giữa thì thứ bị cắt là hai đầu — băng phản hồi nằm ở đáy, nên ở khổ thấp
   chính nó biến mất. Mà nó là chỗ DUY NHẤT nói ra kết quả một lượt: khiên chặn, hết giờ,
   sát thương chiêu cuối. Cho khối nhân vật tự co lại và tự cắt, còn băng chữ thì không co. */
.wd-root #wdFoe {
  flex: 0 1 auto;
  min-height: 0;
  overflow: hidden;
}
.wd-root .wd-flash {
  flex: 0 0 auto;
  min-height: 24px;
  font-size: var(--fs-3);
  font-weight: 800;
  text-align: center;
  padding: 0 12px;
  transition: color .2s ease;
}
.wd-root .wd-flash.good { color: var(--good); }
.wd-root .wd-flash.bad { color: var(--danger); }

/* ---- đồng hồ ---- */
.wd-root .wd-clock { height: 6px; background: var(--panel2); }
.wd-root .wd-clock i {
  display: block;
  height: 100%;
  width: 100%;
  background: linear-gradient(90deg, var(--accent-d), var(--accent));
  transition: width .1s linear;
}

/* ---- bàn tay ---- */
.wd-root .wd-hand {
  flex: 0 0 auto;
  padding: 12px;
  padding-bottom: calc(12px + env(safe-area-inset-bottom));
  background: var(--panel);
  border-top: 1px solid var(--line);
}
.wd-root .wd-hand h4 {
  margin: 0 0 8px;
  font-size: var(--fs-1);
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--dim);
}
.wd-root .wd-cards { display: grid; gap: 8px; }
.wd-root .wd-card {
  display: block;
  width: 100%;
  text-align: left;
  padding: 10px 12px;
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: var(--panel2);
  color: var(--ink);
  cursor: pointer;
}
.wd-root .wd-card:active { transform: translateY(1px); }
.wd-root .wd-card.wd-fit { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent) inset; }
.wd-root .wd-topic {
  display: inline-block;
  font-size: var(--fs-1);
  font-weight: 800;
  color: var(--accent);
  text-transform: uppercase;
  letter-spacing: .04em;
}
.wd-root .wd-stem { display: block; font-size: var(--fs-3); margin-top: 2px; }
.wd-root .wd-subject { display: block; font-size: var(--fs-1); color: var(--dim); margin-top: 2px; }
.wd-root .wd-blank {
  display: inline-block;
  width: 54px;
  height: 2px;
  vertical-align: middle;
  margin: 0 4px;
  background: var(--accent);
}
.wd-root .wd-q { padding: 0 2px 6px; }
.wd-root .wd-hintvi { margin: 0 0 10px; font-size: var(--fs-2); color: var(--dim); }
.wd-root .wd-hintvi b { color: var(--ink); }
.wd-root .wd-opts { display: grid; gap: 8px; }
.wd-root .wd-opt {
  padding: 12px;
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: var(--panel2);
  color: var(--ink);
  font-size: var(--fs-3);
  font-weight: 700;
  cursor: pointer;
}
.wd-root .wd-opt:active { transform: translateY(1px); }

/* ---- bảng kết quả + SỐ ĐO (lý do P0 tồn tại) ---- */
/* z-index CAO NHẤT trong ba lớp phủ (chiêu cuối 45, màn nhân vật 44). Trận kết thúc được
   trong lúc một lớp phủ khác đang mở — sát thương chiêu cuối rơi về muộn là đúng ca ấy — và
   khi đó bảng kết quả nằm DƯỚI thì học sinh nhìn thấy một màn hình không có lối ra. */
.wd-root #wdOverWrap {
  position: fixed;
  inset: 0;
  z-index: 46;
  display: grid;
  place-items: center;
  padding: 16px;
  background: rgba(6, 16, 11, .72);
}
.wd-root #wdOver {
  width: 100%;
  max-width: 380px;
  padding: 16px;
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  background: var(--panel);
  /* dvh SAU vh, không thay nó: Safari cũ bỏ qua dòng dvh và vẫn còn dòng vh để dùng. Thiếu
     dvh thì trên iOS lúc thanh địa chỉ đang nở, 86vh đo theo khung TO NHẤT ⇒ hộp cao hơn
     màn hình và nút ở đáy nằm ngoài vùng chạm được. */
  max-height: 86vh;
  max-height: 86dvh;
  overflow: auto;
}
/* CHỮ NGHỆ THUẬT của bảng cuối trận (P7). Món rẻ nhất trong cả đợt tham chiếu hình thức và
   đổi cảm giác nhiều nhất: game kia cho chữ "Thắng" chiếm nửa màn với hào quang, còn ở đây
   nó từng là một dòng 26px trông y hệt mọi dòng khác.
   MÀU ĐẶT TRƯỚC, gradient đặt sau: `background-clip: text` không chạy trên vài trình duyệt
   cũ (đúng nhóm máy của app này), và khi nó không chạy thì `color` bên dưới vẫn cho ra một
   dòng chữ đọc được thay vì một khoảng trống. */
.wd-root .wd-over-t {
  margin: 0 0 6px;
  font-size: clamp(38px, 12vw, 52px);
  line-height: 1.05;
  letter-spacing: -.02em;
  text-align: center;
  font-weight: 800;
}
.wd-root .wd-win {
  color: var(--accent);
  background-image: linear-gradient(180deg, #ffe6a8, var(--accent) 55%, var(--accent-d));
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  filter: drop-shadow(0 0 18px rgba(242, 181, 68, .45));
}
.wd-root .wd-lose { color: var(--danger); filter: drop-shadow(0 0 14px rgba(232, 97, 95, .35)); }
.wd-root .wd-measure {
  margin: 12px 0 6px;
  font-size: var(--fs-1);
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--dim);
}
.wd-root .wd-stat {
  padding: 8px 10px;
  margin-bottom: 8px;
  border-radius: var(--r-md);
  background: var(--panel2);
}
.wd-root .wd-stat-h { font-size: var(--fs-1); color: var(--dim); }
.wd-root .wd-stat-big { font-size: var(--fs-4); font-weight: 800; }
.wd-root .wd-stat-big.bad { color: var(--danger); }
.wd-root .wd-stat-sub { font-size: var(--fs-1); color: var(--dim); }
.wd-root .wd-verdict { margin: 4px 0 12px; font-size: var(--fs-2); font-weight: 700; }
.wd-root .wd-verdict.ok { color: var(--good); }
.wd-root .wd-verdict.bad { color: var(--danger); }
.wd-root .wd-over-btns { display: grid; gap: 8px; }
.wd-root .wd-btn {
  padding: 11px;
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: var(--panel2);
  color: var(--ink);
  font-weight: 700;
  cursor: pointer;
}
.wd-root .wd-btn-main { background: var(--accent); border-color: var(--accent-d); color: #21180a; }
.wd-root .wd-btn:active { transform: translateY(1px); }

/* ---- P1: màn nói ---- */
.wd-root .wd-mic {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  margin-bottom: 8px;
  border-radius: var(--r-md);
  background: var(--panel2);
  border: 1px solid var(--line);
  font-size: var(--fs-2);
  color: var(--dim);
}
.wd-root .wd-mic-dot {
  flex: 0 0 auto;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--dim);
}
/* Chấm đỏ nhấp nháy CHỈ khi máy đang thật sự nghe. Một chấm đứng yên lúc micro đã chết là
   lời nói dối mà học sinh chỉ phát hiện sau khi mất trắng một lượt. */
.wd-root .wd-mic.live { border-color: var(--accent-d); color: var(--ink); }
.wd-root .wd-mic.live .wd-mic-dot { background: var(--danger); animation: wd-pulse 1.1s ease-in-out infinite; }
@keyframes wd-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }
.wd-root .wd-heard {
  margin: 0 0 10px;
  min-height: 34px;
  padding: 7px 10px;
  border-radius: var(--r-md);
  background: rgba(0, 0, 0, .18);
  font-size: var(--fs-2);
  color: var(--dim);
}
.wd-root .wd-heard b { color: var(--ink); }
.wd-root .wd-heard span { color: var(--accent); }
.wd-root .wd-tap-instead { width: 100%; font-size: var(--fs-2); font-weight: 600; }

/* ---- P3: nộ khí + chiêu cuối ---- */
.wd-root .wd-rage {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 8px;
  font-size: var(--fs-1);
  color: var(--dim);
}
.wd-root .wd-rage.done { justify-content: center; }
.wd-root .wd-rage-pips { display: flex; gap: 5px; }
.wd-root .wd-rage-pips i {
  width: 22px;
  height: 5px;
  border-radius: 999px;
  background: var(--panel2);
  border: 1px solid var(--line);
}
.wd-root .wd-rage-pips i.on { background: var(--accent); border-color: var(--accent-d); }
.wd-root .wd-ult-btn {
  display: block;
  width: 100%;
  margin-bottom: 10px;
  padding: 11px;
  border-radius: var(--r-md);
  border: 1px solid var(--accent-d);
  background: linear-gradient(180deg, var(--accent), var(--accent-d));
  color: #21180a;
  font-size: var(--fs-3);
  font-weight: 800;
  cursor: pointer;
}
.wd-root .wd-ult-btn:active { transform: translateY(1px); }
.wd-root #wdUltWrap {
  position: fixed;
  inset: 0;
  z-index: 45;
  display: grid;
  place-items: center;
  padding: 16px;
  background: rgba(6, 16, 11, .8);
}
.wd-root #wdUlt {
  width: 100%;
  max-width: 380px;
  padding: 16px;
  border-radius: var(--r-lg);
  border: 1px solid var(--accent-d);
  background: var(--panel);
  max-height: 86vh;
  max-height: 86dvh;
  overflow: auto;
}
.wd-root .wd-ult-t { margin: 0 0 10px; font-size: 22px; color: var(--accent); }
.wd-root .wd-ult-q { margin: 0 0 8px; font-size: var(--fs-4); line-height: 1.35; }
.wd-root .wd-ult-note { margin: 0 0 12px; font-size: var(--fs-1); color: var(--dim); }

/* ---- P1: nhật ký nhận giọng (trong bảng cuối trận) ---- */
.wd-root .wd-vnote { margin: 0 0 6px; font-size: var(--fs-1); color: var(--dim); }
.wd-root .wd-vlog { list-style: none; margin: 0 0 12px; padding: 0; }
.wd-root .wd-vrow {
  display: grid;
  gap: 1px;
  padding: 6px 8px;
  margin-bottom: 5px;
  border-radius: var(--r-sm);
  background: var(--panel2);
  border-left: 3px solid var(--dim);
  font-size: var(--fs-1);
}
.wd-root .wd-vrow b { color: var(--accent); }
.wd-root .wd-vrow span { color: var(--ink); }
.wd-root .wd-vrow i { color: var(--dim); font-style: normal; }
.wd-root .wd-v-perfect { border-left-color: var(--good); }
.wd-root .wd-v-hit { border-left-color: var(--accent); }
.wd-root .wd-v-miss { border-left-color: var(--danger); }

/* ---- P6: sprite từ atlas ----
   Khung chạy bằng JS (engine đặt `--f` mỗi nhịp 100ms), KHÔNG bằng steps() của CSS: Safari
   không nhận var() bên trong steps(), mà số khung thì mỗi động tác một khác. Ở đây CSS chỉ
   còn việc dịch nền theo hai biến — phép tính ấy thì mọi trình duyệt đều làm được.

   image-rendering KHÔNG đặt pixelated: art của trò này là cel-shading thu nhỏ từ video, chứ
   không phải pixel art như My Room — làm sắc cạnh nó là làm lộ răng cưa của khâu thu ảnh. */
.wd-root .wd-sp {
  display: block;
  width: var(--w);
  height: var(--h);
  background-repeat: no-repeat;
  background-position: calc(var(--f, 0) * var(--w) * -1) calc(var(--row, 0) * var(--h) * -1);
}
/* `overflow: hidden` KHÔNG phải để cho gọn: sprite cao 180px, mà #wdStage co lại theo khổ
   máy (nó là ô flex duy nhất được giãn). Ở khổ thấp — máy nhỏ, hoặc trang xem trước có thêm
   thanh điều khiển — hàng nhân vật tràn NGƯỢC LÊN và đè vào thanh máu ở đầu màn. Đo được
   trên trang xem trước ở 565×665. */
.wd-root .wd-stage-row {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: 12px;
  min-height: 96px;
  max-height: 100%;
  overflow: hidden;
}
/* Nhân vật của mình QUAY MẶT SANG PHẢI, về phía trùm. Clip được sinh ở tư thế nhìn thẳng
   nên lật bằng CSS rẻ hơn nhiều so với sinh thêm một bộ art quay ngược. */
.wd-root .wd-me .wd-sp { transform: scaleX(-1); }
/* Trùm NHỈNH HƠN 12%. Atlas co mọi hàng về cùng 180px nên tương quan cỡ giữa các nhân vật
   bị xoá sạch — một con quỷ khổng lồ cao đúng bằng cô phù thuỷ nhí. Trả lại bằng CSS chứ
   không đổi cỡ ô: đổi ô là mỗi hàng một cỡ và CSS phải biết cỡ của từng hàng. */
.wd-root .wd-foe-art .wd-sp { transform: scale(1.12); transform-origin: bottom center; }

/* ---- P5: màn nhân vật ---- */
.wd-root #wdHeroWrap {
  position: fixed;
  inset: 0;
  z-index: 44;
  display: grid;
  place-items: center;
  padding: 16px;
  background: rgba(6, 16, 11, .8);
}
.wd-root #wdHeroBox {
  width: 100%;
  max-width: 380px;
  padding: 16px;
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  background: var(--panel);
  max-height: 88vh;
  max-height: 88dvh;
  overflow: auto;
}
.wd-root .wd-hero-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; }
.wd-root .wd-hero-name { display: block; font-size: var(--fs-4); }
.wd-root .wd-role {
  display: inline-block;
  margin-top: 2px;
  padding: 1px 8px;
  border-radius: 999px;
  background: rgba(242, 181, 68, .14);
  border: 1px solid var(--accent-d);
  color: var(--accent);
  font-size: var(--fs-1);
  font-weight: 700;
}
/* CON SỐ LỚN NHẤT TRÊN MÀN HÌNH. Nó là "Điểm thuộc" — tổng số hộp đã leo trong lịch ôn tập,
   nên nó có nguồn thật; đó là điều kiện để nó được phép to như thế này. */
.wd-root .wd-power {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin: 12px 0 2px;
  padding: 10px 12px;
  border-radius: var(--r-md);
  background: var(--panel2);
  border: 1px solid var(--line);
}
.wd-root .wd-power span { font-size: var(--fs-1); color: var(--dim); text-transform: uppercase; letter-spacing: .06em; }
.wd-root .wd-power b { font-size: 30px; color: var(--accent); }
.wd-root .wd-hero-sub { font-size: var(--fs-1); color: var(--dim); margin-bottom: 8px; }
.wd-root .wd-lvbar { height: 6px; border-radius: 999px; background: var(--panel2); overflow: hidden; margin-bottom: 4px; }
.wd-root .wd-lvbar i { display: block; height: 100%; background: var(--accent); }
.wd-root .wd-tiers { list-style: none; margin: 10px 0 6px; padding: 0; }
.wd-root .wd-tier {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 7px 10px;
  margin-bottom: 5px;
  border-radius: var(--r-sm);
  background: var(--panel2);
  border-left: 3px solid var(--line);
  font-size: var(--fs-2);
  color: var(--dim);
}
.wd-root .wd-tier.on { border-left-color: var(--good); color: var(--ink); }
.wd-root .wd-tier b { flex: 0 0 auto; }
.wd-root .wd-tier span { flex: 1 1 auto; font-size: var(--fs-1); }
.wd-root .wd-tier i { flex: 0 0 auto; font-style: normal; font-weight: 700; }
.wd-root .wd-ba { width: 100%; border-collapse: collapse; font-size: var(--fs-2); margin-bottom: 10px; }
.wd-root .wd-ba th, .wd-root .wd-ba td { padding: 6px 8px; text-align: left; border-bottom: 1px solid var(--line); }
.wd-root .wd-ba thead th { font-size: var(--fs-1); color: var(--dim); font-weight: 600; }
.wd-root .wd-ba tbody th { font-weight: 600; color: var(--dim); }
/* Vế "sau" bật màu tốt — đó là toàn bộ việc của bảng này: nói ra lên cấp được gì. */
.wd-root .wd-ba td.to { color: var(--good); font-weight: 700; }
.wd-root .wd-goals { list-style: none; margin: 0 0 10px; padding: 0; }
.wd-root .wd-goal {
  padding: 7px 10px;
  margin-bottom: 5px;
  border-radius: var(--r-sm);
  background: var(--panel2);
  border-left: 3px solid var(--accent);
  font-size: var(--fs-2);
}
.wd-root .wd-goal.done { border-left-color: var(--good); color: var(--dim); }
.wd-root .wd-klass { margin-bottom: 8px; }

/* ---- body.s8-imm: toàn màn hình (xem css/ispeak.css) --------------------------------
   MỌI luật nằm trong @media, và KHÔNG phải vì khổ máy: bài kiểm phạm vi hoá của trò này đòi
   mọi selector TOP-LEVEL bắt đầu bằng .wd-root, nên một dòng `body…` không thụt lề là đỏ
   ngay. Nằm trong @media thì nó không còn là top-level nữa — đúng mẹo mà css/pets.css:563-583
   đã dùng.
   KHÔNG bù safe-area-inset-top ở đây: #wdTop đã tự cộng rồi, bù thêm là chừa chỗ cho HAI cái
   tai thỏ. 56px = 48px nút #immExit + 8px lề; con số gốc ở css/ispeak.css, khối .s8-imm-exit. */
@media (max-width: 719px) {
  body.s8-play.s8-imm .wd-root #wdApp {
    height: calc(100vh - 124px);
    height: calc(100dvh - env(safe-area-inset-top) - env(safe-area-inset-bottom));
  }
  body.s8-play.s8-imm .wd-root #wdTop { padding-right: 56px; }
}
@media (min-width: 720px) {
  body.s8-play.s8-imm .wd-root #wdApp {
    height: calc(100vh - 60px);
    height: calc(100dvh - env(safe-area-inset-top) - env(safe-area-inset-bottom));
  }
  body.s8-play.s8-imm .wd-root #wdTop { padding-right: 56px; }
  .wd-root .wd-cards { grid-template-columns: repeat(3, 1fr); }
}

/* ══════════════════════════════════════════════════════════════════════════════════════
   MY DUEL v2 — lớp phủ DOM của bản Phaser (`.wdr-*`).
   NỐI CUỐI FILE theo lệ của kho: cùng độ cụ thể thì THỨ TỰ NGUỒN quyết định, nên luật mới
   phải nằm sau luật cũ. Tiền tố `wdr` (không phải `wd`) để hai bản — DOM và Phaser — sống
   cạnh nhau mà không luật nào với sang bản kia; bản DOM còn là đường lui.

   Chữ tiếng Việt nằm ở ĐÂY chứ không trong Phaser: nó phải chọn được, phải đúng dấu, phải
   co theo cỡ chữ của app, và trình đọc màn hình phải thấy được nó. Canvas thì không. */
.wdr-root { display: flex; flex-direction: column; min-height: 0; }
.wdr-stage {
  position: relative; width: 100%; aspect-ratio: 16 / 10;
  background: #0d1a14; border-radius: 12px; overflow: hidden;
  /* KHÔNG khai `touch-action` ở đây. Nó lan qua ranh giới iframe và giết cuộn bên trong
     game — bài học M7 của room3d, xem css/room3d.css. `overscroll-behavior` thì an toàn và
     là thứ thật sự cần: nó chặn kéo-để-tải-lại khi ngón tay trượt trong sân đấu. */
  overscroll-behavior: none;
}
.wdr-stage > iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; display: block; }

.wdr-ask {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 3;
  padding: 10px 12px calc(12px + env(safe-area-inset-bottom));
  background: linear-gradient(to top, rgba(8, 20, 15, .96) 68%, rgba(8, 20, 15, 0));
  color: #e8f5ee;
}
.wdr-ask[hidden] { display: none; }
.wdr-tag { font-size: 11px; letter-spacing: 1px; color: #7fbf9c; font-weight: 700; }
.wdr-stem { font-size: 17px; line-height: 1.45; margin: 3px 0 2px; }
.wdr-blank { display: inline-block; min-width: 62px; color: #ffc857; letter-spacing: 2px; }
.wdr-hint { font-size: 13px; color: #9fd6b8; }
.wdr-heard { font-size: 13px; color: #cfe8db; min-height: 18px; margin-top: 3px; }
/* Ba mức nói đọc được bằng MÀU, không chỉ bằng chữ: học sinh đang nói thì không kịp đọc. */
.wdr-heard[data-grade="hit"] { color: #ffd166; }
.wdr-heard[data-grade="perfect"] { color: #4ade80; font-weight: 600; }
.wdr-clock { height: 4px; background: #16302a; border-radius: 3px; overflow: hidden; margin: 7px 0; }
.wdr-clock > i { display: block; height: 100%; width: 100%; background: #ffc857; transition: width .1s linear; }
.wdr-taplb { font-size: 12px; color: #8fb9a3; margin-bottom: 5px; }
.wdr-tapwrap { display: flex; gap: 6px; flex-wrap: wrap; }
.wdr-tapwrap .wdr-taplb { flex: 0 0 100%; }
.wdr-tapbtn {
  font: inherit; font-size: 14px; padding: 9px 13px; border-radius: 9px;
  border: 1px solid #6b5b3f; background: #3d3320; color: #f0e6d2; cursor: pointer;
  flex: 1 1 auto; min-height: 40px;   /* 40px: ngón tay trên điện thoại cũ */
}
.wdr-tapbtn:hover { background: #4d4028; }
.wdr-note { font-size: 12px; color: #ef8fa4; min-height: 16px; margin-top: 5px; }

/* Băng trạng thái lúc dựng khung, và là chỗ đặt ĐƯỜNG LUI khi khung không dựng được. */
.wdr-boot {
  position: absolute; inset: 0; z-index: 4; display: grid; place-content: center;
  text-align: center; gap: 10px; padding: 16px;
  font-size: 14px; color: #9fd6b8; background: #0d1a14;
}
.wdr-boot[hidden] { display: none; }
.wdr-boot-hong { color: #ef8fa4; }

.wdr-over {
  position: absolute; inset: 0; z-index: 6; display: grid; place-items: center;
  background: rgba(8, 18, 14, .74); pointer-events: none;
}
.wdr-over[hidden] { display: none; }
/* Nền mờ KHÔNG nhận cú chạm (pointer-events: none ở trên) để không nuốt thao tác rơi ra
   ngoài; hộp trong bật lại, nếu không thì hai cái nút dưới đây bấm không được. */
.wdr-overbox { display: grid; gap: 14px; justify-items: center; pointer-events: auto; }
/* clamp chứ không phải một con số: "THẮNG" ở 46px tràn khỏi khổ 320px. */
.wdr-overttl { font-size: clamp(34px, 11vw, 46px); font-weight: 800; letter-spacing: 3px; }
/* `color` khai THẲNG, không qua background-clip:text — hiệu ứng ấy hỏng trên một phần trình
   duyệt của app này và để lại một khoảng trống đúng chỗ đáng lẽ là chữ "THẮNG". */
.wdr-win { color: #ffd166; }
.wdr-lose { color: #ef476f; }
.wdr-overbtns { display: flex; gap: 8px; flex-wrap: wrap; justify-content: center; }
.wdr-obtn {
  font: inherit; font-size: 15px; font-weight: 600; padding: 11px 18px; border-radius: 10px;
  border: 1px solid #4f8a68; background: #1f4030; color: #e8f5ee; cursor: pointer;
  min-height: 44px; text-decoration: none; display: inline-flex; align-items: center;
}
.wdr-obtn:hover { background: #2b543f; }

@media (max-width: 520px) {
  .wdr-stage { aspect-ratio: 4 / 3; }
  .wdr-stem { font-size: 15px; }
}

/* ---- body.s8-imm cho bản Phaser: sân ăn hết chiều cao, không còn tỉ lệ cố định ----------
   Nằm TRONG @media đúng mẹo của khối .wd-root ở trên: bài kiểm phạm vi hoá chỉ soi selector
   ở độ sâu 0, nên một dòng `body…` không thụt vào trong một @media là đỏ ngay.
   Cùng hai con số (124px / 60px) với bản DOM — chúng đo cùng một thanh trên. */
@media (max-width: 719px) {
  body.s8-play.s8-imm .wdr-root .wdr-stage {
    height: calc(100vh - 124px);
    height: calc(100dvh - env(safe-area-inset-top) - env(safe-area-inset-bottom));
    aspect-ratio: auto; border-radius: 0;
  }
}
@media (min-width: 720px) {
  body.s8-play.s8-imm .wdr-root .wdr-stage {
    height: calc(100vh - 60px);
    height: calc(100dvh - env(safe-area-inset-top) - env(safe-area-inset-bottom));
    aspect-ratio: auto;
  }
}
