/* cardgame.css — 圍獵 UI 原型(CARDGAME_UI_SPEC.md)。
   刻意不套用站內 library.css 語言,當獨立商業 TCG 遊戲做(參照 Hearthstone/Gwent 質感)。 */
@import url("emoji.css");

/* 全站統一 emoji 字型(見該檔說明) */
@font-face {
	font-family: en;
	src: url(../client/public/fonts/inconsolata.woff);
}

@font-face {
	font-family: sym;
	src: url(../client/public/fonts/symmingliu.woff);
}

@font-face {
	font-family: huninn;
	src: url(../font/huakang.ttc);
}

@font-face {
	font-family: zh;
	src: local("微軟正黑體"), local("Microsoft JhengHei"), local("Lantinghei TC");
}

:root {
	--cg-bg: #0d1210;
	--cg-panel: #1a201c;
	--cg-panel-2:#232b25;
	--cg-gold: #c9a45c;
	--cg-gold-dim: #7a6535;
	--cg-text: #e8e2d0;
	--cg-text-dim: #9d9483;
	--cg-red: #d0574a;
	--cg-green: #6fae5c;
	--cg-card-text: #644529;
}

* {
	box-sizing: border-box;	/* 拖曳手勢會經過文字節點,不鎖選取的話滑鼠一動就選到字,破壞拖曳體驗 */
	-webkit-user-select: none;
	user-select: none;
}

/* 彈出 UI 的文字允許選取(2026-07-18 使用者要求):牌桌本體(含手牌/拖曳面)維持上面
*{user-select:none} 以保護拖曳手勢;只有這些 modal 彈窗——放大卡(#cg-lightbox)、技能面板
(#cg-skill-panel)、以及所有 .cg-overlay(開局選職業/規則速查/結算/總戰力明細/戰報)——
覆寫回可選取,方便複製規則/戰報/數值明細。 */
#cg-lightbox, #cg-lightbox *, #cg-skill-panel, #cg-skill-panel *, .cg-overlay, .cg-overlay * {
	-webkit-user-select: text;
	user-select: text;
}

html, body {
	margin: 0;
	height: 100%;
	background: radial-gradient(ellipse at 50% 0%, #1c2620 0%, #0a0e0b 70%);
	color: var(--cg-text);
	font-family: emoji, en, sym, huninn, zh, sans-serif;
	overflow: hidden;
	touch-action: none;
	background-image: url('/image/plank.png');
}

#cg-app {
	display: flex;
	flex-direction: column;	/* 三層漸進 fallback,不能只寫 100vh——手機瀏覽器網址列還顯示著的時候,100vh 量的是「網址列收起後的最大可視高度」,比實際可視範圍高出一截,導致排版整排溢出螢幕下緣(使用者真機截圖抓到)。中間這行用 cardgame_ui.js 的 setVhVar() 拿 window.innerHeight實測值換算,舊版不支援 100dvh 的瀏覽器也有保底;最後一行 100dvh 在支援的瀏覽器上會直接贏過前兩行,且網址列收合/展開時瀏覽器自己動態跟著調整,不必等 JS resize 事件。 */
	height: 100vh;
	height: calc(var(--cg-vh, 1vh) * 100);
	height: 100dvh;
	max-width: 1800px;   /* 2026-07-14 從 1400 放寬,讓超寬螢幕的單欄寬度能吃到平鋪模式(見 cardgame_ui.js 的 STACK_FLAT_MIN) */
	margin: 0 auto;
	padding: 0 8px;
	gap: 6px;
}

/* ===== 上區:對手手牌(純展演) ===== */

/* #cg-opp-row 桌機上單純是 #cg-opp-hand 的外殼;.cg-mobile-strip 改成絕對定位懸浮
(見下方說明),不再是這排的 flex 子項,position:relative 只是給它一個定位錨點。 */
#cg-opp-row {
	display: flex;
	align-items: flex-end;
	flex-shrink: 0;
	position: relative;
}

/* 對手的覆蓋牌要跟我方手牌同一張「牌」的尺寸(128x190),只是用外層容器裁切只露出下半,
不能另外做一組縮小尺寸的卡片——那樣會讓玩家誤以為對手的牌實際比較小張。 */
#cg-opp-hand {
	flex: 1;
	position: relative;
	display: flex;
	justify-content: center;
	min-width: 0;   /* flex item 預設 min-width:auto 不肯縮小於內容寬,見 #cg-my-hand 同處說明 */
	gap: 10px;
	height: 96px;   /* 露出的高度,非卡片本身高度——實際值由 balanceVerticalSpace() 動態覆寫 */
	padding-top: 2px;
	overflow: hidden;	/* 刻意不加 transition:height——balanceVerticalSpace() 一次算出精確比例只套用一次,
																																																																											   不會反覆改動,但曾經加過渡動畫時若跟舊版逐步微調迴圈疊加,短時間內反覆重新起始
																																																																											   十幾次轉場曾在真實瀏覽器上造成渲染花紋(使用者實測抓到),拿掉徹底排除這個風險。 */
}

/* 空間不足時退化成疊放壓縮寬度(見 cardgame_ui.js 的 layoutHandRow),取代 flex 排列,
跟下方我方手牌用同一套邏輯——兩排各自量測容器實際寬度決定攤平或疊放。 */
#cg-opp-hand.mode-compressed {
	display: block;
}

#cg-opp-hand.mode-compressed .cg-oppcard-peek {
	position: absolute;
	top: 0;
}

/* 側欄打掉後,對方/我方的技能圖示與輪到誰標籤原本併入各自的手牌排「排版內」,佔掉一塊
flex 寬度——手牌區是 flex:1 但沒設 min-width:0,窄螢幕上這塊固定寬度會讓手牌容器被迫
撐開超過可用寬度上限,擠爆最後一張牌(使用者真機截圖抓到:第4張牌被推到畫面外)。
改成絕對定位懸浮在手牌排的左下角、獨立 z-index(見下),完全脫離文件流,手牌區永遠拿到
整排寬度,不會再被這塊資訊條影響版面計算;.cg-opp-row/.cg-my-row 是它的定位錨點。 */
.cg-mobile-strip {
	display: none;
	align-items: center;
	gap: 6px;
	padding: 4px 6px;
	position: absolute;
	left: 0;
	bottom: 0;
	z-index: 60;   /* 蓋在手牌卡片(無 z-index,預設疊放順序)之上,但低於拖曳浮動卡(999)/技能面板(950)/lightbox(900) */
	background: rgba(0, 0, 0, 0.6);   /* 懸浮在卡片上方時要跟底下卡面有區隔,不加背景會跟卡片圖案糊在一起看不清 */
	border-radius: 8px;
}

.cg-mobile-strip .cg-skill-icon {
	width: 40px;
	height: 40px;
	font-size: 18px;
}

.cg-turn-num-m {
	font-size: 15px;
	color: var(--cg-gold);
	font-weight: bold;
}

.cg-oppcard-peek {
	width: 128px;
	height: 96px;   /* 裁切窗口:只看得到卡片下半(卡片從畫面外上方垂下)——實際值由 JS 動態覆寫 */
	overflow: hidden;
	position: relative;
	border-radius: 0 0 8px 8px;   /* 只圓下緣——這裡是卡片實際露出的邊,上緣被裁掉不需要圓角 */

	/* 不加 transition:height,理由同 #cg-opp-hand */
}

.cg-oppcard-peek-inner {
	width: 128px;
	height: 190px;
	border-radius: 8px;
	box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.4);
	position: relative;
	top: -104px;
	background-image: url('/image/cardcover.png');
	background-size: 100% 100%;
	border: none;
}

/* ===== 中間主體:左側欄 / 戰場 / 右側欄 ===== */
#cg-main {
	flex: 1;
	display: flex;
	gap: 8px;
	min-height: 0;
}

.cg-sidebar {
	width: 96px;
	flex-shrink: 0;
	background: linear-gradient(180deg, var(--cg-panel) 0%, var(--cg-panel-2) 100%);
	border: 1px solid var(--cg-gold-dim);
	border-radius: 10px;
	padding: 10px 6px;
	display: flex;
	flex-direction: column;
	align-items: center;
}

/* 左側欄(時序):對方相關資訊靠上緣、我方相關資訊靠下緣,跟頁面「上=對手/下=我方」
   的空間語言一致——回合數本身居中,不偏向任何一方。 */
#cg-left {
	justify-content: space-between;
}

#cg-left .cg-turn-whose-slot {
	min-height: 26px;
	display: flex;
	align-items: center;
}

#cg-left .cg-turn-center {
	display: flex;
	flex-direction: column;
	align-items: center;
}

#cg-left .cg-turn-num {
	font-size: 26px;
	color: var(--cg-gold);
	font-weight: bold;
	text-shadow: 0 2px 4px rgba(0, 0, 0, 0.6);
}

#cg-left .cg-turn-label {
	font-size: 11px;
	color: var(--cg-text-dim);
	text-align: center;
}

