/* Khung dọc kiểu điện thoại; trên máy tính sẽ nằm giữa màn hình. Cỡ chữ theo cqw (chiều rộng khung). */
/* v0.9.35 (người chơi: "Bạn lấy font chữ theo ảnh gemini gen (ảnh mình đã cung cấp trong folder asset). Và đồng bộ lại trên tất cả màn hình UI"): mọi chữ và số trong game, cả heading, dùng 'Crystal UI' = Fredoka (css/font.css), cùng kiểu chữ trong ảnh mẫu.
 * Chỉ bảng công cụ tiếng Việt dùng font khác (--font-head): Fredoka không có đủ dấu tiếng Việt. */
:root {
  --font-game: 'Crystal UI', 'Segoe UI', system-ui, -apple-system, Roboto, Arial, sans-serif;
  --font-head: 'Segoe UI', system-ui, -apple-system, Roboto, Arial, sans-serif;
}
html,
body {
  margin: 0;
  height: 100%;
  overflow: hidden;
  background: radial-gradient(circle at 50% 30%, #3b3170, #15122a 75%);
  font-family: var(--font-game);
  font-weight: 600;
  color: #fff;
  user-select: none;
  -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
  /* v0.9.15 điện thoại: không kéo-để-tải-lại / nảy trang (Chrome Android, Safari), không hiện menu khi giữ lâu (iOS) */
  overscroll-behavior: none;
  -webkit-touch-callout: none;
}

/* Kích thước/vị trí đặt bằng JS (js/screen-fit.js) theo window.innerWidth/innerHeight — ổn định hơn vh trên iOS.
 * v0.9.13: mặc định CSS = khung dọc căn giữa như screen-fit, để khung hình đầu tiên (trước khi JS chạy) đã đúng (v0.9.15: 9:16). */
#app {
  position: absolute;
  top: 0;
  left: calc((100% - min(100%, 56.25vh)) / 2);
  width: min(100%, 56.25vh);
  height: 100%;
  overflow: hidden;
  overflow: clip; /* v0.9.20: cắt, không phải khung cuộn — lệnh cuộn nào cũng không dời được cả khung game (js/ui.js › showLevels) */
  /* v0.9.16: nền bàn gỗ (.bg-layer ngay dưới); ở đây chỉ còn màu mặt gỗ cho lúc ảnh chưa tải xong.
   * (Trước: gradient xám tím #46446a → #35345a — v0.9.2, người chơi: "làm sáng phần background lên đủ để rõ bóng của xe".) */
  background: #fcc290;
  /* v0.9.48 đơn vị theo khung game: --cw, --ch = 1% bề ngang, chiều cao #app (js/screen-fit.js đặt), thay cqw, cqh: WebView Chrome 80 chưa có container query (luật của Horus SDK) */
  box-shadow: 0 0 60px rgba(0, 0, 0, 0.5);
  /* v0.9.21 mặt bàn (.bg-layer): cao / rộng 3 phần ảnh (tools/build-gameplay-bg.ps1 in ra), --desk-n = số lần lặp gỗ, js/queue-view.js đặt theo hàng xe dài nhất.
   * v0.9.25: --desk-lip = chỗ mép trên khung tranh trên ảnh (tỉ lệ bề ngang), --desk-y = mặt bàn kéo lên cho khớp chỗ đó (QueueView.fitDesk). */
  --desk-top: 1.088435;
  --desk-tile: 0.362812;
  --desk-end: 0.435374;
  --desk-lip: 0.229373;
  --desk-n: 4;
  --desk-y: 0px;
  --desk-w: calc(100 * var(--cw));
  --desk-h: calc(var(--desk-w) * (var(--desk-top) + var(--desk-n) * var(--desk-tile) + var(--desk-end)));
}

/* v0.9.21 (người chơi: "mình đưa bạn ảnh background mới, có phần ảnh dưới dài trên xếp xe lên luôn (tưởng tượng như bạn xếp tất cả game lên bối cảnh 1 cái bàn)"): cả game nằm trên MỘT
 * mặt bàn, camera lia tới đâu mặt bàn chạy theo tới đó (js/queue-view.js dời .bg-layer đúng bằng camera). Ảnh gốc chỉ cao ~2 lần bề ngang nên cắt 3 phần (tools/build-gameplay-bg.ps1):
 * desk-top (đồ trên bàn + vệt nắng), desk-wood (gỗ, lặp --desk-n lần), desk-end (đồ cuối bàn, nằm ngay sau hàng xe cuối). Ảnh rộng đúng bề ngang màn hình, neo mép trên (v0.9.25 kéo lên --desk-y).
 * Trình duyệt máy tính: rộng đúng khung game. Điện thoại (body.framed): phủ cả màn hình — vùng an toàn, 2 dải hai bên khung.
 * Khó / Siêu khó: nhân thêm một lớp màu (--bg-tint) để vẫn nhận ra màn khó, nền tối hơn màn thường.
 * Ba khung cắt cùng một mặt bàn: #bg sau canvas; #bg-strip trên canvas, chỉ cao tới mép trên thanh booster (21cqw, dời theo --ui-boost-y), mép trên mờ dần 4,8cqw — xe hàng sâu chui
 * xuống dưới thanh như trước; #bg-top (js/queue-view.js). Mọi lớp ảnh cùng cỡ, cùng vị trí trên màn hình nên trùng khít nhau; mặt nạ có lỗi thì cũng chỉ lộ mép dải, không che màn chơi.
 * (v0.9.16–0.9.20: một ảnh vuông assets/bg-desk.jpg phủ theo chiều cao, đứng yên.) */
.bg-layer {
  position: absolute;
  left: 0;
  right: 0;
  top: var(--desk-y);
  height: var(--desk-h);
  pointer-events: none;
  background-color: #fcc290;
  background-image: linear-gradient(var(--bg-tint, #fff), var(--bg-tint, #fff)), url('../assets/desk-top.jpg'), url('../assets/desk-end.jpg'), url('../assets/desk-wood.jpg');
  background-position: 0 0, 0 0, 0 100%, 0 calc(var(--desk-w) * var(--desk-top));
  background-size: 100% 100%, 100% auto, 100% auto, 100% auto;
  background-repeat: no-repeat, no-repeat, no-repeat, repeat-y;
  background-blend-mode: multiply, normal, normal, normal; /* chỉ lớp màu nhân lên ảnh; ảnh không nhân với background-color */
}
#bg {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  overflow: hidden;
  overflow: clip;
  pointer-events: none;
}
#bg-strip {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: calc(calc(21 * var(--cw)) - var(--ui-boost-y, 0) * calc(2 * var(--cw)));
  overflow: hidden;
  pointer-events: none;
  -webkit-mask-image: linear-gradient(transparent, #000 calc(4.8 * var(--cw)));
  mask-image: linear-gradient(transparent, #000 calc(4.8 * var(--cw)));
}
#bg-strip .bg-layer {
  top: auto;
  bottom: calc(calc(100 * var(--ch)) - var(--desk-h) - var(--desk-y));
}
/* v0.9.22 (người chơi: "bạn đánh nắng như ảnh cũ đi, vì mình tính độ sáng tối của ảnh cũ"): đáy màn chơi sau thanh booster tối dần như ngoài vùng nắng của ảnh bàn cũ; lớp này gắn với màn hình,
 * không nằm trên mặt bàn — camera lia xuống thì tắt, hàng xe vẫn trên gỗ sáng */
#bg-strip::after {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background: linear-gradient(rgba(150, 80, 50, 0.45), rgba(150, 80, 50, 0.8));
  transition: opacity 0.35s;
}
body.queue-view #bg-strip::after {
  opacity: 0;
}

#game {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: block;
  touch-action: none;
}

button {
  font: inherit;
  color: inherit;
  cursor: pointer;
  border: 0;
  touch-action: manipulation; /* v0.9.15: chạm nhanh 2 lần không phóng to trang (iOS) */
}

/* ---------- HUD (v0.7 màu theo hình mẫu; v0.8.8 bố cục theo wireframe người chơi gửi) ----------
 * MỘT hàng: coin + nút "+" góc trái trên · "LEVEL n" ở giữa · nút cài đặt góc phải trên (v0.9.11 đổi chỗ: nút cài đặt trái,
 * coin phải). Đáy HUD ~15,5cqw: tranh bắt đầu dưới mức này (HUD_FRAC trong js/render-core.js). */
#hud {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: calc(15.5 * var(--cw));
  pointer-events: none;
}
#hud > * {
  position: absolute;
  pointer-events: auto;
}
/* Nút cài đặt. v0.9.11 (người chơi: "đổi chỗ coin cho icon setting nhé, icon setting thay bằng asset này để màu tím giống
 * booster"): góc TRÁI trên (coin sang góc phải), mặt nút = ảnh nút tròn tím (assets/settings.png), bóng đổ như nút booster.
 * Trước: vuông bo tròn xanh hai tông + bánh răng trắng SVG, góc phải. */
.round {
  top: calc(2.4 * var(--cw));
  left: calc(3.6 * var(--cw));
  width: calc(10.6 * var(--cw));
  height: calc(10.6 * var(--cw));
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: none;
  display: flex;
  align-items: center;
  justify-content: center;
}
.round:active {
  transform: translateY(calc(0.4 * var(--cw)));
}
.round .gear {
  width: 100%;
  height: 100%;
  filter: drop-shadow(0 calc(0.9 * var(--cw)) 0 rgba(90, 24, 92, 0.35));
  pointer-events: none;
}
/* v0.9.9 bố cục chỉnh tay (công cụ "Sửa màn & hình" › 📐 Bố cục; Render.applyUi đặt biến trên #app): dời theo % khung game
 * (cqw / cqh), phóng quanh tâm. Không có biến = như cũ. Coin và thanh booster: xem các khối bên dưới.
 * v0.9.15 (khung theo từng máy — js/screen-fit.js): dời dọc theo % chiều cao khung CHUẨN 1:2 (= 2cqw: khung 1:2 y như trước, khung
 * tỉ lệ khác HUD vẫn đúng chỗ so với bề ngang) và không lên quá mép trên khung + --hud-room (máy mô phỏng iphone.html — không có
 * thanh trạng thái — được lên dải Dynamic Island như người chơi đã chỉnh; máy thật dừng cách mép vùng an toàn 4px).
 * Vùng chạm nút ≥ ~44pt (::after rộng hơn hình nút). */
#btn-menu {
  translate: calc(var(--ui-menu-x, 0) * calc(1 * var(--cw))) max(calc(var(--ui-menu-y, 0) * calc(2 * var(--cw))), calc(4px - calc(2.4 * var(--cw)) - var(--hud-room, 0px)));
  scale: var(--ui-menu-s, 1);
}
#btn-menu::after,
#coins::after {
  content: '';
  position: absolute;
  top: calc(-1.8 * var(--cw));
  right: calc(-1.8 * var(--cw));
  bottom: calc(-1.8 * var(--cw));
  left: calc(-1.8 * var(--cw));
}
/* v0.9.19: nút thu nhỏ trong 📐 Bố cục (người chơi đặt ×0,84) thì vùng chạm vẫn ≥ 44 px sau khi phóng (nút gốc 10,6cqw) */
#btn-menu::after {
  top: min(calc(-1.8 * var(--cw)), calc((calc(10.6 * var(--cw)) - 46px / var(--ui-menu-s, 1)) / 2));
  right: min(calc(-1.8 * var(--cw)), calc((calc(10.6 * var(--cw)) - 46px / var(--ui-menu-s, 1)) / 2));
  bottom: min(calc(-1.8 * var(--cw)), calc((calc(10.6 * var(--cw)) - 46px / var(--ui-menu-s, 1)) / 2));
  left: min(calc(-1.8 * var(--cw)), calc((calc(10.6 * var(--cw)) - 46px / var(--ui-menu-s, 1)) / 2));
}
/* Thanh coin góc PHẢI trên (v0.9.11 đổi chỗ với nút cài đặt). v0.9.35 (người chơi: "đồng bộ lại thanh asset coin ở home và thanh asset coin trong màn hình chơi nhé (để hết theo thanh ở home"): đúng thanh trong ảnh mẫu Home
 * (assets/home/coin-bar.png, tools/build-panels-ui.ps1: đồng coin + dấu + nằm sẵn trong ảnh), cùng cỡ, cùng chỗ ngang, cùng số với #hm-coins, --u = 1 điểm ảnh mẫu. (Trước: thanh trắng ngà CSS, coin + dấu + rời.) */
