@charset "utf-8";
/* ═══════════════════════════════════════════════════════════════════════════
   Dino4VN — hệ thống giao diện, viết lại 2026-08-30.
   ═══════════════════════════════════════════════════════════════════════════

   Site chuyển từ "tờ rơi giới thiệu" sang "cổng người chơi": có đăng nhập, có
   bảng xếp hạng, có dữ liệu của riêng từng người. Hai thứ đó có luật thiết kế
   khác hẳn nhau — một cái bán, một cái phục vụ — nên bản này dựng lại từ đầu
   thay vì vá tiếp bản cũ.

   ⚠️ BA RÀNG BUỘC CỨNG, đọc trước khi sửa:
   1. CSP: `style-src 'self'` -> KHÔNG inline `style=`. Quy ước repo còn chặt hơn:
      KHÔNG đụng `.style` trong JS. Muốn đổi bề rộng thanh thì đổi thuộc tính
      `width` của `<rect>` SVG (xem `gara.js`).
   2. `font-src 'self'` -> bộ chữ BẮT BUỘC tự host. Không Google Fonts.
   3. Mọi thứ động phải chiếm sẵn chỗ. Nội dung "hiện ra sau" khi JS trả lời là
      nhảy layout, và trang chủ có hero là LCP.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Bộ chữ ────────────────────────────────────────────────────────────────
   Be Vietnam Pro — thiết kế cho tiếng Việt, nên dấu chồng (ế ộ ữ ằ) dựng đúng.
   Nhiều bộ chữ đẹp dựng sai chỗ đó và chỉ lộ ra khi đọc một đoạn dài.
   Tách `unicode-range`: trang thuần latin không tải file tiếng Việt.
   `swap` — thà thấy chữ hệ thống ngay còn hơn nhìn khoảng trắng.               */
