/****************** JQUERY MOBILE MOD ******************/
tr {
	border-bottom: 1px solid #d6d6d6;
}
/****************** COMMON ******************/

.header-bar {
	text-align: center;
	margin-bottom: 1px;
}

/*
	Thanh nút đáy — hạ tầng dùng chung cả ba màn, KHÔNG bó trong .spk-moi vì có thanh
	nằm ngoài vùng đó (setting.html đặt nó ở khung trang).

	Ở khổ điện thoại nút tự xuống hàng (xem khối @media phía dưới); trước đây
	responsive.js gom nút phụ vào một ngăn "⋯", script ấy đã bỏ.
*/
.spk-thanh-day {
	position: fixed;
	bottom: 0px;
	left: 0;
	width: 100%;
	z-index: 10;
	box-sizing: border-box;
	display: flex;

	/*
		THANH ĐÁY LUÔN MỘT DÒNG — thứ nhường chỗ là TÊN NHÂN VẬT, không phải cả thanh.

		Bản trước để `wrap`: dưới 341px cụm nút rơi xuống dòng thứ hai và thanh cao
		107px thay vì 58px — mất 49px khung nhìn ở đúng những máy hẹp nhất, nơi từng
		pixel dọc đã phải giành giật. Đo được thanh cần 345px để nằm một dòng.

		Flexbox XUỐNG DÒNG TRƯỚC rồi mới co, nên `min-width: 0` đặt sẵn ở `.spk-tt` từ
		trước không có tác dụng gì chừng nào còn `wrap` — cùng cái bẫy đã cắn ở
		`.spk-hang-aux`, `.spk-them` và `.spk-bang-the td`.

		Thứ tự nhường chỗ: tên nhân vật cắt bớt (có "…"), còn hai nút và chữ "Đã lưu" /
		"Chưa lưu" thì KHÔNG BAO GIỜ co — đó là thao tác chính và cảnh báo mất dữ liệu.
		Đo ở 280/300/320/340px: thanh 58px, không nút nào bị cắt, "Đã lưu" nguyên vẹn,
		tên còn 23/43/63/83px. Từ 360px trở lên KHÔNG đổi một pixel nào.
	*/
	flex-wrap: nowrap;

	/* Hai dòng: trình duyệt chưa có env() bỏ dòng sau và giữ dòng trước. Gộp một
	   dòng như bản cũ thì Chrome 68 mất SẠCH padding của thanh nút. */
	/* Đáy chỉ còn 2px: 4px còn lại là lề dưới của chính các nút — xem bên dưới.
	   Đệm trên 4px thay vì 10px — xem khối "BA DẢI CỐ ĐỊNH" ở .spk-topbar. */
	padding: 4px 14px 2px;
	padding-bottom: calc(2px + env(safe-area-inset-bottom, 0px));
	background: rgba(255, 255, 255, .96);
	border-top: 1px solid var(--spk-vien);
	box-shadow: 0 -2px 10px rgba(0, 0, 0, .06);
}

/*
	NGỮ CẢNH ĐANG LÀM VIỆC ở mép trái thanh đáy:
		tài khoản │ nhân vật │ trạng thái lưu

	Cả cụm được phép CO (`min-width: 0` + `flex: 0 1 auto`) để nó nhường chỗ cho
	hai nút bên phải khi màn hẹp, chứ không đẩy chúng tràn ra ngoài.
*/
.spk-thanh-day .spk-tt {
	flex: 0 1 auto;
	min-width: 0;
	align-self: center;
	display: flex;
	align-items: baseline;
	font-size: 13px;
	color: var(--spk-chu-mo);
	overflow: hidden;
}

/*
	AI NHƯỜNG CHỖ KHI THANH ĐÁY CHẬT.

	Tên nhân vật là mẩu duy nhất được cắt: nó dài không lường trước được, và cắt bớt
	vẫn còn nhận ra. Chữ trạng thái thì không — "Chưa lưu" mà cụt thành "Chưa l…" là
	mất một cảnh báo về dữ liệu.
*/
.spk-tt-nv {
	flex: 0 1 auto;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.spk-tt-luu {
	flex: 0 0 auto;
	white-space: nowrap;
}

/*
	KHỔ QUÁ HẸP: nút "Khác ⋯" rút còn "⋯".

	Dưới 360px — hẹp hơn cả máy hẹp nhất còn hỗ trợ — tên nhân vật phải cắt bớt để cả
	thanh nằm một dòng. Bỏ chữ "Khác" trả lại 34px cho cái tên: ở 320 và 340px tên
	hiện TRỌN "Norrys0 [S329]" thay vì cụt mất mã máy chủ, ở 300px còn 77px thay vì 43.

	Mốc 359px chứ không phải 340px: ngay trên 340 thanh vẫn thiếu 4px nên tên vẫn cụt
	— cắt đúng ở chỗ hết cụt thì mốc mới có nghĩa.

	"⋯" một mình vẫn là quy ước quen thuộc cho "còn nữa". Chữ chỉ ẩn khỏi MẮT, không
	mất khỏi máy đọc màn hình: nút mang `aria-label="Khác"` nên tên gọi vẫn còn.

	THÊM CẢ MÀN HÌNH DỌC, không riêng dưới 360px: ở khổ dọc chiều ngang luôn là thứ
	đáng tiếc nhất, mà "⋯" thì đã đủ nghĩa. Hai điều kiện nối bằng dấu phẩy — CHỈ CẦN
	MỘT đúng là luật chạy: máy nằm ngang mà hẹp dưới 360px cũng vẫn rút gọn.
*/
@media only screen and (max-width: 359px), only screen and (orientation: portrait) {
	.spk-thanh-day .spk-nut-bar .spk-nut-chu {
		display: none;
	}
}

/*
	Dấu phân cách do CSS vẽ — cùng lối với dải tài khoản (.spk-tk-ten::after).
	Đặt ở ::before của mẩu ĐỨNG SAU, và chỉ khi mẩu ấy có chữ: mẩu rỗng mà vẫn vẽ
	dấu thì thanh đáy hiện ra một dấu │ trơ trọi không ngăn cách gì.
*/
.spk-tt-luu:not(:empty)::before {
	content: "|";
	margin: 0 9px;
	color: var(--spk-vien);
	font-weight: 400;
}

/*
	CỤM TRẠNG THÁI TỰ XUỐNG DÒNG KHI KHÔNG ĐỦ CHỖ — không mốc màn hình nào cả.

	Đủ chỗ thì `tài khoản · nhân vật [máy chủ] · trạng thái` nằm một dòng cùng hai
	nút; không đủ thì tài khoản lên dòng trên, cụm còn lại xuống dòng dưới.

	ĐỂ FLEXBOX TỰ QUYẾT, đừng đoán hộ nó bằng mốc. Đã thử ba mốc — 640, 399, rồi
	479px — và cả ba đều sai theo một kiểu: bề rộng CẦN phụ thuộc độ dài tên, mà tên
	là dữ liệu của người dùng. Đo được 441px với "smartpk · ziziziz [S405]" nhưng
	453px với "smartpk · Norrys0 [S329]"; một cái tên dài hơn nữa thì mốc lại sai
	tiếp. `flex-wrap: wrap` biết chính xác lúc nào không vừa, vì nó là bên đo.

	Hai mẩu, không phải ba: `.spk-tt-dong` bọc nhân vật với trạng thái để chúng KHÔNG
	bị tách rời — ba mẩu ngang cấp thì flexbox có thể vỡ thành ba dòng.

	KHÔNG CÓ DẤU │ GIỮA TÀI KHOẢN VÀ NHÂN VẬT, chỉ có khoảng cách. Dấu ấy đặt ở
	`::before` của nhân vật thì khi xuống dòng nó mở đầu dòng dưới; đặt ở `::after`
	của tài khoản thì nó treo ở cuối dòng trên. CSS không có cách nào biết "vừa xuống
	dòng" để giấu đi — nên bỏ hẳn, và để khoảng trắng làm việc phân tách. Dấu │ giữa
	nhân vật và trạng thái thì giữ: hai mẩu ấy luôn cùng một dòng.
*/
.spk-thanh-day .spk-tt {
	flex-wrap: wrap;
}

.spk-tt-tk {
	margin-right: 12px;
}

/*
	Khối bọc "nhân vật · trạng thái".

	PHẢI CÓ LUẬT NỀN, không chỉ luật trong media query khổ hẹp. Bản đầu tôi chỉ khai
	nó ở `@media (max-width: 399px)`; từ 400px trở lên nó là một `<span>` trơn, chữ
	bên trong tự xuống dòng và cụm lại thành HAI dòng — đúng thứ vừa bỏ công chống.
	Đo được ở 400px: cụm cao 39px thay vì 20px.

	Thêm một khối bọc thì phải trả lời cho MỌI khổ, không riêng khổ mình đang sửa.
*/
.spk-tt-dong {
	display: flex;
	align-items: baseline;
	flex: 0 1 auto;
	min-width: 0;
}

/* Tên tài khoản là mẩu dài và nhẹ ký nhất — cho nó co rồi cắt bằng dấu ba chấm. */
.spk-tt-tk {
	flex: 0 1 auto;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.spk-tt-nv {
	flex: 0 1 auto;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	color: var(--spk-chu);
	font-weight: 600;
}

/*
	Trạng thái lưu KHÔNG được co và không được cắt: đó là mẩu duy nhất người dùng
	cần đọc trọn. Hai mẩu kia nhường chỗ cho nó.

	Mờ khi "Đã lưu" — không có gì phải nhìn. "Chưa lưu" thì đỏ và đậm lên, vì đó là
	lúc người dùng cần biết mình còn việc phải làm.
*/
.spk-tt-luu {
	flex: none;
	white-space: nowrap;
}

.spk-tt-luu.spk-chua-luu {
	color: var(--spk-do);
	font-weight: 600;
}


/*
	KHOẢNG CÁCH GIỮA CÁC NÚT bằng MARGIN, không bằng `gap`.

	`gap` của flexbox bị Chrome 68 (MEmu) bỏ qua: trên máy người dùng các nút dính
	liền nhau, còn trên máy mình thì vẫn rời — kiểu hỏng không kêu. Thanh này
	`flex-wrap: wrap` nên không đổi sang grid được như .spk-hang-nut đã làm.

	Lề phải của mục cuối vô hại vì hàng căn trái. Lề dưới bù lại bằng việc bớt
	padding-bottom của thanh, nên chiều cao thanh không đổi.

	Lề dưới còn 4px: từ khi thanh mang `flex-wrap: nowrap` thì nút KHÔNG còn xuống
	hàng nữa, nên 8px cũ không còn phải gánh việc làm khe giữa hai hàng.
*/
.spk-thanh-day > .spk-nut-bar,
.spk-thanh-day > .spk-menu-vo {
	margin: 0 8px 4px 0;

	/* KHÔNG co: từ lúc thanh thôi xuống dòng, thiếu chỗ là flex đi bóp thứ co được.
	   Nút bị bóp hẹp hơn chữ của nó rồi cắt cụt — đúng lỗi đã shipped ở r3665. */
	flex: 0 0 auto;
}

/*
	ĐẨY CẢ CỤM NÚT SANG PHẢI. Lề trái tự động đặt ở món ĐẦU TIÊN của cụm ("Khác"),
	nên nó nuốt hết chỗ trống còn lại và mọi thứ sau nó dồn về mép phải. Chữ trạng
	thái đứng lại bên trái.
*/
.spk-thanh-day > .spk-menu-vo {
	margin-left: auto;
}

/* Nút cuối không cần lề phải — nó đã sát mép rồi. */
.spk-thanh-day > .spk-nut-bar:last-child {
	margin-right: 0;
}

/* Nút của thanh đáy. Cỡ chạm 40px kể cả trên PC — đây là các thao tác chính. */
/*
	Nút ở thanh đáy: VIỀN XANH là mặc định. Bản trước là nút trắng viền xám — cùng
	tông với nền thanh nên cả hàng chìm nghỉm, phải nhìn kỹ mới thấy.

	Chỉ NÚT CHÍNH của thanh mới tô đặc (xem .spk-nut-chinh bên dưới). Bốn thanh
	trong app dùng chung lớp này — Tài khoản, Mua VIP, phân trang lịch sử, Thiết lập
	— mà phần lớn nút trong đó không phải thao tác chính; tô đặc hết thì "Thiết lập
	mặc định" (xoá sạch cấu hình) trông y hệt "Lưu thiết lập" nằm ngay cạnh.

	Dùng --spk-chinh của bảng màu (khai ở :root nên dùng được cả ngoài .spk-moi),
	không viết mã màu riêng.
*/
.spk-nut-bar {
	font: inherit;
	font-size: 14px;
	font-weight: 500;
	color: var(--spk-chinh);
	background: #fff;
	border: 1px solid var(--spk-chinh);
	border-radius: 8px;
	padding: 9px 18px;
	min-height: 40px;
	cursor: pointer;
	white-space: nowrap;
}

/*
	DÃY NÚT NẰM TRONG LUỒNG, ngay dưới thứ nó tác động — khác .spk-thanh-day là
	thanh cố định dính đáy màn.

	Chỉ màn Thiết lập còn dùng thanh cố định, vì "Lưu thiết lập" áp dụng cho cả màn
	và có thể cần ở bất cứ vị trí cuộn nào. Mua VIP / phân trang / đổi mật khẩu thì
	thuộc về đúng một khối, nên đi cùng khối ấy.

	Lề thay `gap` — gap trong flexbox cần Chrome 84, mà người dùng có máy chạy
	Chrome 68. Lề dưới của từng nút cũng là khoảng cách giữa hai dòng khi xuống dòng.
*/
.spk-day-nut {
	display: flex;
	flex-wrap: wrap;
	margin-top: 16px;
}

.spk-day-nut > * {
	margin: 0 8px 8px 0;
}

.spk-nut-bar:hover {
	background: rgba(107, 63, 160, .08);
}

/*
	NÚT CHÍNH của một thanh đáy: tô đặc để nổi hẳn so với các nút còn lại.

	Trước đây luật này viết theo ID (#btnApply) — vai trò "nút chính" nằm ở tên của
	MỘT nút cụ thể, nên thanh nào muốn có nút chính cũng phải chép thêm một luật id
	nữa, và đọc lớp trong HTML thì không thấy nút ấy khác gì các nút cùng lớp.
	Nay vai trò nằm ở lớp, đúng lối của .spk-nut-phu bên nút thường.
*/
.spk-nut-bar.spk-nut-chinh {
	color: #fff;
	background: var(--spk-chinh);
}

.spk-nut-bar.spk-nut-chinh:hover {
	background: #55307f;
	border-color: #55307f;
}

.spk-nut-bar:focus-visible {
	outline: 2px solid #6b3fa0;
	outline-offset: 2px;
}

.div-tool-bar {
	position: fixed;
	bottom: 0px;
	right: 0px;
	width: 60px;
	z-index: 11;
	text-align: right;
}

.div-top-spacing {
	height: 50px;
}

.spk-cho-cuon {
	height: 200px;
	clear: both;
}

.normal-btn {
	min-width: 80px !important;
	background: #663399 !important;
	color: white !important;
	text-shadow:
			-1px -1px 0 #000,
			1px -1px 0 #000,
			-1px 1px 0 #000,
			1px 1px 0 #000 !important;
}

.grey-btn {
	max-width: 120px;
	background: #663399 !important;
	text-overflow: unset;
	color: white !important;
	text-shadow:
			-1px -1px 0 #000,
			1px -1px 0 #000,
			-1px 1px 0 #000,
			1px 1px 0 #000 !important;
}

/*
	Đã gỡ bộ luật cũ của hai danh sách "bỏ qua hoạt động" (Bí Cảnh) và "kênh gửi tin"
	(Tiện ích) — cả hai khối đều đã chuyển sang giao diện mới, và luật cũ nay chỉ gây
	hại:

	  · đường phân cách được vẽ lên HAI CỘT riêng (base-col và extra-col) chứ không lên
	    cả dòng. Thời jQM hai cột là inline-block cao bằng nhau nên nhìn ra một vạch
	    liền; giờ chúng cao khác nhau nên vạch đứt làm hai đoạn lệch nhau.
	  · khung viền quanh base-col của danh sách kênh chồng lên viền của dòng.

	Kiểu dáng thay thế nằm trong khối "GIAO DIỆN MỚI" ở cuối tệp, bó trong .spk-moi.
*/

#accountContent {
	margin-bottom: 250px;
}

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

/*
	Khung cao ĐÚNG BẰNG vùng nhìn, cuộn nằm bên trong khung — đúng cách tham-khao-1
	xếp. Bản cũ để `height: 2500px`: một con số bịa, ở khổ rộng thì thừa khoảng
	trống, ở khổ hẹp thì thành hai thanh cuộn lồng nhau.

	Chuỗi 100% chỉ đứng được khi mọi tổ tiên có chiều cao xác định: #content là
	flex item `flex: 1` nên có, còn .spk-man thì phải nêu ra ở đây.
*/
#spkMan_newsModule.spk-hien,
#guideContent {
	height: 100%;
}

#guideContent iframe {
	/* block: thẻ iframe mặc định inline nên bị canh theo đường cơ chữ, chừa một khe
	   trống dưới đáy — đo được 4px. */
	display: block;
	width: 100%;
	height: 100%;
	border: 0;
}
/****************** SETTINGS ******************/

#playerInfoListTable {
	text-shadow: none;
	font-weight: bold;
	color: #323232;
}

#playerInfoListTable td {
	vertical-align: middle;
}

#playerSettingCheckAllContainer {
	display: none;
}

.setting-time-table input {
	width: 50px;
}

.setting-unit-table input {
	width: 75px;
}

.setting-unit-table-control {
	padding-left: 15px;
}

#pkSkillListContainer table {
	width: 38.5%;
}

#pkSkillListContainer td {
	vertical-align: top;
	width: 50%;
	padding-left: 10px;
}

#pkSkillListContainer td:first-child {
	padding-left: 0;
	padding-right: 10px;
}

#vatphamAuctionItemIdDiv {
	display: inline-block;
	width: 200px;
}

.target-black-list-col {
	width: 50%;
	display: inline-block;
}


/****************** ACCOUNT ******************/
.account-div {
	position: relative;
}

.account-div-title {
	color: blue;
	font-weight: bold;
	margin: 10px 0px;
}

/* ---------- Danh sách gói VIP (#playerLicenseList) ----------

   Mỗi gói là một THẺ, danh sách nhân vật của gói nằm trong chính thẻ ấy — cùng
   cách bản tham-khao-1 xếp. Bản cũ là dải xám tràn viền, dựng bằng <table> lồng
   trong <div> với cột chia theo phần trăm, nên trên điện thoại các cột chồng lên
   nhau. */

/* ---------- KHÔNG DÙNG `gap` TRÊN FLEX ----------

   Chrome 68 (MEmu) chỉ có `gap` cho GRID (từ 66), không có cho FLEX (từ 84).
   Đo được: giả lập Chrome 68 thì màn Quản lý VIP lệch 1035/1087 phần tử — trên
   máy ấy mọi thứ dính sát vào nhau.

   Không dùng @supports: Chrome 68 VẪN PHÂN TÍCH ĐƯỢC `gap`, nên `@supports
   (gap: 1px)` trả true ở đó — không có phép dò trung thực nào. Một đường mã duy
   nhất cho mọi trình duyệt thì không có đường nào để quên.

   HAI CÁCH, chọn theo container (cả hai đã đo trên trang thử tối giản):

     · `> *` + bớt padding dưới đúng bằng N — khớp CHÍNH XÁC chiều cao của bản
       dùng gap. Dùng cho khối chiếm trọn bề ngang, và cho khối có con bị ẩn:
       con bị ẩn không sinh hộp nên không góp lề nào, khe giữa hai con ĐANG
       HIỆN luôn đúng bằng N.

     · `> *:not(:last-child)` — bắt buộc khi con cuối CO GIÃN (flex:1) hoặc khi
       chính container bó theo nội dung: lề thừa sau con cuối không rơi vào
       khoảng trống mà làm con ấy teo đi N, hoặc làm container phình ra N.

   Lề dọc chỉ đặt ở nơi hàng THẬT SỰ xuống dòng (thường là trong media query
   khổ hẹp). Đặt ở khổ rộng nơi hàng không bao giờ xuống dòng thì chỉ tổ làm
   hàng cao thêm N. */

.spk-moi #playerLicenseList {
	display: flex;
	flex-direction: column;
	margin-top: 10px;
}

/*
	Bỏ qua thẻ CUỐI, thay vì kéo margin âm trên khối chứa.

	Lề âm ấy GỘP LỀ ra ngoài khối cha — cha không có padding hay viền dưới nên nó
	không bù được gì, chỉ làm cha cao thêm đúng 10px. Đo được trên cả hai khổ.

	Đổi lại: thẻ cuối bị bộ lọc ẩn (.spk-an) thì thẻ trước nó giữ 10px thừa ở đáy
	danh sách. Đó là trường hợp DUY NHẤT còn lệch, và nó thừa đúng bằng cái vừa bỏ.
*/
.spk-moi #playerLicenseList > *:not(:last-child) {
	margin-bottom: 10px;
}


/* ---------- Thanh lọc của khu Quản lý VIP ----------

   LƯỚI chứ không flex: `gap` của flexbox bị Chrome 68 (MEmu) bỏ qua, còn `gap`
   của grid chạy từ Chrome 66 — cùng lý do đã ghi ở khối hàng thiết lập.

   Hai ô chọn rộng cố định, ô tên ăn phần còn lại: "S12" hay "Còn hạn" không dài,
   kéo chúng bằng ô tên chỉ để lại một khoảng trống giữa chữ và mũi tên. */

.spk-moi .spk-vip-loc {
	display: grid;
	grid-template-columns: 150px 150px 1fr;
	gap: 12px;
	align-items: end;
	margin-top: 10px;
	padding: 12px 14px;
	background: var(--spk-nen-mo);
	border: 1px solid var(--spk-vien);
	border-radius: 10px;
}

.spk-moi .spk-vip-loc .spk-truong {
	margin: 0;
	min-width: 0;
}

.spk-moi .spk-vip-loc .spk-chon,
.spk-moi .spk-vip-loc .spk-nhap {
	width: 100%;
}

/* Dòng đếm chiếm trọn hàng dưới cùng, không chen vào giữa ba ô. */
.spk-moi .spk-vip-loc-dem {
	grid-column: 1 / -1;
	color: var(--spk-chu-mo);
	font-size: 12.5px;
}

/* Lọc xong không còn dòng nào: nói ra hẳn, chứ để trống thì không phân biệt
   được với "chưa nạp xong". */
.spk-moi .spk-vip-trong {
	margin-top: 10px;
	padding: 26px 14px;
	color: var(--spk-chu-mo);
	text-align: center;
	background: var(--spk-nen);
	border: 1px dashed var(--spk-vien);
	border-radius: 10px;
}

@media only screen and (max-width: 640px) {
	/* Khổ hẹp: hai ô chọn chia đôi một hàng, ô tên xuống trọn hàng dưới. */
	.spk-moi .spk-vip-loc {
		grid-template-columns: 1fr 1fr;
		gap: 10px;
		padding: 10px;
	}

	.spk-moi .spk-vip-loc-ten {
		grid-column: 1 / -1;
	}
}

/*
	THẺ VIP XẾP HAI CỘT: trái là thông tin, phải là các nút.

	Bản trước xếp DỌC — thông tin một khối, cụm nút một khối dưới nó. Mỗi gói vì thế
	ăn thêm trọn một hàng nút cao 54px, nhân với 56 gói là 3.024px, tức một phần tư
	toàn bộ chiều cao danh sách (đo được 12.127px ở khổ 412px).

	Xếp ngang thì cụm nút nằm cạnh thông tin chứ không dưới nó, và chiều cao thẻ do
	bên CAO HƠN quyết định thay vì bằng tổng hai bên.

	Làm bằng CSS thuần, không đụng markup: `.spk-vip-goi` thành flex biết vỡ dòng,
	cột trái co giãn, cột nút giữ bề rộng tự nhiên, còn danh sách nhân vật chiếm
	trọn một dòng riêng bên dưới (`flex: 1 1 100%`).

	VỠ DÒNG ĐƯỢC là bắt buộc chứ không phải tuỳ chọn: ở khổ hẹp nhất, thông tin cộng
	cụm nút không đủ chỗ nằm ngang, và flexbox thì VỠ DÒNG TRƯỚC KHI CO — không mở
	`wrap` thì cụm nút bị bóp thay vì xuống dòng.
*/
.spk-moi .spk-vip-goi {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-start;
	background: var(--spk-nen);
	border: 1px solid var(--spk-vien);
	border-radius: 10px;
	overflow: hidden;
}

/* Cột trái: sàn 200px rồi mới cho vỡ dòng — dưới mức ấy tên gói bị bóp thành
   ba bốn dòng chữ, mà cụm nút vẫn nguyên. */
.spk-moi .spk-vip-goi > .spk-vip-goi-dau {
	flex: 1 1 200px;
	min-width: 0;
}

/* Danh sách nhân vật luôn nằm trên dòng riêng, dưới cả hai cột. */
.spk-moi .spk-vip-goi > .spk-vip-nv-ds {
	flex: 1 1 100%;
}

/*
	THẺ 1 NHÂN VẬT XẾP LƯỚI 2×2 — để nó chỉ cao ĐÚNG HAI DÒNG.

	Với flex thì không xong, và lý do đáng ghi lại: cụm nút gói và cụm "Thiết lập ·
	Copy" là hai con NGANG CẤP của thẻ, nên chúng nằm ở hai dòng flex khác nhau. Dòng
	flex thứ nhất cao bằng con CAO NHẤT của nó — mà đó là cột thông tin (tên + hết hạn,
	2 dòng chữ), cao hơn một hàng nút. Kết quả: hàng "Thiết lập" bị đẩy xuống dưới đáy
	cột thông tin, để lại một khe 15px không ai muốn. Rút ngắn cụm nút còn làm khe RỘNG
	ra 23px — đo được đúng thế, vì thứ quyết định là bên KIA.

	Lưới nói được điều flex không nói được: "cột trái chiếm CẢ HAI hàng". Cột phải khi
	ấy có hai hàng nút xếp chồng, sát nhau, và thẻ cao bằng bên cao hơn thay vì bằng
	tổng.

	CSS Grid chạy từ Chrome 57, dưới mức Chrome 68 của máy người dùng.

	CHỈ ÁP CHO GÓI 1 NHÂN VẬT. Gói combo giữ flex: ở đó khối dưới là một DANH SÁCH tới
	60 người, nó phải chiếm trọn bề ngang chứ không nép vào một cột.
*/
.spk-moi .spk-vip-goi[data-combo="0"] {
	display: grid;
	/* `minmax(0, 1fr)` chứ không `1fr` trơn: `1fr` có sàn là min-content, nên một cái
	   tên dài sẽ đẩy cột phải ra ngoài thẻ thay vì tự cắt bằng `…`. */
	grid-template-columns: minmax(0, 1fr) auto;
	grid-template-areas:
		"tin nut"
		"tin nv";
	align-items: start;
}
.spk-moi .spk-vip-goi[data-combo="0"] > .spk-vip-goi-dau { grid-area: tin; }
.spk-moi .spk-vip-goi[data-combo="0"] > .spk-vip-goi-nut { grid-area: nut; }
.spk-moi .spk-vip-goi[data-combo="0"] > .spk-vip-nv-ds { grid-area: nv; }

/*
	THẺ COMBO CŨNG XẾP LƯỚI, chỉ khác một chỗ: danh sách nhân vật chiếm CẢ HAI CỘT.

	Để flex thì ở khổ dọc cụm nút không đủ chỗ nằm cạnh thông tin nên nó vỡ xuống dòng
	riêng — và vì cột thông tin chỉ cao hai dòng chữ, cạnh nó là một mảng trống bằng
	đúng chiều cao cụm nút. Thẻ thành ba dòng với một khoảng hở không nói gì.

	Lưới thì cụm nút nằm đúng cột phải cạnh thông tin, còn danh sách nhân vật (thứ
	THẬT SỰ cần trọn bề ngang, có gói tới 60 người) xuống hàng dưới trải hết hai cột.
*/
.spk-moi .spk-vip-goi[data-combo="1"] {
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto;
	grid-template-areas:
		"tin nut"
		"nv  nv";
	/*
		`stretch` chứ không `start`: hai ô của hàng đầu — khối thông tin và cụm nút — đều
		mang nền của dải tiêu đề, nên chúng phải cao BẰNG NHAU thì dải mới liền một mạch.
		Với `start` thì ô thấp hơn dừng sớm và dải bị khuyết một góc.
	*/
	align-items: stretch;
}

/*
	CẢ CỤM ĐẦU THẺ LÀ MỘT DẢI — như đầu mục ở màn Hoạt động.

	Dải ôm trọn tiêu đề, dòng hết hạn, mã VIP, nút "Gia hạn" và ô tick "Chọn tất cả":
	đó là những thứ nói về CẢ GÓI. Thứ duy nhất nằm ngoài dải là danh sách nhân vật —
	phần mà cái mũi ▸ sổ ra.

	LÀM BẰNG NỀN CHỨ KHÔNG BẰNG MỘT Ô LƯỚI RIÊNG: dựng thêm một hàng cho tiêu đề thì
	đo được thẻ phình 67 → 110px và cả danh sách +18%. Tô nền hai ô sẵn có thì dải vẫn
	liền một mạch mà không tốn thêm một dòng nào.

	KHÔNG có màu rê chuột: dải này gồm hai ô lưới rời nhau, mà CSS không có cách nào
	nói "rê vào ô nào cũng sáng cả hai" nếu không có `:has()` — Chrome 105, người dùng
	có máy Chrome 68. Sáng nửa dải còn tệ hơn không sáng.
*/
.spk-moi .spk-vip-goi[data-combo="1"] > .spk-vip-goi-dau,
.spk-moi .spk-vip-goi[data-combo="1"] > .spk-vip-goi-nut {
	background: var(--spk-nen-dau);
}

.spk-moi .spk-vip-goi[data-combo="1"] > .spk-vip-goi-dau {
	cursor: pointer;
	user-select: none;
	-webkit-user-select: none;
}

/*
	CỤM NÚT NEO LÊN ĐỈNH DẢI.

	`.spk-vip-goi-nut` xếp CHỒNG (`flex-direction: column`), nên `justify-content` của
	nó nói về trục DỌC — và nó đang là `flex-end`. Hồi ô lưới chỉ cao bằng nội dung thì
	luật ấy không làm gì; từ khi hàng đầu chuyển sang `stretch` để nền liền một mạch,
	ô nút cao bằng cả dải và `flex-end` đẩy hai nút xuống đáy — cạnh khối thông tin bốn
	dòng thì chúng trôi hẳn xuống dưới.

	KHÔNG đụng `align-items: flex-end` của nó: cái ấy nói về trục NGANG và đang giữ
	đúng việc dồn nút sang mép phải.
*/
.spk-moi .spk-vip-goi[data-combo="1"] > .spk-vip-goi-nut {
	justify-content: flex-start;
}
.spk-moi .spk-vip-goi[data-combo="1"] > .spk-vip-goi-nut { grid-area: nut; }
.spk-moi .spk-vip-goi[data-combo="1"] > .spk-vip-nv-ds { grid-area: nv; }

/*
	Ô TICK "Chọn tất cả" LUÔN Ở HÀNG DƯỚI nút — mọi khổ, không riêng khổ dọc.

	Hai thứ này khác loại: "Gia hạn" là một VIỆC để bấm, còn "Chọn tất cả" là một
	TRẠNG THÁI để bật. Xếp ngang hàng nhau thì mắt đọc chúng như hai lựa chọn ngang cấp.
	Xếp chồng cũng làm cột phải chỉ rộng bằng cái rộng nhất trong hai thứ, nên cột trái
	thở được — ở 412px trước đây chúng ăn hết ~190px và dòng "Hết hạn" vỡ làm hai.

	VỎ chiếm trọn hàng chứ không phải chính ô tick: cho `flex: 1 1 100%` thẳng vào ô
	tick thì cái viên bo dài ra hết cột, trông như một thanh chứ không như một ô chọn.
*/
.spk-moi .spk-vip-goi-tick {
	display: flex;
	justify-content: flex-end;
	margin-left: 0;
	margin-top: 4px;
}

/*
	MENU "⋯" CỦA THẺ VIP — một markup, hai bố cục.

	KHỔ MÁY TÍNH: các nút bày ra thành hàng ngang như thường, nút "⋯" biến mất. Vỏ
	menu không làm gì cả — nó chỉ là cái hộp trong suốt.

	KHỔ DỌC: nút "⋯" thay chỗ cả cụm, và cụm thành menu tràn neo dưới nó. Đo được lý
	do ở 412px: ba nút ăn hết bề ngang cột phải nên cột trái bị bó tới mức dòng "Hết
	hạn" vỡ làm hai, thẻ thành ba dòng thay vì hai.
*/
.spk-vip-menu-vo {
	position: relative;
	display: inline-flex;
}

.spk-vip-menu {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
}
/*
	Khe giữa các nút trong menu — Chrome 68 không có `gap`. Lề TRÁI vì cùng lý do với
	khối trên: con cuối mang lề phải thì cả cụm bị đẩy vào trong 8px.

	KHÔNG CÓ LỀ DƯỚI. Ở dạng hàng ngang menu không vỡ dòng (khổ hẹp thì nó đã thành
	menu tràn xếp dọc, và ở đó có luật lề riêng), nên 4px lề dưới chẳng để làm gì —
	nhưng nó làm CÁI VỎ cao 32px trong khi nút bên trong 28px, và nút bị đẩy lên 2px so
	với ô tick đứng cạnh. Tâm của vỏ thì vẫn trùng tâm ô tick, nên số đo "tâm" nói
	không có gì sai — thứ lệch là cái nút NẰM TRONG vỏ.
*/
.spk-vip-menu > * {
	margin: 0 0 0 8px;
}


/*
	THẺ ĐANG MỞ MENU THÌ CHO NỘI DUNG TRÀN RA.

	`.spk-vip-goi` có `overflow: hidden` để bo góc cắt gọn nền các khối con — và nó cắt
	luôn menu tràn. Đo được: menu mở ra chỉ lộ MỘT mục, phần còn lại nằm ngoài thẻ nên
	bị xén, nhìn y hệt một menu chỉ có một việc. Người duyệt báo đúng hiện tượng ấy.

	Lớp do JS gắn lúc mở và gỡ lúc đóng: `:has()` mới hỏi được "thẻ này có menu đang
	mở không" mà `:has()` cần Chrome 105, còn máy người dùng chạy Chrome 68.
*/
.spk-moi .spk-vip-goi.spk-vip-cho-tran {
	overflow: visible;
	/*
		NÂNG CẢ THẺ LÊN, không chỉ nâng cái menu.

		Menu đã có `z-index: 20` mà vẫn bị nút của thẻ NGAY DƯỚI vẽ đè — hit-test 25 điểm
		bắt được `spk-nut`, `spk-tick` và cả `spk-vip-goi-dau` của thẻ sau nằm trên. Lý
		do: thẻ là `display: grid`, và con của grid được xếp chồng như thể đã định vị dù
		`position: static` — nên nút trong thẻ SAU vẽ sau menu trong thẻ TRƯỚC.

		`z-index` của menu chỉ so được với anh em TRONG cùng một thẻ. Muốn thắng cả thẻ
		sau thì thứ phải nâng là CHÍNH CÁI THẺ. Đặt cùng lúc với `overflow: visible` vì
		hai thứ phục vụ đúng một việc: cho menu thoát ra và nằm trên.
	*/
	position: relative;
	z-index: 30;
}

/* Gói đã hết hạn: chữ nghiêng và nhạt, không cần thêm nhãn nào. */
.spk-moi .spk-vip-hethan {
	color: var(--spk-chu-mo);
	font-style: italic;
}

/*
	RIÊNG NÚT thì không nghiêng. Chữ nghiêng là để nói "thông tin này đã cũ";
	nút thì không cũ — chúng vẫn bấm được và vẫn làm đúng việc của chúng. Nghiêng cả
	nút chỉ làm nhãn nút khó đọc.
*/
.spk-moi .spk-vip-hethan button,
.spk-moi .spk-vip-hethan .spk-tick {
	font-style: normal;
}