.cg-turn-whose {
	padding: 4px 10px;
	border-radius: 14px;
	font-size: 12px;
	white-space: nowrap;
	background: rgba(111, 174, 92, 0.18);
	color: var(--cg-green);
	border: 1px solid var(--cg-green);
}

.cg-turn-whose.opp {
	background: rgba(208, 87, 74, 0.18);
	color: var(--cg-red);
	border-color: var(--cg-red);
}

/* 右側欄(玩家):對方技能靠上緣、我方技能靠下緣,同一套空間語言 */
#cg-right {
	justify-content: space-between;
}

.cg-skill-slot {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 3px;
}

.cg-skill-icon {
	width: 56px;
	height: 56px;
	border-radius: 50%;
	background: radial-gradient(circle at 35% 30%, #3a3020, #1a1610);
	border: 2px solid var(--cg-gold-dim);
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 24px;
	cursor: pointer;
	position: relative;
	transition: border-color .15s, transform .15s;
}

.cg-skill-icon:hover {
	border-color: var(--cg-gold);
	transform: scale(1.05);
}

.cg-skill-icon.used {
	opacity: 0.4;
	filter: grayscale(0.6);
}

/* 圓形頭像:職業立繪填滿圓框(取上緣=露臉),原本的職業 emoji 縮成右下角小徽章 */
.cg-skill-icon.has-portrait {
	background-size: cover;
	background-position: top center;
	background-repeat: no-repeat;
	overflow: visible;
}

.cg-skill-emoji {
	position: absolute;
	right: -3px;
	bottom: -3px;
	width: 22px;
	height: 22px;
	font-size: 13px;
	line-height: 1;
	display: flex;
	align-items: center;
	justify-content: center;
	border-radius: 50%;
	background: radial-gradient(circle at 35% 30%, #3a3020, #1a1610);
	border: 1.5px solid var(--cg-gold-dim);
	box-shadow: 0 1px 3px rgba(0, 0, 0, .5);
}

.cg-skill-badge {
	position: absolute;
	bottom: -6px;
	right: -6px;
	background: var(--cg-gold);
	color: #201a0d;
	font-size: 11px;
	font-weight: bold;
	border-radius: 9px;
	min-width: 18px;
	height: 18px;
	line-height: 18px;
	text-align: center;
	padding: 0 3px;
	border: 1px solid #100d06;
}

.cg-skill-label {
	font-size: 10px;
	color: var(--cg-text-dim);
	text-align: center;
}

/* ===== 戰場:3 地形欄 ===== */
#cg-board {
	flex: 1;
	display: flex;
	gap: 8px;
	min-width: 0;
}

.cg-column {
	flex: 1;
	min-width: 0;
	display: flex;
	flex-direction: column;
	position: relative;
	z-index: 0;
	background: rgba(0, 0, 0, 0.25);
	border: 1px solid rgba(201, 164, 92, 0.25);
	border-radius: 10px;
	overflow: hidden;
	font-weight: bold;
	box-shadow: 0px 5px 5px 3px rgba(50, 50, 50, 0.6);
}

/* 獵場 ascii 底紋(2026-07-25 新增):壓在卡片之下的氛圍圖案,只在卡片間的空隙/欄位空白處
   露出——卡片本身不透明,不會被蓋掉。內容動態 fetch static/ascii_textures/*.txt(見 JS
   TERRAIN_TEXTURE_URL),依欄位量測到的實際寬高動態拼接重複次數;查無對應地形時 textContent
   留空,視覺上就是回退成現行純色淡底,逐地形擴充只需要補字典+txt,不用動這裡的邏輯。
   font-size 改動時記得同步調整 JS 的 TEX_CHAR_W/TEX_CHAR_H(字元估算尺寸,影響重複份數
   算得夠不夠,兩處脫鉤會導致貼圖填不滿欄位邊緣提早被裁掉一截)。 */
.cg-terrain-texture {
	position: absolute;
	inset: 0;
	z-index: -1;
	margin: 0;
	pointer-events: none;
	overflow: hidden;
	font-family: emoji, en, sym, huninn, zh, sans-serif;
	white-space: pre;
	line-height: 1;
	font-size: 10px;
	color: transparent;
	opacity: 0.5;
}

.cg-column.terrain-desert .cg-terrain-texture {
	color: #ffaa39;
}

.cg-column.terrain-grass .cg-terrain-texture {
	color: #8bb350;
}

.cg-column.terrain-rock .cg-terrain-texture {
	color: #9c9c9c;
}

.cg-column.terrain-water .cg-terrain-texture {
	color: #8dd7ff;
}

.cg-column.terrain-forest .cg-terrain-texture {
	color: #67a17c;
}

/* 地形識別色(2026-07-14 新增):欄位邊框+淡底色+中層地形名文字,五種地形各自對應一組色,
   一眼就能分辨這欄是什麼地形,不用只靠文字。色彩對應 CARDGAME_RULES_CHECKLIST.md §五的
   5 種天氣命名(沙漠沙塵暴/草原野火/岩地落石/水澤暴雨/林地瘴氣)所在的地形本身,
   不是天氣觸發後才上色——地形識別色是常態,天氣 icon 的金黃色發光是疊加上去的效果提示,
   兩者分工不衝突。 */
.cg-column.terrain-desert {
	border-color: rgb(227 163 81);
	background: rgba(73, 52, 22, 0.8);
}

.cg-column.terrain-grass {
	border-color: rgba(139, 179, 80, 1);
	background: rgba(45, 56, 28, 0.85);
}

.cg-column.terrain-rock {
	border-color: rgba(150, 150, 150, 1);
	background: rgba(53, 53, 53, 0.85);
}

.cg-column.terrain-water {
	border-color: rgba(88, 152, 186, 1);
	background: rgba(20, 53, 71, 0.7);
}

.cg-column.terrain-forest {
	border-color: rgba(75, 122, 92, 1);
	background: rgba(0, 54, 24, 0.8);
}

.cg-column.terrain-desert .cg-col-head {
	color: #f7b158;
	border-color: rgba(214, 158, 87, 0.35);
	background: linear-gradient(90deg, rgba(214, 158, 87, 0.5), rgba(214, 158, 87, 0.03));
}

.cg-column.terrain-grass .cg-col-head {
	color: #a1d752;
	border-color: rgba(139, 179, 80, 0.35);
	background: linear-gradient(90deg, rgba(139, 179, 80, 0.5), rgba(139, 179, 80, 0.03));
}

.cg-column.terrain-rock .cg-col-head {
	color: #adadad;
	border-color: rgba(150, 150, 150, 0.35);
	background: linear-gradient(90deg, rgba(150, 150, 150, 0.5), rgba(150, 150, 150, 0.03));
}

.cg-column.terrain-water .cg-col-head {
	color: #84c6e9;
	border-color: rgba(88, 152, 186, 0.35);
	background: linear-gradient(90deg, rgba(88, 152, 186, 0.6), rgba(88, 152, 186, 0.03));
}

.cg-column.terrain-forest .cg-col-head {
	color: #2cb860;
	border-color: rgba(75, 122, 92, 0.35);
	background: linear-gradient(90deg, rgba(33, 200, 06, 0.26), rgba(75, 122, 92, 0.03));
}

/* 2026-07-16 合併單欄:一欄只剩一個共用疊放區(上下分列是「各佔4格」誤解時期的產物),
   垂直空間需求砍半;overflow:hidden 防線保留(極端窄高比時卡片在區內裁掉,不越界)。 */
.cg-col-stack {
	flex: 1;
	position: relative;
	padding: 6px;
	min-height: 60px;
	display: flex;
	align-items: center;
	overflow: hidden;
}

.cg-stack-inner {
	position: relative;
	width: 100%;
	height: 100%;
}

/* 平鋪模式(欄位夠寬,可以一次放 4 張不重疊):交給 flex 排一排,取消疊放用的絕對定位 */
.cg-stack-inner.mode-flat {
	display: flex;
	align-items: center;
	justify-content: center;
	flex-wrap: wrap;
	gap: 6px;
}

.cg-stack-inner.mode-flat .cg-card {
	position: static;
	left: auto;
	margin-left: 0;
}

/* 平鋪且空間充裕(如 1920x1080 桌電):卡片不用縮小,維持跟手牌一樣的原尺寸——縮小只是
   窄一點空間裡的省空間手段,不是「攤平」本身該有的樣子,空間夠大時維持原尺寸看得更清楚、
   跟手牌視覺一致。 */
.cg-stack-inner.mode-flat-large {
	display: flex;
	align-items: center;
	justify-content: center;
	flex-wrap: wrap;
	gap: 6px;
}

.cg-stack-inner.mode-flat-large .cg-card {
	position: static;
	left: auto;
	margin-left: 0;
	width: 128px;
	height: 190px;
}

.cg-stack-inner.mode-flat-large .cg-card .cg-card-art {
	height: 88px;
}

/* 折衷模式(欄位放不下 4 張平鋪,但夠放 2 堆並排):拆成兩個小堆,各自維持接龍疊放 */
.cg-stack-inner.mode-pair {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 10px;
}

.cg-pile {
	position: relative;
	width: 96px;
	height: 100%;
}

.cg-stack-inner.mode-pair .cg-card {
	left: 0;
	margin-left: 0;
}

/* mode-stack(欄位太窄,退回現行單堆疊 4 張只露上緣)不需要額外規則——
   沿用 .cg-card 預設的 position:absolute; left:50%; margin-left:-48px 那一套 */

/* 欄頭(2026-07-16 取代原中層分隔列):地形名+天氣icon 靠左、pips 靠右(雙方加總已於
   同日移入欄內比分徽章,見 .cg-col-score)。合併單欄後它是欄位唯一的資訊列,永遠可見
   (不做收合——分層讓位的第3步已取消)。 */
.cg-col-head {
	flex-shrink: 0;
	padding: 5px 8px;
	background: linear-gradient(90deg, rgba(201, 164, 92, 0.12), rgba(201, 164, 92, 0.03));
	border-bottom: 1px solid rgba(201, 164, 92, 0.25);
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 6px;
	font-size: 13px;
	color: var(--cg-gold);
	position: relative;
}

.cg-head-left {
	display: inline-flex;
	align-items: center;
	gap: 5px;
	white-space: nowrap;
}

/* 欄內比分(2026-07-16 取代欄頭加總):垂直置中後牌堆上下多出空間,比分移到「對方在上、
   我方在下」——方向直接對應盤面,比欄頭一行「紅:綠」更直觀。紅=對方、綠=我方,
   同 pips/輪到誰的色彩語言;對手伏牌的數值以 +? 表示(自己伏牌自己看得到,直接計入)。
   pointer-events:none=純顯示,不擋拖曳落點與卡片點擊;分數變動時數字用 rAF 跑分滾動
   (見 cardgame_ui.js 的 animateNumber),.rolling 期間微放大提示。 */
.cg-col-score {
	position: absolute;
	left: 50%;
	transform: translateX(-50%);
	z-index: 6;
	pointer-events: auto;   /* 2026-07-17 開放點擊=總戰力計算明細面板(原 none 防擋操作;徽章面積小,實測不擋拖曳落點) */
	cursor: pointer;
	font-weight: bold;
	font-size: 15px;
	line-height: 1;
	padding: 3px 9px;
	border-radius: 10px;
	background: rgba(0, 0, 0, 0.45);
	white-space: nowrap;
	transition: transform .15s;
}

.cg-col-score.rolling {
	transform: translateX(-50%) scale(1.2);
}

.cg-col-score.score-opp {
	top: 4px;
	color: var(--cg-red);
}

.cg-col-score.score-mine {
	bottom: 4px;
	color: var(--cg-green);
}

.cg-col-score .score-suffix {
	font-weight: normal;
	opacity: .8;
}

/* 共享格位指示點(2026-07-16 新增):每欄 4 顆,對方紅點由左往右填、我方綠點由右往左填,
   兩端向中間夾=「共享 4 格先到先得」的視覺化——這欄還剩幾格、被誰佔走,一眼可讀。
   規則是雙方共享一欄 4 格(不是各 4 格),UI 需要一個明確載體讓玩家建立正確心智模型,
   光靠上下兩個疊放區的卡片數量不夠直觀(曾經連設計者自己都誤解成各 4 格)。
   2026-07-16 改僅手機模式顯示(媒體查詢內開啟):桌面欄位基本都攤得平,平鋪模式的
   空格框已經把「共享 4 格、被誰佔走」刻在版面上,pips 功能完全重複;疊放模式(手機)
   空格框不畫,pips 才是容量資訊的唯一載體。 */
.cg-slot-pips {
	display: none;
	gap: 4px;
	align-items: center;
}

.cg-pip {
	width: 9px;
	height: 9px;
	border-radius: 50%;
	border: 1px solid var(--cg-gold-dim);
	background: transparent;
}

.cg-pip.opp {
	background: var(--cg-red);
	border-color: var(--cg-red);
}

.cg-pip.mine {
	background: var(--cg-green);
	border-color: var(--cg-green);
}

.cg-terrain-icon {
	font-size: 15px;
	cursor: pointer;
	filter: drop-shadow(0 0 3px rgba(255, 180, 60, 0.7));
}

.cg-terrain-icon.mine-only {
	opacity: 0.85;
}

.cg-terrain-icon.mine-only::after {
	content: '(僅己方可見)';
	display: none;
}

/* (2026-07-16 移除舊 .cg-col-mid.collapsed 收合規則:合併單欄後欄頭資訊密度高不宜收,
   且垂直需求已砍半,分層讓位前兩步即足夠——第3步取消,見 cardgame_ui.js balanceVerticalSpace) */

/* 空格框(僅平鋪模式渲染):共享 4 格的剩餘容量直接畫在戰場上,搶位的張力看得見;
   疊放/雙堆模式空間吃緊不畫,容量資訊由欄頭 pips 承載(手機收合狀態的替代方案)。 */
.cg-slot-empty {
	width: 96px;
	height: 142px;
	border: 1px dashed rgba(201, 164, 92, 0.3);
	border-radius: 8px;
	flex-shrink: 0;
}

.cg-column.terrain-grass .cg-slot-empty {
	background: rgba(19, 26, 18, 0.6);
}

.cg-column.terrain-rock .cg-slot-empty {
	background: rgba(25, 30, 26, 0.6);
}

.cg-column.terrain-water .cg-slot-empty {
	background: rgba(15, 23, 21, 0.6);
}

.cg-column.terrain-forest .cg-slot-empty {
	background: rgba(19, 24, 18, 0.6);
}

.cg-column.terrain-desert .cg-slot-empty {
	background: rgba(26, 27, 21, 0.6);
}

.cg-stack-inner.mode-flat-large .cg-slot-empty {
	width: 128px;
	height: 190px;
}

/* 敵我識別(合併單欄後的側色語言,同 pips/輪到誰:紅=對方、綠=我方):
   上邊條+名稱列底色微染,face 與 back 都要有(對方伏牌是卡背,也得認得出是誰的)。 */
.cg-card.side-opp .cg-card-face, .cg-card.side-opp .cg-card-back {
	border-top: 3px solid var(--cg-red);
}

.cg-card.side-mine .cg-card-face, .cg-card.side-mine .cg-card-back {
	border-top: 3px solid var(--cg-green);
}

.cg-card.side-opp .cg-card-title {
	background: linear-gradient(rgba(208, 87, 74, 0.22), rgba(0, 0, 0, 0.35));
	background: #e9dbc6;
}

.cg-card.side-mine .cg-card-title {
	background: linear-gradient(rgba(111, 174, 92, 0.22), rgba(0, 0, 0, 0.35));
	background: #e9dbc6;
}

/* ===== 疊放卡牌(接龍) ===== */

/* 卡片本來就是直式(跟手牌同一種語言),疊放時絕對不能因為欄位比較寬就被拉伸成橫式——
   固定寬度、水平置中在欄位裡,只用「疊放時只露出上緣」表現堆疊感,形狀本身不變。 */
.cg-card {
	position: absolute;
	left: 50%;
	width: 96px;
	height: 142px;
	margin-left: -48px;
	border-radius: 8px;
	cursor: pointer;
	perspective: 800px;
}

.cg-card-flip {
	position: relative;
	width: 100%;
	height: 100%;
	transition: transform .5s;
	transform-style: preserve-3d;
}

/* 行進中的對手出牌(2026-07-16 翻牌展演):卡背從對手手牌飛向目標欄,落地入欄後才翻正。
   蓋掉 .cg-card 基底的 left:50%/margin-left 置中(那是給欄內疊放用的),行進座標由 JS
   以視窗座標直接指定。 */
.cg-card.cg-travel {
	position: fixed;
	margin-left: 0;
	z-index: 500;
	pointer-events: none;
	transition: left .35s ease-in-out, top .35s ease-in-out;
}

/* 對手手牌可點(沙盒觸發對手出牌展演) */
.cg-oppcard-peek {
	cursor: pointer;
	top: -15px;
}

/* dev 示範按鈕(結算翻伏牌) */
.cg-dev-btn {
	padding: 3px 8px;
	border: 1px solid var(--cg-gold-dim);
	border-radius: 6px;
	font-size: 12px;
	color: var(--cg-gold);
	background: rgba(0, 0, 0, 0.35);
	cursor: pointer;
	user-select: none;
}

/* 全螢幕切換鈕(2026-08-01):雙重把關才顯示——① html.cg-fs-ok(JS 偵測瀏覽器真的有
   Fullscreen API;iPhone Safari 沒有,這顆鈕永遠不出現,不留死鈕)② 窄螢幕才給
   (桌機 F11 本來就是,也沒有網址列吃版面的問題)。斷點與 JS 的 FS_MOBILE_MQ 必須一致。
   放在 .cg-mobile-strip 裡沿用 .cg-dev-btn 的既有樣式,不另外做浮動層;那排在窄螢幕已經很擠,
   所以只給單字元圖示、不加文字。 */
.cg-fs-btn {
	display: none;
}

@media (max-width:880px) {
	html.cg-fs-ok .cg-fs-btn {
		display: block;
	}

}

/* 已在全螢幕:反白提示「再按一下會退出」(手機沒有 hover,title 看不到,得靠顏色講) */
.cg-fs-btn.is-on {
	color: var(--cg-bg);
	background: var(--cg-gold);
	border-color: var(--cg-gold);
}

.cg-card.is-back .cg-card-flip {
	transform: rotateY(180deg);
}

.cg-card-face, .cg-card-back {
	position: absolute;
	inset: 0;
	backface-visibility: hidden;
	border-radius: 8px;
	border: 1px solid var(--cg-gold-dim);
	overflow: hidden;
	box-shadow: 0 3px 10px rgba(0, 0, 0, 0.5);
}

/* .cg-card-desc 寫 flex:1 是要讓說明區「吃掉標題+圖案之外的剩餘空間」,但那個 flex:1
   之前一直沒有效果——.cg-card-face 本身不是 flex container,三塊(標題/圖案/說明)只是照
   正常文件流堆疊,標題+固定 62px 圖案+說明三者相加常常超過卡片總高度(142px),超出的部分
   被這裡的 overflow:hidden 整段悄悄裁掉,不是說明文字自己縮小,而是說明區直接被砍掉一截
   (使用者真機截圖抓到:技能文字被截斷嚴重)。補上 flex column 讓下面 flex:1 真正生效——
   標題/圖案鎖定各自高度(flex-shrink:0),剩餘空間全部分給說明區,不夠時說明區自己
   overflow-y:auto 捲動,不會再讓整張卡片邊界外的內容憑空消失。 */
.cg-card-face {
	background: linear-gradient(160deg, #26221c 0%, #181410 100%);
	display: flex;
	flex-direction: column;
}

.cg-card-back {
	transform: rotateY(180deg);
	display: flex;
	align-items: center;
	justify-content: center;
	background-image: url('/image/cardcover.png');
	border: none;
	background-size: 100% 100%;
}

.cg-card-title {
	display: flex;
	flex-shrink: 0;
	justify-content: flex-start;   /* 2026-07-24 改:原本 space-between 會讓圖示浮在中間;
	                                   現在名稱靠左、其餘(圖示+戰力數字)整組緊貼靠右 */
	align-items: center;
	padding: 3px 6px;
	background: rgba(0, 0, 0, 0.35);
	font-size: 12px;
	line-height: 1.3;
	background: #e9dbc6;
}

.cg-card-name {
	color: var(--cg-card-text);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
	min-width: 0;   /* flex 子項目要能真正被截斷,寬度歸零是前提(量測式排版同款教訓) */
	flex-shrink: 1;
}

/* 圖示+戰力數字整組靠右緊貼(2026-07-24 新增,取代舊版 space-between 平均分散) */
.cg-card-right {
	display: flex;
	align-items: center;
	margin-left: auto;
	flex-shrink: 0;
}

.cg-card-dots {
	font-size: 10px;
	letter-spacing: 1px;
	margin-left: 3px;
}

/* 星級=牌組規則(⭐⭐⭐最多2/⭐⭐以上合計最多6/⭐不限)的視覺翻譯,見 cardgame_ui.js starTier()。
   2026-07-24 從標題列搬到 art 區右下角,跟左上角的棲地圖標對角對稱——兩者都是跟戰鬥無關的
   後設資訊(棲地=地形加成來源,星級=組牌規則分類),標題列只留能力圖示+戰力數字。
   用 emoji ⭐ 全彩定色,color 對它不生效(留著不影響,萬一之後改回文字符號可直接生效)。 */
.cg-card-stars {
	position: absolute;
	right: 3px;
	bottom: 2px;
	z-index: 3;
	pointer-events: none;
	font-size: 10px;
	line-height: 1.2;
	border-radius: 6px;
	padding: 1px 3px;
}

.cg-card-power {
	color: var(--cg-card-text);
	font-weight: bold;
	font-size: 13px;
	transition: color .2s, transform .2s;
}

.cg-card-power.buffed {
	color: var(--cg-green);
	transform: scale(1.25);
}

.cg-card-power.debuffed {
	color: var(--cg-red);
	transform: scale(1.25);
}

.cg-card-art {
	height: 62px;
	flex-shrink: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	overflow: hidden;
	background: rgba(0, 0, 0, 0.2);
}

/* 縮放比例改由 JS 依每張圖實際渲染尺寸動態計算(見 cardgame_ui.js 的 fitArt),
   不在這裡寫死——不同 mob 的圖案大小差異很大,固定比例會讓大圖被切掉、小圖顯得過小。 */
.cg-card-art .mob-ascii {
	font-size: 6px;
	font-family: emoji, en, sym, huninn, zh !important;
	line-height: 1.05;
	margin: 0;
	padding: 0;
	background: none;
	transform-origin: center;
	font-weight: bold;
	filter: brightness(1.3);	/* currentColor 讓每個字元的光暈自動跟隨它自己(ANSI 上色後)的文字顏色,不用是同一種顏色——
	   text-shadow 是可繼承屬性,currentColor 在子元素各自的顏色上分別解析,不會被鎖死成
	   套用這條規則當下的顏色。小卡片字級只有 6px,模糊半徑 >0 反而會把細小字元糊成一團、
	   犧牲清晰度(使用者實測比對後定案)——小卡維持 0 模糊(視覺上只吃 bold+brightness,
	   不吃光暈範圍);lightbox 字級大很多(14px),模糊半徑加大反而更有質感,見下方
	   #cg-lightbox 覆寫規則。 */
	text-shadow: 0 0 0 currentColor;
}

.cg-card-desc {
	flex: 1;
	min-height: 0;   /* flex item 預設 min-height:auto 會撐到內容高度、蓋掉 flex:1 的收縮,必須歸零才能真的被壓縮進剩餘空間 */
	overflow-y: auto;
	font-size: 10px;
	line-height: 1.5;
	padding: 3px 6px;
	color: var(--cg-card-text);
	background: #e9dbc6;
}

.cg-card-desc div {
	white-space: nowrap;
}

/* 小張卡片(牌堆疊放/手牌)版:塞不下完整說明、捲軸體驗也不好——只置中顯示「圖示+名稱」,
   詳細說明留給點開的放大圖。overflow-y:auto=兜底(2026-07-17 由手機媒體查詢改為全域):
   能力 chips+棲地籌碼行數多的卡(如大猩猩 3 能力+林地籌碼)在戰場小卡上會超出說明區,
   visible 只會被卡面的 overflow:hidden 靜默裁掉,寧可能捲動也不無聲消失。 */
.cg-card-desc.compact {
	overflow-y: auto;
	display: flex;
	align-items: center;
	justify-content: center;
	flex-wrap: wrap;
	gap: 2px 8px;
	text-align: center;	/* 置中+溢出的經典陷阱:內容高於容器時,置中會讓頂端跑到捲動原點之上、永遠捲不到——
	   safe center=塞得下才置中,塞不下自動退回 start;不支援 safe 的舊瀏覽器吃上一行 center */
	align-content: center;
	align-content: safe center;
	background: #e9dbc6;
}

.cg-desc-chip {
	white-space: nowrap;
}

/* 棲地圖標(2026-07-17 二版:棲地=固有屬性,收納成 icon 浮貼 ascii art 右下角,不佔排版;
   數量=加成值,☂=浪跡。取代一版的文字籌碼(.cg-terr-chip 已退役);原生/適應的免疫差異
   由放大圖分項說明(.cg-terr-sect)承擔。 */
.cg-art-terr {
	position: absolute;
	left: 3px;
	top: 2px;   /* 左上角=直接接在標題列名稱下方,閱讀動線集中(2026-07-17 使用者調整,原右下) */
	z-index: 3;
	pointer-events: none;
	font-size: 10px;
	line-height: 1.2;
	max-width: 90%;
	text-align: left;
	padding: 1px 3px;
}

.cg-card-art {
	position: relative;   /* 棲地角標定位錨點 */
}

.cg-terr-sect {
	margin-top: 6px;
	padding-top: 5px;
	border-top: 1px dashed rgba(201, 164, 92, 0.3);
}

/* 拖曳中的欄位加成提示:標在欄位頂部中央,壓在投放區之上(dropzones z-index:50) */
.cg-affinity-hint {
	position: absolute;
	top: 34px;
	left: 50%;
	transform: translateX(-50%);
	z-index: 60;
	pointer-events: none;
	padding: 3px 10px;
	border-radius: 12px;
	background: rgba(0, 0, 0, 0.8);
	border: 1px solid var(--cg-text-dim);
	color: var(--cg-text-dim);
	font-size: 14px;
	font-weight: bold;
	white-space: nowrap;
}

.cg-affinity-hint.has-bonus {
	border-color: var(--cg-gold);
	color: var(--cg-gold);
}

/* 手牌區的卡片是完整大小、非疊放 */
.cg-hand-card {
	position: static;
	width: 128px;
	height: 190px;
	flex-shrink: 0;
	transition: transform .18s, box-shadow .18s;	/* .cg-card 基底規則(給戰場疊放卡用)寫死 left:50%+margin-left:-48px 做水平置中——
	   position:static 會讓 left 失效,但 margin-left 是普通盒模型屬性,不受 position 影響,
	   沒有明確歸零的話仍然會讓每張手牌往左偏移 48px、跟下一張卡疊在一起(曾經發生的 bug:
	   layoutHandRow 已經正確判定該用攤平模式,畫面卻仍然顯示疊放,根因就在這裡,不是
	   layoutHandRow 的邏輯錯)。 */
	margin-left: 0;
}

.cg-hand-card .cg-card-art {
	height: 88px;
}

.cg-hand-card:hover:not(.dragging) {
	transform: translateY(-14px);
	box-shadow: 0 10px 24px rgba(0, 0, 0, 0.6);
	z-index: 5;
}

.cg-hand-card.dragging {
	opacity: 0.35;
}

/* ===== 下區:我方手牌 ===== */

/* #cg-my-row 同 #cg-opp-row 的道理:.cg-mobile-strip 絕對定位懸浮,position:relative 給它定位錨點 */
#cg-my-row {
	display: flex;
	align-items: flex-end;
	flex-shrink: 0;
	position: relative;
}

#cg-my-hand {
	flex: 1;
	position: relative;
	height: 210px;   /* 實際值由 balanceVerticalSpace() 動態覆寫(高度不足時線性退縮到 30%) */
	display: flex;
	align-items: flex-end;
	justify-content: center;	/* flex item 預設 min-width:auto 不肯縮小於內容寬——手牌卡全是 flex-shrink:0,四張卡的
	   總寬會把容器自己撐開超過父層(手機實測:#cg-my-row 314px、容器被撐到 386px 並整頁
	   橫向溢出),layoutHandRow 量到的 clientWidth 於是永遠「剛好塞得下」,mode-compressed
	   壓縮模式永遠不會觸發(使用者真機截圖抓到:第4張手牌超出畫面)。歸零後容器乖乖等於
	   父層寬度,壓縮判斷才拿得到真實的可用寬度。 */
	min-width: 0;
	gap: 14px;
	padding: 4px 0;	/* 不加 transition:height,理由同 #cg-opp-hand */
}