#coins {
  --u: calc(calc(100 * var(--cw)) / 1536);
  top: calc(3.78 * var(--cw));
  right: calc(2.86 * var(--cw));
  width: calc(392 * var(--u));
  height: calc(136 * var(--u));
  background: url('../assets/home/coin-bar.png') center / 100% 100% no-repeat;
  /* v0.9.9 bố cục chỉnh tay (v0.9.15 theo khung chuẩn, không lên quá mép trên — xem #btn-menu) */
  translate: calc(var(--ui-coin-x, 0) * calc(1 * var(--cw))) max(calc(var(--ui-coin-y, 0) * calc(2 * var(--cw))), calc(4px - calc(2.9 * var(--cw)) - var(--hud-room, 0px)));
  scale: var(--ui-coin-s, 1);
}
#coin-text {
  position: absolute;
  left: calc(130 * var(--u));
  top: calc(32 * var(--u));
  width: calc(148 * var(--u));
  height: calc(70 * var(--u));
  display: flex;
  align-items: center;
  justify-content: center;
  color: #46307e;
  font-size: calc(60 * var(--u));
  font-weight: 700;
  pointer-events: none;
}
#coin-text.long {
  font-size: calc(46 * var(--u));
}
/* Nút Level: viên thuốc xanh navy, viền vàng (sáng trên, cam dưới) + nét nâu sẫm ngoài cùng, chữ trắng viền xanh đen.
 * v0.8.8: nằm giữa hàng trên cùng (cùng hàng coin và nút cài đặt), chữ "LEVEL n" như wireframe.
 * v0.9.16 (người chơi: "UI build trên các máy đang có điểm chung là nút Level bị dính vào coin, bạn sắp xếp lại nhé"): nút ôm sát chữ —
 * trước nút rộng cố định 42% khung (lòng tối thiểu 30cqw + đệm, chữ chỉ ~23cqw), đè viên coin 3–5 px trên mọi máy; chữ 5,6 → 5,2cqw,
 * đệm 4,6 → 3cqw. Hàng trên trên máy thật: tâm nút cài đặt, Level, coin thẳng một đường (số 2,5 trong translate; coin 2,9).
 * v0.9.17: mép trái nút cố định (nút gốc rộng 30cqw, 35–65cqw): người chơi dời Level sang sát nút cài đặt (levelX −23), màn 3–4 chữ số
 * nút chỉ nới sang phải, không chạm nút cài đặt. */
#lvl {
  top: calc(3.7 * var(--cw));
  left: calc(35 * var(--cw));
  /* v0.9.9 bố cục chỉnh tay: phóng quanh tâm nút gốc, dời bằng translate */
  transform: scale(var(--ui-lvl-s, 1));
  transform-origin: calc(15 * var(--cw)) 50%;
  /* (v0.9.15 theo khung chuẩn, không lên quá mép trên — xem #btn-menu; nhãn HARD nhô 1,6cqw trên nút) */
  translate: calc(var(--ui-lvl-x, 0) * calc(1 * var(--cw))) max(calc(var(--ui-lvl-y, 0) * calc(2 * var(--cw))), calc(4px - calc(2.5 * var(--cw)) - var(--hud-room, 0px)));
  height: calc(8.2 * var(--cw));
  min-width: calc(22 * var(--cw));
  padding: 0 calc(3 * var(--cw));
  border-radius: calc(5.2 * var(--cw));
  border: calc(1 * var(--cw)) solid transparent;
  background: linear-gradient(#0a47a2, #0d51b2 30%) padding-box, linear-gradient(#fdd70a, #f6bd14 50%, #e7890f) border-box;
  box-shadow: inset 0 0 0 calc(0.3 * var(--cw)) #162254, 0 0 0 calc(0.3 * var(--cw)) #6b4a22, 0 calc(0.9 * var(--cw)) 0 calc(0.3 * var(--cw)) rgba(90, 24, 92, 0.35);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: calc(1.6 * var(--cw));
  white-space: nowrap;
  color: #fff;
  font-size: calc(4.8 * var(--cw)); /* v0.9.32: font chung rộng hơn: 5,2 → 4,8, nút giữ đúng bề ngang (tâm nút vẫn giữa khung ở bố cục gốc) */
  font-weight: 900;
  text-shadow: 0 calc(0.45 * var(--cw)) 0 #0b1f55, calc(0.3 * var(--cw)) 0 0 #0b1f55, calc(-0.3 * var(--cw)) 0 0 #0b1f55, 0 calc(-0.3 * var(--cw)) 0 #0b1f55,
    calc(0.22 * var(--cw)) calc(0.22 * var(--cw)) 0 #0b1f55, calc(-0.22 * var(--cw)) calc(0.22 * var(--cw)) 0 #0b1f55, calc(0.22 * var(--cw)) calc(-0.22 * var(--cw)) 0 #0b1f55, calc(-0.22 * var(--cw)) calc(-0.22 * var(--cw)) 0 #0b1f55;
}
/* v0.9.9 (chữ tiếng Anh): nhãn HARD / SUPER HARD gắn ở mép trên nút Level thay vì nằm cạnh chữ "LEVEL n" — nằm cạnh thì
 * "SUPER HARD" làm nút rộng 57% khung, đè lên ô coin (đo: chồng 26 px; "SIÊU KHÓ" cũ đã sát mép, chồng 16 px). */
.hard-badge {
  display: none;
  position: absolute;
  left: 50%;
  top: calc(-2.6 * var(--cw));
  transform: translateX(-50%);
  white-space: nowrap;
  line-height: 1.2;
  font-size: calc(2.6 * var(--cw));
  background: #c03cff;
  padding: calc(0.4 * var(--cw)) calc(1.4 * var(--cw));
  border-radius: calc(2 * var(--cw));
}
/* Màn Khó / Siêu khó: nền ngả tím (v0.9.16 nhân màu lên mặt bàn gỗ — xem .bg-layer), lòng nút Level tím / đỏ + nhãn KHÓ / SIÊU KHÓ.
 * v0.9.52 (người chơi: "super hard background bị ánh đỏ, muốn đổi sang effect background tối như màn hard thôi"): Siêu khó dùng chung nền của Khó (màn Siêu khó có cả 2 class). Trước: --bg-tint #f58f9f. */
body.hard {
  --bg-tint: #b9a2ff;
}
body.hard #lvl {
  background: linear-gradient(#6a22c8, #7b2fe0 30%) padding-box, linear-gradient(#fdd70a, #f6bd14 50%, #e7890f) border-box;
}
body.hard .hard-badge {
  display: inline-block;
}
body.super #lvl {
  background: linear-gradient(#a50f33, #c4123d 30%) padding-box, linear-gradient(#fdd70a, #f6bd14 50%, #e7890f) border-box;
}
body.super .hard-badge {
  background: #1d0a14;
}

/* ---------- Booster (v0.7, theo hình mẫu) ----------
 * Không còn thanh nền xanh: 4 nút nằm thẳng trên nền game, viền kem kẹp giữa hai nét sẫm như nút trong hình mẫu,
 * số lượt ở góc dưới phải. Dải đáy vẫn tô nền (mờ dần ở mép trên) để khối nằm sâu trong cột hàng đợi chui xuống dưới
 * như trước: v0.9.16 lớp #bg-strip (xem .bg-layer). */
/* v0.9.15 (khung theo từng máy): cao + dời dọc theo khung chuẩn 1:2 (10,5% chiều cao khung chuẩn = 21cqw) — thanh neo mép dưới,
 * cỡ theo bề ngang như ô chờ / hàng xe (render-core computeLayout); khung 1:2 y như trước */
#boosters {
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(var(--ui-boost-y, 0) * calc(-2 * var(--cw))); /* v0.9.9 bố cục chỉnh tay: dời dọc (% chiều cao khung chuẩn, + = xuống) */
  height: calc(21 * var(--cw));
  display: flex;
  justify-content: space-evenly;
  align-items: center;
}
/* Mặt nút = icon asset của người chơi (nền tím bo góc vẽ sẵn, giữ nguyên) + số lượt; không có chữ (v0.6). */
.booster {
  position: relative;
  width: calc(14 * var(--cw));
  padding: 0;
  background: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  transition: transform 0.08s, filter 0.15s;
  scale: var(--ui-boost-s, 1); /* v0.9.9 bố cục chỉnh tay: cỡ nút */
}
.booster:active {
  transform: translateY(calc(0.6 * var(--cw)));
}
/* v0.9.15 vùng chạm rộng hơn hình nút (khung hẹp nhất — iPhone SE trong Safari — nút 14cqw ≈ 43 px → vùng chạm ≈ 52 px) */
.booster::after {
  content: '';
  position: absolute;
  top: calc(-1.5 * var(--cw));
  right: calc(-1.5 * var(--cw));
  bottom: calc(-1.5 * var(--cw));
  left: calc(-1.5 * var(--cw));
}
.booster .ico {
  display: block;
  width: calc(14 * var(--cw));
  height: calc(14 * var(--cw));
  border-radius: 23.5%; /* = góc bo của icon asset → viền ôm sát */
  background: #c591f2; /* v0.9.31: ảnh icon Pick & Pour, Magnet trong suốt 4–8 px quanh mặt nút: lấp đi, không nhìn xuyên thấy xe phía sau. v0.9.33: cùng màu nền icon người chơi chọn (tools/build-booster-face.ps1) */
  pointer-events: none;
  box-shadow: 0 0 0 calc(0.3 * var(--cw)) #4b2a8a, 0 0 0 calc(1 * var(--cw)) #fbeae0, 0 0 0 calc(1.3 * var(--cw)) #5a3466, 0 calc(1.1 * var(--cw)) 0 calc(1.3 * var(--cw)) rgba(90, 24, 92, 0.35);
  transition: transform 0.15s, filter 0.15s;
}
.booster .cnt {
  position: absolute;
  right: calc(-2 * var(--cw));
  bottom: calc(-2 * var(--cw));
  min-width: calc(5.4 * var(--cw));
  height: calc(5.4 * var(--cw));
  border-radius: calc(3 * var(--cw));
  background: #e30b61;
  border: calc(0.5 * var(--cw)) solid #fff;
  box-shadow: 0 calc(0.4 * var(--cw)) 0 rgba(90, 10, 40, 0.4);
  font-size: calc(3.2 * var(--cw));
  font-weight: 800;
  display: flex;
  align-items: center;
  justify-content: center;
}
/* Hết booster (v0.8): dấu "+" — bấm để mua bằng coin. v0.8.8: nút "+" xanh lá người chơi gửi (assets/plus.png, tạo bởi
 * tools/build-ui-icons.ps1); chữ "+" vẫn giữ trong ô (cho đọc màn hình / test) nhưng trong suốt. */