.spk-moi .spk-vip-goi-dau {
	display: flex;
	align-items: flex-start;
	padding: 12px 14px;
}
/*
	2px chứ không 10px: mũi nay là hình trần, không còn viên bao để tự tách — mà cái
	viên ấy chính là thứ trước đây cần một khoảng cách để khỏi chạm vào chữ. Hình trần
	thì đứng gần được, và đứng gần mới đọc ra là mũi THUỘC VỀ tiêu đề chứ không phải
	một thứ rời đặt cạnh nó.
*/
/*
	TIÊU ĐỀ THẺ COMBO LÀ MỘT ĐÍCH BẤM (tay bấm ở license.js: `ganTieuDeVip`).

	`user-select: none` vì đây là thứ bấm hai lần liên tiếp là chuyện thường — bấm mở
	rồi bấm đóng — mà bấm đúp thì chữ bôi xanh lè, trông như vừa hỏng cái gì. Cùng lý do
	với `.spk-nhom-dau`.

	CHỈ `[data-combo="1"]`: tiêu đề thẻ lẻ là TÊN NHÂN VẬT, phải bôi đen chép được.
*/
.spk-moi .spk-vip-goi[data-combo="1"] .spk-vip-goi-ten {
	cursor: pointer;
	-webkit-user-select: none;
	user-select: none;
}

.spk-moi .spk-vip-goi-dau > *:not(:last-child) {
	margin-right: 2px;
}


/* Nút mở/đóng danh sách nhân vật. Giữ icon (▸/▾/ⓘ) vì đây là dấu hiệu DUY NHẤT
   cho biết thẻ bấm được; các nút khác đã bỏ icon vì đã có chữ. */
/*
	NÚT SỔ CỦA THẺ COMBO: MŨI TRẦN, KHÔNG VIÊN BAO.

	Cùng một hình với mũi ở đầu mục Hoạt động và ở Tiện ích — ba chỗ đều làm một việc,
	sổ một khối ra xem đầy đủ, nên chúng phải trông như một.

	BỎ KHUNG: cái viên 30px bo góc đọc ra là một NÚT ngang hàng với "Gia hạn" hay
	"Thiết lập", trong khi nó chỉ là dấu hiệu mở/đóng. Mũi trần nói đúng vai của nó.

	Vùng chạm không mất: nút vẫn rộng 24px và cao bằng dòng, chỉ là không còn viền.
*/
.spk-moi .spk-vip-mo {
	flex: none;
	display: inline-flex;
	align-items: center;
	/*
		MŨI SÁT MÉP TRÁI, và cả nút hẹp lại còn 18px.

		Hồi còn cái viên bao 30px thì khoảng trắng hai bên mũi là ĐỆM của nút, mắt đọc ra
		là một khối. Bỏ viên đi thì khoảng ấy thành một quãng trống vô cớ giữa mũi và tên
		gói — mũi trông như rơi ra khỏi tiêu đề.

		NÚT ÔM SÁT MŨI (`width: auto`), không giữ bề rộng 18px: mũi chỉ 5px nên 13px còn
		lại là khoảng trống NẰM TRONG nút, và lề 2px bên ngoài không thu ngắn được nó.

		Vùng chạm bù sang bên TRÁI bằng đệm 6px cộng lề âm 6px — chỗ ấy vốn là khoảng
		trống của thẻ, nên ngón tay được thêm 6px mà mắt không thấy gì dịch đi.
	*/
	justify-content: flex-start;
	width: auto;
	/* Đệm PHẢI bằng 0: mọi pixel ở đây nằm giữa mũi và chữ, và nó cộng thẳng vào cái
	   khe mà lề 2px bên ngoài đang cố giữ. */
	padding: 0 0 0 6px;
	margin-left: -6px;
	min-height: 24px;
	background: none;
	border: 0;
	/*
		ĐẬM NHƯ MŨI CỦA ĐẦU MỤC. Mũi vẽ bằng `currentColor`, mà `--spk-chu-mo` là màu xám
		mờ — trên dải nền tím nhạt của tiêu đề thì nó chìm tới mức nhìn như không có mũi.
		Cùng một sửa đã làm cho nút sổ ở Tiện ích.
	*/
	color: var(--spk-chu);
	font: inherit;
	font-style: normal;
	line-height: 1;
	cursor: pointer;
}

.spk-moi .spk-vip-mo:hover {
	color: var(--spk-chinh-dam);
}

/*
	MŨI VẼ BẰNG VIỀN, không phải ký tự — cùng cách `.spk-nhom-dau::before` làm, nên ba
	mũi trong app bằng nhau tuyệt đối về cỡ và màu, không phụ thuộc font nào đang có.

	Cái `<span class="spk-nut-bt">` do JS sinh (xem datIcon) thành cái vỏ rỗng mang
	hình; ký tự bên trong bị `font-size: 0` nuốt đi.
*/
.spk-moi .spk-vip-mo .spk-nut-bt {
	display: inline-block;
	width: 0;
	height: 0;
	font-size: 0;
	border-left: 5px solid currentColor;
	border-top: 4px solid transparent;
	border-bottom: 4px solid transparent;
	transition: transform .15s ease;
}

/* Mở ra thì mũi quay xuống — đúng 90° như mọi mũi sổ khác. */
.spk-moi .spk-vip-goi.spk-vip-mo-ra .spk-vip-mo .spk-nut-bt {
	transform: rotate(90deg);
}

.spk-moi .spk-vip-goi-tin {
	flex: 1;
	min-width: 0;
}

/*
	TIÊU ĐỀ THẺ VIP CÙNG CỠ VỚI ĐẦU MỤC — 15px, không phải 12px.

	Nó làm đúng việc của một đầu mục: đứng đầu một khối, mang mũi sổ, bấm vào thì khối
	mở ra. Nhưng nó đang là chữ NHỎ NHẤT trong thẻ — nhỏ hơn cả dòng "Hết hạn" bên dưới
	nó, nên mắt đọc nó như một nhãn phụ chứ không như tiêu đề.

	CHỈ CỠ CHỮ, chưa lấy dải nền của đầu mục. Đo ở 412px, 19 thẻ combo:

	                        thẻ combo   cả danh sách
	  hiện tại                 67px        4.891
	  cỡ chữ 15px              71px        4.992   (+2%)   ← chọn
	  + dải nền tràn ngang    110px        5.748   (+18%)

	Dải nền đòi tiêu đề phải chiếm trọn một hàng lưới riêng, đẩy cụm nút xuống — thẻ
	phình 64%. Danh sách này vừa được nén 52% ở đợt trước nên cái giá ấy phải do người
	duyệt quyết, không phải tự lấy.
*/
.spk-moi .spk-vip-goi-ten {
	font-size: 15px;
	font-weight: 600;
	color: var(--spk-chu);
}

.spk-moi .spk-vip-hethan .spk-vip-goi-ten {
	color: var(--spk-chu-mo);
}

/*
	DÒNG "ĐÃ HẾT HẠN" LÀ THỨ DUY NHẤT TRONG THẺ ĐƯỢC MÀU ĐỎ.

	Cả thẻ hết hạn đã mờ đi và nghiêng — đủ để nó lùi lại phía sau khi lướt qua. Nhưng
	khi mắt đã dừng ở một thẻ thì phải có đúng MỘT chỗ nói ra vì sao nó mờ, và đỏ là quy
	ước ai cũng đọc được mà không cần chú giải.

	GIỮ CHỮ NGHIÊNG của thẻ hết hạn — chỉ đổi màu và độ đậm. Nghiêng là dấu hiệu chung
	của cả thẻ; dựng thẳng riêng một dòng thì nó tách khỏi thẻ chứ không nhấn thêm được
	gì, mà màu đỏ đã đủ để mắt dừng lại.
*/
.spk-moi .spk-vip-hethan .spk-vip-qua-han {
	color: var(--spk-do);
	font-weight: 600;
}

.spk-moi .spk-vip-goi-han,
.spk-moi .spk-vip-goi-ma,
.spk-moi .spk-vip-goi-slot {
	margin-top: 2px;
	font-size: 13px;
}

/*
	CÁC DÒNG THÔNG TIN THẲNG VỚI MŨI, không thẳng với chữ của tiêu đề.

	Thẻ combo có nút ▸ đứng trước khối thông tin, nên mọi dòng trong khối bắt đầu ở sau
	cái mũi: đo được mũi ở x=25 còn chữ ở x=32. Mép trái của thẻ thành hai bậc, mà bậc
	ngoài chỉ có đúng một mũi tên 5px đứng.

	7px = 5px bề rộng mũi + 2px khe tới tiêu đề — dựng lại từ chính hai con số vẽ ra cái
	khe ấy, nên đổi hình mũi thì công thức vẫn đúng. (Không trừ 6px đệm trái của nút: đó
	là vùng chạm nằm NGOÀI phần vẽ, kéo theo cả nó thì các dòng lại thò ra ngoài mũi.)

	CHỈ THẺ COMBO: thẻ một nhân vật không dựng nút ▸ nào nên khối thông tin của nó vốn
	đã bắt đầu ở mép trái.
*/
.spk-moi .spk-vip-goi[data-combo="1"] .spk-vip-goi-han,
.spk-moi .spk-vip-goi[data-combo="1"] .spk-vip-goi-ma,
.spk-moi .spk-vip-goi[data-combo="1"] .spk-vip-goi-slot {
	margin-left: calc(0px - 5px - 2px);
}


/*
	Số slot còn trống / đã dùng hết là thứ người mua tìm trước tiên — đỏ và đậm.
	Giữ nguyên màu ấy cả ở gói hết hạn: còn bao nhiêu slot vẫn là con số người
	dùng cần đọc khi quyết định gia hạn.
*/
.spk-moi .spk-vip-goi-slot {
	color: var(--spk-do);
	font-weight: 600;
}

/*
	Còn lại đúng một <a> "Hướng dẫn" ở đây. Luật này có `padding: 0` và gạch chân —
	đúng cho một liên kết nằm trong dòng chữ, nhưng SAI cho nút, nên nút Copy phải
	đứng ngoài luật này (xem luật lề ngay dưới).
*/
/*
	NÚT TRỢ GIÚP "?" trên dòng Mã VIP — tròn, cỡ bằng mọi điều khiển khác (24px).

	Vẫn là thẻ <a> vì nó mở một trang web; chỉ mặc bộ đồ của nút để đứng cạnh nút Copy
	cho gọn hàng. Ba chữ "Hướng dẫn" thu về một ký tự, đủ chỗ cho mã VIP thở.
*/
.spk-moi .spk-vip-tro-giup {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: none;
	/* Cùng bộ số với `.spk-nut-nho` — nút "Copy" đứng cạnh dùng đúng luật đó, và hai
	   nút cạnh nhau lệch 4px chiều cao thì mắt thấy ngay. */
	min-width: 24px;
	/* 28px, không phải 24: nút "Copy" cạnh nó ăn luật `.spk-vip-goi .spk-nut` nên cao
	   28px, mà nút này không phải `.spk-nut` nên phải tự khai. */
	min-height: 28px;
	margin-left: 8px;
	padding: 2px 9px;
	font-size: 14px;
	font-weight: 600;
	line-height: 1;
	/* Bo góc 6px và viền tím — cùng bộ đồ với nút "Copy" đứng ngay cạnh. Vòng tròn
	   tách nó ra thành một loại riêng, mà nó có làm việc gì khác nút đâu. */
	color: var(--spk-chinh);
	background: var(--spk-nen);
	border: 1px solid var(--spk-chinh);
	border-radius: 6px;
	text-decoration: none;
}
.spk-moi .spk-vip-tro-giup:hover {
	background: var(--spk-chinh-nhat);
	border-color: var(--spk-chinh);
}

/* Nút Copy chỉ cần cách chữ ra, không lấy gì khác từ luật liên kết ở trên. */
.spk-moi .spk-vip-goi-ma .spk-nut-nho {
	margin-left: 8px;
}

.spk-moi .spk-vip-goi-nut {
	/*
		XẾP CHỒNG (column), không phải xếp ngang rồi cho vỡ dòng.

		Cột phải của lưới rộng `auto`, tức bằng max-content của cụm này. Khi cụm là flex
		NGANG có một con mang `flex-basis: 100%` (cái vỏ ô tick, để ép nó xuống dòng),
		max-content ấy phình lên 184px trong khi viên tick chỉ rộng 105px — dư gần 80px
		trống nằm giữa khối thông tin và ô tick, và đó là khoảng hở người duyệt thấy.

		Xếp chồng thì mỗi con giữ bề rộng nội dung của nó, cột phải rộng bằng con rộng
		nhất, và không cần mẹo `flex-basis: 100%` nào để ép xuống dòng nữa.
	*/
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	/*
		CỘT PHẢI, VÀ VẪN DỒN PHẢI CẢ KHI ĐÃ VỠ DÒNG.

		`flex: 1 1 auto` chứ không `0 1 auto`: ở khổ hẹp mà thẻ có ba nút (Gia hạn /
		Chuyển VIP / Nâng SVIP) thì cụm này không đủ chỗ nằm cạnh thông tin và tự xuống
		dòng — lúc ấy với `flex: 0` nó co về bề rộng nội dung và dạt sang TRÁI, lệch hẳn
		với hàng "Thiết lập · Copy" bên phải ngay dưới nó.

		Cho nó nở thì cả hai trường hợp đều đúng: nằm cùng hàng thì `justify-content`
		đẩy nút về mép phải; vỡ dòng thì nó chiếm trọn hàng và vẫn dồn phải. Không có
		cách nào hỏi CSS "mày vừa vỡ dòng chưa", nên phải chọn luật đúng cho cả hai.
	*/
	flex: 1 1 auto;
	justify-content: flex-end;
	margin: 0;
	/*
		Đệm trên bằng cột trái để hai cột thẳng hàng nhau ở mép trên; đệm dưới BẰNG 0 để
		hàng "Thiết lập · Copy" nằm SÁT ngay dưới hàng nút này.

		Đo được khe giữa hai hàng là 15px — đủ để mắt đọc ra chúng là hai khối rời nhau,
		trong khi chúng là hai nửa của cùng một thẻ. Bỏ đệm dưới và hạ lề con xuống 4px
		thì khe còn 4px: vẫn tách được hai hàng mà thẻ đọc ra là MỘT.
	*/
	padding: 12px 14px 0;
}
/*
	LỀ TRÁI CHO CON SAU, KHÔNG PHẢI LỀ PHẢI CHO CON TRƯỚC.

	Nút Nâng SVIP / Thêm Slot bị ẩn tuỳ gói, nên `:not(:last-child)` không dùng được —
	con cuối NHÌN THẤY ĐƯỢC đổi theo từng gói. Nhưng để lề phải cho MỌI con thì con
	cuối cũng mang 8px thừa, và cụm bị đẩy vào trong: đo được mép phải nút hàng trên
	cách viền 19px trong khi hàng "Thiết lập · Copy" chỉ cách 11px. Lệch đúng 8px ấy.

	Đổi sang lề TRÁI thì phần thừa rơi về bên trái con đầu — mà cụm dồn phải nên chỗ
	ấy là khoảng trống, không ai thấy. Cùng một cách `.spk-vip-nv-nut` đã dùng.
*/
.spk-moi .spk-vip-goi-nut > * {
	margin: 0 0 4px 8px;
}


/* ---------- Nhân vật trong gói ---------- */

.spk-moi .spk-vip-nv-ds {
	border-top: 1px solid var(--spk-vien-nhat);
}

.spk-moi .spk-vip-nv {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	padding: 9px 14px;
	border-bottom: 1px solid var(--spk-vien-nhat);
}
/* Ở khổ rộng hàng này KHÔNG xuống dòng, nên không đặt lề dọc — đặt vào
   là hàng cao thêm 8px. Lề dọc nằm trong media query khổ hẹp bên dưới,
   đúng chỗ .spk-vip-nv-tin nở ra 100% và đẩy cụm nút xuống dòng. */
/* Lề đặt cho con SAU chứ không con TRƯỚC: .spk-vip-nv-tin co giãn (flex 1 1 200px),
   mà lề phải đặt trên nó thì ăn thẳng vào chiều rộng của chính nó — đo được ô thông
   tin hụt đúng 8px. Hàng này có đúng hai con và không con nào bị ẩn. */
.spk-moi .spk-vip-nv > *:not(:first-child) {
	margin-left: 8px;
}


.spk-moi .spk-vip-nv:last-child {
	border-bottom: 0;
}

/* Sọc xen kẽ để mắt bám được dòng khi gói có tới 60 nhân vật. */
.spk-moi .spk-vip-nv-le {
	background: var(--spk-nen-mo);
}

.spk-moi .spk-vip-nv-tin {
	flex: 1 1 200px;
	min-width: 0;
	font-size: 13px;
}

.spk-moi .spk-vip-nv-nhan {
	color: var(--spk-chu-mo);
}

.spk-moi .spk-vip-nv-ten {
	font-weight: 600;
}

.spk-moi .spk-vip-nv-nut {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
}

/*
	Lề TRÁI cho con SAU, không phải lề phải cho con TRƯỚC.

	Con CUỐI của cụm này là <span> nhắc và nút "Sao chép" — cả hai đều bị .hide(),
	nên :not(:last-child) vẫn cho con nhìn thấy được cuối cùng một lề thừa và cụm nút
	phình ra 8px. Con ĐẦU thì không bao giờ bị ẩn: nút "Chuyển VIP" lúc hết hạn là
	KHÔNG ĐƯỢC DỰNG chứ không phải bị giấu, nên con đầu luôn là một nút đang hiện.
*/
.spk-moi .spk-vip-nv-nut > *:not(:first-child) {
	margin-left: 8px;
}


.spk-moi .spk-vip-nv-nhac {
	color: var(--spk-do);
	font-size: 12px;
}

/*
	NÚT TRONG THẺ VIP GỌN LẠI: 28px thay vì 44px.

	Màn này có 116 nút — nhiều nhất trong cả app — và chúng chiếm 5.104px, tức 42%
	chiều cao danh sách. Mỗi nút bớt 16px là bớt 1.856px.

	28px chứ KHÔNG 24px như ô nhập: 24px là con số cho điều khiển đứng cạnh nhau
	trong một hàng dày đặc, còn đây là nút HÀNH ĐỘNG (Gia hạn, Chuyển VIP) — bấm
	trượt vào nút gia hạn thì mở nhầm một luồng mua bán. Bốn pixel ấy là khoảng cách
	giữa "gọn" và "khó bấm".

	Phải hạ CẢ ĐỆM, không chỉ `min-height`: `.spk-nut` có `padding: 7px 16px`, nên
	chữ 21px cộng đệm 14 cộng viền 2 đã là 37px và sàn không có tác dụng gì.
	`line-height: 1` vì nút chỉ có một dòng chữ.
*/
.spk-moi .spk-vip-goi .spk-nut {
	/*
		CANH GIỮA CHỮ THEO CHIỀU DỌC — bắt buộc khi đã hạ chiều cao.

		`<button>` là `inline-block`, và inline-block KHÔNG có cơ chế canh giữa theo trục
		dọc: chữ nằm trên đường cơ sở, còn phần dư của `min-height` dồn hết xuống dưới.
		Hồi nút cao 36px thì chữ 21px cộng đệm 14 vừa khít nên không ai thấy; hạ xuống
		28px với đệm 1px thì nội dung chỉ 16px và 12px dư lộ ra hết ở dưới — đo được chữ
		cách mép trên 0px, cách mép dưới 12px.

		`inline-flex` + `align-items: center` là cách nói "chia đều phần dư", và nó đúng
		cho mọi bề rộng chữ.
	*/
	display: inline-flex;
	align-items: center;
	justify-content: center;
	line-height: 1;
	min-height: 28px;
	padding: 1px 10px;
}

/*
	NÚT "VIP ⋯" CHỈ CÓ VIỆC Ở KHỔ DỌC.

	Luật này phải đứng SAU khối ngay trên, không phải trước. Cả hai cùng đặc hiệu
	(0-3-0) nên thứ tự trong tệp mới quyết định — để nó ở trên thì `display:
	inline-flex` của khối kia thắng và nút "VIP" hiện ra cả ở khổ máy tính, đo được
	56/56 thẻ.

	Lần đầu tôi chữa bằng cách tăng đặc hiệu, và nó KHÔNG ăn thua vì hai luật vốn đã
	bằng nhau. Hỏi trình duyệt xem luật nào ở dòng nào mới ra: 690 với 926.
*/
.spk-moi .spk-vip-goi .spk-vip-menu-nut {
	display: none;
}

/*
	NÚT "VIP ⋯" MẶC BỘ ĐỒ CỦA NÚT PHỤ — viền tím, nền trắng, như "Gia hạn" hay
	"Nâng SVIP" nằm trong chính cái menu nó mở ra. Nó chỉ mở một nhóm việc chứ không tự
	làm việc gì, nên tô đặc là nói quá vai của nó.

	Chỗ tô đặc trong thẻ này là "Thiết lập" — việc người dùng vào màn này để làm.
*/

/*
	MÃ NHÂN VẬT RỜI KHỎI MẶT THẺ.

	Một số 19 chữ số chiếm trọn một dòng trên mỗi nhân vật — 37 dòng là 722px — mà
	người dùng gần như không bao giờ cần đọc nó: tên nhân vật kèm [server] mới là
	thứ họ nhận ra. Giữ trong DOM chứ không xoá, vì thanh lọc đọc `data-nv` và vì
	phần sổ ra sẽ bày lại nó.
*/
.spk-moi .spk-vip-nv-id {
	display: none;
}

/*
	GÓI 1 NHÂN VẬT: HAI KHỐI NHẬP LÀM MỘT.

	Thẻ vẫn có đủ hai khối trong DOM — khối gói và khối nhân vật — vì thanh lọc đi qua
	`.spk-vip-nv` và đọc `data-ten` / `data-server` trên đó. Nhưng về MẶT NHÌN thì
	chúng phải là một: tên nhân vật đã lên làm tiêu đề (xem addRow trong license.js),
	nên khối dưới chỉ còn cụm nút, và một đường kẻ ngăn giữa hai thứ thuộc về nhau chỉ
	làm thẻ trông như hai thẻ chồng lên nhau.

	Gói COMBO giữ nguyên đường kẻ: ở đó khối dưới thật sự là một DANH SÁCH nhiều người,
	và kẻ ngăn là thứ tách tiêu đề gói khỏi danh sách.
*/
.spk-moi .spk-vip-goi[data-combo="0"] > .spk-vip-nv-ds {
	border-top: 0;
}
.spk-moi .spk-vip-goi[data-combo="0"] .spk-vip-nv {
	padding-top: 0;
	border-bottom: 0;
	background: none;
}

/* Tên nhân vật đã nằm trên tiêu đề thẻ — giữ trong DOM cho thanh lọc, giấu khỏi mắt. */
.spk-moi .spk-vip-goi[data-combo="0"] .spk-vip-nv-tin {
	display: none;
}

/*
	THẺ THU GỌN: thứ ÍT DÙNG nấp đi cho tới khi bấm ▸.

	Màn này có 56 thẻ và mỗi thẻ bày sẵn mọi thứ nó có — mã VIP, số slot còn trống,
	Nâng SVIP, Thêm Slot, Chuyển VIP. Đó đều là việc làm vài lần một năm, trong khi
	thứ người dùng vào đây để làm là bấm "Thiết lập" cho một nhân vật.

	Hai hành động chính KHÔNG nấp: "Thiết lập" và "Gia hạn". Gia hạn ở lại vì nó phải
	đứng cạnh ngày hết hạn — nhìn thấy ngày sắp hết mà không có chỗ bấm ngay thì dấu
	hiệu ấy phí một nửa.

	Dùng lớp trên THẺ chứ không .hide() từng phần tử: JS chỉ bật/tắt một lớp, còn thứ
	gì thuộc nhóm phụ thì khai ở đây. Thêm bớt về sau là gắn thêm một lớp, không phải
	sửa logic.
*/
.spk-moi .spk-vip-goi:not(.spk-vip-mo-ra) .spk-vip-phu {
	display: none;
}

/*
	Ô TICK COPY LUÔN Ở GÓC NGOÀI CÙNG PHẢI của thẻ.

	Trong markup nó đứng TRƯỚC nút "Sao chép" (nút ấy bị .hide() cho tới khi có ai
	được tick), nên theo thứ tự tự nhiên nó không phải thứ ngoài cùng. `order` đẩy nó
	xuống cuối hàng mà không phải đổi markup — và quan trọng hơn, không phải đổi thứ
	tự đọc của bàn phím lẫn trình đọc màn hình một cách vô cớ, vì hai thứ ấy vẫn theo
	DOM.

	Nó cũng KHÔNG nấp khi thu gọn: chọn nhiều nhân vật để sao chép thiết lập là việc
	làm trên NHIỀU thẻ một lúc, mà bắt sổ từng thẻ ra mới tick được thì việc ấy hỏng.
*/
/*
	Ô TICK COPY LÀ THỨ CUỐI CÙNG BÊN PHẢI, và "Thiết lập" đứng NGAY CẠNH nó.

	Trong markup ô tick đứng trước nút "Sao chép" (nút ấy bị ẩn cho tới khi có ai được
	tick), nên theo thứ tự tự nhiên nó không phải thứ ngoài cùng. `order` đẩy nó xuống
	cuối hàng mà không đổi markup — thứ tự đọc của bàn phím và trình đọc màn hình vẫn
	theo DOM.

	KHÔNG dùng `margin-left: auto` để dạt ô tick ra: làm thế thì nó dính mép phải còn
	"Thiết lập" bị bỏ lại tít bên trái, trong khi hai thứ ấy là MỘT CẶP — cùng nói về
	thiết lập của nhân vật. Đẩy CẢ CỤM sang phải thì cặp ấy đi liền nhau.
*/
.spk-moi .spk-vip-nv-nut .spk-tick,
.spk-moi .spk-vip-goi-nut .spk-tick {
	order: 9;
}

/* Cụm nút của nhân vật chiếm trọn bề ngang rồi dồn phải — mép phải của nó khớp với
   mép phải của cụm nút gói ở hàng trên, nên hai hàng thẳng cột nhau. */
.spk-moi .spk-vip-goi[data-combo="0"] .spk-vip-nv-nut {
	flex: 1 1 100%;
	justify-content: flex-end;
}

@media only screen and (max-width: 640px) {
	.spk-moi .spk-vip-goi-dau,
	.spk-moi .spk-vip-nv {
		padding-left: 10px;
		padding-right: 10px;
	}

	/* Khổ này tab CÓ xuống dòng nên cần lại khe dọc. */
	.spk-moi .spk-luoi-radio-tab > span > * {
		margin-bottom: 6px;
	}

	/*
		ĐỆM TRÊN GIỮ NGUYÊN 12px NHƯ CỘT TRÁI — chỉ hai bên hông thu về 10px.

		Luật cũ khai `padding: 0 10px 2px`, tức đệm trên BẰNG 0, và nút ở hàng trên dính
		sát viền thẻ: đo được cách viền trên 1px trong khi hàng nút dưới cách viền dưới
		12px. Một thẻ mà mép trên chật mép dưới rộng thì đọc ra là bị lệch, dù không có
		con số nào sai riêng lẻ.

		Đệm dưới vẫn 0: hàng "Thiết lập · Copy" phải nằm sát ngay dưới hàng này.
	*/
	.spk-moi .spk-vip-goi-nut {
		padding: 12px 10px 0;
	}


	/*
		TÊN NHÂN VẬT VÀ CỤM NÚT CÙNG MỘT DÒNG.

		Luật cũ cho khối thông tin chiếm trọn một dòng và đẩy nút xuống dưới, với lý do
		đúng vào lúc ấy: khối ấy còn chứa MÃ NHÂN VẬT 19 chữ số, và nút thì cao 44px —
		nhét cả hai vào một dòng thì nút bị bóp còn vài chục pixel.

		Nay mã nhân vật đã rời khỏi mặt thẻ và nút còn 28px, nên chỗ đủ: tên ~90px cộng
		"Thiết lập" ~70px cộng "Copy" ~105px vẫn lọt trong 370px của khổ 412. Mỗi nhân
		vật vì thế còn MỘT dòng thay vì hai — với gói combo 60 người thì đó là 60 dòng.

		Sàn 90px để tên không bị bóp thành từng chữ một; dưới mức ấy thì cho vỡ dòng.
	*/
	.spk-moi .spk-vip-nv-tin {
		flex: 1 1 90px;
		min-width: 0;
	}

	/* Xuống dòng thật ở khổ này, nên giờ mới cần khe dọc. Bớt padding dưới đúng
	   bằng 8 để tổng chiều cao khớp với bản dùng gap. */
	.spk-moi .spk-vip-nv {
		padding-bottom: 1px;
	}

	.spk-moi .spk-vip-nv > * {
		margin-bottom: 8px;
	}

	/*
		Hai con nằm hai dòng nên không cần khe ngang; để nguyên thì cụm nút thụt vào
		8px so với ô thông tin ngay trên nó.

		Phải viết ĐÚNG BẰNG bộ chọn của luật gốc. Bản đầu tôi viết `> *` cho gọn — độ
		đặc hiệu (0,2,0) thua luật gốc `> *:not(:first-child)` (0,3,0) nên nó không ăn,
		và cụm nút vẫn thụt: đo được dx=+8 trên 36 hàng.
	*/
	.spk-moi .spk-vip-nv > *:not(:first-child) {
		margin-left: 0;
	}
}

/* ---------- Ba form xác thực (đăng nhập · đăng ký · quên mật khẩu) ----------

   Bố cục lấy theo bản tham-khao-1: thẻ hẹp căn giữa thay vì ô nhập kéo ngang hết
   vùng nội dung, nhãn nằm TRÊN ô, nút nằm trong thẻ chứ không ở thanh nút đáy. */

.spk-moi .spk-the-form {
	width: 100%;
	max-width: 420px;
	margin: 24px auto;
	padding: 20px;
	background: var(--spk-nen);
	border: 1px solid var(--spk-vien);
	border-radius: 12px;
}

.spk-moi .spk-truong {
	margin: 0 0 14px;
}

.spk-moi .spk-truong > label:not(.spk-tick) {
	display: block;
	margin-bottom: 5px;
	font-size: 13.5px;
	font-weight: 600;
}

.spk-moi .spk-truong .spk-nhap {
	width: 100%;
}

/*
	TRONG HỘP THOẠI: NHÃN VÀ CONTROL CÙNG MỘT DÒNG, chỉ xuống dòng khi không đủ chỗ.

	Luật chung cho `.spk-truong` là nhãn `display: block` — đúng ở một biểu mẫu dài,
	nơi hàng chục trường xếp dọc và mắt quét theo cột nhãn. Trong hộp thoại thì thường
	chỉ có MỘT trường: "Bạn muốn nâng lên gói:" chiếm trọn một dòng rồi ô chọn rộng
	115px nằm trơ ở dòng dưới, trong khi cạnh nhãn còn thừa hơn nửa hộp.

	`flex-wrap: wrap` + `flex: 1 1 200px` cho ô chọn: hộp đủ rộng thì hai thứ nằm cùng
	dòng và ô chọn ăn hết phần còn lại; hẹp quá thì ô chọn tự rơi xuống dòng dưới và
	vẫn trải hết bề ngang. Không có con số ngưỡng nào phải canh theo khổ màn.
*/
.spk-moi.spk-hop .spk-truong {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
}

.spk-moi.spk-hop .spk-truong > label:not(.spk-tick) {
	flex: 0 0 auto;
	margin: 0 8px 0 0;
}

.spk-moi.spk-hop .spk-truong > .spk-chon,
.spk-moi.spk-hop .spk-truong > .spk-nhap {
	flex: 1 1 200px;
	min-width: 0;
	width: auto;
}

/*
	MÀN MUA VIP / CHUYỂN XU: CONTROL NẰM CẠNH NHÃN, chỉ xuống dòng khi không đủ chỗ.

	Bảy hàng ở hai màn này dùng `spk-hang-doc` — nhãn một dòng, control ở dòng dưới —
	với lý lẽ chép trong markup: "để ở ô `aux` thì nó dạt sang mép phải màn, cách nhãn
	của chính nó hơn 600px". Lý lẽ ấy đúng về HẬU QUẢ nhưng chọn sai LỐI RA: thứ cần
	tránh là control bị ném sang mép phải, không phải việc nó đứng cùng dòng. Đo được ở
	1280px cả bảy hàng đều để control xuống dòng trong khi cạnh nhãn còn thừa hơn nửa
	màn hình.

	FLEX + WRAP thay vì đổi vùng lưới: control ăn phần còn lại NGAY SAU nhãn (chứ không
	dạt sang cột phải), và khi hẹp quá thì tự rơi xuống dòng dưới trải hết bề ngang —
	đúng dáng cũ. Không có ngưỡng khổ màn nào phải canh.

	BA Ô RỖNG PHẢI ẨN: `aux`, `sw`, `btn` của các hàng này không chứa gì, nhưng trong
	flex thì chúng vẫn là ba phần tử chiếm chỗ và mang lề — cùng cái bẫy "ô rỗng vẫn
	giữ chỗ" đã gỡ ở cột phụ và cột công tắc.

	LỀ ÂM CỦA NHÃN CŨNG PHẢI GỠ: nó kéo nhãn về đầu cột `btn` của LƯỚI, mà ở đây không
	còn lưới nào — để nguyên thì nhãn thò ra ngoài mép trái khung.
*/
#purchasePanel .spk-hang.spk-hang-doc,
#coinTransferPanel .spk-hang.spk-hang-doc {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
}

#purchasePanel .spk-hang.spk-hang-doc > .spk-hang-aux,
#purchasePanel .spk-hang.spk-hang-doc > .spk-hang-sw,
#purchasePanel .spk-hang.spk-hang-doc > .spk-hang-btn,
#coinTransferPanel .spk-hang.spk-hang-doc > .spk-hang-aux,
#coinTransferPanel .spk-hang.spk-hang-doc > .spk-hang-sw,
#coinTransferPanel .spk-hang.spk-hang-doc > .spk-hang-btn {
	display: none;
}

#purchasePanel .spk-hang.spk-hang-doc > .spk-hang-nhan,
#coinTransferPanel .spk-hang.spk-hang-doc > .spk-hang-nhan {
	flex: 0 0 auto;
	margin: 0 10px 0 0;
}

#purchasePanel .spk-hang.spk-hang-doc > .spk-hang-rong,
#coinTransferPanel .spk-hang.spk-hang-doc > .spk-hang-rong {
	flex: 1 1 240px;
	min-width: 0;
	margin-top: 0;
}

/* Dòng cảnh báo dưới ô nhập. Trước đây là một <label> thứ hai của cùng ô nhập —
   sai về ngữ nghĩa, và trình đọc màn hình đọc gộp cả hai thành một nhãn dài. */
.spk-moi .spk-canh-bao {
	margin-top: 5px;
	color: var(--spk-do);
	font-size: 12px;
	line-height: 1.45;
}

/*
	GRID chứ không flex: `gap` của flexbox bị Chrome 68 (MEmu) bỏ qua, còn `gap`
	của grid chạy từ Chrome 66. Một cột thì hai cách xếp như nhau, nên đổi sang
	grid là được khoảng cách miễn phí — không thì các nút dính liền nhau trên máy
	người dùng, còn trên máy mình thì vẫn đẹp.
*/
.spk-moi .spk-hang-nut {
	display: grid;
	gap: 8px;
	margin-top: 18px;
}

.spk-moi .spk-hang-nut .spk-nut {
	width: 100%;
}

/* Hành động phụ: chữ bấm được, không phải nút thứ hai tranh chỗ với nút chính. */
.spk-moi .spk-lien-ket {
	padding: 7px 6px;
	background: none;
	border: 0;
	color: var(--spk-chinh);
	font: inherit;
	font-size: 13px;
	text-align: center;
	cursor: pointer;
}

.spk-moi .spk-lien-ket:hover {
	color: var(--spk-chinh-dam);
	text-decoration: underline;
}

.spk-moi .spk-lien-ket:focus-visible {
	outline: 2px solid var(--spk-chinh);
	outline-offset: 2px;
	border-radius: 4px;
}

/****************** LICENSE ******************/

#licenseEditForm {
	text-align: center;
}

#purchaseVIPNote ul {
	list-style-type: square;
	padding: 10px 0 0 20px;
	margin: 0;
	font-size: 14px;
}

#purchaseVIPNote li {
	padding: 0 0 5px 0;
	margin: 0;
}

#bankPaymentPanel iframe {
	width: 100%;
	height: 2500px;
}