/* 空間不足時退化成疊放壓縮寬度(見 cardgame_ui.js 的 layoutHandRow):容器夠寬就維持
   上面的 flex 攤平排列,不夠寬才切到這個模式——絕對定位讓卡片可以互相重疊而不是被擠爆版面。
   這是「寬度不夠」的壓縮,跟下面 .height-peek「高度不夠」的壓縮是兩個獨立軸,可以同時套用。 */
#cg-my-hand.mode-compressed {
	display: block;
}

#cg-my-hand.mode-compressed .cg-hand-card {
	position: absolute;
	bottom: 4px;
}

/* 高度不夠時的退讓(2026-07-14 定案,見 CARDGAME_IDEA.md 的分層讓位策略第2步):容器本身
   的高度被 JS 線性壓縮到最低 30%,卡片本身尺寸不變(190px),超出容器高度的部分預設裁掉
   只露一小截;滑鼠移入該卡片時用 :has() 讓父容器暫時 overflow:visible,卡片原有的
   hover 上浮動畫(見上面 .cg-hand-card:hover)就足以完整浮出,不需要另外設計更大幅度的位移。
   關鍵:改成 align-items:flex-start(從預設的 flex-end 切換)——露出的一小截要保留卡片
   「頂部」(名稱+戰力數字,最容易辨識),裁掉的是底部的詳細說明文字,不是反過來(曾經
   實測發現預設的 flex-end 對齊在壓縮時會先裁掉頂部名稱、只留下面的描述文字,方向錯了)。 */