.booster .cnt.buy {
  right: calc(-2.6 * var(--cw));
  bottom: calc(-2.6 * var(--cw));
  width: calc(7.4 * var(--cw));
  min-width: calc(7.4 * var(--cw));
  height: calc(7.4 * var(--cw));
  border: 0;
  border-radius: 50%;
  background: url('../assets/plus.png') center / contain no-repeat;
  box-shadow: none;
  color: transparent;
  font-size: calc(4.6 * var(--cw));
}
#coins {
  cursor: pointer;
}
.booster.off {
  filter: grayscale(0.7) brightness(0.7);
}
.booster.active .ico {
  transform: scale(1.08);
  filter: drop-shadow(0 0 calc(1.2 * var(--cw)) #fff3b0) drop-shadow(0 0 calc(2.6 * var(--cw)) #ffb21c);
}
/* v0.9.6 mở booster theo màn: chưa tới màn mở → icon xám tối, ổ khoá trắng giữa icon, nhãn "Màn N" thay số lượt */
.booster .lock,
.booster .lock-lv {
  display: none;
  position: absolute;
  pointer-events: none;
}
.booster.locked .ico {
  filter: grayscale(1) brightness(0.55);
}
.booster.locked .cnt {
  display: none;
}
.booster.locked .lock {
  display: block;
  left: 50%;
  top: calc(7 * var(--cw));
  width: calc(6.4 * var(--cw));
  height: calc(6.4 * var(--cw));
  transform: translate(-50%, -50%);
  filter: drop-shadow(0 calc(0.45 * var(--cw)) 0 rgba(40, 10, 60, 0.65));
}
.booster .lock svg {
  display: block;
  width: 100%;
  height: 100%;
}
.booster.locked .lock-lv {
  display: block;
  left: 50%;
  bottom: calc(-2.4 * var(--cw));
  transform: translateX(-50%);
  padding: calc(0.3 * var(--cw)) calc(1.6 * var(--cw));
  border-radius: calc(2 * var(--cw));
  background: #2a2350;
  border: calc(0.4 * var(--cw)) solid #8d7fd0;
  font-size: calc(2.8 * var(--cw));
  font-weight: 800;
  white-space: nowrap;
}
/* booster vừa mở ở màn này: nhấp nháy tới lần dùng đầu */
.booster.fresh .ico {
  animation: booster-fresh 1.1s ease-in-out infinite;
}
@keyframes booster-fresh {
  0%, 100% { transform: scale(1); filter: drop-shadow(0 0 0 rgba(255, 230, 109, 0)); }
  50% { transform: scale(1.1); filter: drop-shadow(0 0 calc(1.2 * var(--cw)) #fff3b0) drop-shadow(0 0 calc(2.6 * var(--cw)) #ffb21c); }
}
/* Bảng "BOOSTER MỚI" (v0.9.6): icon booster to, viền như nút */
/* v0.9.12 bảng "NEW BOOSTER" = ảnh thẻ mẫu người chơi gửi (assets/card-<booster>.png, chữ đã sửa theo từng booster); nút trong
 * suốt đè đúng nút "Claim" vẽ trong ảnh (cùng chỗ ở cả 4 thẻ: ngang 26–74%, dọc 79,5–94% ảnh). Thẻ nảy lên khi hiện. */
.card.booster-card {
  position: relative;
  width: calc(78 * var(--cw));
  max-height: none;
  overflow: visible;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  box-shadow: none;
  display: block;
  animation: bc-pop 0.32s ease-out;
}
.booster-card .bc-img {
  display: block;
  width: 100%;
  height: auto;
  filter: drop-shadow(0 calc(2 * var(--cw)) calc(3 * var(--cw)) rgba(0, 0, 0, 0.45));
  transition: transform 0.08s;
}
.booster-card .bc-claim {
  position: absolute;
  left: 26%;
  right: 26%;
  top: 79.5%;
  bottom: 6%;
  padding: 0;
  border: 0;
  border-radius: calc(6 * var(--cw));
  background: transparent;
  cursor: pointer;
}
.booster-card:has(.bc-claim:active) .bc-img {
  transform: scale(0.985);
}
.sr {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}
@keyframes bc-pop {
  0% { transform: scale(0.7); opacity: 0; }
  70% { transform: scale(1.04); opacity: 1; }
  100% { transform: scale(1); }
}

/* Coin (assets/coin.png) trong popup */
.coin-ico {
  height: 1.3em;
  width: auto;
  vertical-align: middle;
  pointer-events: none;
}
/* Icon booster nhỏ trong chữ của popup */
.inline-ico {
  height: 1.5em;
  width: auto;
  vertical-align: middle;
  margin: -0.3em 0.1em;
  pointer-events: none;
}

/* v0.9.35 (người chơi: "xoá hết các thông báo trong màn hình chơi mà bạn tự viết khi user bấm sai. (chỉ cần hiệu ứng rung nhẹ của asset là user sẽ hiểu không sort được)"): asset rung nhẹ thay chữ (UI.shake; xe: Pieces.nudge) */
.nudge {
  animation: ui-nudge 0.3s;
}
@keyframes ui-nudge {
  0%, 100% { translate: 0 0; }
  20% { translate: calc(-0.9 * var(--cw)) 0; }
  40% { translate: calc(0.8 * var(--cw)) 0; }
  60% { translate: calc(-0.5 * var(--cw)) 0; }
  80% { translate: calc(0.3 * var(--cw)) 0; }
}
/* Khung chữ hướng dẫn (v0.9.35, người chơi: "bạn lấy khung này làm mẫu để chèn text tất cả các phần tutorial vào nhé"): bong bóng trắng ngả xanh nhạt ở mép, chữ xanh đậm, từ nhấn màu cam (ảnh mẫu IMG_5744). Dùng cho .tut-bubble, #toast, .card.feature */
:root {
  --bubble-bg: radial-gradient(115% 135% at 50% 42%, #fff 58%, #eef8fd 78%, #d3ecf9 100%);
  --bubble-shadow: inset 0 0 calc(1.6 * var(--cw)) calc(0.3 * var(--cw)) #cfe8f6, 0 0 0 calc(0.32 * var(--cw)) rgba(84, 66, 74, 0.62), 0 calc(1.1 * var(--cw)) calc(2.2 * var(--cw)) rgba(30, 14, 40, 0.38);
  --bubble-ink: #3f6c96;
  --bubble-hot: #e0812e;
}

/* ---------- Thông báo ---------- */
#toast {
  position: absolute;
  top: calc(16.5 * var(--cw)); /* ngay dưới HUD (v0.8.8: HUD một hàng) */
  left: 50%;
  transform: translate(-50%, calc(-2 * var(--ch)));
  width: calc(84 * var(--cw));
  padding: calc(2.4 * var(--cw)) calc(3.6 * var(--cw));
  border-radius: calc(3.8 * var(--cw));
  background: var(--bubble-bg);
  box-shadow: var(--bubble-shadow);
  color: var(--bubble-ink);
  font-size: calc(3.9 * var(--cw));
  line-height: 1.28;
  text-align: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s, transform 0.25s;
  z-index: 9; /* v0.9.17: trên cả popup (báo ngay trong bảng Settings) */
}
#toast.show {
  opacity: 1;
  transform: translate(-50%, 0);
}

/* Vào màn Khó / Siêu khó. v0.9.35 (người chơi: "bạn lấy UI thông báo level hard- super hard ở đây", ảnh Screenshot 2026-11-05 180251.png): dải ngang tối nằm giữa màn hình, hơi chếch lên bên phải, 2 đường neon trên + dưới, sọc xiên sát 2 đường,
 * đầu lâu đè mép trên, chữ trắng viền neon: đỏ (Khó) / tím (Siêu khó, --neon). Nền phía sau tối đi cho dải neon nổi như ảnh mẫu. Cả hai ảnh đầu lâu nạp sẵn (2 thẻ img), class .super chọn ảnh + màu. Cùng lúc viền màn hình nháy đỏ 3 nhịp (#hard-flash).
 * (v0.9.12–0.9.34: đầu lâu to + chữ HARD LEVEL / SUPER HARD LEVEL ở 1/4 trên màn hình, không có dải.) */
#splash {
  --neon: #ff4326;
  --neon-soft: #ff6a3e;
  --deep: #340600;
  --glow: rgba(255, 46, 20, 0.78);
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background: rgba(8, 4, 16, 0.66);
  pointer-events: none;
  opacity: 0;
  z-index: 6;
}
#splash.super {
  --neon: #c23cff;
  --neon-soft: #d46bff;
  --deep: #23063f;
  --glow: rgba(182, 56, 255, 0.78);
}
body.framed #splash {
  top: calc(-1 * var(--safe-top, 0px));
  bottom: calc(-1 * var(--safe-bottom, 0px));
  left: calc((100% - 100vw) / 2);
  right: calc((100% - 100vw) / 2);
}
.sp-band {
  position: absolute;
  left: -8%;
  right: -8%;
  top: calc(50% - calc(8 * var(--cw)));
  height: calc(23 * var(--cw));
  rotate: -1.6deg;
  background: linear-gradient(90deg, #120208, var(--deep) 22%, var(--deep) 78%, #120208);
  border: solid var(--neon);
  border-width: calc(0.7 * var(--cw)) 0;
  box-shadow: 0 0 calc(4.5 * var(--cw)) calc(1.2 * var(--cw)) var(--glow), inset 0 0 calc(2.6 * var(--cw)) calc(0.2 * var(--cw)) var(--glow);
}
.sp-band::before,
.sp-band::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  height: calc(3.6 * var(--cw));
  background: repeating-linear-gradient(112deg, transparent 0 calc(3 * var(--cw)), var(--neon-soft) calc(3 * var(--cw)) calc(6.6 * var(--cw)), transparent calc(6.6 * var(--cw)) calc(8 * var(--cw)), var(--neon-soft) calc(8 * var(--cw)) calc(9.4 * var(--cw)), transparent calc(9.4 * var(--cw)) calc(14 * var(--cw)));
  opacity: 0.72;
}
.sp-band::before {
  top: 0;
  -webkit-mask-image: linear-gradient(#000, transparent);
  mask-image: linear-gradient(#000, transparent);
}
.sp-band::after {
  bottom: 0;
  -webkit-mask-image: linear-gradient(transparent, #000);
  mask-image: linear-gradient(transparent, #000);
}
#splash .skull {
  position: absolute;
  left: 50%;
  top: calc(50% - calc(18.5 * var(--cw)));
  width: calc(23 * var(--cw));
  height: calc(23 * var(--cw));
  margin-left: calc(-11.5 * var(--cw));
  filter: drop-shadow(calc(0.34 * var(--cw)) 0 0 #fff) drop-shadow(calc(-0.34 * var(--cw)) 0 0 #fff) drop-shadow(0 calc(0.34 * var(--cw)) 0 #fff) drop-shadow(0 calc(-0.34 * var(--cw)) 0 #fff) drop-shadow(0 0 calc(3 * var(--cw)) var(--glow));
}
#splash .skull.super,
#splash.super .skull.hard {
  display: none;
}
#splash.super .skull.super {
  display: block;
}
#splash b {
  --o: calc(0.52 * var(--cw));
  position: absolute;
  left: 0;
  right: 0;
  top: calc(50% + calc(5.4 * var(--cw)));
  text-align: center;
  rotate: -1.6deg;
  font-size: calc(8 * var(--cw));
  line-height: 1;
  white-space: nowrap;
  font-weight: 700;
  letter-spacing: calc(0.3 * var(--cw));
  color: #fff;
  text-shadow: var(--o) 0 0 var(--neon), calc(-1 * var(--o)) 0 0 var(--neon), 0 var(--o) 0 var(--neon), 0 calc(-1 * var(--o)) 0 var(--neon), calc(0.7 * var(--o)) calc(0.7 * var(--o)) 0 var(--neon),
    calc(-0.7 * var(--o)) calc(0.7 * var(--o)) 0 var(--neon), calc(0.7 * var(--o)) calc(-0.7 * var(--o)) 0 var(--neon), calc(-0.7 * var(--o)) calc(-0.7 * var(--o)) 0 var(--neon), 0 0 calc(3.4 * var(--cw)) var(--neon);
}
#splash.show {
  animation: splash 2.1s ease-out;
}
#splash.show .sp-band {
  animation: sp-band 2.1s ease-out;
}
#splash.show .skull {
  animation: skull-pop 2.1s ease-out;
}
#splash.show b {
  animation: sp-text 2.1s ease-out;
}
@keyframes splash {
  0% { opacity: 0; }
  7% { opacity: 1; }
  82% { opacity: 1; }
  100% { opacity: 0; }
}
@keyframes sp-band {
  0% { transform: scaleX(0); }
  12% { transform: scaleX(1); }
}
@keyframes sp-text {
  0%, 8% { transform: scale(0.5); opacity: 0; }
  16% { transform: scale(1.1); opacity: 1; }
  24% { transform: scale(1); }
}
@keyframes skull-pop {
  0% { transform: scale(0.3) rotate(-14deg); }
  12% { transform: scale(1.16) rotate(5deg); }
  20% { transform: scale(0.95) rotate(-3deg); }
  28% { transform: scale(1) rotate(0); }
  38% { transform: rotate(-5deg); }
  46% { transform: rotate(5deg); }
  54% { transform: rotate(-3deg); }
  62%, 100% { transform: rotate(0); }
}
/* Viền màn hình nháy đỏ 3 nhịp (cùng lúc với #splash). Khung iPhone (body.framed): phủ luôn vùng an toàn trên / dưới. */
#hard-flash {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  pointer-events: none;
  opacity: 0;
  z-index: 5;
  box-shadow: inset 0 0 calc(16 * var(--cw)) calc(3 * var(--cw)) rgba(255, 22, 48, 0.9);
  background: radial-gradient(ellipse at center, rgba(255, 0, 40, 0) 50%, rgba(255, 0, 40, 0.3) 100%);
}
#hard-flash.show {
  animation: hard-flash 1.8s ease-in-out;
}
@keyframes hard-flash {
  0% { opacity: 0; }
  10% { opacity: 1; }
  24% { opacity: 0.12; }
  40% { opacity: 1; }
  54% { opacity: 0.12; }
  70% { opacity: 0.9; }
  100% { opacity: 0; }
}
body.framed #hard-flash {
  top: calc(-1 * var(--safe-top, 0px));
  bottom: calc(-1 * var(--safe-bottom, 0px));
  left: calc((100% - 100vw) / 2);
  right: calc((100% - 100vw) / 2);
}

#loading {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  display: none;
  align-items: center;
  justify-content: center;
  font-size: calc(4.5 * var(--cw));
  background: rgba(15, 12, 35, 0.8);
  z-index: 8;
  text-align: center;
  padding: calc(8 * var(--cw));
}
#loading.show {
  display: flex;
}

/* v0.9.13 Màn hình loading lúc mới vào game (js/boot-loading.js): ảnh "Crystal Fill" phủ kín khung (ảnh dọc cắt từ ảnh vuông,
 * tools/build-loading.ps1), thanh gem trên đống gem vàng dưới đáy. Thanh = 3 lớp cùng khung ảnh: khung trống, dải vàng (JS cắt
 * theo tiến độ bằng clip-path), viên gem (JS dời ngang theo đầu dải vàng; tia sáng lấp lánh nhấp nháy đè đúng chỗ tia sáng
 * trong ảnh gốc). Xong thì mờ dần (.done) rồi gỡ khỏi trang. */