#bankPaymentGuideLink {
	background: #663399 !important;
	color: white !important;
	text-shadow:
		-1px -1px 0 #000,
		1px -1px 0 #000,
		-1px 1px 0 #000,
		1px 1px 0 #000 !important;
}

/* ---------- Chọn phương thức thanh toán (#purchaseMethodDiv) ----------

   Cùng hình dáng .spk-tick: hàng có viền, ô tick thật, sáng lên khi được chọn.
   Bản cũ ẩn ô radio và tô nền bằng JS, nên bàn phím không lái tới được. */

.spk-moi .spk-httt-de {
	margin-bottom: 4px;
	font-weight: 600;
}

.spk-moi .spk-httt {
	display: flex;
	align-items: center;
	margin-top: 8px;
	padding: 9px 12px;
	background: var(--spk-nen);
	border: 1px solid var(--spk-vien);
	border-radius: 10px;
	cursor: pointer;
}
.spk-moi .spk-httt > *:not(:last-child) {
	margin-right: 10px;
}


.spk-moi .spk-httt:hover {
	border-color: #c6cbd2;
	background: var(--spk-nen-mo);
}

.spk-moi .spk-httt:has(input:checked) {
	border-color: var(--spk-chinh);
	background: rgba(107, 63, 160, .07);
}

.spk-moi .spk-httt:focus-within {
	outline: 2px solid var(--spk-chinh);
	outline-offset: 1px;
}

.spk-moi .spk-httt input {
	flex: none;
	width: 17px;
	height: 17px;
	margin: 0;
	accent-color: var(--spk-chinh);
	cursor: pointer;
}

/* Nhãn chiếm trọn phần còn lại để bấm đâu trong hàng cũng chọn được kênh. */
.spk-moi .spk-httt label {
	display: flex;
	flex: 1;
	align-items: center;
	min-width: 0;
	margin: 0;
	font-weight: 600;
	cursor: pointer;
}
.spk-moi .spk-httt label > *:not(:last-child) {
	margin-right: 10px;
}


.spk-moi .spk-httt img {
	flex: none;
	width: 28px;
	height: 28px;
}

/* Phần nói thêm của một kênh: thụt vào cho thấy nó thuộc hàng ngay trên. */
.spk-moi .spk-httt-ct {
	margin: 6px 0 0 39px;
	font-size: 13px;
}

#purchaseBankSelector {
	display: block;
	width: 100%;
	font-size: 1em;
	padding: 0.5rem 0.3rem;
	border: 1px solid #8D8D8DFF;
	margin-top: 10px;
}

#purchaseSmartPKDetail a:link,
#purchaseSmartPKDetail a:visited {
	background-color: #663399;
	color: white;
	padding: 5px 10px;
	text-align: center;
	text-decoration: none;
	text-shadow: none;
	display: inline-block;
}

/****************** HỘP THOẠI ******************/
/* Của app/js/app/main/hopthoai.js, thay thư viện jquery-confirm.

   Nằm NGOÀI .spk-moi vì lớp phủ gắn thẳng vào <body>; nhưng chính hộp thì MANG
   lớp .spk-moi, nhờ vậy nội dung bên trong (spk-nhan-manh, spk-nhap…) vẫn ăn kiểu
   của giao diện mới. */

.spk-lop-phu {
	display: none;
	position: fixed;
	/* Bốn khai báo dài thay `inset: 0` — inset cần Chrome 87, mà Chrome 68 (giả
	   lập MEmu) bỏ qua nó và thả lớp phủ xuống dưới mép màn hình. */
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	/* Trên .spk-thanh-day (z-index 10) và trên mọi thứ khác của trang. */
	z-index: 100010;
	align-items: center;
	justify-content: center;
	padding: 16px;
	background: rgba(31, 35, 40, 0.55);
}

.spk-lop-phu.spk-hien {
	display: flex;
}

.spk-hop {
	display: flex;
	flex-direction: column;
	/* = min(560px, 100%), nhưng chạy cả trên trình duyệt chưa có min(). */
	width: 100%;
	max-width: 560px;
	max-height: calc(100vh - 32px);
	background: var(--spk-nen);
	border-radius: var(--spk-bk);
	box-shadow: 0 12px 32px rgba(31, 35, 40, 0.28);
	overflow: hidden;
}

.spk-hop-dau {
	padding: 13px 16px 0;
	font-weight: 700;
}

.spk-hop-than {
	flex: 1;
	min-height: 0;
	padding: 16px;
	overflow-y: auto;
	line-height: 1.6;
}

.spk-hop-chan {
	flex: none;
	display: flex;
	flex-wrap: wrap;
	justify-content: flex-end;
	padding: 2px 16px 14px 8px;
	border-top: 1px solid var(--spk-vien-nhat);
}
/* Căn phải và có thể xuống dòng: lề TRÁI để khoảng trống bên trái nuốt
   lề thừa, lề TRÊN cho khe giữa hai hàng. Bớt padding trên/trái đúng 8. */
.spk-hop-chan > * {
	margin: 8px 0 0 8px;
}


.spk-nut-hop {
	min-width: 110px;
	min-height: 38px;
	padding: 7px 16px;
	background: var(--spk-nen);
	border: 1px solid var(--spk-vien);
	border-radius: 6px;
	color: var(--spk-chu);
	font: inherit;
	font-size: 14px;
	cursor: pointer;
}

.spk-nut-hop:hover {
	border-color: var(--spk-chinh);
	color: var(--spk-chinh-dam);
}

.spk-nut-hop.spk-hop-chinh {
	background: var(--spk-chinh);
	border-color: var(--spk-chinh);
	color: #fff;
	font-weight: 500;
}

.spk-nut-hop.spk-hop-chinh:hover {
	background: #55307f;
	border-color: #55307f;
	color: #fff;
}

/* Nút thuận mở ra ở trạng thái TẮT cho tới khi người dùng chọn xong (hộp chọn
   phương thức thanh toán). Phải chặn cả :hover, nếu không nút tắt vẫn đổi màu
   như thể bấm được. */
.spk-nut-hop:disabled,
.spk-nut-hop:disabled:hover {
	opacity: 0.5;
	cursor: default;
	background: var(--spk-nen);
	border-color: var(--spk-vien);
	color: var(--spk-chu);
}

.spk-nut-hop.spk-hop-chinh:disabled,
.spk-nut-hop.spk-hop-chinh:disabled:hover {
	background: var(--spk-chinh);
	border-color: var(--spk-chinh);
	color: #fff;
}

@media only screen and (max-width: 640px) {
	.spk-nut-hop {
		flex: 1 1 auto;
		min-width: 0;
	}
}

/****************** PORTRAIT ******************/
@media only screen and (max-width: 640px) {
	#playerInfoListTable {
		border-collapse: collapse;
		border-spacing: 0 20px;
	}

	#playerSettingCheckAllContainer {
		margin-bottom: 20px;
	}

	#playerSettingCheckAllContainer {
		display: block;
	}

	.spk-moi #playerLicenseList,
	.spk-moi #playerLicenseList .spk-nut
	{
		font-size: 12px !important;
	}

}

@media only screen and (max-width: 640px) and (orientation: portrait) {

	.grey-btn {
		max-width: 100%;
	}

	.normal-btn {
		width: 97.5% !important;
		margin-left: 1% !important;
		margin-right: 1.5% !important;
		padding-left: 0 !important;
		padding-right: 0 !important;
	}

	#pkSkillListContainer table {
		width: 78%;
	}
}

/* ============================================================
   GIAO DIỆN ĐIỆN THOẠI — hiển thị tốt CẢ dọc & ngang.
   Trước đây có app/js/app/main/responsive.js đi kèm (gom nút vào ngăn
   "⋯", đo chiều cao thanh nút, wrap bảng rộng); đã bỏ hẳn — hai việc
   sau đã thành thừa, việc đầu thay bằng cho nút xuống hàng.
   ============================================================ */
/* CHỈ áp cho ĐIỆN THOẠI (màn hẹp ≤640px HOẶC thấp ≤480px — gồm dọc & ngang).
   Màn rộng (PC / WebView kéo to) GIỮ NGUYÊN giao diện gốc. */
@media (max-width: 640px), (max-height: 480px) {

/* ---------- Thanh nút đáy trên điện thoại ----------

   XUỐNG HÀNG chứ không ép một hàng. Bản trước đặt flex-wrap: nowrap rồi để
   responsive.js gom các nút phụ vào một ngăn "⋯"; đã bỏ script ấy nên nút tự
   xuống hàng. Đo được: ở 320px một hàng thì thanh TRÀN NGANG 32px (nút cuối bị
   cắt); xuống hàng thì cao 107px và không tràn.

   Chỗ cuộn dưới cùng do .spk-cho-cuon (200px, có sẵn trong mỗi view) lo —
   dư gấp đôi thanh nút cao nhất, nên không cần đo chiều cao thanh bằng JS nữa. */
.spk-thanh-day{
  box-sizing: border-box !important;   /* width:100% gốc là content-box -> +padding = tràn 20px */
  /* `nowrap`: xem luật nền `.spk-thanh-day` — thanh luôn một dòng, tên nhân vật
     mới là thứ nhường chỗ. Luật này nằm sau trong tệp nên phải sửa cả ở đây. */
  display: flex !important; flex-wrap: nowrap; align-items: stretch;
  /* Đáy 0: lề dưới của các nút lo phần ấy (xem luật .spk-thanh-day > *).
     Đệm trên 4px thay vì 8px — xem khối "BA DẢI CỐ ĐỊNH" ở .spk-topbar. */
  padding: 4px 10px 0 !important;
  padding-bottom: env(safe-area-inset-bottom, 0px) !important;
  box-shadow: 0 -3px 12px rgba(0, 0, 0, .10);
}
/* margin do luật .spk-thanh-day > * lo; `margin: 0 !important` ở đây là di sản
   chặn lề của jQuery Mobile, thư viện ấy đã gỡ và không luật nào còn đặt lề. */
/* `0 0`: nút không co, kẻo chữ trong nút bị cắt cụt khi thanh chật. */
.spk-thanh-day .spk-nut-bar{ flex: 0 0 auto; padding: 9px 10px; }
/* ---------- Menu danh mục: 2 cột ----------
   LƯU Ý: KHÔNG đè display của #settingsMenu, vì app dùng display:none để ẩn
   menu khi đã vào mục con. Chỉ chỉnh bề rộng nút (giữ float gốc) -> 2 cột. */

/* ---------- Khung giờ [giờ]:[phút] tới [giờ]:[phút]: không tràn ---------- */
.setting-time-table table, .setting-time-table tbody, .setting-time-table tr{ display: block; }
.setting-time-table td{ display: inline-block; vertical-align: middle; }
.setting-time-table input{ width: 52px !important; }
/* ---------- Controlgroup ngang (9 radio VIP, checkbox...) cho xuống hàng ---------- */

/* ---------- Bảng rộng có class (đấu giá/lịch sử/Bang 9 cột): cuộn ngang ---------- */

} /* ===== hết @media GIAO DIỆN ĐIỆN THOẠI (chỉ áp cho điện thoại) ===== */
/* ============================================================
   GIAO DIỆN MỚI — Phase 1
   ------------------------------------------------------------
   Kiểu dáng cho các khối đã chuyển sang HTML thuần (control mang
   data-role="none" nên jQuery Mobile bỏ qua).

   MỌI luật đều bó trong .spk-moi. Đây là điều kiện để thay TỪNG
   KHỐI: các khối chưa chuyển vẫn ăn nguyên kiểu jQM cũ, không bị
   khối này đụng vào.

   Khối đã chuyển: #settingParty (Tổ đội + Lệnh điều khiển).
   ============================================================ */

/*
	TÔNG TÍM, số đo lấy từ bảng màu của tham-khao-1:
		--spk-accent #6b3fa0 · --spk-accent-strong #55307f · --spk-accent-soft #f0e9f8
		--spk-ink #221d2b · --spk-muted #6a6279 · --spk-off #8b8397
		--spk-line #e2dcec · --spk-line-soft #eeeaf4 · --spk-ground #f6f4f9

	--spk-nen-mo lấy --spk-ground (#f6f4f9) chứ KHÔNG lấy --spk-surface-2 (#fbfafd):
	bên họ tách hai biến, ta chỉ có một, mà biến ấy đang sơn nền của cả <body>.
	Lấy #fbfafd thì trang gần như trắng trơn và mất hẳn lớp phân tách với các thẻ.

	--spk-do GIỮ NGUYÊN: đó là màu NGHĨA (nguy hiểm / chưa lưu), không phải
	tông màu của app.

	Mọi chỗ VIẾT CỨNG màu nhấn trong tệp này cũng đã đổi theo (18 chỗ). Đổi mỗi
	biến ở đây mà bỏ chúng thì app ra hai tông.
*/
:root {
	--spk-vien: #e2dcec;
	--spk-vien-nhat: #eeeaf4;
	--spk-nen: #ffffff;
	--spk-nen-mo: #f6f4f9;
	--spk-chu: #221d2b;
	--spk-chu-mo: #6a6279;
	--spk-chinh: #6b3fa0;
	--spk-do: #d1242f;

	/*
		NỀN VÀ VIỀN CỦA Ô NHẬP — xám, không phải trắng.

		Người dùng báo: giao diện sau refactor "toàn màu trắng, khó phân biệt các control".
		Đo lại thì đúng: khối nền #ffffff, ô nhập cũng #ffffff, và thứ duy nhất tách chúng
		là một đường viền #e2dcec — tím nhạt tới mức gần như trắng.

		Một ô nhập phải nói ra rằng nó LÕM XUỐNG so với mặt giấy. Nền tối hơn nền giấy
		làm việc ấy, và làm được cả ở chỗ đường viền thua: màn hình chói, độ sáng thấp,
		mắt kém.
	*/
	--spk-nen-o: #f1eef7;
	--spk-vien-o: #d5cce4;

	/*
		NỀN THANH TIÊU ĐỀ CỦA MỘT MỤC SỔ RA — đậm hơn cả nền thân lẫn nền trang.

		Ba lớp chồng nhau ở màn Thiết lập: nền trang #f6f4f9, thân mục #ffffff, và thanh
		tiêu đề nằm giữa. Trước đây tiêu đề dùng chính #f6f4f9 của nền trang, nên nó chìm
		xuống thành một dải mờ — mắt không bám được đâu là chỗ bắt đầu một mục khi cuộn
		qua ba bốn chục mục liền nhau.

		Đậm hơn một nấc rõ thì thanh tiêu đề nổi lên như cái gáy sách, và thứ tự ba lớp
		đọc ra được: trang nhạt nhất, thân trắng, tiêu đề đậm nhất.
	*/
	--spk-nen-dau: #e8e1f2;

	--spk-bk: 8px;

	/* Nền & chữ của mục đang chọn trong cây điều hướng. */
	--spk-chinh-nhat: #f0e9f8;
	--spk-chinh-dam: #55307f;

	/* Bề rộng cột điều hướng bên trái. */
	--spk-cot-trai: 262px;

	/* Chấm dẫn dòng của đầu mục lá — nhạt hơn chữ một bậc. */
	--spk-cham: #8b8397;

}

.spk-moi {
	/*
		Bề rộng ba cột phải của hàng thiết lập. Số đo lấy ĐÚNG từ tham-khao-1
		(--spk-col-aux/sw/btn), không tự nghĩ ra.
	*/
	--spk-cot-phu: 158px;
	--spk-cot-ct: 92px;
	--spk-cot-nut: 40px;

	/*
		Cột của nút sổ, nay nằm ở ĐẦU dòng chứ không cuối.

		RỘNG CỐ ĐỊNH chứ không `auto`: chỉ 11/27 hàng ở Tiện ích có nút, mà nếu cột co về
		0 ở những hàng còn lại thì nhãn của chúng bắt đầu ở một chỗ khác — 16 hàng thụt ra,
		11 hàng thụt vào. Chừa sẵn 18px cho mọi hàng thì mọi nhãn cùng một mép trái.
	*/
	--spk-cot-mo: 18px;

	/*
		SÀN của cột nhãn. Không có trong tham-khao-1 vì bản ấy không gặp — xem lý do ở
		`grid-template-columns` của `.spk-hang`.
	*/
	--spk-cot-nhan: 160px;

	color: var(--spk-chu);
	font-size: 14px;
	line-height: 1.5;
	-webkit-text-size-adjust: 100%;
}

.spk-moi *,
.spk-moi *::before,
.spk-moi *::after {
	box-sizing: border-box;
}
	    input            { font-size: 1em; line-height: 1.3; font-family: sans-serif }

.spk-moi input,
.spk-moi select,
.spk-moi button,
.spk-moi textarea {
	font-family: inherit;
	line-height: inherit;
}

/* Dải phân cách giữa các nhóm trong một danh mục. */
.spk-moi .spk-de-muc {
	margin: 18px 0 10px;
	color: var(--spk-chu-mo);
	font-size: 12.5px;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: .04em;
}

/* ---------- Nhóm (details/summary — gập mở không cần JS) ---------- */

.spk-moi .spk-nhom {
	background: var(--spk-nen);
	border: 1px solid var(--spk-vien);
	border-radius: var(--spk-bk);
	margin: 0 0 12px;
	overflow: hidden;
}

.spk-moi .spk-nhom-dau {
	display: flex;
	align-items: center;
	padding: 12px 14px;
	background: var(--spk-nen-dau);
	border-bottom: 1px solid var(--spk-vien);
	font-size: 15px;
	font-weight: 600;
	cursor: pointer;
	user-select: none;
	-webkit-user-select: none;
	list-style: none;
}
.spk-moi .spk-nhom-dau > *:not(:last-child) {
	margin-right: 8px;
}


/* Giấu tam giác mặc định (Chromium/WebView2 dùng ::-webkit-details-marker,
   trình duyệt mới dùng ::marker) rồi tự vẽ mũi tên để xoay được. */
.spk-moi .spk-nhom-dau::-webkit-details-marker { display: none; }
.spk-moi .spk-nhom-dau::marker { content: ""; }

.spk-moi .spk-nhom-dau::before {
	content: "";
	flex: none;
	width: 0;
	height: 0;
	border-left: 5px solid currentColor;
	border-top: 4px solid transparent;
	border-bottom: 4px solid transparent;
	/*
		CHỪA 2px GIỮA MŨI TÊN VÀ CHỮ.

		Mũi vẽ bằng viền nên nó không có bề rộng nội dung, và chữ dính sát ngay sau đỉnh
		tam giác — đọc ra thành một ký tự lạ mọc trước tên mục. Lề 2px là đủ để mắt tách
		hai thứ mà không làm mũi trôi ra xa thành một dấu hiệu rời rạc.

		Không dùng khe của flex: `.spk-nhom-dau` là flex container nhưng Chrome 68 không
		có `gap`, và một cái lề trên đúng phần tử cần thì rẻ hơn.
	*/
	margin-right: 2px;
	transition: transform .15s ease;
}

.spk-moi .spk-nhom[open] > .spk-nhom-dau::before {
	transform: rotate(90deg);
}

/*
	RÊ CHUỘT THÌ ĐẬM THÊM, KHÔNG PHẢI SÁNG LÊN.

	Màu cũ là #eef0f3 — xám XANH, đặt từ hồi nền thanh tiêu đề còn là #f6f4f9. Nay nền
	nghỉ đã đậm lên #e8e1f2 thì màu ấy sai cả hai chiều: nó SÁNG hơn nền nghỉ (rê vào
	thì thanh nhạt đi, ngược với mọi nút khác trong app) và nó lệch tông sang xanh giữa
	một màn hình tím. Người duyệt thấy ngay: "nhấn vào title thì màu bị đổi".

	Đậm thêm một nấc, cùng họ tím. Và KHÔNG cho bôi đen chữ: đây là một thanh để bấm,
	bấm hai lần liên tiếp mà chữ hoá xanh lè thì trông như vừa hỏng cái gì.
*/
.spk-moi .spk-nhom-dau {
	user-select: none;
	-webkit-user-select: none;
}
.spk-moi .spk-nhom-dau:hover { background: #ded4ec; }

.spk-moi .spk-nhom-dau:focus-visible {
	outline: 2px solid var(--spk-chinh);
	outline-offset: -2px;
}

/*
	Ẩn một hàng. Có !important vì JS của bản gốc có thể đã để lại inline display trên
	phần tử; inline chỉ thua được !important.
*/
.spk-moi .spk-an {
	display: none !important;
}

/* ---------- Hàng thiết lập: lưới 4 cột ---------- */

/*
	   lab (co giãn)  |  aux 158px  |  sw 92px  |  btn 40px

	Mỗi hàng LUÔN có đủ bốn ô, kể cả ô rỗng. Đó chính là thứ làm công tắc và nút
	thẳng hàng dọc suốt cả danh sách.

	Bản trước dùng flex nên mỗi hàng tự căn theo nội dung của riêng nó: 34 công tắc
	trong "Cấu hình chung" nằm ở 34 vị trí ngang khác nhau, nhìn răng cưa. Bố cục
	lưới này lấy từ tham-khao-1.
*/
.spk-moi .spk-hang {
	display: grid;
	/* Mốc neo cho lớp phủ viền khi hàng đang được thao tác — xem `:focus-within`
	   ở cuối khối này. Đo được 0 phần tử `absolute` nào nằm trong hàng, nên đặt
	   `relative` ở đây không đổi mốc neo của thứ gì đang có. */
	position: relative;
	/*
		Cột phụ là minmax chứ KHÔNG cố định: 158px là mức TỐI THIỂU, hàng nào cần rộng
		hơn thì cột tự nới và cột nhãn (1fr) nhường chỗ.

		Đo được 78 ô phụ rộng quá 158px — hàng "Tank với Boss khi máu còn trong khoảng"
		nhét 6 thứ (ô số, %, "đến", ô số, %, đệm) vào đó, cái rộng nhất tới ~1600px. Cố
		định 158px thì chúng bị bóp về gần bằng 0, nhìn ra như ô RỖNG chứ không phải ô hẹp.

		Cột công tắc và cột nút vẫn cố định, và ô phụ dồn phải, nên mép phải của cả ba cột
		vẫn thẳng hàng suốt danh sách — thứ mà lưới sinh ra để có.

		NHƯNG CỘT NHÃN PHẢI CÓ SÀN, không được để `1fr` trơn.

		Trong thuật toán lưới, `1fr` có cỡ nền bằng 0: các cột khác lấy đủ phần của mình
		trước, `fr` chỉ ăn chỗ THỪA. Nên ở dải 561–700px — vừa qua mốc 560 để về lưới 4
		cột mà màn vẫn hẹp — ô phụ nới tới cỡ nội dung của nó (đo được 422px ở hàng "Độ
		khó") và cột nhãn bị bỏ đói về gần 0. Đo `grid-template-columns` thật:

		  600px → "0px 398px 78px 40px"   nhãn 0px,  chữ bị cắt sạch
		  630px → "6px 422px 78px 40px"   nhãn 6px
		  700px → "72px 422px 78px 40px"  nhãn 72px, bắt đầu đọc được
		  840px → "212px 422px 78px 40px" nhãn 212px, bình thường
		Đúng dải bề rộng cửa sổ app PC hay dùng.
	*/
	/*
		CỘT CÔNG TẮC VÀ CỘT NÚT CO VỀ 0 KHI RỖNG.

		Khách phản hồi: công tắc nằm ở một cột, ô chọn ở cột khác, mép phải không đều nên
		nhìn tổng thể không thuận mắt. Đo ở 1280px thì đúng thế — mép hàng 1265, công tắc
		dừng ở 1201, ô chọn dừng ở 1098: ba cột khác nhau.

		Gốc là hai cột cuối khai bề rộng CỐ ĐỊNH (92px và 40px), nên chúng chiếm chỗ kể
		cả ở hàng không có công tắc lẫn nút — và ô nhập phải dừng lại trước một khoảng
		trống không chứa gì. Đổi sang `auto` thì cột rỗng rộng đúng 0.
	*/
	grid-template-columns:
		var(--spk-cot-mo)
		minmax(var(--spk-cot-nhan), 1fr)
		minmax(var(--spk-cot-phu), auto)
		auto;
	/*
		CÔNG TẮC ĐỨNG NGOÀI CÙNG, NÚT LÙI VÀO TRONG.

		Khách muốn hai điều: control sát lề phải, VÀ thẳng hàng với nhau. Hai điều ấy chỉ
		cùng thoả được khi thứ đứng cuối là thứ có mặt ở MỌI hàng — mà đó là công tắc
		(996 cái), không phải nút (chỉ 11/27 hàng ở Tiện ích có).

		Để nút đứng cuối như bản cũ thì công tắc ở hàng có nút bị đẩy vào 18px so với hàng
		không có — đo được mép 1233 với 1251. Đảo lại thì mọi công tắc cùng một mép, và
		nút cũng thẳng cột với nhau ở vị trí trước đó.

		CHỈ ĐỔI THỨ TỰ HIỂN THỊ. Thứ tự trong DOM giữ nguyên nên bàn phím và trình đọc
		màn hình vẫn đi qua chúng theo đúng mạch cũ.
	*/	grid-template-areas: "btn lab aux sw";
	align-items: center;

	/*
		KHE ĐẶT BẰNG LỀ, KHÔNG BẰNG `gap`.

		`gap` chừa khe ở MỌI ranh giới cột, kể cả hai bên một cột rộng 0 — ba khe 10px là
		30px trống dồn về bên phải, và control lại không sát mép nữa. Lề thì gỡ được bằng
		`:empty` cho đúng những vùng không chứa gì.

		Khe DỌC vẫn cần `row-gap` cho hàng xuống dòng ở khổ hẹp.
	*/
	row-gap: 2px;

	/*
		ĐỆM DỌC 2px Ở MỌI KHỔ, kể cả máy tính.

		Ban đầu đặt 4px và chỉ trong `@media (max-width: 640px)` — tức chỉ khổ hẹp theo
		BỀ NGANG. Đo lại thì thấy nó bỏ sót đúng hai chỗ đang chật nhất: điện thoại NẰM
		NGANG (800×360, bề ngang 800 nên không lọt mốc) và cửa sổ app PC hẹp. Nên luật
		này về đây, chỗ áp cho mọi khổ.

		Đã thử 8 → 4 → 0 → 2 → 3 → 2px trên máy thật, mỗi nấc một lượt nhìn bằng mắt.
		Số đo danh sách Hoạt động ở 412×800, và số mục thấy trọn một khung nhìn:

		  đệm  hàng thấp nhất  tổng    thấy trọn
		  8px       42px       21.484      11
		  4px       32px       19.324      12
		  3px       30px       18.334      12
		  2px       28px       17.986      12
		  0px       24px       17.164      12

		Từ 4px trở xuống KHÔNG mức nào thấy thêm được một mục nào nữa — cái được chỉ
		còn là cuộn ít hơn. Nên mức chọn là chuyện nhìn, không phải chuyện đo, và
		người duyệt chốt 2px sau khi xem cả năm nấc.

		KHÔNG đụng cỡ chạm: điều khiển nhỏ nhất trong hàng cao 24px ở mọi giá trị đệm.
		Cái mất là khoảng thở — hàng một dòng còn 28px thay vì 42px, và chính vì thế
		mà khe dọc TRONG hàng phải xiết theo (xem `gap` ở khối khổ hẹp) và đường kẻ
		phải đậm lên (xem ngay dưới).
	*/
	padding: 2px 14px;

	/*
		ĐƯỜNG KẺ ĐẬM HƠN (--spk-vien thay --spk-vien-nhat).

		Khi khoảng trắng giữa hai hàng chỉ còn 5px, khoảng cách thôi không đủ nói
		"hết hàng này sang hàng khác" — phải để ĐƯỜNG KẺ gánh việc ấy. Đây là cách
		tách không tốn một pixel dọc nào, khác hẳn việc nới đệm.
	*/
	border-bottom: 1px solid var(--spk-vien);
}

.spk-moi .spk-nhom-than > .spk-hang:last-child,
.spk-moi .spk-nhom-than > .spk-hang-doc:last-child {
	border-bottom: 0;
}

/*
	HÀNG ĐẦU THỞ THÊM 2px dưới đường kẻ của tiêu đề nhóm.

	Hàng thiết lập có đệm dọc 2px — mức đã vắt kiệt qua năm lần thử (8/4/3/2/0px) để
	nhét được nhiều mục nhất vào một khung nhìn. Nhưng ở HÀNG ĐẦU, 2px ấy nằm ngay
	dưới một đường kẻ đậm, nên chữ dính vào đường kẻ và mục trông như bị cắt cụt đầu.

	Chỉ nới hàng đầu, không nới cả danh sách: 2px nhân với hàng trăm hàng là chỗ ngồi
	của vài mục nữa, mà cái chật thật sự chỉ ở đúng chỗ giáp ranh này.
*/
.spk-moi .spk-nhom-than > .spk-hang:first-child,
.spk-moi .spk-nhom-than > .spk-hang-doc:first-child {
	padding-top: 4px;
}

/* Và hàng CUỐI thở thêm đúng bằng ấy, để mục cân trên dưới — hở 4px ở đầu mà 2px ở
   đáy thì cả khối trông như bị tụt xuống. */
.spk-moi .spk-nhom-than > .spk-hang:last-child,
.spk-moi .spk-nhom-than > .spk-hang-doc:last-child {
	padding-bottom: 4px;
}

.spk-moi .spk-hang-nhan {
	grid-area: lab;
	min-width: 0;
}

.spk-moi .spk-hang-nhan label {
	display: block;
	cursor: pointer;
}

.spk-moi .spk-goiy {
	margin: 2px 0 0;
	color: var(--spk-chu-mo);
	font-size: 12.5px;
}

/* Ba ô phải đều dồn nội dung về mép phải để mọi hàng khớp cột với nhau. */
.spk-moi .spk-hang-aux,
.spk-moi .spk-hang-sw,
.spk-moi .spk-hang-btn {
	display: flex;
	align-items: center;
	justify-content: flex-end;
	min-width: 0;
}
/*
	Căn phải nên lấy lề TRÁI, và phải BỎ QUA CON ĐẦU: ô nhập trong đây co giãn
	(.spk-nhap có flex: 1 1 auto), nên lề trái đặt lên nó ăn thẳng vào chiều rộng của
	chính nó — đo được ô hụt đúng 6px và cả hàng xô theo.
*/
.spk-moi .spk-hang-aux > *:not(:first-child),
.spk-moi .spk-hang-sw > *:not(:first-child),
.spk-moi .spk-hang-btn > *:not(:first-child) {
	margin-left: 6px;
}


/* Ô phụ quá dài cho màn hẹp thì xuống dòng, thà cao thêm còn hơn bóp nát control. */
.spk-moi .spk-hang-aux {
	flex-wrap: wrap;
}

.spk-moi .spk-hang-aux { grid-area: aux; }
.spk-moi .spk-hang-sw { grid-area: sw; }
.spk-moi .spk-hang-btn { grid-area: btn; }

/*
	KHE 10px GIỮA CÁC VÙNG — nhưng chỉ khi vùng ấy THẬT SỰ chứa gì.

	Vùng rỗng vẫn là một ô lưới, và nếu nó mang lề thì khoảng trống ấy đẩy control ra
	xa mép phải đúng bằng thứ mà việc bỏ `gap` vừa thu lại được.

	`:empty` khớp phần tử không có con nào, kể cả text — markup của các vùng này viết
	liền `<div class="spk-hang-sw"></div>` nên nó khớp. Chạy từ Chrome 4.
*/
.spk-moi .spk-hang-aux,
.spk-moi .spk-hang-sw {
	margin-left: 10px;
}
.spk-moi .spk-hang-aux:empty,
.spk-moi .spk-hang-sw:empty {
	margin-left: 0;
}

/* Control trong cột phụ lấp đầy cột, trừ ô số vốn nên gọn và co được. */
.spk-moi .spk-hang-aux > .spk-chon,
.spk-moi .spk-hang-aux > .spk-nhap {
	width: 100%;
}

/*
	SÀN 220px CHO COMBOBOX Ở KHỔ RỘNG — để chúng nhìn ra một cột, không phải một hàng
	răng cưa.

	Mỗi hàng là một lưới ĐỘC LẬP, nên cột phụ co theo nội dung của chính hàng ấy: đo ở
	màn Hoạt động, 33 combobox bày ra 13–14 bề rộng khác nhau (122 → 402px), cạnh nhau
	trong cùng một khối.

	SÀN chứ không phải bề rộng CỐ ĐỊNH. Đã đo cả hai:

	                      bề rộng khác nhau   combobox bị cắt chữ   cả màn (900px)
	  hiện tại                  14                   —              14.931
	  cố định 132px              1                 15/33            16.559  (+11%)
	  cố định 158px              1                 11/33            —
	  SÀN 220px                  7 (16/33 bằng)      0               14.949  ← chọn

	Cố định thì đều tuyệt đối nhưng cắt cụt một phần ba số ô — ô dài nhất ("Chỉ nhận NV
	3 sao & tự động…") cần 422px, mà kéo mọi ô lên 422 thì vô lý ở cửa sổ 700px. Sàn thì
	chỉ NỚI ô ngắn ra, không bao giờ bó ô dài lại: nó không thể làm cắt thêm chữ nào.

	220px là mức mà 27/33 ô đủ chỗ cho chữ của chúng. Ở cửa sổ app PC 700px thì cả
	33/33 về đúng một bề rộng, vì ở đó không hàng nào rộng hơn 220 được nữa.

	CHỈ TỪ 561px: dưới mốc ấy cột phụ đã bị chặn trần `fit-content(150px)` cho vừa khổ
	điện thoại, một cái sàn 220 ở đó sẽ bóp nát cột nhãn.
*/
@media only screen and (min-width: 561px) {
	.spk-moi .spk-hang-aux > .spk-chon {
		min-width: 220px;
	}
}

/*
	KHỔ ĐIỆN THOẠI: combobox LẤY TRỌN TRẦN CỦA CỘT, không co theo nội dung.

	Cột phụ ở khổ này là `fit-content(150px)` — co theo nội dung rồi mới chặn trần. Với
	ô nhập thì đúng, nhưng combobox thì mỗi cái ra một bề rộng theo chữ đang chọn: đo
	được BẢY bề rộng khác nhau (65 → 140px) nằm cạnh nhau trong cùng một khối.

	150px chính là con số trần của cột ấy, không phải một số mới: đặt bề rộng bằng trần
	thì cột luôn nở hết cỡ cho phép và mọi combobox về cùng một mức. Bề rộng vẽ ra là
	140px — 150 trừ 10px khe của cột phụ.

	Không tốn chỗ: đo ở 412px, cả màn Hoạt động 16.019px trước và sau đúng bằng nhau.
*/
@media only screen and (max-width: 560px) {
	.spk-moi .spk-hang-aux > .spk-chon {
		width: 150px;
	}
}

.spk-moi .spk-hang-aux > .spk-so {
	flex: 0 0 auto;
	width: 72px;
	/* Sàn bề rộng: co dưới mức này thì ô số không còn đọc được số bên trong. */
	min-width: 56px;
}

/*
	Hàng chứa danh sách, bảng hay lưới ô tick: dòng đầu VẪN là lưới 4 cột như hàng
	thường — nhờ vậy công tắc của nó (vd toolThuocTinh_..._Enable) thẳng cột với công
	tắc mọi hàng khác — rồi phần thân trải hết bề ngang ở dòng dưới.
*/
.spk-moi .spk-hang-doc {
	grid-template-areas:
		"btn lab aux sw"
		"than than than than";
	padding: 11px 14px;
}

.spk-moi .spk-hang-rong,
.spk-moi .spk-luoi-tick,
.spk-moi .spk-bang-khoi {
	grid-area: than;
	margin-top: 4px;
}

/* Ô nhập đứng một mình ở hàng dưới thì trải hết hàng — cạnh nó, ô "Mã quà tặng"
   nằm trong .spk-them đã trải sẵn, để nó co lại 180px thì hai hàng so le nhau. */
.spk-moi .spk-hang-rong > .spk-nhap {
	width: 100%;
}

/* ---------- Công tắc ---------- */

.spk-moi .spk-congtac {
	appearance: none;
	-webkit-appearance: none;
	flex: none;
	position: relative;
	width: 44px;
	height: 24px;
	margin: 0;
	padding: 0;
	border: 0;
	border-radius: 12px;
	background: #c6cbd2;
	cursor: pointer;
	transition: background .15s ease;
}

.spk-moi .spk-congtac::after {
	content: "";
	position: absolute;
	top: 2px;
	left: 2px;
	width: 20px;
	height: 20px;
	border-radius: 50%;
	background: #fff;
	box-shadow: 0 1px 2px rgba(0, 0, 0, .3);
	transition: transform .15s ease;
}

.spk-moi .spk-congtac:checked { background: var(--spk-chinh); }
.spk-moi .spk-congtac:checked::after { transform: translateX(20px); }

.spk-moi .spk-congtac:focus-visible {
	outline: 2px solid var(--spk-chinh);
	outline-offset: 2px;
}

/* ---------- Ô chọn, ô nhập, nút ---------- */

/*
	Ô NHẬP, Ô CHỌN: 36px ở luật nền, 40px ở khổ điện thoại — như trước.

	MÀN THIẾT LẬP CÓ LUẬT RIÊNG, hạ xuống 24px (bằng công tắc). Xem khối
	"#settingContent" ở ngay dưới. Người duyệt chốt phạm vi ấy: màn Thiết lập là nơi
	có hàng trăm hàng điều khiển xếp sát nhau nên từng pixel dọc đáng giá; còn
	Tài khoản, Mua VIP, Tra cứu… chỉ có dăm ô nhập, thu chúng lại không được gì mà
	mất cỡ chạm.
*/
.spk-moi .spk-chon,
.spk-moi .spk-nhap,
.spk-moi .spk-so {
	font: inherit;
	color: inherit;
	background: var(--spk-nen-o);
	border: 1px solid var(--spk-vien-o);
	border-radius: 6px;
	padding: 7px 10px;
	margin: 0;
	min-height: 36px;
}

/*
	CHỈ MÀN THIẾT LẬP: ô nhập và ô chọn cao bằng CÔNG TẮC (24px).

	Một con số cho cả ba loại điều khiển, lấy theo thứ đã có sẵn (`.spk-congtac` cao
	24px) chứ không đặt ra số mới. Trước đó chiều cao rải ra bốn mức tuỳ chỗ.

	`line-height: 1.4` KHÔNG PHẢI TRANG TRÍ — nó là thứ quyết định con số có ra đúng
	24 hay không. Ô kế thừa `line-height` 1.5 của trang, nên nội dung cao 21px và
	cộng viền thành 25px: `min-height: 24px` thua, ô vẫn 25px. Đo cả ba mức:

	| line-height | 1.5 | 1.4 | 1.3 | 1.2 |
	|---|---|---|---|---|
	| chiều cao ô | 25 | **24** | 24 | 24 |

	Chọn 1.4 vì nó là mức CAO NHẤT còn ra 24px — chừa nhiều chỗ nhất cho dấu tiếng
	Việt. Không mức nào cắt chữ, nhưng dấu "ộ" hụt vài phần pixel là mắt thấy.

	VÙNG CHẠM 24px, dưới hẳn khuyến nghị (Apple 44pt, Google 48dp) — người duyệt chốt
	sau khi xem số đo. Nút thì GIỮ NGUYÊN 44px: bấm trượt một cái nút là thấy ngay và
	bấm lại được, còn bấm trượt vào ô số là âm thầm gõ đè lên một giá trị thiết lập.

	Và đừng kỳ vọng nó làm màn ngắn lại: đo ở 412×800, danh sách Hoạt động cao 1056px
	TRƯỚC VÀ SAU đều y nguyên, vì hàng thiết lập cao 74px do nhãn và lưới, không do ô.
	Thứ ngắn đi là hàng DANH SÁCH (điểm luyện công, kênh gửi tin): 102 → 70px.

	Dùng `#settingContent` — id gốc của cả bảy màn Thiết lập. Đặc hiệu của id thắng
	mọi luật lớp ở trên lẫn trong media query, nên không phải xếp thứ tự cẩn thận.
*/
#settingContent .spk-chon,
#settingContent .spk-nhap,
#settingContent .spk-so {
	line-height: 1.4;
	padding: 1px 10px;
	min-height: 24px;
}
.spk-moi .spk-chon {
	appearance: none;
	-webkit-appearance: none;
	/* Chừa chỗ cho mũi tên tự vẽ bên dưới. */
	padding-right: 30px;
	background-image:
		linear-gradient(45deg, transparent 50%, var(--spk-chu-mo) 50%),
		linear-gradient(135deg, var(--spk-chu-mo) 50%, transparent 50%);
	background-position: right 14px center, right 9px center;
	background-size: 5px 5px, 5px 5px;
	background-repeat: no-repeat;
	max-width: 100%;
}