#cg-my-hand.height-peek {
	overflow: hidden;
	align-items: flex-start;
}

#cg-my-hand.height-peek:has(.cg-hand-card:hover) {
	overflow: visible;
}

/* ===== 拖曳中的浮動卡 ===== */
#cg-drag-ghost {
	position: fixed;
	width: 128px;
	height: 190px;
	pointer-events: none;
	z-index: 999;
	display: none;
}

/* ===== 拖曳時出現的雙落點 ===== */
.cg-dropzones {
	position: absolute;
	inset: 0;
	display: none;
	flex-direction: column;
	z-index: 50;
}

.cg-column.drag-target .cg-dropzones {
	display: flex;
}

.cg-dropzone {
	flex: 1;
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 12px;
	border: 2px dashed transparent;
	transition: background .15s, border-color .15s;
}

.cg-dropzone.face-up {
	flex: 3;
	background: rgba(111, 174, 92, 0.08);
}

.cg-dropzone.face-down {
	flex: 1;
	background: repeating-linear-gradient(45deg, rgba(90, 70, 30, 0.25) 0 8px, rgba(60, 45, 20, 0.25) 8px 16px);
	color: var(--cg-gold);
}

/* 場地格滿 4 隻(cardgame_ui.js 的 STACK_CAP)時明打/蓋牌兩個落點都要灰掉,不是只灰蓋牌那格 */
.cg-dropzone.disabled {
	opacity: 0.25;
	filter: grayscale(1);
}