@font-face {
  font-family: "Be Vietnam Pro"; font-style: normal; font-weight: 400;
  font-display: swap; src: url("/assets/fonts/be-vietnam-pro-latin-400-normal.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Be Vietnam Pro"; font-style: normal; font-weight: 400;
  font-display: swap; src: url("/assets/fonts/be-vietnam-pro-vietnamese-400-normal.woff2") format("woff2");
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
@font-face {
  font-family: "Be Vietnam Pro"; font-style: normal; font-weight: 600;
  font-display: swap; src: url("/assets/fonts/be-vietnam-pro-latin-600-normal.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Be Vietnam Pro"; font-style: normal; font-weight: 600;
  font-display: swap; src: url("/assets/fonts/be-vietnam-pro-vietnamese-600-normal.woff2") format("woff2");
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
@font-face {
  font-family: "Be Vietnam Pro"; font-style: normal; font-weight: 800;
  font-display: swap; src: url("/assets/fonts/be-vietnam-pro-latin-800-normal.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Be Vietnam Pro"; font-style: normal; font-weight: 800;
  font-display: swap; src: url("/assets/fonts/be-vietnam-pro-vietnamese-800-normal.woff2") format("woff2");
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}

/* ── Mã màu & thang ───────────────────────────────────────────────────────── */
:root {
  --nen:      #07100C;   /* đêm trong rừng */
  --nen-1:    #0C1913;
  --nen-2:    #12241B;
  --nen-3:    #172E22;
  --vien:     #1E3A2C;
  --vien-sang:#2B5340;

  --chu:      #E9F3EC;
  --chu-mo:   #9EB5A7;
  --chu-nhat: #6C8579;

  --vang:     #E8B84B;   /* thương hiệu */
  --vang-dam: #C79A2E;
  --vang-chu: #221A05;
  --luc:      #4ADE80;   /* đang chạy */
  --do:       #F87171;   /* cảnh báo */

  --r-nho: 8px;
  --r:     14px;
  --r-to:  22px;
  --r-tron: 999px;

  --bong-1: 0 1px 2px rgb(0 0 0 / .4);
  --bong-2: 0 10px 30px -12px rgb(0 0 0 / .7);
  --bong-vang: 0 8px 26px -14px rgb(232 184 75 / .55);

  --font: "Be Vietnam Pro", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

  /* Thang chữ co giãn theo bề rộng màn — không cần media query cho từng cỡ. */
  --b--1: clamp(.82rem, .78rem + .2vw, .9rem);
  --b-0:  clamp(.95rem, .9rem + .25vw, 1.05rem);
  --b-1:  clamp(1.1rem, 1rem + .5vw, 1.3rem);
  --b-2:  clamp(1.35rem, 1.15rem + 1vw, 1.8rem);
  --b-3:  clamp(1.7rem, 1.3rem + 2vw, 2.6rem);
  --b-4:  clamp(2.1rem, 1.5rem + 3.4vw, 3.6rem);

  --cot: 1140px;   /* bề rộng nội dung tối đa */
}

/* ── Nền tảng ─────────────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  font: 400 var(--b-0)/1.65 var(--font);
  color: var(--chu);
  background: var(--nen);
  /* Hai vệt sáng rất nhạt để nền không phẳng lì. Không dùng ảnh -> 0 request. */
  background-image:
    radial-gradient(60rem 40rem at 15% -10%, rgb(74 222 128 / .07), transparent 60%),
    radial-gradient(50rem 34rem at 100% 0%, rgb(232 184 75 / .06), transparent 60%);
  background-attachment: fixed;
  overflow-wrap: break-word;
}

h1, h2, h3 { line-height: 1.2; margin: 0 0 .5em; font-weight: 800; letter-spacing: -.02em; }
h1 { font-size: var(--b-4); }
h2 { font-size: var(--b-3); }
h3 { font-size: var(--b-1); }
p, ul, ol, dl, table { margin: 0 0 1em; }
a { color: var(--vang); text-underline-offset: .18em; text-decoration-thickness: 1px; }
a:hover { color: #F5D27E; }
img { max-width: 100%; height: auto; }
:focus-visible { outline: 2px solid var(--vang); outline-offset: 3px; border-radius: 4px; }

/* 🔴 `[hidden]` PHẢI có `!important`.
   Trình duyệt đặt `[hidden] { display: none }` trong stylesheet của CHÍNH NÓ, mà
   mọi rule của ta đều là author style nên THẮNG nó. Hệ quả: bất cứ phần tử nào có
   `display:` tường minh — `.btn` là `inline-flex` — sẽ **vẫn hiện dù đã `hidden`**.

   Đã xảy ra thật trên production 2026-08-30: thanh app hiện ĐỒNG THỜI nút "Đăng
   nhập Steam" và tên tài khoản đã đăng nhập. JS chạy đúng (`vao.hidden = true`),
   CSS mới là chỗ sai. Không có lỗi nào trong console — chỉ nhìn mới thấy.

   Đặt Ở ĐÂY, ngay đầu file, để mọi rule sau không cần nhớ tới nó nữa. */
[hidden] { display: none !important; }

.wrap { width: min(100% - 2rem, var(--cot)); margin-inline: auto; }
.dim   { color: var(--chu-nhat); }
.muted { color: var(--chu-mo); }
.nho   { font-size: var(--b--1); }
.giua  { text-align: center; }
.mt-0 { margin-top: 0; } .mb-0 { margin-bottom: 0; }
.mt-2 { margin-top: 1rem; }
.so { font-variant-numeric: tabular-nums; font-feature-settings: "tnum"; }

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 99;
  background: var(--vang); color: var(--vang-chu); padding: 10px 16px;
  border-radius: 0 0 var(--r-nho) 0; font-weight: 800;
}
.skip:focus { left: 0; }

/* ═══ THANH APP ═══════════════════════════════════════════════════════════ */
.app {
  position: sticky; top: 0; z-index: 20;
  background: color-mix(in srgb, var(--nen) 88%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--vien);
}
.app__hang {
  display: flex; align-items: center; gap: 12px;
  min-height: 58px; padding-block: 6px;
}

.brand { display: inline-flex; align-items: center; gap: 9px; text-decoration: none; color: var(--chu); }
.brand img { border-radius: var(--r-nho); }
.brand__txt { font-weight: 800; font-size: var(--b-1); letter-spacing: -.02em; }
@media (max-width: 400px) { .brand__txt { display: none; } }

/* Trạng thái server — luôn chiếm chỗ, kể cả lúc chưa biết gì. */
.tt {
  margin: 0 auto 0 8px; display: inline-flex; align-items: center; gap: 7px;
  font-size: var(--b--1); color: var(--chu-mo); white-space: nowrap;
  min-width: 0; overflow: hidden; text-overflow: ellipsis;
}
.tt__cham {
  width: 8px; height: 8px; border-radius: 50%; flex: none;
  background: var(--chu-nhat); box-shadow: 0 0 0 3px rgb(108 133 121 / .18);
}
.tt--song  .tt__cham { background: var(--luc); box-shadow: 0 0 0 3px rgb(74 222 128 / .2); }
.tt--tat   .tt__cham { background: var(--do);  box-shadow: 0 0 0 3px rgb(248 113 113 / .2); }
@media (max-width: 560px) { .tt { display: none; } }

.tk { margin-left: auto; display: inline-flex; align-items: center; gap: 8px; }
.tk__ten { font-size: var(--b--1); font-weight: 600; color: var(--chu-mo); }
.tk__ra  { font-size: var(--b--1); font-weight: 600; }

/* ── Điều hướng ───────────────────────────────────────────────────────────
   Cuộn ngang trên màn hẹp; thanh cuộn ẩn nên PHẢI có vệt mờ ở mép phải làm
   dấu hiệu, nếu không người dùng không biết còn mục bị cắt. Comment cũ trong
   repo khẳng định "4 trang vừa màn 360px" — sai, nó đã tràn từ lâu.          */
.nav { border-top: 1px solid color-mix(in srgb, var(--vien) 55%, transparent); }
.nav__trong {
  display: flex; gap: 2px; overflow-x: auto; scrollbar-width: none;
  -webkit-mask-image: linear-gradient(to left, transparent 0, #000 26px);
  mask-image: linear-gradient(to left, transparent 0, #000 26px);
}
.nav__trong::-webkit-scrollbar { display: none; }
@media (min-width: 760px) { .nav__trong { -webkit-mask-image: none; mask-image: none; } }
.nav a {
  display: inline-flex; align-items: center; white-space: nowrap;
  min-height: 44px; padding: 0 13px; color: var(--chu-mo);
  text-decoration: none; font-size: var(--b--1); font-weight: 600;
  border-bottom: 2px solid transparent;
}
.nav a:hover { color: var(--chu); }
.nav a[aria-current="page"] { color: var(--vang); border-bottom-color: var(--vang); }

/* ═══ Khối nội dung ══════════════════════════════════════════════════════ */
.doan { padding-block: clamp(2.5rem, 6vw, 4.5rem); }
.doan--hep { padding-block: clamp(1.8rem, 4vw, 3rem); }
.doan + .doan { border-top: 1px solid color-mix(in srgb, var(--vien) 50%, transparent); }

.nhan {
  display: inline-block; font-size: var(--b--1); font-weight: 800;
  letter-spacing: .1em; text-transform: uppercase; color: var(--vang);
  margin-bottom: .6em;
}
.dat { font-size: var(--b-1); color: var(--chu-mo); max-width: 62ch; }

.the {
  background: linear-gradient(180deg, var(--nen-1), var(--nen));
  border: 1px solid var(--vien); border-radius: var(--r-to);
  padding: clamp(1.1rem, 3vw, 1.8rem); box-shadow: var(--bong-2);
}
.the--sang { border-color: var(--vien-sang); }
.the > :last-child { margin-bottom: 0; }

.luoi { display: grid; gap: 16px; }
@media (min-width: 720px) {
  .luoi--2 { grid-template-columns: repeat(2, 1fr); }
  .luoi--3 { grid-template-columns: repeat(3, 1fr); }
}

/* ── Nút ─────────────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .5em;
  min-height: 48px; padding: 12px 24px; border: 1px solid transparent;
  border-radius: var(--r-tron); font: 700 var(--b-0)/1.2 var(--font);
  text-decoration: none; cursor: pointer; color: var(--chu);
  background: var(--nen-2); border-color: var(--vien-sang);
  transition: background-color .15s, border-color .15s, transform .06s;
}
.btn:hover { background: var(--nen-3); color: var(--chu); }
.btn:active { transform: translateY(1px); }
.btn--chinh { background: var(--vang); color: var(--vang-chu); border-color: var(--vang); box-shadow: var(--bong-vang); }
.btn--chinh:hover { background: #F2C763; color: var(--vang-chu); }
.btn--nho { min-height: 38px; padding: 6px 14px; font-size: var(--b--1); }
.hang-nut { display: flex; flex-wrap: wrap; gap: 12px; }
@media (max-width: 479px) { .hang-nut .btn { flex: 1 1 100%; } }

.pill {
  display: inline-flex; align-items: center; gap: .4em;
  padding: 3px 11px; border-radius: var(--r-tron);
  border: 1px solid var(--vien-sang); background: var(--nen-2);
  font-size: var(--b--1); font-weight: 600; color: var(--chu-mo);
}
.pill--vang { border-color: var(--vang-dam); color: var(--vang); background: rgb(232 184 75 / .08); }
.pill--luc  { border-color: #2F6B45; color: var(--luc); background: rgb(74 222 128 / .08); }
.canhbao { color: var(--do); }
.canhbao::before { content: "⚠ "; }

/* ═══ HERO ═══════════════════════════════════════════════════════════════ */
.hero { position: relative; isolation: isolate; overflow: hidden; }
.hero__anh {
  position: absolute; inset: 0; z-index: -2;
  width: 100%; height: 100%; object-fit: cover;
}
.hero__phu {
  position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(180deg, rgb(7 16 12 / .55) 0%, rgb(7 16 12 / .82) 55%, var(--nen) 100%);
}
.hero__trong { padding-block: clamp(3.5rem, 12vw, 7rem); }
.hero h1 { max-width: 16ch; }
.hero__sub { font-size: var(--b-1); color: var(--chu-mo); max-width: 52ch; }

/* ═══ Thẻ trạng thái lớn (trang chủ) ═════════════════════════════════════ */
.tthai { display: grid; gap: 6px; }
.tthai__dau { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.tthai__ten { font-weight: 800; font-size: var(--b-1); }
.tthai__chinh { font-size: var(--b-2); font-weight: 800; }
.tthai__phu { color: var(--chu-mo); }
.tthai__meta { color: var(--chu-nhat); font-size: var(--b--1); }

/* ═══ BẢNG XẾP HẠNG ══════════════════════════════════════════════════════ */
/* Bục top-3. Đây là thứ chụp màn hình đăng Facebook có người bấm vào. */
.buc { display: grid; gap: 14px; margin-bottom: 22px; }
@media (min-width: 720px) {
  .buc { grid-template-columns: 1fr 1.15fr 1fr; align-items: end; }
  .buc__o:nth-child(1) { order: 2; } /* hạng 1 vào giữa và cao hơn */
  .buc__o:nth-child(2) { order: 1; }
  .buc__o:nth-child(3) { order: 3; }
}
.buc__o {
  background: linear-gradient(180deg, var(--nen-2), var(--nen-1));
  border: 1px solid var(--vien); border-radius: var(--r-to);
  padding: 18px 16px; text-align: center; box-shadow: var(--bong-2);
}
.buc__o--1 { border-color: var(--vang-dam); box-shadow: var(--bong-vang), var(--bong-2); }
.buc__hang {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; border-radius: 50%; font-weight: 800;
  background: var(--nen-3); color: var(--chu-mo); margin-bottom: 8px;
}
.buc__o--1 .buc__hang { background: var(--vang); color: var(--vang-chu); }
.buc__ten { font-weight: 800; font-size: var(--b-1); overflow-wrap: anywhere; }
.buc__loai { color: var(--chu-mo); font-size: var(--b--1); }
.buc__diem { font-size: var(--b-2); font-weight: 800; color: var(--vang); }
.buc__avt {
  width: 56px; height: 56px; border-radius: 50%; margin: 0 auto 8px;
  display: grid; place-items: center; font-weight: 800; font-size: var(--b-1);
  background: var(--nen-3); color: var(--chu-mo); border: 1px solid var(--vien-sang);
  object-fit: cover;
}

/* Bảng. Repo không có component bảng nào ngoài `.spec` 2 cột, và rule `table`
   chung giấu `thead` dưới 560px — với 7 cột là MẤT NGHĨA CỘT. Nên trên màn hẹp
   mỗi `<tr>` thành một thẻ, nhãn bơm từ `data-nhan` (hợp lệ: nằm trong
   stylesheet, không phải inline style).                                       */
.bxh { width: 100%; border-collapse: collapse; font-size: var(--b--1); }
.bxh caption { text-align: left; color: var(--chu-nhat); padding-bottom: 10px; }
.bxh th, .bxh td { padding: 11px 10px; text-align: left; border-bottom: 1px solid var(--vien); }
.bxh thead th { color: var(--vang); font-weight: 800; white-space: nowrap; }
.bxh tbody tr:hover { background: color-mix(in srgb, var(--nen-2) 60%, transparent); }
.bxh__ten { font-weight: 800; overflow-wrap: anywhere; }
.bxh__diem { font-weight: 800; color: var(--vang); }
.bxh tbody tr:nth-child(-n+3) .bxh__hang { color: var(--vang); font-weight: 800; }

@media (max-width: 660px) {
  .bxh thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .bxh, .bxh tbody, .bxh tr, .bxh td { display: block; width: auto; }
  /* 🔴 `caption` PHẢI đổi theo. Nó giữ `display: table-caption` trong khi cha đã
     thành `block` -> caption mồ côi, co lại theo nội dung. Đo được trên viewport
     360px thật: rộng **42px**, cao 119px, câu "Đang tải bảng xếp hạng…" xuống
     dòng MỖI CHỮ MỘT HÀNG. Đó là thứ người vào bằng điện thoại nhìn thấy đầu
     tiên, trước khi dữ liệu về. Không lỗi console, không cổng chặn nào bắt. */
  .bxh caption { display: block; }
  .bxh tr { padding: 12px 0; border-bottom: 1px solid var(--vien); }
  .bxh td { border: 0; padding: 2px 0; display: flex; gap: 10px; justify-content: space-between; }
  .bxh td::before { content: attr(data-nhan); color: var(--chu-nhat); }
  /* ⚠️ PHẢI viết `.bxh td.bxh__hang`, KHÔNG được `.bxh__hang` trần.
     `.bxh td` có độ đặc hiệu (0,1,1) — cao hơn `.bxh__hang` (0,1,0) — nên hai
     dòng dưới ở dạng trần **chưa từng chạy ngày nào**: thẻ trên điện thoại vẫn
     hiện "Hạng  #1" và "Người chơi  hung36acd" thay vì một dòng tiêu đề.
     Đo trên viewport 360px thật: `display` vẫn là `flex`, `::before` vẫn `"Hạng"`.
     CSS chết thì im lặng tuyệt đối — không cảnh báo, không lỗi console. */
  .bxh td.bxh__hang, .bxh td.bxh__ten { display: inline-block; }
  /* Hai ô nằm cạnh nhau thành dòng tiêu đề của thẻ. Không có khoảng này thì
     nó dính thành "#2Bui Anh Hung" — nhìn thấy ngay trên ảnh chụp 360px. */
  .bxh td.bxh__hang { margin-right: 6px; }
  .bxh td.bxh__hang::before, .bxh td.bxh__ten::before { content: none; }
  .bxh__ten { font-size: var(--b-0); }
}

/* Bốn ô tổng */
.tong { display: grid; gap: 12px; grid-template-columns: repeat(2, 1fr); margin-bottom: 20px; }
@media (min-width: 720px) { .tong { grid-template-columns: repeat(4, 1fr); } }
.tong__o { background: var(--nen-1); border: 1px solid var(--vien); border-radius: var(--r); padding: 14px; }
.tong__nhan { font-size: var(--b--1); color: var(--chu-nhat); }
.tong__so { font-size: var(--b-2); font-weight: 800; }

/* Nút chuyển tab mùa / mọi thời */
.tab { display: inline-flex; gap: 4px; padding: 4px; background: var(--nen-1);
       border: 1px solid var(--vien); border-radius: var(--r-tron); margin-bottom: 18px; }
.tab button {
  appearance: none; border: 0; background: transparent; cursor: pointer;
  color: var(--chu-mo); font: 700 var(--b--1)/1 var(--font);
  padding: 9px 16px; border-radius: var(--r-tron);
}
.tab button[aria-selected="true"] { background: var(--vang); color: var(--vang-chu); }

/* ═══ Bảng thông số (data-cfg) ═══════════════════════════════════════════ */
.thongso { width: 100%; border-collapse: collapse; }
.thongso th, .thongso td { padding: 13px 14px; text-align: left; vertical-align: top;
                           border-bottom: 1px solid var(--vien); }
.thongso th { width: 36%; color: var(--vang); font-weight: 800; }
.thongso td { color: var(--chu-mo); }
.thongso tr:last-child :is(th, td) { border-bottom: 0; }
@media (max-width: 560px) {
  .thongso, .thongso tbody, .thongso tr, .thongso th, .thongso td { display: block; width: auto; }
  .thongso tr { padding: 12px 0; border-bottom: 1px solid var(--vien); }
  .thongso th { padding: 0 0 4px; border: 0; }
  .thongso td { padding: 0; border: 0; }
}

/* ═══ Các bước ═══════════════════════════════════════════════════════════ */
.buoc { list-style: none; padding: 0; margin: 0; display: grid; gap: 14px; counter-reset: b; }
.buoc > li {
  counter-increment: b; position: relative; padding-left: 52px;
  background: var(--nen-1); border: 1px solid var(--vien);
  border-radius: var(--r); padding-block: 16px; padding-right: 16px;
}
.buoc > li::before {
  content: counter(b); position: absolute; left: 14px; top: 14px;
  width: 26px; height: 26px; border-radius: 50%;
  background: var(--vang); color: var(--vang-chu);
  display: grid; place-items: center; font-weight: 800; font-size: var(--b--1);
}
.buoc h3 { margin-bottom: .25em; font-size: var(--b-0); }
.buoc p { margin: 0; color: var(--chu-mo); }

/* ═══ FAQ — <details> thuần, không JS ════════════════════════════════════
   Bàn phím, screen reader, Ctrl+F đều chạy sẵn, và Google index được nội dung
   bên trong. Một accordion tự viết bằng JS thì mất cả bốn.                    */
.faq { background: var(--nen-1); border: 1px solid var(--vien);
       border-radius: var(--r); overflow: hidden; }
.faq details + details { border-top: 1px solid var(--vien); }
.faq summary { cursor: pointer; padding: 15px 18px; font-weight: 800; list-style: none; }
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: "+"; float: right; color: var(--vang); font-weight: 800; }
.faq details[open] summary::after { content: "−"; }
.faq__than { padding: 0 18px 15px; color: var(--chu-mo); }
.faq__than > :last-child { margin-bottom: 0; }

/* ═══ Danh sách loài ═════════════════════════════════════════════════════ */
.loai { display: grid; gap: 16px; grid-template-columns: 1fr; margin: 0; }
@media (min-width: 640px) { .loai { grid-template-columns: repeat(2, 1fr); } }
.loai dt { color: var(--vang); font-weight: 800; margin-bottom: .3em; }
.loai dd { margin: 0; color: var(--chu-mo); }
.sp { display: inline-flex; align-items: center; gap: 5px; }
.sp--on { color: var(--chu); font-weight: 600; }
.sp--on b { background: var(--luc); color: #06180E; border-radius: var(--r-tron);
            padding: 0 6px; font-size: .8em; }

/* ═══ Luật ═══════════════════════════════════════════════════════════════ */
.luat { list-style: none; padding: 0; margin: 0; display: grid; gap: 10px; }
.luat > li { padding-left: 30px; position: relative; }
.luat > li::before { content: "✕"; position: absolute; left: 6px; color: var(--do); font-weight: 800; }
.luat--ok > li::before { content: "✓"; color: var(--luc); }

/* ═══ Thẻ khủng long (gara / khủng long của tôi) ═════════════════════════ */
.dino { display: flex; flex-direction: column; gap: 12px;
        background: var(--nen-1); border: 1px solid var(--vien);
        border-radius: var(--r); padding: 14px; }
.dino__dau { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.dino__ten { font-weight: 800; font-size: var(--b-1); }
.dino__meta { color: var(--chu-nhat); font-size: var(--b--1); }
.chiso { display: grid; gap: 7px; }
.chiso__hang { display: flex; justify-content: space-between; font-size: var(--b--1); }
.chiso__so { color: var(--chu-mo); }
.o-mau { display: inline-block; width: 22px; height: 22px; border-radius: 6px;
         border: 1px solid var(--vien-sang); vertical-align: middle; }

/* ═══ Chân trang ═════════════════════════════════════════════════════════ */
.chan { border-top: 1px solid var(--vien); background: var(--nen-1);
        margin-top: clamp(2.5rem, 6vw, 4.5rem); padding-block: 28px; }
.chan__trong { display: grid; gap: 20px; }
@media (min-width: 720px) { .chan__trong { grid-template-columns: 1fr auto; align-items: start; } }
.chan__ten { font-weight: 800; font-size: var(--b-1); margin: 0 0 .2em; }
.chan__ds { list-style: none; padding: 0; margin: 0; display: grid; gap: 8px 24px;
            grid-template-columns: repeat(2, auto); }
.chan__ds a { color: var(--chu-mo); text-decoration: none; font-size: var(--b--1); }
.chan__ds a:hover { color: var(--vang); }

/* ═══ Trạng thái rỗng / lỗi ══════════════════════════════════════════════ */
.trong { text-align: center; padding: 34px 16px; color: var(--chu-nhat); }

/* ═══════════════════════════════════════════════════════════════════════════
   LỚP TƯƠNG THÍCH cho `gara.js` và `dino3d.js`
   ═══════════════════════════════════════════════════════════════════════════
   Hai file đó dựng DOM bằng JS với một bộ tên class riêng (`stat`, `swatch`,
   `act`, `v3d`, `grid--2`, `row`…). Chúng đang chạy production, vừa được cập
   nhật (trần chỉ số + xem 3D), và một luồng làm việc khác đang đụng tới chúng.

   Nên bản thiết kế mới KHÔNG đổi tên class trong JS — nó cấp style cho đúng
   những tên đó. Đổi tên trong JS là vừa có nguy cơ phá một tính năng đang chạy,
   vừa giẫm lên việc của người khác, để đổi lấy đúng một chút gọn gàng.

   ⚠️ Khi nào dọn được: chỉ sau khi `gara.js` được viết lại có chủ đích, và
   phải cùng một lần thay đổi.                                                 */
.grid { display: grid; gap: 16px; }
@media (min-width: 720px) { .grid--2 { grid-template-columns: repeat(2, 1fr); } }
.row { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }

.dino__top { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.dino__o { color: var(--chu-nhat); font-size: var(--b--1); }
.dino__nut { display: flex; flex-wrap: wrap; gap: 8px; margin-top: auto; }

/* Thanh chỉ số. Bề rộng do JS đặt qua thuộc tính `width` của <rect> SVG, KHÔNG
   qua `.style` — CSP `style-src 'self'` và quy ước repo cấm đụng `.style`. */
.stat { display: grid; gap: 3px; }
.stat__bar { display: block; width: 100%; height: 7px; border-radius: var(--r-tron);
             background: var(--nen-3); overflow: hidden; }
.stat__fill { fill: var(--luc); }
.stat--low .stat__fill { fill: var(--do); }
.stat__so { color: var(--chu-mo); font-size: var(--b--1); font-variant-numeric: tabular-nums; }

.swatch { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.swatch img, .swatch__pick {
  width: 26px; height: 26px; border-radius: 7px; border: 1px solid var(--vien-sang);
  padding: 0; cursor: pointer; background: var(--nen-2);
}
.swatch__pick { appearance: none; }

.act {
  appearance: none; display: inline-flex; align-items: center; justify-content: center;
  min-height: 40px; padding: 8px 16px; cursor: pointer;
  border: 1px solid var(--vien-sang); border-radius: var(--r-tron);
  background: var(--nen-2); color: var(--chu);
  font: 700 var(--b--1)/1.2 var(--font);
}
.act:hover { background: var(--nen-3); }
.act:disabled { opacity: .5; cursor: not-allowed; }
.act--primary { background: var(--vang); color: var(--vang-chu); border-color: var(--vang); }
/* Nut phu (Ngau nhien / Chep / Dan / Dat lai): bon cai tren mot hang, o man 360px
   `.act` mac dinh (40px cao, padding 16px) se tran. Van giu >=32px cho vua ngon tay. */
.act--nho { min-height: 32px; padding: 4px 10px; font-size: var(--b--1); }
.act--primary:hover { background: #F2C763; }

.pill--gold { border-color: var(--vang-dam); color: var(--vang); background: rgb(232 184 75 / .08); }

/* Khung xem 3D — `dino3d.js` không đụng `.style`, nó gọi setSize(w, h, false).

   🔴 HAI LỖI HIỂN THỊ ĐÃ ĐO ĐƯỢC VÀ SỬA Ở ĐÂY (2026-08-30). Cả hai đều câm.

   (a) CHIỀU CAO KHAI Ở HAI CHỖ. Bản trước: `.v3d{min-height:260px}` nhưng
       `.v3d__canvas{height:320px}`. `.v3d__san` là `position:absolute` nên nằm
       NGOÀI luồng ⇒ chiều cao `.v3d` do `min-height` quyết (260). `dino3d.js`
       lấy `san.clientHeight` làm buffer, nên đo được trên máy thật:
           buffer 1138x258   ·   canvas CSS 320px
       ⇒ ảnh 3D bị KÉO DỌC 320/258 = 1,24 lần rồi bị `overflow:hidden` xén hai
       đầu. Không lỗi, không cảnh báo — chỉ là con dino hơi "cao" hơn thật.
       Nay chiều cao khai ĐÚNG MỘT CHỖ (`.v3d`), canvas ăn theo 100%.

   (b) `.v3d__ghi` BỊ CANVAS PHỦ LÊN. Đo trên `/gara`: `.v3d__ghi` top=1376,
       `.v3d__san` top=1376 — trùng khít, mà canvas thì đục (`alpha:false`).
       Nghĩa là dòng chú thích 132 ký tự, TRONG ĐÓ CÓ CẢNH BÁO
       "⚠ ánh xạ vùng CHƯA xác nhận", chưa từng được ai nhìn thấy.
       Nay `.v3d__ghi` phải nằm NGOÀI `.v3d` (xem `gara.njk`/`skin.njk`);
       `dino3d.js` tìm nó trên cả trang nên đặt ở đâu cũng được.               */
.v3d { position: relative; background: var(--nen); border: 1px solid var(--vien);
       border-radius: var(--r); overflow: hidden; min-height: 320px; }
.v3d__canvas { display: block; width: 100%; height: 100%; }
.v3d__san { position: absolute; inset: 0; display: grid; place-items: center; }
.v3d__msg { color: var(--chu-nhat); font-size: var(--b--1); padding: 16px; text-align: center; }
.v3d__ghi { color: var(--chu-nhat); font-size: var(--b--1); padding: 8px 2px; margin: 0; }
.v3d__quay { position: absolute; right: 10px; bottom: 10px; }
/* Trang /skin: khung là NỘI DUNG CHÍNH nên cho nó cao hẳn. Vẫn chỉ MỘT chỗ khai. */
.v3d--to { min-height: min(60vh, 520px); }

/* Đăng xuất: kín đáo, không tranh chỗ với "Trang của tôi". Nó là lối thoát,
   không phải hành động chính. */
.tk__thoat {
  background: none; border: 0; padding: .25rem .4rem; cursor: pointer;
  color: var(--chu-nhat); font: inherit; font-size: var(--b--1);
  border-radius: var(--r-nho);
}
.tk__thoat:hover { color: var(--chu); background: var(--nen-2); }
.tk__thoat[disabled] { opacity: .5; cursor: default; }
@media (max-width: 460px) { .tk__thoat { display: none; } }

/* ══════════════════════════════════════════════════════════════════════════
   BẢN ĐỒ  (/map) — trang TOÀN MÀN HÌNH
   ══════════════════════════════════════════════════════════════════════════
   Trang này là bản đồ, không phải bài viết có bản đồ. Bản đầu đặt bản đồ giữa
   một trang dài toàn chữ và người dùng phải cuộn mới thấy thứ mình vào để xem.

   Chiều cao dùng FLEX, không dùng `calc(100svh - <số>px)`: chiều cao thanh app
   đổi theo cỡ chữ và theo màn (nav xuống dòng), nên mọi con số cứng đều sẽ sai
   ở một cỡ màn nào đó — và sai kiểu bản đồ bị cắt hoặc trang thừa thanh cuộn.

   🔴 MỌI màu/cỡ chữ của NHÃN CHỮ nằm ở đây, không nằm trong `map.js`: CSP là
      `style-src 'self'` nên `style="…"` do JS sinh ra bị chặn câm.
   ⚠️ NHƯNG màu CHẤM/HÌNH thì KHÔNG ở đây — `preferCanvas: true` khiến chúng
      được vẽ bằng canvas, nơi CSS không với tới. Xem `MAU` trong `map.js` và
      CLAUDE.md §2.39. Thêm `.poi-cham--*` vào đây là dựng lại một rule chết. */

body.la-bando { height: 100svh; display: flex; flex-direction: column; overflow: hidden; }
body.la-bando #main { flex: 1; min-height: 0; display: flex; }

/* Stacking context riêng: control của Leaflet (z-index 400/800/1000) sẽ vẽ ĐÈ
   LÊN thanh app dính (z-index 20) nếu thiếu dòng này. */
/* 🔴 `overflow: hidden` KHONG phai lam dep. Bang dieu khien luc dong nam o
   `translateX(101%)` — tuc la no van CHIEM CHO ben phai khung. Do duoc o 360px:
   `body.scrollWidth` = 680 thay vi 360, tuc trang cuon ngang duoc mot man hinh
   sang phai vao vung trong. `body { overflow:hidden }` KHONG cuu duoc vi phan
   tho ra nam trong `.bd`, khong phai trong body. */
.bd { position: relative; z-index: 0; flex: 1; min-height: 0; overflow: hidden;
  background: var(--nen); }
#bando { position: absolute; inset: 0; background: var(--nen); }
.leaflet-container { background: var(--nen); font: inherit; }
.leaflet-tooltip { font: inherit; font-size: var(--b--1); }
.bd__noscript { position: absolute; inset: auto 0 auto 0; top: 40%; text-align: center;
  color: var(--chu-mo); padding: 1rem; }

/* ── Thanh trên: danh tính + trạng thái. Nổi trên bản đồ, không chiếm chỗ. ── */
.bd__tren {
  position: absolute; z-index: 500; top: .6rem; left: .6rem;
  display: flex; align-items: baseline; gap: .7rem; flex-wrap: wrap;
  max-width: calc(100% - 1.2rem);
  padding: .45rem .8rem; border-radius: var(--r-nho);
  background: color-mix(in srgb, var(--nen) 82%, transparent);
  border: 1px solid var(--vien); backdrop-filter: blur(6px);
}
.bd__ten { margin: 0; font-size: var(--b-1); letter-spacing: -.01em; }
.bd__tt { margin: 0; display: flex; align-items: center; gap: .4rem;
  color: var(--chu-mo); font-size: var(--b--1); }

/* Nút zoom tự làm (`L.control.zoom` bị tắt — xem ghi chú trong `map.njk`).
   Đặt dưới thanh trên để hai thứ không chồng nhau. */
.bd__zoom {
  position: absolute; z-index: 600; top: 3.6rem; left: .6rem;
  display: flex; flex-direction: column; gap: 1px;
  border-radius: var(--r-nho); overflow: hidden; box-shadow: var(--bong-1);
}
.bd__zoom button {
  width: 36px; height: 36px; border: 1px solid var(--vien);
  background: color-mix(in srgb, var(--nen) 88%, transparent);
  color: var(--chu); font: 400 20px/1 var(--font); cursor: pointer;
  backdrop-filter: blur(6px);
}
.bd__zoom button:hover:not([disabled]) { background: var(--nen-2); color: var(--vang); }
.bd__zoom button[disabled] { opacity: .35; cursor: default; }

/* ── Nút mở bảng ─────────────────────────────────────────────────────────── */
.bd__nut-bang {
  position: absolute; z-index: 600; top: .6rem; right: .6rem;
  padding: .5rem .9rem; border-radius: var(--r-nho);
  background: var(--vang); color: var(--vang-chu); border: 0;
  font: 600 var(--b--1)/1 var(--font); cursor: pointer;
  box-shadow: var(--bong-1);
}
.bd__nut-bang:hover { background: #F5D27E; }

/* ── Bảng điều khiển ─────────────────────────────────────────────────────
   Điện thoại: phủ gần hết màn khi mở. Desktop: cột bên phải.
   Dùng `translate` để trượt — GPU lo, không reflow. */
.bd__bang {
  position: absolute; z-index: 700; top: 0; right: 0; bottom: 0;
  width: min(340px, 88vw);
  display: flex; flex-direction: column;
  background: color-mix(in srgb, var(--nen-1) 96%, transparent);
  border-left: 1px solid var(--vien);
  backdrop-filter: blur(10px);
  transform: translateX(101%);
  transition: transform .18s ease-out;
}
@media (prefers-reduced-motion: reduce) { .bd__bang { transition: none; } }
.bang-mo .bd__bang { transform: translateX(0); }
.bang-mo .bd__nut-bang { display: none; }

.bd__bang-tren {
  display: flex; align-items: center; justify-content: space-between;
  gap: .5rem; padding: .7rem .9rem; border-bottom: 1px solid var(--vien);
  flex: none;
}
.bd__dong { background: none; border: 0; color: var(--chu-mo); cursor: pointer;
  font-size: 1.1rem; line-height: 1; padding: .3rem .5rem; border-radius: var(--r-nho); }
.bd__dong:hover { color: var(--chu); background: var(--nen-2); }

.bd__cuon { flex: 1; min-height: 0; overflow-y: auto; padding: .9rem; }
.bd__khoi { margin-top: 1.1rem; }
.bd__h2 { font-size: var(--b--1); text-transform: uppercase; letter-spacing: .06em;
  color: var(--chu-nhat); margin: 0 0 .5rem; font-weight: 700; }
.bd__nhan { display: block; font-size: var(--b--1); color: var(--chu-mo); margin: .6rem 0 .3rem; }

/* ── Tìm địa danh ────────────────────────────────────────────────────────── */
.bd__o-tim {
  width: 100%; padding: .5rem .7rem; border-radius: var(--r-nho);
  background: var(--nen); border: 1px solid var(--vien-sang); color: var(--chu);
  font: inherit; font-size: var(--b--1);
}
.bd__kq { display: flex; flex-direction: column; gap: 2px; margin-top: .35rem; }
.bd__kq-o {
  display: flex; justify-content: space-between; gap: .6rem; text-align: left;
  padding: .42rem .6rem; border-radius: var(--r-nho);
  background: var(--nen-2); border: 1px solid transparent; color: var(--chu);
  font: inherit; font-size: var(--b--1); cursor: pointer;
}
.bd__kq-o:hover { border-color: var(--vien-sang); background: var(--nen-3); }
.bd__kq-nhom { color: var(--chu-nhat); flex: none; font-variant-numeric: tabular-nums; }

/* ── Hàng chọn (lớp + tuỳ chọn) ──────────────────────────────────────────── */
.bd__o {
  display: flex; align-items: center; gap: .55rem;
  padding: .42rem .1rem; cursor: pointer; font-size: var(--b--1);
  border-bottom: 1px solid color-mix(in srgb, var(--vien) 45%, transparent);
}
.bd__o:last-child { border-bottom: 0; }
.bd__o input { accent-color: var(--vang); width: 18px; height: 18px; flex: none; }
.bd__cham { width: 10px; height: 10px; border-radius: 999px; flex: none; }
.bd__so { margin-left: auto; color: var(--chu-nhat); font-variant-numeric: tabular-nums; }
.bd__lop { border: 0; padding: 0; margin: 0; }
.bd__truot { width: 100%; accent-color: var(--vang); }

.bd__cham--kv { background: #CBD5E1; }  .bd__cham--dd { background: #E2E8F0; }
.bd__cham--nc { background: #38BDF8; }  .bd__cham--sa { background: #3FB950; }
.bd__cham--dc { background: #D29922; }  .bd__cham--tt { background: #C56B6B; }
.bd__cham--ha { background: #A78BFA; }  .bd__cham--mu { background: #C9A227; }
.bd__cham--ac { background: #E07A5F; }  .bd__cham--an { background: #4CC9F0; }
.bd__cham--cq { background: #F4A261; }  .bd__cham--cc { background: #C9A227; }
.bd__cham--ch { background: #E07BE0; }  .bd__cham--ck { background: #7BC47F; }
.bd__cham--nm { background: #B08968; }

/* ── Vị trí của tôi ──────────────────────────────────────────────────────── */
.bd__o-toi {
  display: inline-block; margin: 0 0 .4rem;
  padding: .25rem .65rem; border-radius: var(--r-tron);
  background: var(--vang); color: var(--vang-chu);
  font-weight: 800; font-size: var(--b--1); letter-spacing: .02em;
}

/* ── Chip loài ───────────────────────────────────────────────────────────── */
.bd__loai { display: flex; flex-wrap: wrap; gap: .35rem; }
.bd__loai-o {
  display: inline-flex; align-items: baseline; gap: .35rem;
  padding: .25rem .55rem; border-radius: var(--r-tron);
  background: var(--nen-2); border: 1px solid var(--vien);
  font-size: var(--b--1);
}
.bd__loai-n { color: var(--vang); font-weight: 800; font-variant-numeric: tabular-nums; }


/* ── Chấm "chỗ tôi đứng" ─────────────────────────────────────────────────
   Khớp với lớp phủ launcher (`launcher/src/renderer/gate0.html`): hai vòng rỗng
   lệch pha nửa nhịp, cùng màu `#7CF2A6`. Lý do thiết kế lấy nguyên từ bên đó:

   🔴 VÒNG RỖNG, không phải hình tròn đặc. Vòng nở tới ~3 lần bán kính, tô đặc là
      NUỐT MẤT địa hình ngay quanh mình — đúng phần người chơi cần đọc nhất khi
      mở bản đồ ra. Nó phải CHỈ chỗ, không được CHE chỗ.
   🔴 HAI vòng lệch nửa nhịp. Một vòng đơn lẻ chỉ đọc ra là "có gì đó nhấp nháy";
      hai vòng nối nhau cho mắt thấy HƯỚNG LAN TOẢ nên não đọc ra "đây là một
      điểm" nhanh hơn hẳn.

   Cỡ vòng theo `clamp()`: launcher để cố định 132px cho khung 846px, còn khung
   web co từ 345px (điện thoại) tới ~1900px. Giữ 132px trên điện thoại là vòng
   chiếm 38% bề ngang màn — che mất chính thứ nó chỉ vào. */
@keyframes nhipVong {
  0%   { transform: translate(-50%, -50%) scale(.30); opacity: .9;  border-width: 3px; }
  70%  { opacity: .16; }
  100% { transform: translate(-50%, -50%) scale(1);   opacity: 0;   border-width: 1px; }
}
.ct { pointer-events: none; }
.ct__vong {
  position: absolute; left: 0; top: 0;
  width: clamp(96px, 19vw, 150px); height: clamp(96px, 19vw, 150px);
  border-radius: 50%; border: 3px solid #7CF2A6; pointer-events: none;
  animation: nhipVong 3.6s cubic-bezier(.25, .55, .3, 1) infinite;
}
.ct__vong--sau { animation-delay: 1.8s; }
/* Nhãn "300 m" / "1 km" trên vòng tầm. */
.ct__tam-nhan {
  white-space: nowrap; pointer-events: none;
  transform: translate(-50%, -50%);
  font: 600 9px/1 var(--font); color: rgba(159, 216, 182, .8);
  background: rgba(10, 15, 20, .75); padding: 2px 5px; border-radius: 3px;
}
.ct__cham {
  position: absolute; left: 0; top: 0; width: 14px; height: 14px;
  margin: -7px 0 0 -7px; border-radius: 50%; background: #B6FFD0;
  box-shadow: 0 0 0 2px #04120B, 0 0 10px rgba(182, 255, 208, .95);
}
/* Người bật "giảm chuyển động" vẫn PHẢI thấy mình ở đâu — giữ một vòng đứng yên
   ở độ mờ đọc được, chỉ bỏ phần nhấp nháy. Ẩn hẳn là lấy mất tính năng. */
@media (prefers-reduced-motion: reduce) {
  .ct__vong { animation: none; opacity: .5; transform: translate(-50%, -50%) scale(.55); }
  .ct__vong--sau { display: none; }
}

/* ── Nhãn chữ trên bản đồ ────────────────────────────────────────────────
   Nền bản đồ là ảnh SÁNG (đảo xanh trên biển xanh), nên nhãn phải là chữ SÁNG
   kèm bóng đổ TỐI dày — ngược với phần còn lại của site. */
.poi-nhan, .o-luoi {
  background: none !important; border: none !important;
  white-space: nowrap; pointer-events: none;
  text-shadow: 0 0 3px #04120B, 0 0 6px #04120B, 0 1px 2px #04120B;
}
.poi-nhan { font-weight: 600; font-size: 11px; }
.o-luoi { font-weight: 800; font-size: 26px; color: #C7D6CB; opacity: .5; }

.poi-nhan--kv { color: #CBD5E1; font-size: 13px; letter-spacing: .04em; }
.poi-nhan--dd { color: #E2E8F0; }
.poi-nhan--nc { color: #7DD3FC; }
.poi-nhan--sa { color: #6EE7A0; }
.poi-nhan--dc { color: #FBBF52; }
.poi-nhan--tt { color: #F19A9A; }
.poi-nhan--ha { color: #C4B5FD; }
.poi-nhan--mu { color: #E4CE86; }

/* Chỉ dùng cho nhãn ẩn với trình đọc màn hình (legend của fieldset). */
.sr { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

/* ══════════════════════════════════════════════════════════════════════════
   TRÌNH SỬA NGOẠI TRANG  (/skin)
   ══════════════════════════════════════════════════════════════════════════
   Bố cục hai cột: khung 3D bên trái (dính khi cuộn), cột điều khiển bên phải.
   Điện thoại xếp dọc và khung 3D LÊN TRÊN — nó là thứ người ta vào để xem.

   🔴 Không một dòng nào ở đây được thay bằng `.style` trong JS. Ba thứ dễ bị
      cám dỗ nhất, và cách làm đúng:
        · ô màu       -> chính `<input type="color">` tự vẽ, không cần CSS
        · khoá/mở     -> `[aria-pressed="true"]`, không phải class màu
        · khe vô hiệu -> `.khe--tat`, đặt bằng classList (KHÔNG phải .style)   */
.skin { display: grid; gap: 16px; }
.skin__xem { display: grid; gap: 8px; }
@media (min-width: 900px) {
  .skin { grid-template-columns: minmax(0, 1.5fr) minmax(330px, 1fr); align-items: start; }
  /* Cột phải dài hơn cột trái -> cho khung 3D dính lại để đổi màu là thấy ngay.
     `top` bằng chiều cao thanh app, nếu không khung chui xuống dưới nav. */
  .skin__xem { position: sticky; top: 84px; }
}

/* Thanh trượt trưởng thành. `accent-color` là cách DUY NHẤT tô màu thanh trượt
   mà không cần một đống pseudo-element riêng cho từng trình duyệt. */
.truot { display: grid; grid-template-columns: auto 1fr 5ch; gap: 10px; align-items: center;
         font-size: var(--b--1); color: var(--chu-mo); }
.truot input[type="range"] { width: 100%; accent-color: var(--vang); min-height: 24px; }
.truot output { font-variant-numeric: tabular-nums; text-align: right; color: var(--chu); }

/* Một dòng màu: [ô màu] [tên] [hex] [khoá] [đặt lại] */
.khe { display: grid; grid-template-columns: 26px 1fr 9ch auto auto; gap: 8px;
       align-items: center; padding: 4px 0; }
.khe__ten { font-size: var(--b--1); }
.khe__hex {
  font: 400 var(--b--1)/1.4 ui-monospace, "Cascadia Mono", Consolas, monospace;
  width: 100%; min-height: 34px; padding: 4px 6px;
  color: var(--chu); background: var(--nen-2);
  border: 1px solid var(--vien); border-radius: var(--r-nho);
}
.khe__hex:focus-visible { outline: 2px solid var(--vang); outline-offset: 1px; }
.khe__hex[aria-invalid="true"] { border-color: var(--do); }
.khe__nut {
  appearance: none; cursor: pointer; min-width: 34px; min-height: 34px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--chu-mo); background: var(--nen-2);
  border: 1px solid var(--vien); border-radius: var(--r-nho);
  font-size: var(--b--1); line-height: 1;
}
.khe__nut:hover { background: var(--nen-3); color: var(--chu); }
/* Khoá: KHÔNG chỉ đổi màu — đổi cả nền và viền, vì màu không bao giờ được là
   tín hiệu duy nhất. `aria-pressed` lo phần người dùng đọc màn hình. */
.khe__nut[aria-pressed="true"] {
  color: var(--vang); border-color: var(--vang-dam); background: rgb(232 184 75 / .12);
}
/* Khe mà loài đang chọn KHÔNG vẽ được trên bản xem trước. Vẫn nhập và vẫn áp
   vào game được — chỉ là không thấy. Làm mờ + có chú thích, KHÔNG vô hiệu hoá. */
.khe--tat .khe__ten { color: var(--chu-nhat); }
.khe--tat .khe__ten::after { content: " ·"; }

.khe__nhom { display: grid; gap: 2px; }
/* Hàng nút của thẻ Màu sắc (ngẫu nhiên / chép / dán / đặt lại). */
.the__dau { display: flex; align-items: center; justify-content: space-between;
            gap: 10px; flex-wrap: wrap; margin-bottom: 8px; }
.the__dau h2 { margin: 0; }
.nut-nho { display: flex; gap: 6px; flex-wrap: wrap; }

/* Lưới các ô nhập nhỏ (Biến thể / Hoạ tiết / Chủ đề). */
.oso { display: grid; grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); gap: 10px; }
.oso label { display: grid; gap: 4px; font-size: var(--b--1); color: var(--chu-mo); }
.oso input {
  font: 400 var(--b--1)/1.4 var(--font); min-height: 38px; padding: 4px 8px;
  color: var(--chu); background: var(--nen-2);
  border: 1px solid var(--vien); border-radius: var(--r-nho);
}

/* Đực/Cái: hai nút, trạng thái bằng aria-pressed. */
.gioi { display: inline-flex; border: 1px solid var(--vien); border-radius: var(--r-tron);
        overflow: hidden; }
.gioi button {
  appearance: none; cursor: pointer; border: 0; padding: 8px 18px; min-height: 38px;
  font: 700 var(--b--1)/1.2 var(--font); color: var(--chu-mo); background: transparent;
}
.gioi button[aria-pressed="true"] { color: var(--vang-chu); background: var(--vang); }

/* Chuỗi máy đọc: mã băm SHA256, lệnh PowerShell. Dùng ở trang tải launcher.
   ⚠️ `overflow-wrap: anywhere` là BẮT BUỘC, không phải trang trí: một chuỗi băm dài 64
   ký tự không có dấu cách nào, nên trên điện thoại nó sẽ ĐẨY TOÀN TRANG RỘNG RA và làm
   cả site cuộn ngang. Đây đúng là thứ `web/README.md` cấm.
   Cố ý KHÔNG đặt luật cho thẻ `code` trần: site này chưa từng dùng nó, và thêm một luật
   toàn cục cho một trang là cách những thứ nhỏ bắt đầu đánh nhau. */
.bam {
  font: 400 var(--b--1)/1.5 ui-monospace, "Cascadia Mono", Consolas, monospace;
  display: inline-block; padding: 6px 9px;
  color: var(--chu); background: var(--nen-2);
  border: 1px solid var(--vien); border-radius: var(--r-nho);
  overflow-wrap: anywhere; word-break: break-all; max-width: 100%;
}

/* ⚠️ KHÔNG có rule màu cho chấm/hình ở đây — CÓ CHỦ Ý.
   Bản đồ chạy `preferCanvas: true`, nên chấm và hình được vẽ bằng `ctx.fill()`
   chứ không phải phần tử DOM. `className` của Leaflet không có gì để bám và CSS
   KHÔNG BAO GIỜ được áp. Đã dẫm phải: mọi chấm ra màu xanh mặc định trong khi
   CSS trông hoàn toàn đúng, và không có lỗi nào ở đâu cả.
   Màu chấm/hình nằm trong bảng `MAU` của `map.js`. Đừng thêm lại vào đây —
   thêm là dựng lại đúng cái bẫy đó cho người sau.
   (Nhãn CHỮ thì ngược lại: chúng là `divIcon` = DOM thật, nên `.poi-nhan--*`
   ở trên hoạt động bình thường.) */


/* Bảng bật/tắt lớp: checkbox thật, không phải L.control.layers.
   Vùng chạm đủ to cho ngón tay, đọc được bằng bàn phím và trình đọc màn hình. */
.bando-lop { border: 0; padding: 0; margin: 0 0 .5rem; }
.bando-lop legend { padding: 0 0 .4rem; }
.bando-lop__o {
  display: flex; align-items: center; gap: .55rem;
  padding: .42rem .1rem; cursor: pointer; font-size: var(--b--1);
  border-bottom: 1px solid color-mix(in srgb, var(--vien) 45%, transparent);
}
.bando-lop__o:last-child { border-bottom: 0; }
.bando-lop__o input { accent-color: var(--vang); width: 18px; height: 18px; flex: none; }
.bando-lop__cham { width: 10px; height: 10px; border-radius: 999px; flex: none; }
.bando-lop__so { margin-left: auto; color: var(--chu-nhat); font-variant-numeric: tabular-nums; }

.bando-lop__cham--kv { background: #CBD5E1; }
.bando-lop__cham--dd { background: #E2E8F0; }
.bando-lop__cham--nc { background: #38BDF8; }
.bando-lop__cham--sa { background: #3FB950; }
.bando-lop__cham--dc { background: #D29922; }
.bando-lop__cham--tt { background: #C56B6B; }
.bando-lop__cham--ha { background: #A78BFA; }
.bando-lop__cham--mu { background: #C9A227; }
.bando-lop__cham--ac { background: #E07A5F; }
.bando-lop__cham--an { background: #4CC9F0; }
.bando-lop__cham--cq { background: #F4A261; }
.bando-lop__cham--cc { background: #C9A227; }
.bando-lop__cham--ch { background: #E07BE0; }
.bando-lop__cham--ck { background: #7BC47F; }
.bando-lop__cham--nm { background: #B08968; }

/* Thanh trạng thái riêng của trang (thanh app đã có một cái, nhưng ở 560px trở
   xuống nó bị ẩn — mà đây đúng là trang cần biết server có ai không). */
.bando-tt { display: flex; align-items: center; gap: .5rem; color: var(--chu-mo); margin: 0; }

/* Chip loài. `flex-wrap` vì 20 loài không bao giờ vừa một hàng ở 360px. */
.bando-loai { display: flex; flex-wrap: wrap; gap: .45rem; }
.bando-loai__o {
  display: inline-flex; align-items: baseline; gap: .4rem;
  padding: .3rem .6rem; border-radius: var(--r-tron);
  background: var(--nen-2); border: 1px solid var(--vien);
  font-size: var(--b--1);
}
.bando-loai__n { color: var(--vang); font-weight: 800; font-variant-numeric: tabular-nums; }
.bando-ghicong { margin: 0; }

/* ═══════════════════════════════════════════════════════════════════════════
   TRANG /me — hồ sơ + con đang chơi + tiến độ Prime
   ═══════════════════════════════════════════════════════════════════════════
   THÊM VÀO CUỐI, không sửa một rule nào ở trên: file này thuộc một luồng làm
   việc khác đang chạy song song, và nav mới của họ phụ thuộc
   `[hidden]{display:none!important}` ở đầu file — đừng gỡ dòng đó.

   Phần lớn trang dùng lại class có sẵn (.the .doan .nhan .pill .stat .luat .v3d
   .luoi .row .dim). `.chiso` ở khối "Thẻ khủng long" phía trên vốn là CSS chết,
   khai sẵn dưới đúng tiêu đề "gara / khủng long của tôi" — nay nó có người dùng. */

.me__ten { font-size: var(--b-3); font-weight: 800; letter-spacing: -.02em;
           margin: clamp(1.4rem, 4vw, 2.2rem) 0 .4em;
           /* "Pachycephalosaurus" ở 28px trên màn 360px là ~277px trong ~291px khả
              dụng — sát tới mức không nên đánh cược. Cùng cách xử lý với `.buc__ten`. */
           overflow-wrap: anywhere; }

/* Huy hiệu Prime đẩy sang phải trên màn rộng. Dưới 560px thì bỏ, vì khi hàng đã
   xuống dòng thì `margin-left:auto` đẩy nó ra một mình bên phải và trông như bị
   rơi khỏi nhóm. */
.day-phai { margin-left: auto; }
@media (max-width: 559px) { .day-phai { margin-left: 0; } }

.luoi--3d { display: grid; gap: 16px; margin-top: 14px; }
@media (min-width: 720px) {
  .luoi--3d { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); align-items: start; }
}

/* Khung 3D của /me: KHÔNG dùng tầng tuyệt đối như `.v3d` gốc.
   🔴 `dino3d.js` lấy kích thước từ `CANVAS.parentElement` rồi gọi
   `setSize(w, h, false)`. Nếu sân và canvas không cùng cỡ thì ảnh bị kéo giãn —
   và không có lỗi nào hiện ra, chỉ là con dino trông hơi sai tỉ lệ. Ở đây canvas
   quyết định chiều cao, sân bám theo, còn dòng thông báo phủ lên trên. */
.v3d--me .v3d__san { position: static; display: block; }
.v3d--me .v3d__canvas { height: 300px;
  /* 🔴 Sửa lỗi ĐIỆN THOẠI đáng giá nhất ở trang này. `dino3d.js` gắn `pointermove`
     với `{passive:false}` + `preventDefault()`. Trên một canvas cao 300px chiếm hết
     bề ngang màn 360px, người vuốt để CUỘN QUA sẽ bị kẹt xoay mô hình và không
     xuống được phần dưới trang. `pan-y` trả cử chỉ dọc lại cho trình duyệt và giữ
     kéo ngang cho việc xoay.
     Đánh đổi phải chấp nhận: xoay theo chiều DỌC (camPhi) không dùng được trên
     cảm ứng. Kẹt trang nặng hơn nhiều so với mất một trục xoay. */
  touch-action: pan-y; }
.v3d--me .v3d__msg { position: absolute; inset: 0; display: grid; place-items: center;
                     margin: 0; }
.v3d--me[data-state="ready"] .v3d__msg { display: none; }

/* 🔴 SỐ CŨ KHÔNG BAO GIỜ ĐƯỢC NHÌN GIỐNG SỐ SỐNG.
   Làm xám cả nhãn, số VÀ thanh — nên một ảnh chụp bị cắt mất cái pill "Ngoại
   tuyến" vẫn không đọc nhầm được. Đây là lớp phòng thủ thứ hai; lớp thứ nhất là
   chữ, lớp thứ ba là dòng ghi chú luôn kèm mốc thời gian. */
[data-cu="1"] .stat > span { color: var(--chu-nhat); }
[data-cu="1"] .stat__fill { fill: var(--chu-nhat); }

/* Checklist Prime: BA trạng thái, vì "chưa biết" KHÁC "chưa đạt".
   ⚠️ PHẢI đặt SAU `.luat--ok`: `.luat--dk > li::before` có cùng độ đặc hiệu
   (0,1,2) với `.luat > li::before`, nên CHỈ thứ tự nguồn quyết định cái nào
   thắng. `site.css` đã có một lỗi y hệt từng KHÔNG CHẠY NGÀY NÀO (`.bxh__hang`
   thua `.bxh td`) — đừng dời khối này lên trên. */
/* Danh sách cảnh cáo trong hồ sơ. `.luat` mặc định dùng dấu ✕ ĐỎ, nghĩa là "điều
   cấm" — sai hẳn nghĩa ở đây: một cảnh cáo đã xảy ra là một SỰ KIỆN, không phải một
   điều luật. Dùng dấu chấm than vàng, cùng tông với `.canhbao`. */
.luat--hs > li::before { content: "!"; color: var(--vang); }

.luat--dk > li::before          { content: "?"; color: var(--chu-nhat); }
.luat--dk > li[data-dat="0"]::before { content: "○"; color: var(--chu-nhat); }
.luat--dk > li[data-dat="1"]::before { content: "✓"; color: var(--luc); }
.luat--dk > li:not([data-dat])  { color: var(--chu-nhat); }