#boot {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 40;
  overflow: hidden;
  background: #8fd0f5;
  transition: opacity 0.38s ease;
}
#boot.done {
  opacity: 0;
  pointer-events: none;
}
#boot .boot-art {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
#boot .boot-bar {
  position: absolute;
  left: 12%;
  width: 76%;
  top: 85%;
  height: 0;
  padding-bottom: 17.1747%; /* = 76% : 4,4251 khung ảnh thanh (dòng GEOM của tools/build-loading.ps1); v0.9.48: không dùng aspect-ratio, WebView Chrome 80 chưa có */
  transform: translateY(-50%);
}
#boot .boot-bar img,
#boot .boot-bar .knob {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
}
#boot .boot-bar .frame {
  filter: drop-shadow(0 calc(0.9 * var(--cw)) calc(1.2 * var(--cw)) rgba(70, 30, 0, 0.45));
}
/* 0% trước khi js/boot-loading.js chạy (khung hình đầu tiên): dải vàng ẩn hết, gem ở đầu trái */
#boot .boot-bar .fill {
  clip-path: inset(0 100% 0 0);
}
#boot .boot-bar .knob {
  transform: translateX(-42.39%);
}
#boot .boot-bar .knob img {
  filter: drop-shadow(calc(0.5 * var(--cw)) calc(0.6 * var(--cw)) calc(0.5 * var(--cw)) rgba(10, 16, 70, 0.45));
}
#boot .spark {
  position: absolute;
  left: 50.2%; /* tâm tia sáng trong ảnh gốc (GEOM sparkX / sparkY) */
  top: 23.9%;
  width: 7.5%;
  height: 0;
  padding-bottom: 7.5%;
  background: radial-gradient(circle, #fff 0 9%, rgba(214, 244, 255, 0.55) 20%, rgba(170, 225, 255, 0) 48%);
  animation: boot-spark 1.7s ease-in-out infinite;
}
#boot .spark::before,
#boot .spark::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  border-radius: 50%;
  transform: translate(-50%, -50%);
}
#boot .spark::before {
  width: 100%;
  height: 9%;
  background: linear-gradient(90deg, rgba(255, 255, 255, 0), #fff 50%, rgba(255, 255, 255, 0));
}
#boot .spark::after {
  width: 9%;
  height: 100%;
  background: linear-gradient(rgba(255, 255, 255, 0), #fff 50%, rgba(255, 255, 255, 0));
}
@keyframes boot-spark {
  0%, 100% { transform: translate(-50%, -50%) scale(0.45) rotate(0deg); opacity: 0.55; }
  50% { transform: translate(-50%, -50%) scale(1.05) rotate(45deg); opacity: 1; }
}
#boot .boot-text {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(85% + calc(9.5 * var(--cw)));
  text-align: center;
  font-weight: 900;
  font-size: calc(4.6 * var(--cw));
  letter-spacing: calc(0.25 * var(--cw));
  color: #fff;
  /* viền tím đậm như viền logo "Crystal Fill" (#31184d, đo trên ảnh) */
  text-shadow: calc(0.35 * var(--cw)) 0 0 #31184d, calc(-0.35 * var(--cw)) 0 0 #31184d, 0 calc(0.35 * var(--cw)) 0 #31184d, 0 calc(-0.35 * var(--cw)) 0 #31184d, calc(0.25 * var(--cw)) calc(0.25 * var(--cw)) 0 #31184d,
    calc(-0.25 * var(--cw)) calc(0.25 * var(--cw)) 0 #31184d, calc(0.25 * var(--cw)) calc(-0.25 * var(--cw)) 0 #31184d, calc(-0.25 * var(--cw)) calc(-0.25 * var(--cw)) 0 #31184d, 0 calc(0.8 * var(--cw)) 0 #31184d;
}

/* ---------- Popup ---------- */
.overlay {
  --dim: rgba(12, 9, 30, 0.5); /* v0.9.46: một biến cho lớp tối + phần lan ra vùng an toàn (body.framed .overlay): 2 chỗ luôn cùng màu */
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--dim);
  z-index: 7;
  transition: opacity 0.15s;
}
.overlay.dim {
  --dim: rgba(12, 9, 30, 0.72);
}
.overlay.fail-bg {
  --dim: rgba(40, 6, 22, 0.55);
}
.overlay.hidden {
  display: none;
}
.card {
  width: calc(80 * var(--cw));
  max-height: calc(86 * var(--ch));
  overflow: auto;
  padding: calc(5 * var(--cw));
  border-radius: calc(6 * var(--cw));
  background: linear-gradient(#4a46c9, #2c2a8c);
  border: calc(0.8 * var(--cw)) solid #8fa4ff;
  box-shadow: 0 calc(2 * var(--cw)) 0 #1b1966, 0 calc(4 * var(--cw)) calc(10 * var(--cw)) rgba(0, 0, 0, 0.5);
  display: flex;
  flex-direction: column;
  gap: calc(2.6 * var(--cw));
  text-align: center;
  font-size: calc(3.8 * var(--cw));
}
.card.wide {
  width: calc(90 * var(--cw));
}
.card h2 {
  margin: 0 0 calc(1 * var(--cw));
  font-size: calc(6.5 * var(--cw));
}
/* bảng công cụ tiếng Việt: xem :root */
.card.dev,
#edit-tool {
  font-family: var(--font-head);
}
.card p {
  margin: 0;
  line-height: 1.4;
}
.card .note {
  font-size: calc(3 * var(--cw));
  opacity: 0.75;
}
.btn {
  padding: calc(3 * var(--cw));
  border-radius: calc(3.5 * var(--cw));
  background: linear-gradient(#6f8bff, #4a62e0);
  box-shadow: 0 calc(1 * var(--cw)) 0 #2b3c9e;
  font-weight: 800;
  font-size: calc(4.2 * var(--cw));
}
.btn.big {
  font-size: calc(5.4 * var(--cw));
  padding: calc(3.6 * var(--cw));
}
.btn.green {
  background: linear-gradient(#7be35a, #33b52a);
  box-shadow: 0 calc(1 * var(--cw)) 0 #1f7c1a;
}
.btn.red {
  background: linear-gradient(#ff6b7d, #e0304d);
  box-shadow: 0 calc(1 * var(--cw)) 0 #8f1a2e;
}
.btn.ghost {
  background: rgba(255, 255, 255, 0.12);
  box-shadow: none;
}
.btn.purple {
  background: linear-gradient(#b16cff, #7b2fe0);
  box-shadow: 0 calc(1 * var(--cw)) 0 #4a168f;
}
.btn:disabled {
  filter: grayscale(1) brightness(0.65);
  cursor: default;
}
.row {
  display: flex;
  gap: calc(2.6 * var(--cw));
}
.row .btn {
  flex: 1;
}
/* Màn hình chính (v0.9.33, js/ui.js › showHome): theo ảnh mẫu 1536 × 2752, --u = 1 điểm ảnh mẫu. Nền 3 dải (assets/home/): dải trên neo mép trên, dải dưới neo mép dưới, dải giữa (mặt gỗ) giãn theo chiều cao khung.
 * Đường đi: huy hiệu trên cùng neo theo dải trên, huy hiệu màn đang chơi neo theo dải dưới, 2 huy hiệu giữa chia đều theo đúng tỉ lệ ảnh mẫu. Nút trong suốt đè đúng chỗ vẽ trong ảnh. */
#home {
  --u: calc(calc(100 * var(--cw)) / 1536);
  --top: calc(760 * var(--u));
  --bot: calc(752 * var(--u));
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 6;
  background-color: #b5704c;
  background-image: url('../assets/home/bg-top.jpg'), url('../assets/home/bg-bot.jpg'), url('../assets/home/bg-mid.jpg');
  background-position: 0 0, 0 100%, 0 calc(var(--top) - 1px); /* (dải giữa chờm 1 px dưới 2 dải kia: không lộ đường kẻ ở chỗ nối) */
  background-size: 100% auto, 100% auto, 100% calc(100% - var(--top) - var(--bot) + 2px);
  background-repeat: no-repeat;
}
#home.hidden {
  display: none;
}
.hm-bar {
  position: absolute;
  left: calc(727 * var(--u));
  width: calc(83 * var(--u));
  top: calc(520 * var(--u));
  bottom: calc(1150 * var(--u));
  background: linear-gradient(90deg, #482452 0 7%, #593561 7% 93%, #482452 93%);
}
.hm-node {
  position: absolute;
}
.hm-node img {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
.hm-node b {
  position: absolute;
  left: var(--cx);
  top: var(--cy);
  transform: translate(-50%, -50%);
  color: #f3ecfb;
  font-size: calc(92 * var(--u));
  font-weight: 900;
  line-height: 1;
  --o: calc(5 * var(--u));
  text-shadow: var(--o) 0 0 #33203f, calc(-1 * var(--o)) 0 0 #33203f, 0 var(--o) 0 #33203f, 0 calc(-1 * var(--o)) 0 #33203f, calc(0.7 * var(--o)) calc(0.7 * var(--o)) 0 #33203f,
    calc(-0.7 * var(--o)) calc(0.7 * var(--o)) 0 #33203f, calc(0.7 * var(--o)) calc(-0.7 * var(--o)) 0 #33203f, calc(-0.7 * var(--o)) calc(-0.7 * var(--o)) 0 #33203f, 0 calc(1.7 * var(--o)) 0 #33203f;
}
.hm-node b.l3 {
  font-size: calc(70 * var(--u));
}
.hm-node b.l4 {
  font-size: calc(56 * var(--u));
}
.hm-node.n3 {
  --cx: calc(150 * var(--u));
  --cy: calc(152 * var(--u));
  left: calc(618 * var(--u));
  top: calc(228 * var(--u));
  width: calc(300 * var(--u));
  height: calc(307 * var(--u));
}
.hm-node.n2 {
  --cx: calc(147 * var(--u));
  --cy: calc(146 * var(--u));
  left: calc(620 * var(--u));
  top: calc(380 * var(--u) + (100% - 1342 * var(--u)) * 0.3085 - 148 * var(--u));
  width: calc(295 * var(--u));
  height: calc(296 * var(--u));
}
.hm-node.n1 {
  --cx: calc(148 * var(--u));
  --cy: calc(147 * var(--u));
  left: calc(620 * var(--u));
  top: calc(380 * var(--u) + (100% - 1342 * var(--u)) * 0.6326 - 147.5 * var(--u));
  width: calc(295 * var(--u));
  height: calc(295 * var(--u));
}
.hm-node.n0 {
  --cx: calc(230 * var(--u));
  --cy: calc(232 * var(--u));
  left: calc(540 * var(--u));
  bottom: calc(742 * var(--u));
  width: calc(460 * var(--u));
  height: calc(460 * var(--u));
}
.hm-node.n0 b {
  color: #fff;
  font-size: calc(122 * var(--u));
  --o: calc(7 * var(--u));
}
.hm-node.n0 b.l3 {
  font-size: calc(96 * var(--u));
}
.hm-node.n0 b.l4 {
  font-size: calc(74 * var(--u));
}
/* quầng sáng quanh huy hiệu màn đang chơi (trong ảnh mẫu dính vào nền gỗ: xoá khỏi nền, vẽ lại ở đây) */
.hm-node.n0::before {
  content: '';
  position: absolute;
  top: -12%;
  right: -12%;
  bottom: -12%;
  left: -12%;
  background: radial-gradient(closest-side, rgba(255, 255, 255, 0.82) 62%, rgba(255, 255, 255, 0.34) 76%, rgba(255, 255, 255, 0));
  animation: hm-glow 1.8s ease-in-out infinite alternate;
}
@keyframes hm-glow {
  from { opacity: 0.7; transform: scale(0.97); }
  to { opacity: 1; transform: scale(1.03); }
}
#hm-coins {
  position: absolute;
  left: calc(1230 * var(--u));
  top: calc(104 * var(--u));
  width: calc(148 * var(--u));
  height: calc(70 * var(--u));
  display: flex;
  align-items: center;
  justify-content: center;
  color: #46307e;
  font-size: calc(60 * var(--u));
  font-weight: 900;
  pointer-events: none;
}
#hm-coins.long {
  font-size: calc(46 * var(--u));
}
/* v0.9.34 mạng thật (js/lives.js): số tim trong trái tim, "Full" hoặc đồng hồ hồi tim trong thanh */
#hm-lives,
.lv-num {
  --o: calc(5 * var(--u));
  color: #fff;
  font-weight: 900;
  text-shadow: var(--o) 0 0 #7a1030, calc(-1 * var(--o)) 0 0 #7a1030, 0 var(--o) 0 #7a1030, 0 calc(-1 * var(--o)) 0 #7a1030, calc(0.7 * var(--o)) calc(0.7 * var(--o)) 0 #7a1030,
    calc(-0.7 * var(--o)) calc(0.7 * var(--o)) 0 #7a1030, calc(0.7 * var(--o)) calc(-0.7 * var(--o)) 0 #7a1030, calc(-0.7 * var(--o)) calc(-0.7 * var(--o)) 0 #7a1030;
  pointer-events: none;
}
#hm-lives {
  position: absolute;
  left: calc(730 * var(--u));
  top: calc(96 * var(--u));
  width: calc(80 * var(--u));
  height: calc(80 * var(--u));
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: calc(70 * var(--u));
}
#hm-clock {
  position: absolute;
  left: calc(846 * var(--u));
  top: calc(104 * var(--u));
  width: calc(136 * var(--u));
  height: calc(70 * var(--u));
  display: flex;
  align-items: center;
  justify-content: center;
  color: #46307e;
  font-size: calc(50 * var(--u));
  font-weight: 900;
  pointer-events: none;
}
#hm-clock.full {
  font-size: calc(60 * var(--u));
}
/* Màn hình mua coin (v0.9.48, js/ui.js › showCoinShop): theo ảnh mẫu 937 × 1678, --u = 1 điểm ảnh mẫu. Nền 3 dải như #home: dải trên (mái + thanh tim, coin) neo mép trên, dải dưới (Restore + thanh điều hướng) neo mép dưới, dải giữa giãn theo khung. */
#cshop {
  --u: calc(calc(100 * var(--cw)) / 937);
  --top: calc(300 * var(--u));
  --bot: calc(368 * var(--u));
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 6;
  background-color: #1f568f;
  background-image: url('../assets/coinshop/bg-top.jpg'), url('../assets/coinshop/bg-bot.jpg'), url('../assets/coinshop/bg-mid.jpg');
  background-position: 0 0, 0 100%, 0 calc(var(--top) - 1px);
  background-size: 100% auto, 100% auto, 100% calc(100% - var(--top) - var(--bot) + 2px);
  background-repeat: no-repeat;
}
#cshop.hidden {
  display: none;
}
/* Người chơi: "bạn sửa lại một chút cho bảng coin nằm đối xứng nút restore và mái shop": thân bảng (cao 759) nằm giữa đáy mái (232) và đỉnh nút Restore (cách đáy khung 351), 2 khoảng hở bằng nhau ở mọi cỡ khung; ảnh dư 76 phía trên thân (linh vật nhô lên) */
.cs-panel {
  position: absolute;
  left: calc(36 * var(--u));
  top: calc(232 * var(--u) + (100% - 1342 * var(--u)) / 2 - 76 * var(--u));
  width: calc(866 * var(--u));
  height: calc(844 * var(--u));
}
.cs-panel img {
  display: block;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
.cs-pack {
  position: absolute;
  left: calc(var(--x) * var(--u));
  top: calc(var(--t) * var(--u));
  width: calc(252 * var(--u));
  height: calc(267 * var(--u));
  padding: 0;
  border-radius: calc(32 * var(--u));
  background: transparent;
}
.cs-pack:active {
  background: rgba(30, 8, 60, 0.16);
}
/* giá thật theo store nằm trên mặt nút xanh (đã xoá chữ trong ảnh), cùng kiểu chữ khắc như ảnh mẫu */
.cs-price {
  position: absolute;
  left: calc(14 * var(--u));
  top: calc(184 * var(--u));
  width: calc(226 * var(--u));
  height: calc(67 * var(--u));
  display: flex;
  align-items: center;
  justify-content: center;
  white-space: nowrap;
  color: #0f5a08;
  font-size: calc(40 * var(--u));
  font-weight: 700;
  text-shadow: 0 calc(2 * var(--u)) 0 rgba(190, 255, 120, 0.55);
}
.cs-price.long {
  font-size: calc(31 * var(--u));
}
#cs-lives,
#cs-clock,
#cs-coins {
  position: absolute;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 900;
  pointer-events: none;
}
#cs-lives {
  --o: calc(3 * var(--u));
  left: calc(348 * var(--u));
  top: calc(115 * var(--u));
  width: calc(40 * var(--u));
  height: calc(44 * var(--u));
  color: #fff;
  font-size: calc(38 * var(--u));
  text-shadow: var(--o) 0 0 #7a1030, calc(-1 * var(--o)) 0 0 #7a1030, 0 var(--o) 0 #7a1030, 0 calc(-1 * var(--o)) 0 #7a1030;
}
#cs-clock,
#cs-coins {
  top: calc(117 * var(--u));
  height: calc(38 * var(--u));
  color: #46307e;
}
#cs-clock {
  left: calc(412 * var(--u));
  width: calc(92 * var(--u));
  font-size: calc(29 * var(--u));
}
#cs-clock.full {
  font-size: calc(36 * var(--u));
}
#cs-coins {
  left: calc(746 * var(--u));
  width: calc(82 * var(--u));
  font-size: calc(36 * var(--u));
}
#cs-coins.long {
  font-size: calc(27 * var(--u));
}
/* bảng mua tim: toạ độ trong ô cắt 1330 × 1660 như .fl-hit */
.lv-num {
  position: absolute;
  left: calc(650 * var(--u));
  top: calc(590 * var(--u));
  transform: translate(-50%, -50%);
  --o: calc(8 * var(--u));
  font-size: calc(170 * var(--u));
  line-height: 1;
}
.lv-clock {
  position: absolute;
  left: calc(110 * var(--u));
  right: calc(110 * var(--u));
  top: calc(925 * var(--u));
  text-align: center;
  color: #5b2d91;
  font-size: calc(76 * var(--u));
  font-weight: 900;
  pointer-events: none;
}
.hm-hit {
  position: absolute;
  left: calc(var(--x) * var(--u));
  top: calc(var(--t) * var(--u));
  bottom: calc(var(--b) * var(--u));
  width: calc(var(--w) * var(--u));
  height: calc(var(--h) * var(--u));
  padding: 0;
  border-radius: calc(var(--r) * var(--u));
  background: transparent;
}
.hm-hit:active {
  background: rgba(30, 8, 60, 0.2);
}
/* Bảng thua (v0.9.33, js/ui.js › showPreLose, showLose): ảnh đã cắt assets/fail/, ô cắt 1330 × 1660 của ảnh mẫu rộng 1536, --u = 1 điểm ảnh mẫu; nút trong suốt đè đúng chỗ, số coin = ảnh chữ số. */
.fl-panel {
  --u: calc(calc(100 * var(--cw)) / 1536);
  position: relative;
  flex: none;
  width: calc(1330 * var(--u));
  height: calc(1660 * var(--u));
}
.fl-art {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  filter: drop-shadow(0 calc(2 * var(--cw)) calc(3 * var(--cw)) rgba(0, 0, 0, 0.45));
}
.fl-hit {
  position: absolute;
  padding: 0;
  background: transparent;
}
.fl-hit:active {
  background: rgba(30, 8, 60, 0.22);
}
.fl-hit.x {
  left: calc(1148 * var(--u));
  top: calc(92 * var(--u));
  width: calc(172 * var(--u));
  height: calc(172 * var(--u));
  border-radius: 50%;
}
.fl-hit.coins,
.fl-hit.ad {
  top: calc(1234 * var(--u));
  width: calc(538 * var(--u));
  height: calc(300 * var(--u));
  border-radius: calc(92 * var(--u));
}
.fl-hit.coins {
  left: calc(92 * var(--u));
}
.fl-hit.coins.off {
  background: rgba(60, 48, 84, 0.5);
}
.fl-hit.ad {
  left: calc(678 * var(--u));
}
.fl-hit.retry {
  left: calc(264 * var(--u));
  top: calc(1244 * var(--u));
  width: calc(780 * var(--u));
  height: calc(296 * var(--u));
  border-radius: calc(130 * var(--u));
}
.fl-num {
  position: absolute;
  left: calc(434 * var(--u));
  top: calc(1432 * var(--u));
  transform: translate(-50%, -50%);
  display: flex;
  pointer-events: none;
}
.fl-num i {
  width: calc(96 * var(--u));
  height: calc(130 * var(--u));
  margin: 0 calc(-12 * var(--u));
  background: url('../assets/fail/digits.png') calc(var(--d) * 100% / 9) 0 / 1000% 100% no-repeat;
}
/* Bảng Settings (v0.9.33, js/ui.js › showSettings). v0.9.35 (người chơi: "khi mình bấm bật setting bạn làm cho UI setting zoom out như 1 layer đè lên màn hình (không đổi hẳn màn hình như bản hiện tại)"): lớp đè giữa khung, bung ra từ giữa (bc-pop), màn đang mở vẫn thấy phía sau.
 * Theo ảnh mẫu 1536 × 2752, --u = 1 điểm ảnh mẫu. Bảng là ảnh rời (assets/settings/, tools/build-panels-ui.ps1): mọi số trong bảng là toạ độ điểm ảnh của ảnh mẫu trừ gốc 100, 660 (nhân --u) nên khớp ảnh ở mọi cỡ khung. Ray, núm vẽ bằng CSS theo màu đo trên ảnh mẫu: ray xanh nhạt khi tắt, tím xanh + dải vàng cam khi bật (đúng 2 thanh trong mẫu). */