.spk-moi .spk-so {
	width: 80px;
	text-align: right;
}

.spk-moi .spk-nhap {
	flex: 1 1 auto;
	min-width: 0;
}

.spk-moi .spk-donvi {
	color: var(--spk-chu-mo);
}

/*
	ĐANG GÕ THÌ SÁNG LÊN — nền trắng, ngược với lúc nghỉ.

	Ô nghỉ thì lõm (nền xám), ô đang gõ thì nổi (nền trắng). Hai trạng thái khác nhau
	ở NỀN chứ không chỉ ở viền, nên nhìn thấy được cả khi vòng sáng bị màn hình chói
	nuốt mất.
*/
.spk-moi .spk-chon:focus,
.spk-moi .spk-nhap:focus,
.spk-moi .spk-so:focus {
	outline: 0;
	background: var(--spk-nen);
	border-color: var(--spk-chinh);
	box-shadow: 0 0 0 3px rgba(107, 63, 160, .18);
}

.spk-moi .spk-nut {
	font: inherit;
	font-weight: 500;
	color: #fff;
	background: var(--spk-chinh);
	border: 1px solid var(--spk-chinh);
	border-radius: 6px;
	padding: 7px 16px;
	min-height: 36px;
	cursor: pointer;
	white-space: nowrap;
}