.cg-dropzone.hover-ok {
	border-color: var(--cg-gold);
	background: rgba(201, 164, 92, 0.22);
}

/* ===== 卡片放大 lightbox ===== */
#cg-lightbox {
	position: fixed;
	inset: 0;
	background: rgba(0, 0, 0, 0.82);
	display: none;
	align-items: center;
	justify-content: center;
	z-index: 900;
	cursor: zoom-out;
}

#cg-lightbox.show {
	display: flex;
}

/* 放大卡片本身不接收點擊——關閉判斷(見 cardgame_ui.js 的 #cg-lightbox click 監聽)是
   「點到的是背景本體」才收合,放大卡沒有任何互動功能,乾脆讓事件直接穿透到背景,
   點卡片任何位置都能收掉,不用另外幫卡片加一個 click-to-close 處理常式。 */
#cg-lightbox-slot {
	pointer-events: none;
}

/* art 區維持跟小卡片同一個高度佔比(小卡:62/142≈43.7%),不是任意挑一個看起來夠看的高度——
   2026-07-14 從固定 220px(僅佔 35.5%,比小卡片的佔比明顯縮水)改成 271px(620×43.7%),
   放大圖的視覺重心跟小卡片一致,不會因為放大反而讓圖片相對變小。 */
#cg-lightbox .cg-card {
	position: static;
	width: 380px;
	height: 620px;
	margin-left: 0;
	cursor: default;
}

#cg-lightbox .cg-card-art {
	height: 271px;
}

#cg-lightbox .cg-card-title {
	font-size: 20px;
	padding: 10px 16px;
	background: #e9dbc6;
}

#cg-lightbox .cg-card-dots {
	font-size: 17px;
}

#cg-lightbox .cg-card-desc {
	font-size: 16px;
	line-height: 1.9;
	padding: 12px 16px;
}

#cg-lightbox .cg-card-desc div {
	white-space: normal;
}

#cg-lightbox .cg-card-art .mob-ascii {
	font-size: 14px;   /* 縮放同樣交給 JS 動態計算,不寫死 none */
	text-shadow: 0 0 5px currentColor;   /* 放大圖字級夠大,光暈範圍加大更有質感(2026-07-14 使用者定案) */
}

/* ===== 技能說明面板 ===== */
#cg-skill-panel {
	position: fixed;
	inset: 0;
	background: rgba(0, 0, 0, 0.7);
	display: none;
	align-items: center;
	justify-content: center;
	z-index: 950;
}

#cg-skill-panel.show {
	display: flex;
}

/* ===== 職業技過場特效(出絕招登場):立繪橫掃 + 對角光帶 + 技名橫幅,~1.3s 後淡出 =====
   pointer-events:none 純視覺;z-index 970 壓在 overlay(960)之上但施放發生在對局中、無 overlay 顯示。
   .play 由 JS 掛上觸發,1.3s 後移除;side-mine(金)/side-opp(紅)決定方位與色調。 */
#cg-cutscene {
	position: fixed;
	inset: 0;
	z-index: 970;
	pointer-events: none;
	overflow: hidden;
	opacity: 0;
	visibility: hidden;
}

#cg-cutscene.play {
	visibility: visible;
	animation: cg-cut-env 1.3s ease forwards;
}

@keyframes cg-cut-env {
	0% {
		opacity: 0;
	}

	10% {
		opacity: 1;
	}

	80% {
		opacity: 1;
	}

	100% {
		opacity: 0;
	}

}