.set-panel {
  --u: calc(calc(100 * var(--cw)) / 1536);
  position: relative;
  flex: none;
  width: calc(1336 * var(--u));
  height: calc(1600 * var(--u));
  animation: bc-pop 0.32s ease-out;
}
.set-check {
  position: absolute;
  left: calc(835 * var(--u));
  top: calc(985 * var(--u));
  width: calc(160 * var(--u));
  height: calc(145 * var(--u));
  pointer-events: none;
}
.set-art {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  filter: drop-shadow(0 calc(2 * var(--cw)) calc(3 * var(--cw)) rgba(0, 0, 0, 0.45));
}
.set-row {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(var(--y) * var(--u));
  height: 0;
}
/* nút vẽ sẵn trong ảnh bảng (X, Log in, Support, Quit): nút trong suốt đè đúng chỗ, bấm thì tối đi */
.set-hit {
  position: absolute;
  left: calc(var(--x) * var(--u));
  top: calc(var(--t) * var(--u));
  width: calc(var(--w) * var(--u));
  height: calc(var(--h) * var(--u));
  padding: 0;
  border-radius: calc(var(--r) * var(--u));
  background: transparent;
}
.set-hit:active {
  background: rgba(30, 8, 60, 0.22);
}
.set-ico {
  position: absolute;
  left: calc(176 * var(--u));
  top: calc(-78 * var(--u));
  width: calc(146 * var(--u));
  height: calc(162 * var(--u));
  pointer-events: none;
}
.set-ico[data-ico='music'] {
  top: calc(-82 * var(--u));
}
.set-slider {
  --v: 1;
  position: absolute;
  left: calc(345 * var(--u));
  top: calc(-90 * var(--u));
  width: calc(801 * var(--u));
  height: calc(180 * var(--u));
  cursor: pointer;
  touch-action: none;
}
.set-slider i {
  position: absolute;
  display: block;
  pointer-events: none;
}
.set-slider .tr,
.set-slider .fill {
  left: 0;
  top: calc(38 * var(--u));
  height: calc(103 * var(--u));
  border-radius: calc(34 * var(--u));
}
.set-slider .tr {
  right: 0;
  background: #b5d0fb;
  box-shadow: inset 0 calc(6 * var(--u)) 0 #a3b6ee;
}
.set-slider.on .tr {
  background: #6e7ecc;
  box-shadow: none;
}
.set-slider .fill {
  display: none;
  width: calc((var(--v) * 745 + 28) * var(--u));
  background: linear-gradient(#fff874, #fddd4e 24%, #feb42d 52%, #ff8f09 82%, #f77d00);
}
.set-slider.on .fill {
  display: block;
}
.set-slider .knob {
  left: calc(var(--v) * 745 * var(--u));
  top: calc(21 * var(--u));
  width: calc(56 * var(--u));
  height: calc(138 * var(--u));
  border-radius: calc(28 * var(--u));
  background: linear-gradient(#de90fd, #c66bf6 14%, #c86df6 84%, #ae68dc);
  box-shadow: 0 calc(4 * var(--u)) calc(9 * var(--u)) rgba(120, 70, 200, 0.45);
}
.set-gem {
  position: absolute;
  top: calc(-87 * var(--u));
  width: calc(155 * var(--u));
  height: calc(175 * var(--u));
  padding: 0;
  background: none;
}
.set-gem.left {
  left: calc(170 * var(--u));
}
.set-gem.right {
  left: calc(1010 * var(--u));
}
/* vùng chạm ≥ ~44 px ở khung hẹp nhất */
.set-gem::after {
  content: '';
  position: absolute;
  top: calc(-1.5 * var(--cw));
  right: calc(-1.5 * var(--cw));
  bottom: calc(-1.5 * var(--cw));
  left: calc(-1.5 * var(--cw));
}
.set-gem img {
  display: block;
  width: 100%;
  height: 100%;
  pointer-events: none;
  transition: transform 0.08s;
}
.set-gem:active img {
  transform: scale(0.88);
}
/* chữ Settings: bấm 5 lần mở bảng Dev Settings (v0.9.17, không có dấu hiệu gì) */
.set-title {
  position: absolute;
  left: calc(440 * var(--u));
  top: calc(58 * var(--u));
  width: calc(460 * var(--u));
  height: calc(146 * var(--u));
}
/* Màn thắng (v0.9.17, js/ui.js › showWin): theo ảnh mẫu người chơi gửi — ảnh cắt trong assets/win/ (tools/build-panels-ui.ps1). Khung tranh vẽ bằng
 * CSS theo màu đo trên mẫu (ôm theo tỉ lệ tranh). Quầng cam + sao lấp lánh sau khung; pháo hoa .win-fw (BR.FX) nằm sau cả bảng, không che tranh và nút. */
.overlay.win-bg {
  --dim: rgba(10, 6, 20, 0.84);
}
.win-panel {
  --w: calc(calc(42 * var(--cw)) / 600); /* 1 điểm ảnh của ảnh nút */
  position: relative;
  flex: none;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.win-glow {
  position: absolute;
  left: 50%;
  top: 46%;
  width: calc(150 * var(--cw));
  height: calc(150 * var(--cw));
  margin: calc(-75 * var(--cw));
  background: radial-gradient(closest-side, rgba(255, 150, 40, 0.62), rgba(255, 105, 10, 0.26) 46%, rgba(255, 90, 0, 0));
  pointer-events: none;
  animation: win-glow 2.2s ease-in-out infinite alternate;
}
@keyframes win-glow {
  from { opacity: 0.72; }
  to { opacity: 1; }
}
.win-title,
.win-frame,
.win-coins,
.win-btns {
  position: relative;
}
.win-title {
  width: calc(70 * var(--cw));
  margin-bottom: calc(3 * var(--cw));
  animation: bc-pop 0.42s ease-out both;
}
.win-title img,
.win-coins img,
.win-btn img {
  display: block;
  width: 100%;
  height: auto;
  pointer-events: none;
}
.win-title img {
  filter: drop-shadow(0 calc(1 * var(--cw)) calc(1.4 * var(--cw)) rgba(0, 0, 0, 0.45));
}
.win-frame {
  padding: calc(3.6 * var(--cw));
  border-radius: calc(1.4 * var(--cw));
  background: #c1d1e7;
  box-shadow: inset 0 calc(0.25 * var(--cw)) 0 #d9e4f2, 0 calc(1 * var(--cw)) 0 #8da8bd, 0 calc(2.6 * var(--cw)) calc(5 * var(--cw)) rgba(0, 0, 0, 0.5);
  animation: bc-pop 0.42s 0.06s ease-out both;
}
.win-frame .in {
  padding: calc(1 * var(--cw));
  border-radius: calc(1.6 * var(--cw));
  background: #fff;
}
.win-pic {
  display: block;
  width: auto;
  height: auto;
  max-width: calc(56 * var(--cw));
  max-height: calc(56 * var(--cw));
  border-radius: calc(0.5 * var(--cw));
}
.win-star {
  position: absolute;
  width: calc(9 * var(--cw));
  height: calc(9 * var(--cw));
  margin: calc(-4.5 * var(--cw));
  pointer-events: none;
  animation: win-twinkle 1.7s ease-in-out infinite;
}
.win-star::before,
.win-star::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 0;
  width: calc(0.8 * var(--cw));
  height: 100%;
  margin-left: calc(-0.4 * var(--cw));
  border-radius: 50%;
  background: linear-gradient(rgba(255, 240, 190, 0), #fff6d0 50%, rgba(255, 240, 190, 0));
}
.win-star::after {
  transform: rotate(90deg);
}
.win-star.s1 {
  right: calc(-3 * var(--cw));
  top: calc(3 * var(--cw));
}
.win-star.s2 {
  right: calc(-1 * var(--cw));
  top: 42%;
  animation-delay: 0.6s;
}
.win-star.s3 {
  left: calc(-2 * var(--cw));
  top: 64%;
  animation-delay: 1.1s;
}
@keyframes win-twinkle {
  0%, 100% { transform: scale(0.3) rotate(0deg); opacity: 0.2; }
  50% { transform: scale(1) rotate(20deg); opacity: 1; }
}
.win-coins {
  width: calc(25 * var(--cw));
  margin-top: calc(-5.4 * var(--cw));
  animation: bc-pop 0.42s 0.14s ease-out both;
}
.win-coins img {
  filter: drop-shadow(0 calc(0.6 * var(--cw)) calc(0.8 * var(--cw)) rgba(0, 0, 0, 0.5));
}
/* số coin: ảnh 10 chữ số digits.png, mỗi ô 96 × 130 */
.win-num {
  position: absolute;
  left: 50%;
  bottom: calc(-5 * var(--cw));
  transform: translateX(-50%);
  display: flex;
}
.win-num i {
  width: calc(7.4 * var(--cw));
  height: calc(10 * var(--cw));
  margin: 0 calc(-0.8 * var(--cw));
  background: url('../assets/win/digits.png') calc(var(--d) * 100% / 9) 0 / 1000% 100% no-repeat;
}
.win-btns {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: calc(2.6 * var(--cw));
  margin-top: calc(6.5 * var(--cw));
  animation: bc-pop 0.42s 0.2s ease-out both;
}
.win-btn {
  padding: 0;
  background: none;
  transition: transform 0.08s;
}
.win-btn:active {
  transform: translateY(calc(0.6 * var(--cw)));
}
.win-btn.next {
  width: calc(612 * var(--w));
}
.win-btn.ad {
  width: calc(644 * var(--w));
}
.win-btn:disabled {
  filter: grayscale(0.85) brightness(0.75);
  cursor: default;
}
.win-fw {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
.ribbon {
  align-self: center;
  margin-top: calc(-9 * var(--cw));
  padding: calc(2 * var(--cw)) calc(7 * var(--cw));
  border-radius: calc(3 * var(--cw));
  background: linear-gradient(#ffcf3f, #f29b12);
  color: #3a2300;
  font-weight: 900;
  font-size: calc(6 * var(--cw));
  box-shadow: 0 calc(1 * var(--cw)) 0 #a65f00;
}
.rules {
  text-align: left;
  margin: 0;
  padding-left: calc(5 * var(--cw));
  line-height: 1.45;
  display: flex;
  flex-direction: column;
  gap: calc(1.4 * var(--cw));
}
.grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: calc(2.4 * var(--cw));
}
.lvl {
  position: relative;
  aspect-ratio: 1;
  border-radius: calc(3 * var(--cw));
  background: linear-gradient(#6f8bff, #4a62e0);
  box-shadow: 0 calc(0.9 * var(--cw)) 0 #2b3c9e;
  font-size: calc(5.5 * var(--cw));
  font-weight: 900;
}
.lvl.done {
  background: linear-gradient(#7be35a, #33b52a);
  box-shadow: 0 calc(0.9 * var(--cw)) 0 #1f7c1a;
}
.lvl.hard {
  outline: calc(0.7 * var(--cw)) solid #d68bff;
}
.lvl i {
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(0.8 * var(--cw));
  font-style: normal;
  font-size: calc(2.4 * var(--cw));
  color: #f1dcff;
}
/* Chọn màn (1000 màn): trang 100 màn, ô có ảnh tranh + vạch màu bậc độ khó */
.card.levels h2 small {
  font-size: calc(3.4 * var(--cw));
  opacity: 0.7;
  font-weight: 600;
}
.tabs {
  display: flex;
  gap: calc(1.2 * var(--cw));
  overflow-x: auto;
  padding-bottom: calc(1 * var(--cw));
  flex: none;
}
.tabs .tab {
  flex: none;
  padding: calc(1.4 * var(--cw)) calc(2.4 * var(--cw));
  border-radius: calc(2.4 * var(--cw));
  background: rgba(255, 255, 255, 0.12);
  font-size: calc(3 * var(--cw));
  font-weight: 700;
}
.tabs .tab.on {
  background: #ffd34d;
  color: #3a2300;
}
.grid.thumbs {
  grid-template-columns: repeat(5, 1fr);
  gap: calc(1.8 * var(--cw));
  max-height: calc(58 * var(--ch));
  overflow-y: auto;
  padding: calc(0.6 * var(--cw));
}
.grid.thumbs .lvl {
  padding: 0;
  overflow: hidden;
  background: #241f45;
  box-shadow: 0 0 0 calc(0.5 * var(--cw)) var(--tc), 0 calc(0.8 * var(--cw)) 0 rgba(0, 0, 0, 0.35);
  border-radius: calc(2.4 * var(--cw));
}
.grid.thumbs .lvl canvas {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 100%;
  image-rendering: pixelated;
  opacity: 0.92;
}
.grid.thumbs .lvl span {
  position: absolute;
  left: calc(0.8 * var(--cw));
  top: calc(0.6 * var(--cw));
  padding: 0 calc(1 * var(--cw));
  border-radius: calc(1.6 * var(--cw));
  background: rgba(20, 16, 45, 0.82);
  font-size: calc(2.9 * var(--cw));
  font-weight: 900;
}
.grid.thumbs .lvl i {
  left: auto;
  right: calc(0.6 * var(--cw));
  bottom: calc(0.6 * var(--cw));
  padding: calc(0.2 * var(--cw)) calc(1 * var(--cw));
  border-radius: calc(1.4 * var(--cw));
  background: var(--tc);
  color: #1d0a14;
  font-size: calc(2.2 * var(--cw));
  font-weight: 900;
}
.grid.thumbs .lvl.done::after {
  content: '✓';
  position: absolute;
  right: calc(0.8 * var(--cw));
  top: calc(0.4 * var(--cw));
  font-size: calc(3.6 * var(--cw));
  font-weight: 900;
  color: #7bf1a8;
  text-shadow: 0 calc(0.3 * var(--cw)) 0 rgba(0, 0, 0, 0.6);
}
.grid.thumbs .lvl.cur {
  box-shadow: 0 0 0 calc(0.9 * var(--cw)) #fff, 0 0 calc(4 * var(--cw)) rgba(255, 255, 255, 0.5);
}
/* (v0.9.12 bỏ bảng thông báo trước màn Khó / Siêu khó — xem #splash, #hard-flash) */
@keyframes wobble {
  0%, 100% { transform: rotate(-6deg) scale(1); }
  50% { transform: rotate(6deg) scale(1.08); }
}
table {
  width: 100%;
  border-collapse: collapse;
  font-size: calc(3.1 * var(--cw));
}
th,
td {
  padding: calc(1.2 * var(--cw)) calc(0.6 * var(--cw));
  border-bottom: calc(0.3 * var(--cw)) solid rgba(255, 255, 255, 0.15);
}
.sw {
  aspect-ratio: 1;
  border-radius: calc(3 * var(--cw));
  border: calc(0.6 * var(--cw)) solid rgba(255, 255, 255, 0.7);
  box-shadow: 0 calc(0.9 * var(--cw)) 0 rgba(0, 0, 0, 0.35);
  display: flex;
  align-items: flex-end;
  justify-content: center;
}

/* Bảng mua booster (v0.9.19, js/ui.js › showBoosterShop): thẻ cắt từ ảnh mẫu assets/shop/ (tools/build-panels-ui.ps1), mọi số theo khung thẻ 1430 × 1855
 * (nhân --u). Số lượng + giá = ảnh chữ số .dg, cùng font trên mọi máy. Không đủ coin: nút xám. */
.shop-card {
  --u: calc(calc(86 * var(--cw)) / 1430);
  position: relative;
  flex: none;
  width: calc(1430 * var(--u));
  height: calc(1855 * var(--u));
}
.shop-art {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  filter: drop-shadow(0 calc(2 * var(--cw)) calc(3 * var(--cw)) rgba(0, 0, 0, 0.45));
}
.shop-buy {
  position: absolute;
  left: calc(var(--x) * var(--u));
  top: calc(1438 * var(--u));
  width: calc(614 * var(--u));
  height: calc(335 * var(--u));
  padding: 0;
  background: none;
  transition: transform 0.08s;
}
.shop-buy:active {
  transform: translateY(calc(0.6 * var(--cw)));
}
.shop-buy.off {
  filter: grayscale(0.9) brightness(0.88);
}
.shop-buy .face {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
.shop-buy span {
  position: absolute;
  left: 0;
  right: calc(14 * var(--u));
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}
.shop-buy .q {
  top: calc(38 * var(--u));
  height: calc(96 * var(--u));
}
.shop-buy .q img {
  height: 100%;
  width: auto;
}
.shop-buy .p {
  top: calc(130 * var(--u));
  height: calc(128 * var(--u));
}
.shop-buy .p img {
  height: calc(120 * var(--u));
  width: auto;
  margin-left: calc(16 * var(--u));
}
.dg {
  display: block;
  width: calc(94 * var(--u));
  height: calc(127 * var(--u));
  margin: 0 calc(-9 * var(--u));
  background: url('../assets/shop/digits.png') calc(var(--d) * 100% / 9) 0 / 1000% 100% no-repeat;
}
/* (cùng ảnh, cùng cỡ chữ với buy.png: cao 96 / 130) */
.shop-buy .q .dg {
  width: calc(71 * var(--u));
  height: calc(96 * var(--u));
  margin: 0 0 0 calc(10 * var(--u));
}
.shop-x {
  position: absolute;
  left: calc(1264 * var(--u));
  top: calc(44 * var(--u));
  width: calc(151 * var(--u));
  height: calc(148 * var(--u));
  padding: 0;
  background: none;
  transition: transform 0.08s;
}
.shop-x::after {
  content: '';
  position: absolute;
  top: calc(-1.5 * var(--cw));
  right: calc(-1.5 * var(--cw));
  bottom: calc(-1.5 * var(--cw));
  left: calc(-1.5 * var(--cw));
}
.shop-x:active {
  transform: scale(0.92);
}
.shop-x img {
  display: block;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
/* ---------- Booster chọn trên màn chơi (js/booster-pick.js, js/queue-view.js) ----------
 * #pick-bar: thanh nhắc trên tranh (Grab, Pick & Pour: chạm vùng; Magnet: chạm màu). #queue-bar: thanh nhắc lúc xem toàn bộ hàng xe. */
#pick-bar,
#queue-bar {
  position: absolute;
  left: 50%;
  bottom: calc(calc(21 * var(--cw)) - var(--ui-boost-y, 0) * calc(2 * var(--cw))); /* ngay trên thanh booster: tranh và dãy ô chờ không bị che, chạm được hết */
  transform: translateX(-50%);
  z-index: 5;
  display: flex;
  align-items: center;
  gap: calc(2 * var(--cw));
  width: max-content;
  max-width: calc(92 * var(--cw));
  padding: calc(1.2 * var(--cw)) calc(2 * var(--cw)) calc(1.2 * var(--cw)) calc(1.2 * var(--cw));
  border-radius: calc(4 * var(--cw));
  background: var(--bubble-bg); /* v0.9.35: cùng khung chữ hướng dẫn */
  box-shadow: var(--bubble-shadow);
  color: var(--bubble-ink);
  font-size: calc(3.6 * var(--cw));
  font-weight: 600;
  line-height: 1.25;
  pointer-events: auto;
}
#pick-bar img {
  width: calc(10 * var(--cw));
  height: calc(10 * var(--cw));
  object-fit: cover;
  flex: none;
}
#pick-bar button,
#queue-bar button {
  flex: none;
  padding: calc(1.2 * var(--cw)) calc(2.6 * var(--cw));
  border-radius: calc(2.6 * var(--cw));
  background: #4b4190;
  color: #fff;
  font-size: calc(3.2 * var(--cw));
  font-weight: 700;
}
#queue-bar {
  bottom: calc(5 * var(--cw));
  padding: calc(1.8 * var(--cw)) calc(2 * var(--cw)) calc(1.8 * var(--cw)) calc(3.4 * var(--cw));
  font-size: calc(3.8 * var(--cw));
}
/* v0.9.20 xem toàn bộ hàng xe (người chơi: "chuyển cảnh từ màn hình chơi xuống toàn phần xe xếp dưới cho user xem và pick nhé (setting bố cục ánh sáng và background vẫn như
 * vậy)"): camera lia xuống (Render.setViewY), thanh booster trượt ra khỏi màn hình, dải nền đáy thu lại còn mép mờ; #bg-top = dải nền trên cùng (khung cắt mặt bàn như #bg-strip) che
 * dãy ô chờ / xe cuộn lên phía sau HUD. v0.9.21: mặt bàn chạy theo camera (xem .bg-layer). */
#bg-top {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: calc(17 * var(--cw));
  overflow: hidden;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.3s;
  -webkit-mask-image: linear-gradient(#000 calc(100% - calc(3 * var(--cw))), transparent);
  mask-image: linear-gradient(#000 calc(100% - calc(3 * var(--cw))), transparent);
}
/* (chỉ lúc camera đang lia: xoay máy, đổi cỡ màn hình thì thanh + dải nền đổi cỡ ngay) */
body.queue-pan #boosters {
  transition: transform 0.35s ease-in-out;
}
body.queue-pan #bg-strip {
  transition: height 0.35s ease-in-out;
}
body.queue-view #bg-top {
  opacity: 1;
}
body.queue-view #boosters {
  transform: translateY(calc(100% + calc(10 * var(--cw))));
}
.ad-lid {
  transition: opacity 0.15s;
}
body.queue-view .ad-lid {
  opacity: 0;
  pointer-events: none;
}

/* ---------- v0.9.10 ô chờ khoá chờ xem quảng cáo (js/ad-slot.js): icon quảng cáo đè lên khung ô ----------
 * v0.9.32 (người chơi: "slot có ad reward bạn bỏ kính mờ màu trắng đi"): bỏ tấm kính (viền trắng, phủ trắng, bóng, làm mờ), nút trong suốt, chỉ còn icon. */
.ad-lid {
  position: absolute;
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border-radius: 20%;
  background: none;
}
/* v0.9.19 (người chơi: "icon xem ad ở slot thừa config để nó biến đổi theo size của slot đó luôn nhé"): --s = cỡ ô (js/ad-slot.js) */
.ad-lid img {
  width: 74%;
  height: auto;
  pointer-events: none;
  filter: drop-shadow(0 calc(var(--s) * 0.03) calc(var(--s) * 0.036) rgba(0, 0, 0, 0.45));
  animation: ad-lid-bob 1.8s ease-in-out infinite;
}
.ad-lid:active {
  transform: translateY(calc(0.4 * var(--cw)));
}
@keyframes ad-lid-bob {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.07); }
}
/* quảng cáo giả: trên trình duyệt, APK thử chưa có id quảng cáo (js/horus.js). v0.9.48 lớp riêng #ad-sim đè lên bảng đang mở, đóng sớm thì bảng vẫn còn */
.overlay.ad-bg {
  --dim: rgba(0, 0, 0, 0.88);
}
.card.ad-card {
  position: relative;
  align-items: center;
  background: linear-gradient(#2c2a4a, #16152a);
  border-color: #6e6aa8;
}
.ad-tag {
  position: absolute;
  left: calc(3 * var(--cw));
  top: calc(3 * var(--cw));
  padding: calc(0.4 * var(--cw)) calc(1.6 * var(--cw));
  border-radius: calc(1.4 * var(--cw));
  background: #ffcf3f;
  color: #3a2300;
  font-size: calc(3 * var(--cw));
  font-weight: 900;
}
.ad-art {
  width: calc(34 * var(--cw));
  height: auto;
  animation: ad-lid-bob 1.8s ease-in-out infinite;
}
/* Bảng mở ô khoá (chạm nắp ô 5): v0.9.46 theo ảnh mẫu 1760 × 2270 (assets/fail/unlock-slot.png, tools/build-panels-ui.ps1), --u = 1 điểm ảnh mẫu, nút trong suốt đè đúng chỗ vẽ trong ảnh. Không đủ coin: nút Unlock mờ, bấm thì bảng rung (js/ui.js › showUnlockSlot) */
.un-panel {
  --u: calc(calc(92 * var(--cw)) / 1760);
  position: relative;
  flex: none;
  width: calc(1760 * var(--u));
  height: calc(2270 * var(--u));
  animation: bc-pop 0.32s ease-out;
}
.un-art {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  filter: drop-shadow(0 calc(2 * var(--cw)) calc(3 * var(--cw)) rgba(0, 0, 0, 0.45));
}
.un-hit {
  position: absolute;
  padding: 0;
  background: transparent;
  left: calc(912 * var(--u));
  width: calc(718 * var(--u));
}
.un-hit:active {
  background: rgba(30, 8, 60, 0.22);
}
.un-hit.ad {
  left: calc(125 * var(--u));
  top: calc(1760 * var(--u));
  width: calc(716 * var(--u));
  height: calc(366 * var(--u));
  border-radius: calc(92 * var(--u));
}
.un-hit.coins {
  top: calc(1762 * var(--u));
  height: calc(180 * var(--u));
  border-radius: calc(84 * var(--u));
}
.un-hit.coins.off {
  background: rgba(70, 58, 110, 0.55);
}
.un-hit.cancel {
  top: calc(1970 * var(--u));
  height: calc(156 * var(--u));
  border-radius: calc(78 * var(--u));
}

/* ---------- Hướng dẫn từng bước (v0.8.5, js/tutorial.js) ----------
 * Lớp phủ trên HUD / booster, dưới thông báo (#toast) và popup: tối màn hình trừ các ô "đèn chiếu" (viền trắng nhấp nháy),
 * bàn tay chỉ thao tác, bong bóng chữ. Bước bắt buộc ('act') vẫn cho chạm xuyên xuống tranh (js chặn thao tác sai); bước
 * đọc ('info') chặn chạm — chạm bất kỳ đâu để đọc tiếp; bước nhắc ('soft') không làm tối, chơi tự do. */
#tut {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 4;
  pointer-events: none;
}
#tut.hidden {
  display: none;
}
#tut.tut-info {
  pointer-events: auto;
}
#tut svg.tut-dim {
  position: absolute;
  left: 0;
  top: 0;
}
#tut .tut-shade {
  fill: rgba(8, 6, 24, 0.66);
}
/* v0.9.13: bước nhắc ('soft') và bước không làm tối (màn 2, người chơi: "Tut của level 2 không cần làm tối màn hình") */
#tut.tut-soft .tut-shade,
#tut.tut-nodim .tut-shade {
  display: none;
}
/* v0.9.13 (người chơi: "Tutorial bỏ những cái khung bạn tự vẽ đi, chỉ để 1 icon ngón tay chỉ dẫn thôi"): bỏ khung viền trắng nhấp nháy quanh chỗ được chỉ (.tut-ring).
 * v0.9.35 chữ nằm trong khung chữ hướng dẫn (--bubble-*), đuôi nhọn chỉ về chỗ được chỉ: dưới khung (.tail-down) hoặc trên khung (.tail-up), --tail = chỗ ngang của đuôi (Tutorial.placeBubble). */
