/* 天下大勢：手機優先的單欄版面。紙與墨的配色，朱紅當主色。
   原則：狀態列與分頁列永遠在，中間只放「這一頁要做的事」；會長大的東西一律限高可捲。 */

:root {
  --paper: #f4ede0;
  --card: #fbf7ef;
  --card-2: #efe6d5;
  --ink: #2a241d;
  --ink-2: #6b6155;
  --line: #ddd1bc;
  --accent: #a8322a;
  --accent-ink: #fff;
  --accent-soft: rgba(168, 50, 42, 0.10);
  --gold: #b7862b;
  --ok: #2f7d4f;
  --bad: #b23a2b;
  --stam: #c08a1e;
  --hp: #b23a2b;
  /* 輪盤：墨色圓盤與四種礦物顏料（朱、石青、石綠、赭），四格依序是剛／快／柔／慢，也是江湖頁的探索／遊歷／交友／打坐 */
  --disk: #2a241d; --disk-2: #3a3128;
  --gang: #a8322a; --kuai: #2f5d8a; --rou: #3f7d5c; --man: #9a6a2a;
  --shadow: 0 1px 2px rgba(60, 40, 20, 0.08), 0 2px 8px rgba(60, 40, 20, 0.06);
  --radius: 14px;
  --serif: "Noto Serif TC", "Songti TC", "PMingLiU", "MingLiU", serif;
  --sans: -apple-system, BlinkMacSystemFont, "PingFang TC", "Noto Sans TC", "Microsoft JhengHei", sans-serif;
  --top: env(safe-area-inset-top, 0px);
  --bottom: env(safe-area-inset-bottom, 0px);
  /* journal.css（引擎產生的江湖紀錄）用的是 Gradio 的變數名，這裡接上 */
  --border-color-primary: var(--line);
  --background-fill-secondary: var(--card);
  color-scheme: light;
}
@media (prefers-color-scheme: dark) {
  :root {
    --paper: #16130f;
    --card: #211c17;
    --card-2: #2b251e;
    --ink: #ece3d3;
    --ink-2: #a89b88;
    --line: #3a3229;
    --accent: #d2574a;
    --accent-soft: rgba(210, 87, 74, 0.16);
    --gold: #d6a548;
    --ok: #5cb67f;
    --bad: #e06a5c;
    --stam: #d6a548;
    --hp: #e06a5c;
    --disk: #0d0b09; --disk-2: #1d1914;
    --gang: #c2473c; --kuai: #4a7cae; --rou: #55a079; --man: #b98634;
    --shadow: none;
    color-scheme: dark;
  }
  .seg button.on { background: #3d342a; }
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0; background: var(--paper); color: var(--ink);
  font: 15px/1.65 var(--sans);
  -webkit-tap-highlight-color: transparent;
}
button, input, select { font: inherit; color: inherit; }
input, select { font-size: 16px; } /* 低於 16px 的話 iOS Safari 一聚焦就放大整頁 */
h1, h2, h3, h4 { font-family: var(--serif); line-height: 1.35; margin: 0.4em 0; }
p { margin: 0.45em 0; }
a { color: var(--accent); }
code { font-size: 12px; letter-spacing: -1px; color: var(--accent); background: none; }
hr { border: 0; border-top: 1px solid var(--line); margin: 12px 0; }
table { border-collapse: collapse; font-size: 14px; }
td, th { border-bottom: 1px solid var(--line); padding: 4px 8px; text-align: left; }
ul { padding-left: 1.3em; margin: 0.4em 0; }

.boot { height: 100vh; display: grid; place-items: center; font: 600 28px var(--serif); letter-spacing: 0.3em; color: var(--ink-2); }

/* ── 版面骨架 ── */
.shell { max-width: 640px; margin: 0 auto; min-height: 100vh; }
.page { padding: 12px 16px calc(84px + var(--bottom)); }

/* 頂上的狀態列：名號、所在、四個數字 */
.top {
  position: sticky; top: 0; z-index: 20;
  background: color-mix(in srgb, var(--paper) 92%, transparent);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
  padding: calc(8px + var(--top)) 16px 8px;
}
.top-row { display: flex; align-items: center; gap: 8px; }
.who { flex: 1; min-width: 0; cursor: pointer; }
.who-name { display: flex; align-items: baseline; gap: 4px; font: 600 17px var(--serif); }
.who-name > span { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.who-name small { font: 500 12px var(--sans); color: var(--ink-2); margin-left: 6px; }
/* 名號長、又有門派・陣營・頭銜時，收著會被省略號吃掉頭銜；點名號展開就整行看得到（計畫 T5）。展開之後（FB-071）各有各的位置：
   第一行只有名號與 ▴，頭銜在第二行（.who-title），「可配 N 點」在＋鈕上面（.pts-label）。名號欄寬 375 是 295、360 是 280
   （視窗寬 − 左右各 16 − 設定鈕 40 − 縫 8）；16 字的名號 17px 時要 272＋縫 4＋▴ 11 ≈ 287，360 寬放不下，所以展開時縮到 16px
   （256＋15 ≈ 271，兩種寬度都一行放得下）；再窄的螢幕才折行——折行也比用「…」藏掉名號的後半好 */
.who[aria-expanded="true"] .who-name { font-size: 16px; }
.who[aria-expanded="true"] .who-name > span { flex: 1; white-space: normal; overflow-wrap: anywhere; }
/* 展開的頭銜：門派、陣營、頭銜、匿名、第 N 級各是一個 .who-seg，不折行；只在段與段之間換行，「地方豪強」不會被從中間折斷。
   不能叫 .seg：那是全站的分段選單（display: flex、下方留白），套到頭銜上每一段都會變成整列 */
.who-title { margin-top: 1px; font: 500 12px/1.5 var(--sans); color: var(--ink-2); }
.who-title .who-seg { white-space: nowrap; }
.who-ranger { margin-top: 2px; font: 500 12px/1.5 var(--sans); color: var(--ink-2); }
.who-ranger small { display: block; font-size: 11.5px; color: var(--ink-2); opacity: 0.85; }
/* 點名號展開更多數值的提示（畫面流程 S1），名號再長也不會被省略號吃掉 */
/* 升級的屬性點：自己一個不縮的元素（flex: none）、放在會「…」的名號 <span> 外面——長長的「門派・陣營」只擠名號，擠不掉這一句 */
.who-name .pts { flex: none; font: 600 12px var(--sans); color: var(--gold); }
.who-name .more-ico { flex: none; font: 400 11px var(--sans); color: var(--ink-2); }
.where { font-size: 12px; color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.where small { font-size: 10.5px; }
/* 狀態列底下的小字行：下一件、閉關剩幾小時、在路上那一句（比較長，手機上可以折成兩行，不要把倒數省略掉）。
   會折行的行不能留著 .where 的 overflow／省略號：行尾的全形括號尾端會被瀏覽器收掉半格，剛好塞滿一行時
   scrollWidth 仍比寬度多幾 px，省略號就把最後一個字蓋掉（FB-062） */
.where.sub { white-space: normal; font-size: 11px; line-height: 1.45; overflow: visible; text-overflow: clip; }
.icon-btn {
  flex: none; width: 40px; height: 40px; border-radius: 12px; border: 1px solid var(--line);
  background: var(--card); display: grid; place-items: center; cursor: pointer; font-size: 18px;
}
/* 氣血條寬一點：有內傷時左邊寫「氣血 N/M」、右邊寫「傷 N」，兩段之間要留得出空 */
.vitals { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr) auto auto; gap: 6px 10px; align-items: center; margin-top: 6px; }
.bar { position: relative; height: 20px; border-radius: 10px; background: var(--card-2); overflow: hidden; }
.bar > i { position: absolute; inset: 0 auto 0 0; border-radius: 10px; transition: width 0.4s ease; }
.bar.stam > i { background: var(--stam); }
.bar.hp > i { background: var(--hp); }
/* 內傷那一截（FB-049）：用氣血的紅畫淡斜紋、左邊一道細線，看得出是氣血條上被佔掉的一段，不像一個小破圖 */
.bar.hp > b {
  position: absolute; inset: 0 0 0 auto; border-left: 1.5px solid var(--hp);
  background: repeating-linear-gradient(45deg, color-mix(in srgb, var(--hp) 40%, transparent) 0 2px, transparent 2px 5px);
}
.bar > span { position: relative; display: block; font-size: 11px; line-height: 20px; padding: 0 8px; font-weight: 600; color: var(--ink); white-space: nowrap; }
/* 氣血條上的字壓在紅條、底色與斜紋上都要讀得清楚：描一圈底色。「傷 N」靠右，落在斜紋那一頭 */
.bar.hp > span { text-shadow: 0 0 2px var(--card), 0 0 2px var(--card); }
.bar.hp > span.inj { position: absolute; top: 0; right: 0; padding: 0 7px; }
/* 回體丹（內測贈送）：體力條右端一顆小鈕「丹 N」，跟氣血條的「傷 N」同一個位置；整條高度內、不擠格線 */
.bar.stam > .pill-btn {
  position: absolute; top: 2px; right: 2px; height: 16px; padding: 0 5px; border-radius: 8px;
  border: 1px solid var(--stam); background: var(--card); color: var(--ink); font-size: 10px; line-height: 14px;
  font-weight: 700; cursor: pointer;
}
.bar.stam > .pill-btn:disabled { opacity: 0.45; cursor: default; }
/* 點體力條攤開體力怎麼回（explain-1）：整條是按鈕（丹的鈕自己另外一顆，點它照樣是服丹／補滿）；說明排在數字那一列底下，小字一行一句 */
.bar.stam[data-act="stam-help"] { cursor: pointer; }
.bar.stam[data-act="stam-help"]:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.more-stats.stam-help { line-height: 1.5; }
.more-stats.stam-help p { margin: 0; }
/* 有丹時體力條多擠一顆鈕：把寬度從氣血條那邊借一點，「體力 132/150」才不會被鈕蓋住 */
.vitals:has(.pill-btn) { grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr) auto auto; }
.num { font-size: 13px; font-weight: 600; white-space: nowrap; }
.num em { font-style: normal; font-weight: 400; color: var(--ink-2); font-size: 11px; margin-right: 2px; }
.more-stats { font-size: 12px; color: var(--ink-2); margin-top: 6px; line-height: 1.7; }
.more-stats .hint { color: var(--gold); }
.more-stats .row { margin-top: 6px; } /* 升級的屬性點：每項屬性一顆「＋臂力」（狀態列展開後才出現） */
/* 「可配 N 點」（FB-071）：展開後放在＋鈕上面當那一排的標題，樣子同收起來時名號那一行的那句（金色粗體 12px） */
.more-stats .pts-label { margin-top: 6px; line-height: 1.4; }
.more-stats .pts-label .pts { font: 600 12px var(--sans); color: var(--gold); }
/* 五顆＋鈕一排放得下（FB-071）：排寬 375 是 343、360 是 328（視窗寬 − 左右各 16），五顆加四個 4px 的縫，每顆 65.4／62.4px；
   扣掉 1px 邊框與 2px 左右內距，裡面各剩 59.4／56.4px，標籤「＋博聞」是三個全形字 14px ≈ 42px，放得下、不折行。
   高度仍是 .btn.small 的 38px。只改這一排（.alloc），不動全站的 .btn */
.more-stats .alloc { gap: 4px; margin-top: 4px; }
.more-stats .alloc .btn { min-width: 0; padding: 6px 2px; white-space: nowrap; }
/* ＋鈕底下那一行（五項各管什麼）：比面板再小一號；一項一個 inline-block，整項一起換行，太長時在項裡面折，不撐寬 */
.more-stats .stat-uses { margin-top: 4px; font-size: 11px; line-height: 1.5; }
.more-stats .stat-uses span { display: inline-block; max-width: 100%; margin-right: 0.8em; }
/* 在路上的 💡 提示收成一行（FB-060）：是按鈕，點了展開全文；樣子跟平常的提示一樣 */
.more-stats .road-hint { display: block; width: 100%; margin: 0; padding: 0; border: 0; background: none; font: inherit; line-height: inherit; text-align: left; cursor: pointer; }
.more-stats .road-hint.clamp { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.flash { animation: flash 0.9s ease-out; }
@keyframes flash { from { background: var(--accent-soft); } to { background: transparent; } }

/* 底部分頁列 */
.tabs {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 20;
  background: color-mix(in srgb, var(--card) 94%, transparent);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  border-top: 1px solid var(--line);
  padding-bottom: var(--bottom);
}
.tabs-inner { max-width: 640px; margin: 0 auto; display: grid; grid-template-columns: repeat(5, 1fr); }
.tab {
  border: 0; background: none; padding: 7px 0 6px; cursor: pointer; color: var(--ink-2);
  display: flex; flex-direction: column; align-items: center; gap: 1px; font-size: 11px; position: relative;
}
.tab .ico { font: 600 19px/1.2 var(--serif); }
.tab.on { color: var(--accent); }
.tab.on::before { content: ""; position: absolute; top: 0; left: 30%; right: 30%; height: 3px; border-radius: 0 0 3px 3px; background: var(--accent); }
.tab .dot { position: absolute; top: 6px; right: calc(50% - 18px); width: 8px; height: 8px; border-radius: 50%; background: var(--accent); }

/* ── 共用元件 ── */
.card { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: 12px 14px; margin: 0 0 12px; box-shadow: var(--shadow); }
.card > :first-child { margin-top: 0; }
.card > :last-child { margin-bottom: 0; }
.label { font-size: 12px; color: var(--ink-2); letter-spacing: 0.08em; margin: 16px 2px 6px; display: flex; align-items: center; gap: 8px; }
.label::after { content: ""; flex: 1; border-top: 1px solid var(--line); }
.muted { color: var(--ink-2); font-size: 13px; }

.btn {
  display: flex; align-items: center; justify-content: center; gap: 6px; width: 100%;
  min-height: 48px; padding: 10px 14px; border-radius: 12px; cursor: pointer;
  border: 1px solid var(--line); background: var(--card); color: var(--ink);
  font-size: 15px; text-align: center; line-height: 1.35;
  transition: transform 0.08s ease, background 0.15s ease;
}
.btn:active:not(:disabled) { transform: scale(0.98); }
.btn.primary { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); font-weight: 600; }
.btn.ghost { background: transparent; }
.btn.small { min-height: 38px; padding: 6px 12px; font-size: 14px; width: auto; }
.btn:disabled { opacity: 0.45; cursor: default; }
.btn.busy { opacity: 1; position: relative; overflow: hidden; }
.btn.busy::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,0.35), transparent);
  background-size: 50% 100%; background-repeat: no-repeat; animation: sweep 1.1s linear infinite;
}
@keyframes sweep { from { background-position: -60% 0; } to { background-position: 160% 0; } }
/* 送出中（app.js 的 busy）：按下去的那一顆不變灰、掃光，等回應的時候不能再按 */
.sending { cursor: progress; }
.btn.sending:disabled { opacity: 1; position: relative; overflow: hidden; }
.btn.sending::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,0.35), transparent);
  background-size: 50% 100%; background-repeat: no-repeat; animation: sweep 1.1s linear infinite;
}
/* 等了一下還沒回來：畫面底下（分頁列上面、提示泡泡的位置）浮一行「已送出，等候回應…」，前面一顆墨點在暈開 */
.sending-line {
  position: fixed; left: 50%; bottom: calc(84px + var(--bottom)); transform: translateX(-50%); z-index: 55;
  display: flex; align-items: center; gap: 8px; max-width: min(90vw, 520px); white-space: nowrap;
  background: color-mix(in srgb, var(--ink) 88%, transparent); color: var(--paper);
  padding: 8px 14px; border-radius: 999px; font-size: 13px; pointer-events: none;
  animation: sending-in 0.2s ease-out;
}
.sending-line i { width: 9px; height: 9px; border-radius: 50%; background: var(--gold, #c9a45c); flex: none; animation: ink-spread 1.2s ease-in-out infinite; }
@keyframes sending-in { from { opacity: 0; transform: translate(-50%, 8px); } to { opacity: 1; transform: translate(-50%, 0); } }
@keyframes ink-spread { 0% { transform: scale(0.6); opacity: 1; } 70% { transform: scale(1.5); opacity: 0.35; } 100% { transform: scale(0.6); opacity: 1; } }
.row { display: flex; gap: 8px; }
.row > * { flex: 1; }
.stack > * + * { margin-top: 8px; }

.seg { display: flex; background: var(--card-2); border-radius: 12px; padding: 3px; gap: 3px; margin: 0 0 12px; overflow-x: auto; scrollbar-width: none; }
.seg::-webkit-scrollbar { display: none; }
.seg button { flex: 1 0 auto; border: 0; background: none; padding: 8px 12px; border-radius: 9px; cursor: pointer; font-size: 14px; color: var(--ink-2); white-space: nowrap; }
.seg button.on { background: var(--card); color: var(--ink); font-weight: 600; box-shadow: var(--shadow); }

.field { display: block; margin: 0 0 10px; }
.field > span { display: block; font-size: 12px; color: var(--ink-2); margin: 0 2px 4px; }
.input { width: 100%; min-height: 46px; padding: 10px 12px; border-radius: 12px; border: 1px solid var(--line); background: var(--card); }
.input:focus { outline: 2px solid var(--accent); outline-offset: -1px; }
/* 表單的結果訊息（QA L3）：留在表單裡，錯誤醒目、成功用一般文字色；沒有訊息時不佔位 */
.form-msg { margin: 0 2px 10px; font-size: 14px; font-weight: 600; color: var(--bad); }
.form-msg.ok { color: var(--ink); font-weight: 400; }
.form-msg:empty { display: none; }
#reset-form .form-msg { margin: 8px 2px 0; }

.list { border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; background: var(--card); margin-bottom: 12px; }
.list button { display: flex; width: 100%; align-items: center; gap: 8px; text-align: left; border: 0; border-bottom: 1px solid var(--line); background: none; padding: 12px 14px; cursor: pointer; min-height: 48px; }
.list button:last-child { border-bottom: 0; }
.list button.on { background: var(--accent-soft); }
.list button::after { content: "›"; margin-left: auto; color: var(--ink-2); }

/* 修練頁、煉製頁的「屬性有什麼用」（W2）：收著只多一行小字，不用框，免得第一屏多出一整張卡 */
details.attr-note { font-size: 13px; color: var(--ink-2); margin: 4px 0 12px; }
.card > details.attr-note { margin-bottom: 0; }
details.attr-note > summary { list-style: none; cursor: pointer; padding: 2px 0; line-height: 1.5; }
details.attr-note > summary::-webkit-details-marker { display: none; }
details.attr-note > summary::after { content: " ▾"; }
details.attr-note:not([open]) > summary::after { content: " ▸"; }
details.attr-note > p { margin: 2px 0 0; }
details.fold { margin-bottom: 12px; }
details.fold > summary { list-style: none; cursor: pointer; padding: 10px 14px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--card); display: flex; align-items: center; gap: 8px; font-weight: 600; }
details.fold > summary::-webkit-details-marker { display: none; }
details.fold > summary::after { content: "▾"; margin-left: auto; color: var(--ink-2); transition: transform 0.2s; }
details.fold:not([open]) > summary::after { transform: rotate(-90deg); }
details.fold[open] > summary { border-radius: var(--radius) var(--radius) 0 0; }
details.fold > .fold-body { border: 1px solid var(--line); border-top: 0; border-radius: 0 0 var(--radius) var(--radius); padding: 10px 14px; background: var(--card); }

.msg { border-left: 3px solid var(--accent); background: var(--accent-soft); border-radius: 8px; padding: 8px 12px; margin-bottom: 12px; font-size: 14px; animation: rise 0.25s ease-out; }
.msg:empty { display: none; }
.msg.still { animation: none; } /* 輪詢重畫時訊息沒變，不重播浮現（app.js 的 redrawPage） */
@keyframes rise { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

/* ── 江湖頁 ── */
/* 「剛剛」（A4）：收著時敘事只露出開頭三行左右、最後一行淡出，右下角「展開全文」；展開後整則攤開，不在卡片裡捲。
   數值變化（.tx-chgs）被 app.js 搬到敘事外面（.now-text 之後），收著也看得到。卡片的框與底色畫在 .now 上，
   裡面的 .tx-now 不再自己畫一層。放得下的（.fits）沒有淡出也沒有按鈕（app.js 的 pageJianghu、afterPage） */
.now {
  margin-bottom: 12px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--card);
  padding: 10px 14px; line-height: 1.6; animation: tx-now-rise 0.28s ease-out;
}
.now .tx-now { border: 0; border-radius: 0; background: none; padding: 0; animation: none; }
.now-text { position: relative; }
/* 在路上：剛按完沿途打聽之類，「剛剛」的字比平常多，只露三行（其餘點「展開全文」），最底下的「走法」才不會被擠到分頁列底下（FB-060） */
.now.clamp.road .tx-now { max-height: 4.8em; }
.now.clamp .tx-now {
  max-height: 8em; overflow: hidden;
  -webkit-mask-image: linear-gradient(#000 calc(100% - 1.6em), transparent); mask-image: linear-gradient(#000 calc(100% - 1.6em), transparent);
}
.now-more { display: block; margin: 0 0 0 auto; }
.now.clamp .now-more { position: absolute; right: 0; bottom: -6px; padding-left: 1.6em; background: linear-gradient(90deg, transparent, var(--card) 1.4em); }
.now.fits .now-more { display: none; }
/* 戰鬥卡片壓縮（PM 2026-10-05）：打完一場要在第一屏直接按下一顆行動，不必捲動。只動「剛剛」那張戰鬥卡片
   （.battle-card 只用在它身上，別張卡片、狀態列與行動列不動）：內距、段距、標題與行高收緊，字級不縮
   （內文 15px、過程與補充 14px，都不小於 .order-text 的 13px；標題 16px，比場景標題的 18px 小一號）。
   行高第二輪（PM 2026-10-05）：內文 1.55→1.45、過程／補充 1.5→1.45；標題 1.3 是單行，其餘都不低於 1.4，字不擠 */
.battle-card { border-color: var(--accent); padding: 9px 12px; line-height: 1.45; }
.battle-card h3 { margin: 0 0 1px; font-size: 16px; line-height: 1.3; }
.battle-card p { margin: 3px 0; }
.battle-card .tx-extra { margin: 3px 0 0; padding: 0 10px; line-height: 1.45; }
/* 戰鬥卡片底下聽來的那一句「你聽到一件事：…」（FB-074；伺服器標 tx-hearsay，app.js 的 decorateHearsay 讓它能點）：
   常有兩三行高、多撐 46～66px，收成一行、放不下加「…」，點了看全文。點擊範圍上下各多 7px、用負的 margin 吃回去，不多撐那一行。
   只寫上下的 padding，不用簡寫：Reduce Motion 時 journal 的 .tx-new 靠 padding-left 8px 讓字離左邊那條金條遠一點，
   簡寫（權重比它高）會把左邊歸零、條就壓在第一個字上 */
.battle-card .tx-extra .tx-hearsay { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: pointer; padding-top: 7px; padding-bottom: 7px; margin: -5px 0; }
.battle-card .tx-extra .tx-hearsay.open { white-space: normal; overflow: visible; text-overflow: clip; }
/* ── 第一屏放不下時一步一步收（FB-107，app.js 的 fitFirstScreen / FIT_STEPS）：每一步一個 class，放得下就停在那一步 ── */
/* 1. 間距：頁頂、卡與卡之間 12→8，「剛剛」、戰鬥卡片、場景、對話框的內距收一點；一個字都不少 */
.page.fit-space { padding-top: 8px; }
.page.fit-space > .peek, .page.fit-space > .now, .page.fit-space > .card, .page.fit-space > .guide-line { margin-bottom: 8px; }
.page.fit-space > .now { padding-top: 6px; padding-bottom: 6px; }
.battle-card.fit-space { padding-top: 6px; padding-bottom: 6px; } /* 戰鬥卡片的規則一律寫在 .battle-card 底下（tests/test_server.py） */
.page.fit-space > .card.scene { padding-top: 8px; padding-bottom: 8px; }
.page.fit-space > .card.guide { padding-top: 6px; padding-bottom: 6px; }
/* 玩家互動那幾塊（「此地還有」、結伴、邀請）是另一條線的，這裡不動它們 */
/* 2. 師父的框收緊（框裡的話一個字都不切）：「知道了」照樣 38px 高、點得到；上 −6px 伸進框的內距（第 1 步之後是 6px，不出框），
   下 −2px 剛好停在話的第一行上面（.guide-text 的 margin-top 2px，不壓字，審查 M1）——標題那一行 38→30px；話的行高 1.6→1.5 */
.card.guide.fit-box .guide-head .btn { margin-top: -6px; margin-bottom: -2px; }
.card.guide.fit-box .guide-text { line-height: 1.5; }
/* 3. 💡 收成一行（在路上那一種，FB-060：點了看全文），app.js 的 hintHtml 照 S.hintTight 畫 */
/* 4. 戰鬥卡片底下的補充收成一行、放不下加「…」，點了看全文（同聽來的那一句，上下多 7px 的點擊範圍用負的 margin 吃回去） */
.battle-card .tx-extra .tx-line.tx-tight { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: pointer; padding-top: 7px; padding-bottom: 7px; margin: -5px 0; }
.battle-card .tx-extra .tx-line.tx-tight.open { white-space: normal; overflow: visible; text-overflow: clip; }
/* 5. 第一回合也收進「展開過程」（按了 .open 照舊一回合一回合攤開）；「得失」那一段不在這裡面，照舊看得到 */
.battle-card ul.rounds.fit-fold:not(.open) { display: none; }
.battle-card p.rounds-tale.fit-fold:not(.open) { display: none; }
/* 6. 「剛剛」收著時只露三行（同在路上，FB-060） */
.now.clamp.fit-short .tx-now { max-height: 4.8em; }
/* 7、8. 決戰時接在戰場底下的所在地（fit-own）、集結那一句（fit-muster）：每段一行、放不下加「…」，點了攤開（app.js 的 fitClip、ownOpen） */
.card.scene p.fit-clip { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: pointer; }
/* FB-120：只能觀戰的人，開打中的戰場收成一行（名字那一行的字體，app.js 的 battleScene）；放不下加「…」，點了攤開。
   攤開之後戰場底下一顆「收起戰場」，靠右、小字，不多撐一行的高度以外的空間 */
.card.scene p.battle-fold { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: pointer; }
.card.scene p.battle-shut { margin: 0; text-align: right; font-size: 13px; line-height: 1.5; }
/* 9. 一組選項（事件、有所感的做法）：縫 8→6、鈕高 48→44（觸控照樣按得到） */
.page > .options.fit-tight { gap: 6px; }
.page > .options.fit-tight > .btn { min-height: 44px; padding-top: 8px; padding-bottom: 8px; }
/* 「看完整戰報 ›」在「過程」那一行的中間（app.js 的 roundsFold）：不撐高那一行，點擊範圍上下各多 8px（約 38px 高）。
   沒有「過程」那一行的卡片（全服決戰、舊戰報）才接在卡片最後一段的句尾（withReportLink）：行內、不撐高那一行；
   放不下時整顆換到下一行（inline-block） */
.battle-card .report-link { display: inline-block; margin: -8px 0 -8px 6px; padding: 8px 4px; vertical-align: baseline; white-space: nowrap; }
.battle-card .rounds-head .report-link { margin: -8px 0; }
/* 戰鬥卡片的「過程」（計畫三 Task 1、G6 暫定）：「剛剛」那張只露第一回合，第一屏留給剛剛、場景與整排行動（企劃者 2026-10-04）；
   「展開過程」攤開其餘回合，一回合晚一點浮現，代替「當場一回合一回合播」（減少動態時全站的動畫都關掉，見 prefers-reduced-motion）。
   「看完整戰報 ›」在這一行的中間、「展開過程」在右邊，不多佔一行（寬度夠：375px 下三樣加起來約 215px，這一行有約 315px）。
   戰報頁（.report-detail）不收，整段列出（app.js 的 roundsFold） */
.battle-card .rounds-head { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; margin-bottom: 0; }
.battle-card .rounds-more { flex: none; padding: 8px 2px; margin: -8px 0; white-space: nowrap; }
.battle-card ul.rounds { margin: 1px 0 5px; padding-left: 1.2em; font-size: 14px; line-height: 1.45; }
/* 收著時露出第一個「不是功效句」的 li（功效的演出句以〔開頭，app.js 的 foldTraitItems 標成 .trait；沒有功效句的卡片就是第一個 li，跟以前一樣）：
   功效句整個藏起來，第一回合照舊帶頭（Task 4 審查 I-1）。展開（.open）與戰報頁照引擎寫的順序全部列出 */
.battle-card ul.rounds:not(.open) > li.trait { display: none; }
.battle-card ul.rounds:not(.open) > li:not(.trait) ~ li:not(.trait) { display: none; }
/* 收著的第一回合最多兩行（PM 2026-10-05）：app.js 的 fitFirstRound 量過、放不進兩行又拼得出數字行時，整句（.r-full）省略、
   換成只有數字的那一行（.r-short，「第1回合　你氣血 -13，對手氣勢 -10……」）；展開時一律是整句 */
.battle-card ul.rounds .r-short { display: none; }
.battle-card ul.rounds.tight:not(.open) .r-full { display: none; }
.battle-card ul.rounds.tight:not(.open) .r-short { display: inline; }
.battle-card ul.rounds > li { animation: tx-round-in 0.3s ease-out both; }
.battle-card ul.rounds > li:nth-child(2) { animation-delay: 0.25s; }
.battle-card ul.rounds > li:nth-child(3) { animation-delay: 0.5s; }
.battle-card ul.rounds > li:nth-child(4) { animation-delay: 0.75s; }
.battle-card ul.rounds > li:nth-child(5) { animation-delay: 1s; }
/* 功效的句子加進去之後過程可以有十幾行（前 3＋回合 5＋後 8）：每一個位置都有延遲、一路遞增，後面的一定比前面的晚浮現
   （延遲只寫到第 5 個時，第 6 個以後會比第 2～5 個先出來）；第 13 個以後一起在最後。減少動態時整站的動畫都關掉（prefers-reduced-motion） */
.battle-card ul.rounds > li:nth-child(6) { animation-delay: 1.25s; }
.battle-card ul.rounds > li:nth-child(7) { animation-delay: 1.5s; }
.battle-card ul.rounds > li:nth-child(8) { animation-delay: 1.75s; }
.battle-card ul.rounds > li:nth-child(9) { animation-delay: 2s; }
.battle-card ul.rounds > li:nth-child(10) { animation-delay: 2.25s; }
.battle-card ul.rounds > li:nth-child(11) { animation-delay: 2.5s; }
.battle-card ul.rounds > li:nth-child(12) { animation-delay: 2.75s; }
.battle-card ul.rounds > li:nth-child(n+13) { animation-delay: 3s; }
/* 收著時看得到的只有第一個「不是功效句」的 li（上面藏起來的功效句佔著 nth-child 的位置，第一回合因此會晚 0.25～0.75 秒才浮現，
   最終審查 M2）：收著時它們的延遲都是 0（權重比上面的 nth-child 高）；展開（.open）之後這條不管，照位置遞增 */
.battle-card ul.rounds:not(.open) > li:not(.trait) { animation-delay: 0s; }
/* 大場面模型寫的過程是一段話（最多 200 字、手機上約十行）：收著只露前兩行，「展開過程」攤開（PM 2026-10-05，計畫三 Task 2 審查修正 2） */
.battle-card p.rounds-tale { margin: 1px 0 5px; font-size: 14px; line-height: 1.45; }
.battle-card p.rounds-tale:not(.open) { display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.battle-card p.rounds-tale:not(.open) .trait { display: none; } /* 功效的句子收著時藏起來，兩行的截斷看到的是模型的話（app.js 的 foldTraitText） */
@keyframes tx-round-in { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
/* 本週江湖大事（第一季，計畫 T2）：江湖頁最上面那一排小標「大事」點開的面板（見 .peek-panel），一則一段、新的在前 */
.bulletin-item { font-size: 14px; line-height: 1.65; }
.bulletin-item + .bulletin-item { border-top: 1px dashed var(--line); margin-top: 8px; padding-top: 8px; }
.bulletin-item p { margin: 0 0 4px; }
.bulletin-item p:last-child { margin-bottom: 0; }
.scene { font-size: 15.5px; line-height: 1.75; }
.scene > p:first-child { font: 600 16px var(--serif); margin-bottom: 2px; }
.card.scene.road { padding: 8px 12px; font-size: 14px; line-height: 1.55; cursor: pointer; }
.card.scene.road.clamp > p:not(:first-child) { display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; } /* 在路上：整段話小一號，路上的五個選項才全在第一屏（FB-055） */
.scene h2, .scene h3 { font-size: 18px; }
/* 決戰集結時還沒參戰（FB-105）：加入的鈕在戰場名字那一行的右邊（app.js 的 musterScene）。鈕是 .btn.small（38px 高，點得到），
   上下各 −8px：佔的高度只有 22px，不高過名字那一行，剛剛、場景與整排行動一個 px 都不往下推（375×812 估過，見 tests/test_fb105_muster_join.py）。
   名字與鈕中間那一小句（.muster-note，「報名在這裡 →」）佔剩下的寬度、靠右貼著鈕；放不下就省略號收尾——基準寬度 0（flex: 1 1 0），
   這一行永遠不會因為它折行。散人臨時投效的兩顆字多、放不進名字旁邊：另起一行（.wide）、兩顆並排，這一行就是實打實的 38px，
   不往上吃（不然蓋到名字）；那一小句留在名字右邊往下指 */
.scene .muster-head { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; margin-bottom: 2px; }
.scene .muster-head > p { flex: none; margin: 0; font: 600 16px var(--serif); }
.scene .muster-note { flex: 1 1 0; min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; text-align: right; font-size: 12px; line-height: 1.5; color: var(--ink-2); }
.scene .muster-join { display: flex; flex: none; flex-wrap: wrap; gap: 6px; margin: 0; }
.scene .muster-join .btn { width: auto; margin: -8px 0; }
.scene .muster-join.wide { flex-basis: 100%; }
.scene .muster-join.wide .btn { flex: 1 1 0; min-width: 0; margin: 0; padding: 6px 8px; justify-content: center; }
/* 決戰：對面上一回合的出招比例與自己的結果（引擎寫成一段 markdown 引用「> 」，伺服器轉成 blockquote）：小字、淡色、行距緊、
   沒有瀏覽器預設的縮排與邊線，375px 上約 65px（含上面一段的間距；15.5px 兩段是 95px） */
.scene blockquote { margin: 2px 0; padding: 0; border: 0; font-size: 13px; line-height: 1.5; color: var(--ink-2); }
.scene blockquote p { margin: 0; }
.options { display: grid; gap: 8px; margin-bottom: 12px; }
.options .btn { justify-content: flex-start; text-align: left; }
/* 有所感的畫布（悟意境設計 0.2）：一筆畫到底；等模型取名時整塊微微晃（同煉製的爐子） */
.sense-pad { display: grid; gap: 8px; justify-items: center; padding: 10px; border: 1px solid var(--line); border-radius: 12px; background: var(--card); }
.sense-hint { font-family: var(--serif); font-size: 15px; }
.sense-canvas { width: min(256px, 100%); aspect-ratio: 1; border-radius: 10px; background: var(--card-2); touch-action: none;
  box-shadow: inset 0 0 0 1px var(--line); cursor: crosshair; }
.sense-note { min-height: 1.5em; font-size: 13px; color: var(--ink-2); text-align: center; }
.sense-acts { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; }
.glyph-mini { width: 16px; height: 16px; margin-right: 2px; vertical-align: -3px; opacity: 0.8; }
.glyph-big { float: right; width: 48px; height: 48px; margin: 0 0 4px 8px; opacity: 0.85; }
.glyph-from { font-size: 12px; color: var(--ink-2); }
.sense-pad.brewing .sense-canvas { animation: w-shake 0.42s linear infinite; }
@media (prefers-reduced-motion: reduce) { .sense-pad.brewing .sense-canvas { animation: none; opacity: 0.7; } }
.options .btn .k { flex: none; width: 24px; height: 24px; border-radius: 7px; display: grid; place-items: center; background: var(--card-2); font-size: 12px; color: var(--ink-2); }
.options .btn.go .k { background: var(--accent); color: #fff; }
/* 有所感的做法（explain-2）：伺服器給了心意才用（審查 I1 起預設不給，sensing.SHOW_KINDS）：那一格寫剛柔快慢而不是 1～4，一樣寬，鈕不變高 */
.options .btn .k.sense { font: 600 13px var(--serif); color: var(--ink); }
/* 有所感做法底下的兩行小字（explain-2）：跟行動列底下那幾行同一個樣子，排在做法後面 */
.act-notes.sense-notes { margin-top: -4px; }
/* 決戰三招的按鈕：名字在左（佔剩下的寬度），招與分數在右邊一小行不換行，十一、十二個字的名字也不會把按鈕折成兩行 */
.options .btn .b-name { flex: 1 1 auto; min-width: 0; }
.options .btn .b-move { flex: none; margin-left: auto; font-size: 12px; color: var(--ink-2); white-space: nowrap; }
/* FB-132：鐵匠鋪的長標籤照標點切成小段（app.js 的 nbHtml），每段不折行，段與段之間才換行——375px 上「下品」「沒人」「壓得住」不會被拆在兩行 */
.nb { display: inline-block; white-space: nowrap; }
.move-mode { margin-bottom: 8px; } /* 走法切換：一列、緊貼在第一個「前往」上面（排在選項之間，A4） */
.options > .move-mode { margin: 4px 0 0; }
/* 在路上：四樣小事排成 2×2，名字一行、補充小字一行（FB-055）；折返與喊停照舊一整列 */
.road-tasks { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
/* 折返與喊停併成一列（FB-060）：折返那格的字比較多（「↩ 折返 潁川郡（陽翟）」），多給一點寬、名字小一號，才不會折成兩行 */
.road-ways { grid-template-columns: 1.45fr 1fr; }
.road-ways .t-name { font-size: 15px; }
.options .btn.task { flex-direction: column; align-items: flex-start; justify-content: center; gap: 2px; padding: 8px 12px; min-height: 56px; }
.btn.task .t-name { font-weight: 600; }
.btn.task .t-note { font-size: 12px; line-height: 1.3; color: var(--ink-2); }
.move-mode > span { flex: none; align-self: center; padding: 0 4px 0 9px; font-size: 13px; color: var(--ink-2); }
.move-mode button { min-height: 48px; } /* 觸控目標跟 .btn 一樣大 */
/* 路上的三個捷徑（路上設計 3.3）：一列，手機上擠不下就換行；觸控目標同 .btn */
.road-links { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 12px; }
.road-links .btn { flex: 1 1 auto; min-height: 48px; }
.free { display: flex; gap: 8px; margin-bottom: 12px; }
.free .input { flex: 1; }
.free-note { margin: -6px 0 12px; font-size: 13px; color: var(--ink-2); }
.mini { border-radius: var(--radius); overflow: hidden; border: 1px solid var(--line); margin-bottom: 12px; cursor: pointer; position: relative; background: #e9e2cc; }
.mini svg { height: 150px !important; }
.mini::after { content: "展開輿圖 ›"; position: absolute; right: 8px; bottom: 8px; font-size: 12px; background: var(--card); border: 1px solid var(--line); padding: 2px 8px; border-radius: 8px; }
/* 江湖頁的三條戰況（第一季濃縮版，伺服器有送才畫）：三格並排一行；條的底色是官軍（石青），黃的那一截是黃巾 */
.fronts { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; margin-bottom: 12px; }
.front { min-width: 0; padding: 6px 8px 7px; border: 1px solid var(--line); border-radius: 10px; background: var(--card); }
.front-head { display: flex; justify-content: space-between; gap: 4px; font-size: 12px; line-height: 1.4; }
.front-head span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink-2); }
.front-head b { font-variant-numeric: tabular-nums; }
.front-bar { position: relative; height: 6px; margin-top: 4px; border-radius: 3px; background: var(--kuai); overflow: hidden; }
.front-bar > i { display: block; height: 100%; background: var(--gold); transition: width 0.4s ease; }
/* 亂局帶（FB-065）：條上淺色的一段（兩端含在內，位置與寬度由伺服器給的 chaos_band 算，不寫死 35／65），豪強的地盤；
   淺色蓋在金與藍上都看得出來，兩側各一道細線，戰況剛好落在邊上的就貼著那條線 */
.front-bar > .chaos-band { position: absolute; top: 0; bottom: 0; background: rgba(255, 255, 255, 0.42); box-shadow: inset 1px 0 rgba(255, 255, 255, 0.9), inset -1px 0 rgba(255, 255, 255, 0.9); pointer-events: none; }
.front.chaos { border-color: var(--ink-2); }
/* 戰況條兩端的陣營（FB-041）與下面那一行態勢（S1） */
.front-ends { display: flex; justify-content: space-between; margin-top: 2px; font-size: 10px; line-height: 1.2; font-weight: 700; }
.front-ends .huang { color: var(--gold); }
.front-ends .guan { color: var(--kuai); }
.front-ends span { white-space: nowrap; } /* 兩個字的標不在字中間換行：大字體或很窄的螢幕時圖卡才不會變高 */
/* 「亂局」標（FB-065）：在兩端字的正中間、亂局帶的正下面，中性的顏色；用內陰影畫框、不加上下留白，圖卡不會因此變高 */
.front-ends .chaos-tag { padding: 0 4px; border-radius: 4px; color: var(--ink-2); background: var(--card-2); box-shadow: inset 0 0 0 1px var(--ink-2); font-weight: 600; }
/* 態勢兩行（FB-065）：「態勢」靠左，官軍、黃巾（三條戰線合計）與豪強（亂局條數與漸長／漸消）各一行 */
.stances-line { display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: 0.7em; margin: -6px 0 12px; font-size: 12px; line-height: 1.5; color: var(--ink-2); }
.more-stats .stances-line { margin: 0; font-size: inherit; line-height: inherit; }
/* 結算卡的最終態勢：三條各用自己陣營的顏色（T9 審查 M3） */
.front-bar.stance { background: var(--card-2); }
.front-bar.side-guan > i { background: var(--kuai); }
.front-bar.side-huang > i { background: var(--gold); }
.front-bar.side-haoqiang > i { background: var(--rou); }
/* 江湖頁最上面的一排小標「態勢｜大事｜主線」（正式版辛，PM 2026-10-06）：三張各 44px 的摺疊卡疊起來有 170px，打完一仗整排行動
   就被擠出第一屏；一排 44px。每顆至少 44px 高；點哪一顆，它的內容在這一排正下面攤開（.peek-panel），同一時間只開一個。
   一行放得下三顆：375 寬約 330px 可用、320 寬約 270px。大事的小標一律只有「大事 N」加一個點、不寫標題（寫了，428～440px 的手機
   一行放不下、整排折成兩行，點掉亮點又跳回一行）；最窄（≤340px）連小箭頭也不畫；態勢的數字永遠不縮、不截（nowrap），
   實在放不下整排折行，也不截字。
   類別名稱獨一無二：.chip／.chips 是別處（人物、線索）在用的 */
.peek { margin-bottom: 12px; }
.peek-row { display: flex; flex-wrap: wrap; gap: 6px; }
.peek-chip { flex: 1 1 auto; min-height: 44px; box-sizing: border-box; display: inline-flex; align-items: center; justify-content: center; gap: 4px; padding: 6px 8px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--card); color: var(--ink); font: inherit; font-size: 14px; font-weight: 600; white-space: nowrap; cursor: pointer; }
.peek-chip::after { content: "▾"; font-size: 12px; font-weight: 400; color: var(--ink-2); transform: rotate(-90deg); transition: transform 0.2s; }
.peek-chip.board { border-color: var(--gold); }
.peek-chip.on { background: var(--card-2); }
.peek-chip.on::after { transform: none; }
.peek-name { color: var(--ink-2); }
.peek-nums b { font-weight: 700; font-variant-numeric: tabular-nums; }
.peek-nums .side-guan { color: var(--kuai); }
.peek-nums .side-huang { color: var(--gold); }
.peek-nums .side-haoqiang { color: var(--rou); }
.peek-count { color: var(--gold); font-variant-numeric: tabular-nums; }
.peek-dot { flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--gang); }
.peek-panel { margin-top: 6px; padding: 10px 14px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--card); max-height: 50vh; overflow: auto; }
.peek-panel.board { border-color: var(--gold); }
.peek-panel.quest { font-size: 14px; }
.peek-panel.quest h3 { font-size: 15px; margin-top: 0; }
.peek-panel > .fronts { margin-bottom: 8px; }
.peek-panel > :last-child { margin-bottom: 0; }
.stance-rule { margin: 0; font-size: 12px; line-height: 1.5; color: var(--ink); }
.stance-how { margin: 2px 0 0; font-size: 11px; line-height: 1.5; color: var(--ink-2); }
/* 點開戰況、態勢、大事、主線看的說明（explain-2）：小字淡色，一行一段；面板裡的接在最後、上面一條細線隔開。
   戰況圖卡那一段排在圖卡底下（#war 包著兩樣），只推動它底下的小地圖 */
.war-help { font-size: 12px; line-height: 1.55; color: var(--ink-2); }
.war-help p { margin: 4px 0 0; }
.peek-panel > .war-help { margin-top: 8px; padding-top: 6px; border-top: 1px solid var(--line); }
.war { margin-bottom: 12px; }
.war > .fronts { margin-bottom: 0; }
/* 決戰的即時戰局條（Joy 2026-10-10，web/app.js 的 gaugeHtml）：拔河，左邊是自己那一邊，旗子被拉向佔上風的那一頭；
   淺色兩截是大勝、兩道細線是當場分勝負、條上的色帶是上一回合怎麼移的、底下一格一回合。顏色照陣營（同戰況圖卡：官軍石青、黃巾金） */
.gauge { margin: 6px 0 10px; }
.gauge .side-guan { --c: var(--kuai); }
.gauge .side-huang { --c: var(--gold); }
.gauge .side-haoqiang { --c: var(--rou); }
.g-head { display: flex; justify-content: space-between; gap: 8px; font-size: 12px; line-height: 1.5; }
.g-side { color: var(--c, var(--ink-2)); white-space: nowrap; }
.g-side.mine { font-weight: 700; }
.g-side b { font-variant-numeric: tabular-nums; color: var(--ink); }
.g-bar { position: relative; height: 18px; margin-top: 2px; border-radius: 9px; background: var(--card-2); box-shadow: inset 0 0 0 1px var(--line); overflow: hidden; }
.g-zone { position: absolute; top: 0; bottom: 0; background: color-mix(in srgb, var(--c, var(--ink-2)) 22%, transparent); display: flex; align-items: center; font-style: normal; }
.g-zone.right { justify-content: flex-end; }
.g-zone span { position: relative; z-index: 1; padding: 0 6px; font-size: 10px; line-height: 1; font-weight: 600; color: var(--c, var(--ink-2)); white-space: nowrap; overflow: hidden; }
.g-tick { position: absolute; top: 0; bottom: 0; width: 2px; margin-left: -1px; background: var(--ink-2); opacity: 0.55; }
.g-mid { position: absolute; top: 3px; bottom: 3px; left: 50%; width: 1px; background: var(--ink-2); opacity: 0.35; }
.g-trail { position: absolute; top: 6px; height: 6px; border-radius: 3px; background: var(--c, var(--ink-2)); opacity: 0.6; }
.g-flag { position: absolute; z-index: 2; top: 1px; bottom: 1px; width: 6px; margin-left: -3px; border-radius: 3px; background: var(--ink); box-shadow: 0 0 0 2px var(--card); transition: left 0.5s ease; }
.g-rounds { display: flex; gap: 3px; list-style: none; margin: 5px 0 0; padding: 0; }
.g-r { flex: 1 1 0; min-width: 0; height: 16px; border-radius: 4px; background: var(--card-2); color: var(--ink-2); font-size: 10px; line-height: 16px; text-align: center; font-variant-numeric: tabular-nums; }
.g-r[class*="side-"] { background: var(--c); color: #fff; }
.g-r.side-huang { color: #2a241d; } /* 金底配白字太淡：兩種模式都用深墨 */
.g-r.tie { background: var(--line); color: var(--ink); }
.g-r.g-now { box-shadow: inset 0 0 0 1.5px var(--ink); color: var(--ink); font-weight: 700; }
.g-cap { margin: 3px 0 0; font-size: 12px; line-height: 1.5; color: var(--ink-2); }
.battle-card .gauge { margin: 8px 0 4px; }
.g-merit { margin-top: 8px; padding-top: 6px; border-top: 1px dashed var(--line); font-size: 12px; line-height: 1.5; }
.g-mtitle { margin: 0 0 2px; font-weight: 700; color: var(--ink-2); }
.g-mcols { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.g-mcol { min-width: 0; }
.g-mside { display: block; color: var(--c, var(--ink-2)); }
.g-mcol ol { list-style: none; margin: 0; padding: 0; }
.g-mcol li { display: flex; gap: 6px; }
.g-mcol li i { font-style: normal; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.g-mcol li span { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.g-mcol li b { font-variant-numeric: tabular-nums; }
.g-mcol li.mine span { font-weight: 700; color: var(--c, var(--ink)); }
.g-mcol .muted { margin: 0; }
.g-me { margin: 4px 0 0; color: var(--ink); }
.war > .fronts-help { margin: 2px 4px 0; }
.fronts[data-act="fronts-help"] { cursor: pointer; }
.fronts[data-act="fronts-help"]:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 10px; }
@media (max-width: 340px) {
  .peek-chip::after { display: none; }
}
/* 第一季的本週軍令（計畫 T6） */
.orders .order, .bounties .order { padding: 8px 0; border-top: 1px solid var(--line); }
.orders .order:first-child, .bounties .order:first-child { border-top: 0; padding-top: 0; }
.order-head { display: flex; justify-content: space-between; gap: 8px; font-size: 14px; }
.order-head span { color: var(--ink-2); font-variant-numeric: tabular-nums; white-space: nowrap; }
.order-text { margin-top: 2px; font-size: 13px; line-height: 1.5; color: var(--ink-2); }
/* 打擊那道軍令多一行「怎麼打、他在哪」（FB-072）：字色比上面的軍令文字深一點、前面一條金線，看得出是補充說明；窄螢幕自然換行 */
.order-how { margin-top: 4px; padding-left: 8px; border-left: 2px solid var(--gold); font-size: 12.5px; line-height: 1.5; color: var(--ink); overflow-wrap: anywhere; }
.order-bar { height: 5px; margin-top: 6px; border-radius: 3px; background: var(--line); overflow: hidden; }
.order-bar > i { display: block; height: 100%; background: var(--gold); transition: width 0.4s ease; }
.order-meta { margin-top: 4px; font-size: 12px; color: var(--ink-2); }
.bounty-foot { margin-top: 8px; }
.order-cart { padding-bottom: 8px; font-size: 13px; color: var(--ink); }
.order.done .order-head b::after { content: " ✔"; color: var(--gold); }
/* 第一季的結算卡（休季，計畫 T9） */
.result h2 { margin: 0 0 6px; font-size: 18px; }
.result h3 { margin: 10px 0 4px; font-size: 13px; color: var(--ink-2); font-weight: 600; }
.result-text { line-height: 1.6; }
.result-text p { margin: 0; }
.result .fronts { margin-bottom: 4px; }
.result .fold { margin-top: 8px; }
.result-event { padding: 6px 0; border-top: 1px solid var(--line); font-size: 13px; line-height: 1.5; }
.result-event:first-child { border-top: 0; padding-top: 0; }
.result-event b { display: block; }
.result-event small { display: block; color: var(--ink-2); }
.result-event p { margin: 2px 0 0; }
.result-ranks { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; font-size: 13px; }
.result-rank ol { margin: 4px 0 0; padding-left: 18px; }
.result-rank li { display: flex; justify-content: space-between; gap: 4px; }
.result-rank li span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.result-rank li i { font-style: normal; font-variant-numeric: tabular-nums; color: var(--ink-2); }
.result-rank p { margin: 4px 0 0; color: var(--ink-2); }
.linkish { border: 0; background: none; color: var(--accent); cursor: pointer; padding: 6px 2px; font-size: 14px; }

/* ── 修練 ── */
/* 卷軸卡（企劃者 2026-10-06「先用捲軸卡」）：一門一張卡，左邊一條品質色、左上一方品質印。品質色是 --q（q1～q4 四階） */
:root { --q-1: #8a7f70; --q-2: #3f7a62; --q-3: #b7862b; --q-4: #a8322a; }
@media (prefers-color-scheme: dark) { :root { --q-1: #a39684; --q-2: #5fae8c; --q-3: #d6a548; --q-4: #d2574a; } }
.q1 { --q: var(--q-1); } .q2 { --q: var(--q-2); } .q3 { --q: var(--q-3); } .q4 { --q: var(--q-4); }
.qseal { display: inline-grid; place-items: center; width: 26px; height: 26px; flex: none; border-radius: 6px; border: 1.5px solid var(--q);
  color: var(--q); font: 800 14px/1 var(--serif); background: color-mix(in srgb, var(--q) 10%, var(--card)); }
.qseal.big { width: 40px; height: 40px; font-size: 21px; border-width: 2px; }
.naming { display: block; border: 1.5px dashed var(--gold); border-radius: 14px; padding: 10px 12px; margin-bottom: 12px; background: color-mix(in srgb, var(--gold) 6%, var(--card)); }
.naming small { color: var(--gold); font-weight: 700; font-size: 11px; }
.naming p { margin: 4px 0 8px; font-size: 14px; }
.naming .input { flex: 1 1 auto; min-width: 0; }
.naming .btn { flex: none; }
.naming.divine { margin-top: 6px; } /* 神器原品定名：接在裝備庫那一列底下 */
/* 療傷、閉關兩格：閉關那一格是表單，底下一個時數選單 */
.tune { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-bottom: 4px; }
.tune .btn, .acts .btn { flex-direction: column; gap: 0; min-height: 50px; padding: 6px 8px; }
.tune .btn small, .acts .btn small { font-size: 11px; font-weight: 400; opacity: 0.85; line-height: 1.3; }
.seclude { display: grid; gap: 4px; }
.seclude .btn { min-height: 44px; }
.seclude .input { min-height: 34px; padding: 2px 8px; font-size: 14px; }
.acard { background: var(--card); border: 1px solid var(--line); border-left: 4px solid var(--q, var(--line)); border-radius: 16px;
  padding: 12px; margin-bottom: 10px; box-shadow: var(--shadow); overflow-wrap: anywhere; }
.acard.empty { color: var(--ink-2); }
/* 修練頁的「裝備」塊（app.js 的 gearBlock，裝備四欄設計 2.5）：一欄一小段（.gear-slot），一件一行。FB-125：名字與說明在左邊自己折行，
   兩顆鈕包在右邊不折行，列與列之間一條線，看得出哪顆鈕屬於哪一件 */
.gear .sub { font-size: 12px; color: var(--ink-2); margin: 10px 2px 2px; }
.gear .wrow { display: flex; gap: 8px; align-items: center; padding: 6px 2px; border-bottom: 1px solid var(--line); }
.gear .wrow .winfo { flex: 1 1 auto; min-width: 0; display: flex; flex-wrap: wrap; gap: 0 6px; }
.gear .wrow .wbtns { flex: none; display: flex; gap: 6px; }
.gear p { margin: 4px 2px; }
.acard .hd { display: flex; gap: 10px; align-items: center; }
.acard .hd > div { min-width: 0; }
.acard .hd h3 { margin: 0; font: 700 18px/1.3 var(--serif); }
.acard .hd .sub { font-size: 12px; color: var(--ink-2); }
.acard .hd .worn { margin-left: auto; flex: none; font-size: 11px; color: var(--accent); border: 1px solid var(--accent); border-radius: 999px; padding: 1px 8px; }
.ten { display: grid; grid-template-columns: repeat(10, 1fr); gap: 3px; margin: 10px 0 4px; }
.ten i { height: 7px; border-radius: 2px; background: var(--card-2); }
.ten i.on { background: var(--q, var(--ink-2)); }
.ten.mini { display: inline-grid; width: 120px; margin: 0 4px; vertical-align: middle; gap: 2px; }
.ten.mini i, .lib .art-body .ten.mini i { height: 6px; background: var(--line); }
.ten.mini i.on, .lib .art-body .ten.mini i.on { background: var(--q, var(--ink-2)); }
.lvline { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; font-size: 12px; color: var(--ink-2); }
.lvline b { color: var(--ink); font-size: 14px; flex: none; }
.lvline span { text-align: right; }
/* 功法庫那張卡的比較句（W6、FB-088）：跟身上同一種那門比，寫在兩顆大鈕上面，改練之前看得到 */
.art-body .cmp { margin: 6px 0 0; font-size: 12px; line-height: 1.5; color: var(--ink-2); }
.acts { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 10px; }
.acard .legend, .art-body .legend { display: flex; align-items: center; gap: 10px; min-height: 44px; margin-top: 6px; font-size: 14px; color: var(--gold); cursor: pointer; }
.acard .legend input, .art-body .legend input { width: 20px; height: 20px; flex: none; margin: 0; accent-color: var(--accent); }
.odds { display: flex; align-items: center; gap: 3px; font-size: 11px; margin-top: 8px; }
.odds span { color: var(--ink-2); margin-right: 4px; white-space: nowrap; }
.odds b { font-weight: 600; text-align: center; padding: 3px 0; border-radius: 4px; color: #fff; background: var(--q); white-space: nowrap; min-width: 46px; flex-basis: 0; }
.more { display: flex; gap: 6px; justify-content: flex-end; flex-wrap: wrap; margin-top: 4px; }
.more .linkish { color: var(--ink-2); min-height: 40px; padding: 6px 8px; }
.more .linkish:disabled { opacity: 0.45; cursor: default; }
/* 熔煉灰掉的原因（review-ap3 M1）：手機沒有 title 可看，寫在這一排左邊的空位；吃掉剩下的寬度、自己折行，這一排不會變高 */
.more .why { flex: 1 1 0; min-width: 0; align-self: center; text-align: left; font-size: 12px; line-height: 1.35; color: var(--ink-2); }
.art-card { margin-top: 6px; padding: 8px 10px; border-radius: 10px; background: var(--card-2); font-size: 13px; }
.art-card > :first-child { margin-top: 0; } .art-card > :last-child { margin-bottom: 0; }
/* 功法庫：一門一列（品質印＋名字），點開攤成卡的內容。不放在 .list 裡（.list button 的列樣式會蓋到卡裡的鈕） */
.lib { border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; background: var(--card); margin-bottom: 12px; }
.lib button.libr { display: flex; width: 100%; align-items: center; gap: 10px; text-align: left; border: 0; border-bottom: 1px solid var(--line);
  background: none; color: var(--ink); padding: 10px 14px; cursor: pointer; min-height: 52px; font: inherit; }
.lib button.libr:last-child { border-bottom: 0; }
.lib button.libr::after { content: "›"; margin-left: auto; color: var(--ink-2); }
.lib button.libr.on { background: var(--accent-soft); }
.lib button.libr.on::after { content: "▾"; }
.lib button.libr > .txt { min-width: 0; display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 8px; }
.lib button.libr b { font-size: 15px; }
.lib button.libr small { color: var(--ink-2); font-size: 12px; }
.lib .art-body { padding: 4px 14px 10px; border-bottom: 1px solid var(--line); background: var(--card-2); overflow-wrap: anywhere; }
.lib .art-body:last-child { border-bottom: 0; }
.lib .art-body .ten i { background: var(--card); }
.lib .art-body .ten i.on { background: var(--q, var(--ink-2)); }
.lib .art-body .art-card { background: var(--card); }
/* 武學多時（上限 50 門）：篩選一排，橫向可滑 */
.lib-filter { display: flex; gap: 6px; overflow-x: auto; scrollbar-width: none; margin: 0 0 8px; padding-bottom: 2px; }
.lib-filter button { flex: none; min-height: 36px; padding: 4px 12px; border-radius: 999px; border: 1px solid var(--line); background: var(--card); color: var(--ink); font-size: 13px; cursor: pointer; }
.lib-filter button.on { border-color: var(--accent); color: var(--accent); background: var(--accent-soft); font-weight: 600; }
.lib-more { margin: -4px 0 12px; }
/* 意境：一顆一顆的籤，點一下底下攤開說明 */
.ins { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
.ins button { min-height: 38px; border: 1px solid var(--line); border-radius: 999px; padding: 4px 12px; font-size: 14px; background: var(--card); color: var(--ink); cursor: pointer; }
.ins button small { color: var(--ink-2); font-size: 12px; margin-left: 2px; }
.ins button.on { border-color: var(--accent); background: var(--accent-soft); }
/* 點開的那一個意境：左邊名字與模型寫的一句話，右邊「化成心得」 */
.insight { display: flex; align-items: center; justify-content: space-between; gap: 10px; border: 1px solid var(--line); background: var(--card); border-radius: 12px; padding: 8px 10px; margin-bottom: 12px; }
/* 修練的結果（W7）：寫在卡上那排鈕的底下，按的那顆鈕旁邊就看得到 */
.acard .art-result, .art-body .art-result { margin: 8px 0 0; font-size: 13px; }
.art-result p { margin: 0 0 4px; }
.art-result p:last-child { margin-bottom: 0; }
.insight > div { min-width: 0; overflow-wrap: anywhere; }
.insight b { font-weight: 600; font-size: 14px; }
.insight p { margin: 2px 0 0; color: var(--ink-2); font-size: 12px; }
.insight .btn { flex: none; }

/* ── 煉製 ── */
.chips { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 8px; margin-bottom: 12px; }
.chip { border: 1px solid var(--line); background: var(--card); border-radius: 12px; padding: 8px 10px; text-align: left; cursor: pointer; min-height: 52px; }
.chip b { display: block; font-weight: 600; font-size: 14px; }
.chip small { color: var(--ink-2); font-size: 11px; }
.chip.r2 { border-color: color-mix(in srgb, var(--gold) 60%, var(--line)); }
.chip.r3 { border-color: var(--gold); background: color-mix(in srgb, var(--gold) 10%, var(--card)); }
.chip.used { opacity: 0.4; }
/* 煉製頁挑東西那一排的篩選（FB-085）：全部／內功／武學／意境四顆小鈕排一行，併在「功法」那行標籤裡（第一屏不多一行）。
   畫出來的鈕只有一行字高，觸控範圍用 ::after 撐到約 40px。（修練頁的庫用卷軸卡自己的篩選，.lib-filter） */
.fchips { display: inline-flex; gap: 4px; flex: none; }
.fchip { position: relative; border: 1px solid var(--line); background: var(--card); color: var(--ink-2); border-radius: 999px; padding: 0 9px; font-size: 12px; line-height: 1.6; letter-spacing: 0; white-space: nowrap; cursor: pointer; }
.fchip::after { content: ""; position: absolute; inset: -9px -2px; }
.fchip.on { background: var(--accent-soft); border-color: var(--accent); color: var(--ink); font-weight: 600; }
.chip .n { float: right; font-size: 12px; color: var(--ink-2); }
/* 煉製頁武學與意境旁的「伏筆物品」：只列名字與數量，不能點，比武學的格子矮、排得密，手機上不把開爐擠出第一屏 */
.chips.clues { grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 6px; }
.clue { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; border: 1px dashed var(--line); background: var(--card); border-radius: 10px; padding: 5px 10px; font-size: 13px; }
.clue b { font-weight: 600; }
.clue span { color: var(--ink-2); font-size: 12px; }
/* 煉製頁的「開爐」與輿圖的步行／趕路／疾行排在內容裡、不黏在底部（FB-048）：黏著時會蓋住底下的字 */
.act-row { margin-bottom: 12px; }
.travel-row { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; margin: 10px 0 12px; }
.travel-row .btn:first-child { grid-column: 1 / -1; }
.travel-row .btn:not(:first-child) { min-height: 44px; padding: 8px 6px; font-size: 14px; }
.travel-row .btn { margin: 0; }
/* 事件還沒了結擋著路（FB-063）：灰的那顆寫是哪一則，旁邊一顆「回江湖」，同一排、不多佔一行 */
.travel-row.blocked { grid-template-columns: 1fr auto; align-items: stretch; }
.travel-row.blocked .btn:first-child { grid-column: auto; }
.travel-row.blocked .btn:not(:first-child) { min-height: 48px; padding: 8px 16px; font-size: 15px; white-space: nowrap; }
.forging { animation: ember 1.6s ease-in-out infinite; }
@keyframes ember { 0%, 100% { box-shadow: 0 0 0 rgba(214, 120, 40, 0); } 50% { box-shadow: 0 0 18px rgba(214, 120, 40, 0.75); } }

/* ── 輿圖 ── */
/* 地圖框（W16）：固定高度的視窗，地圖照原本的像素大小放在裡面，靠 transform 平移、縮放（app.js 的 applyMapView）。
   框裡的手勢全歸地圖（touch-action: none）：不捲頁面、不放大整頁；長按不跳選字、不跳 iOS 的選單 */
/* 框高：第一屏要整個露在底部分頁列上面。框頂約在 280px（狀態列、說明卡、圖層、下拉選單），分頁列約 55px，
   再留一點空隙，所以是 100svh − 340px；第一個 62vh 給不認得 svh 的瀏覽器 */
.map-wrap {
  position: relative; overflow: hidden; height: 62vh; height: min(62vh, calc(100svh - 340px)); min-height: 260px; margin-bottom: 12px;
  border-radius: var(--radius); border: 1px solid var(--line); background: #e9e2cc;
  touch-action: none; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; cursor: grab;
}
/* 伺服器包的那一層 div 自帶捲軸與限高（overflow:auto、max-height:75vh），這裡蓋掉，免得裁到地圖或冒出捲軸 */
.map-wrap .tx-world-map { position: absolute; left: 0; top: 0; overflow: visible !important; max-width: none !important; max-height: none !important; }
.map-wrap .tx-world-map > svg { display: block; transform-origin: 0 0; }
/* 拖移、雙指縮放中才升成合成層（不常駐：停下來還開著的話字會糊）；按鈕、下拉選單的移動滑一下，手勢與滾輪中不滑 */
.map-wrap.moving .tx-world-map > svg { will-change: transform; }
.map-wrap.glide .tx-world-map > svg { transition: transform 0.15s ease-out; }
.map-wrap [data-loc] { cursor: pointer; }
.map-wrap.grabbing, .map-wrap.grabbing [data-loc] { cursor: grabbing !important; }
/* 地點的點擊區（E2／E3）：mapview 替每個地點畫了一個透明的圓（r=16）接點擊，這裡再加透明的粗外框。
   外框寬 --hit 由 app.js 跟著倍率算：半徑 R＝22÷倍率，夾在 22～34（地圖單位），螢幕上至少約 22px；
   上限 34 是因為 40 個地點裡最近的兩個（嵩山深處與南華觀）相距 68.6，再大會互相蓋住 */
.map-wrap [data-loc] > circle[fill-opacity="0"] { stroke: transparent; stroke-width: var(--hit, 12px); pointer-events: all; }
/* 右上角的按鈕（回到所在地、放大、縮小）：疊在地圖上，不另佔一列；觸控目標 44px。
   放上面不放下面：框底可能落在固定的底部分頁列後面，按鈕會被蓋住 */
.map-ctl { position: absolute; top: 8px; right: 8px; display: flex; flex-direction: column; gap: 6px; }
.map-ctl button {
  width: 44px; height: 44px; padding: 0; display: grid; place-items: center; cursor: pointer;
  border-radius: 12px; border: 1px solid var(--line); background: var(--card); color: var(--ink); box-shadow: var(--shadow);
}
.map-ctl button:disabled { opacity: 0.45; cursor: default; }
.map-ctl svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; }
/* 圖例（企劃者 10/4）：浮在地圖框左下角的一層 HTML，不畫進 SVG、不跟著地圖平移縮放。紙色半透明（--lg-alpha 是不透明度，
   改一個數字就調），顏色用地圖的固定紙色、不跟深色主題走（地圖本身也不跟）。收合鈕在最下面、說明疊在它上面（column-reverse），
   展開收合時鈕不跳位置。寬度上限留出右上角那一排按鈕（44px＋右邊 8px＋8px 空隙＝68px），所以橫向永遠碰不到它們；
   高度上限是框高減 16px，說明那一塊矮的時候自己捲（touch-action: pan-y，蓋掉地圖框的 none：手指在說明上直著滑，滑的是
   說明或頁面，不是地圖）。外層不收滑鼠與觸控（pointer-events: none）：只有鈕與說明收，框裡沒字的地方照常拖地圖、點地點 */
.map-legend {
  --lg-alpha: 0.88; --lg-paper: 244 239 223; --lg-line: #b9ad8e; --lg-ink: #5f5e5a;
  position: absolute; left: 8px; bottom: 8px; z-index: 1; display: flex; flex-direction: column-reverse; align-items: flex-start; gap: 6px;
  max-width: min(380px, calc(100% - 68px)); max-height: calc(100% - 16px); pointer-events: none;
}
.legend-toggle, .legend-body { pointer-events: auto; background: rgb(var(--lg-paper) / var(--lg-alpha)); border: 1px solid var(--lg-line); color: var(--lg-ink); box-shadow: var(--shadow); }
.legend-toggle { flex: none; min-height: 44px; padding: 0 14px 0 10px; display: inline-flex; align-items: center; gap: 4px; border-radius: 12px; font-size: 14px; cursor: pointer; }
.legend-toggle svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; transition: transform 0.15s; }
.map-legend.open .legend-toggle svg { transform: rotate(180deg); }
.legend-body { min-height: 0; overflow-y: auto; overscroll-behavior: contain; touch-action: pan-y; border-radius: 10px; padding: 8px 10px; font-size: 12px; line-height: 1.55; cursor: default; }
.legend-body[hidden] { display: none; }
.legend-body p { margin: 4px 0 0; }
.legend-icons { display: flex; flex-wrap: wrap; gap: 2px 12px; margin: 0; padding: 0; list-style: none; }
.legend-icons li { display: inline-flex; align-items: center; gap: 2px; white-space: nowrap; }
.legend-icons svg { flex: none; width: 24px; height: 20px; }
/* 地圖框用 overflow: hidden 裁切，但 hidden 的框仍然是捲動容器：程式叫 scrollIntoView（讀屏軟體、自動化測試常這樣做）時，
   框自己會被捲走一截，裡面的地圖、圖例、按鈕一起上移。clip 一樣裁切、而且不能被捲；不認得 clip 的舊瀏覽器照舊用上面的 hidden */
.map-wrap { overflow: clip; }
.map-tools { display: flex; margin-bottom: 8px; }
.map-tools select { flex: 1; }

/* ── 戰報／見聞 ── */
.report-detail { font-size: 14px; }
.back { margin-bottom: 8px; }

/* ── 設定抽屜 ── */
.sheet-bg { position: fixed; inset: 0; z-index: 40; background: rgba(0, 0, 0, 0.35); animation: fade 0.2s; }
.sheet {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 41; max-height: 88vh; overflow: auto;
  max-width: 640px; margin: 0 auto; background: var(--paper); border-radius: 18px 18px 0 0;
  padding: 8px 16px calc(20px + var(--bottom)); animation: up 0.25s ease-out;
}
.sheet .grip { width: 40px; height: 4px; border-radius: 2px; background: var(--line); margin: 4px auto 10px; }
@keyframes fade { from { opacity: 0; } }
@keyframes up { from { transform: translateY(40px); opacity: 0; } }
.toggle { display: flex; align-items: center; gap: 10px; padding: 12px 14px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--card); margin-bottom: 10px; cursor: pointer; }
.toggle input { width: 20px; height: 20px; accent-color: var(--accent); }
/* 管理者工具（G3）：排在一般設定之後、虛線框加淡金底，一眼看得出是另一塊；「開啟下一季」用警示樣式 */
.admin-zone {
  margin-top: 24px; padding: 12px 14px 14px; border: 1.5px dashed var(--gold); border-radius: var(--radius);
  background: color-mix(in srgb, var(--gold) 9%, var(--paper));
}
.admin-zone h4 { margin: 0; font-size: 16px; }
.admin-zone .muted { margin-bottom: 0; }
/* 管理者區的按鈕字不斷開（FB-033）：375 寬時「立刻收季」「開啟下一季」被擠成一排會折成兩行字 */
.admin-zone .btn { white-space: nowrap; }
/* 開季／收季／開下一季三顆：照字寬排，擠不下就整顆換到下一行（每顆長滿它那一行，不留空）；只動這一列、不動別頁的 .row */
.admin-zone .row.seasons { flex-wrap: wrap; }
.admin-zone .row.seasons > .btn { flex: 1 1 auto; width: auto; }
.ad-row > .ad-tag { flex: none; align-self: center; font-size: 13px; color: var(--ink-2); }
.ad-row > .btn { flex: none; }
/* 管理者觸發鈕（2026-10-07）：每週的事兩顆鈕擠不下就換行；開不了的大戲與召見在鈕前寫一句為什麼，字小、可以折行 */
.admin-zone .row.wrap { flex-wrap: wrap; }
.admin-zone .row.wrap > .btn { flex: 1 1 auto; width: auto; }
.ad-row > .ad-note { flex: 1 1 auto; min-width: 0; align-self: center; font-size: 12px; }
.btn.warn { color: var(--bad); border-color: var(--bad); font-weight: 600; }
/* 確認鈕固定用深一點的朱紅：深色模式的 --bad（#e06a5c）配白字只有 3.3:1，這個顏色兩種模式都是 5.9:1 */
.btn.danger { background: #b23a2b; border-color: #b23a2b; color: #fff; font-weight: 600; }
/* 管理者動作的確認框：疊在設定抽屜上面的小抽屜（app.js 的 ask） */
.ask-layer { position: fixed; inset: 0; z-index: 45; }
.ask-bg { position: absolute; inset: 0; background: rgba(0, 0, 0, 0.35); animation: fade 0.2s; }
.ask {
  position: absolute; left: 0; right: 0; bottom: 0; max-width: 640px; margin: 0 auto;
  background: var(--paper); border-radius: 18px 18px 0 0; box-shadow: 0 -4px 24px rgba(0, 0, 0, 0.18);
  padding: 18px 16px calc(20px + var(--bottom)); animation: up 0.25s ease-out;
}
.ask p { margin: 0 0 14px; font-size: 15px; }

/* ── 登入 ── */
.gate { max-width: 420px; margin: 0 auto; padding: calc(48px + var(--top)) 20px 32px; }
.brand { text-align: center; margin-bottom: 28px; }
.brand h1 { font-size: 40px; letter-spacing: 0.35em; margin: 0 0 0 0.35em; }
.brand p { color: var(--ink-2); margin: 4px 0 0; font-size: 14px; }
.seal { display: inline-grid; place-items: center; width: 56px; height: 56px; border-radius: 14px; background: var(--accent); color: #fff; font: 600 30px var(--serif); margin-bottom: 12px; }

#toast {
  position: fixed; left: 50%; bottom: calc(84px + var(--bottom)); transform: translateX(-50%) translateY(20px);
  max-width: min(90vw, 520px); background: var(--ink); color: var(--paper); padding: 10px 16px; border-radius: 12px;
  font-size: 14px; z-index: 60; opacity: 0; pointer-events: none; transition: opacity 0.2s, transform 0.2s;
}
#toast.show { opacity: 1; transform: translateX(-50%); }
.offline { position: fixed; top: calc(6px + var(--top)); left: 50%; transform: translateX(-50%); z-index: 50; background: var(--bad); color: #fff; font-size: 12px; padding: 3px 10px; border-radius: 10px; }

@media (min-width: 900px) {
  .page { padding-top: 16px; }
}

/* ── 太極火爐（煉製頁）：外圈火舌明滅，太極在爐裡慢慢轉，左右兩格放武學與意境；開爐等結果時整座爐子晃動 ── */
.furnace-wrap { width: 100%; max-width: 250px; margin: 4px auto 10px; aspect-ratio: 1; }
.wheel { width: 100%; height: 100%; display: block; overflow: visible; touch-action: manipulation; -webkit-user-select: none; user-select: none; }
.wheel text { text-anchor: middle; dominant-baseline: central; pointer-events: none; }
.w-rim { fill: none; stroke: var(--gold); stroke-width: 1; opacity: 0.7; }
.w-hub { cursor: pointer; }
.w-hub-rim { fill: var(--disk); stroke: var(--gold); stroke-width: 1.4; }
.w-yang { fill: #efe6d5; }
.w-yin { fill: #2a241d; }
.w-spin { transform-origin: 0 0; animation: w-turn 28s linear infinite; }
.w-spin.hot { animation-duration: 3s; }
@keyframes w-turn { to { transform: rotate(360deg); } }
.w-flames path { fill: none; stroke: #e0782a; stroke-width: 3; stroke-linecap: round; opacity: 0.75; transform-origin: 0 0; animation: w-flicker 0.9s ease-in-out infinite alternate; }
.w-flames.hot path, .w-furnace.forging .w-flames path { stroke: #f0a23a; stroke-width: 4; animation-duration: 0.35s; }
@keyframes w-flicker { from { opacity: 0.45; transform: scale(0.97); } to { opacity: 0.95; transform: scale(1.04); } }
.w-slot rect { fill: rgba(42, 36, 29, 0.78); stroke: var(--gold); stroke-width: 1; stroke-dasharray: 3 2; }
.w-slot.full rect { fill: rgba(42, 36, 29, 0.92); stroke-dasharray: none; stroke-width: 1.4; }
.w-slot.full { cursor: pointer; }
.w-slot.full.r3 rect { stroke: #f0c060; stroke-width: 2; }
.w-slot-name { font-family: var(--serif); font-weight: 700; font-size: 10.5px; fill: #fbf7ef; }
.w-slot-sub { font-size: 7.5px; fill: rgba(251, 247, 239, 0.75); }
.w-furnace-lab { font-family: var(--serif); font-size: 9px; fill: var(--gold); paint-order: stroke; stroke: var(--disk); stroke-width: 3px; }
.w-furnace.ready .w-furnace-lab { font-weight: 700; }
.w-furnace.forging .w-shake { animation: w-shake 0.42s linear infinite; }
@keyframes w-shake {
  0% { transform: translate(0, 0) rotate(0); } 20% { transform: translate(-2px, 1px) rotate(-1.5deg); }
  40% { transform: translate(2px, -1px) rotate(1.5deg); } 60% { transform: translate(-1.5px, -1px) rotate(-1deg); }
  80% { transform: translate(1.5px, 1px) rotate(1deg); } 100% { transform: translate(0, 0) rotate(0); }
}

/* ── 江湖頁的行動列：一排五顆「水墨氣勁」（企劃者 2026-10-04 給的樣式），黑底金邊、圖示、底下一行消耗 ── */
.act-bar { display: grid; grid-template-columns: repeat(5, 1fr); gap: 6px; padding: 8px 4px; margin-bottom: 12px;
  background: color-mix(in srgb, var(--disk) 5%, transparent); border: 1px dashed var(--line); border-radius: 12px; }
.act-ink { position: relative; overflow: hidden; min-height: 72px; padding: 8px 2px 6px; display: flex; flex-direction: column; align-items: center; justify-content: center;
  background: var(--disk); border: 1px solid color-mix(in srgb, var(--gold) 25%, transparent); border-radius: 10px; cursor: pointer; color: #ede2d3;
  font: inherit; transition: transform 0.22s ease, border-color 0.22s ease, box-shadow 0.22s ease, background 0.22s ease; -webkit-tap-highlight-color: transparent; }
.act-ink::after { content: ""; position: absolute; inset: 0; pointer-events: none; opacity: 0; transition: opacity 0.3s ease;
  background: radial-gradient(circle at 50% 25%, color-mix(in srgb, var(--gold) 18%, transparent), transparent 70%); }
.ink-icon { width: 22px; height: 22px; margin-bottom: 2px; fill: none; stroke: #d0c4b2; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round;
  transition: transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1), stroke 0.2s ease; }
.act-ink b { font-size: 13px; font-weight: 800; letter-spacing: 0.5px; }
.act-ink small { font-size: 10px; color: #9e8e7c; margin-top: 2px; white-space: nowrap; }
/* 遊歷的勝算（FB-044）：體力底下一行，照風險上色（黑底上的淺色） */
.act-ink small.ink-note { margin-top: 0; font-weight: 700; }
.act-ink small.ink-note.good { color: #8fc79f; }
.act-ink small.ink-note.even { color: #e3c77d; }
.act-ink small.ink-note.bad { color: #ec8a78; }
/* 選到的（展開的移動、按下去等結果的那一顆）往上浮 4px、金邊 */
.act-ink.on, .act-ink.busy, .act-ink.sending { background: #171310; border-color: var(--gold); transform: translateY(-4px);
  box-shadow: 0 4px 12px color-mix(in srgb, var(--gold) 22%, transparent), inset 0 0 12px color-mix(in srgb, var(--gold) 15%, transparent); }
.act-ink.on::after, .act-ink.busy::after, .act-ink.sending::after { opacity: 1; }
.act-ink.on .ink-icon, .act-ink.busy .ink-icon, .act-ink.sending .ink-icon { stroke: #f5d77f; transform: scale(1.15); }
.act-ink.on b, .act-ink.busy b, .act-ink.sending b { color: #f5d77f; }
.act-ink.on small, .act-ink.busy small, .act-ink.sending small { color: var(--gold); font-weight: 600; }
.act-ink:active:not(:disabled) { transform: translateY(-1px) scale(0.95); }
/* 不能用的：灰掉 */
.act-ink.sending:disabled { opacity: 1; filter: none; border-color: var(--gold); cursor: progress; animation: ink-wait 1.2s ease-in-out infinite; }
@keyframes ink-wait { 50% { box-shadow: 0 4px 18px color-mix(in srgb, var(--gold) 45%, transparent), inset 0 0 16px color-mix(in srgb, var(--gold) 25%, transparent); } }
.act-ink:disabled { opacity: 0.4; filter: grayscale(100%); cursor: not-allowed; border-color: rgba(255, 255, 255, 0.06); }
.act-ink:disabled .ink-icon { stroke: #666; }
/* 點下去的水墨漣漪 */
.ink-drop { position: absolute; width: 10px; height: 10px; border-radius: 50%; pointer-events: none; background: color-mix(in srgb, var(--gold) 45%, transparent);
  transform: translate(-50%, -50%) scale(0); animation: ink-burst 0.6s cubic-bezier(0.1, 0.8, 0.2, 1) forwards; }
@keyframes ink-burst { 0% { transform: translate(-50%, -50%) scale(1); opacity: 0.8; } 100% { transform: translate(-50%, -50%) scale(16); opacity: 0; } }
/* 行動列底下那幾行（explain-1）：這一下會怎樣。小字淡色、緊貼行動列（吃掉行動列下緣 12px 的一半），一個行動一行，名字粗一點。
   排在行動列之後，不動第一屏的「剛剛」、場景與行動列；375 寬一行約 27 字，長的照常折行 */
.act-notes { margin: -6px 4px 12px; font-size: 12px; line-height: 1.5; color: var(--ink-2); }
.act-notes p { margin: 0; }
.act-notes b { margin-right: 6px; color: var(--ink); font-weight: 600; }
/* 新手期的「玩法說明 ›」入口（explain-2）：跟上面幾行同一個字級、同一個行高，不多佔高度；按的範圍用內距加負外距撐大，行高不變 */
.act-notes .howto-entry button { font-size: 12px; line-height: inherit; font-weight: 600; padding: 8px 6px; margin: -8px 2px -8px -6px; }
.act-move { margin-bottom: 12px; scroll-margin-bottom: calc(64px + var(--bottom)); }
.act-move .options { margin: 8px 0 0; }
.act-move .move-mode { margin: 0; }
.fold.here summary { font-size: 14px; }
.fold.here .options { margin: 0; }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}

/* 設定頁的時刻表（計畫 T10）：一件一列，標題與狀態一行，可排的下面一行是時間欄位與「排定」 */
.tt-list { display: flex; flex-direction: column; gap: 6px; }
.tt-row { border: 1px solid var(--line); border-radius: 10px; padding: 6px 8px; }
.tt-head { display: flex; justify-content: space-between; gap: 8px; font-size: 13px; }
.tt-state { color: var(--ink-2); white-space: nowrap; }
.tt-real { margin-top: 4px; font-size: 11px; color: var(--ink-2); } /* 時間欄是現實時間，不是季曆（FB-062）；寫在欄位上面，不佔欄位的寬 */
.tt-row .row { margin-top: 2px; }
.tt-row input[type="datetime-local"] { flex: 1; min-width: 0; }
.tt-row .row > .btn { flex: none; }  /* 「排定」照字寬，日期與時刻才放得下 */

/* 說書人的對話框（引導重做設計 8.1、6.2）：行動上方，金框淡底；收起時縮成一行虛線框 */
.card.guide { padding: 8px 12px; border-color: color-mix(in srgb, var(--gold) 60%, var(--line));
  background: color-mix(in srgb, var(--gold) 7%, var(--card)); }
.guide-head { display: flex; justify-content: space-between; align-items: center; font-size: 12px; color: var(--gold); }
.guide-head .linkish { font-size: 12px; }
.guide-next { display: block; margin: 0 0 0 auto; font-size: 13px; color: var(--gold); } /* 分頁的步驟：「下一段 ▸」靠右；不留上緣——入伍段第一步第一頁 375×812 量過，留 4px 行動列下緣就碰到分頁列（757 對 756） */
.guide-text { margin: 2px 0 0; font-size: 14px; line-height: 1.6; cursor: pointer; white-space: pre-line; } /* 序章師父的話有段落（\n\n） */
.guide-text.clamp { display: -webkit-box; -webkit-line-clamp: 3; line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.guide-done { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 2px; font-size: 12px; }
.guide-done .ok { color: var(--ok); font-weight: 700; }
.guide-done .reward { padding: 0 6px; border: 1px solid var(--line); border-radius: 6px; }
.guide-line { display: block; width: 100%; margin: 0 0 12px; padding: 6px 10px; text-align: left; white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; border: 1px dashed color-mix(in srgb, var(--gold) 60%, var(--line)); border-radius: 10px;
  background: var(--card); color: var(--ink); font: inherit; font-size: 13px; cursor: pointer; }
.guide-line b { color: var(--gold); }

/* 序章（新手引導計畫一）：要按的鈕發光；新亮起來的元件閃一閃。減少動態時只留靜態的金邊 */
.glow { box-shadow: 0 0 0 2px var(--gold), 0 0 12px 2px color-mix(in srgb, var(--gold) 55%, transparent); animation: tx-glow 1.6s ease-in-out infinite; }
.lit { animation: tx-lit 0.9s ease-out 1; }
@keyframes tx-glow { 50% { box-shadow: 0 0 0 2px var(--gold), 0 0 4px 0 color-mix(in srgb, var(--gold) 20%, transparent); } }
/* 功法庫收著的那一列（序章指它「改練」「熔煉」）：.lib 要 overflow: hidden（卷軸卡的圓角），列又貼滿左右兩邊，往外長的金邊整個被裁掉、
   看不見。這一列的金邊改成往裡長（inset），一樣的顏色與呼吸，只是畫在列的裡面；卡裡的鈕有邊距，照舊往外長 */
.lib button.libr.glow { box-shadow: inset 0 0 0 2px var(--gold), inset 0 0 12px 2px color-mix(in srgb, var(--gold) 55%, transparent); animation-name: tx-glow-in; }
@keyframes tx-glow-in { 50% { box-shadow: inset 0 0 0 2px var(--gold), inset 0 0 4px 0 color-mix(in srgb, var(--gold) 20%, transparent); } }
@keyframes tx-lit { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
.guide-scene { margin: 4px 0 0; font-size: 13px; line-height: 1.6; color: var(--ink-2); font-style: italic; }
.skip-prologue { display: block; margin: 8px auto 0; font-size: 13px; color: var(--ink-2); }
.top[hidden] { display: none; }
.who.static { cursor: default; }
.who.static .more-ico { display: none; } /* 序章裡屬性還沒亮：名號不是按鈕，不畫展開的小箭頭 */
.recap { margin-top: 10px; font-size: 13px; line-height: 1.7; max-height: 50vh; overflow-y: auto; }
/* 設定抽屜的「玩法說明」（explain-1）：跟重看序章一樣是抽屜裡的一張卡；不另外限高、不自己捲（抽屜本身會捲，電腦上滾輪在暗處也捲它），
   手機上不會出現捲軸裡還有捲軸。一節一個小標題，底下一兩句 */
.howto { margin-top: 10px; font-size: 14px; line-height: 1.65; }
.howto h4 { margin: 12px 0 2px; font-size: 15px; }
.howto h4:first-child { margin-top: 0; }
.howto ul { margin: 0; padding-left: 1.2em; }
.howto li + li { margin-top: 2px; }
.recap hr { border: 0; border-top: 1px solid var(--line); margin: 10px 0; }
@media (prefers-reduced-motion: reduce) {
  .glow, .lit { animation: none; }
  .lib button.libr.glow { animation: none; } /* 上面那條的 animation-name 比 .glow 的選擇器重，要自己關；金邊還在，只是不呼吸 */
}

/* ── 玩家之間的互動（第一層）：場景卡底下「此地還有」與玩家卡 ── */
/* 只認 div：「此地還能做」的摺疊是 <details class="fold here">（FB-087），寫成 .here 的話它也被套上虛線、上緣與 flex（FB-107 順手修） */
div.here { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 8px; margin-top: 8px; padding-top: 6px; border-top: 1px dashed var(--line); font-size: 14px; line-height: 1.6; }
.here-k { color: var(--ink-2); font-size: 13px; }
.peer-name { background: none; border: 0; padding: 2px 0; font: inherit; color: var(--accent); cursor: pointer; text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px; }
.peer-name small { color: var(--ink-2); text-decoration: none; display: inline-block; }
.here-more { font-size: 13px; }
.peer-head h3 { margin: 0 0 2px; font-size: 20px; }
.peer-record { margin: 2px 0 0; font-size: 12px; color: var(--ink-2); }
.peer-title { color: var(--ink-2); font-size: 13px; }
.peer-title .peer-seg { white-space: nowrap; }
.peer-arts { display: grid; gap: 8px; margin: 14px 0; }
.peer-art { display: flex; align-items: baseline; gap: 10px; padding: 10px 12px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--card); }
.peer-art small { color: var(--ink-2); flex: none; }
.peer-art b { flex: 1; min-width: 0; }
.peer-art span { flex: none; color: var(--ink-2); font-size: 13px; }
.peer-acts { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 8px; margin-bottom: 12px; }
.peer-acts .btn small { display: block; font-size: 12px; color: var(--ink-2); font-weight: normal; }
.peer-msg { margin-bottom: 12px; padding: 10px 12px; border-radius: var(--radius); background: color-mix(in srgb, var(--gold) 12%, var(--paper)); font-size: 14px; }
.peer-msg p { margin: 0; }
.peer-amount { margin-bottom: 12px; }
/* 第二層：別人遞給你的打招呼、結伴邀請，與結伴同行的那一行（場景卡底下，「此地還有」之後） */
.calls { display: grid; gap: 6px; margin-top: 8px; padding-top: 6px; border-top: 1px dashed var(--line); font-size: 14px; }
.call, .party { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.call > span, .party > span { flex: 1 1 100%; }
.peer-amount { flex-wrap: wrap; }
.peer-amount select { flex: 1 1 100%; }
.peer-pick { grid-column: 1 / -1; display: grid; gap: 8px; }
.peer-pick select { min-width: 0; }

/* 煉製頁（企劃者 2026-10-10）：合不了的灰掉、寫兩三個字的原因；清單的篩選；結果就寫在開爐底下 */
.chip.no { opacity: 0.5; border-style: dashed; }
.chip.no .why { font-style: normal; color: var(--ink-2); }
.craft-filter { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 10px; }
.craft-filter select.input { width: auto; flex: 1 1 72px; min-width: 72px; padding: 6px 8px; font-size: 13px; }
.craft-filter .fchip { flex: 0 0 auto; }
.forge-result { margin: 0 0 12px; }

/* 武學譜（manualEntry 是煉製頁上的入口，bookHtml 是點開的一本書）：線裝古書的版面——泛黃的紙、雙線版框、界欄，
   口訣直書大字，合中了的那一頁蓋一方朱印。顏色只在這一段用，暗色時換成燈下的舊紙 */
:root {
  --bk-paper: #f2e5c6; --bk-paper-2: #e8d6ad; --bk-ink: #241a11; --bk-ink-2: #6d5a43; --bk-rule: #a9814b;
  --bk-cover: #2f4a5c; --bk-cover-2: #1d3140; --bk-slip: #f6edd8; --bk-seal: #b3261e; --bk-thread: #e9dcc0; --bk-seal-ink: #fbf3e2;
  --bk-serif: "Noto Serif TC", "Noto Serif CJK TC", "Source Han Serif TC", "Songti TC", "PMingLiU", "MingLiU", serif;
}
@media (prefers-color-scheme: dark) {
  :root {
    --bk-paper: #2b241b; --bk-paper-2: #221c15; --bk-ink: #efe1c3; --bk-ink-2: #b39e7f; --bk-rule: #8a6a3e;
    --bk-cover: #23394a; --bk-cover-2: #142431; --bk-slip: #e9dcc0; --bk-seal: #c4372c; --bk-thread: #cdbd9c;
  }
}
.book-icon { width: 40px; height: 46px; flex: none; }
.book-icon .bk-cover { fill: var(--bk-cover); }
.book-icon .bk-slip { fill: var(--bk-slip); stroke: var(--bk-seal); stroke-width: 1.2; }
.book-icon .bk-slip-ink { stroke: var(--bk-ink); stroke-width: 2.2; stroke-dasharray: 4 3; }
.book-icon .bk-thread { stroke: var(--bk-thread); stroke-width: 1.4; fill: none; }
.manual-entry {
  display: flex; align-items: center; gap: 14px; width: 100%; margin: 4px 0 12px; padding: 12px 14px; text-align: left; cursor: pointer;
  border: 1px solid var(--bk-rule); border-radius: var(--radius); color: var(--bk-ink); font: inherit;
  background: linear-gradient(135deg, var(--bk-paper) 0%, var(--bk-paper-2) 100%); box-shadow: var(--shadow);
}
.manual-entry span { display: flex; flex-direction: column; flex: 1; min-width: 0; }
.manual-entry b { font-family: var(--bk-serif); font-size: 19px; letter-spacing: 4px; }
.manual-entry small { color: var(--bk-ink-2); font-size: 13px; }
.manual-entry .go { font-style: normal; color: var(--bk-seal); font-weight: 600; white-space: nowrap; }

.book-layer {
  position: fixed; inset: 0; z-index: 42; overflow-y: auto; overscroll-behavior: contain; color: var(--bk-ink);
  background: radial-gradient(circle at 20% 10%, rgba(255, 255, 255, 0.10), transparent 60%), var(--bk-paper-2);
  animation: fade 0.2s; padding-bottom: calc(24px + var(--bottom));
}
.book-bar {
  position: sticky; top: 0; z-index: 2; display: flex; align-items: center; gap: 8px;
  padding: calc(8px + var(--top)) 12px 8px; background: var(--bk-cover-2); color: var(--bk-slip);
}
.book-back { border: 0; background: transparent; color: inherit; font: 600 16px var(--sans); padding: 6px 8px; cursor: pointer; }
.book-bar-title { font-family: var(--bk-serif); letter-spacing: 4px; opacity: 0.85; }
.book-cover {
  position: relative; height: 210px; overflow: hidden; margin-bottom: 18px;
  background: linear-gradient(180deg, var(--bk-cover-2) 0%, var(--bk-cover) 70%);
}
.book-hills { position: absolute; left: 0; right: 0; bottom: 0; width: 100%; height: 120px; }
.book-moon { position: absolute; top: 40px; left: 54px; width: 34px; height: 34px; border-radius: 50%; background: rgba(246, 237, 216, 0.6); box-shadow: 0 0 24px 6px rgba(246, 237, 216, 0.18); }
.book-hills .far { fill: rgba(233, 220, 192, 0.16); }
.book-hills .near { fill: rgba(63, 125, 92, 0.45); }
.book-title {
  position: absolute; top: 22px; right: 36px; padding: 16px 10px; writing-mode: vertical-rl; background: var(--bk-slip); border: 2px solid var(--bk-seal);
  box-shadow: inset 0 0 0 3px var(--bk-slip), inset 0 0 0 4px var(--bk-seal), 0 4px 12px rgba(0, 0, 0, 0.25);
}
.book-title span { display: block; font: 700 30px/1 var(--bk-serif); letter-spacing: 10px; color: #241a11; }
.book-sub { position: absolute; left: 20px; bottom: 14px; margin: 0; color: var(--bk-slip); font-size: 13px; letter-spacing: 1px; text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5); }
.leaves { display: flex; flex-direction: column; gap: 22px; padding: 0 16px; max-width: 560px; margin: 0 auto; }
.leaf {
  position: relative; padding: 14px 16px 12px; border: 2px solid var(--bk-rule);
  box-shadow: inset 0 0 0 4px var(--bk-paper), inset 0 0 0 5px var(--bk-rule), 0 3px 10px rgba(60, 40, 20, 0.18);
  background:
    radial-gradient(ellipse at 85% 15%, rgba(150, 110, 50, 0.10), transparent 55%),
    radial-gradient(ellipse at 10% 90%, rgba(150, 110, 50, 0.12), transparent 50%),
    var(--bk-paper);
}
.leaf-head { display: flex; justify-content: space-between; font: 600 13px var(--bk-serif); color: var(--bk-ink-2); letter-spacing: 2px; padding: 0 4px 8px; border-bottom: 1px solid var(--bk-rule); }
.leaf.solved .leaf-state { color: var(--bk-seal); }
/* 直書、右起；界欄是一欄一條細線，欄寬＝行高 */
.leaf-text {
  writing-mode: vertical-rl; width: 100%; height: 300px; overflow-x: auto; overflow-y: hidden; padding: 14px 6px;
  font: 700 26px/44px var(--bk-serif); letter-spacing: 3px; color: var(--bk-ink);
  background: repeating-linear-gradient(to left, transparent 0 43px, rgba(169, 129, 75, 0.35) 43px 44px) right 6px top 0 / auto 100% no-repeat;
}
.leaf-text p { margin: 0 0 0 44px; } /* 兩則口訣之間空一欄 */
.leaf-text p:last-child { margin-left: 0; }
.leaf-text span { display: block; }
.leaf-foot { display: flex; align-items: center; gap: 12px; min-height: 56px; padding: 8px 4px 0; border-top: 1px solid var(--bk-rule); }
.leaf-sign { font: 15px var(--bk-serif); color: var(--bk-ink-2); }
.leaf-sign b { color: var(--bk-ink); font-size: 17px; }
.seal { width: 60px; height: 60px; flex: none; transform: rotate(-5deg); filter: drop-shadow(0 0 0.5px var(--bk-seal)); }
.seal .seal-bg { fill: var(--bk-seal); }
.seal .seal-rim { fill: none; stroke: var(--bk-seal-ink); stroke-width: 1.2; opacity: 0.85; }
.seal .seal-ink text { fill: var(--bk-seal-ink); font-family: var(--bk-serif); font-weight: 700; text-anchor: middle; dominant-baseline: central; }
.leaf-foot { flex-wrap: wrap; } /* 鑄譜打中過的那一頁：配方獨佔一行，放在朱印與名號底下 */
.leaf-recipe { flex-basis: 100%; margin: 6px 0 0; font-family: var(--bk-serif); font-size: 14px; color: var(--bk-ink-2); letter-spacing: 1px; }
.leaf.empty .leaf-text { height: 180px; color: var(--bk-ink-2); }
.leaf-hint { margin: 10px 4px 0; color: var(--bk-ink-2); font: 14px var(--bk-serif); }

/* 見聞的「行狀」（玩家傳第一批，annalsHtml）：一則一列，新的在上。時刻與種類是一行小字，事實一行，你說的那一句與他回的那一句
   縮排在底下；份量重的（4 以上）左邊一道朱紅。字體跟武學譜同一套襯線，留一點史書的味道，顏色照一般卡片走 */
.annals-head h3 { margin: 0 0 4px; font-family: var(--bk-serif); letter-spacing: 0.08em; }
.annals-head p { margin: 0; }
ol.annals { list-style: none; margin: 0; padding: 4px 14px; }
.annal { padding: 10px 0 10px 10px; border-left: 3px solid transparent; }
.annal + .annal { border-top: 1px solid var(--card-2); }
.annal.heavy { border-left-color: var(--accent); }
.annal-meta { display: flex; flex-wrap: wrap; gap: 4px 8px; align-items: baseline; font-size: 12px; color: var(--ink-2); }
.annal-kind { padding: 0 6px; border: 1px solid var(--card-2); border-radius: 999px; letter-spacing: 0.1em; }
.annal-text { margin: 4px 0 0; font-family: var(--bk-serif); line-height: 1.65; }
.annal-quote, .annal-reply { margin: 4px 0 0 1em; font-size: 14px; line-height: 1.6; color: var(--ink-2); }
.annal-quote { color: var(--ink); }
.annal-reply b { font-weight: 600; color: var(--ink); }

/* ── 修練頁最上面的人物面板（企劃者 2026-10-12 給的版面）：一幅掛在紙上的水墨人物，身上的光點對上屬性、身上的兩門與裝備。
   舞台不論深淺色都是紙（剪影是墨，畫在紙上才看得見），深色時紙調暗一點 ── */
:root {
  --hero-paper: #f4eee2;
  --hero-paper-2: #ebdfcb;
  --hero-edge: rgba(200, 155, 60, 0.28);
  --hero-gold: #c89b3c;
  --hero-gold-light: #fbe69b;
  --hero-cinnabar: #b22d15;
  --hero-label-bg: rgba(255, 255, 255, 0.86);
  --hero-label-ink: #3b2b1b;
}
@media (prefers-color-scheme: dark) {
  :root {
    --hero-paper: #d9cfbc;
    --hero-paper-2: #c4b79f;
    --hero-edge: rgba(214, 165, 72, 0.35);
    --hero-label-bg: rgba(244, 238, 226, 0.9);
  }
}
.hero { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: 12px 12px 10px; margin: 4px 0 12px; box-shadow: var(--shadow); }
.hero-hd { display: flex; justify-content: space-between; align-items: flex-start; gap: 8px; border-bottom: 1px dashed var(--line); padding-bottom: 8px; margin-bottom: 8px; }
.hero-name { font: 900 18px/1.3 var(--serif); letter-spacing: 1px; }
.hero-tag { display: inline-block; margin-top: 4px; font-size: 11px; font-weight: 700; color: var(--hero-gold-light); background: var(--disk); padding: 2px 8px; border-radius: 4px; }
.hero-sub { text-align: right; font-size: 11px; line-height: 1.6; color: var(--ink-2); white-space: nowrap; }
.hero-stage { position: relative; height: 380px; border-radius: 12px; overflow: hidden; border: 1px solid var(--hero-edge);
  background: radial-gradient(circle at 45% 38%, var(--hero-paper) 0%, var(--hero-paper) 35%, var(--hero-paper-2) 100%); }
.hero-halo { position: absolute; width: 300px; height: 300px; top: 30px; left: calc(50% - 150px); border-radius: 50%;
  border: 1.5px dashed var(--hero-edge); animation: hero-spin 45s linear infinite; pointer-events: none; }
@keyframes hero-spin { to { transform: rotate(360deg); } }
.hero-fig { position: absolute; top: 6px; bottom: 6px; left: 50%; transform: translateX(-50%); aspect-ratio: 674 / 900; } /* 照哪一張剪影，app.js 用 style 蓋掉 */
.hero-fig img { display: block; width: 100%; height: 100%; filter: drop-shadow(0 6px 12px rgba(0, 0, 0, 0.22)); pointer-events: none; user-select: none; -webkit-user-drag: none; }
.hero-node { position: absolute; transform: translate(-50%, -50%); width: 28px; height: 28px; padding: 0; border: 0; background: none;
  display: flex; justify-content: center; align-items: center; cursor: pointer; z-index: 2; -webkit-tap-highlight-color: transparent; }
.hero-node .dot { width: 10px; height: 10px; border-radius: 50%; background: rgba(255, 255, 255, 0.95); border: 1.5px solid var(--hero-gold);
  box-shadow: 0 0 8px rgba(200, 155, 60, 0.8), 0 0 16px rgba(251, 230, 155, 0.6); transition: transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1), background 0.25s; }
.hero-node .pulse { position: absolute; inset: 0; border-radius: 50%; border: 1px solid var(--hero-gold-light); animation: hero-pulse 2.2s ease-in-out infinite; pointer-events: none; }
@keyframes hero-pulse { 0%, 100% { transform: scale(0.6); opacity: 0.2; } 50% { transform: scale(1.4); opacity: 0.8; } }
.hero-node.on .dot { transform: scale(1.5); background: var(--hero-cinnabar); border-color: #fff; box-shadow: 0 0 12px rgba(178, 45, 21, 1), 0 0 20px rgba(255, 120, 100, 0.8); }
.hero-node.dim .dot { background: rgba(255, 255, 255, 0.5); box-shadow: none; border-color: rgba(200, 155, 60, 0.6); }
.hero-node.dim .pulse { display: none; }
.hero-node span { position: absolute; font-size: 10px; font-weight: 800; line-height: 1.4; white-space: nowrap; color: var(--hero-label-ink);
  background: var(--hero-label-bg); border: 1px solid #dcd1be; padding: 0 5px; border-radius: 3px; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); pointer-events: none; }
.hero-node.r span { left: 24px; }
.hero-node.l span { right: 24px; }
.hero-node.on span { color: var(--hero-cinnabar); border-color: var(--hero-cinnabar); }
.hero-node.dim span { opacity: 0.7; }
.hero-ripple { position: absolute; width: 24px; height: 24px; border-radius: 50%; border: 1.5px solid var(--hero-cinnabar); pointer-events: none; z-index: 3;
  transform: translate(-50%, -50%) scale(0); animation: hero-ripple 0.5s cubic-bezier(0.1, 0.8, 0.2, 1) forwards; }
@keyframes hero-ripple { to { transform: translate(-50%, -50%) scale(3); opacity: 0; } }
.hero-ft { margin-top: 8px; background: var(--card-2); border: 1px solid var(--line); border-radius: 10px; padding: 8px 10px; }
.hero-ft-title { font: 800 14px/1.4 var(--serif); color: var(--accent); }
.hero-ft-title small { margin-left: 6px; font: 600 11px var(--sans); color: var(--gold); }
.hero-ft-row { display: flex; align-items: center; gap: 8px; }
.hero-ft-row p { flex: 1; min-width: 0; margin: 2px 0 0; font-size: 12px; line-height: 1.5; color: var(--ink-2); }
.hero-ft-row .btn { flex: none; min-height: 34px; padding: 4px 10px; font-size: 13px; }
.hero-ft-row .btn small { margin-left: 4px; font-size: 11px; font-weight: 400; opacity: 0.85; }
@media (prefers-reduced-motion: reduce) { .hero-halo, .hero-node .pulse { animation: none; } }
.acard[data-worn], .gear-slot { scroll-margin-top: 130px; } /* 人物面板的「看這一門／看這件」捲過去時不被頂上的狀態列蓋住 */

/* 設定頁的性別（PM 2026-10-12）：還沒選過的舊角色選一次 */
.gender-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0 0 10px; }
.gender-row > span { flex: 1 1 auto; }
.gender-row.card { flex-direction: column; align-items: stretch; padding: 10px 12px; }
.gender-row.card p { margin: 0; }
.gender-row .row { display: flex; gap: 8px; }

/* 建角色畫面選性別（PM 2026-10-12）：兩張剪影的小牌，選中的那張描紅 */
.sex-pick { border: 0; padding: 0; margin: 4px 0 12px; display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.sex-pick legend { padding: 0; margin-bottom: 8px; font-size: 14px; color: var(--ink-2, inherit); }
.sex-tile { position: relative; display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 10px 6px 8px;
  border: 1.5px solid var(--line, #d8ccb8); border-radius: 12px; background: #efe7d8; cursor: pointer; }
.sex-tile input { position: absolute; opacity: 0; pointer-events: none; }
.sex-tile img { height: 112px; width: auto; max-width: 100%; object-fit: contain; }
.sex-tile span { font-weight: 700; color: #2a241d; }
.sex-tile small { margin-left: 6px; font-weight: 400; color: #6b6155; }
.sex-tile:has(input:checked) { border-color: var(--accent, #b22d15); box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent, #b22d15) 25%, transparent); }
.sex-tile:has(input:focus-visible) { outline: 2px solid var(--accent, #b22d15); outline-offset: 2px; }

/* 登入頁的宣傳影片（企劃者 2026-10-12）：貼齊頂端與兩側的主視覺，登入框在它下面；375×812 第一屏看得到登入框的開頭 */
.gate.has-promo { padding-top: var(--top); }
.gate.has-promo .brand { margin: 14px 0 18px; }
.gate.has-promo .brand h1 { font-size: 32px; }
.promo { position: relative; margin: 0 -20px; aspect-ratio: 864 / 496; max-width: calc(100% + 40px); background: #e9e2d3; overflow: hidden; }
.promo video, .promo img { display: block; width: 100%; height: 100%; object-fit: cover; }
.promo::after { content: ""; position: absolute; inset: auto 0 0; height: 28%; pointer-events: none;
  background: linear-gradient(to bottom, transparent, var(--paper)); }
.promo-sound { position: absolute; right: 10px; bottom: 10px; z-index: 1; border: 0; border-radius: 999px; padding: 6px 12px;
  background: rgba(26, 22, 18, 0.62); color: #fff; font: 13px var(--sans); cursor: pointer; }
.promo-sound:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
@media (min-width: 461px) { .promo { margin: 16px 0 0; max-width: 100%; border-radius: var(--radius); } }