#cg-cutscene::before {

	/* 背景暗角:聚焦中央 */
	content: '';
	position: absolute;
	inset: 0;
	background: radial-gradient(ellipse at center, rgba(0, 0, 0, .3) 0%, rgba(0, 0, 0, .72) 100%);
}

/* 對角掃光帶 */
.cg-cutscene-flash {
	position: absolute;
	top: -10%;
	bottom: -10%;
	left: 0;
	width: 42vw;
	transform: skewX(-16deg);
	background: linear-gradient(90deg, transparent 0%, rgba(201, 164, 92, .5) 50%, transparent 100%);
	opacity: 0;
}

.side-opp .cg-cutscene-flash {
	background: linear-gradient(90deg, transparent 0%, rgba(208, 87, 74, .5) 50%, transparent 100%);
}

#cg-cutscene.play .cg-cutscene-flash {
	animation: cg-cut-sweep 1.3s ease-out forwards;
}

@keyframes cg-cut-sweep {
	0% {
		transform: translateX(-50vw) skewX(-16deg);
		opacity: 0;
	}

	20% {
		opacity: 1;
	}

	65% {
		opacity: .5;
	}

	100% {
		transform: translateX(150vw) skewX(-16deg);
		opacity: 0;
	}

}

/* 立繪 */
.cg-cutscene-portrait {
	position: absolute;
	top: 0;
	bottom: 0;
	display: flex;
	align-items: center;
}

.cg-cutscene-portrait img {
	height: 64vh;
	max-height: 540px;
	width: auto;
	filter: drop-shadow(0 10px 26px rgba(0, 0, 0, .75));
}

.side-mine .cg-cutscene-portrait {
	left: 3vw;
	justify-content: flex-start;
}

.side-opp .cg-cutscene-portrait {
	right: 3vw;
	justify-content: flex-end;
}

#cg-cutscene.play.side-mine .cg-cutscene-portrait {
	animation: cg-cut-in-left 1.3s cubic-bezier(.16, .8, .3, 1) forwards;
}

#cg-cutscene.play.side-opp .cg-cutscene-portrait {
	animation: cg-cut-in-right 1.3s cubic-bezier(.16, .8, .3, 1) forwards;
}

@keyframes cg-cut-in-left {
	0% {
		transform: translateX(-42vw) scale(.92);
		opacity: 0;
	}

	16% {
		opacity: 1;
	}

	24% {
		transform: translateX(0) scale(1);
	}

	82% {
		transform: translateX(0) scale(1);
		opacity: 1;
	}

	100% {
		transform: translateX(-12vw) scale(.98);
		opacity: 0;
	}

}

@keyframes cg-cut-in-right {
	0% {
		transform: translateX(42vw) scale(.92);
		opacity: 0;
	}

	16% {
		opacity: 1;
	}

	24% {
		transform: translateX(0) scale(1);
	}

	82% {
		transform: translateX(0) scale(1);
		opacity: 1;
	}

	100% {
		transform: translateX(12vw) scale(.98);
		opacity: 0;
	}

}

/* 技名橫幅(大字壓在立繪上,格鬥遊戲式登場) */
.cg-cutscene-banner {
	position: absolute;
	left: 0;
	right: 0;
	top: 50%;
	transform: translateY(-50%);
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 6px;
	text-align: center;
}

.cg-cut-cls {
	font-size: clamp(15px, 3.4vw, 22px);
	letter-spacing: 4px;
	color: var(--cg-text);
	text-shadow: 0 2px 6px #000;
}

.cg-cut-skill {
	font-size: clamp(44px, 12vw, 92px);
	font-weight: 900;
	letter-spacing: 8px;
	line-height: 1;
	padding-left: 8px;   /* 抵銷字距讓視覺置中 */
	color: var(--cg-gold);
	text-shadow: 0 0 20px rgba(201, 164, 92, .6), 0 4px 12px #000;
}

.side-opp .cg-cut-skill {
	color: var(--cg-red);
	text-shadow: 0 0 20px rgba(208, 87, 74, .6), 0 4px 12px #000;
}

#cg-cutscene.play .cg-cutscene-banner {
	animation: cg-cut-banner 1.3s cubic-bezier(.16, .8, .3, 1) forwards;
}

@keyframes cg-cut-banner {
	0% {
		transform: translateY(-50%) scale(1.35);
		opacity: 0;
	}

	20% {
		opacity: 0;
	}

	32% {
		transform: translateY(-50%) scale(1);
		opacity: 1;
	}

	80% {
		opacity: 1;
	}

	100% {
		transform: translateY(-50%) scale(1);
		opacity: 0;
	}

}

@media (prefers-reduced-motion:reduce) {
	.cg-cutscene-flash {
		display: none;
	}

	#cg-cutscene.play .cg-cutscene-portrait, #cg-cutscene.play .cg-cutscene-banner {
		animation: none;
	}

}

/* ===== 通用全屏 overlay(開局選職業/結算,同技能面板的遮罩語言) ===== */
.cg-overlay {
	position: fixed;
	inset: 0;
	background: rgba(0, 0, 0, 0.78);
	display: none;
	align-items: center;
	justify-content: center;
	z-index: 960;
}

.cg-overlay.show {
	display: flex;
}

.cg-dim {
	color: var(--cg-text-dim);
	font-size: 12px;
}

/* 開局:六職業選單 */
.cg-opening-box {
	max-width: 520px;
	max-height: 92vh;
	overflow-y: auto;
}

#cg-class-list {
	display: grid;
	grid-template-columns: repeat(6, 1fr);
	gap: 6px;
	margin: 10px 0 4px;
}

.cg-class-btn {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 3px;
	padding: 8px 3px;
	background: rgba(201, 164, 92, 0.08);
	border: 1px solid var(--cg-gold-dim);
	border-radius: 8px;
	color: var(--cg-text);
	cursor: pointer;
	text-align: center;
}

.cg-class-btn:hover {
	background: rgba(201, 164, 92, 0.2);
	border-color: var(--cg-gold);
}

.cg-class-btn.selected {
	background: rgba(201, 164, 92, 0.28);
	border-color: var(--cg-gold);
	box-shadow: inset 0 0 0 1px var(--cg-gold);
}

.cg-class-btn .cls-icon {
	font-size: 22px;
}

.cg-class-btn .cls-name {
	font-weight: bold;
	color: var(--cg-gold);
	font-size: 12px;
}

/* 選中職業的技能說明(只顯示被選的那一個,取代舊版全部並列的做法) */
#cg-class-desc {
	min-height: 3.4em;
	margin: 0 0 12px;
	padding: 10px 12px;
	background: rgba(0, 0, 0, 0.25);
	border: 1px solid var(--cg-gold-dim);
	border-radius: 8px;
	font-size: 13px;
	color: var(--cg-text-dim);
	line-height: 1.5;
	text-align: left;
}

#cg-class-desc b {
	color: var(--cg-gold);
}

@media (max-width:560px) {
	#cg-class-list {
		grid-template-columns: repeat(3, 1fr);
	}

}

/* 規則速查/戰報彈窗:可捲動,行動裝置吃滿高度。選擇器帶 .cg-panel-box 提高特異度——
基底 .cg-panel-box{text-align:center} 在樣式表較後面,同特異度會反過來蓋掉這裡的置左
(使用者實測抓到:戰報行被置中)。 */
.cg-panel-box.cg-rules-box {
	max-width: 560px;
	width: calc(100vw - 32px);
	max-height: 90vh;
	overflow-y: auto;
	text-align: left;
	font-size: 13px;
	line-height: 1.6;
}

.cg-rules-box h4 {
	color: var(--cg-gold);
	margin: 12px 0 4px;
	border-bottom: 1px solid rgba(201, 164, 92, 0.3);
	padding-bottom: 2px;
}

.cg-rules-box ul {
	margin: 0;
	padding-left: 18px;
	color: var(--cg-text-dim);
}

.cg-rules-box li b, .cg-rules-cls b, .cg-rules-dots b {
	color: var(--cg-text);
}

.cg-rules-terr div, .cg-rules-cls div, .cg-rules-dots div {
	color: var(--cg-text-dim);
	margin: 2px 0;
}

/* 總戰力計算明細:生物|事件|生命|聲勢 四欄列(2026-07-25 使用者要求把數值拆兩欄各自小計)。
生命=直接加減卡面戰力、聲勢=只進獵場分數;一列只填其中一欄,另一欄留白當分類線索。 */
.cg-score-row {
	display: flex;
	gap: 8px;
	padding: 2px 4px;
	font-size: 12.5px;
	border-bottom: 1px dashed rgba(201, 164, 92, 0.15);
}

.cg-score-row .sr-name {
	flex: 0 0 32%;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	color: var(--cg-text);
}

.cg-score-row .sr-src {
	flex: 1;
	min-width: 0;
	color: var(--cg-text-dim);
}

.cg-score-row .sr-hp, .cg-score-row .sr-pr, .cg-score-row .sr-val {
	flex: 0 0 40px;
	text-align: right;
	font-weight: bold;
}