.tut-bubble {
  --tail: 50%;
  position: absolute;
  left: calc(7 * var(--cw));
  right: calc(7 * var(--cw));
  top: calc(30 * var(--ch));
  padding: calc(3 * var(--cw)) calc(3.6 * var(--cw));
  border-radius: calc(4.4 * var(--cw));
  background: var(--bubble-bg);
  box-shadow: var(--bubble-shadow);
  color: var(--bubble-ink);
  font-size: calc(4.6 * var(--cw));
  font-weight: 600;
  line-height: 1.26;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(2.2 * var(--cw));
}
.tut-bubble em {
  font-style: normal;
  font-weight: 700;
  color: var(--bubble-hot);
}
.tut-bubble::after {
  content: '';
  display: none;
  position: absolute;
  left: var(--tail);
  width: calc(5 * var(--cw));
  height: calc(3 * var(--cw));
  margin-left: calc(-2.5 * var(--cw));
  background: linear-gradient(#e6f4fc, #c6e5f6);
  clip-path: polygon(0 0, 100% 0, 50% 100%);
}
.tut-bubble.tail-down::after {
  display: block;
  bottom: calc(-2.8 * var(--cw));
}
.tut-bubble.tail-up::after {
  display: block;
  top: calc(-2.8 * var(--cw));
  rotate: 180deg;
}.tut-bubble .tut-ok {
  pointer-events: auto;
  padding: calc(1.8 * var(--cw)) calc(9 * var(--cw));
  font-size: calc(4.2 * var(--cw));
  color: #fff;
}
.tut-bubble.shake {
  animation: tut-shake 0.35s;
}
@keyframes tut-shake {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(calc(-2 * var(--cw))); }
  75% { transform: translateX(calc(2 * var(--cw))); }
}
/* Bàn tay 👆: lệch để đầu ngón trỏ đúng điểm chỉ (thu phóng quanh đầu ngón) */
.tut-hand {
  position: absolute;
  left: 0;
  top: 0;
  margin-left: calc(-5.5 * var(--cw));
  margin-top: calc(-0.7 * var(--cw));
  font-size: calc(13 * var(--cw));
  line-height: 1;
  transform-origin: calc(5.5 * var(--cw)) calc(0.7 * var(--cw));
  filter: drop-shadow(0 calc(0.6 * var(--cw)) calc(0.6 * var(--cw)) rgba(0, 0, 0, 0.5));
  opacity: 0;
}
/* Xe mờ (bàn tay kéo xe, minh hoạ thua): ảnh xe 3D trong game (Render.cartImage, v0.9.5), JS đặt ảnh + cỡ + vị trí */
.tut-ghost {
  position: absolute;
  left: 0;
  top: 0;
  opacity: 0;
  background-repeat: no-repeat;
  background-size: 100% 100%;
}
.tut-x {
  position: absolute;
  left: 0;
  top: 0;
  padding: calc(1 * var(--cw)) calc(3 * var(--cw));
  border-radius: calc(2.5 * var(--cw));
  background: linear-gradient(#ff7a8a, #d92b48);
  color: #fff;
  font-weight: 900;
  font-size: calc(5 * var(--cw));
  box-shadow: 0 calc(0.8 * var(--cw)) 0 #85152a;
  opacity: 0;
  transition: opacity 0.15s;
}
/* Ảnh xe đẩy cắt từ ảnh ghép BR.CART_ATLAS (4 × 4 ô; biến --cart-atlas do js/tutorial.js đặt) */
.cart-ico {
  display: inline-block;
  width: calc(20 * var(--cw));
  height: calc(20 * var(--cw));
  background-image: var(--cart-atlas);
  background-size: 400% 400%;
  background-repeat: no-repeat;
}
/* Bảng "TÍNH NĂNG MỚI" (màn giới thiệu cơ chế). v0.9.35: cùng khung chữ hướng dẫn (--bubble-*) */
.card.feature {
  overflow: visible;
  margin-top: calc(6 * var(--cw));
  border: 0;
  background: var(--bubble-bg);
  box-shadow: var(--bubble-shadow);
  color: var(--bubble-ink);
  font-size: calc(4.4 * var(--cw));
}
.card.feature h2 {
  color: var(--bubble-ink);
}
.card.feature .btn {
  color: #fff;
}
.card.feature p {
  line-height: 1.28;
}
.feat-art {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: calc(1 * var(--cw));
  min-height: calc(26 * var(--cw));
}
.feat-img {
  max-width: calc(54 * var(--cw));
  max-height: calc(34 * var(--cw));
  filter: drop-shadow(0 calc(1.2 * var(--cw)) calc(1 * var(--cw)) rgba(0, 0, 0, 0.4));
  animation: wobble 1.6s ease-in-out infinite;
}
.feat-arrow {
  font-size: calc(8 * var(--cw));
  font-weight: 900;
  color: #ffe66d;
}
.feat-chain {
  width: calc(14 * var(--cw));
  height: calc(6 * var(--cw));
  background-size: auto 100%;
  background-repeat: repeat-x;
}

/* ---------- Công cụ "Sửa màn & hình" (v0.9, js/edit-tool.js): bảng cạnh màn chơi, cỡ px (không theo khung game) ---------- */
#edit-tool {
  position: fixed;
  top: 0;
  right: 0;
  width: 400px;
  max-width: 100%;
  height: 100%;
  display: none;
  flex-direction: column;
  background: #1b1733;
  border-left: 2px solid #3d3470;
  box-shadow: -10px 0 30px rgba(0, 0, 0, 0.45);
  z-index: 60;
  font-size: 13px;
  user-select: none;
}
#edit-tool.show {
  display: flex;
}
#edit-tool button {
  background: #3a3270;
  border-radius: 7px;
  padding: 6px 9px;
  font-size: 12.5px;
  font-weight: 600;
}
#edit-tool button:hover {
  background: #4b4190;
}
#edit-tool button.green {
  background: #2f9e55;
}
#edit-tool button.ghost {
  background: transparent;
  border: 1px solid #5a4f96;
}
#edit-tool .note {
  color: #b9b3dc;
  font-size: 11.5px;
  line-height: 1.4;
  margin: 8px 0;
}
#edit-tool .warn {
  color: #ffb46b;
}
#edit-tool .ed {
  color: #7dffa8;
}
.et-tabs {
  display: flex;
  gap: 6px;
  padding: 8px;
  border-bottom: 1px solid #3d3470;
}
.et-tabs button {
  flex: 1;
}
.et-tabs button.on {
  background: #6c5ce7;
}
.et-tabs button.x {
  flex: 0 0 34px;
}
.et-body {
  flex: 1;
  overflow-y: auto;
  padding: 10px;
}
.et-lv {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 8px;
}
.et-lv span {
  font-weight: 700;
}
.et-num {
  width: 64px;
  font: inherit;
  padding: 4px;
  border-radius: 6px;
  border: 1px solid #5a4f96;
  background: #120f26;
  color: #fff;
}
.et-lv .tier {
  margin-left: auto;
}
.et-stat {
  background: #241f45;
  border-radius: 8px;
  padding: 8px;
  line-height: 1.5;
  margin-bottom: 8px;
}
.et-cols {
  display: flex;
  gap: 6px;
  align-items: flex-start;
  margin-bottom: 8px;
}
.et-col {
  flex: 1;
  min-width: 0;
  background: #13102a;
  border-radius: 8px;
  padding: 4px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.et-ch {
  font-size: 11px;
  color: #b9b3dc;
  text-align: center;
}
.et-card {
  position: relative;
  height: 34px;
  border-radius: 7px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 15px;
  cursor: grab;
  box-shadow: inset 0 -3px 0 rgba(0, 0, 0, 0.25);
  touch-action: none;
}
.et-card.on {
  outline: 3px solid #ffd64a;
  outline-offset: 1px;
}
.et-card.dragging {
  opacity: 0.85;
  z-index: 5;
  cursor: grabbing;
  pointer-events: none;
}
.et-card.mark {
  box-shadow: 0 -4px 0 #ffd64a, inset 0 -3px 0 rgba(0, 0, 0, 0.25);
}
.et-card .q,
.et-card .lk {
  position: absolute;
  font-style: normal;
  font-size: 11px;
  top: 2px;
}
.et-card .q {
  left: 4px;
  background: #111;
  color: #fff;
  border-radius: 4px;
  padding: 0 3px;
}
.et-card .lk {
  right: 4px;
}
.et-drop {
  height: 12px;
  border-radius: 4px;
}
.et-drop.mark {
  background: #ffd64a;
}
.et-sel {
  min-height: 20px;
  margin-bottom: 6px;
}
.et-sel .sw {
  display: inline-block;
  width: 12px;
  height: 12px;
  border-radius: 3px;
  vertical-align: middle;
}
.et-btns {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  margin-bottom: 8px;
}
.et-pad {
  display: flex;
  gap: 12px;
  align-items: center;
  margin: 6px 0 10px;
}
.et-pad canvas {
  width: 170px;
  height: 170px;
  cursor: crosshair;
  touch-action: none;
}
.et-padv {
  line-height: 1.6;
}
.et-sl {
  display: block;
  margin-bottom: 8px;
}
.et-sl span {
  display: block;
  margin-bottom: 2px;
}
.et-sl input {
  width: 100%;
}
/* v0.9.9 tab "📐 Bố cục": tiêu đề nhóm (v0.9.11 bỏ khung cam chỗ ô tràn — không còn ô thứ 6) */
.et-grp {
  margin: 12px 0 6px;
  padding-top: 8px;
  border-top: 1px solid #3d3470;
  font-weight: 700;
  color: #e3defc;
}
.et-foot {
  border-top: 1px solid #3d3470;
  margin-top: 10px;
  padding-top: 10px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

/* ---------- Khung iPhone (v0.9.4): iphone.html mở game với ?safe=trên,dưới (js/main.js thêm body.framed) ----------
 * Khung game (#app) nằm trong vùng an toàn của máy mô phỏng (dưới Dynamic Island / thanh trạng thái, trên thanh home) như
 * game thật trên iPhone. v0.9.16: mặt bàn gỗ (.bg-layer) phủ cả phần ngoài vùng an toàn và 2 dải hai bên khung, mọi bậc màn
 * (trước: nền thân trang vẽ lại --bg của #app). Lớp tối của popup / hướng dẫn / "Đang tạo màn" phủ luôn phần ngoài đó
 * (box-shadow lan ra ngoài #app, bố cục bên trong không đổi). */
body.framed {
  background: #fcc290;
}
body.framed #app {
  overflow: visible;
  box-shadow: none;
  --desk-w: 100vw;
}
body.framed #bg {
  top: calc(-1 * var(--safe-top, 0px));
  bottom: calc(-1 * var(--safe-bottom, 0px));
  left: calc((100% - 100vw) / 2);
  right: calc((100% - 100vw) / 2);
}
body.framed #bg-strip {
  left: calc((100% - 100vw) / 2);
  right: calc((100% - 100vw) / 2);
  bottom: calc(-1 * var(--safe-bottom, 0px));
  height: calc(calc(21 * var(--cw)) - var(--ui-boost-y, 0) * calc(2 * var(--cw)) + var(--safe-bottom, 0px));
}
body.framed #bg-strip .bg-layer {
  bottom: calc(calc(100 * var(--ch)) + var(--safe-top, 0px) + var(--safe-bottom, 0px) - var(--desk-h) - var(--desk-y));
}
body.framed #bg-top {
  left: calc((100% - 100vw) / 2);
  right: calc((100% - 100vw) / 2);
  top: calc(-1 * var(--safe-top, 0px));
  height: calc(calc(17 * var(--cw)) + var(--safe-top, 0px));
}
/* v0.9.46 (người chơi: "bấm xem ad reward ở UI win bị lỗi viền như này… bạn check lại toàn bộ và fix"): phần lan ra ngoài khung dùng đúng màu lớp tối của bảng đang mở (--dim, .overlay). Trước: viết tay từng loại, quảng cáo giả (.ad-bg) thiếu nên dải tai thỏ + dải đáy sáng hơn */
body.framed .overlay {
  box-shadow: 0 0 0 100vmax var(--dim);
}
/* v0.9.33 màn hình chính phủ kín khung; 2 dải hai bên khung cùng tông mặt bàn.
 * v0.9.46 (người chơi: "lỗi khi dùng khung iphone"): dải tai thỏ + dải thanh home dùng ảnh nối tiếp ảnh nền (tools/build-panels-ui.ps1), không còn mảng nâu phẳng phía trên. Nút vẽ sẵn trên ảnh phải nằm dưới tai thỏ nên ảnh không dời lên được */