.spk-moi .spk-nut:hover { background: #55307f; border-color: #55307f; }

/*
	MENU TRÀN của nút "Khác ⋯" ở thanh đáy.

	Mở LÊN TRÊN (`bottom: 100%`) vì thanh nút nằm sát đáy màn hình. Thanh đáy có
	`position: fixed` và `z-index: 10` nên nó tự là một tầng xếp riêng — menu nằm
	trong đó là đã ở trên nội dung trang, không cần z-index to.

	GRID chứ không flex — `gap` của flexbox bị Chrome 68 (MEmu) bỏ qua.
*/
.spk-menu-vo {
	position: relative;
	display: inline-flex;
}

/* Trong thanh đáy, cái vỏ thay nút làm mục flex nên phải mang luật của nút. */
.spk-thanh-day .spk-menu-vo {
	flex: 0 1 auto;
}

.spk-menu {
	display: none;
	position: absolute;

	/*
		Neo theo mép PHẢI của nút. Hồi nút "Khác" còn nằm ở ĐẦU thanh thì neo phải
		làm menu trồi ra ngoài màn ở khổ hẹp (đo được ở 360px: mép trái ở x=-1) nên
		phải neo trái; nay cụm nút dồn sang PHẢI thì ngược lại — neo trái mới là cái
		tràn ra ngoài mép phải.
	*/
	right: 0;
	bottom: 100%;
	margin-bottom: 6px;
	min-width: 190px;
	padding: 6px;
	background: var(--spk-nen);
	border: 1px solid var(--spk-vien);
	border-radius: var(--spk-bk);
	box-shadow: 0 6px 20px rgba(0, 0, 0, .14);
}

/* Bật/tắt bằng LỚP: .show() của jQuery trả về display mặc định của thẻ, mất grid. */
.spk-menu.spk-hien {
	display: grid;
	gap: 2px;
}

.spk-menu-muc {
	font: inherit;
	text-align: left;
	white-space: nowrap;
	color: var(--spk-chu);
	background: none;
	border: 0;
	border-radius: 6px;
	padding: 9px 12px;
	min-height: 36px;
	cursor: pointer;
}

.spk-menu-muc:hover { background: var(--spk-nen-mo); }

/* Việc phá huỷ: chữ đỏ để không lẫn với mục thường ngay trên nó. */
.spk-menu-muc.spk-menu-nguy { color: var(--spk-do); }

.spk-menu-muc.spk-menu-nguy:hover { background: #fdf0f0; }

/*
	Nút chỉ có icon: vuông, cùng chiều cao với ô nhập bên cạnh. Dùng cho "Thêm khung
	giờ" — nhãn chữ chiếm ~110px, mà hàng giờ/phút đã có 4 ô số nên trên màn dọc là
	tràn xuống dòng thứ hai. Chữ chuyển vào title/aria-label nên bàn phím và trình đọc
	màn hình vẫn biết nút làm gì.
*/
.spk-moi .spk-nut-icon {
	flex: none;
	width: 36px;
	padding: 0;
	font-size: 18px;
	line-height: 1;
}

/*
	Biểu tượng đứng trước chữ trong nút. Khác .spk-nut-icon (nút CHỈ có icon, rộng cố
	định 36px): ở đây icon đi kèm chữ nên chỉ cần một khoảng cách nhỏ.
*/
.spk-moi .spk-nut-bt {
	margin-right: 5px;
	font-size: 15px;
	line-height: 1;
}

.spk-moi .spk-nut-bt:only-child {
	margin-right: 0;
}

/*
	NÚT PHỤ: viền xanh, chữ xanh, nền trắng — cùng lối với .spk-nut-bar.

	Một lúc lớp này ra HAI kiểu: các nút trong thẻ gói VIP được tô xanh bằng một
	luật nhắm theo khối chứa, còn "Chỉ định nhân vật của tôi làm đội trưởng" ở màn
	Thiết lập thì vẫn xám — cùng một lớp mà hai bộ mặt. Rà lại toàn bộ nút mới thấy;
	đã gộp về MỘT luật ở đây.
*/
.spk-moi .spk-nut-phu {
	color: var(--spk-chinh);
	background: var(--spk-nen);
	border-color: var(--spk-chinh);
	font-weight: 500;
}

.spk-moi .spk-nut-phu:hover { background: var(--spk-chinh-nhat); border-color: var(--spk-chinh); }

/*
	CỠ NHỎ — cho nút nằm LẪN TRONG một dòng chữ, ví dụ "Mã VIP: XXXX [Copy]".
	Cỡ thường (đệm 7/16, cao tối thiểu 36) sẽ đội dòng chữ ấy phồng lên.
*/
.spk-moi .spk-nut-nho {
	padding: 2px 9px;
	min-height: 24px;
	font-size: 12.5px;
}

.spk-moi .spk-nut:focus-visible {
	outline: 2px solid var(--spk-chinh);
	outline-offset: 2px;
}

/* ---------- Khối thêm thành viên ---------- */

/* Ô nhập + "Thêm" + "Chỉ định..." nằm CÙNG một hàng, xuống dòng khi hẹp. */
.spk-moi .spk-them {
	display: flex;
	flex-wrap: wrap;
	margin-bottom: -8px;
	/* align-items mặc định là stretch: <span> bị kéo cao bằng ô nhập rồi chữ nằm sát
	   MÉP TRÊN, lệch hẳn so với chữ trong ô. Phải căn giữa theo trục dọc. */
	align-items: center;
}
.spk-moi .spk-them > * {
	margin: 0 8px 8px 0;
}

/*
	NÚT TRONG KHỐI NÀY CAO BẰNG Ô NHẬP ĐỨNG CẠNH NÓ — 24px.

	Luật này đã có sẵn cho khổ điện thoại từ đợt trước, với đúng lý do: "hai chiều
	cao lệch nhau 4px cạnh nhau thì mắt thấy ngay, dù chẳng cái nào sai". Nay ô nhập
	về 24px thì khoảng lệch thành 16px chứ không còn 4px, nên luật phải theo — và
	theo ở MỌI khổ, vì trên máy tính nút `.spk-nut` cao 36px cũng đứng cạnh ô 24px.

	Chỉ nút NẰM TRONG `.spk-them` mới hạ. Nút ở nơi khác vẫn 44px: bấm trượt một cái
	nút là thấy ngay và bấm lại được, còn bấm trượt vào ô số là âm thầm gõ đè lên một
	giá trị thiết lập — đó là lý do hai thứ được phép có cỡ chạm khác nhau.

	VÀ CHỈ TRONG #settingContent — cùng ranh giới với luật hạ ô nhập về 24px, vì luật
	này tồn tại để nút cao BẰNG ô nhập đứng cạnh. Ngoài màn Thiết lập thì ô nhập vẫn
	40px, nên hạ nút xuống 24 là tự tạo ra đúng cái lệch mà nó sinh ra để tránh: ở màn
	"Coupon & chuyển xu", nút "Nhập mã quà tặng" cao 24px đứng cạnh ô mã cao 40px, và
	cạnh nút "Chuyển Xu" 44px ngay bên dưới.
*/
#settingContent .spk-them .spk-nut {
	/*
		PHẢI HẠ ĐỆM, không chỉ hạ `min-height`. `.spk-nut` có `padding: 7px 16px`, nên
		chữ 21px cộng đệm 14 cộng viền 2 ra 37px — `min-height: 24px` thua và nút vẫn
		37px. Đây đúng là điều đã đo được khi hạ ô nhập: `min-height` không phải thứ
		quyết định chiều cao, ĐỆM mới là.

		`line-height: 1` chứ không 1.4 như ô nhập: nút chỉ có MỘT dòng chữ nên không cần
		khoảng thở giữa dòng, và nút biểu tượng `.spk-nut-icon` dùng font 18px — nhân với
		1.4 là 25px, cộng viền thành 29px, vượt qua cả `min-height`. Đo được đúng 29px
		trước khi sửa. Với `1` thì cả nút chữ (14px) lẫn nút biểu tượng (18px) đều nằm
		dưới 24px nên `min-height` mới là thứ quyết định, và cả hai ra đúng 24.
	*/
	/* Cùng lý do với nút trong thẻ VIP: hạ chiều cao thì phải tự canh giữa, vì
	   `inline-block` dồn hết phần dư xuống dưới. */
	display: inline-flex;
	align-items: center;
	justify-content: center;
	line-height: 1;
	padding-top: 1px;
	padding-bottom: 1px;
	min-height: 24px;
}


/* Dấu ngăn giờ:phút — sát hai ô số hơn các thành phần khác. */
.spk-moi .spk-gio-cham {
	margin: 0 -3px;
	color: var(--spk-chu-mo);
}

/* ---------- Danh sách động ---------- */

/*
	Dòng tiêu đề "Đội trưởng?" dùng ĐÚNG cấu trúc flex của một dòng danh sách, với một
	ô trống rộng bằng tay cầm kéo. Nhờ vậy chữ tự nằm trên cột ô tick mà không phải
	đo đạc bằng tay — sửa bề rộng tay cầm thì tiêu đề tự chạy theo.

	(Bản gốc căn phải dòng này nên nó nằm lệch hẳn khỏi cột ô tick.)
*/
.spk-moi .spk-ds-dau {
	display: flex;
	align-items: center;
	margin-top: 12px;
	padding: 0 10px 5px;
	color: var(--spk-chu-mo);
	font-size: 12.5px;
}
.spk-moi .spk-ds-dau > *:not(:last-child) {
	margin-right: 8px;
}


.spk-moi .spk-ds {
	list-style: none;
	margin: 8px 0 0;
	padding: 0;
	border: 1px solid var(--spk-vien);
	border-radius: 6px;
	overflow: hidden;
}

/* Có dòng tiêu đề thì danh sách đã cách sẵn, khỏi cộng thêm. */
.spk-moi .spk-ds-dau + .spk-ds {
	margin-top: 0;
}

.spk-moi .spk-ds:empty {
	display: none;
}

.spk-moi .spk-ds-hang {
	display: flex;
	align-items: center;
	/* Mốc neo cho nút Xoá ở những dòng nhấc nút lên góc trên phải. */
	position: relative;
	padding: 7px 10px;
	background: var(--spk-nen);
	border-top: 1px solid var(--spk-vien-nhat);
}
.spk-moi .spk-ds-hang > *:not(:last-child) {
	margin-right: 10px;
}


.spk-moi .spk-ds-hang:first-child { border-top: 0; }
.spk-moi .spk-ds-hang:nth-child(even) { background: var(--spk-nen-mo); }

/*
	Kéo thả: jQuery UI sortable lấy spk-ds-tay làm tay cầm, spk-ds-tru làm vùng loại
	trừ (xem updateTeamMember). Cả bốn danh sách kéo được đều dùng chung một cấu hình
	sortable, nên hai lớp này phải có mặt trên item mới sinh ra; ở đây chúng chỉ là
	móc cho JS, không mang kiểu dáng riêng. (Tên cũ: field-contain-base-col /
	-extra-col — tàn dư bố cục jQuery Mobile, chẳng liên quan gì tới kéo thả.)
*/
.spk-moi .spk-ds-hang > .spk-ds-tay {
	flex: 1 1 auto;
	min-width: 0;
	display: flex;
	align-items: center;
}
.spk-moi .spk-ds-hang > .spk-ds-tay > *:not(:last-child) {
	margin-right: 8px;
}

/*
	DÒNG DANH SÁCH CÓ Ô NHẬP — điểm luyện công và kênh gửi tin.

	Mọi dòng khác chỉ chứa chữ nên xếp ngang một dòng là vừa. Hai danh sách này thì
	không: điểm luyện công có ô tên cộng bốn ô giờ, đo được cần 430px mới đủ một
	hàng — rộng hơn cả màn hình điện thoại.

	Mà FLEXBOX VỠ DÒNG TRƯỚC KHI CO. Không mở `wrap` thì nó không xuống dòng, nó bóp:
	ô tên teo lại còn vài chục pixel trong khi bốn ô giờ vẫn nguyên. Đây là lần thứ
	SÁU cùng một cái bẫy trong dự án (spk-hang-aux, spk-them, spk-bang-the td,
	spk-thanh-day, spk-tt, và giờ là đây) — hễ một hàng flex chứa thứ co được nằm
	cạnh thứ không co được thì phải quyết định trước: cho vỡ, hay đặt sàn.

	Lề âm ở dưới cùng với lề dương trên từng con: khổ Chrome 68 không có `gap`.
*/
.spk-moi .spk-ds-hang > .spk-ds-tay.spk-ds-tay-nhap {
	flex-wrap: wrap;
	margin-bottom: -8px;
	/* Chừa chỗ cho nút Xoá đã nhấc lên góc trên phải (xem khối ngay dưới). */
	padding-right: 40px;
}
.spk-moi .spk-ds-hang > .spk-ds-tay.spk-ds-tay-nhap > * {
	margin-bottom: 8px;
}

/*
	NÚT XOÁ LÊN GÓC TRÊN PHẢI, đúng chỗ thẻ vật phẩm đặt nó.

	Mọi dòng danh sách khác chỉ cao một dòng nên nút xoá canh giữa hay canh trên đều
	ra cùng một chỗ. Hai dòng này thì cao 59–107px tuỳ khổ, và canh giữa làm nút trôi
	xuống lưng chừng — mắt phải đi tìm. Thẻ vật phẩm đã giải xong bài này: ô cuối
	`position: absolute; top: 6px; right: 8px`. Dùng lại đúng số ấy để hai chỗ khớp
	nhau, chứ không chọn lại số mới.

	Hàng phải `position: relative` — nếu không thì `absolute` neo vào tổ tiên định vị
	gần nhất, đo được là cả khối trang, và nút bay lên đầu màn hình.
*/
.spk-moi .spk-ds-hang > .spk-ds-tay-nhap ~ .spk-ds-tru {
	position: absolute;
	top: 6px;
	right: 8px;
}
.spk-moi .spk-ds-hang > .spk-ds-tay-nhap {
	position: static;
}

/*
	Ô GIỜ TRONG HÀNG DANH SÁCH HẸP HƠN Ô GIỜ THƯỜNG: 48px thay vì 72px.

	Không phải để cho đẹp — 24px ấy quyết định hàng cao bao nhiêu. Hàng chứa ô tên
	cộng hai cụm giờ, và cụm nào không đủ chỗ thì xuống dòng riêng. Đo ở khổ 386px
	(khổ trong ảnh người duyệt gửi):

	| bề rộng ô | 320px | 360px | 386px | 412px |
	|---|---|---|---|---|
	| 72 (như cũ) | 150 | 150 | **150** | **150** |
	| 56 | 150 | 150 | 150 | 150 |
	| 48 | 150 | 150 | **102** | **102** |

	Hai chữ số cần chừng 16px, nên 48px vẫn thừa chỗ và không cắt cả chữ mờ "phút".
	Canh GIỮA chứ không canh phải: `.spk-so` canh phải vì nó chứa số tới hàng triệu,
	còn ô hai chữ số canh phải thì trông như bị dồn vào góc.

	320/360px vẫn 150px, và đó là câu trả lời đúng — ở đó hai cụm giờ THẬT SỰ không
	đủ chỗ nằm chung một dòng. Ép chúng vào thì phải bóp ô xuống dưới ngưỡng đọc được.
*/
.spk-moi .spk-ds-tay-nhap .spk-gio .spk-so {
	width: 48px;
	padding-left: 4px;
	padding-right: 4px;
	text-align: center;
}

/*
	Ô TÊN CO ĐƯỢC NHƯNG CÓ CẢ SÀN LẪN TRẦN.

	SÀN 120px, KHÔNG PHẢI 150 — con số này quyết định hàng có vỡ dòng hay không, vì
	flexbox xếp dòng theo flex-basis chứ không theo bề rộng cuối cùng. Đo cả ba nấc:

	| sàn/trần | 560px | 640px | 1280px | ô tên khi co |
	|---|---|---|---|---|
	| 150/320 | hai dòng | **hai dòng** | một dòng | 320 |
	| 120/260 | hai dòng | **một dòng** | một dòng | 140 |
	| 100/260 | hai dòng | một dòng | một dòng | 140 |

	30px sàn đổi được một dòng ở khổ 640px — hàng cao 107 → 59px, bớt 48px cho MỖI
	điểm luyện công. Hạ tiếp xuống 100 thì không mua thêm được gì, nên dừng ở 120.

	Trần 260px: khi ô tên nằm một mình một dòng thì `flex-grow` kéo nó rộng hết cỡ —
	đo được 484px, một ô nhập dài gần nửa màn hình cho một cái tên bản đồ chừng hai
	chục ký tự. Rộng không đồng nghĩa với dùng được.
*/
.spk-moi .spk-ds-tay-nhap .spk-nhap {
	flex: 1 1 120px;
	max-width: 260px;
	min-width: 0;
}


.spk-moi .spk-ds-hang > .spk-ds-tru {
	flex: none;
}

/* ---------- Dấu hiệu kéo thả ---------- */

/*
	Icon ⇅ ở đầu vùng kéo là dấu hiệu chính; kèm con trỏ bàn tay trên cả vùng tay cầm và
	hiệu ứng nhấc dòng lên khi đang kéo.

	Icon do JS sinh, CHỈ ở danh sách Tổ đội và 3 bảng Vật phẩm thật sự gọi .sortable()
	(Đấu giá, Mua đồ trên Shop, Mua trên chợ). Bốn bảng còn lại không có icon.

	Lớp spk-ds-keo-duoc cũng do JS gắn ĐÚNG lên container gọi .sortable(), để con trỏ bàn
	tay không xuất hiện ở bảng không kéo được — dấu hiệu phải nói thật.
*/

.spk-moi .spk-ds-keo {
	flex: none;
	display: inline-block;
	width: 18px;
	text-align: center;
	color: var(--spk-chu-mo);
	cursor: grab;
	user-select: none;
	-webkit-user-select: none;
}

/* Trong ô của bảng không có flex gap, phải tự chừa khoảng cách với tên vật phẩm. */
.spk-moi td.spk-bang-the-keo .spk-ds-keo { margin-right: 6px; }

/* Ô đệm canh cột ở dòng tiêu đề: không kéo được gì, đừng gợi ý là kéo được. */
.spk-moi .spk-ds-dau .spk-ds-keo { cursor: default; }

.spk-moi .spk-ds-keo-duoc .spk-ds-tay,
.spk-moi .spk-ds-keo-duoc .spk-bang-the-keo {
	cursor: grab;
}

/*
	HÀNG CÓ Ô NHẬP: CON TRỎ KHÔNG ĐƯỢC NÓI DỐI.

	Ở những hàng ấy chỉ biểu tượng ⇅ mới kéo được (sortable nhận `handle`), vì để kéo
	cả dòng thì trên điện thoại chạm vào ô nhập là không gõ được gì. Mà lớp
	`.spk-ds-keo-duoc` lại phủ bàn tay nắm lên CẢ cột trái — trông kéo được mà kéo
	không đi.

	Biểu tượng ⇅ giữ nguyên `cursor: grab` của nó (khai ở `.spk-ds-keo`), nên chỗ kéo
	được vẫn tự nói ra.
*/
.spk-moi .spk-ds-keo-duoc .spk-ds-tay.spk-ds-tay-nhap {
	cursor: auto;
}

/*
	VÙNG CHẠM CỦA ⇅ RỘNG RA Ở HÀNG CÓ Ô NHẬP: 24px, bằng mọi điều khiển khác.

	Khi cả dòng kéo được thì icon 18px chỉ là dấu hiệu, trượt tay vẫn kéo trúng dòng.
	Nay nó là CHỖ DUY NHẤT kéo được, nên nó phải đủ to để ngón tay đặt trúng.
*/
.spk-moi .spk-ds-tay-nhap > .spk-ds-keo {
	width: 24px;
	height: 24px;
	line-height: 24px;
}

.spk-moi .spk-ds-keo:active,
.spk-moi .spk-ds-keo-duoc .spk-ds-tay:active,
.spk-moi .spk-ds-keo-duoc .spk-bang-the-keo:active {
	cursor: grabbing;
}

/* Bản sao đang bay theo con trỏ. jQuery UI tự gắn lớp này.
   Kèm tên thẻ để độ đặc hiệu vượt .spk-bang-the-chan (nền xám vằn của bảng), khỏi
   phụ thuộc thứ tự luật trong tệp. */
.spk-moi tr.ui-sortable-helper,
.spk-moi li.ui-sortable-helper {
	background: var(--spk-nen);
	border: 1px solid var(--spk-chinh);
	border-radius: 6px;
	box-shadow: 0 6px 16px rgba(0, 0, 0, .18);
}

/*
	Chỗ sắp thả, chỉ làm cho danh sách <li>.

	jQuery UI LUÔN tạo phần tử này nhưng đặt visibility:hidden thẳng trên thẻ, nên phải
	!important mới hiện ra. Nó là thẻ RỖNG mang class của dòng đang kéo, chiều cao do
	jQuery UI gán. Với <tr> thì một hàng rỗng không có <td> hầu như không dựng được chiều
	cao, nên KHÔNG áp cho bảng — ở đó dòng bay + tô sáng tay cầm đã đủ.
*/
.spk-moi li.ui-sortable-placeholder {
	visibility: visible !important;
	background: #eef3fe;
	outline: 1px dashed var(--spk-chinh);
	outline-offset: -2px;
}

.spk-moi .spk-ds-tick {
	flex: none;
	width: 17px;
	height: 17px;
	margin: 0;
	accent-color: var(--spk-chinh);
	cursor: pointer;
}

.spk-moi .spk-ds-tick:focus-visible {
	outline: 2px solid var(--spk-chinh);
	outline-offset: 2px;
}

.spk-moi .spk-ds-ten {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

/*
	NÚT BIỂU TƯỢNG TRONG HÀNG DANH SÁCH — nền chung của hai việc: xoá (✕) và thêm (+).

	Trước đây chỉ có MỘT lớp, tên .spk-ds-xoa, mà nút "+" (mở ô nhập khung giờ) cũng
	đeo nó — một lớp tên "xoá" đi vẽ nút thêm. Vì thế phải tách hai kiểu bằng
	`[aria-label^="Xóa"]`, tức là màu nút phụ thuộc vào CHỮ TIẾNG VIỆT trong nhãn:
	sửa nhãn thành "Xoá" (dấu đặt chỗ khác) là nút mất màu đỏ mà không ai hay.

	Nay việc nào lớp ấy: .spk-ds-nut lo hình dáng, .spk-ds-xoa lo màu đỏ,
	.spk-ds-them lo nút thêm.
*/
/*
	NÚT XOÁ / THÊM CỦA HÀNG DANH SÁCH: VUÔNG 24px, bằng công tắc.

	Trước đây 30px ở máy tính và 22px ở khổ điện thoại — hai con số, không cái nào
	liên quan tới thứ gì khác trên màn hình. Nay lấy đúng chiều cao công tắc như ô
	nhập và ô chọn, nên cả bốn loại điều khiển trong một hàng cùng một cỡ.

	Ở khổ điện thoại đây là nới ra (22 → 24), không phải bóp lại: cỡ chạm tốt hơn
	một chút so với trước.
*/
.spk-moi .spk-ds-nut {
	font: inherit;
	font-size: 15px;
	line-height: 1;
	color: var(--spk-chu-mo);
	background: transparent;
	border: 1px solid var(--spk-vien);
	border-radius: 6px;
	width: 24px;
	height: 24px;
	padding: 0;
	cursor: pointer;
}

/*
	NÚT XOÁ ĐỎ SẴN, không phải chỉ đỏ khi rê chuột — trên điện thoại không có "rê
	chuột" nên trước đây nút xoá chưa bao giờ đỏ. Đỏ để đọc ra ngay là thao tác
	không lùi lại được.
*/
.spk-moi .spk-ds-xoa {
	color: var(--spk-do);
	border-color: var(--spk-vien);
}

.spk-moi .spk-ds-xoa:hover {
	color: var(--spk-do);
	border-color: var(--spk-do);
	background: rgba(209, 36, 47, .07);
}

/*
	Nút THÊM rê chuột ra màu xanh, không mượn màu đỏ của nút xoá. Trước đây luật
	hover viết cho cả lớp .spk-ds-xoa nên nút "+" cũng đỏ lên khi rê chuột.
*/
.spk-moi .spk-ds-them:hover {
	color: var(--spk-chinh);
	border-color: var(--spk-chinh);
	background: var(--spk-chinh-nhat);
}

.spk-moi .spk-ds-nut:focus-visible {
	outline: 2px solid var(--spk-chinh);
	outline-offset: 2px;
}

/*
	NHÁY VIỀN quanh mục vừa nhảy tới từ cây điều hướng — ba nhịp, 3 giây, rồi tắt.
	setting.js gỡ lớp này sau 3 giây (xem nhayMuc).

	Vẽ bằng box-shadow INSET, không bằng border hay outline:
	  · border  — đổi kích thước, đẩy nội dung và làm lệch chính chỗ vừa cuộn tới
	  · outline — Chrome 68 chưa bo tròn outline theo border-radius (phải Chrome 94),
	              nên góc vuông chồng lên hộp bo tròn
	  · box-shadow NGOÀI — bị cắt: .spk-nhom có `overflow: hidden`, mà đầu mục của
	              Tiện ích là một HÀNG nằm trong đó
	  · box-shadow inset — không bị cắt, nhưng NỀN CỦA CON vẽ đè lên nó: đo được,
	              viền quanh một <details> mất hẳn đoạn chạy qua dòng tiêu đề, vì
	              .spk-nhom-dau có nền riêng
	  · lớp phủ ::after — là phần tử ĐƯỢC ĐỊNH VỊ nên vẽ trên nền của mọi con nằm
	              trong luồng; viền liền mạch quanh cả tiêu đề lẫn thân, không đổi
	              bố cục, theo đúng bo tròn (border-radius: inherit)

	Màu là --spk-chinh (#6b3fa0) viết thành rgba: biến CSS không lồng được vào
	trong rgba() nếu chỉ giữ mã màu dạng hex.

	Ba nhịp trong 3 giây là 1 lần/giây — dưới xa ngưỡng ba lần mỗi giây mà hướng dẫn
	về nội dung nhấp nháy đặt ra.
*/
@keyframes spk-nhay {
	0% { border-color: rgba(107, 63, 160, 0); }
	35% { border-color: rgba(107, 63, 160, 0.6); }
	100% { border-color: rgba(107, 63, 160, 0); }
}

.spk-moi .spk-nhay {
	position: relative;
}

.spk-moi .spk-nhay::after {
	content: "";
	position: absolute;
	/* Bốn khai báo dài thay `inset: 0` — inset cần Chrome 87. */
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	border: 3px solid rgba(107, 63, 160, 0);
	border-radius: inherit;
	pointer-events: none;
	animation: spk-nhay 1s ease-in-out 3;
}

/*
	VIỀN QUANH HÀNG ĐANG ĐƯỢC THAO TÁC — cùng dáng với viền nhảy, nhưng ĐỨNG YÊN.

	Hai việc khác nhau nên hai cách vẽ khác nhau, dù dùng chung một hình:
	  · nhảy tới  — một SỰ KIỆN, xảy ra rồi thôi, nên nháy ba nhịp rồi tắt;
	  · đang sửa  — một TRẠNG THÁI, kéo dài bao lâu tuỳ người dùng, nên giữ nguyên
	                cho tới khi tiêu điểm rời đi. Nháy ở đây thì thành thứ nhấp nháy
	                suốt lúc người ta đang gõ.

	`:focus-within` chứ không `:focus`: thứ nhận tiêu điểm là ô nhập / công tắc / nút
	BÊN TRONG hàng, còn thứ cần đánh dấu là CẢ HÀNG. Chạy từ Chrome 60, dưới mức
	Chrome 68 của máy người dùng.

	Dùng lại y hệt cách vẽ của `.spk-nhay`: lớp phủ `::after` chứ không `border` (đổi
	kích thước, đẩy nội dung) và không `outline` (Chrome 68 chưa bo tròn outline theo
	`border-radius`). Cả bốn lý do đã chép ở khối ngay trên.

	Màu lấy đúng ĐỈNH của hoạt ảnh nhảy — `rgba(107, 63, 160, .6)` ở nhịp 35% — nên
	hai dấu hiệu trông như một họ, không phải hai thứ hao hao.

	CHỈ TRONG #settingContent. Nó sinh ra cho màn Thiết lập, nơi có hàng trăm hàng giống
	hệt nhau xếp sát nhau và người dùng cần biết mình đang gõ vào hàng nào. Các màn Tài
	khoản chỉ có dăm trường, mỗi trường một nhãn riêng — ở đó cái viền không thêm thông
	tin gì mà lại nhấp nháy lên mỗi lần chạm vào một ô.

	Bộ chọn cũ `.spk-moi .spk-hang` bắt luôn cả Mua VIP, Chuyển Xu, Quản lý VIP vì các
	màn ấy cũng dùng chung lớp `.spk-hang` — lọt lưới, không phải một lựa chọn.
*/
#settingContent .spk-hang:focus-within::after {
	content: "";
	position: absolute;
	/* Bốn khai báo dài thay `inset: 0` — inset cần Chrome 87. */
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	/*
		MỎNG HƠN VIỀN NHẢY: 2px thay vì 3px.

		Viền nhảy chỉ sống 3 giây và phải cướp được sự chú ý, nên nó dày. Viền này ở lại
		suốt lúc người ta đang gõ, mà hàng chỉ cao 28px — 3px chiếm hơn một phần mười
		chiều cao hàng và bắt đầu trông như một cái khung chứ không như một dấu hiệu.
	*/
	border: 2px solid rgba(107, 63, 160, .6);
	border-radius: inherit;
	pointer-events: none;
}

/*
	KHÔNG tắt hoạt ảnh này theo `prefers-reduced-motion`.

	Bản đầu có tắt, và hậu quả đo được: trên Edge của chính máy đặt hàng tính năng
	này, viền hiện ra nhưng KHÔNG nháy. Không phải Edge thiếu gì — hỏi thẳng
	Windows bằng SystemParametersInfo(SPI_GETCLIENTAREAANIMATION) thì nó trả về
	False, tức hệ điều hành đang báo "ít chuyển động", và Chromium dịch thẳng cờ ấy
	thành prefers-reduced-motion: reduce.

	Mà thứ đang chạy ở đây KHÔNG PHẢI chuyển động: không gì dịch chuyển, không gì
	phồng to hay xoay — chỉ có màu viền đậm lên rồi nhạt đi. Thứ mà
	`prefers-reduced-motion` sinh ra để chặn là chuyển động gây chóng mặt. Còn
	ngưỡng an toàn về nhấp nháy là ba lần mỗi giây; ở đây là một lần mỗi giây.
*/

/* ---------- Ô TÌM THIẾT LẬP ---------- */

/*
	Nằm ở VỎ, ngay dưới thanh trên cùng, chỉ hiện ở màn Thiết lập (app.js xét).
	Không nằm trong hộp cuộn nên không cần `position: sticky`, và không đè lên
	mục vừa nhảy tới.
*/
/* Đệm dọc 5px thay vì 10px — xem khối "BA DẢI CỐ ĐỊNH" ở .spk-topbar. Ô nhập bên
   trong giữ nguyên `min-height: 36px`, nên vùng chạm không đổi. */
.spk-tim-vo {
	position: relative;
	flex: none;
	padding: 5px 16px;
	background: var(--spk-nen);
	border-bottom: 1px solid var(--spk-vien);
}

/*
	Rộng hết phần chứa nó ở CẢ HAI chỗ đặt: trong cây thì bằng đúng bề ngang các
	hàng của cây (đo được: cùng mép 10→251); ở khu nội dung thì bằng bề ngang khu.
	Trước đó có trần 480px, nên ở khổ rộng ô tìm nằm lọt thỏm giữa một dải trống.
*/
.spk-tim {
	display: block;
	width: 100%;
	min-height: 36px;
	padding: 7px 12px;
	/* Nền xám như mọi ô nhập khác: dải chứa nó cũng trắng, nên ô trắng trên nền trắng
	   là một cái hộp vô hình. Xem khối "NỀN VÀ VIỀN CỦA Ô NHẬP" ở bảng màu. */
	background: var(--spk-nen-o);
	border: 1px solid var(--spk-vien-o);
	border-radius: var(--spk-bk);
	color: var(--spk-chu);
	font: inherit;
	font-size: 14px;
}

.spk-tim:focus {
	border-color: var(--spk-chinh);
	outline: 2px solid var(--spk-chinh);
	outline-offset: -1px;
	background: var(--spk-nen);
}

/*
	Danh sách gợi ý thả xuống. `display: none` mặc định, .spk-hien mới bày ra —
	cùng lối bật/tắt với các khối khác trong app, không dùng style inline.

	Cao tối đa 50vh chứ không một con số px: màn điện thoại nằm ngang chỉ cao
	vài trăm px, danh sách cố định 340px sẽ tràn khỏi màn.
*/
.spk-tim-goi-y {
	display: none;
	position: absolute;
	z-index: 20;
	top: 48px;
	/* Neo cả hai mép thay vì đặt bề ngang: danh sách luôn rộng bằng ô nhập. */
	left: 16px;
	right: 16px;
	max-height: 50vh;
	margin: 0;
	padding: 4px;
	overflow-y: auto;
	list-style: none;
	background: var(--spk-nen);
	border: 1px solid var(--spk-vien);
	border-radius: var(--spk-bk);
	box-shadow: 0 8px 24px rgba(31, 35, 40, 0.16);
}

.spk-tim-goi-y.spk-hien {
	display: block;
}

.spk-tim-muc {
	display: block;
	padding: 7px 10px;
	border-radius: 6px;
	cursor: pointer;
}

.spk-tim-muc:hover,
.spk-tim-muc.spk-dang {
	background: var(--spk-chinh-nhat);
}

.spk-tim-ten {
	display: block;
	font-size: 13.5px;
	color: var(--spk-chu);
}

/* Đường dẫn là thứ phân biệt 232 mục trùng tên nhau — không được cắt bỏ. */
.spk-tim-duong {
	display: block;
	margin-top: 1px;
	font-size: 12px;
	color: var(--spk-chu-mo);
}

/*
	Ô TÌM KHI NẰM TRÊN ĐẦU CÂY (khổ rộng, cây luôn hiện). nav.js chuyển phần tử
	vào #spkSideTren và đeo lớp này — xem datChoOTim.

	Bỏ nền và đường kẻ: trong cây nó không còn là một dải riêng nữa. Lề dưới bằng
	margin chứ không dựa vào `gap` của .spk-side — gap của flexbox cần Chrome 84.

	Danh sách gợi ý thu về đúng bề rộng cột: .spk-side có `overflow-y: auto`, mà
	hộp cuộn thì cắt cả bề ngang — một danh sách rộng 480px trong cột 262px sẽ bị
	cắt cụt.
*/
.spk-side-tren {
	flex: none;
}

.spk-tim-vo-cay {
	padding: 0;
	margin-bottom: 8px;
	background: transparent;
	border-bottom: 0;
}

.spk-tim-vo-cay .spk-tim-goi-y {
	top: 42px;
	left: 0;
	right: 0;
}

/* ---------- Bảng vật phẩm ---------- */

/*
	Bảy bảng vật phẩm dùng chung bộ luật này. Tên cũ là spk-bang-the-* — nói sai việc,
	vì nó không riêng của Đấu giá; đổi sang spk-bang-the-* cho khớp việc nó làm: biến
	<table> thành thẻ ở khổ hẹp. Bốn lớp chết đã bỏ từ Phase 1: -hidden, -input,
	-control, -disable-row (không nơi nào sinh ra chúng).

	Mỗi <td> chứa sẵn một <span class="spk-bang-the-nhan"> ghi tên cột. Màn rộng: nhãn đó
	ẩn vì đã có hàng tiêu đề. Dưới 640px: hàng tiêu đề ẩn, nhãn hiện ra, mỗi <tr> thành một
	thẻ — nhờ vậy bảng 7 cột vẫn đọc được trên điện thoại.
*/

.spk-moi .spk-bang-khoi {
	padding: 12px 14px;
	border-bottom: 1px solid var(--spk-vien-nhat);
}

.spk-moi .spk-nhom-than > .spk-bang-khoi:last-child { border-bottom: 0; }

.spk-moi .spk-bang-nhan {
	margin: 0;
	font-weight: 600;
}

.spk-moi .spk-bang-nhan + .spk-goiy { margin-top: 2px; }

/* Bảng nhiều cột hẹp hơn màn thì cuộn ngang TRONG khung, không đẩy cả trang. */
.spk-moi .spk-bang-cuon {
	margin-top: 8px;
	overflow-x: auto;
	border: 1px solid var(--spk-vien);
	border-radius: 6px;
}

.spk-moi .spk-bang-the {
	width: 100%;
	border-collapse: collapse;
}

/*
	Ô BẢNG ĐƯỢC XUỐNG DÒNG.

	`nowrap` bắt mỗi ô rộng bằng cả chuỗi dài nhất trong nó, nên cột tên vật phẩm
	phình tới 456px và cả bảng ra 861px — rộng hơn khu nội dung, cột cuối (nút Xoá)
	bị đẩy ra ngoài và phải cuộn ngang mới thấy. Đo ở app PC 890px: 5 trên 7 bảng
	tràn, chỉ 6 trên 58 nút Xoá nằm trong tầm nhìn.

	Cho xuống dòng thì ở 890px còn 1 bảng tràn và 57/58 nút thấy được; hàng cao thêm
	16% — đắt hơn nhiều nếu phải cuộn ngang để bấm Xoá.

	Cột tên của 3 bảng kéo được vốn đã `white-space: normal` (xem .spk-bang-the-keo);
	luật này chỉ nới cho 4 bảng còn lại theo.
*/
.spk-moi .spk-bang-the td {
	padding: 7px 10px;
	vertical-align: middle;
	white-space: normal;
	word-break: break-word;
}


.spk-moi .spk-bang-the-dau td {
	position: sticky;
	top: 0;
	background: var(--spk-nen-mo);
	border-bottom: 1px solid var(--spk-vien);
	color: var(--spk-chu-mo);
	font-size: 12.5px;
	font-weight: 600;
	white-space: normal;
}

.spk-moi .spk-bang-the-chan td,
.spk-moi .spk-bang-the-le td {
	border-top: 1px solid var(--spk-vien-nhat);
}

.spk-moi .spk-bang-the-chan { background: var(--spk-nen-mo); }

/*
	Hàng lẻ phải nêu nền RÕ RÀNG chứ không để trong suốt: ô cuối ghim ở luật dưới
	lấy `background: inherit`, mà kế thừa từ một hàng trong suốt thì nội dung trượt
	qua bên dưới vẫn nhìn thấy xuyên qua nút Xoá.
*/
.spk-moi .spk-bang-the-le { background: var(--spk-nen); }

/* ────────── GHIM CỘT CUỐI (nút Xoá) VÀO MÉP PHẢI

   Cho ô xuống dòng đã gỡ phần lớn tràn, nhưng bảng rộng nhất vẫn quá khổ ở cửa sổ
   app PC hẹp — mà bảng nào cũng có nút Xoá ở cột cuối, tức thao tác dễ mất nhất
   lại nằm đúng chỗ bị đẩy ra ngoài trước tiên. Ghim cột ấy thì dù bảng còn cuộn
   ngang, nút Xoá vẫn đứng nguyên ở mép phải: đo được 58/58 nút thấy được ở
   700/840/890/1000px, thay vì 0/6/6/21.

   `position: sticky` chạy từ Chrome 56 nên máy người dùng (Chrome 68) có. Hàng
   tiêu đề trong chính bảng này đã dùng sticky theo trục dọc từ trước — ở đây là
   trục ngang, và ô cuối của hàng tiêu đề ghim CẢ HAI trục cùng lúc.

   CHỈ Ở KHỔ BẢNG. Từ 640px trở xuống bảng biến thành thẻ và ô cuối là
   `position: absolute` — đè lên nhau thì nút Xoá rơi khỏi góc thẻ. */
@media only screen and (min-width: 641px) {
	.spk-moi .spk-bang-the tbody td:last-child,
	.spk-moi .spk-bang-the .spk-bang-the-dau td:last-child {
		position: sticky;
		right: 0;
		background: inherit;
	}

	/* Ô cuối của hàng tiêu đề: nền riêng của nó (nen-mo) chứ không kế thừa hàng. */
	.spk-moi .spk-bang-the .spk-bang-the-dau td:last-child {
		background: var(--spk-nen-mo);
	}
}

/* Nhãn cột nhúng trong ô: chỉ dùng ở khổ điện thoại. */
.spk-moi .spk-bang-the-nhan { display: none; }

/* Nút sổ/thu chỉ có nghĩa ở khổ THẺ. Ở khổ bảng mọi cột đã bày sẵn, thêm nút là
   thêm một cột rỗng nghĩa. */
.spk-moi .spk-the-nut-mo { display: none; }

/*
	MŨI SỔ CỦA THẺ VẬT PHẨM — vẽ bằng viền như ba chỗ kia, và trạng thái đọc từ
	`aria-expanded` thay vì từ ký tự do JS đặt.

	Khai ở đây, ngoài media query, để hình của nút không phụ thuộc khổ màn; còn việc
	nút CÓ HIỆN hay không thì vẫn do khổ quyết định (chỉ khổ thẻ mới cần nó).
*/
.spk-moi .spk-the-nut-mo::before {
	content: "";
	display: inline-block;
	width: 0;
	height: 0;
	border-left: 5px solid currentColor;
	border-top: 4px solid transparent;
	border-bottom: 4px solid transparent;
	transition: transform .15s ease;
}

.spk-moi .spk-the-nut-mo[aria-expanded="true"]::before {
	transform: rotate(90deg);
}

.spk-moi .spk-bang-the-noidung {
	display: inline-flex;
	align-items: center;
}

.spk-moi .spk-bang-the-tick {
	width: 17px;
	height: 17px;
	margin: 0;
	accent-color: var(--spk-chinh);
	cursor: pointer;
}

/* Ô nhập trong thẻ vật phẩm là LỚP RIÊNG, không ăn luật nền — nên chiều cao phải
   khai lại ở đây, cùng một con số (24px, bằng công tắc) và cùng lý do line-height
   1.4. Bỏ sót chỗ này thì ô ra 33px giữa một màn hình toàn ô 24px. */
/*
	Ô NHẬP TRONG THẺ VẬT PHẨM CŨNG NỀN XÁM.

	Đợt trước đổi nền ô nhập và combobox từ trắng sang `--spk-nen-o` vì có người dùng
	báo "giao diện toàn màu trắng, khó phân biệt các control": ô trắng trên nền trắng
	thì thứ duy nhất tách chúng là một đường viền tím nhạt gần như trắng, và trên màn
	hình chói hoặc độ sáng thấp thì viền ấy biến mất.

	Các ô trong thẻ vật phẩm bị bỏ sót vì chúng mang lớp riêng (`.spk-bang-the-nhap`)
	chứ không phải `.spk-nhap`. Cùng một bệnh, cùng một thuốc.
*/
.spk-moi .spk-bang-the-nhap {
	font: inherit;
	line-height: 1.4;
	color: inherit;
	width: 84px;
	padding: 1px 8px;
	min-height: 24px;
	background: var(--spk-nen-o);
	border: 1px solid var(--spk-vien-o);
	border-radius: 6px;
}

/*
	ĐANG GÕ THÌ NỔI LÊN: ô nghỉ LÕM (nền xám), ô đang gõ NỔI (nền trắng). Trước đây hai
	trạng thái chỉ khác nhau ở viền; nay khác cả ở nền nên thấy được kể cả khi vòng sáng
	bị chói nuốt. Cùng lối với `.spk-nhap` ở màn Thiết lập.
*/
.spk-moi .spk-bang-the-nhap:focus {
	background: var(--spk-nen);
}

.spk-moi .spk-bang-the-nhap:focus {
	outline: 0;
	border-color: var(--spk-chinh);
	box-shadow: 0 0 0 3px rgba(107, 63, 160, .18);
}

/*
	KHÔNG CÒN LUẬT RIÊNG CHO <select> TRONG BẢNG THẺ.

	Ô chọn "Hành động" từng là <select> TRẦN — cả dự án có 53 select và 52 cái mang
	`.spk-chon`, riêng cái này do JS sinh ra nên bị bỏ quên. Luật ở đây dựng lại một
	phiên bản rút gọn của `.spk-chon`: có viền có bo, nhưng không mũi tên tự vẽ và
	đệm dọc 5px thay vì 1px.

	Nay select ấy mang `.spk-chon` như mọi ô chọn khác, nên luật này chỉ còn là thứ
	ĐÈ LÊN nó: `.spk-bang-the select` (0-2-1) đặc hiệu hơn `.spk-chon` (0-2-0), nên ô
	vẫn cao 33px trong khi mọi ô khác đã về 24px. Gắn lớp mà không gỡ luật cũ thì
	không thấy gì thay đổi — đúng cái bẫy đặc hiệu đã cắn nhiều lần trong dự án này.
*/

/*
	Ô "Giá bán" KHÔNG ĐƯỢC XUỐNG DÒNG.

	Nó là ô duy nhất trong app có dạng `min ≤ [ô nhập] ≤ max` — năm mẩu phải đọc
	liền một mạch mới hiểu là một khoảng. Từ khi ô bảng được xuống dòng (để bảng hẹp
	lại, xem `.spk-bang-the td`), cột này chỉ được chia 104px trong khi cần ~190px,
	nên nó vỡ thành ba dòng: "1000 ≤ 2500" rồi "≤ 20000" — trông như hai con số rời.

	Đo ở cửa sổ app PC 890px: ô 90–111px → 48–57px, cả bảy bảng thấp đi 5.897 →
	4.919px (−17%). Cái giá là bảng rộng thêm: phần tràn ngang 75 → 228px. Chấp nhận
	được vì cột cuối (nút Xoá) đã GHIM vào mép phải — đo được 82/82 nút vẫn thấy
	được ở mọi khổ.

	Lớp gắn ngay tại nơi dựng ô (setting.js), không dò theo nội dung: CSS không chọn
	được "ô có hai dấu ≤", và một bộ chọn mò thì hỏng lặng lẽ khi nội dung đổi.

	KÈM TÊN THẺ `td` cho đủ độ cụ thể. Bản đầu viết `.spk-moi .spk-bang-the-gia`
	(0,2,0) và nó THUA `.spk-moi .spk-bang-the td` (0,2,1) — luật nằm im, ô vẫn
	xuống dòng, `getComputedStyle` vẫn trả `white-space: normal`. Đo mới thấy.

	CHỈ Ở KHỔ BẢNG (≥641px). Bản đầu áp cho mọi khổ và làm hỏng chế độ THẺ: ở đó ô
	đã là flex một dòng sẵn, còn nhãn "Giá bán:" thì cần xuống dòng — cấm nó là nhãn
	bị CẮT CỤT. Bài đo bắt được ngay (mục 5: "không nhãn nào bị cắt cụt: 1"), trong
	khi phép đo tay của tôi soi cái Ô nên báo sạch.
*/
@media only screen and (min-width: 641px) {
	.spk-moi .spk-bang-the td.spk-bang-the-gia {
		white-space: nowrap;
	}
}

/* Ô tên vật phẩm. Ở 3 bảng kéo được thì chính ô này là tay cầm (xem cấu hình
   sortable trong setting.js); phần dấu hiệu kéo nằm ở khối "Dấu hiệu kéo thả". */
.spk-moi .spk-bang-the-keo {
	white-space: normal;
	min-width: 140px;
}

/* ---------- Hàng có cấu hình chi tiết sổ ra tại chỗ ---------- */

/*
	Bố cục của tham-khao-1: panel nằm NGAY DƯỚI hàng của nó, không phải một khối
	gập riêng ở cuối danh mục. Chú thích trong mã nguồn của họ nói rõ vì sao:
	xếp riêng ở cuối thì "người chơi phải tự đoán khối nào thuộc công tắc nào".

	Mũi ⌄ nằm ở CỘT THỨ TƯ — cùng cột với nút của mọi hàng khác — nên lưới không
	lệch khi một hàng có mũi còn hàng bên cạnh thì không.
*/
/*
	MỖI MỤC SỔ ĐƯỢC LÀ MỘT THẺ RIÊNG — cùng bộ đo với `.spk-nhom` ở Hoạt động.

	Trước đây chúng nằm liền một dải: mục này hết thì mục sau bắt đầu ngay, chỉ cách
	nhau một đường kẻ 1px. Mở một mục ra thì phần chi tiết của nó trôi thẳng vào hàng
	đầu của mục kế — mắt không có chỗ nào để biết mình vừa ra khỏi mục nào.

	Khoảng hở 12px làm việc mà một đường kẻ không làm được: nó nói "hết rồi" bằng
	KHOẢNG TRỐNG, thứ đọc được ngay cả khi lướt nhanh.

	KHE CẢ HAI PHÍA, không chỉ phía dưới. Ở Hoạt động mọi mục đều là thẻ nên lề dưới
	một mình là đủ — thẻ nào cũng có, khe nào cũng đều. Ở Tiện ích thì thẻ xen giữa các
	hàng thường, nên lề dưới một mình để lại đúng một nửa: hở ở dưới mà hàng ngay TRÊN
	vẫn dính vào tiêu đề. Hai thẻ cạnh nhau thì lề dọc chập lại còn 12px, không cộng
	thành 24.
*/
.spk-moi .spk-hang-boc {
	margin: 12px 0;
	background: var(--spk-nen);
	border: 1px solid var(--spk-vien);
	border-radius: var(--spk-bk);
	overflow: hidden;
}

.spk-moi .spk-hang-boc > .spk-hang {
	border-bottom: 0;
	cursor: pointer;
	/*
		ĐỆM 8px như đầu mục. Hàng thường đệm 2px vì có hàng trăm hàng xếp sát nhau và
		từng pixel dọc đáng giá; thanh tiêu đề thì ngược lại — nó cần thở ra để tách khỏi
		các hàng quanh nó, và mỗi màn chỉ có dăm cái.
	*/
	padding-top: 8px;
	padding-bottom: 8px;
}

/*
	TIÊU ĐỀ MỤC SỔ ĐƯỢC = ĐẦU MỤC CỦA HOẠT ĐỘNG.

	Hai thứ làm CÙNG MỘT việc: đứng đầu một khối và sổ khối ấy ra. Trước đây chúng chỉ
	giống nhau ở chữ đậm, còn lại lệch hết — đo được:

	                  đầu mục Hoạt động   mục sổ Tiện ích
	  nền                  #e8e1f2          trong suốt
	  cỡ chữ                15px               14px
	  khe mũi–chữ            2px               6,5px
	  user-select           none               auto
	  cao                   40px               44px

	Một thanh không có nền thì mắt không bám được đâu là chỗ bắt đầu một mục khi cuộn
	qua vài chục hàng liền nhau — đúng lý do đã làm nền cho đầu mục ở đợt trước.
*/
.spk-moi .spk-hang-boc > .spk-hang {
	background: var(--spk-nen-dau);
	user-select: none;
	-webkit-user-select: none;
}

/* Cùng màu rê chuột với đầu mục: đậm thêm một nấc, không sáng lên. */
.spk-moi .spk-hang-boc > .spk-hang:hover {
	background: #ded4ec;
}

.spk-moi .spk-hang-boc > .spk-hang > .spk-hang-nhan {
	font-size: 15px;
	font-weight: 600;
	color: var(--spk-chu);
	/*
		KHE MŨI–CHỮ ĐÚNG 2px, như đầu mục.

		Mũi nằm trong cột `btn` rộng `--spk-cot-mo` (18px) và được căn GIỮA cột, nên nó
		thừa 6,5px mỗi bên — chữ bắt đầu ở mép phải của cột chứ không phải ngay sau mũi.
		Nút đã đổi sang căn TRÁI (luật `.spk-mo-ct` bên dưới), còn chữ thì kéo ngược lại
		đúng phần cột còn thừa.

		Viết bằng `calc` theo chính hai biến sinh ra nó — bề rộng cột và bề rộng mũi —
		chứ không gõ `-11px`: đổi `--spk-cot-mo` thì khe vẫn là 2px, không phải đi tìm
		lại một con số đã quên mất vì đâu mà có.
	*/
	margin-left: calc(2px + 5px - var(--spk-cot-mo));
}

/* Mũi nép TRÁI cột, không nằm giữa: xem lý do ở khe 2px ngay trên. */
.spk-moi .spk-hang-boc > .spk-hang > .spk-hang-btn > .spk-mo-ct {
	justify-content: flex-start;
}

/*
	MỌI NHÃN CHUNG MỘT MỐC LỀ TRÁI — mép trái của mũi.

	Cột `btn` rộng `--spk-cot-mo` (18px) tồn tại cho mũi sổ. Hàng nào KHÔNG có mũi thì
	cột ấy rỗng mà vẫn chiếm chỗ, nên nhãn của nó bắt đầu ở mép PHẢI của cột — lệch
	đúng 18px so với hàng có mũi. Đo ở màn Tiện ích: mục sổ được 27px, mục đơn 45px,
	mục con bên trong 45px. Ba bậc thụt lề cho ba thứ đáng lẽ cùng một cột.

	Đây chính là cái bẫy "ô rỗng vẫn giữ chỗ" đã gỡ cho `.spk-hang-aux` và
	`.spk-hang-sw` — lần này ở cột đầu. Kéo nhãn về đúng đầu cột, trọn `--spk-cot-mo`,
	nên đổi biến ấy thì mọi hàng vẫn thẳng.

	HÀNG CÓ MŨI KHÔNG DÙNG LUẬT NÀY: luật riêng của `.spk-hang-boc > .spk-hang` đặc
	hiệu hơn (0-4-0 so với 0-3-0) và kéo ít hơn 7px, để chữ nằm sau mũi 2px.
*/
.spk-moi .spk-hang > .spk-hang-nhan {
	margin-left: calc(0px - var(--spk-cot-mo));
}

/*
	ĐANG MỞ THÌ NỀN ĐỔI. Trước đây còn một vệt viền trái 3px sáng lên, nhưng viền ấy
	để lộ MỘT VỆT TRẮNG dọc mép trái thanh tiêu đề khi mục đang đóng: viền trong suốt
	vẫn nằm trong hộp nền của thẻ, nên nền trắng của thẻ hiện qua đúng 3px ấy trong khi
	thanh tiêu đề tím chỉ phủ tới mép padding.

	Giờ mục nào cũng là một thẻ riêng có khoảng hở hai bên, nên "đang ở trong mục nào"
	đã đọc được từ chính hình thẻ — không cần thêm một dấu hiệu nữa.

	NỀN KHI MỞ CŨNG BỎ NỐT: thân thẻ để trắng như thân nhóm ở Hoạt động. Thanh tiêu đề
	đã có nền tím và mũi đã quay — hai dấu hiệu ấy đủ nói mục đang mở, còn tô thêm nền
	cho thân thì thành lớp nền thứ hai chồng lên nhau.
*/

/*
	VÙNG CHẠM LÀ CẢ HÀNG, không phải riêng cái nút — `.spk-hang-boc > .spk-hang` mang
	`cursor: pointer` và tay bấm nằm ở đó. Nên sàn 40px của nút không còn là thứ giữ
	vùng chạm: hạ về 24px cho hàng cao đúng 40px như đầu mục, mà chỗ bấm vẫn là trọn
	thanh 40px × cả bề ngang.
*/
.spk-moi .spk-mo-ct {
	flex: none;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	min-height: 24px;
	padding: 0;
	background: none;
	border: 0;
	/*
		CÙNG MÀU VỚI MŨI CỦA ĐẦU MỤC. Mũi vẽ bằng `currentColor`, mà chỗ này đặt
		`--spk-chu-mo` (xám mờ) trong khi đầu mục ở Hoạt động thừa hưởng `--spk-chu`
		(gần đen) — hai mũi cùng hình, cùng cỡ, mà một cái nhạt hơn hẳn. Người duyệt
		nhận ra bằng mắt trước khi tôi nghĩ tới việc đo.

		Mờ đi là đúng khi nó còn là một nút phụ nép bên phải hàng; nay nó đứng đầu một
		thanh tiêu đề, nên nó phải đậm như chữ nó đứng cạnh.
	*/
	color: var(--spk-chu);
	font: inherit;
	line-height: 1;
	cursor: pointer;
}

/*
	CHÍNH SPAN xoay, không phải cả nút. Xoay cả nút thì bao hình xoay theo: một nút
	cao 40px quay 180° vẫn 40px, nhưng nếu sau này nút không vuông thì vùng chạm tụt
	xuống dưới ngưỡng — tách span ra là chặn sẵn lớp lỗi đó.
*/
/*
	MŨI SỔ VẼ BẰNG VIỀN — cùng một hình với đầu mục ở Hoạt động và cây điều hướng.

	Trước đây chỗ này bày ký tự ⌄ còn đầu mục dùng tam giác ▸. Hai nút làm CÙNG MỘT
	việc — sổ một khối ra xem đầy đủ — mà mang hai hình khác nhau thì người dùng phải
	học hai lần.

	Vẽ bằng bốn đường viền thay vì đặt ký tự: cùng cách `.spk-nhom-dau::before` làm, nên
	hai mũi bằng nhau tuyệt đối về cỡ và về màu, không phụ thuộc font nào đang có.
	Cái `<span>` trong markup thành cái vỏ rỗng mang phép xoay.
*/
.spk-moi .spk-mo-ct-mui {
	display: inline-block;
	width: 0;
	height: 0;
	font-size: 0;
	border-left: 5px solid currentColor;
	border-top: 4px solid transparent;
	border-bottom: 4px solid transparent;
	transition: transform .15s ease;
}

/* Mở ra thì mũi quay xuống — đúng 90° như đầu mục, không phải 180°. */
.spk-moi .spk-ct-mo .spk-mo-ct-mui {
	transform: rotate(90deg);
}

/* Ẩn/hiện bằng LỚP trên thẻ bọc, không đặt display inline từ JS. */
/*
	THÂN MỤC LÀ THÂN THẺ, không phải một khung riêng lồng trong thẻ.

	Trước đây chỗ này tự vẽ một khung: nền trắng, viền, bo góc, thụt vào 14px mỗi bên —
	đúng khi mục sổ được còn là một HÀNG nằm giữa danh sách, vì khi ấy phần chi tiết cần
	một đường bao để nói "chỗ này thuộc về hàng bên trên".

	Từ khi mỗi mục sổ được là một THẺ riêng thì cái khung ấy thành lớp thứ hai: thẻ mở
	ra tô nền tím nhạt, rồi bên trong lại một hộp trắng có viền. Đầu mục ở Hoạt động
	không làm vậy — `.spk-nhom-than` không có nền cũng không có viền của riêng nó, nó
	CHÍNH LÀ thân của thẻ.
*/
.spk-moi .spk-chi-tiet {
	display: none;
}

.spk-moi .spk-ct-mo > .spk-chi-tiet {
	display: block;
}


/* Hàng cuối trong panel không cần kẻ dưới, đã có viền panel. */
.spk-moi .spk-chi-tiet > .spk-hang:last-child,
.spk-moi .spk-chi-tiet > .spk-hang-doc:last-child {
	border-bottom: 0;
}

/* Mục con lồng trong panel: bớt viền để không thành ba lớp khung chồng nhau. */
.spk-moi .spk-chi-tiet .spk-nhom {
	margin: 0;
	border-width: 1px 0 0;
	border-radius: 0;
}

/* ---------- Mục "bỏ qua hoạt động" (Bí Cảnh Mê Cung) ---------- */

/*
	Cột trái của dòng này xếp DỌC: tên hoạt động, bảng nhập khung giờ (ẩn cho tới khi
	bấm +), rồi các chip khung giờ đã thêm. Mọi dòng danh sách khác chỉ có một dòng chữ
	nên xếp ngang là đủ; riêng đây thì không.
*/
.spk-moi .spk-ds-hang > .spk-ds-tay.spk-cot {
	flex-direction: column;
	align-items: flex-start;
	margin-bottom: -6px;
}
/* Xếp dọc thì chỉ cần lề dưới; kéo margin âm cho khỏi thừa một khe. */
.spk-moi .spk-ds-hang > .spk-ds-tay.spk-cot > * {
	margin-bottom: 6px;
}


.spk-moi .spk-khung-gio-them,
.spk-moi .spk-khung-gio-ds {
	width: 100%;
}

.spk-moi .spk-khung-gio-ds {
	display: flex;
	flex-wrap: wrap;
	margin-bottom: -6px;
}
.spk-moi .spk-khung-gio-ds > * {
	margin: 0 6px 6px 0;
}


.spk-moi .spk-khung-gio-ds:empty {
	display: none;
}

/* Chip một khung giờ đã thêm. */
.spk-moi .spk-khung-gio-the {
	display: inline-flex;
	align-items: center;
	padding: 3px 4px 3px 10px;
	background: var(--spk-nen-mo);
	border: 1px solid var(--spk-vien);
	border-radius: 999px;
	font-size: 12.5px;
	font-variant-numeric: tabular-nums;
}
.spk-moi .spk-khung-gio-the > *:not(:last-child) {
	margin-right: 4px;
}


.spk-moi .spk-chip-xoa {
	font: inherit;
	font-size: 15px;
	line-height: 1;
	color: var(--spk-chu-mo);
	background: transparent;
	border: 0;
	border-radius: 50%;
	width: 20px;
	height: 20px;
	padding: 0;
	cursor: pointer;
}

.spk-moi .spk-chip-xoa:hover {
	color: var(--spk-do);
	background: var(--spk-nen);
}

/* ---------- Form tài khoản (đăng nhập / đăng ký / đổi mật khẩu) ---------- */

/*
	Bản gốc xếp hai cột bằng `float: left; width: 46%` — cần clearfix và không tự về một
	cột khi hẹp. Lưới auto-fit làm đúng việc đó: hai cột khi còn chỗ cho 300px mỗi cột,
	một cột khi không.
*/
.spk-moi #registerForm,
.spk-moi #editAccountPass1,
.spk-moi #editAccountPass2 {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
	gap: 2px 18px;
	align-items: start;
}
/* Những thứ chiếm trọn bề ngang dù lưới có mấy cột. */

.spk-moi .account-div-title {
	margin: 12px 0;
	color: var(--spk-chu);
	font-weight: 600;
}

/* ---------- Nhóm chọn một (radio) ---------- */

/*
	jQM dựng nhóm radio thành dải nút phân đoạn. Ở đây mỗi lựa chọn là một "chip", cùng
	hình với ô tick nhưng chọn một.

	KHÔNG bọc <input> vào trong <label>: JS thay TOÀN BỘ nội dung nhãn theo id
	($("#purchaseLabelProgram" + i).text(...)), bọc vào là mất luôn ô radio. Hai thẻ là
	ANH EM, và markup đã đảo về input-trước-label để `input:checked + label` bắt được.
*/
.spk-moi .spk-luoi-radio {
	display: flex;
	flex-wrap: wrap;
	margin-bottom: -6px;
}
/*
	Kèm cả CHÁU cho biến thể tab.

	`.spk-luoi-radio-tab` bọc các radio trong một <span> mang `display: contents`:
	span biến mất khỏi cây bố cục nên CHÁU mới là mục flex thật, nhưng bộ chọn `> *`
	vẫn chỉ trúng cái span. Thiếu dòng thứ hai thì các nhãn tab không nhận lề nào và
	dính sát nhau — đo được ba nhãn dịch trái 6, 12, 18px.
*/
.spk-moi .spk-luoi-radio > *,
.spk-moi .spk-luoi-radio-tab > span > * {
	margin: 0 6px 6px 0;
}


/* Ô radio thật: ẩn khỏi mắt nhưng GIỮ trong luồng tiêu điểm để bàn phím dùng được. */
.spk-moi .spk-radio {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: 0;
	opacity: 0;
	pointer-events: none;
}

.spk-moi .spk-luoi-radio label {
	display: inline-flex;
	align-items: center;
	padding: 7px 14px;
	background: var(--spk-nen);
	border: 1px solid var(--spk-vien);
	border-radius: 999px;
	cursor: pointer;
	user-select: none;
	-webkit-user-select: none;
	transition: background-color .12s ease, border-color .12s ease;
}

.spk-moi .spk-luoi-radio label:hover {
	background: var(--spk-nen-mo);
	border-color: #c6cbd2;
}

.spk-moi .spk-radio:checked + label {
	background: rgba(107, 63, 160, .08);
	border-color: var(--spk-chinh);
	color: var(--spk-chinh);
	font-weight: 600;
}

/* Ô radio ẩn nên viền tiêu điểm phải vẽ lên chính cái nhãn. */
.spk-moi .spk-radio:focus-visible + label {
	outline: 2px solid var(--spk-chinh);
	outline-offset: 2px;
}

/* Dải chọn kiểu tab (lịch sử giao dịch): rộng hơn, nằm trên cùng. */
.spk-moi .spk-luoi-radio-tab {
	margin-bottom: 12px;
}

/*
	Thanh tab ở khổ rộng KHÔNG xuống dòng, nên bỏ lề dọc của các tab đi.

	Để nguyên thì thanh cao thêm 6px, mà lề dưới của nó lại GỘP LỀ với lề trên 8px
	của khối bảng ngay dưới — gộp lề lấy giá trị LỚN HƠN, nên chỉnh lề dưới xuống
	bao nhiêu cũng không kéo lại được 6px ấy: đo được cả bảng tra cứu tụt 2px dù đã
	trừ. Cách duy nhất khớp lại là đừng làm thanh cao thêm.

	Khổ hẹp thì tab CÓ xuống dòng, nên lề dọc trả lại ở media query bên dưới.
*/
.spk-moi .spk-luoi-radio-tab > span > * {
	margin-bottom: 0;
}

.spk-moi .spk-luoi-radio-tab > span {
	display: contents;
}

/* ---------- Bảng lịch sử giao dịch ---------- */

.spk-moi .spk-bang-gd {
	width: 100%;
	border-collapse: collapse;
	white-space: nowrap;
}

.spk-moi .spk-bang-gd th {
	padding: 8px 12px;
	background: var(--spk-nen-mo);
	border-bottom: 1px solid var(--spk-vien);
	color: var(--spk-chu-mo);
	font-size: 12.5px;
	font-weight: 600;
	text-align: left;
}

.spk-moi .spk-bang-gd td {
	padding: 8px 12px;
	border-top: 1px solid var(--spk-vien-nhat);
}

.spk-moi .spk-bang-gd tbody tr:nth-child(even) {
	background: var(--spk-nen-mo);
}

/*
	Bảng rỗng thì không hiện khung — khu Tra cứu lịch sử có tới 5 bảng, mỗi lúc chỉ
	một cái có dữ liệu.

	CHỈ trong #transactionList. Bên Thiết lập cũng có 8 khung .spk-bang-cuon nhưng
	là bảng người dùng tự thêm dòng vào; giấu cả khung khi chưa có dòng nào thì mất
	luôn hàng tiêu đề.

	`:not(:has(tbody tr))` chứ không phải `:has(tbody:empty)`: <tbody> trong
	license.html viết xuống dòng nên luôn chứa một node văn bản trắng, `:empty`
	không bao giờ trúng — luật cũ chết từ lúc viết, để lộ bốn vạch 2px.
*/
.spk-moi #transactionList .spk-bang-cuon:not(:has(tbody tr)) {
	display: none;
}