/* 合計只有一個數字,橫跨生命+聲勢兩欄的寬度(40+8+40)靠右對齊 */
.cg-score-row.total .sr-val {
	flex: 0 0 88px;
	color: var(--cg-gold);
	font-size: 14px;
}

.cg-score-row .pos {
	color: var(--cg-green);
}

.cg-score-row .neg {
	color: var(--cg-red);
}

.cg-score-row.note {
	opacity: .65;
}

/* 表頭:不是資料,壓低存在感 */
.cg-score-row.head {
	color: var(--cg-gold-dim);
	font-size: 11.5px;
	font-weight: bold;
	border-bottom: 1px solid rgba(201, 164, 92, 0.3);
}

.cg-score-row.head .sr-name, .cg-score-row.head .sr-src {
	color: inherit;
}

/* 合計=生命+聲勢,算式寫在事件欄(不另設小計列,兩者功能重複) */
.cg-score-row.total {
	border-top: 1px solid var(--cg-gold-dim);
	border-bottom: none;
	margin-top: 4px;
}

/* 戰報:逐行事件記錄,天氣/陷阱行高亮 */
.cg-log-body {
	max-height: 60vh;
	overflow-y: auto;
	font-size: 12.5px;
	line-height: 1.7;
	color: var(--cg-text-dim);
}

.cg-log-body .lg-play {
	color: var(--cg-text);
}

.cg-log-body .lg-skill {
	color: var(--cg-gold);
}

.cg-log-body .lg-weather {
	color: var(--cg-red);
	font-weight: bold;
}

.cg-log-body .lg-die {
	color: var(--cg-red);
}

.cg-log-body .lg-dim {
	opacity: .8;
}

/* 牌組瀏覽:12張唯讀展示,重用 .cg-hand-card 的尺寸/定位覆寫(見該規則註解,同一個坑)。
   狀態用透明度+標籤區分,不需要另外設計卡面樣式。 */
.cg-deck-body {
	max-height: 65vh;
	overflow-y: auto;
	display: flex;
	flex-wrap: wrap;
	gap: 10px;
	justify-content: center;
}

.cg-deck-row {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 4px;
}

.cg-deck-status {
	font-size: 11px;
	padding: 1px 8px;
	border-radius: 10px;
	background: rgba(0, 0, 0, 0.4);
	color: var(--cg-text-dim);
}

.cg-deck-row.cg-deck-hand .cg-deck-status {
	color: var(--cg-green);
}

.cg-deck-row.cg-deck-board .cg-deck-status {
	color: var(--cg-gold);
}

.cg-deck-row.cg-deck-dead {
	opacity: .45;
}

.cg-deck-row.cg-deck-dead .cg-deck-status {
	color: var(--cg-red);
}

.cg-deck-row.cg-deck-undrawn {
	filter: brightness(0.5) saturate(0.5);
}

/* 結算:三欄戰果列 */
.cg-result-row {
	display: flex;
	justify-content: space-between;
	gap: 12px;
	padding: 6px 10px;
	margin: 4px 0;
	border: 1px solid var(--cg-gold-dim);
	border-radius: 6px;
	font-size: 14px;
}

.cg-result-row.win {
	border-color: var(--cg-green);
	background: rgba(111, 174, 92, 0.12);
}

.cg-result-row.lose {
	border-color: var(--cg-red);
	background: rgba(208, 87, 74, 0.10);
}

.cg-result-row .tot-opp {
	color: var(--cg-red);
	font-weight: bold;
}

.cg-result-row .tot-mine {
	color: var(--cg-green);
	font-weight: bold;
}

#cg-result-title.win {
	color: var(--cg-green);
}

#cg-result-title.lose {
	color: var(--cg-red);
}

/* ===== Toast(局內訊息:天氣降臨/陷阱引爆/技能宣告) ===== */
#cg-toast {
	position: fixed;
	top: 14%;
	left: 50%;
	transform: translateX(-50%);
	max-width: 90vw;
	padding: 8px 16px;
	background: rgba(0, 0, 0, 0.85);
	border: 1px solid var(--cg-gold);
	border-radius: 20px;
	color: var(--cg-gold);
	font-size: 14px;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
	z-index: 940;
	opacity: 0;
	pointer-events: none;
	transition: opacity .25s;
}

#cg-toast.show {
	opacity: 1;
}

/* ===== 技能選欄模式:欄位高亮呼吸 ===== */
.cg-column.targeting {
	cursor: pointer;
	box-shadow: 0 0 0 2px var(--cg-gold), 0 0 18px rgba(201, 164, 92, 0.45);
	animation: cg-target-pulse 1.1s ease-in-out infinite;
}

@keyframes cg-target-pulse {
	50% {
		box-shadow: 0 0 0 2px var(--cg-gold), 0 0 30px rgba(201, 164, 92, 0.75);
	}

}

/* ===== 逐步判定展演(2026-07-17) ===== */

/* 能力名稱浮標:fade in(0~20%)→ 停留 → fade out(80~100%),全程 1.5s(JS 同步步長);
掛在發動來源的卡片上(欄級效果掛在欄位上,字級放大)。 */
.cg-ability-float {
	position: absolute;
	left: 50%;
	top: 40%;
	z-index: 80;
	pointer-events: none;
	padding: 3px 10px;
	border-radius: 12px;
	background: rgba(0, 0, 0, 0.88);
	border: 1px solid var(--cg-gold);
	color: var(--cg-gold);
	font-size: 14px;
	font-weight: bold;
	white-space: nowrap;
	opacity: 0;
	animation: cg-ability-float 1.5s ease forwards;
}

.cg-column > .cg-ability-float {
	font-size: 17px;
	top: 30%;
}

@keyframes cg-ability-float {
	0% {
		opacity: 0;
		transform: translate(-50%, -20%);
	}

	20% {
		opacity: 1;
		transform: translate(-50%, -50%);
	}

	80% {
		opacity: 1;
		transform: translate(-50%, -50%);
	}

	100% {
		opacity: 0;
		transform: translate(-50%, -85%);
	}

}

/* 登場指定技無合格目標:失敗註記浮標(暗紅框,與正常金框效果浮標區隔) */
.cg-ability-float.miss {
	color: var(--cg-red);
	border-color: var(--cg-red);
}

/* 掠食滑走:光滑目標「逃脫」浮標(青色=外表光滑識別色 #5ec8e0) */
.cg-ability-float.escape {
	color: #5ec8e0;
	border-color: #5ec8e0;
}

/* ===== 受效果整卡閃光:增益閃藍、減益閃紅 =====
打在卡面 .cg-card-face 上用 inset 內光暈——欄位容器 overflow:hidden 會裁掉外擴陰影,
inset 畫在卡內邊緣故不受影響,連續受效果由 JS 強制重排重播。 */
@keyframes cg-flash-buff {
	0% {
		box-shadow: inset 0 0 0 1px rgba(94, 168, 224, 0), inset 0 0 10px 2px rgba(94, 168, 224, 0);
	}

	25% {
		box-shadow: inset 0 0 0 2px rgba(94, 168, 224, 0.95), inset 0 0 15px 4px rgba(94, 168, 224, 0.8);
	}

	100% {
		box-shadow: inset 0 0 0 1px rgba(94, 168, 224, 0), inset 0 0 10px 2px rgba(94, 168, 224, 0);
	}

}

@keyframes cg-flash-debuff {
	0% {
		box-shadow: inset 0 0 0 1px rgba(208, 87, 74, 0), inset 0 0 10px 2px rgba(208, 87, 74, 0);
	}

	25% {
		box-shadow: inset 0 0 0 2px rgba(208, 87, 74, 0.95), inset 0 0 15px 4px rgba(208, 87, 74, 0.8);
	}

	100% {
		box-shadow: inset 0 0 0 1px rgba(208, 87, 74, 0), inset 0 0 10px 2px rgba(208, 87, 74, 0);
	}

}

@keyframes cg-flash-escape {
	0% {
		box-shadow: inset 0 0 0 1px rgba(94, 200, 224, 0), inset 0 0 10px 2px rgba(94, 200, 224, 0);
	}

	25% {
		box-shadow: inset 0 0 0 2px rgba(94, 200, 224, 0.95), inset 0 0 15px 4px rgba(94, 200, 224, 0.8);
	}

	100% {
		box-shadow: inset 0 0 0 1px rgba(94, 200, 224, 0), inset 0 0 10px 2px rgba(94, 200, 224, 0);
	}

}

.cg-card.flash-buff .cg-card-face, .cg-card.flash-buff .cg-card-back {
	animation: cg-flash-buff 0.65s ease-out;
}

.cg-card.flash-debuff .cg-card-face, .cg-card.flash-debuff .cg-card-back {
	animation: cg-flash-debuff 0.65s ease-out;
}

.cg-card.flash-escape .cg-card-face, .cg-card.flash-escape .cg-card-back {
	animation: cg-flash-escape 0.65s ease-out;
}