body.framed #home {
  box-shadow: 0 0 0 100vmax #8f5a42;
}
body.framed #cshop {
  box-shadow: 0 0 0 100vmax #1f568f;
}
body.framed #home::before,
body.framed #home::after,
body.framed #cshop::before,
body.framed #cshop::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  pointer-events: none;
}
body.framed #home::before,
body.framed #cshop::before {
  bottom: 100%;
  height: var(--safe-top, 0px);
}
body.framed #home::after,
body.framed #cshop::after {
  top: 100%;
  height: var(--safe-bottom, 0px);
}
body.framed #home::before {
  background: url('../assets/home/bg-safe-top.jpg') 0 100% / 100% auto no-repeat #6b4034;
}
body.framed #home::after {
  background: url('../assets/home/bg-safe-bot.jpg') 0 0 / 100% 100% no-repeat;
}
/* mái sọc dọc: kéo dài hàng đầu ảnh lên dải tai thỏ */
body.framed #cshop::before {
  background: url('../assets/coinshop/bg-safe-top.jpg') 0 0 / 100% 100% no-repeat;
}
body.framed #cshop::after {
  background: url('../assets/coinshop/bg-safe-bot.jpg') 0 0 / 100% 100% no-repeat;
}
body.framed .win-fw {
  left: calc((100% - 100vw) / 2);
  top: calc(-1 * var(--safe-top, 0px));
  width: 100vw;
  height: calc(100% + var(--safe-top, 0px) + var(--safe-bottom, 0px));
}
body.framed #loading {
  box-shadow: 0 0 0 100vmax rgba(15, 12, 35, 0.8);
}
body.framed #boot {
  top: calc(-1 * var(--safe-top, 0px));
  bottom: calc(-1 * var(--safe-bottom, 0px));
  left: calc((100% - 100vw) / 2);
  right: calc((100% - 100vw) / 2);
}
body.framed #tut.tut-act,
body.framed #tut.tut-info {
  box-shadow: 0 0 0 100vmax rgba(8, 6, 24, 0.66);
}
body.framed #tut.tut-nodim {
  box-shadow: none;
}