/* ---------- Khối tóm tắt đơn hàng ---------- */

.spk-moi .spk-tom-tat {
	padding: 12px 14px;
	background: var(--spk-nen-mo);
	border-top: 1px solid var(--spk-vien-nhat);
}

.spk-moi .spk-tom-tat > div {
	margin-bottom: 4px;
}

.spk-moi .spk-tom-tat > div:last-child { margin-bottom: 0; }
/*
	Bí danh cho hai lớp cũ: JS còn ~30 chỗ ghép chuỗi `class='red-text-bold'` vào nội
	dung, phần lớn là thông báo hộp thoại (nằm NGOÀI .spk-moi, giữ nguyên đỏ tươi), số
	còn lại đổ vào #licenseTotalPrice, #bangPrice… (nằm TRONG .spk-moi).

	Đặt bí danh thay vì sửa 30 chuỗi: sửa chuỗi thì phải phân biệt chỗ nào vào hộp thoại
	chỗ nào vào panel — mà cùng một hàm dựng chuỗi có thể dùng cho cả hai.
*/

/* Chữ cần nhấn mạnh (gộp cả .red-text / .red-text-bold của bản gốc). */
.spk-moi .spk-nhan-manh {
	color: var(--spk-do);
	font-weight: 600;
}

/* Chữ phụ trong tiêu đề nhóm (vd "(tối đa 50 nhân vật)"). */
.spk-moi .spk-nhom-phu {
	color: var(--spk-chu-mo);
	font-weight: 400;
}

/* Hàng chỉ chứa các nút thao tác. */
.spk-moi .spk-thanh-nut {
	display: flex;
	flex-wrap: wrap;
	margin: 0;
	padding: 11px 14px 3px;
	border-bottom: 1px solid var(--spk-vien-nhat);
}
.spk-moi .spk-thanh-nut > * {
	margin: 0 8px 8px 0;
}


.spk-moi .spk-nhom-than > .spk-thanh-nut:last-child { border-bottom: 0; }

/* ---------- Lưới ô tick ---------- */

/*
	Nhóm ô tick của bản gốc là chuỗi <input>+<label> rời nằm trong một controlgroup
	của jQM. Ở đây mỗi ô là một "chip" bọc trong <label> nên bấm vào chữ cũng tick
	được, và chúng tự xuống hàng theo bề ngang.

	JS đọc nhóm bằng $("#nhom").find("input") và bật từng ô bằng id — bọc thêm
	<label> không đụng gì tới hai cách đó.
*/
/*
	DỒN PHẢI như mọi control khác. Lưới tick nằm ở dòng dưới của hàng, và trước đây nó
	nép trái trong khi công tắc, ô nhập và combobox của các hàng quanh nó đều ăn về mép
	phải — một khối viên tròn lệch hẳn sang bên kia màn hình.

	LỀ ĐỔI SANG BÊN TRÁI của mỗi viên. Lề phải đặt lên MỌI con thì con CUỐI cũng mang
	nó, và 6px ấy chen giữa viên cuối với mép phải làm cả cụm lệch đúng 6px so với các
	hàng khác. Lề trái thì phần thừa rơi vào chỗ vốn đã là khoảng trống.
*/
.spk-moi .spk-luoi-tick {
	display: flex;
	flex-wrap: wrap;
	justify-content: flex-end;
	/*
		KHÔNG kéo giãn viên theo chiều dọc. `display: flex` mặc định `stretch`, và từ khi
		lưới vào ô `aux` của hàng thì ô ấy cao bằng cả hàng — nhãn hai dòng là viên cao
		theo, đo được 44px thay vì 24px. Trước đây lỗi này không lộ vì lưới nằm ở dòng
		riêng, cao đúng bằng chính nó.
	*/
	align-items: center;
	margin-bottom: -6px;
}
.spk-moi .spk-luoi-tick > * {
	margin: 0 0 6px 6px;
}


/*
	VIÊN TICK CAO BẰNG CÔNG TẮC — 24px kể cả viền, giống ô nhập và nút.

	Ô TICK BÊN TRONG GIỮ NGUYÊN 17px: nó đang vừa mắt, và nó cũng là con số dùng
	chung với `.spk-ds-tick` / `.spk-bang-the-tick`. Thứ phải co là CÁI VỎ.

	Cách co: bỏ đệm dọc, đặt sàn 24px. Nội dung cao nhất trong viên là dòng chữ
	(14px × line-height 1.5 = 21px), cộng viền thành 23px — nhỏ hơn sàn, nên sàn mới
	là thứ quyết định và viên ra đúng 24px. Không phải đụng tới `line-height`, cũng
	không phải đụng tới ô tick.

	Trước đây đệm dọc 7px cho ra 37px: chữ 21 + đệm 14 + viền 2. Nhớ rằng `min-height`
	một mình KHÔNG hạ được gì — nó chỉ là sàn, phải cắt đệm thì nội dung mới lọt xuống
	dưới sàn.
*/
.spk-moi .spk-tick {
	display: inline-flex;
	align-items: center;
	/*
		VIỀN BAO THEO BẢN THAM-KHẢO-1: bo 8px, đệm 8px bên trái và 10px bên phải.

		Bo 999px cho ra hình viên thuốc, và ở chiều cao 24px thì hai đầu cong gần thành
		nửa đường tròn — viên trông như cái nút bấm chứ không như một ô chọn. Bo 8px giữ
		đúng họ với ô nhập (6px) và nút (6px) quanh nó.

		Hai đệm ngang LỆCH NHAU là cố ý, chép đúng bản tham khảo: bên trái là ô tick
		vuông sát mép, bên phải là chữ — cùng một con số thì mắt thấy lệch phải.
	*/
	padding: 0 10px 0 8px;
	min-height: 24px;
	background: var(--spk-nen);
	border: 1px solid var(--spk-vien);
	border-radius: 8px;
	cursor: pointer;
	user-select: none;
	-webkit-user-select: none;
}
.spk-moi .spk-tick > *:not(:last-child) {
	margin-right: 7px;
}


.spk-moi .spk-tick:hover {
	border-color: #c6cbd2;
	background: var(--spk-nen-mo);
}

.spk-moi .spk-tick input {
	/* Cùng 17px với mọi ô tick khác (spk-ds-tick, spk-bang-the-tick) — lệch 1px
	   giữa các danh sách nhìn ra ngay là không đều. */
	width: 17px;
	height: 17px;
	margin: 0;
	accent-color: var(--spk-chinh);
	cursor: pointer;
}

.spk-moi .spk-tick:has(input:checked) {
	border-color: var(--spk-chinh);
	background: rgba(107, 63, 160, .07);
}

.spk-moi .spk-tick:focus-within {
	outline: 2px solid var(--spk-chinh);
	outline-offset: 1px;
}

/*
	BIẾN THỂ KHÔNG VIỀN — dùng cho "Lưu đăng nhập" ở form đăng nhập.

	Dạng viên có viền là cố ý ở màn Thiết lập: ở đó mỗi ô tick là một lựa chọn
	trong một HÀNG DÀI, viền giúp tách chiên nhau. Trong form đăng nhập thì chỉ có
	MỘT ô, viền quanh nó chỉ làm rối.

	Không sửa luật chung `.spk-tick` vì lớp ấy dùng ở khoảng 150 chỗ khác.

*/
.spk-moi .spk-tick.spk-tick-tran {
	padding: 0;
	background: none;
	border: 0;
}

.spk-moi .spk-tick.spk-tick-tran:hover {
	background: none;
}

/*
	Không vẽ khung khi nhận tiêu điểm.

	Bấm chuột vào nhãn cũng làm ô tick nhận tiêu điểm, nên `:focus-within` của luật
	chung vẽ một khung xanh 2px quanh CẢ NHÃN — với biến thể trần thì đó đúng là
	"cái viền hiện ra khi bấm".

	Bỏ khung ấy KHÔNG làm mất dấu tiêu điểm: chính ô tick vẫn có vòng tiêu điểm
	mặc định của trình duyệt, đúng như mọi ô tick thông thường khác.
*/
.spk-moi .spk-tick.spk-tick-tran:focus-within {
	outline: none;
}

/*
	`:has()` cần Chrome 105 nên trên Chrome 68 cả luật này lẫn luật tô màu khi được
	chọn ở trên đều bị bỏ — cùng bị bỏ thì kết quả vẫn khớp nhau, không lệch.
*/
.spk-moi .spk-tick.spk-tick-tran:has(input:checked) {
	background: none;
	border-color: transparent;
}


/* ---------- Khối ghi chú / hướng dẫn ---------- */

/*
	Bản gốc dùng .red-text-bold: cả đoạn hướng dẫn dài in đỏ đậm, đọc rất mệt. Đổi thành
	một khung ghi chú nền nhạt, chỉ tiêu đề được nhấn.
*/
.spk-moi .spk-luuy {
	margin: 0;
	padding: 11px 14px;
	background: var(--spk-nen-mo);
	border-bottom: 1px solid var(--spk-vien-nhat);
	font-size: 13px;
}

.spk-moi .spk-luuy-dau {
	margin: 0 0 4px;
	font-weight: 600;
}

.spk-moi .spk-luuy p + .spk-luuy-dau { margin-top: 10px; }

.spk-moi .spk-luuy ul {
	margin: 0;
	padding-left: 20px;
}

.spk-moi .spk-luuy ul ul {
	margin-top: 3px;
}

.spk-moi .spk-luuy li { margin-bottom: 3px; }
.spk-moi .spk-luuy li:last-child { margin-bottom: 0; }

/* ---------- Ô giờ:phút ---------- */

.spk-moi .spk-gio {
	display: inline-flex;
	align-items: center;
}
.spk-moi .spk-gio > *:not(:last-child) {
	margin-right: 5px;
}


.spk-moi .spk-gio .spk-so { width: 62px; }

/* ---------- ĐIỆN THOẠI ---------- */
/*
	LƯỚI TICK NGẮN LÊN CÙNG DÒNG VỚI NHÃN.

	Lưới tick vốn nằm ở vùng `than`, tức luôn chiếm trọn một dòng riêng bên dưới nhãn.
	Với một lưới ba viên thì đó là một dòng gần như trống bên phải nhãn và một dòng gần
	như trống bên trái lưới — hai nửa dòng thừa cho một thứ vừa một dòng.

	Đo ở màn Hoạt động, 21 hàng có lưới tick, ở khổ máy tính:

	             cùng dòng   cao TB      cả màn
	  640px       12/21      62 → 48   12.720 → 12.420
	  900px       12/21      89 → 74   13.825 → 13.525
	  1280px      12/21      76 → 62   13.129 → 12.829

	CHỈ ≤4 VIÊN được gắn lớp: 8/21 hàng có mười viên, khoảng 1.050px — ở khổ máy tính
	cột phụ nhận `auto` nên nó đòi bằng max-content và TRÀN ra ngoài hàng. Lưới do JS đổ
	đầy (0 `<label>` trong markup) cũng KHÔNG gắn: đếm lúc build không nói được gì về số
	viên lúc chạy.

	PHẢI có lớp đánh dấu, cùng lý do với `.spk-hang-ct`: đếm số viên là hỏi về CON, mà
	chọn cha theo con thì cần `:has()` — Chrome 105, người dùng có máy Chrome 68.
	`tools/gate.py` canh cả hai chiều.
*/
.spk-moi .spk-hang-tick > .spk-luoi-tick {
	grid-area: aux;
	margin-top: 0;
}
/* Mốc 640px theo đúng mốc đã dùng trong khối "GIAO DIỆN ĐIỆN THOẠI" ở trên. */

/*
	Hai mốc khổ màn dưới đây lấy từ tham-khao-1, KHÔNG phải số tự nghĩ:
	  ≤900px — cột phụ 158→132, cột công tắc 92→78, cột nút giữ 40
	  ≤560px — nhãn chiếm trọn dòng trên, ba ô còn lại xuống dòng dưới
	Mốc 640px sẵn có trong tệp lo việc bảng → thẻ, để nguyên.
*/
@media only screen and (max-width: 900px) {
	.spk-moi {
		--spk-cot-phu: 132px;
		--spk-cot-ct: 78px;
	}
}

@media only screen and (max-width: 560px) {
	/*
		MỌI CONTROL NẰM CÙNG DÒNG VỚI NHÃN — `fit-content(150px)` cho cột phụ.

		Bản trước cho nhãn chiếm trọn dòng trên và đẩy cả cụm điều khiển xuống dòng dưới,
		với lý lẽ "chia dòng thì nhãn hẹp đi và phần lớn phải xuống thêm dòng". Đo lại thì
		lý lẽ ấy chỉ đúng khi cột phụ được lấy BAO NHIÊU TUỲ Ý: để cột là `auto` thì một
		combobox đòi bằng nội dung dài nhất của nó, nhãn tụt từ hai xuống ba dòng và cả màn
		phình 8%. Chặn trần cột phụ lại thì kết quả lật ngược — đo ở màn Hoạt động, 137 hàng:

		                       hàng cùng dòng   360px      412px
		  nhãn riêng một dòng      74/137       17.077     15.541
		  fit-content(120px)      137/137       16.551     14.487
		  fit-content(150px)      137/137       16.992     14.901   ← chọn
		  minmax(0, 150px)        137/137       17.577     15.237
		  fit-content(170px)      137/137       17.556     15.267

		VỪA cùng dòng VỪA ngắn hơn: một dòng nhãn tốn 21px, còn chỗ cột phụ lấy của nhãn
		phần lớn KHÔNG làm nhãn dài thêm dòng nào.

		`fit-content(150px)` chứ không `minmax(0, 150px)`: minmax GIỮ CHỖ đủ 150px kể cả
		khi trong đó chỉ có một ô số rộng 96px — 54px ấy lấy không của nhãn. fit-content co
		theo nội dung rồi mới chặn trần, nên ô số lấy 96 và combobox lấy 150.
		Chrome 57 trở lên có, người dùng có máy Chrome 68.

		150 chứ không 120: 120px ngắn hơn được 3% nhưng cắt cụt chữ trong combobox
		("Tự động dùng ngay" còn "Tự động dùng"). Một danh sách ngắn hơn mà không đọc được
		đang chọn gì thì không phải là gọn.
	*/
	.spk-moi .spk-hang {
		grid-template-columns:
			var(--spk-cot-mo) minmax(0, 1fr) fit-content(150px) auto;
		grid-template-areas: "btn lab aux sw";

		/*
			Khe DỌC 2px: ở khổ này nhãn và cụm điều khiển là hai dòng của CÙNG một hàng,
			nên chúng phải sát nhau HƠN HẲN khoảng cách sang hàng kế. Khe ngang giữ 10px
			vì ba ô ở dòng dưới là ba thứ độc lập thật.

			Con số này là TƯƠNG QUAN, không phải giá trị tuyệt đối. Hồi đệm hàng còn 8px
			thì 4px là đủ: trong hàng 4px so với giữa hàng 17px, tỉ lệ 4,25. Đệm xuống
			2px thì giữa hàng chỉ còn 5px — tỉ lệ tụt về 1,25 và mắt thôi tách được:
			bốn hàng combo liên tiếp trông như nhãn thuộc về combo PHÍA TRÊN nó.

			Xiết khe trong hàng là nước đi KHÔNG TỐN GÌ: tỉ lệ lên 2,5 mà danh sách còn
			ngắn đi 18px, khác với việc nới đệm ra — nới thì tách rõ hơn nhưng dài thêm.

			CHỈ KHE DỌC: khe ngang do lề của từng vùng lo (xem `.spk-hang-aux` ở luật nền),
			vì `gap` chừa chỗ ở cả hai bên một cột rỗng và đẩy control ra khỏi mép phải.
		*/
		row-gap: 2px;
	}

	.spk-moi .spk-hang-doc {
		grid-template-areas:
			"btn lab aux sw"
			"than than than than";
	}

	/*
		CỘT PHỤ VẪN DỒN PHẢI, kể cả khi nó nằm ở dòng dưới.

		Trước đây chỗ này ghi `flex-start` với lý lẽ "xuống dòng riêng thì hết lý do dồn
		phải". Lý lẽ ấy nhìn từng hàng một, mà mắt người đọc CẢ CỘT: dòng dưới có ô nhập
		nép trái và công tắc ở mép phải, nên mỗi hàng bày một trục dọc khác nhau — đo được
		chỉ 33/137 hàng có control sát công tắc, 104 hàng còn lại rải rác giữa dòng.

		Dồn phải thì cả 137 hàng cùng một trục, và KHÔNG TỐN MỘT PIXEL nào: chiều cao đo
		trước và sau đúng bằng nhau (16.211px ở khổ 412). Cùng một lẽ với việc căn công
		tắc thẳng cột ở đợt trước.
	*/


	/*
		HÀNG CHỈ CÓ CÔNG TẮC: nhãn và công tắc CÙNG MỘT DÒNG, công tắc ở mép phải.

		Nhãn nào vừa một dòng thì hàng còn 48px (từ 66); nhãn nào cần hai dòng thì 67px
		— vẫn gọn hơn, và nhãn được phép xuống hai dòng chứ không bị cắt.
		Đo ở 412×800: 14 → 18 hàng thấy trọn một khung nhìn.

		PHẢI có lớp đánh dấu vì điều kiện là "ô phụ RỖNG", mà chọn cha theo con thì cần
		`:has()` — Chrome 105, trong khi người dùng có máy chạy Chrome 68. Lớp do
		`tools/gate.py` canh cho khỏi trôi: hàng nào đủ điều kiện mà thiếu lớp, hoặc có
		lớp mà không đủ điều kiện, đều bị chặn.

		KHÔNG đụng 161 hàng có ô phụ: ở đó nhãn vẫn chiếm trọn dòng trên, vì chia dòng
		với cột công tắc thì nhãn chỉ còn ~198px và phần lớn xuống hai dòng — đo được
		chúng phình từ 82 lên 103px. Được vế này mất vế kia, nên tách bằng lớp.
	*/
	.spk-moi .spk-hang.spk-hang-ct {
		grid-template-columns: var(--spk-cot-mo) 1fr auto;
		grid-template-areas: "btn lab sw";
	}

	/*
		PHẢI gỡ hẳn ô phụ khỏi lưới, không thì công tắc LỆCH 20px so với các hàng khác.

		`.spk-hang-aux` vẫn mang `grid-area: aux`, mà mẫu lưới ở trên không có vùng tên
		ấy — trình duyệt bèn đẻ ra hai cột NGẦM rộng 0px để chứa nó. Cột rộng 0 nhưng
		KHE GIỮA CỘT vẫn tính đủ: 2 × 10px = đúng 20px, và cả cụm bị đẩy sang trái.
		Đo được `grid-template-columns` ra "148px 78px 40px 0px 0px" thay vì ba cột.

		Ở hàng này ô phụ vốn RỖNG (đó chính là điều kiện để được gắn lớp), nên ẩn hẳn
		là đúng nghĩa chứ không phải mẹo che.
	*/
	.spk-moi .spk-hang.spk-hang-ct > .spk-hang-aux {
		display: none;
	}

	/*
		Ô số KHÔNG kéo full bề ngang: đơn vị đo ("mét", "%", "giây") phải nằm NGAY CẠNH
		con số nó giải thích. Cho full thì đơn vị bị đẩy xuống dòng dưới, đứng trơ ra
		không rõ đang nói về cái gì.

		96px là bề rộng MONG MUỐN, không phải bề rộng cứng — `flex: 0 1 96px` cho ô co
		lại khi chỗ không đủ. Hàng có HAI ô số ("[ô] % đến [ô] %", "[ô] giờ [ô] phút")
		nhờ đó nằm gọn MỘT dòng thay vì hai.

		Bản trước cố tình để nó xuống dòng — 96px được chọn để cụm sau rơi xuống dòng
		dưới. Đo lại thì cái giá quá đắt: 30 hàng như vậy, mỗi hàng 122–143px. Cho co
		thì còn 82–103px, ô thu về 48–61px (vẫn đủ cho ba chữ số), 74 hàng một ô
		KHÔNG đổi một pixel, và không chỗ nào tràn ngang.

		`nowrap` là phần bắt buộc đi kèm: flexbox XUỐNG DÒNG TRƯỚC rồi mới co, nên chỉ
		cho co mà vẫn để `wrap` thì không đổi được gì.

		`min-width` của select và ô chữ phải về 0, kẻo chúng không chịu co và đẩy phần
		sau tràn ra ngoài.
	*/
	.spk-moi .spk-hang-aux {
		flex-wrap: nowrap;
	}

	.spk-moi .spk-hang-aux > .spk-so {
		width: auto;
		flex: 0 1 96px;
		min-width: 44px;
	}

	.spk-moi .spk-hang-aux > .spk-chon,
	.spk-moi .spk-hang-aux > .spk-nhap {
		min-width: 0;
	}
}

/* ────────── KHỔ SIÊU HẸP (≤340px): TRẢ LẠI LỐI XUỐNG DÒNG

   `flex-wrap: nowrap` ở trên đưa hàng hai ô số về một dòng — đúng ở 360px trở lên,
   nhưng ở 320px thì chỗ KHÔNG ĐỦ THẬT. Bài đo toạ độ bắt được 30 hàng ở màn Hoạt
   động và 1 ở Vật phẩm có đơn vị ("%", "giây") bị đẩy TRÀN ra ngoài ô phụ, 5–32px.
   Bài đo mật độ không thấy vì nó chỉ thử 360 và 412.

   Hạ sàn ô số 44 → 36px KHÔNG cứu được: đo lại vẫn còn 24 hàng tràn 11–16px. Thiếu
   là thiếu ở tổng bề rộng, không phải ở một con số nào.

   Nên ở đây trả lại `wrap`: dưới 340px thì chấp nhận hàng hai ô cao 143–164px thay
   vì 82–103px, cả danh sách 26.149 → 28.513px (+9%), đổi lấy KHÔNG chỗ nào tràn.
   Ngưỡng 340px nằm giữa 320 và 360, nên mọi khổ người dùng thật (360, 412, 840,
   1280) KHÔNG mất một pixel nào của phần đã tối ưu. */
/*
	HÀNG CÓ LƯỚI TICK Ở KHỔ HẸP: cột lưới lấy phần co giãn, nhãn co theo nội dung.

	Luật chung ở khổ này chặn trần cột phụ ở 150px — đúng cho một ô nhập hay một
	combobox, sai hẳn cho một lưới viên: ba viên nhét vào 150px thì chúng xếp CHỒNG
	lên nhau thành một cột cao, đo được hàng cao 76 → 131px, tệ hơn cả lối cũ.

	Đảo hai cột: nhãn co theo chữ của chính nó, lưới lấy hết phần còn lại. Lưới vốn đã
	`flex-wrap: wrap`, nên viên nào không còn chỗ mới xuống dòng — chứ không phải cả cụm
	xuống dòng vì một viên.

	SÀN 210px CHO CỘT LƯỚI, không để nó co tuỳ ý. Nhãn dài thì phần còn lại chỉ được
	111px, và ở bề ngang ấy chính CHỮ TRONG VIÊN xuống dòng: viên "12:00 - 13:00" cao
	44px thay vì 24px. Thu cột lưới lại không tiết kiệm được gì — nó chỉ chuyển chỗ chật
	từ ngoài vào trong viên. Đo ở 360px, 12 hàng:

	  sàn      viên cao nhất   cao TB   cả màn
	  không         44px         90     17.062
	  150px         24px         86     17.022
	  210px         24px         65     16.761   ← chọn

	Ở 412px sàn này KHÔNG đổi một pixel nào (lưới vốn đã rộng 163px trở lên).
*/
@media only screen and (max-width: 560px) {
	.spk-moi .spk-hang.spk-hang-tick {
		grid-template-columns:
			var(--spk-cot-mo) minmax(0, auto) minmax(210px, 1fr) auto;
	}
}

@media only screen and (max-width: 340px) {
	.spk-moi .spk-hang-aux {
		flex-wrap: wrap;
	}

	/*
		VÀ TRẢ LẠI LỐI HAI DÒNG: đưa control lên cùng dòng với nhãn là nước lời ở 360 và
		412px (đo được ngắn đi 1–8%), nhưng ở 320px thì chỗ KHÔNG ĐỦ THẬT — 94/137 nhãn
		còn dưới 90px, phải xuống ba bốn dòng, và cả màn 25.213 → 26.256px (+4%).

		Cùng một ngưỡng 340px với luật `wrap` ngay trên: mọi khổ người dùng thật (360, 412,
		840, 1280) KHÔNG mất một pixel nào của phần đã tối ưu.
	*/
	.spk-moi .spk-hang {
		grid-template-columns: var(--spk-cot-mo) 1fr auto;
		grid-template-areas:
			"btn lab lab"
			"aux aux sw";
	}

	.spk-moi .spk-hang-doc {
		grid-template-areas:
			"btn lab lab"
			"aux aux sw"
			"than than than";
	}

	/* Hàng chỉ có công tắc vẫn một dòng: ở đó cột phụ rỗng nên không tranh chỗ. */
	.spk-moi .spk-hang.spk-hang-ct {
		grid-template-columns: var(--spk-cot-mo) 1fr auto;
		grid-template-areas: "btn lab sw";
	}

	/*
		HÀNG CÓ LƯỚI TICK cũng trả lưới về dòng riêng. Sàn 210px cho cột lưới là thứ cứu
		được khổ 360px, nhưng ở 320px thì 210px ấy KHÔNG CÒN Ở ĐÂU RA: đo được viên phình
		từ 24 lên 86px và hàng từ 82 lên 178px. Ở dòng riêng, lưới có trọn 259px và mọi
		viên về đúng 24px.
	*/
	.spk-moi .spk-hang.spk-hang-tick {
		grid-template-columns: var(--spk-cot-mo) 1fr auto;
	}

	.spk-moi .spk-hang-tick > .spk-luoi-tick {
		grid-area: than;
		margin-top: 4px;
	}
}

/* ────────── ĐẦU NHÓM GỌN LẠI Ở KHỔ ĐIỆN THOẠI

   Từ khi các nhóm mặc định GẬP (r3660, r3661), màn hình chủ yếu là một chồng
   đầu nhóm. Đo ở màn Hoạt động: 29 đầu nhóm × 48px = 1.392px, tức **80%** của cả
   danh sách 1.748px. Đây là chỗ tốn nhất, không phải khoảng cách giữa các dòng.

   12px → 8px đệm dọc đưa đầu nhóm về 40px: cả danh sách 1.748 → 1.580 (−10%),
   và một khung nhìn 360×640 thấy 5 đầu mục thay vì 4.

   40px vẫn chạm được: đầu nhóm rộng CẢ MÀN HÌNH nên diện tích chạm rất lớn, khác
   hẳn một ô nhập 96px. Vì thế 44px của ô nhập thì KHÔNG đụng — dưới ngưỡng ấy là
   bấm trượt vào ô số và gõ nhầm giá trị thiết lập.

   Chỉ ở khổ điện thoại: khổ máy tính và app PC không thiếu chỗ dọc. */
@media only screen and (max-width: 640px) {
	.spk-moi .spk-nhom-dau {
		padding-top: 8px;
		padding-bottom: 8px;
	}
}