/* 受擊震動(2026-07-24):只掛在真正受傷的 dmg 事件上(見 cardgame_ui.js execStep 的
ev.t==='dmg' 分支),持續性計分(地形/協同/毒性等)的 flash-debuff 不觸發——避免把
非「被打中」的分數變化也震得像挨揍。動畫加在 .cg-card 本身(不是 face/back),
因為翻牌用的 rotateY 轉場是 .cg-card-flip 在動,兩者各自 transform 互不干擾。 */
@keyframes cg-hit-shake {
	0% {
		transform: translateX(0);
	}

	10% {
		transform: translateX(-9px);
	}

	20% {
		transform: translateX(8px);
	}

	30% {
		transform: translateX(-7px);
	}

	40% {
		transform: translateX(6px);
	}

	50% {
		transform: translateX(-5px);
	}

	60% {
		transform: translateX(4px);
	}

	70% {
		transform: translateX(-3px);
	}

	80% {
		transform: translateX(2px);
	}

	90% {
		transform: translateX(-1px);
	}

	100% {
		transform: translateX(0);
	}

}

.cg-card.hit-shake {
	animation: cg-hit-shake 0.5s ease-in-out;
}

/* 陣亡淡出:判定步驟中只淡出不移除 DOM,最終 renderAll 重建真實盤面 */
.cg-card.dying {
	transition: opacity .5s, filter .5s;
	opacity: 0;
	filter: grayscale(1);
}

/* ===== 表演命中:持續性能力被永久移除(圓點/說明淡出,名稱戰力保留) ===== */
.cg-card.is-silenced .cg-card-dots, .cg-card.is-silenced .cg-card-desc {
	opacity: 0.25;
	filter: grayscale(1);
}

/* 淡化的原因說明(2026-08-01 使用者要求):暗掉的是能力,這一行是「為什麼暗掉」,
   所以刻意不吃上面那條淡化規則(它只選 dots/desc,這是獨立的第三塊)。
   預設 display:none,只有 .is-silenced 才出現——渲染端無條件輸出這個節點即可,
   靜態建卡與逐步判定動態加 class 兩條路徑共用同一份控制。
   flex-shrink:0 = .cg-card-face 是 flex column,說明區 flex:1 會自己讓出這一行的高度。 */
.cg-card-silenced {
	display: none;
}

.cg-card.is-silenced .cg-card-silenced {
	display: block;
	flex-shrink: 0;
	font-size: 9px;
	line-height: 1.4;
	text-align: center;
	white-space: nowrap;
	padding: 1px 4px 3px;
	color: var(--cg-red);
	letter-spacing: .5px;
}

#cg-lightbox .cg-card.is-silenced .cg-card-silenced {
	font-size: 15px;
	line-height: 1.6;
	padding: 4px 12px 12px;
}

/* ===== 柵欄實體卡 ===== */
.cg-card.is-fence .cg-card-face {
	background: repeating-linear-gradient(45deg, #2a2318 0 10px, #1c170e 10px 20px);
}

/* 柵欄卡面改用 ascii(2026-07-25,取代原本的 🚧 emoji):走與生物卡同一條 .mob-ascii +
   fitArt 縮放路徑,只把基準字級調大——柵欄圖案只有 17 字寬,沿用生物卡的 6px 會小到看不清,
   10px 讓它在手牌/場上不必縮放就填滿卡面,放大圖仍由 fitArt 自動upscale。 */
.cg-fence-art .mob-ascii {
	font-size: 10px;
	color: var(--cg-gold);
}

.cg-panel-box {
	width: 300px;
	background: linear-gradient(160deg, #26221c, #181410);
	border: 2px solid var(--cg-gold);
	border-radius: 12px;
	padding: 18px;
	text-align: center;
}

.cg-panel-box h3 {
	margin: 0 0 8px;
	color: var(--cg-gold);
}

.cg-panel-box p {
	font-size: 13px;
	color: var(--cg-text-dim);
	line-height: 1.6;
	margin: 0 0 14px;
}

.cg-panel-btn {
	background: var(--cg-gold);
	color: #201a0d;
	border: none;
	border-radius: 8px;
	padding: 8px 20px;
	font-weight: bold;
	cursor: pointer;
	font-size: 14px;
}

.cg-panel-btn:disabled {
	background: #555;
	color: #999;
	cursor: default;
}

.cg-panel-close {
	margin-top: 10px;
	background: none;
	border: none;
	color: var(--cg-text-dim);
	cursor: pointer;
	font-size: 12px;
	text-decoration: underline;
}

/* 側欄一律不顯示(2026-07-14 從「僅窄螢幕」改成桌機也一律套用)——側欄佔掉的寬度讓給
中央戰場區,技能圖示+輪到誰標籤+回合數統一併入對方/我方手牌那一排(.cg-mobile-strip),
不分桌機/手機都用同一套版面語言,不需要側欄這個桌機專屬的容器。 */
.cg-sidebar {
	display: none;
}

.cg-mobile-strip {
	display: flex;
}

/* ===== 窄螢幕才需要的尺寸縮小(先求核心版面可用,細節之後再打磨)===== */

/* 這裡只調整「螢幕太窄塞不下桌機尺寸」的縮放,跟上面「側欄一律隱藏」是兩件事——
側欄拿掉之後桌機依然有大量寬度可用,卡片/手牌不需要跟著縮小。 */
@media (max-width:880px) {
	.cg-skill-icon {
		width: 42px;
		height: 42px;
		font-size: 18px;
	}

	.cg-hand-card {
		width: 92px;
		height: 138px;
	}

	.cg-hand-card .cg-card-art {
		height: 56px;
	}

	#cg-my-hand {
		height: 150px;
		gap: 6px;
	}

	/* 疊放卡維持跟手牌一樣的直式長寬比,只是縮小尺寸,不拉伸變形——
	   :not(.cg-hand-card) 是必要的:手牌卡同時帶 .cg-card + .cg-hand-card 兩個 class,
	   若這裡不排除,cascade 順序會讓這條規則的 76px/-38px margin 蓋掉上面 92px 的手牌設定
	   (等特異度下,寫在後面的規則獲勝),導致手牌卡片被錯誤縮小、疊出不該有的重疊
	   (曾經發生的 bug,教訓寫在這——手牌是否要疊放交給 layoutHandRow 判斷,不該被這裡的
	   margin-left 意外強制疊在一起)。 */
	.cg-card:not(.cg-hand-card) {
		width: 76px;
		height: 112px;
		margin-left: -38px;
	}

	/* 戰場卡的 art 高度也要跟著縮——上面只縮了卡片外框(142→112),art 沿用桌機的 62px,
	   佔比從 43.7% 暴增到 55%,說明區只剩 23px,多能力卡的 chips 被整段無聲裁掉(使用者
	   真機截圖抓到:哥利亞綿羊的能力顯示不出來;探針實測 desc scrollHeight 52 > client 23)。
	   縮到 38px(~34%)+ chips 字級/行距/padding 同步收緊,說明區拿回 ~47px,3~4 行都放得下。 */
	.cg-card:not(.cg-hand-card) .cg-card-art {
		height: 38px;
	}

	.cg-card:not(.cg-hand-card) .cg-card-desc {
		font-size: 9px;
		line-height: 1.35;
		padding: 2px 4px;
	}

	/* (原「compact 說明允許捲動」兜底已於 2026-07-17 移到基底規則全域生效,此處不再重複) */
	.cg-oppcard-peek, .cg-oppcard-peek-inner {
		width: 92px;
	}

	.cg-oppcard-peek {
		height: 70px;
	}

	.cg-oppcard-peek-inner {
		height: 138px;
	}

	/* 這裡把卡片縮到跟 #cg-my-hand 一樣的 92px,但漏改 gap——base 規則的 gap:10px 沒被覆寫,
	   跟 #cg-my-hand 這裡的 6px 對不上(使用者真機截圖抓到:兩排間距明顯不一致,像兩套規則)。
	   4 張 92px 卡 + 3 個 gap 在窄螢幕上本來就頂著容器寬度,10px 比 6px 多出的 12px 總寬度
	   剛好是右邊第 4 張卡被裁掉一截的差距,兩個問題同一個根因,補上跟手牌同值就一併解決。 */
	#cg-opp-hand {
		height: 74px;
		gap: 6px;
	}

	/* 窄欄(~123px)塞不下「地形名+pips+加總」單行(實測 head 內容需 138~151px,溢出的
	   加總數字會被裁掉)——欄頭改兩行:第一行 地形名/加總 兩端對齊,pips 換行置中。 */
	.cg-col-head {
		flex-wrap: wrap;
		font-size: 11px;
		padding: 3px 6px;
		gap: 2px 4px;
	}

	.cg-slot-pips {
		display: inline-flex;   /* 桌面隱藏(平鋪空格框已承載同樣資訊),手機疊放模式才是唯一載體 */
		order: 3;
		width: 100%;
		justify-content: center;
	}

	.cg-pip {
		width: 7px;
		height: 7px;
	}

}