/* v0.9.20 xem toàn bộ hàng xe: dải nền đáy còn lại mép mờ — xe cuộn xuống không bị cắt cứng (js/queue-view.js) */
body.queue-view #bg-strip,
body.framed.queue-view #bg-strip {
  height: calc(calc(6 * var(--cw)) + var(--safe-bottom, 0px));
}

/* ---------- v0.9.15 điện thoại xoay ngang (js/screen-fit.js thêm body.turn): game chỉ chơi dọc → phủ kín, nhắc xoay dọc ---------- */
#rotate {
  display: none;
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 1000;
  background: linear-gradient(#46446a, #35345a);
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 22px;
  padding: 0 24px;
  text-align: center;
  font-size: 18px;
  font-weight: 800;
}
body.turn #rotate {
  display: flex;
}
#rotate .phone {
  width: 40px;
  height: 70px;
  border: 5px solid #fff;
  border-radius: 10px;
  animation: rotate-hint 1.8s ease-in-out infinite;
}
@keyframes rotate-hint {
  0%,
  25% {
    transform: rotate(-90deg);
  }
  60%,
  100% {
    transform: rotate(0deg);
  }
}

/* ---------- v0.9.48 WebView đời cũ (luật Horus SDK: game phải chạy được từ Chrome 80). Máy mới không đọc 2 khối này, hình giữ nguyên ---------- */
/* Chrome < 104 chưa có translate, scale, rotate viết riêng: viết lại bằng transform */
@supports not (translate: 0) {
  #btn-menu {
    transform: translate(calc(var(--ui-menu-x, 0) * var(--cw)), max(calc(var(--ui-menu-y, 0) * calc(2 * var(--cw))), calc(4px - calc(2.4 * var(--cw)) - var(--hud-room, 0px)))) scale(var(--ui-menu-s, 1)) translateY(var(--press, 0px));
  }
  #btn-menu:active {
    --press: calc(0.4 * var(--cw));
  }
  #coins {
    transform: translate(calc(var(--ui-coin-x, 0) * var(--cw)), max(calc(var(--ui-coin-y, 0) * calc(2 * var(--cw))), calc(4px - calc(2.9 * var(--cw)) - var(--hud-room, 0px)))) scale(var(--ui-coin-s, 1));
  }
  #lvl {
    transform: translate(calc(var(--ui-lvl-x, 0) * var(--cw)), max(calc(var(--ui-lvl-y, 0) * calc(2 * var(--cw))), calc(4px - calc(2.5 * var(--cw)) - var(--hud-room, 0px)))) scale(var(--ui-lvl-s, 1));
  }
  .booster {
    transform: scale(var(--ui-boost-s, 1));
  }
  .booster:active {
    transform: scale(var(--ui-boost-s, 1)) translateY(calc(0.6 * var(--cw)));
  }
  .sp-band,
  #splash b {
    transform: rotate(-1.6deg);
  }
  .tut-bubble.tail-up::after {
    transform: rotate(180deg);
  }
}
/* Chrome < 84 chưa có gap của flex (CSS không dò riêng được, lấy mốc aspect-ratio = Chrome 88): dùng margin */
@supports not (aspect-ratio: 1) {
  #lvl,
  .card,
  .row,
  .win-btns,
  #pick-bar,
  #queue-bar,
  .tut-bubble,
  .feat-art {
    gap: 0;
  }
  #lvl .hard-badge {
    margin-right: calc(1.6 * var(--cw));
  }
  .card > * + * {
    margin-top: calc(2.6 * var(--cw));
  }
  .tut-bubble > * + * {
    margin-top: calc(2.2 * var(--cw));
  }
  .row > * + *,
  .win-btns > * + * {
    margin-left: calc(2.6 * var(--cw));
  }
  #pick-bar > * + *,
  #queue-bar > * + * {
    margin-left: calc(2 * var(--cw));
  }
  .feat-art > * + * {
    margin-left: calc(1 * var(--cw));
  }
}