@media only screen and (max-width: 640px) {

	/*
		Đệm dọc 8px. Đo ở 360×640: một khung nhìn chỉ thấy TRỌN 4 hàng, mà chiều cao
		một hàng thì gần như không có mỡ — khoảng cách GIỮA các hàng vốn đã bằng 0,
		và 44px của ô nhập là cỡ chạm cố ý, không đụng.

		Riêng con số này không dời được hàng nào (đo: 1748 → 1740); nó chỉ có nghĩa
		khi đi cùng khe dọc 4px và đầu nhóm 40px — ba thứ cộng lại mới đẩy chiều cao
		hàng qua ngưỡng: 92 → 86, và 9 → 11 hàng thấy trọn ở 412×800.

		BỚT TIẾP 8 → 4px (2026-09-08). Đo trên 270 hàng của màn Hoạt động:

		  đệm  hàng thấp nhất  trung vị  tổng @360  thấy trọn 360 / 412
		  8px       40px          82      23.010        10  /  11
		  6px       36px          78      21.930        10  /  11
		  5px       34px          76      21.390        11  /  11
		  4px       32px          74      20.850        11  /  12

		Mỗi khổ có ngưỡng riêng; 4px là giá trị duy nhất thắng ở CẢ HAI. Cả danh sách
		ngắn đi 9,4%.

		KHÔNG đụng cỡ chạm: điều khiển nhỏ nhất trong hàng (công tắc) cao 24px ở MỌI
		giá trị đệm — đệm hàng chưa bao giờ là thứ bảo vệ vùng chạm ấy, nên bớt nó
		không lấy đi gì. Cái mất là khoảng thở: hàng một dòng còn 32px.
	*/
	.spk-moi .spk-hang,
	.spk-moi .spk-hang-doc {
		padding: 2px 12px;
	}

	.spk-moi .spk-chon,
	.spk-moi .spk-nhap {
		width: 100%;
	}

	/* Vùng chạm tối thiểu 44px trên điện thoại. */
	.spk-moi .spk-nut {
		min-height: 44px;
	}

	/*
		Ô NHẬP 40px Ở KHỔ ĐIỆN THOẠI — cho những màn NGOÀI Thiết lập.

		Màn Thiết lập có luật riêng theo id (`#settingContent`, 24px) và đặc hiệu của
		id thắng luật này, nên không phải viết `:not()` gì cả.

		NÚT thì giữ 44px: bấm trượt một cái nút là thấy ngay và bấm lại được, còn bấm
		trượt vào ô số là âm thầm gõ đè lên một giá trị.
	*/
	.spk-moi .spk-chon,
	.spk-moi .spk-nhap,
	.spk-moi .spk-so {
		min-height: 40px;
	}

	/*
		NÚT ĐỨNG CÙNG DÒNG VỚI Ô NHẬP thì cao bằng ô — nút "+" thêm khung giờ là chỗ
		duy nhất như vậy (đo bằng hình học trên cả bảy danh mục: mọi kết quả khác đều
		là dương tính giả — nút cây điều hướng và nút thanh đáy chỉ tình cờ trùng băng
		ngang vì chúng ở lớp khác).

		Hai chiều cao lệch nhau 4px cạnh nhau thì mắt thấy ngay là "lỗi", dù chẳng cái
		nào sai. Người dùng đã chấp nhận đánh đổi cỡ chạm ở đây.

		Các nút KHÁC vẫn 44px — xem luật ngay trên.
	*/
	.spk-moi .spk-nut-icon {
		min-height: 40px;
	}

	/* Khổ điện thoại: nút trên dải cao hơn cho dễ chạm. */
	.spk-tk-thoat {
		min-height: 38px;
	}

	/*
		NÚT TRONG HÀNG DANH SÁCH: 22×22, để hàng CÓ nút cao bằng hàng KHÔNG nút.

		Đo ở 360px trước khi sửa: hàng có nút 58–59px, hàng chỉ có nhãn 35–36px —
		chênh 22px, và chênh ấy đúng bằng phần nút 44px thò ra ngoài dòng chữ 21px.
		Cùng một danh sách mà hai kiểu hàng cao khác nhau thì nhìn ra như hỏng.

		22px là con số ĐO ĐƯỢC chứ không chọn cho tròn: thử 30/28/24/22 thì hàng ra
		44/42/38/36-37px, và 36 mới bằng hàng không nút.

		CỠ CHẠM: 22px thấp hơn hẳn khuyến nghị, người dùng đã chấp nhận đánh đổi —
		"bấm button hơi khó". Bù lại nút vẫn rộng 22px và nằm tách hẳn về mép phải,
		không có gì bấm nhầm sang được. Muốn trả lại thì đổi đúng con số ở đây.
	*/
	/*
		KHỔ DỌC: bốn nút của gói lui vào menu "⋯".

		Neo XUỐNG DƯỚI nút (`top: 100%`), khác menu của thanh đáy neo lên trên — thanh
		đáy dính mép dưới màn nên chỗ trống của nó ở phía trên, còn thẻ thì nằm giữa
		danh sách và chỗ trống ở phía dưới.

		Neo theo mép PHẢI: cụm nút dồn sang phải, neo trái thì menu tràn ra ngoài màn.
	*/
	/* Cùng độ đặc hiệu với luật ẩn ở trên, và đứng sau nó trong tệp. */
	.spk-moi .spk-vip-goi .spk-vip-menu-nut {
		display: inline-flex;
	}

	.spk-moi .spk-vip-menu {
		display: none;
		position: absolute;
		z-index: 20;
		top: 100%;
		right: 0;
		margin-top: 6px;
		min-width: 150px;
		padding: 6px;
		background: var(--spk-nen);
		border: 1px solid var(--spk-vien);
		border-radius: var(--spk-bk);
		box-shadow: 0 6px 20px rgba(0, 0, 0, .14);
	}

	/*
		Mở ra thì xếp DỌC, mỗi việc một dòng, và mỗi nút rộng hết menu — trong một menu
		thì "vùng bấm" của một mục là cả dòng, không phải mỗi chữ.
	*/
	.spk-moi .spk-vip-menu-vo.spk-hien .spk-vip-menu {
		display: block;
	}
	.spk-moi .spk-vip-menu-vo.spk-hien .spk-vip-menu > * {
		display: flex;
		width: 100%;
		margin: 0 0 4px;
		justify-content: center;
	}
	.spk-moi .spk-vip-menu-vo.spk-hien .spk-vip-menu > *:last-child {
		margin-bottom: 0;
	}

	/*
		MENU CHỈ CÒN MỘT VIỆC: bày thẳng việc ấy, giấu nút "VIP ⋯".

		Gói hết hạn chỉ còn "Gia hạn" — mở một menu một mục là bắt bấm hai lần cho một
		việc, mà cú thứ nhất không nói thêm được gì. JS đếm nút còn dùng được rồi gắn lớp
		(xem soLaiMenuVip trong license.js); ở đây chỉ là hệ quả.
	*/
	.spk-moi .spk-vip-goi .spk-vip-menu-vo.spk-vip-menu-don > .spk-vip-menu-nut {
		display: none;
	}
	.spk-moi .spk-vip-menu-vo.spk-vip-menu-don > .spk-vip-menu {
		display: flex;
		position: static;
		margin: 0;
		min-width: 0;
		padding: 0;
		background: none;
		border: 0;
		box-shadow: none;
	}

	/*
		NÚT DANH SÁCH KHÔNG CÒN CON SỐ RIÊNG Ở KHỔ NÀY — luật nền cho 24px vuông
		(bằng công tắc) ở mọi khổ. Bánh răng thì giữ cỡ riêng vì nó nằm trên hàng
		tiêu đề nhóm chứ không đứng cạnh ô nhập nào.
	*/
	.spk-moi .spk-banhrang {
		width: 22px;
		height: 22px;
		font-size: 13px;
	}

	/*
		Bảng vật phẩm có tới 7 cột — cuộn ngang trên điện thoại là không dùng được. Mỗi <tr>
		thành một thẻ: hàng tiêu đề ẩn đi, nhãn cột nhúng sẵn trong từng ô hiện ra thay thế.
	*/
	.spk-moi .spk-bang-khoi { padding: 12px; }

	/*
		CHỈ bảng vật phẩm — loại biến thành thẻ ở khổ này — mới bỏ cuộn ngang. Trước
		đây luật này áp cho MỌI .spk-bang-cuon, nên bảng giao dịch (rộng 1053px, không
		biến thành thẻ) bị cắt cụt trong khung nhìn 412px mà không cuộn được.
	*/
	.spk-moi .spk-bang-cuon:has(.spk-bang-the) {
		overflow-x: visible;
		border: 0;
		border-radius: 0;
	}

	.spk-moi .spk-bang-the,
	.spk-moi .spk-bang-the tbody,
	.spk-moi .spk-bang-the tr,
	.spk-moi .spk-bang-the td {
		display: block;
		width: auto;
	}

	.spk-moi .spk-bang-the-chan,
	.spk-moi .spk-bang-the-le {
		/* Mốc định vị cho ô xoá ở góc trên–phải. */
		position: relative;
		margin-bottom: 10px;
		padding: 4px 0;
		background: var(--spk-nen);
		border: 1px solid var(--spk-vien);
		border-radius: 6px;
	}

	/*
		NHÃN TRÁI — ĐIỀU KHIỂN PHẢI, cùng một hàng.

		Bản trước đặt nhãn thành một dòng riêng rồi cho điều khiển `width: 100%`; bảy
		trường thành mười bốn dòng và một thẻ cao 512px trong khung nhìn 800px — gần
		hai phần ba màn hình cho MỘT vật phẩm. Ô nhập chứa số "5" mà rộng 402px.

		flex-wrap giữ cho cụm "Giá bán: 6 ≤ [ô] ≤ 15" xuống dòng gọn gàng khi hẹp
		thay vì tràn.
	*/
	.spk-moi .spk-bang-the-chan td,
	.spk-moi .spk-bang-the-le td {
		display: flex;
		align-items: center;

		/*
			`nowrap` chứ không `wrap`: flexbox XUỐNG DÒNG TRƯỚC rồi mới co, nên để `wrap`
			thì mọi thứ cho con co lại đều vô nghĩa. Đo trên dữ liệu thật (81 thẻ, bảy
			bảng): 28 ô hai dòng → 0, và không ô nào tràn.

			Ô "Giá bán" là chỗ chật nhất — nhãn 83 + "1000" 30 + ô 100 + "≤" 24 +
			"20000" 38 = 275, cộng 5 khe × 6px là 305 trên 304px chỗ có. Tràn ĐÚNG 1px,
			và "20000" rơi xuống dòng riêng.
		*/
		flex-wrap: nowrap;
		padding: 4px 10px;
		border-top: 0;
		white-space: normal;
	}

	/*
		Markup của hàng "Giá bán" có một <span> RỖNG (setting.js:2300) — nó không hiện
		gì mà vẫn ăn 6px lề, tức 6px trong đúng cái ô chật nhất. Ẩn hẳn.
	*/
	.spk-moi .spk-bang-the-chan td > span:empty,
	.spk-moi .spk-bang-the-le td > span:empty {
		display: none;
	}

	/* Lề thay cho `gap` — gap trong flexbox cần Chrome 84. */
	.spk-moi .spk-bang-the-chan td > * + *,
	.spk-moi .spk-bang-the-le td > * + * {
		margin-left: 6px;
	}

	/*
		Ô xoá lên GÓC TRÊN–PHẢI của thẻ, đúng cách tham-khao-1 xếp (đo được:
		position:absolute tại 351,7 kích thước 44×44). Bản trước để nó thành một hàng
		riêng ở đáy — chiếm trọn 48px chỉ để chứa một nút 40px.

		`td:last-child` là mốc đúng: ô xoá luôn là <td> cuối trong cả bảy bảng vật
		phẩm. Dùng nó thay `:has(.spk-ds-xoa)` vì `:has()` cần Chrome 105, mà người
		dùng có máy chạy Chrome 68.
	*/
	.spk-moi .spk-bang-the-chan td:last-child,
	.spk-moi .spk-bang-the-le td:last-child {
		position: absolute;
		top: 6px;
		right: 8px;
		padding: 0;
	}

	/*
		THU GỌN: nút Xoá căn giữa theo DÒNG TIÊU ĐỀ, không theo mép trên thẻ.

		Nút nằm ngoài luồng (`absolute`) nên nó không tự biết dòng đầu cao bao nhiêu. Ở
		thẻ thu gọn, dòng đầu cao 40px vì ô tick giữ sàn 40 cho vừa ngón tay, trong khi ô
		tên chỉ 31 — nút neo ở `top: 6px` bèn nằm cao hơn tiêu đề 6px, đọc ra thành hai
		thứ ở hai dòng khác nhau.

		8px = 4px đệm trên của thẻ + (31 − 24) / 2, với 31 là chiều cao dòng tiêu đề và 24
		là chiều cao nút. Cùng công thức cho cả hai trạng thái, nên chúng khớp nhau.
	*/
	.spk-moi tr.spk-bang-the-le > td:last-child,
	.spk-moi tr.spk-bang-the-chan > td:last-child {
		top: 8px;
	}

	/*
		Hàng đầu chừa chỗ NGANG cho nút Xoá ở góc trên phải.

		SÀN 52px ĐÃ BỎ. Nó đặt từ hồi góc ấy có HAI nút cao 40px, và hàng đầu phải đủ cao
		để chứa trọn chúng kẻo chúng thò xuống đè hàng dưới. Nay chỉ còn nút Xoá cao 24px
		— mũi sổ đã về đứng trước tên — nên 52px chỉ còn là một khoảng hở thừa, và nó đẩy
		tiêu đề xuống 5px so với chính thẻ ấy lúc sổ ra.

		44px cũng thay cho 96px vì cùng lý do: một nút chứ không phải hai.
	*/
	.spk-moi .spk-bang-the-chan td:first-child,
	.spk-moi .spk-bang-the-le td:first-child {
		padding-right: 44px;
	}

	/*
		THẺ THU GỌN: chỉ bày Kích hoạt · Tên · một ô tóm tắt · Xoá.

		Mỗi thẻ bày trọn 5–7 trường cao 199–299px; 82 thẻ là 20.218px phải cuộn qua.
		Thu gọn đưa thẻ về 143px và cả cụm về 11.384px (−44%).

		Ô tóm tắt được chọn theo TỪNG BẢNG (setting.js gắn lớp `spk-the-tomtat`), vì
		mỗi bảng có một trường đáng nhớ khác nhau: Giá bán · Giá tối đa · Số lượng ·
		Số lượng tối thiểu · Số lượng giữ lại. Nó vẫn là ô NHẬP nên sửa được ngay khi
		đang thu gọn.

		Bốn `:not()` chứ không một lớp "ô phụ" gắn tay: bốn ô được giữ đều xác định
		bằng VỊ TRÍ (đầu, thứ hai, cuối) hoặc bằng vai (tóm tắt), nên không có gì phải
		nhớ khai thêm khi bảng đổi cột. `:not()` một mức chạy từ Chrome 4.
	*/
	.spk-moi .spk-bang-the tr:not(.spk-the-mo) > td:not(:first-child):not(:nth-child(2)):not(:last-child):not(.spk-the-tomtat) {
		display: none;
	}

	/*
		THẺ THU GỌN XẾP LẠI: [tick] [tên] trên MỘT dòng, tóm tắt xuống dòng dưới.

		Bỏ hai nhãn "Kích hoạt:" và "Tên vật phẩm:" — nhìn vào là hiểu, không cần nói.
		Nhưng bỏ nhãn KHÔNG THÔI thì gần như không được gì: đo được 11.384 → 11.342px,
		vì chiều cao thẻ do ô tick và ô tên NẰM HAI DÒNG quyết định, chứ không do nhãn.
		Phải xếp lại mới ăn: 11.384 → 7.183px (−37%).

		Hàng thành flex để hai ô đầu chung một dòng; ô tóm tắt `flex: 1 1 100%` nên tự
		xuống dòng dưới. Ô cuối vẫn `position: absolute` nên đứng ngoài luồng, hai nút
		mũi/Xoá không bị kéo theo.

		Ô tick giữ `min-height: 40px`: ô tick chỉ 17px, chỗ chạm thật nằm ở cả ô. Bỏ
		hẳn sàn thì hàng còn 39px và vùng chạm co theo — tiết kiệm 1px, mất một ngón tay.
	*/
	.spk-moi .spk-bang-the tr:not(.spk-the-mo) {
		display: flex;
		flex-wrap: wrap;
		align-items: center;
	}

	/*
		HÀNG TIÊU ĐỀ KHÔNG CÓ VIỆC GÌ Ở KHỔ THẺ — mỗi thẻ đã tự mang nhãn của từng ô.

		Luật này PHẢI đứng sau khối `tr:not(.spk-the-mo)` ngay trên. Hai selector có cùng
		độ đặc hiệu (0-3-1), nên thứ tự trong tệp là thứ quyết định — và hàng tiêu đề thì
		không mang lớp `spk-the-mo` nên nó KHỚP cả luật kia.

		Trước đây luật ẩn nằm ở đầu khối, và nó đúng cho tới khi đợt "thẻ thu gọn" thêm
		luật `display: flex` vào cuối: từ lúc ấy hàng tiêu đề hiện trở lại, bày ba ô lẻ
		trên một dải xám không phủ hết bề ngang. Người duyệt nhìn ra ngay — "ở chế độ item
		card thì đâu cần title đó nữa".
	*/
	.spk-moi .spk-bang-the tr.spk-bang-the-dau { display: none; }

	/*
		TÊN VẬT PHẨM LÀ TIÊU ĐỀ THẺ — luôn luôn, không chỉ lúc thu gọn.

		Trước đây nhãn "Tên vật phẩm:" bị ẩn khi thu gọn rồi HIỆN LẠI khi sổ ra, nên thẻ
		mở có một dòng "Tên vật phẩm: Bánh Răng" nằm ngay dưới chính cái tên đang làm tiêu
		đề. Một cái tên nói hai lần.

		Nhãn "Kích hoạt:" thì chỉ hiện KHI SỔ RA: lúc ấy nó là một dòng "nhãn: giá trị"
		như mọi dòng khác nên phải có nhãn. Lúc thu gọn nó nằm ngay trước tên trên cùng
		một dòng — nhìn vào là hiểu, thêm chữ chỉ tốn chỗ.
	*/
	.spk-moi .spk-bang-the > tbody > tr > td.spk-bang-the-keo .spk-bang-the-nhan,
	.spk-moi .spk-bang-the tr:not(.spk-the-mo) > td:first-child .spk-bang-the-nhan {
		display: none;
	}

	/* Tên là tiêu đề thẻ ở CẢ HAI trạng thái: cùng cỡ, cùng độ đậm với đầu mục. */
	.spk-moi .spk-bang-the > tbody > tr > td.spk-bang-the-keo {
		min-width: 0;
		padding-left: 0;
		/* Chừa chỗ cho nút Xoá ở góc trên phải. */
		padding-right: 44px;
		font-size: 15px;
		font-weight: 600;
	}

	/* THU GỌN: ô tick và tên chung MỘT dòng, tick đứng đầu — như cũ. */
	.spk-moi .spk-bang-the tr:not(.spk-the-mo) > td:first-child {
		flex: 0 0 auto;
		padding-right: 8px;
	}

	/*
		DÒNG TIÊU ĐỀ CAO ĐÚNG BẰNG TIÊU ĐỀ, không bằng sàn chạm của ô tick.

		Ô tick vốn giữ `min-height: 40px` cho vừa ngón tay. Nhưng ô tên chỉ cao 31, mà
		hàng căn giữa — nên 9px thừa chia đôi và đẩy tiêu đề xuống: đo được đệm từ mép
		trên thẻ tới tiêu đề là 10px khi thu gọn còn 5px khi sổ ra. Cùng một cái thẻ mà
		hai trạng thái thở khác nhau.

		`stretch` cho ô tick cao BẰNG DÒNG thay vì tự đặt sàn: dòng cao 31 theo tiêu đề,
		ô tick cũng 31, và vùng chạm mất 9px (40 → 31) — đổi lấy hai trạng thái khớp nhau.
		Chỗ bấm để SỔ vẫn là trọn ô tên, không đụng gì tới thay đổi này.
	*/
	.spk-moi .spk-bang-the tr:not(.spk-the-mo) {
		align-items: stretch;
	}

	/*
		LỀ 6px CỦA VỎ NỘI DUNG LÀ KHE SAU CÁI NHÃN — mà ở đây nhãn "Kích hoạt:" đang ẩn,
		nên 6px ấy là chỗ trống không có gì đứng trước: ô tick lệch phải 6px so với nhãn
		của mọi dòng bên dưới (đo được x=44 với x=38).

		Cùng một cái bẫy với lề của `.spk-hang-aux` rỗng: một cái lề chỉ có nghĩa khi thứ
		nó cách ra còn hiện.
	*/
	.spk-moi .spk-bang-the tr:not(.spk-the-mo) > td:first-child > .spk-bang-the-noidung {
		margin-left: 0;
	}

	.spk-moi .spk-bang-the tr:not(.spk-the-mo) > td.spk-bang-the-keo {
		flex: 1 1 0;
	}

	/*
		SỔ RA: tên lên làm tiêu đề một dòng riêng, "Kích hoạt" thành một dòng thuộc tính
		như mọi dòng khác.

		Ghép [tick] [tên] trên một dòng là đúng khi thẻ thu gọn — hai thứ, một dòng, đọc
		xong là hết. Nhưng khi thẻ mở ra thì dưới nó là năm sáu dòng "nhãn: giá trị", và
		cái tên bị kẹp giữa một ô tick bên trái với chúng bên dưới thì không còn đọc ra là
		tiêu đề của cả khối nữa.

		HÀNG MỞ PHẢI LÀ FLEX. `order` không có nghĩa trong `display: block`, mà luật nền ở
		khổ thẻ đặt mọi `tr` là block và chỉ hàng THU GỌN mới được flex. Lần đầu tôi đặt
		`order: -1` mà quên điều ấy: thẻ mở ra vẫn bày "Kích hoạt" trên tên, y như trước.
	*/
	.spk-moi .spk-bang-the > tbody > tr.spk-the-mo {
		display: flex;
		flex-wrap: wrap;
		align-items: center;
	}

	.spk-moi .spk-bang-the > tbody > tr.spk-the-mo > td {
		flex: 1 1 100%;
	}

	/*
		DÒNG "KÍCH HOẠT" CAO BẰNG CÁC DÒNG KHÁC.

		Sàn 40px của ô tick sinh ra cho khổ thu gọn, nơi ô ấy là một đích chạm nằm cạnh
		tiêu đề. Khi sổ ra thì nó là một dòng "nhãn: giá trị" như năm dòng dưới nó, mà các
		dòng kia cao 32px (ô nhập 24 + đệm 8) còn nó 52px — một khoảng hở lạc lõng ngay
		dưới tiêu đề.

		24px là chiều cao ô nhập, cùng con số đã dùng cho công tắc và nút khắp app; cộng
		đệm 4px trên dưới thành đúng 32px như các dòng kia.
	*/
	.spk-moi .spk-bang-the > tbody > tr.spk-the-mo > td:first-child {
		min-height: 32px;
		/*
			ĐỆM PHẢI VỀ 10px NHƯ MỌI DÒNG KHÁC. 44px là chỗ chừa cho nút Xoá ở góc trên
			phải — đúng khi thu gọn, vì lúc ấy ô tick nằm CÙNG DÒNG với nút. Khi sổ ra thì
			nút ở dòng tiêu đề phía trên, nên 44px thành chỗ trống đẩy ô tick lệch trái so
			với mép phải của các ô nhập bên dưới.
		*/
		padding-right: 10px;
	}

	/*
		Thứ tự trong <tr> giữ nguyên cho khổ BẢNG, nơi "Kích hoạt" đúng là cột đầu.

		VÀ TRẢ LẠI ĐỆM TRÁI 10px: ô tên bỏ đệm trái để lúc thu gọn nó nép sát ngay sau ô
		tick. Khi sổ ra thì nó đứng một mình trên dòng đầu, và mũi ▸ của nó thụt ra ngoài
		10px so với nhãn của mọi dòng bên dưới — đo được mũi ở x=28 còn nhãn ở x=38.
		10px là đúng đệm ngang của `.spk-bang-the td`, không phải một số chọn cho vừa mắt.
	*/
	.spk-moi .spk-bang-the > tbody > tr.spk-the-mo > td.spk-bang-the-keo {
		order: -1;
		padding-left: 10px;
	}

	.spk-moi .spk-bang-the tr:not(.spk-the-mo) > td.spk-the-tomtat {
		flex: 1 1 100%;
	}

	/*
		NÚT MŨI ĐỨNG TRƯỚC TÊN VẬT PHẨM, cùng bộ đo với đầu mục ở Hoạt động.

		Trước đây nó là một ô vuông 30px có viền, nằm ở góc trên phải cạnh nút Xoá — một
		cái nút trông như nút, đặt xa thứ nó mở. Nay nó về đúng chỗ mắt tìm: ngay trước
		tên, không vỏ, màu chữ như tên, cách tên 2px.

		Và bấm vào TÊN cũng sổ được (tay bấm ở setting.js) — mũi 5×8px là một đích quá
		nhỏ để bắt người ta nhắm vào.
	*/
	.spk-moi .spk-the-nut-mo {
		display: inline-flex;
		align-items: center;
		justify-content: center;
		width: auto;
		height: auto;
		margin-right: 2px;
		padding: 0;
		background: none;
		border: 0;
		color: var(--spk-chu);
		font-size: 14px;
		line-height: 1;
		cursor: pointer;
		vertical-align: baseline;
	}

	/* Ô tên là một đích bấm: đừng bôi đen chữ khi bấm liền hai lần để đóng lại. */
	.spk-moi .spk-bang-the-keo {
		cursor: pointer;
		user-select: none;
		-webkit-user-select: none;
	}

	.spk-moi .spk-bang-the-nhan {
		display: block;
		flex: 1 1 auto;
		min-width: 0;
		margin: 0;
		color: var(--spk-chu-mo);
		font-size: 12.5px;
		font-weight: 600;
	}

	.spk-moi .spk-bang-the-keo {
		min-width: 0;
		font-weight: 600;
	}

	/*
		Cả 12 ô nhập của các bảng này đều nằm trong <span class="spk-bang-the-nhap-nho">
		— chính markup đã khai chúng là ô NHỎ (số lượng, giá). `width: 100%` là luật
		CSS ép ngược lại. Trả về đúng bề rộng cần dùng, giữ chiều cao 44px cho vùng chạm.
	*/
	/*
		Ô NHẬP RỘNG VỪA ĐỦ, KHÔNG GIÃN — để nhãn và ô nằm CÙNG MỘT DÒNG.

		Bản trước cho vỏ bọc `flex: 1 1 auto` để mọi điều khiển kết thúc ở một mép phải
		chung, chép cách xếp của tham-khao-1. Ở khổ dọc thì cái giá quá đắt: ô giãn tới
		186–278px, không còn chỗ cho nhãn nên nhãn chiếm trọn dòng trên và ô rơi xuống
		dòng dưới. Đo được thẻ vật phẩm cao 358px, không ô nào nằm cạnh nhãn của nó.

		100px là con số đo được, không chọn cho tròn:
		  nhãn dài nhất "Số lượng trong hành trang:" rộng 161px, chỗ có 286px,
		  161 + 6 (lề) + 100 = 267 < 286 → vừa một dòng.
		Thử 120/100/90/80: thẻ ra 339/320/320/299px. Chọn 100 vì nó vẫn chứa trọn 8 chữ
		số (giá tới hàng triệu); 80px thì bắt đầu cắt số dài.

		Hàng "Giá bán" vẫn xếp đúng: `1000 ≤` và `≤ 20000` giữ bề rộng tự nhiên, chỉ ô
		nhập ở giữa là cố định.
	*/
	.spk-moi .spk-bang-the-nhap-nho {
		/*
			`0 1` chứ không `0 0`: 100px là bề rộng MONG MUỐN, còn ô "Giá bán" thì chật
			hơn nên phải nhường vài pixel. Đo được ô co về 77–96px ở đúng những hàng cần,
			còn 173/194 ô khác giữ nguyên 100px.

			Sàn 56px để còn đọc được bốn chữ số.
		*/
		flex: 0 1 100px;
		min-width: 56px;
	}

	/* Chiều cao theo luật nền (24px, bằng công tắc) — không nâng riêng ở đây nữa. */
	.spk-moi .spk-bang-the-nhap {
		width: 100%;
	}

	.spk-moi .spk-bang-the select {
		flex: 1 1 auto;
		width: auto;
		min-width: 0;
	}

	.spk-moi .spk-gio .spk-so { width: 72px; }

	/*
		KHỐI THÊM (giờ/phút, ô nhập + nút) NẰM GỌN MỘT DÒNG.

		Hàng dải giờ có 4 ô số + 2 dấu ":" + chữ "tới" + nút. Bản trước nén ô còn 52px
		và khe còn 5px để vừa một dòng — đo ở 390px. Ở 360px thì hụt: cộng lại 311px
		trên 306px chỗ có, tràn 5px và cả cụm rơi xuống dòng thứ hai, khối cao 90px.

		Đó là hằng số nói TRẠNG THÁI của một bố cục, nên nó chết ngay khi bố cục đổi.
		Thay bằng CHO CO: `nowrap` + ô số co được, thiếu bao nhiêu thì ô nhường bấy
		nhiêu. Không còn con số nào phải chỉnh lại khi khổ màn đổi.

		Đo trên bảy danh mục ở ba khổ 320/360/412 — mọi loại khối đều về một dòng và
		không khối nào tràn:
		  12 khối 4 ô số      90 → 45px
		   1 khối nhập+2 nút  143 → 49px
		   2 khối select+nút   94 → 49px
		   1 khối giờ-tới-giờ  90 → 45px
		   2 khối 2 ô số       45 → 45px (vốn đã gọn)

		`min-width: 0` cho MỌI con là phần bắt buộc: mặc định `min-width: auto` của
		flex item không cho co nhỏ hơn nội dung, nên chỉ đặt `flex` là chưa đủ.
		Riêng ô số giữ sàn 34px để còn đọc được hai chữ số.
	*/
	.spk-moi .spk-them {
		flex-wrap: nowrap;
		margin-bottom: -5px;
	}

	/* Khổ hẹp: khe 5px thay vì 8px. */
	.spk-moi .spk-them > * {
		margin: 0 5px 5px 0;
		min-width: 0;
	}

	/*
		NÚT thì KHÔNG co. `min-width: 0` ở trên mở cho mọi con co nhỏ hơn nội dung —
		đúng cho ô số, sai cho nút: đo được nút "Thêm hoạt động" bị bóp hẹp hơn chữ của
		nó rồi CẮT CỤT (`scrollWidth > clientWidth`), ở cả 360px lẫn 412px.

		Khối vẫn không tràn ra ngoài, nên phép chốt "tràn" của bài đo — vốn chỉ nhìn mép
		ngoài hộp chứa — không thấy gì. Chữ bị cắt nằm BÊN TRONG một con bị bóp.
	*/
	.spk-moi .spk-them > .spk-nut {
		flex: 0 0 auto;
		min-width: auto;
	}

	.spk-moi .spk-them > .spk-so {
		width: 52px;
		flex: 0 1 auto;
		min-width: 34px;
		padding-left: 6px;
		padding-right: 6px;
	}

	/* Hộp con `.spk-gio` cũng phải co được, kẻo nó giữ nguyên bề rộng và đẩy nút ra ngoài. */
	.spk-moi .spk-them .spk-gio {
		flex: 0 1 auto;
		min-width: 0;
	}

	/*
		Ô giờ/phút phải có BỀ RỘNG MONG MUỐN, không được để `auto`.

		`width: auto` + `flex-basis: auto` trên một `<input>` cho ra bề rộng NỘI TẠI
		của nó (mặc định `size=20`, khoảng 170px), rồi flex mới co dần khi hết chỗ.
		Nên ô CÀNG RỘNG KHI MÀN HÌNH CÀNG RỘNG, và ở ngay dưới mốc 640px thì nó phình
		to nhất — trong khi vượt mốc 640px là rơi về 62px của khổ máy tính. Đo được:

		  320px 43px · 360px 53px · 412px 66px · 500px 88px · 630px 119px
		  700px 62px · 840px 62px · 1280px 62px

		119px rồi rơi thẳng xuống 62px chỉ vì rộng thêm 70px: đó là cái vực người dùng
		nhìn thấy. Lỗi là ở `auto`, không phải ở mốc.

		72px là đúng con số của dòng `.spk-gio .spk-so` ngay trong khối điện thoại này,
		nên trong cùng một khổ mọi ô giờ bằng nhau. `flex: 0 1 auto` + sàn 34px giữ
		nguyên khả năng co ở khổ hẹp — 320px vẫn về 43px như trước.
	*/
	.spk-moi .spk-them .spk-gio .spk-so {
		width: 72px;
		flex: 0 1 auto;
		min-width: 34px;
	}

	/*
		Chiều cao đã do luật nền lo (24px, bằng ô nhập đứng cạnh) — ở đây chỉ còn bề
		ngang. Trước kia chỗ này khai 40px vì ô nhập ở khổ điện thoại cũng 40px.
	*/

	.spk-moi .spk-nut-icon {
		width: 40px;
	}
}

/*
	Trình duyệt chưa có :has() (Safari < 15.4, WebView2 đời cũ) sẽ BỎ QUA hai luật
	:has() ở trên vì selector không hợp lệ. Khi đó mọi hàng đều xếp dọc, kể cả hàng
	công tắc — vẫn dùng tốt, chỉ tốn thêm một dòng. Không cần dự phòng riêng.
*/

/* ===== hết GIAO DIỆN MỚI ===== */

/* ============================================================
   VỎ ỨNG DỤNG — bỏ hoàn toàn jQuery Mobile
   ------------------------------------------------------------
   Từ bản này trang KHÔNG nạp jquery.mobile.min.css nữa, nên khối
   này phải tự lo cả phần nền tảng (box-sizing, margin của body,
   chiều cao html/body) — trước đây jQM lo hộ.

   BỐ CỤC: một cột dọc cao đúng bằng khung nhìn.

       .spk-topbar            ☰ · tên màn · đường dẫn      (không cuộn)
       .spk-than                                            (phần còn lại)
           .spk-side          cây điều hướng — ngăn kéo khi hẹp
           .spk-scrim         nền mờ sau ngăn kéo
           .spk-mans
               #accountInfo   dòng "bạn là ai", DÙNG CHUNG cả ba màn
               #content       VÙNG CUỘN DUY NHẤT
                   .spk-man ×4    bốn màn nằm sẵn, bật/tắt bằng class

   #content GIỮ NGUYÊN TÊN ID có chủ ý: goToSection cuộn chính nó. (Lý do
   thứ hai — responsive.js tìm bảng quá khổ bằng `#content table` — đã mất
   theo script ấy.)

   Bốn màn nằm sẵn trong DOM thay vì nạp lại mỗi lần đổi màn. Bản cũ
   dùng $content.empty() + $.load(), nên quay lại một màn là mất sạch
   những gì đang nhập dở ở đó.
   ============================================================ */

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

html,
body {
	height: 100%;
}

body {
	margin: 0;
	background: var(--spk-nen-mo);
	color: var(--spk-chu);
	font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;
	font-size: 14px;
	line-height: 1.5;
	/*
		Prefix này CẦN cho Safari trên iOS: thiếu nó thì chữ tự phóng to khi xoay
		ngang máy và vỡ lưới bốn cột của hàng thiết lập. license.js còn nhánh riêng
		cho Safari cũ, tức có người chơi dùng thật.
	*/
	-webkit-text-size-adjust: 100%;
}

button,
input,
select,
textarea {
	font-family: inherit;
	color: inherit;
}

.spk-app {
	height: 100vh;
	/* dvh: thanh địa chỉ của trình duyệt di động co vào duỗi ra thì vỏ vẫn khít. */
	height: 100dvh;
	display: flex;
	flex-direction: column;
	overflow: hidden;
}

/* ---------- thanh trên cùng ---------- */

/*
	Khoảng cách trong thanh này dùng MARGIN, không dùng `gap`: `gap` của flexbox
	cần Chrome 84 mà người dùng có máy chạy Chrome 68 — ở đó nút ☰ dính liền vào
	dải chữ. Cùng lối mà .spk-day-nut và .spk-thanh-day đã dùng.
*/
/*
	BA DẢI CỐ ĐỊNH — thanh trên, ô tìm, thanh đáy — ăn 173px trong một khung nhìn
	360×800, tức 22% màn hình trước khi hiện được một dòng thiết lập nào. Ở khổ nằm
	ngang 800×360 thì hai dải còn lại ăn 115 trên 360px.

	Đệm dọc của cả ba đều rộng gấp đôi mức cần: mỗi dải chỉ chứa MỘT thứ cao 36–40px,
	phần còn lại là khoảng trắng. Bớt đệm đưa 173 → 147px (khổ dọc), 115 → 99px (nằm
	ngang), 119 → 101px (máy tính) mà KHÔNG đụng tới cỡ chạm: nút vẫn 40px.

	Đã CÂN NHẮC VÀ BỎ việc thu nút burger xuống 36px: chỉ được thêm 4px, đổi lấy một
	vùng chạm dưới ngưỡng 40px của chính tài liệu này.
*/
.spk-topbar {
	flex: none;
	z-index: 40;
	display: flex;
	align-items: center;
	padding: 4px 14px;
	background: var(--spk-nen);
	border-bottom: 1px solid var(--spk-vien);
}

/*
	CHỮ TRÊN NÚT BURGER — chỉ ở khổ có cột cố định.

	Hình `«` một mình không nói được nó sắp làm gì; người dùng app PC báo không biết
	bấm vào đâu để mở rộng khung nhìn. Chữ do nav.js đổ (`capNhatNutBurger`), CSS chỉ
	quyết khi nào cho thấy.

	MỐC 641px: dưới mốc ấy cây luôn là NGĂN KÉO, mà `☰` mở ngăn kéo là quy ước ai
	cũng biết — thêm chữ chỉ tốn chỗ. Đo bề rộng còn trống của thanh trên: 125px ở
	360px (chật), 322–882px từ 720px trở lên (thừa sức cho một chữ ~95px).
*/
.spk-burger-chu {
	display: none;
}

@media only screen and (min-width: 641px) {
	.spk-burger-chu {
		display: inline;
		margin-left: 6px;
		font-size: 13px;
		font-weight: 500;
	}

	/*
		Có chữ thì nút không còn vuông: bề rộng theo nội dung, sàn 40px giữ nguyên cỡ
		chạm cho lúc chữ bị ẩn.

		KÈM `.spk-topbar` cho ĐỦ ĐỘ CỤ THỂ (0,2,0). Bản đầu viết `.spk-burger` trơn
		(0,1,0) và đặt khối này TRƯỚC luật nền `.spk-burger { width: 40px }` — bằng độ
		cụ thể thì thứ tự quyết, luật nền đứng sau nên thắng, nút vẫn 40×40 và chữ bị
		ép ra ngoài. Đo mới thấy. Dựa vào vị trí trong tệp là chỗ dễ vỡ nhất khi ai đó
		sắp xếp lại; dựa vào độ cụ thể thì không.
	*/
	.spk-topbar .spk-burger {
		width: auto;
		min-width: 40px;
		padding-left: 10px;
		padding-right: 10px;
	}
}

.spk-burger {
	display: none;
	margin-right: 10px;
	width: 40px;
	height: 40px;
	flex: none;
	align-items: center;
	justify-content: center;
	background: var(--spk-nen-mo);
	border: 1px solid var(--spk-vien);
	border-radius: var(--spk-bk);
	font-size: 17px;
	line-height: 1;
	color: var(--spk-chu);
	cursor: pointer;
}

/*
	HIỆU CỦA APP ở góc phải thanh trên cùng.

	`margin-left: auto` đẩy nó sang phải; `min-width: 0` ở .spk-brand bên trái lo
	phần còn lại co được khi chật.

	Khoảng cách giữa ảnh và chữ dùng `margin` chứ không `gap`: `gap` của flexbox
	cần Chrome 84, mà người dùng có máy chạy Chrome 68 (thanh này vẫn còn
	`gap: 10px` từ trước — lỗi có sẵn, không phải của khối này).
*/
.spk-hieu {
	flex: none;
	margin-left: auto;
	display: flex;
	align-items: center;
	white-space: nowrap;
}

.spk-hieu-anh {
	flex: none;
	width: 24px;
	height: 24px;
	margin-right: 8px;
	border-radius: 5px;
}

.spk-hieu-ten {
	font-size: 13px;
	font-weight: 600;
	color: var(--spk-chu-mo);
}

/*
	KHỔ HẸP: giữ logo, BỎ dòng chữ.

	Đo ở 320px khi còn cả chữ: đường dẫn "/ Hoạt động" và tên nhân vật bị đẩy hết
	khỏi thanh. Điều hướng là thứ người dùng cần từng giây, còn nhãn hiệu thì không
	— nhường chỗ cho đường dẫn.
*/
@media (max-width: 640px) {
	.spk-hieu-ten {
		display: none;
	}

	.spk-hieu-anh {
		margin-right: 0;
	}
}

.spk-brand {
	display: flex;
	align-items: baseline;
	min-width: 0;
}

/*
	Là <button> chứ không phải <span>: đoạn đầu của đường dẫn đưa về trang hub. Phải
	gỡ sạch dáng mặc định của nút — cỡ chữ, nền, viền, đệm — để nằm trong dòng chữ
	y hệt như cũ.
*/
.spk-brand-ten {
	flex: none;
	margin: 0;
	padding: 0;
	background: none;
	border: 0;
	font-size: inherit;
	font-weight: 700;
	white-space: nowrap;
	cursor: pointer;
}

.spk-brand-ten:hover {
	text-decoration: underline;
}

/*
	Đường dẫn "Thiết lập / Hoạt động". Nhạt hơn tên màn để đọc ra ngay đâu là màn,
	đâu là mục đang xem; cắt bằng dấu ba chấm chứ không đẩy thứ khác ra khỏi thanh
	khi tên mục dài.
*/
.spk-duong-dan {
	margin-left: 8px;
	min-width: 0;
	color: var(--spk-chu-mo);
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

/*
	Mỗi đoạn là một nút đưa tới đúng mục của nó. Lề chứ không `gap`: đây là nội dung
	inline trong một dòng chữ, và gap trong flexbox cần Chrome 84 còn người dùng có
	máy chạy Chrome 68.
*/
.spk-dd-nut {
	margin: 0;
	padding: 0;
	background: none;
	border: 0;
	font-size: inherit;
	color: inherit;
	white-space: nowrap;
	cursor: pointer;
}

.spk-dd-nut:hover {
	color: var(--spk-chu);
	text-decoration: underline;
}

/* Chỗ đang đứng: đậm hơn các đoạn trước, nhưng vẫn bấm được — xem _duongDan. */
.spk-dd-nay {
	color: var(--spk-chu);
}

.spk-dd-gach {
	margin: 0 6px;
	color: var(--spk-vien);
}

/* Rỗng thì ẩn hẳn — không thì cái lề 8px ở trên vẫn ăn chỗ. */
.spk-duong-dan:empty {
	display: none;
}

/*
	Màu phẩm chất vật phẩm trong game (Lục · Lam · Tím · Cam · Đỏ). Trước viết thẳng
	vào style= của từng <option>; đưa ra đây để bảng màu nằm cùng chỗ với các màu
	khác, và để đặt được chữ trắng — nền đỏ #c50505 với chữ đen mặc định thì gần như
	không đọc nổi.
*/
.spk-pc {
	color: #fff;
}

.spk-pc-luc { background-color: #54ab4d; }
.spk-pc-lam { background-color: #057fc5; }
.spk-pc-tim { background-color: #b326fc; }
.spk-pc-cam { background-color: #c56d05; }
.spk-pc-do  { background-color: #c50505; }

/* ---------- thân ---------- */

.spk-than {
	flex: 1;
	display: flex;
	min-height: 0;
	overflow: hidden;
	/* Mốc định vị cho ngăn kéo ở khổ hẹp — xem @media (max-width: 1000px). */
	position: relative;
}

.spk-side {
	width: var(--spk-cot-trai);
	flex: none;
	display: flex;
	flex-direction: column;
	padding: 10px 10px 2px;
	background: var(--spk-nen);
	border-right: 1px solid var(--spk-vien);
	overflow-y: auto;
}
.spk-side > * {
	margin-bottom: 8px;
}


.spk-scrim {
	display: none;
	position: fixed;
	/* Bốn khai báo dài thay `inset: 0` — inset cần Chrome 87, mà Chrome 68 (giả
	   lập MEmu) bỏ qua nó và thả lớp phủ xuống dưới mép màn hình. */
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	z-index: 30;
	background: rgba(31, 35, 40, 0.45);
}

.spk-scrim.spk-hien {
	display: block;
}

.spk-mans {
	flex: 1;
	min-width: 0;
	display: flex;
	flex-direction: column;
	overflow: hidden;
}

/*
	MỘT LỀ DUY NHẤT cho cả vùng nội dung, đúng cách tham-khao-1 làm: bên họ `.spk-main`
	giữ `padding: 0 16px` và mọi thứ bên trong đều bằng 0.

	Bản ta trước đó căn lề CỤC BỘ: 14px lặp lại ở .spk-hang, #editAccount,
	.spk-thanh-nut, #spkKhu, #accountInfo — năm chỗ cùng phải nhớ một con số, sót một
	chỗ là lệch, và đúng là đã lệch: khối đổi mật khẩu chưa bao giờ có lề.

	Dải "bạn là ai" và hàng thẻ nằm NGOÀI #content nên giữ lề riêng: chúng có nền
	tràn viền, đặt vào trong lề chung là mảng màu hụt hai bên.
*/
#content {
	flex: 1;
	min-height: 0;

	/* Cuộn nay ở TỪNG MÀN, không ở đây nữa — xem .spk-man.spk-hien. */
	overflow: hidden;
}

/* Bốn màn bật/tắt bằng CLASS, không bằng style inline. */
.spk-man {
	display: none;
}

/*
	MỖI MÀN MỘT HỘP CUỘN RIÊNG.

	`scrollTop` là thuộc tính của hộp cuộn chứ không phải của màn. Hồi cả bốn màn
	dùng chung #content thì đổi màn là mất chỗ đang đọc: đo được ở màn VIP cuộn
	xuống 400 (cuộn được 9254px), sang màn Hướng dẫn (cao 664px, không cuộn được)
	là trình duyệt kẹp scrollTop về 0, quay lại VIP thì về đầu trang.

	Riêng bản thân hộp cuộn thì trình duyệt giữ giúp, không cần một dòng JS nào —
	đã kiểm: đặt scrollTop rồi cho display:none, ép tính lại bố cục, hiện lại thì
	con số vẫn còn nguyên.

	NHƯNG NHƯ THẾ VẪN CHƯA ĐỦ để giữ chỗ đang đọc khi đổi màn: đo lại sau khi đổi thì
	vị trí vẫn về 0. Cô lập được thủ phạm bằng hai phép thử: ẩn/hiện suông giữ nguyên
	400, nhưng gọi resume() tại chỗ là tụt về 0 — resume() dựng lại nội dung, chiều cao
	sụp, trình duyệt kẹp scrollTop. Muốn giữ thật thì phải sửa resume(), không phải
	sửa CSS. Hai lần thử vá bằng JS trước đó cũng thua chính cuộc đua ấy.

	Dù vậy đây vẫn là nền đúng: mỗi màn một hộp thì không màn nào kéo tụt màn khác.

	`height: 100%` đứng được vì #content là mục flex có chiều cao xác định
	(`flex: 1` trong .spk-mans, một cột flex). Lề 14px chuyển từ #content xuống
	đây — vẫn nằm trong hộp cuộn như cũ, nên khoảng cách tới thanh cuộn không đổi.
*/
.spk-man.spk-hien {
	display: block;
	height: 100%;
	padding: 0 14px;
	overflow-y: auto;
	overflow-x: hidden;
}

/* ---------- cây điều hướng ---------- */

/*
	KHỐI CHỨA của cây dùng bố cục KHỐI, không dùng flex.

	Cây là một danh sách dọc thuần tuý; flex ở đây chỉ để lấy `gap`, mà `gap` cho
	flexbox phải tới Chrome 84 mới có. Trên Chrome 68 (trình duyệt của giả lập MEmu)
	nó vừa bị bỏ qua, vừa tạo ra năm tầng flex lồng nhau trong một vùng cuộn — và ở
	đó Blink đời cũ tính sai chiều cao khi một nhánh xoè ra: các mục cấp 2 ngang hàng
	đè lên danh sách vừa mở.

	Bố cục khối + lề chạy đúng ở mọi trình duyệt, và khoảng cách nay có thật trên
	Chrome 68 thay vì bị bỏ qua.
*/
.spk-nav {
	display: block;
}

.spk-nav > * + * {
	margin-top: 2px;
}

.spk-nav-nhom {
	display: block;
}

.spk-nav-c1 {
	display: flex;
	align-items: center;
	width: 100%;
	min-height: 42px;
	padding: 0 10px;
	background: transparent;
	border: 0;
	border-radius: var(--spk-bk);
	color: var(--spk-chu);
	font-size: 14px;
	font-weight: 600;
	text-align: left;
	cursor: pointer;
}

.spk-nav-c1:hover {
	background: var(--spk-nen-mo);
}

.spk-nav-c1.spk-dang {
	background: var(--spk-chinh-nhat);
	color: var(--spk-chinh-dam);
}

/*
	Bốn biểu tượng cấp 1 đều thuộc Emoji 1.0 (📖 💎 👤 phi-BMP, ⚙️ thì BMP), tức có
	mặt trên Android/iOS/Windows từ 2015. Nhưng font chữ mặc định KHÔNG chứa chúng —
	phải gọi đích danh font emoji của từng hệ, nếu không ra ô vuông rỗng. App này còn
	chạy trong trình duyệt của giả lập Android, nên đây
	không phải lo xa.
*/
.spk-nav-ic {
	flex: none;
	width: 20px;
	font-size: 15px;
	text-align: center;
	font-family: "Segoe UI Emoji", "Apple Color Emoji", "Noto Color Emoji",
		"Android Emoji", "Segoe UI Symbol", sans-serif;
}

/* Thay `gap: 8px` của hàng cấp 1 — gap trong flexbox cần Chrome 84. */
.spk-nav-c1 > * + * {
	margin-left: 8px;
}

.spk-nav-ten {
	flex: 1;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

/*
	MŨI SỔ CỦA CÂY ĐIỀU HƯỚNG — vẽ bằng viền, cùng một hình với đầu mục ở Hoạt động,
	nút chi tiết ở Tiện ích và nút sổ thẻ VIP.

	Trước đây chỗ này bày ký tự ▸ cỡ 10px: cùng HÌNH nhưng khác CỠ, và cỡ của một ký
	tự còn phụ thuộc font máy đang có. Vẽ bằng bốn đường viền thì bốn mũi trong app
	bằng nhau tuyệt đối.
*/
.spk-nav-mui {
	flex: none;
	display: inline-block;
	width: 0;
	height: 0;
	font-size: 0;
	border-left: 5px solid currentColor;
	border-top: 4px solid transparent;
	border-bottom: 4px solid transparent;
	color: var(--spk-chu-mo);
	transition: transform 0.15s ease;
}

.spk-nav-c1[aria-expanded="true"] .spk-nav-mui {
	transform: rotate(90deg);
}

/* Cấp 2 và cấp 3 ẩn/hiện bằng CLASS, không bằng display inline. */
.spk-nav-c2,
.spk-nav-c3 {
	display: none;
}

.spk-nav-c2.spk-xoe,
.spk-nav-c3.spk-xoe {
	display: block;
}

.spk-nav-c2 > * + *,
.spk-nav-c3 > * + * {
	margin-top: 1px;
}

/*
	Tiêu đề nhóm trong cây cấp 2 — màn Thiết lập có hai nhánh (Nhân vật, Bang hội).
	Không có tiêu đề thì các mục đổ liền một dãy và không biết cái nào thuộc đâu.
*/
/* Thay `gap: 6px` của hàng cấp 2 — cùng lý do với hàng cấp 1. */
.spk-nav-c2-nut > * + * {
	margin-left: 6px;
}

.spk-nav-c2-de {
	display: flex;
	align-items: center;
	padding: 8px 10px 3px 30px;
	color: var(--spk-chu-mo);
	font-size: 11px;
	font-weight: 600;
	letter-spacing: 0.06em;
	text-transform: uppercase;
}

.spk-nav-c2-de > * + * {
	margin-left: 6px;
}

.spk-nav-c2-de:first-child {
	padding-top: 3px;
}

/* Biểu tượng của tiêu đề nhóm (💎 cho nhóm VIP) — cùng ngăn xếp font với .spk-nav-ic. */
.spk-nav-c2-de-ic {
	font-size: 12px;
	line-height: 1;
	letter-spacing: 0;
	font-family: "Segoe UI Emoji", "Apple Color Emoji", "Noto Color Emoji",
		"Android Emoji", "Segoe UI Symbol", sans-serif;
}

.spk-nav-c2-nut {
	display: flex;
	align-items: center;
	width: 100%;
	/* 40px là ngưỡng vùng chạm — thanh nút cũ từng có nút 34px và bấm hụt. */
	min-height: 40px;
	padding: 0 10px 0 38px;
	background: transparent;
	border: 0;
	border-radius: var(--spk-bk);
	color: var(--spk-chu);
	font-size: 13.5px;
	text-align: left;
	cursor: pointer;
}

.spk-nav-c2-nut:hover {
	background: var(--spk-nen-mo);
}

.spk-nav-c2-nut.spk-dang {
	background: var(--spk-chinh-nhat);
	color: var(--spk-chinh-dam);
	font-weight: 600;
}

.spk-nav-c2-nut[aria-expanded="true"] .spk-nav-mui {
	transform: rotate(90deg);
}

/*
	Cấp 3 — từng hoạt động, từng nhóm vật phẩm. Mục Hoạt động có 20 mục con nên hàng
	phải gọn: chữ nhỏ hơn, cao 34px, và cắt bằng ba chấm thay vì xuống dòng để một
	tên dài không đẩy cả cột trái rộng ra.
*/
/*
	ĐẦU MỤC LÁ có một chấm tròn dẫn dòng, đúng bản tham-khao-1. Đo bên họ: chấm
	7×7px, đệm trái của nút 42px, chữ bắt đầu ở 56px — và CHỈ cấp 3 có chấm,
	cấp 1 và cấp 2 không.

	Họ giữ khoảng cách bằng `gap: 7px`; ta dùng `margin-right` vì `gap` của flexbox
	cần Chrome 84, mà người dùng có máy chạy Chrome 68.

	Cắt bằng ba chấm chuyển xuống .spk-nav-ten: nút nay là flex, `text-overflow`
	đặt ở đó không còn tác dụng.
*/
.spk-nav-c3-nut {
	display: flex;
	align-items: center;
	width: 100%;
	min-height: 34px;
	/*
		50px chứ không phải 42px như số đo TUYỆT ĐỐI của tham-khao-1: chỗ đáng chép
		là khoảng LỤT VÀO so với mục cha, không phải con số rời.

		Bên họ chữ cấp 2 bắt đầu ở 30, chữ cấp 3 ở 56 — lùi 26px. Bên ta chữ cấp 2 ở
		38, nên chép thẳng 42 thì chữ cấp 3 ở 56, chỉ lùi 18px: lá trông gần ngang hàng
		với cha. Đệm 50 đưa chấm về 50 và chữ về 64 — lại đúng 26px, và chấm cũng
		đứng lệch 12px so với chữ cha y như bên họ.
	*/
	padding: 0 10px 0 50px;
	background: transparent;
	border: 0;
	border-radius: var(--spk-bk);
	color: var(--spk-chu-mo);
	font-size: 12.5px;
	text-align: left;
	overflow: hidden;
	cursor: pointer;
}

.spk-cham {
	flex: none;
	width: 7px;
	height: 7px;
	margin-right: 7px;
	border-radius: 50%;
	background: var(--spk-cham);
}

.spk-nav-ten {
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.spk-nav-c3-nut:hover {
	background: var(--spk-nen-mo);
	color: var(--spk-chu);
}

.spk-nav-c3-nut:hover .spk-cham {
	background: var(--spk-chu-mo);
}

.spk-nav-c3-nut.spk-dang {
	background: var(--spk-chinh-nhat);
	color: var(--spk-chinh-dam);
	font-weight: 600;
}

/* Chấm đi theo chữ: mục đang xem thì chấm cũng ăn màu nhấn. */
.spk-nav-c3-nut.spk-dang .spk-cham {
	background: var(--spk-chinh-dam);
}

/* ---------- Ô NHẬP KHU TÀI KHOẢN ----------

   Ô nhập chữ dừng ở 480px, không kéo hết bề ngang màn. Đo trên tham-khao-1: mọi ô
   nhập chữ ở khu này đều 480px dù màn rộng bao nhiêu. Bản ta trước đó: mã quà tặng
   827px, tên người nhận 988px — một cái mã hay một tên đăng nhập không dài tới thế,
   mà ô càng dài thì mắt càng phải đi xa mới biết mình gõ tới đâu.

   BÓ TRONG HAI MÀN ấy chứ không đặt lên .spk-nhap chung: màn Thiết lập có những ô
   nhập nằm trong bảng, chiều rộng do cột quyết định. */

#spkMan_licenseModule .spk-nhap,
#spkMan_accountModule .spk-nhap {
	max-width: 480px;
}

/* Lề hai bên do #content lo chung cho cả vùng nội dung; ở đây chỉ trừ lề của
   `.spk-thanh-nut`, kẻo hai nút đổi mật khẩu thụt vào sâu hơn ba ô nhập bên dưới. */
#editAccount > .spk-thanh-nut {
	padding-left: 0;
	padding-right: 0;
}

/*
	Khối đổi mật khẩu: MỘT CỘT chứ không ba. Lưới là `repeat(auto-fit, minmax(300px,
	1fr))`, nên chặn bề rộng khối ở 480px là nó tự còn một cột và ô nhập vừa đúng
	480px — không phải viết lại lưới. Đúng cách tham-khao-1 xếp: ba ô 480px chồng dọc.

	Ba ô trải ngang 1018px còn kèm một tật: nhãn ô thứ ba dài, xuống hai dòng, nên ô
	nhập của nó tụt thấp hơn hai ô kia.
*/
.spk-moi #editAccountPass1,
.spk-moi #editAccountPass2 {
	max-width: 480px;
}

/* ---------- dòng "bạn là ai", dùng chung cả ba màn ---------- */

/*
	NỀN XANH NHẠT + VẠCH XANH BÊN TRÁI để dải bật hẳn ra. Ba mốc màu đo được quanh
	nó: nền trang #f6f4f9 (xám tím nhạt), thanh trên #ffffff (trắng), còn dải thì trong suốt
	— chìm nghỉm giữa hai thứ ấy. Để trắng thì nó dính liền vào thanh trên; xanh
	nhạt tách được khỏi cả hai.

	Vạch trái 3px chịu phần "đây là khối của bạn", nên đệm trái bớt đi 3px để chữ
	vẫn thẳng hàng với mọi thứ bên dưới.

	Kiểu dáng đặt ở #accountInfo chứ không ở #accountInfoContainer, vì dãy nút nằm
	NGOÀI container ấy mà vẫn phải nằm trong cùng một dải màu.

	CHO XUỐNG HÀNG ở tầng này: khổ hẹp thì dãy nút rơi xuống dòng dưới, căn phải.
	Chuỗi tên · email · xu bên trong container vẫn là một dòng cứng, nên dấu phân
	cách không bao giờ rơi xuống đầu dòng.
*/
#accountInfo {
	flex: none;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	padding: 7px 14px 7px 11px;
	border-left: 3px solid var(--spk-chinh);
	border-bottom: 1px solid var(--spk-vien);
	background: var(--spk-chinh-nhat);
	font-size: 13px;
}

/*
	220px quyết ĐIỂM XUỐNG HÀNG. Chỗ xuống hàng được tính theo bề rộng ưa thích
	của mục (flex-basis) chứ không phải bề rộng sau khi co: rộng hơn 220px thì còn đủ
	chỗ cho dãy nút đứng chung một hàng, hẹp hơn thì thà cho dãy nút xuống hàng còn
	hơn bóp email lại còn vài ký tự.

	`min-width: 0` là điều kiện để con số trên có hiệu lực. Mặc định `min-width: auto`
	nâng bề rộng ưa thích lên bằng bề rộng tối thiểu của nội dung — đo được 334px ở
	khổ 360px — nên hễ có nút là xuống hàng, kể cả màn VIP chỉ có mỗi icon đăng
	xuất. Phần không co được của chuỗi (icon · tên · xu) là 228px, vẫn nằm dưới
	bề rộng còn lại ở mọi khổ thực tế, nên không có chuyện tràn ra ngoài.
*/
#accountInfoContainer {
	flex: 1 1 220px;
	min-width: 0;
}

/* Dãy nút: dồn sang mép phải, và khi xuống hàng vẫn nằm bên phải. */
.spk-tk-nut {
	flex: none;
	display: flex;
	align-items: center;
	margin-left: auto;
}

/*
	Dải chỉ còn MỘT nút. Nhãn chữ nằm ở title và aria-label nên trình đọc màn hình
	lẫn tooltip đều vẫn đọc ra "Đăng xuất".

	Màu chữ thường chứ không xanh: một hình vẽ đặc màu xanh đặt giữa dải xanh thì chìm.
*/
.spk-tk-thoat {
	box-sizing: border-box;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-height: 30px;
	padding: 4px 9px;
	background: var(--spk-nen);
	border: 1px solid var(--spk-vien);
	border-radius: 6px;
	color: var(--spk-chu);
	cursor: pointer;
}

.spk-tk-thoat:hover {
	border-color: var(--spk-chinh);
}

.spk-tk-thoat svg {
	display: block;
	width: 17px;
	height: 17px;
}
/* ---------- dòng thông tin tài khoản ----------

   Tên lớp lấy đúng bản tham-khao-1 (main.js getInfo sinh ra). Nằm trong
   #accountInfo, vốn căn giữa cho dòng "Nhân vật … (tài khoản …)" của màn Thiết
   lập — nên nó tự đặt lại căn lề trái cho chính mình.

   MỘT HÀNG NGANG, co đúng bằng nội dung. Bản trước là một thẻ có viền chiếm trọn
   bề rộng màn (đo được 975 × 92px ở khổ 1280px) để chứa ba dòng chữ ngắn xếp dọc,
   bên phải trống hơn 800px — mà #accountInfoContainer thì đã có sẵn đệm và đường
   kẻ dưới, nên còn là hộp nằm trong hộp.

   LỀ CHỨ KHÔNG DÙNG `gap`: gap trong flexbox cần Chrome 84, người dùng có máy
   chạy Chrome 68. Luật cũ đặt `gap: 9px` nên trên máy ấy ba dòng dính sát nhau.

   KHÔNG CHO XUỐNG HÀNG: có dấu phân cách rồi thì chỗ xuống hàng sẽ đẩy một cây
   gạch đứng xuống đầu dòng dưới, đứng lơ lửng chẳng ngăn cách gì. Hết chỗ thì cho
   email co lại, xem luật của nó bên dưới. */

.spk-tk-khoi {
	display: flex;
	flex-wrap: nowrap;
	align-items: baseline;
	text-align: left;
}

/* Cùng con icon nav.js dùng cho mục "Tài khoản" — hai chỗ nói cùng một thứ. */
.spk-tk-ic {
	flex: none;
	margin-right: 7px;
	font-size: 13px;
}

.spk-tk-ten {
	flex: none;
	font-size: 13px;
	font-weight: 700;
}

/*
	Dấu phân cách do CSS vẽ, đặt ở HAI MẨU KHÔNG BỊ CẮT. Không đặt ở
	`.spk-tk-mail::before` vì ô email có `overflow: hidden`, dấu nằm trong đó sẽ bị
	cắt cụt cùng với email khi hết chỗ.
*/
.spk-tk-ten::after,
.spk-tk-vi::before {
	content: "|";
	margin: 0 9px;
	color: var(--spk-vien);
	font-weight: 400;
}

/*
	Email là mẩu dài nhất và nhẹ ký nhất — cho nó co lại rồi cắt bằng dấu ba chấm
	khi hết chỗ, thay vì để nó đẩy số xu đi chỗ khác. `min-width: 0` là điều kiện
	để một mục flex được phép co xuống dưới bề rộng nội dung của nó.
*/
.spk-tk-mail {
	flex: 0 1 auto;
	min-width: 0;
	font-size: 12.5px;
	color: var(--spk-chu-mo);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

/*
	Số dư Xu là thông tin PHỤ: một dòng chữ nhỏ, không hộp, không màu nhấn. Bản
	trước là hộp nền xanh với con số cỡ 21px — nặng ngang tên tài khoản.
*/
/* `flex: none` — chỉ email được phép co, tên và số xu phải nguyên vẹn. */
.spk-tk-vi {
	flex: none;
	display: flex;
	align-items: baseline;
	font-size: 12.5px;
	color: var(--spk-chu-mo);
}

.spk-tk-vi-nhan {
	margin-right: 6px;
}

/* tabular-nums: số dư đổi sau mỗi lần đồng bộ, chữ số không cùng bề rộng thì cả
   dòng nhảy qua nhảy lại. */
.spk-tk-vi-so {
	font-weight: 600;
	color: var(--spk-chu);
	font-variant-numeric: tabular-nums;
}


/* ---------- hàng thẻ trang hub ----------

   Chỉ bày ở TRANG HUB: thẻ lớn có icon và mô tả. Vào một khu rồi thì cây cột trái
   ganh việc đi lại, hàng thẻ ẩn hẳn.

   Từng có dạng thứ hai — dải nút gọn kèm nút quay lại hub — hồi khu Tài khoản
   chưa đổ vào cây. Từ r3600 không nhánh nào như vậy nữa nên dạng đó đã bỏ.

   Đặt ở vỏ (ngoài mọi .spk-man) vì nó phải ở lại khi đổi giữa màn Tài khoản và màn
   VIP — hai màn ấy là hai view riêng. */

/*
	LƯỚI AUTO-FIT, không phải flex-wrap — đúng cách tham-khao-1 dàn hàng thẻ hub.

	Flex cho mỗi HÀNG tự giãn riêng, nên hàng cuối thiếu thẻ thì mấy cái còn lại phình
	ra khác hẳn hàng trên. Đo được với 5 thẻ:
		1000px   236+236+236+236 / 260      còn họ: 186 × 5 một hàng
		 854px   199 × 4 / 260             còn họ: 156 × 5
		 640px   197 × 3 / 260 + 260       còn họ: 196 × 3 / 196 × 2
		 412px   260 × 5, MỖI THẺ MỘT HÀNG   còn họ: 191 × 2 / 191 × 2 / 191
	Khổ dọc hỏng nặng nhất và chỉ vì thiếu 6px: hai thẻ cần 190+190+10 = 390 mà chỗ
	có 384, nên rớt xuống còn một thẻ rồi giãn tới 260.

	Lưới thì mọi cột BẰNG NHAU dù hàng cuối thiếu thẻ, và số cột tự rút theo bề rộng.
	`auto-fit` thu các cột thừa về 0 nên 5 thẻ ở khổ rộng vẫn trải đều hết hàng.

	Thêm một cái lợi: `gap` của LƯỚI có từ Chrome 66, còn gap của FLEX phải đợi
	Chrome 84 — trên máy Chrome 68 của người dùng, luật cũ bị bỏ qua và các thẻ dính sát
	nhau. Đổi sang lưới là hết luôn tật đó.
*/
.spk-khu {
	flex: none;
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
	gap: 10px;
	padding: 12px 14px;
	background: var(--spk-nen-mo);
	border-bottom: 1px solid var(--spk-vien-nhat);
}

/* nav.js bật/tắt bằng thuộc tính hidden; display:flex ở trên sẽ thắng nó nếu
   không có dòng này. */
.spk-khu[hidden] {
	display: none;
}

/* Bề rộng do CỘT của lưới quyết định; thẻ không tự giãn nữa. */
.spk-the {
	display: flex;
	flex-direction: column;
	padding: 11px 13px 9px;
	background: var(--spk-nen);
	border: 1px solid var(--spk-vien);
	border-radius: 10px;
	color: var(--spk-chu);
	font: inherit;
	text-align: left;
	cursor: pointer;
}
.spk-the > * {
	margin-bottom: 2px;
}


.spk-the:hover {
	border-color: var(--spk-chinh);
}

.spk-the.spk-dang {
	border-color: var(--spk-chinh);
	box-shadow: inset 0 0 0 1px var(--spk-chinh);
}

.spk-the-ic {
	font-size: 17px;
	line-height: 1.2;
	font-family: "Segoe UI Emoji", "Apple Color Emoji", "Noto Color Emoji",
		"Android Emoji", "Segoe UI Symbol", sans-serif;
}

.spk-the-ten {
	font-weight: 600;
	color: var(--spk-chinh-dam);
}

.spk-the-phu {
	font-size: 12px;
	color: var(--spk-chu-mo);
}

/* ---------- lớp phủ toàn màn (điều khoản sử dụng) ---------- */

.spk-phu {
	display: none;
	position: fixed;
	/* Bốn khai báo dài thay `inset: 0` — inset cần Chrome 87, mà Chrome 68 (giả
	   lập MEmu) bỏ qua nó và thả lớp phủ xuống dưới mép màn hình. */
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	z-index: 100002;
	background: rgba(31, 35, 40, 0.55);
	align-items: center;
	justify-content: center;
	padding: 16px;
}

.spk-phu.spk-hien {
	display: flex;
}

.spk-phu-hop {
	position: relative;
	width: 100%;
	max-width: 880px;
	height: 100%;
	max-height: 85vh;
	background: var(--spk-nen);
	border-radius: var(--spk-bk);
	overflow: hidden;
}

.spk-phu-hop iframe {
	width: 100%;
	height: 100%;
	border: 0;
	display: block;
}

.spk-phu-dong {
	position: absolute;
	top: 8px;
	right: 8px;
	width: 32px;
	height: 32px;
	background: var(--spk-nen);
	border: 1px solid var(--spk-vien);
	border-radius: 6px;
	font-size: 18px;
	line-height: 1;
	cursor: pointer;
}

/* ---------- lớp phủ "đang tải" (thay $.mobile.loading) ---------- */

.spk-tai {
	display: none;
	position: fixed;
	/* Bốn khai báo dài thay `inset: 0` — inset cần Chrome 87, mà Chrome 68 (giả
	   lập MEmu) bỏ qua nó và thả lớp phủ xuống dưới mép màn hình. */
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	z-index: 100003;
	align-items: center;
	justify-content: center;
	background: rgba(31, 35, 40, 0.25);
}

.spk-tai.spk-hien {
	display: flex;
}

.spk-tai-vong {
	width: 38px;
	height: 38px;
	border: 3px solid var(--spk-vien);
	border-top-color: var(--spk-chinh);
	border-radius: 50%;
	animation: spk-quay 0.7s linear infinite;
}

@keyframes spk-quay {
	to {
		transform: rotate(360deg);
	}
}

@media (prefers-reduced-motion: reduce) {
	.spk-tai-vong {
		animation-duration: 2.4s;
	}

	.spk-nav-mui {
		transition: none;
	}
}

/* ---------- ô nhập có tiền tố/hậu tố, do JS sinh ----------
   Thay bộ lớp ui-input-text/ui-body-inherit/ui-corner-all/ui-shadow-inset mà
   main.js, setting.js và license.js viết tay để mượn kiểu của jQM. */

/*
	VỎ Ô NHẬP CŨNG NỀN XÁM như mọi control khác.

	Đây là ô nhập của hộp thoại "Chuyển VIP" — nó bị bỏ sót ở đợt đổi nền vì nó mang
	lớp riêng (`.spk-boc-nhap`) chứ không phải `.spk-nhap`. Cùng một bệnh người dùng đã
	báo: "giao diện toàn màu trắng, khó phân biệt các control".

	TRÊN NỀN HỘP THOẠI thì càng cần: hộp thoại vốn đã là một tấm trắng nổi lên giữa màn
	hình, ô trắng đặt trên tấm trắng ấy chỉ còn một đường viền tím nhạt để tự phân biệt.
*/
.spk-boc-nhap {
	display: flex;
	align-items: center;
	background: var(--spk-nen-o);
	border: 1px solid var(--spk-vien-o);
	border-radius: var(--spk-bk);
	padding: 2px 8px;
}

/* Đang gõ thì NỔI lên (nền trắng), nghỉ thì LÕM — cùng lối với `.spk-nhap`. */
.spk-boc-nhap:focus-within {
	background: var(--spk-nen);
}

.spk-boc-nhap input {
	flex: 1;
	min-width: 0;
	border: 0;
	background: transparent;
	padding: 6px 0;
	font-size: 14px;
}

.spk-boc-nhap input:focus {
	outline: none;
}

/* ══════════════════════════ NGĂN KÉO ở khổ hẹp ══════════════════════════ */

@media (max-width: 1000px) {
	.spk-burger {
		display: inline-flex;
	}

	.spk-side {
		/*
			ABSOLUTE trong .spk-than, KHÔNG fixed theo cửa sổ. Ngăn kéo fixed top:0
			chui lên dưới thanh trên cùng, và phần đầu cây bị che, bấm không được.
		*/
		position: absolute;
		top: 0;
		bottom: 0;
		left: 0;
		z-index: 35;
		width: var(--spk-cot-trai);
		max-width: 84vw;
		transform: translateX(-100%);
		transition: transform 0.18s ease;
		box-shadow: 0 8px 24px rgba(31, 35, 40, 0.18);
		/* Máy có tai thỏ khi xoay ngang thì khuyết nằm ở CẠNH BÊN, đúng chỗ ngăn kéo trượt ra. */
		padding-left: 10px;
		padding-left: max(10px, env(safe-area-inset-left));
	}

	.spk-side.spk-mo {
		transform: translateX(0);
	}

	.spk-scrim {
		position: absolute;
	}
}

@media (max-width: 1000px) and (prefers-reduced-motion: reduce) {
	.spk-side {
		transition: none;
	}
}

/* ────────── APP PC: TRẢ LẠI cột trái cố định ở khổ 641–1000px

   Ngưỡng 1000px ở trên đúng cho TRÌNH DUYỆT, nhưng bề ngang không phân biệt được
   cửa sổ app PC hẹp với một chiếc điện thoại. `?platform=winApp` thì phân biệt
   được, và app PC vốn đã truyền sẵn tham số ấy.

   Đây là khối HOÀN TÁC chứ không phải bản chép thứ hai của luật ngăn kéo — chép
   thành hai bản là có hai chỗ phải nhớ sửa cùng lúc. Hoàn tác thì chỉ đụng
   body.spk-winapp, tức bán kính ảnh hưởng lên mọi khổ khác bằng KHÔNG.

   MỘT NGOẠI LỆ của việc hoàn tác: burger vẫn HIỆN. Ở chế độ cột cố định nó đổi
   nghĩa thành nút ẩn/hiện cột — xem khối "ẨN CỘT TRÁI" bên dưới.

   SÀN 641px mượn đúng mốc @media (max-width: 640px) của khối giao diện điện
   thoại phía trên: dưới mốc đó cửa sổ là khổ điện thoại thật, và ngăn kéo mới
   đúng kể cả trên app PC. Không đẻ thêm con số nào. */
@media (min-width: 641px) and (max-width: 1000px) {
	body.spk-winapp .spk-burger {
		display: inline-flex;
	}

	body.spk-winapp .spk-side {
		position: static;
		z-index: auto;
		width: var(--spk-cot-trai);
		transform: none;
		transition: none;
		box-shadow: none;
		padding-left: 10px;
	}

	body.spk-winapp .spk-scrim {
		position: fixed;
	}
}

/* ────────── NẰM NGANG: TRẢ LẠI cột trái cố định — và ô tìm vào theo

   Xoay ngang là chiều DỌC hoá ra của hiếm còn chiều NGANG thì thừa. Đo ở
   800×360: khu nội dung chỉ cao 245px, mà riêng ô tìm nằm phía trên đã ăn 58px
   — gần một phần tư.

   Trả cây về cột cố định thì ô tìm TỰ vào trong cây: `datChoOTim()` hỏi CSS
   (`laCotCoDinh()`) chứ không tự giữ một mốc riêng, nên không phải sửa một dòng JS
   nào. Đo lại ở 640/720/800×360 và 900×400: khu nội dung 245 → 303px (+24%), cây
   luôn thấy, không cuộn ngang.

   Cái mất là bề ngang: 640 → 378px, 800 → 538px cho nội dung. Ở khổ ngang thì đó là
   thứ đang dư, và ai cần rộng vẫn bấm burger ẩn cây được — lựa chọn ấy được nhớ
   (xem khối "ẨN CỘT TRÁI").

   SÀN 640px: hẹp hơn thế thì cột 262px chiếm quá nửa màn, ngăn kéo mới đúng.

   TRẦN 480px CHIỀU CAO là phần bắt buộc, và nó suýt bị bỏ quên: chỉ hỏi
   `orientation: landscape` thì một cửa sổ TRÌNH DUYỆT 900×800 cũng là "ngang" —
   rộng hơn cao — và luật này đổi luôn bố cục ở chỗ không ai yêu cầu. `max-height:
   480px` là dấu hiệu "điện thoại nằm ngang": mọi điện thoại xoay ngang đều thấp hơn
   thế, còn cửa sổ trình duyệt thì không. Con số 480 mượn đúng mốc
   `@media (max-width: 640px), (max-height: 480px)` đã có sẵn trong tệp, không đẻ
   thêm số nào.

   Đây là khối HOÀN TÁC như khối app PC ngay trên, không phải bản chép thứ hai của
   luật ngăn kéo — chỉ có một chỗ phải nhớ sửa. */
@media (min-width: 640px) and (max-width: 1000px)
	and (orientation: landscape) and (max-height: 480px) {
	.spk-side {
		position: static;
		z-index: auto;
		width: var(--spk-cot-trai);
		max-width: none;
		transform: none;
		transition: none;
		box-shadow: none;
		padding-left: 10px;
	}

	/* Màn tối của ngăn kéo hết việc: cây không còn trượt đè lên nội dung nữa. */
	.spk-scrim {
		position: fixed;
	}
}

/* ────────── Thanh nút đáy KHÔNG phủ sang cột trái

   .spk-thanh-day là position:fixed; width:100% — có từ thời chưa có cột trái, nên
   nó phủ ngang cả phần dưới của cây điều hướng. Xoè hết một danh mục rồi cuộn cây
   xuống hết thì mấy mục cuối vẫn nằm khuất sau nó, không cách nào tới được (đo được
   62px cuối của .spk-side ở cửa sổ cao 760px).

   Thanh này thao tác trên NỘI DUNG chứ không trên cây, nên cho nó bắt đầu sau cột
   trái. CHỈ cần ở chế độ cột trái cố định: ở chế độ ngăn kéo, .spk-side mang
   z-index 35 nên vốn đã nằm TRÊN thanh nút (z-index 10) và không bị che. */

@media (min-width: 1001px) {
	.spk-thanh-day {
		left: var(--spk-cot-trai);
		right: 0;
		width: auto;
	}
}

@media (min-width: 641px) and (max-width: 1000px) {
	body.spk-winapp .spk-thanh-day {
		left: var(--spk-cot-trai);
		right: 0;
		width: auto;
	}
}

/* ────────── ẨN CỘT TRÁI — CHỈ ở chế độ cột cố định

   Khách dùng app PC (cửa sổ khoảng 840px) muốn lấy lại 262px của cột trái. Đo
   được ở 840px: nội dung chỉ còn 578px, tức 31% cửa sổ dành cho cây mà không có
   cách nào tắt. Mặc định VẪN HIỆN; ẩn là lựa chọn, và nav.js nhớ nó theo máy.

   BÓ TRONG ĐÚNG HAI MEDIA QUERY của chế độ cột cố định, tuyệt đối KHÔNG viết
   thành luật toàn cục. Ở chế độ ngăn kéo, .spk-side là absolute + translateX,
   và một luật `display: none` toàn cục sẽ làm NGĂN KÉO KHÔNG MỞ RA ĐƯỢC NỮA —
   ẩn cột ở khổ rộng rồi thu cửa sổ lại là dính đúng cái bẫy ấy: bấm burger mà
   không có gì xảy ra.

   Ẩn cột thì phải HOÀN TÁC luôn hai luật .spk-thanh-day ở ngay trên, kẻo thanh
   nút đáy chừa một khoảng trống 262px không còn gì lấp. */

@media (min-width: 1001px) {
	/* Ở khổ này burger vốn `display: none` — giờ nó là nút bật/tắt cột. */
	.spk-burger {
		display: inline-flex;
	}

	body.spk-an-cay .spk-side {
		display: none;
	}

	body.spk-an-cay .spk-thanh-day {
		left: 0;
		width: 100%;
	}
}

@media (min-width: 641px) and (max-width: 1000px) {
	body.spk-winapp.spk-an-cay .spk-side {
		display: none;
	}

	body.spk-winapp.spk-an-cay .spk-thanh-day {
		left: 0;
		width: 100%;
	}
}

@supports (padding: max(0px)) {
	.spk-topbar {
		padding-left: max(14px, env(safe-area-inset-left));
		padding-right: max(14px, env(safe-area-inset-right));
	}

	/*
		Tách riêng vì dải "bạn là ai" có vạch trái 3px: đệm trái phải bớt đúng 3px
		ấy thì chữ mới thẳng hàng với hàng thẻ bên dưới. Gộp chung với .spk-topbar
		như trước là đè mất 3px đó — luật này đứng sau nên nó thắng.
	*/
	#accountInfo {
		padding-left: max(11px, env(safe-area-inset-left));
		padding-right: max(14px, env(safe-area-inset-right));
	}
}
